1
1
This commit is contained in:
2008-09-26 18:53:26 +00:00
parent b542721f32
commit db90946d82
336 changed files with 38558 additions and 18440 deletions

View File

@@ -422,6 +422,26 @@ if env['OURPLATFORM']!='darwin':
source=[dp+os.sep+f for f in df]
scriptinstall.append(env.Install(dir=dir,source=source))
#-- icons
if env['OURPLATFORM']=='linux2':
iconlist = []
icontargetlist = []
for tp, tn, tf in os.walk('release/freedesktop/icons'):
if 'CVS' in tn:
tn.remove('CVS')
if '.svn' in tn:
tn.remove('.svn')
for f in tf:
print ">>>", env['BF_INSTALLDIR'], tp, f
iconlist.append(tp+os.sep+f)
icontargetlist.append(env['BF_INSTALLDIR']+tp[19:]+os.sep+f)
iconinstall = []
for targetdir,srcfile in zip(icontargetlist, iconlist):
td, tf = os.path.split(targetdir)
iconinstall.append(env.Install(dir=td, source=srcfile))
#-- plugins
pluglist = []
plugtargetlist = []
@@ -470,6 +490,8 @@ textinstall = env.Install(dir=env['BF_INSTALLDIR'], source=textlist)
if env['OURPLATFORM']=='darwin':
allinstall = [blenderinstall, plugininstall, textinstall]
elif env['OURPLATFORM']=='linux2':
allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall, iconinstall]
else:
allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall]

View File

@@ -31,6 +31,7 @@ FILE(GLOB SRC
src/BulletCollision/BroadphaseCollision/*.cpp
src/BulletCollision/CollisionShapes/*.cpp
src/BulletCollision/NarrowPhaseCollision/*.cpp
src/BulletCollision/Gimpact/*.cpp
src/BulletCollision//CollisionDispatch/*.cpp
src/BulletDynamics/ConstraintSolver/*.cpp
src/BulletDynamics/Vehicle/*.cpp

View File

@@ -37,6 +37,7 @@ LinearMath \
BulletCollision/BroadphaseCollision \
BulletCollision/CollisionShapes \
BulletCollision/NarrowPhaseCollision \
BulletCollision/Gimpact \
BulletCollision//CollisionDispatch \
BulletDynamics/ConstraintSolver \
BulletDynamics/Vehicle \

View File

@@ -53,21 +53,21 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\Gimpact MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Vehicle MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\LinearMath MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\LinearMath
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletSoftBody MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletSoftBody
XCOPY /Y ..\..\src\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include
XCOPY /Y ..\..\src\LinearMath\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\LinearMath
XCOPY /Y ..\..\src\BulletSoftBody\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletSoftBody
XCOPY /Y ..\..\src\BulletCollision\BroadphaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\BroadphaseCollision
XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
XCOPY /Y ..\..\src\BulletCollision\Gimpact\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
@@ -135,6 +135,7 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\Gimpact MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
@@ -148,6 +149,7 @@ XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build
XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
XCOPY /Y ..\..\src\BulletCollision\Gimpact\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
@@ -213,6 +215,7 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\Gimpact MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
@@ -226,6 +229,7 @@ XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build
XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
XCOPY /Y ..\..\src\BulletCollision\Gimpact\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
@@ -293,6 +297,7 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\Gimpact MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
@@ -306,6 +311,7 @@ XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build
XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
XCOPY /Y ..\..\src\BulletCollision\Gimpact\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
@@ -962,6 +968,124 @@ ECHO Done
RelativePath="..\..\src\BulletCollision\CollisionShapes\btUniformScalingShape.h">
</File>
</Filter>
<Filter
Name="Gimpact"
Filter="">
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btBoxCollision.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btClipPolygon.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btContactProcessing.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btContactProcessing.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGenericPoolAllocator.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGenericPoolAllocator.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGeometryOperations.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactBvh.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactBvh.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactMassUtil.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactQuantizedBvh.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactQuantizedBvh.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btQuantization.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btTriangleShapeEx.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btTriangleShapeEx.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_array.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_basic_geometry_operations.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_bitset.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_box_collision.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_box_set.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_box_set.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_clip_polygon.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_contact.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_contact.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_geom_types.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_geometry.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_hash_table.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_linear_math.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_math.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_memory.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_memory.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_radixsort.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_tri_collision.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_tri_collision.h">
</File>
</Filter>
</Filter>
<Filter
Name="LinearMath"

View File

@@ -46,6 +46,7 @@ IMPLICIT_CONVEX_SHAPES_START_HERE,
CONCAVE_SHAPES_START_HERE,
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
TRIANGLE_MESH_SHAPE_PROXYTYPE,
SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
///used for demo integration FAST/Swift collision library and Bullet
FAST_CONCAVE_MESH_PROXYTYPE,
//terrain

View File

@@ -164,7 +164,7 @@ btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin,
void* userPtr,
short int collisionFilterGroup,
short int collisionFilterMask,
btDispatcher* dispatcher,
btDispatcher* /*dispatcher*/,
void* /*multiSapProxy*/)
{
btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( userPtr,
@@ -180,6 +180,7 @@ if(!m_deferedcollide)
btDbvtTreeCollider collider(this);
collider.proxy=proxy;
btDbvt::collideTV(m_sets[0].m_root,proxy->aabb,collider);
btDbvt::collideTV(m_sets[1].m_root,proxy->aabb,collider);
}
return(proxy);
}

View File

@@ -86,7 +86,6 @@ int m_gid; // Gen id
bool m_releasepaircache; // Release pair cache on delete
bool m_deferedcollide; // Defere dynamic/static collision to collide call
bool m_needcleanup; // Need to run cleanup?
bool m_initialize; // Initialization
#if DBVT_BP_PROFILE
btClock m_clock;
struct {

View File

@@ -143,7 +143,7 @@ public:
virtual ~btCollisionObject();
void setCollisionShape(btCollisionShape* collisionShape)
virtual void setCollisionShape(btCollisionShape* collisionShape)
{
m_collisionShape = collisionShape;
m_rootCollisionShape = collisionShape;

View File

@@ -105,7 +105,7 @@ void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* col
for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
{
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
if (collisionObject->mergesSimulationIslands())
if (!collisionObject->isStaticOrKinematicObject())
{
collisionObject->setIslandTag( m_unionFind.find(index) );
collisionObject->setCompanionId(-1);

View File

@@ -56,11 +56,16 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();
//m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
#ifdef CLEAR_MANIFOLD
m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
#endif
///iff distance positive, don't generate a new contact
if ( len > (radius0+radius1))
{
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
return;
}
///distance (negative means penetration)
@@ -82,7 +87,9 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0
resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
//no resultOut->refreshContactPoints(); needed, because of clearManifold (all points are new)
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
}

View File

@@ -36,6 +36,13 @@ btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int
}
void btConvexHullShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
recalcLocalAabb();
}
void btConvexHullShape::addPoint(const btPoint3& point)
{
m_points.push_back(point);

View File

@@ -71,7 +71,8 @@ public:
virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const;
virtual bool isInside(const btPoint3& pt,btScalar tolerance) const;
///in case we receive negative scaling
virtual void setLocalScaling(const btVector3& scaling);
};

View File

@@ -26,7 +26,7 @@ m_collisionMargin(CONVEX_DISTANCE_MARGIN)
void btConvexInternalShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
m_localScaling = scaling.absolute();
}

View File

@@ -56,8 +56,18 @@ void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callb
btScaledTriangleCallback scaledCallback(callback,m_localScaling);
btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ());
btVector3 scaledAabbMin = aabbMin * invLocalScaling;
btVector3 scaledAabbMax = aabbMax * invLocalScaling;
btVector3 scaledAabbMin,scaledAabbMax;
///support negative scaling
scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax);
}
@@ -66,8 +76,16 @@ void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& a
{
btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin();
btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax();
localAabbMin *= m_localScaling;
localAabbMax *= m_localScaling;
btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling;
btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling;
localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
btScalar margin = m_bvhTriMeshShape->getMargin();
@@ -99,5 +117,5 @@ const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const
void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
///don't make this a movable object!
btAssert(0);
// btAssert(0);
}

View File

@@ -39,7 +39,7 @@ public:
virtual int getShapeType() const
{
//use un-used 'FAST_CONCAVE_MESH_PROXYTYPE' for now, later add SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE to btBroadphaseProxy.h
return FAST_CONCAVE_MESH_PROXYTYPE;
return SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
}
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
@@ -49,6 +49,16 @@ public:
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
btBvhTriangleMeshShape* getChildShape()
{
return m_bvhTriMeshShape;
}
const btBvhTriangleMeshShape* getChildShape() const
{
return m_bvhTriMeshShape;
}
//debugging
virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";}

View File

@@ -19,7 +19,8 @@ subject to the following restrictions:
btTriangleMesh::btTriangleMesh (bool use32bitIndices,bool use4componentVertices)
:m_use32bitIndices(use32bitIndices),
m_use4componentVertices(use4componentVertices)
m_use4componentVertices(use4componentVertices),
m_weldingThreshold(0.0)
{
btIndexedMesh meshIndex;
meshIndex.m_numTriangles = 0;
@@ -60,49 +61,66 @@ m_use4componentVertices(use4componentVertices)
}
void btTriangleMesh::addIndex(int index)
{
if (m_use32bitIndices)
{
m_32bitIndices.push_back(index);
m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0];
} else
{
m_16bitIndices.push_back(index);
m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0];
}
}
int btTriangleMesh::findOrAddVertex(const btVector3& vertex)
{
//return index of new/existing vertex
//todo: could use acceleration structure for this
if (m_use4componentVertices)
{
for (int i=0;i< m_4componentVertices.size();i++)
{
if ((m_4componentVertices[i]-vertex).length2() <= m_weldingThreshold)
{
return i;
}
}
m_indexedMeshes[0].m_numVertices++;
m_4componentVertices.push_back(vertex);
m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];
return m_4componentVertices.size()-1;
} else
{
for (int i=0;i< m_3componentVertices.size();i+=3)
{
btVector3 vtx(m_3componentVertices[i],m_3componentVertices[i+1],m_3componentVertices[i+2]);
if ((vtx-vertex).length2() <= m_weldingThreshold)
{
return i/3;
}
}
m_3componentVertices.push_back(vertex.getX());
m_3componentVertices.push_back(vertex.getY());
m_3componentVertices.push_back(vertex.getZ());
m_indexedMeshes[0].m_numVertices++;
m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];
return (m_3componentVertices.size()/3)-1;
}
}
void btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2)
{
m_indexedMeshes[0].m_numTriangles++;
m_indexedMeshes[0].m_numVertices+=3;
if (m_use4componentVertices)
{
m_4componentVertices.push_back(vertex0);
m_4componentVertices.push_back(vertex1);
m_4componentVertices.push_back(vertex2);
m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];
} else
{
m_3componentVertices.push_back(vertex0.getX());
m_3componentVertices.push_back(vertex0.getY());
m_3componentVertices.push_back(vertex0.getZ());
m_3componentVertices.push_back(vertex1.getX());
m_3componentVertices.push_back(vertex1.getY());
m_3componentVertices.push_back(vertex1.getZ());
m_3componentVertices.push_back(vertex2.getX());
m_3componentVertices.push_back(vertex2.getY());
m_3componentVertices.push_back(vertex2.getZ());
m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];
}
if (m_use32bitIndices)
{
int curIndex = m_32bitIndices.size();
m_32bitIndices.push_back(curIndex++);
m_32bitIndices.push_back(curIndex++);
m_32bitIndices.push_back(curIndex++);
m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0];
} else
{
short curIndex = static_cast<short>(m_16bitIndices.size());
m_16bitIndices.push_back(curIndex++);
m_16bitIndices.push_back(curIndex++);
m_16bitIndices.push_back(curIndex++);
m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0];
}
addIndex(findOrAddVertex(vertex0));
addIndex(findOrAddVertex(vertex1));
addIndex(findOrAddVertex(vertex2));
}
int btTriangleMesh::getNumTriangles() const

View File

@@ -25,6 +25,7 @@ subject to the following restrictions:
///It allows either 32bit or 16bit indices, and 4 (x-y-z-w) or 3 (x-y-z) component vertices.
///If you want to share triangle/index data between graphics mesh and collision mesh (btBvhTriangleMeshShape), you can directly use btTriangleIndexVertexArray or derive your own class from btStridingMeshInterface.
///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same.
///It has a brute-force option to weld together closeby vertices.
class btTriangleMesh : public btTriangleIndexVertexArray
{
btAlignedObjectArray<btVector3> m_4componentVertices;
@@ -34,11 +35,16 @@ class btTriangleMesh : public btTriangleIndexVertexArray
btAlignedObjectArray<unsigned short int> m_16bitIndices;
bool m_use32bitIndices;
bool m_use4componentVertices;
public:
btScalar m_weldingThreshold;
btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true);
int findOrAddVertex(const btVector3& vertex);
void addIndex(int index);
bool getUse32bitIndices() const
{
return m_use32bitIndices;

View File

@@ -0,0 +1,651 @@
#ifndef BT_BOX_COLLISION_H_INCLUDED
#define BT_BOX_COLLISION_H_INCLUDED
/*! \file gim_box_collision.h
\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btTransform.h"
/*! \defgroup BOUND_AABB_OPERATIONS
*/
//! @{
///Swap numbers
#define BT_SWAP_NUMBERS(a,b){ \
a = a+b; \
b = a-b; \
a = a-b; \
}\
#define BT_MAX(a,b) (a<b?b:a)
#define BT_MIN(a,b) (a>b?b:a)
#define BT_GREATER(x, y) fabsf(x) > (y)
#define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c))
#define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c))
enum eBT_PLANE_INTERSECTION_TYPE
{
BT_CONST_BACK_PLANE = 0,
BT_CONST_COLLIDE_PLANE,
BT_CONST_FRONT_PLANE
};
//SIMD_FORCE_INLINE bool test_cross_edge_box(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, const btVector3 & extend,
// int dir_index0,
// int dir_index1
// int component_index0,
// int component_index1)
//{
// // dir coords are -z and y
//
// const btScalar dir0 = -edge[dir_index0];
// const btScalar dir1 = edge[dir_index1];
// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
// //find minmax
// if(pmin>pmax)
// {
// BT_SWAP_NUMBERS(pmin,pmax);
// }
// //find extends
// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
// extend[component_index1] * absolute_edge[dir_index1];
//
// if(pmin>rad || -rad>pmax) return false;
// return true;
//}
//
//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, btVector3 & extend)
//{
//
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
//}
//
//
//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, btVector3 & extend)
//{
//
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
//}
//
//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, btVector3 & extend)
//{
//
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
//}
#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
{\
const btScalar dir0 = -edge[i_dir_0];\
const btScalar dir1 = edge[i_dir_1];\
btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
if(pmin>pmax)\
{\
BT_SWAP_NUMBERS(pmin,pmax); \
}\
const btScalar abs_dir0 = absolute_edge[i_dir_0];\
const btScalar abs_dir1 = absolute_edge[i_dir_1];\
const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
if(pmin>rad || -rad>pmax) return false;\
}\
#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
{\
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
}\
#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
{\
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
}\
#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
{\
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
}\
//! Returns the dot product between a vec3f and the col of a matrix
SIMD_FORCE_INLINE btScalar bt_mat3_dot_col(
const btMatrix3x3 & mat, const btVector3 & vec3, int colindex)
{
return vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex];
}
//! Class for transforming a model1 to the space of model0
ATTRIBUTE_ALIGNED16 (class) BT_BOX_BOX_TRANSFORM_CACHE
{
public:
btVector3 m_T1to0;//!< Transforms translation of model1 to model 0
btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1
btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
SIMD_FORCE_INLINE void calc_absolute_matrix()
{
// static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
// m_AR[0] = vepsi + m_R1to0[0].absolute();
// m_AR[1] = vepsi + m_R1to0[1].absolute();
// m_AR[2] = vepsi + m_R1to0[2].absolute();
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++ )
{
m_AR[i][j] = 1e-6f + fabsf(m_R1to0[i][j]);
}
}
}
BT_BOX_BOX_TRANSFORM_CACHE()
{
}
//! Calc the transformation relative 1 to 0. Inverts matrics by transposing
SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
{
btTransform temp_trans = trans0.inverse();
temp_trans = temp_trans * trans1;
m_T1to0 = temp_trans.getOrigin();
m_R1to0 = temp_trans.getBasis();
calc_absolute_matrix();
}
//! Calcs the full invertion of the matrices. Useful for scaling matrices
SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
{
m_R1to0 = trans0.getBasis().inverse();
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
m_T1to0 += m_R1to0*trans1.getOrigin();
m_R1to0 *= trans1.getBasis();
calc_absolute_matrix();
}
SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const
{
return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
m_R1to0[1].dot(point) + m_T1to0.y(),
m_R1to0[2].dot(point) + m_T1to0.z());
}
};
#define BOX_PLANE_EPSILON 0.000001f
//! Axis aligned box
ATTRIBUTE_ALIGNED16 (class) btAABB
{
public:
btVector3 m_min;
btVector3 m_max;
btAABB()
{}
btAABB(const btVector3 & V1,
const btVector3 & V2,
const btVector3 & V3)
{
m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
}
btAABB(const btVector3 & V1,
const btVector3 & V2,
const btVector3 & V3,
btScalar margin)
{
m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
btAABB(const btAABB &other):
m_min(other.m_min),m_max(other.m_max)
{
}
btAABB(const btAABB &other,btScalar margin ):
m_min(other.m_min),m_max(other.m_max)
{
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
SIMD_FORCE_INLINE void invalidate()
{
m_min[0] = SIMD_INFINITY;
m_min[1] = SIMD_INFINITY;
m_min[2] = SIMD_INFINITY;
m_max[0] = -SIMD_INFINITY;
m_max[1] = -SIMD_INFINITY;
m_max[2] = -SIMD_INFINITY;
}
SIMD_FORCE_INLINE void increment_margin(btScalar margin)
{
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin)
{
m_min[0] = other.m_min[0] - margin;
m_min[1] = other.m_min[1] - margin;
m_min[2] = other.m_min[2] - margin;
m_max[0] = other.m_max[0] + margin;
m_max[1] = other.m_max[1] + margin;
m_max[2] = other.m_max[2] + margin;
}
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void calc_from_triangle(
const CLASS_POINT & V1,
const CLASS_POINT & V2,
const CLASS_POINT & V3)
{
m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
}
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void calc_from_triangle_margin(
const CLASS_POINT & V1,
const CLASS_POINT & V2,
const CLASS_POINT & V3, btScalar margin)
{
m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
//! Apply a transform to an AABB
SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
{
btVector3 center = (m_max+m_min)*0.5f;
btVector3 extends = m_max - center;
// Compute new center
center = trans(center);
btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
extends.dot(trans.getBasis().getRow(1).absolute()),
extends.dot(trans.getBasis().getRow(2).absolute()));
m_min = center - textends;
m_max = center + textends;
}
//! Apply a transform to an AABB
SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE & trans)
{
btVector3 center = (m_max+m_min)*0.5f;
btVector3 extends = m_max - center;
// Compute new center
center = trans.transform(center);
btVector3 textends(extends.dot(trans.m_R1to0.getRow(0).absolute()),
extends.dot(trans.m_R1to0.getRow(1).absolute()),
extends.dot(trans.m_R1to0.getRow(2).absolute()));
m_min = center - textends;
m_max = center + textends;
}
//! Merges a Box
SIMD_FORCE_INLINE void merge(const btAABB & box)
{
m_min[0] = BT_MIN(m_min[0],box.m_min[0]);
m_min[1] = BT_MIN(m_min[1],box.m_min[1]);
m_min[2] = BT_MIN(m_min[2],box.m_min[2]);
m_max[0] = BT_MAX(m_max[0],box.m_max[0]);
m_max[1] = BT_MAX(m_max[1],box.m_max[1]);
m_max[2] = BT_MAX(m_max[2],box.m_max[2]);
}
//! Merges a point
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
{
m_min[0] = BT_MIN(m_min[0],point[0]);
m_min[1] = BT_MIN(m_min[1],point[1]);
m_min[2] = BT_MIN(m_min[2],point[2]);
m_max[0] = BT_MAX(m_max[0],point[0]);
m_max[1] = BT_MAX(m_max[1],point[1]);
m_max[2] = BT_MAX(m_max[2],point[2]);
}
//! Gets the extend and center
SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
{
center = (m_max+m_min)*0.5f;
extend = m_max - center;
}
//! Finds the intersecting box between this box and the other.
SIMD_FORCE_INLINE void find_intersection(const btAABB & other, btAABB & intersection) const
{
intersection.m_min[0] = BT_MAX(other.m_min[0],m_min[0]);
intersection.m_min[1] = BT_MAX(other.m_min[1],m_min[1]);
intersection.m_min[2] = BT_MAX(other.m_min[2],m_min[2]);
intersection.m_max[0] = BT_MIN(other.m_max[0],m_max[0]);
intersection.m_max[1] = BT_MIN(other.m_max[1],m_max[1]);
intersection.m_max[2] = BT_MIN(other.m_max[2],m_max[2]);
}
SIMD_FORCE_INLINE bool has_collision(const btAABB & other) const
{
if(m_min[0] > other.m_max[0] ||
m_max[0] < other.m_min[0] ||
m_min[1] > other.m_max[1] ||
m_max[1] < other.m_min[1] ||
m_min[2] > other.m_max[2] ||
m_max[2] < other.m_min[2])
{
return false;
}
return true;
}
/*! \brief Finds the Ray intersection parameter.
\param aabb Aligned box
\param vorigin A vec3f with the origin of the ray
\param vdir A vec3f with the direction of the ray
*/
SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) const
{
btVector3 extents,center;
this->get_center_extend(center,extents);;
btScalar Dx = vorigin[0] - center[0];
if(BT_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
btScalar Dy = vorigin[1] - center[1];
if(BT_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
btScalar Dz = vorigin[2] - center[2];
if(BT_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
btScalar f = vdir[1] * Dz - vdir[2] * Dy;
if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
f = vdir[2] * Dx - vdir[0] * Dz;
if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
f = vdir[0] * Dy - vdir[1] * Dx;
if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
return true;
}
SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
{
btVector3 center = (m_max+m_min)*0.5f;
btVector3 extend = m_max-center;
btScalar _fOrigin = direction.dot(center);
btScalar _fMaximumExtent = extend.dot(direction.absolute());
vmin = _fOrigin - _fMaximumExtent;
vmax = _fOrigin + _fMaximumExtent;
}
SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
{
btScalar _fmin,_fmax;
this->projection_interval(plane,_fmin,_fmax);
if(plane[3] > _fmax + BOX_PLANE_EPSILON)
{
return BT_CONST_BACK_PLANE; // 0
}
if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
{
return BT_CONST_COLLIDE_PLANE; //1
}
return BT_CONST_FRONT_PLANE;//2
}
SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB & box, btTransform & trans1_to_0) const
{
btAABB tbox = box;
tbox.appy_transform(trans1_to_0);
return has_collision(tbox);
}
SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB & box,
const BT_BOX_BOX_TRANSFORM_CACHE & trans1_to_0) const
{
btAABB tbox = box;
tbox.appy_transform_trans_cache(trans1_to_0);
return has_collision(tbox);
}
//! transcache is the transformation cache from box to this AABB
SIMD_FORCE_INLINE bool overlapping_trans_cache(
const btAABB & box,const BT_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) const
{
//Taken from OPCODE
btVector3 ea,eb;//extends
btVector3 ca,cb;//extends
get_center_extend(ca,ea);
box.get_center_extend(cb,eb);
btVector3 T;
btScalar t,t2;
int i;
// Class I : A's basis vectors
for(i=0;i<3;i++)
{
T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
t = transcache.m_AR[i].dot(eb) + ea[i];
if(BT_GREATER(T[i], t)) return false;
}
// Class II : B's basis vectors
for(i=0;i<3;i++)
{
t = bt_mat3_dot_col(transcache.m_R1to0,T,i);
t2 = bt_mat3_dot_col(transcache.m_AR,ea,i) + eb[i];
if(BT_GREATER(t,t2)) return false;
}
// Class III : 9 cross products
if(fulltest)
{
int j,m,n,o,p,q,r;
for(i=0;i<3;i++)
{
m = (i+1)%3;
n = (i+2)%3;
o = i==0?1:0;
p = i==2?1:2;
for(j=0;j<3;j++)
{
q = j==2?1:2;
r = j==0?1:0;
t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
if(BT_GREATER(t,t2)) return false;
}
}
}
return true;
}
//! Simple test for planes.
SIMD_FORCE_INLINE bool collide_plane(
const btVector4 & plane) const
{
eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane);
return (classify == BT_CONST_COLLIDE_PLANE);
}
//! test for a triangle, with edges
SIMD_FORCE_INLINE bool collide_triangle_exact(
const btVector3 & p1,
const btVector3 & p2,
const btVector3 & p3,
const btVector4 & triangle_plane) const
{
if(!collide_plane(triangle_plane)) return false;
btVector3 center,extends;
this->get_center_extend(center,extends);
const btVector3 v1(p1 - center);
const btVector3 v2(p2 - center);
const btVector3 v3(p3 - center);
//First axis
btVector3 diff(v2 - v1);
btVector3 abs_diff = diff.absolute();
//Test With X axis
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
//Test With Y axis
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
//Test With Z axis
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
diff = v3 - v2;
abs_diff = diff.absolute();
//Test With X axis
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
//Test With Y axis
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
//Test With Z axis
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
diff = v1 - v3;
abs_diff = diff.absolute();
//Test With X axis
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
//Test With Y axis
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
//Test With Z axis
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
return true;
}
};
//! Compairison of transformation objects
SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
{
if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
return true;
}
//! @}
#endif // GIM_BOX_COLLISION_H_INCLUDED

View File

@@ -0,0 +1,186 @@
#ifndef BT_CLIP_POLYGON_H_INCLUDED
#define BT_CLIP_POLYGON_H_INCLUDED
/*! \file btClipPolygon.h
\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btTransform.h"
#include "LinearMath/btGeometryUtil.h"
/*! \addtogroup GEOMETRIC_OPERATIONS
*/
//! @{
SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 & plane,const btVector3 &point)
{
return point.dot(plane) - plane[3];
}
/*! Vector blending
Takes two vectors a, b, blends them together*/
SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va,const btVector3 &vb, btScalar blend_factor)
{
vr = (1-blend_factor)*va + blend_factor*vb;
}
//! This function calcs the distance from a 3D plane
SIMD_FORCE_INLINE void bt_plane_clip_polygon_collect(
const btVector3 & point0,
const btVector3 & point1,
btScalar dist0,
btScalar dist1,
btVector3 * clipped,
int & clipped_count)
{
bool _prevclassif = (dist0>SIMD_EPSILON);
bool _classif = (dist1>SIMD_EPSILON);
if(_classif!=_prevclassif)
{
btScalar blendfactor = -dist0/(dist1-dist0);
bt_vec_blend(clipped[clipped_count],point0,point1,blendfactor);
clipped_count++;
}
if(!_classif)
{
clipped[clipped_count] = point1;
clipped_count++;
}
}
//! Clips a polygon by a plane
/*!
*\return The count of the clipped counts
*/
SIMD_FORCE_INLINE int bt_plane_clip_polygon(
const btVector4 & plane,
const btVector3 * polygon_points,
int polygon_point_count,
btVector3 * clipped)
{
int clipped_count = 0;
//clip first point
btScalar firstdist = bt_distance_point_plane(plane,polygon_points[0]);;
if(!(firstdist>SIMD_EPSILON))
{
clipped[clipped_count] = polygon_points[0];
clipped_count++;
}
btScalar olddist = firstdist;
for(int i=1;i<polygon_point_count;i++)
{
btScalar dist = bt_distance_point_plane(plane,polygon_points[i]);
bt_plane_clip_polygon_collect(
polygon_points[i-1],polygon_points[i],
olddist,
dist,
clipped,
clipped_count);
olddist = dist;
}
//RETURN TO FIRST point
bt_plane_clip_polygon_collect(
polygon_points[polygon_point_count-1],polygon_points[0],
olddist,
firstdist,
clipped,
clipped_count);
return clipped_count;
}
//! Clips a polygon by a plane
/*!
*\param clipped must be an array of 16 points.
*\return The count of the clipped counts
*/
SIMD_FORCE_INLINE int bt_plane_clip_triangle(
const btVector4 & plane,
const btVector3 & point0,
const btVector3 & point1,
const btVector3& point2,
btVector3 * clipped // an allocated array of 16 points at least
)
{
int clipped_count = 0;
//clip first point0
btScalar firstdist = bt_distance_point_plane(plane,point0);;
if(!(firstdist>SIMD_EPSILON))
{
clipped[clipped_count] = point0;
clipped_count++;
}
// point 1
btScalar olddist = firstdist;
btScalar dist = bt_distance_point_plane(plane,point1);
bt_plane_clip_polygon_collect(
point0,point1,
olddist,
dist,
clipped,
clipped_count);
olddist = dist;
// point 2
dist = bt_distance_point_plane(plane,point2);
bt_plane_clip_polygon_collect(
point1,point2,
olddist,
dist,
clipped,
clipped_count);
olddist = dist;
//RETURN TO FIRST point0
bt_plane_clip_polygon_collect(
point2,point0,
olddist,
firstdist,
clipped,
clipped_count);
return clipped_count;
}
//! @}
#endif // GIM_TRI_COLLISION_H_INCLUDED

View File

@@ -0,0 +1,181 @@
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btContactProcessing.h"
#define MAX_COINCIDENT 8
struct CONTACT_KEY_TOKEN
{
unsigned int m_key;
int m_value;
CONTACT_KEY_TOKEN()
{
}
CONTACT_KEY_TOKEN(unsigned int key,int token)
{
m_key = key;
m_value = token;
}
CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken)
{
m_key = rtoken.m_key;
m_value = rtoken.m_value;
}
inline bool operator <(const CONTACT_KEY_TOKEN& other) const
{
return (m_key < other.m_key);
}
inline bool operator >(const CONTACT_KEY_TOKEN& other) const
{
return (m_key > other.m_key);
}
};
class CONTACT_KEY_TOKEN_COMP
{
public:
bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b )
{
return ( a < b );
}
};
void btContactArray::merge_contacts(
const btContactArray & contacts, bool normal_contact_average)
{
clear();
int i;
if(contacts.size()==0) return;
if(contacts.size()==1)
{
push_back(contacts[0]);
return;
}
btAlignedObjectArray<CONTACT_KEY_TOKEN> keycontacts;
keycontacts.reserve(contacts.size());
//fill key contacts
for ( i = 0;i<contacts.size() ;i++ )
{
keycontacts.push_back(CONTACT_KEY_TOKEN(contacts[i].calc_key_contact(),i));
}
//sort keys
keycontacts.quickSort(CONTACT_KEY_TOKEN_COMP());
// Merge contacts
int coincident_count=0;
btVector3 coincident_normals[MAX_COINCIDENT];
unsigned int last_key = keycontacts[0].m_key;
unsigned int key = 0;
push_back(contacts[keycontacts[0].m_value]);
BT_CONTACT * pcontact = &(*this)[0];
for( i=1;i<keycontacts.size();i++)
{
key = keycontacts[i].m_key;
const BT_CONTACT * scontact = &contacts[keycontacts[i].m_value];
if(last_key == key)//same points
{
//merge contact
if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
{
*pcontact = *scontact;
coincident_count = 0;
}
else if(normal_contact_average)
{
if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
{
if(coincident_count<MAX_COINCIDENT)
{
coincident_normals[coincident_count] = scontact->m_normal;
coincident_count++;
}
}
}
}
else
{//add new contact
if(normal_contact_average && coincident_count>0)
{
pcontact->interpolate_normals(coincident_normals,coincident_count);
coincident_count = 0;
}
push_back(*scontact);
pcontact = &(*this)[this->size()-1];
}
last_key = key;
}
}
void btContactArray::merge_contacts_unique(const btContactArray & contacts)
{
clear();
if(contacts.size()==0) return;
if(contacts.size()==1)
{
push_back(contacts[0]);
return;
}
BT_CONTACT average_contact = contacts[0];
for (int i=1;i<contacts.size() ;i++ )
{
average_contact.m_point += contacts[i].m_point;
average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
}
//divide
btScalar divide_average = 1.0f/((btScalar)contacts.size());
average_contact.m_point *= divide_average;
average_contact.m_normal *= divide_average;
average_contact.m_depth = average_contact.m_normal.length();
average_contact.m_normal /= average_contact.m_depth;
}

View File

