Allow Bullet soft bodies to be created using a AddObject actuator. Added a fake world...
authorErwin Coumans <blender@erwincoumans.com>
Fri, 26 Sep 2008 02:27:59 +0000 (02:27 +0000)
committerErwin Coumans <blender@erwincoumans.com>
Fri, 26 Sep 2008 02:27:59 +0000 (02:27 +0000)
Added Bullet/Gimpact concave collision detection to Blender. If your build system isn't updated yet, please add extern/bullet2/src/BulletCollision/Gimpact/*
This allows moving/dynamic concave triangle meshes (decomposing meshes into compound convex shapes, and using 'compound' shapes is still preferred)

55 files changed:
extern/bullet2/CMakeLists.txt
extern/bullet2/Makefile
extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGImpactMassUtil.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_array.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_clip_polygon.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_contact.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_contact.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_geom_types.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_geometry.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_hash_table.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_linear_math.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_math.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_memory.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_memory.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_radixsort.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_tri_collision.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/Gimpact/gim_tri_collision.h [new file with mode: 0644]
extern/bullet2/src/BulletSoftBody/btSoftBody.cpp
extern/bullet2/src/BulletSoftBody/btSoftBody.h
extern/bullet2/src/SConscript
source/gameengine/Converter/BL_DeformableGameObject.cpp
source/gameengine/Converter/BL_MeshDeformer.h
source/gameengine/Converter/BL_ShapeDeformer.cpp
source/gameengine/Converter/BL_ShapeDeformer.h
source/gameengine/Converter/BL_SkinDeformer.cpp
source/gameengine/Converter/BL_SkinDeformer.h
source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
source/gameengine/Rasterizer/RAS_Deformer.h
source/gameengine/Rasterizer/RAS_TexVert.cpp

