initial upgrade to GIMPACT 0.3, thanks to Francisco Leon for the update. GIMPACT demo/build system will be fixed today.

This commit is contained in:
ejcoumans
2007-09-30 00:05:52 +00:00
parent c98a678c9a
commit 78fe8b7249
22 changed files with 5240 additions and 1082 deletions

View File

@@ -0,0 +1,651 @@
#ifndef BT_BOX_COLLISION_H_INCLUDED
#define BT_BOX_COLLISION_H_INCLUDED
/*! \file gim_box_collision.h
\author Francisco Le<4C>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

View File

@@ -0,0 +1,186 @@
#ifndef BT_CLIP_POLYGON_H_INCLUDED
#define BT_CLIP_POLYGON_H_INCLUDED
/*! \file btClipPolygon.h
\author Francisco Le<4C>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

View File

@@ -0,0 +1,149 @@
#ifndef BT_CONTACT_H_INCLUDED
#define BT_CONTACT_H_INCLUDED
/*! \file gim_contact.h
\author Francisco Le<4C>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 "GIMPACT/Bullet/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

View File

@@ -0,0 +1,401 @@
#ifndef GIM_BOX_SET_H_INCLUDED
#define GIM_BOX_SET_H_INCLUDED
/*! \file gim_box_set.h
\author Francisco Le<4C>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 "GIMPACT/Bullet/btBoxCollision.h"
#include "GIMPACT/Bullet/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

View File

@@ -2,32 +2,23 @@
\author Francisco Le<4C>n N<>jera \author Francisco Le<4C>n N<>jera
*/ */
/* /*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library. This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/ For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com 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, This software is provided 'as-is', without any express or implied warranty.
but WITHOUT ANY WARRANTY; without even the implied warranty of In no event will the authors be held liable for any damages arising from the use of this software.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files Permission is granted to anyone to use this software for any purpose,
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
----------------------------------------------------------------------------- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, 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 #ifndef BVH_CONCAVE_COLLISION_ALGORITHM_H
@@ -47,9 +38,8 @@ class btDispatcher;
#include "GIMPACT/Bullet/btGImpactShape.h" #include "GIMPACT/Bullet/btGImpactShape.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" #include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" #include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
#include "LinearMath/btIDebugDraw.h"
@@ -65,7 +55,7 @@ class btGImpactCollisionAlgorithm : public btCollisionAlgorithm
{ {
protected: protected:
btCollisionAlgorithm * m_convex_algorithm; btCollisionAlgorithm * m_convex_algorithm;
btPersistentManifold* m_manifoldPtr; btPersistentManifold * m_manifoldPtr;
btManifoldResult* m_resultOut; btManifoldResult* m_resultOut;
const btDispatcherInfo * m_dispatchInfo; const btDispatcherInfo * m_dispatchInfo;
int m_triface0; int m_triface0;
@@ -73,10 +63,11 @@ protected:
int m_triface1; int m_triface1;
int m_part1; int m_part1;
//! Creates a new contact point
SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(btCollisionObject* body0,btCollisionObject* body1) SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(btCollisionObject* body0,btCollisionObject* body1)
{ {
clearCache(); m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
return m_manifoldPtr; return m_manifoldPtr;
} }
@@ -90,14 +81,16 @@ protected:
} }
} }
SIMD_FORCE_INLINE void destroyContactManifolds()
{
if(m_manifoldPtr == NULL) return;
m_dispatcher->releaseManifold(m_manifoldPtr);
m_manifoldPtr = NULL;
}
SIMD_FORCE_INLINE void clearCache() SIMD_FORCE_INLINE void clearCache()
{ {
if(m_manifoldPtr) destroyContactManifolds();
{
//m_manifoldPtr->clearManifold();
m_dispatcher->releaseManifold(m_manifoldPtr);
m_manifoldPtr = NULL;
}
destroyConvexAlgorithm(); destroyConvexAlgorithm();
m_triface0 = -1; m_triface0 = -1;
@@ -106,31 +99,30 @@ protected:
m_part1 = -1; m_part1 = -1;
} }
SIMD_FORCE_INLINE btPersistentManifold* getLastManifold()
{
return m_manifoldPtr;
}
// Call before process collision // Call before process collision
SIMD_FORCE_INLINE void checkManifold(btCollisionObject* body0,btCollisionObject* body1) SIMD_FORCE_INLINE void checkManifold(btCollisionObject* body0,btCollisionObject* body1)
{ {
if(m_manifoldPtr == NULL) if(getLastManifold() == 0)
{ {
newContactManifold(body0,body1); newContactManifold(body0,body1);
} }
/*else if(m_manifoldPtr->getBody0()!=body0)
{ m_resultOut->setPersistentManifold(getLastManifold());
clearCache();
newContactManifold(body0,body1);
}*/
m_resultOut->setPersistentManifold(m_manifoldPtr);
} }
// Call before process collision // Call before process collision
SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(btCollisionObject* body0,btCollisionObject* body1) SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
{ {
checkManifold(body0,body1); checkManifold(body0,body1);
/*btConvexConvexAlgorithm::CreateFunc convexcreatefunc;
btCollisionAlgorithmConstructionInfo cinfo; btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm(
cinfo.m_dispatcher = m_dispatcher; body0,body1,getLastManifold());
cinfo.m_manifold = m_manifoldPtr;*/
btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm(body0,body1,m_manifoldPtr);
return convex_algorithm ; return convex_algorithm ;
} }
@@ -144,33 +136,63 @@ protected:
SIMD_FORCE_INLINE void addContactPoint(btCollisionObject * body0, void addContactPoint(btCollisionObject * body0,
btCollisionObject * body1, btCollisionObject * body1,
const btVector3 & point, const btVector3 & point,
const btVector3 & normal, const btVector3 & normal,
btScalar distance) btScalar distance);
{
checkManifold(body0,body1);
m_resultOut->addContactPoint(normal,point,distance);
}
void gimpactcompound_vs_gimpactcompound_find_pairs( //! Collision routines
const btTransform & trans0, //!@{
const btTransform & trans1,
btGImpactCompoundShape * shape0,
btGImpactCompoundShape * shape1,gim_pair_set & pairset) const;
void gimpacttrimeshpart_vs_gimpacttrimeshpart_find_pairs( void collide_gjk_triangles(btCollisionObject * body0,
const btTransform & trans0, btCollisionObject * body1,
const btTransform & trans1, btGImpactMeshShapePart * shape0,
btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count);
void collide_sat_triangles(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0, btGImpactMeshShapePart * shape0,
btGImpactMeshShapePart * shape1,gim_pair_set & pairset) const; btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count);
void gimpactcompound_vs_gimpacttrimeshpart_find_pairs(
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 & trans0,
const btTransform & trans1, const btTransform & trans1,
btGImpactCompoundShape * shape0, btGImpactShapeInterface * shape0,
btGImpactMeshShapePart * shape1,gim_pair_set & pairset) const; 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: public:
@@ -197,92 +219,27 @@ public:
//! Use this function for register the algorithm externally //! Use this function for register the algorithm externally
static void registerAlgorithm(btCollisionDispatcher * dispatcher); static void registerAlgorithm(btCollisionDispatcher * dispatcher);
//! Collision algorithms //! 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,
void shape_vs_shape_collision(
btCollisionObject * body0,
btCollisionObject * body1, btCollisionObject * body1,
btCollisionShape * shape0, btGImpactShapeInterface * shape0,
btCollisionShape * shape1,bool swapped); btGImpactShapeInterface * shape1);
void convex_vs_convex_collision(btCollisionObject * body0, void gimpact_vs_shape(btCollisionObject * body0,
btCollisionObject * body1, btCollisionObject * body1,
btCollisionShape * shape0, btGImpactShapeInterface * shape0,
btCollisionShape * shape1);
void gimpacttrimesh_vs_shape_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShape * shape0,
btCollisionShape * shape1,bool swapped);
void gimpacttrimesh_vs_gimpacttrimesh(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShape * shape0,
btGImpactMeshShape * shape1);
void gimpacttrimesh_vs_gimpactcompound(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShape * shape0,
btGImpactCompoundShape * shape1,bool swapped);
void gimpacttrimesh_vs_trimeshpart(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShape * shape0,
btGImpactMeshShapePart * shape1,bool swapped);
void gimpactcompound_vs_gimpactcompound_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactCompoundShape * shape0,
btGImpactCompoundShape * shape1);
void gimpactcompound_vs_gimpacttrimeshpart_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactCompoundShape * shape0,
btGImpactMeshShapePart * shape1,bool swapped);
void gimpactcompound_vs_shape_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactCompoundShape * shape0,
btCollisionShape * shape1,bool swapped);
void gimpacttrimeshpart_vs_gimpacttrimeshpart_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0,
btGImpactMeshShapePart * shape1,bool swapped);
void gimpacttrimeshpart_vs_plane_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0,
btStaticPlaneShape * shape1,bool swapped);
void gimpacttrimeshpart_vs_concave_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0,
btConcaveShape * shape1,bool swapped);
void gimpacttrimeshpart_vs_shape_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0,
btCollisionShape * shape1,bool swapped); btCollisionShape * shape1,bool swapped);
void gimpact_vs_compoundshape(btCollisionObject * body0, void gimpact_vs_compoundshape(btCollisionObject * body0,
@@ -290,21 +247,26 @@ public:
btGImpactShapeInterface * shape0, btGImpactShapeInterface * shape0,
btCompoundShape * shape1,bool swapped); btCompoundShape * shape1,bool swapped);
void gimpact_vs_concave(
void gimpact_vs_shape(btCollisionObject * body0, btCollisionObject * body0,
btCollisionObject * body1, btCollisionObject * body1,
btGImpactShapeInterface * shape0, btGImpactShapeInterface * shape0,
btCollisionShape * shape1,bool swapped); btConcaveShape * shape1,bool swapped);
//!@}
void gimpact_vs_gimpact(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactShapeInterface * shape0,
btGImpactShapeInterface * shape1);
//!@}
}; };
//algorithm details
//#define BULLET_TRIANGLE_COLLISION 1
#define GIMPACT_VS_PLANE_COLLISION 1
#endif //BVH_CONCAVE_COLLISION_ALGORITHM_H #endif //BVH_CONCAVE_COLLISION_ALGORITHM_H