@@ -0,0 +1,149 @@
#ifndef BT_CONTACT_H_INCLUDED
#define BT_CONTACT_H_INCLUDED
/*! \file gim_contact.h
\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btTransform.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "btTriangleShapeEx.h"
/*! \defgroup CONTACTS
\brief
Functions for managing and sorting contacts resulting from a collision query.
*/
//! @{
/**
Configuration var for applying interpolation of contact normals
*/
#define NORMAL_CONTACT_AVERAGE 1
#define CONTACT_DIFF_EPSILON 0.00001f
/// Structure for collision results
class BT_CONTACT
{
public:
btVector3 m_point;
btVector3 m_normal;
btScalar m_depth;//Positive value indicates interpenetration
btScalar m_distance;//Padding not for use
int m_feature1;//Face number
int m_feature2;//Face number
public:
BT_CONTACT()
{
}
BT_CONTACT(const BT_CONTACT & contact):
m_point(contact.m_point),
m_normal(contact.m_normal),
m_depth(contact.m_depth),
m_feature1(contact.m_feature1),
m_feature2(contact.m_feature2)
{
}
BT_CONTACT(const btVector3 &point,const btVector3 & normal,
btScalar depth, int feature1, int feature2):
m_point(point),
m_normal(normal),
m_depth(depth),
m_feature1(feature1),
m_feature2(feature2)
{
}
//! Calcs key for coord classification
SIMD_FORCE_INLINE unsigned int calc_key_contact() const
{
int _coords[] = {
(int)(m_point[0]*1000.0f+1.0f),
(int)(m_point[1]*1333.0f),
(int)(m_point[2]*2133.0f+3.0f)};
unsigned int _hash=0;
unsigned int *_uitmp = (unsigned int *)(&_coords[0]);
_hash = *_uitmp;
_uitmp++;
_hash += (*_uitmp)<<4;
_uitmp++;
_hash += (*_uitmp)<<8;
return _hash;
}
SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,int normal_count)
{
btVector3 vec_sum(m_normal);
for(int i=0;i<normal_count;i++)
{
vec_sum += normals[i];
}
btScalar vec_sum_len = vec_sum.length2();
if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
//GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
m_normal = vec_sum/btSqrt(vec_sum_len);
}
};
class btContactArray:public btAlignedObjectArray<BT_CONTACT>
{
public:
btContactArray()
{
reserve(64);
}
SIMD_FORCE_INLINE void push_contact(
const btVector3 &point,const btVector3 & normal,
btScalar depth, int feature1, int feature2)
{
push_back( BT_CONTACT(point,normal,depth,feature1,feature2) );
}
SIMD_FORCE_INLINE void push_triangle_contacts(
const BT_TRIANGLE_CONTACT & tricontact,
int feature1,int feature2)
{
for(int i = 0;i<tricontact.m_point_count ;i++ )
{
push_contact(
tricontact.m_points[i],
tricontact.m_separating_normal,
tricontact.m_penetration_depth,feature1,feature2);
}
}
void merge_contacts(const btContactArray & contacts, bool normal_contact_average = true);
void merge_contacts_unique(const btContactArray & contacts);
};
//! @}
#endif // GIM_CONTACT_H_INCLUDED

View File

@@ -0,0 +1,499 @@
/*! \file gim_box_set.h
\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGImpactBvh.h"
#include "LinearMath/btQuickprof.h"
#ifdef TRI_COLLISION_PROFILING
btClock g_tree_clock;
float g_accum_tree_collision_time = 0;
int g_count_traversing = 0;
void bt_begin_gim02_tree_time()
{
g_tree_clock.reset();
}
void bt_end_gim02_tree_time()
{
g_accum_tree_collision_time += g_tree_clock.getTimeMicroseconds();
g_count_traversing++;
}
//! Gets the average time in miliseconds of tree collisions
float btGImpactBvh::getAverageTreeCollisionTime()
{
if(g_count_traversing == 0) return 0;
float avgtime = g_accum_tree_collision_time;
avgtime /= (float)g_count_traversing;
g_accum_tree_collision_time = 0;
g_count_traversing = 0;
return avgtime;
// float avgtime = g_count_traversing;
// g_count_traversing = 0;
// return avgtime;
}
#endif //TRI_COLLISION_PROFILING
/////////////////////// btBvhTree /////////////////////////////////
int btBvhTree::_calc_splitting_axis(
BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
{
int i;
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
int numIndices = endIndex-startIndex;
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
btVector3 diff2 = center-means;
diff2 = diff2 * diff2;
variance += diff2;
}
variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
return variance.maxAxis();
}
int btBvhTree::_sort_and_calc_splitting_index(
BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex,
int endIndex, int splitAxis)
{
int i;
int splitIndex =startIndex;
int numIndices = endIndex - startIndex;
// average of centers
btScalar splitValue = 0.0f;
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
splitValue = means[splitAxis];
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
if (center[splitAxis] > splitValue)
{
//swap
primitive_boxes.swap(i,splitIndex);
//swapLeafNodes(i,splitIndex);
splitIndex++;
}
}
//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
//otherwise the tree-building might fail due to stack-overflows in certain cases.
//unbalanced1 is unsafe: it can cause stack overflows
//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
//unbalanced2 should work too: always use center (perfect balanced trees)
//bool unbalanced2 = true;
//this should be safe too:
int rangeBalancedIndices = numIndices/3;
bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
if (unbalanced)
{
splitIndex = startIndex+ (numIndices>>1);
}
bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
btAssert(!unbal);
return splitIndex;
}
void btBvhTree::_build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
{
int curIndex = m_num_nodes;
m_num_nodes++;
btAssert((endIndex-startIndex)>0);
if ((endIndex-startIndex)==1)
{
//We have a leaf node
setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
return;
}
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
//split axis
int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
splitIndex = _sort_and_calc_splitting_index(
primitive_boxes,startIndex,endIndex,
splitIndex//split axis
);
//calc this node bounding box
btAABB node_bound;
node_bound.invalidate();
for (int i=startIndex;i<endIndex;i++)
{
node_bound.merge(primitive_boxes[i].m_bound);
}
setNodeBound(curIndex,node_bound);
//build left branch
_build_sub_tree(primitive_boxes, startIndex, splitIndex );
//build right branch
_build_sub_tree(primitive_boxes, splitIndex ,endIndex);
m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
}
//! stackless build tree
void btBvhTree::build_tree(
BT_BVH_DATA_ARRAY & primitive_boxes)
{
// initialize node count to 0
m_num_nodes = 0;
// allocate nodes
m_node_array.resize(primitive_boxes.size()*2);
_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
}
////////////////////////////////////class btGImpactBvh
void btGImpactBvh::refit()
{
int nodecount = getNodeCount();
while(nodecount--)
{
if(isLeafNode(nodecount))
{
btAABB leafbox;
m_primitive_manager->get_primitive_box(getNodeData(nodecount),leafbox);
setNodeBound(nodecount,leafbox);
}
else
{
//const BT_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
//get left bound
btAABB bound;
bound.invalidate();
btAABB temp_box;
int child_node = getLeftNode(nodecount);
if(child_node)
{
getNodeBound(child_node,temp_box);
bound.merge(temp_box);
}
child_node = getRightNode(nodecount);
if(child_node)
{
getNodeBound(child_node,temp_box);
bound.merge(temp_box);
}
setNodeBound(nodecount,bound);
}
}
}
//! this rebuild the entire set
void btGImpactBvh::buildSet()
{
//obtain primitive boxes
BT_BVH_DATA_ARRAY primitive_boxes;
primitive_boxes.resize(m_primitive_manager->get_primitive_count());
for (int i = 0;i<primitive_boxes.size() ;i++ )
{
m_primitive_manager->get_primitive_box(i,primitive_boxes[i].m_bound);
primitive_boxes[i].m_data = i;
}
m_box_tree.build_tree(primitive_boxes);
}
//! returns the indices of the primitives in the m_primitive_manager
bool btGImpactBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
while (curIndex < numNodes)
{
btAABB bound;
getNodeBound(curIndex,bound);
//catch bugs in tree data
bool aabbOverlap = bound.has_collision(box);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData(curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getEscapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
//! returns the indices of the primitives in the m_primitive_manager
bool btGImpactBvh::rayQuery(
const btVector3 & ray_dir,const btVector3 & ray_origin ,
btAlignedObjectArray<int> & collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
while (curIndex < numNodes)
{
btAABB bound;
getNodeBound(curIndex,bound);
//catch bugs in tree data
bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData( curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getEscapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
SIMD_FORCE_INLINE bool _node_collision(
btGImpactBvh * boxset0, btGImpactBvh * boxset1,
const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
int node0 ,int node1, bool complete_primitive_tests)
{
btAABB box0;
boxset0->getNodeBound(node0,box0);
btAABB box1;
boxset1->getNodeBound(node1,box1);
return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests );
// box1.appy_transform_trans_cache(trans_cache_1to0);
// return box0.has_collision(box1);
}
//stackless recursive collision routine
static void _find_collision_pairs_recursive(
btGImpactBvh * boxset0, btGImpactBvh * boxset1,
btPairSet * collision_pairs,
const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
int node0, int node1, bool complete_primitive_tests)
{
if( _node_collision(
boxset0,boxset1,trans_cache_1to0,
node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes
if(boxset0->isLeafNode(node0))
{
if(boxset1->isLeafNode(node1))
{
// collision result
collision_pairs->push_pair(
boxset0->getNodeData(node0),boxset1->getNodeData(node1));
return;
}
else
{
//collide left recursive
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
node0,boxset1->getLeftNode(node1),false);
//collide right recursive
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
node0,boxset1->getRightNode(node1),false);
}
}
else
{
if(boxset1->isLeafNode(node1))
{
//collide left recursive
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),node1,false);
//collide right recursive
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),node1,false);
}
else
{
//collide left0 left1
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false);
//collide left0 right1
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false);
//collide right0 left1
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false);
//collide right0 right1
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),boxset1->getRightNode(node1),false);
}// else if node1 is not a leaf
}// else if node0 is not a leaf
}
void btGImpactBvh::find_collision(btGImpactBvh * boxset0, const btTransform & trans0,
btGImpactBvh * boxset1, const btTransform & trans1,
btPairSet & collision_pairs)
{
if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return;
BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
trans_cache_1to0.calc_from_homogenic(trans0,trans1);
#ifdef TRI_COLLISION_PROFILING
bt_begin_gim02_tree_time();
#endif //TRI_COLLISION_PROFILING
_find_collision_pairs_recursive(
boxset0,boxset1,
&collision_pairs,trans_cache_1to0,0,0,true);
#ifdef TRI_COLLISION_PROFILING
bt_end_gim02_tree_time();
#endif //TRI_COLLISION_PROFILING
}

View File

@@ -0,0 +1,401 @@
#ifndef GIM_BOX_SET_H_INCLUDED
#define GIM_BOX_SET_H_INCLUDED
/*! \file gim_box_set.h
\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btAlignedObjectArray.h"
#include "btBoxCollision.h"
#include "btTriangleShapeEx.h"
/*! \defgroup BOX_TREES
*/
//! @{
//! Overlapping pair
struct BT_PAIR
{
int m_index1;
int m_index2;
BT_PAIR()
{}
BT_PAIR(const BT_PAIR & p)
{
m_index1 = p.m_index1;
m_index2 = p.m_index2;
}
BT_PAIR(int index1, int index2)
{
m_index1 = index1;
m_index2 = index2;
}
};
//! A pairset array
class btPairSet: public btAlignedObjectArray<BT_PAIR>
{
public:
btPairSet()
{
reserve(32);
}
inline void push_pair(int index1,int index2)
{
push_back(BT_PAIR(index1,index2));
}
inline void push_pair_inv(int index1,int index2)
{
push_back(BT_PAIR(index2,index1));
}
};
struct BT_BVH_DATA
{
btAABB m_bound;
int m_data;
};
//! Node Structure for trees
class BT_BVH_TREE_NODE
{
public:
btAABB m_bound;
protected:
int m_escapeIndexOrDataIndex;
public:
BT_BVH_TREE_NODE()
{
m_escapeIndexOrDataIndex = 0;
}
SIMD_FORCE_INLINE bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrDataIndex>=0);
}
SIMD_FORCE_INLINE int getEscapeIndex() const
{
//btAssert(m_escapeIndexOrDataIndex < 0);
return -m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setEscapeIndex(int index)
{
m_escapeIndexOrDataIndex = -index;
}
SIMD_FORCE_INLINE int getDataIndex() const
{
//btAssert(m_escapeIndexOrDataIndex >= 0);
return m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setDataIndex(int index)
{
m_escapeIndexOrDataIndex = index;
}
};
class BT_BVH_DATA_ARRAY:public btAlignedObjectArray<BT_BVH_DATA>
{
};
class BT_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray<BT_BVH_TREE_NODE>
{
};
//! Basic Box tree structure
class btBvhTree
{
protected:
int m_num_nodes;
BT_BVH_TREE_NODE_ARRAY m_node_array;
protected:
int _sort_and_calc_splitting_index(
BT_BVH_DATA_ARRAY & primitive_boxes,
int startIndex, int endIndex, int splitAxis);
int _calc_splitting_axis(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
void _build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
public:
btBvhTree()
{
m_num_nodes = 0;
}
//! prototype functions for box tree management
//!@{
void build_tree(BT_BVH_DATA_ARRAY & primitive_boxes);
SIMD_FORCE_INLINE void clearNodes()
{
m_node_array.clear();
m_num_nodes = 0;
}
//! node count
SIMD_FORCE_INLINE int getNodeCount() const
{
return m_num_nodes;
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
{
return m_node_array[nodeindex].isLeafNode();
}
SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
{
return m_node_array[nodeindex].getDataIndex();
}
SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
{
bound = m_node_array[nodeindex].m_bound;
}
SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
{
m_node_array[nodeindex].m_bound = bound;
}
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
return nodeindex+1;
}
SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
{
if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
}
SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
{
return m_node_array[nodeindex].getEscapeIndex();
}
SIMD_FORCE_INLINE const BT_BVH_TREE_NODE * get_node_pointer(int index = 0) const
{
return &m_node_array[index];
}
//!@}
};
//! Prototype Base class for primitive classification
/*!
This class is a wrapper for primitive collections.
This tells relevant info for the Bounding Box set classes, which take care of space classification.
This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
*/
class btPrimitiveManagerBase
{
public:
//! determines if this manager consist on only triangles, which special case will be optimized
virtual bool is_trimesh() const = 0;
virtual int get_primitive_count() const = 0;
virtual void get_primitive_box(int prim_index ,btAABB & primbox) const = 0;
//! retrieves only the points of the triangle, and the collision margin
virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const= 0;
};
//! Structure for containing Boxes
/*!
This class offers an structure for managing a box tree of primitives.
Requires a Primitive prototype (like btPrimitiveManagerBase )
*/
class btGImpactBvh
{
protected:
btBvhTree m_box_tree;
btPrimitiveManagerBase * m_primitive_manager;
protected:
//stackless refit
void refit();
public:
//! this constructor doesn't build the tree. you must call buildSet
btGImpactBvh()
{
m_primitive_manager = NULL;
}
//! this constructor doesn't build the tree. you must call buildSet
btGImpactBvh(btPrimitiveManagerBase * primitive_manager)
{
m_primitive_manager = primitive_manager;
}
SIMD_FORCE_INLINE btAABB getGlobalBox() const
{
btAABB totalbox;
getNodeBound(0, totalbox);
return totalbox;
}
SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
{
m_primitive_manager = primitive_manager;
}
SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
{
return m_primitive_manager;
}
//! node manager prototype functions
///@{
//! this attemps to refit the box set.
SIMD_FORCE_INLINE void update()
{
refit();
}
//! this rebuild the entire set
void buildSet();
//! returns the indices of the primitives in the m_primitive_manager
bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
{
btAABB transbox=box;
transbox.appy_transform(transform);
return boxQuery(transbox,collided_results);
}
//! returns the indices of the primitives in the m_primitive_manager
bool rayQuery(
const btVector3 & ray_dir,const btVector3 & ray_origin ,
btAlignedObjectArray<int> & collided_results) const;
//! tells if this set has hierarcht
SIMD_FORCE_INLINE bool hasHierarchy() const
{
return true;
}
//! tells if this set is a trimesh
SIMD_FORCE_INLINE bool isTrimesh() const
{
return m_primitive_manager->is_trimesh();
}
//! node count
SIMD_FORCE_INLINE int getNodeCount() const
{
return m_box_tree.getNodeCount();
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
{
return m_box_tree.isLeafNode(nodeindex);
}
SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
{
return m_box_tree.getNodeData(nodeindex);
}
SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
{
m_box_tree.getNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
{
m_box_tree.setNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
return m_box_tree.getLeftNode(nodeindex);
}
SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
{
return m_box_tree.getRightNode(nodeindex);
}
SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
{
return m_box_tree.getEscapeNodeIndex(nodeindex);
}
SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
{
m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
}
SIMD_FORCE_INLINE const BT_BVH_TREE_NODE * get_node_pointer(int index = 0) const
{
return m_box_tree.get_node_pointer(index);
}
//! @}
static float getAverageTreeCollisionTime();
static void find_collision(btGImpactBvh * boxset1, const btTransform & trans1,
btGImpactBvh * boxset2, const btTransform & trans2,
btPairSet & collision_pairs);
};
#endif // GIM_BOXPRUNING_H_INCLUDED

View File

@@ -0,0 +1,896 @@
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
Author: Francisco Le<4C>n N<>jera
Concave-Concave Collision
*/
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "btGImpactCollisionAlgorithm.h"
#include "btContactProcessing.h"
#include "LinearMath/btQuickprof.h"
//! Class for accessing the plane equation
class btPlaneShape : public btStaticPlaneShape
{
public:
btPlaneShape(const btVector3& v, float f)
:btStaticPlaneShape(v,f)
{
}
void get_plane_equation(btVector4 &equation)
{
equation[0] = m_planeNormal[0];
equation[1] = m_planeNormal[1];
equation[2] = m_planeNormal[2];
equation[3] = m_planeConstant;
}
void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation)
{
equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal);
equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal);
equation[2] = trans.getBasis().getRow(2).dot(m_planeNormal);
equation[3] = trans.getOrigin().dot(m_planeNormal) + m_planeConstant;
}
};
//////////////////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_COLLISION_PROFILING
btClock g_triangle_clock;
float g_accum_triangle_collision_time = 0;
int g_count_triangle_collision = 0;
void bt_begin_gim02_tri_time()
{
g_triangle_clock.reset();
}
void bt_end_gim02_tri_time()
{
g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
g_count_triangle_collision++;
}
#endif //TRI_COLLISION_PROFILING
//! Retrieving shapes shapes
/*!
Declared here due of insuficent space on Pool allocators
*/
//!@{
class GIM_ShapeRetriever
{
public:
btGImpactShapeInterface * m_gim_shape;
btTriangleShapeEx m_trishape;
btTetrahedronShapeEx m_tetrashape;
public:
class ChildShapeRetriever
{
public:
GIM_ShapeRetriever * m_parent;
virtual btCollisionShape * getChildShape(int index)
{
return m_parent->m_gim_shape->getChildShape(index);
}
};
class TriangleShapeRetriever:public ChildShapeRetriever
{
public:
virtual btCollisionShape * getChildShape(int index)
{
m_parent->m_gim_shape->getBulletTriangle(index,m_parent->m_trishape);
return &m_parent->m_trishape;
}
};
class TetraShapeRetriever:public ChildShapeRetriever
{
public:
virtual btCollisionShape * getChildShape(int index)
{
m_parent->m_gim_shape->getBulletTetrahedron(index,m_parent->m_tetrashape);
return &m_parent->m_tetrashape;
}
};
public:
ChildShapeRetriever m_child_retriever;
TriangleShapeRetriever m_tri_retriever;
TetraShapeRetriever m_tetra_retriever;
ChildShapeRetriever * m_current_retriever;
GIM_ShapeRetriever(btGImpactShapeInterface * gim_shape)
{
m_gim_shape = gim_shape;
//select retriever
if(m_gim_shape->needsRetrieveTriangles())
{
m_current_retriever = &m_tri_retriever;
}
else if(m_gim_shape->needsRetrieveTetrahedrons())
{
m_current_retriever = &m_tetra_retriever;
}
else
{
m_current_retriever = &m_child_retriever;
}
m_current_retriever->m_parent = this;
}
btCollisionShape * getChildShape(int index)
{
return m_current_retriever->getChildShape(index);
}
};
//!@}
#ifdef TRI_COLLISION_PROFILING
//! Gets the average time in miliseconds of tree collisions
float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
{
return btGImpactBoxSet::getAverageTreeCollisionTime();
}
//! Gets the average time in miliseconds of triangle collisions
float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
{
if(g_count_triangle_collision == 0) return 0;
float avgtime = g_accum_triangle_collision_time;
avgtime /= (float)g_count_triangle_collision;
g_accum_triangle_collision_time = 0;
g_count_triangle_collision = 0;
return avgtime;
}
#endif //TRI_COLLISION_PROFILING
btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
: btCollisionAlgorithm(ci)
{
m_manifoldPtr = NULL;
m_convex_algorithm = NULL;
}
btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
{
clearCache();
}
void btGImpactCollisionAlgorithm::addContactPoint(btCollisionObject * body0,
btCollisionObject * body1,
const btVector3 & point,
const btVector3 & normal,
btScalar distance)
{
m_resultOut->setShapeIdentifiers(m_part0,m_triface0,m_part1,m_triface1);
checkManifold(body0,body1);
m_resultOut->addContactPoint(normal,point,distance);
}
void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btCollisionShape * shape0,
btCollisionShape * shape1)
{
btCollisionShape* tmpShape0 = body0->getCollisionShape();
btCollisionShape* tmpShape1 = body1->getCollisionShape();
body0->internalSetTemporaryCollisionShape(shape0);
body1->internalSetTemporaryCollisionShape(shape1);
{
btCollisionAlgorithm* algor = newAlgorithm(body0,body1);
// post : checkManifold is called
m_resultOut->setShapeIdentifiers(m_part0,m_triface0,m_part1,m_triface1);
algor->processCollision(body0,body1,*m_dispatchInfo,m_resultOut);
algor->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algor);
}
body0->internalSetTemporaryCollisionShape(tmpShape0);
body1->internalSetTemporaryCollisionShape(tmpShape1);
}
void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btCollisionShape * shape0,
btCollisionShape * shape1)
{
btCollisionShape* tmpShape0 = body0->getCollisionShape();
btCollisionShape* tmpShape1 = body1->getCollisionShape();
body0->internalSetTemporaryCollisionShape(shape0);
body1->internalSetTemporaryCollisionShape(shape1);
m_resultOut->setShapeIdentifiers(m_part0,m_triface0,m_part1,m_triface1);
checkConvexAlgorithm(body0,body1);
m_convex_algorithm->processCollision(body0,body1,*m_dispatchInfo,m_resultOut);
body0->internalSetTemporaryCollisionShape(tmpShape0);
body1->internalSetTemporaryCollisionShape(tmpShape1);
}
void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
btGImpactShapeInterface * shape0,
btGImpactShapeInterface * shape1,btPairSet & pairset)
{
if(shape0->hasBoxSet() && shape1->hasBoxSet())
{
btGImpactBoxSet::find_collision(shape0->getBoxSet(),trans0,shape1->getBoxSet(),trans1,pairset);
}
else
{
btAABB boxshape0;
btAABB boxshape1;
int i = shape0->getNumChildShapes();
while(i--)
{
shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
int j = shape1->getNumChildShapes();
while(j--)
{
shape1->getChildAabb(i,trans1,boxshape1.m_min,boxshape1.m_max);
if(boxshape1.has_collision(boxshape0))
{
pairset.push_pair(i,j);
}
}
}
}
}
void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
btGImpactShapeInterface * shape0,
btCollisionShape * shape1,
btAlignedObjectArray<int> & collided_primitives)
{
btAABB boxshape;
if(shape0->hasBoxSet())
{
btTransform trans1to0 = trans0.inverse();
trans1to0 *= trans1;
shape1->getAabb(trans1to0,boxshape.m_min,boxshape.m_max);
shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
}
else
{
shape1->getAabb(trans1,boxshape.m_min,boxshape.m_max);
btAABB boxshape0;
int i = shape0->getNumChildShapes();
while(i--)
{
shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
if(boxshape.has_collision(boxshape0))
{
collided_primitives.push_back(i);
}
}
}
}
void btGImpactCollisionAlgorithm::collide_gjk_triangles(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0,
btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count)
{
btTriangleShapeEx tri0;
btTriangleShapeEx tri1;
shape0->lockChildShapes();
shape1->lockChildShapes();
const int * pair_pointer = pairs;
while(pair_count--)
{
m_triface0 = *(pair_pointer);
m_triface1 = *(pair_pointer+1);
pair_pointer+=2;
shape0->getBulletTriangle(m_triface0,tri0);
shape1->getBulletTriangle(m_triface1,tri1);
//collide two convex shapes
if(tri0.overlap_test_conservative(tri1))
{
convex_vs_convex_collision(body0,body1,&tri0,&tri1);
}
}
shape0->unlockChildShapes();
shape1->unlockChildShapes();
}
void btGImpactCollisionAlgorithm::collide_sat_triangles(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0,
btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count)
{
btTransform orgtrans0 = body0->getWorldTransform();
btTransform orgtrans1 = body1->getWorldTransform();
btPrimitiveTriangle ptri0;
btPrimitiveTriangle ptri1;
BT_TRIANGLE_CONTACT contact_data;
shape0->lockChildShapes();
shape1->lockChildShapes();
const int * pair_pointer = pairs;
while(pair_count--)
{
m_triface0 = *(pair_pointer);
m_triface1 = *(pair_pointer+1);
pair_pointer+=2;
shape0->getPrimitiveTriangle(m_triface0,ptri0);
shape1->getPrimitiveTriangle(m_triface1,ptri1);
#ifdef TRI_COLLISION_PROFILING
bt_begin_gim02_tri_time();
#endif
ptri0.applyTransform(orgtrans0);
ptri1.applyTransform(orgtrans1);
//build planes
ptri0.buildTriPlane();
ptri1.buildTriPlane();
// test conservative
if(ptri0.overlap_test_conservative(ptri1))
{
if(ptri0.find_triangle_collision_clip_method(ptri1,contact_data))
{
int j = contact_data.m_point_count;
while(j--)
{
addContactPoint(body0, body1,
contact_data.m_points[j],
contact_data.m_separating_normal,
-contact_data.m_penetration_depth);
}
}
}
#ifdef TRI_COLLISION_PROFILING
bt_end_gim02_tri_time();
#endif
}
shape0->unlockChildShapes();
shape1->unlockChildShapes();
}
void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactShapeInterface * shape0,
btGImpactShapeInterface * shape1)
{
if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
{
btGImpactMeshShape * meshshape0 = static_cast<btGImpactMeshShape *>(shape0);
m_part0 = meshshape0->getMeshPartCount();
while(m_part0--)
{
gimpact_vs_gimpact(body0,body1,meshshape0->getMeshPart(m_part0),shape1);
}
return;
}
if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
{
btGImpactMeshShape * meshshape1 = static_cast<btGImpactMeshShape *>(shape1);
m_part1 = meshshape1->getMeshPartCount();
while(m_part1--)
{
gimpact_vs_gimpact(body0,body1,shape0,meshshape1->getMeshPart(m_part1));
}
return;
}
btTransform orgtrans0 = body0->getWorldTransform();
btTransform orgtrans1 = body1->getWorldTransform();
btPairSet pairset;
gimpact_vs_gimpact_find_pairs(orgtrans0,orgtrans1,shape0,shape1,pairset);
if(pairset.size()== 0) return;
if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
{
btGImpactMeshShapePart * shapepart0 = static_cast<btGImpactMeshShapePart * >(shape0);
btGImpactMeshShapePart * shapepart1 = static_cast<btGImpactMeshShapePart * >(shape1);
//specialized function
#ifdef BULLET_TRIANGLE_COLLISION
collide_gjk_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
#else
collide_sat_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
#endif
return;
}
//general function
shape0->lockChildShapes();
shape1->lockChildShapes();
GIM_ShapeRetriever retriever0(shape0);
GIM_ShapeRetriever retriever1(shape1);
bool child_has_transform0 = shape0->childrenHasTransform();
bool child_has_transform1 = shape1->childrenHasTransform();
int i = pairset.size();
while(i--)
{
BT_PAIR * pair = &pairset[i];
m_triface0 = pair->m_index1;
m_triface1 = pair->m_index2;
btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0);
btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1);
if(child_has_transform0)
{
body0->setWorldTransform(orgtrans0*shape0->getChildTransform(m_triface0));
}
if(child_has_transform1)
{
body1->setWorldTransform(orgtrans1*shape1->getChildTransform(m_triface1));
}
//collide two convex shapes
convex_vs_convex_collision(body0,body1,colshape0,colshape1);
if(child_has_transform0)
{
body0->setWorldTransform(orgtrans0);
}
if(child_has_transform1)
{
body1->setWorldTransform(orgtrans1);
}
}
shape0->unlockChildShapes();
shape1->unlockChildShapes();
}
void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactShapeInterface * shape0,
btCollisionShape * shape1,bool swapped)
{
if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
{
btGImpactMeshShape * meshshape0 = static_cast<btGImpactMeshShape *>(shape0);
m_part0 = meshshape0->getMeshPartCount();
while(m_part0--)
{
gimpact_vs_shape(body0,
body1,
meshshape0->getMeshPart(m_part0),
shape1,swapped);
}
return;
}
#ifdef GIMPACT_VS_PLANE_COLLISION
if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
{
btGImpactMeshShapePart * shapepart = static_cast<btGImpactMeshShapePart *>(shape0);
btStaticPlaneShape * planeshape = static_cast<btStaticPlaneShape * >(shape1);
gimpacttrimeshpart_vs_plane_collision(body0,body1,shapepart,planeshape,swapped);
return;
}
#endif
if(shape1->isCompound())
{
btCompoundShape * compoundshape = static_cast<btCompoundShape *>(shape1);
gimpact_vs_compoundshape(body0,body1,shape0,compoundshape,swapped);
return;
}
else if(shape1->isConcave())
{
btConcaveShape * concaveshape = static_cast<btConcaveShape *>(shape1);
gimpact_vs_concave(body0,body1,shape0,concaveshape,swapped);
return;
}
btTransform orgtrans0 = body0->getWorldTransform();
btTransform orgtrans1 = body1->getWorldTransform();
btAlignedObjectArray<int> collided_results;
gimpact_vs_shape_find_pairs(orgtrans0,orgtrans1,shape0,shape1,collided_results);
if(collided_results.size() == 0) return;
shape0->lockChildShapes();
GIM_ShapeRetriever retriever0(shape0);
bool child_has_transform0 = shape0->childrenHasTransform();
int i = collided_results.size();
while(i--)
{
int child_index = collided_results[i];
if(swapped)
m_triface1 = child_index;
else
m_triface0 = child_index;
btCollisionShape * colshape0 = retriever0.getChildShape(child_index);
if(child_has_transform0)
{
body0->setWorldTransform(orgtrans0*shape0->getChildTransform(child_index));
}
//collide two shapes
if(swapped)
{
shape_vs_shape_collision(body1,body0,shape1,colshape0);
}
else
{
shape_vs_shape_collision(body0,body1,colshape0,shape1);
}
//restore transforms
if(child_has_transform0)
{
body0->setWorldTransform(orgtrans0);
}
}
shape0->unlockChildShapes();
}
void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactShapeInterface * shape0,
btCompoundShape * shape1,bool swapped)
{
btTransform orgtrans1 = body1->getWorldTransform();
int i = shape1->getNumChildShapes();
while(i--)
{
btCollisionShape * colshape1 = shape1->getChildShape(i);
btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i);
body1->setWorldTransform(childtrans1);
//collide child shape
gimpact_vs_shape(body0, body1,
shape0,colshape1,swapped);
//restore transforms
body1->setWorldTransform(orgtrans1);
}
}
void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0,
btStaticPlaneShape * shape1,bool swapped)
{
btTransform orgtrans0 = body0->getWorldTransform();
btTransform orgtrans1 = body1->getWorldTransform();
btPlaneShape * planeshape = static_cast<btPlaneShape *>(shape1);
btVector4 plane;
planeshape->get_plane_equation_transformed(orgtrans1,plane);
//test box against plane
btAABB tribox;
shape0->getAabb(orgtrans0,tribox.m_min,tribox.m_max);
tribox.increment_margin(planeshape->getMargin());
if( tribox.plane_classify(plane)!= BT_CONST_COLLIDE_PLANE) return;
shape0->lockChildShapes();
btScalar margin = shape0->getMargin() + planeshape->getMargin();
btVector3 vertex;
int vi = shape0->getVertexCount();
while(vi--)
{
shape0->getVertex(vi,vertex);
vertex = orgtrans0(vertex);
btScalar distance = vertex.dot(plane) - plane[3] - margin;
if(distance<0.0)//add contact
{
if(swapped)
{
addContactPoint(body1, body0,
vertex,
-plane,
distance);
}
else
{
addContactPoint(body0, body1,
vertex,
plane,
distance);
}
}
}
shape0->unlockChildShapes();
}
class btGImpactTriangleCallback: public btTriangleCallback
{
public:
btGImpactCollisionAlgorithm * algorithm;
btCollisionObject * body0;
btCollisionObject * body1;
btGImpactShapeInterface * gimpactshape0;
bool swapped;
btScalar margin;
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
btTriangleShapeEx tri1(triangle[0],triangle[1],triangle[2]);
tri1.setMargin(margin);
if(swapped)
{
algorithm->setPart0(partId);
algorithm->setFace0(triangleIndex);
}
else
{
algorithm->setPart1(partId);
algorithm->setFace1(triangleIndex);
}
algorithm->gimpact_vs_shape(
body0,body1,gimpactshape0,&tri1,swapped);
}
};
void btGImpactCollisionAlgorithm::gimpact_vs_concave(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactShapeInterface * shape0,
btConcaveShape * shape1,bool swapped)
{
//create the callback
btGImpactTriangleCallback tricallback;
tricallback.algorithm = this;
tricallback.body0 = body0;
tricallback.body1 = body1;
tricallback.gimpactshape0 = shape0;
tricallback.swapped = swapped;
tricallback.margin = shape1->getMargin();
//getting the trimesh AABB
btTransform gimpactInConcaveSpace;
gimpactInConcaveSpace = body1->getWorldTransform().inverse() * body0->getWorldTransform();
btVector3 minAABB,maxAABB;
shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB);
shape1->processAllTriangles(&tricallback,minAABB,maxAABB);
}
void btGImpactCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
clearCache();
m_resultOut = resultOut;
m_dispatchInfo = &dispatchInfo;
btGImpactShapeInterface * gimpactshape0;
btGImpactShapeInterface * gimpactshape1;
if (body0->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE)
{
gimpactshape0 = static_cast<btGImpactShapeInterface *>(body0->getCollisionShape());
if( body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
{
gimpactshape1 = static_cast<btGImpactShapeInterface *>(body1->getCollisionShape());
gimpact_vs_gimpact(body0,body1,gimpactshape0,gimpactshape1);
}
else
{
gimpact_vs_shape(body0,body1,gimpactshape0,body1->getCollisionShape(),false);
}
}
else if (body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
{
gimpactshape1 = static_cast<btGImpactShapeInterface *>(body1->getCollisionShape());
gimpact_vs_shape(body1,body0,gimpactshape1,body0->getCollisionShape(),true);
}
}
btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
return 1.f;
}
///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
btGImpactCollisionAlgorithm::CreateFunc g_gimpact_cf;
//! Use this function for register the algorithm externally
void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher * dispatcher)
{
int i;
for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
{
dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&g_gimpact_cf);
}
for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
{
dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&g_gimpact_cf);
}
}

