upgrade to GIMPACT 0.2
This commit is contained in:
308
Extras/GIMPACT/include/GIMPACT/Bullet/btGImpactCollisionAlgorithm.h
Executable file
308
Extras/GIMPACT/include/GIMPACT/Bullet/btGImpactCollisionAlgorithm.h
Executable file
@@ -0,0 +1,308 @@
|
||||
/*! \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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef BVH_CONCAVE_COLLISION_ALGORITHM_H
|
||||
#define BVH_CONCAVE_COLLISION_ALGORITHM_H
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
class btDispatcher;
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
#include "GIMPACT/Bullet/btGImpactShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
|
||||
|
||||
|
||||
|
||||
|
||||
//! Collision Algorithm for GImpact Shapes
|
||||
/*!
|
||||
For register this algorithm in Bullet, proceed as following:
|
||||
\code
|
||||
btCollisionDispatcher * dispatcher = static_cast<btCollisionDispatcher *>(m_dynamicsWorld ->getDispatcher());
|
||||
btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
|
||||
\endcode
|
||||
*/
|
||||
class btGImpactCollisionAlgorithm : public btCollisionAlgorithm
|
||||
{
|
||||
protected:
|
||||
btCollisionAlgorithm * m_convex_algorithm;
|
||||
btPersistentManifold* m_manifoldPtr;
|
||||
btManifoldResult* m_resultOut;
|
||||
const btDispatcherInfo * m_dispatchInfo;
|
||||
int m_triface0;
|
||||
int m_part0;
|
||||
int m_triface1;
|
||||
int m_part1;
|
||||
|
||||
SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
clearCache();
|
||||
m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
|
||||
return m_manifoldPtr;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void destroyConvexAlgorithm()
|
||||
{
|
||||
if(m_convex_algorithm)
|
||||
{
|
||||
delete m_convex_algorithm;
|
||||
m_convex_algorithm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void clearCache()
|
||||
{
|
||||
if(m_manifoldPtr)
|
||||
{
|
||||
//m_manifoldPtr->clearManifold();
|
||||
m_dispatcher->releaseManifold(m_manifoldPtr);
|
||||
m_manifoldPtr = NULL;
|
||||
}
|
||||
destroyConvexAlgorithm();
|
||||
|
||||
m_triface0 = -1;
|
||||
m_part0 = -1;
|
||||
m_triface1 = -1;
|
||||
m_part1 = -1;
|
||||
}
|
||||
|
||||
|
||||
// Call before process collision
|
||||
SIMD_FORCE_INLINE void checkManifold(btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
if(m_manifoldPtr == NULL)
|
||||
{
|
||||
newContactManifold(body0,body1);
|
||||
}
|
||||
/*else if(m_manifoldPtr->getBody0()!=body0)
|
||||
{
|
||||
clearCache();
|
||||
newContactManifold(body0,body1);
|
||||
}*/
|
||||
m_resultOut->setPersistentManifold(m_manifoldPtr);
|
||||
}
|
||||
|
||||
// Call before process collision
|
||||
SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
checkManifold(body0,body1);
|
||||
/*btConvexConvexAlgorithm::CreateFunc convexcreatefunc;
|
||||
btCollisionAlgorithmConstructionInfo cinfo;
|
||||
cinfo.m_dispatcher = m_dispatcher;
|
||||
cinfo.m_manifold = m_manifoldPtr;*/
|
||||
btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm(body0,body1,m_manifoldPtr);
|
||||
return convex_algorithm ;
|
||||
}
|
||||
|
||||
// Call before process collision
|
||||
SIMD_FORCE_INLINE void checkConvexAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
if(m_convex_algorithm) return;
|
||||
m_convex_algorithm = newAlgorithm(body0,body1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE void addContactPoint(btCollisionObject * body0,
|
||||
btCollisionObject * body1,
|
||||
const btVector3 & point,
|
||||
const btVector3 & normal,
|
||||
btScalar distance)
|
||||
{
|
||||
checkManifold(body0,body1);
|
||||
m_resultOut->addContactPoint(normal,point,distance);
|
||||
}
|
||||
|
||||
void gimpactcompound_vs_gimpactcompound_find_pairs(
|
||||
const btTransform & trans0,
|
||||
const btTransform & trans1,
|
||||
btGImpactCompoundShape * shape0,
|
||||
btGImpactCompoundShape * shape1,gim_pair_set & pairset) const;
|
||||
|
||||
void gimpacttrimeshpart_vs_gimpacttrimeshpart_find_pairs(
|
||||
const btTransform & trans0,
|
||||
const btTransform & trans1,
|
||||
btGImpactMeshShapePart * shape0,
|
||||
btGImpactMeshShapePart * shape1,gim_pair_set & pairset) const;
|
||||
|
||||
void gimpactcompound_vs_gimpacttrimeshpart_find_pairs(
|
||||
const btTransform & trans0,
|
||||
const btTransform & trans1,
|
||||
btGImpactCompoundShape * shape0,
|
||||
btGImpactMeshShapePart * shape1,gim_pair_set & pairset) const;
|
||||
|
||||
public:
|
||||
|
||||
btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
|
||||
|
||||
virtual ~btGImpactCollisionAlgorithm();
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
|
||||
|
||||
|
||||
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
return new btGImpactCollisionAlgorithm(ci,body0,body1);
|
||||
}
|
||||
};
|
||||
|
||||
//! Use this function for register the algorithm externally
|
||||
static void registerAlgorithm(btCollisionDispatcher * dispatcher);
|
||||
|
||||
//! Collision algorithms
|
||||
//!@{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void shape_vs_shape_collision(
|
||||
btCollisionObject * body0,
|
||||
btCollisionObject * body1,
|
||||
btCollisionShape * shape0,
|
||||
btCollisionShape * shape1,bool swapped);
|
||||
|
||||
void convex_vs_convex_collision(btCollisionObject * body0,
|
||||
btCollisionObject * body1,
|
||||
btCollisionShape * 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);
|
||||
|
||||
void gimpact_vs_compoundshape(btCollisionObject * body0,
|
||||
btCollisionObject * body1,
|
||||
btGImpactShapeInterface * shape0,
|
||||
btCompoundShape * shape1,bool swapped);
|
||||
|
||||
|
||||
void gimpact_vs_shape(btCollisionObject * body0,
|
||||
btCollisionObject * body1,
|
||||
btGImpactShapeInterface * shape0,
|
||||
btCollisionShape * shape1,bool swapped);
|
||||
|
||||
void gimpact_vs_gimpact(btCollisionObject * body0,
|
||||
btCollisionObject * body1,
|
||||
btGImpactShapeInterface * shape0,
|
||||
btGImpactShapeInterface * shape1);
|
||||
|
||||
//!@}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //BVH_CONCAVE_COLLISION_ALGORITHM_H
|
||||
69
Extras/GIMPACT/include/GIMPACT/Bullet/btGImpactMassUtil.h
Executable file
69
Extras/GIMPACT/include/GIMPACT/Bullet/btGImpactMassUtil.h
Executable file
@@ -0,0 +1,69 @@
|
||||
/*! \file btGImpactMassUtil.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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GIMPACT_MASS_UTIL_H
|
||||
#define GIMPACT_MASS_UTIL_H
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed(
|
||||
const btVector3 & source_inertia, const btVector3 & added_inertia, const btTransform & transform)
|
||||
{
|
||||
btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose();
|
||||
|
||||
btScalar x2 = transform.getOrigin()[0];
|
||||
x2*= x2;
|
||||
btScalar y2 = transform.getOrigin()[1];
|
||||
y2*= y2;
|
||||
btScalar z2 = transform.getOrigin()[2];
|
||||
z2*= z2;
|
||||
|
||||
btScalar ix = rotatedTensor[0][0]*(y2+z2);
|
||||
btScalar iy = rotatedTensor[1][1]*(x2+z2);
|
||||
btScalar iz = rotatedTensor[2][2]*(x2+y2);
|
||||
|
||||
return btVector3(source_inertia[0]+ix,source_inertia[1]+iy,source_inertia[2] + iz);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3 & point, btScalar mass)
|
||||
{
|
||||
btScalar x2 = point[0]*point[0];
|
||||
btScalar y2 = point[1]*point[1];
|
||||
btScalar z2 = point[2]*point[2];
|
||||
return btVector3(mass*(y2+z2),mass*(x2+z2),mass*(x2+y2));
|
||||
}
|
||||
|
||||
|
||||
#endif //GIMPACT_MESH_SHAPE_H
|
||||
811
Extras/GIMPACT/include/GIMPACT/Bullet/btGImpactShape.h
Executable file
811
Extras/GIMPACT/include/GIMPACT/Bullet/btGImpactShape.h
Executable file
@@ -0,0 +1,811 @@
|
||||
/*! \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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GIMPACT_SHAPE_H
|
||||
#define GIMPACT_SHAPE_H
|
||||
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
|
||||
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
|
||||
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "LinearMath/btMatrix3x3.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
#include "GIMPACT/core/gim_box_set.h"
|
||||
|
||||
|
||||
enum eGIMPACT_SHAPE_TYPE
|
||||
{
|
||||
CONST_GIMPACT_COMPOUND_SHAPE = 0,
|
||||
CONST_GIMPACT_TRIMESH_SHAPE_PART,
|
||||
CONST_GIMPACT_TRIMESH_SHAPE
|
||||
};
|
||||
|
||||
//! Base class for gimpact shapes
|
||||
class btGImpactShapeInterface : public btConcaveShape
|
||||
{
|
||||
protected:
|
||||
GIM_AABB m_localAABB;
|
||||
bool m_needs_update;
|
||||
btVector3 localScaling;
|
||||
|
||||
//! use this function for perfofm refit in bounding boxes
|
||||
virtual void calcLocalAABB() = 0;
|
||||
|
||||
|
||||
public:
|
||||
btGImpactShapeInterface()
|
||||
{
|
||||
m_localAABB.invalidate();
|
||||
m_needs_update = true;
|
||||
localScaling.setValue(1.f,1.f,1.f);
|
||||
}
|
||||
|
||||
|
||||
//! performs refit operation
|
||||
/*!
|
||||
Updates the entire Box set of this shape.
|
||||
\pre postUpdate() must be called for attemps to calculating the box set, else this function
|
||||
will does nothing.
|
||||
\post if m_needs_update == true, then it calls calcLocalAABB();
|
||||
*/
|
||||
SIMD_FORCE_INLINE void updateBound()
|
||||
{
|
||||
if(!m_needs_update) return;
|
||||
calcLocalAABB();
|
||||
m_needs_update = false;
|
||||
}
|
||||
|
||||
//! If the Bounding box is not updated, then this class attemps to calculate it.
|
||||
/*!
|
||||
\post Calls updateBound() for update the box set.
|
||||
*/
|
||||
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
||||
{
|
||||
GIM_AABB transformedbox = m_localAABB;
|
||||
transformedbox.appy_transform(t);
|
||||
aabbMin = transformedbox.m_min;
|
||||
aabbMax = transformedbox.m_max;
|
||||
}
|
||||
|
||||
//! Tells to this object that is needed to refit the box set
|
||||
virtual void postUpdate()
|
||||
{
|
||||
m_needs_update = true;
|
||||
}
|
||||
|
||||
//! Obtains the local box, which is the global calculated box of the total of subshapes
|
||||
const GIM_AABB & getLocalBox()
|
||||
{
|
||||
return m_localAABB;
|
||||
}
|
||||
|
||||
|
||||
virtual int getShapeType() const
|
||||
{
|
||||
return GIMPACT_SHAPE_PROXYTYPE;
|
||||
}
|
||||
|
||||
//! Base method for determinig which kind of GIMPACT shape we get
|
||||
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() = 0;
|
||||
|
||||
//! Determines if this class has a hierarchy structure for sorting its primitives
|
||||
virtual bool hasBoxSet() const = 0;
|
||||
|
||||
/*!
|
||||
\post You must call updateBound() for update the box set.
|
||||
*/
|
||||
virtual void setLocalScaling(const btVector3& scaling)
|
||||
{
|
||||
localScaling = scaling;
|
||||
postUpdate();
|
||||
}
|
||||
virtual const btVector3& getLocalScaling() const
|
||||
{
|
||||
return localScaling;
|
||||
}
|
||||
|
||||
|
||||
//! virtual method for ray collision
|
||||
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
|
||||
{
|
||||
}
|
||||
|
||||
//! Function for retrieve triangles.
|
||||
/*!
|
||||
It gives the triangles in local space
|
||||
*/
|
||||
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
|
||||
{
|
||||
}
|
||||
|
||||
//!@}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! btGIMPACTCompoundShape allows to handle multiple btCollisionShape objects at once
|
||||
/*!
|
||||
This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape.
|
||||
*/
|
||||
class btGImpactCompoundShape : public btGImpactShapeInterface
|
||||
{
|
||||
public:
|
||||
//! compound primitive manager
|
||||
class CompoundPrimitiveManager
|
||||
{
|
||||
public:
|
||||
btGImpactCompoundShape * m_compoundShape;
|
||||
|
||||
CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
|
||||
{
|
||||
m_compoundShape = compound.m_compoundShape;
|
||||
}
|
||||
|
||||
CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape)
|
||||
{
|
||||
m_compoundShape = compoundShape;
|
||||
}
|
||||
|
||||
CompoundPrimitiveManager()
|
||||
{
|
||||
m_compoundShape = NULL;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool is_trimesh() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT get_primitive_count() const
|
||||
{
|
||||
return (GUINT )m_compoundShape->getNumChildShapes();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) const
|
||||
{
|
||||
btTransform prim_trans = m_compoundShape->getChildTransform(prim_index);
|
||||
const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index);
|
||||
shape->getAabb(prim_trans,primbox.m_min,primbox.m_max);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) const
|
||||
{
|
||||
btAssert(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class BoxSetClass: public GIM_BOX_TREE_SET<CompoundPrimitiveManager>
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
BoxSetClass m_box_set;
|
||||
btAlignedObjectArray<btTransform> m_childTransforms;
|
||||
btAlignedObjectArray<btCollisionShape*> m_childShapes;
|
||||
|
||||
|
||||
//! use this function for perfofm refit in bounding boxes
|
||||
virtual void calcLocalAABB()
|
||||
{
|
||||
if(m_box_set.getNodeCount() == 0)
|
||||
{
|
||||
m_box_set.buildSet();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_box_set.update();
|
||||
}
|
||||
|
||||
m_localAABB = m_box_set.getGlobalBox();
|
||||
}
|
||||
public:
|
||||
|
||||
btGImpactCompoundShape()
|
||||
{
|
||||
m_box_set.setPrimitiveManager(CompoundPrimitiveManager(this));
|
||||
}
|
||||
|
||||
virtual ~btGImpactCompoundShape()
|
||||
{
|
||||
}
|
||||
|
||||
//! Obtains the primitive manager
|
||||
SIMD_FORCE_INLINE const CompoundPrimitiveManager & getPrimitiveManager() const
|
||||
{
|
||||
return m_box_set.getPrimitiveManager();
|
||||
}
|
||||
|
||||
//! Use this method for adding children
|
||||
void addChildShape(const btTransform& localTransform,btCollisionShape* shape)
|
||||
{
|
||||
m_childTransforms.push_back(localTransform);
|
||||
m_childShapes.push_back(shape);
|
||||
}
|
||||
|
||||
//! Gets the number of children
|
||||
int getNumChildShapes() const
|
||||
{
|
||||
return int (m_childShapes.size());
|
||||
}
|
||||
|
||||
//! Gets the children
|
||||
btCollisionShape* getChildShape(int index)
|
||||
{
|
||||
return m_childShapes[index];
|
||||
}
|
||||
|
||||
//! Gets the children
|
||||
const btCollisionShape* getChildShape(int index) const
|
||||
{
|
||||
return m_childShapes[index];
|
||||
}
|
||||
|
||||
//! Gets the children transform
|
||||
btTransform getChildTransform(int index) const
|
||||
{
|
||||
return m_childTransforms[index];
|
||||
}
|
||||
|
||||
//! Sets the children transform
|
||||
/*!
|
||||
\post You must call updateBound() for update the box set.
|
||||
*/
|
||||
void setChildTransform(int index, const btTransform & transform)
|
||||
{
|
||||
m_childTransforms[index] = transform;
|
||||
postUpdate();
|
||||
}
|
||||
|
||||
//! Calculates the exact inertia tensor for this shape
|
||||
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
|
||||
|
||||
|
||||
BoxSetClass * getBoxSet()
|
||||
{
|
||||
return &m_box_set;
|
||||
}
|
||||
|
||||
virtual char* getName()const
|
||||
{
|
||||
return "GImpactCompound";
|
||||
}
|
||||
|
||||
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType()
|
||||
{
|
||||
return CONST_GIMPACT_COMPOUND_SHAPE;
|
||||
}
|
||||
|
||||
virtual bool hasBoxSet() const
|
||||
{
|
||||
if(m_box_set.getNodeCount() == 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
//! 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(const btVector3& p0,const btVector3& p1,const btVector3& p2): btTriangleShape(p0,p1,p2)
|
||||
{
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
GIM_AABB trianglebox(tv0,tv1,tv2,m_collisionMargin);
|
||||
aabbMin = trianglebox.m_min;
|
||||
aabbMax = trianglebox.m_max;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface.
|
||||
/*!
|
||||
- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh
|
||||
- When making operations with this shape, you must call <b>lock</b> before accessing to the trimesh primitives, and then call <b>unlock</b>
|
||||
- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
|
||||
|
||||
*/
|
||||
class btGImpactMeshShapePart : public btGImpactShapeInterface
|
||||
{
|
||||
public:
|
||||
//! Trimesh primitive manager
|
||||
/*!
|
||||
Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism
|
||||
*/
|
||||
class TrimeshPrimitiveManager
|
||||
{
|
||||
public:
|
||||
btScalar m_margin;
|
||||
btStridingMeshInterface * m_meshInterface;
|
||||
btVector3 m_scale;
|
||||
int m_part;
|
||||
GUINT m_lock_count;
|
||||
const unsigned char *vertexbase;
|
||||
int numverts;
|
||||
PHY_ScalarType type;
|
||||
int stride;
|
||||
const unsigned char *indexbase;
|
||||
int indexstride;
|
||||
int numfaces;
|
||||
PHY_ScalarType indicestype;
|
||||
|
||||
TrimeshPrimitiveManager()
|
||||
{
|
||||
m_meshInterface = NULL;
|
||||
m_part = 0;
|
||||
m_margin = 0.1f;
|
||||
m_scale = btVector3(1.f,1.f,1.f);
|
||||
m_lock_count = 0;
|
||||
vertexbase = 0;
|
||||
numverts = 0;
|
||||
stride = 0;
|
||||
indexbase = 0;
|
||||
indexstride = 0;
|
||||
numfaces = 0;
|
||||
}
|
||||
|
||||
TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager)
|
||||
{
|
||||
m_meshInterface = manager.m_meshInterface;
|
||||
m_part = manager.m_part;
|
||||
m_margin = manager.m_margin;
|
||||
m_scale = manager.m_meshInterface->getScaling();
|
||||
m_lock_count = 0;
|
||||
vertexbase = 0;
|
||||
numverts = 0;
|
||||
stride = 0;
|
||||
indexbase = 0;
|
||||
indexstride = 0;
|
||||
numfaces = 0;
|
||||
|
||||
}
|
||||
|
||||
TrimeshPrimitiveManager(
|
||||
btStridingMeshInterface * meshInterface, int part)
|
||||
{
|
||||
m_meshInterface = meshInterface;
|
||||
m_part = part;
|
||||
m_scale = m_meshInterface->getScaling();
|
||||
m_margin = 0.1f;
|
||||
m_lock_count = 0;
|
||||
vertexbase = 0;
|
||||
numverts = 0;
|
||||
stride = 0;
|
||||
indexbase = 0;
|
||||
indexstride = 0;
|
||||
numfaces = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void lock()
|
||||
{
|
||||
if(m_lock_count>0)
|
||||
{
|
||||
m_lock_count++;
|
||||
return;
|
||||
}
|
||||
m_meshInterface->getLockedReadOnlyVertexIndexBase(
|
||||
&vertexbase,numverts,
|
||||
type, stride,&indexbase, indexstride, numfaces,indicestype,m_part);
|
||||
|
||||
m_lock_count = 1;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
if(m_lock_count == 0) return;
|
||||
if(m_lock_count>1)
|
||||
{
|
||||
--m_lock_count;
|
||||
return;
|
||||
}
|
||||
m_meshInterface->unLockReadOnlyVertexBase(m_part);
|
||||
vertexbase = NULL;
|
||||
m_lock_count = 0;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool is_trimesh() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT get_primitive_count() const
|
||||
{
|
||||
return (GUINT )numfaces;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT get_vertex_count() const
|
||||
{
|
||||
return (GUINT )numverts;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void get_indices(GUINT face_index,GUINT &i0,GUINT &i1,GUINT &i2) const
|
||||
{
|
||||
if(indicestype == PHY_SHORT)
|
||||
{
|
||||
GUSHORT * s_indices = (GUSHORT *)(indexbase + face_index*indexstride);
|
||||
i0 = s_indices[0];
|
||||
i1 = s_indices[1];
|
||||
i2 = s_indices[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
GUINT * i_indices = (GUINT *)(indexbase + face_index*indexstride);
|
||||
i0 = i_indices[0];
|
||||
i1 = i_indices[1];
|
||||
i2 = i_indices[2];
|
||||
}
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void get_vertex(GUINT vertex_index, btVector3 & vertex) const
|
||||
{
|
||||
if(indicestype == PHY_DOUBLE)
|
||||
{
|
||||
double * dvertices = (double *)(vertexbase + vertex_index*stride);
|
||||
vertex[0] = btScalar(dvertices[0]*m_scale[0]);
|
||||
vertex[1] = btScalar(dvertices[1]*m_scale[1]);
|
||||
vertex[2] = btScalar(dvertices[2]*m_scale[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
float * svertices = (float *)(vertexbase + vertex_index*stride);
|
||||
vertex[0] = svertices[0]*m_scale[0];
|
||||
vertex[1] = svertices[1]*m_scale[1];
|
||||
vertex[2] = svertices[2]*m_scale[2];
|
||||
}
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) const
|
||||
{
|
||||
GIM_TRIANGLE triangle;
|
||||
get_primitive_triangle(prim_index,triangle);
|
||||
primbox = triangle.get_box();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) const
|
||||
{
|
||||
GUINT indices[3];
|
||||
get_indices(prim_index,indices[0],indices[1],indices[2]);
|
||||
get_vertex(indices[0],triangle.m_vertices[0]);
|
||||
get_vertex(indices[1],triangle.m_vertices[1]);
|
||||
get_vertex(indices[2],triangle.m_vertices[2]);
|
||||
triangle.m_margin = m_margin;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void get_bullet_triangle(GUINT prim_index,btTriangleShapeEx & triangle) const
|
||||
{
|
||||
GUINT indices[3];
|
||||
get_indices(prim_index,indices[0],indices[1],indices[2]);
|
||||
get_vertex(indices[0],triangle.m_vertices1[0]);
|
||||
get_vertex(indices[1],triangle.m_vertices1[1]);
|
||||
get_vertex(indices[2],triangle.m_vertices1[2]);
|
||||
triangle.setMargin(m_margin);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class BoxSetClass: public GIM_BOX_TREE_SET<TrimeshPrimitiveManager>
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
BoxSetClass m_box_set;
|
||||
|
||||
//! use this function for perfofm refit in bounding boxes
|
||||
virtual void calcLocalAABB()
|
||||
{
|
||||
lock();
|
||||
if(m_box_set.getNodeCount() == 0)
|
||||
{
|
||||
m_box_set.buildSet();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_box_set.update();
|
||||
}
|
||||
unlock();
|
||||
|
||||
m_localAABB = m_box_set.getGlobalBox();
|
||||
}
|
||||
public:
|
||||
|
||||
btGImpactMeshShapePart()
|
||||
{
|
||||
}
|
||||
|
||||
btGImpactMeshShapePart(const btGImpactMeshShapePart & meshpart)
|
||||
{
|
||||
m_box_set.setPrimitiveManager(meshpart.getPrimitiveManager());
|
||||
}
|
||||
|
||||
|
||||
btGImpactMeshShapePart(btStridingMeshInterface * meshInterface, int part)
|
||||
{
|
||||
m_box_set.setPrimitiveManager(TrimeshPrimitiveManager(meshInterface,part));
|
||||
}
|
||||
|
||||
virtual ~btGImpactMeshShapePart()
|
||||
{
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE const TrimeshPrimitiveManager & getPrimitiveManager() const
|
||||
{
|
||||
return m_box_set.getPrimitiveManager();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void lock() const
|
||||
{
|
||||
void * dummy = (void*)(& m_box_set.getPrimitiveManager());
|
||||
TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>(dummy);
|
||||
dummymanager->lock();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void unlock() const
|
||||
{
|
||||
void * dummy = (void*)(&m_box_set.getPrimitiveManager());
|
||||
TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>(dummy);
|
||||
dummymanager->unlock();
|
||||
}
|
||||
|
||||
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
|
||||
|
||||
SIMD_FORCE_INLINE BoxSetClass * getBoxSet()
|
||||
{
|
||||
return &m_box_set;
|
||||
}
|
||||
|
||||
virtual char* getName()const
|
||||
{
|
||||
return "GImpactMeshShapePart";
|
||||
}
|
||||
|
||||
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType()
|
||||
{
|
||||
return CONST_GIMPACT_TRIMESH_SHAPE_PART;
|
||||
}
|
||||
|
||||
virtual bool hasBoxSet() const
|
||||
{
|
||||
if(m_box_set.getNodeCount() == 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getTriangleCount() const
|
||||
{
|
||||
return m_box_set.getPrimitiveManager().get_primitive_count();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void getTriangle(GUINT triangle_index, GIM_TRIANGLE & triangle) const
|
||||
{
|
||||
m_box_set.getPrimitiveManager().get_primitive_triangle(triangle_index,triangle);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void getBulletTriangle(GUINT prim_index,btTriangleShapeEx & triangle) const
|
||||
{
|
||||
m_box_set.getPrimitiveManager().get_bullet_triangle(prim_index,triangle);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getVertexCount() const
|
||||
{
|
||||
return m_box_set.getPrimitiveManager().get_vertex_count();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void getVertex(GUINT vertex_index, btVector3 & vertex) const
|
||||
{
|
||||
m_box_set.getPrimitiveManager().get_vertex(vertex_index,vertex);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void setMargin(btScalar margin)
|
||||
{
|
||||
m_box_set.getPrimitiveManager().m_margin = margin;
|
||||
postUpdate();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE btScalar getMargin() const
|
||||
{
|
||||
return m_box_set.getPrimitiveManager().m_margin;
|
||||
}
|
||||
|
||||
virtual void setLocalScaling(const btVector3& scaling)
|
||||
{
|
||||
m_box_set.getPrimitiveManager().m_scale = scaling;
|
||||
postUpdate();
|
||||
}
|
||||
|
||||
virtual const btVector3& getLocalScaling() const
|
||||
{
|
||||
return m_box_set.getPrimitiveManager().m_scale;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getPart() const
|
||||
{
|
||||
return (GUINT)m_box_set.getPrimitiveManager().m_part;
|
||||
}
|
||||
|
||||
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
|
||||
|
||||
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||
};
|
||||
|
||||
|
||||
//! This class manages a mesh supplied by the btStridingMeshInterface interface.
|
||||
/*!
|
||||
Set of btGImpactMeshShapePart parts
|
||||
- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh
|
||||
|
||||
- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
|
||||
|
||||
*/
|
||||
|
||||
class btGImpactMeshShape : public btGImpactShapeInterface
|
||||
{
|
||||
protected:
|
||||
btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts;
|
||||
void buildMeshParts(btStridingMeshInterface * meshInterface)
|
||||
{
|
||||
for (int i=0;i<meshInterface->getNumSubParts() ;++i )
|
||||
{
|
||||
btGImpactMeshShapePart * newpart = new btGImpactMeshShapePart(meshInterface,i);
|
||||
m_mesh_parts.push_back(newpart);
|
||||
}
|
||||
}
|
||||
|
||||
//! use this function for perfofm refit in bounding boxes
|
||||
virtual void calcLocalAABB()
|
||||
{
|
||||
m_localAABB.invalidate();
|
||||
int i = m_mesh_parts.size();
|
||||
while(i--)
|
||||
{
|
||||
m_mesh_parts[i]->updateBound();
|
||||
m_localAABB.merge(m_mesh_parts[i]->getLocalBox());
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
btGImpactMeshShape(btStridingMeshInterface * meshInterface)
|
||||
{
|
||||
buildMeshParts(meshInterface);
|
||||
}
|
||||
|
||||
virtual ~btGImpactMeshShape()
|
||||
{
|
||||
int i = m_mesh_parts.size();
|
||||
while(i--)
|
||||
{
|
||||
btGImpactMeshShapePart * part = m_mesh_parts[i];
|
||||
delete part;
|
||||
}
|
||||
m_mesh_parts.clear();
|
||||
}
|
||||
|
||||
int getMeshPartCount()
|
||||
{
|
||||
return m_mesh_parts.size();
|
||||
}
|
||||
|
||||
btGImpactMeshShapePart * getMeshPart(int index)
|
||||
{
|
||||
return m_mesh_parts[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
const btGImpactMeshShapePart * getMeshPart(int index) const
|
||||
{
|
||||
return m_mesh_parts[index];
|
||||
}
|
||||
|
||||
|
||||
virtual void setLocalScaling(const btVector3& scaling)
|
||||
{
|
||||
localScaling = scaling;
|
||||
|
||||
int i = m_mesh_parts.size();
|
||||
while(i--)
|
||||
{
|
||||
btGImpactMeshShapePart * part = m_mesh_parts[i];
|
||||
part->setLocalScaling(scaling);
|
||||
}
|
||||
|
||||
m_needs_update = true;
|
||||
}
|
||||
|
||||
//! Tells to this object that is needed to refit all the meshes
|
||||
virtual void postUpdate()
|
||||
{
|
||||
int i = m_mesh_parts.size();
|
||||
while(i--)
|
||||
{
|
||||
btGImpactMeshShapePart * part = m_mesh_parts[i];
|
||||
part->postUpdate();
|
||||
}
|
||||
|
||||
m_needs_update = true;
|
||||
}
|
||||
|
||||
|
||||
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
|
||||
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType()
|
||||
{
|
||||
return CONST_GIMPACT_TRIMESH_SHAPE;
|
||||
}
|
||||
|
||||
virtual bool hasBoxSet() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual char* getName()const
|
||||
{
|
||||
return "GImpactMesh";
|
||||
}
|
||||
|
||||
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
|
||||
|
||||
//! Function for retrieve triangles.
|
||||
/*!
|
||||
It gives the triangles in local space
|
||||
*/
|
||||
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||
};
|
||||
|
||||
|
||||
#endif //GIMPACT_MESH_SHAPE_H
|
||||
332
Extras/GIMPACT/include/GIMPACT/core/gim_array.h
Executable file
332
Extras/GIMPACT/include/GIMPACT/core/gim_array.h
Executable file
@@ -0,0 +1,332 @@
|
||||
#ifndef GIM_ARRAY_H_INCLUDED
|
||||
#define GIM_ARRAY_H_INCLUDED
|
||||
/*! \file gim_array.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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "GIMPACT/core/gim_memory.h"
|
||||
|
||||
/*! \addtogroup CONTAINERS
|
||||
\brief
|
||||
Abstract class for template containers
|
||||
*/
|
||||
//! @{
|
||||
|
||||
#define GIM_ARRAY_GROW_INCREMENT 2
|
||||
#define GIM_ARRAY_GROW_FACTOR 2
|
||||
|
||||
//! Very simple array container with fast access and simd memory
|
||||
template<typename T>
|
||||
class gim_array
|
||||
{
|
||||
public:
|
||||
//! properties
|
||||
//!@{
|
||||
T *m_data;
|
||||
GUINT m_size;
|
||||
GUINT m_allocated_size;
|
||||
//!@}
|
||||
//! protected operations
|
||||
//!@{
|
||||
|
||||
inline void destroyData()
|
||||
{
|
||||
m_allocated_size = 0;
|
||||
if(m_data==NULL) return;
|
||||
gim_free(m_data);
|
||||
m_data = NULL;
|
||||
}
|
||||
|
||||
inline bool resizeData(GUINT newsize)
|
||||
{
|
||||
if(newsize==0)
|
||||
{
|
||||
destroyData();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(m_size>0)
|
||||
{
|
||||
m_data = (T*)gim_realloc(m_data,m_size*sizeof(T),newsize*sizeof(T));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data = (T*)gim_alloc(newsize*sizeof(T));
|
||||
}
|
||||
m_allocated_size = newsize;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool growingCheck()
|
||||
{
|
||||
if(m_allocated_size<=m_size)
|
||||
{
|
||||
GUINT requestsize = m_size;
|
||||
m_size = m_allocated_size;
|
||||
if(resizeData((requestsize+GIM_ARRAY_GROW_INCREMENT)*GIM_ARRAY_GROW_FACTOR)==false) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//!@}
|
||||
//! public operations
|
||||
//!@{
|
||||
inline bool reserve(GUINT size)
|
||||
{
|
||||
if(m_allocated_size>=size) return false;
|
||||
return resizeData(size);
|
||||
}
|
||||
|
||||
inline void clear_range(GUINT start_range)
|
||||
{
|
||||
while(m_size>start_range)
|
||||
{
|
||||
m_data[--m_size].~T();
|
||||
}
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
if(m_size==0)return;
|
||||
clear_range(0);
|
||||
}
|
||||
|
||||
inline void clear_memory()
|
||||
{
|
||||
clear();
|
||||
destroyData();
|
||||
}
|
||||
|
||||
gim_array()
|
||||
{
|
||||
m_data = 0;
|
||||
m_size = 0;
|
||||
m_allocated_size = 0;
|
||||
}
|
||||
|
||||
gim_array(GUINT reservesize)
|
||||
{
|
||||
m_data = 0;
|
||||
m_size = 0;
|
||||
|
||||
m_allocated_size = 0;
|
||||
reserve(reservesize);
|
||||
}
|
||||
|
||||
~gim_array()
|
||||
{
|
||||
clear_memory();
|
||||
}
|
||||
|
||||
inline GUINT size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
inline GUINT max_size() const
|
||||
{
|
||||
return m_allocated_size;
|
||||
}
|
||||
|
||||
inline T & operator[](size_t i)
|
||||
{
|
||||
return m_data[i];
|
||||
}
|
||||
inline const T & operator[](size_t i) const
|
||||
{
|
||||
return m_data[i];
|
||||
}
|
||||
|
||||
inline T * pointer(){ return m_data;}
|
||||
inline const T * pointer() const
|
||||
{ return m_data;}
|
||||
|
||||
|
||||
inline T * get_pointer_at(GUINT i)
|
||||
{
|
||||
return m_data + i;
|
||||
}
|
||||
|
||||
inline const T * get_pointer_at(GUINT i) const
|
||||
{
|
||||
return m_data + i;
|
||||
}
|
||||
|
||||
inline T & at(GUINT i)
|
||||
{
|
||||
return m_data[i];
|
||||
}
|
||||
|
||||
inline const T & at(GUINT i) const
|
||||
{
|
||||
return m_data[i];
|
||||
}
|
||||
|
||||
inline T & front()
|
||||
{
|
||||
return *m_data;
|
||||
}
|
||||
|
||||
inline const T & front() const
|
||||
{
|
||||
return *m_data;
|
||||
}
|
||||
|
||||
inline T & back()
|
||||
{
|
||||
return m_data[m_size-1];
|
||||
}
|
||||
|
||||
inline const T & back() const
|
||||
{
|
||||
return m_data[m_size-1];
|
||||
}
|
||||
|
||||
|
||||
inline void swap(GUINT i, GUINT j)
|
||||
{
|
||||
gim_swap_elements(m_data,i,j);
|
||||
}
|
||||
|
||||
inline void push_back(const T & obj)
|
||||
{
|
||||
this->growingCheck();
|
||||
m_data[m_size] = obj;
|
||||
m_size++;
|
||||
}
|
||||
|
||||
//!Simply increase the m_size, doesn't call the new element constructor
|
||||
inline void push_back_mem()
|
||||
{
|
||||
this->growingCheck();
|
||||
m_size++;
|
||||
}
|
||||
|
||||
inline void push_back_memcpy(const T & obj)
|
||||
{
|
||||
this->growingCheck();
|
||||
irr_simd_memcpy(&m_data[m_size],&obj,sizeof(T));
|
||||
m_size++;
|
||||
}
|
||||
|
||||
inline void pop_back()
|
||||
{
|
||||
m_size--;
|
||||
m_data[m_size].~T();
|
||||
}
|
||||
|
||||
//!Simply decrease the m_size, doesn't call the deleted element destructor
|
||||
inline void pop_back_mem()
|
||||
{
|
||||
m_size--;
|
||||
}
|
||||
|
||||
//! fast erase
|
||||
inline void erase(GUINT index)
|
||||
{
|
||||
if(index<m_size-1)
|
||||
{
|
||||
swap(index,m_size-1);
|
||||
}
|
||||
pop_back();
|
||||
}
|
||||
|
||||
inline void erase_sorted_mem(GUINT index)
|
||||
{
|
||||
m_size--;
|
||||
for(GUINT i = index;i<m_size;i++)
|
||||
{
|
||||
gim_simd_memcpy(m_data+i,m_data+i+1,sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
inline void erase_sorted(GUINT index)
|
||||
{
|
||||
m_data[index].~T();
|
||||
erase_sorted_mem(index);
|
||||
}
|
||||
|
||||
inline void insert_mem(GUINT index)
|
||||
{
|
||||
this->growingCheck();
|
||||
for(GUINT i = m_size;i>index;i--)
|
||||
{
|
||||
gim_simd_memcpy(m_data+i,m_data+i-1,sizeof(T));
|
||||
}
|
||||
m_size++;
|
||||
}
|
||||
|
||||
inline void insert(const T & obj,GUINT index)
|
||||
{
|
||||
insert_mem(index);
|
||||
m_data[index] = obj;
|
||||
}
|
||||
|
||||
inline void resize(GUINT size, bool call_constructor = true)
|
||||
{
|
||||
|
||||
if(size>m_size)
|
||||
{
|
||||
reserve(size);
|
||||
if(call_constructor)
|
||||
{
|
||||
T obj;
|
||||
while(m_size<size)
|
||||
{
|
||||
m_data[m_size] = obj;
|
||||
m_size++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_size = size;
|
||||
}
|
||||
}
|
||||
else if(size<m_size)
|
||||
{
|
||||
if(call_constructor) clear_range(size);
|
||||
m_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
inline void refit()
|
||||
{
|
||||
resizeData(m_size);
|
||||
}
|
||||
//!@}
|
||||
};
|
||||
|
||||
|
||||
//! @}
|
||||
|
||||
|
||||
|
||||
#endif // GIM_CONTAINERS_H_INCLUDED
|
||||
547
Extras/GIMPACT/include/GIMPACT/core/gim_basic_geometry_operations.h
Executable file
547
Extras/GIMPACT/include/GIMPACT/core/gim_basic_geometry_operations.h
Executable file
@@ -0,0 +1,547 @@
|
||||
#ifndef GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
|
||||
#define GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
|
||||
|
||||
/*! \file gim_basic_geometry_operations.h
|
||||
*\author Francisco Le<4C>n N<>jera
|
||||
type independant geometry routines
|
||||
|
||||
*/
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of GIMPACT Library.
|
||||
|
||||
For the latest info, see http://gimpact.sourceforge.net/
|
||||
|
||||
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "GIMPACT/core/gim_linear_math.h"
|
||||
|
||||
|
||||
|
||||
/*! \defgroup GEOMETRIC_OPERATIONS
|
||||
*/
|
||||
//! @{
|
||||
|
||||
|
||||
#define PLANEDIREPSILON 0.0000001f
|
||||
#define PARALELENORMALS 0.000001f
|
||||
|
||||
|
||||
#define TRIANGLE_NORMAL(v1,v2,v3,n)\
|
||||
{\
|
||||
vec3f _dif1,_dif2;\
|
||||
VEC_DIFF(_dif1,v2,v1);\
|
||||
VEC_DIFF(_dif2,v3,v1);\
|
||||
VEC_CROSS(n,_dif1,_dif2);\
|
||||
VEC_NORMALIZE(n);\
|
||||
}\
|
||||
|
||||
#define TRIANGLE_NORMAL_FAST(v1,v2,v3,n){\
|
||||
vec3f _dif1,_dif2; \
|
||||
VEC_DIFF(_dif1,v2,v1); \
|
||||
VEC_DIFF(_dif2,v3,v1); \
|
||||
VEC_CROSS(n,_dif1,_dif2); \
|
||||
}\
|
||||
|
||||
/// plane is a vec4f
|
||||
#define TRIANGLE_PLANE(v1,v2,v3,plane) {\
|
||||
TRIANGLE_NORMAL(v1,v2,v3,plane);\
|
||||
plane[3] = VEC_DOT(v1,plane);\
|
||||
}\
|
||||
|
||||
/// plane is a vec4f
|
||||
#define TRIANGLE_PLANE_FAST(v1,v2,v3,plane) {\
|
||||
TRIANGLE_NORMAL_FAST(v1,v2,v3,plane);\
|
||||
plane[3] = VEC_DOT(v1,plane);\
|
||||
}\
|
||||
|
||||
/// Calc a plane from an edge an a normal. plane is a vec4f
|
||||
#define EDGE_PLANE(e1,e2,n,plane) {\
|
||||
vec3f _dif; \
|
||||
VEC_DIFF(_dif,e2,e1); \
|
||||
VEC_CROSS(plane,_dif,n); \
|
||||
VEC_NORMALIZE(plane); \
|
||||
plane[3] = VEC_DOT(e1,plane);\
|
||||
}\
|
||||
|
||||
#define DISTANCE_PLANE_POINT(plane,point) (VEC_DOT(plane,point) - plane[3])
|
||||
|
||||
#define PROJECT_POINT_PLANE(point,plane,projected) {\
|
||||
GREAL _dis;\
|
||||
_dis = DISTANCE_PLANE_POINT(plane,point);\
|
||||
VEC_SCALE(projected,-_dis,plane);\
|
||||
VEC_SUM(projected,projected,point); \
|
||||
}\
|
||||
|
||||
//! Verifies if a point is in the plane hull
|
||||
template<typename CLASS_POINT,typename CLASS_PLANE>
|
||||
SIMD_FORCE_INLINE bool POINT_IN_HULL(
|
||||
const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count)
|
||||
{
|
||||
GREAL _dis;
|
||||
for (GUINT _i = 0;_i< plane_count;++_i)
|
||||
{
|
||||
_dis = DISTANCE_PLANE_POINT(planes[_i],point);
|
||||
if(_dis>0.0f) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename CLASS_POINT,typename CLASS_PLANE>
|
||||
SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT(
|
||||
const CLASS_POINT& s1,
|
||||
const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped)
|
||||
{
|
||||
GREAL _dis1,_dis2;
|
||||
_dis1 = DISTANCE_PLANE_POINT(plane,s1);
|
||||
VEC_DIFF(clipped,s2,s1);
|
||||
_dis2 = VEC_DOT(clipped,plane);
|
||||
VEC_SCALE(clipped,-_dis1/_dis2,clipped);
|
||||
VEC_SUM(clipped,clipped,s1);
|
||||
}
|
||||
|
||||
enum ePLANE_INTERSECTION_TYPE
|
||||
{
|
||||
G_BACK_PLANE = 0,
|
||||
G_COLLIDE_PLANE,
|
||||
G_FRONT_PLANE
|
||||
};
|
||||
|
||||
enum eLINE_PLANE_INTERSECTION_TYPE
|
||||
{
|
||||
G_FRONT_PLANE_S1 = 0,
|
||||
G_FRONT_PLANE_S2,
|
||||
G_BACK_PLANE_S1,
|
||||
G_BACK_PLANE_S2,
|
||||
G_COLLIDE_PLANE_S1,
|
||||
G_COLLIDE_PLANE_S2
|
||||
};
|
||||
|
||||
//! Confirms if the plane intersect the edge or nor
|
||||
/*!
|
||||
intersection type must have the following values
|
||||
<ul>
|
||||
<li> 0 : Segment in front of plane, s1 closest
|
||||
<li> 1 : Segment in front of plane, s2 closest
|
||||
<li> 2 : Segment in back of plane, s1 closest
|
||||
<li> 3 : Segment in back of plane, s2 closest
|
||||
<li> 4 : Segment collides plane, s1 in back
|
||||
<li> 5 : Segment collides plane, s2 in back
|
||||
</ul>
|
||||
*/
|
||||
|
||||
template<typename CLASS_POINT,typename CLASS_PLANE>
|
||||
SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2(
|
||||
const CLASS_POINT& s1,
|
||||
const CLASS_POINT &s2,
|
||||
const CLASS_PLANE &plane,CLASS_POINT &clipped)
|
||||
{
|
||||
GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1);
|
||||
GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2);
|
||||
if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON)
|
||||
{
|
||||
if(_dis1<_dis2) return G_FRONT_PLANE_S1;
|
||||
return G_FRONT_PLANE_S2;
|
||||
}
|
||||
else if(_dis1 <G_EPSILON && _dis2 <G_EPSILON)
|
||||
{
|
||||
if(_dis1>_dis2) return G_BACK_PLANE_S1;
|
||||
return G_BACK_PLANE_S2;
|
||||
}
|
||||
|
||||
VEC_DIFF(clipped,s2,s1);
|
||||
_dis2 = VEC_DOT(clipped,plane);
|
||||
VEC_SCALE(clipped,-_dis1/_dis2,clipped);
|
||||
VEC_SUM(clipped,clipped,s1);
|
||||
if(_dis1<_dis2) return G_COLLIDE_PLANE_S1;
|
||||
return G_COLLIDE_PLANE_S2;
|
||||
}
|
||||
|
||||
//! Confirms if the plane intersect the edge or not
|
||||
/*!
|
||||
clipped1 and clipped2 are the vertices behind the plane.
|
||||
clipped1 is the closest
|
||||
|
||||
intersection_type must have the following values
|
||||
<ul>
|
||||
<li> 0 : Segment in front of plane, s1 closest
|
||||
<li> 1 : Segment in front of plane, s2 closest
|
||||
<li> 2 : Segment in back of plane, s1 closest
|
||||
<li> 3 : Segment in back of plane, s2 closest
|
||||
<li> 4 : Segment collides plane, s1 in back
|
||||
<li> 5 : Segment collides plane, s2 in back
|
||||
</ul>
|
||||
*/
|
||||
template<typename CLASS_POINT,typename CLASS_PLANE>
|
||||
SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
|
||||
const CLASS_POINT& s1,
|
||||
const CLASS_POINT &s2,
|
||||
const CLASS_PLANE &plane,
|
||||
CLASS_POINT &clipped1,CLASS_POINT &clipped2)
|
||||
{
|
||||
eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1);
|
||||
switch(intersection_type)
|
||||
{
|
||||
case G_FRONT_PLANE_S1:
|
||||
VEC_COPY(clipped1,s1);
|
||||
VEC_COPY(clipped2,s2);
|
||||
break;
|
||||
case G_FRONT_PLANE_S2:
|
||||
VEC_COPY(clipped1,s2);
|
||||
VEC_COPY(clipped2,s1);
|
||||
break;
|
||||
case G_BACK_PLANE_S1:
|
||||
VEC_COPY(clipped1,s1);
|
||||
VEC_COPY(clipped2,s2);
|
||||
break;
|
||||
case G_BACK_PLANE_S2:
|
||||
VEC_COPY(clipped1,s2);
|
||||
VEC_COPY(clipped2,s1);
|
||||
break;
|
||||
case G_COLLIDE_PLANE_S1:
|
||||
VEC_COPY(clipped2,s1);
|
||||
break;
|
||||
case G_COLLIDE_PLANE_S2:
|
||||
VEC_COPY(clipped2,s2);
|
||||
break;
|
||||
}
|
||||
return intersection_type;
|
||||
}
|
||||
|
||||
|
||||
//! Finds the 2 smallest cartesian coordinates of a plane normal
|
||||
#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1)
|
||||
|
||||
//! Ray plane collision in one way
|
||||
/*!
|
||||
Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).<br/>
|
||||
It uses the PLANEDIREPSILON constant.
|
||||
*/
|
||||
template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
|
||||
SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
|
||||
const CLASS_PLANE & plane,
|
||||
const CLASS_POINT & vDir,
|
||||
const CLASS_POINT & vPoint,
|
||||
CLASS_POINT & pout,T &tparam)
|
||||
{
|
||||
GREAL _dis,_dotdir;
|
||||
_dotdir = VEC_DOT(plane,vDir);
|
||||
if(_dotdir<PLANEDIREPSILON)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_dis = DISTANCE_PLANE_POINT(plane,vPoint);
|
||||
tparam = -_dis/_dotdir;
|
||||
VEC_SCALE(pout,tparam,vDir);
|
||||
VEC_SUM(pout,vPoint,pout);
|
||||
return true;
|
||||
}
|
||||
|
||||
//! line collision
|
||||
/*!
|
||||
*\return
|
||||
-0 if the ray never intersects
|
||||
-1 if the ray collides in front
|
||||
-2 if the ray collides in back
|
||||
*/
|
||||
template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
|
||||
SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
|
||||
const CLASS_PLANE & plane,
|
||||
const CLASS_POINT & vDir,
|
||||
const CLASS_POINT & vPoint,
|
||||
CLASS_POINT & pout,
|
||||
T &tparam,
|
||||
T tmin, T tmax)
|
||||
{
|
||||
GREAL _dis,_dotdir;
|
||||
_dotdir = VEC_DOT(plane,vDir);
|
||||
if(btFabs(_dotdir)<PLANEDIREPSILON)
|
||||
{
|
||||
tparam = tmax;
|
||||
return 0;
|
||||
}
|
||||
_dis = DISTANCE_PLANE_POINT(plane,vPoint);
|
||||
char returnvalue = _dis<0.0f?2:1;
|
||||
tparam = -_dis/_dotdir;
|
||||
|
||||
if(tparam<tmin)
|
||||
{
|
||||
returnvalue = 0;
|
||||
tparam = tmin;
|
||||
}
|
||||
else if(tparam>tmax)
|
||||
{
|
||||
returnvalue = 0;
|
||||
tparam = tmax;
|
||||
}
|
||||
|
||||
VEC_SCALE(pout,tparam,vDir);
|
||||
VEC_SUM(pout,vPoint,pout);
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
/*! \brief Returns the Ray on which 2 planes intersect if they do.
|
||||
Written by Rodrigo Hernandez on ODE convex collision
|
||||
|
||||
\param p1 Plane 1
|
||||
\param p2 Plane 2
|
||||
\param p Contains the origin of the ray upon returning if planes intersect
|
||||
\param d Contains the direction of the ray upon returning if planes intersect
|
||||
\return true if the planes intersect, 0 if paralell.
|
||||
|
||||
*/
|
||||
template<typename CLASS_POINT,typename CLASS_PLANE>
|
||||
SIMD_FORCE_INLINE bool INTERSECT_PLANES(
|
||||
const CLASS_PLANE &p1,
|
||||
const CLASS_PLANE &p2,
|
||||
CLASS_POINT &p,
|
||||
CLASS_POINT &d)
|
||||
{
|
||||
VEC_CROSS(d,p1,p2);
|
||||
GREAL denom = VEC_DOT(d, d);
|
||||
if(GIM_IS_ZERO(denom)) return false;
|
||||
vec3f _n;
|
||||
_n[0]=p1[3]*p2[0] - p2[3]*p1[0];
|
||||
_n[1]=p1[3]*p2[1] - p2[3]*p1[1];
|
||||
_n[2]=p1[3]*p2[2] - p2[3]*p1[2];
|
||||
VEC_CROSS(p,_n,d);
|
||||
p[0]/=denom;
|
||||
p[1]/=denom;
|
||||
p[2]/=denom;
|
||||
return true;
|
||||
}
|
||||
|
||||
//***************** SEGMENT and LINE FUNCTIONS **********************************///
|
||||
|
||||
/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
|
||||
*/
|
||||
template<typename CLASS_POINT>
|
||||
SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
|
||||
CLASS_POINT & cp, const CLASS_POINT & v,
|
||||
const CLASS_POINT &e1,const CLASS_POINT &e2)
|
||||
{
|
||||
vec3f _n;
|
||||
VEC_DIFF(_n,e2,e1);
|
||||
VEC_DIFF(cp,v,e1);
|
||||
GREAL _scalar = VEC_DOT(cp, _n);
|
||||
_scalar/= VEC_DOT(_n, _n);
|
||||
if(_scalar <0.0f)
|
||||
{
|
||||
VEC_COPY(cp,e1);
|
||||
}
|
||||
else if(_scalar >1.0f)
|
||||
{
|
||||
VEC_COPY(cp,e2);
|
||||
}
|
||||
else
|
||||
{
|
||||
VEC_SCALE(cp,_scalar,_n);
|
||||
VEC_SUM(cp,cp,e1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Finds the line params where these lines intersect.
|
||||
|
||||
\param dir1 Direction of line 1
|
||||
\param point1 Point of line 1
|
||||
\param dir2 Direction of line 2
|
||||
\param point2 Point of line 2
|
||||
\param t1 Result Parameter for line 1
|
||||
\param t2 Result Parameter for line 2
|
||||
\param dointersect 0 if the lines won't intersect, else 1
|
||||
|
||||
*/
|
||||
template<typename T,typename CLASS_POINT>
|
||||
SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS(
|
||||
const CLASS_POINT & dir1,
|
||||
CLASS_POINT & point1,
|
||||
const CLASS_POINT & dir2,
|
||||
CLASS_POINT & point2,
|
||||
T& t1,T& t2)
|
||||
{
|
||||
GREAL det;
|
||||
GREAL e1e1 = VEC_DOT(dir1,dir1);
|
||||
GREAL e1e2 = VEC_DOT(dir1,dir2);
|
||||
GREAL e2e2 = VEC_DOT(dir2,dir2);
|
||||
vec3f p1p2;
|
||||
VEC_DIFF(p1p2,point1,point2);
|
||||
GREAL p1p2e1 = VEC_DOT(p1p2,dir1);
|
||||
GREAL p1p2e2 = VEC_DOT(p1p2,dir2);
|
||||
det = e1e2*e1e2 - e1e1*e2e2;
|
||||
if(GIM_IS_ZERO(det)) return false;
|
||||
t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det;
|
||||
t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Find closest points on segments
|
||||
template<typename CLASS_POINT>
|
||||
SIMD_FORCE_INLINE void SEGMENT_COLLISION(
|
||||
const CLASS_POINT & vA1,
|
||||
const CLASS_POINT & vA2,
|
||||
const CLASS_POINT & vB1,
|
||||
const CLASS_POINT & vB2,
|
||||
CLASS_POINT & vPointA,
|
||||
CLASS_POINT & vPointB)
|
||||
{
|
||||
CLASS_POINT _AD,_BD,_N;
|
||||
vec4f _M;//plane
|
||||
VEC_DIFF(_AD,vA2,vA1);
|
||||
VEC_DIFF(_BD,vB2,vB1);
|
||||
VEC_CROSS(_N,_AD,_BD);
|
||||
GREAL _tp = VEC_DOT(_N,_N);
|
||||
if(_tp<G_EPSILON)//ARE PARALELE
|
||||
{
|
||||
//project B over A
|
||||
bool invert_b_order = false;
|
||||
_M[0] = VEC_DOT(vB1,_AD);
|
||||
_M[1] = VEC_DOT(vB2,_AD);
|
||||
if(_M[0]>_M[1])
|
||||
{
|
||||
invert_b_order = true;
|
||||
GIM_SWAP_NUMBERS(_M[0],_M[1]);
|
||||
}
|
||||
_M[2] = VEC_DOT(vA1,_AD);
|
||||
_M[3] = VEC_DOT(vA2,_AD);
|
||||
//mid points
|
||||
_N[0] = (_M[0]+_M[1])*0.5f;
|
||||
_N[1] = (_M[2]+_M[3])*0.5f;
|
||||
|
||||
if(_N[0]<_N[1])
|
||||
{
|
||||
if(_M[1]<_M[2])
|
||||
{
|
||||
vPointB = invert_b_order?vB1:vB2;
|
||||
vPointA = vA1;
|
||||
}
|
||||
else if(_M[1]<_M[3])
|
||||
{
|
||||
vPointB = invert_b_order?vB1:vB2;
|
||||
CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
|
||||
}
|
||||
else
|
||||
{
|
||||
vPointA = vA2;
|
||||
CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_M[3]<_M[0])
|
||||
{
|
||||
vPointB = invert_b_order?vB2:vB1;
|
||||
vPointA = vA2;
|
||||
}
|
||||
else if(_M[3]<_M[1])
|
||||
{
|
||||
vPointA = vA2;
|
||||
CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
|
||||
}
|
||||
else
|
||||
{
|
||||
vPointB = invert_b_order?vB1:vB2;
|
||||
CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
VEC_CROSS(_M,_N,_BD);
|
||||
_M[3] = VEC_DOT(_M,vB1);
|
||||
|
||||
LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,0.0f, 1.0f);
|
||||
/*Closest point on segment*/
|
||||
VEC_DIFF(vPointB,vPointA,vB1);
|
||||
_tp = VEC_DOT(vPointB, _BD);
|
||||
_tp/= VEC_DOT(_BD, _BD);
|
||||
_tp = GIM_CLAMP(_tp,0.0f,1.0f);
|
||||
VEC_SCALE(vPointB,_tp,_BD);
|
||||
VEC_SUM(vPointB,vPointB,vB1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! Line box intersection in one dimension
|
||||
/*!
|
||||
|
||||
*\param pos Position of the ray
|
||||
*\param dir Projection of the Direction of the ray
|
||||
*\param bmin Minimum bound of the box
|
||||
*\param bmax Maximum bound of the box
|
||||
*\param tfirst the minimum projection. Assign to 0 at first.
|
||||
*\param tlast the maximum projection. Assign to INFINITY at first.
|
||||
*\return true if there is an intersection.
|
||||
*/
|
||||
template<typename T>
|
||||
SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast)
|
||||
{
|
||||
if(GIM_IS_ZERO(dir))
|
||||
{
|
||||
return !(pos < bmin || pos > bmax);
|
||||
}
|
||||
GREAL a0 = (bmin - pos) / dir;
|
||||
GREAL a1 = (bmax - pos) / dir;
|
||||
if(a0 > a1) GIM_SWAP_NUMBERS(a0, a1);
|
||||
tfirst = GIM_MAX(a0, tfirst);
|
||||
tlast = GIM_MIN(a1, tlast);
|
||||
if (tlast < tfirst) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! Sorts 3 componets
|
||||
template<typename T>
|
||||
SIMD_FORCE_INLINE void SORT_3_INDICES(
|
||||
const T * values,
|
||||
GUINT * order_indices)
|
||||
{
|
||||
//get minimum
|
||||
order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
|
||||
|
||||
//get second and third
|
||||
GUINT i0 = (order_indices[0] + 1)%3;
|
||||
GUINT i1 = (i0 + 1)%3;
|
||||
|
||||
if(values[i0] < values[i1])
|
||||
{
|
||||
order_indices[1] = i0;
|
||||
order_indices[2] = i1;
|
||||
}
|
||||
else
|
||||
{
|
||||
order_indices[1] = i1;
|
||||
order_indices[2] = i0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! @}
|
||||
|
||||
|
||||
#endif // GIM_VECTOR_H_INCLUDED
|
||||
129
Extras/GIMPACT/include/GIMPACT/core/gim_bitset.h
Executable file
129
Extras/GIMPACT/include/GIMPACT/core/gim_bitset.h
Executable file
@@ -0,0 +1,129 @@
|
||||
#ifndef GIM_BITSET_H_INCLUDED
|
||||
#define GIM_BITSET_H_INCLUDED
|
||||
/*! \file gim_bitset.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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "GIMPACT/core/gim_array.h"
|
||||
|
||||
/*! \addtogroup CONTAINERS
|
||||
\brief
|
||||
Abstract class for template containers
|
||||
*/
|
||||
//! @{
|
||||
|
||||
#define GUINT_BIT_COUNT 32
|
||||
#define GUINT_EXPONENT 5
|
||||
|
||||
class gim_bitset
|
||||
{
|
||||
public:
|
||||
gim_array<GUINT> m_container;
|
||||
|
||||
gim_bitset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
gim_bitset(GUINT bits_count)
|
||||
{
|
||||
resize(bits_count);
|
||||
}
|
||||
|
||||
~gim_bitset()
|
||||
{
|
||||
}
|
||||
|
||||
inline bool resize(GUINT newsize)
|
||||
{
|
||||
GUINT oldsize = m_container.size();
|
||||
m_container.resize(newsize/GUINT_BIT_COUNT + 1,false);
|
||||
while(oldsize<m_container.size())
|
||||
{
|
||||
m_container[oldsize] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline GUINT size()
|
||||
{
|
||||
return m_container.size()*GUINT_BIT_COUNT;
|
||||
}
|
||||
|
||||
inline void set_all()
|
||||
{
|
||||
for(GUINT i = 0;i<m_container.size();++i)
|
||||
{
|
||||
m_container[i] = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
inline void clear_all()
|
||||
{
|
||||
for(GUINT i = 0;i<m_container.size();++i)
|
||||
{
|
||||
m_container[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void set(GUINT bit_index)
|
||||
{
|
||||
if(bit_index>=size())
|
||||
{
|
||||
resize(bit_index);
|
||||
}
|
||||
m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT-1)));
|
||||
}
|
||||
|
||||
///Return 0 or 1
|
||||
inline char get(GUINT bit_index)
|
||||
{
|
||||
if(bit_index>=size())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
char value = m_container[bit_index >> GUINT_EXPONENT] &
|
||||
(1 << (bit_index & (GUINT_BIT_COUNT-1)));
|
||||
return value;
|
||||
}
|
||||
|
||||
inline void clear(GUINT bit_index)
|
||||
{
|
||||
m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT-1)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! @}
|
||||
|
||||
|
||||
|
||||
#endif // GIM_CONTAINERS_H_INCLUDED
|
||||
594
Extras/GIMPACT/include/GIMPACT/core/gim_box_collision.h
Executable file
594
Extras/GIMPACT/include/GIMPACT/core/gim_box_collision.h
Executable file
@@ -0,0 +1,594 @@
|
||||
#ifndef GIM_BOX_COLLISION_H_INCLUDED
|
||||
#define GIM_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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
#include "GIMPACT/core/gim_basic_geometry_operations.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
|
||||
/*! \defgroup BOUND_AABB_OPERATIONS
|
||||
*/
|
||||
//! @{
|
||||
|
||||
|
||||
//SIMD_FORCE_INLINE bool test_cross_edge_box(
|
||||
// const btVector3 & edge,
|
||||
// const btVector3 & absolute_edge,
|
||||
// const btVector3 & pointa,
|
||||
// const btVector3 & pointb, const btVector3 & extend,
|
||||
// int dir_index0,
|
||||
// int dir_index1
|
||||
// int component_index0,
|
||||
// int component_index1)
|
||||
//{
|
||||
// // dir coords are -z and y
|
||||
//
|
||||
// const btScalar dir0 = -edge[dir_index0];
|
||||
// const btScalar dir1 = edge[dir_index1];
|
||||
// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
|
||||
// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
|
||||
// //find minmax
|
||||
// if(pmin>pmax)
|
||||
// {
|
||||
// GIM_SWAP_NUMBERS(pmin,pmax);
|
||||
// }
|
||||
// //find extends
|
||||
// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
|
||||
// extend[component_index1] * absolute_edge[dir_index1];
|
||||
//
|
||||
// if(pmin>rad || -rad>pmax) return false;
|
||||
// return true;
|
||||
//}
|
||||
//
|
||||
//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
|
||||
// const btVector3 & edge,
|
||||
// const btVector3 & absolute_edge,
|
||||
// const btVector3 & pointa,
|
||||
// const btVector3 & pointb, btVector3 & extend)
|
||||
//{
|
||||
//
|
||||
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
|
||||
//}
|
||||
//
|
||||
//
|
||||
//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
|
||||
// const btVector3 & edge,
|
||||
// const btVector3 & absolute_edge,
|
||||
// const btVector3 & pointa,
|
||||
// const btVector3 & pointb, btVector3 & extend)
|
||||
//{
|
||||
//
|
||||
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
|
||||
//}
|
||||
//
|
||||
//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
|
||||
// const btVector3 & edge,
|
||||
// const btVector3 & absolute_edge,
|
||||
// const btVector3 & pointa,
|
||||
// const btVector3 & pointb, btVector3 & extend)
|
||||
//{
|
||||
//
|
||||
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
|
||||
//}
|
||||
|
||||
#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
|
||||
{\
|
||||
const btScalar dir0 = -edge[i_dir_0];\
|
||||
const btScalar dir1 = edge[i_dir_1];\
|
||||
btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
|
||||
btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
|
||||
if(pmin>pmax)\
|
||||
{\
|
||||
GIM_SWAP_NUMBERS(pmin,pmax); \
|
||||
}\
|
||||
const btScalar abs_dir0 = absolute_edge[i_dir_0];\
|
||||
const btScalar abs_dir1 = absolute_edge[i_dir_1];\
|
||||
const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
|
||||
if(pmin>rad || -rad>pmax) return false;\
|
||||
}\
|
||||
|
||||
|
||||
#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
|
||||
{\
|
||||
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
|
||||
}\
|
||||
|
||||
#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
|
||||
{\
|
||||
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
|
||||
}\
|
||||
|
||||
#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
|
||||
{\
|
||||
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
|
||||
}\
|
||||
|
||||
|
||||
|
||||
//! Class for transforming a model1 to the space of model0
|
||||
class GIM_BOX_BOX_TRANSFORM_CACHE
|
||||
{
|
||||
public:
|
||||
btVector3 m_T1to0;//!< Transforms translation of model1 to model 0
|
||||
btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1
|
||||
btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
|
||||
|
||||
SIMD_FORCE_INLINE void calc_absolute_matrix()
|
||||
{
|
||||
static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
|
||||
m_AR[0] = vepsi + m_R1to0[0].absolute();
|
||||
m_AR[1] = vepsi + m_R1to0[1].absolute();
|
||||
m_AR[2] = vepsi + m_R1to0[2].absolute();
|
||||
}
|
||||
|
||||
GIM_BOX_BOX_TRANSFORM_CACHE()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0)
|
||||
{
|
||||
COPY_MATRIX_3X3(m_R1to0,trans1_to_0)
|
||||
MAT_GET_TRANSLATION(trans1_to_0,m_T1to0)
|
||||
calc_absolute_matrix();
|
||||
}
|
||||
|
||||
//! Calc the transformation relative 1 to 0. Inverts matrics by transposing
|
||||
SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
|
||||
{
|
||||
|
||||
m_R1to0 = trans0.getBasis().transpose();
|
||||
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
|
||||
|
||||
m_T1to0 += m_R1to0*trans1.getOrigin();
|
||||
m_R1to0 *= trans1.getBasis();
|
||||
|
||||
calc_absolute_matrix();
|
||||
}
|
||||
|
||||
//! Calcs the full invertion of the matrices. Useful for scaling matrices
|
||||
SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
|
||||
{
|
||||
m_R1to0 = trans0.getBasis().inverse();
|
||||
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
|
||||
|
||||
m_T1to0 += m_R1to0*trans1.getOrigin();
|
||||
m_R1to0 *= trans1.getBasis();
|
||||
|
||||
calc_absolute_matrix();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point)
|
||||
{
|
||||
return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
|
||||
m_R1to0[1].dot(point) + m_T1to0.y(),
|
||||
m_R1to0[2].dot(point) + m_T1to0.z());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define BOX_PLANE_EPSILON 0.000001f
|
||||
|
||||
//! Axis aligned box
|
||||
class GIM_AABB
|
||||
{
|
||||
public:
|
||||
btVector3 m_min;
|
||||
btVector3 m_max;
|
||||
|
||||
GIM_AABB()
|
||||
{}
|
||||
|
||||
|
||||
GIM_AABB(const btVector3 & V1,
|
||||
const btVector3 & V2,
|
||||
const btVector3 & V3)
|
||||
{
|
||||
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
|
||||
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
|
||||
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
|
||||
|
||||
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
|
||||
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
|
||||
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
|
||||
}
|
||||
|
||||
GIM_AABB(const btVector3 & V1,
|
||||
const btVector3 & V2,
|
||||
const btVector3 & V3,
|
||||
GREAL margin)
|
||||
{
|
||||
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
|
||||
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
|
||||
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
|
||||
|
||||
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
|
||||
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
|
||||
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
|
||||
|
||||
m_min[0] -= margin;
|
||||
m_min[1] -= margin;
|
||||
m_min[2] -= margin;
|
||||
m_max[0] += margin;
|
||||
m_max[1] += margin;
|
||||
m_max[2] += margin;
|
||||
}
|
||||
|
||||
GIM_AABB(const GIM_AABB &other):
|
||||
m_min(other.m_min),m_max(other.m_max)
|
||||
{
|
||||
}
|
||||
|
||||
GIM_AABB(const GIM_AABB &other,btScalar margin ):
|
||||
m_min(other.m_min),m_max(other.m_max)
|
||||
{
|
||||
m_min[0] -= margin;
|
||||
m_min[1] -= margin;
|
||||
m_min[2] -= margin;
|
||||
m_max[0] += margin;
|
||||
m_max[1] += margin;
|
||||
m_max[2] += margin;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void invalidate()
|
||||
{
|
||||
m_min[0] = G_REAL_INFINITY;
|
||||
m_min[1] = G_REAL_INFINITY;
|
||||
m_min[2] = G_REAL_INFINITY;
|
||||
m_max[0] = -G_REAL_INFINITY;
|
||||
m_max[1] = -G_REAL_INFINITY;
|
||||
m_max[2] = -G_REAL_INFINITY;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void increment_margin(btScalar margin)
|
||||
{
|
||||
m_min[0] -= margin;
|
||||
m_min[1] -= margin;
|
||||
m_min[2] -= margin;
|
||||
m_max[0] += margin;
|
||||
m_max[1] += margin;
|
||||
m_max[2] += margin;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin)
|
||||
{
|
||||
m_min[0] = other.m_min[0] - margin;
|
||||
m_min[1] = other.m_min[1] - margin;
|
||||
m_min[2] = other.m_min[2] - margin;
|
||||
|
||||
m_max[0] = other.m_max[0] + margin;
|
||||
m_max[1] = other.m_max[1] + margin;
|
||||
m_max[2] = other.m_max[2] + margin;
|
||||
}
|
||||
|
||||
template<typename CLASS_POINT>
|
||||
SIMD_FORCE_INLINE void calc_from_triangle(
|
||||
const CLASS_POINT & V1,
|
||||
const CLASS_POINT & V2,
|
||||
const CLASS_POINT & V3)
|
||||
{
|
||||
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
|
||||
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
|
||||
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
|
||||
|
||||
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
|
||||
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
|
||||
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
|
||||
}
|
||||
|
||||
template<typename CLASS_POINT>
|
||||
SIMD_FORCE_INLINE void calc_from_triangle_margin(
|
||||
const CLASS_POINT & V1,
|
||||
const CLASS_POINT & V2,
|
||||
const CLASS_POINT & V3, btScalar margin)
|
||||
{
|
||||
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
|
||||
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
|
||||
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
|
||||
|
||||
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
|
||||
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
|
||||
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
|
||||
|
||||
m_min[0] -= margin;
|
||||
m_min[1] -= margin;
|
||||
m_min[2] -= margin;
|
||||
m_max[0] += margin;
|
||||
m_max[1] += margin;
|
||||
m_max[2] += margin;
|
||||
}
|
||||
|
||||
//! Apply a transform to an AABB
|
||||
SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
|
||||
{
|
||||
btVector3 center = (m_max+m_min)*0.5f;
|
||||
btVector3 extends = m_max - center;
|
||||
// Compute new center
|
||||
center = trans(center);
|
||||
|
||||
btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
|
||||
extends.dot(trans.getBasis().getRow(1).absolute()),
|
||||
extends.dot(trans.getBasis().getRow(2).absolute()));
|
||||
|
||||
m_min = center - textends;
|
||||
m_max = center + textends;
|
||||
}
|
||||
|
||||
//! Merges a Box
|
||||
SIMD_FORCE_INLINE void merge(const GIM_AABB & box)
|
||||
{
|
||||
m_min[0] = GIM_MIN(m_min[0],box.m_min[0]);
|
||||
m_min[1] = GIM_MIN(m_min[1],box.m_min[1]);
|
||||
m_min[2] = GIM_MIN(m_min[2],box.m_min[2]);
|
||||
|
||||
m_max[0] = GIM_MAX(m_max[0],box.m_max[0]);
|
||||
m_max[1] = GIM_MAX(m_max[1],box.m_max[1]);
|
||||
m_max[2] = GIM_MAX(m_max[2],box.m_max[2]);
|
||||
}
|
||||
|
||||
//! Merges a point
|
||||
template<typename CLASS_POINT>
|
||||
SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
|
||||
{
|
||||
m_min[0] = GIM_MIN(m_min[0],point[0]);
|
||||
m_min[1] = GIM_MIN(m_min[1],point[1]);
|
||||
m_min[2] = GIM_MIN(m_min[2],point[2]);
|
||||
|
||||
m_max[0] = GIM_MAX(m_max[0],point[0]);
|
||||
m_max[1] = GIM_MAX(m_max[1],point[1]);
|
||||
m_max[2] = GIM_MAX(m_max[2],point[2]);
|
||||
}
|
||||
|
||||
//! Gets the extend and center
|
||||
SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
|
||||
{
|
||||
center = (m_max+m_min)*0.5f;
|
||||
extend = m_max - center;
|
||||
}
|
||||
|
||||
//! Finds the intersecting box between this box and the other.
|
||||
SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection) const
|
||||
{
|
||||
intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]);
|
||||
intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]);
|
||||
intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]);
|
||||
|
||||
intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]);
|
||||
intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]);
|
||||
intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]);
|
||||
}
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const
|
||||
{
|
||||
if(m_min[0] > other.m_max[0] ||
|
||||
m_max[0] < other.m_min[0] ||
|
||||
m_min[1] > other.m_max[1] ||
|
||||
m_max[1] < other.m_min[1] ||
|
||||
m_min[2] > other.m_max[2] ||
|
||||
m_max[2] < other.m_min[2])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! \brief Finds the Ray intersection parameter.
|
||||
\param aabb Aligned box
|
||||
\param vorigin A vec3f with the origin of the ray
|
||||
\param vdir A vec3f with the direction of the ray
|
||||
*/
|
||||
SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir)
|
||||
{
|
||||
btVector3 extents,center;
|
||||
this->get_center_extend(center,extents);;
|
||||
|
||||
btScalar Dx = vorigin[0] - center[0];
|
||||
if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
|
||||
btScalar Dy = vorigin[1] - center[1];
|
||||
if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
|
||||
btScalar Dz = vorigin[2] - center[2];
|
||||
if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
|
||||
|
||||
|
||||
btScalar f = vdir[1] * Dz - vdir[2] * Dy;
|
||||
if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
|
||||
f = vdir[2] * Dx - vdir[0] * Dz;
|
||||
if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
|
||||
f = vdir[0] * Dy - vdir[1] * Dx;
|
||||
if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
|
||||
{
|
||||
btVector3 center = (m_max+m_min)*0.5f;
|
||||
btVector3 extend = m_max-center;
|
||||
|
||||
btScalar _fOrigin = direction.dot(center);
|
||||
btScalar _fMaximumExtent = extend.dot(direction.absolute());
|
||||
vmin = _fOrigin - _fMaximumExtent;
|
||||
vmax = _fOrigin + _fMaximumExtent;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
|
||||
{
|
||||
btScalar _fmin,_fmax;
|
||||
this->projection_interval(plane,_fmin,_fmax);
|
||||
|
||||
if(plane[3] > _fmax + BOX_PLANE_EPSILON)
|
||||
{
|
||||
return G_BACK_PLANE; // 0
|
||||
}
|
||||
|
||||
if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
|
||||
{
|
||||
return G_COLLIDE_PLANE; //1
|
||||
}
|
||||
return G_FRONT_PLANE;//2
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0)
|
||||
{
|
||||
GIM_AABB tbox = box;
|
||||
tbox.appy_transform(trans1_to_0);
|
||||
return has_collision(tbox);
|
||||
}
|
||||
|
||||
//! transcache is the transformation cache from box to this AABB
|
||||
SIMD_FORCE_INLINE bool overlapping_trans_cache(
|
||||
const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest)
|
||||
{
|
||||
|
||||
//Taken from OPCODE
|
||||
btVector3 ea,eb;//extends
|
||||
btVector3 ca,cb;//extends
|
||||
get_center_extend(ca,ea);
|
||||
box.get_center_extend(cb,eb);
|
||||
|
||||
|
||||
btVector3 T;
|
||||
btScalar t,t2;
|
||||
int i;
|
||||
|
||||
// Class I : A's basis vectors
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
|
||||
t = transcache.m_AR[i].dot(eb) + ea[i];
|
||||
if(GIM_GREATER(T[i], t)) return false;
|
||||
}
|
||||
// Class II : B's basis vectors
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
t = MAT_DOT_COL(transcache.m_R1to0,T,i);
|
||||
t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i];
|
||||
if(GIM_GREATER(t,t2)) return false;
|
||||
}
|
||||
// Class III : 9 cross products
|
||||
if(fulltest)
|
||||
{
|
||||
int j,m,n,o,p,q,r;
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
m = (i+1)%3;
|
||||
n = (i+2)%3;
|
||||
o = i==0?1:0;
|
||||
p = i==2?1:2;
|
||||
for(j=0;j<3;j++)
|
||||
{
|
||||
q = j==2?1:2;
|
||||
r = j==0?1:0;
|
||||
t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
|
||||
t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
|
||||
eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
|
||||
if(GIM_GREATER(t,t2)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Simple test for planes.
|
||||
SIMD_FORCE_INLINE bool collide_plane(
|
||||
const btVector4 & plane)
|
||||
{
|
||||
ePLANE_INTERSECTION_TYPE classify = plane_classify(plane);
|
||||
return (classify == G_COLLIDE_PLANE);
|
||||
}
|
||||
|
||||
//! test for a triangle, with edges
|
||||
SIMD_FORCE_INLINE bool collide_triangle_exact(
|
||||
const btVector3 & p1,
|
||||
const btVector3 & p2,
|
||||
const btVector3 & p3,
|
||||
const btVector4 & triangle_plane)
|
||||
{
|
||||
if(!collide_plane(triangle_plane)) return false;
|
||||
|
||||
btVector3 center,extends;
|
||||
this->get_center_extend(center,extends);
|
||||
|
||||
const btVector3 v1(p1 - center);
|
||||
const btVector3 v2(p2 - center);
|
||||
const btVector3 v3(p3 - center);
|
||||
|
||||
//First axis
|
||||
btVector3 diff(v2 - v1);
|
||||
btVector3 abs_diff = diff.absolute();
|
||||
//Test With X axis
|
||||
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
|
||||
//Test With Y axis
|
||||
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
|
||||
//Test With Z axis
|
||||
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
|
||||
|
||||
|
||||
diff = v3 - v2;
|
||||
abs_diff = diff.absolute();
|
||||
//Test With X axis
|
||||
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
|
||||
//Test With Y axis
|
||||
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
|
||||
//Test With Z axis
|
||||
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
|
||||
|
||||
diff = v1 - v3;
|
||||
abs_diff = diff.absolute();
|
||||
//Test With X axis
|
||||
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
|
||||
//Test With Y axis
|
||||
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
|
||||
//Test With Z axis
|
||||
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Compairison of transformation objects
|
||||
SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
|
||||
{
|
||||
if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
|
||||
|
||||
if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
|
||||
if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
|
||||
if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // GIM_BOX_COLLISION_H_INCLUDED
|
||||
678
Extras/GIMPACT/include/GIMPACT/core/gim_box_set.h
Executable file
678
Extras/GIMPACT/include/GIMPACT/core/gim_box_set.h
Executable file
@@ -0,0 +1,678 @@
|
||||
#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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "GIMPACT/core/gim_array.h"
|
||||
#include "GIMPACT/core/gim_radixsort.h"
|
||||
#include "GIMPACT/core/gim_box_collision.h"
|
||||
#include "GIMPACT/core/gim_tri_collision.h"
|
||||
|
||||
|
||||
/*! \defgroup BOX_PRUNNING
|
||||
|
||||
|
||||
|
||||
*/
|
||||
//! @{
|
||||
|
||||
//! Overlapping pair
|
||||
struct GIM_PAIR
|
||||
{
|
||||
GUINT m_index1;
|
||||
GUINT m_index2;
|
||||
GIM_PAIR()
|
||||
{}
|
||||
|
||||
GIM_PAIR(const GIM_PAIR & p)
|
||||
{
|
||||
m_index1 = p.m_index1;
|
||||
m_index2 = p.m_index2;
|
||||
}
|
||||
|
||||
GIM_PAIR(GUINT index1, GUINT index2)
|
||||
{
|
||||
m_index1 = index1;
|
||||
m_index2 = index2;
|
||||
}
|
||||
};
|
||||
|
||||
//! A pairset array
|
||||
class gim_pair_set: public gim_array<GIM_PAIR>
|
||||
{
|
||||
public:
|
||||
gim_pair_set():gim_array<GIM_PAIR>(32)
|
||||
{
|
||||
}
|
||||
inline void push_pair(GUINT index1,GUINT index2)
|
||||
{
|
||||
push_back(GIM_PAIR(index1,index2));
|
||||
}
|
||||
|
||||
inline void push_pair_inv(GUINT index1,GUINT index2)
|
||||
{
|
||||
push_back(GIM_PAIR(index2,index1));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Prototype Base class for primitive classification
|
||||
/*!
|
||||
This class is a wrapper for primitive collections.
|
||||
This tells relevant info for the Bounding Box set classes, which take care of space classification.
|
||||
This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
|
||||
*/
|
||||
class GIM_PRIMITIVE_MANAGER_PROTOTYPE
|
||||
{
|
||||
public:
|
||||
|
||||
//! determines if this manager consist on only triangles, which special case will be optimized
|
||||
virtual bool is_trimesh() = 0;
|
||||
virtual GUINT get_primitive_count() = 0;
|
||||
virtual void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) = 0;
|
||||
virtual void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) = 0;
|
||||
};
|
||||
|
||||
|
||||
struct GIM_AABB_DATA
|
||||
{
|
||||
GIM_AABB m_bound;
|
||||
GUINT m_data;
|
||||
};
|
||||
|
||||
//! Node Structure for trees
|
||||
struct GIM_BOX_TREE_NODE
|
||||
{
|
||||
GIM_AABB m_bound;
|
||||
GUINT m_left;//!< Left subtree
|
||||
GUINT m_right;//!< Right subtree
|
||||
GUINT m_escapeIndex;//!< Scape index for traversing
|
||||
GUINT m_data;//!< primitive index if apply
|
||||
|
||||
GIM_BOX_TREE_NODE()
|
||||
{
|
||||
m_left = 0;
|
||||
m_right = 0;
|
||||
m_escapeIndex = 0;
|
||||
m_data = 0;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool is_leaf_node() const
|
||||
{
|
||||
return (!m_left && !m_right);
|
||||
}
|
||||
};
|
||||
|
||||
//! Basic Box tree structure
|
||||
class GIM_BOX_TREE
|
||||
{
|
||||
protected:
|
||||
GUINT m_num_nodes;
|
||||
gim_array<GIM_BOX_TREE_NODE> m_node_array;
|
||||
protected:
|
||||
GUINT _sort_and_calc_splitting_index(
|
||||
gim_array<GIM_AABB_DATA> & primitive_boxes,
|
||||
GUINT startIndex, GUINT endIndex, GUINT splitAxis);
|
||||
|
||||
GUINT _calc_splitting_axis(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex);
|
||||
|
||||
void _build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex);
|
||||
public:
|
||||
GIM_BOX_TREE()
|
||||
{
|
||||
m_num_nodes = 0;
|
||||
}
|
||||
|
||||
//! prototype functions for box tree management
|
||||
//!@{
|
||||
void build_tree(gim_array<GIM_AABB_DATA> & primitive_boxes);
|
||||
|
||||
SIMD_FORCE_INLINE void clearNodes()
|
||||
{
|
||||
m_node_array.clear();
|
||||
m_num_nodes = 0;
|
||||
}
|
||||
|
||||
//! node count
|
||||
SIMD_FORCE_INLINE GUINT getNodeCount() const
|
||||
{
|
||||
return m_num_nodes;
|
||||
}
|
||||
|
||||
//! tells if the node is a leaf
|
||||
SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
|
||||
{
|
||||
return m_node_array[nodeindex].is_leaf_node();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
|
||||
{
|
||||
return m_node_array[nodeindex].m_data;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
|
||||
{
|
||||
bound = m_node_array[nodeindex].m_bound;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
|
||||
{
|
||||
m_node_array[nodeindex].m_bound = bound;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
|
||||
{
|
||||
return m_node_array[nodeindex].m_left;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
|
||||
{
|
||||
return m_node_array[nodeindex].m_right;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
|
||||
{
|
||||
return m_node_array[nodeindex].m_escapeIndex;
|
||||
}
|
||||
|
||||
//!@}
|
||||
};
|
||||
|
||||
|
||||
//! Generic Box Tree Template
|
||||
/*!
|
||||
This class offers an structure for managing a box tree of primitives.
|
||||
Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and
|
||||
a Box tree structure ( like GIM_BOX_TREE).
|
||||
*/
|
||||
template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE, typename _GIM_BOX_TREE_PROTOTYPE>
|
||||
class GIM_BOX_TREE_TEMPLATE_SET
|
||||
{
|
||||
protected:
|
||||
_GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager;
|
||||
_GIM_BOX_TREE_PROTOTYPE m_box_tree;
|
||||
protected:
|
||||
//stackless refit
|
||||
SIMD_FORCE_INLINE void refit()
|
||||
{
|
||||
GUINT nodecount = getNodeCount();
|
||||
while(nodecount--)
|
||||
{
|
||||
if(isLeafNode(nodecount))
|
||||
{
|
||||
GIM_AABB leafbox;
|
||||
m_primitive_manager.get_primitive_box(getNodeData(nodecount),leafbox);
|
||||
setNodeBound(nodecount,leafbox);
|
||||
}
|
||||
else
|
||||
{
|
||||
//get left bound
|
||||
GUINT childindex = getLeftNodeIndex(nodecount);
|
||||
GIM_AABB bound;
|
||||
getNodeBound(childindex,bound);
|
||||
//get right bound
|
||||
childindex = getRightNodeIndex(nodecount);
|
||||
GIM_AABB bound2;
|
||||
getNodeBound(childindex,bound2);
|
||||
bound.merge(bound2);
|
||||
|
||||
setNodeBound(nodecount,bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
GIM_BOX_TREE_TEMPLATE_SET()
|
||||
{
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const
|
||||
{
|
||||
GIM_AABB totalbox;
|
||||
getNodeBound(0, totalbox);
|
||||
return totalbox;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & primitive_manager)
|
||||
{
|
||||
m_primitive_manager = primitive_manager;
|
||||
}
|
||||
|
||||
const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() const
|
||||
{
|
||||
return m_primitive_manager;
|
||||
}
|
||||
|
||||
_GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager()
|
||||
{
|
||||
return m_primitive_manager;
|
||||
}
|
||||
|
||||
//! node manager prototype functions
|
||||
///@{
|
||||
|
||||
//! this attemps to refit the box set.
|
||||
SIMD_FORCE_INLINE void update()
|
||||
{
|
||||
refit();
|
||||
}
|
||||
|
||||
//! this rebuild the entire set
|
||||
SIMD_FORCE_INLINE void buildSet()
|
||||
{
|
||||
//obtain primitive boxes
|
||||
gim_array<GIM_AABB_DATA> primitive_boxes;
|
||||
primitive_boxes.resize(m_primitive_manager.get_primitive_count(),false);
|
||||
|
||||
for (GUINT i = 0;i<primitive_boxes.size() ;i++ )
|
||||
{
|
||||
m_primitive_manager.get_primitive_box(i,primitive_boxes[i].m_bound);
|
||||
primitive_boxes[i].m_data = i;
|
||||
}
|
||||
|
||||
m_box_tree.build_tree(primitive_boxes);
|
||||
}
|
||||
|
||||
//! returns the indices of the primitives in the m_primitive_manager
|
||||
SIMD_FORCE_INLINE bool boxQuery(const GIM_AABB & box, gim_array<GUINT> & collided_results) const
|
||||
{
|
||||
GUINT curIndex = 0;
|
||||
GUINT numNodes = getNodeCount();
|
||||
|
||||
while (curIndex < numNodes)
|
||||
{
|
||||
GIM_AABB bound;
|
||||
getNodeBound(curIndex,bound);
|
||||
|
||||
//catch bugs in tree data
|
||||
|
||||
bool aabbOverlap = bound.has_collision(box);
|
||||
bool isleafnode = isLeafNode(curIndex);
|
||||
|
||||
if (isleafnode && aabbOverlap)
|
||||
{
|
||||
collided_results.push_back(getNodeData(curIndex));
|
||||
}
|
||||
|
||||
if (aabbOverlap || isleafnode)
|
||||
{
|
||||
//next subnode
|
||||
curIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//skip node
|
||||
curIndex+= getScapeNodeIndex(curIndex);
|
||||
}
|
||||
}
|
||||
if(collided_results.size()>0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//! returns the indices of the primitives in the m_primitive_manager
|
||||
SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB & box,
|
||||
const btTransform & transform, gim_array<GUINT> & collided_results) const
|
||||
{
|
||||
GIM_AABB transbox=box;
|
||||
transbox.appy_transform(transform);
|
||||
return boxQuery(transbox,collided_results);
|
||||
}
|
||||
|
||||
//! returns the indices of the primitives in the m_primitive_manager
|
||||
SIMD_FORCE_INLINE bool rayQuery(
|
||||
const btVector3 & ray_dir,const btVector3 & ray_origin ,
|
||||
gim_array<GUINT> & collided_results) const
|
||||
{
|
||||
GUINT curIndex = 0;
|
||||
GUINT numNodes = getNodeCount();
|
||||
|
||||
while (curIndex < numNodes)
|
||||
{
|
||||
GIM_AABB bound;
|
||||
getNodeBound(curIndex,bound);
|
||||
|
||||
//catch bugs in tree data
|
||||
|
||||
bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
|
||||
bool isleafnode = isLeafNode(curIndex);
|
||||
|
||||
if (isleafnode && aabbOverlap)
|
||||
{
|
||||
collided_results.push_back(getNodeData( curIndex));
|
||||
}
|
||||
|
||||
if (aabbOverlap || isleafnode)
|
||||
{
|
||||
//next subnode
|
||||
curIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//skip node
|
||||
curIndex+= getScapeNodeIndex(curIndex);
|
||||
}
|
||||
}
|
||||
if(collided_results.size()>0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//! tells if this set has hierarcht
|
||||
SIMD_FORCE_INLINE bool hasHierarchy() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//! tells if this set is a trimesh
|
||||
SIMD_FORCE_INLINE bool isTrimesh() const
|
||||
{
|
||||
return m_primitive_manager.is_trimesh();
|
||||
}
|
||||
|
||||
//! node count
|
||||
SIMD_FORCE_INLINE GUINT getNodeCount() const
|
||||
{
|
||||
return m_box_tree.getNodeCount();
|
||||
}
|
||||
|
||||
//! tells if the node is a leaf
|
||||
SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
|
||||
{
|
||||
return m_box_tree.isLeafNode(nodeindex);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
|
||||
{
|
||||
return m_box_tree.getNodeData(nodeindex);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
|
||||
{
|
||||
m_box_tree.getNodeBound(nodeindex, bound);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
|
||||
{
|
||||
m_box_tree.setNodeBound(nodeindex, bound);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
|
||||
{
|
||||
return m_box_tree.getLeftNodeIndex(nodeindex);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
|
||||
{
|
||||
return m_box_tree.getRightNodeIndex(nodeindex);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
|
||||
{
|
||||
return m_box_tree.getScapeNodeIndex(nodeindex);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex,GIM_TRIANGLE & triangle) const
|
||||
{
|
||||
m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex),triangle);
|
||||
}
|
||||
|
||||
//! @}
|
||||
};
|
||||
|
||||
//! Class for Box Tree Sets
|
||||
/*!
|
||||
this has the GIM_BOX_TREE implementation for bounding boxes.
|
||||
*/
|
||||
template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE>
|
||||
class GIM_BOX_TREE_SET: public GIM_BOX_TREE_TEMPLATE_SET< _GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE>
|
||||
{
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// GIM_BOX_SET collision methods
|
||||
template<typename BOX_SET_CLASS0,typename BOX_SET_CLASS1>
|
||||
class GIM_TREE_TREE_COLLIDER
|
||||
{
|
||||
public:
|
||||
gim_pair_set * m_collision_pairs;
|
||||
BOX_SET_CLASS0 * m_boxset0;
|
||||
BOX_SET_CLASS1 * m_boxset1;
|
||||
GUINT current_node0;
|
||||
GUINT current_node1;
|
||||
bool node0_is_leaf;
|
||||
bool node1_is_leaf;
|
||||
bool t0_is_trimesh;
|
||||
bool t1_is_trimesh;
|
||||
bool node0_has_triangle;
|
||||
bool node1_has_triangle;
|
||||
GIM_AABB m_box0;
|
||||
GIM_AABB m_box1;
|
||||
GIM_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
|
||||
btTransform trans_cache_0to1;
|
||||
GIM_TRIANGLE m_tri0;
|
||||
btVector4 m_tri0_plane;
|
||||
GIM_TRIANGLE m_tri1;
|
||||
btVector4 m_tri1_plane;
|
||||
|
||||
|
||||
public:
|
||||
GIM_TREE_TREE_COLLIDER()
|
||||
{
|
||||
current_node0 = G_UINT_INFINITY;
|
||||
current_node1 = G_UINT_INFINITY;
|
||||
}
|
||||
protected:
|
||||
SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0)
|
||||
{
|
||||
if(node0_has_triangle) return;
|
||||
m_boxset0->getNodeTriangle(node0,m_tri0);
|
||||
//transform triangle
|
||||
m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]);
|
||||
m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]);
|
||||
m_tri0.m_vertices[2] = trans_cache_0to1(m_tri0.m_vertices[2]);
|
||||
m_tri0.get_plane(m_tri0_plane);
|
||||
|
||||
node0_has_triangle = true;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1)
|
||||
{
|
||||
if(node1_has_triangle) return;
|
||||
m_boxset1->getNodeTriangle(node1,m_tri1);
|
||||
//transform triangle
|
||||
m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]);
|
||||
m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]);
|
||||
m_tri1.m_vertices[2] = trans_cache_1to0.transform(m_tri1.m_vertices[2]);
|
||||
m_tri1.get_plane(m_tri1_plane);
|
||||
|
||||
node1_has_triangle = true;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0)
|
||||
{
|
||||
if(node0 == current_node0) return;
|
||||
m_boxset0->getNodeBound(node0,m_box0);
|
||||
node0_is_leaf = m_boxset0->isLeafNode(node0);
|
||||
node0_has_triangle = false;
|
||||
current_node0 = node0;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1)
|
||||
{
|
||||
if(node1 == current_node1) return;
|
||||
m_boxset1->getNodeBound(node1,m_box1);
|
||||
node1_is_leaf = m_boxset1->isLeafNode(node1);
|
||||
node1_has_triangle = false;
|
||||
current_node1 = node1;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool node_collision(GUINT node0 ,GUINT node1)
|
||||
{
|
||||
retrieve_node0_info(node0);
|
||||
retrieve_node1_info(node1);
|
||||
bool result = m_box0.overlapping_trans_cache(m_box1,trans_cache_1to0,true);
|
||||
if(!result) return false;
|
||||
|
||||
if(t0_is_trimesh && node0_is_leaf)
|
||||
{
|
||||
//perform primitive vs box collision
|
||||
retrieve_node0_triangle(node0);
|
||||
//do triangle vs box collision
|
||||
m_box1.increment_margin(m_tri0.m_margin);
|
||||
|
||||
result = m_box1.collide_triangle_exact(
|
||||
m_tri0.m_vertices[0],m_tri0.m_vertices[1],m_tri0.m_vertices[2],m_tri0_plane);
|
||||
|
||||
m_box1.increment_margin(-m_tri0.m_margin);
|
||||
|
||||
if(!result) return false;
|
||||
return true;
|
||||
}
|
||||
else if(t1_is_trimesh && node1_is_leaf)
|
||||
{
|
||||
//perform primitive vs box collision
|
||||
retrieve_node1_triangle(node1);
|
||||
//do triangle vs box collision
|
||||
m_box0.increment_margin(m_tri1.m_margin);
|
||||
|
||||
result = m_box0.collide_triangle_exact(
|
||||
m_tri1.m_vertices[0],m_tri1.m_vertices[1],m_tri1.m_vertices[2],m_tri1_plane);
|
||||
|
||||
m_box0.increment_margin(-m_tri1.m_margin);
|
||||
|
||||
if(!result) return false;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//stackless collision routine
|
||||
void find_collision_pairs()
|
||||
{
|
||||
gim_pair_set stack_collisions;
|
||||
stack_collisions.reserve(32);
|
||||
|
||||
//add the first pair
|
||||
stack_collisions.push_pair(0,0);
|
||||
|
||||
|
||||
while(stack_collisions.size())
|
||||
{
|
||||
//retrieve the last pair and pop
|
||||
GUINT node0 = stack_collisions.back().m_index1;
|
||||
GUINT node1 = stack_collisions.back().m_index2;
|
||||
stack_collisions.pop_back();
|
||||
if(node_collision(node0,node1)) // a collision is found
|
||||
{
|
||||
if(node0_is_leaf)
|
||||
{
|
||||
if(node1_is_leaf)
|
||||
{
|
||||
m_collision_pairs->push_pair(m_boxset1->getNodeData(node0),m_boxset1->getNodeData(node1));
|
||||
}
|
||||
else
|
||||
{
|
||||
//collide left
|
||||
stack_collisions.push_pair(node0,m_boxset1->getLeftNodeIndex(node1));
|
||||
|
||||
//collide right
|
||||
stack_collisions.push_pair(node0,m_boxset1->getRightNodeIndex(node1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(node1_is_leaf)
|
||||
{
|
||||
//collide left
|
||||
stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0),node1);
|
||||
//collide right
|
||||
stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0),node1);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUINT left0 = m_boxset0->getLeftNodeIndex(node0);
|
||||
GUINT right0 = m_boxset0->getRightNodeIndex(node0);
|
||||
GUINT left1 = m_boxset1->getLeftNodeIndex(node1);
|
||||
GUINT right1 = m_boxset1->getRightNodeIndex(node1);
|
||||
//collide left
|
||||
stack_collisions.push_pair(left0,left1);
|
||||
//collide right
|
||||
stack_collisions.push_pair(left0,right1);
|
||||
//collide left
|
||||
stack_collisions.push_pair(right0,left1);
|
||||
//collide right
|
||||
stack_collisions.push_pair(right0,right1);
|
||||
|
||||
}// else if node1 is not a leaf
|
||||
}// else if node0 is not a leaf
|
||||
|
||||
}// if(node_collision(node0,node1))
|
||||
}//while(stack_collisions.size())
|
||||
}
|
||||
public:
|
||||
void find_collision(BOX_SET_CLASS0 * boxset1, const btTransform & trans1,
|
||||
BOX_SET_CLASS1 * boxset2, const btTransform & trans2,
|
||||
gim_pair_set & collision_pairs, bool complete_primitive_tests = true)
|
||||
{
|
||||
m_collision_pairs = &collision_pairs;
|
||||
m_boxset0 = boxset1;
|
||||
m_boxset1 = boxset2;
|
||||
|
||||
trans_cache_1to0.calc_from_homogenic(trans1,trans2);
|
||||
|
||||
trans_cache_0to1 = trans2.inverse();
|
||||
trans_cache_0to1 *= trans1;
|
||||
|
||||
|
||||
if(complete_primitive_tests)
|
||||
{
|
||||
t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh();
|
||||
t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh();
|
||||
}
|
||||
else
|
||||
{
|
||||
t0_is_trimesh = false;
|
||||
t1_is_trimesh = false;
|
||||
}
|
||||
|
||||
find_collision_pairs();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // GIM_BOXPRUNING_H_INCLUDED
|
||||
214
Extras/GIMPACT/include/GIMPACT/core/gim_clip_polygon.h
Executable file
214
Extras/GIMPACT/include/GIMPACT/core/gim_clip_polygon.h
Executable file
@@ -0,0 +1,214 @@
|
||||
#ifndef GIM_CLIP_POLYGON_H_INCLUDED
|
||||
#define GIM_CLIP_POLYGON_H_INCLUDED
|
||||
|
||||
/*! \file gim_tri_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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*! \addtogroup GEOMETRIC_OPERATIONS
|
||||
*/
|
||||
//! @{
|
||||
|
||||
//! This function calcs the distance from a 3D plane
|
||||
class DISTANCE_PLANE_3D_FUNC
|
||||
{
|
||||
public:
|
||||
template<typename CLASS_POINT,typename CLASS_PLANE>
|
||||
inline GREAL operator()(const CLASS_PLANE & plane, const CLASS_POINT & point)
|
||||
{
|
||||
return DISTANCE_PLANE_POINT(plane, point);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename CLASS_POINT>
|
||||
SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT(
|
||||
const CLASS_POINT & point0,
|
||||
const CLASS_POINT & point1,
|
||||
GREAL dist0,
|
||||
GREAL dist1,
|
||||
CLASS_POINT * clipped,
|
||||
GUINT & clipped_count)
|
||||
{
|
||||
GUINT _prevclassif = (dist0>G_EPSILON);
|
||||
GUINT _classif = (dist1>G_EPSILON);
|
||||
if(_classif!=_prevclassif)
|
||||
{
|
||||
GREAL blendfactor = -dist0/(dist1-dist0);
|
||||
VEC_BLEND(clipped[clipped_count],point0,point1,blendfactor);
|
||||
clipped_count++;
|
||||
}
|
||||
if(!_classif)
|
||||
{
|
||||
VEC_COPY(clipped[clipped_count],point1);
|
||||
clipped_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Clips a polygon by a plane
|
||||
/*!
|
||||
*\return The count of the clipped counts
|
||||
*/
|
||||
template<typename CLASS_POINT,typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
|
||||
SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC(
|
||||
const CLASS_PLANE & plane,
|
||||
const CLASS_POINT * polygon_points,
|
||||
GUINT polygon_point_count,
|
||||
CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)
|
||||
{
|
||||
GUINT clipped_count = 0;
|
||||
|
||||
|
||||
//clip first point
|
||||
GREAL firstdist = distance_func(plane,polygon_points[0]);;
|
||||
if(!(firstdist>G_EPSILON))
|
||||
{
|
||||
VEC_COPY(clipped[clipped_count],polygon_points[0]);
|
||||
clipped_count++;
|
||||
}
|
||||
|
||||
GREAL olddist = firstdist;
|
||||
for(GUINT _i=1;_i<polygon_point_count;_i++)
|
||||
{
|
||||
GREAL dist = distance_func(plane,polygon_points[_i]);
|
||||
|
||||
PLANE_CLIP_POLYGON_COLLECT(
|
||||
polygon_points[_i-1],polygon_points[_i],
|
||||
olddist,
|
||||
dist,
|
||||
clipped,
|
||||
clipped_count);
|
||||
|
||||
|
||||
olddist = dist;
|
||||
}
|
||||
|
||||
//RETURN TO FIRST point
|
||||
|
||||
PLANE_CLIP_POLYGON_COLLECT(
|
||||
polygon_points[polygon_point_count-1],polygon_points[0],
|
||||
olddist,
|
||||
firstdist,
|
||||
clipped,
|
||||
clipped_count);
|
||||
|
||||
return clipped_count;
|
||||
}
|
||||
|
||||
//! Clips a polygon by a plane
|
||||
/*!
|
||||
*\return The count of the clipped counts
|
||||
*/
|
||||
template<typename CLASS_POINT,typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
|
||||
SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC(
|
||||
const CLASS_PLANE & plane,
|
||||
const CLASS_POINT & point0,
|
||||
const CLASS_POINT & point1,
|
||||
const CLASS_POINT & point2,
|
||||
CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)
|
||||
{
|
||||
GUINT clipped_count = 0;
|
||||
|
||||
//clip first point
|
||||
GREAL firstdist = distance_func(plane,point0);;
|
||||
if(!(firstdist>G_EPSILON))
|
||||
{
|
||||
VEC_COPY(clipped[clipped_count],point0);
|
||||
clipped_count++;
|
||||
}
|
||||
|
||||
// point 1
|
||||
GREAL olddist = firstdist;
|
||||
GREAL dist = distance_func(plane,point1);
|
||||
|
||||
PLANE_CLIP_POLYGON_COLLECT(
|
||||
point0,point1,
|
||||
olddist,
|
||||
dist,
|
||||
clipped,
|
||||
clipped_count);
|
||||
|
||||
olddist = dist;
|
||||
|
||||
|
||||
// point 2
|
||||
dist = distance_func(plane,point2);
|
||||
|
||||
PLANE_CLIP_POLYGON_COLLECT(
|
||||
point1,point2,
|
||||
olddist,
|
||||
dist,
|
||||
clipped,
|
||||
clipped_count);
|
||||
olddist = dist;
|
||||
|
||||
|
||||
|
||||
//RETURN TO FIRST point
|
||||
PLANE_CLIP_POLYGON_COLLECT(
|
||||
point2,point0,
|
||||
olddist,
|
||||
firstdist,
|
||||
clipped,
|
||||
clipped_count);
|
||||
|
||||
return clipped_count;
|
||||
}
|
||||
|
||||
|
||||
template<typename CLASS_POINT,typename CLASS_PLANE>
|
||||
SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D(
|
||||
const CLASS_PLANE & plane,
|
||||
const CLASS_POINT * polygon_points,
|
||||
GUINT polygon_point_count,
|
||||
CLASS_POINT * clipped)
|
||||
{
|
||||
return PLANE_CLIP_POLYGON_GENERIC<CLASS_POINT,CLASS_PLANE>(plane,polygon_points,polygon_point_count,clipped,DISTANCE_PLANE_3D_FUNC());
|
||||
}
|
||||
|
||||
|
||||
template<typename CLASS_POINT,typename CLASS_PLANE>
|
||||
SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D(
|
||||
const CLASS_PLANE & plane,
|
||||
const CLASS_POINT & point0,
|
||||
const CLASS_POINT & point1,
|
||||
const CLASS_POINT & point2,
|
||||
CLASS_POINT * clipped)
|
||||
{
|
||||
return PLANE_CLIP_TRIANGLE_GENERIC<CLASS_POINT,CLASS_PLANE>(plane,point0,point1,point2,clipped,DISTANCE_PLANE_3D_FUNC());
|
||||
}
|
||||
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // GIM_TRI_COLLISION_H_INCLUDED
|
||||
172
Extras/GIMPACT/include/GIMPACT/core/gim_contact.h
Executable file
172
Extras/GIMPACT/include/GIMPACT/core/gim_contact.h
Executable file
@@ -0,0 +1,172 @@
|
||||
#ifndef GIM_CONTACT_H_INCLUDED
|
||||
#define GIM_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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
#include "GIMPACT/core/gim_geometry.h"
|
||||
#include "GIMPACT/core/gim_radixsort.h"
|
||||
#include "GIMPACT/core/gim_array.h"
|
||||
|
||||
/*! \defgroup CONTACTS
|
||||
\brief
|
||||
Functions for managing and sorting contacts resulting from a collision query.
|
||||
<ul>
|
||||
<li> Contact lists must be create by calling \ref GIM_CREATE_CONTACT_LIST
|
||||
<li> After querys, contact lists must be destroy by calling \ref GIM_DYNARRAY_DESTROY
|
||||
<li> Contacts can be merge for avoid duplicate results by calling \ref gim_merge_contacts
|
||||
</ul>
|
||||
|
||||
*/
|
||||
//! @{
|
||||
|
||||
/**
|
||||
Configuration var for applying interpolation of contact normals
|
||||
*/
|
||||
#define NORMAL_CONTACT_AVERAGE 1
|
||||
#define CONTACT_DIFF_EPSILON 0.00001f
|
||||
|
||||
/// Structure for collision results
|
||||
class GIM_CONTACT
|
||||
{
|
||||
public:
|
||||
btVector3 m_point;
|
||||
btVector3 m_normal;
|
||||
GREAL m_depth;//Positive value indicates interpenetration
|
||||
GREAL m_distance;//Padding not for use
|
||||
GUINT m_feature1;//Face number
|
||||
GUINT m_feature2;//Face number
|
||||
public:
|
||||
GIM_CONTACT()
|
||||
{
|
||||
}
|
||||
|
||||
GIM_CONTACT(const GIM_CONTACT & contact):
|
||||
m_point(contact.m_point),
|
||||
m_normal(contact.m_normal),
|
||||
m_depth(contact.m_depth),
|
||||
m_feature1(contact.m_feature1),
|
||||
m_feature2(contact.m_feature2)
|
||||
{
|
||||
m_point = contact.m_point;
|
||||
m_normal = contact.m_normal;
|
||||
m_depth = contact.m_depth;
|
||||
m_feature1 = contact.m_feature1;
|
||||
m_feature2 = contact.m_feature2;
|
||||
}
|
||||
|
||||
GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
|
||||
GREAL depth, GUINT feature1, GUINT feature2):
|
||||
m_point(point),
|
||||
m_normal(normal),
|
||||
m_depth(depth),
|
||||
m_feature1(feature1),
|
||||
m_feature2(feature2)
|
||||
{
|
||||
}
|
||||
|
||||
//! Calcs key for coord classification
|
||||
SIMD_FORCE_INLINE GUINT calc_key_contact() const
|
||||
{
|
||||
GINT _coords[] = {
|
||||
(GINT)(m_point[0]*1000.0f+1.0f),
|
||||
(GINT)(m_point[1]*1333.0f),
|
||||
(GINT)(m_point[2]*2133.0f+3.0f)};
|
||||
GUINT _hash=0;
|
||||
GUINT *_uitmp = (GUINT *)(&_coords[0]);
|
||||
_hash = *_uitmp;
|
||||
_uitmp++;
|
||||
_hash += (*_uitmp)<<4;
|
||||
_uitmp++;
|
||||
_hash += (*_uitmp)<<8;
|
||||
return _hash;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,GUINT normal_count)
|
||||
{
|
||||
btVector3 vec_sum(m_normal);
|
||||
for(GUINT i=0;i<normal_count;i++)
|
||||
{
|
||||
vec_sum += normals[i];
|
||||
}
|
||||
|
||||
GREAL vec_sum_len = vec_sum.length2();
|
||||
if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
|
||||
|
||||
GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
|
||||
|
||||
m_normal = vec_sum*vec_sum_len;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class gim_contact_array:public gim_array<GIM_CONTACT>
|
||||
{
|
||||
public:
|
||||
gim_contact_array():gim_array<GIM_CONTACT>(64)
|
||||
{
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void push_contact(const btVector3 &point,const btVector3 & normal,
|
||||
GREAL depth, GUINT feature1, GUINT feature2)
|
||||
{
|
||||
push_back_mem();
|
||||
GIM_CONTACT & newele = back();
|
||||
newele.m_point = point;
|
||||
newele.m_normal = normal;
|
||||
newele.m_depth = depth;
|
||||
newele.m_feature1 = feature1;
|
||||
newele.m_feature2 = feature2;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void push_triangle_contacts(
|
||||
const GIM_TRIANGLE_CONTACT_DATA & tricontact,
|
||||
GUINT feature1,GUINT feature2)
|
||||
{
|
||||
for(GUINT i = 0;i<tricontact.m_point_count ;i++ )
|
||||
{
|
||||
push_back_mem();
|
||||
GIM_CONTACT & newele = back();
|
||||
newele.m_point = tricontact.m_points[i];
|
||||
newele.m_normal = tricontact.m_separating_normal;
|
||||
newele.m_depth = tricontact.m_penetration_depth;
|
||||
newele.m_feature1 = feature1;
|
||||
newele.m_feature2 = feature2;
|
||||
}
|
||||
}
|
||||
|
||||
void merge_contacts(const gim_contact_array & contacts, bool normal_contact_average = true);
|
||||
void merge_contacts_unique(const gim_contact_array & contacts);
|
||||
};
|
||||
|
||||
//! @}
|
||||
#endif // GIM_CONTACT_H_INCLUDED
|
||||
102
Extras/GIMPACT/include/GIMPACT/core/gim_geom_types.h
Executable file
102
Extras/GIMPACT/include/GIMPACT/core/gim_geom_types.h
Executable file
@@ -0,0 +1,102 @@
|
||||
#ifndef GIM_GEOM_TYPES_H_INCLUDED
|
||||
#define GIM_GEOM_TYPES_H_INCLUDED
|
||||
|
||||
/*! \file gim_geom_types.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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "GIMPACT/core/gim_math.h"
|
||||
|
||||
/*! \defgroup GEOMETRIC_TYPES
|
||||
\brief
|
||||
Basic types and constants for geometry
|
||||
*/
|
||||
//! @{
|
||||
|
||||
//! Short Integer vector 2D
|
||||
typedef GSHORT vec2s[2];
|
||||
//! Integer vector 3D
|
||||
typedef GSHORT vec3s[3];
|
||||
//! Integer vector 4D
|
||||
typedef GSHORT vec4s[4];
|
||||
|
||||
//! Short Integer vector 2D
|
||||
typedef GUSHORT vec2us[2];
|
||||
//! Integer vector 3D
|
||||
typedef GUSHORT vec3us[3];
|
||||
//! Integer vector 4D
|
||||
typedef GUSHORT vec4us[4];
|
||||
|
||||
//! Integer vector 2D
|
||||
typedef GINT vec2i[2];
|
||||
//! Integer vector 3D
|
||||
typedef GINT vec3i[3];
|
||||
//! Integer vector 4D
|
||||
typedef GINT vec4i[4];
|
||||
|
||||
//! Unsigned Integer vector 2D
|
||||
typedef GUINT vec2ui[2];
|
||||
//! Unsigned Integer vector 3D
|
||||
typedef GUINT vec3ui[3];
|
||||
//! Unsigned Integer vector 4D
|
||||
typedef GUINT vec4ui[4];
|
||||
|
||||
//! Float vector 2D
|
||||
typedef GREAL vec2f[2];
|
||||
//! Float vector 3D
|
||||
typedef GREAL vec3f[3];
|
||||
//! Float vector 4D
|
||||
typedef GREAL vec4f[4];
|
||||
|
||||
//! Double vector 2D
|
||||
typedef GREAL2 vec2d[2];
|
||||
//! Float vector 3D
|
||||
typedef GREAL2 vec3d[3];
|
||||
//! Float vector 4D
|
||||
typedef GREAL2 vec4d[4];
|
||||
|
||||
//! Matrix 2D, row ordered
|
||||
typedef GREAL mat2f[2][2];
|
||||
//! Matrix 3D, row ordered
|
||||
typedef GREAL mat3f[3][3];
|
||||
//! Matrix 4D, row ordered
|
||||
typedef GREAL mat4f[4][4];
|
||||
|
||||
//! Quaternion
|
||||
typedef GREAL quatf[4];
|
||||
|
||||
//typedef struct _aabb3f aabb3f;
|
||||
//! @}
|
||||
|
||||
|
||||
|
||||
#endif // GIM_GEOM_TYPES_H_INCLUDED
|
||||
44
Extras/GIMPACT/include/GIMPACT/core/gim_geometry.h
Executable file
44
Extras/GIMPACT/include/GIMPACT/core/gim_geometry.h
Executable file
@@ -0,0 +1,44 @@
|
||||
#ifndef GIM_GEOMETRY_H_INCLUDED
|
||||
#define GIM_GEOMETRY_H_INCLUDED
|
||||
|
||||
/*! \file gim_geometry.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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
///Additional Headers for Collision
|
||||
#include "GIMPACT/core/gim_basic_geometry_operations.h"
|
||||
#include "GIMPACT/core/gim_clip_polygon.h"
|
||||
#include "GIMPACT/core/gim_box_collision.h"
|
||||
#include "GIMPACT/core/gim_tri_collision.h"
|
||||
//#include "GIMPACT/core/gim_tri_sphere_collision.h"
|
||||
//#include "GIMPACT/core/gim_tri_capsule_collision.h"
|
||||
|
||||
#endif // GIM_VECTOR_H_INCLUDED
|
||||
920
Extras/GIMPACT/include/GIMPACT/core/gim_hash_table.h
Executable file
920
Extras/GIMPACT/include/GIMPACT/core/gim_hash_table.h
Executable file
@@ -0,0 +1,920 @@
|
||||
#ifndef GIM_HASH_TABLE_H_INCLUDED
|
||||
#define GIM_HASH_TABLE_H_INCLUDED
|
||||
/*! \file gim_trimesh_data.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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "GIMPACT/core/gim_radixsort.h"
|
||||
|
||||
/*! \addtogroup CONTAINERS
|
||||
\brief
|
||||
Abstract class for collision objects
|
||||
*/
|
||||
//! @{
|
||||
|
||||
#define GIM_INVALID_HASH 0xffffffff //!< A very very high value
|
||||
#define GIM_DEFAULT_HASH_TABLE_SIZE 380
|
||||
#define GIM_DEFAULT_HASH_TABLE_NODE_SIZE 4
|
||||
#define GIM_HASH_TABLE_GROW_FACTOR 2
|
||||
|
||||
#define GIM_MIN_RADIX_SORT_SIZE 860 //!< calibrated on a PIII
|
||||
|
||||
template<typename T>
|
||||
struct GIM_HASH_TABLE_NODE
|
||||
{
|
||||
GUINT m_key;
|
||||
T m_data;
|
||||
GIM_HASH_TABLE_NODE()
|
||||
{
|
||||
}
|
||||
|
||||
GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value)
|
||||
{
|
||||
m_key = value.m_key;
|
||||
m_data = value.m_data;
|
||||
}
|
||||
|
||||
GIM_HASH_TABLE_NODE(GUINT key, const T & data)
|
||||
{
|
||||
m_key = key;
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
bool operator <(const GIM_HASH_TABLE_NODE<T> & other) const
|
||||
{
|
||||
///inverse order, further objects are first
|
||||
if(m_key < other.m_key) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator >(const GIM_HASH_TABLE_NODE<T> & other) const
|
||||
{
|
||||
///inverse order, further objects are first
|
||||
if(m_key > other.m_key) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator ==(const GIM_HASH_TABLE_NODE<T> & other) const
|
||||
{
|
||||
///inverse order, further objects are first
|
||||
if(m_key == other.m_key) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
///Macro for getting the key
|
||||
class GIM_HASH_NODE_GET_KEY
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
inline GUINT operator()( const T& a)
|
||||
{
|
||||
return a.m_key;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
///Macro for comparing the key and the element
|
||||
class GIM_HASH_NODE_CMP_KEY_MACRO
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
inline int operator() ( const T& a, GUINT key)
|
||||
{
|
||||
return ((int)(a.m_key - key));
|
||||
}
|
||||
};
|
||||
|
||||
///Macro for comparing Hash nodes
|
||||
class GIM_HASH_NODE_CMP_MACRO
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
inline int operator() ( const T& a, const T& b )
|
||||
{
|
||||
return ((int)(a.m_key - b.m_key));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//! Sorting for hash table
|
||||
/*!
|
||||
switch automatically between quicksort and radixsort
|
||||
*/
|
||||
template<typename T>
|
||||
void gim_sort_hash_node_array(T * array, GUINT array_count)
|
||||
{
|
||||
if(array_count<GIM_MIN_RADIX_SORT_SIZE)
|
||||
{
|
||||
gim_heap_sort(array,array_count,GIM_HASH_NODE_CMP_MACRO());
|
||||
}
|
||||
else
|
||||
{
|
||||
memcopy_elements_func cmpfunc;
|
||||
gim_radix_sort(array,array_count,GIM_HASH_NODE_GET_KEY(),cmpfunc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Note: assumes long is at least 32 bits.
|
||||
#define GIM_NUM_PRIME 28
|
||||
|
||||
static const GUINT gim_prime_list[GIM_NUM_PRIME] =
|
||||
{
|
||||
53ul, 97ul, 193ul, 389ul, 769ul,
|
||||
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
|
||||
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
|
||||
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
|
||||
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
|
||||
1610612741ul, 3221225473ul, 4294967291ul
|
||||
};
|
||||
|
||||
inline GUINT gim_next_prime(GUINT number)
|
||||
{
|
||||
//Find nearest upper prime
|
||||
GUINT result_ind = 0;
|
||||
gim_binary_search(gim_prime_list,0,(GIM_NUM_PRIME-2),number,result_ind);
|
||||
|
||||
// inv: result_ind < 28
|
||||
return gim_prime_list[result_ind];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! A compact hash table implementation
|
||||
/*!
|
||||
A memory aligned compact hash table that coud be treated as an array.
|
||||
It could be a simple sorted array without the overhead of the hash key bucked, or could
|
||||
be a formely hash table with an array of keys.
|
||||
You can use switch_to_hashtable() and switch_to_sorted_array for saving space or increase speed.
|
||||
</br>
|
||||
|
||||
<ul>
|
||||
<li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
|
||||
When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
|
||||
<li> If node_size != 0, then this container becomes a hash table for ever
|
||||
</ul>
|
||||
|
||||
*/
|
||||
template<class T>
|
||||
class gim_hash_table
|
||||
{
|
||||
protected:
|
||||
typedef GIM_HASH_TABLE_NODE<T> _node_type;
|
||||
|
||||
//!The nodes
|
||||
//array< _node_type, SuperAllocator<_node_type> > m_nodes;
|
||||
gim_array< _node_type > m_nodes;
|
||||
//SuperBufferedArray< _node_type > m_nodes;
|
||||
bool m_sorted;
|
||||
|
||||
/*! \defgroup HASH_TABLE_STRUCTURES
|
||||
\brief
|
||||
Hash table data management. The hash table has the indices to the corresponding m_nodes array
|
||||
*/
|
||||
//! @{
|
||||
|
||||
GUINT * m_hash_table;//!<
|
||||
GUINT m_table_size;//!<
|
||||
GUINT m_node_size;//!<
|
||||
GUINT m_min_hash_table_size;
|
||||
|
||||
|
||||
|
||||
//! Returns the cell index
|
||||
inline GUINT _find_cell(GUINT hashkey)
|
||||
{
|
||||
_node_type * nodesptr = m_nodes.pointer();
|
||||
GUINT start_index = (hashkey%m_table_size)*m_node_size;
|
||||
GUINT end_index = start_index + m_node_size;
|
||||
|
||||
while(start_index<end_index)
|
||||
{
|
||||
GUINT value = m_hash_table[start_index];
|
||||
if(value != GIM_INVALID_HASH)
|
||||
{
|
||||
if(nodesptr[value].m_key == hashkey) return start_index;
|
||||
}
|
||||
start_index++;
|
||||
}
|
||||
return GIM_INVALID_HASH;
|
||||
}
|
||||
|
||||
//! Find the avaliable cell for the hashkey, and return an existing cell if it has the same hash key
|
||||
inline GUINT _find_avaliable_cell(GUINT hashkey)
|
||||
{
|
||||
_node_type * nodesptr = m_nodes.pointer();
|
||||
GUINT avaliable_index = GIM_INVALID_HASH;
|
||||
GUINT start_index = (hashkey%m_table_size)*m_node_size;
|
||||
GUINT end_index = start_index + m_node_size;
|
||||
|
||||
while(start_index<end_index)
|
||||
{
|
||||
GUINT value = m_hash_table[start_index];
|
||||
if(value == GIM_INVALID_HASH)
|
||||
{
|
||||
if(avaliable_index==GIM_INVALID_HASH)
|
||||
{
|
||||
avaliable_index = start_index;
|
||||
}
|
||||
}
|
||||
else if(nodesptr[value].m_key == hashkey)
|
||||
{
|
||||
return start_index;
|
||||
}
|
||||
start_index++;
|
||||
}
|
||||
return avaliable_index;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! reserves the memory for the hash table.
|
||||
/*!
|
||||
\pre hash table must be empty
|
||||
\post reserves the memory for the hash table, an initializes all elements to GIM_INVALID_HASH.
|
||||
*/
|
||||
inline void _reserve_table_memory(GUINT newtablesize)
|
||||
{
|
||||
if(newtablesize==0) return;
|
||||
if(m_node_size==0) return;
|
||||
|
||||
//Get a Prime size
|
||||
|
||||
m_table_size = gim_next_prime(newtablesize);
|
||||
|
||||
GUINT datasize = m_table_size*m_node_size;
|
||||
//Alloc the data buffer
|
||||
m_hash_table = (GUINT *)gim_alloc(datasize*sizeof(GUINT));
|
||||
}
|
||||
|
||||
inline void _invalidate_keys()
|
||||
{
|
||||
GUINT datasize = m_table_size*m_node_size;
|
||||
for(GUINT i=0;i<datasize;i++)
|
||||
{
|
||||
m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
|
||||
}
|
||||
}
|
||||
|
||||
//! Clear all memory for the hash table
|
||||
inline void _clear_table_memory()
|
||||
{
|
||||
if(m_hash_table==NULL) return;
|
||||
gim_free(m_hash_table);
|
||||
m_hash_table = NULL;
|
||||
m_table_size = 0;
|
||||
}
|
||||
|
||||
//! Invalidates the keys (Assigning GIM_INVALID_HASH to all) Reorders the hash keys
|
||||
inline void _rehash()
|
||||
{
|
||||
_invalidate_keys();
|
||||
|
||||
_node_type * nodesptr = m_nodes.pointer();
|
||||
for(GUINT i=0;i<(GUINT)m_nodes.size();i++)
|
||||
{
|
||||
GUINT nodekey = nodesptr[i].m_key;
|
||||
if(nodekey != GIM_INVALID_HASH)
|
||||
{
|
||||
//Search for the avaliable cell in buffer
|
||||
GUINT index = _find_avaliable_cell(nodekey);
|
||||
|
||||
|
||||
if(m_hash_table[index]!=GIM_INVALID_HASH)
|
||||
{//The new index is alreade used... discard this new incomming object, repeated key
|
||||
btAssert(m_hash_table[index]==nodekey);
|
||||
nodesptr[i].m_key = GIM_INVALID_HASH;
|
||||
}
|
||||
else
|
||||
{
|
||||
//;
|
||||
//Assign the value for alloc
|
||||
m_hash_table[index] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Resize hash table indices
|
||||
inline void _resize_table(GUINT newsize)
|
||||
{
|
||||
//Clear memory
|
||||
_clear_table_memory();
|
||||
//Alloc the data
|
||||
_reserve_table_memory(newsize);
|
||||
//Invalidate keys and rehash
|
||||
_rehash();
|
||||
}
|
||||
|
||||
//! Destroy hash table memory
|
||||
inline void _destroy()
|
||||
{
|
||||
if(m_hash_table==NULL) return;
|
||||
_clear_table_memory();
|
||||
}
|
||||
|
||||
//! Finds an avaliable hash table cell, and resizes the table if there isn't space
|
||||
inline GUINT _assign_hash_table_cell(GUINT hashkey)
|
||||
{
|
||||
GUINT cell_index = _find_avaliable_cell(hashkey);
|
||||
|
||||
if(cell_index==GIM_INVALID_HASH)
|
||||
{
|
||||
//rehashing
|
||||
_resize_table(m_table_size+1);
|
||||
GUINT cell_index = _find_avaliable_cell(hashkey);
|
||||
btAssert(cell_index!=GIM_INVALID_HASH);
|
||||
}
|
||||
return cell_index;
|
||||
}
|
||||
|
||||
//! erase by index in hash table
|
||||
inline bool _erase_by_index_hash_table(GUINT index)
|
||||
{
|
||||
if(index >= m_nodes.size()) return false;
|
||||
if(m_nodes[index].m_key != GIM_INVALID_HASH)
|
||||
{
|
||||
//Search for the avaliable cell in buffer
|
||||
GUINT cell_index = _find_cell(m_nodes[index].m_key);
|
||||
|
||||
btAssert(cell_index!=GIM_INVALID_HASH);
|
||||
btAssert(m_hash_table[cell_index]==index);
|
||||
|
||||
m_hash_table[cell_index] = GIM_INVALID_HASH;
|
||||
}
|
||||
|
||||
return this->_erase_unsorted(index);
|
||||
}
|
||||
|
||||
//! erase by key in hash table
|
||||
inline bool _erase_hash_table(GUINT hashkey)
|
||||
{
|
||||
if(hashkey == GIM_INVALID_HASH) return false;
|
||||
|
||||
//Search for the avaliable cell in buffer
|
||||
GUINT cell_index = _find_cell(hashkey);
|
||||
if(cell_index ==GIM_INVALID_HASH) return false;
|
||||
|
||||
GUINT index = m_hash_table[cell_index];
|
||||
m_hash_table[cell_index] = GIM_INVALID_HASH;
|
||||
|
||||
return this->_erase_unsorted(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! insert an element in hash table
|
||||
/*!
|
||||
If the element exists, this won't insert the element
|
||||
\return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
|
||||
If so, the element has been inserted at the last position of the array.
|
||||
*/
|
||||
inline GUINT _insert_hash_table(GUINT hashkey, const T & value)
|
||||
{
|
||||
if(hashkey==GIM_INVALID_HASH)
|
||||
{
|
||||
//Insert anyway
|
||||
_insert_unsorted(hashkey,value);
|
||||
return GIM_INVALID_HASH;
|
||||
}
|
||||
|
||||
GUINT cell_index = _assign_hash_table_cell(hashkey);
|
||||
|
||||
GUINT value_key = m_hash_table[cell_index];
|
||||
|
||||
if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited
|
||||
|
||||
m_hash_table[cell_index] = m_nodes.size();
|
||||
|
||||
_insert_unsorted(hashkey,value);
|
||||
return GIM_INVALID_HASH;
|
||||
}
|
||||
|
||||
//! insert an element in hash table.
|
||||
/*!
|
||||
If the element exists, this replaces the element.
|
||||
\return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
|
||||
If so, the element has been inserted at the last position of the array.
|
||||
*/
|
||||
inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value)
|
||||
{
|
||||
if(hashkey==GIM_INVALID_HASH)
|
||||
{
|
||||
//Insert anyway
|
||||
_insert_unsorted(hashkey,value);
|
||||
return GIM_INVALID_HASH;
|
||||
}
|
||||
|
||||
GUINT cell_index = _assign_hash_table_cell(hashkey);
|
||||
|
||||
GUINT value_key = m_hash_table[cell_index];
|
||||
|
||||
if(value_key!= GIM_INVALID_HASH)
|
||||
{//replaces the existing
|
||||
m_nodes[value_key] = _node_type(hashkey,value);
|
||||
return value_key;// index of the replaced element
|
||||
}
|
||||
|
||||
m_hash_table[cell_index] = m_nodes.size();
|
||||
|
||||
_insert_unsorted(hashkey,value);
|
||||
return GIM_INVALID_HASH;
|
||||
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
/*! \defgroup SORTED_ARRAY_STRUCTURES
|
||||
\brief
|
||||
Sorted array data management. The hash table has the indices to the corresponding m_nodes array
|
||||
*/
|
||||
//! @{
|
||||
inline bool _erase_sorted(GUINT index)
|
||||
{
|
||||
if(index>=(GUINT)m_nodes.size()) return false;
|
||||
m_nodes.erase_sorted(index);
|
||||
if(m_nodes.size()<2) m_sorted = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! faster, but unsorted
|
||||
inline bool _erase_unsorted(GUINT index)
|
||||
{
|
||||
if(index>=m_nodes.size()) return false;
|
||||
|
||||
GUINT lastindex = m_nodes.size()-1;
|
||||
if(index<lastindex && m_hash_table!=0)
|
||||
{
|
||||
GUINT hashkey = m_nodes[lastindex].m_key;
|
||||
if(hashkey!=GIM_INVALID_HASH)
|
||||
{
|
||||
//update the new position of the last element
|
||||
GUINT cell_index = _find_cell(hashkey);
|
||||
btAssert(cell_index!=GIM_INVALID_HASH);
|
||||
//new position of the last element which will be swaped
|
||||
m_hash_table[cell_index] = index;
|
||||
}
|
||||
}
|
||||
m_nodes.erase(index);
|
||||
m_sorted = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Insert in position ordered
|
||||
/*!
|
||||
Also checks if it is needed to transform this container to a hash table, by calling check_for_switching_to_hashtable
|
||||
*/
|
||||
inline void _insert_in_pos(GUINT hashkey, const T & value, GUINT pos)
|
||||
{
|
||||
m_nodes.insert(_node_type(hashkey,value),pos);
|
||||
this->check_for_switching_to_hashtable();
|
||||
}
|
||||
|
||||
//! Insert an element in an ordered array
|
||||
inline GUINT _insert_sorted(GUINT hashkey, const T & value)
|
||||
{
|
||||
if(hashkey==GIM_INVALID_HASH || size()==0)
|
||||
{
|
||||
m_nodes.push_back(_node_type(hashkey,value));
|
||||
return GIM_INVALID_HASH;
|
||||
}
|
||||
//Insert at last position
|
||||
//Sort element
|
||||
|
||||
|
||||
GUINT result_ind=0;
|
||||
GUINT last_index = m_nodes.size()-1;
|
||||
_node_type * ptr = m_nodes.pointer();
|
||||
|
||||
bool found = gim_binary_search_ex(
|
||||
ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
|
||||
|
||||
|
||||
//Insert before found index
|
||||
if(found)
|
||||
{
|
||||
return result_ind;
|
||||
}
|
||||
else
|
||||
{
|
||||
_insert_in_pos(hashkey, value, result_ind);
|
||||
}
|
||||
return GIM_INVALID_HASH;
|
||||
}
|
||||
|
||||
inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value)
|
||||
{
|
||||
if(hashkey==GIM_INVALID_HASH || size()==0)
|
||||
{
|
||||
m_nodes.push_back(_node_type(hashkey,value));
|
||||
return GIM_INVALID_HASH;
|
||||
}
|
||||
//Insert at last position
|
||||
//Sort element
|
||||
GUINT result_ind;
|
||||
GUINT last_index = m_nodes.size()-1;
|
||||
_node_type * ptr = m_nodes.pointer();
|
||||
|
||||
bool found = gim_binary_search_ex(
|
||||
ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
|
||||
|
||||
//Insert before found index
|
||||
if(found)
|
||||
{
|
||||
m_nodes[result_ind] = _node_type(hashkey,value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_insert_in_pos(hashkey, value, result_ind);
|
||||
}
|
||||
return result_ind;
|
||||
}
|
||||
|
||||
//! Fast insertion in m_nodes array
|
||||
inline GUINT _insert_unsorted(GUINT hashkey, const T & value)
|
||||
{
|
||||
m_nodes.push_back(_node_type(hashkey,value));
|
||||
m_sorted = false;
|
||||
return GIM_INVALID_HASH;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
<li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
|
||||
When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
|
||||
<li> If node_size != 0, then this container becomes a hash table for ever
|
||||
</ul>
|
||||
*/
|
||||
gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE,
|
||||
GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE,
|
||||
GUINT min_hash_table_size = GIM_INVALID_HASH)
|
||||
{
|
||||
m_hash_table = NULL;
|
||||
m_table_size = 0;
|
||||
m_sorted = false;
|
||||
m_node_size = node_size;
|
||||
m_min_hash_table_size = min_hash_table_size;
|
||||
|
||||
if(m_node_size!=0)
|
||||
{
|
||||
if(reserve_size!=0)
|
||||
{
|
||||
m_nodes.reserve(reserve_size);
|
||||
_reserve_table_memory(reserve_size);
|
||||
_invalidate_keys();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE);
|
||||
_reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE);
|
||||
_invalidate_keys();
|
||||
}
|
||||
}
|
||||
else if(reserve_size!=0)
|
||||
{
|
||||
m_nodes.reserve(reserve_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
~gim_hash_table()
|
||||
{
|
||||
_destroy();
|
||||
}
|
||||
|
||||
inline bool is_hash_table()
|
||||
{
|
||||
if(m_hash_table) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool is_sorted()
|
||||
{
|
||||
if(size()<2) return true;
|
||||
return m_sorted;
|
||||
}
|
||||
|
||||
bool sort()
|
||||
{
|
||||
if(is_sorted()) return true;
|
||||
if(m_nodes.size()<2) return false;
|
||||
|
||||
|
||||
_node_type * ptr = m_nodes.pointer();
|
||||
GUINT siz = m_nodes.size();
|
||||
gim_sort_hash_node_array(ptr,siz);
|
||||
m_sorted=true;
|
||||
|
||||
|
||||
|
||||
if(m_hash_table)
|
||||
{
|
||||
_rehash();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool switch_to_hashtable()
|
||||
{
|
||||
if(m_hash_table) return false;
|
||||
if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
|
||||
if(m_nodes.size()<GIM_DEFAULT_HASH_TABLE_SIZE)
|
||||
{
|
||||
_resize_table(GIM_DEFAULT_HASH_TABLE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
_resize_table(m_nodes.size()+1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool switch_to_sorted_array()
|
||||
{
|
||||
if(m_hash_table==NULL) return true;
|
||||
_clear_table_memory();
|
||||
return sort();
|
||||
}
|
||||
|
||||
//!If the container reaches the
|
||||
bool check_for_switching_to_hashtable()
|
||||
{
|
||||
if(this->m_hash_table) return true;
|
||||
|
||||
if(!(m_nodes.size()< m_min_hash_table_size))
|
||||
{
|
||||
if(m_node_size == 0)
|
||||
{
|
||||
m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
|
||||
}
|
||||
|
||||
_resize_table(m_nodes.size()+1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void set_sorted(bool value)
|
||||
{
|
||||
m_sorted = value;
|
||||
}
|
||||
|
||||
//! Retrieves the amount of keys.
|
||||
inline GUINT size() const
|
||||
{
|
||||
return m_nodes.size();
|
||||
}
|
||||
|
||||
//! Retrieves the hash key.
|
||||
inline GUINT get_key(GUINT index) const
|
||||
{
|
||||
return m_nodes[index].m_key;
|
||||
}
|
||||
|
||||
//! Retrieves the value by index
|
||||
/*!
|
||||
*/
|
||||
inline T * get_value_by_index(GUINT index)
|
||||
{
|
||||
return &m_nodes[index].m_data;
|
||||
}
|
||||
|
||||
inline const T& operator[](GUINT index) const
|
||||
{
|
||||
return m_nodes[index].m_data;
|
||||
}
|
||||
|
||||
inline T& operator[](GUINT index)
|
||||
{
|
||||
return m_nodes[index].m_data;
|
||||
}
|
||||
|
||||
//! Finds the index of the element with the key
|
||||
/*!
|
||||
\return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
|
||||
If so, the element has been inserted at the last position of the array.
|
||||
*/
|
||||
inline GUINT find(GUINT hashkey)
|
||||
{
|
||||
if(m_hash_table)
|
||||
{
|
||||
GUINT cell_index = _find_cell(hashkey);
|
||||
if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH;
|
||||
return m_hash_table[cell_index];
|
||||
}
|
||||
GUINT last_index = m_nodes.size();
|
||||
if(last_index<2)
|
||||
{
|
||||
if(last_index==0) return GIM_INVALID_HASH;
|
||||
if(m_nodes[0].m_key == hashkey) return 0;
|
||||
return GIM_INVALID_HASH;
|
||||
}
|
||||
else if(m_sorted)
|
||||
{
|
||||
//Binary search
|
||||
GUINT result_ind = 0;
|
||||
last_index--;
|
||||
_node_type * ptr = m_nodes.pointer();
|
||||
|
||||
bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
|
||||
|
||||
|
||||
if(found) return result_ind;
|
||||
}
|
||||
return GIM_INVALID_HASH;
|
||||
}
|
||||
|
||||
//! Retrieves the value associated with the index
|
||||
/*!
|
||||
\return the found element, or null
|
||||
*/
|
||||
inline T * get_value(GUINT hashkey)
|
||||
{
|
||||
GUINT index = find(hashkey);
|
||||
if(index == GIM_INVALID_HASH) return NULL;
|
||||
return &m_nodes[index].m_data;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
*/
|
||||
inline bool erase_by_index(GUINT index)
|
||||
{
|
||||
if(index > m_nodes.size()) return false;
|
||||
|
||||
if(m_hash_table == NULL)
|
||||
{
|
||||
if(is_sorted())
|
||||
{
|
||||
return this->_erase_sorted(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->_erase_unsorted(index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->_erase_by_index_hash_table(index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool erase_by_index_unsorted(GUINT index)
|
||||
{
|
||||
if(index > m_nodes.size()) return false;
|
||||
|
||||
if(m_hash_table == NULL)
|
||||
{
|
||||
return this->_erase_unsorted(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->_erase_by_index_hash_table(index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
inline bool erase_by_key(GUINT hashkey)
|
||||
{
|
||||
if(size()==0) return false;
|
||||
|
||||
if(m_hash_table)
|
||||
{
|
||||
return this->_erase_hash_table(hashkey);
|
||||
}
|
||||
//Binary search
|
||||
|
||||
if(is_sorted()==false) return false;
|
||||
|
||||
GUINT result_ind = find(hashkey);
|
||||
if(result_ind!= GIM_INVALID_HASH)
|
||||
{
|
||||
return this->_erase_sorted(result_ind);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_nodes.clear();
|
||||
|
||||
if(m_hash_table==NULL) return;
|
||||
GUINT datasize = m_table_size*m_node_size;
|
||||
//Initialize the hashkeys.
|
||||
GUINT i;
|
||||
for(i=0;i<datasize;i++)
|
||||
{
|
||||
m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
|
||||
}
|
||||
m_sorted = false;
|
||||
}
|
||||
|
||||
//! Insert an element into the hash
|
||||
/*!
|
||||
\return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
|
||||
of the existing element.
|
||||
*/
|
||||
inline GUINT insert(GUINT hashkey, const T & element)
|
||||
{
|
||||
if(m_hash_table)
|
||||
{
|
||||
return this->_insert_hash_table(hashkey,element);
|
||||
}
|
||||
if(this->is_sorted())
|
||||
{
|
||||
return this->_insert_sorted(hashkey,element);
|
||||
}
|
||||
return this->_insert_unsorted(hashkey,element);
|
||||
}
|
||||
|
||||
//! Insert an element into the hash, and could overrite an existing object with the same hash.
|
||||
/*!
|
||||
\return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
|
||||
of the replaced element.
|
||||
*/
|
||||
inline GUINT insert_override(GUINT hashkey, const T & element)
|
||||
{
|
||||
if(m_hash_table)
|
||||
{
|
||||
return this->_insert_hash_table_replace(hashkey,element);
|
||||
}
|
||||
if(this->is_sorted())
|
||||
{
|
||||
return this->_insert_sorted_replace(hashkey,element);
|
||||
}
|
||||
this->_insert_unsorted(hashkey,element);
|
||||
return m_nodes.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted
|
||||
/*!
|
||||
*/
|
||||
inline GUINT insert_unsorted(GUINT hashkey,const T & element)
|
||||
{
|
||||
if(m_hash_table)
|
||||
{
|
||||
return this->_insert_hash_table(hashkey,element);
|
||||
}
|
||||
return this->_insert_unsorted(hashkey,element);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
|
||||
|
||||
#endif // GIM_CONTAINERS_H_INCLUDED
|
||||
1584
Extras/GIMPACT/include/GIMPACT/core/gim_linear_math.h
Executable file
1584
Extras/GIMPACT/include/GIMPACT/core/gim_linear_math.h
Executable file
File diff suppressed because it is too large
Load Diff
181
Extras/GIMPACT/include/GIMPACT/core/gim_math.h
Executable file
181
Extras/GIMPACT/include/GIMPACT/core/gim_math.h
Executable file
@@ -0,0 +1,181 @@
|
||||
#ifndef GIM_MATH_H_INCLUDED
|
||||
#define GIM_MATH_H_INCLUDED
|
||||
/*! \file gim_math.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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "LinearMath/btScalar.h"
|
||||
|
||||
|
||||
/*! \defgroup BASIC_TYPES
|
||||
Basic types and constants
|
||||
Conventions:
|
||||
Types starting with G
|
||||
Constants starting with G_
|
||||
*/
|
||||
//! @{
|
||||
|
||||
#define GREAL btScalar
|
||||
#define GREAL2 double
|
||||
#define GINT int
|
||||
#define GUINT unsigned int
|
||||
#define GSHORT short
|
||||
#define GUSHORT unsigned short
|
||||
#define GINT64 long long
|
||||
#define GUINT64 unsigned long long
|
||||
|
||||
//! @}
|
||||
|
||||
/*! \defgroup BASIC_CONSTANTS
|
||||
Basic constants
|
||||
Conventions:
|
||||
Types starting with G
|
||||
Constants starting with G_
|
||||
*/
|
||||
//! @{
|
||||
|
||||
#define G_PI 3.14159265358979f
|
||||
#define G_HALF_PI 1.5707963f
|
||||
//267948966
|
||||
#define G_TWO_PI 6.28318530f
|
||||
//71795864
|
||||
#define G_ROOT3 1.73205f
|
||||
#define G_ROOT2 1.41421f
|
||||
#define G_UINT_INFINITY 0xffffffff //!< A very very high value
|
||||
#define G_REAL_INFINITY FLT_MAX
|
||||
#define G_SIGN_BITMASK 0x80000000
|
||||
#define G_EPSILON SIMD_EPSILON
|
||||
//! @}
|
||||
|
||||
|
||||
/*! \defgroup SCALAR_TYPES
|
||||
\brief
|
||||
Precision type constants
|
||||
*/
|
||||
//! @{
|
||||
enum GIM_SCALAR_TYPES
|
||||
{
|
||||
G_STYPE_REAL =0,
|
||||
G_STYPE_REAL2,
|
||||
G_STYPE_SHORT,
|
||||
G_STYPE_USHORT,
|
||||
G_STYPE_INT,
|
||||
G_STYPE_UINT,
|
||||
G_STYPE_INT64,
|
||||
G_STYPE_UINT64
|
||||
};
|
||||
//! @}
|
||||
|
||||
/*! \defgroup MATH_FUNCTIONS
|
||||
mathematical functions
|
||||
*/
|
||||
//! @{
|
||||
|
||||
#define G_DEGTORAD(X) ((X)*3.1415926f/180.0f)
|
||||
#define G_RADTODEG(X) ((X)*180.0f/3.1415926f)
|
||||
|
||||
//! Integer representation of a floating-point value.
|
||||
#define GIM_IR(x) ((GUINT&)(x))
|
||||
|
||||
//! Signed integer representation of a floating-point value.
|
||||
#define GIM_SIR(x) ((GINT&)(x))
|
||||
|
||||
//! Absolute integer representation of a floating-point value
|
||||
#define GIM_AIR(x) (GIM_IR(x)&0x7fffffff)
|
||||
|
||||
//! Floating-point representation of an integer value.
|
||||
#define GIM_FR(x) ((GREAL&)(x))
|
||||
|
||||
#define GIM_MAX(a,b) (a<b?b:a)
|
||||
#define GIM_MIN(a,b) (a>b?b:a)
|
||||
|
||||
#define GIM_MAX3(a,b,c) GIM_MAX(a,GIM_MAX(b,c))
|
||||
#define GIM_MIN3(a,b,c) GIM_MIN(a,GIM_MIN(b,c))
|
||||
|
||||
#define GIM_IS_ZERO(value) (value < G_EPSILON && value > -G_EPSILON)
|
||||
|
||||
#define GIM_IS_NEGATIVE(value) (value <= -G_EPSILON)
|
||||
|
||||
#define GIM_IS_POSISITVE(value) (value >= G_EPSILON)
|
||||
|
||||
#define GIM_NEAR_EQUAL(v1,v2) GIM_IS_ZERO((v1-v2))
|
||||
|
||||
///returns a clamped number
|
||||
#define GIM_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
|
||||
|
||||
#define GIM_GREATER(x, y) fabsf(x) > (y)
|
||||
|
||||
///Swap numbers
|
||||
#define GIM_SWAP_NUMBERS(a,b){ \
|
||||
a = a+b; \
|
||||
b = a-b; \
|
||||
a = a-b; \
|
||||
}\
|
||||
|
||||
#define GIM_INV_SQRT(va,isva)\
|
||||
{\
|
||||
if(va<=0.0000001f)\
|
||||
{\
|
||||
isva = G_REAL_INFINITY;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
GREAL _x = va * 0.5f;\
|
||||
GUINT _y = 0x5f3759df - ( GIM_IR(va) >> 1);\
|
||||
isva = GIM_FR(_y);\
|
||||
isva = isva * ( 1.5f - ( _x * isva * isva ) );\
|
||||
}\
|
||||
}\
|
||||
|
||||
#define GIM_SQRT(va,sva)\
|
||||
{\
|
||||
GIM_INV_SQRT(va,sva);\
|
||||
sva = 1.0f/sva;\
|
||||
}\
|
||||
|
||||
//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html
|
||||
inline GREAL gim_inv_sqrt(GREAL f)
|
||||
{
|
||||
GREAL r;
|
||||
GIM_INV_SQRT(f,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
inline GREAL gim_sqrt(GREAL f)
|
||||
{
|
||||
GREAL r;
|
||||
GIM_SQRT(f,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // GIM_MATH_H_INCLUDED
|
||||
208
Extras/GIMPACT/include/GIMPACT/core/gim_memory.h
Executable file
208
Extras/GIMPACT/include/GIMPACT/core/gim_memory.h
Executable file
@@ -0,0 +1,208 @@
|
||||
#ifndef GIM_MEMORY_H_INCLUDED
|
||||
#define GIM_MEMORY_H_INCLUDED
|
||||
/*! \file gim_memory.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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "GIMPACT/core/gim_math.h"
|
||||
#include <memory.h>
|
||||
|
||||
//#define PREFETCH 1
|
||||
//! \defgroup PREFETCH
|
||||
//! @{
|
||||
#ifdef PREFETCH
|
||||
#include <xmmintrin.h> // for prefetch
|
||||
#define pfval 64
|
||||
#define pfval2 128
|
||||
//! Prefetch 64
|
||||
#define pf(_x,_i) _mm_prefetch((void *)(_x + _i + pfval), 0)
|
||||
//! Prefetch 128
|
||||
#define pf2(_x,_i) _mm_prefetch((void *)(_x + _i + pfval2), 0)
|
||||
#else
|
||||
//! Prefetch 64
|
||||
#define pf(_x,_i)
|
||||
//! Prefetch 128
|
||||
#define pf2(_x,_i)
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
/*! \defgroup ARRAY_UTILITIES
|
||||
\brief
|
||||
Functions for manip packed arrays of numbers
|
||||
*/
|
||||
//! @{
|
||||
#define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\
|
||||
{\
|
||||
for (GUINT _i_=0;_i_<element_count ;++_i_)\
|
||||
{\
|
||||
dest_array[_i_] = source_array[_i_];\
|
||||
}\
|
||||
}\
|
||||
|
||||
#define GIM_COPY_ARRAYS_1(dest_array,source_array,element_count,copy_macro)\
|
||||
{\
|
||||
for (GUINT _i_=0;_i_<element_count ;++_i_)\
|
||||
{\
|
||||
copy_macro(dest_array[_i_],source_array[_i_]);\
|
||||
}\
|
||||
}\
|
||||
|
||||
|
||||
#define GIM_ZERO_ARRAY(array,element_count)\
|
||||
{\
|
||||
for (GUINT _i_=0;_i_<element_count ;++_i_)\
|
||||
{\
|
||||
array[_i_] = 0;\
|
||||
}\
|
||||
}\
|
||||
|
||||
#define GIM_CONSTANT_ARRAY(array,element_count,constant)\
|
||||
{\
|
||||
for (GUINT _i_=0;_i_<element_count ;++_i_)\
|
||||
{\
|
||||
array[_i_] = constant;\
|
||||
}\
|
||||
}\
|
||||
//! @}
|
||||
|
||||
/*! \defgroup MEMORY_FUNCTION_PROTOTYPES
|
||||
Function prototypes to allocate and free memory.
|
||||
*/
|
||||
//! @{
|
||||
typedef void * gim_alloc_function (size_t size);
|
||||
typedef void * gim_alloca_function (size_t size);//Allocs on the heap
|
||||
typedef void * gim_realloc_function (void *ptr, size_t oldsize, size_t newsize);
|
||||
typedef void gim_free_function (void *ptr);
|
||||
//! @}
|
||||
|
||||
/*! \defgroup MEMORY_FUNCTION_HANDLERS
|
||||
\brief
|
||||
Memory Function Handlers
|
||||
set new memory management functions. if fn is 0, the default handlers are
|
||||
used. */
|
||||
//! @{
|
||||
void gim_set_alloc_handler (gim_alloc_function *fn);
|
||||
void gim_set_alloca_handler (gim_alloca_function *fn);
|
||||
void gim_set_realloc_handler (gim_realloc_function *fn);
|
||||
void gim_set_free_handler (gim_free_function *fn);
|
||||
//! @}
|
||||
|
||||
/*! \defgroup MEMORY_FUNCTION_GET_HANDLERS
|
||||
\brief
|
||||
get current memory management functions.
|
||||
*/
|
||||
//! @{
|
||||
gim_alloc_function *gim_get_alloc_handler (void);
|
||||
gim_alloca_function *gim_get_alloca_handler(void);
|
||||
gim_realloc_function *gim_get_realloc_handler (void);
|
||||
gim_free_function *gim_get_free_handler (void);
|
||||
//! @}
|
||||
|
||||
/*! \defgroup MEMORY_FUNCTIONS
|
||||
Standar Memory functions
|
||||
*/
|
||||
//! @{
|
||||
void * gim_alloc(size_t size);
|
||||
void * gim_alloca(size_t size);
|
||||
void * gim_realloc(void *ptr, size_t oldsize, size_t newsize);
|
||||
void gim_free(void *ptr);
|
||||
//! @}
|
||||
|
||||
|
||||
#if defined (WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||
#define GIM_SIMD_MEMORY 1
|
||||
#endif
|
||||
|
||||
//! SIMD POINTER INTEGER
|
||||
#define SIMD_T GUINT64
|
||||
//! SIMD INTEGER SIZE
|
||||
#define SIMD_T_SIZE sizeof(SIMD_T)
|
||||
|
||||
|
||||
inline void gim_simd_memcpy(void * dst, const void * src, size_t copysize)
|
||||
{
|
||||
#ifdef GIM_SIMD_MEMORY
|
||||
//copy words
|
||||
SIMD_T * ui_src_ptr = (SIMD_T *)src;
|
||||
SIMD_T * ui_dst_ptr = (SIMD_T *)dst;
|
||||
while(copysize>=SIMD_T_SIZE)
|
||||
{
|
||||
*(ui_dst_ptr++) = *(ui_src_ptr++);
|
||||
copysize-=SIMD_T_SIZE;
|
||||
}
|
||||
if(copysize==0) return;
|
||||
|
||||
char * c_src_ptr = (char *)ui_src_ptr;
|
||||
char * c_dst_ptr = (char *)ui_dst_ptr;
|
||||
while(copysize>0)
|
||||
{
|
||||
*(c_dst_ptr++) = *(c_src_ptr++);
|
||||
copysize--;
|
||||
}
|
||||
return;
|
||||
#else
|
||||
memcpy(dst,src,copysize);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void gim_swap_elements(T* _array,size_t _i,size_t _j)
|
||||
{
|
||||
T _e_tmp_ = _array[_i];
|
||||
_array[_i] = _array[_j];
|
||||
_array[_j] = _e_tmp_;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void gim_swap_elements_memcpy(T* _array,size_t _i,size_t _j)
|
||||
{
|
||||
char _e_tmp_[sizeof(T)];
|
||||
gim_simd_memcpy(_e_tmp_,&_array[_i],sizeof(T));
|
||||
gim_simd_memcpy(&_array[_i],&_array[_j],sizeof(T));
|
||||
gim_simd_memcpy(&_array[_j],_e_tmp_,sizeof(T));
|
||||
}
|
||||
|
||||
template <int SIZE>
|
||||
inline void gim_swap_elements_ptr(char * _array,size_t _i,size_t _j)
|
||||
{
|
||||
char _e_tmp_[SIZE];
|
||||
_i*=SIZE;
|
||||
_j*=SIZE;
|
||||
gim_simd_memcpy(_e_tmp_,_array+_i,SIZE);
|
||||
gim_simd_memcpy(_array+_i,_array+_j,SIZE);
|
||||
gim_simd_memcpy(_array+_j,_e_tmp_,SIZE);
|
||||
}
|
||||
|
||||
#endif // GIM_MEMORY_H_INCLUDED
|
||||
410
Extras/GIMPACT/include/GIMPACT/core/gim_radixsort.h
Executable file
410
Extras/GIMPACT/include/GIMPACT/core/gim_radixsort.h
Executable file
@@ -0,0 +1,410 @@
|
||||
#ifndef GIM_RADIXSORT_H_INCLUDED
|
||||
#define GIM_RADIXSORT_H_INCLUDED
|
||||
/*! \file gim_radixsort.h
|
||||
\author Francisco Le<4C>n N<>jera.
|
||||
Based on the work of Michael Herf : "fast floating-point radix sort"
|
||||
Avaliable on http://www.stereopsis.com/radix.html
|
||||
*/
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of GIMPACT Library.
|
||||
|
||||
For the latest info, see http://gimpact.sourceforge.net/
|
||||
|
||||
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "GIMPACT/core/gim_memory.h"
|
||||
|
||||
/*! \defgroup SORTING
|
||||
\brief
|
||||
Macros for sorting.
|
||||
*/
|
||||
|
||||
//! Prototype for comparators
|
||||
class less_comparator
|
||||
{
|
||||
public:
|
||||
|
||||
template<class T,class Z>
|
||||
inline int operator() ( const T& a, const Z& b )
|
||||
{
|
||||
return ( a<b?-1:(a>b?1:0));
|
||||
}
|
||||
};
|
||||
|
||||
//! Prototype for comparators
|
||||
class integer_comparator
|
||||
{
|
||||
public:
|
||||
|
||||
template<class T>
|
||||
inline int operator() ( const T& a, const T& b )
|
||||
{
|
||||
return (int)(a-b);
|
||||
}
|
||||
};
|
||||
|
||||
//!Prototype for getting the integer representation of an object
|
||||
class uint_key_func
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
inline GUINT operator()( const T& a)
|
||||
{
|
||||
return (GUINT)a;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//!Prototype for copying elements
|
||||
class copy_elements_func
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
inline void operator()(T& a,T& b)
|
||||
{
|
||||
a = b;
|
||||
}
|
||||
};
|
||||
|
||||
//!Prototype for copying elements
|
||||
class memcopy_elements_func
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
inline void operator()(T& a,T& b)
|
||||
{
|
||||
gim_simd_memcpy(&a,&b,sizeof(T));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! @{
|
||||
struct GIM_RSORT_TOKEN
|
||||
{
|
||||
GUINT m_key;
|
||||
GUINT m_value;
|
||||
GIM_RSORT_TOKEN()
|
||||
{
|
||||
}
|
||||
GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
|
||||
{
|
||||
m_key = rtoken.m_key;
|
||||
m_value = rtoken.m_value;
|
||||
}
|
||||
|
||||
inline bool operator <(const GIM_RSORT_TOKEN& other) const
|
||||
{
|
||||
return (m_key < other.m_key);
|
||||
}
|
||||
|
||||
inline bool operator >(const GIM_RSORT_TOKEN& other) const
|
||||
{
|
||||
return (m_key > other.m_key);
|
||||
}
|
||||
};
|
||||
|
||||
//! Prototype for comparators
|
||||
class GIM_RSORT_TOKEN_COMPARATOR
|
||||
{
|
||||
public:
|
||||
|
||||
inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b )
|
||||
{
|
||||
return (int)((a.m_key) - (b.m_key));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define kHist 2048
|
||||
// ---- utils for accessing 11-bit quantities
|
||||
#define D11_0(x) (x & 0x7FF)
|
||||
#define D11_1(x) (x >> 11 & 0x7FF)
|
||||
#define D11_2(x) (x >> 22 )
|
||||
|
||||
|
||||
|
||||
///Radix sort for unsigned integer keys
|
||||
inline void gim_radix_sort_rtokens(
|
||||
GIM_RSORT_TOKEN * array,
|
||||
GIM_RSORT_TOKEN * sorted, GUINT element_count)
|
||||
{
|
||||
GUINT i;
|
||||
GUINT b0[kHist * 3];
|
||||
GUINT *b1 = b0 + kHist;
|
||||
GUINT *b2 = b1 + kHist;
|
||||
for (i = 0; i < kHist * 3; ++i)
|
||||
{
|
||||
b0[i] = 0;
|
||||
}
|
||||
GUINT fi;
|
||||
GUINT pos;
|
||||
for (i = 0; i < element_count; ++i)
|
||||
{
|
||||
fi = array[i].m_key;
|
||||
b0[D11_0(fi)] ++;
|
||||
b1[D11_1(fi)] ++;
|
||||
b2[D11_2(fi)] ++;
|
||||
}
|
||||
{
|
||||
GUINT sum0 = 0, sum1 = 0, sum2 = 0;
|
||||
GUINT tsum;
|
||||
for (i = 0; i < kHist; ++i)
|
||||
{
|
||||
tsum = b0[i] + sum0;
|
||||
b0[i] = sum0 - 1;
|
||||
sum0 = tsum;
|
||||
tsum = b1[i] + sum1;
|
||||
b1[i] = sum1 - 1;
|
||||
sum1 = tsum;
|
||||
tsum = b2[i] + sum2;
|
||||
b2[i] = sum2 - 1;
|
||||
sum2 = tsum;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < element_count; ++i)
|
||||
{
|
||||
fi = array[i].m_key;
|
||||
pos = D11_0(fi);
|
||||
pos = ++b0[pos];
|
||||
sorted[pos].m_key = array[i].m_key;
|
||||
sorted[pos].m_value = array[i].m_value;
|
||||
}
|
||||
for (i = 0; i < element_count; ++i)
|
||||
{
|
||||
fi = sorted[i].m_key;
|
||||
pos = D11_1(fi);
|
||||
pos = ++b1[pos];
|
||||
array[pos].m_key = sorted[i].m_key;
|
||||
array[pos].m_value = sorted[i].m_value;
|
||||
}
|
||||
for (i = 0; i < element_count; ++i)
|
||||
{
|
||||
fi = array[i].m_key;
|
||||
pos = D11_2(fi);
|
||||
pos = ++b2[pos];
|
||||
sorted[pos].m_key = array[i].m_key;
|
||||
sorted[pos].m_value = array[i].m_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN
|
||||
/*!
|
||||
*\param array Array of elements to sort
|
||||
*\param sorted_tokens Tokens of sorted elements
|
||||
*\param element_count element count
|
||||
*\param uintkey_macro Functor which retrieves the integer representation of an array element
|
||||
*/
|
||||
template<typename T, class GETKEY_CLASS>
|
||||
void gim_radix_sort_array_tokens(
|
||||
T* array ,
|
||||
GIM_RSORT_TOKEN * sorted_tokens,
|
||||
GUINT element_count,GETKEY_CLASS uintkey_macro)
|
||||
{
|
||||
GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
|
||||
for (GUINT _i=0;_i<element_count;++_i)
|
||||
{
|
||||
_unsorted[_i].m_key = uintkey_macro(array[_i]);
|
||||
_unsorted[_i].m_value = _i;
|
||||
}
|
||||
gim_radix_sort_rtokens(_unsorted,sorted_tokens,element_count);
|
||||
gim_free(_unsorted);
|
||||
gim_free(_unsorted);
|
||||
}
|
||||
|
||||
/// Sorts array in place. For generic use
|
||||
/*!
|
||||
\param type Type of the array
|
||||
\param array
|
||||
\param element_count
|
||||
\param get_uintkey_macro Macro for extract the Integer value of the element. Similar to SIMPLE_GET_UINTKEY
|
||||
\param copy_elements_macro Macro for copy elements, similar to SIMPLE_COPY_ELEMENTS
|
||||
*/
|
||||
template<typename T, class GETKEY_CLASS, class COPY_CLASS>
|
||||
void gim_radix_sort(
|
||||
T * array, GUINT element_count,
|
||||
GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
|
||||
{
|
||||
GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
|
||||
gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro);
|
||||
T * _original_array = (T *) gim_alloc(sizeof(T)*element_count);
|
||||
gim_simd_memcpy(_original_array,array,sizeof(T)*element_count);
|
||||
for (GUINT _i=0;_i<element_count;++_i)
|
||||
{
|
||||
copy_elements_macro(array[_i],_original_array[_sorted[_i].m_value]);
|
||||
}
|
||||
gim_free(_original_array);
|
||||
gim_free(_sorted);
|
||||
}
|
||||
|
||||
//! Failsafe Iterative binary search,
|
||||
/*!
|
||||
If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
|
||||
\param _array
|
||||
\param _start_i the beginning of the array
|
||||
\param _end_i the ending index of the array
|
||||
\param _search_key Value to find
|
||||
\param _comp_macro macro for comparing elements
|
||||
\param _found If true the value has found. Boolean
|
||||
\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
|
||||
*/
|
||||
template<class T, typename KEYCLASS, typename COMP_CLASS>
|
||||
bool gim_binary_search_ex(
|
||||
const T* _array, GUINT _start_i,
|
||||
GUINT _end_i,GUINT & _result_index,
|
||||
const KEYCLASS & _search_key,
|
||||
COMP_CLASS _comp_macro)
|
||||
{
|
||||
GUINT _k;
|
||||
int _comp_result;
|
||||
GUINT _i = _start_i;
|
||||
GUINT _j = _end_i+1;
|
||||
while (_i < _j)
|
||||
{
|
||||
_k = (_j+_i-1)/2;
|
||||
_comp_result = _comp_macro(_array[_k], _search_key);
|
||||
if (_comp_result == 0)
|
||||
{
|
||||
_result_index = _k;
|
||||
return true;
|
||||
}
|
||||
else if (_comp_result < 0)
|
||||
{
|
||||
_i = _k+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_j = _k;
|
||||
}
|
||||
}
|
||||
_result_index = _i;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Failsafe Iterative binary search,Template version
|
||||
/*!
|
||||
If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
|
||||
\param _array
|
||||
\param _start_i the beginning of the array
|
||||
\param _end_i the ending index of the array
|
||||
\param _search_key Value to find
|
||||
\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
|
||||
\return true if found, else false
|
||||
*/
|
||||
template<class T>
|
||||
bool gim_binary_search(
|
||||
const T*_array,GUINT _start_i,
|
||||
GUINT _end_i,const T & _search_key,
|
||||
GUINT & _result_index)
|
||||
{
|
||||
GUINT _i = _start_i;
|
||||
GUINT _j = _end_i+1;
|
||||
GUINT _k;
|
||||
while(_i < _j)
|
||||
{
|
||||
_k = (_j+_i-1)/2;
|
||||
if(_array[_k]==_search_key)
|
||||
{
|
||||
_result_index = _k;
|
||||
return true;
|
||||
}
|
||||
else if (_array[_k]<_search_key)
|
||||
{
|
||||
_i = _k+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_j = _k;
|
||||
}
|
||||
}
|
||||
_result_index = _i;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
|
||||
template <typename T, typename COMP_CLASS>
|
||||
void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc)
|
||||
{
|
||||
/* PRE: a[k+1..N] is a heap */
|
||||
/* POST: a[k..N] is a heap */
|
||||
|
||||
T temp = pArr[k - 1];
|
||||
/* k has child(s) */
|
||||
while (k <= n/2)
|
||||
{
|
||||
int child = 2*k;
|
||||
|
||||
if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0)
|
||||
{
|
||||
child++;
|
||||
}
|
||||
/* pick larger child */
|
||||
if (CompareFunc(temp , pArr[child - 1])<0)
|
||||
{
|
||||
/* move child up */
|
||||
pArr[k - 1] = pArr[child - 1];
|
||||
k = child;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
pArr[k - 1] = temp;
|
||||
} /*downHeap*/
|
||||
|
||||
|
||||
template <typename T, typename COMP_CLASS>
|
||||
void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc)
|
||||
{
|
||||
/* sort a[0..N-1], N.B. 0 to N-1 */
|
||||
GUINT k;
|
||||
GUINT n = element_count;
|
||||
for (k = n/2; k > 0; k--)
|
||||
{
|
||||
gim_down_heap(pArr, k, n, CompareFunc);
|
||||
}
|
||||
|
||||
/* a[1..N] is now a heap */
|
||||
while ( n>=2 )
|
||||
{
|
||||
gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */
|
||||
--n;
|
||||
/* restore a[1..i-1] heap */
|
||||
gim_down_heap(pArr, 1, n, CompareFunc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! @}
|
||||
#endif // GIM_RADIXSORT_H_INCLUDED
|
||||
381
Extras/GIMPACT/include/GIMPACT/core/gim_tri_collision.h
Executable file
381
Extras/GIMPACT/include/GIMPACT/core/gim_tri_collision.h
Executable file
@@ -0,0 +1,381 @@
|
||||
#ifndef GIM_TRI_COLLISION_H_INCLUDED
|
||||
#define GIM_TRI_COLLISION_H_INCLUDED
|
||||
|
||||
/*! \file gim_tri_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) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "GIMPACT/core/gim_box_collision.h"
|
||||
#include "GIMPACT/core/gim_clip_polygon.h"
|
||||
|
||||
/*! \addtogroup GEOMETRIC_OPERATIONS
|
||||
*/
|
||||
//! @{
|
||||
|
||||
|
||||
|
||||
#define MAX_TRI_CLIPPING 16
|
||||
|
||||
//! Structure for collision
|
||||
struct GIM_TRIANGLE_CONTACT_DATA
|
||||
{
|
||||
GREAL m_penetration_depth;
|
||||
GUINT m_point_count;
|
||||
btVector4 m_separating_normal;
|
||||
btVector3 m_points[MAX_TRI_CLIPPING];
|
||||
|
||||
SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT_DATA& other)
|
||||
{
|
||||
m_penetration_depth = other.m_penetration_depth;
|
||||
m_separating_normal = other.m_separating_normal;
|
||||
m_point_count = other.m_point_count;
|
||||
GUINT i = m_point_count;
|
||||
while(i--)
|
||||
{
|
||||
m_points[i] = other.m_points[i];
|
||||
}
|
||||
}
|
||||
|
||||
GIM_TRIANGLE_CONTACT_DATA()
|
||||
{
|
||||
}
|
||||
|
||||
GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA& other)
|
||||
{
|
||||
copy_from(other);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! classify points that are closer
|
||||
template<typename DISTANCE_FUNC,typename CLASS_PLANE>
|
||||
SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE & plane,
|
||||
GREAL margin, const btVector3 * points, GUINT point_count, DISTANCE_FUNC distance_func)
|
||||
{
|
||||
m_point_count = 0;
|
||||
m_penetration_depth= -1000.0f;
|
||||
|
||||
GUINT point_indices[MAX_TRI_CLIPPING];
|
||||
|
||||
for(GUINT _k=0;_k<point_count;_k++)
|
||||
{
|
||||
GREAL _dist = -distance_func(plane,points[_k]) + margin;
|
||||
|
||||
if(_dist>=0.0f)
|
||||
{
|
||||
if(_dist>m_penetration_depth)
|
||||
{
|
||||
m_penetration_depth = _dist;
|
||||
point_indices[0] = _k;
|
||||
m_point_count=1;
|
||||
}
|
||||
else if((_dist+G_EPSILON)>=m_penetration_depth)
|
||||
{
|
||||
point_indices[m_point_count] = _k;
|
||||
m_point_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(GUINT _k=0;_k<m_point_count;_k++)
|
||||
{
|
||||
m_points[_k] = points[point_indices[_k]];
|
||||
}
|
||||
}
|
||||
|
||||
//! classify points that are closer
|
||||
SIMD_FORCE_INLINE void merge_points(const btVector4 & plane, GREAL margin,
|
||||
const btVector3 * points, GUINT point_count)
|
||||
{
|
||||
m_separating_normal = plane;
|
||||
mergepoints_generic(plane, margin, points, point_count, DISTANCE_PLANE_3D_FUNC());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Class for colliding triangles
|
||||
class GIM_TRIANGLE
|
||||
{
|
||||
public:
|
||||
btScalar m_margin;
|
||||
btVector3 m_vertices[3];
|
||||
|
||||
GIM_TRIANGLE():m_margin(0.1f)
|
||||
{
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE GIM_AABB get_box() const
|
||||
{
|
||||
return GIM_AABB(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void get_normal(btVector3 &normal) const
|
||||
{
|
||||
TRIANGLE_NORMAL(m_vertices[0],m_vertices[1],m_vertices[2],normal);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void get_plane(btVector4 &plane) const
|
||||
{
|
||||
TRIANGLE_PLANE(m_vertices[0],m_vertices[1],m_vertices[2],plane);;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void apply_transform(const btTransform & trans)
|
||||
{
|
||||
m_vertices[0] = trans(m_vertices[0]);
|
||||
m_vertices[1] = trans(m_vertices[1]);
|
||||
m_vertices[2] = trans(m_vertices[2]);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index,const btVector3 &triangle_normal,btVector4 &plane) const
|
||||
{
|
||||
const btVector3 & e0 = m_vertices[edge_index];
|
||||
const btVector3 & e1 = m_vertices[(edge_index+1)%3];
|
||||
EDGE_PLANE(e0,e1,triangle_normal,plane);
|
||||
}
|
||||
|
||||
//! Gets the relative transformation of this triangle
|
||||
/*!
|
||||
The transformation is oriented to the triangle normal , and aligned to the 1st edge of this triangle. The position corresponds to vertice 0:
|
||||
- triangle normal corresponds to Z axis.
|
||||
- 1st normalized edge corresponds to X axis,
|
||||
|
||||
*/
|
||||
SIMD_FORCE_INLINE void get_triangle_transform(btTransform & triangle_transform) const
|
||||
{
|
||||
btMatrix3x3 & matrix = triangle_transform.getBasis();
|
||||
|
||||
btVector3 zaxis;
|
||||
get_normal(zaxis);
|
||||
MAT_SET_Z(matrix,zaxis);
|
||||
|
||||
btVector3 xaxis = m_vertices[1] - m_vertices[0];
|
||||
VEC_NORMALIZE(xaxis);
|
||||
MAT_SET_X(matrix,xaxis);
|
||||
|
||||
//y axis
|
||||
xaxis = zaxis.cross(xaxis);
|
||||
MAT_SET_Y(matrix,xaxis);
|
||||
|
||||
triangle_transform.setOrigin(m_vertices[0]);
|
||||
}
|
||||
|
||||
|
||||
//! Test triangles by finding separating axis
|
||||
/*!
|
||||
\param other Triangle for collide
|
||||
\param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
|
||||
*/
|
||||
bool collide_triangle_hard_test(
|
||||
const GIM_TRIANGLE & other,
|
||||
GIM_TRIANGLE_CONTACT_DATA & contact_data) const;
|
||||
|
||||
//! Test boxes before doing hard test
|
||||
/*!
|
||||
\param other Triangle for collide
|
||||
\param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
|
||||
\
|
||||
*/
|
||||
SIMD_FORCE_INLINE bool collide_triangle(
|
||||
const GIM_TRIANGLE & other,
|
||||
GIM_TRIANGLE_CONTACT_DATA & contact_data) const
|
||||
{
|
||||
//test box collisioin
|
||||
GIM_AABB boxu(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
|
||||
GIM_AABB boxv(other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin);
|
||||
if(!boxu.has_collision(boxv)) return false;
|
||||
|
||||
//do hard test
|
||||
return collide_triangle_hard_test(other,contact_data);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
Solve the System for u,v parameters:
|
||||
|
||||
u*axe1[i1] + v*axe2[i1] = vecproj[i1]
|
||||
u*axe1[i2] + v*axe2[i2] = vecproj[i2]
|
||||
|
||||
sustitute:
|
||||
v = (vecproj[i2] - u*axe1[i2])/axe2[i2]
|
||||
|
||||
then the first equation in terms of 'u':
|
||||
|
||||
--> u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1]
|
||||
|
||||
--> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1]
|
||||
|
||||
--> u*(axe1[i1] - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2]
|
||||
|
||||
--> u*((axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2]
|
||||
|
||||
--> u*(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]
|
||||
|
||||
--> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])
|
||||
|
||||
if 0.0<= u+v <=1.0 then they are inside of triangle
|
||||
|
||||
\return false if the point is outside of triangle.This function doesn't take the margin
|
||||
*/
|
||||
SIMD_FORCE_INLINE bool get_uv_parameters(
|
||||
const btVector3 & point,
|
||||
const btVector3 & tri_plane,
|
||||
GREAL & u, GREAL & v) const
|
||||
{
|
||||
btVector3 _axe1 = m_vertices[1]-m_vertices[0];
|
||||
btVector3 _axe2 = m_vertices[2]-m_vertices[0];
|
||||
btVector3 _vecproj = point - m_vertices[0];
|
||||
GUINT _i1 = (tri_plane.closestAxis()+1)%3;
|
||||
GUINT _i2 = (_i1+1)%3;
|
||||
if(btFabs(_axe2[_i2])<G_EPSILON)
|
||||
{
|
||||
u = (_vecproj[_i2]*_axe2[_i1] - _vecproj[_i1]*_axe2[_i2]) /(_axe1[_i2]*_axe2[_i1] - _axe1[_i1]*_axe2[_i2]);
|
||||
v = (_vecproj[_i1] - u*_axe1[_i1])/_axe2[_i1];
|
||||
}
|
||||
else
|
||||
{
|
||||
u = (_vecproj[_i1]*_axe2[_i2] - _vecproj[_i2]*_axe2[_i1]) /(_axe1[_i1]*_axe2[_i2] - _axe1[_i2]*_axe2[_i1]);
|
||||
v = (_vecproj[_i2] - u*_axe1[_i2])/_axe2[_i2];
|
||||
}
|
||||
|
||||
if(u<-G_EPSILON)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(v<-G_EPSILON)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
float sumuv;
|
||||
sumuv = u+v;
|
||||
if(sumuv<-G_EPSILON)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(sumuv-1.0f>G_EPSILON)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! is point in triangle beam?
|
||||
/*!
|
||||
Test if point is in triangle, with m_margin tolerance
|
||||
*/
|
||||
SIMD_FORCE_INLINE bool is_point_inside(const btVector3 & point, const btVector3 & tri_normal) const
|
||||
{
|
||||
//Test with edge 0
|
||||
btVector4 edge_plane;
|
||||
this->get_edge_plane(0,tri_normal,edge_plane);
|
||||
GREAL dist = DISTANCE_PLANE_POINT(edge_plane,point);
|
||||
if(dist-m_margin>0.0f) return false; // outside plane
|
||||
|
||||
this->get_edge_plane(1,tri_normal,edge_plane);
|
||||
dist = DISTANCE_PLANE_POINT(edge_plane,point);
|
||||
if(dist-m_margin>0.0f) return false; // outside plane
|
||||
|
||||
this->get_edge_plane(2,tri_normal,edge_plane);
|
||||
dist = DISTANCE_PLANE_POINT(edge_plane,point);
|
||||
if(dist-m_margin>0.0f) return false; // outside plane
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! Bidireccional ray collision
|
||||
SIMD_FORCE_INLINE bool ray_collision(
|
||||
const btVector3 & vPoint,
|
||||
const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
|
||||
GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
|
||||
{
|
||||
btVector4 faceplane;
|
||||
{
|
||||
btVector3 dif1 = m_vertices[1] - m_vertices[0];
|
||||
btVector3 dif2 = m_vertices[2] - m_vertices[0];
|
||||
VEC_CROSS(faceplane,dif1,dif2);
|
||||
faceplane[3] = m_vertices[0].dot(faceplane);
|
||||
}
|
||||
|
||||
GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam,0.0f, tmax);
|
||||
if(res == 0) return false;
|
||||
if(! is_point_inside(pout,faceplane)) return false;
|
||||
|
||||
if(res==2) //invert normal
|
||||
{
|
||||
triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
|
||||
}
|
||||
|
||||
VEC_NORMALIZE(triangle_normal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! one direccion ray collision
|
||||
SIMD_FORCE_INLINE bool ray_collision_front_side(
|
||||
const btVector3 & vPoint,
|
||||
const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
|
||||
GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
|
||||
{
|
||||
btVector4 faceplane;
|
||||
{
|
||||
btVector3 dif1 = m_vertices[1] - m_vertices[0];
|
||||
btVector3 dif2 = m_vertices[2] - m_vertices[0];
|
||||
VEC_CROSS(faceplane,dif1,dif2);
|
||||
faceplane[3] = m_vertices[0].dot(faceplane);
|
||||
}
|
||||
|
||||
GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam,0.0f, tmax);
|
||||
if(res != 1) return false;
|
||||
|
||||
if(!is_point_inside(pout,faceplane)) return false;
|
||||
|
||||
triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
|
||||
|
||||
VEC_NORMALIZE(triangle_normal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // GIM_TRI_COLLISION_H_INCLUDED
|
||||
146
Extras/GIMPACT/include/GIMPACT/gim_manual.h
Executable file
146
Extras/GIMPACT/include/GIMPACT/gim_manual.h
Executable file
@@ -0,0 +1,146 @@
|
||||
#ifndef GIM_MANUAL_H_INCLUDED
|
||||
#define GIM_MANUAL_H_INCLUDED
|
||||
|
||||
/*! \file gim_manual.h
|
||||
*\author Francisco Le<4C>n N<>jera
|
||||
GIMPACT documentation
|
||||
|
||||
*/
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of GIMPACT Library.
|
||||
|
||||
For the latest info, see http://gimpact.sourceforge.net/
|
||||
|
||||
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of EITHER:
|
||||
(1) The GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version. The text of the GNU Lesser
|
||||
General Public License is included with this library in the
|
||||
file GIMPACT-LICENSE-LGPL.TXT.
|
||||
(2) The BSD-style license that is included with this library in
|
||||
the file GIMPACT-LICENSE-BSD.TXT.
|
||||
(3) The zlib/libpng license that is included with this library in
|
||||
the file GIMPACT-LICENSE-ZLIB.TXT.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
|
||||
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*! \mainpage GIMPACT
|
||||
*\section INTRO INTRODUCTION
|
||||
<p>
|
||||
<b>GIMPACT</b> is a software library with tools for geometry processing and collision detection, focused on solving most common problems on Virtual Reality development.
|
||||
</p>
|
||||
<p>
|
||||
Since Version 0.2, <b>GIMPACT</b> will work integrated with the <b>Bullet Engine</b> for general collision detection and physics. For more details, please visit http://www.continuousphysics.com/Bullet/
|
||||
</p>
|
||||
<p>For updates, please visit http://sourceforge.net/projects/gimpact/ </p>
|
||||
|
||||
*\section CONTENT
|
||||
- \subpage FEATURES
|
||||
- \subpage REQUIREMENTS
|
||||
- \subpage PROGRAMMERS_GUIDE "PROGRAMMERS GUIDE"
|
||||
- \subpage TODO
|
||||
*/
|
||||
/*! \page FEATURES
|
||||
- C++ oriented.
|
||||
- Extensible design.
|
||||
- Collision detection algorithm for concave shapes in the <b>Bullet Physics Engine</b>. See btGImpactCollisionAlgorithm.
|
||||
- Efficient Dynamic <b>Hierarcht Bounding Box tree structures</b> for handle collisions with composed shapes whose have large sets of primitives (triangles or convex shapes) See the GIM_BOX_TREE_SET class.
|
||||
- Collision detection for trimeshes with the btGImpactMeshShape class. Now <b>GIMPACT</b> works fine with the btStridingInterface class for getting the data from trimesh models.
|
||||
- Support for deformable trimeshes.
|
||||
- Collision detection for compound shapes through the btGImpactCompoundShape class. This class takes advantage from the Hierarcht Bounding Box structure (GIM_BOX_TREE_SET class).
|
||||
- Collision Shapes (Both btGImpactCompoundSape and btGImpactTrimeshShape ) can be shared by two or more Rigid Bodies in <b>Bullet</b>.
|
||||
|
||||
*/
|
||||
/*! \page REQUIREMENTS
|
||||
- GIMPACT has dependencies to the <a href = "http://www.continuousphysics.com/Bullet/"> Bullet Physics Engine</a>.
|
||||
- Ansi C++ compiler,
|
||||
*/
|
||||
/*! \page PROGRAMMERS_GUIDE PROGRAMMERS GUIDE
|
||||
This guide will show how to incorpore the GIMPACt functionality on the Bullet Engine:
|
||||
*\section REG Registering the Algorithm
|
||||
For register this algorithm in Bullet, proceed as following:
|
||||
\code
|
||||
btCollisionDispatcher * dispatcher = static_cast<btCollisionDispatcher *>(m_dynamicsWorld ->getDispatcher());
|
||||
btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
|
||||
\endcode
|
||||
</p>
|
||||
With the instructon above, btGImpactCollisionAlgorithm will handle:
|
||||
- Convex shapes vs GImpact shapes.
|
||||
- Concave shapes vs GImpact shapes.
|
||||
- Compoind shapes vs GImpact shapes.
|
||||
|
||||
*\section CREATING_SHAPES Creating Shapes.
|
||||
*\subsection TRIMESH Creating trimeshes.
|
||||
<p>For creating trimeshes you must provide an interface for your model data. You could use btTriangleIndexVertexArray class for providing the indices and the vertices from your triangle models.</p>
|
||||
<p>
|
||||
For example, you could create a trimesh from memory as following:
|
||||
\code
|
||||
btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(NUM_TRIANGLES,
|
||||
&gIndices[0][0],
|
||||
3*sizeof(int),
|
||||
NUM_VERTICES,(REAL*) &gVertices[0],sizeof(REAL)*3);
|
||||
\endcode
|
||||
</p>
|
||||
<p>
|
||||
Where gIndices is an array of integers and gVertices is an array of float with 3 components.
|
||||
</p>
|
||||
Then you must create the Trimesh shape as following:
|
||||
\code
|
||||
btGImpactMeshShape * trimesh = new btGImpactMeshShape(indexVertexArrays);
|
||||
\endcode
|
||||
The next step is configuring the trimesh, for example changing the scale:
|
||||
\code
|
||||
trimesh->setLocalScaling(btVector3(4.f,4.f,4.f));
|
||||
\endcode
|
||||
At end, you must call btGImpactMeshShape.updateBound for ensure that the shape will build its internal Box set structure:
|
||||
\code
|
||||
trimesh->updateBound();// Call this method once before doing collisions
|
||||
\endcode
|
||||
Also you must call btGImpactMeshShape.postUpdate() each time when changing the trimesh data ( For deformable meshes), this will enable a flag to the trimesh shape which tells that the trimesh data has been changed and btGImpactMeshShape.updateBound will be called in collision routines.
|
||||
<
|
||||
|
||||
*\subsection COMPOUND Compound Shapes.
|
||||
For compound shapes, you must create btGImpactCompoundShape objects. Then you could add
|
||||
sub shapes as following;
|
||||
\code
|
||||
btGImpactCompoundShape * mycompound = new btGImpactCompoundShape();
|
||||
|
||||
btTransform localtransform;
|
||||
.... Setting transformation
|
||||
|
||||
//add shapes with transformation
|
||||
btCollisionShape * subshape = creatingShape(0);
|
||||
mycompound->addChildShape(localtransform,subshape);
|
||||
.... Setting transformation
|
||||
btCollisionShape * subshape2 = creatingShape(1);
|
||||
mycompound->addChildShape(localtransform,subshape);
|
||||
.... add more shapes
|
||||
\endcode
|
||||
At end, you must call btGImpactCompoundShape.updateBound for ensure that the shape will build its internal Box set structure:
|
||||
*/
|
||||
|
||||
/*! \page TODO
|
||||
*\section FEATURE FEATURE REQUESTS
|
||||
- Tetrahedrization for solid trimeshes.
|
||||
- Examples for implement deformable collisions, like cloth simulations and finite elements dynamics.
|
||||
- Generic Ray collision functionality.
|
||||
- Implement Low level SAT algorithms for speed up convex collisions.
|
||||
*\section MISCELANEOUS
|
||||
- Improve the documentation.
|
||||
- Benchmarking.
|
||||
- Bug reports and Bug Fixes.
|
||||
*/
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user