index e28e811087f556622744d9d575086dbd992b5749..edb6b9c525fcaa9f82e914a39d41ca43d0339a30 100644 (file)
@@ -31,6 +31,7 @@ FILE(GLOB SRC
   src/BulletCollision/BroadphaseCollision/*.cpp
   src/BulletCollision/CollisionShapes/*.cpp
   src/BulletCollision/NarrowPhaseCollision/*.cpp
+  src/BulletCollision/Gimpact/*.cpp
   src/BulletCollision//CollisionDispatch/*.cpp
   src/BulletDynamics/ConstraintSolver/*.cpp
   src/BulletDynamics/Vehicle/*.cpp
index d26289c8b010b8d72ab30a8c4c079ec0f87b762e..f3abb86e404da93361dc92bb98f4cab55a29d5ad 100644 (file)
@@ -37,6 +37,7 @@ LinearMath \
 BulletCollision/BroadphaseCollision \
 BulletCollision/CollisionShapes \
 BulletCollision/NarrowPhaseCollision \
+BulletCollision/Gimpact \
 BulletCollision//CollisionDispatch \
 BulletDynamics/ConstraintSolver \
 BulletDynamics/Vehicle \
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h b/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h
new file mode 100644 (file)
index 0000000..c98526f
--- /dev/null
@@ -0,0 +1,651 @@
+#ifndef BT_BOX_COLLISION_H_INCLUDED
+#define BT_BOX_COLLISION_H_INCLUDED
+
+/*! \file gim_box_collision.h
+\author Francisco León 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.
+*/
+
+#include "LinearMath/btTransform.h"
+
+/*! \defgroup BOUND_AABB_OPERATIONS
+*/
+//! @{
+
+///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)       fabsf(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 + fabsf(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 btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
+                       m_R1to0[1].dot(point) + m_T1to0.y(),
+                       m_R1to0[2].dot(point) + m_T1to0.z());
+       }
+};
+
+
+#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_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]);
+       }
+
+       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_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_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_max[0] = -SIMD_INFINITY;
+               m_max[1] = -SIMD_INFINITY;
+               m_max[2] = -SIMD_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 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_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] = 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_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]);
+       }
+
+       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_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_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.dot(trans.getBasis().getRow(0).absolute()),
+                                extends.dot(trans.getBasis().getRow(1).absolute()),
+                                extends.dot(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.dot(trans.m_R1to0.getRow(0).absolute()),
+                                extends.dot(trans.m_R1to0.getRow(1).absolute()),
+                                extends.dot(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/extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h b/extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h
new file mode 100644 (file)
index 0000000..32d470a
--- /dev/null
@@ -0,0 +1,186 @@
+#ifndef BT_CLIP_POLYGON_H_INCLUDED
+#define BT_CLIP_POLYGON_H_INCLUDED
+
+/*! \file btClipPolygon.h
+\author Francisco León 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.
+*/
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btGeometryUtil.h"
+
+/*! \addtogroup GEOMETRIC_OPERATIONS
+*/
+//! @{
+
+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/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp
new file mode 100644 (file)
index 0000000..faba2d8
--- /dev/null
@@ -0,0 +1,181 @@
+
+/*
+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 )
+               {
+                       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]);
+
+       BT_CONTACT * pcontact = &(*this)[0];
+
+       for( i=1;i<keycontacts.size();i++)
+       {
+           key = keycontacts[i].m_key;
+               const BT_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;
+       }
+
+       BT_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/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.h b/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.h
new file mode 100644 (file)
index 0000000..5ff7629
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef BT_CONTACT_H_INCLUDED
+#define BT_CONTACT_H_INCLUDED
+
+/*! \file gim_contact.h
+\author Francisco León 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.
+*/
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btTriangleShapeEx.h"
+
+
+/*! \defgroup CONTACTS
+\brief
+Functions for managing and sorting contacts resulting from a collision query.
+*/
+//! @{
+
+/**
+Configuration var for applying interpolation of  contact normals
+*/
+#define NORMAL_CONTACT_AVERAGE 1
+
+#define CONTACT_DIFF_EPSILON 0.00001f
+
+/// Structure for collision results
+class BT_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:
+    BT_CONTACT()
+    {
+    }
+
+    BT_CONTACT(const BT_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)
+    {
+    }
+
+    BT_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);
+    }
+
+};
+
+
+class btContactArray:public btAlignedObjectArray<BT_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( BT_CONTACT(point,normal,depth,feature1,feature2) );
+       }
+
+       SIMD_FORCE_INLINE void push_triangle_contacts(
+               const BT_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/extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.cpp
new file mode 100644 (file)
index 0000000..8d08ca8
--- /dev/null
@@ -0,0 +1,499 @@
+/*! \file gim_box_set.h
+\author Francisco León 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.
+*/
+#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(
+       BT_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(
+       BT_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);
+       }
+
+       bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+       btAssert(!unbal);
+
+       return splitIndex;
+
+}
+
+
+void btBvhTree::_build_sub_tree(BT_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(
+       BT_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 BT_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
+       BT_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/extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.h
new file mode 100644 (file)
index 0000000..7138b23
--- /dev/null
@@ -0,0 +1,401 @@
+#ifndef GIM_BOX_SET_H_INCLUDED
+#define GIM_BOX_SET_H_INCLUDED
+
+/*! \file gim_box_set.h
+\author Francisco León 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.
+*/
+
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+#include "btBoxCollision.h"
+#include "btTriangleShapeEx.h"
+
+
+
+/*! \defgroup BOX_TREES
+
+
+
+*/
+//! @{
+
+
+//! Overlapping pair
+struct BT_PAIR
+{
+    int m_index1;
+    int m_index2;
+    BT_PAIR()
+    {}
+
+    BT_PAIR(const BT_PAIR & p)
+    {
+       m_index1 = p.m_index1;
+       m_index2 = p.m_index2;
+       }
+
+       BT_PAIR(int index1, int index2)
+    {
+       m_index1 = index1;
+       m_index2 = index2;
+       }
+};
+
+//! A pairset array
+class btPairSet: public btAlignedObjectArray<BT_PAIR>
+{
+public:
+       btPairSet()
+       {
+               reserve(32);
+       }
+       inline void push_pair(int index1,int index2)
+       {
+               push_back(BT_PAIR(index1,index2));
+       }
+
+       inline void push_pair_inv(int index1,int index2)
+       {
+               push_back(BT_PAIR(index2,index1));
+       }
+};
+
+
+
+struct BT_BVH_DATA
+{
+       btAABB m_bound;
+       int m_data;
+};
+
+//! Node Structure for trees
+class BT_BVH_TREE_NODE
+{
+public:
+       btAABB m_bound;
+protected:
+       int     m_escapeIndexOrDataIndex;
+public:
+       BT_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;
+       }
+
+};
+
+
+class BT_BVH_DATA_ARRAY:public btAlignedObjectArray<BT_BVH_DATA>
+{
+};
+
+
+class BT_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray<BT_BVH_TREE_NODE>
+{
+};
+
+
+
+
+//! Basic Box tree structure
+class btBvhTree
+{
+protected:
+       int m_num_nodes;
+       BT_BVH_TREE_NODE_ARRAY m_node_array;
+protected:
+       int _sort_and_calc_splitting_index(
+               BT_BVH_DATA_ARRAY & primitive_boxes,
+                int startIndex,  int endIndex, int splitAxis);
+
+       int _calc_splitting_axis(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex);
+
+       void _build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex);
+public:
+       btBvhTree()
+       {
+               m_num_nodes = 0;
+       }
+
+       //! prototype functions for box tree management
+       //!@{
+       void build_tree(BT_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 BT_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:
+
+       //! 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 BT_BVH_TREE_NODE * get_node_pointer(int index = 0) const
+       {
+               return m_box_tree.get_node_pointer(index);
+       }
+
+//! @}
+
+       static float getAverageTreeCollisionTime();
+
+
+       static void find_collision(btGImpactBvh * boxset1, const btTransform & trans1,
+               btGImpactBvh * boxset2, const btTransform & trans2,
+               btPairSet & collision_pairs);
+};
+
+
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..60bcfe7
--- /dev/null
@@ -0,0 +1,896 @@
+/*
+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 León Nájera
+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)
+       {
+               equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal);
+               equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal);
+               equation[2] = trans.getBasis().getRow(2).dot(m_planeNormal);
+               equation[3] = trans.getOrigin().dot(m_planeNormal) + m_planeConstant;
+       }
+};
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+#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:
+       btGImpactShapeInterface * m_gim_shape;
+       btTriangleShapeEx m_trishape;
+       btTetrahedronShapeEx m_tetrashape;
+
+public:
+       class ChildShapeRetriever
+       {
+       public:
+               GIM_ShapeRetriever * m_parent;
+               virtual btCollisionShape * getChildShape(int index)
+               {
+                       return m_parent->m_gim_shape->getChildShape(index);
+               }
+       };
+
+       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;
+               }
+       };
+
+       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(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;
+       }
+
+       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, btCollisionObject* body0,btCollisionObject* body1)
+: btCollisionAlgorithm(ci)
+{
+       m_manifoldPtr = NULL;
+       m_convex_algorithm = NULL;
+}
+
+btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
+{
+       clearCache();
+}
+
+
+
+
+
+void btGImpactCollisionAlgorithm::addContactPoint(btCollisionObject * body0,
+                               btCollisionObject * body1,
+                               const btVector3 & point,
+                               const btVector3 & normal,
+                               btScalar distance)
+{
+       m_resultOut->setShapeIdentifiers(m_part0,m_triface0,m_part1,m_triface1);
+       checkManifold(body0,body1);
+       m_resultOut->addContactPoint(normal,point,distance);
+}
+
+
+void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
+                                         btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btCollisionShape * shape0,
+                                         btCollisionShape * shape1)
+{
+
+       btCollisionShape* tmpShape0 = body0->getCollisionShape();
+       btCollisionShape* tmpShape1 = body1->getCollisionShape();
+       
+       body0->internalSetTemporaryCollisionShape(shape0);
+       body1->internalSetTemporaryCollisionShape(shape1);
+
+       {
+               btCollisionAlgorithm* algor = newAlgorithm(body0,body1);
+               // post :       checkManifold is called
+
+               m_resultOut->setShapeIdentifiers(m_part0,m_triface0,m_part1,m_triface1);
+
+               algor->processCollision(body0,body1,*m_dispatchInfo,m_resultOut);
+
+               algor->~btCollisionAlgorithm();
+               m_dispatcher->freeCollisionAlgorithm(algor);
+       }
+
+       body0->internalSetTemporaryCollisionShape(tmpShape0);
+       body1->internalSetTemporaryCollisionShape(tmpShape1);
+}
+
+void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
+                                         btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btCollisionShape * shape0,
+                                         btCollisionShape * shape1)
+{
+
+       btCollisionShape* tmpShape0 = body0->getCollisionShape();
+       btCollisionShape* tmpShape1 = body1->getCollisionShape();
+       
+       body0->internalSetTemporaryCollisionShape(shape0);
+       body1->internalSetTemporaryCollisionShape(shape1);
+
+
+       m_resultOut->setShapeIdentifiers(m_part0,m_triface0,m_part1,m_triface1);
+
+       checkConvexAlgorithm(body0,body1);
+       m_convex_algorithm->processCollision(body0,body1,*m_dispatchInfo,m_resultOut);
+
+       body0->internalSetTemporaryCollisionShape(tmpShape0);
+       body1->internalSetTemporaryCollisionShape(tmpShape1);
+
+}
+
+
+
+
+void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
+                                         const btTransform & trans0,
+                                         const btTransform & trans1,
+                                         btGImpactShapeInterface * shape0,
+                                         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,
+                                         btGImpactShapeInterface * shape0,
+                                         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(btCollisionObject * body0,
+                                 btCollisionObject * body1,
+                                 btGImpactMeshShapePart * shape0,
+                                 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(body0,body1,&tri0,&tri1);
+               }
+
+       }
+
+       shape0->unlockChildShapes();
+       shape1->unlockChildShapes();
+}
+
+void btGImpactCollisionAlgorithm::collide_sat_triangles(btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btGImpactMeshShapePart * shape0,
+                                         btGImpactMeshShapePart * shape1,
+                                         const int * pairs, int pair_count)
+{
+       btTransform orgtrans0 = body0->getWorldTransform();
+       btTransform orgtrans1 = body1->getWorldTransform();
+
+       btPrimitiveTriangle ptri0;
+       btPrimitiveTriangle ptri1;
+       BT_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(body0, body1,
+                                                               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(
+                                               btCollisionObject * body0,
+                                               btCollisionObject * body1,
+                                               btGImpactShapeInterface * shape0,
+                                               btGImpactShapeInterface * shape1)
+{
+
+       if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+       {
+               btGImpactMeshShape * meshshape0 = static_cast<btGImpactMeshShape *>(shape0);
+               m_part0 = meshshape0->getMeshPartCount();
+
+               while(m_part0--)
+               {
+                       gimpact_vs_gimpact(body0,body1,meshshape0->getMeshPart(m_part0),shape1);
+               }
+
+               return;
+       }
+
+       if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+       {
+               btGImpactMeshShape * meshshape1 = static_cast<btGImpactMeshShape *>(shape1);
+               m_part1 = meshshape1->getMeshPartCount();
+
+               while(m_part1--)
+               {
+
+                       gimpact_vs_gimpact(body0,body1,shape0,meshshape1->getMeshPart(m_part1));
+
+               }
+
+               return;
+       }
+
+
+       btTransform orgtrans0 = body0->getWorldTransform();
+       btTransform orgtrans1 = body1->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)
+       {
+               btGImpactMeshShapePart * shapepart0 = static_cast<btGImpactMeshShapePart * >(shape0);
+               btGImpactMeshShapePart * shapepart1 = static_cast<btGImpactMeshShapePart * >(shape1);
+               //specialized function
+               #ifdef BULLET_TRIANGLE_COLLISION
+               collide_gjk_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
+               #else
+               collide_sat_triangles(body0,body1,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--)
+       {
+               BT_PAIR * pair = &pairset[i];
+               m_triface0 = pair->m_index1;
+               m_triface1 = pair->m_index2;
+               btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0);
+               btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1);
+
+               if(child_has_transform0)
+               {
+                       body0->setWorldTransform(orgtrans0*shape0->getChildTransform(m_triface0));
+               }
+
+               if(child_has_transform1)
+               {
+                       body1->setWorldTransform(orgtrans1*shape1->getChildTransform(m_triface1));
+               }
+
+               //collide two convex shapes
+               convex_vs_convex_collision(body0,body1,colshape0,colshape1);
+
+
+               if(child_has_transform0)
+               {
+                       body0->setWorldTransform(orgtrans0);
+               }
+
+               if(child_has_transform1)
+               {
+                       body1->setWorldTransform(orgtrans1);
+               }
+
+       }
+
+       shape0->unlockChildShapes();
+       shape1->unlockChildShapes();
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0,
+                                 btCollisionObject * body1,
+                                 btGImpactShapeInterface * shape0,
+                                 btCollisionShape * shape1,bool swapped)
+{
+       if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+       {
+               btGImpactMeshShape * meshshape0 = static_cast<btGImpactMeshShape *>(shape0);
+               m_part0 = meshshape0->getMeshPartCount();
+
+               while(m_part0--)
+               {
+
+                       gimpact_vs_shape(body0,
+                                 body1,
+                                 meshshape0->getMeshPart(m_part0),
+                                 shape1,swapped);
+
+               }
+
+               return;
+       }
+
+       #ifdef GIMPACT_VS_PLANE_COLLISION
+       if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
+               shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
+       {
+               btGImpactMeshShapePart * shapepart = static_cast<btGImpactMeshShapePart *>(shape0);
+               btStaticPlaneShape * planeshape = static_cast<btStaticPlaneShape * >(shape1);
+               gimpacttrimeshpart_vs_plane_collision(body0,body1,shapepart,planeshape,swapped);
+               return;
+       }
+
+       #endif
+
+
+
+       if(shape1->isCompound())
+       {
+               btCompoundShape * compoundshape = static_cast<btCompoundShape *>(shape1);
+               gimpact_vs_compoundshape(body0,body1,shape0,compoundshape,swapped);
+               return;
+       }
+       else if(shape1->isConcave())
+       {
+               btConcaveShape * concaveshape = static_cast<btConcaveShape *>(shape1);
+               gimpact_vs_concave(body0,body1,shape0,concaveshape,swapped);
+               return;
+       }
+
+
+       btTransform orgtrans0 = body0->getWorldTransform();
+
+       btTransform orgtrans1 = body1->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;
+
+               btCollisionShape * colshape0 = retriever0.getChildShape(child_index);
+
+               if(child_has_transform0)
+               {
+                       body0->setWorldTransform(orgtrans0*shape0->getChildTransform(child_index));
+               }
+
+               //collide two shapes
+               if(swapped)
+               {
+                       shape_vs_shape_collision(body1,body0,shape1,colshape0);
+               }
+               else
+               {
+                       shape_vs_shape_collision(body0,body1,colshape0,shape1);
+               }
+
+               //restore transforms
+               if(child_has_transform0)
+               {
+                       body0->setWorldTransform(orgtrans0);
+               }
+
+       }
+
+       shape0->unlockChildShapes();
+
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(btCollisionObject * body0,
+                                 btCollisionObject * body1,
+                                 btGImpactShapeInterface * shape0,
+                                 btCompoundShape * shape1,bool swapped)
+{
+       btTransform orgtrans1 = body1->getWorldTransform();
+
+       int i = shape1->getNumChildShapes();
+       while(i--)
+       {
+
+               btCollisionShape * colshape1 = shape1->getChildShape(i);
+               btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i);
+
+               body1->setWorldTransform(childtrans1);
+
+               //collide child shape
+               gimpact_vs_shape(body0, body1,
+                                         shape0,colshape1,swapped);
+
+
+               //restore transforms
+               body1->setWorldTransform(orgtrans1);
+       }
+}
+
+void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
+                                         btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btGImpactMeshShapePart * shape0,
+                                         btStaticPlaneShape * shape1,bool swapped)
+{
+
+
+       btTransform orgtrans0 = body0->getWorldTransform();
+       btTransform orgtrans1 = body1->getWorldTransform();
+
+       btPlaneShape * planeshape = static_cast<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(body1, body0,
+                                       vertex,
+                                       -plane,
+                                       distance);
+                       }
+                       else
+                       {
+                               addContactPoint(body0, body1,
+                                       vertex,
+                                       plane,
+                                       distance);
+                       }
+               }
+       }
+
+       shape0->unlockChildShapes();
+}
+
+
+
+
+class btGImpactTriangleCallback: public btTriangleCallback
+{
+public:
+       btGImpactCollisionAlgorithm * algorithm;
+       btCollisionObject * body0;
+       btCollisionObject * body1;
+       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);
+        }
+               algorithm->gimpact_vs_shape(
+                                                       body0,body1,gimpactshape0,&tri1,swapped);
+       }
+};
+
+
+
+
+void btGImpactCollisionAlgorithm::gimpact_vs_concave(
+                                 btCollisionObject * body0,
+                                 btCollisionObject * body1,
+                                 btGImpactShapeInterface * shape0,
+                                 btConcaveShape * shape1,bool swapped)
+{
+       //create the callback
+       btGImpactTriangleCallback tricallback;
+       tricallback.algorithm = this;
+       tricallback.body0 = body0;
+       tricallback.body1 = body1;
+       tricallback.gimpactshape0 = shape0;
+       tricallback.swapped = swapped;
+       tricallback.margin = shape1->getMargin();
+
+       //getting the trimesh AABB
+       btTransform gimpactInConcaveSpace;
+
+       gimpactInConcaveSpace = body1->getWorldTransform().inverse() * body0->getWorldTransform();
+
+       btVector3 minAABB,maxAABB;
+       shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB);
+
+       shape1->processAllTriangles(&tricallback,minAABB,maxAABB);
+
+}
+
+
+
+void btGImpactCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+    clearCache();
+
+    m_resultOut = resultOut;
+       m_dispatchInfo = &dispatchInfo;
+    btGImpactShapeInterface * gimpactshape0;
+    btGImpactShapeInterface * gimpactshape1;
+
+       if (body0->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE)
+       {
+               gimpactshape0 = static_cast<btGImpactShapeInterface *>(body0->getCollisionShape());
+
+               if( body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
+               {
+                       gimpactshape1 = static_cast<btGImpactShapeInterface *>(body1->getCollisionShape());
+
+                       gimpact_vs_gimpact(body0,body1,gimpactshape0,gimpactshape1);
+               }
+               else
+               {
+                       gimpact_vs_shape(body0,body1,gimpactshape0,body1->getCollisionShape(),false);
+               }
+
+       }
+       else if (body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
+       {
+               gimpactshape1 = static_cast<btGImpactShapeInterface *>(body1->getCollisionShape());
+
+               gimpact_vs_shape(body1,body0,gimpactshape1,body0->getCollisionShape(),true);
+       }
+}
+
+
+btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+       return 1.f;
+
+}
+
+///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
+
+btGImpactCollisionAlgorithm::CreateFunc g_gimpact_cf;
+
+//! Use this function for register the algorithm externally
+void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher * dispatcher)
+{
+
+       int i;
+
+       for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
+       {
+               dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&g_gimpact_cf);
+       }
+
+       for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
+       {
+               dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&g_gimpact_cf);
+       }
+
+}
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..8998cd0
--- /dev/null
@@ -0,0 +1,306 @@
+/*! \file btGImpactShape.h
+\author Francisco León 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 BVH_CONCAVE_COLLISION_ALGORITHM_H
+#define BVH_CONCAVE_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "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"
+
+
+
+//! 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 btCollisionAlgorithm
+{
+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(btCollisionObject* body0,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(btCollisionObject* body0,btCollisionObject* body1)
+       {
+               if(getLastManifold() == 0)
+               {
+                       newContactManifold(body0,body1);
+               }
+
+               m_resultOut->setPersistentManifold(getLastManifold());
+       }
+
+       // Call before process collision
+       SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
+       {
+               checkManifold(body0,body1);
+
+               btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm(
+                               body0,body1,getLastManifold());
+               return convex_algorithm ;
+       }
+
+       // Call before process collision
+       SIMD_FORCE_INLINE void checkConvexAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
+       {
+               if(m_convex_algorithm) return;
+               m_convex_algorithm = newAlgorithm(body0,body1);
+       }
+
+
+
+
+       void addContactPoint(btCollisionObject * body0,
+                                       btCollisionObject * body1,
+                                       const btVector3 & point,
+                                       const btVector3 & normal,
+                                       btScalar distance);
+
+//! Collision routines
+//!@{
+
+       void collide_gjk_triangles(btCollisionObject * body0,
+                                 btCollisionObject * body1,
+                                 btGImpactMeshShapePart * shape0,
+                                 btGImpactMeshShapePart * shape1,
+                                 const int * pairs, int pair_count);
+
+       void collide_sat_triangles(btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btGImpactMeshShapePart * shape0,
+                                         btGImpactMeshShapePart * shape1,
+                                         const int * pairs, int pair_count);
+
+
+
+
+       void shape_vs_shape_collision(
+                                         btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btCollisionShape * shape0,
+                                         btCollisionShape * shape1);
+
+       void convex_vs_convex_collision(btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btCollisionShape * shape0,
+                                         btCollisionShape * shape1);
+
+
+
+       void gimpact_vs_gimpact_find_pairs(
+                                         const btTransform & trans0,
+                                         const btTransform & trans1,
+                                         btGImpactShapeInterface * shape0,
+                                         btGImpactShapeInterface * shape1,btPairSet & pairset);
+
+       void gimpact_vs_shape_find_pairs(
+                                         const btTransform & trans0,
+                                         const btTransform & trans1,
+                                         btGImpactShapeInterface * shape0,
+                                         btCollisionShape * shape1,
+                                         btAlignedObjectArray<int> & collided_primitives);
+
+
+       void gimpacttrimeshpart_vs_plane_collision(
+                                         btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btGImpactMeshShapePart * shape0,
+                                         btStaticPlaneShape * shape1,bool swapped);
+
+
+public:
+
+       btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+       virtual ~btGImpactCollisionAlgorithm();
+
+       virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+       btScalar        calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+       virtual void    getAllContactManifolds(btManifoldArray& manifoldArray)
+       {
+               if (m_manifoldPtr)
+                       manifoldArray.push_back(m_manifoldPtr);
+       }
+
+
+       struct CreateFunc :public       btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm));
+                       return new(mem) btGImpactCollisionAlgorithm(ci,body0,body1);
+               }
+       };
+
+       //! Use this function for register the algorithm externally
+       static void registerAlgorithm(btCollisionDispatcher * dispatcher);
+
+       //! Gets the average time in miliseconds of tree collisions
+       static float getAverageTreeCollisionTime();
+
+       //! Gets the average time in miliseconds of triangle collisions
+       static float getAverageTriangleCollisionTime();
+
+
+       //! Collides two gimpact shapes
+       /*!
+       \pre shape0 and shape1 couldn't be btGImpactMeshShape objects
+       */
+
+
+       void gimpact_vs_gimpact(btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btGImpactShapeInterface * shape0,
+                                         btGImpactShapeInterface * shape1);
+
+       void gimpact_vs_shape(btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btGImpactShapeInterface * shape0,
+                                         btCollisionShape * shape1,bool swapped);
+
+       void gimpact_vs_compoundshape(btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btGImpactShapeInterface * shape0,
+                                         btCompoundShape * shape1,bool swapped);
+
+       void gimpact_vs_concave(
+                                         btCollisionObject * body0,
+                                         btCollisionObject * body1,
+                                         btGImpactShapeInterface * shape0,
+                                         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 //BVH_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactMassUtil.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactMassUtil.h
new file mode 100644 (file)
index 0000000..b3c4056
--- /dev/null
@@ -0,0 +1,60 @@
+/*! \file btGImpactMassUtil.h
+\author Francisco León 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_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/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
new file mode 100644 (file)
index 0000000..957cc97
--- /dev/null
@@ -0,0 +1,529 @@
+/*! \file gim_box_set.h
+\author Francisco León 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.
+*/
+
+#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(
+       BT_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(
+       BT_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(
+       BT_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);
+       }
+
+       bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+       btAssert(!unbal);
+
+       return splitIndex;
+
+}
+
+
+void btQuantizedBvhTree::_build_sub_tree(BT_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(
+       BT_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 BT_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
+       BT_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(
+       btGImpactQuantizedBvh * boxset0, 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(
+       btGImpactQuantizedBvh * boxset0, 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(btGImpactQuantizedBvh * boxset0, const btTransform & trans0,
+               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/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
new file mode 100644 (file)
index 0000000..e9e60c7
--- /dev/null
@@ -0,0 +1,379 @@
+#ifndef GIM_QUANTIZED_SET_H_INCLUDED
+#define GIM_QUANTIZED_SET_H_INCLUDED
+
+/*! \file btGImpactQuantizedBvh.h
+\author Francisco León 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.
+*/
+
+#include "btGImpactBvh.h"
+#include "btQuantization.h"
+
+
+
+/*! \defgroup BOX_TREES
+
+
+
+*/
+//! @{
+
+
+///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;
+       }
+
+};
+
+
+
+class BT_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE>
+{
+};
+
+
+
+
+//! Basic Box tree structure
+class btQuantizedBvhTree
+{
+protected:
+       int m_num_nodes;
+       BT_QUANTIZED_BVH_NODE_ARRAY m_node_array;
+       btAABB m_global_bound;
+       btVector3 m_bvhQuantization;
+protected:
+       void calc_quantization(BT_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) );
+
+       int _sort_and_calc_splitting_index(
+               BT_BVH_DATA_ARRAY & primitive_boxes,
+                int startIndex,  int endIndex, int splitAxis);
+
+       int _calc_splitting_axis(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex);
+
+       void _build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex);
+public:
+       btQuantizedBvhTree()
+       {
+               m_num_nodes = 0;
+       }
+
+       //! prototype functions for box tree management
+       //!@{
+       void build_tree(BT_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);
+       }
+
+//! @}
+
+       static float getAverageTreeCollisionTime();
+
+
+       static void find_collision(btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
+               btGImpactQuantizedBvh * boxset2, const btTransform & trans2,
+               btPairSet & collision_pairs);
+};
+
+
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp
new file mode 100644 (file)
index 0000000..da6a4db
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+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"
+
+
+#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::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);
+       }
+}
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h
new file mode 100644 (file)
index 0000000..2e16509
--- /dev/null
@@ -0,0 +1,1109 @@
+/*! \file btGImpactShape.h
+\author Francisco León 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_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() = 0;
+
+       //! gets boxset
+       SIMD_FORCE_INLINE btGImpactBoxSet * getBoxSet()
+       {
+               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
+       {
+       }
+
+       //! Function for retrieve triangles.
+       /*!
+       It gives the triangles in local space
+       */
+       virtual void    processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) 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:
+               btGImpactCompoundShape * m_compoundShape;
+
+
+               CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
+               {
+                       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);
+               }
+
+       };
+
+
+
+protected:
+       CompoundPrimitiveManager m_primitive_manager;
+       btAlignedObjectArray<btTransform>               m_childTransforms;
+       btAlignedObjectArray<btCollisionShape*> m_childShapes;
+
+
+public:
+
+       btGImpactCompoundShape(bool children_has_transform = true)
+       {
+               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
+       {
+               btAssert(0);
+       }
+
+       virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
+       {
+               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()
+       {
+               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)
+               {
+                       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;
+
+               }
+
+
+               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,int &i0,int &i1,int &i2) const
+               {
+                       if(indicestype == PHY_SHORT)
+                       {
+                               short * s_indices = (short *)(indexbase + face_index*indexstride);
+                               i0 = s_indices[0];
+                               i1 = s_indices[1];
+                               i2 = s_indices[2];
+                       }
+                       else
+                       {
+                               int * i_indices = (int *)(indexbase + face_index*indexstride);
+                               i0 = i_indices[0];
+                               i1 = i_indices[1];
+                               i2 = i_indices[2];
+                       }
+               }
+
+               SIMD_FORCE_INLINE void get_vertex(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
+               {
+                       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
+               {
+                       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)
+       {
+               m_primitive_manager.m_meshInterface = meshInterface;
+               m_primitive_manager.m_part = part;
+               m_box_set.setPrimitiveManager(&m_primitive_manager);
+       }
+
+       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
+       {
+               void * dummy = (void*)(m_box_set.getPrimitiveManager());
+               TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>(dummy);
+               dummymanager->lock();
+       }
+
+       virtual void unlockChildShapes()  const
+       {
+               void * dummy = (void*)(m_box_set.getPrimitiveManager());
+               TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>(dummy);
+               dummymanager->unlock();
+       }
+
+       //! Gets the number of children
+       virtual int     getNumChildShapes() const
+       {
+               return m_primitive_manager.get_primitive_count();
+       }
+
+
+       //! Gets the children
+       virtual btCollisionShape* getChildShape(int index)
+       {
+               btAssert(0);
+               return NULL;
+       }
+
+
+
+       //! Gets the child
+       virtual const btCollisionShape* getChildShape(int index) const
+       {
+               btAssert(0);
+               return NULL;
+       }
+
+       //! Gets the children transform
+       virtual btTransform     getChildTransform(int index) const
+       {
+               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)
+       {
+               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()
+       {
+               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
+       {
+               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;
+};
+
+
+//! 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
+{
+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)
+       {
+               buildMeshParts(meshInterface);
+       }
+
+       virtual ~btGImpactMeshShape()
+       {
+               int i = m_mesh_parts.size();
+       while(i--)
+       {
+                       btGImpactMeshShapePart * part = m_mesh_parts[i];
+                       delete part;
+       }
+               m_mesh_parts.clear();
+       }
+
+
+
+       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
+       {
+               btAssert(0);
+       }
+
+       virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
+       {
+               btAssert(0);
+       }
+
+       //! call when reading child shapes
+       virtual void lockChildShapes()
+       {
+               btAssert(0);
+       }
+
+       virtual void unlockChildShapes()
+       {
+               btAssert(0);
+       }
+
+
+
+
+       //! Retrieves the bound from a child
+    /*!
+    */
+    virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+    {
+        btAssert(0);
+    }
+
+       //! Gets the children
+       virtual btCollisionShape* getChildShape(int index)
+       {
+               btAssert(0);
+               return NULL;
+       }
+
+
+       //! Gets the child
+       virtual const btCollisionShape* getChildShape(int index) const
+       {
+               btAssert(0);
+               return NULL;
+       }
+
+       //! Gets the children transform
+       virtual btTransform     getChildTransform(int index) const
+       {
+               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)
+       {
+               btAssert(0);
+       }
+
+
+       virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType()
+       {
+               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;
+};
+
+
+#endif //GIMPACT_MESH_SHAPE_H
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp
new file mode 100644 (file)
index 0000000..a1e46e6
--- /dev/null
@@ -0,0 +1,283 @@
+/*! \file btGenericPoolAllocator.cpp
+\author Francisco León Nájera. email projectileman@yahoo.com
+
+General purpose allocator class
+*/
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, 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 BT_STANDARD_ALLOCATOR: public btGenericPoolAllocator
+{
+public:
+       BT_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE)
+       {
+       }
+};
+
+// global allocator
+BT_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/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.h b/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.h
new file mode 100644 (file)
index 0000000..0e6a585
--- /dev/null
@@ -0,0 +1,168 @@
+/*! \file btGenericPoolAllocator.h
+\author Francisco León Nájera. email projectileman@yahoo.com
+
+General purpose allocator class
+*/
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, 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 <memory.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);
+};
+
+
+
+/*! \defgroup POOL_MEMORY_FUNCTIONS
+standar managed Memory functions. Memory pools are used.
+*/
+//! @{
+void * btPoolAlloc(size_t size);
+void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize);
+void btPoolFree(void *ptr);
+//! @}
+
+
+#endif
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h b/extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h
new file mode 100644 (file)
index 0000000..72ab00e
--- /dev/null
@@ -0,0 +1,216 @@
+#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+
+/*! \file btGeometryOperations.h
+*\author Francisco León 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.
+*/
+
+#include "btBoxCollision.h"
+
+
+
+/*! \defgroup GEOMETRIC_OPERATIONS
+*/
+//! @{
+
+
+#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/extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h b/extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h
new file mode 100644 (file)
index 0000000..fd4aea4
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef BT_QUANTIZATION_H_INCLUDED
+#define BT_QUANTIZATION_H_INCLUDED
+
+/*! \file btQuantization.h
+*\author Francisco León 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.
+*/
+
+#include "LinearMath/btTransform.h"
+
+
+
+/*! \defgroup GEOMETRIC_OPERATIONS
+*/
+//! @{
+
+
+
+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 // GIM_VECTOR_H_INCLUDED
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp
new file mode 100644 (file)
index 0000000..8cb980d
--- /dev/null
@@ -0,0 +1,218 @@
+/*! \file btGImpactTriangleShape.h
+\author Francisco León 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.
+*/
+
+#include "btTriangleShapeEx.h"
+
+
+
+void BT_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, BT_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
+
+    BT_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
+    BT_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/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h b/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h
new file mode 100644 (file)
index 0000000..c5c737c
--- /dev/null
@@ -0,0 +1,180 @@
+/*! \file btGImpactShape.h
+\author Francisco León 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 TRIANGLE_SHAPE_EX_H
+#define 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 BT_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 BT_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];
+               }
+       }
+
+       BT_TRIANGLE_CONTACT()
+       {
+       }
+
+       BT_TRIANGLE_CONTACT(const BT_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, BT_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 //TRIANGLE_MESH_SHAPE_H
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h
new file mode 100644 (file)
index 0000000..80c35f7
--- /dev/null
@@ -0,0 +1,332 @@
+#ifndef GIM_ARRAY_H_INCLUDED
+#define GIM_ARRAY_H_INCLUDED
+/*! \file gim_array.h
+\author Francisco León Nájera
+*/
+/*
+-----------------------------------------------------------------------------
+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"
+
+/*! \addtogroup CONTAINERS
+\brief
+Abstract class for template containers
+*/
+//! @{
+
+#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();
+           irr_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)
+       {
+
+           if(size>m_size)
+           {
+            reserve(size);
+            if(call_constructor)
+            {
+               T obj;
+                while(m_size<size)
+                {
+                    m_data[m_size] = obj;
+                    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/extern/bullet2/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h
new file mode 100644 (file)
index 0000000..9c77ebb
--- /dev/null
@@ -0,0 +1,547 @@
+#ifndef GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+#define GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+
+/*! \file gim_basic_geometry_operations.h
+*\author Francisco León Nájera
+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"
+
+
+
+/*! \defgroup GEOMETRIC_OPERATIONS
+*/
+//! @{
+
+
+#define PLANEDIREPSILON 0.0000001f
+#define PARALELENORMALS 0.000001f
+
+
+#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/extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h
new file mode 100644 (file)
index 0000000..417aa72
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef GIM_BITSET_H_INCLUDED
+#define GIM_BITSET_H_INCLUDED
+/*! \file gim_bitset.h
+\author Francisco León Nájera
+*/
+/*
+-----------------------------------------------------------------------------
+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"
+
+/*! \addtogroup CONTAINERS
+\brief
+Abstract class for template containers
+*/
+//! @{
+
+#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/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h
new file mode 100644 (file)
index 0000000..4f825cf
--- /dev/null
@@ -0,0 +1,594 @@
+#ifndef GIM_BOX_COLLISION_H_INCLUDED
+#define GIM_BOX_COLLISION_H_INCLUDED
+
+/*! \file gim_box_collision.h
+\author Francisco León Nájera
+*/
+/*
+-----------------------------------------------------------------------------
+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"
+
+/*! \defgroup BOUND_AABB_OPERATIONS
+*/
+//! @{
+
+
+//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);
+//}
+
+#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;\
+}\
+
+
+#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 btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
+                       m_R1to0[1].dot(point) + m_T1to0.y(),
+                       m_R1to0[2].dot(point) + m_T1to0.z());
+       }
+};
+
+
+#define BOX_PLANE_EPSILON 0.000001f
+
+//! 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.dot(trans.getBasis().getRow(0).absolute()),
+                                extends.dot(trans.getBasis().getRow(1).absolute()),
+                                extends.dot(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;
+       }
+};
+
+
+//! 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/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp
new file mode 100644 (file)
index 0000000..1ffc2bb
--- /dev/null
@@ -0,0 +1,182 @@
+
+/*
+-----------------------------------------------------------------------------
+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);
+       }
+
+       bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+       btAssert(!unbal);
+
+       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/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h
new file mode 100644 (file)
index 0000000..1c6c395
--- /dev/null
@@ -0,0 +1,678 @@
+#ifndef GIM_BOX_SET_H_INCLUDED
+#define GIM_BOX_SET_H_INCLUDED
+
+/*! \file gim_box_set.h
+\author Francisco León Nájera
+*/
+/*
+-----------------------------------------------------------------------------
+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"
+
+
+/*! \defgroup BOX_PRUNNING
+
+
+
+*/
+//! @{
+
+//! Overlapping pair
+struct GIM_PAIR
+{
+    GUINT m_index1;
+    GUINT m_index2;
+    GIM_PAIR()
+    {}
+
+    GIM_PAIR(const GIM_PAIR & p)
+    {
+       m_index1 = p.m_index1;
+       m_index2 = p.m_index2;
+       }
+
+       GIM_PAIR(GUINT index1, GUINT index2)
+    {
+       m_index1 = index1;
+       m_index2 = index2;
+       }
+};
+
+//! 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:
+
+       //! 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