View File

@@ -0,0 +1,306 @@
/*! \file btGImpactShape.h
\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BVH_CONCAVE_COLLISION_ALGORITHM_H
#define BVH_CONCAVE_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
class btDispatcher;
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "btGImpactShape.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
#include "LinearMath/btIDebugDraw.h"
//! Collision Algorithm for GImpact Shapes
/*!
For register this algorithm in Bullet, proceed as following:
\code
btCollisionDispatcher * dispatcher = static_cast<btCollisionDispatcher *>(m_dynamicsWorld ->getDispatcher());
btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
\endcode
*/
class btGImpactCollisionAlgorithm : public btCollisionAlgorithm
{
protected:
btCollisionAlgorithm * m_convex_algorithm;
btPersistentManifold * m_manifoldPtr;
btManifoldResult* m_resultOut;
const btDispatcherInfo * m_dispatchInfo;
int m_triface0;
int m_part0;
int m_triface1;
int m_part1;
//! Creates a new contact point
SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(btCollisionObject* body0,btCollisionObject* body1)
{
m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
return m_manifoldPtr;
}
SIMD_FORCE_INLINE void destroyConvexAlgorithm()
{
if(m_convex_algorithm)
{
m_convex_algorithm->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm( m_convex_algorithm);
m_convex_algorithm = NULL;
}
}
SIMD_FORCE_INLINE void destroyContactManifolds()
{
if(m_manifoldPtr == NULL) return;
m_dispatcher->releaseManifold(m_manifoldPtr);
m_manifoldPtr = NULL;
}
SIMD_FORCE_INLINE void clearCache()
{
destroyContactManifolds();
destroyConvexAlgorithm();
m_triface0 = -1;
m_part0 = -1;
m_triface1 = -1;
m_part1 = -1;
}
SIMD_FORCE_INLINE btPersistentManifold* getLastManifold()
{
return m_manifoldPtr;
}
// Call before process collision
SIMD_FORCE_INLINE void checkManifold(btCollisionObject* body0,btCollisionObject* body1)
{
if(getLastManifold() == 0)
{
newContactManifold(body0,body1);
}
m_resultOut->setPersistentManifold(getLastManifold());
}
// Call before process collision
SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
{
checkManifold(body0,body1);
btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm(
body0,body1,getLastManifold());
return convex_algorithm ;
}
// Call before process collision
SIMD_FORCE_INLINE void checkConvexAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
{
if(m_convex_algorithm) return;
m_convex_algorithm = newAlgorithm(body0,body1);
}
void addContactPoint(btCollisionObject * body0,
btCollisionObject * body1,
const btVector3 & point,
const btVector3 & normal,
btScalar distance);
//! Collision routines
//!@{
void collide_gjk_triangles(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0,
btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count);
void collide_sat_triangles(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0,
btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count);
void shape_vs_shape_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btCollisionShape * shape0,
btCollisionShape * shape1);
void convex_vs_convex_collision(btCollisionObject * body0,
btCollisionObject * body1,
btCollisionShape * shape0,
btCollisionShape * shape1);
void gimpact_vs_gimpact_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
btGImpactShapeInterface * shape0,
btGImpactShapeInterface * shape1,btPairSet & pairset);
void gimpact_vs_shape_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
btGImpactShapeInterface * shape0,
btCollisionShape * shape1,
btAlignedObjectArray<int> & collided_primitives);
void gimpacttrimeshpart_vs_plane_collision(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactMeshShapePart * shape0,
btStaticPlaneShape * shape1,bool swapped);
public:
btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
virtual ~btGImpactCollisionAlgorithm();
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr)
manifoldArray.push_back(m_manifoldPtr);
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm));
return new(mem) btGImpactCollisionAlgorithm(ci,body0,body1);
}
};
//! Use this function for register the algorithm externally
static void registerAlgorithm(btCollisionDispatcher * dispatcher);
//! Gets the average time in miliseconds of tree collisions
static float getAverageTreeCollisionTime();
//! Gets the average time in miliseconds of triangle collisions
static float getAverageTriangleCollisionTime();
//! Collides two gimpact shapes
/*!
\pre shape0 and shape1 couldn't be btGImpactMeshShape objects
*/
void gimpact_vs_gimpact(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactShapeInterface * shape0,
btGImpactShapeInterface * shape1);
void gimpact_vs_shape(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactShapeInterface * shape0,
btCollisionShape * shape1,bool swapped);
void gimpact_vs_compoundshape(btCollisionObject * body0,
btCollisionObject * body1,
btGImpactShapeInterface * shape0,
btCompoundShape * shape1,bool swapped);
void gimpact_vs_concave(
btCollisionObject * body0,
btCollisionObject * body1,
btGImpactShapeInterface * shape0,
btConcaveShape * shape1,bool swapped);
/// Accessor/Mutator pairs for Part and triangleID
void setFace0(int value)
{
m_triface0 = value;
}
int getFace0()
{
return m_triface0;
}
void setFace1(int value)
{
m_triface1 = value;
}
int getFace1()
{
return m_triface1;
}
void setPart0(int value)
{
m_part0 = value;
}
int getPart0()
{
return m_part0;
}
void setPart1(int value)
{
m_part1 = value;
}
int getPart1()
{
return m_part1;
}
};
//algorithm details
//#define BULLET_TRIANGLE_COLLISION 1
#define GIMPACT_VS_PLANE_COLLISION 1
#endif //BVH_CONCAVE_COLLISION_ALGORITHM_H

View File

@@ -0,0 +1,60 @@
/*! \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) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef GIMPACT_MASS_UTIL_H
#define GIMPACT_MASS_UTIL_H
#include "LinearMath/btTransform.h"
SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed(
const btVector3 & source_inertia, const btVector3 & added_inertia, const btTransform & transform)
{
btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose();
btScalar x2 = transform.getOrigin()[0];
x2*= x2;
btScalar y2 = transform.getOrigin()[1];
y2*= y2;
btScalar z2 = transform.getOrigin()[2];
z2*= z2;
btScalar ix = rotatedTensor[0][0]*(y2+z2);
btScalar iy = rotatedTensor[1][1]*(x2+z2);
btScalar iz = rotatedTensor[2][2]*(x2+y2);
return btVector3(source_inertia[0]+ix,source_inertia[1]+iy,source_inertia[2] + iz);
}
SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3 & point, btScalar mass)
{
btScalar x2 = point[0]*point[0];
btScalar y2 = point[1]*point[1];
btScalar z2 = point[2]*point[2];
return btVector3(mass*(y2+z2),mass*(x2+z2),mass*(x2+y2));
}
#endif //GIMPACT_MESH_SHAPE_H

View File

@@ -0,0 +1,529 @@
/*! \file gim_box_set.h
\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGImpactQuantizedBvh.h"
#include "LinearMath/btQuickprof.h"
#ifdef TRI_COLLISION_PROFILING
btClock g_q_tree_clock;
float g_q_accum_tree_collision_time = 0;
int g_q_count_traversing = 0;
void bt_begin_gim02_q_tree_time()
{
g_q_tree_clock.reset();
}
void bt_end_gim02_q_tree_time()
{
g_q_accum_tree_collision_time += g_q_tree_clock.getTimeMicroseconds();
g_q_count_traversing++;
}
//! Gets the average time in miliseconds of tree collisions
float btGImpactQuantizedBvh::getAverageTreeCollisionTime()
{
if(g_q_count_traversing == 0) return 0;
float avgtime = g_q_accum_tree_collision_time;
avgtime /= (float)g_q_count_traversing;
g_q_accum_tree_collision_time = 0;
g_q_count_traversing = 0;
return avgtime;
// float avgtime = g_q_count_traversing;
// g_q_count_traversing = 0;
// return avgtime;
}
#endif //TRI_COLLISION_PROFILING
/////////////////////// btQuantizedBvhTree /////////////////////////////////
void btQuantizedBvhTree::calc_quantization(
BT_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin)
{
//calc globa box
btAABB global_bound;
global_bound.invalidate();
for (int i=0;i<primitive_boxes.size() ;i++ )
{
global_bound.merge(primitive_boxes[i].m_bound);
}
bt_calc_quantization_parameters(
m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization,global_bound.m_min,global_bound.m_max,boundMargin);
}
int btQuantizedBvhTree::_calc_splitting_axis(
BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
{
int i;
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
int numIndices = endIndex-startIndex;
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
btVector3 diff2 = center-means;
diff2 = diff2 * diff2;
variance += diff2;
}
variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
return variance.maxAxis();
}
int btQuantizedBvhTree::_sort_and_calc_splitting_index(
BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex,
int endIndex, int splitAxis)
{
int i;
int splitIndex =startIndex;
int numIndices = endIndex - startIndex;
// average of centers
btScalar splitValue = 0.0f;
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
splitValue = means[splitAxis];
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
if (center[splitAxis] > splitValue)
{
//swap
primitive_boxes.swap(i,splitIndex);
//swapLeafNodes(i,splitIndex);
splitIndex++;
}
}
//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
//otherwise the tree-building might fail due to stack-overflows in certain cases.
//unbalanced1 is unsafe: it can cause stack overflows
//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
//unbalanced2 should work too: always use center (perfect balanced trees)
//bool unbalanced2 = true;
//this should be safe too:
int rangeBalancedIndices = numIndices/3;
bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
if (unbalanced)
{
splitIndex = startIndex+ (numIndices>>1);
}
bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
btAssert(!unbal);
return splitIndex;
}
void btQuantizedBvhTree::_build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
{
int curIndex = m_num_nodes;
m_num_nodes++;
btAssert((endIndex-startIndex)>0);
if ((endIndex-startIndex)==1)
{
//We have a leaf node
setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
return;
}
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
//split axis
int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
splitIndex = _sort_and_calc_splitting_index(
primitive_boxes,startIndex,endIndex,
splitIndex//split axis
);
//calc this node bounding box
btAABB node_bound;
node_bound.invalidate();
for (int i=startIndex;i<endIndex;i++)
{
node_bound.merge(primitive_boxes[i].m_bound);
}
setNodeBound(curIndex,node_bound);
//build left branch
_build_sub_tree(primitive_boxes, startIndex, splitIndex );
//build right branch
_build_sub_tree(primitive_boxes, splitIndex ,endIndex);
m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
}
//! stackless build tree
void btQuantizedBvhTree::build_tree(
BT_BVH_DATA_ARRAY & primitive_boxes)
{
calc_quantization(primitive_boxes);
// initialize node count to 0
m_num_nodes = 0;
// allocate nodes
m_node_array.resize(primitive_boxes.size()*2);
_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
}
////////////////////////////////////class btGImpactQuantizedBvh
void btGImpactQuantizedBvh::refit()
{
int nodecount = getNodeCount();
while(nodecount--)
{
if(isLeafNode(nodecount))
{
btAABB leafbox;
m_primitive_manager->get_primitive_box(getNodeData(nodecount),leafbox);
setNodeBound(nodecount,leafbox);
}
else
{
//const BT_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
//get left bound
btAABB bound;
bound.invalidate();
btAABB temp_box;
int child_node = getLeftNode(nodecount);
if(child_node)
{
getNodeBound(child_node,temp_box);
bound.merge(temp_box);
}
child_node = getRightNode(nodecount);
if(child_node)
{
getNodeBound(child_node,temp_box);
bound.merge(temp_box);
}
setNodeBound(nodecount,bound);
}
}
}
//! this rebuild the entire set
void btGImpactQuantizedBvh::buildSet()
{
//obtain primitive boxes
BT_BVH_DATA_ARRAY primitive_boxes;
primitive_boxes.resize(m_primitive_manager->get_primitive_count());
for (int i = 0;i<primitive_boxes.size() ;i++ )
{
m_primitive_manager->get_primitive_box(i,primitive_boxes[i].m_bound);
primitive_boxes[i].m_data = i;
}
m_box_tree.build_tree(primitive_boxes);
}
//! returns the indices of the primitives in the m_primitive_manager
bool btGImpactQuantizedBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
//quantize box
unsigned short quantizedMin[3];
unsigned short quantizedMax[3];
m_box_tree.quantizePoint(quantizedMin,box.m_min);
m_box_tree.quantizePoint(quantizedMax,box.m_max);
while (curIndex < numNodes)
{
//catch bugs in tree data
bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin,quantizedMax);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData(curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getEscapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
//! returns the indices of the primitives in the m_primitive_manager
bool btGImpactQuantizedBvh::rayQuery(
const btVector3 & ray_dir,const btVector3 & ray_origin ,
btAlignedObjectArray<int> & collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
while (curIndex < numNodes)
{
btAABB bound;
getNodeBound(curIndex,bound);
//catch bugs in tree data
bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData( curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getEscapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
SIMD_FORCE_INLINE bool _quantized_node_collision(
btGImpactQuantizedBvh * boxset0, btGImpactQuantizedBvh * boxset1,
const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
int node0 ,int node1, bool complete_primitive_tests)
{
btAABB box0;
boxset0->getNodeBound(node0,box0);
btAABB box1;
boxset1->getNodeBound(node1,box1);
return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests );
// box1.appy_transform_trans_cache(trans_cache_1to0);
// return box0.has_collision(box1);
}
//stackless recursive collision routine
static void _find_quantized_collision_pairs_recursive(
btGImpactQuantizedBvh * boxset0, btGImpactQuantizedBvh * boxset1,
btPairSet * collision_pairs,
const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
int node0, int node1, bool complete_primitive_tests)
{
if( _quantized_node_collision(
boxset0,boxset1,trans_cache_1to0,
node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes
if(boxset0->isLeafNode(node0))
{
if(boxset1->isLeafNode(node1))
{
// collision result
collision_pairs->push_pair(
boxset0->getNodeData(node0),boxset1->getNodeData(node1));
return;
}
else
{
//collide left recursive
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
node0,boxset1->getLeftNode(node1),false);
//collide right recursive
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
node0,boxset1->getRightNode(node1),false);
}
}
else
{
if(boxset1->isLeafNode(node1))
{
//collide left recursive
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),node1,false);
//collide right recursive
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),node1,false);
}
else
{
//collide left0 left1
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false);
//collide left0 right1
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false);
//collide right0 left1
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false);
//collide right0 right1
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),boxset1->getRightNode(node1),false);
}// else if node1 is not a leaf
}// else if node0 is not a leaf
}
void btGImpactQuantizedBvh::find_collision(btGImpactQuantizedBvh * boxset0, const btTransform & trans0,
btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
btPairSet & collision_pairs)
{
if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return;
BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
trans_cache_1to0.calc_from_homogenic(trans0,trans1);
#ifdef TRI_COLLISION_PROFILING
bt_begin_gim02_q_tree_time();
#endif //TRI_COLLISION_PROFILING
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
&collision_pairs,trans_cache_1to0,0,0,true);
#ifdef TRI_COLLISION_PROFILING
bt_end_gim02_q_tree_time();
#endif //TRI_COLLISION_PROFILING
}

View File

@@ -0,0 +1,379 @@
#ifndef GIM_QUANTIZED_SET_H_INCLUDED
#define GIM_QUANTIZED_SET_H_INCLUDED
/*! \file btGImpactQuantizedBvh.h
\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGImpactBvh.h"
#include "btQuantization.h"
/*! \defgroup BOX_TREES
*/
//! @{
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE
{
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes
int m_escapeIndexOrDataIndex;
BT_QUANTIZED_BVH_NODE()
{
m_escapeIndexOrDataIndex = 0;
}
SIMD_FORCE_INLINE bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrDataIndex>=0);
}
SIMD_FORCE_INLINE int getEscapeIndex() const
{
//btAssert(m_escapeIndexOrDataIndex < 0);
return -m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setEscapeIndex(int index)
{
m_escapeIndexOrDataIndex = -index;
}
SIMD_FORCE_INLINE int getDataIndex() const
{
//btAssert(m_escapeIndexOrDataIndex >= 0);
return m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setDataIndex(int index)
{
m_escapeIndexOrDataIndex = index;
}
SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
unsigned short * quantizedMin,unsigned short * quantizedMax) const
{
if(m_quantizedAabbMin[0] > quantizedMax[0] ||
m_quantizedAabbMax[0] < quantizedMin[0] ||
m_quantizedAabbMin[1] > quantizedMax[1] ||
m_quantizedAabbMax[1] < quantizedMin[1] ||
m_quantizedAabbMin[2] > quantizedMax[2] ||
m_quantizedAabbMax[2] < quantizedMin[2])
{
return false;
}
return true;
}
};
class BT_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE>
{
};
//! Basic Box tree structure
class btQuantizedBvhTree
{
protected:
int m_num_nodes;
BT_QUANTIZED_BVH_NODE_ARRAY m_node_array;
btAABB m_global_bound;
btVector3 m_bvhQuantization;
protected:
void calc_quantization(BT_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) );
int _sort_and_calc_splitting_index(
BT_BVH_DATA_ARRAY & primitive_boxes,
int startIndex, int endIndex, int splitAxis);
int _calc_splitting_axis(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
void _build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
public:
btQuantizedBvhTree()
{
m_num_nodes = 0;
}
//! prototype functions for box tree management
//!@{
void build_tree(BT_BVH_DATA_ARRAY & primitive_boxes);
SIMD_FORCE_INLINE void quantizePoint(
unsigned short * quantizedpoint, const btVector3 & point) const
{
bt_quantize_clamp(quantizedpoint,point,m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization);
}
SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
int node_index,
unsigned short * quantizedMin,unsigned short * quantizedMax) const
{
return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin,quantizedMax);
}
SIMD_FORCE_INLINE void clearNodes()
{
m_node_array.clear();
m_num_nodes = 0;
}
//! node count
SIMD_FORCE_INLINE int getNodeCount() const
{
return m_num_nodes;
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
{
return m_node_array[nodeindex].isLeafNode();
}
SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
{
return m_node_array[nodeindex].getDataIndex();
}
SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
{
bound.m_min = bt_unquantize(
m_node_array[nodeindex].m_quantizedAabbMin,
m_global_bound.m_min,m_bvhQuantization);
bound.m_max = bt_unquantize(
m_node_array[nodeindex].m_quantizedAabbMax,
m_global_bound.m_min,m_bvhQuantization);
}
SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
{
bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMin,
bound.m_min,
m_global_bound.m_min,
m_global_bound.m_max,
m_bvhQuantization);
bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMax,
bound.m_max,
m_global_bound.m_min,
m_global_bound.m_max,
m_bvhQuantization);
}
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
return nodeindex+1;
}
SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
{
if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
}
SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
{
return m_node_array[nodeindex].getEscapeIndex();
}
SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const
{
return &m_node_array[index];
}
//!@}
};
//! Structure for containing Boxes
/*!
This class offers an structure for managing a box tree of primitives.
Requires a Primitive prototype (like btPrimitiveManagerBase )
*/
class btGImpactQuantizedBvh
{
protected:
btQuantizedBvhTree m_box_tree;
btPrimitiveManagerBase * m_primitive_manager;
protected:
//stackless refit
void refit();
public:
//! this constructor doesn't build the tree. you must call buildSet
btGImpactQuantizedBvh()
{
m_primitive_manager = NULL;
}
//! this constructor doesn't build the tree. you must call buildSet
btGImpactQuantizedBvh(btPrimitiveManagerBase * primitive_manager)
{
m_primitive_manager = primitive_manager;
}
SIMD_FORCE_INLINE btAABB getGlobalBox() const
{
btAABB totalbox;
getNodeBound(0, totalbox);
return totalbox;
}
SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
{
m_primitive_manager = primitive_manager;
}
SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
{
return m_primitive_manager;
}
//! node manager prototype functions
///@{
//! this attemps to refit the box set.
SIMD_FORCE_INLINE void update()
{
refit();
}
//! this rebuild the entire set
void buildSet();
//! returns the indices of the primitives in the m_primitive_manager
bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
{
btAABB transbox=box;
transbox.appy_transform(transform);
return boxQuery(transbox,collided_results);
}
//! returns the indices of the primitives in the m_primitive_manager
bool rayQuery(
const btVector3 & ray_dir,const btVector3 & ray_origin ,
btAlignedObjectArray<int> & collided_results) const;
//! tells if this set has hierarcht
SIMD_FORCE_INLINE bool hasHierarchy() const
{
return true;
}
//! tells if this set is a trimesh
SIMD_FORCE_INLINE bool isTrimesh() const
{
return m_primitive_manager->is_trimesh();
}
//! node count
SIMD_FORCE_INLINE int getNodeCount() const
{
return m_box_tree.getNodeCount();
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
{
return m_box_tree.isLeafNode(nodeindex);
}
SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
{
return m_box_tree.getNodeData(nodeindex);
}
SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
{
m_box_tree.getNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
{
m_box_tree.setNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
return m_box_tree.getLeftNode(nodeindex);
}
SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
{
return m_box_tree.getRightNode(nodeindex);
}
SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
{
return m_box_tree.getEscapeNodeIndex(nodeindex);
}
SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
{
m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
}
SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const
{
return m_box_tree.get_node_pointer(index);
}
//! @}
static float getAverageTreeCollisionTime();
static void find_collision(btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
btGImpactQuantizedBvh * boxset2, const btTransform & trans2,
btPairSet & collision_pairs);
};
#endif // GIM_BOXPRUNING_H_INCLUDED

View File

@@ -0,0 +1,183 @@
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGImpactShape.h"
#include "btGImpactMassUtil.h"
#define CALC_EXACT_INERTIA 1
void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
lockChildShapes();
#ifdef CALC_EXACT_INERTIA
inertia.setValue(0.f,0.f,0.f);
int i = this->getNumChildShapes();
btScalar shapemass = mass/btScalar(i);
while(i--)
{
btVector3 temp_inertia;
m_childShapes[i]->calculateLocalInertia(shapemass,temp_inertia);
if(childrenHasTransform())
{
inertia = gim_inertia_add_transformed( inertia,temp_inertia,m_childTransforms[i]);
}
else
{
inertia = gim_inertia_add_transformed( inertia,temp_inertia,btTransform::getIdentity());
}
}
#else
// Calc box inertia
btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
#endif
unlockChildShapes();
}
void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
lockChildShapes();
#ifdef CALC_EXACT_INERTIA
inertia.setValue(0.f,0.f,0.f);
int i = this->getVertexCount();
btScalar pointmass = mass/btScalar(i);
while(i--)
{
btVector3 pointintertia;
this->getVertex(i,pointintertia);
pointintertia = gim_get_point_inertia(pointintertia,pointmass);
inertia+=pointintertia;
}
#else
// Calc box inertia
btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
#endif
unlockChildShapes();
}
void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
#ifdef CALC_EXACT_INERTIA
inertia.setValue(0.f,0.f,0.f);
int i = this->getMeshPartCount();
btScalar partmass = mass/btScalar(i);
while(i--)
{
btVector3 partinertia;
getMeshPart(i)->calculateLocalInertia(partmass,partinertia);
inertia+=partinertia;
}
#else
// Calc box inertia
btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
#endif
}
void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
{
}
void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
lockChildShapes();
btAABB box;
box.m_min = aabbMin;
box.m_max = aabbMax;
btAlignedObjectArray<int> collided;
m_box_set.boxQuery(box,collided);
if(collided.size()==0)
{
unlockChildShapes();
return;
}
int part = (int)getPart();
btPrimitiveTriangle triangle;
int i = collided.size();
while(i--)
{
this->getPrimitiveTriangle(collided[i],triangle);
callback->processTriangle(triangle.m_vertices,part,collided[i]);
}
unlockChildShapes();
}
void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
int i = m_mesh_parts.size();
while(i--)
{
m_mesh_parts[i]->processAllTriangles(callback,aabbMin,aabbMax);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,283 @@
/*! \file btGenericPoolAllocator.cpp
\author Francisco Le<4C>n N<>jera. email projectileman@yahoo.com
General purpose allocator class
*/
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGenericPoolAllocator.h"
/// *************** btGenericMemoryPool ******************///////////
size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements)
{
size_t ptr = BT_UINT_MAX;
if(m_free_nodes_count == 0) return BT_UINT_MAX;
// find an avaliable free node with the correct size
size_t revindex = m_free_nodes_count;
while(revindex-- && ptr == BT_UINT_MAX)
{
if(m_allocated_sizes[m_free_nodes[revindex]]>=num_elements)
{
ptr = revindex;
}
}
if(ptr == BT_UINT_MAX) return BT_UINT_MAX; // not found
revindex = ptr;
ptr = m_free_nodes[revindex];
// post: ptr contains the node index, and revindex the index in m_free_nodes
size_t finalsize = m_allocated_sizes[ptr];
finalsize -= num_elements;
m_allocated_sizes[ptr] = num_elements;
// post: finalsize>=0, m_allocated_sizes[ptr] has the requested size
if(finalsize>0) // preserve free node, there are some free memory
{
m_free_nodes[revindex] = ptr + num_elements;
m_allocated_sizes[ptr + num_elements] = finalsize;
}
else // delete free node
{
// swap with end
m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count-1];
m_free_nodes_count--;
}
return ptr;
}
size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements)
{
if(m_allocated_count+num_elements>m_max_element_count) return BT_UINT_MAX;
size_t ptr = m_allocated_count;
m_allocated_sizes[m_allocated_count] = num_elements;
m_allocated_count+=num_elements;
return ptr;
}
void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count)
{
m_allocated_count = 0;
m_free_nodes_count = 0;
m_element_size = element_size;
m_max_element_count = element_count;
m_pool = (unsigned char *) btAlignedAlloc(m_element_size*m_max_element_count,16);
m_free_nodes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
m_allocated_sizes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
for (size_t i = 0;i< m_max_element_count;i++ )
{
m_allocated_sizes[i] = 0;
}
}
void btGenericMemoryPool::end_pool()
{
btAlignedFree(m_pool);
btAlignedFree(m_free_nodes);
btAlignedFree(m_allocated_sizes);
m_allocated_count = 0;
m_free_nodes_count = 0;
}
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
void * btGenericMemoryPool::allocate(size_t size_bytes)
{
size_t module = size_bytes%m_element_size;
size_t element_count = size_bytes/m_element_size;
if(module>0) element_count++;
size_t alloc_pos = allocate_from_free_nodes(element_count);
// a free node is found
if(alloc_pos != BT_UINT_MAX)
{
return get_element_data(alloc_pos);
}
// allocate directly on pool
alloc_pos = allocate_from_pool(element_count);
if(alloc_pos == BT_UINT_MAX) return NULL; // not space
return get_element_data(alloc_pos);
}
bool btGenericMemoryPool::freeMemory(void * pointer)
{
unsigned char * pointer_pos = (unsigned char *)pointer;
unsigned char * pool_pos = (unsigned char *)m_pool;
// calc offset
if(pointer_pos<pool_pos) return false;//other pool
size_t offset = size_t(pointer_pos - pool_pos);
if(offset>=get_pool_capacity()) return false;// far away
// find free position
m_free_nodes[m_free_nodes_count] = offset/m_element_size;
m_free_nodes_count++;
return true;
}
/// *******************! btGenericPoolAllocator *******************!///
btGenericPoolAllocator::~btGenericPoolAllocator()
{
// destroy pools
size_t i;
for (i=0;i<m_pool_count;i++)
{
m_pools[i]->end_pool();
btAlignedFree(m_pools[i]);
}
}
// creates a pool
btGenericMemoryPool * btGenericPoolAllocator::push_new_pool()
{
if(m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL;
btGenericMemoryPool * newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool),16);
m_pools[m_pool_count] = newptr;
m_pools[m_pool_count]->init_pool(m_pool_element_size,m_pool_element_count);
m_pool_count++;
return newptr;
}
void * btGenericPoolAllocator::failback_alloc(size_t size_bytes)
{
btGenericMemoryPool * pool = NULL;
if(size_bytes<=get_pool_capacity())
{
pool = push_new_pool();
}
if(pool==NULL) // failback
{
return btAlignedAlloc(size_bytes,16);
}
return pool->allocate(size_bytes);
}
bool btGenericPoolAllocator::failback_free(void * pointer)
{
btAlignedFree(pointer);
return true;
}
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
void * btGenericPoolAllocator::allocate(size_t size_bytes)
{
void * ptr = NULL;
size_t i = 0;
while(i<m_pool_count && ptr == NULL)
{
ptr = m_pools[i]->allocate(size_bytes);
++i;
}
if(ptr) return ptr;
return failback_alloc(size_bytes);
}
bool btGenericPoolAllocator::freeMemory(void * pointer)
{
bool result = false;
size_t i = 0;
while(i<m_pool_count && result == false)
{
result = m_pools[i]->freeMemory(pointer);
++i;
}
if(result) return true;
return failback_free(pointer);
}
/// ************** STANDARD ALLOCATOR ***************************///
#define BT_DEFAULT_POOL_SIZE 32768
#define BT_DEFAULT_POOL_ELEMENT_SIZE 8
// main allocator
class BT_STANDARD_ALLOCATOR: public btGenericPoolAllocator
{
public:
BT_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE)
{
}
};
// global allocator
BT_STANDARD_ALLOCATOR g_main_allocator;
void * btPoolAlloc(size_t size)
{
return g_main_allocator.allocate(size);
}
void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize)
{
void * newptr = btPoolAlloc(newsize);
size_t copysize = oldsize<newsize?oldsize:newsize;
memcpy(newptr,ptr,copysize);
btPoolFree(ptr);
return newptr;
}
void btPoolFree(void *ptr)
{
g_main_allocator.freeMemory(ptr);
}

View File

@@ -0,0 +1,168 @@
/*! \file btGenericPoolAllocator.h
\author Francisco Le<4C>n N<>jera. email projectileman@yahoo.com
General purpose allocator class
*/
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_GENERIC_POOL_ALLOCATOR_H
#define BT_GENERIC_POOL_ALLOCATOR_H
#include <limits.h>
#include <stdio.h>
#include <memory.h>
#include "LinearMath/btAlignedAllocator.h"
#define BT_UINT_MAX UINT_MAX
#define BT_DEFAULT_MAX_POOLS 16
//! Generic Pool class
class btGenericMemoryPool
{
public:
unsigned char * m_pool; //[m_element_size*m_max_element_count];
size_t * m_free_nodes; //[m_max_element_count];//! free nodes
size_t * m_allocated_sizes;//[m_max_element_count];//! Number of elements allocated per node
size_t m_allocated_count;
size_t m_free_nodes_count;
protected:
size_t m_element_size;
size_t m_max_element_count;
size_t allocate_from_free_nodes(size_t num_elements);
size_t allocate_from_pool(size_t num_elements);
public:
void init_pool(size_t element_size, size_t element_count);
void end_pool();
btGenericMemoryPool(size_t element_size, size_t element_count)
{
init_pool(element_size, element_count);
}
~btGenericMemoryPool()
{
end_pool();
}
inline size_t get_pool_capacity()
{
return m_element_size*m_max_element_count;
}
inline size_t gem_element_size()
{
return m_element_size;
}
inline size_t get_max_element_count()
{
return m_max_element_count;
}
inline size_t get_allocated_count()
{
return m_allocated_count;
}
inline size_t get_free_positions_count()
{
return m_free_nodes_count;
}
inline void * get_element_data(size_t element_index)
{
return &m_pool[element_index*m_element_size];
}
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
void * allocate(size_t size_bytes);
bool freeMemory(void * pointer);
};
//! Generic Allocator with pools
/*!
General purpose Allocator which can create Memory Pools dynamiacally as needed.
*/
class btGenericPoolAllocator
{
protected:
size_t m_pool_element_size;
size_t m_pool_element_count;
public:
btGenericMemoryPool * m_pools[BT_DEFAULT_MAX_POOLS];
size_t m_pool_count;
inline size_t get_pool_capacity()
{
return m_pool_element_size*m_pool_element_count;
}
protected:
// creates a pool
btGenericMemoryPool * push_new_pool();
void * failback_alloc(size_t size_bytes);
bool failback_free(void * pointer);
public:
btGenericPoolAllocator(size_t pool_element_size, size_t pool_element_count)
{
m_pool_count = 0;
m_pool_element_size = pool_element_size;
m_pool_element_count = pool_element_count;
}
virtual ~btGenericPoolAllocator();
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
void * allocate(size_t size_bytes);
bool freeMemory(void * pointer);
};
/*! \defgroup POOL_MEMORY_FUNCTIONS
standar managed Memory functions. Memory pools are used.
*/
//! @{
void * btPoolAlloc(size_t size);
void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize);
void btPoolFree(void *ptr);
//! @}
#endif

View File