View File

@@ -2,32 +2,23 @@
\author Francisco Le<4C>n N<>jera \author Francisco Le<4C>n N<>jera
*/ */
/* /*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library. This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/ For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com 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, This software is provided 'as-is', without any express or implied warranty.
but WITHOUT ANY WARRANTY; without even the implied warranty of In no event will the authors be held liable for any damages arising from the use of this software.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files Permission is granted to anyone to use this software for any purpose,
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
----------------------------------------------------------------------------- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/ */

View File

@@ -0,0 +1,379 @@
#ifndef GIM_QUANTIZED_SET_H_INCLUDED
#define GIM_QUANTIZED_SET_H_INCLUDED
/*! \file btGImpactQuantizedBvh.h
\author Francisco Le<4C>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 "GIMPACT/Bullet/btGImpactBvh.h"
#include "GIMPACT/Bullet/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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,216 @@
#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
/*! \file btGeometryOperations.h
*\author Francisco Le<4C>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 "GIMPACT/Bullet/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

View File

@@ -0,0 +1,92 @@
#ifndef BT_QUANTIZATION_H_INCLUDED
#define BT_QUANTIZATION_H_INCLUDED
/*! \file btQuantization.h
*\author Francisco Le<4C>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

View File

@@ -0,0 +1,180 @@
/*! \file btGImpactShape.h
\author Francisco Le<4C>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 "GIMPACT/Bullet/btBoxCollision.h"
#include "GIMPACT/Bullet/btClipPolygon.h"
#include "GIMPACT/Bullet/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

View File

@@ -152,7 +152,7 @@ public:
const GIM_TRIANGLE_CONTACT_DATA & tricontact, const GIM_TRIANGLE_CONTACT_DATA & tricontact,
GUINT feature1,GUINT feature2) GUINT feature1,GUINT feature2)
{ {
for(GUINT i = 0;i<tricontact.m_point_count ;i++ ) for(GUINT i = 0;i<tricontact.m_point_count ;i++ )
{ {
push_back_mem(); push_back_mem();
GIM_CONTACT & newele = back(); GIM_CONTACT & newele = back();
@@ -160,7 +160,7 @@ public:
newele.m_normal = tricontact.m_separating_normal; newele.m_normal = tricontact.m_separating_normal;
newele.m_depth = tricontact.m_penetration_depth; newele.m_depth = tricontact.m_penetration_depth;
newele.m_feature1 = feature1; newele.m_feature1 = feature1;
newele.m_feature2 = feature2; newele.m_feature2 = feature2;
} }
} }

View File

@@ -7,32 +7,23 @@ GIMPACT documentation
*/ */
/* /*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library. This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/ For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com 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, This software is provided 'as-is', without any express or implied warranty.
but WITHOUT ANY WARRANTY; without even the implied warranty of In no event will the authors be held liable for any damages arising from the use of this software.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files Permission is granted to anyone to use this software for any purpose,
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
----------------------------------------------------------------------------- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/ */
/*! \mainpage GIMPACT /*! \mainpage GIMPACT

View File

@@ -0,0 +1,180 @@
/*
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 "GIMPACT/Bullet/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();
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 (int i = 0;i<contacts.size() ;i++ )
{
keycontacts.push_back(CONTACT_KEY_TOKEN(contacts[i].calc_key_contact(),i));
}
//sort keys
keycontacts.heapSort(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(int 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;
}

View File

@@ -0,0 +1,493 @@
/*! \file gim_box_set.h
\author Francisco Le<4C>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 "GIMPACT/Bullet/btGImpactBvh.h"
#include "LinearMath/btQuickprof.h"
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;
}
/////////////////////// 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);
bt_begin_gim02_tree_time();
_find_collision_pairs_recursive(
boxset0,boxset1,
&collision_pairs,trans_cache_1to0,0,0,true);
bt_end_gim02_tree_time();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,523 @@
/*! \file gim_box_set.h
\author Francisco Le<4C>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 "GIMPACT/Bullet/btGImpactQuantizedBvh.h"
#include "LinearMath/btQuickprof.h"
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;
}
/////////////////////// 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);
bt_begin_gim02_q_tree_time();
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
&collision_pairs,trans_cache_1to0,0,0,true);
bt_end_gim02_q_tree_time();
}

View File

@@ -1,30 +1,21 @@
/* /*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library. This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/ For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com 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, This software is provided 'as-is', without any express or implied warranty.
but WITHOUT ANY WARRANTY; without even the implied warranty of In no event will the authors be held liable for any damages arising from the use of this software.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files Permission is granted to anyone to use this software for any purpose,
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
----------------------------------------------------------------------------- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/ */
@@ -36,18 +27,26 @@ email: projectileman@yahoo.com
void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
{ {
lockChildShapes();
#ifdef CALC_EXACT_INERTIA #ifdef CALC_EXACT_INERTIA
inertia.setValue(0.f,0.f,0.f); inertia.setValue(0.f,0.f,0.f);
GUINT i = this->getNumChildShapes(); int i = this->getNumChildShapes();
GREAL shapemass = mass/btScalar(i); btScalar shapemass = mass/btScalar(i);
while(i--) while(i--)
{ {
btVector3 temp_inertia; btVector3 temp_inertia;
m_childShapes[i]->calculateLocalInertia(shapemass,temp_inertia); m_childShapes[i]->calculateLocalInertia(shapemass,temp_inertia);
inertia = gim_inertia_add_transformed( inertia,temp_inertia,m_childTransforms[i]); 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 #else
@@ -65,20 +64,21 @@ void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& iner
inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
#endif #endif
unlockChildShapes();
} }
void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& inertia) void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& inertia)
{ {
lock(); lockChildShapes();
#ifdef CALC_EXACT_INERTIA #ifdef CALC_EXACT_INERTIA
inertia.setValue(0.f,0.f,0.f); inertia.setValue(0.f,0.f,0.f);
GUINT i = this->getVertexCount(); int i = this->getVertexCount();
GREAL pointmass = mass/btScalar(i); btScalar pointmass = mass/btScalar(i);
while(i--) while(i--)
{ {
@@ -104,7 +104,7 @@ void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& iner
#endif #endif
unlock(); unlockChildShapes();
} }
void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
@@ -113,8 +113,8 @@ void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
#ifdef CALC_EXACT_INERTIA #ifdef CALC_EXACT_INERTIA
inertia.setValue(0.f,0.f,0.f); inertia.setValue(0.f,0.f,0.f);
GUINT i = this->getMeshPartCount(); int i = this->getMeshPartCount();
GREAL partmass = mass/btScalar(i); btScalar partmass = mass/btScalar(i);
while(i--) while(i--)
{ {
@@ -140,53 +140,42 @@ void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
#endif #endif
} }
void btGImpactCompoundShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
{
}
void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
{ {
} }
void btGImpactMeshShapePart::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
{
}
void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{ {
lock(); lockChildShapes();
GIM_AABB box; btAABB box;
box.m_min = aabbMin; box.m_min = aabbMin;
box.m_max = aabbMax; box.m_max = aabbMax;
gim_array<GUINT> collided; btAlignedObjectArray<int> collided;
m_box_set.boxQuery(box,collided); m_box_set.boxQuery(box,collided);
if(collided.size()==0) if(collided.size()==0)
{ {
unlock(); unlockChildShapes();
return; return;
} }
int part = (int)getPart(); int part = (int)getPart();
GIM_TRIANGLE triangle; btPrimitiveTriangle triangle;
GUINT i = collided.size(); int i = collided.size();
while(i--) while(i--)
{ {
this->getTriangle(collided[i],triangle); this->getPrimitiveTriangle(collided[i],triangle);
callback->processTriangle(triangle.m_vertices,part,collided[i]); callback->processTriangle(triangle.m_vertices,part,collided[i]);
} }
unlock(); unlockChildShapes();
} }
void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{ {
GUINT i = m_mesh_parts.size(); int i = m_mesh_parts.size();
while(i--) while(i--)
{ {
m_mesh_parts[i]->processAllTriangles(callback,aabbMin,aabbMax); m_mesh_parts[i]->processAllTriangles(callback,aabbMin,aabbMax);

View File

@@ -0,0 +1,216 @@
/*! \file btGImpactTriangleShape.h
\author Francisco Le<4C>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 "GIMPACT/Bullet/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];
for (int _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 (int _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;
}

View File

@@ -48,10 +48,10 @@ void gim_contact_array::merge_contacts(
//fill key contacts //fill key contacts
for (GUINT i = 0;i<contacts.size() ;i++ ) for (GUINT i = 0;i<contacts.size() ;i++ )
{ {
keycontacts[i].m_key = contacts[i].calc_key_contact(); keycontacts[i].m_key = contacts[i].calc_key_contact();
keycontacts[i].m_value = i; keycontacts[i].m_value = i;
} }
//sort keys //sort keys
@@ -121,10 +121,10 @@ void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts
GIM_CONTACT average_contact = contacts.back(); GIM_CONTACT average_contact = contacts.back();
for (GUINT i=1;i<contacts.size() ;i++ ) for (GUINT i=1;i<contacts.size() ;i++ )
{ {
average_contact.m_point += contacts[i].m_point; average_contact.m_point += contacts[i].m_point;
average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth; average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
} }
//divide //divide

View File

@@ -0,0 +1,221 @@
/*
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 "btGImpactConvexDecompositionShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
#include "ConvexBuilder.h"
class GIM_ConvexDecomposition : public ConvexDecomposition::ConvexDecompInterface
{
protected:
btGImpactConvexDecompositionShape * m_compoundShape;
public:
int mBaseCount;
int mHullCount;
bool m_transformSubShapes;
GIM_ConvexDecomposition(btGImpactConvexDecompositionShape * compoundShape,bool transformSubShapes)
{
mBaseCount = 0;
mHullCount = 0;
m_compoundShape = compoundShape;
m_transformSubShapes = transformSubShapes;
}
virtual void ConvexDecompResult(ConvexDecomposition::ConvexResult &result)
{
//calc centroid, to shift vertices around center of mass
btVector3 centroid(0,0,0);
btAlignedObjectArray<btVector3> vertices;
if(m_transformSubShapes)
{
//const unsigned int *src = result.mHullIndices;
for (unsigned int i=0; i<result.mHullVcount; i++)
{
btVector3 vertex(result.mHullVertices[i*3],result.mHullVertices[i*3+1],result.mHullVertices[i*3+2]);
centroid += vertex;
}
centroid *= 1.f/(float(result.mHullVcount) );
}
// collect vertices
for (unsigned int i=0; i<result.mHullVcount; i++)
{
btVector3 vertex(result.mHullVertices[i*3],result.mHullVertices[i*3+1],result.mHullVertices[i*3+2]);
if(m_transformSubShapes)
{
vertex -= centroid ;
}
vertices.push_back(vertex);
}
// build convex shape
btCollisionShape* convexShape = new btConvexHullShape(
&(vertices[0].getX()),vertices.size(),sizeof(btVector3));
convexShape->setMargin(m_compoundShape->getMargin());
if(m_transformSubShapes)
{
btTransform trans;
trans.setIdentity();
trans.setOrigin(centroid);
// add convex shape
m_compoundShape->addChildShape(trans,convexShape);
}
else
{
btTransform trans;
trans.setIdentity();
//trans.setOrigin(centroid);
// add convex shape
m_compoundShape->addChildShape(trans,convexShape);
//m_compoundShape->addChildShape(convexShape);
}
}
void processDecomposition(int part)
{
btGImpactMeshShapePart::TrimeshPrimitiveManager * trimeshInterface =
m_compoundShape->getTrimeshInterface(part);
trimeshInterface->lock();
//collect vertices
btAlignedObjectArray<float> vertices;
vertices.reserve(trimeshInterface->get_vertex_count()*3);
for(int vi = 0;vi<trimeshInterface->get_vertex_count();vi++)
{
btVector3 vec;
trimeshInterface->get_vertex(vi,vec);
vertices.push_back(vec[0]);
vertices.push_back(vec[1]);
vertices.push_back(vec[2]);
}
//collect indices
btAlignedObjectArray<unsigned int> indices;
indices.reserve(trimeshInterface->get_primitive_count()*3);
for(int i = 0;i<trimeshInterface->get_primitive_count();i++)
{
int i0, i1,i2;
trimeshInterface->get_indices(i,i0,i1,i2);
indices.push_back(i0);
indices.push_back(i1);
indices.push_back(i2);
}
trimeshInterface->unlock();
unsigned int depth = 5;
float cpercent = 5;
float ppercent = 15;
unsigned int maxv = 16;
float skinWidth = 0.0;
ConvexDecomposition::DecompDesc desc;
desc.mVcount = trimeshInterface->get_vertex_count();
desc.mVertices = &vertices[0];
desc.mTcount = trimeshInterface->get_primitive_count();
desc.mIndices = &indices[0];
desc.mDepth = depth;
desc.mCpercent = cpercent;
desc.mPpercent = ppercent;
desc.mMaxVertices = maxv;
desc.mSkinWidth = skinWidth;
desc.mCallback = this;
//convexDecomposition.performConvexDecomposition(desc);
ConvexBuilder cb(desc.mCallback);
cb.process(desc);
}
};
void btGImpactConvexDecompositionShape::buildConvexDecomposition(bool transformSubShapes)
{
GIM_ConvexDecomposition decomposition(this,transformSubShapes);
int part_count = m_trimeshInterfaces.size();
for (int i = 0;i<part_count ;i++ )
{
decomposition.processDecomposition(i);
}
postUpdate();
}
void btGImpactConvexDecompositionShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
int part_count = m_trimeshInterfaces.size();
for (int part = 0;part<part_count ;part++ )
{
void * ptr = (void * )&m_trimeshInterfaces[part];
btGImpactMeshShapePart::TrimeshPrimitiveManager * trimeshInterface =
static_cast<btGImpactMeshShapePart::TrimeshPrimitiveManager *>(ptr);
trimeshInterface->lock();
btPrimitiveTriangle triangle;
int i = trimeshInterface->get_primitive_count();
while(i--)
{
trimeshInterface->get_primitive_triangle(i,triangle);
callback->processTriangle(triangle.m_vertices,part,i);
}
trimeshInterface->unlock();
}
}

View File

@@ -0,0 +1,86 @@
/*! \file btGImpactConvexDecompositionShape.h
\author Francisco Le<4C>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_CONVEX_DECOMPOSITION_SHAPE_H
#define GIMPACT_CONVEX_DECOMPOSITION_SHAPE_H
#include "GIMPACT/Bullet/btGImpactShape.h" // box tree class
//! This class creates a decomposition from a trimesh.
/*!
*/
class btGImpactConvexDecompositionShape : public btGImpactCompoundShape
{
protected:
btAlignedObjectArray<btGImpactMeshShapePart::TrimeshPrimitiveManager> m_trimeshInterfaces;
void buildConvexDecomposition(bool transformSubShapes);
public:
btGImpactConvexDecompositionShape(
btStridingMeshInterface * meshInterface,
const btVector3 & mesh_scale,
btScalar margin = btScalar(0.01),bool children_has_transform = true)
:btGImpactCompoundShape(children_has_transform)
{
m_collisionMargin = margin;
btGImpactMeshShapePart::TrimeshPrimitiveManager triInterface;
triInterface.m_meshInterface = meshInterface;
triInterface.m_scale = mesh_scale;
triInterface.m_margin = btScalar(1.0);
//add parts
int part_count = meshInterface->getNumSubParts();
for (int i=0;i< part_count;i++ )
{
triInterface.m_part = i;
m_trimeshInterfaces.push_back(triInterface);
}
buildConvexDecomposition(children_has_transform);
}
virtual ~btGImpactConvexDecompositionShape()
{
}
SIMD_FORCE_INLINE btGImpactMeshShapePart::TrimeshPrimitiveManager * getTrimeshInterface(int part)
{
return &m_trimeshInterfaces[part];
}
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
};
#endif //GIMPACT_MESH_SHAPE_H