@@ -0,0 +1,216 @@
#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
/*! \file btGeometryOperations.h
*\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btBoxCollision.h"
/*! \defgroup GEOMETRIC_OPERATIONS
*/
//! @{
#define PLANEDIREPSILON 0.0000001f
#define PARALELENORMALS 0.000001f
#define BT_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
/// Calc a plane from a triangle edge an a normal. plane is a vec4f
SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 & e1,const btVector3 & e2, const btVector3 & normal,btVector4 & plane)
{
btVector3 planenormal = (e2-e1).cross(normal);
planenormal.normalize();
plane.setValue(planenormal[0],planenormal[1],planenormal[2],e2.dot(planenormal));
}
//***************** SEGMENT and LINE FUNCTIONS **********************************///
/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
*/
SIMD_FORCE_INLINE void bt_closest_point_on_segment(
btVector3 & cp, const btVector3 & v,
const btVector3 &e1,const btVector3 &e2)
{
btVector3 n = e2-e1;
cp = v - e1;
btScalar _scalar = cp.dot(n)/n.dot(n);
if(_scalar <0.0f)
{
cp = e1;
}
else if(_scalar >1.0f)
{
cp = e2;
}
else
{
cp = _scalar*n + e1;
}
}
//! line plane collision
/*!
*\return
-0 if the ray never intersects
-1 if the ray collides in front
-2 if the ray collides in back
*/
SIMD_FORCE_INLINE int bt_line_plane_collision(
const btVector4 & plane,
const btVector3 & vDir,
const btVector3 & vPoint,
btVector3 & pout,
btScalar &tparam,
btScalar tmin, btScalar tmax)
{
btScalar _dotdir = vDir.dot(plane);
if(btFabs(_dotdir)<PLANEDIREPSILON)
{
tparam = tmax;
return 0;
}
btScalar _dis = bt_distance_point_plane(plane,vPoint);
char returnvalue = _dis<0.0f? 2:1;
tparam = -_dis/_dotdir;
if(tparam<tmin)
{
returnvalue = 0;
tparam = tmin;
}
else if(tparam>tmax)
{
returnvalue = 0;
tparam = tmax;
}
pout = tparam*vDir + vPoint;
return returnvalue;
}
//! Find closest points on segments
SIMD_FORCE_INLINE void bt_segment_collision(
const btVector3 & vA1,
const btVector3 & vA2,
const btVector3 & vB1,
const btVector3 & vB2,
btVector3 & vPointA,
btVector3 & vPointB)
{
btVector3 AD = vA2 - vA1;
btVector3 BD = vB2 - vB1;
btVector3 N = AD.cross(BD);
btScalar tp = N.length2();
btVector4 _M;//plane
if(tp<SIMD_EPSILON)//ARE PARALELE
{
//project B over A
bool invert_b_order = false;
_M[0] = vB1.dot(AD);
_M[1] = vB2.dot(AD);
if(_M[0]>_M[1])
{
invert_b_order = true;
BT_SWAP_NUMBERS(_M[0],_M[1]);
}
_M[2] = vA1.dot(AD);
_M[3] = vA2.dot(AD);
//mid points
N[0] = (_M[0]+_M[1])*0.5f;
N[1] = (_M[2]+_M[3])*0.5f;
if(N[0]<N[1])
{
if(_M[1]<_M[2])
{
vPointB = invert_b_order?vB1:vB2;
vPointA = vA1;
}
else if(_M[1]<_M[3])
{
vPointB = invert_b_order?vB1:vB2;
bt_closest_point_on_segment(vPointA,vPointB,vA1,vA2);
}
else
{
vPointA = vA2;
bt_closest_point_on_segment(vPointB,vPointA,vB1,vB2);
}
}
else
{
if(_M[3]<_M[0])
{
vPointB = invert_b_order?vB2:vB1;
vPointA = vA2;
}
else if(_M[3]<_M[1])
{
vPointA = vA2;
bt_closest_point_on_segment(vPointB,vPointA,vB1,vB2);
}
else
{
vPointB = invert_b_order?vB1:vB2;
bt_closest_point_on_segment(vPointA,vPointB,vA1,vA2);
}
}
return;
}
N = N.cross(BD);
_M.setValue(N[0],N[1],N[2],vB1.dot(N));
// get point A as the plane collision point
bt_line_plane_collision(_M,AD,vA1,vPointA,tp,btScalar(0), btScalar(1));
/*Closest point on segment*/
vPointB = vPointA - vB1;
tp = vPointB.dot(BD);
tp/= BD.dot(BD);
tp = BT_CLAMP(tp,0.0f,1.0f);
vPointB = tp*BD + vB1;
}
//! @}
#endif // GIM_VECTOR_H_INCLUDED

View File

@@ -0,0 +1,92 @@
#ifndef BT_QUANTIZATION_H_INCLUDED
#define BT_QUANTIZATION_H_INCLUDED
/*! \file btQuantization.h
*\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btTransform.h"
/*! \defgroup GEOMETRIC_OPERATIONS
*/
//! @{
SIMD_FORCE_INLINE void bt_calc_quantization_parameters(
btVector3 & outMinBound,
btVector3 & outMaxBound,
btVector3 & bvhQuantization,
const btVector3& srcMinBound,const btVector3& srcMaxBound,
btScalar quantizationMargin)
{
//enlarge the AABB to avoid division by zero when initializing the quantization values
btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
outMinBound = srcMinBound - clampValue;
outMaxBound = srcMaxBound + clampValue;
btVector3 aabbSize = outMaxBound - outMinBound;
bvhQuantization = btVector3(btScalar(65535.0),
btScalar(65535.0),
btScalar(65535.0)) / aabbSize;
}
SIMD_FORCE_INLINE void bt_quantize_clamp(
unsigned short* out,
const btVector3& point,
const btVector3 & min_bound,
const btVector3 & max_bound,
const btVector3 & bvhQuantization)
{
btVector3 clampedPoint(point);
clampedPoint.setMax(min_bound);
clampedPoint.setMin(max_bound);
btVector3 v = (clampedPoint - min_bound) * bvhQuantization;
out[0] = (unsigned short)(v.getX()+0.5f);
out[1] = (unsigned short)(v.getY()+0.5f);
out[2] = (unsigned short)(v.getZ()+0.5f);
}
SIMD_FORCE_INLINE btVector3 bt_unquantize(
const unsigned short* vecIn,
const btVector3 & offset,
const btVector3 & bvhQuantization)
{
btVector3 vecOut;
vecOut.setValue(
(btScalar)(vecIn[0]) / (bvhQuantization.getX()),
(btScalar)(vecIn[1]) / (bvhQuantization.getY()),
(btScalar)(vecIn[2]) / (bvhQuantization.getZ()));
vecOut += offset;
return vecOut;
}
//! @}
#endif // GIM_VECTOR_H_INCLUDED

View File

@@ -0,0 +1,218 @@
/*! \file btGImpactTriangleShape.h
\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btTriangleShapeEx.h"
void BT_TRIANGLE_CONTACT::merge_points(const btVector4 & plane,
btScalar margin, const btVector3 * points, int point_count)
{
m_point_count = 0;
m_penetration_depth= -1000.0f;
int point_indices[MAX_TRI_CLIPPING];
int _k;
for ( _k=0;_k<point_count;_k++)
{
btScalar _dist = - bt_distance_point_plane(plane,points[_k]) + margin;
if (_dist>=0.0f)
{
if (_dist>m_penetration_depth)
{
m_penetration_depth = _dist;
point_indices[0] = _k;
m_point_count=1;
}
else if ((_dist+SIMD_EPSILON)>=m_penetration_depth)
{
point_indices[m_point_count] = _k;
m_point_count++;
}
}
}
for ( _k=0;_k<m_point_count;_k++)
{
m_points[_k] = points[point_indices[_k]];
}
}
///class btPrimitiveTriangle
bool btPrimitiveTriangle::overlap_test_conservative(const btPrimitiveTriangle& other)
{
btScalar total_margin = m_margin + other.m_margin;
// classify points on other triangle
btScalar dis0 = bt_distance_point_plane(m_plane,other.m_vertices[0]) - total_margin;
btScalar dis1 = bt_distance_point_plane(m_plane,other.m_vertices[1]) - total_margin;
btScalar dis2 = bt_distance_point_plane(m_plane,other.m_vertices[2]) - total_margin;
if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
// classify points on this triangle
dis0 = bt_distance_point_plane(other.m_plane,m_vertices[0]) - total_margin;
dis1 = bt_distance_point_plane(other.m_plane,m_vertices[1]) - total_margin;
dis2 = bt_distance_point_plane(other.m_plane,m_vertices[2]) - total_margin;
if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
return true;
}
int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points )
{
// edge 0
btVector3 temp_points[MAX_TRI_CLIPPING];
btVector4 edgeplane;
get_edge_plane(0,edgeplane);
int clipped_count = bt_plane_clip_triangle(
edgeplane,other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],temp_points);
if (clipped_count == 0) return 0;
btVector3 temp_points1[MAX_TRI_CLIPPING];
// edge 1
get_edge_plane(1,edgeplane);
clipped_count = bt_plane_clip_polygon(edgeplane,temp_points,clipped_count,temp_points1);
if (clipped_count == 0) return 0;
// edge 2
get_edge_plane(2,edgeplane);
clipped_count = bt_plane_clip_polygon(
edgeplane,temp_points1,clipped_count,clipped_points);
return clipped_count;
}
bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle & other, BT_TRIANGLE_CONTACT & contacts)
{
btScalar margin = m_margin + other.m_margin;
btVector3 clipped_points[MAX_TRI_CLIPPING];
int clipped_count;
//create planes
// plane v vs U points
BT_TRIANGLE_CONTACT contacts1;
contacts1.m_separating_normal = m_plane;
clipped_count = clip_triangle(other,clipped_points);
if (clipped_count == 0 )
{
return false;//Reject
}
//find most deep interval face1
contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
if (contacts1.m_point_count == 0) return false; // too far
//Normal pointing to this triangle
contacts1.m_separating_normal *= -1.f;
//Clip tri1 by tri2 edges
BT_TRIANGLE_CONTACT contacts2;
contacts2.m_separating_normal = other.m_plane;
clipped_count = other.clip_triangle(*this,clipped_points);
if (clipped_count == 0 )
{
return false;//Reject
}
//find most deep interval face1
contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
if (contacts2.m_point_count == 0) return false; // too far
////check most dir for contacts
if (contacts2.m_penetration_depth<contacts1.m_penetration_depth)
{
contacts.copy_from(contacts2);
}
else
{
contacts.copy_from(contacts1);
}
return true;
}
///class btTriangleShapeEx: public btTriangleShape
bool btTriangleShapeEx::overlap_test_conservative(const btTriangleShapeEx& other)
{
btScalar total_margin = getMargin() + other.getMargin();
btVector4 plane0;
buildTriPlane(plane0);
btVector4 plane1;
other.buildTriPlane(plane1);
// classify points on other triangle
btScalar dis0 = bt_distance_point_plane(plane0,other.m_vertices1[0]) - total_margin;
btScalar dis1 = bt_distance_point_plane(plane0,other.m_vertices1[1]) - total_margin;
btScalar dis2 = bt_distance_point_plane(plane0,other.m_vertices1[2]) - total_margin;
if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
// classify points on this triangle
dis0 = bt_distance_point_plane(plane1,m_vertices1[0]) - total_margin;
dis1 = bt_distance_point_plane(plane1,m_vertices1[1]) - total_margin;
dis2 = bt_distance_point_plane(plane1,m_vertices1[2]) - total_margin;
if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
return true;
}

View File

@@ -0,0 +1,180 @@
/*! \file btGImpactShape.h
\author Francisco Le<4C>n N<>jera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef TRIANGLE_SHAPE_EX_H
#define TRIANGLE_SHAPE_EX_H
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "btBoxCollision.h"
#include "btClipPolygon.h"
#include "btGeometryOperations.h"
#define MAX_TRI_CLIPPING 16
//! Structure for collision
struct BT_TRIANGLE_CONTACT
{
btScalar m_penetration_depth;
int m_point_count;
btVector4 m_separating_normal;
btVector3 m_points[MAX_TRI_CLIPPING];
SIMD_FORCE_INLINE void copy_from(const BT_TRIANGLE_CONTACT& other)
{
m_penetration_depth = other.m_penetration_depth;
m_separating_normal = other.m_separating_normal;
m_point_count = other.m_point_count;
int i = m_point_count;
while(i--)
{
m_points[i] = other.m_points[i];
}
}
BT_TRIANGLE_CONTACT()
{
}
BT_TRIANGLE_CONTACT(const BT_TRIANGLE_CONTACT& other)
{
copy_from(other);
}
//! classify points that are closer
void merge_points(const btVector4 & plane,
btScalar margin, const btVector3 * points, int point_count);
};
class btPrimitiveTriangle
{
public:
btVector3 m_vertices[3];
btVector4 m_plane;
btScalar m_margin;
btScalar m_dummy;
btPrimitiveTriangle():m_margin(0.01f)
{
}
SIMD_FORCE_INLINE void buildTriPlane()
{
btVector3 normal = (m_vertices[1]-m_vertices[0]).cross(m_vertices[2]-m_vertices[0]);
normal.normalize();
m_plane.setValue(normal[0],normal[1],normal[2],m_vertices[0].dot(normal));
}
//! Test if triangles could collide
bool overlap_test_conservative(const btPrimitiveTriangle& other);
//! Calcs the plane which is paralele to the edge and perpendicular to the triangle plane
/*!
\pre this triangle must have its plane calculated.
*/
SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4 &plane) const
{
const btVector3 & e0 = m_vertices[edge_index];
const btVector3 & e1 = m_vertices[(edge_index+1)%3];
bt_edge_plane(e0,e1,m_plane,plane);
}
void applyTransform(const btTransform& t)
{
m_vertices[0] = t(m_vertices[0]);
m_vertices[1] = t(m_vertices[1]);
m_vertices[2] = t(m_vertices[2]);
}
//! Clips the triangle against this
/*!
\pre clipped_points must have MAX_TRI_CLIPPING size, and this triangle must have its plane calculated.
\return the number of clipped points
*/
int clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points );
//! Find collision using the clipping method
/*!
\pre this triangle and other must have their triangles calculated
*/
bool find_triangle_collision_clip_method(btPrimitiveTriangle & other, BT_TRIANGLE_CONTACT & contacts);
};
//! Helper class for colliding Bullet Triangle Shapes
/*!
This class implements a better getAabb method than the previous btTriangleShape class
*/
class btTriangleShapeEx: public btTriangleShape
{
public:
btTriangleShapeEx():btTriangleShape(btVector3(0,0,0),btVector3(0,0,0),btVector3(0,0,0))
{
}
btTriangleShapeEx(const btVector3& p0,const btVector3& p1,const btVector3& p2): btTriangleShape(p0,p1,p2)
{
}
btTriangleShapeEx(const btTriangleShapeEx & other): btTriangleShape(other.m_vertices1[0],other.m_vertices1[1],other.m_vertices1[2])
{
}
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const
{
btVector3 tv0 = t(m_vertices1[0]);
btVector3 tv1 = t(m_vertices1[1]);
btVector3 tv2 = t(m_vertices1[2]);
btAABB trianglebox(tv0,tv1,tv2,m_collisionMargin);
aabbMin = trianglebox.m_min;
aabbMax = trianglebox.m_max;
}
void applyTransform(const btTransform& t)
{
m_vertices1[0] = t(m_vertices1[0]);
m_vertices1[1] = t(m_vertices1[1]);
m_vertices1[2] = t(m_vertices1[2]);
}
SIMD_FORCE_INLINE void buildTriPlane(btVector4 & plane) const
{
btVector3 normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]);
normal.normalize();
plane.setValue(normal[0],normal[1],normal[2],m_vertices1[0].dot(normal));
}
bool overlap_test_conservative(const btTriangleShapeEx& other);
};
#endif //TRIANGLE_MESH_SHAPE_H

View 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 "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

View 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 "gim_linear_math.h"
/*! \defgroup GEOMETRIC_OPERATIONS
*/
//! @{
#define PLANEDIREPSILON 0.0000001f
#define PARALELENORMALS 0.000001f
#define TRIANGLE_NORMAL(v1,v2,v3,n)\
{\
vec3f _dif1,_dif2;\
VEC_DIFF(_dif1,v2,v1);\
VEC_DIFF(_dif2,v3,v1);\
VEC_CROSS(n,_dif1,_dif2);\
VEC_NORMALIZE(n);\
}\
#define TRIANGLE_NORMAL_FAST(v1,v2,v3,n){\
vec3f _dif1,_dif2; \
VEC_DIFF(_dif1,v2,v1); \
VEC_DIFF(_dif2,v3,v1); \
VEC_CROSS(n,_dif1,_dif2); \
}\
/// plane is a vec4f
#define TRIANGLE_PLANE(v1,v2,v3,plane) {\
TRIANGLE_NORMAL(v1,v2,v3,plane);\
plane[3] = VEC_DOT(v1,plane);\
}\
/// plane is a vec4f
#define TRIANGLE_PLANE_FAST(v1,v2,v3,plane) {\
TRIANGLE_NORMAL_FAST(v1,v2,v3,plane);\
plane[3] = VEC_DOT(v1,plane);\
}\
/// Calc a plane from an edge an a normal. plane is a vec4f
#define EDGE_PLANE(e1,e2,n,plane) {\
vec3f _dif; \
VEC_DIFF(_dif,e2,e1); \
VEC_CROSS(plane,_dif,n); \
VEC_NORMALIZE(plane); \
plane[3] = VEC_DOT(e1,plane);\
}\
#define DISTANCE_PLANE_POINT(plane,point) (VEC_DOT(plane,point) - plane[3])
#define PROJECT_POINT_PLANE(point,plane,projected) {\
GREAL _dis;\
_dis = DISTANCE_PLANE_POINT(plane,point);\
VEC_SCALE(projected,-_dis,plane);\
VEC_SUM(projected,projected,point); \
}\
//! Verifies if a point is in the plane hull
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE bool POINT_IN_HULL(
const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count)
{
GREAL _dis;
for (GUINT _i = 0;_i< plane_count;++_i)
{
_dis = DISTANCE_PLANE_POINT(planes[_i],point);
if(_dis>0.0f) return false;
}
return true;
}
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT(
const CLASS_POINT& s1,
const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped)
{
GREAL _dis1,_dis2;
_dis1 = DISTANCE_PLANE_POINT(plane,s1);
VEC_DIFF(clipped,s2,s1);
_dis2 = VEC_DOT(clipped,plane);
VEC_SCALE(clipped,-_dis1/_dis2,clipped);
VEC_SUM(clipped,clipped,s1);
}
enum ePLANE_INTERSECTION_TYPE
{
G_BACK_PLANE = 0,
G_COLLIDE_PLANE,
G_FRONT_PLANE
};
enum eLINE_PLANE_INTERSECTION_TYPE
{
G_FRONT_PLANE_S1 = 0,
G_FRONT_PLANE_S2,
G_BACK_PLANE_S1,
G_BACK_PLANE_S2,
G_COLLIDE_PLANE_S1,
G_COLLIDE_PLANE_S2
};
//! Confirms if the plane intersect the edge or nor
/*!
intersection type must have the following values
<ul>
<li> 0 : Segment in front of plane, s1 closest
<li> 1 : Segment in front of plane, s2 closest
<li> 2 : Segment in back of plane, s1 closest
<li> 3 : Segment in back of plane, s2 closest
<li> 4 : Segment collides plane, s1 in back
<li> 5 : Segment collides plane, s2 in back
</ul>
*/
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2(
const CLASS_POINT& s1,
const CLASS_POINT &s2,
const CLASS_PLANE &plane,CLASS_POINT &clipped)
{
GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1);
GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2);
if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON)
{
if(_dis1<_dis2) return G_FRONT_PLANE_S1;
return G_FRONT_PLANE_S2;
}
else if(_dis1 <G_EPSILON && _dis2 <G_EPSILON)
{
if(_dis1>_dis2) return G_BACK_PLANE_S1;
return G_BACK_PLANE_S2;
}
VEC_DIFF(clipped,s2,s1);
_dis2 = VEC_DOT(clipped,plane);
VEC_SCALE(clipped,-_dis1/_dis2,clipped);
VEC_SUM(clipped,clipped,s1);
if(_dis1<_dis2) return G_COLLIDE_PLANE_S1;
return G_COLLIDE_PLANE_S2;
}
//! Confirms if the plane intersect the edge or not
/*!
clipped1 and clipped2 are the vertices behind the plane.
clipped1 is the closest
intersection_type must have the following values
<ul>
<li> 0 : Segment in front of plane, s1 closest
<li> 1 : Segment in front of plane, s2 closest
<li> 2 : Segment in back of plane, s1 closest
<li> 3 : Segment in back of plane, s2 closest
<li> 4 : Segment collides plane, s1 in back
<li> 5 : Segment collides plane, s2 in back
</ul>
*/
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
const CLASS_POINT& s1,
const CLASS_POINT &s2,
const CLASS_PLANE &plane,
CLASS_POINT &clipped1,CLASS_POINT &clipped2)
{
eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1);
switch(intersection_type)
{
case G_FRONT_PLANE_S1:
VEC_COPY(clipped1,s1);
VEC_COPY(clipped2,s2);
break;
case G_FRONT_PLANE_S2:
VEC_COPY(clipped1,s2);
VEC_COPY(clipped2,s1);
break;
case G_BACK_PLANE_S1:
VEC_COPY(clipped1,s1);
VEC_COPY(clipped2,s2);
break;
case G_BACK_PLANE_S2:
VEC_COPY(clipped1,s2);
VEC_COPY(clipped2,s1);
break;
case G_COLLIDE_PLANE_S1:
VEC_COPY(clipped2,s1);
break;
case G_COLLIDE_PLANE_S2:
VEC_COPY(clipped2,s2);
break;
}
return intersection_type;
}
//! Finds the 2 smallest cartesian coordinates of a plane normal
#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1)
//! Ray plane collision in one way
/*!
Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).<br/>
It uses the PLANEDIREPSILON constant.
*/
template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
const CLASS_PLANE & plane,
const CLASS_POINT & vDir,
const CLASS_POINT & vPoint,
CLASS_POINT & pout,T &tparam)
{
GREAL _dis,_dotdir;
_dotdir = VEC_DOT(plane,vDir);
if(_dotdir<PLANEDIREPSILON)
{
return false;
}
_dis = DISTANCE_PLANE_POINT(plane,vPoint);
tparam = -_dis/_dotdir;
VEC_SCALE(pout,tparam,vDir);
VEC_SUM(pout,vPoint,pout);
return true;
}
//! line collision
/*!
*\return
-0 if the ray never intersects
-1 if the ray collides in front
-2 if the ray collides in back
*/
template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
const CLASS_PLANE & plane,
const CLASS_POINT & vDir,
const CLASS_POINT & vPoint,
CLASS_POINT & pout,
T &tparam,
T tmin, T tmax)
{
GREAL _dis,_dotdir;
_dotdir = VEC_DOT(plane,vDir);
if(btFabs(_dotdir)<PLANEDIREPSILON)
{
tparam = tmax;
return 0;
}
_dis = DISTANCE_PLANE_POINT(plane,vPoint);
char returnvalue = _dis<0.0f?2:1;
tparam = -_dis/_dotdir;
if(tparam<tmin)
{
returnvalue = 0;
tparam = tmin;
}
else if(tparam>tmax)
{
returnvalue = 0;
tparam = tmax;
}
VEC_SCALE(pout,tparam,vDir);
VEC_SUM(pout,vPoint,pout);
return returnvalue;
}
/*! \brief Returns the Ray on which 2 planes intersect if they do.
Written by Rodrigo Hernandez on ODE convex collision
\param p1 Plane 1
\param p2 Plane 2
\param p Contains the origin of the ray upon returning if planes intersect
\param d Contains the direction of the ray upon returning if planes intersect
\return true if the planes intersect, 0 if paralell.
*/
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE bool INTERSECT_PLANES(
const CLASS_PLANE &p1,
const CLASS_PLANE &p2,
CLASS_POINT &p,
CLASS_POINT &d)
{
VEC_CROSS(d,p1,p2);
GREAL denom = VEC_DOT(d, d);
if(GIM_IS_ZERO(denom)) return false;
vec3f _n;
_n[0]=p1[3]*p2[0] - p2[3]*p1[0];
_n[1]=p1[3]*p2[1] - p2[3]*p1[1];
_n[2]=p1[3]*p2[2] - p2[3]*p1[2];
VEC_CROSS(p,_n,d);
p[0]/=denom;
p[1]/=denom;
p[2]/=denom;
return true;
}
//***************** SEGMENT and LINE FUNCTIONS **********************************///
/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
*/
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
CLASS_POINT & cp, const CLASS_POINT & v,
const CLASS_POINT &e1,const CLASS_POINT &e2)
{
vec3f _n;
VEC_DIFF(_n,e2,e1);
VEC_DIFF(cp,v,e1);
GREAL _scalar = VEC_DOT(cp, _n);
_scalar/= VEC_DOT(_n, _n);
if(_scalar <0.0f)
{
VEC_COPY(cp,e1);
}
else if(_scalar >1.0f)
{
VEC_COPY(cp,e2);
}
else
{
VEC_SCALE(cp,_scalar,_n);
VEC_SUM(cp,cp,e1);
}
}
/*! \brief Finds the line params where these lines intersect.
\param dir1 Direction of line 1
\param point1 Point of line 1
\param dir2 Direction of line 2
\param point2 Point of line 2
\param t1 Result Parameter for line 1
\param t2 Result Parameter for line 2
\param dointersect 0 if the lines won't intersect, else 1
*/
template<typename T,typename CLASS_POINT>
SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS(
const CLASS_POINT & dir1,
CLASS_POINT & point1,
const CLASS_POINT & dir2,
CLASS_POINT & point2,
T& t1,T& t2)
{
GREAL det;
GREAL e1e1 = VEC_DOT(dir1,dir1);
GREAL e1e2 = VEC_DOT(dir1,dir2);
GREAL e2e2 = VEC_DOT(dir2,dir2);
vec3f p1p2;
VEC_DIFF(p1p2,point1,point2);
GREAL p1p2e1 = VEC_DOT(p1p2,dir1);
GREAL p1p2e2 = VEC_DOT(p1p2,dir2);
det = e1e2*e1e2 - e1e1*e2e2;
if(GIM_IS_ZERO(det)) return false;
t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det;
t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det;
return true;
}
//! Find closest points on segments
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void SEGMENT_COLLISION(
const CLASS_POINT & vA1,
const CLASS_POINT & vA2,
const CLASS_POINT & vB1,
const CLASS_POINT & vB2,
CLASS_POINT & vPointA,
CLASS_POINT & vPointB)
{
CLASS_POINT _AD,_BD,_N;
vec4f _M;//plane
VEC_DIFF(_AD,vA2,vA1);
VEC_DIFF(_BD,vB2,vB1);
VEC_CROSS(_N,_AD,_BD);
GREAL _tp = VEC_DOT(_N,_N);
if(_tp<G_EPSILON)//ARE PARALELE
{
//project B over A
bool invert_b_order = false;
_M[0] = VEC_DOT(vB1,_AD);
_M[1] = VEC_DOT(vB2,_AD);
if(_M[0]>_M[1])
{
invert_b_order = true;
GIM_SWAP_NUMBERS(_M[0],_M[1]);
}
_M[2] = VEC_DOT(vA1,_AD);
_M[3] = VEC_DOT(vA2,_AD);
//mid points
_N[0] = (_M[0]+_M[1])*0.5f;
_N[1] = (_M[2]+_M[3])*0.5f;
if(_N[0]<_N[1])
{
if(_M[1]<_M[2])
{
vPointB = invert_b_order?vB1:vB2;
vPointA = vA1;
}
else if(_M[1]<_M[3])
{
vPointB = invert_b_order?vB1:vB2;
CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
}
else
{
vPointA = vA2;
CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
}
}
else
{
if(_M[3]<_M[0])
{
vPointB = invert_b_order?vB2:vB1;
vPointA = vA2;
}
else if(_M[3]<_M[1])
{
vPointA = vA2;
CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
}
else
{
vPointB = invert_b_order?vB1:vB2;
CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
}
}
return;
}
VEC_CROSS(_M,_N,_BD);
_M[3] = VEC_DOT(_M,vB1);
LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,btScalar(0), btScalar(1));
/*Closest point on segment*/
VEC_DIFF(vPointB,vPointA,vB1);
_tp = VEC_DOT(vPointB, _BD);
_tp/= VEC_DOT(_BD, _BD);
_tp = GIM_CLAMP(_tp,0.0f,1.0f);
VEC_SCALE(vPointB,_tp,_BD);
VEC_SUM(vPointB,vPointB,vB1);
}
//! Line box intersection in one dimension
/*!
*\param pos Position of the ray
*\param dir Projection of the Direction of the ray
*\param bmin Minimum bound of the box
*\param bmax Maximum bound of the box
*\param tfirst the minimum projection. Assign to 0 at first.
*\param tlast the maximum projection. Assign to INFINITY at first.
*\return true if there is an intersection.
*/
template<typename T>
SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast)
{
if(GIM_IS_ZERO(dir))
{
return !(pos < bmin || pos > bmax);
}
GREAL a0 = (bmin - pos) / dir;
GREAL a1 = (bmax - pos) / dir;
if(a0 > a1) GIM_SWAP_NUMBERS(a0, a1);
tfirst = GIM_MAX(a0, tfirst);
tlast = GIM_MIN(a1, tlast);
if (tlast < tfirst) return false;
return true;
}
//! Sorts 3 componets
template<typename T>
SIMD_FORCE_INLINE void SORT_3_INDICES(
const T * values,
GUINT * order_indices)
{
//get minimum
order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
//get second and third
GUINT i0 = (order_indices[0] + 1)%3;
GUINT i1 = (i0 + 1)%3;
if(values[i0] < values[i1])
{
order_indices[1] = i0;
order_indices[2] = i1;
}
else
{
order_indices[1] = i1;
order_indices[2] = i0;
}
}
//! @}
#endif // GIM_VECTOR_H_INCLUDED

View 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 "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

View 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 "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

View File

@@ -0,0 +1,182 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_box_set.h"
GUINT GIM_BOX_TREE::_calc_splitting_axis(
gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex)
{
GUINT i;
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
GUINT numIndices = endIndex-startIndex;
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
btVector3 diff2 = center-means;
diff2 = diff2 * diff2;
variance += diff2;
}
variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
return variance.maxAxis();
}
GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index(
gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex,
GUINT endIndex, GUINT splitAxis)
{
GUINT i;
GUINT splitIndex =startIndex;
GUINT numIndices = endIndex - startIndex;
// average of centers
btScalar splitValue = 0.0f;
for (i=startIndex;i<endIndex;i++)
{
splitValue+= 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
primitive_boxes[i].m_bound.m_min[splitAxis]);
}
splitValue /= (btScalar)numIndices;
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
for (i=startIndex;i<endIndex;i++)
{
btScalar center = 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
primitive_boxes[i].m_bound.m_min[splitAxis]);
if (center > splitValue)
{
//swap
primitive_boxes.swap(i,splitIndex);
splitIndex++;
}
}
//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
//otherwise the tree-building might fail due to stack-overflows in certain cases.
//unbalanced1 is unsafe: it can cause stack overflows
//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
//unbalanced2 should work too: always use center (perfect balanced trees)
//bool unbalanced2 = true;
//this should be safe too:
GUINT rangeBalancedIndices = numIndices/3;
bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
if (unbalanced)
{
splitIndex = startIndex+ (numIndices>>1);
}
bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
btAssert(!unbal);
return splitIndex;
}
void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex)
{
GUINT current_index = m_num_nodes++;
btAssert((endIndex-startIndex)>0);
if((endIndex-startIndex) == 1) //we got a leaf
{
m_node_array[current_index].m_left = 0;
m_node_array[current_index].m_right = 0;
m_node_array[current_index].m_escapeIndex = 0;
m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound;
m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data;
return;
}
//configure inner node
GUINT splitIndex;
//calc this node bounding box
m_node_array[current_index].m_bound.invalidate();
for (splitIndex=startIndex;splitIndex<endIndex;splitIndex++)
{
m_node_array[current_index].m_bound.merge(primitive_boxes[splitIndex].m_bound);
}
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
//split axis
splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
splitIndex = _sort_and_calc_splitting_index(
primitive_boxes,startIndex,endIndex,splitIndex);
//configure this inner node : the left node index
m_node_array[current_index].m_left = m_num_nodes;
//build left child tree
_build_sub_tree(primitive_boxes, startIndex, splitIndex );
//configure this inner node : the right node index
m_node_array[current_index].m_right = m_num_nodes;
//build right child tree
_build_sub_tree(primitive_boxes, splitIndex ,endIndex);
//configure this inner node : the escape index
m_node_array[current_index].m_escapeIndex = m_num_nodes - current_index;
}
//! stackless build tree
void GIM_BOX_TREE::build_tree(
gim_array<GIM_AABB_DATA> & primitive_boxes)
{
// initialize node count to 0
m_num_nodes = 0;
// allocate nodes
m_node_array.resize(primitive_boxes.size()*2);
_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
}

View 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 "gim_array.h"
#include "gim_radixsort.h"
#include "gim_box_collision.h"
#include "gim_tri_collision.h"
/*! \defgroup BOX_PRUNNING
*/
//! @{
//! Overlapping pair
struct GIM_PAIR
{
GUINT m_index1;
GUINT m_index2;
GIM_PAIR()
{}
GIM_PAIR(const GIM_PAIR & p)
{
m_index1 = p.m_index1;
m_index2 = p.m_index2;
}
GIM_PAIR(GUINT index1, GUINT index2)
{
m_index1 = index1;
m_index2 = index2;
}
};
//! A pairset array
class gim_pair_set: public gim_array<GIM_PAIR>
{
public:
gim_pair_set():gim_array<GIM_PAIR>(32)
{
}
inline void push_pair(GUINT index1,GUINT index2)
{
push_back(GIM_PAIR(index1,index2));
}
inline void push_pair_inv(GUINT index1,GUINT index2)
{
push_back(GIM_PAIR(index2,index1));
}
};
//! Prototype Base class for primitive classification
/*!
This class is a wrapper for primitive collections.
This tells relevant info for the Bounding Box set classes, which take care of space classification.
This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
*/
class GIM_PRIMITIVE_MANAGER_PROTOTYPE
{
public:
//! determines if this manager consist on only triangles, which special case will be optimized
virtual bool is_trimesh() = 0;
virtual GUINT get_primitive_count() = 0;
virtual void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) = 0;
virtual void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) = 0;
};
struct GIM_AABB_DATA
{
GIM_AABB m_bound;
GUINT m_data;
};
//! Node Structure for trees
struct GIM_BOX_TREE_NODE
{
GIM_AABB m_bound;
GUINT m_left;//!< Left subtree
GUINT m_right;//!< Right subtree
GUINT m_escapeIndex;//!< Scape index for traversing
GUINT m_data;//!< primitive index if apply
GIM_BOX_TREE_NODE()
{
m_left = 0;
m_right = 0;
m_escapeIndex = 0;
m_data = 0;
}
SIMD_FORCE_INLINE bool is_leaf_node() const
{
return (!m_left && !m_right);
}
};
//! Basic Box tree structure
class GIM_BOX_TREE
{
protected:
GUINT m_num_nodes;
gim_array<GIM_BOX_TREE_NODE> m_node_array;
protected:
GUINT _sort_and_calc_splitting_index(
gim_array<GIM_AABB_DATA> & primitive_boxes,
GUINT startIndex, GUINT endIndex, GUINT splitAxis);
GUINT _calc_splitting_axis(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex);
void _build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex);
public:
GIM_BOX_TREE()
{
m_num_nodes = 0;
}
//! prototype functions for box tree management
//!@{
void build_tree(gim_array<GIM_AABB_DATA> & primitive_boxes);
SIMD_FORCE_INLINE void clearNodes()
{
m_node_array.clear();
m_num_nodes = 0;
}
//! node count
SIMD_FORCE_INLINE GUINT getNodeCount() const
{
return m_num_nodes;
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
{
return m_node_array[nodeindex].is_leaf_node();
}
SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
{
return m_node_array[nodeindex].m_data;
}
SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
{
bound = m_node_array[nodeindex].m_bound;
}
SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
{
m_node_array[nodeindex].m_bound = bound;
}
SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
{
return m_node_array[nodeindex].m_left;
}
SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
{
return m_node_array[nodeindex].m_right;
}
SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
{
return m_node_array[nodeindex].m_escapeIndex;
}
//!@}
};
//! Generic Box Tree Template
/*!
This class offers an structure for managing a box tree of primitives.
Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and
a Box tree structure ( like GIM_BOX_TREE).
*/
template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE, typename _GIM_BOX_TREE_PROTOTYPE>
class GIM_BOX_TREE_TEMPLATE_SET
{
protected:
_GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager;
_GIM_BOX_TREE_PROTOTYPE m_box_tree;
protected:
//stackless refit
SIMD_FORCE_INLINE void refit()
{
GUINT nodecount = getNodeCount();
while(nodecount--)
{
if(isLeafNode(nodecount))
{
GIM_AABB leafbox;
m_primitive_manager.get_primitive_box(getNodeData(nodecount),leafbox);
setNodeBound(nodecount,leafbox);
}
else
{
//get left bound
GUINT childindex = getLeftNodeIndex(nodecount);
GIM_AABB bound;
getNodeBound(childindex,bound);
//get right bound
childindex = getRightNodeIndex(nodecount);
GIM_AABB bound2;
getNodeBound(childindex,bound2);
bound.merge(bound2);
setNodeBound(nodecount,bound);
}
}
}
public:
GIM_BOX_TREE_TEMPLATE_SET()
{
}
SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const
{
GIM_AABB totalbox;
getNodeBound(0, totalbox);
return totalbox;
}
SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & primitive_manager)
{
m_primitive_manager = primitive_manager;
}
const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() const
{
return m_primitive_manager;
}
_GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager()
{
return m_primitive_manager;
}
//! node manager prototype functions
///@{
//! this attemps to refit the box set.
SIMD_FORCE_INLINE void update()
{
refit();
}
//! this rebuild the entire set
SIMD_FORCE_INLINE void buildSet()
{
//obtain primitive boxes
gim_array<GIM_AABB_DATA> primitive_boxes;
primitive_boxes.resize(m_primitive_manager.get_primitive_count(),false);
for (GUINT i = 0;i<primitive_boxes.size() ;i++ )
{
m_primitive_manager.get_primitive_box(i,primitive_boxes[i].m_bound);
primitive_boxes[i].m_data = i;
}
m_box_tree.build_tree(primitive_boxes);
}
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool boxQuery(const GIM_AABB & box, gim_array<GUINT> & collided_results) const
{
GUINT curIndex = 0;
GUINT numNodes = getNodeCount();
while (curIndex < numNodes)
{
GIM_AABB bound;
getNodeBound(curIndex,bound);
//catch bugs in tree data
bool aabbOverlap = bound.has_collision(box);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData(curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getScapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB & box,
const btTransform & transform, gim_array<GUINT> & collided_results) const
{
GIM_AABB transbox=box;
transbox.appy_transform(transform);
return boxQuery(transbox,collided_results);
}
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool rayQuery(
const btVector3 & ray_dir,const btVector3 & ray_origin ,
gim_array<GUINT> & collided_results) const
{
GUINT curIndex = 0;
GUINT numNodes = getNodeCount();
while (curIndex < numNodes)
{
GIM_AABB bound;
getNodeBound(curIndex,bound);
//catch bugs in tree data
bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData( curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getScapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
//! tells if this set has hierarcht
SIMD_FORCE_INLINE bool hasHierarchy() const
{
return true;
}
//! tells if this set is a trimesh
SIMD_FORCE_INLINE bool isTrimesh() const
{
return m_primitive_manager.is_trimesh();
}
//! node count
SIMD_FORCE_INLINE GUINT getNodeCount() const
{
return m_box_tree.getNodeCount();
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
{
return m_box_tree.isLeafNode(nodeindex);
}
SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
{
return m_box_tree.getNodeData(nodeindex);
}
SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
{
m_box_tree.getNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
{
m_box_tree.setNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
{
return m_box_tree.getLeftNodeIndex(nodeindex);
}
SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
{
return m_box_tree.getRightNodeIndex(nodeindex);
}
SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
{
return m_box_tree.getScapeNodeIndex(nodeindex);
}
SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex,GIM_TRIANGLE & triangle) const
{
m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex),triangle);
}
//! @}
};
//! Class for Box Tree Sets
/*!
this has the GIM_BOX_TREE implementation for bounding boxes.
*/
template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE>
class GIM_BOX_TREE_SET: public GIM_BOX_TREE_TEMPLATE_SET< _GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE>
{
public:
};
/// GIM_BOX_SET collision methods
template<typename BOX_SET_CLASS0,typename BOX_SET_CLASS1>
class GIM_TREE_TREE_COLLIDER
{
public:
gim_pair_set * m_collision_pairs;
BOX_SET_CLASS0 * m_boxset0;
BOX_SET_CLASS1 * m_boxset1;
GUINT current_node0;
GUINT current_node1;
bool node0_is_leaf;
bool node1_is_leaf;
bool t0_is_trimesh;
bool t1_is_trimesh;
bool node0_has_triangle;
bool node1_has_triangle;
GIM_AABB m_box0;
GIM_AABB m_box1;
GIM_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
btTransform trans_cache_0to1;
GIM_TRIANGLE m_tri0;
btVector4 m_tri0_plane;
GIM_TRIANGLE m_tri1;
btVector4 m_tri1_plane;
public:
GIM_TREE_TREE_COLLIDER()
{
current_node0 = G_UINT_INFINITY;
current_node1 = G_UINT_INFINITY;
}
protected:
SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0)
{
if(node0_has_triangle) return;
m_boxset0->getNodeTriangle(node0,m_tri0);
//transform triangle
m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]);
m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]);
m_tri0.m_vertices[2] = trans_cache_0to1(m_tri0.m_vertices[2]);
m_tri0.get_plane(m_tri0_plane);
node0_has_triangle = true;
}
SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1)
{
if(node1_has_triangle) return;
m_boxset1->getNodeTriangle(node1,m_tri1);
//transform triangle
m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]);
m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]);
m_tri1.m_vertices[2] = trans_cache_1to0.transform(m_tri1.m_vertices[2]);
m_tri1.get_plane(m_tri1_plane);
node1_has_triangle = true;
}
SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0)
{
if(node0 == current_node0) return;
m_boxset0->getNodeBound(node0,m_box0);
node0_is_leaf = m_boxset0->isLeafNode(node0);
node0_has_triangle = false;
current_node0 = node0;
}
SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1)
{
if(node1 == current_node1) return;
m_boxset1->getNodeBound(node1,m_box1);
node1_is_leaf = m_boxset1->isLeafNode(node1);
node1_has_triangle = false;
current_node1 = node1;
}
SIMD_FORCE_INLINE bool node_collision(GUINT node0 ,GUINT node1)
{
retrieve_node0_info(node0);
retrieve_node1_info(node1);
bool result = m_box0.overlapping_trans_cache(m_box1,trans_cache_1to0,true);
if(!result) return false;
if(t0_is_trimesh && node0_is_leaf)
{
//perform primitive vs box collision
retrieve_node0_triangle(node0);
//do triangle vs box collision
m_box1.increment_margin(m_tri0.m_margin);
result = m_box1.collide_triangle_exact(
m_tri0.m_vertices[0],m_tri0.m_vertices[1],m_tri0.m_vertices[2],m_tri0_plane);
m_box1.increment_margin(-m_tri0.m_margin);
if(!result) return false;
return true;
}
else if(t1_is_trimesh && node1_is_leaf)
{
//perform primitive vs box collision
retrieve_node1_triangle(node1);
//do triangle vs box collision
m_box0.increment_margin(m_tri1.m_margin);
result = m_box0.collide_triangle_exact(
m_tri1.m_vertices[0],m_tri1.m_vertices[1],m_tri1.m_vertices[2],m_tri1_plane);
m_box0.increment_margin(-m_tri1.m_margin);
if(!result) return false;
return true;
}
return true;
}
//stackless collision routine
void find_collision_pairs()
{
gim_pair_set stack_collisions;
stack_collisions.reserve(32);
//add the first pair
stack_collisions.push_pair(0,0);
while(stack_collisions.size())
{
//retrieve the last pair and pop
GUINT node0 = stack_collisions.back().m_index1;
GUINT node1 = stack_collisions.back().m_index2;
stack_collisions.pop_back();
if(node_collision(node0,node1)) // a collision is found
{
if(node0_is_leaf)
{
if(node1_is_leaf)
{
m_collision_pairs->push_pair(m_boxset0->getNodeData(node0),m_boxset1->getNodeData(node1));
}
else
{
//collide left
stack_collisions.push_pair(node0,m_boxset1->getLeftNodeIndex(node1));
//collide right
stack_collisions.push_pair(node0,m_boxset1->getRightNodeIndex(node1));
}
}
else
{
if(node1_is_leaf)
{
//collide left
stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0),node1);
//collide right
stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0),node1);
}
else
{
GUINT left0 = m_boxset0->getLeftNodeIndex(node0);
GUINT right0 = m_boxset0->getRightNodeIndex(node0);
GUINT left1 = m_boxset1->getLeftNodeIndex(node1);
GUINT right1 = m_boxset1->getRightNodeIndex(node1);
//collide left
stack_collisions.push_pair(left0,left1);
//collide right
stack_collisions.push_pair(left0,right1);
//collide left
stack_collisions.push_pair(right0,left1);
//collide right
stack_collisions.push_pair(right0,right1);
}// else if node1 is not a leaf
}// else if node0 is not a leaf
}// if(node_collision(node0,node1))
}//while(stack_collisions.size())
}
public:
void find_collision(BOX_SET_CLASS0 * boxset1, const btTransform & trans1,
BOX_SET_CLASS1 * boxset2, const btTransform & trans2,
gim_pair_set & collision_pairs, bool complete_primitive_tests = true)
{
m_collision_pairs = &collision_pairs;
m_boxset0 = boxset1;
m_boxset1 = boxset2;
trans_cache_1to0.calc_from_homogenic(trans1,trans2);
trans_cache_0to1 = trans2.inverse();
trans_cache_0to1 *= trans1;
if(complete_primitive_tests)
{
t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh();
t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh();
}
else
{
t0_is_trimesh = false;
t1_is_trimesh = false;
}
find_collision_pairs();
}
};
#endif // GIM_BOXPRUNING_H_INCLUDED

View 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

View File

@@ -0,0 +1,146 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_contact.h"
#define MAX_COINCIDENT 8
void gim_contact_array::merge_contacts(
const gim_contact_array & contacts, bool normal_contact_average)
{
clear();
if(contacts.size()==1)
{
push_back(contacts.back());
return;
}
gim_array<GIM_RSORT_TOKEN> keycontacts(contacts.size());
keycontacts.resize(contacts.size(),false);
//fill key contacts
GUINT i;
for (i = 0;i<contacts.size() ;i++ )
{
keycontacts[i].m_key = contacts[i].calc_key_contact();
keycontacts[i].m_value = i;
}
//sort keys
gim_heap_sort(keycontacts.pointer(),keycontacts.size(),GIM_RSORT_TOKEN_COMPARATOR());
// Merge contacts
GUINT coincident_count=0;
btVector3 coincident_normals[MAX_COINCIDENT];
GUINT last_key = keycontacts[0].m_key;
GUINT key = 0;
push_back(contacts[keycontacts[0].m_value]);
GIM_CONTACT * pcontact = &back();
for( i=1;i<keycontacts.size();i++)
{
key = keycontacts[i].m_key;
const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value];
if(last_key == key)//same points
{
//merge contact
if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
{
*pcontact = *scontact;
coincident_count = 0;
}
else if(normal_contact_average)
{
if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
{
if(coincident_count<MAX_COINCIDENT)
{
coincident_normals[coincident_count] = scontact->m_normal;
coincident_count++;
}
}
}
}
else
{//add new contact
if(normal_contact_average && coincident_count>0)
{
pcontact->interpolate_normals(coincident_normals,coincident_count);
coincident_count = 0;
}
push_back(*scontact);
pcontact = &back();
}
last_key = key;
}
}
void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts)
{
clear();
if(contacts.size()==1)
{
push_back(contacts.back());
return;
}
GIM_CONTACT average_contact = contacts.back();
for (GUINT i=1;i<contacts.size() ;i++ )
{
average_contact.m_point += contacts[i].m_point;
average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
}
//divide
GREAL divide_average = 1.0f/((GREAL)contacts.size());
average_contact.m_point *= divide_average;
average_contact.m_normal *= divide_average;
average_contact.m_depth = average_contact.m_normal.length();
average_contact.m_normal /= average_contact.m_depth;
}

View 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 "gim_geometry.h"
#include "gim_radixsort.h"
#include "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

View 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 "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

View File

@@ -0,0 +1,42 @@
#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 "gim_basic_geometry_operations.h"
#include "gim_clip_polygon.h"
#include "gim_box_collision.h"
#include "gim_tri_collision.h"
#endif // GIM_VECTOR_H_INCLUDED

View 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 "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

File diff suppressed because it is too large Load Diff

View 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

View File

@@ -0,0 +1,135 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_memory.h"
#include "stdlib.h"
#ifdef GIM_SIMD_MEMORY
#include "LinearMath/btAlignedAllocator.h"
#endif
static gim_alloc_function *g_allocfn = 0;
static gim_alloca_function *g_allocafn = 0;
static gim_realloc_function *g_reallocfn = 0;
static gim_free_function *g_freefn = 0;
void gim_set_alloc_handler (gim_alloc_function *fn)
{
g_allocfn = fn;
}
void gim_set_alloca_handler (gim_alloca_function *fn)
{
g_allocafn = fn;
}
void gim_set_realloc_handler (gim_realloc_function *fn)
{
g_reallocfn = fn;
}
void gim_set_free_handler (gim_free_function *fn)
{
g_freefn = fn;
}
gim_alloc_function *gim_get_alloc_handler()
{
return g_allocfn;
}
gim_alloca_function *gim_get_alloca_handler()
{
return g_allocafn;
}
gim_realloc_function *gim_get_realloc_handler ()
{
return g_reallocfn;
}
gim_free_function *gim_get_free_handler ()
{
return g_freefn;
}
void * gim_alloc(size_t size)
{
void * ptr;
if (g_allocfn)
{
ptr = g_allocfn(size);
}
else
{
#ifdef GIM_SIMD_MEMORY
ptr = btAlignedAlloc(size,16);
#else
ptr = malloc(size);
#endif
}
return ptr;
}
void * gim_alloca(size_t size)
{
if (g_allocafn) return g_allocafn(size); else return gim_alloc(size);
}
void * gim_realloc(void *ptr, size_t oldsize, size_t newsize)
{
void * newptr = gim_alloc(newsize);
size_t copysize = oldsize<newsize?oldsize:newsize;
gim_simd_memcpy(newptr,ptr,copysize);
gim_free(ptr);
return newptr;
}
void gim_free(void *ptr)
{
if (!ptr) return;
if (g_freefn)
{
g_freefn(ptr);
}
else
{
#ifdef GIM_SIMD_MEMORY
btAlignedFree(ptr);
#else
free(ptr);
#endif
}
}

View File

@@ -0,0 +1,211 @@
#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 "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
/*
//'long long int' is incompatible with visual studio 6...
//copy words
SIMD_T * ui_src_ptr = (SIMD_T *)src;
SIMD_T * ui_dst_ptr = (SIMD_T *)dst;
while(copysize>=SIMD_T_SIZE)
{
*(ui_dst_ptr++) = *(ui_src_ptr++);
copysize-=SIMD_T_SIZE;
}
if(copysize==0) return;
*/
char * c_src_ptr = (char *)src;
char * c_dst_ptr = (char *)dst;
while(copysize>0)
{
*(c_dst_ptr++) = *(c_src_ptr++);
copysize--;
}
return;
#else
memcpy(dst,src,copysize);
#endif
}
template<class T>
inline void gim_swap_elements(T* _array,size_t _i,size_t _j)
{
T _e_tmp_ = _array[_i];
_array[_i] = _array[_j];
_array[_j] = _e_tmp_;
}
template<class T>
inline void gim_swap_elements_memcpy(T* _array,size_t _i,size_t _j)
{
char _e_tmp_[sizeof(T)];
gim_simd_memcpy(_e_tmp_,&_array[_i],sizeof(T));
gim_simd_memcpy(&_array[_i],&_array[_j],sizeof(T));
gim_simd_memcpy(&_array[_j],_e_tmp_,sizeof(T));
}
template <int SIZE>
inline void gim_swap_elements_ptr(char * _array,size_t _i,size_t _j)
{
char _e_tmp_[SIZE];
_i*=SIZE;
_j*=SIZE;
gim_simd_memcpy(_e_tmp_,_array+_i,SIZE);
gim_simd_memcpy(_array+_i,_array+_j,SIZE);
gim_simd_memcpy(_array+_j,_e_tmp_,SIZE);
}
#endif // GIM_MEMORY_H_INCLUDED

View 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 "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

View File

@@ -0,0 +1,640 @@
/*! \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 "gim_tri_collision.h"
#define TRI_LOCAL_EPSILON 0.000001f
#define MIN_EDGE_EDGE_DIS 0.00001f
class _GIM_TRIANGLE_CALCULATION_CACHE
{
public:
GREAL margin;
btVector3 tu_vertices[3];
btVector3 tv_vertices[3];
btVector4 tu_plane;
btVector4 tv_plane;
btVector3 closest_point_u;
btVector3 closest_point_v;
btVector3 edge_edge_dir;
btVector3 distances;
GREAL du[4];
GREAL du0du1;
GREAL du0du2;
GREAL dv[4];
GREAL dv0dv1;
GREAL dv0dv2;
btVector3 temp_points[MAX_TRI_CLIPPING];
btVector3 temp_points1[MAX_TRI_CLIPPING];
btVector3 contact_points[MAX_TRI_CLIPPING];
//! if returns false, the faces are paralele
SIMD_FORCE_INLINE bool compute_intervals(
const GREAL &D0,
const GREAL &D1,
const GREAL &D2,
const GREAL &D0D1,
const GREAL &D0D2,
GREAL & scale_edge0,
GREAL & scale_edge1,
GUINT &edge_index0,
GUINT &edge_index1)
{
if(D0D1>0.0f)
{
/* here we know that D0D2<=0.0 */
/* that is D0, D1 are on the same side, D2 on the other or on the plane */
scale_edge0 = -D2/(D0-D2);
scale_edge1 = -D1/(D2-D1);
edge_index0 = 2;edge_index1 = 1;
}
else if(D0D2>0.0f)
{
/* here we know that d0d1<=0.0 */
scale_edge0 = -D0/(D1-D0);
scale_edge1 = -D1/(D2-D1);
edge_index0 = 0;edge_index1 = 1;
}
else if(D1*D2>0.0f || D0!=0.0f)
{
/* here we know that d0d1<=0.0 or that D0!=0.0 */
scale_edge0 = -D0/(D1-D0);
scale_edge1 = -D2/(D0-D2);
edge_index0 = 0 ;edge_index1 = 2;
}
else
{
return false;
}
return true;
}
//! clip triangle
/*!
*/
SIMD_FORCE_INLINE GUINT clip_triangle(
const btVector4 & tri_plane,
const btVector3 * tripoints,
const btVector3 * srcpoints,
btVector3 * clip_points)
{
// edge 0
btVector4 edgeplane;
EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
if(clipped_count == 0) return 0;
// edge 1
EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
clipped_count = PLANE_CLIP_POLYGON3D(
edgeplane,temp_points,clipped_count,temp_points1);
if(clipped_count == 0) return 0;
// edge 2
EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
clipped_count = PLANE_CLIP_POLYGON3D(
edgeplane,temp_points1,clipped_count,clip_points);
return clipped_count;
/*GUINT i0 = (tri_plane.closestAxis()+1)%3;
GUINT i1 = (i0+1)%3;
// edge 0
btVector3 temp_points[MAX_TRI_CLIPPING];
btVector3 temp_points1[MAX_TRI_CLIPPING];
GUINT clipped_count= PLANE_CLIP_TRIANGLE_GENERIC(
0,srcpoints[0],srcpoints[1],srcpoints[2],temp_points,
DISTANCE_EDGE(tripoints[0],tripoints[1],i0,i1));
if(clipped_count == 0) return 0;
// edge 1
clipped_count = PLANE_CLIP_POLYGON_GENERIC(
0,temp_points,clipped_count,temp_points1,
DISTANCE_EDGE(tripoints[1],tripoints[2],i0,i1));
if(clipped_count == 0) return 0;
// edge 2
clipped_count = PLANE_CLIP_POLYGON_GENERIC(
0,temp_points1,clipped_count,clipped_points,
DISTANCE_EDGE(tripoints[2],tripoints[0],i0,i1));
return clipped_count;*/
}
SIMD_FORCE_INLINE void sort_isect(
GREAL & isect0,GREAL & isect1,GUINT &e0,GUINT &e1,btVector3 & vec0,btVector3 & vec1)
{
if(isect1<isect0)
{
//swap
GIM_SWAP_NUMBERS(isect0,isect1);
GIM_SWAP_NUMBERS(e0,e1);
btVector3 tmp = vec0;
vec0 = vec1;
vec1 = tmp;
}
}
//! Test verifying interval intersection with the direction between planes
/*!
\pre tv_plane and tu_plane must be set
\post
distances[2] is set with the distance
closest_point_u, closest_point_v, edge_edge_dir are set too
\return
- 0: faces are paralele
- 1: face U casts face V
- 2: face V casts face U
- 3: nearest edges
*/
SIMD_FORCE_INLINE GUINT cross_line_intersection_test()
{
// Compute direction of intersection line
edge_edge_dir = tu_plane.cross(tv_plane);
GREAL Dlen;
VEC_LENGTH(edge_edge_dir,Dlen);
if(Dlen<0.0001)
{
return 0; //faces near paralele
}
edge_edge_dir*= 1/Dlen;//normalize
// Compute interval for triangle 1
GUINT tu_e0,tu_e1;//edge indices
GREAL tu_scale_e0,tu_scale_e1;//edge scale
if(!compute_intervals(du[0],du[1],du[2],
du0du1,du0du2,tu_scale_e0,tu_scale_e1,tu_e0,tu_e1)) return 0;
// Compute interval for triangle 2
GUINT tv_e0,tv_e1;//edge indices
GREAL tv_scale_e0,tv_scale_e1;//edge scale
if(!compute_intervals(dv[0],dv[1],dv[2],
dv0dv1,dv0dv2,tv_scale_e0,tv_scale_e1,tv_e0,tv_e1)) return 0;
//proyected vertices
btVector3 up_e0 = tu_vertices[tu_e0].lerp(tu_vertices[(tu_e0+1)%3],tu_scale_e0);
btVector3 up_e1 = tu_vertices[tu_e1].lerp(tu_vertices[(tu_e1+1)%3],tu_scale_e1);
btVector3 vp_e0 = tv_vertices[tv_e0].lerp(tv_vertices[(tv_e0+1)%3],tv_scale_e0);
btVector3 vp_e1 = tv_vertices[tv_e1].lerp(tv_vertices[(tv_e1+1)%3],tv_scale_e1);
//proyected intervals
GREAL isect_u[] = {up_e0.dot(edge_edge_dir),up_e1.dot(edge_edge_dir)};
GREAL isect_v[] = {vp_e0.dot(edge_edge_dir),vp_e1.dot(edge_edge_dir)};
sort_isect(isect_u[0],isect_u[1],tu_e0,tu_e1,up_e0,up_e1);
sort_isect(isect_v[0],isect_v[1],tv_e0,tv_e1,vp_e0,vp_e1);
const GREAL midpoint_u = 0.5f*(isect_u[0]+isect_u[1]); // midpoint
const GREAL midpoint_v = 0.5f*(isect_v[0]+isect_v[1]); // midpoint
if(midpoint_u<midpoint_v)
{
if(isect_u[1]>=isect_v[1]) // face U casts face V
{
return 1;
}
else if(isect_v[0]<=isect_u[0]) // face V casts face U
{
return 2;
}
// closest points
closest_point_u = up_e1;
closest_point_v = vp_e0;
// calc edges and separation
if(isect_u[1]+ MIN_EDGE_EDGE_DIS<isect_v[0]) //calc distance between two lines instead
{
SEGMENT_COLLISION(
tu_vertices[tu_e1],tu_vertices[(tu_e1+1)%3],
tv_vertices[tv_e0],tv_vertices[(tv_e0+1)%3],
closest_point_u,
closest_point_v);
edge_edge_dir = closest_point_u-closest_point_v;
VEC_LENGTH(edge_edge_dir,distances[2]);
edge_edge_dir *= 1.0f/distances[2];// normalize
}
else
{
distances[2] = isect_v[0]-isect_u[1];//distance negative
//edge_edge_dir *= -1.0f; //normal pointing from V to U
}
}
else
{
if(isect_v[1]>=isect_u[1]) // face V casts face U
{
return 2;
}
else if(isect_u[0]<=isect_v[0]) // face U casts face V
{
return 1;
}
// closest points
closest_point_u = up_e0;
closest_point_v = vp_e1;
// calc edges and separation
if(isect_v[1]+MIN_EDGE_EDGE_DIS<isect_u[0]) //calc distance between two lines instead
{
SEGMENT_COLLISION(
tu_vertices[tu_e0],tu_vertices[(tu_e0+1)%3],
tv_vertices[tv_e1],tv_vertices[(tv_e1+1)%3],
closest_point_u,
closest_point_v);
edge_edge_dir = closest_point_u-closest_point_v;
VEC_LENGTH(edge_edge_dir,distances[2]);
edge_edge_dir *= 1.0f/distances[2];// normalize
}
else
{
distances[2] = isect_u[0]-isect_v[1];//distance negative
//edge_edge_dir *= -1.0f; //normal pointing from V to U
}
}
return 3;
}
//! collides by two sides
SIMD_FORCE_INLINE bool triangle_collision(
const btVector3 & u0,
const btVector3 & u1,
const btVector3 & u2,
GREAL margin_u,
const btVector3 & v0,
const btVector3 & v1,
const btVector3 & v2,
GREAL margin_v,
GIM_TRIANGLE_CONTACT_DATA & contacts)
{
margin = margin_u + margin_v;
tu_vertices[0] = u0;
tu_vertices[1] = u1;
tu_vertices[2] = u2;
tv_vertices[0] = v0;
tv_vertices[1] = v1;
tv_vertices[2] = v2;
//create planes
// plane v vs U points
TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],tv_plane);
du[0] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[0]);
du[1] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[1]);
du[2] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[2]);
du0du1 = du[0] * du[1];
du0du2 = du[0] * du[2];
if(du0du1>0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ?
{
if(du[0]<0) //we need test behind the triangle plane
{
distances[0] = GIM_MAX3(du[0],du[1],du[2]);
distances[0] = -distances[0];
if(distances[0]>margin) return false; //never intersect
//reorder triangle v
VEC_SWAP(tv_vertices[0],tv_vertices[1]);
VEC_SCALE_4(tv_plane,-1.0f,tv_plane);
}
else
{
distances[0] = GIM_MIN3(du[0],du[1],du[2]);
if(distances[0]>margin) return false; //never intersect
}
}
else
{
//Look if we need to invert the triangle
distances[0] = (du[0]+du[1]+du[2])/3.0f; //centroid
if(distances[0]<0.0f)
{
//reorder triangle v
VEC_SWAP(tv_vertices[0],tv_vertices[1]);
VEC_SCALE_4(tv_plane,-1.0f,tv_plane);
distances[0] = GIM_MAX3(du[0],du[1],du[2]);
distances[0] = -distances[0];
}
else
{
distances[0] = GIM_MIN3(du[0],du[1],du[2]);
}
}
// plane U vs V points
TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],tu_plane);
dv[0] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[0]);
dv[1] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[1]);
dv[2] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[2]);
dv0dv1 = dv[0] * dv[1];
dv0dv2 = dv[0] * dv[2];
if(dv0dv1>0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ?
{
if(dv[0]<0) //we need test behind the triangle plane
{
distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]);
distances[1] = -distances[1];
if(distances[1]>margin) return false; //never intersect
//reorder triangle u
VEC_SWAP(tu_vertices[0],tu_vertices[1]);
VEC_SCALE_4(tu_plane,-1.0f,tu_plane);
}
else
{
distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]);
if(distances[1]>margin) return false; //never intersect
}
}
else
{
//Look if we need to invert the triangle
distances[1] = (dv[0]+dv[1]+dv[2])/3.0f; //centroid
if(distances[1]<0.0f)
{
//reorder triangle v
VEC_SWAP(tu_vertices[0],tu_vertices[1]);
VEC_SCALE_4(tu_plane,-1.0f,tu_plane);
distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]);
distances[1] = -distances[1];
}
else
{
distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]);
}
}
GUINT bl;
/* bl = cross_line_intersection_test();
if(bl==3)
{
//take edge direction too
bl = distances.maxAxis();
}
else
{*/
bl = 0;
if(distances[0]<distances[1]) bl = 1;
//}
if(bl==2) //edge edge separation
{
if(distances[2]>margin) return false;
contacts.m_penetration_depth = -distances[2] + margin;
contacts.m_points[0] = closest_point_v;
contacts.m_point_count = 1;
VEC_COPY(contacts.m_separating_normal,edge_edge_dir);
return true;
}
//clip face against other
GUINT point_count;
//TODO
if(bl == 0) //clip U points against V
{
point_count = clip_triangle(tv_plane,tv_vertices,tu_vertices,contact_points);
if(point_count == 0) return false;
contacts.merge_points(tv_plane,margin,contact_points,point_count);
}
else //clip V points against U
{
point_count = clip_triangle(tu_plane,tu_vertices,tv_vertices,contact_points);
if(point_count == 0) return false;
contacts.merge_points(tu_plane,margin,contact_points,point_count);
contacts.m_separating_normal *= -1.f;
}
if(contacts.m_point_count == 0) return false;
return true;
}
};
/*class _GIM_TRIANGLE_CALCULATION_CACHE
{
public:
GREAL margin;
GUINT clipped_count;
btVector3 tu_vertices[3];
btVector3 tv_vertices[3];
btVector3 temp_points[MAX_TRI_CLIPPING];
btVector3 temp_points1[MAX_TRI_CLIPPING];
btVector3 clipped_points[MAX_TRI_CLIPPING];
GIM_TRIANGLE_CONTACT_DATA contacts1;
GIM_TRIANGLE_CONTACT_DATA contacts2;
//! clip triangle
GUINT clip_triangle(
const btVector4 & tri_plane,
const btVector3 * tripoints,
const btVector3 * srcpoints,
btVector3 * clipped_points)
{
// edge 0
btVector4 edgeplane;
EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
if(clipped_count == 0) return 0;
// edge 1
EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
clipped_count = PLANE_CLIP_POLYGON3D(
edgeplane,temp_points,clipped_count,temp_points1);
if(clipped_count == 0) return 0;
// edge 2
EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
clipped_count = PLANE_CLIP_POLYGON3D(
edgeplane,temp_points1,clipped_count,clipped_points);
return clipped_count;
}
//! collides only on one side
bool triangle_collision(
const btVector3 & u0,
const btVector3 & u1,
const btVector3 & u2,
GREAL margin_u,
const btVector3 & v0,
const btVector3 & v1,
const btVector3 & v2,
GREAL margin_v,
GIM_TRIANGLE_CONTACT_DATA & contacts)
{
margin = margin_u + margin_v;
tu_vertices[0] = u0;
tu_vertices[1] = u1;
tu_vertices[2] = u2;
tv_vertices[0] = v0;
tv_vertices[1] = v1;
tv_vertices[2] = v2;
//create planes
// plane v vs U points
TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],contacts1.m_separating_normal);
clipped_count = clip_triangle(
contacts1.m_separating_normal,tv_vertices,tu_vertices,clipped_points);
if(clipped_count == 0 )
{
return false;//Reject
}
//find most deep interval face1
contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
if(contacts1.m_point_count == 0) return false; // too far
//Normal pointing to triangle1
//contacts1.m_separating_normal *= -1.f;
//Clip tri1 by tri2 edges
TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],contacts2.m_separating_normal);
clipped_count = clip_triangle(
contacts2.m_separating_normal,tu_vertices,tv_vertices,clipped_points);
if(clipped_count == 0 )
{
return false;//Reject
}
//find most deep interval face1
contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
if(contacts2.m_point_count == 0) return false; // too far
contacts2.m_separating_normal *= -1.f;
////check most dir for contacts
if(contacts2.m_penetration_depth<contacts1.m_penetration_depth)
{
contacts.copy_from(contacts2);
}
else
{
contacts.copy_from(contacts1);
}
return true;
}
};*/
bool GIM_TRIANGLE::collide_triangle_hard_test(
const GIM_TRIANGLE & other,
GIM_TRIANGLE_CONTACT_DATA & contact_data) const
{
_GIM_TRIANGLE_CALCULATION_CACHE calc_cache;
return calc_cache.triangle_collision(
m_vertices[0],m_vertices[1],m_vertices[2],m_margin,
other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin,
contact_data);
}

View File

@@ -0,0 +1,383 @@
#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 "gim_box_collision.h"
#include "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];
GUINT _k;
for(_k=0;_k<point_count;_k++)
{
GREAL _dist = -distance_func(plane,points[_k]) + margin;
if(_dist>=0.0f)
{
if(_dist>m_penetration_depth)
{
m_penetration_depth = _dist;
point_indices[0] = _k;
m_point_count=1;
}
else if((_dist+G_EPSILON)>=m_penetration_depth)
{
point_indices[m_point_count] = _k;
m_point_count++;
}
}
}
for( _k=0;_k<m_point_count;_k++)
{
m_points[_k] = points[point_indices[_k]];
}
}
//! classify points that are closer
SIMD_FORCE_INLINE void merge_points(const btVector4 & plane, GREAL margin,
const btVector3 * points, GUINT point_count)
{
m_separating_normal = plane;
mergepoints_generic(plane, margin, points, point_count, DISTANCE_PLANE_3D_FUNC());
}
};
//! Class for colliding triangles
class GIM_TRIANGLE
{
public:
btScalar m_margin;
btVector3 m_vertices[3];
GIM_TRIANGLE():m_margin(0.1f)
{
}
SIMD_FORCE_INLINE GIM_AABB get_box() const
{
return GIM_AABB(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
}
SIMD_FORCE_INLINE void get_normal(btVector3 &normal) const
{
TRIANGLE_NORMAL(m_vertices[0],m_vertices[1],m_vertices[2],normal);
}
SIMD_FORCE_INLINE void get_plane(btVector4 &plane) const
{
TRIANGLE_PLANE(m_vertices[0],m_vertices[1],m_vertices[2],plane);;
}
SIMD_FORCE_INLINE void apply_transform(const btTransform & trans)
{
m_vertices[0] = trans(m_vertices[0]);
m_vertices[1] = trans(m_vertices[1]);
m_vertices[2] = trans(m_vertices[2]);
}
SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index,const btVector3 &triangle_normal,btVector4 &plane) const
{
const btVector3 & e0 = m_vertices[edge_index];
const btVector3 & e1 = m_vertices[(edge_index+1)%3];
EDGE_PLANE(e0,e1,triangle_normal,plane);
}
//! Gets the relative transformation of this triangle
/*!
The transformation is oriented to the triangle normal , and aligned to the 1st edge of this triangle. The position corresponds to vertice 0:
- triangle normal corresponds to Z axis.
- 1st normalized edge corresponds to X axis,
*/
SIMD_FORCE_INLINE void get_triangle_transform(btTransform & triangle_transform) const
{
btMatrix3x3 & matrix = triangle_transform.getBasis();
btVector3 zaxis;
get_normal(zaxis);
MAT_SET_Z(matrix,zaxis);
btVector3 xaxis = m_vertices[1] - m_vertices[0];
VEC_NORMALIZE(xaxis);
MAT_SET_X(matrix,xaxis);
//y axis
xaxis = zaxis.cross(xaxis);
MAT_SET_Y(matrix,xaxis);
triangle_transform.setOrigin(m_vertices[0]);
}
//! Test triangles by finding separating axis
/*!
\param other Triangle for collide
\param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
*/
bool collide_triangle_hard_test(
const GIM_TRIANGLE & other,
GIM_TRIANGLE_CONTACT_DATA & contact_data) const;
//! Test boxes before doing hard test
/*!
\param other Triangle for collide
\param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
\
*/
SIMD_FORCE_INLINE bool collide_triangle(
const GIM_TRIANGLE & other,
GIM_TRIANGLE_CONTACT_DATA & contact_data) const
{
//test box collisioin
GIM_AABB boxu(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
GIM_AABB boxv(other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin);
if(!boxu.has_collision(boxv)) return false;
//do hard test
return collide_triangle_hard_test(other,contact_data);
}
/*!
Solve the System for u,v parameters:
u*axe1[i1] + v*axe2[i1] = vecproj[i1]
u*axe1[i2] + v*axe2[i2] = vecproj[i2]
sustitute:
v = (vecproj[i2] - u*axe1[i2])/axe2[i2]
then the first equation in terms of 'u':
--> u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1]
--> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1]
--> u*(axe1[i1] - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2]
--> u*((axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2]
--> u*(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]
--> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])
if 0.0<= u+v <=1.0 then they are inside of triangle
\return false if the point is outside of triangle.This function doesn't take the margin
*/
SIMD_FORCE_INLINE bool get_uv_parameters(
const btVector3 & point,
const btVector3 & tri_plane,
GREAL & u, GREAL & v) const
{
btVector3 _axe1 = m_vertices[1]-m_vertices[0];
btVector3 _axe2 = m_vertices[2]-m_vertices[0];
btVector3 _vecproj = point - m_vertices[0];
GUINT _i1 = (tri_plane.closestAxis()+1)%3;
GUINT _i2 = (_i1+1)%3;
if(btFabs(_axe2[_i2])<G_EPSILON)
{
u = (_vecproj[_i2]*_axe2[_i1] - _vecproj[_i1]*_axe2[_i2]) /(_axe1[_i2]*_axe2[_i1] - _axe1[_i1]*_axe2[_i2]);
v = (_vecproj[_i1] - u*_axe1[_i1])/_axe2[_i1];
}
else
{
u = (_vecproj[_i1]*_axe2[_i2] - _vecproj[_i2]*_axe2[_i1]) /(_axe1[_i1]*_axe2[_i2] - _axe1[_i2]*_axe2[_i1]);
v = (_vecproj[_i2] - u*_axe1[_i2])/_axe2[_i2];
}
if(u<-G_EPSILON)
{
return false;
}
else if(v<-G_EPSILON)
{
return false;
}
else
{
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, btScalar(0), tmax);
if(res == 0) return false;
if(! is_point_inside(pout,faceplane)) return false;
if(res==2) //invert normal
{
triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]);
}
else
{
triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
}
VEC_NORMALIZE(triangle_normal);
return true;
}
//! one direccion ray collision
SIMD_FORCE_INLINE bool ray_collision_front_side(
const btVector3 & vPoint,
const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
{
btVector4 faceplane;
{
btVector3 dif1 = m_vertices[1] - m_vertices[0];
btVector3 dif2 = m_vertices[2] - m_vertices[0];
VEC_CROSS(faceplane,dif1,dif2);
faceplane[3] = m_vertices[0].dot(faceplane);
}
GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
if(res != 1) return false;
if(!is_point_inside(pout,faceplane)) return false;
triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
VEC_NORMALIZE(triangle_normal);
return true;
}
};
//! @}
#endif // GIM_TRI_COLLISION_H_INCLUDED

View File

@@ -688,8 +688,8 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands()
const btRigidBody* colObj0 = &constraint->getRigidBodyA();
const btRigidBody* colObj1 = &constraint->getRigidBodyB();
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
((colObj1) && ((colObj1)->mergesSimulationIslands())))
if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
{
if (colObj0->isActive() || colObj1->isActive())
{

View File

@@ -69,7 +69,7 @@ btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btV
pm->m_flags = fMaterial::Default;
/* Collision shape */
///for now, create a collision shape internally
setCollisionShape(new btSoftBodyCollisionShape(this));
m_collisionShape = new btSoftBodyCollisionShape(this);
m_collisionShape->setMargin(0.25);
/* Nodes */
const btScalar margin=getCollisionShape()->getMargin();
@@ -384,6 +384,20 @@ void btSoftBody::addVelocity(const btVector3& velocity)
for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
}
/* Set velocity for the entire body */
void btSoftBody::setVelocity( const btVector3& velocity)
{
for(int i=0,ni=m_nodes.size();i<ni;++i)
{
Node& n=m_nodes[i];
if(n.m_im>0)
{
n.m_v = velocity;
}
}
}
//
void btSoftBody::addVelocity(const btVector3& velocity,int node)
{

View File

@@ -29,7 +29,7 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
class btBroadphaseInterface;
class btCollisionDispatcher;
class btDispatcher;
/* btSoftBodyWorldInfo */
struct btSoftBodyWorldInfo
@@ -39,7 +39,7 @@ struct btSoftBodyWorldInfo
btScalar water_offset;
btVector3 water_normal;
btBroadphaseInterface* m_broadphase;
btCollisionDispatcher* m_dispatcher;
btDispatcher* m_dispatcher;
btVector3 m_gravity;
btSparseSdf<3> m_sparsesdf;
};
@@ -606,6 +606,14 @@ public:
/* dtor */
virtual ~btSoftBody();
/* Check for existing link */
btAlignedObjectArray<int> m_userIndexMapping;
virtual void setCollisionShape(btCollisionShape* collisionShape)
{
//don't do anything, due to the internal shape hack: todo: fix this
}
bool checkLink( int node0,
int node1) const;
bool checkLink( const Node* node0,
@@ -669,6 +677,10 @@ public:
int node);
/* Add velocity to the entire body */
void addVelocity( const btVector3& velocity);
/* Set velocity for the entire body */
void setVelocity( const btVector3& velocity);
/* Add velocity to a node of the body */
void addVelocity( const btVector3& velocity,
int node);

View File

@@ -94,7 +94,6 @@ public:
virtual void setLocalScaling(const btVector3& /*scaling*/)
{
///na
btAssert(0);
}
virtual const btVector3& getLocalScaling() const
{

View File

@@ -21,6 +21,10 @@ subject to the following restrictions:
#include "btSoftBody.h"
#include "btSoftBodyHelpers.h"
btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
{
@@ -28,6 +32,11 @@ m_drawFlags = fDrawFlags::Std;
m_drawNodeTree = true;
m_drawFaceTree = false;
m_drawClusterTree = false;
m_sbi.m_broadphase = pairCache;
m_sbi.m_dispatcher = dispatcher;
m_sbi.m_sparsesdf.Initialize();
m_sbi.m_sparsesdf.Reset();
}
btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()

View File

@@ -13,12 +13,12 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H
#define BT_SOFT_RIGID_DYNAMICS_WORLD_H
class btSoftBody;
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#include "btSoftBody.h"
typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld
@@ -29,7 +29,8 @@ class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld
bool m_drawNodeTree;
bool m_drawFaceTree;
bool m_drawClusterTree;
btSoftBodyWorldInfo m_sbi;
protected:
virtual void predictUnconstraintMotion(btScalar timeStep);
@@ -40,7 +41,6 @@ protected:
void solveSoftBodiesConstraints();
public:
@@ -57,6 +57,15 @@ public:
int getDrawFlags() const { return(m_drawFlags); }
void setDrawFlags(int f) { m_drawFlags=f; }
btSoftBodyWorldInfo& getWorldInfo()
{
return m_sbi;
}
const btSoftBodyWorldInfo& getWorldInfo() const
{
return m_sbi;
}
btSoftBodyArray& getSoftBodyArray()
{

View File

@@ -869,6 +869,8 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
{
if ( svcount == 0 ) return false;
m_vertexIndexMapping.resize(0);
#define EPSILON btScalar(0.000001) /* close enough to consider two btScalaring point numbers to be 'the same'. */
@@ -1027,6 +1029,7 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
v[0] = px;
v[1] = py;
v[2] = pz;
}
break;
@@ -1041,6 +1044,7 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
dest[2] = pz;
vcount++;
}
m_vertexIndexMapping.push_back(j);
}
}
@@ -1116,13 +1120,22 @@ bool HullLibrary::CleanupVertices(unsigned int svcount,
void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount)
{
btAlignedObjectArray<int>tmpIndices;
tmpIndices.resize(m_vertexIndexMapping.size());
int i;
for (i=0;i<m_vertexIndexMapping.size();i++)
{
tmpIndices[i] = m_vertexIndexMapping[i];
}
TUIntArray usedIndices;
usedIndices.resize(static_cast<int>(vcount));
memset(&usedIndices[0],0,sizeof(unsigned int)*vcount);
ocount = 0;
for (unsigned int i=0; i<indexcount; i++)
for (i=0; i<indexcount; i++)
{
unsigned int v = indices[i]; // original array index
@@ -1141,11 +1154,19 @@ void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, b
overts[ocount][1] = verts[v][1];
overts[ocount][2] = verts[v][2];
for (int k=0;k<m_vertexIndexMapping.size();k++)
{
if (tmpIndices[k]==v)
m_vertexIndexMapping[k]=ocount;
}
ocount++; // increment output vert count
btAssert( ocount >=0 && ocount <= vcount );
usedIndices[static_cast<int>(v)] = ocount; // assign new index remapping
}
}

View File

@@ -192,6 +192,9 @@ class HullLibrary
public:
btAlignedObjectArray<int> m_vertexIndexMapping;
HullError CreateConvexHull(const HullDesc& desc, // describes the input request
HullResult& result); // contains the resulst
HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.

View File

@@ -36,6 +36,7 @@ BulletCollision/BroadphaseCollision \
BulletCollision/CollisionShapes \
BulletCollision/NarrowPhaseCollision \
BulletCollision/CollisionDispatch \
BulletCollision/Gimpact \
BulletDynamics/ConstraintSolver \
BulletDynamics/Vehicle \
BulletDynamics/Dynamics \
@@ -47,6 +48,7 @@ BulletCollision/BroadphaseCollision/*.cpp \
BulletCollision/CollisionShapes/*.cpp \
BulletCollision/NarrowPhaseCollision/*.cpp \
BulletCollision/CollisionDispatch/*.cpp \
BulletCollision/Gimpact/*.cpp \
BulletDynamics/ConstraintSolver/*.cpp \
BulletDynamics/Vehicle/*.cpp \
BulletDynamics/Dynamics/*.cpp \

View File

@@ -25,8 +25,11 @@ linearmath_src = env.Glob("LinearMath/*.cpp")
bulletdyn_src = env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp")
collision_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp") + env.Glob("BulletCollision/CollisionDispatch/*.cpp")
collision_src += env.Glob("BulletCollision/CollisionShapes/*.cpp") + env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp")
collision_broadphase_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp")
collision_dispatch_src = env.Glob("BulletCollision/CollisionDispatch/*.cpp")
collision_gimpact_src = env.Glob("BulletCollision/Gimpact/*.cpp")
collision_shapes_src = env.Glob("BulletCollision/CollisionShapes/*.cpp")
collision_narrowphase_src = env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp")
softbody_src = env.Glob("BulletSoftBody/*.cpp")
@@ -34,5 +37,9 @@ incs = '. BulletCollision BulletDynamics LinearMath BulletSoftBody'
env.BlenderLib ( libname = 'extern_bullet2linmath', sources=linearmath_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags )
env.BlenderLib ( libname = 'extern_bullet2dynamics', sources=bulletdyn_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[19, 169], compileflags=cflags )
env.BlenderLib ( libname = 'extern_bullet2collision', sources=collision_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags )
env.BlenderLib ( libname = 'extern_bullet2collision_broadphase', sources=collision_broadphase_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[25, 175], compileflags=cflags )
env.BlenderLib ( libname = 'extern_bullet2collision_dispatch', sources=collision_dispatch_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags )
env.BlenderLib ( libname = 'extern_bullet2collision_gimpact', sources=collision_gimpact_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags )
env.BlenderLib ( libname = 'extern_bullet2collision_shapes', sources=collision_shapes_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags )
env.BlenderLib ( libname = 'extern_bullet2collision_narrowphase', sources=collision_narrowphase_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags )
env.BlenderLib ( libname = 'extern_bullet2softbody', sources=softbody_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[18,168], compileflags=cflags )

View File

@@ -14,4 +14,7 @@ if env['WITH_BF_OPENAL']:
else:
defs = 'NO_SOUND'
if not env['WITH_BF_SDL']:
defs += ' DISABLE_SDL'
env.BlenderLib ('bf_soundsystem', sources, Split(incs), Split(defs), libtype=['core','player'], priority = [20,140] )

View File

@@ -34,11 +34,6 @@
#include "SND_Utils.h"
#include "SoundDefines.h"
#include "SND_DependKludge.h"
/*
extern "C" {
#include "license_key.h"
}
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

View File

@@ -55,6 +55,10 @@ SND_SDLCDDevice::SND_SDLCDDevice() :
void SND_SDLCDDevice::init()
{
#ifdef DISABLE_SDL
fprintf(stderr, "Blender compiled without SDL, no CDROM support\n");
return;
#else
if (SDL_InitSubSystem(SDL_INIT_CDROM))
{
fprintf(stderr, "Error initializing CDROM\n");
@@ -75,19 +79,23 @@ void SND_SDLCDDevice::init()
/* Did if open? Check if cdrom is NULL */
if(!m_cdrom)
{
fprintf(stderr, "Couldn't open drive: %s", SDL_GetError());
fprintf(stderr, "Couldn't open drive: %s\n", SDL_GetError());
return;
}
#endif
}
SND_SDLCDDevice::~SND_SDLCDDevice()
{
#ifndef DISABLE_SDL
StopCD();
SDL_CDClose(m_cdrom);
#endif
}
void SND_SDLCDDevice::NextFrame()
{
#ifndef DISABLE_SDL
m_frame++;
m_frame &= 127;
@@ -111,20 +119,24 @@ void SND_SDLCDDevice::NextFrame()
}
}
#endif
}
void SND_SDLCDDevice::PlayCD(int track)
{
#ifndef DISABLE_SDL
if ( m_cdrom && CD_INDRIVE(SDL_CDStatus(m_cdrom)) ) {
SDL_CDPlayTracks(m_cdrom, track-1, 0, track, 0);
m_cdplaying = true;
m_cdtrack = track;
}
#endif
}
void SND_SDLCDDevice::PauseCD(bool pause)
{
#ifndef DISABLE_SDL
if (!m_cdrom)
return;
@@ -132,13 +144,16 @@ void SND_SDLCDDevice::PauseCD(bool pause)
SDL_CDPause(m_cdrom);
else
SDL_CDResume(m_cdrom);
#endif
}
void SND_SDLCDDevice::StopCD()
{
#ifndef DISABLE_SDL
if (m_cdrom)
SDL_CDStop(m_cdrom);
m_cdplaying = false;
#endif
}
void SND_SDLCDDevice::SetCDPlaymode(int playmode)

View File

@@ -24,7 +24,7 @@
#
# ***** END GPL LICENSE BLOCK *****
SET(INC ${PNG_INC} ${ZLIB_INC} ${SDL_INC})
SET(INC ${PNG_INC} ${ZLIB_INC} ${SDL_INC} extern)
FILE(GLOB SRC intern/*.cpp)

View File

@@ -5,13 +5,14 @@ Import('env')
sources = env.Glob('intern/*.cpp')
defs = ' NOGUI ELBEEM_BLENDER=1'
defs = 'NOGUI ELBEEM_BLENDER=1'
if env['WITH_BF_OPENMP'] == 1:
defs += ' PARALLEL'
if env['OURPLATFORM']=='win32-vc':
defs += ' USE_MSVC6FIXES'
incs = env['BF_PNG_INC'] + ' ' + env['BF_ZLIB_INC'] + ' ' +env['BF_SDL_INC']
incs = env['BF_PNG_INC'] + ' ' + env['BF_ZLIB_INC'] + ' ' +env['BF_SDL_INC']
incs += ' extern '
env.BlenderLib ('bf_elbeem', sources, Split(incs), Split(defs), libtype='blender', priority=0 )

View File

@@ -63,11 +63,6 @@ void loadFluidsimMesh(struct Object *srcob, int useRenderParams);
// WARNING - implemented in intern/elbeem/blendercall.cpp
int performElbeemSimulation(char *cfgfilename);
/* init axis aligned BB for mesh object */
// implemented in source/blender/blenkernel/intern/DerivedMesh.c
void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
/*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh );
#endif

View File

@@ -32,7 +32,7 @@ typedef struct elbeemSimulationSettings {
short version;
/* id number of simulation domain, needed if more than a
* single domain should be simulated */
short domainId;
short domainId; // unused within blender
/* geometrical extent */
float geoStart[3], geoSize[3];
@@ -97,10 +97,13 @@ typedef struct elbeemSimulationSettings {
// defines for elbeemMesh->type below
/* please keep in sync with DNA_object_fluidsim.h */
#define OB_FLUIDSIM_FLUID 4
#define OB_FLUIDSIM_OBSTACLE 8
#define OB_FLUIDSIM_INFLOW 16
#define OB_FLUIDSIM_OUTFLOW 32
#define OB_FLUIDSIM_PARTICLE 64
#define OB_FLUIDSIM_CONTROL 128
// defines for elbeemMesh->obstacleType below
#define FLUIDSIM_OBSTACLE_NOSLIP 1
@@ -113,7 +116,7 @@ typedef struct elbeemSimulationSettings {
// a single mesh object
typedef struct elbeemMesh {
/* obstacle,fluid or inflow... */
/* obstacle,fluid or inflow or control ... */
short type;
/* id of simulation domain it belongs to */
short parentDomainId;
@@ -155,6 +158,20 @@ typedef struct elbeemMesh {
/* name of the mesh, mostly for debugging */
const char *name;
/* fluid control settings */
float cpsTimeStart;
float cpsTimeEnd;
float cpsQuality;
int channelSizeAttractforceStrength;
float *channelAttractforceStrength;
int channelSizeAttractforceRadius;
float *channelAttractforceRadius;
int channelSizeVelocityforceStrength;
float *channelVelocityforceStrength;
int channelSizeVelocityforceRadius;
float *channelVelocityforceRadius;
} elbeemMesh;
// API functions
@@ -170,6 +187,9 @@ void elbeemResetSettings(struct elbeemSimulationSettings*);
// start fluidsim init (returns !=0 upon failure)
int elbeemInit(void);
// frees fluidsim
int elbeemFree(void);
// start fluidsim init (returns !=0 upon failure)
int elbeemAddDomain(struct elbeemSimulationSettings*);
@@ -223,6 +243,7 @@ double elbeemEstimateMemreq(int res,
// structs, for these use OB_xxx defines above
/*! fluid geometry init types */
// type "int" used, so max is 8
#define FGI_FLAGSTART 16
#define FGI_FLUID (1<<(FGI_FLAGSTART+ 0))
#define FGI_NO_FLUID (1<<(FGI_FLAGSTART+ 1))
@@ -232,6 +253,7 @@ double elbeemEstimateMemreq(int res,
#define FGI_NO_BND (1<<(FGI_FLAGSTART+ 5))
#define FGI_MBNDINFLOW (1<<(FGI_FLAGSTART+ 6))
#define FGI_MBNDOUTFLOW (1<<(FGI_FLAGSTART+ 7))
#define FGI_CONTROL (1<<(FGI_FLAGSTART+ 8))
// all boundary types at once
#define FGI_ALLBOUNDS ( FGI_BNDNO | FGI_BNDFREE | FGI_BNDPART | FGI_MBNDINFLOW | FGI_MBNDOUTFLOW )

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,301 @@
// --------------------------------------------------------------------------
//
// El'Beem - the visual lattice boltzmann freesurface simulator
// All code distributed as part of El'Beem is covered by the version 2 of the
// GNU General Public License. See the file COPYING for details.
//
// Copyright 2008 Nils Thuerey , Richard Keiser, Mark Pauly, Ulrich Ruede
//
// control particle classes
//
// --------------------------------------------------------------------------
#ifndef CONTROLPARTICLES_H
#define CONTROLPARTICLES_H
#include "ntl_geometrymodel.h"
// indicator for LBM inclusion
//#ifndef LBMDIM
//#include <NxFoundation.h>
//#include <vector>
//class MultisphGUI;
//#define NORMALIZE(a) a.normalize()
//#define MAGNITUDE(a) a.magnitude()
//#define CROSS(a,b,c) a.cross(b,c)
//#define ABS(a) (a>0. ? (a) : -(a))
//#include "cpdefines.h"
//#else // LBMDIM
// use compatibility defines
//#define NORMALIZE(a) normalize(a)
//#define MAGNITUDE(a) norm(a)
//#define CROSS(a,b,c) a=cross(b,c)
//#endif // LBMDIM
#define MAGNITUDE(a) norm(a)
// math.h compatibility
#define CP_PI ((LbmFloat)3.14159265358979323846)
// project 2d test cases onto plane?
// if not, 3d distance is used for 2d sim as well
#define CP_PROJECT2D 1
// default init for mincpdist, ControlForces::maxDistance
#define CPF_MAXDINIT 10000.
// storage of influence for a fluid cell/particle in lbm/sph
class ControlForces
{
public:
ControlForces() { };
~ControlForces() {};
// attraction force
LbmFloat weightAtt;
LbmVec forceAtt;
// velocity influence
LbmFloat weightVel;
LbmVec forceVel;
// maximal distance influence,
// first is max. distance to first control particle
// second attraction strength
LbmFloat maxDistance;
LbmVec forceMaxd;
LbmFloat compAvWeight;
LbmVec compAv;
void resetForces() {
weightAtt = weightVel = 0.;
maxDistance = CPF_MAXDINIT;
forceAtt = forceVel = forceMaxd = LbmVec(0.,0.,0.);
compAvWeight=0.; compAv=LbmVec(0.);
};
};
// single control particle
class ControlParticle
{
public:
ControlParticle() { reset(); };
~ControlParticle() {};
// control parameters
// position
LbmVec pos;
// size (influences influence radius)
LbmFloat size;
// overall strength of influence
LbmFloat influence;
// rotation axis
LbmVec rotaxis;
// computed values
// velocity
LbmVec vel;
// computed density
LbmFloat density;
LbmFloat densityWeight;
LbmVec avgVel;
LbmVec avgVelAcc;
LbmFloat avgVelWeight;
// init all zero / defaults
void reset();
};
// container for a particle configuration at time t
class ControlParticleSet
{
public:
// time of particle set
LbmFloat time;
// particle positions
std::vector<ControlParticle> particles;
};
// container & management of control particles
class ControlParticles
{
public:
ControlParticles();
~ControlParticles();
// reset datastructures for next influence step
// if motion object is given, particle 1 of second system is used for overall
// position and speed offset
void prepareControl(LbmFloat simtime, LbmFloat dt, ControlParticles *motion);
// post control operations
void finishControl(std::vector<ControlForces> &forces, LbmFloat iatt, LbmFloat ivel, LbmFloat imaxd);
// recalculate
void calculateKernelWeight();
// calculate forces at given position, and modify velocity
// according to timestep (from initControl)
void calculateCpInfluenceOpt (ControlParticle *cp, LbmVec fluidpos, LbmVec fluidvel, ControlForces *force, LbmFloat fillFactor);
void calculateMaxdForce (ControlParticle *cp, LbmVec fluidpos, ControlForces *force);
// no. of particles
inline int getSize() { return (int)_particles.size(); }
int getTotalSize();
// get particle [i]
inline ControlParticle* getParticle(int i){ return &_particles[i]; }
// set influence parameters
void setInfluenceTangential(LbmFloat set) { _influenceTangential=set; }
void setInfluenceAttraction(LbmFloat set) { _influenceAttraction=set; }
void setInfluenceMaxdist(LbmFloat set) { _influenceMaxdist=set; }
// calculate for delta t
void setInfluenceVelocity(LbmFloat set, LbmFloat dt);
// get influence parameters
inline LbmFloat getInfluenceAttraction() { return _influenceAttraction; }
inline LbmFloat getInfluenceTangential() { return _influenceTangential; }
inline LbmFloat getInfluenceVelocity() { return _influenceVelocity; }
inline LbmFloat getInfluenceMaxdist() { return _influenceMaxdist; }
inline LbmFloat getCurrTimestep() { return _currTimestep; }
void setRadiusAtt(LbmFloat set) { _radiusAtt=set; }
inline LbmFloat getRadiusAtt() { return _radiusAtt; }
void setRadiusVel(LbmFloat set) { _radiusVel=set; }
inline LbmFloat getRadiusVel() { return _radiusVel; }
void setRadiusMaxd(LbmFloat set) { _radiusMaxd=set; }
inline LbmFloat getRadiusMaxd() { return _radiusMaxd; }
void setRadiusMinMaxd(LbmFloat set) { _radiusMinMaxd=set; }
inline LbmFloat getRadiusMinMaxd() { return _radiusMinMaxd; }
LbmFloat getControlTimStart();
LbmFloat getControlTimEnd();
// set/get characteristic length (and inverse)
void setCharLength(LbmFloat set) { _charLength=set; _charLengthInv=1./_charLength; }
inline LbmFloat getCharLength() { return _charLength;}
inline LbmFloat getCharLengthInv() { return _charLengthInv;}
// set init parameters
void setInitTimeScale(LbmFloat set) { _initTimeScale = set; };
void setInitMirror(string set) { _initMirror = set; };
string getInitMirror() { return _initMirror; };
void setLastOffset(LbmVec set) { _initLastPartOffset = set; };
void setLastScale(LbmVec set) { _initLastPartScale = set; };
void setOffset(LbmVec set) { _initPartOffset = set; };
void setScale(LbmVec set) { _initPartScale = set; };
// set/get cps params
void setCPSWith(LbmFloat set) { mCPSWidth = set; };
void setCPSTimestep(LbmFloat set) { mCPSTimestep = set; };
void setCPSTimeStart(LbmFloat set) { mCPSTimeStart = set; };
void setCPSTimeEnd(LbmFloat set) { mCPSTimeEnd = set; };
void setCPSMvmWeightFac(LbmFloat set) { mCPSWeightFac = set; };
LbmFloat getCPSWith() { return mCPSWidth; };
LbmFloat getCPSTimestep() { return mCPSTimestep; };
LbmFloat getCPSTimeStart() { return mCPSTimeStart; };
LbmFloat getCPSTimeEnd() { return mCPSTimeEnd; };
LbmFloat getCPSMvmWeightFac() { return mCPSWeightFac; };
void setDebugInit(int set) { mDebugInit = set; };
// set init parameters
void setFluidSpacing(LbmFloat set) { _fluidSpacing = set; };
// load positions & timing from text file
int initFromTextFile(string filename);
int initFromTextFileOld(string filename);
// load positions & timing from gzipped binary file
int initFromBinaryFile(string filename);
int initFromMVCMesh(string filename);
// init an example test case
int initExampleSet();
// init for a given time
void initTime(LbmFloat t, LbmFloat dt);
// blender test init
void initBlenderTest();
int initFromObject(ntlGeometryObjModel *model);
protected:
// sets influence params
friend class MultisphGUI;
// tangential and attraction influence
LbmFloat _influenceTangential, _influenceAttraction;
// direct velocity influence
LbmFloat _influenceVelocity;
// maximal distance influence
LbmFloat _influenceMaxdist;
// influence radii
LbmFloat _radiusAtt, _radiusVel, _radiusMinMaxd, _radiusMaxd;
// currently valid time & timestep
LbmFloat _currTime, _currTimestep;
// all particles
std::vector<ControlParticle> _particles;
// particle sets
std::vector<ControlParticleSet> mPartSets;
// additional parameters for initing particles
LbmFloat _initTimeScale;
LbmVec _initPartOffset;
LbmVec _initPartScale;
LbmVec _initLastPartOffset;
LbmVec _initLastPartScale;
// mirror particles for loading?
string _initMirror;
// row spacing paramter, e.g. use for approximation of kernel area/volume
LbmFloat _fluidSpacing;
// save current kernel weight
LbmFloat _kernelWeight;
// charateristic length in world coordinates for normalizatioon of forces
LbmFloat _charLength, _charLengthInv;
/*! do ani mesh CPS */
void calculateCPS(string filename);
//! ani mesh cps params
ntlVec3Gfx mvCPSStart, mvCPSEnd;
gfxReal mCPSWidth, mCPSTimestep;
gfxReal mCPSTimeStart, mCPSTimeEnd;
gfxReal mCPSWeightFac;
int mDebugInit;
protected:
// apply init transformations
void applyTrafos();
// helper function for init -> swap components everywhere
void swapCoords(int a,int b);
// helper function for init -> mirror time
void mirrorTime();
// helper, init given array
void initTimeArray(LbmFloat t, std::vector<ControlParticle> &parts);
bool checkPointInside(ntlTree *tree, ntlVec3Gfx org, gfxReal &distance);
};
#endif

View File

@@ -30,6 +30,7 @@ int guiRoiMaxLev=6, guiRoiMinLev=0;
ntlWorld *gpWorld = NULL;
// API
// reset elbeemSimulationSettings struct with defaults
@@ -95,6 +96,13 @@ int elbeemInit() {
return 0;
}
// fluidsim end
extern "C"
int elbeemFree() {
return 0;
}
// start fluidsim init
extern "C"
int elbeemAddDomain(elbeemSimulationSettings *settings) {
@@ -158,13 +166,27 @@ void elbeemResetMesh(elbeemMesh *mesh) {
/* name of the mesh, mostly for debugging */
mesh->name = "[unnamed]";
/* fluid control settings */
mesh->cpsTimeStart = 0;
mesh->cpsTimeEnd = 0;
mesh->cpsQuality = 0;
mesh->channelSizeAttractforceStrength = 0;
mesh->channelAttractforceStrength = NULL;
mesh->channelSizeAttractforceRadius = 0;
mesh->channelAttractforceRadius = NULL;
mesh->channelSizeVelocityforceStrength = 0;
mesh->channelVelocityforceStrength = NULL;
mesh->channelSizeVelocityforceRadius = 0;
mesh->channelVelocityforceRadius = NULL;
}
int globalMeshCounter = 1;
// add mesh as fluidsim object
extern "C"
int elbeemAddMesh(elbeemMesh *mesh) {
int initType = -1;
int initType;
if(getElbeemState() != SIMWORLD_INITIALIZING) { errFatal("elbeemAddMesh","World and domain not initialized, call elbeemInit and elbeemAddDomain before...", SIMWORLD_INITERROR); }
switch(mesh->type) {
@@ -176,9 +198,9 @@ int elbeemAddMesh(elbeemMesh *mesh) {
case OB_FLUIDSIM_FLUID: initType = FGI_FLUID; break;
case OB_FLUIDSIM_INFLOW: initType = FGI_MBNDINFLOW; break;
case OB_FLUIDSIM_OUTFLOW: initType = FGI_MBNDOUTFLOW; break;
case OB_FLUIDSIM_CONTROL: initType = FGI_CONTROL; break;
default: return 1; // invalid type
}
// invalid type?
if(initType<0) return 1;
ntlGeometryObjModel *obj = new ntlGeometryObjModel( );
gpWorld->getRenderGlobals()->getSimScene()->addGeoClass( obj );
@@ -195,17 +217,34 @@ int elbeemAddMesh(elbeemMesh *mesh) {
obj->setGeoInitId( mesh->parentDomainId+1 );
obj->setGeoInitIntersect(true);
obj->setGeoInitType(initType);
obj->setGeoPartSlipValue(mesh->obstaclePartslip);
// abuse partslip value for control fluid: reverse control keys or not
if(initType == FGI_CONTROL)
obj->setGeoPartSlipValue(mesh->obstacleType);
else
obj->setGeoPartSlipValue(mesh->obstaclePartslip);
obj->setGeoImpactFactor(mesh->obstacleImpactFactor);
/* fluid control features */
obj->setCpsTimeStart(mesh->cpsTimeStart);
obj->setCpsTimeEnd(mesh->cpsTimeEnd);
obj->setCpsQuality(mesh->cpsQuality);
if((mesh->volumeInitType<VOLUMEINIT_VOLUME)||(mesh->volumeInitType>VOLUMEINIT_BOTH)) mesh->volumeInitType = VOLUMEINIT_VOLUME;
obj->setVolumeInit(mesh->volumeInitType);
// use channel instead, obj->setInitialVelocity( ntlVec3Gfx(mesh->iniVelocity[0], mesh->iniVelocity[1], mesh->iniVelocity[2]) );
obj->initChannels(
mesh->channelSizeTranslation, mesh->channelTranslation,
mesh->channelSizeRotation, mesh->channelRotation,
mesh->channelSizeScale, mesh->channelScale,
mesh->channelSizeActive, mesh->channelActive,
mesh->channelSizeInitialVel, mesh->channelInitialVel
mesh->channelSizeInitialVel, mesh->channelInitialVel,
mesh->channelSizeAttractforceStrength, mesh->channelAttractforceStrength,
mesh->channelSizeAttractforceRadius, mesh->channelAttractforceRadius,
mesh->channelSizeVelocityforceStrength, mesh->channelVelocityforceStrength,
mesh->channelSizeVelocityforceRadius, mesh->channelVelocityforceRadius
);
obj->setLocalCoordInivel( mesh->localInivelCoords );
@@ -227,6 +266,7 @@ int elbeemSimulate(void) {
if(getElbeemState() != SIMWORLD_STOP) {
// ok, we're done...
delete gpWorld;
gpWorld = NULL;
debMsgStd("elbeemSimulate",DM_NOTIFY, "El'Beem simulation done, time: "<<getTimeString(timeend-timestart)<<".\n", 2 );
} else {

View File

@@ -1,240 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
* Copyright 2003-2006 Nils Thuerey
*
* API header
*/
#ifndef ELBEEM_API_H
#define ELBEEM_API_H
// simulation run callback function type (elbeemSimulationSettings->runsimCallback)
// best use with FLUIDSIM_CBxxx defines below.
// >parameters
// return values: 0=continue, 1=stop, 2=abort
// data pointer: user data pointer from elbeemSimulationSettings->runsimUserData
// status integer: 1=running simulation, 2=new frame saved
// frame integer: if status is 1, contains current frame number
typedef int (*elbeemRunSimulationCallback)(void *data, int status, int frame);
#define FLUIDSIM_CBRET_CONTINUE 0
#define FLUIDSIM_CBRET_STOP 1
#define FLUIDSIM_CBRET_ABORT 2
#define FLUIDSIM_CBSTATUS_STEP 1
#define FLUIDSIM_CBSTATUS_NEWFRAME 2
// global settings for the simulation
typedef struct elbeemSimulationSettings {
/* version number */
short version;
/* id number of simulation domain, needed if more than a
* single domain should be simulated */
short domainId;
/* geometrical extent */
float geoStart[3], geoSize[3];
/* resolutions */
short resolutionxyz;
short previewresxyz;
/* size of the domain in real units (meters along largest resolution x,y,z extent) */
float realsize;
/* fluid properties */
double viscosity;
/* gravity strength */
float gravity[3];
/* anim start end time */
float animStart, aniFrameTime;
/* no. of frames to simulate & output */
short noOfFrames;
/* g star param (LBM compressibility) */
float gstar;
/* activate refinement? */
short maxRefine;
/* probability for surface particle generation (0.0=off) */
float generateParticles;
/* amount of tracer particles to generate (0=off) */
int numTracerParticles;
/* store output path, and file prefix for baked fluid surface */
char outputPath[160+80];
/* channel for frame time, visc & gravity animations */
int channelSizeFrameTime;
float *channelFrameTime;
int channelSizeViscosity;
float *channelViscosity;
int channelSizeGravity;
float *channelGravity; // vector
/* boundary types and settings for domain walls */
short domainobsType;
float domainobsPartslip;
/* generate speed vectors for vertices (e.g. for image based motion blur)*/
short generateVertexVectors;
/* strength of surface smoothing */
float surfaceSmoothing;
/* no. of surface subdivisions */
int surfaceSubdivs;
/* global transformation to apply to fluidsim mesh */
float surfaceTrafo[4*4];
/* development variables, testing for upcoming releases...*/
float farFieldSize;
/* callback function to notify calling program of performed simulation steps
* or newly available frame data, if NULL it is ignored */
elbeemRunSimulationCallback runsimCallback;
/* pointer passed to runsimCallback for user data storage */
void* runsimUserData;
} elbeemSimulationSettings;
// defines for elbeemMesh->type below
#define OB_FLUIDSIM_FLUID 4
#define OB_FLUIDSIM_OBSTACLE 8
#define OB_FLUIDSIM_INFLOW 16
#define OB_FLUIDSIM_OUTFLOW 32
// defines for elbeemMesh->obstacleType below
#define FLUIDSIM_OBSTACLE_NOSLIP 1
#define FLUIDSIM_OBSTACLE_PARTSLIP 2
#define FLUIDSIM_OBSTACLE_FREESLIP 3
#define OB_VOLUMEINIT_VOLUME 1
#define OB_VOLUMEINIT_SHELL 2
#define OB_VOLUMEINIT_BOTH (OB_VOLUMEINIT_SHELL|OB_VOLUMEINIT_VOLUME)
// a single mesh object
typedef struct elbeemMesh {
/* obstacle,fluid or inflow... */
short type;
/* id of simulation domain it belongs to */
short parentDomainId;
/* vertices */
int numVertices;
float *vertices; // = float[n][3];
/* animated vertices */
int channelSizeVertices;
float *channelVertices; // = float[channelSizeVertices* (n*3+1) ];
/* triangles */
int numTriangles;
int *triangles; // = int[][3];
/* animation channels */
int channelSizeTranslation;
float *channelTranslation;
int channelSizeRotation;
float *channelRotation;
int channelSizeScale;
float *channelScale;
/* active channel */
int channelSizeActive;
float *channelActive;
/* initial velocity channel (e.g. for inflow) */
int channelSizeInitialVel;
float *channelInitialVel; // vector
/* use initial velocity in object coordinates? (e.g. for rotation) */
short localInivelCoords;
/* boundary types and settings */
short obstacleType;
float obstaclePartslip;
/* amount of force transfer from fluid to obj, 0=off, 1=normal */
float obstacleImpactFactor;
/* init volume, shell or both? use OB_VOLUMEINIT_xxx defines above */
short volumeInitType;
/* name of the mesh, mostly for debugging */
const char *name;
} elbeemMesh;
// API functions
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// reset elbeemSimulationSettings struct with defaults
void elbeemResetSettings(struct elbeemSimulationSettings*);
// start fluidsim init (returns !=0 upon failure)
int elbeemInit(void);
// start fluidsim init (returns !=0 upon failure)
int elbeemAddDomain(struct elbeemSimulationSettings*);
// get failure message during simulation or init
// if an error occured (the string is copied into buffer,
// max. length = 256 chars )
void elbeemGetErrorString(char *buffer);
// reset elbeemMesh struct with zeroes
void elbeemResetMesh(struct elbeemMesh*);
// add mesh as fluidsim object
int elbeemAddMesh(struct elbeemMesh*);
// do the actual simulation
int elbeemSimulate(void);
// continue a previously stopped simulation
int elbeemContinueSimulation(void);
// helper functions
// simplify animation channels
// returns if the channel and its size changed
int elbeemSimplifyChannelFloat(float *channel, int *size);
int elbeemSimplifyChannelVec3(float *channel, int *size);
// helper functions implemented in utilities.cpp
/* set elbeem debug output level (0=off to 10=full on) */
void elbeemSetDebugLevel(int level);
/* elbeem debug output function, prints if debug level >0 */
void elbeemDebugOut(char *msg);
/* estimate how much memory a given setup will require */
double elbeemEstimateMemreq(int res,
float sx, float sy, float sz,
int refine, char *retstr);
#ifdef __cplusplus
}
#endif // __cplusplus
/******************************************************************************/
// internal defines, do not use for initializing elbeemMesh
// structs, for these use OB_xxx defines above
/*! fluid geometry init types */
#define FGI_FLAGSTART 16
#define FGI_FLUID (1<<(FGI_FLAGSTART+ 0))
#define FGI_NO_FLUID (1<<(FGI_FLAGSTART+ 1))
#define FGI_BNDNO (1<<(FGI_FLAGSTART+ 2))
#define FGI_BNDFREE (1<<(FGI_FLAGSTART+ 3))
#define FGI_BNDPART (1<<(FGI_FLAGSTART+ 4))
#define FGI_NO_BND (1<<(FGI_FLAGSTART+ 5))
#define FGI_MBNDINFLOW (1<<(FGI_FLAGSTART+ 6))
#define FGI_MBNDOUTFLOW (1<<(FGI_FLAGSTART+ 7))
// all boundary types at once
#define FGI_ALLBOUNDS ( FGI_BNDNO | FGI_BNDFREE | FGI_BNDPART | FGI_MBNDINFLOW | FGI_MBNDOUTFLOW )
#endif // ELBEEM_API_H

View File

@@ -0,0 +1,25 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
* Copyright 2003-2006 Nils Thuerey
*
* Control API header
*/
#include "elbeem.h"
#include "elbeem_control.h"
// add mesh as fluidsim object
int elbeemControlAddSet(struct elbeemControl*) {
return 0;
}
int elbeemControlComputeMesh(struct elbeemMesh*) {
return 0;
}

View File

@@ -0,0 +1,62 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
* Copyright 2003-2006 Nils Thuerey
*
* Control API header
*/
#ifndef ELBEEMCONTROL_API_H
#define ELBEEMCONTROL_API_H
// a single control particle set
typedef struct elbeemControl {
/* influence forces */
float influenceAttraction;
float *channelInfluenceAttraction;
float channelSizeInfluenceAttraction;
float influenceVelocity;
float *channelInfluenceVelocity;
float channelSizeInfluenceVelocity;
float influenceMaxdist;
float *channelInfluenceMaxdist;
float channelSizeInfluenceMaxdist;
/* influence force radii */
float radiusAttraction;
float *channelRadiusAttraction;
float channelSizeRadiusAttraction;
float radiusVelocity;
float *channelRadiusVelocity;
float channelSizeRadiusVelocity;
float radiusMindist;
float *channelRadiusMindist;
float channelSizeRadiusMindist;
float radiusMaxdist;
float *channelRadiusMaxdist;
float channelSizeRadiusMaxdist;
/* control particle positions/scale */
float offset[3];
float *channelOffset;
float channelSizeOffset;
float scale[3];
float *channelScale;
float channelSizeScale;
} elbeemControl;
// add mesh as fluidsim object
int elbeemControlAddSet(struct elbeemControl*);
// sample & track mesh control particles, TODO add return type...
int elbeemControlComputeMesh(struct elbeemMesh*);
#endif // ELBEEMCONTROL_API_H

View File

@@ -13,8 +13,8 @@
#include <algorithm>
#include <stdio.h>
#if (defined (__sun__) || defined (__sun)) || (!defined(linux) && (defined (__sparc) || defined (__sparc__)))
#include <ieeefp.h>
#ifdef sun
#include "ieeefp.h"
#endif
// just use default rounding for platforms where its not available

View File

@@ -0,0 +1,193 @@
/******************************************************************************
*
// El'Beem - the visual lattice boltzmann freesurface simulator
// All code distributed as part of El'Beem is covered by the version 2 of the
// GNU General Public License. See the file COPYING for details.
//
// Copyright 2008 Nils Thuerey , Richard Keiser, Mark Pauly, Ulrich Ruede
//
*
* Mean Value Mesh Coords class
*
*****************************************************************************/
#include "mvmcoords.h"
#include <algorithm>
using std::vector;
void MeanValueMeshCoords::clear()
{
mVertices.resize(0);
mNumVerts = 0;
}
void MeanValueMeshCoords::calculateMVMCs(vector<ntlVec3Gfx> &reference_vertices, vector<ntlTriangle> &tris,
vector<ntlVec3Gfx> &points, gfxReal numweights)
{
clear();
mvmTransferPoint tds;
int mem = 0;
int i = 0;
mNumVerts = (int)reference_vertices.size();
for (vector<ntlVec3Gfx>::iterator iter = points.begin(); iter != points.end(); ++iter, ++i) {
/*
if(i%(points.size()/10)==1) debMsgStd("MeanValueMeshCoords::calculateMVMCs",DM_MSG,"Computing weights, points: "<<i<<"/"<<points.size(),5 );
*/
tds.lastpos = *iter;
tds.weights.resize(0); // clear
computeWeights(reference_vertices, tris, tds, numweights);
mem += (int)tds.weights.size();
mVertices.push_back(tds);
}
int mbmem = mem * sizeof(mvmFloat) / (1024*1024);
debMsgStd("MeanValueMeshCoords::calculateMVMCs",DM_MSG,"vertices:"<<mNumVerts<<" points:"<<points.size()<<" weights:"<<mem<<", wmem:"<<mbmem<<"MB ",7 );
}
// from: mean value coordinates for closed triangular meshes
// attention: fails if a point is exactly (or very close) to a vertex
void MeanValueMeshCoords::computeWeights(vector<ntlVec3Gfx> &reference_vertices, vector<ntlTriangle>& tris,
mvmTransferPoint& tds, gfxReal numweights)
{
const bool mvmFullDebug=false;
//const ntlVec3Gfx cEPS = 1.0e-6;
const mvmFloat cEPS = 1.0e-14;
//mvmFloat d[3], s[3], phi[3],c[3];
ntlVec3d u[3],c,d,s,phi;
int indices[3];
for (int i = 0; i < (int)reference_vertices.size(); ++i) {
tds.weights.push_back(mvmIndexWeight(i, 0.0));
}
// for each triangle
//for (vector<ntlTriangle>::iterator iter = tris.begin(); iter != tris.end();) {
for(int t=0; t<(int)tris.size(); t++) {
for (int i = 0; i < 3; ++i) { //, ++iter) {
indices[i] = tris[t].getPoints()[i];
u[i] = vec2D(reference_vertices[ indices[i] ]-tds.lastpos);
d[i] = normalize(u[i]); //.normalize();
//assert(d[i] != 0.);
if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","t"<<t<<" i"<<indices[i] //<<" lp"<<tds.lastpos
<<" v"<<reference_vertices[indices[i]]<<" u"<<u[i]<<" ");
// on vertex!
//? if(d[i]<=0.) continue;
}
//for (int i = 0; i < 3; ++i) { errMsg("III"," "<<i <<" i"<<indices[i]<<reference_vertices[ indices[i] ] ); }
// arcsin is not needed, see paper
phi[0] = 2.*asin( (mvmFloat)(0.5* norm(u[1]-u[2]) ) );
phi[1] = 2.*asin( (mvmFloat)(0.5* norm(u[0]-u[2]) ) );
phi[2] = 2.*asin( (mvmFloat)(0.5* norm(u[0]-u[1]) ) );
mvmFloat h = (phi[0] + phi[1] + phi[2])*0.5;
if (M_PI-h < cEPS) {
if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","point on triangle");
tds.weights.resize(0);
tds.weights.push_back( mvmIndexWeight(indices[0], sin(phi[0])*d[1]*d[2]));
tds.weights.push_back( mvmIndexWeight(indices[1], sin(phi[1])*d[0]*d[2]));
tds.weights.push_back( mvmIndexWeight(indices[2], sin(phi[2])*d[1]*d[0]));
break;
}
mvmFloat sinh = 2.*sin(h);
c[0] = (sinh*sin(h-phi[0]))/(sin(phi[1])*sin(phi[2]))-1.;
c[1] = (sinh*sin(h-phi[1]))/(sin(phi[0])*sin(phi[2]))-1.;
c[2] = (sinh*sin(h-phi[2]))/(sin(phi[0])*sin(phi[1]))-1.;
if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","c="<<c<<" phi="<<phi<<" d="<<d);
//if (c[0] > 1. || c[0] < 0. || c[1] > 1. || c[1] < 0. || c[2] > 1. || c[2] < 0.) continue;
s[0] = sqrtf((float)(1.-c[0]*c[0]));
s[1] = sqrtf((float)(1.-c[1]*c[1]));
s[2] = sqrtf((float)(1.-c[2]*c[2]));
if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","s");
if (s[0] <= cEPS || s[1] <= cEPS || s[2] <= cEPS) {
//MSG("position lies outside the triangle on the same plane -> ignore it");
continue;
}
const mvmFloat u0x = u[0][0];
const mvmFloat u0y = u[0][1];
const mvmFloat u0z = u[0][2];
const mvmFloat u1x = u[1][0];
const mvmFloat u1y = u[1][1];
const mvmFloat u1z = u[1][2];
const mvmFloat u2x = u[2][0];
const mvmFloat u2y = u[2][1];
const mvmFloat u2z = u[2][2];
mvmFloat det = u0x*u1y*u2z - u0x*u1z*u2y + u0y*u1z*u2x - u0y*u1x*u2z + u0z*u1x*u2y - u0z*u1y*u2x;
//assert(det != 0.);
if (det < 0.) {
s[0] = -s[0];
s[1] = -s[1];
s[2] = -s[2];
}
tds.weights[indices[0]].weight += (phi[0]-c[1]*phi[2]-c[2]*phi[1])/(d[0]*sin(phi[1])*s[2]);
tds.weights[indices[1]].weight += (phi[1]-c[2]*phi[0]-c[0]*phi[2])/(d[1]*sin(phi[2])*s[0]);
tds.weights[indices[2]].weight += (phi[2]-c[0]*phi[1]-c[1]*phi[0])/(d[2]*sin(phi[0])*s[1]);
if(mvmFullDebug) { errMsg("MeanValueMeshCoords::computeWeights","i"<<indices[0]<<" o"<<tds.weights[indices[0]].weight);
errMsg("MeanValueMeshCoords::computeWeights","i"<<indices[1]<<" o"<<tds.weights[indices[1]].weight);
errMsg("MeanValueMeshCoords::computeWeights","i"<<indices[2]<<" o"<<tds.weights[indices[2]].weight);
errMsg("MeanValueMeshCoords::computeWeights","\n\n\n"); }
}
//sort weights
if((numweights>0.)&& (numweights<1.) ) {
//if( ((int)tds.weights.size() > maxNumWeights) && (maxNumWeights > 0) ) {
int maxNumWeights = (int)(tds.weights.size()*numweights);
if(maxNumWeights<=0) maxNumWeights = 1;
std::sort(tds.weights.begin(), tds.weights.end(), std::greater<mvmIndexWeight>());
// only use maxNumWeights-th largest weights
tds.weights.resize(maxNumWeights);
}
// normalize weights
mvmFloat totalWeight = 0.;
for (vector<mvmIndexWeight>::const_iterator witer = tds.weights.begin();
witer != tds.weights.end(); ++witer) {
totalWeight += witer->weight;
}
mvmFloat invTotalWeight;
if (totalWeight == 0.) {
if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","totalWeight == 0");
invTotalWeight = 0.0;
} else {
invTotalWeight = 1.0/totalWeight;
}
for (vector<mvmIndexWeight>::iterator viter = tds.weights.begin();
viter != tds.weights.end(); ++viter) {
viter->weight *= invTotalWeight;
//assert(finite(viter->weight) != 0);
if(!finite(viter->weight)) viter->weight=0.;
}
}
void MeanValueMeshCoords::transfer(vector<ntlVec3Gfx> &vertices, vector<ntlVec3Gfx>& displacements)
{
displacements.resize(0);
//debMsgStd("MeanValueMeshCoords::transfer",DM_MSG,"vertices:"<<mNumVerts<<" curr_verts:"<<vertices.size()<<" ",7 );
if((int)vertices.size() != mNumVerts) {
errMsg("MeanValueMeshCoords::transfer","Different no of verts: "<<vertices.size()<<" vs "<<mNumVerts);
return;
}
for (vector<mvmTransferPoint>::iterator titer = mVertices.begin(); titer != mVertices.end(); ++titer) {
mvmTransferPoint &tds = *titer;
ntlVec3Gfx newpos(0.0);
for (vector<mvmIndexWeight>::iterator witer = tds.weights.begin();
witer != tds.weights.end(); ++witer) {
newpos += vertices[witer->index] * witer->weight;
//errMsg("transfer","np"<<newpos<<" v"<<vertices[witer->index]<<" w"<< witer->weight);
}
displacements.push_back(newpos);
//displacements.push_back(newpos - tds.lastpos);
//tds.lastpos = newpos;
}
}

View File

@@ -0,0 +1,89 @@
/******************************************************************************
*
// El'Beem - the visual lattice boltzmann freesurface simulator
// All code distributed as part of El'Beem is covered by the version 2 of the
// GNU General Public License. See the file COPYING for details.
//
// Copyright 2008 Nils Thuerey , Richard Keiser, Mark Pauly, Ulrich Ruede
//
*
* Mean Value Mesh Coords class
*
*****************************************************************************/
#ifndef MVMCOORDS_H
#define MVMCOORDS_H
#include "utilities.h"
#include "ntl_ray.h"
#include <vector>
#define mvmFloat double
#ifdef WIN32
#ifndef FREE_WINDOWS
#include "float.h"
#define isnan(n) _isnan(n)
#define finite _finite
#endif
#endif
#ifdef sun
#include "ieeefp.h"
#endif
// weight and triangle index
class mvmIndexWeight {
public:
mvmIndexWeight() : weight(0.0) {}
mvmIndexWeight(int const& i, mvmFloat const& w) :
weight(w), index(i) {}
// for sorting
bool operator> (mvmIndexWeight const& w) const { return this->weight > w.weight; }
bool operator< (mvmIndexWeight const& w) const { return this->weight < w.weight; }
mvmFloat weight;
int index;
};
// transfer point with weights
class mvmTransferPoint {
public:
//! position of transfer point
ntlVec3Gfx lastpos;
//! triangle weights
std::vector<mvmIndexWeight> weights;
};
//! compute mvmcs
class MeanValueMeshCoords {
public:
MeanValueMeshCoords() {}
~MeanValueMeshCoords() {
clear();
}
void clear();
void calculateMVMCs(std::vector<ntlVec3Gfx> &reference_vertices,
std::vector<ntlTriangle> &tris, std::vector<ntlVec3Gfx> &points, gfxReal numweights);
void transfer(std::vector<ntlVec3Gfx> &vertices, std::vector<ntlVec3Gfx>& displacements);
protected:
void computeWeights(std::vector<ntlVec3Gfx> &reference_vertices,
std::vector<ntlTriangle> &tris, mvmTransferPoint& tds, gfxReal numweights);
std::vector<mvmTransferPoint> mVertices;
int mNumVerts;
};
#endif

View File

@@ -37,6 +37,7 @@ class ntlGeometryClass
//! Default destructor
virtual ~ntlGeometryClass() {
delete mpAttrs;
delete mpSwsAttrs;
};
//! Return type id

View File

@@ -41,7 +41,9 @@ ntlGeometryObject::ntlGeometryObject() :
mCachedMovPoints(), mCachedMovNormals(),
mTriangleDivs1(), mTriangleDivs2(), mTriangleDivs3(),
mMovPntsInited(-100.0), mMaxMovPnt(-1),
mcGeoActive(1.)
mcGeoActive(1.),
mCpsTimeStart(0.), mCpsTimeEnd(1.0), mCpsQuality(10.),
mcAttrFStr(0.),mcAttrFRad(0.), mcVelFStr(0.), mcVelFRad(0.)
{
};
@@ -82,20 +84,21 @@ bool ntlGeometryObject::checkIsAnimated() {
/*****************************************************************************/
/* Init attributes etc. of this object */
/*****************************************************************************/
#define GEOINIT_STRINGS 9
#define GEOINIT_STRINGS 10
static const char *initStringStrs[GEOINIT_STRINGS] = {
"fluid",
"bnd_no","bnd_noslip",
"bnd_free","bnd_freeslip",
"bnd_part","bnd_partslip",
"inflow", "outflow"
"inflow", "outflow", "control",
};
static int initStringTypes[GEOINIT_STRINGS] = {
FGI_FLUID,
FGI_BNDNO, FGI_BNDNO,
FGI_BNDFREE, FGI_BNDFREE,
FGI_BNDPART, FGI_BNDPART,
FGI_MBNDINFLOW, FGI_MBNDOUTFLOW
FGI_MBNDINFLOW, FGI_MBNDOUTFLOW,
FGI_CONTROL
};
void ntlGeometryObject::initialize(ntlRenderGlobals *glob)
{
@@ -330,7 +333,11 @@ void ntlGeometryObject::sceneAddTriangleNoVert(int *trips,
void ntlGeometryObject::initChannels(
int nTrans, float *trans, int nRot, float *rot, int nScale, float *scale,
int nAct, float *act, int nIvel, float *ivel
int nAct, float *act, int nIvel, float *ivel,
int nAttrFStr, float *attrFStr,
int nAttrFRad, float *attrFRad,
int nVelFStr, float *velFStr,
int nVelFRad, float *velFRad
) {
const bool debugInitc=true;
if(debugInitc) { debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"nt:"<<nTrans<<" nr:"<<nRot<<" ns:"<<nScale, 10);
@@ -343,8 +350,15 @@ void ntlGeometryObject::initChannels(
if((scale)&&(nScale>0)) { ADD_CHANNEL_VEC(mcScale, nScale, scale); }
if((act)&&(nAct>0)) { ADD_CHANNEL_FLOAT(mcGeoActive, nAct, act); }
if((ivel)&&(nIvel>0)) { ADD_CHANNEL_VEC(mcInitialVelocity, nIvel, ivel); }
/* fluid control channels */
if((attrFStr)&&(nAttrFStr>0)) { ADD_CHANNEL_FLOAT(mcAttrFStr, nAttrFStr, attrFStr); }
if((attrFRad)&&(nAttrFRad>0)) { ADD_CHANNEL_FLOAT(mcAttrFRad, nAttrFRad, attrFRad); }
if((velFStr)&&(nVelFStr>0)) { ADD_CHANNEL_FLOAT(mcVelFStr, nAct, velFStr); }
if((velFRad)&&(nVelFRad>0)) { ADD_CHANNEL_FLOAT(mcVelFRad, nVelFRad, velFRad); }
checkIsAnimated();
if(debugInitc) {
debMsgStd("ntlGeometryObject::initChannels",DM_MSG,getName()<<
" nt:"<<mcTrans.accessValues().size()<<" nr:"<<mcRot.accessValues().size()<<
@@ -565,7 +579,7 @@ void ntlGeometryObject::initMovingPoints(double time, gfxReal featureSize) {
}
}
if( (this-getMeshAnimated())
if( (this->getMeshAnimated())
|| (mcTrans.accessValues().size()>1) // VALIDATE
|| (mcRot.accessValues().size()>1)
|| (mcScale.accessValues().size()>1)

View File

@@ -97,11 +97,37 @@ class ntlGeometryObject : public ntlGeometryClass
/*! Set/get the local inivel coords flag */
inline bool getLocalCoordInivel() const { return mLocalCoordInivel; }
inline void setLocalCoordInivel(bool set) { mLocalCoordInivel=set; }
/****************************************/
/* fluid control features */
/****************************************/
/*! Set/get the particle control set attract force strength */
inline float getCpsTimeStart() const { return mCpsTimeStart; }
inline void setCpsTimeStart(float set) { mCpsTimeStart=set; }
/*! Set/get the particle control set attract force strength */
inline float getCpsTimeEnd() const { return mCpsTimeEnd; }
inline void setCpsTimeEnd(float set) { mCpsTimeEnd=set; }
/*! Set/get the particle control set quality */
inline float getCpsQuality() const { return mCpsQuality; }
inline void setCpsQuality(float set) { mCpsQuality=set; }
inline AnimChannel<float> getCpsAttrFStr() const { return mcAttrFStr; }
inline AnimChannel<float> getCpsAttrFRad() const { return mcAttrFRad; }
inline AnimChannel<float> getCpsVelFStr() const { return mcVelFStr; }
inline AnimChannel<float> getCpsVelFRad() const { return mcVelFRad; }
/****************************************/
/*! Init channels from float arrays (for elbeem API) */
void initChannels(
int nTrans, float *trans, int nRot, float *rot, int nScale, float *scale,
int nAct, float *act, int nIvel, float *ivel
int nAct, float *act, int nIvel, float *ivel,
int nAttrFStr, float *attrFStr,
int nAttrFRad, float *attrFRad,
int nVelFStr, float *velFStr,
int nVelFRad, float *velFRad
);
/*! is the object animated? */
@@ -202,6 +228,12 @@ class ntlGeometryObject : public ntlGeometryClass
/*! animated channels for in/outflow on/off */
AnimChannel<float> mcGeoActive;
/* fluid control settings */
float mCpsTimeStart;
float mCpsTimeEnd;
float mCpsQuality;
AnimChannel<float> mcAttrFStr, mcAttrFRad, mcVelFStr, mcVelFRad;
public:

View File

@@ -688,7 +688,8 @@ ntlScene::~ntlScene()
if(mpTree != NULL) delete mpTree;
// cleanup lists, only if this is the rendering cleanup scene
if(mSceneDel) {
if(mSceneDel)
{
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
iter != mGeos.end(); iter++) {
//errMsg("ntlScene::~ntlScene","Deleting obj "<<(*iter)->getName() );

View File

@@ -20,6 +20,7 @@ class ntlRay;
class ntlTree;
class ntlScene;
class ntlRenderGlobals;
class ntlGeometryObject;
//! store data for an intersection of a ray and a triangle
// NOT YET USED
@@ -323,8 +324,8 @@ public:
/* CONSTRUCTORS */
/*! Default constructor */
ntlScene( ntlRenderGlobals *glob, bool del=true );
/*! Default destructor */
~ntlScene();
/*! Default destructor */
~ntlScene();
/*! Add an object to the scene */
inline void addGeoClass(ntlGeometryClass *geo) {

View File

@@ -236,10 +236,15 @@ ntlWorld::~ntlWorld()
{
delete mpGlob->getRenderScene();
delete mpGlob->getSimScene();
delete mpGlob;
delete mpLightList;
delete mpPropList;
delete mpSims;
delete mpGlob;
// these get assigned to mpGlob but not freed there
delete mpLightList;
delete mpPropList; // materials
delete mpSims;
#ifndef NOGUI
if(mpOpenGLRenderer) delete mpOpenGLRenderer;
#endif // NOGUI
@@ -895,6 +900,8 @@ ntlRenderGlobals::ntlRenderGlobals() :
ntlRenderGlobals::~ntlRenderGlobals() {
if(mpOpenGlAttr) delete mpOpenGlAttr;
if(mpBlenderAttr) delete mpBlenderAttr;
}

View File

@@ -58,7 +58,8 @@ SimulationObject::~SimulationObject()
if(mpGiTree) delete mpGiTree;
if(mpElbeemSettings) delete mpElbeemSettings;
if(mpLbm) delete mpLbm;
if(mpParam) delete mpParam;
if(mpParam) delete mpParam;
if(mpParts) delete mpParts;
debMsgStd("SimulationObject",DM_MSG,"El'Beem Done!\n",10);
}

View File

@@ -11,9 +11,7 @@
#include "solver_relax.h"
#include "particletracer.h"
#if (defined (__sun__) || defined (__sun)) || (!defined(linux) && (defined (__sparc) || defined (__sparc__)))
#include <ieeefp.h>
#endif
/*****************************************************************************/
//! coarse step functions

View File

@@ -100,11 +100,14 @@
// sirdude fix for solaris
#if !defined(linux) && defined(sun)
#include "ieeefp.h"
#ifndef expf
#define expf(x) exp((double)(x))
#endif
#endif
#include "solver_control.h"
#if LBM_INCLUDE_TESTSOLVERS==1
#include "solver_test.h"
#endif // LBM_INCLUDE_TESTSOLVERS==1
@@ -497,6 +500,12 @@ class LbmFsgrSolver :
LbmFloat& debRAC(LbmFloat* s,int l);
# endif // FSGR_STRICT_DEBUG==1
LbmControlData *mpControl;
void initCpdata();
void handleCpdata();
void cpDebugDisplay(int dispset);
bool mUseTestdata;
# if LBM_INCLUDE_TESTSOLVERS==1
// test functions
@@ -506,10 +515,6 @@ class LbmFsgrSolver :
void handleTestdata();
void set3dHeight(int ,int );
void initCpdata();
void handleCpdata();
void cpDebugDisplay(int dispset);
int mMpNum,mMpIndex;
int mOrgSizeX;
LbmFloat mOrgStartX;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
/******************************************************************************
*
* El'Beem - the visual lattice boltzmann freesurface simulator
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
* Copyright 2003-2006 Nils Thuerey
*
* testing extensions
*
*****************************************************************************/
#ifndef LBM_TESTCLASS_H
#define LBM_TESTCLASS_H
//class IsoSurface;
class ParticleObject;
class ControlParticles;
class ControlForces;
//#define NUMGRIDS 2
//#define MAXNUMSWS 10
// farfield modes
#define FARF_3DONLY -1
#define FARF_BOTH 0
#define FARF_SWEONLY 1
// dont reuse 3d vars/init
#define FARF_SEPSWE 2
// relaxation macros for solver_relax.h
// WARNING has to match controlparts.h
#define CPF_ENTRIES 12
#define CPF_FORCE 0
#define CPF_VELWEIGHT 3
#define CPF_VELOCITY 4
#define CPF_FORCEWEIGHT 7
#define CPF_MINCPDIST 8
#define CPF_MINCPDIR 9
#include "controlparticles.h"
#include "ntl_geometrymodel.h"
// get force entry, set=0 is unused anyway
#define LBMGET_FORCE(lev, i,j,k) mpControl->mCpForces[lev][ (LBMGI(lev,i,j,k,0)) ]
// debug mods off...
// same as in src/solver_relax.h!
#define __PRECOLLIDE_MODS(rho,ux,uy,uz, grav) \
ux += (grav)[0]; \
uy += (grav)[1]; \
uz += (grav)[2];
//void testMaxdmod(int i, int j,int k, LbmFloat &ux,LbmFloat &uy,LbmFloat &uz,ControlForces &ff);
#if LBMDIM==3
#define MAXDGRAV \
if(myforce->forceMaxd[0]*ux+myforce->forceMaxd[1]*uy<LBM_EPSILON) { \
ux = v2w*myforce->forceVel[0]+ v2wi*ux; \
uy = v2w*myforce->forceVel[1]+ v2wi*uy; } \
/* movement inverse to g? */ \
if((uz>LBM_EPSILON)&&(uz>myforce->forceVel[2])) { \
uz = v2w*myforce->forceVel[2]+ v2wi*uz; }
#else // LBMDIM==3
#define MAXDGRAV \
if(myforce->forceMaxd[0]*ux<LBM_EPSILON) { \
ux = v2w*myforce->forceVel[0]+ v2wi*ux; } \
/* movement inverse to g? */ \
if((uy>LBM_EPSILON)&&(uy>myforce->forceVel[1])) { \
uy = v2w*myforce->forceVel[1]+ v2wi*uy; }
#endif // LBMDIM==3
// debug modifications of collide vars (testing)
// requires: lev,i,j,k
#define PRECOLLIDE_MODS(rho,ux,uy,uz, grav) \
LbmFloat attforce = 1.; \
if(this->mTForceStrength>0.) { \
ControlForces* myforce = &LBMGET_FORCE(lev,i,j,k); \
const LbmFloat vf = myforce->weightAtt;\
const LbmFloat vw = myforce->weightVel;\
if(vf!=0.) { attforce = MAX(0., 1.-vf); /* TODO FIXME? use ABS(vf) for repulsion force? */ \
ux += myforce->forceAtt[0]; \
uy += myforce->forceAtt[1]; \
uz += myforce->forceAtt[2]; \
\
} else if(( myforce->maxDistance>0.) && ( myforce->maxDistance<CPF_MAXDINIT)) {\
const LbmFloat v2w = mpControl->mCons[0]->mCparts->getInfluenceMaxdist() * \
(myforce->maxDistance-mpControl->mCons[0]->mCparts->getRadiusMinMaxd()) / (mpControl->mCons[0]->mCparts->getRadiusMaxd()-mpControl->mCons[0]->mCparts->getRadiusMinMaxd()); \
const LbmFloat v2wi = 1.-v2w; \
if(v2w>0.){ MAXDGRAV; \
/* errMsg("ERRMDTT","at "<<PRINT_IJK<<" maxd="<<myforce->maxDistance<<", newu"<<PRINT_VEC(ux,uy,uz)<<", org"<<PRINT_VEC(oux,ouy,ouz)<<", fv"<<myforce->forceVel<<" " ); */ \
}\
} \
if(vw>0.) { \
const LbmFloat vwi = 1.-vw;\
const LbmFloat vwd = mpControl->mDiffVelCon;\
ux += vw*(myforce->forceVel[0]-myforce->compAv[0] + vwd*(myforce->compAv[0]-ux) ); \
uy += vw*(myforce->forceVel[1]-myforce->compAv[1] + vwd*(myforce->compAv[1]-uy) ); \
uz += vw*(myforce->forceVel[2]-myforce->compAv[2] + vwd*(myforce->compAv[2]-uz) ); \
/* TODO test!? modify smooth vel by influence of force for each lbm step, to account for force update only each N steps */ \
myforce->compAv = (myforce->forceVel*vw+ myforce->compAv*vwi); \
} \
} \
ux += (grav)[0]*attforce; \
uy += (grav)[1]*attforce; \
uz += (grav)[2]*attforce; \
/* end PRECOLLIDE_MODS */
#define TEST_IF_CHECK \
if((!iffilled)&&(LBMGET_FORCE(lev,i,j,k).weightAtt!=0.)) { \
errMsg("TESTIFFILL"," at "<<PRINT_IJK<<" "<<mass<<" "<<rho); \
iffilled = true; \
if(mass<rho*1.0) mass = rho*1.0; myfrac = 1.0; \
}
// a single set of control particles and params
class LbmControlSet {
public:
LbmControlSet();
~LbmControlSet();
void initCparts();
// control particles
ControlParticles *mCparts;
// control particle overall motion (for easier manual generation)
ControlParticles *mCpmotion;
// cp data file
string mContrPartFile;
string mCpmotionFile;
// cp debug displau
LbmFloat mDebugCpscale, mDebugVelScale, mDebugCompavScale, mDebugAttScale, mDebugMaxdScale, mDebugAvgVelScale;
// params
AnimChannel<float> mcForceAtt;
AnimChannel<float> mcForceVel;
AnimChannel<float> mcForceMaxd;
AnimChannel<float> mcRadiusAtt;
AnimChannel<float> mcRadiusVel;
AnimChannel<float> mcRadiusMind;
AnimChannel<float> mcRadiusMaxd;
AnimChannel<ntlVec3f> mcCpScale;
AnimChannel<ntlVec3f> mcCpOffset;
};
// main control data storage
class LbmControlData
{
public:
LbmControlData();
virtual ~LbmControlData();
// control data
// contorl params
void parseControldataAttrList(AttributeList *attr);
// control strength, set for solver interface
LbmFloat mSetForceStrength;
// cp vars
std::vector<LbmControlSet*> mCons;
// update interval
int mCpUpdateInterval;
// output
string mCpOutfile;
// control particle precomputed influence
std::vector< std::vector<ControlForces> > mCpForces;
std::vector<ControlForces> mCpKernel;
std::vector<ControlForces> mMdKernel;
// activate differential velcon
LbmFloat mDiffVelCon;
// cp debug displau
LbmFloat mDebugCpscale, mDebugVelScale, mDebugCompavScale, mDebugAttScale, mDebugMaxdScale, mDebugAvgVelScale;
};
#endif // LBM_TESTCLASS_H

View File

@@ -328,7 +328,8 @@ LbmFsgrSolver::LbmFsgrSolver() :
mInit2dYZ(false),
mForceTadapRefine(-1), mCutoff(-1)
{
// not much to do here...
mpControl = new LbmControlData();
#if LBM_INCLUDE_TESTSOLVERS==1
mpTest = new LbmTestdata();
mMpNum = mMpIndex = 0;
@@ -438,6 +439,8 @@ LbmFsgrSolver::~LbmFsgrSolver()
delete mpIso;
if(mpPreviewSurface) delete mpPreviewSurface;
// cleanup done during scene deletion...
if(mpControl) delete mpControl;
// always output performance estimate
debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG," Avg. MLSUPS:"<<(mAvgMLSUPS/mAvgMLSUPSCnt), 5);
@@ -488,6 +491,8 @@ void LbmFsgrSolver::parseAttrList()
mSimulationTime += starttimeskip;
if(starttimeskip>0.) debMsgStd("LbmFsgrSolver::parseStdAttrList",DM_NOTIFY,"Used starttimeskip="<<starttimeskip<<", t="<<mSimulationTime, 1);
mpControl->parseControldataAttrList(mpSifAttrs);
#if LBM_INCLUDE_TESTSOLVERS==1
mUseTestdata = 0;
mUseTestdata = mpSifAttrs->readBool("use_testdata", mUseTestdata,"LbmFsgrSolver", "mUseTestdata", false);
@@ -689,21 +694,21 @@ bool LbmFsgrSolver::initializeSolverMemory()
// restrict max. chunk of 1 mem block to 1GB for windos
bool memBlockAllocProblem = false;
double maxWinMemChunk = 1100.*1024.*1024.;
double maxMacMemChunk = 1200.*1024.*1024.;
double maxDefaultMemChunk = 2.*1024.*1024.*1024.;
//std::cerr<<" memEstFine "<< memEstFine <<" maxWin:" <<maxWinMemChunk <<" maxMac:" <<maxMacMemChunk ; // DEBUG
#ifdef WIN32
double maxWinMemChunk = 1100.*1024.*1024.;
if(sizeof(void *)==4 && memEstFine>maxWinMemChunk) {
memBlockAllocProblem = true;
}
#endif // WIN32
#ifdef __APPLE__
double maxMacMemChunk = 1200.*1024.*1024.;
if(memEstFine> maxMacMemChunk) {
memBlockAllocProblem = true;
}
#endif // Mac
if(sizeof(void *)==4 && memEstFine>maxDefaultMemChunk) {
if(sizeof(void*)==4 && memEstFine>maxDefaultMemChunk) {
// max memory chunk for 32bit systems 2gig
memBlockAllocProblem = true;
}
@@ -1264,8 +1269,10 @@ bool LbmFsgrSolver::initializeSolverPostinit() {
debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init done ... ",10);
mInitDone = 1;
#if LBM_INCLUDE_TESTSOLVERS==1
// init fluid control
initCpdata();
#if LBM_INCLUDE_TESTSOLVERS==1
initTestdata();
#endif // ELBEEM_PLUGIN!=1
// not inited? dont use...

View File

@@ -13,11 +13,6 @@
#include "loop_tools.h"
#include <stdlib.h>
#if (defined (__sun__) || defined (__sun)) || (!defined(linux) && (defined (__sparc) || defined (__sparc__)))
#include <ieeefp.h>
#endif
/*****************************************************************************/
/*! perform a single LBM step */
/*****************************************************************************/
@@ -58,9 +53,9 @@ void LbmFsgrSolver::stepMain() {
// init moving bc's, can change mMaxVlen
initMovingObstacles(false);
#if LBM_INCLUDE_TESTSOLVERS==1
// handle fluid control
handleCpdata();
#endif
// important - keep for tadap
LbmFloat lastMass = mCurrentMass;

View File

@@ -14,53 +14,6 @@
#else // FSGR_STRICT_DEBUG==1
#define CAUSE_PANIC { this->mPanic=1; } /*set flag*/
#endif // FSGR_STRICT_DEBUG==1
#if LBM_INCLUDE_TESTSOLVERS!=1
#define PRECOLLIDE_MODS(rho,ux,uy,uz, grav) \
ux += (grav)[0]; \
uy += (grav)[1]; \
uz += (grav)[2];
#define TEST_IF_CHECK
#else // LBM_INCLUDE_TESTSOLVERS!=1
// defined in test.h
#define NEWDIRVELMOTEST 0
#if NEWDIRVELMOTEST==1
// off for non testing
#undef PRECOLLIDE_MODS
#define PRECOLLIDE_MODS(rho,ux,uy,uz, grav) \
ux += (grav)[0]; \
uy += (grav)[1]; \
uz += (grav)[2]; \
{ \
int lev = mMaxRefine, nomb=0; \
LbmFloat bcnt = 0.,nux=0.,nuy=0.,nuz=0.; \
for(int l=1; l<this->cDfNum; l++) { \
if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { \
if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBndMoving) { \
nux += QCELL_NB(lev, i,j,k,SRCS(lev),l, dMass); \
nuy += QCELL_NB(lev, i,j,k,SRCS(lev),l, dFfrac); \
bcnt += 1.; \
} else { \
nomb++; \
} \
} \
} \
if((bcnt>0.)&&(nomb==0)) { \
ux = nux/bcnt; \
uy = nuy/bcnt; \
uz = nuz/bcnt; \
} \
}
#else // NEWDIRVELMOTEST==1
// off for non testing
#endif // NEWDIRVELMOTEST==1
#endif // LBM_INCLUDE_TESTSOLVERS!=1
/******************************************************************************
* normal relaxation

View File

@@ -19,8 +19,8 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\intern;..\..\..\..\..\lib\windows\png\include;..\..\..\..\..\lib\windows\zlib\include;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\..\lib\windows\sdl\include"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;NOGUI;ELBEEM_BLENDER=1"
AdditionalIncludeDirectories="..\..\intern;..\..\extern;..\..\..\..\..\lib\windows\png\include;..\..\..\..\..\lib\windows\zlib\include;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\..\lib\windows\sdl\include"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;NOGUI;ELBEEM_BLENDER=1;LBM_INCLUDE_CONTROL=1"
MinimalRebuild="FALSE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@@ -72,8 +72,8 @@ ECHO Done
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\intern;..\..\..\..\..\lib\windows\png\include;..\..\..\..\..\lib\windows\zlib\include;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\..\lib\windows\sdl\include"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;NOGUI;ELBEEM_BLENDER=1"
AdditionalIncludeDirectories="..\..\intern;..\..\extern;..\..\..\..\..\lib\windows\png\include;..\..\..\..\..\lib\windows\zlib\include;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\..\lib\windows\sdl\include"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;NOGUI;ELBEEM_BLENDER=1;LBM_INCLUDE_CONTROL=1"
StringPooling="TRUE"
MinimalRebuild="FALSE"
RuntimeLibrary="0"
@@ -126,7 +126,7 @@ ECHO Done
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\intern;..\..\..\..\..\lib\windows\png\include;..\..\..\..\..\lib\windows\zlib\include;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\..\lib\windows\sdl\include"
AdditionalIncludeDirectories="..\..\intern;..\..\extern;..\..\..\..\..\lib\windows\png\include;..\..\..\..\..\lib\windows\zlib\include;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\..\lib\windows\sdl\include"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;NOGUI;ELBEEM_BLENDER=1"
MinimalRebuild="FALSE"
BasicRuntimeChecks="3"
@@ -179,7 +179,7 @@ ECHO Done
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\intern;..\..\..\..\..\lib\windows\png\include;..\..\..\..\..\lib\windows\zlib\include;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\..\lib\windows\sdl\include"
AdditionalIncludeDirectories="..\..\intern;..\..\extern;..\..\..\..\..\lib\windows\png\include;..\..\..\..\..\lib\windows\zlib\include;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\..\lib\windows\sdl\include"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;NOGUI;ELBEEM_BLENDER=1"
StringPooling="TRUE"
MinimalRebuild="FALSE"
@@ -235,12 +235,21 @@ ECHO Done
<File
RelativePath="..\..\intern\attributes.cpp">
</File>
<File
RelativePath="..\..\intern\controlparticles.cpp">
</File>
<File
RelativePath="..\..\intern\elbeem.cpp">
</File>
<File
RelativePath="..\..\intern\elbeem_control.cpp">
</File>
<File
RelativePath="..\..\intern\isosurface.cpp">
</File>
<File
RelativePath="..\..\intern\mvmcoords.cpp">
</File>
<File
RelativePath="..\..\intern\ntl_blenderdumper.cpp">
</File>
@@ -274,6 +283,9 @@ ECHO Done
<File
RelativePath="..\..\intern\solver_adap.cpp">
</File>
<File
RelativePath="..\..\intern\solver_control.cpp">
</File>
<File
RelativePath="..\..\intern\solver_init.cpp">
</File>
@@ -298,7 +310,13 @@ ECHO Done
RelativePath="..\..\intern\attributes.h">
</File>
<File
RelativePath="..\..\intern\elbeem.h">
RelativePath="..\..\intern\controlparticles.h">
</File>
<File
RelativePath="..\..\extern\elbeem.h">
</File>
<File
RelativePath="..\..\intern\elbeem_control.h">
</File>
<File
RelativePath="..\..\intern\isosurface.h">
@@ -306,6 +324,9 @@ ECHO Done
<File
RelativePath="..\..\intern\mcubes_tables.h">
</File>
<File
RelativePath="..\..\intern\mvmcoords.h">
</File>
<File
RelativePath="..\..\intern\ntl_blenderdumper.h">
</File>
@@ -351,6 +372,9 @@ ECHO Done
<File
RelativePath="..\..\intern\solver_class.h">
</File>
<File
RelativePath="..\..\intern\solver_control.h">
</File>
<File
RelativePath="..\..\intern\solver_interface.h">
</File>

View File

@@ -96,25 +96,17 @@ GHOST_SystemX11(
if (!m_display) return;
#ifdef __sgi
m_delete_window_atom = XSGIFastInternAtom(m_display,
m_delete_window_atom
= XSGIFastInternAtom(m_display,
"WM_DELETE_WINDOW",
SGI_XA_WM_DELETE_WINDOW, False);
#else
m_delete_window_atom = XInternAtom(m_display, "WM_DELETE_WINDOW", False);
m_delete_window_atom
= XInternAtom(m_display, "WM_DELETE_WINDOW", True);
#endif
m_wm_protocols= XInternAtom(m_display, "WM_PROTOCOLS", False);
m_wm_take_focus= XInternAtom(m_display, "WM_TAKE_FOCUS", False);
m_wm_state= XInternAtom(m_display, "WM_STATE", False);
m_wm_change_state= XInternAtom(m_display, "WM_CHANGE_STATE", False);
m_net_state= XInternAtom(m_display, "_NET_WM_STATE", False);
m_net_max_horz= XInternAtom(m_display,
"_NET_WM_STATE_MAXIMIZED_HORZ", False);
m_net_max_vert= XInternAtom(m_display,
"_NET_WM_STATE_MAXIMIZED_VERT", False);
m_net_fullscreen= XInternAtom(m_display,
"_NET_WM_STATE_FULLSCREEN", False);
m_motif= XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
// compute the initial time
timeval tv;
@@ -522,12 +514,10 @@ GHOST_SystemX11::processEvent(XEvent *xe)
GHOST_kEventNDOFButton,
window, data);
}
}
else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
} else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
/* as ICCCM say, we need reply this event
* with a SetInputFocus, the data[1] have
* the valid timestamp (send by the window
* manager).
* the valid timestamp (send by the wm).
*/
XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
} else {
@@ -547,24 +537,6 @@ GHOST_SystemX11::processEvent(XEvent *xe)
// XCrossingEvents pointer leave enter window.
break;
case MapNotify:
/*
* From ICCCM:
* [ Clients can select for StructureNotify on their
* top-level windows to track transition between
* Normal and Iconic states. Receipt of a MapNotify
* event will indicate a transition to the Normal
* state, and receipt of an UnmapNotify event will
* indicate a transition to the Iconic state. ]
*/
if (window->m_post_init == True) {
/*
* Now we are sure that the window is
* mapped, so only need change the state.
*/
window->setState(window->m_post_state);
window->m_post_init= False;
}
break;
case UnmapNotify:
break;
case MappingNotify:

View File

@@ -215,21 +215,9 @@ public:
*/
virtual void putClipboard(GHOST_TInt8 *buffer, int flag) const;
/**
* Atom used for ICCCM, WM-spec and Motif.
* We only need get this atom at the start, it's relative
* to the display not the window and are public for every
* window that need it.
*/
Atom m_wm_protocols;
/* Atom used for ICCCM. */
Atom m_wm_take_focus;
Atom m_wm_state;
Atom m_wm_change_state;
Atom m_net_state;
Atom m_net_max_horz;
Atom m_net_max_vert;
Atom m_net_fullscreen;
Atom m_motif;
Atom m_wm_protocols;
Atom m_delete_window_atom;
private :

View File

@@ -54,16 +54,6 @@ typedef struct {
#define MWM_HINTS_DECORATIONS (1L << 1)
/*
* A client can't change the window property, that is the
* work of the window manager. We send a ClientMessage
* event to the Root window with the property
* and the Action (WM-spec define this):
*/
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
#define _NET_WM_STATE_TOGGLE 2
/*
import bpy
I = bpy.data.images['blender.png'] # the 48x48 icon
@@ -164,10 +154,10 @@ GHOST_WindowX11(
// Set up the minimum atrributes that we require and see if
// X can find us a visual matching those requirements.
Atom atoms[2];
int natom;
int attributes[40], i = 0;
Atom atoms[2];
int natom;
if(m_stereoVisual)
attributes[i++] = GLX_STEREO;
@@ -272,26 +262,46 @@ GHOST_WindowX11(
// Are we in fullscreen mode - then include
// some obscure blut code to remove decorations.
/*
* One of the problem with WM_spec is that can't set a property
* to a window that isn't mapped. That is why we can't "just
* call setState" here.
*
* To fix this, we first need know that the window is really
* mapped waiting for the MapNotify event.
*
* So, m_post_init indicate that we need wait for the MapNotify
* event and then set the window state to the m_post_state.
*/
if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
m_post_init = True;
m_post_state = state;
}
else {
m_post_init = False;
m_post_state = GHOST_kWindowStateNormal;
}
if (state == GHOST_kWindowStateFullScreen) {
MotifWmHints hints;
Atom atom;
atom = XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
if (atom == None) {
GHOST_PRINT("Could not intern X atom for _MOTIF_WM_HINTS.\n");
} else {
hints.flags = MWM_HINTS_DECORATIONS;
hints.decorations = 0; /* Absolutely no decorations. */
// other hints.decorations make no sense
// you can't select individual decorations
XChangeProperty(m_display, m_window,
atom, atom, 32,
PropModeReplace, (unsigned char *) &hints, 4);
}
} else if (state == GHOST_kWindowStateMaximized) {
// With this, xprop should report the following just after launch
// _NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ
// After demaximization the right side is empty, though (maybe not the most correct then?)
Atom state, atomh, atomv;
state = XInternAtom(m_display, "_NET_WM_STATE", False);
atomh = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
atomv = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
if (state == None ) {
GHOST_PRINT("Atom _NET_WM_STATE requested but not avaliable nor created.\n");
} else {
XChangeProperty(m_display, m_window,
state, XA_ATOM, 32,
PropModeAppend, (unsigned char *) &atomh, 1);
XChangeProperty(m_display, m_window,
state, XA_ATOM, 32,
PropModeAppend, (unsigned char *) &atomv, 1);
}
}
// Create some hints for the window manager on how
// we want this window treated.
@@ -654,298 +664,28 @@ clientToScreen(
outY = ay;
}
void GHOST_WindowX11::icccmSetState(int state)
{
XEvent xev;
if (state != IconicState)
return;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.display = m_display;
xev.xclient.window = m_window;
xev.xclient.format = 32;
xev.xclient.message_type = m_system->m_wm_change_state;
xev.xclient.data.l[0] = state;
XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)),
False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
GHOST_TWindowState
GHOST_WindowX11::
getState(
) const {
//FIXME
return GHOST_kWindowStateNormal;
}
int GHOST_WindowX11::icccmGetState(void) const
{
unsigned char *prop_ret;
unsigned long bytes_after, num_ret;
Atom type_ret;
int format_ret, st;
GHOST_TSuccess
GHOST_WindowX11::
setState(
GHOST_TWindowState state
){
//TODO
prop_ret = NULL;
st = XGetWindowProperty(m_display, m_window, m_system->m_wm_state, 0,
0x7fffffff, False, m_system->m_wm_state, &type_ret,
&format_ret, &num_ret, &bytes_after, &prop_ret);
if ((st == Success) && (prop_ret) && (num_ret == 2))
st = prop_ret[0];
else
st = NormalState;
if (prop_ret)
XFree(prop_ret);
return (st);
}
void GHOST_WindowX11::netwmMaximized(bool set)
{
XEvent xev;
xev.xclient.type= ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = m_window;
xev.xclient.message_type = m_system->m_net_state;
xev.xclient.format = 32;
if (set == True)
xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
else
xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
xev.xclient.data.l[1] = m_system->m_net_max_horz;
xev.xclient.data.l[2] = m_system->m_net_max_vert;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)),
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
}
bool GHOST_WindowX11::netwmIsMaximized(void) const
{
unsigned char *prop_ret;
unsigned long bytes_after, num_ret, i;
Atom type_ret;
bool st;
int format_ret, count;
prop_ret = NULL;
st = False;
i = XGetWindowProperty(m_display, m_window, m_system->m_net_state, 0,
0x7fffffff, False, XA_ATOM, &type_ret, &format_ret,
&num_ret, &bytes_after, &prop_ret);
if ((i == Success) && (prop_ret) && (format_ret == 32)) {
count = 0;
for (i = 0; i < num_ret; i++) {
if (((unsigned long *) prop_ret)[i] == m_system->m_net_max_horz)
count++;
if (((unsigned long *) prop_ret)[i] == m_system->m_net_max_vert)
count++;
if (count == 2) {
st = True;
break;
}
}
}
if (prop_ret)
XFree(prop_ret);
return (st);
}
void GHOST_WindowX11::netwmFullScreen(bool set)
{
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = m_window;
xev.xclient.message_type = m_system->m_net_state;
xev.xclient.format = 32;
if (set == True)
xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
else
xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
xev.xclient.data.l[1] = m_system->m_net_fullscreen;
xev.xclient.data.l[2] = 0;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)),
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
}
bool GHOST_WindowX11::netwmIsFullScreen(void) const
{
unsigned char *prop_ret;
unsigned long bytes_after, num_ret, i;
Atom type_ret;
bool st;
int format_ret;
prop_ret = NULL;
st = False;
i = XGetWindowProperty(m_display, m_window, m_system->m_net_state, 0,
0x7fffffff, False, XA_ATOM, &type_ret, &format_ret,
&num_ret, &bytes_after, &prop_ret);
if ((i == Success) && (prop_ret) && (format_ret == 32)) {
for (i = 0; i < num_ret; i++) {
if (((unsigned long *)prop_ret)[i] == m_system->m_net_fullscreen) {
st = True;
break;
}
}
}
if (prop_ret)
XFree(prop_ret);
return (st);
}
void GHOST_WindowX11::motifFullScreen(bool set)
{
MotifWmHints hints;
hints.flags = MWM_HINTS_DECORATIONS;
if (set == True)
hints.decorations = 0;
else
hints.decorations = 1;
XChangeProperty(m_display, m_window, m_system->m_motif,
m_system->m_motif, 32, PropModeReplace,
(unsigned char *)&hints, 4);
}
bool GHOST_WindowX11::motifIsFullScreen(void) const
{
unsigned char *prop_ret;
unsigned long bytes_after, num_ret;
MotifWmHints *hints;
Atom type_ret;
bool state;
int format_ret, st;
prop_ret = NULL;
state = False;
st = XGetWindowProperty(m_display, m_window, m_system->m_motif, 0,
0x7fffffff, False, m_system->m_motif,
&type_ret, &format_ret, &num_ret,
&bytes_after, &prop_ret);
if ((st == Success) && (prop_ret)) {
hints = (MotifWmHints *)prop_ret;
if (hints->flags & MWM_HINTS_DECORATIONS) {
if (!hints->decorations)
state = True;
}
}
if (prop_ret)
XFree(prop_ret);
return (state);
}
GHOST_TWindowState GHOST_WindowX11::getState() const
{
GHOST_TWindowState state_ret;
int state;
state_ret = GHOST_kWindowStateNormal;
state = icccmGetState();
/*
* In the Iconic and Withdrawn state, the window is
* unmaped, so only need return a Minimized state.
*/
if ((state == IconicState) || (state == WithdrawnState))
state_ret = GHOST_kWindowStateMinimized;
else if (netwmIsMaximized() == True)
state_ret = GHOST_kWindowStateMaximized;
else if (netwmIsFullScreen() == True)
state_ret = GHOST_kWindowStateFullScreen;
else if (motifIsFullScreen() == True)
state_ret = GHOST_kWindowStateFullScreen;
return (state_ret);
}
GHOST_TSuccess GHOST_WindowX11::setState(GHOST_TWindowState state)
{
GHOST_TWindowState cur_state;
bool is_max, is_full, is_motif_full;
cur_state = getState();
if (state == (int)cur_state)
if (state == (int)getState()) {
return GHOST_kSuccess;
if (cur_state != GHOST_kWindowStateMinimized) {
/*
* The window don't have this property's
* if it's not mapped.
*/
is_max = netwmIsMaximized();
is_full = netwmIsFullScreen();
}
else {
is_max = False;
is_full = False;
} else {
return GHOST_kFailure;
}
is_motif_full = motifIsFullScreen();
if (state == GHOST_kWindowStateNormal) {
if (is_max == True)
netwmMaximized(False);
if (is_full == True)
netwmFullScreen(False);
if (is_motif_full == True)
motifFullScreen(False);
icccmSetState(NormalState);
return (GHOST_kSuccess);
}
if (state == GHOST_kWindowStateFullScreen) {
/*
* We can't change to full screen if the window
* isn't mapped.
*/
if (cur_state == GHOST_kWindowStateMinimized)
return (GHOST_kFailure);
if (is_max == True)
netwmMaximized(False);
if (is_full == False)
netwmFullScreen(True);
if (is_motif_full == False)
motifFullScreen(True);
return (GHOST_kSuccess);
}
if (state == GHOST_kWindowStateMaximized) {
/*
* We can't change to Maximized if the window
* isn't mapped.
*/
if (cur_state == GHOST_kWindowStateMinimized)
return (GHOST_kFailure);
if (is_full == True)
netwmFullScreen(False);
if (is_motif_full == True)
motifFullScreen(False);
if (is_max == False)
netwmMaximized(True);
return (GHOST_kSuccess);
}
if (state == GHOST_kWindowStateMinimized) {
/*
* The window manager need save the current state of
* the window (maximized, full screen, etc).
*/
icccmSetState(IconicState);
return (GHOST_kSuccess);
}
return (GHOST_kFailure);
}
#include <iostream>

View File

@@ -212,15 +212,6 @@ public:
const GHOST_TabletData* GetTabletData()
{ return &m_xtablet.CommonData; }
/*
* Need this in case that we want start the window
* in FullScreen or Maximized state.
* Check GHOST_WindowX11.cpp
*/
bool m_post_init;
GHOST_TWindowState m_post_state;
protected:
/**
* Tries to install a rendering context in this window.
@@ -336,18 +327,6 @@ private :
/* Tablet devices */
XTablet m_xtablet;
void icccmSetState(int state);
int icccmGetState() const;
void netwmMaximized(bool set);
bool netwmIsMaximized() const;
void netwmFullScreen(bool set);
bool netwmIsFullScreen() const;
void motifFullScreen(bool set);
bool motifIsFullScreen() const;
};

Some files were not shown because too many files have changed in this diff Show More