Added Bullet library.

Only windows projectfiles for now.
Will ask Hans to get unix makefiles done.
This commit is contained in:
Erwin Coumans
2005-07-16 09:58:01 +00:00
parent 1921a356be
commit feb4f51103
156 changed files with 19816 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef BROADPHASE_INTERFACE_H
#define BROADPHASE_INTERFACE_H
struct DispatcherInfo;
class Dispatcher;
struct BroadphaseProxy;
#include "SimdVector3.h"
///BroadphaseInterface for aabb-overlapping object pairs
class BroadphaseInterface
{
public:
virtual BroadphaseProxy* CreateProxy( void *object,int type, const SimdVector3& min, const SimdVector3& max) =0;
virtual void DestroyProxy(BroadphaseProxy* proxy)=0;
virtual void SetAabb(BroadphaseProxy* proxy,const SimdVector3& aabbMin,const SimdVector3& aabbMax)=0;
virtual void CleanProxyFromPairs(BroadphaseProxy* proxy)=0;
virtual void DispatchAllCollisionPairs(Dispatcher& dispatcher,DispatcherInfo& dispatchInfo)=0;
};
#endif //BROADPHASE_INTERFACE_H

View File

@@ -0,0 +1,12 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "BroadphaseProxy.h"

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef BROADPHASE_PROXY_H
#define BROADPHASE_PROXY_H
/// Dispatcher uses these types
/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
/// to facilitate type checking
enum BroadphaseNativeTypes
{
// polyhedral convex shapes
BOX_SHAPE_PROXYTYPE,
TRIANGLE_SHAPE_PROXYTYPE,
TETRAHEDRAL_SHAPE_PROXYTYPE,
CONVEX_HULL_SHAPE_PROXYTYPE,
//implicit convex shapes
IMPLICIT_CONVEX_SHAPES_START_HERE,
SPHERE_SHAPE_PROXYTYPE,
MULTI_SPHERE_SHAPE_PROXYTYPE,
CONE_SHAPE_PROXYTYPE,
CONVEX_SHAPE_PROXYTYPE,
CYLINDER_SHAPE_PROXYTYPE,
MINKOWSKI_SUM_SHAPE_PROXYTYPE,
MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
//concave shapes
CONCAVE_SHAPES_START_HERE,
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
TRIANGLE_MESH_SHAPE_PROXYTYPE,
MAX_BROADPHASE_COLLISION_TYPES
};
///BroadphaseProxy
struct BroadphaseProxy
{
BroadphaseProxy() :m_clientObject(0),m_clientObjectType(-1){}
BroadphaseProxy(void* object,int type)
:m_clientObject(object),
m_clientObjectType(type)
{
}
void *m_clientObject;
int GetClientObjectType ( ) const { return m_clientObjectType;}
void SetClientObjectType( int type ) {
m_clientObjectType = type;
}
bool IsConvexShape()
{
return (GetClientObjectType () < TRIANGLE_MESH_SHAPE_PROXYTYPE);
}
bool IsConcaveShape()
{
return (GetClientObjectType() > CONCAVE_SHAPES_START_HERE);
}
protected:
int m_clientObjectType;
};
class CollisionAlgorithm;
struct BroadphaseProxy;
#define SIMPLE_MAX_ALGORITHMS 2
/// contains a pair of aabb-overlapping objects
struct BroadphasePair
{
BroadphasePair ()
:
m_pProxy0(0),
m_pProxy1(0)
{
for (int i=0;i<SIMPLE_MAX_ALGORITHMS;i++)
{
m_algorithms[i] = 0;
}
}
BroadphasePair(const BroadphasePair& other)
: m_pProxy0(other.m_pProxy0),
m_pProxy1(other.m_pProxy1)
{
for (int i=0;i<SIMPLE_MAX_ALGORITHMS;i++)
{
m_algorithms[i] = other.m_algorithms[i];
}
}
BroadphasePair(BroadphaseProxy& proxy0,BroadphaseProxy& proxy1)
:
m_pProxy0(&proxy0),
m_pProxy1(&proxy1)
{
for (int i=0;i<SIMPLE_MAX_ALGORITHMS;i++)
{
m_algorithms[i] = 0;
}
}
BroadphaseProxy* m_pProxy0;
BroadphaseProxy* m_pProxy1;
mutable CollisionAlgorithm* m_algorithms[SIMPLE_MAX_ALGORITHMS];
};
#endif //BROADPHASE_PROXY_H

View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "CollisionAlgorithm.h"
#include "CollisionDispatcher.h"
CollisionAlgorithm::CollisionAlgorithm(const CollisionAlgorithmConstructionInfo& ci)
{
m_dispatcher = ci.m_dispatcher;
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef COLLISION_ALGORITHM_H
#define COLLISION_ALGORITHM_H
struct BroadphaseProxy;
class Dispatcher;
struct CollisionAlgorithmConstructionInfo
{
CollisionAlgorithmConstructionInfo()
:m_dispatcher(0)
{
}
CollisionAlgorithmConstructionInfo(Dispatcher* dispatcher,int temp)
:m_dispatcher(dispatcher)
{
}
Dispatcher* m_dispatcher;
int GetDispatcherId();
};
///CollisionAlgorithm is an collision interface that is compatible with the Broadphase and Dispatcher.
///It is persistent over frames
class CollisionAlgorithm
{
protected:
Dispatcher* m_dispatcher;
protected:
int GetDispatcherId();
public:
CollisionAlgorithm() {};
CollisionAlgorithm(const CollisionAlgorithmConstructionInfo& ci);
virtual ~CollisionAlgorithm() {};
virtual void ProcessCollision (BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep,int stepCount, bool useContinuous) = 0;
virtual float CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep,int stepCount) = 0;
};
#endif //COLLISION_ALGORITHM_H

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "CollisionDispatcher.h"
Dispatcher::~Dispatcher()
{
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef COLLISION_DISPATCHER_H
#define COLLISION_DISPATCHER_H
class CollisionAlgorithm;
struct BroadphaseProxy;
class RigidBody;
enum CollisionDispatcherId
{
RIGIDBODY_DISPATCHER = 0,
RAGDOLL_DISPATCHER
};
class PersistentManifold;
struct DispatcherInfo
{
enum DispatchFunc
{
DISPATCH_DISCRETE = 1,
DISPATCH_CONTINUOUS
};
DispatcherInfo()
:m_dispatchFunc(DISPATCH_DISCRETE),
m_timeOfImpact(1.f),
m_useContinuous(false)
{
}
float m_timeStep;
int m_stepCount;
int m_dispatchFunc;
float m_timeOfImpact;
bool m_useContinuous;
};
/// Collision Dispatcher can be used in combination with broadphase and collision algorithms.
class Dispatcher
{
public:
virtual ~Dispatcher() ;
virtual CollisionAlgorithm* FindAlgorithm(BroadphaseProxy& proxy0,BroadphaseProxy& proxy1) = 0;
//
// asume dispatchers to have unique id's in the range [0..max dispacher]
//
virtual int GetUniqueId() = 0;
virtual PersistentManifold* GetNewManifold(void* body0,void* body1)=0;
virtual void ReleaseManifold(PersistentManifold* manifold)=0;
};
#endif //COLLISION_DISPATCHER_H

View File

@@ -0,0 +1,273 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "SimpleBroadphase.h"
#include "BroadphaseCollision/CollisionDispatcher.h"
#include "BroadphaseCollision/CollisionAlgorithm.h"
#include "SimdVector3.h"
#include "SimdTransform.h"
#include "SimdMatrix3x3.h"
#include <vector>
#include "NarrowPhaseCollision/CollisionMargin.h"
SimpleBroadphase::SimpleBroadphase()
: m_firstFreeProxy(0),
m_numProxies(0),
m_blockedForChanges(false),
m_NumOverlapBroadphasePair(0)
{
int i;
for (i=0;i<SIMPLE_MAX_PROXIES;i++)
{
m_freeProxies[i] = i;
}
}
SimpleBroadphase::~SimpleBroadphase()
{
/*int i;
for (i=m_numProxies-1;i>=0;i--)
{
BP_Proxy* proxy = m_pProxies[i];
destroyProxy(proxy);
}
*/
}
BroadphaseProxy* SimpleBroadphase::CreateProxy( void *object, int type, const SimdVector3& min, const SimdVector3& max)
{
if (m_numProxies >= SIMPLE_MAX_PROXIES)
{
assert(0);
return 0; //should never happen, but don't let the game crash ;-)
}
assert(min[0]<= max[0] && min[1]<= max[1] && min[2]<= max[2]);
int freeIndex= m_freeProxies[m_firstFreeProxy];
BroadphaseProxy* proxy = new (&m_proxies[freeIndex])SimpleBroadphaseProxy(object,type,min,max);
m_firstFreeProxy++;
m_pProxies[m_numProxies] = proxy;
m_numProxies++;
return proxy;
}
void SimpleBroadphase::DestroyProxy(BroadphaseProxy* proxy)
{
m_numProxies--;
BroadphaseProxy* proxy1 = &m_proxies[0];
int index = proxy - proxy1;
m_freeProxies[--m_firstFreeProxy] = index;
}
SimpleBroadphaseProxy* SimpleBroadphase::GetSimpleProxyFromProxy(BroadphaseProxy* proxy)
{
SimpleBroadphaseProxy* proxy0 = static_cast<SimpleBroadphaseProxy*>(proxy);
int index = proxy0 - &m_proxies[0];
assert(index < m_numProxies);
SimpleBroadphaseProxy* sbp = &m_proxies[index];
return sbp;
}
void SimpleBroadphase::SetAabb(BroadphaseProxy* proxy,const SimdVector3& aabbMin,const SimdVector3& aabbMax)
{
SimpleBroadphaseProxy* sbp = GetSimpleProxyFromProxy(proxy);
sbp->m_min = aabbMin;
sbp->m_max = aabbMax;
}
void SimpleBroadphase::CleanOverlappingPair(BroadphasePair& pair)
{
for (int dispatcherId=0;dispatcherId<SIMPLE_MAX_ALGORITHMS;dispatcherId++)
{
if (pair.m_algorithms[dispatcherId])
{
{
delete pair.m_algorithms[dispatcherId];
pair.m_algorithms[dispatcherId]=0;
}
}
}
}
void SimpleBroadphase::CleanProxyFromPairs(BroadphaseProxy* proxy)
{
for (int i=0;i<m_NumOverlapBroadphasePair;i++)
{
BroadphasePair& pair = m_OverlappingPairs[i];
if (pair.m_pProxy0 == proxy ||
pair.m_pProxy1 == proxy)
{
CleanOverlappingPair(pair);
}
}
}
void SimpleBroadphase::AddOverlappingPair(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1)
{
BroadphasePair pair(*proxy0,*proxy1);
m_OverlappingPairs[m_NumOverlapBroadphasePair] = pair;
int i;
for (i=0;i<SIMPLE_MAX_ALGORITHMS;i++)
{
assert(!m_OverlappingPairs[m_NumOverlapBroadphasePair].m_algorithms[i]);
m_OverlappingPairs[m_NumOverlapBroadphasePair].m_algorithms[i] = 0;
}
m_NumOverlapBroadphasePair++;
}
bool SimpleBroadphase::FindPair(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1)
{
bool found = false;
int i;
for (i=m_NumOverlapBroadphasePair-1;i>=0;i--)
{
BroadphasePair& pair = m_OverlappingPairs[i];
if (((pair.m_pProxy0 == proxy0) && (pair.m_pProxy1 == proxy1)) ||
((pair.m_pProxy0 == proxy1) && (pair.m_pProxy1 == proxy0)))
{
found = true;
break;
}
}
return found;
}
void SimpleBroadphase::RemoveOverlappingPair(BroadphasePair& pair)
{
CleanOverlappingPair(pair);
int index = &pair - &m_OverlappingPairs[0];
//remove efficiently, swap with the last
m_OverlappingPairs[index] = m_OverlappingPairs[m_NumOverlapBroadphasePair-1];
m_NumOverlapBroadphasePair--;
}
bool SimpleBroadphase::AabbOverlap(SimpleBroadphaseProxy* proxy0,SimpleBroadphaseProxy* proxy1)
{
return proxy0->m_min[0] <= proxy1->m_max[0] && proxy1->m_min[0] <= proxy0->m_max[0] &&
proxy0->m_min[1] <= proxy1->m_max[1] && proxy1->m_min[1] <= proxy0->m_max[1] &&
proxy0->m_min[2] <= proxy1->m_max[2] && proxy1->m_min[2] <= proxy0->m_max[2];
}
void SimpleBroadphase::RefreshOverlappingPairs()
{
//first check for new overlapping pairs
int i,j;
for (i=0;i<m_numProxies;i++)
{
BroadphaseProxy* proxy0 = m_pProxies[i];
for (j=i+1;j<m_numProxies;j++)
{
BroadphaseProxy* proxy1 = m_pProxies[j];
SimpleBroadphaseProxy* p0 = GetSimpleProxyFromProxy(proxy0);
SimpleBroadphaseProxy* p1 = GetSimpleProxyFromProxy(proxy1);
if (AabbOverlap(p0,p1))
{
if ( !FindPair(proxy0,proxy1))
{
AddOverlappingPair(proxy0,proxy1);
}
}
}
}
//then remove non-overlapping ones
for (i=0;i<m_NumOverlapBroadphasePair;i++)
{
BroadphasePair& pair = m_OverlappingPairs[i];
SimpleBroadphaseProxy* proxy0 = GetSimpleProxyFromProxy(pair.m_pProxy0);
SimpleBroadphaseProxy* proxy1 = GetSimpleProxyFromProxy(pair.m_pProxy1);
if (!AabbOverlap(proxy0,proxy1))
{
RemoveOverlappingPair(pair);
}
}
//BroadphasePair m_OverlappingPairs[SIMPLE_MAX_OVERLAP];
//int m_NumOverlapBroadphasePair;
}
void SimpleBroadphase::DispatchAllCollisionPairs(Dispatcher& dispatcher,DispatcherInfo& dispatchInfo)
{
m_blockedForChanges = true;
int i;
int dispatcherId = dispatcher.GetUniqueId();
RefreshOverlappingPairs();
for (i=0;i<m_NumOverlapBroadphasePair;i++)
{
BroadphasePair& pair = m_OverlappingPairs[i];
if (dispatcherId>= 0)
{
//dispatcher will keep algorithms persistent in the collision pair
if (!pair.m_algorithms[dispatcherId])
{
pair.m_algorithms[dispatcherId] = dispatcher.FindAlgorithm(
*pair.m_pProxy0,
*pair.m_pProxy1);
}
if (pair.m_algorithms[dispatcherId])
{
if (dispatchInfo.m_dispatchFunc == DispatcherInfo::DISPATCH_DISCRETE)
{
pair.m_algorithms[dispatcherId]->ProcessCollision(pair.m_pProxy0,pair.m_pProxy1,dispatchInfo.m_timeStep,dispatchInfo.m_stepCount,dispatchInfo.m_useContinuous);
} else
{
float toi = pair.m_algorithms[dispatcherId]->CalculateTimeOfImpact(pair.m_pProxy0,pair.m_pProxy1,dispatchInfo.m_timeStep,dispatchInfo.m_stepCount);
if (dispatchInfo.m_timeOfImpact > toi)
dispatchInfo.m_timeOfImpact = toi;
}
}
} else
{
//non-persistent algorithm dispatcher
CollisionAlgorithm* algo = dispatcher.FindAlgorithm(
*pair.m_pProxy0,
*pair.m_pProxy1);
if (algo)
{
if (dispatchInfo.m_dispatchFunc == DispatcherInfo::DISPATCH_DISCRETE)
{
algo->ProcessCollision(pair.m_pProxy0,pair.m_pProxy1,dispatchInfo.m_timeStep,dispatchInfo.m_stepCount,dispatchInfo.m_useContinuous);
} else
{
float toi = algo->CalculateTimeOfImpact(pair.m_pProxy0,pair.m_pProxy1,dispatchInfo.m_timeStep,dispatchInfo.m_stepCount);
if (dispatchInfo.m_timeOfImpact > toi)
dispatchInfo.m_timeOfImpact = toi;
}
}
}
}
m_blockedForChanges = false;
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef SIMPLE_BROADPHASE_H
#define SIMPLE_BROADPHASE_H
#define SIMPLE_MAX_PROXIES 8192
#define SIMPLE_MAX_OVERLAP 4096
#include "BroadphaseInterface.h"
#include "BroadphaseProxy.h"
#include "SimdPoint3.h"
struct SimpleBroadphaseProxy : public BroadphaseProxy
{
SimdVector3 m_min;
SimdVector3 m_max;
SimpleBroadphaseProxy() {};
SimpleBroadphaseProxy(void* object,int type,const SimdPoint3& minpt,const SimdPoint3& maxpt)
:BroadphaseProxy(object,type),
m_min(minpt),m_max(maxpt)
{
}
};
///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks
class SimpleBroadphase : public BroadphaseInterface
{
SimpleBroadphaseProxy m_proxies[SIMPLE_MAX_PROXIES];
int m_freeProxies[SIMPLE_MAX_PROXIES];
int m_firstFreeProxy;
BroadphaseProxy* m_pProxies[SIMPLE_MAX_PROXIES];
int m_numProxies;
//during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges;
BroadphasePair m_OverlappingPairs[SIMPLE_MAX_OVERLAP];
int m_NumOverlapBroadphasePair;
SimpleBroadphaseProxy* GetSimpleProxyFromProxy(BroadphaseProxy* proxy);
bool AabbOverlap(SimpleBroadphaseProxy* proxy0,SimpleBroadphaseProxy* proxy1);
void RemoveOverlappingPair(BroadphasePair& pair);
void CleanOverlappingPair(BroadphasePair& pair);
void AddOverlappingPair(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1);
bool FindPair(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1);
void RefreshOverlappingPairs();
public:
SimpleBroadphase();
virtual ~SimpleBroadphase();
virtual BroadphaseProxy* CreateProxy( void *object,int type, const SimdVector3& min, const SimdVector3& max) ;
virtual void DestroyProxy(BroadphaseProxy* proxy);
virtual void SetAabb(BroadphaseProxy* proxy,const SimdVector3& aabbMin,const SimdVector3& aabbMax);
virtual void CleanProxyFromPairs(BroadphaseProxy* proxy);
virtual void DispatchAllCollisionPairs(Dispatcher& dispatcher,DispatcherInfo& dispatchInfo);
};
#endif //SIMPLE_BROADPHASE_H

412
extern/bullet/Bullet/Bullet3.dsp vendored Normal file
View File

@@ -0,0 +1,412 @@
# Microsoft Developer Studio Project File - Name="Bullet" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=Bullet - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Bullet3.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Bullet3.mak" CFG="Bullet - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Bullet - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "Bullet - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Bullet - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
MTL=midl.exe
LINK32=link.exe -lib
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /Zd /O2 /I "../LinearMath" /I "." /D "NDEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /D "BUM_INLINED" /D "USE_ALGEBRAIC" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "Bullet - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
MTL=midl.exe
LINK32=link.exe -lib
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../LinearMath" /I "." /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /D "BUM_INLINED" /D "USE_ALGEBRAIC" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "Bullet - Win32 Release"
# Name "Bullet - Win32 Debug"
# Begin Group "NarrowPhaseCollision"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_AlgebraicPolynomialSolver.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_AlgebraicPolynomialSolver.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_Collidable.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_Collidable.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_CollisionPair.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_CollisionPair.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_EdgeEdge.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_EdgeEdge.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_MotionStateInterface.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_PolynomialSolverInterface.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_Screwing.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_Screwing.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_StaticMotionState.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_VertexPoly.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\BU_VertexPoly.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\CollisionMargin.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\ContinuousConvexCollision.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\ContinuousConvexCollision.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\ConvexCast.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\ConvexCast.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\ConvexPenetrationDepthSolver.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\DiscreteCollisionDetectorInterface.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\GjkConvexCast.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\GjkConvexCast.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\GjkPairDetector.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\GjkPairDetector.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\ManifoldPoint.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\MinkowskiPenetrationDepthSolver.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\MinkowskiPenetrationDepthSolver.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\PersistentManifold.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\PersistentManifold.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\PointCollector.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\RaycastCallback.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\RaycastCallback.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\SimplexSolverInterface.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\SubSimplexConvexCast.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\SubSimplexConvexCast.h
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\VoronoiSimplexSolver.cpp
# End Source File
# Begin Source File
SOURCE=.\NarrowPhaseCollision\VoronoiSimplexSolver.h
# End Source File
# End Group
# Begin Group "BroadphaseCollision"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\BroadphaseCollision\BroadPhaseInterface.h
# End Source File
# Begin Source File
SOURCE=.\BroadphaseCollision\BroadphaseProxy.cpp
# End Source File
# Begin Source File
SOURCE=.\BroadphaseCollision\BroadphaseProxy.h
# End Source File
# Begin Source File
SOURCE=.\BroadphaseCollision\CollisionAlgorithm.cpp
# End Source File
# Begin Source File
SOURCE=.\BroadphaseCollision\CollisionAlgorithm.h
# End Source File
# Begin Source File
SOURCE=.\BroadphaseCollision\CollisionDispatcher.cpp
# End Source File
# Begin Source File
SOURCE=.\BroadphaseCollision\CollisionDispatcher.h
# End Source File
# Begin Source File
SOURCE=.\BroadphaseCollision\SimpleBroadphase.cpp
# End Source File
# Begin Source File
SOURCE=.\BroadphaseCollision\SimpleBroadphase.h
# End Source File
# End Group
# Begin Group "CollisionShapes"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\CollisionShapes\BoxShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\BoxShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\CollisionShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\CollisionShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\ConeShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\ConeShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\ConvexHullShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\ConvexHullShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\ConvexShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\ConvexShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\CylinderShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\CylinderShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\MinkowskiSumShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\MinkowskiSumShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\MultiSphereShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\MultiSphereShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\PolyhedralConvexShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\PolyhedralConvexShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\Simplex1to4Shape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\Simplex1to4Shape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\SphereShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\SphereShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\StridingMeshInterface.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\StridingMeshInterface.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\TriangleCallback.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\TriangleMesh.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\TriangleMesh.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\TriangleMeshShape.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\TriangleMeshShape.h
# End Source File
# Begin Source File
SOURCE=.\CollisionShapes\TriangleShape.h
# End Source File
# End Group
# End Target
# End Project

427
extern/bullet/Bullet/Bullet3_vc7.vcproj vendored Normal file
View File

@@ -0,0 +1,427 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="Bullet3ContinuousCollision"
ProjectGUID="{FFD3C64A-30E2-4BC7-BC8F-51818C320400}"
SccProjectName=""
SccLocalPath="">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="4"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=".;..\LinearMath"
PreprocessorDefinitions="_DEBUG;_LIB;WIN32;BUM_INLINED;USE_ALGEBRAIC"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="2"
PrecompiledHeaderFile=".\Debug/Bullet.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\Debug\Bullet.lib"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="4"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories=".;..\LinearMath"
PreprocessorDefinitions="NDEBUG;_LIB;WIN32;BUM_INLINED;USE_ALGEBRAIC"
StringPooling="TRUE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="2"
PrecompiledHeaderFile=".\Release/Bullet.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="2"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="..\..\..\..\build\msvc_7\libs\extern\Bullet.lib"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="ECHO Copying header files
IF NOT EXIST ..\..\..\..\build\msvc_7\extern\bullet\include MKDIR ..\..\..\..\build\msvc_7\extern\bullet\include
IF NOT EXIST ..\..\..\..\build\msvc_7\extern\bullet\include\BroadphaseCollision MKDIR ..\..\..\..\build\msvc_7\extern\bullet\include\BroadphaseCollision
IF NOT EXIST ..\..\..\..\build\msvc_7\extern\bullet\include\CollisionShapes MKDIR ..\..\..\..\build\msvc_7\extern\bullet\include\CollisionShapes
IF NOT EXIST ..\..\..\..\build\msvc_7\extern\bullet\include\NarrowPhaseCollision MKDIR ..\..\..\..\build\msvc_7\extern\bullet\include\NarrowPhaseCollision
XCOPY /Y ..\LinearMath\*.h ..\..\..\..\build\msvc_7\extern\bullet\include
XCOPY /Y ..\Bullet\BroadphaseCollision\*.h ..\..\..\..\build\msvc_7\extern\bullet\include\BroadphaseCollision
XCOPY /Y ..\Bullet\CollisionShapes\*.h ..\..\..\..\build\msvc_7\extern\bullet\include\CollisionShapes
XCOPY /Y ..\Bullet\NarrowPhaseCollision\*.h ..\..\..\..\build\msvc_7\extern\bullet\include\NarrowPhaseCollision
ECHO Done
"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="NarrowPhaseCollision"
Filter="">
<File
RelativePath=".\NarrowPhaseCollision\BU_AlgebraicPolynomialSolver.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_AlgebraicPolynomialSolver.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_Collidable.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_Collidable.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_CollisionPair.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_CollisionPair.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_EdgeEdge.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_EdgeEdge.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_MotionStateInterface.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_PolynomialSolverInterface.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_Screwing.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_Screwing.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_StaticMotionState.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_VertexPoly.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_VertexPoly.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\CollisionMargin.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\ContinuousConvexCollision.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\ContinuousConvexCollision.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\ConvexCast.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\ConvexPenetrationDepthSolver.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\DiscreteCollisionDetectorInterface.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\GjkConvexCast.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\GjkConvexCast.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\GjkPairDetector.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\GjkPairDetector.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\ManifoldPoint.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\MinkowskiPenetrationDepthSolver.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\MinkowskiPenetrationDepthSolver.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\PersistentManifold.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\PersistentManifold.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\PointCollector.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\RaycastCallback.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\RaycastCallback.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\SimplexSolverInterface.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\SubSimplexConvexCast.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\SubSimplexConvexCast.h">
</File>
<File
RelativePath=".\NarrowPhaseCollision\VoronoiSimplexSolver.cpp">
</File>
<File
RelativePath=".\NarrowPhaseCollision\VoronoiSimplexSolver.h">
</File>
</Filter>
<Filter
Name="CollisionShapes"
Filter="">
<File
RelativePath=".\CollisionShapes\BoxShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\BoxShape.h">
</File>
<File
RelativePath=".\CollisionShapes\CollisionShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\CollisionShape.h">
</File>
<File
RelativePath=".\CollisionShapes\ConeShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\ConeShape.h">
</File>
<File
RelativePath=".\CollisionShapes\ConvexHullShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\ConvexHullShape.h">
</File>
<File
RelativePath=".\CollisionShapes\ConvexShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\ConvexShape.h">
</File>
<File
RelativePath=".\CollisionShapes\CylinderShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\CylinderShape.h">
</File>
<File
RelativePath=".\CollisionShapes\MinkowskiSumShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\MinkowskiSumShape.h">
</File>
<File
RelativePath=".\CollisionShapes\MultiSphereShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\MultiSphereShape.h">
</File>
<File
RelativePath=".\CollisionShapes\PolyhedralConvexShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\PolyhedralConvexShape.h">
</File>
<File
RelativePath=".\CollisionShapes\Simplex1to4Shape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\Simplex1to4Shape.h">
</File>
<File
RelativePath=".\CollisionShapes\SphereShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\SphereShape.h">
</File>
<File
RelativePath=".\CollisionShapes\StridingMeshInterface.cpp">
</File>
<File
RelativePath=".\CollisionShapes\StridingMeshInterface.h">
</File>
<File
RelativePath=".\CollisionShapes\TriangleCallback.h">
</File>
<File
RelativePath=".\CollisionShapes\TriangleMesh.cpp">
</File>
<File
RelativePath=".\CollisionShapes\TriangleMesh.h">
</File>
<File
RelativePath=".\CollisionShapes\TriangleMeshShape.cpp">
</File>
<File
RelativePath=".\CollisionShapes\TriangleMeshShape.h">
</File>
<File
RelativePath=".\CollisionShapes\TriangleShape.h">
</File>
</Filter>
<Filter
Name="BroadphaseCollision"
Filter="">
<File
RelativePath=".\BroadphaseCollision\BroadPhaseInterface.h">
</File>
<File
RelativePath=".\BroadphaseCollision\BroadphaseProxy.cpp">
</File>
<File
RelativePath=".\BroadphaseCollision\BroadphaseProxy.h">
</File>
<File
RelativePath=".\BroadphaseCollision\CollisionAlgorithm.cpp">
</File>
<File
RelativePath=".\BroadphaseCollision\CollisionAlgorithm.h">
</File>
<File
RelativePath=".\BroadphaseCollision\CollisionDispatcher.cpp">
</File>
<File
RelativePath=".\BroadphaseCollision\CollisionDispatcher.h">
</File>
<File
RelativePath=".\BroadphaseCollision\SimpleBroadphase.cpp">
</File>
<File
RelativePath=".\BroadphaseCollision\SimpleBroadphase.h">
</File>
</Filter>
<Filter
Name="LinearAlgebra"
Filter="">
<File
RelativePath="..\LinearMath\AabbUtil2.h">
</File>
<File
RelativePath="..\LinearMath\GEN_List.h">
</File>
<File
RelativePath="..\LinearMath\GEN_MinMax.h">
</File>
<File
RelativePath="..\LinearMath\GEN_random.h">
</File>
<File
RelativePath="..\LinearMath\SimdMatrix3x3.h">
</File>
<File
RelativePath="..\LinearMath\SimdMinMax.h">
</File>
<File
RelativePath="..\LinearMath\SimdPoint3.h">
</File>
<File
RelativePath="..\LinearMath\SimdQuadword.h">
</File>
<File
RelativePath="..\LinearMath\SimdQuaternion.h">
</File>
<File
RelativePath="..\LinearMath\SimdScalar.h">
</File>
<File
RelativePath="..\LinearMath\SimdTransform.h">
</File>
<File
RelativePath="..\LinearMath\SimdTransformUtil.h">
</File>
<File
RelativePath="..\LinearMath\SimdVector3.h">
</File>
</Filter>
<File
RelativePath=".\NarrowPhaseCollision\ConvexCast.cpp">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

20
extern/bullet/Bullet/Bullet3_vc8.sln vendored Normal file
View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bullet3ContinuousCollision", "Bullet3_vc8.vcproj", "{FFD3C64A-30E2-4BC7-BC8F-51818C320400}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Debug|Win32.ActiveCfg = Debug|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Debug|Win32.Build.0 = Debug|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Release|Win32.ActiveCfg = Release|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

552
extern/bullet/Bullet/Bullet3_vc8.vcproj vendored Normal file
View File

@@ -0,0 +1,552 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="Bullet3ContinuousCollision"
ProjectGUID="{FFD3C64A-30E2-4BC7-BC8F-51818C320400}"
SignManifests="true"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="4"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=".;..\LinearMath"
PreprocessorDefinitions="_DEBUG;_LIB;WIN32;BUM_INLINED;USE_ALGEBRAIC"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=""
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\Debug\Bullet.lib"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="4"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories=".;..\LinearMath"
PreprocessorDefinitions="NDEBUG;_LIB;WIN32;BUM_INLINED;USE_ALGEBRAIC"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=""
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\Release\Bullet.lib"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="NarrowPhaseCollision"
>
<File
RelativePath=".\NarrowPhaseCollision\BU_AlgebraicPolynomialSolver.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_AlgebraicPolynomialSolver.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_Collidable.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_Collidable.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_CollisionPair.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_CollisionPair.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_EdgeEdge.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_EdgeEdge.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_MotionStateInterface.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_PolynomialSolverInterface.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_Screwing.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_Screwing.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_StaticMotionState.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_VertexPoly.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\BU_VertexPoly.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\CollisionMargin.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\ContinuousConvexCollision.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\ContinuousConvexCollision.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\ConvexCast.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\ConvexCast.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\ConvexPenetrationDepthSolver.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\DiscreteCollisionDetectorInterface.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\GjkConvexCast.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\GjkConvexCast.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\GjkPairDetector.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\GjkPairDetector.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\ManifoldPoint.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\ManifoldPointCollector.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\ManifoldPointCollector.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\MinkowskiPenetrationDepthSolver.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\MinkowskiPenetrationDepthSolver.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\PersistentManifold.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\PersistentManifold.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\PointCollector.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\RaycastCallback.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\RaycastCallback.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\SimplexSolverInterface.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\SubSimplexConvexCast.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\SubSimplexConvexCast.h"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\VoronoiSimplexSolver.cpp"
>
</File>
<File
RelativePath=".\NarrowPhaseCollision\VoronoiSimplexSolver.h"
>
</File>
</Filter>
<Filter
Name="CollisionShapes"
>
<File
RelativePath=".\CollisionShapes\BoxShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\BoxShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\CollisionShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\CollisionShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\ConeShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\ConeShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\ConvexHullShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\ConvexHullShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\ConvexShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\ConvexShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\CylinderShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\CylinderShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\MinkowskiSumShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\MinkowskiSumShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\MultiSphereShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\MultiSphereShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\PolyhedralConvexShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\PolyhedralConvexShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\Simplex1to4Shape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\Simplex1to4Shape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\SphereShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\SphereShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\StridingMeshInterface.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\StridingMeshInterface.h"
>
</File>
<File
RelativePath=".\CollisionShapes\TriangleCallback.h"
>
</File>
<File
RelativePath=".\CollisionShapes\TriangleMeshShape.cpp"
>
</File>
<File
RelativePath=".\CollisionShapes\TriangleMeshShape.h"
>
</File>
<File
RelativePath=".\CollisionShapes\TriangleShape.h"
>
</File>
</Filter>
<Filter
Name="BroadphaseCollision"
>
<File
RelativePath=".\BroadphaseCollision\BroadPhaseInterface.h"
>
</File>
<File
RelativePath=".\BroadphaseCollision\BroadphaseProxy.cpp"
>
</File>
<File
RelativePath=".\BroadphaseCollision\BroadphaseProxy.h"
>
</File>
<File
RelativePath=".\BroadphaseCollision\CollisionAlgorithm.cpp"
>
</File>
<File
RelativePath=".\BroadphaseCollision\CollisionAlgorithm.h"
>
</File>
<File
RelativePath=".\BroadphaseCollision\CollisionDispatcher.cpp"
>
</File>
<File
RelativePath=".\BroadphaseCollision\CollisionDispatcher.h"
>
</File>
<File
RelativePath=".\BroadphaseCollision\SimpleBroadphase.cpp"
>
</File>
<File
RelativePath=".\BroadphaseCollision\SimpleBroadphase.h"
>
</File>
</Filter>
<Filter
Name="LinearAlgebra"
>
<File
RelativePath="..\LinearMath\AabbUtil2.h"
>
</File>
<File
RelativePath="..\LinearMath\GEN_List.h"
>
</File>
<File
RelativePath="..\LinearMath\GEN_MinMax.h"
>
</File>
<File
RelativePath="..\LinearMath\GEN_random.h"
>
</File>
<File
RelativePath="..\LinearMath\SimdMatrix3x3.h"
>
</File>
<File
RelativePath="..\LinearMath\SimdMinMax.h"
>
</File>
<File
RelativePath="..\LinearMath\SimdPoint3.h"
>
</File>
<File
RelativePath="..\LinearMath\SimdQuadword.h"
>
</File>
<File
RelativePath="..\LinearMath\SimdQuaternion.h"
>
</File>
<File
RelativePath="..\LinearMath\SimdScalar.h"
>
</File>
<File
RelativePath="..\LinearMath\SimdTransform.h"
>
</File>
<File
RelativePath="..\LinearMath\SimdTransformUtil.h"
>
</File>
<File
RelativePath="..\LinearMath\SimdVector3.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "BoxShape.h"
void BoxShape::GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const
{
SimdVector3 halfExtents = GetHalfExtents();
SimdMatrix3x3 abs_b = t.getBasis().absolute();
SimdPoint3 center = t.getOrigin();
SimdVector3 extent = SimdVector3(abs_b[0].dot(halfExtents),
abs_b[1].dot(halfExtents),
abs_b[2].dot(halfExtents));
extent += SimdVector3(GetMargin(),GetMargin(),GetMargin());
//todo: this is a quick fix, we need to enlarge the aabb dependent on several criteria
//extent += SimdVector3(.2f,.2f,.2f);
aabbMin = center - extent;
aabbMax = center + extent;
}

View File

@@ -0,0 +1,274 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef OBB_BOX_MINKOWSKI_H
#define OBB_BOX_MINKOWSKI_H
#include "PolyhedralConvexShape.h"
#include "NarrowPhaseCollision/CollisionMargin.h"
#include "BroadphaseCollision/BroadphaseProxy.h"
#include "SimdPoint3.h"
#include "SimdMinMax.h"
///BoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box
class BoxShape: public PolyhedralConvexShape
{
SimdVector3 m_boxHalfExtents1;
public:
virtual ~BoxShape()
{
}
SimdVector3 GetHalfExtents() const{ return m_boxHalfExtents1 * m_localScaling;}
//const SimdVector3& GetHalfExtents() const{ return m_boxHalfExtents1;}
virtual int GetShapeType() const { return BOX_SHAPE_PROXYTYPE;}
virtual SimdVector3 LocalGetSupportingVertex(const SimdVector3& vec) const
{
SimdVector3 halfExtents = GetHalfExtents();
SimdVector3 supVertex;
supVertex = SimdPoint3(vec.x() < SimdScalar(0.0f) ? -halfExtents.x() : halfExtents.x(),
vec.y() < SimdScalar(0.0f) ? -halfExtents.y() : halfExtents.y(),
vec.z() < SimdScalar(0.0f) ? -halfExtents.z() : halfExtents.z());
if ( GetMargin()!=0.f )
{
SimdVector3 vecnorm = vec;
if (vecnorm .length2() == 0.f)
{
vecnorm.setValue(-1.f,-1.f,-1.f);
}
vecnorm.normalize();
supVertex+= GetMargin() * vecnorm;
}
return supVertex;
}
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const
{
SimdVector3 halfExtents = GetHalfExtents();
return SimdVector3(vec.x() < SimdScalar(0.0f) ? -halfExtents.x() : halfExtents.x(),
vec.y() < SimdScalar(0.0f) ? -halfExtents.y() : halfExtents.y(),
vec.z() < SimdScalar(0.0f) ? -halfExtents.z() : halfExtents.z());
}
BoxShape( const SimdVector3& boxHalfExtents) : m_boxHalfExtents1(boxHalfExtents){};
virtual void GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const;
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
{
float margin = GetMargin();
SimdVector3 halfExtents = GetHalfExtents();
SimdScalar lx=2.f*(halfExtents.x()+margin);
SimdScalar ly=2.f*(halfExtents.y()+margin);
SimdScalar lz=2.f*(halfExtents.z()+margin);
const SimdScalar x2 = lx*lx;
const SimdScalar y2 = ly*ly;
const SimdScalar z2 = lz*lz;
const SimdScalar scaledmass = mass * 0.08333333f;
inertia = scaledmass * (SimdVector3(y2+z2,x2+z2,x2+y2));
// inertia.x() = scaledmass * (y2+z2);
// inertia.y() = scaledmass * (x2+z2);
// inertia.z() = scaledmass * (x2+y2);
}
virtual void GetPlane(SimdVector3& planeNormal,SimdPoint3& planeSupport,int i ) const
{
//this plane might not be aligned...
SimdVector4 plane ;
GetPlaneEquation(plane,i);
planeNormal = SimdVector3(plane.getX(),plane.getY(),plane.getZ());
planeSupport = LocalGetSupportingVertex(-planeNormal);
}
virtual int GetNumPlanes() const
{
return 6;
}
virtual int GetNumVertices() const
{
return 8;
}
virtual int GetNumEdges() const
{
return 12;
}
virtual void GetVertex(int i,SimdVector3& vtx) const
{
SimdVector3 halfExtents = GetHalfExtents();
vtx = SimdVector3(
halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
}
virtual void GetPlaneEquation(SimdVector4& plane,int i) const
{
SimdVector3 halfExtents = GetHalfExtents();
switch (i)
{
case 0:
plane.setValue(1.f,0.f,0.f);
plane[3] = -halfExtents.x();
break;
case 1:
plane.setValue(-1.f,0.f,0.f);
plane[3] = -halfExtents.x();
break;
case 2:
plane.setValue(0.f,1.f,0.f);
plane[3] = -halfExtents.y();
break;
case 3:
plane.setValue(0.f,-1.f,0.f);
plane[3] = -halfExtents.y();
break;
case 4:
plane.setValue(0.f,0.f,1.f);
plane[3] = -halfExtents.z();
break;
case 5:
plane.setValue(0.f,0.f,-1.f);
plane[3] = -halfExtents.z();
break;
default:
assert(0);
}
}
virtual void GetEdge(int i,SimdPoint3& pa,SimdPoint3& pb) const
//virtual void GetEdge(int i,Edge& edge) const
{
int edgeVert0 = 0;
int edgeVert1 = 0;
switch (i)
{
case 0:
edgeVert0 = 0;
edgeVert1 = 1;
break;
case 1:
edgeVert0 = 0;
edgeVert1 = 2;
break;
case 2:
edgeVert0 = 1;
edgeVert1 = 3;
break;
case 3:
edgeVert0 = 2;
edgeVert1 = 3;
break;
case 4:
edgeVert0 = 0;
edgeVert1 = 4;
break;
case 5:
edgeVert0 = 1;
edgeVert1 = 5;
break;
case 6:
edgeVert0 = 2;
edgeVert1 = 6;
break;
case 7:
edgeVert0 = 3;
edgeVert1 = 7;
break;
case 8:
edgeVert0 = 4;
edgeVert1 = 5;
break;
case 9:
edgeVert0 = 4;
edgeVert1 = 6;
break;
case 10:
edgeVert0 = 5;
edgeVert1 = 7;
break;
case 11:
edgeVert0 = 6;
edgeVert1 = 7;
break;
default:
ASSERT(0);
}
GetVertex(edgeVert0,pa );
GetVertex(edgeVert1,pb );
}
virtual bool IsInside(const SimdPoint3& pt,SimdScalar tolerance) const
{
SimdVector3 halfExtents = GetHalfExtents();
//SimdScalar minDist = 2*tolerance;
bool result = (pt.x() <= (halfExtents.x()+tolerance)) &&
(pt.x() >= (-halfExtents.x()-tolerance)) &&
(pt.y() <= (halfExtents.y()+tolerance)) &&
(pt.y() >= (-halfExtents.y()-tolerance)) &&
(pt.z() <= (halfExtents.z()+tolerance)) &&
(pt.z() >= (-halfExtents.z()-tolerance));
return result;
}
//debugging
virtual char* GetName()const
{
return "Box";
}
};
#endif //OBB_BOX_MINKOWSKI_H

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "CollisionShapes/CollisionShape.h"
void CollisionShape::GetBoundingSphere(SimdVector3& center,SimdScalar& radius) const
{
SimdTransform tr;
tr.setIdentity();
SimdVector3 aabbMin,aabbMax;
GetAabb(tr,aabbMin,aabbMax);
radius = (aabbMax-aabbMin).length()*0.5f;
center = (aabbMin+aabbMax)*0.5f;
}
float CollisionShape::GetAngularMotionDisc() const
{
SimdVector3 center;
float disc;
GetBoundingSphere(center,disc);
disc += (center).length();
return disc;
}
void CollisionShape::CalculateTemporalAabb(const SimdTransform& curTrans,const SimdVector3& linvel,const SimdVector3& angvel,SimdScalar timeStep, SimdVector3& temporalAabbMin,SimdVector3& temporalAabbMax)
{
//start with static aabb
GetAabb(curTrans,temporalAabbMin,temporalAabbMax);
float temporalAabbMaxx = temporalAabbMax.getX();
float temporalAabbMaxy = temporalAabbMax.getY();
float temporalAabbMaxz = temporalAabbMax.getZ();
float temporalAabbMinx = temporalAabbMin.getX();
float temporalAabbMiny = temporalAabbMin.getY();
float temporalAabbMinz = temporalAabbMin.getZ();
// add linear motion
SimdVector3 linMotion = linvel*timeStep;
//todo: simd would have a vector max/min operation, instead of per-element access
if (linMotion.x() > 0.f)
temporalAabbMaxx += linMotion.x();
else
temporalAabbMinx += linMotion.x();
if (linMotion.y() > 0.f)
temporalAabbMaxy += linMotion.y();
else
temporalAabbMiny += linMotion.y();
if (linMotion.z() > 0.f)
temporalAabbMaxz += linMotion.z();
else
temporalAabbMinz += linMotion.z();
//add conservative angular motion
SimdScalar angularMotion = angvel.length() * GetAngularMotionDisc() * timeStep;
SimdVector3 angularMotion3d(angularMotion,angularMotion,angularMotion);
temporalAabbMin = SimdVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz);
temporalAabbMax = SimdVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz);
temporalAabbMin -= angularMotion3d;
temporalAabbMax += angularMotion3d;
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef COLLISION_SHAPE_H
#define COLLISION_SHAPE_H
#include "SimdTransform.h"
#include "SimdVector3.h"
#include <SimdMatrix3x3.h>
#include "SimdPoint3.h"
#include "BroadphaseCollision/BroadphaseProxy.h" //for the shape types
///CollisionShape provides generic interface for collidable objects
class CollisionShape
{
public:
CollisionShape()
:m_tempDebug(0)
{
}
virtual ~CollisionShape()
{
}
virtual void GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const =0;
virtual void GetBoundingSphere(SimdVector3& center,SimdScalar& radius) const;
virtual float GetAngularMotionDisc() const;
virtual int GetShapeType() const=0;
///CalculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
///result is conservative
void CalculateTemporalAabb(const SimdTransform& curTrans,const SimdVector3& linvel,const SimdVector3& angvel,SimdScalar timeStep, SimdVector3& temporalAabbMin,SimdVector3& temporalAabbMax);
bool IsPolyhedral() const
{
return (GetShapeType() < IMPLICIT_CONVEX_SHAPES_START_HERE);
}
bool IsConvex() const
{
return (GetShapeType() < CONCAVE_SHAPES_START_HERE);
}
bool IsConcave() const
{
return (GetShapeType() > CONCAVE_SHAPES_START_HERE);
}
virtual void setLocalScaling(const SimdVector3& scaling) =0;
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia) = 0;
//debugging support
virtual char* GetName()const =0 ;
const char* GetExtraDebugInfo() const { return m_tempDebug;}
void SetExtraDebugInfo(const char* extraDebugInfo) { m_tempDebug = extraDebugInfo;}
const char * m_tempDebug;
//endif debugging support
};
#endif //COLLISION_SHAPE_H

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "ConeShape.h"
#include "SimdPoint3.h"
#ifdef WIN32
static int coneindices[3] = {1,2,0};
#else
static int coneindices[3] = {2,1,0};
#endif
ConeShape::ConeShape (SimdScalar radius,SimdScalar height):
m_radius (radius),
m_height(height)
{
SimdVector3 halfExtents;
m_sinAngle = (m_radius / sqrt(m_radius * m_radius + m_height * m_height));
}
SimdVector3 ConeShape::ConeLocalSupport(const SimdVector3& v) const
{
float halfHeight = m_height * 0.5f;
if (v[coneindices[1]] > v.length() * m_sinAngle)
{
SimdVector3 tmp;
tmp[coneindices[0]] = 0.f;
tmp[coneindices[1]] = halfHeight;
tmp[coneindices[2]] = 0.f;
return tmp;
}
else {
SimdScalar s = sqrtf(v[coneindices[0]] * v[coneindices[0]] + v[coneindices[2]] * v[coneindices[2]]);
if (s > SIMD_EPSILON) {
SimdScalar d = m_radius / s;
SimdVector3 tmp;
tmp[coneindices[0]] = v[coneindices[0]] * d;
tmp[coneindices[1]] = -halfHeight;
tmp[coneindices[2]] = v[coneindices[2]] * d;
return tmp;
}
else {
SimdVector3 tmp;
tmp[coneindices[0]] = 0.f;
tmp[coneindices[1]] = -halfHeight;
tmp[coneindices[2]] = 0.f;
return tmp;
}
}
}
SimdVector3 ConeShape::LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec) const
{
return ConeLocalSupport(vec);
}
SimdVector3 ConeShape::LocalGetSupportingVertex(const SimdVector3& vec) const
{
SimdVector3 supVertex = ConeLocalSupport(vec);
if ( GetMargin()!=0.f )
{
SimdVector3 vecnorm = vec;
if (vecnorm .length2() == 0.f)
{
vecnorm.setValue(-1.f,-1.f,-1.f);
}
vecnorm.normalize();
supVertex+= GetMargin() * vecnorm;
}
return supVertex;
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONE_MINKOWSKI_H
#define CONE_MINKOWSKI_H
#include "ConvexShape.h"
#include "BroadphaseCollision/BroadphaseProxy.h" // for the types
/// implements cone shape interface
class ConeShape : public ConvexShape
{
float m_sinAngle;
float m_radius;
float m_height;
SimdVector3 ConeLocalSupport(const SimdVector3& v) const;
public:
ConeShape (SimdScalar radius,SimdScalar height);
virtual SimdVector3 LocalGetSupportingVertex(const SimdVector3& vec) const;
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec) const;
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
{
SimdTransform identity;
identity.setIdentity();
SimdVector3 aabbMin,aabbMax;
GetAabb(identity,aabbMin,aabbMax);
SimdVector3 halfExtents = (aabbMax-aabbMin)*0.5f;
float margin = GetMargin();
SimdScalar lx=2.f*(halfExtents.x()+margin);
SimdScalar ly=2.f*(halfExtents.y()+margin);
SimdScalar lz=2.f*(halfExtents.z()+margin);
const SimdScalar x2 = lx*lx;
const SimdScalar y2 = ly*ly;
const SimdScalar z2 = lz*lz;
const SimdScalar scaledmass = mass * 0.08333333f;
inertia = scaledmass * (SimdVector3(y2+z2,x2+z2,x2+y2));
// inertia.x() = scaledmass * (y2+z2);
// inertia.y() = scaledmass * (x2+z2);
// inertia.z() = scaledmass * (x2+y2);
}
virtual int GetShapeType() const { return CONE_SHAPE_PROXYTYPE; }
virtual char* GetName()const
{
return "Cone";
}
};
#endif //CONE_MINKOWSKI_H

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "ConvexHullShape.h"
#include "NarrowPhaseCollision/CollisionMargin.h"
#include "SimdQuaternion.h"
ConvexHullShape ::ConvexHullShape (SimdPoint3* points,int numPoints)
{
m_points.resize(numPoints);
for (int i=0;i<numPoints;i++)
m_points[i] = points[i];
}
SimdVector3 ConvexHullShape::LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec0)const
{
SimdVector3 supVec(0.f,0.f,0.f);
SimdScalar newDot,maxDot = -1e30f;
SimdVector3 vec = vec0;
SimdScalar lenSqr = vec.length2();
if (lenSqr < 0.0001f)
{
vec.setValue(1,0,0);
} else
{
float rlen = 1.f / sqrtf(lenSqr );
vec *= rlen;
}
for (int i=0;i<m_points.size();i++)
{
SimdPoint3 vtx = m_points[i] * m_localScaling;
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supVec = vtx;
}
}
return supVec;
}
SimdVector3 ConvexHullShape::LocalGetSupportingVertex(const SimdVector3& vec)const
{
SimdVector3 supVertex = LocalGetSupportingVertexWithoutMargin(vec);
if ( GetMargin()!=0.f )
{
SimdVector3 vecnorm = vec;
if (vecnorm .length2() == 0.f)
{
vecnorm.setValue(-1.f,-1.f,-1.f);
}
vecnorm.normalize();
supVertex+= GetMargin() * vecnorm;
}
return supVertex;
}
void ConvexHullShape::CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
{
//not yet, return box inertia
float margin = GetMargin();
SimdTransform ident;
ident.setIdentity();
SimdVector3 aabbMin,aabbMax;
GetAabb(ident,aabbMin,aabbMax);
SimdVector3 halfExtents = (aabbMax-aabbMin)*0.5f;
SimdScalar lx=2.f*(halfExtents.x()+margin);
SimdScalar ly=2.f*(halfExtents.y()+margin);
SimdScalar lz=2.f*(halfExtents.z()+margin);
const SimdScalar x2 = lx*lx;
const SimdScalar y2 = ly*ly;
const SimdScalar z2 = lz*lz;
const SimdScalar scaledmass = mass * 0.08333333f;
inertia = scaledmass * (SimdVector3(y2+z2,x2+z2,x2+y2));
}
//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
//Please note that you can debug-draw ConvexHullShape with the Raytracer Demo
int ConvexHullShape::GetNumVertices() const
{
return m_points.size();
}
int ConvexHullShape::GetNumEdges() const
{
return m_points.size()*m_points.size();
}
void ConvexHullShape::GetEdge(int i,SimdPoint3& pa,SimdPoint3& pb) const
{
int index0 = i%m_points.size();
int index1 = i/m_points.size();
pa = m_points[index0];
pb = m_points[index1];
}
void ConvexHullShape::GetVertex(int i,SimdPoint3& vtx) const
{
vtx = m_points[i];
}
int ConvexHullShape::GetNumPlanes() const
{
return 0;
}
void ConvexHullShape::GetPlane(SimdVector3& planeNormal,SimdPoint3& planeSupport,int i ) const
{
assert(0);
}
//not yet
bool ConvexHullShape::IsInside(const SimdPoint3& pt,SimdScalar tolerance) const
{
assert(0);
return false;
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONVEX_HULL_SHAPE_H
#define CONVEX_HULL_SHAPE_H
#include "PolyhedralConvexShape.h"
#include "BroadphaseCollision/BroadphaseProxy.h" // for the types
#include <vector>
///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices)
///No connectivity is needed. LocalGetSupportingVertex iterates linearly though all vertices.
///on modern hardware, due to cache coherency this isn't that bad. Complex algorithms tend to trash the cash.
///(memory is much slower then the cpu)
class ConvexHullShape : public PolyhedralConvexShape
{
std::vector<SimdPoint3> m_points;
public:
ConvexHullShape(SimdPoint3* points,int numPoints);
void AddPoint(const SimdPoint3& point)
{
m_points.push_back(point);
}
virtual SimdVector3 LocalGetSupportingVertex(const SimdVector3& vec)const;
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const;
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia);
virtual int GetShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; }
//debugging
virtual char* GetName()const {return "Convex";}
virtual int GetNumVertices() const;
virtual int GetNumEdges() const;
virtual void GetEdge(int i,SimdPoint3& pa,SimdPoint3& pb) const;
virtual void GetVertex(int i,SimdPoint3& vtx) const;
virtual int GetNumPlanes() const;
virtual void GetPlane(SimdVector3& planeNormal,SimdPoint3& planeSupport,int i ) const;
virtual bool IsInside(const SimdPoint3& pt,SimdScalar tolerance) const;
};
#endif //CONVEX_HULL_SHAPE_H

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "ConvexShape.h"
ConvexShape::~ConvexShape()
{
}
ConvexShape::ConvexShape()
:m_collisionMargin(CONVEX_DISTANCE_MARGIN),
m_localScaling(1.f,1.f,1.f)
{
}
void ConvexShape::setLocalScaling(const SimdVector3& scaling)
{
m_localScaling = scaling;
}
void ConvexShape::GetAabbSlow(const SimdTransform& trans,SimdVector3&minAabb,SimdVector3&maxAabb) const
{
SimdScalar margin = 0.05f;
for (int i=0;i<3;i++)
{
SimdVector3 vec(0.f,0.f,0.f);
vec[i] = 1.f;
SimdVector3 tmp = trans(LocalGetSupportingVertex(vec*trans.getBasis()));
maxAabb[i] = tmp[i]+margin;
vec[i] = -1.f;
tmp = trans(LocalGetSupportingVertex(vec*trans.getBasis()));
minAabb[i] = tmp[i]-margin;
}
};
SimdVector3 ConvexShape::LocalGetSupportingVertex(const SimdVector3& vec)const
{
SimdVector3 supVertex = LocalGetSupportingVertexWithoutMargin(vec);
if ( GetMargin()!=0.f )
{
SimdVector3 vecnorm = vec;
if (vecnorm .length2() == 0.f)
{
vecnorm.setValue(-1.f,-1.f,-1.f);
}
vecnorm.normalize();
supVertex+= GetMargin() * vecnorm;
}
return supVertex;
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONVEX_SHAPE_INTERFACE1
#define CONVEX_SHAPE_INTERFACE1
#include "CollisionShape.h"
#include "SimdVector3.h"
#include "SimdTransform.h"
#include "SimdMatrix3x3.h"
#include <vector>
#include "NarrowPhaseCollision/CollisionMargin.h"
//todo: get rid of this ConvexCastResult thing!
struct ConvexCastResult;
/// ConvexShape is an abstract shape interface.
/// The explicit part provides plane-equations, the implicit part provides GetClosestPoint interface.
/// used in combination with GJK or ConvexCast
class ConvexShape : public CollisionShape
{
public:
ConvexShape();
virtual ~ConvexShape();
virtual SimdVector3 LocalGetSupportingVertex(const SimdVector3& vec)const;
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec) const= 0;
// testing for hullnode code
///GetAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
void GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const
{
GetAabbSlow(t,aabbMin,aabbMax);
}
virtual void GetAabbSlow(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const;
virtual void setLocalScaling(const SimdVector3& scaling);
virtual void SetMargin(float margin)
{
m_collisionMargin = margin;
}
virtual float GetMargin() const
{
return m_collisionMargin;
}
private:
SimdScalar m_collisionMargin;
//local scaling. collisionMargin is not scaled !
protected:
SimdVector3 m_localScaling;
};
#endif //CONVEX_SHAPE_INTERFACE1

View File

@@ -0,0 +1,169 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "CylinderShape.h"
#include "SimdPoint3.h"
CylinderShape::CylinderShape (const SimdVector3& halfExtents)
:BoxShape(halfExtents)
{
}
CylinderShapeX::CylinderShapeX (const SimdVector3& halfExtents)
:CylinderShape(halfExtents)
{
}
CylinderShapeZ::CylinderShapeZ (const SimdVector3& halfExtents)
:CylinderShape(halfExtents)
{
}
SimdVector3 CylinderLocalSupportX(const SimdVector3& halfExtents,const SimdVector3& v)
{
const int cylinderUpAxis = 0;
const int XX = 1;
const int YY = 0;
const int ZZ = 2;
//mapping depends on how cylinder local orientation is
// extents of the cylinder is: X,Y is for radius, and Z for height
float radius = halfExtents[XX];
float halfHeight = halfExtents[cylinderUpAxis];
SimdVector3 tmp;
SimdScalar d ;
SimdScalar s = sqrtf(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
if (s != SimdScalar(0.0))
{
d = radius / s;
tmp[XX] = v[XX] * d;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = v[ZZ] * d;
return tmp;
}
else
{
tmp[XX] = radius;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = SimdScalar(0.0);
return tmp;
}
}
SimdVector3 CylinderLocalSupportY(const SimdVector3& halfExtents,const SimdVector3& v)
{
const int cylinderUpAxis = 1;
const int XX = 0;
const int YY = 1;
const int ZZ = 2;
float radius = halfExtents[XX];
float halfHeight = halfExtents[cylinderUpAxis];
SimdVector3 tmp;
SimdScalar d ;
SimdScalar s = sqrtf(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
if (s != SimdScalar(0.0))
{
d = radius / s;
tmp[XX] = v[XX] * d;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = v[ZZ] * d;
return tmp;
}
else
{
tmp[XX] = radius;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = SimdScalar(0.0);
return tmp;
}
}
SimdVector3 CylinderLocalSupportZ(const SimdVector3& halfExtents,const SimdVector3& v)
{
const int cylinderUpAxis = 2;
const int XX = 0;
const int YY = 2;
const int ZZ = 1;
//mapping depends on how cylinder local orientation is
// extents of the cylinder is: X,Y is for radius, and Z for height
float radius = halfExtents[XX];
float halfHeight = halfExtents[cylinderUpAxis];
SimdVector3 tmp;
SimdScalar d ;
SimdScalar s = sqrtf(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
if (s != SimdScalar(0.0))
{
d = radius / s;
tmp[XX] = v[XX] * d;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = v[ZZ] * d;
return tmp;
}
else
{
tmp[XX] = radius;
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
tmp[ZZ] = SimdScalar(0.0);
return tmp;
}
}
SimdVector3 CylinderShapeX::LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const
{
return CylinderLocalSupportX(GetHalfExtents(),vec);
}
SimdVector3 CylinderShapeZ::LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const
{
return CylinderLocalSupportZ(GetHalfExtents(),vec);
}
SimdVector3 CylinderShape::LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const
{
return CylinderLocalSupportY(GetHalfExtents(),vec);
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CYLINDER_MINKOWSKI_H
#define CYLINDER_MINKOWSKI_H
#include "BoxShape.h"
#include "BroadphaseCollision/BroadphaseProxy.h" // for the types
#include "SimdVector3.h"
/// implements cylinder shape interface
class CylinderShape : public BoxShape
{
public:
CylinderShape (const SimdVector3& halfExtents);
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const;
//use box inertia
// virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia);
virtual int GetShapeType() const
{
return CYLINDER_SHAPE_PROXYTYPE;
}
};
class CylinderShapeX : public CylinderShape
{
public:
CylinderShapeX (const SimdVector3& halfExtents);
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const;
};
class CylinderShapeZ : public CylinderShape
{
public:
CylinderShapeZ (const SimdVector3& halfExtents);
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const;
};
#endif //CYLINDER_MINKOWSKI_H

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "MinkowskiSumShape.h"
MinkowskiSumShape::MinkowskiSumShape(ConvexShape* shapeA,ConvexShape* shapeB)
:m_shapeA(shapeA),
m_shapeB(shapeB)
{
m_transA.setIdentity();
m_transB.setIdentity();
}
SimdVector3 MinkowskiSumShape::LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const
{
SimdVector3 supVertexA = m_transA(m_shapeA->LocalGetSupportingVertexWithoutMargin(vec*m_transA.getBasis()));
SimdVector3 supVertexB = m_transB(m_shapeB->LocalGetSupportingVertexWithoutMargin(vec*m_transB.getBasis()));
return supVertexA + supVertexB;
}
float MinkowskiSumShape::GetMargin() const
{
return m_shapeA->GetMargin() + m_shapeB->GetMargin();
}
void MinkowskiSumShape::CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
{
assert(0);
inertia.setValue(0,0,0);
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef MINKOWSKI_SUM_SHAPE_H
#define MINKOWSKI_SUM_SHAPE_H
#include "ConvexShape.h"
#include "BroadphaseCollision/BroadphaseProxy.h" // for the types
/// MinkowskiSumShape represents implicit (getSupportingVertex) based minkowski sum of two convex implicit shapes.
class MinkowskiSumShape : public ConvexShape
{
SimdTransform m_transA;
SimdTransform m_transB;
ConvexShape* m_shapeA;
ConvexShape* m_shapeB;
public:
MinkowskiSumShape(ConvexShape* shapeA,ConvexShape* shapeB);
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const;
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia);
void SetTransformA(const SimdTransform& transA) { m_transA = transA;}
void SetTransformB(const SimdTransform& transB) { m_transB = transB;}
const SimdTransform& GetTransformA()const { return m_transA;}
const SimdTransform& GetTransformB()const { return m_transB;}
virtual int GetShapeType() const { return MINKOWSKI_SUM_SHAPE_PROXYTYPE; }
virtual float GetMargin() const;
const ConvexShape* GetShapeA() const { return m_shapeA;}
const ConvexShape* GetShapeB() const { return m_shapeB;}
virtual char* GetName()const
{
return "MinkowskiSum";
}
};
#endif //MINKOWSKI_SUM_SHAPE_H

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "MultiSphereShape.h"
#include "NarrowPhaseCollision/CollisionMargin.h"
#include "SimdQuaternion.h"
MultiSphereShape::MultiSphereShape (const SimdVector3& inertiaHalfExtents,const SimdVector3* positions,const SimdScalar* radi,int numSpheres)
:m_inertiaHalfExtents(inertiaHalfExtents)
{
m_minRadius = 1e30f;
m_numSpheres = numSpheres;
for (int i=0;i<m_numSpheres;i++)
{
m_localPositions[i] = positions[i];
m_radi[i] = radi[i];
if (radi[i] < m_minRadius)
m_minRadius = radi[i];
}
SetMargin(m_minRadius);
}
SimdVector3 MultiSphereShape::LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec0)const
{
int i;
SimdVector3 supVec(0,0,0);
SimdScalar maxDot(-1e30f);
SimdVector3 vec = vec0;
SimdScalar lenSqr = vec.length2();
if (lenSqr < 0.0001f)
{
vec.setValue(1,0,0);
} else
{
float rlen = 1.f / sqrtf(lenSqr );
vec *= rlen;
}
SimdVector3 vtx;
SimdScalar newDot;
const SimdVector3* pos = &m_localPositions[0];
const SimdScalar* rad = &m_radi[0];
for (i=0;i<m_numSpheres;i++)
{
vtx = (*pos) +vec*((*rad)-m_minRadius);
pos++;
rad++;
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supVec = vtx;
}
}
return supVec;
}
void MultiSphereShape::CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
{
//as an approximation, take the inertia of the box that bounds the spheres
SimdTransform ident;
ident.setIdentity();
// SimdVector3 aabbMin,aabbMax;
// GetAabb(ident,aabbMin,aabbMax);
SimdVector3 halfExtents = m_inertiaHalfExtents;//(aabbMax - aabbMin)* 0.5f;
float margin = CONVEX_DISTANCE_MARGIN;
SimdScalar lx=2.f*(halfExtents[0]+margin);
SimdScalar ly=2.f*(halfExtents[1]+margin);
SimdScalar lz=2.f*(halfExtents[2]+margin);
const SimdScalar x2 = lx*lx;
const SimdScalar y2 = ly*ly;
const SimdScalar z2 = lz*lz;
const SimdScalar scaledmass = mass * 0.08333333f;
inertia[0] = scaledmass * (y2+z2);
inertia[1] = scaledmass * (x2+z2);
inertia[2] = scaledmass * (x2+y2);
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef MULTI_SPHERE_MINKOWSKI_H
#define MULTI_SPHERE_MINKOWSKI_H
#include "ConvexShape.h"
#include "BroadphaseCollision/BroadphaseProxy.h" // for the types
#define MAX_NUM_SPHERES 5
///MultiSphereShape represents implicit convex hull of a collection of spheres (using getSupportingVertex)
class MultiSphereShape : public ConvexShape
{
SimdVector3 m_localPositions[MAX_NUM_SPHERES];
SimdScalar m_radi[MAX_NUM_SPHERES];
SimdVector3 m_inertiaHalfExtents;
int m_numSpheres;
float m_minRadius;
public:
MultiSphereShape (const SimdVector3& inertiaHalfExtents,const SimdVector3* positions,const SimdScalar* radi,int numSpheres);
///CollisionShape Interface
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia);
/// ConvexShape Interface
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const;
virtual int GetShapeType() const { return MULTI_SPHERE_SHAPE_PROXYTYPE; }
virtual char* GetName()const
{
return "MultiSphere";
}
};
#endif //MULTI_SPHERE_MINKOWSKI_H

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include <CollisionShapes/PolyhedralConvexShape.h>
PolyhedralConvexShape::PolyhedralConvexShape()
{
}
SimdVector3 PolyhedralConvexShape::LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec0)const
{
int i;
SimdVector3 supVec(0,0,0);
SimdScalar maxDot(-1e30f);
SimdVector3 vec = vec0;
SimdScalar lenSqr = vec.length2();
if (lenSqr < 0.0001f)
{
vec.setValue(1,0,0);
} else
{
float rlen = 1.f / sqrtf(lenSqr );
vec *= rlen;
}
SimdVector3 vtx;
SimdScalar newDot;
for (i=0;i<GetNumVertices();i++)
{
GetVertex(i,vtx);
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supVec = vtx;
}
}
return supVec;
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef BU_SHAPE
#define BU_SHAPE
#include <SimdPoint3.h>
#include <SimdMatrix3x3.h>
#include <CollisionShapes/ConvexShape.h>
///PolyhedralConvexShape is an interface class for feature based (vertex/edge/face) convex shapes.
class PolyhedralConvexShape : public ConvexShape
{
public:
PolyhedralConvexShape();
//brute force implementations
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const;
virtual int GetNumVertices() const = 0 ;
virtual int GetNumEdges() const = 0;
virtual void GetEdge(int i,SimdPoint3& pa,SimdPoint3& pb) const = 0;
virtual void GetVertex(int i,SimdPoint3& vtx) const = 0;
virtual int GetNumPlanes() const = 0;
virtual void GetPlane(SimdVector3& planeNormal,SimdPoint3& planeSupport,int i ) const = 0;
// virtual int GetIndex(int i) const = 0 ;
virtual bool IsInside(const SimdPoint3& pt,SimdScalar tolerance) const = 0;
};
#endif //BU_SHAPE

View File

@@ -0,0 +1,188 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "Simplex1to4Shape.h"
#include "SimdMatrix3x3.h"
BU_Simplex1to4::BU_Simplex1to4()
:m_numVertices(0)
{
}
BU_Simplex1to4::BU_Simplex1to4(const SimdPoint3& pt0)
:m_numVertices(0)
{
AddVertex(pt0);
}
BU_Simplex1to4::BU_Simplex1to4(const SimdPoint3& pt0,const SimdPoint3& pt1)
:m_numVertices(0)
{
AddVertex(pt0);
AddVertex(pt1);
}
BU_Simplex1to4::BU_Simplex1to4(const SimdPoint3& pt0,const SimdPoint3& pt1,const SimdPoint3& pt2)
:m_numVertices(0)
{
AddVertex(pt0);
AddVertex(pt1);
AddVertex(pt2);
}
BU_Simplex1to4::BU_Simplex1to4(const SimdPoint3& pt0,const SimdPoint3& pt1,const SimdPoint3& pt2,const SimdPoint3& pt3)
:m_numVertices(0)
{
AddVertex(pt0);
AddVertex(pt1);
AddVertex(pt2);
AddVertex(pt3);
}
void BU_Simplex1to4::AddVertex(const SimdPoint3& pt)
{
m_vertices[m_numVertices++] = pt;
}
int BU_Simplex1to4::GetNumVertices() const
{
return m_numVertices;
}
int BU_Simplex1to4::GetNumEdges() const
{
//euler formula, F-E+V = 2, so E = F+V-2
switch (m_numVertices)
{
case 0:
return 0;
case 1: return 0;
case 2: return 1;
case 3: return 3;
case 4: return 6;
}
return 0;
}
void BU_Simplex1to4::GetEdge(int i,SimdPoint3& pa,SimdPoint3& pb) const
{
switch (m_numVertices)
{
case 2:
pa = m_vertices[0];
pb = m_vertices[1];
break;
case 3:
switch (i)
{
case 0:
pa = m_vertices[0];
pb = m_vertices[1];
break;
case 1:
pa = m_vertices[1];
pb = m_vertices[2];
break;
case 2:
pa = m_vertices[2];
pb = m_vertices[0];
break;
}
break;
case 4:
switch (i)
{
case 0:
pa = m_vertices[0];
pb = m_vertices[1];
break;
case 1:
pa = m_vertices[1];
pb = m_vertices[2];
break;
case 2:
pa = m_vertices[2];
pb = m_vertices[0];
break;
case 3:
pa = m_vertices[0];
pb = m_vertices[3];
break;
case 4:
pa = m_vertices[1];
pb = m_vertices[3];
break;
case 5:
pa = m_vertices[2];
pb = m_vertices[3];
break;
}
}
}
void BU_Simplex1to4::GetVertex(int i,SimdPoint3& vtx) const
{
vtx = m_vertices[i];
}
int BU_Simplex1to4::GetNumPlanes() const
{
switch (m_numVertices)
{
case 0:
return 0;
case 1:
return 0;
case 2:
return 0;
case 3:
return 2;
case 4:
return 4;
default:
{
}
}
return 0;
}
void BU_Simplex1to4::GetPlane(SimdVector3& planeNormal,SimdPoint3& planeSupport,int i) const
{
}
int BU_Simplex1to4::GetIndex(int i) const
{
return 0;
}
bool BU_Simplex1to4::IsInside(const SimdPoint3& pt,SimdScalar tolerance) const
{
return false;
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef BU_SIMPLEX_1TO4_SHAPE
#define BU_SIMPLEX_1TO4_SHAPE
#include <CollisionShapes/PolyhedralConvexShape.h>
#include "BroadphaseCollision/BroadphaseProxy.h"
///BU_Simplex1to4 implements feature based and implicit simplex of up to 4 vertices (tetrahedron, triangle, line, vertex).
class BU_Simplex1to4 : public PolyhedralConvexShape
{
protected:
int m_numVertices;
SimdPoint3 m_vertices[4];
public:
BU_Simplex1to4();
BU_Simplex1to4(const SimdPoint3& pt0);
BU_Simplex1to4(const SimdPoint3& pt0,const SimdPoint3& pt1);
BU_Simplex1to4(const SimdPoint3& pt0,const SimdPoint3& pt1,const SimdPoint3& pt2);
BU_Simplex1to4(const SimdPoint3& pt0,const SimdPoint3& pt1,const SimdPoint3& pt2,const SimdPoint3& pt3);
void Reset()
{
m_numVertices = 0;
}
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
{
inertia = SimdVector3(1.f,1.f,1.f);
}
virtual int GetShapeType() const{ return TETRAHEDRAL_SHAPE_PROXYTYPE; }
void AddVertex(const SimdPoint3& pt);
//PolyhedralConvexShape interface
virtual int GetNumVertices() const;
virtual int GetNumEdges() const;
virtual void GetEdge(int i,SimdPoint3& pa,SimdPoint3& pb) const;
virtual void GetVertex(int i,SimdPoint3& vtx) const;
virtual int GetNumPlanes() const;
virtual void GetPlane(SimdVector3& planeNormal,SimdPoint3& planeSupport,int i) const;
virtual int GetIndex(int i) const;
virtual bool IsInside(const SimdPoint3& pt,SimdScalar tolerance) const;
///GetName is for debugging
virtual char* GetName()const { return "BU_Simplex1to4";}
};
#endif //BU_SIMPLEX_1TO4_SHAPE

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "SphereShape.h"
#include "NarrowPhaseCollision/CollisionMargin.h"
#include "SimdQuaternion.h"
SphereShape ::SphereShape (SimdScalar radius)
: m_radius(radius)
{
SetMargin( radius );
}
SimdVector3 SphereShape::LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const
{
return SimdVector3(0.f,0.f,0.f);
}
SimdVector3 SphereShape::LocalGetSupportingVertex(const SimdVector3& vec)const
{
SimdScalar len = vec.length2();
if (fabsf(len) < 0.0001f)
{
return SimdVector3(GetMargin(),GetMargin(),GetMargin());
}
return vec * (GetMargin() / sqrtf(len));
}
void SphereShape::GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const
{
const SimdVector3& center = t.getOrigin();
SimdScalar radius = m_radius + CONVEX_DISTANCE_MARGIN;
radius += 1;
const SimdVector3 extent(radius,radius,radius);
aabbMin = center - extent;
aabbMax = center + extent;
}
void SphereShape::CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
{
SimdScalar elem = 0.4f * mass * m_radius*m_radius;
inertia[0] = inertia[1] = inertia[2] = elem;
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef SPHERE_MINKOWSKI_H
#define SPHERE_MINKOWSKI_H
#include "ConvexShape.h"
#include "BroadphaseCollision/BroadphaseProxy.h" // for the types
///SphereShape implements an implicit (getSupportingVertex) Sphere
class SphereShape : public ConvexShape
{
SimdScalar m_radius;
public:
SphereShape (SimdScalar radius);
virtual SimdVector3 LocalGetSupportingVertex(const SimdVector3& vec)const;
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const;
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia);
virtual void GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const;
virtual int GetShapeType() const { return SPHERE_SHAPE_PROXYTYPE; }
SimdScalar GetRadius() { return m_radius;}
//debugging
virtual char* GetName()const {return "SPHERE";}
};
#endif //SPHERE_MINKOWSKI_H

View File

@@ -0,0 +1,16 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "StridingMeshInterface.h"
StridingMeshInterface::~StridingMeshInterface()
{
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef STRIDING_MESHINTERFACE_H
#define STRIDING_MESHINTERFACE_H
#include "SimdVector3.h"
/// PHY_ScalarType enumerates possible scalar types.
/// See the StridingMeshInterface for its use
typedef enum PHY_ScalarType {
PHY_FLOAT,
PHY_DOUBLE,
PHY_INTEGER,
PHY_SHORT,
PHY_FIXEDPOINT88
} PHY_ScalarType;
/// StridingMeshInterface is the interface class for high performance access to triangle meshes
/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
class StridingMeshInterface
{
protected:
SimdVector3 m_scaling;
public:
StridingMeshInterface() :m_scaling(1.f,1.f,1.f)
{
}
virtual ~StridingMeshInterface();
/// get read and write access to a subpart of a triangle mesh
/// this subpart has a continuous array of vertices and indices
/// in this way the mesh can be handled as chunks of memory with striding
/// very similar to OpenGL vertexarray support
/// make a call to unLockVertexBase when the read and write access is finished
virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0;
/// unLockVertexBase finishes the access to a subpart of the triangle mesh
/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
virtual void unLockVertexBase(int subpart)=0;
/// getNumSubParts returns the number of seperate subparts
/// each subpart has a continuous array of vertices and indices
virtual int getNumSubParts()=0;
virtual void preallocateVertices(int numverts)=0;
virtual void preallocateIndices(int numindices)=0;
const SimdVector3& getScaling() {
return m_scaling;
}
void setScaling(const SimdVector3& scaling)
{
m_scaling = scaling;
}
};
#endif //STRIDING_MESHINTERFACE_H

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef TRIANGLE_CALLBACK_H
#define TRIANGLE_CALLBACK_H
#include "SimdVector3.h"
class TriangleCallback
{
public:
virtual ~TriangleCallback();
virtual void ProcessTriangle(SimdVector3* triangle) = 0;
};
#endif //TRIANGLE_CALLBACK_H

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "TriangleMesh.h"
#include <assert.h>
static int myindices[3] = {0,1,2};
TriangleMesh::TriangleMesh ()
{
}
void TriangleMesh::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
{
numverts = 3;
*vertexbase = (unsigned char*)&m_triangles[subpart];
type = PHY_FLOAT;
stride = sizeof(SimdVector3);
numfaces = 1;
*indexbase = (unsigned char*) &myindices[0];
indicestype = PHY_INTEGER;
indexstride = sizeof(int);
}
int TriangleMesh::getNumSubParts()
{
return m_triangles.size();
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef TRIANGLE_MESH_H
#define TRIANGLE_MESH_H
#include "CollisionShapes/StridingMeshInterface.h"
#include <vector>
#include <SimdVector3.h>
struct MyTriangle
{
SimdVector3 m_vert0;
SimdVector3 m_vert1;
SimdVector3 m_vert2;
};
///TriangleMesh provides storage for a concave triangle mesh. It can be used as data for the TriangleMeshShape.
class TriangleMesh : public StridingMeshInterface
{
std::vector<MyTriangle> m_triangles;
public:
TriangleMesh ();
void AddTriangle(const SimdVector3& vertex0,const SimdVector3& vertex1,const SimdVector3& vertex2)
{
MyTriangle tri;
tri.m_vert0 = vertex0;
tri.m_vert1 = vertex1;
tri.m_vert2 = vertex2;
m_triangles.push_back(tri);
}
//StridingMeshInterface interface implementation
virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
/// unLockVertexBase finishes the access to a subpart of the triangle mesh
/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
virtual void unLockVertexBase(int subpart) {}
/// getNumSubParts returns the number of seperate subparts
/// each subpart has a continuous array of vertices and indices
virtual int getNumSubParts();
virtual void preallocateVertices(int numverts){}
virtual void preallocateIndices(int numindices){}
};
#endif //TRIANGLE_MESH_H

View File

@@ -0,0 +1,182 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "TriangleMeshShape.h"
#include "SimdVector3.h"
#include "SimdQuaternion.h"
#include "StridingMeshInterface.h"
#include "AabbUtil2.h"
TriangleMeshShape::TriangleMeshShape(StridingMeshInterface* meshInterface)
: m_meshInterface(meshInterface)
{
}
TriangleMeshShape::~TriangleMeshShape()
{
}
void TriangleMeshShape::GetAabb(const SimdTransform& trans,SimdVector3& aabbMin,SimdVector3& aabbMax) const
{
SimdScalar margin = 0.5f;
for (int i=0;i<3;i++)
{
SimdVector3 vec(0.f,0.f,0.f);
vec[i] = 1.f;
SimdVector3 tmp = trans(LocalGetSupportingVertex(vec*trans.getBasis()));
aabbMax[i] = tmp[i]+margin;
vec[i] = -1.f;
tmp = trans(LocalGetSupportingVertex(vec*trans.getBasis()));
aabbMin[i] = tmp[i]-margin;
}
}
TriangleCallback::~TriangleCallback()
{
}
class SupportVertexCallback : public TriangleCallback
{
SimdVector3 m_supportVertexLocal;
public:
SimdTransform m_worldTrans;
SimdScalar m_maxDot;
SimdVector3 m_supportVecLocal;
SupportVertexCallback(const SimdVector3& supportVecWorld,const SimdTransform& trans)
: m_supportVertexLocal(0.f,0.f,0.f), m_worldTrans(trans) ,m_maxDot(-1e30f)
{
m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis();
}
virtual void ProcessTriangle( SimdVector3* triangle)
{
for (int i=0;i<3;i++)
{
SimdScalar dot = m_supportVecLocal.dot(triangle[i]);
if (dot > m_maxDot)
{
m_maxDot = dot;
m_supportVertexLocal = triangle[i];
}
}
}
SimdVector3 GetSupportVertexWorldSpace()
{
return m_worldTrans(m_supportVertexLocal);
}
SimdVector3 GetSupportVertexLocal()
{
return m_supportVertexLocal;
}
};
void TriangleMeshShape::setLocalScaling(const SimdVector3& scaling)
{
m_meshInterface->setScaling(scaling);
}
void TriangleMeshShape::ProcessAllTriangles(TriangleCallback* callback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const
{
SimdVector3 meshScaling = m_meshInterface->getScaling();
int numtotalphysicsverts = 0;
int part,graphicssubparts = m_meshInterface->getNumSubParts();
for (part=0;part<graphicssubparts ;part++)
{
unsigned char * vertexbase;
unsigned char * indexbase;
int indexstride;
PHY_ScalarType type;
PHY_ScalarType gfxindextype;
int stride,numverts,numtriangles;
m_meshInterface->getLockedVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
numtotalphysicsverts+=numtriangles*3; //upper bound
int gfxindex;
SimdVector3 triangle[3];
for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
{
int graphicsindex=0;
for (int j=2;j>=0;j--)
{
ASSERT(gfxindextype == PHY_INTEGER);
int* gfxbase = (int*)(indexbase+gfxindex*indexstride);
graphicsindex = gfxbase[j];
float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
triangle[j] = SimdVector3(
graphicsbase[0]*meshScaling.getX(),
graphicsbase[1]*meshScaling.getY(),
graphicsbase[2]*meshScaling.getZ());
}
if (TestTriangleAgainstAabb2(&triangle[0],aabbMin,aabbMax))
{
//check aabb in triangle-space, before doing this
callback->ProcessTriangle(triangle);
}
}
m_meshInterface->unLockVertexBase(part);
}
}
void TriangleMeshShape::CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
{
//moving concave objects not supported
assert(0);
inertia.setValue(0.f,0.f,0.f);
}
SimdVector3 TriangleMeshShape::LocalGetSupportingVertex(const SimdVector3& vec) const
{
SimdVector3 supportVertex;
SimdTransform ident;
ident.setIdentity();
SupportVertexCallback supportCallback(vec,ident);
SimdVector3 aabbMax(1e30f,1e30f,1e30f);
ProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
supportVertex = supportCallback.GetSupportVertexLocal();
return supportVertex;
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef TRIANGLE_MESH_SHAPE_H
#define TRIANGLE_MESH_SHAPE_H
#include "CollisionShapes/CollisionShape.h"
#include "BroadphaseCollision/BroadphaseProxy.h" // for the types
#include "StridingMeshInterface.h"
#include "TriangleCallback.h"
///Concave triangle mesh. Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
class TriangleMeshShape : public CollisionShape
{
StridingMeshInterface* m_meshInterface;
public:
TriangleMeshShape(StridingMeshInterface* meshInterface);
virtual ~TriangleMeshShape();
virtual SimdVector3 LocalGetSupportingVertex(const SimdVector3& vec) const;
virtual SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& vec)const
{
assert(0);
return LocalGetSupportingVertex(vec);
}
virtual int GetShapeType() const
{
return TRIANGLE_MESH_SHAPE_PROXYTYPE;
}
virtual void GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const;
void ProcessAllTriangles(TriangleCallback* callback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const;
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia);
virtual void setLocalScaling(const SimdVector3& scaling);
//debugging
virtual char* GetName()const {return "TRIANGLEMESH";}
};
#endif //TRIANGLE_MESH_SHAPE_H

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef OBB_TRIANGLE_MINKOWSKI_H
#define OBB_TRIANGLE_MINKOWSKI_H
#include "ConvexShape.h"
#include "CollisionShapes/BoxShape.h"
class TriangleShape : public PolyhedralConvexShape
{
public:
SimdVector3 m_vertices1[3];
virtual int GetNumVertices() const
{
return 3;
}
const SimdVector3& GetVertexPtr(int index) const
{
return m_vertices1[index];
}
virtual void GetVertex(int index,SimdVector3& vert) const
{
vert = m_vertices1[index];
}
virtual int GetShapeType() const
{
return TRIANGLE_SHAPE_PROXYTYPE;
}
virtual int GetNumEdges() const
{
return 3;
}
virtual void GetEdge(int i,SimdPoint3& pa,SimdPoint3& pb) const
{
GetVertex(i,pa);
GetVertex((i+1)%3,pb);
}
virtual void GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax)const
{
// ASSERT(0);
GetAabbSlow(t,aabbMin,aabbMax);
}
SimdVector3 LocalGetSupportingVertexWithoutMargin(const SimdVector3& dir)const
{
SimdVector3 dots(dir.dot(m_vertices1[0]), dir.dot(m_vertices1[1]), dir.dot(m_vertices1[2]));
return m_vertices1[dots.maxAxis()];
}
TriangleShape(const SimdVector3& p0,const SimdVector3& p1,const SimdVector3& p2)
{
m_vertices1[0] = p0;
m_vertices1[1] = p1;
m_vertices1[2] = p2;
}
virtual void GetPlane(SimdVector3& planeNormal,SimdPoint3& planeSupport,int i) const
{
GetPlaneEquation(i,planeNormal,planeSupport);
}
virtual int GetNumPlanes() const
{
return 1;
}
void CalcNormal(SimdVector3& normal) const
{
normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]);
normal.normalize();
}
virtual void GetPlaneEquation(int i, SimdVector3& planeNormal,SimdPoint3& planeSupport) const
{
CalcNormal(planeNormal);
planeSupport = m_vertices1[0];
}
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
{
ASSERT(0);
inertia.setValue(0.f,0.f,0.f);
}
virtual bool IsInside(const SimdPoint3& pt,SimdScalar tolerance) const
{
SimdVector3 normal;
CalcNormal(normal);
//distance to plane
SimdScalar dist = pt.dot(normal);
SimdScalar planeconst = m_vertices1[0].dot(normal);
dist -= planeconst;
if (dist >= -tolerance && dist <= tolerance)
{
//inside check on edge-planes
int i;
for (i=0;i<3;i++)
{
SimdPoint3 pa,pb;
GetEdge(i,pa,pb);
SimdVector3 edge = pb-pa;
SimdVector3 edgeNormal = edge.cross(normal);
edgeNormal.normalize();
SimdScalar dist = pt.dot( edgeNormal);
SimdScalar edgeConst = pa.dot(edgeNormal);
dist -= edgeConst;
if (dist < -tolerance)
return false;
}
return true;
}
return false;
}
//debugging
virtual char* GetName()const
{
return "Triangle";
}
};
#endif //OBB_TRIANGLE_MINKOWSKI_H

746
extern/bullet/Bullet/Doxyfile vendored Normal file
View File

@@ -0,0 +1,746 @@
# Doxyfile 1.2.4
# This file describes the settings to be used by doxygen for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = Continuous Collision Detection Library
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY =
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese,
# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian,
# Polish, Portuguese and Slovene.
OUTPUT_LANGUAGE = English
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = YES
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these class will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = NO
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. It is allowed to use relative paths in the argument list.
STRIP_FROM_PATH =
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a class diagram (in Html and LaTeX) for classes with base or
# super classes. Setting the tag to NO turns the diagrams off.
CLASS_DIAGRAMS = YES
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = YES
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
# file names in lower case letters. If set to YES upper case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# users are adviced to set this option to NO.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like the Qt-style comments (thus requiring an
# explict @brief command for a brief description.
JAVADOC_AUTOBRIEF = YES
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# reimplements.
INHERIT_DOCS = YES
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
# will sort the (detailed) documentation of file and class members
# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 8
# The ENABLE_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
ENABLED_SECTIONS =
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
# put the command \sideeffect (or @sideeffect) in the documentation, which
# will result in a user defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
ALIASES =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = YES
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = YES
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
# warning originated and the warning text.
WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = .
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
FILE_PATTERNS = *.h *.cpp *.c
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE =
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
EXCLUDE_PATTERNS =
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS =
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output.
INPUT_FILTER =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse.
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = NO
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
HTML_OUTPUT = html
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
# will generate a default style sheet
HTML_STYLESHEET =
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
HTML_ALIGN_MEMBERS = YES
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = NO
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
DISABLE_INDEX = NO
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
ENUM_VALUES_PER_LINE = 4
# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be
# generated containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript and frames is required (for instance Netscape 4.0+
# or Internet explorer 4.0+).
GENERATE_TREEVIEW = NO
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT = latex
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4wide
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
LATEX_HEADER =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = NO
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = NO
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
# The RTF output is optimised for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
# contain links (just like the HTML output) instead of page references.
# This makes the output suitable for online browsing using a WORD or other.
# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assigments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION = .3
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
# the code including all documentation. Warning: This feature
# is still experimental and very incomplete.
GENERATE_XML = NO
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_PREDEFINED tags.
EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH = ../../generic/extern
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED =
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tagfiles.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = NO
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = YES
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = YES
# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to
# YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other
# documented files.
INCLUDE_GRAPH = YES
# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to
# YES then doxygen will generate a graph for each documented header file showing
# the documented files that directly or indirectly include this file
INCLUDED_BY_GRAPH = YES
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found on the path.
DOT_PATH =
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_WIDTH = 1024
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_HEIGHT = 1024
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
SEARCHENGINE = NO
# The CGI_NAME tag should be the name of the CGI script that
# starts the search engine (doxysearch) with the correct parameters.
# A script with this name will be generated by doxygen.
CGI_NAME = search.cgi
# The CGI_URL tag should be the absolute URL to the directory where the
# cgi binaries are located. See the documentation of your http daemon for
# details.
CGI_URL =
# The DOC_URL tag should be the absolute URL to the directory where the
# documentation is located. If left blank the absolute path to the
# documentation, with file:// prepended to it, will be used.
DOC_URL =
# The DOC_ABSPATH tag should be the absolute path to the directory where the
# documentation is located. If left blank the directory on the local machine
# will be used.
DOC_ABSPATH =
# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
# is installed.
BIN_ABSPATH = c:\program files\doxygen\bin
# The EXT_DOC_PATHS tag can be used to specify one or more paths to
# documentation generated for other projects. This allows doxysearch to search
# the documentation for these projects as well.
EXT_DOC_PATHS =

View File

@@ -0,0 +1,355 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "BU_AlgebraicPolynomialSolver.h"
#include <math.h>
#include <SimdMinMax.h>
int BU_AlgebraicPolynomialSolver::Solve2Quadratic(SimdScalar p, SimdScalar q)
{
SimdScalar basic_h_local;
SimdScalar basic_h_local_delta;
basic_h_local = p * 0.5f;
basic_h_local_delta = basic_h_local * basic_h_local - q;
if (basic_h_local_delta > 0.0f) {
basic_h_local_delta = sqrtf(basic_h_local_delta);
m_roots[0] = - basic_h_local + basic_h_local_delta;
m_roots[1] = - basic_h_local - basic_h_local_delta;
return 2;
}
else if (SimdGreaterEqual(basic_h_local_delta, SIMD_EPSILON)) {
m_roots[0] = - basic_h_local;
return 1;
}
else {
return 0;
}
}
int BU_AlgebraicPolynomialSolver::Solve2QuadraticFull(SimdScalar a,SimdScalar b, SimdScalar c)
{
SimdScalar radical = b * b - 4.0f * a * c;
if(radical >= 0.f)
{
SimdScalar sqrtRadical = sqrtf(radical);
SimdScalar idenom = 1.0f/(2.0f * a);
m_roots[0]=(-b + sqrtRadical) * idenom;
m_roots[1]=(-b - sqrtRadical) * idenom;
return 2;
}
return 0;
}
#define cubic_rt(x) \
((x) > 0.0f ? powf((SimdScalar)(x), 0.333333333333333333333333f) : \
((x) < 0.0f ? -powf((SimdScalar)-(x), 0.333333333333333333333333f) : 0.0f))
/* */
/* this function solves the following cubic equation: */
/* */
/* 3 2 */
/* lead * x + a * x + b * x + c = 0. */
/* */
/* it returns the number of different roots found, and stores the roots in */
/* roots[0,2]. it returns -1 for a degenerate equation 0 = 0. */
/* */
int BU_AlgebraicPolynomialSolver::Solve3Cubic(SimdScalar lead, SimdScalar a, SimdScalar b, SimdScalar c)
{
SimdScalar p, q, r;
SimdScalar delta, u, phi;
SimdScalar dummy;
if (lead != 1.0) {
/* */
/* transform into normal form: x^3 + a x^2 + b x + c = 0 */
/* */
if (SimdEqual(lead, SIMD_EPSILON)) {
/* */
/* we have a x^2 + b x + c = 0 */
/* */
if (SimdEqual(a, SIMD_EPSILON)) {
/* */
/* we have b x + c = 0 */
/* */
if (SimdEqual(b, SIMD_EPSILON)) {
if (SimdEqual(c, SIMD_EPSILON)) {
return -1;
}
else {
return 0;
}
}
else {
m_roots[0] = -c / b;
return 1;
}
}
else {
p = c / a;
q = b / a;
return Solve2QuadraticFull(a,b,c);
}
}
else {
a = a / lead;
b = b / lead;
c = c / lead;
}
}
/* */
/* we substitute x = y - a / 3 in order to eliminate the quadric term. */
/* we get x^3 + p x + q = 0 */
/* */
a /= 3.0f;
u = a * a;
p = b / 3.0f - u;
q = a * (2.0f * u - b) + c;
/* */
/* now use Cardano's formula */
/* */
if (SimdEqual(p, SIMD_EPSILON)) {
if (SimdEqual(q, SIMD_EPSILON)) {
/* */
/* one triple root */
/* */
m_roots[0] = -a;
return 1;
}
else {
/* */
/* one real and two complex roots */
/* */
m_roots[0] = cubic_rt(-q) - a;
return 1;
}
}
q /= 2.0f;
delta = p * p * p + q * q;
if (delta > 0.0f) {
/* */
/* one real and two complex roots. note that v = -p / u. */
/* */
u = -q + sqrtf(delta);
u = cubic_rt(u);
m_roots[0] = u - p / u - a;
return 1;
}
else if (delta < 0.0) {
/* */
/* Casus irreducibilis: we have three real roots */
/* */
r = sqrtf(-p);
p *= -r;
r *= 2.0;
phi = acosf(-q / p) / 3.0f;
dummy = SIMD_2_PI / 3.0f;
m_roots[0] = r * cosf(phi) - a;
m_roots[1] = r * cosf(phi + dummy) - a;
m_roots[2] = r * cosf(phi - dummy) - a;
return 3;
}
else {
/* */
/* one single and one SimdScalar root */
/* */
r = cubic_rt(-q);
m_roots[0] = 2.0f * r - a;
m_roots[1] = -r - a;
return 2;
}
}
/* */
/* this function solves the following quartic equation: */
/* */
/* 4 3 2 */
/* lead * x + a * x + b * x + c * x + d = 0. */
/* */
/* it returns the number of different roots found, and stores the roots in */
/* roots[0,3]. it returns -1 for a degenerate equation 0 = 0. */
/* */
int BU_AlgebraicPolynomialSolver::Solve4Quartic(SimdScalar lead, SimdScalar a, SimdScalar b, SimdScalar c, SimdScalar d)
{
SimdScalar p, q ,r;
SimdScalar u, v, w;
int i, num_roots, num_tmp;
//SimdScalar tmp[2];
if (lead != 1.0) {
/* */
/* transform into normal form: x^4 + a x^3 + b x^2 + c x + d = 0 */
/* */
if (SimdEqual(lead, SIMD_EPSILON)) {
/* */
/* we have a x^3 + b x^2 + c x + d = 0 */
/* */
if (SimdEqual(a, SIMD_EPSILON)) {
/* */
/* we have b x^2 + c x + d = 0 */
/* */
if (SimdEqual(b, SIMD_EPSILON)) {
/* */
/* we have c x + d = 0 */
/* */
if (SimdEqual(c, SIMD_EPSILON)) {
if (SimdEqual(d, SIMD_EPSILON)) {
return -1;
}
else {
return 0;
}
}
else {
m_roots[0] = -d / c;
return 1;
}
}
else {
p = c / b;
q = d / b;
return Solve2QuadraticFull(b,c,d);
}
}
else {
return Solve3Cubic(1.0, b / a, c / a, d / a);
}
}
else {
a = a / lead;
b = b / lead;
c = c / lead;
d = d / lead;
}
}
/* */
/* we substitute x = y - a / 4 in order to eliminate the cubic term. */
/* we get: y^4 + p y^2 + q y + r = 0. */
/* */
a /= 4.0f;
p = b - 6.0f * a * a;
q = a * (8.0f * a * a - 2.0f * b) + c;
r = a * (a * (b - 3.f * a * a) - c) + d;
if (SimdEqual(q, SIMD_EPSILON)) {
/* */
/* biquadratic equation: y^4 + p y^2 + r = 0. */
/* */
num_roots = Solve2Quadratic(p, r);
if (num_roots > 0) {
if (m_roots[0] > 0.0f) {
if (num_roots > 1) {
if ((m_roots[1] > 0.0f) && (m_roots[1] != m_roots[0])) {
u = sqrtf(m_roots[1]);
m_roots[2] = u - a;
m_roots[3] = -u - a;
u = sqrtf(m_roots[0]);
m_roots[0] = u - a;
m_roots[1] = -u - a;
return 4;
}
else {
u = sqrtf(m_roots[0]);
m_roots[0] = u - a;
m_roots[1] = -u - a;
return 2;
}
}
else {
u = sqrtf(m_roots[0]);
m_roots[0] = u - a;
m_roots[1] = -u - a;
return 2;
}
}
}
return 0;
}
else if (SimdEqual(r, SIMD_EPSILON)) {
/* */
/* no absolute term: y (y^3 + p y + q) = 0. */
/* */
num_roots = Solve3Cubic(1.0, 0.0, p, q);
for (i = 0; i < num_roots; ++i) m_roots[i] -= a;
if (num_roots != -1) {
m_roots[num_roots] = -a;
++num_roots;
}
else {
m_roots[0] = -a;
num_roots = 1;;
}
return num_roots;
}
else {
/* */
/* we solve the resolvent cubic equation */
/* */
num_roots = Solve3Cubic(1.0f, -0.5f * p, -r, 0.5f * r * p - 0.125f * q * q);
if (num_roots == -1) {
num_roots = 1;
m_roots[0] = 0.0f;
}
/* */
/* build two quadric equations */
/* */
w = m_roots[0];
u = w * w - r;
v = 2.0f * w - p;
if (SimdEqual(u, SIMD_EPSILON))
u = 0.0;
else if (u > 0.0f)
u = sqrtf(u);
else
return 0;
if (SimdEqual(v, SIMD_EPSILON))
v = 0.0;
else if (v > 0.0f)
v = sqrtf(v);
else
return 0;
if (q < 0.0f) v = -v;
w -= u;
num_roots=Solve2Quadratic(v, w);
for (i = 0; i < num_roots; ++i)
{
m_roots[i] -= a;
}
w += 2.0f *u;
SimdScalar tmp[2];
tmp[0] = m_roots[0];
tmp[1] = m_roots[1];
num_tmp = Solve2Quadratic(-v, w);
for (i = 0; i < num_tmp; ++i)
{
m_roots[i + num_roots] = tmp[i] - a;
m_roots[i]=tmp[i];
}
return (num_tmp + num_roots);
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef BU_ALGEBRAIC_POLYNOMIAL_SOLVER_H
#define BU_ALGEBRAIC_POLYNOMIAL_SOLVER_H
#include "BU_PolynomialSolverInterface.h"
/// BU_AlgebraicPolynomialSolver implements polynomial root finding by analytically solving algebraic equations.
/// Polynomials up to 4rd degree are supported, Cardano's formula is used for 3rd degree
class BU_AlgebraicPolynomialSolver : public BUM_PolynomialSolverInterface
{
public:
BU_AlgebraicPolynomialSolver() {};
int Solve2Quadratic(SimdScalar p, SimdScalar q);
int Solve2QuadraticFull(SimdScalar a,SimdScalar b, SimdScalar c);
int Solve3Cubic(SimdScalar lead, SimdScalar a, SimdScalar b, SimdScalar c);
int Solve4Quartic(SimdScalar lead, SimdScalar a, SimdScalar b, SimdScalar c, SimdScalar d);
SimdScalar GetRoot(int i) const
{
return m_roots[i];
}
private:
SimdScalar m_roots[4];
};
#endif //BU_ALGEBRAIC_POLYNOMIAL_SOLVER_H

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "BU_Collidable.h"
#include "CollisionShapes/CollisionShape.h"
#include <SimdTransform.h>
#include "BU_MotionStateInterface.h"
BU_Collidable::BU_Collidable(BU_MotionStateInterface& motion,PolyhedralConvexShape& shape,void* userPointer )
:m_motionState(motion),m_shape(shape),m_userPointer(userPointer)
{
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef BU_COLLIDABLE
#define BU_COLLIDABLE
class PolyhedralConvexShape;
class BU_MotionStateInterface;
#include <SimdPoint3.h>
class BU_Collidable
{
public:
BU_Collidable(BU_MotionStateInterface& motion,PolyhedralConvexShape& shape, void* userPointer);
void* GetUserPointer() const
{
return m_userPointer;
}
BU_MotionStateInterface& GetMotionState()
{
return m_motionState;
}
inline const BU_MotionStateInterface& GetMotionState() const
{
return m_motionState;
}
inline const PolyhedralConvexShape& GetShape() const
{
return m_shape;
};
private:
BU_MotionStateInterface& m_motionState;
PolyhedralConvexShape& m_shape;
void* m_userPointer;
};
#endif //BU_COLLIDABLE

View File

@@ -0,0 +1,576 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "BU_CollisionPair.h"
#include "NarrowPhaseCollision/BU_VertexPoly.h"
#include "NarrowPhaseCollision/BU_EdgeEdge.h"
#include "BU_Collidable.h"
#include "BU_MotionStateInterface.h"
#include "CollisionShapes/PolyhedralConvexShape.h"
#include <SimdMinMax.h>
#include "SimdTransformUtil.h"
BU_CollisionPair::BU_CollisionPair(const PolyhedralConvexShape* convexA,const PolyhedralConvexShape* convexB,SimdScalar tolerance)
: m_convexA(convexA),m_convexB(convexB),m_screwing(SimdVector3(0,0,0),SimdVector3(0,0,0)),
m_tolerance(tolerance)
{
}
// if there exists a time-of-impact between any feature_pair (edgeA,edgeB),
// (vertexA,faceB) or (vertexB,faceA) in [0..1], report true and smallest time
/*
bool BU_CollisionPair::GetTimeOfImpact(const SimdVector3& linearMotionA,const SimdQuaternion& angularMotionA,const SimdVector3& linearMotionB,const SimdQuaternion& angularMotionB, SimdScalar& toi,SimdTransform& impactTransA,SimdTransform& impactTransB)
*/
bool BU_CollisionPair::calcTimeOfImpact(
const SimdTransform& fromA,
const SimdTransform& toA,
const SimdTransform& fromB,
const SimdTransform& toB,
CastResult& result)
{
SimdVector3 linvelA,angvelA;
SimdVector3 linvelB,angvelB;
SimdTransformUtil::CalculateVelocity(fromA,toA,1.f,linvelA,angvelA);
SimdTransformUtil::CalculateVelocity(fromB,toB,1.f,linvelB,angvelB);
SimdVector3 linearMotionA = toA.getOrigin() - fromA.getOrigin();
SimdQuaternion angularMotionA(0,0,0,1.f);
SimdVector3 linearMotionB = toB.getOrigin() - fromB.getOrigin();
SimdQuaternion angularMotionB(0,0,0,1);
result.m_fraction = 1.f;
SimdTransform impactTransA;
SimdTransform impactTransB;
int index=0;
SimdScalar toiUnscaled=result.m_fraction;
const SimdScalar toiUnscaledLimit = result.m_fraction;
SimdTransform a2w;
a2w = fromA;
SimdTransform b2w = fromB;
/* debugging code
{
const int numvertsB = m_convexB->GetNumVertices();
for (int v=0;v<numvertsB;v++)
{
SimdPoint3 pt;
m_convexB->GetVertex(v,pt);
pt = b2w * pt;
char buf[1000];
if (pt.y() < 0.)
{
sprintf(buf,"PRE ERROR (%d) %.20E %.20E %.20E!!!!!!!!!\n",v,pt.x(),pt.y(),pt.z());
if (debugFile)
fwrite(buf,1,strlen(buf),debugFile);
} else
{
sprintf(buf,"PRE %d = %.20E,%.20E,%.20E\n",v,pt.x(),pt.y(),pt.z());
if (debugFile)
fwrite(buf,1,strlen(buf),debugFile);
}
}
}
*/
SimdTransform b2wp = b2w;
b2wp.setOrigin(b2w.getOrigin() + linearMotionB);
b2wp.setRotation( b2w.getRotation() + angularMotionB);
impactTransB = b2wp;
SimdTransform a2wp;
a2wp.setOrigin(a2w.getOrigin()+ linearMotionA);
a2wp.setRotation(a2w.getRotation()+angularMotionA);
impactTransA = a2wp;
SimdTransform a2winv;
a2winv = a2w.inverse();
SimdTransform b2wpinv;
b2wpinv = b2wp.inverse();
SimdTransform b2winv;
b2winv = b2w.inverse();
SimdTransform a2wpinv;
a2wpinv = a2wp.inverse();
//Redon's version with concatenated transforms
SimdTransform relative;
relative = b2w * b2wpinv * a2wp * a2winv;
//relative = a2winv * a2wp * b2wpinv * b2w;
SimdQuaternion qrel;
relative.getBasis().getRotation(qrel);
SimdVector3 linvel = relative.getOrigin();
if (linvel.length() < SCREWEPSILON)
{
linvel.setValue(0.,0.,0.);
}
SimdVector3 angvel;
angvel[0] = 2.f * asinf (qrel[0]);
angvel[1] = 2.f * asinf (qrel[1]);
angvel[2] = 2.f * asinf (qrel[2]);
if (angvel.length() < SCREWEPSILON)
{
angvel.setValue(0.f,0.f,0.f);
}
//Redon's version with concatenated transforms
m_screwing = BU_Screwing(linvel,angvel);
SimdTransform w2s;
m_screwing.LocalMatrix(w2s);
SimdTransform s2w;
s2w = w2s.inverse();
//impactTransA = a2w;
//impactTransB = b2w;
bool hit = false;
if (SimdFuzzyZero(m_screwing.GetS()) && SimdFuzzyZero(m_screwing.GetW()))
{
//W = 0 , S = 0 , no collision
//toi = 0;
/*
{
const int numvertsB = m_convexB->GetNumVertices();
for (int v=0;v<numvertsB;v++)
{
SimdPoint3 pt;
m_convexB->GetVertex(v,pt);
pt = impactTransB * pt;
char buf[1000];
if (pt.y() < 0.)
{
sprintf(buf,"EARLY POST ERROR (%d) %.20E,%.20E,%.20E!!!!!!!!!\n",v,pt.x(),pt.y(),pt.z());
if (debugFile)
fwrite(buf,1,strlen(buf),debugFile);
}
else
{
sprintf(buf,"EARLY POST %d = %.20E,%.20E,%.20E\n",v,pt.x(),pt.y(),pt.z());
if (debugFile)
fwrite(buf,1,strlen(buf),debugFile);
}
}
}
*/
return false;//don't continue moving within epsilon
}
#define EDGEEDGE
#ifdef EDGEEDGE
BU_EdgeEdge edgeEdge;
//for all edged in A check agains all edges in B
for (int ea = 0;ea < m_convexA->GetNumEdges();ea++)
{
SimdPoint3 pA0,pA1;
m_convexA->GetEdge(ea,pA0,pA1);
pA0= a2w * pA0;//in world space
pA0 = w2s * pA0;//in screwing space
pA1= a2w * pA1;//in world space
pA1 = w2s * pA1;//in screwing space
int numedgesB = m_convexB->GetNumEdges();
for (int eb = 0; eb < numedgesB;eb++)
{
{
SimdPoint3 pB0,pB1;
m_convexB->GetEdge(eb,pB0,pB1);
pB0= b2w * pB0;//in world space
pB0 = w2s * pB0;//in screwing space
pB1= b2w * pB1;//in world space
pB1 = w2s * pB1;//in screwing space
SimdScalar lambda,mu;
toiUnscaled = 1.;
SimdVector3 edgeDirA(pA1-pA0);
SimdVector3 edgeDirB(pB1-pB0);
if (edgeEdge.GetTimeOfImpact(m_screwing,pA0,edgeDirA,pB0,edgeDirB,toiUnscaled,lambda,mu))
{
//printf("edgeedge potential hit\n");
if (toiUnscaled>=0)
{
if (toiUnscaled < toiUnscaledLimit)
{
//inside check is already done by checking the mu and gamma !
SimdPoint3 vtx = pA0+lambda * (pA1-pA0);
SimdPoint3 hitpt = m_screwing.InBetweenPosition(vtx,toiUnscaled);
SimdPoint3 hitptWorld = s2w * hitpt;
{
if (toiUnscaled < result.m_fraction)
result.m_fraction = toiUnscaled;
hit = true;
SimdVector3 hitNormal = edgeDirB.cross(edgeDirA);
hitNormal = m_screwing.InBetweenVector(hitNormal,toiUnscaled);
hitNormal.normalize();
//an approximated normal can be calculated by taking the cross product of both edges
//take care of the sign !
SimdVector3 hitNormalWorld = s2w.getBasis() * hitNormal ;
SimdScalar dist = m_screwing.GetU().dot(hitNormalWorld);
if (dist > 0)
hitNormalWorld *= -1;
//todo: this is the wrong point, because b2winv is still at begin of motion
// not at time-of-impact location!
//bhitpt = b2winv * hitptWorld;
// m_manifold.SetContactPoint(BUM_FeatureEdgeEdge,index,ea,eb,hitptWorld,hitNormalWorld);
}
}
}
}
}
index++;
}
};
#endif //EDGEEDGE
#define VERTEXFACE
#ifdef VERTEXFACE
// for all vertices in A, for each face in B,do vertex-face
{
const int numvertsA = m_convexA->GetNumVertices();
for (int v=0;v<numvertsA;v++)
//int v=3;
{
SimdPoint3 vtx;
m_convexA->GetVertex(v,vtx);
vtx = a2w * vtx;//in world space
vtx = w2s * vtx;//in screwing space
const int numplanesB = m_convexB->GetNumPlanes();
for (int p = 0 ; p < numplanesB; p++)
//int p=2;
{
{
SimdVector3 planeNorm;
SimdPoint3 planeSupport;
m_convexB->GetPlane(planeNorm,planeSupport,p);
planeSupport = b2w * planeSupport;//transform to world space
SimdVector3 planeNormWorld = b2w.getBasis() * planeNorm;
planeSupport = w2s * planeSupport ; //transform to screwing space
planeNorm = w2s.getBasis() * planeNormWorld;
planeNorm.normalize();
SimdScalar d = planeSupport.dot(planeNorm);
SimdVector4 planeEq(planeNorm[0],planeNorm[1],planeNorm[2],d);
BU_VertexPoly vtxApolyB;
toiUnscaled = 1.;
if ((p==2) && (v==6))
{
// printf("%f toiUnscaled\n",toiUnscaled);
}
if (vtxApolyB.GetTimeOfImpact(m_screwing,vtx,planeEq,toiUnscaled,false))
{
if (toiUnscaled >= 0. )
{
//not only collect the first point, get every contactpoint, later we have to check the
//manifold properly!
if (toiUnscaled <= toiUnscaledLimit)
{
// printf("toiUnscaled %f\n",toiUnscaled );
SimdPoint3 hitpt = m_screwing.InBetweenPosition(vtx,toiUnscaled);
SimdVector3 hitNormal = m_screwing.InBetweenVector(planeNorm ,toiUnscaled);
SimdVector3 hitNormalWorld = s2w.getBasis() * hitNormal ;
SimdPoint3 hitptWorld = s2w * hitpt;
hitpt = b2winv * hitptWorld;
//vertex has to be 'within' the facet's boundary
if (m_convexB->IsInside(hitpt,m_tolerance))
{
// m_manifold.SetContactPoint(BUM_FeatureVertexFace, index,v,p,hitptWorld,hitNormalWorld);
if (toiUnscaled < result.m_fraction)
result.m_fraction= toiUnscaled;
hit = true;
}
}
}
}
}
index++;
}
}
}
//
// for all vertices in B, for each face in A,do vertex-face
//copy and pasted from all verts A -> all planes B so potential typos!
//todo: make this into one method with a kind of 'swapped' logic
//
{
const int numvertsB = m_convexB->GetNumVertices();
for (int v=0;v<numvertsB;v++)
//int v=0;
{
SimdPoint3 vtx;
m_convexB->GetVertex(v,vtx);
vtx = b2w * vtx;//in world space
/*
char buf[1000];
if (vtx.y() < 0.)
{
sprintf(buf,"ERROR !!!!!!!!!\n",v,vtx.x(),vtx.y(),vtx.z());
if (debugFile)
fwrite(buf,1,strlen(buf),debugFile);
}
sprintf(buf,"vertexWorld(%d) = (%.20E,%.20E,%.20E)\n",v,vtx.x(),vtx.y(),vtx.z());
if (debugFile)
fwrite(buf,1,strlen(buf),debugFile);
*/
vtx = w2s * vtx;//in screwing space
const int numplanesA = m_convexA->GetNumPlanes();
for (int p = 0 ; p < numplanesA; p++)
//int p=2;
{
{
SimdVector3 planeNorm;
SimdPoint3 planeSupport;
m_convexA->GetPlane(planeNorm,planeSupport,p);
planeSupport = a2w * planeSupport;//transform to world space
SimdVector3 planeNormWorld = a2w.getBasis() * planeNorm;
planeSupport = w2s * planeSupport ; //transform to screwing space
planeNorm = w2s.getBasis() * planeNormWorld;
planeNorm.normalize();
SimdScalar d = planeSupport.dot(planeNorm);
SimdVector4 planeEq(planeNorm[0],planeNorm[1],planeNorm[2],d);
BU_VertexPoly vtxBpolyA;
toiUnscaled = 1.;
if (vtxBpolyA.GetTimeOfImpact(m_screwing,vtx,planeEq,toiUnscaled,true))
{
if (toiUnscaled>=0.)
{
if (toiUnscaled < toiUnscaledLimit)
{
SimdPoint3 hitpt = m_screwing.InBetweenPosition( vtx , -toiUnscaled);
SimdVector3 hitNormal = m_screwing.InBetweenVector(-planeNorm ,-toiUnscaled);
SimdScalar len = hitNormal.length()-1;
//assert( SimdFuzzyZero(len) );
SimdVector3 hitNormalWorld = s2w.getBasis() * hitNormal ;
SimdPoint3 hitptWorld = s2w * hitpt;
hitpt = a2winv * hitptWorld;
//vertex has to be 'within' the facet's boundary
if (m_convexA->IsInside(hitpt,m_tolerance))
{
// m_manifold.SetContactPoint(BUM_FeatureFaceVertex,index,p,v,hitptWorld,hitNormalWorld);
if (toiUnscaled <result.m_fraction)
result.m_fraction = toiUnscaled;
hit = true;
}
}
}
}
}
}
index++;
}
}
#endif// VERTEXFACE
//the manifold now consists of all points/normals generated by feature-pairs that have a time-of-impact within this frame
//in addition there are contact points from previous frames
//we have to cleanup the manifold, using an additional epsilon/tolerance
//as long as the distance from the contactpoint (in worldspace) to both objects is within this epsilon we keep the point
//else throw it away
if (hit)
{
//try to avoid numerical drift on close contact
if (result.m_fraction < 0.00001)
{
// printf("toiUnscaledMin< 0.00001\n");
impactTransA = a2w;
impactTransB = b2w;
} else
{
//SimdScalar vel = linearMotionB.length();
//todo: check this margin
result.m_fraction *= 0.99f;
//move B to new position
impactTransB.setOrigin(b2w.getOrigin()+ result.m_fraction*linearMotionB);
SimdQuaternion ornB = b2w.getRotation()+angularMotionB*result.m_fraction;
ornB.normalize();
impactTransB.setRotation(ornB);
//now transform A
SimdTransform a2s,a2b;
a2s.mult( w2s , a2w);
a2s= m_screwing.InBetweenTransform(a2s,result.m_fraction);
a2s.multInverseLeft(w2s,a2s);
a2b.multInverseLeft(b2w, a2s);
//transform by motion B
impactTransA.mult(impactTransB, a2b);
//normalize rotation
SimdQuaternion orn;
impactTransA.getBasis().getRotation(orn);
orn.normalize();
impactTransA.setBasis(SimdMatrix3x3(orn));
}
}
/*
{
const int numvertsB = m_convexB->GetNumVertices();
for (int v=0;v<numvertsB;v++)
{
SimdPoint3 pt;
m_convexB->GetVertex(v,pt);
pt = impactTransB * pt;
char buf[1000];
if (pt.y() < 0.)
{
sprintf(buf,"POST ERROR (%d) %.20E,%.20E,%.20E!!!!!!!!!\n",v,pt.x(),pt.y(),pt.z());
if (debugFile)
fwrite(buf,1,strlen(buf),debugFile);
}
else
{
sprintf(buf,"POST %d = %.20E,%.20E,%.20E\n",v,pt.x(),pt.y(),pt.z());
if (debugFile)
fwrite(buf,1,strlen(buf),debugFile);
}
}
}
*/
return hit;
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef BU_COLLISIONPAIR
#define BU_COLLISIONPAIR
#include <NarrowPhaseCollision/BU_Screwing.h>
#include <NarrowPhaseCollision/ConvexCast.h>
#include <SimdQuaternion.h>
class PolyhedralConvexShape;
///BU_CollisionPair implements collision algorithm for algebraic time of impact calculation of feature based shapes.
class BU_CollisionPair : public ConvexCast
{
public:
BU_CollisionPair(const PolyhedralConvexShape* convexA,const PolyhedralConvexShape* convexB,SimdScalar tolerance=0.2f);
//toi
virtual bool calcTimeOfImpact(
const SimdTransform& fromA,
const SimdTransform& toA,
const SimdTransform& fromB,
const SimdTransform& toB,
CastResult& result);
private:
const PolyhedralConvexShape* m_convexA;
const PolyhedralConvexShape* m_convexB;
BU_Screwing m_screwing;
SimdScalar m_tolerance;
};
#endif //BU_COLLISIONPAIR

View File

@@ -0,0 +1,573 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "BU_EdgeEdge.h"
#include "BU_Screwing.h"
#include <SimdPoint3.h>
#include <SimdPoint3.h>
//#include "BU_IntervalArithmeticPolynomialSolver.h"
#include "BU_AlgebraicPolynomialSolver.h"
#define USE_ALGEBRAIC
#ifdef USE_ALGEBRAIC
#define BU_Polynomial BU_AlgebraicPolynomialSolver
#else
#define BU_Polynomial BU_IntervalArithmeticPolynomialSolver
#endif
BU_EdgeEdge::BU_EdgeEdge()
{
}
bool BU_EdgeEdge::GetTimeOfImpact(
const BU_Screwing& screwAB,
const SimdPoint3& a,//edge in object A
const SimdVector3& u,
const SimdPoint3& c,//edge in object B
const SimdVector3& v,
SimdScalar &minTime,
SimdScalar &lambda1,
SimdScalar& mu1
)
{
bool hit=false;
SimdScalar lambda;
SimdScalar mu;
const SimdScalar w=screwAB.GetW();
const SimdScalar s=screwAB.GetS();
if (SimdFuzzyZero(s) &&
SimdFuzzyZero(w))
{
//no motion, no collision
return false;
}
if (SimdFuzzyZero(w) )
{
//pure translation W=0, S <> 0
//no trig, f(t)=t
SimdScalar det = u.y()*v.x()-u.x()*v.y();
if (!SimdFuzzyZero(det))
{
lambda = (a.x()*v.y() - c.x() * v.y() - v.x() * a.y() + v.x() * c.y()) / det;
mu = (u.y() * a.x() - u.y() * c.x() - u.x() * a.y() + u.x() * c.y()) / det;
if (mu >=0 && mu <= 1 && lambda >= 0 && lambda <= 1)
{
// single potential collision is
SimdScalar t = (c.z()-a.z()+mu*v.z()-lambda*u.z())/s;
//if this is on the edge, and time t within [0..1] report hit
if (t>=0 && t <= minTime)
{
hit = true;
lambda1 = lambda;
mu1 = mu;
minTime=t;
}
}
} else
{
//parallel case, not yet
}
} else
{
if (SimdFuzzyZero(s) )
{
if (SimdFuzzyZero(u.z()) )
{
if (SimdFuzzyZero(v.z()) )
{
//u.z()=0,v.z()=0
if (SimdFuzzyZero(a.z()-c.z()))
{
//printf("NOT YET planar problem, 4 vertex=edge cases\n");
} else
{
//printf("parallel but distinct planes, no collision\n");
return false;
}
} else
{
SimdScalar mu = (a.z() - c.z())/v.z();
if (0<=mu && mu <= 1)
{
// printf("NOT YET//u.z()=0,v.z()<>0\n");
} else
{
return false;
}
}
} else
{
//u.z()<>0
if (SimdFuzzyZero(v.z()) )
{
//printf("u.z()<>0,v.z()=0\n");
lambda = (c.z() - a.z())/u.z();
if (0<=lambda && lambda <= 1)
{
//printf("u.z()<>0,v.z()=0\n");
SimdPoint3 rotPt(a.x()+lambda * u.x(), a.y()+lambda * u.y(),0.f);
SimdScalar r2 = rotPt.length2();//px*px + py*py;
//either y=a*x+b, or x = a*x+b...
//depends on whether value v.x() is zero or not
SimdScalar aa;
SimdScalar bb;
if (SimdFuzzyZero(v.x()))
{
aa = v.x()/v.y();
bb= c.x()+ (-c.y() /v.y()) *v.x();
} else
{
//line is c+mu*v;
//x = c.x()+mu*v.x();
//mu = ((x-c.x())/v.x());
//y = c.y()+((x-c.x())/v.x())*v.y();
//y = c.y()+ (-c.x() /v.x()) *v.y() + (x /v.x()) *v.y();
//y = a*x+b,where a = v.y()/v.x(), b= c.y()+ (-c.x() /v.x()) *v.y();
aa = v.y()/v.x();
bb= c.y()+ (-c.x() /v.x()) *v.y();
}
SimdScalar disc = aa*aa*r2 + r2 - bb*bb;
if (disc <0)
{
//edge doesn't intersect the circle (motion of the vertex)
return false;
}
SimdScalar rad = sqrtf(r2);
if (SimdFuzzyZero(disc))
{
SimdPoint3 intersectPt;
SimdScalar mu;
//intersectionPoint edge with circle;
if (SimdFuzzyZero(v.x()))
{
intersectPt.setY( (-2*aa*bb)/(2*(aa*aa+1)));
intersectPt.setX( aa*intersectPt.y()+bb );
mu = ((intersectPt.y()-c.y())/v.y());
} else
{
intersectPt.setX((-2*aa*bb)/(2*(aa*aa+1)));
intersectPt.setY(aa*intersectPt.x()+bb);
mu = ((intersectPt.getX()-c.getX())/v.getX());
}
if (0 <= mu && mu <= 1)
{
hit = Calc2DRotationPointPoint(rotPt,rad,screwAB.GetW(),intersectPt,minTime);
}
//only one solution
} else
{
//two points...
//intersectionPoint edge with circle;
SimdPoint3 intersectPt;
//intersectionPoint edge with circle;
if (SimdFuzzyZero(v.x()))
{
SimdScalar mu;
intersectPt.setY((-2.f*aa*bb+2.f*sqrtf(disc))/(2.f*(aa*aa+1.f)));
intersectPt.setX(aa*intersectPt.y()+bb);
mu = ((intersectPt.getY()-c.getY())/v.getY());
if (0.f <= mu && mu <= 1.f)
{
hit = Calc2DRotationPointPoint(rotPt,rad,screwAB.GetW(),intersectPt,minTime);
}
intersectPt.setY((-2.f*aa*bb-2.f*sqrtf(disc))/(2.f*(aa*aa+1.f)));
intersectPt.setX(aa*intersectPt.y()+bb);
mu = ((intersectPt.getY()-c.getY())/v.getY());
if (0 <= mu && mu <= 1)
{
hit = hit || Calc2DRotationPointPoint(rotPt,rad,screwAB.GetW(),intersectPt,minTime);
}
} else
{
SimdScalar mu;
intersectPt.setX((-2.f*aa*bb+2.f*sqrtf(disc))/(2*(aa*aa+1.f)));
intersectPt.setY(aa*intersectPt.x()+bb);
mu = ((intersectPt.getX()-c.getX())/v.getX());
if (0 <= mu && mu <= 1)
{
hit = Calc2DRotationPointPoint(rotPt,rad,screwAB.GetW(),intersectPt,minTime);
}
intersectPt.setX((-2.f*aa*bb-2.f*sqrtf(disc))/(2.f*(aa*aa+1.f)));
intersectPt.setY(aa*intersectPt.x()+bb);
mu = ((intersectPt.getX()-c.getX())/v.getX());
if (0.f <= mu && mu <= 1.f)
{
hit = hit || Calc2DRotationPointPoint(rotPt,rad,screwAB.GetW(),intersectPt,minTime);
}
}
}
int k=0;
} else
{
return false;
}
} else
{
//u.z()<>0,v.z()<>0
//printf("general case with s=0\n");
hit = GetTimeOfImpactGeneralCase(screwAB,a,u,c,v,minTime,lambda,mu);
if (hit)
{
lambda1 = lambda;
mu1 = mu;
}
}
}
} else
{
//printf("general case, W<>0,S<>0\n");
hit = GetTimeOfImpactGeneralCase(screwAB,a,u,c,v,minTime,lambda,mu);
if (hit)
{
lambda1 = lambda;
mu1 = mu;
}
}
//W <> 0,pure rotation
}
return hit;
}
bool BU_EdgeEdge::GetTimeOfImpactGeneralCase(
const BU_Screwing& screwAB,
const SimdPoint3& a,//edge in object A
const SimdVector3& u,
const SimdPoint3& c,//edge in object B
const SimdVector3& v,
SimdScalar &minTime,
SimdScalar &lambda,
SimdScalar& mu
)
{
bool hit = false;
SimdScalar coefs[4];
BU_Polynomial polynomialSolver;
int numroots = 0;
SimdScalar eps=1e-15f;
SimdScalar eps2=1e-20f;
SimdScalar s=screwAB.GetS();
SimdScalar w = screwAB.GetW();
SimdScalar ax = a.x();
SimdScalar ay = a.y();
SimdScalar az = a.z();
SimdScalar cx = c.x();
SimdScalar cy = c.y();
SimdScalar cz = c.z();
SimdScalar vx = v.x();
SimdScalar vy = v.y();
SimdScalar vz = v.z();
SimdScalar ux = u.x();
SimdScalar uy = u.y();
SimdScalar uz = u.z();
if (!SimdFuzzyZero(v.z()))
{
//Maple Autogenerated C code
SimdScalar t1,t2,t3,t4,t7,t8,t10;
SimdScalar t13,t14,t15,t16,t17,t18,t19,t20;
SimdScalar t21,t22,t23,t24,t25,t26,t27,t28,t29,t30;
SimdScalar t31,t32,t33,t34,t35,t36,t39,t40;
SimdScalar t41,t43,t48;
SimdScalar t63;
SimdScalar aa,bb,cc,dd;//the coefficients
t1 = v.y()*s; t2 = t1*u.x();
t3 = v.x()*s;
t4 = t3*u.y();
t7 = tanf(w/2.0f);
t8 = 1.0f/t7;
t10 = 1.0f/v.z();
aa = (t2-t4)*t8*t10;
t13 = a.x()*t7;
t14 = u.z()*v.y();
t15 = t13*t14;
t16 = u.x()*v.z();
t17 = a.y()*t7;
t18 = t16*t17;
t19 = u.y()*v.z();
t20 = t13*t19;
t21 = v.y()*u.x();
t22 = c.z()*t7;
t23 = t21*t22;
t24 = v.x()*a.z();
t25 = t7*u.y();
t26 = t24*t25;
t27 = c.y()*t7;
t28 = t16*t27;
t29 = a.z()*t7;
t30 = t21*t29;
t31 = u.z()*v.x();
t32 = t31*t27;
t33 = t31*t17;
t34 = c.x()*t7;
t35 = t34*t19;
t36 = t34*t14;
t39 = v.x()*c.z();
t40 = t39*t25;
t41 = 2.0f*t1*u.y()-t15+t18-t20-t23-t26+t28+t30+t32+t33-t35-t36+2.0f*t3*u.x()+t40;
bb = t41*t8*t10;
t43 = t7*u.x();
t48 = u.y()*v.y();
cc = (-2.0f*t39*t43+2.0f*t24*t43+t4-2.0f*t48*t22+2.0f*t34*t16-2.0f*t31*t13-t2
-2.0f*t17*t14+2.0f*t19*t27+2.0f*t48*t29)*t8*t10;
t63 = -t36+t26+t32-t40+t23+t35-t20+t18-t28-t33+t15-t30;
dd = t63*t8*t10;
coefs[0]=aa;
coefs[1]=bb;
coefs[2]=cc;
coefs[3]=dd;
} else
{
SimdScalar t1,t2,t3,t4,t7,t8,t10;
SimdScalar t13,t14,t15,t16,t17,t18,t19,t20;
SimdScalar t21,t22,t23,t24,t25,t26,t27,t28,t29,t30;
SimdScalar t31,t32,t33,t34,t35,t36,t37,t38,t57;
SimdScalar p1,p2,p3,p4;
t1 = uy*s;
t2 = t1*vx;
t3 = ux*s;
t4 = t3*vy;
t7 = tanf(w/2.0f);
t8 = 1/t7;
t10 = 1/uz;
t13 = ux*az;
t14 = t7*vy;
t15 = t13*t14;
t16 = ax*t7;
t17 = uy*vz;
t18 = t16*t17;
t19 = cx*t7;
t20 = t19*t17;
t21 = vy*uz;
t22 = t19*t21;
t23 = ay*t7;
t24 = vx*uz;
t25 = t23*t24;
t26 = uy*cz;
t27 = t7*vx;
t28 = t26*t27;
t29 = t16*t21;
t30 = cy*t7;
t31 = ux*vz;
t32 = t30*t31;
t33 = ux*cz;
t34 = t33*t14;
t35 = t23*t31;
t36 = t30*t24;
t37 = uy*az;
t38 = t37*t27;
p4 = (-t2+t4)*t8*t10;
p3 = 2.0f*t1*vy+t15-t18-t20-t22+t25+t28-t29+t32-t34+t35+t36-t38+2.0f*t3*vx;
p2 = -2.0f*t33*t27-2.0f*t26*t14-2.0f*t23*t21+2.0f*t37*t14+2.0f*t30*t17+2.0f*t13
*t27+t2-t4+2.0f*t19*t31-2.0f*t16*t24;
t57 = -t22+t29+t36-t25-t32+t34+t35-t28-t15+t20-t18+t38;
p1 = t57*t8*t10;
coefs[0] = p4;
coefs[1] = p3;
coefs[2] = p2;
coefs[1] = p1;
}
numroots = polynomialSolver.Solve3Cubic(coefs[0],coefs[1],coefs[2],coefs[3]);
for (int i=0;i<numroots;i++)
{
//SimdScalar tau = roots[i];//polynomialSolver.GetRoot(i);
SimdScalar tau = polynomialSolver.GetRoot(i);
//check whether mu and lambda are in range [0..1]
if (!SimdFuzzyZero(v.z()))
{
SimdScalar A1=(ux-ux*tau*tau-2.f*tau*uy)-((1.f+tau*tau)*vx*uz/vz);
SimdScalar B1=((1.f+tau*tau)*(cx*tanf(1.f/2.f*w)*vz+
vx*az*tanf(1.f/2.f*w)-vx*cz*tanf(1.f/2.f*w)+
vx*s*tau)/tanf(1.f/2.f*w)/vz)-(ax-ax*tau*tau-2.f*tau*ay);
lambda = B1/A1;
mu = (a.z()-c.z()+lambda*u.z()+(s*tau)/(tanf(w/2.f)))/v.z();
//double check in original equation
SimdScalar lhs = (a.x()+lambda*u.x())
*((1.f-tau*tau)/(1.f+tau*tau))-
(a.y()+lambda*u.y())*((2.f*tau)/(1.f+tau*tau));
lhs = lambda*((ux-ux*tau*tau-2.f*tau*uy)-((1.f+tau*tau)*vx*uz/vz));
SimdScalar rhs = c.x()+mu*v.x();
rhs = ((1.f+tau*tau)*(cx*tanf(1.f/2.f*w)*vz+vx*az*tanf(1.f/2.f*w)-
vx*cz*tanf(1.f/2.f*w)+vx*s*tau)/(tanf(1.f/2.f*w)*vz))-
(ax-ax*tau*tau-2.f*tau*ay);
SimdScalar res = coefs[0]*tau*tau*tau+
coefs[1]*tau*tau+
coefs[2]*tau+
coefs[3];
//lhs should be rhs !
if (0.<= mu && mu <=1 && 0.<=lambda && lambda <= 1)
{
} else
{
//skip this solution, not really touching
continue;
}
}
SimdScalar t = 2.f*atanf(tau)/screwAB.GetW();
//tau = tan (wt/2) so 2*atan (tau)/w
if (t>=0.f && t<minTime)
{
#ifdef STATS_EDGE_EDGE
printf(" ax = %12.12f\n ay = %12.12f\n az = %12.12f\n",a.x(),a.y(),a.z());
printf(" ux = %12.12f\n uy = %12.12f\n uz = %12.12f\n",u.x(),u.y(),u.z());
printf(" cx = %12.12f\n cy = %12.12f\n cz = %12.12f\n",c.x(),c.y(),c.z());
printf(" vx = %12.12f\n vy = %12.12f\n vz = %12.12f\n",v.x(),v.y(),v.z());
printf(" s = %12.12f\n w = %12.12f\n", s, w);
printf(" tau = %12.12f \n lambda = %12.12f \n mu = %f\n",tau,lambda,mu);
printf(" ---------------------------------------------\n");
#endif
// v,u,a,c,s,w
// BU_IntervalArithmeticPolynomialSolver iaSolver;
// int numroots2 = iaSolver.Solve3Cubic(coefs[0],coefs[1],coefs[2],coefs[3]);
minTime = t;
hit = true;
}
}
return hit;
}
//C -S
//S C
bool BU_EdgeEdge::Calc2DRotationPointPoint(const SimdPoint3& rotPt, SimdScalar rotRadius, SimdScalar rotW,const SimdPoint3& intersectPt,SimdScalar& minTime)
{
bool hit = false;
// now calculate the planeEquation for the vertex motion,
// and check if the intersectionpoint is at the positive side
SimdPoint3 rotPt1(cosf(rotW)*rotPt.x()-sinf(rotW)*rotPt.y(),
sinf(rotW)*rotPt.x()+cosf(rotW)*rotPt.y(),
0.f);
SimdVector3 rotVec = rotPt1-rotPt;
SimdVector3 planeNormal( -rotVec.y() , rotVec.x() ,0.f);
//SimdPoint3 pt(a.x(),a.y());//for sake of readability,could write dot directly
SimdScalar planeD = planeNormal.dot(rotPt1);
SimdScalar dist = (planeNormal.dot(intersectPt)-planeD);
hit = (dist >= -0.001);
//if (hit)
{
// minTime = 0;
//calculate the time of impact, using the fact of
//toi = alpha / screwAB.getW();
// cos (alpha) = adjacent/hypothenuse;
//adjacent = dotproduct(ipedge,point);
//hypothenuse = sqrt(r2);
SimdScalar adjacent = intersectPt.dot(rotPt)/rotRadius;
SimdScalar hypo = rotRadius;
SimdScalar alpha = acosf(adjacent/hypo);
SimdScalar t = alpha / rotW;
if (t >= 0 && t < minTime)
{
hit = true;
minTime = t;
} else
{
hit = false;
}
}
return hit;
}
bool BU_EdgeEdge::GetTimeOfImpactVertexEdge(
const BU_Screwing& screwAB,
const SimdPoint3& a,//edge in object A
const SimdVector3& u,
const SimdPoint3& c,//edge in object B
const SimdVector3& v,
SimdScalar &minTime,
SimdScalar &lamda,
SimdScalar& mu
)
{
return false;
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef BU_EDGEEDGE
#define BU_EDGEEDGE
class BU_Screwing;
#include <SimdTransform.h>
#include <SimdPoint3.h>
#include <SimdVector3.h>
//class BUM_Point2;
#include <SimdScalar.h>
///BU_EdgeEdge implements algebraic time of impact calculation between two (angular + linear) moving edges.
class BU_EdgeEdge
{
public:
BU_EdgeEdge();
bool GetTimeOfImpact(
const BU_Screwing& screwAB,
const SimdPoint3& a,//edge in object A
const SimdVector3& u,
const SimdPoint3& c,//edge in object B
const SimdVector3& v,
SimdScalar &minTime,
SimdScalar &lamda,
SimdScalar& mu
);
private:
bool Calc2DRotationPointPoint(const SimdPoint3& rotPt, SimdScalar rotRadius, SimdScalar rotW,const SimdPoint3& intersectPt,SimdScalar& minTime);
bool GetTimeOfImpactGeneralCase(
const BU_Screwing& screwAB,
const SimdPoint3& a,//edge in object A
const SimdVector3& u,
const SimdPoint3& c,//edge in object B
const SimdVector3& v,
SimdScalar &minTime,
SimdScalar &lamda,
SimdScalar& mu
);
bool GetTimeOfImpactVertexEdge(
const BU_Screwing& screwAB,
const SimdPoint3& a,//edge in object A
const SimdVector3& u,
const SimdPoint3& c,//edge in object B
const SimdVector3& v,
SimdScalar &minTime,
SimdScalar &lamda,
SimdScalar& mu
);
};
#endif //BU_EDGEEDGE

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef BU_MOTIONSTATE
#define BU_MOTIONSTATE
#include <SimdTransform.h>
#include <SimdPoint3.h>
#include <SimdQuaternion.h>
class BU_MotionStateInterface
{
public:
virtual ~BU_MotionStateInterface(){};
virtual void SetTransform(const SimdTransform& trans) = 0;
virtual void GetTransform(SimdTransform& trans) const = 0;
virtual void SetPosition(const SimdPoint3& position) = 0;
virtual void GetPosition(SimdPoint3& position) const = 0;
virtual void SetOrientation(const SimdQuaternion& orientation) = 0;
virtual void GetOrientation(SimdQuaternion& orientation) const = 0;
virtual void SetBasis(const SimdMatrix3x3& basis) = 0;
virtual void GetBasis(SimdMatrix3x3& basis) const = 0;
virtual void SetLinearVelocity(const SimdVector3& linvel) = 0;
virtual void GetLinearVelocity(SimdVector3& linvel) const = 0;
virtual void GetAngularVelocity(SimdVector3& angvel) const = 0;
virtual void SetAngularVelocity(const SimdVector3& angvel) = 0;
};
#endif //BU_MOTIONSTATE

View File

@@ -0,0 +1,26 @@
#ifndef BUM_POLYNOMIAL_SOLVER_INTERFACE
#define BUM_POLYNOMIAL_SOLVER_INTERFACE
#include <SimdScalar.h>
//
//BUM_PolynomialSolverInterface is interface class for polynomial root finding.
//The number of roots is returned as a result, query GetRoot to get the actual solution.
//
class BUM_PolynomialSolverInterface
{
public:
virtual ~BUM_PolynomialSolverInterface() {};
// virtual int Solve2QuadraticFull(SimdScalar a,SimdScalar b, SimdScalar c) = 0;
virtual int Solve3Cubic(SimdScalar lead, SimdScalar a, SimdScalar b, SimdScalar c) = 0;
virtual int Solve4Quartic(SimdScalar lead, SimdScalar a, SimdScalar b, SimdScalar c, SimdScalar d) = 0;
virtual SimdScalar GetRoot(int i) const = 0;
};
#endif //BUM_POLYNOMIAL_SOLVER_INTERFACE

View File

@@ -0,0 +1,197 @@
/*
* Copyright (c) 2005 Stephane Redon / Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "BU_Screwing.h"
BU_Screwing::BU_Screwing(const SimdVector3& relLinVel,const SimdVector3& relAngVel) {
const SimdScalar dx=relLinVel[0];
const SimdScalar dy=relLinVel[1];
const SimdScalar dz=relLinVel[2];
const SimdScalar wx=relAngVel[0];
const SimdScalar wy=relAngVel[1];
const SimdScalar wz=relAngVel[2];
// Compute the screwing parameters :
// w : total amount of rotation
// s : total amount of translation
// u : vector along the screwing axis (||u||=1)
// o : point on the screwing axis
m_w=sqrtf(wx*wx+wy*wy+wz*wz);
//if (!w) {
if (fabs(m_w)<SCREWEPSILON ) {
assert(m_w == 0.f);
m_w=0.;
m_s=sqrtf(dx*dx+dy*dy+dz*dz);
if (fabs(m_s)<SCREWEPSILON ) {
assert(m_s == 0.);
m_s=0.;
m_u=SimdPoint3(0.,0.,1.);
m_o=SimdPoint3(0.,0.,0.);
}
else {
float t=1.f/m_s;
m_u=SimdPoint3(dx*t,dy*t,dz*t);
m_o=SimdPoint3(0.f,0.f,0.f);
}
}
else { // there is some rotation
// we compute u
float v(1.f/m_w);
m_u=SimdPoint3(wx*v,wy*v,wz*v); // normalization
// decomposition of the translation along u and one orthogonal vector
SimdPoint3 t(dx,dy,dz);
m_s=t.dot(m_u); // component along u
if (fabs(m_s)<SCREWEPSILON)
{
//printf("m_s component along u < SCREWEPSILION\n");
m_s=0.f;
}
SimdPoint3 n1(t-(m_s*m_u)); // the remaining part (which is orthogonal to u)
// now we have to compute o
SimdScalar len = n1.length2();
//(len >= BUM_EPSILON2) {
if (n1[0] || n1[1] || n1[2]) { // n1 is not the zero vector
n1.normalize();
SimdVector3 n1orth=m_u.cross(n1);
float n2x=cosf(0.5f*m_w);
float n2y=sinf(0.5f*m_w);
m_o=0.5f*t.dot(n1)*(n1+n2x/n2y*n1orth);
}
else
{
m_o=SimdPoint3(0.f,0.f,0.f);
}
}
}
//Then, I need to compute Pa, the matrix from the reference (global) frame to
//the screwing frame :
void BU_Screwing::LocalMatrix(SimdTransform &t) const {
//So the whole computations do this : align the Oz axis along the
// screwing axis (thanks to u), and then find two others orthogonal axes to
// complete the basis.
if ((m_u[0]>SCREWEPSILON)||(m_u[0]<-SCREWEPSILON)||(m_u[1]>SCREWEPSILON)||(m_u[1]<-SCREWEPSILON))
{
// to avoid numerical problems
float n=sqrtf(m_u[0]*m_u[0]+m_u[1]*m_u[1]);
float invn=1.0f/n;
SimdMatrix3x3 mat;
mat[0][0]=-m_u[1]*invn;
mat[0][1]=m_u[0]*invn;
mat[0][2]=0.f;
mat[1][0]=-m_u[0]*invn*m_u[2];
mat[1][1]=-m_u[1]*invn*m_u[2];
mat[1][2]=n;
mat[2][0]=m_u[0];
mat[2][1]=m_u[1];
mat[2][2]=m_u[2];
t.setOrigin(SimdPoint3(
m_o[0]*m_u[1]*invn-m_o[1]*m_u[0]*invn,
-(m_o[0]*mat[1][0]+m_o[1]*mat[1][1]+m_o[2]*n),
-(m_o[0]*m_u[0]+m_o[1]*m_u[1]+m_o[2]*m_u[2])));
t.setBasis(mat);
}
else {
SimdMatrix3x3 m;
m[0][0]=1.;
m[1][0]=0.;
m[2][0]=0.;
m[0][1]=0.f;
m[1][1]=float(SimdSign(m_u[2]));
m[2][1]=0.f;
m[0][2]=0.f;
m[1][2]=0.f;
m[2][2]=float(SimdSign(m_u[2]));
t.setOrigin(SimdPoint3(
-m_o[0],
-SimdSign(m_u[2])*m_o[1],
-SimdSign(m_u[2])*m_o[2]
));
t.setBasis(m);
}
}
//gives interpolated transform for time in [0..1] in screwing frame
SimdTransform BU_Screwing::InBetweenTransform(const SimdTransform& tr,SimdScalar t) const
{
SimdPoint3 org = tr.getOrigin();
SimdPoint3 neworg (
org.x()*cosf(m_w*t)-org.y()*sinf(m_w*t),
org.x()*sinf(m_w*t)+org.y()*cosf(m_w*t),
org.z()+m_s*CalculateF(t));
SimdTransform newtr;
newtr.setOrigin(neworg);
SimdMatrix3x3 basis = tr.getBasis();
SimdMatrix3x3 basisorg = tr.getBasis();
SimdQuaternion rot(SimdVector3(0.,0.,1.),m_w*t);
SimdQuaternion tmpOrn;
tr.getBasis().getRotation(tmpOrn);
rot = rot * tmpOrn;
//to avoid numerical drift, normalize quaternion
rot.normalize();
newtr.setBasis(SimdMatrix3x3(rot));
return newtr;
}
SimdScalar BU_Screwing::CalculateF(SimdScalar t) const
{
SimdScalar result;
if (!m_w)
{
result = t;
} else
{
result = ( tanf((m_w*t)/2.f) / tanf(m_w/2.f));
}
return result;
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef B_SCREWING_H
#define B_SCREWING_H
#include <SimdVector3.h>
#include <SimdPoint3.h>
#include <SimdTransform.h>
#define SCREWEPSILON 0.00001f
///BU_Screwing implements screwing motion interpolation.
class BU_Screwing
{
public:
BU_Screwing(const SimdVector3& relLinVel,const SimdVector3& relAngVel);
~BU_Screwing() {
};
SimdScalar CalculateF(SimdScalar t) const;
//gives interpolated position for time in [0..1] in screwing frame
inline SimdPoint3 InBetweenPosition(const SimdPoint3& pt,SimdScalar t) const
{
return SimdPoint3(
pt.x()*cosf(m_w*t)-pt.y()*sinf(m_w*t),
pt.x()*sinf(m_w*t)+pt.y()*cosf(m_w*t),
pt.z()+m_s*CalculateF(t));
}
inline SimdVector3 InBetweenVector(const SimdVector3& vec,SimdScalar t) const
{
return SimdVector3(
vec.x()*cosf(m_w*t)-vec.y()*sinf(m_w*t),
vec.x()*sinf(m_w*t)+vec.y()*cosf(m_w*t),
vec.z());
}
//gives interpolated transform for time in [0..1] in screwing frame
SimdTransform InBetweenTransform(const SimdTransform& tr,SimdScalar t) const;
//gives matrix from global frame into screwing frame
void LocalMatrix(SimdTransform &t) const;
inline const SimdVector3& GetU() const { return m_u;}
inline const SimdVector3& GetO() const {return m_o;}
inline const SimdScalar GetS() const{ return m_s;}
inline const SimdScalar GetW() const { return m_w;}
private:
float m_w;
float m_s;
SimdVector3 m_u;
SimdVector3 m_o;
};
#endif //B_SCREWING_H

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef BU_STATIC_MOTIONSTATE
#define BU_STATIC_MOTIONSTATE
#include <CollisionShapes/BU_MotionStateInterface.h>
class BU_StaticMotionState :public BU_MotionStateInterface
{
public:
virtual ~BU_StaticMotionState(){};
virtual void SetTransform(const SimdTransform& trans)
{
m_trans = trans;
}
virtual void GetTransform(SimdTransform& trans) const
{
trans = m_trans;
}
virtual void SetPosition(const SimdPoint3& position)
{
m_trans.setOrigin( position );
}
virtual void GetPosition(SimdPoint3& position) const
{
position = m_trans.getOrigin();
}
virtual void SetOrientation(const SimdQuaternion& orientation)
{
m_trans.setRotation( orientation);
}
virtual void GetOrientation(SimdQuaternion& orientation) const
{
orientation = m_trans.getRotation();
}
virtual void SetBasis(const SimdMatrix3x3& basis)
{
m_trans.setBasis( basis);
}
virtual void GetBasis(SimdMatrix3x3& basis) const
{
basis = m_trans.getBasis();
}
virtual void SetLinearVelocity(const SimdVector3& linvel)
{
m_linearVelocity = linvel;
}
virtual void GetLinearVelocity(SimdVector3& linvel) const
{
linvel = m_linearVelocity;
}
virtual void SetAngularVelocity(const SimdVector3& angvel)
{
m_angularVelocity = angvel;
}
virtual void GetAngularVelocity(SimdVector3& angvel) const
{
angvel = m_angularVelocity;
}
protected:
SimdTransform m_trans;
SimdVector3 m_angularVelocity;
SimdVector3 m_linearVelocity;
};
#endif //BU_STATIC_MOTIONSTATE

View File

@@ -0,0 +1,154 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "BU_VertexPoly.h"
#include "BU_Screwing.h"
#include <SimdTransform.h>
#include <SimdPoint3.h>
#include <SimdVector3.h>
#define USE_ALGEBRAIC
#ifdef USE_ALGEBRAIC
#include "BU_AlgebraicPolynomialSolver.h"
#define BU_Polynomial BU_AlgebraicPolynomialSolver
#else
#include "BU_IntervalArithmeticPolynomialSolver.h"
#define BU_Polynomial BU_IntervalArithmeticPolynomialSolver
#endif
inline bool TestFuzzyZero(SimdScalar x) { return fabsf(x) < 0.0001f; }
BU_VertexPoly::BU_VertexPoly()
{
}
//return true if a collision will occur between [0..1]
//false otherwise. If true, minTime contains the time of impact
bool BU_VertexPoly::GetTimeOfImpact(
const BU_Screwing& screwAB,
const SimdPoint3& a,
const SimdVector4& planeEq,
SimdScalar &minTime,bool swapAB)
{
bool hit = false;
// precondition: s=0 and w= 0 is catched by caller!
if (TestFuzzyZero(screwAB.GetS()) &&
TestFuzzyZero(screwAB.GetW()))
{
return false;
}
//case w<>0 and s<> 0
const SimdScalar w=screwAB.GetW();
const SimdScalar s=screwAB.GetS();
SimdScalar coefs[4];
const SimdScalar p=planeEq[0];
const SimdScalar q=planeEq[1];
const SimdScalar r=planeEq[2];
const SimdScalar d=planeEq[3];
const SimdVector3 norm(p,q,r);
BU_Polynomial polynomialSolver;
int numroots = 0;
SimdScalar eps=1e-80f;
SimdScalar eps2=1e-100f;
if (TestFuzzyZero(screwAB.GetS()) )
{
//S = 0 , W <> 0
//ax^3+bx^2+cx+d=0
coefs[0]=0.;
coefs[1]=(-p*a.x()-q*a.y()+r*a.z()-d);
coefs[2]=-2*p*a.y()+2*q*a.x();
coefs[3]=p*a.x()+q*a.y()+r*a.z()-d;
// numroots = polynomialSolver.Solve3Cubic(coefs[0],coefs[1],coefs[2],coefs[3]);
numroots = polynomialSolver.Solve2QuadraticFull(coefs[1],coefs[2],coefs[3]);
} else
{
if (TestFuzzyZero(screwAB.GetW()))
{
// W = 0 , S <> 0
//pax+qay+r(az+st)=d
SimdScalar dist = (d - a.dot(norm));
if (TestFuzzyZero(r))
{
if (TestFuzzyZero(dist))
{
// no hit
} else
{
// todo a a' might hit sides of polygon T
//printf("unhandled case, w=0,s<>0,r<>0, a a' might hit sides of polygon T \n");
}
} else
{
SimdScalar etoi = (dist)/(r*screwAB.GetS());
if (swapAB)
etoi *= -1;
if (etoi >= 0. && etoi <= minTime)
{
minTime = etoi;
hit = true;
}
}
} else
{
//ax^3+bx^2+cx+d=0
//degenerate coefficients mess things up :(
SimdScalar ietsje = (r*s)/tanf(w/2.f);
if (ietsje*ietsje < 0.01f)
ietsje = 0.f;
coefs[0]=ietsje;//(r*s)/tan(w/2.);
coefs[1]=(-p*a.x()-q*a.y()+r*a.z()-d);
coefs[2]=-2.f*p*a.y()+2.f*q*a.x()+ietsje;//((r*s)/(tan(w/2.)));
coefs[3]=p*a.x()+q*a.y()+r*a.z()-d;
numroots = polynomialSolver.Solve3Cubic(coefs[0],coefs[1],coefs[2],coefs[3]);
}
}
for (int i=0;i<numroots;i++)
{
SimdScalar tau = polynomialSolver.GetRoot(i);
SimdScalar t = 2.f*atanf(tau)/w;
//tau = tan (wt/2) so 2*atan (tau)/w
if (swapAB)
{
t *= -1.;
}
if (t>=0 && t<minTime)
{
minTime = t;
hit = true;
}
}
return hit;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef VERTEX_POLY_H
#define VERTEX_POLY_H
class BU_Screwing;
#include <SimdTransform.h>
#include <SimdPoint3.h>
#include <SimdScalar.h>
///BU_VertexPoly implements algebraic time of impact calculation between vertex and a plane.
class BU_VertexPoly
{
public:
BU_VertexPoly();
bool GetTimeOfImpact(
const BU_Screwing& screwAB,
const SimdPoint3& vtx,
const SimdVector4& planeEq,
SimdScalar &minTime,
bool swapAB);
private:
//cached data (frame coherency etc.) here
};
#endif //VERTEX_POLY_H

View File

@@ -0,0 +1,11 @@
#ifndef COLLISION_MARGIN_H
#define COLLISION_MARGIN_H
//used by Gjk and some other algorithms
#define CONVEX_DISTANCE_MARGIN 0.05f// 0.1f//;//0.01f
#endif //COLLISION_MARGIN_H

View File

@@ -0,0 +1,186 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "ContinuousConvexCollision.h"
#include "CollisionShapes/ConvexShape.h"
#include "CollisionShapes/MinkowskiSumShape.h"
#include "NarrowPhaseCollision/SimplexSolverInterface.h"
#include "SimdTransformUtil.h"
#include "CollisionShapes/SphereShape.h"
#include "GjkPairDetector.h"
#include "PointCollector.h"
ContinuousConvexCollision::ContinuousConvexCollision ( ConvexShape* convexA,ConvexShape* convexB,SimplexSolverInterface* simplexSolver, ConvexPenetrationDepthSolver* penetrationDepthSolver)
:m_simplexSolver(simplexSolver),
m_penetrationDepthSolver(penetrationDepthSolver),
m_convexA(convexA),m_convexB(convexB)
{
}
/// This maximum should not be necessary. It allows for untested/degenerate cases in production code.
/// You don't want your game ever to lock-up.
#define MAX_ITERATIONS 1000
bool ContinuousConvexCollision::calcTimeOfImpact(
const SimdTransform& fromA,
const SimdTransform& toA,
const SimdTransform& fromB,
const SimdTransform& toB,
CastResult& result)
{
m_simplexSolver->reset();
/// compute linear and angular velocity for this interval, to interpolate
SimdVector3 linVelA,angVelA,linVelB,angVelB;
SimdTransformUtil::CalculateVelocity(fromA,toA,1.f,linVelA,angVelA);
SimdTransformUtil::CalculateVelocity(fromB,toB,1.f,linVelB,angVelB);
SimdScalar boundingRadiusA = m_convexA->GetAngularMotionDisc();
SimdScalar boundingRadiusB = m_convexB->GetAngularMotionDisc();
SimdScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
float radius = 0.001f;
SimdScalar lambda = 0.f;
SimdVector3 v(1,0,0);
int maxIter = MAX_ITERATIONS;
SimdVector3 n;
n.setValue(0.f,0.f,0.f);
bool hasResult = false;
SimdVector3 c;
float lastLambda = lambda;
float epsilon = 0.001f;
int numIter = 0;
//first solution, using GJK
SimdTransform identityTrans;
identityTrans.setIdentity();
SphereShape raySphere(0.0f);
raySphere.SetMargin(0.f);
// result.DrawCoordSystem(sphereTr);
PointCollector pointCollector1;
{
GjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver);
GjkPairDetector::ClosestPointInput input;
input.m_transformA = fromA;
input.m_transformB = fromB;
gjk.GetClosestPoints(input,pointCollector1);
hasResult = pointCollector1.m_hasResult;
c = pointCollector1.m_pointInWorld;
}
if (hasResult)
{
SimdScalar dist;
dist = pointCollector1.m_distance;
n = pointCollector1.m_normalOnBInWorld;
//not close enough
while (dist > radius)
{
numIter++;
if (numIter > maxIter)
return false; //todo: report a failure
float dLambda = 0.f;
//calculate safe moving fraction from distance / (linear+rotational velocity)
//float clippedDist = GEN_min(angularConservativeRadius,dist);
float clippedDist = dist;
float projectedLinearVelocity = (linVelB-linVelA).dot(n);
dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity);
lambda = lambda + dLambda;
//todo: next check with relative epsilon
if (lambda <= lastLambda)
break;
lastLambda = lambda;
if (lambda > 1.f)
return false;
//interpolate to next lambda
SimdTransform interpolatedTransA,interpolatedTransB,relativeTrans;
SimdTransformUtil::IntegrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA);
SimdTransformUtil::IntegrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB);
relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA);
result.DebugDraw( lambda );
PointCollector pointCollector;
GjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver);
GjkPairDetector::ClosestPointInput input;
input.m_transformA = interpolatedTransA;
input.m_transformB = interpolatedTransB;
gjk.GetClosestPoints(input,pointCollector);
if (pointCollector.m_hasResult)
{
if (pointCollector.m_distance < 0.f)
{
//degenerate ?!
result.m_fraction = lastLambda;
result.m_normal = n;
return true;
}
c = pointCollector.m_pointInWorld;
dist = pointCollector.m_distance;
} else
{
//??
return false;
}
}
result.m_fraction = lambda;
result.m_normal = n;
return true;
}
return false;
/*
//todo:
//if movement away from normal, discard result
SimdVector3 move = transBLocalTo.getOrigin() - transBLocalFrom.getOrigin();
if (result.m_fraction < 1.f)
{
if (move.dot(result.m_normal) <= 0.f)
{
}
}
*/
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONTINUOUS_COLLISION_CONVEX_CAST_H
#define CONTINUOUS_COLLISION_CONVEX_CAST_H
#include "ConvexCast.h"
#include "SimplexSolverInterface.h"
class ConvexPenetrationDepthSolver;
class ConvexShape;
/// ContinuousConvexCollision implements angular and linear time of impact for convex objects.
/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis).
/// Algorithm operates in worldspace, in order to keep inbetween motion globally consistent.
/// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops
class ContinuousConvexCollision : public ConvexCast
{
SimplexSolverInterface* m_simplexSolver;
ConvexPenetrationDepthSolver* m_penetrationDepthSolver;
ConvexShape* m_convexA;
ConvexShape* m_convexB;
public:
ContinuousConvexCollision (ConvexShape* shapeA,ConvexShape* shapeB ,SimplexSolverInterface* simplexSolver,ConvexPenetrationDepthSolver* penetrationDepthSolver);
virtual bool calcTimeOfImpact(
const SimdTransform& fromA,
const SimdTransform& toA,
const SimdTransform& fromB,
const SimdTransform& toB,
CastResult& result);
};
#endif //CONTINUOUS_COLLISION_CONVEX_CAST_H

View File

@@ -0,0 +1,5 @@
#include "ConvexCast.h"
ConvexCast::~ConvexCast()
{
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONVEX_CAST_H
#define CONVEX_CAST_H
#include <SimdTransform.h>
#include <SimdVector3.h>
#include <SimdScalar.h>
class MinkowskiSumShape;
/// ConvexCast is an interface for Casting
class ConvexCast
{
public:
virtual ~ConvexCast();
///RayResult stores the closest result
/// alternatively, add a callback method to decide about closest/all results
struct CastResult
{
//virtual bool addRayResult(const SimdVector3& normal,SimdScalar fraction) = 0;
virtual void DebugDraw(SimdScalar fraction) {}
virtual void DrawCoordSystem(const SimdTransform& trans) {}
CastResult()
:m_fraction(1e30f)
{
}
SimdVector3 m_normal;
SimdScalar m_fraction;
SimdTransform m_hitTransformA;
SimdTransform m_hitTransformB;
};
/// cast a convex against another convex object
virtual bool calcTimeOfImpact(
const SimdTransform& fromA,
const SimdTransform& toA,
const SimdTransform& fromB,
const SimdTransform& toB,
CastResult& result) = 0;
};
#endif //CONVEX_CAST_H

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONVEX_PENETRATION_DEPTH_H
#define CONVEX_PENETRATION_DEPTH_H
class SimdVector3;
#include "SimplexSolverInterface.h"
class ConvexShape;
#include "SimdPoint3.h"
class SimdTransform;
///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation.
class ConvexPenetrationDepthSolver
{
public:
virtual bool CalcPenDepth( SimplexSolverInterface& simplexSolver,
ConvexShape* convexA,ConvexShape* convexB,
const SimdTransform& transA,const SimdTransform& transB,
SimdVector3& v, SimdPoint3& pa, SimdPoint3& pb) = 0;
};
#endif //CONVEX_PENETRATION_DEPTH_H

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef DISCRETE_COLLISION_DETECTOR_INTERFACE_H
#define DISCRETE_COLLISION_DETECTOR_INTERFACE_H
#include "SimdTransform.h"
#include "SimdVector3.h"
/// This interface is made to be used by an iterative approach to do TimeOfImpact calculations
/// This interface allows to query for closest points and penetration depth between two (convex) objects
/// the closest point is on the second object (B), and the normal points from the surface on B towards A.
/// distance is between closest points on B and closest point on A. So you can calculate closest point on A
/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB
struct DiscreteCollisionDetectorInterface
{
void operator delete(void* ptr) {};
struct Result
{
void operator delete(void* ptr) {};
virtual void AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth)=0;
};
struct ClosestPointInput
{
ClosestPointInput()
:m_maximumDistanceSquared(1e30f)
{
}
SimdTransform m_transformA;
SimdTransform m_transformB;
SimdScalar m_maximumDistanceSquared;
};
virtual ~DiscreteCollisionDetectorInterface() {};
//
// give either closest points (distance > 0) or penetration (distance)
// the normal always points from B towards A
//
virtual void GetClosestPoints(const ClosestPointInput& input,Result& output) = 0;
SimdScalar getCollisionMargin() { return 0.2f;}
};
struct StorageResult : public DiscreteCollisionDetectorInterface::Result
{
SimdVector3 m_normalOnSurfaceB;
SimdVector3 m_closestPointInB;
SimdScalar m_distance; //negative means penetration !
StorageResult() : m_distance(1e30f)
{
}
virtual void AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth)
{
if (depth < m_distance)
{
m_normalOnSurfaceB = normalOnBInWorld;
m_closestPointInB = pointInWorld;
m_distance = depth;
}
}
};
#endif //DISCRETE_COLLISION_DETECTOR_INTERFACE_H

View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "GjkConvexCast.h"
#include "CollisionShapes/SphereShape.h"
#include "CollisionShapes/MinkowskiSumShape.h"
#include "GjkPairDetector.h"
#include "PointCollector.h"
GjkConvexCast::GjkConvexCast(ConvexShape* convexA,ConvexShape* convexB,SimplexSolverInterface* simplexSolver)
:m_simplexSolver(simplexSolver),
m_convexA(convexA),
m_convexB(convexB)
{
}
bool GjkConvexCast::calcTimeOfImpact(
const SimdTransform& fromA,
const SimdTransform& toA,
const SimdTransform& fromB,
const SimdTransform& toB,
CastResult& result)
{
MinkowskiSumShape combi(m_convexA,m_convexB);
MinkowskiSumShape* convex = &combi;
SimdTransform rayFromLocalA;
SimdTransform rayToLocalA;
rayFromLocalA = fromA.inverse()* fromB;
rayToLocalA = toA.inverse()* toB;
SimdTransform trA,trB;
trA = SimdTransform(fromA);
trB = SimdTransform(fromB);
trA.setOrigin(SimdPoint3(0,0,0));
trB.setOrigin(SimdPoint3(0,0,0));
convex->SetTransformA(trA);
convex->SetTransformB(trB);
float radius = 0.01f;
SimdScalar lambda = 0.f;
SimdVector3 s = rayFromLocalA.getOrigin();
SimdVector3 r = rayToLocalA.getOrigin()-rayFromLocalA.getOrigin();
SimdVector3 x = s;
SimdVector3 n;
n.setValue(0,0,0);
bool hasResult = false;
SimdVector3 c;
float lastLambda = lambda;
//first solution, using GJK
//no penetration support for now, perhaps pass a pointer when we really want it
ConvexPenetrationDepthSolver* penSolverPtr = 0;
SimdTransform identityTrans;
identityTrans.setIdentity();
SphereShape raySphere(0.0f);
raySphere.SetMargin(0.f);
SimdTransform sphereTr;
sphereTr.setIdentity();
sphereTr.setOrigin( rayFromLocalA.getOrigin());
result.DrawCoordSystem(sphereTr);
{
PointCollector pointCollector1;
GjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr);
GjkPairDetector::ClosestPointInput input;
input.m_transformA = sphereTr;
input.m_transformB = identityTrans;
gjk.GetClosestPoints(input,pointCollector1);
hasResult = pointCollector1.m_hasResult;
c = pointCollector1.m_pointInWorld;
n = pointCollector1.m_normalOnBInWorld;
}
if (hasResult)
{
SimdScalar dist;
dist = (c-x).length();
//not close enough
while (dist > radius)
{
n = x - c;
SimdScalar nDotr = n.dot(r);
if (nDotr >= 0.f)
return false;
lambda = lambda - n.dot(n) / nDotr;
if (lambda <= lastLambda)
break;
lastLambda = lambda;
x = s + lambda * r;
sphereTr.setOrigin( x );
result.DrawCoordSystem(sphereTr);
PointCollector pointCollector;
GjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr);
GjkPairDetector::ClosestPointInput input;
input.m_transformA = sphereTr;
input.m_transformB = identityTrans;
gjk.GetClosestPoints(input,pointCollector);
if (pointCollector.m_hasResult)
{
if (pointCollector.m_distance < 0.f)
{
//degeneracy, report a hit
result.m_fraction = lastLambda;
result.m_normal = n;
return true;
}
c = pointCollector.m_pointInWorld;
dist = (c-x).length();
} else
{
//??
return false;
}
}
result.m_fraction = lambda;
result.m_normal = n;
return true;
}
return false;
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef GJK_CONVEX_CAST_H
#define GJK_CONVEX_CAST_H
#include "CollisionMargin.h"
#include "SimdVector3.h"
#include "ConvexCast.h"
class ConvexShape;
class MinkowskiSumShape;
#include "SimplexSolverInterface.h"
///GjkConvexCast performs a raycast on a convex object using support mapping.
class GjkConvexCast : public ConvexCast
{
SimplexSolverInterface* m_simplexSolver;
ConvexShape* m_convexA;
ConvexShape* m_convexB;
public:
GjkConvexCast(ConvexShape* convexA,ConvexShape* convexB,SimplexSolverInterface* simplexSolver);
/// cast a convex against another convex object
virtual bool calcTimeOfImpact(
const SimdTransform& fromA,
const SimdTransform& toA,
const SimdTransform& fromB,
const SimdTransform& toB,
CastResult& result);
};
#endif //GJK_CONVEX_CAST_H

View File

@@ -0,0 +1,186 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "GjkPairDetector.h"
#include "CollisionShapes/ConvexShape.h"
#include "NarrowPhaseCollision/SimplexSolverInterface.h"
#include "NarrowPhaseCollision/ConvexPenetrationDepthSolver.h"
static const SimdScalar rel_error = SimdScalar(1.0e-3);
SimdScalar rel_error2 = rel_error * rel_error;
float maxdist2 = 1.e30f;
GjkPairDetector::GjkPairDetector(ConvexShape* objectA,ConvexShape* objectB,SimplexSolverInterface* simplexSolver,ConvexPenetrationDepthSolver* penetrationDepthSolver)
:m_cachedSeparatingAxis(0.f,0.f,1.f),
m_penetrationDepthSolver(penetrationDepthSolver),
m_simplexSolver(simplexSolver),
m_minkowskiA(objectA),
m_minkowskiB(objectB)
{
}
void GjkPairDetector::GetClosestPoints(const ClosestPointInput& input,Result& output)
{
SimdScalar distance;
SimdVector3 normalInB(0.f,0.f,0.f);
SimdVector3 pointOnA,pointOnB;
float marginA = m_minkowskiA->GetMargin();
float marginB = m_minkowskiB->GetMargin();
bool isValid = false;
bool checkSimplex = false;
bool checkPenetration = true;
{
SimdScalar squaredDistance = SIMD_INFINITY;
SimdScalar delta = 0.f;
SimdScalar margin = marginA + marginB;
m_simplexSolver->reset();
while (true)
{
SimdVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* input.m_transformA.getBasis();
SimdVector3 seperatingAxisInB = m_cachedSeparatingAxis* input.m_transformB.getBasis();
SimdVector3 pInA = m_minkowskiA->LocalGetSupportingVertexWithoutMargin(seperatingAxisInA);
SimdVector3 qInB = m_minkowskiB->LocalGetSupportingVertexWithoutMargin(seperatingAxisInB);
SimdPoint3 pWorld = input.m_transformA(pInA);
SimdPoint3 qWorld = input.m_transformB(qInB);
SimdVector3 w = pWorld - qWorld;
delta = m_cachedSeparatingAxis.dot(w);
// potential exit, they don't overlap
if ((delta > SimdScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared))
{
checkPenetration = false;
break;
}
//exit 0: the new point is already in the simplex, or we didn't come any closer
if (m_simplexSolver->inSimplex(w))
{
checkSimplex = true;
break;
}
// are we getting any closer ?
if (squaredDistance - delta <= squaredDistance * rel_error2)
{
checkSimplex = true;
break;
}
//add current vertex to simplex
m_simplexSolver->addVertex(w, pWorld, qWorld);
//calculate the closest point to the origin (update vector v)
if (!m_simplexSolver->closest(m_cachedSeparatingAxis))
{
checkSimplex = true;
break;
}
SimdScalar previousSquaredDistance = squaredDistance;
squaredDistance = m_cachedSeparatingAxis.length2();
//redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
//are we getting any closer ?
if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
{
m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
checkSimplex = true;
break;
}
bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
if (!check)
{
//do we need this backup_closest here ?
m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
break;
}
}
if (checkSimplex)
{
m_simplexSolver->compute_points(pointOnA, pointOnB);
normalInB = pointOnA-pointOnB;
float lenSqr = m_cachedSeparatingAxis.length2();
//valid normal
if (lenSqr > SIMD_EPSILON)
{
float rlen = 1.f / sqrtf(lenSqr );
normalInB *= rlen; //normalize
SimdScalar s = sqrtf(squaredDistance);
ASSERT(s > SimdScalar(0.0));
pointOnA -= m_cachedSeparatingAxis * (marginA / s);
pointOnB += m_cachedSeparatingAxis * (marginB / s);
distance = ((1.f/rlen) - margin);
isValid = true;
}
}
if (checkPenetration && !isValid)
{
//penetration case
m_minkowskiA->SetMargin(marginA);
m_minkowskiB->SetMargin(marginB);
//if there is no way to handle penetrations, bail out
if (m_penetrationDepthSolver)
{
// Penetration depth case.
isValid = m_penetrationDepthSolver->CalcPenDepth(
*m_simplexSolver,
m_minkowskiA,m_minkowskiB,
input.m_transformA,input.m_transformB,
m_cachedSeparatingAxis, pointOnA, pointOnB);
if (isValid)
{
normalInB = pointOnB-pointOnA;
float lenSqr = normalInB.length2();
if (lenSqr > SIMD_EPSILON)
{
normalInB /= sqrtf(lenSqr);
distance = -(pointOnA-pointOnB).length();
} else
{
isValid = false;
}
}
}
}
}
if (isValid)
{
output.AddContactPoint(
normalInB,
pointOnB,
distance);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef GJK_PAIR_DETECTOR_H
#define GJK_PAIR_DETECTOR_H
#include "DiscreteCollisionDetectorInterface.h"
#include "SimdPoint3.h"
#include "CollisionMargin.h"
class ConvexShape;
#include "SimplexSolverInterface.h"
class ConvexPenetrationDepthSolver;
/// GjkPairDetector uses GJK to implement the DiscreteCollisionDetectorInterface
class GjkPairDetector : public DiscreteCollisionDetectorInterface
{
SimdVector3 m_cachedSeparatingAxis;
ConvexPenetrationDepthSolver* m_penetrationDepthSolver;
SimplexSolverInterface* m_simplexSolver;
ConvexShape* m_minkowskiA;
ConvexShape* m_minkowskiB;
public:
GjkPairDetector(ConvexShape* objectA,ConvexShape* objectB,SimplexSolverInterface* simplexSolver,ConvexPenetrationDepthSolver* penetrationDepthSolver);
virtual ~GjkPairDetector() {};
virtual void GetClosestPoints(const ClosestPointInput& input,Result& output);
void SetMinkowskiA(ConvexShape* minkA)
{
m_minkowskiA = minkA;
}
void SetMinkowskiB(ConvexShape* minkB)
{
m_minkowskiB = minkB;
}
void SetCachedSeperatingAxis(const SimdVector3& seperatingAxis)
{
m_cachedSeparatingAxis = seperatingAxis;
}
};
#endif //GJK_PAIR_DETECTOR_H

View File

@@ -0,0 +1,59 @@
#ifndef MANIFOLD_CONTACT_POINT_H
#define MANIFOLD_CONTACT_POINT_H
#include "SimdVector3.h"
/// ManifoldContactPoint collects and maintains persistent contactpoints.
/// used to improve stability and performance of rigidbody dynamics response.
class ManifoldPoint
{
public:
ManifoldPoint()
{
}
ManifoldPoint( const SimdVector3 &pointA, const SimdVector3 &pointB,
const SimdVector3 &normal,
SimdScalar distance ) :
m_localPointA( pointA ),
m_localPointB( pointB ),
m_normalWorldOnB( normal ),
m_distance1( distance )
,m_appliedImpulse(0.f)
{}
SimdVector3 m_localPointA;
SimdVector3 m_localPointB;
SimdVector3 m_positionWorldOnB;
///m_positionWorldOnA is redundant information, see GetPositionWorldOnA(), but for clarity
SimdVector3 m_positionWorldOnA;
SimdVector3 m_normalWorldOnB;
float m_distance1;
/// total applied impulse during most recent frame
float m_appliedImpulse;
float GetDistance() const
{
return m_distance1;
}
SimdVector3 GetPositionWorldOnA() {
return m_positionWorldOnA;
// return m_positionWorldOnB + m_normalWorldOnB * m_distance1;
}
const SimdVector3& GetPositionWorldOnB()
{
return m_positionWorldOnB;
}
void SetDistance(float dist)
{
m_distance1 = dist;
}
};
#endif //MANIFOLD_CONTACT_POINT_H

View File

@@ -0,0 +1,132 @@
#include "MinkowskiPenetrationDepthSolver.h"
#include "CollisionShapes/MinkowskiSumShape.h"
#include "NarrowPhaseCollision/SubSimplexConvexCast.h"
#include "NarrowPhaseCollision/VoronoiSimplexSolver.h"
#include "NarrowPhaseCollision/GjkPairDetector.h"
struct MyResult : public DiscreteCollisionDetectorInterface::Result
{
SimdVector3 m_normalOnBInWorld;
SimdVector3 m_pointInWorld;
float m_depth;
void AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth)
{
m_normalOnBInWorld = normalOnBInWorld;
m_pointInWorld = pointInWorld;
m_depth = depth;
}
};
bool MinkowskiPenetrationDepthSolver::CalcPenDepth(SimplexSolverInterface& simplexSolver,
ConvexShape* convexA,ConvexShape* convexB,
const SimdTransform& transA,const SimdTransform& transB,
SimdVector3& v, SimdPoint3& pa, SimdPoint3& pb)
{
//just take fixed number of orientation, and sample the penetration depth in that direction
int N = 3;
float minProj = 1e30f;
SimdVector3 minNorm;
SimdVector3 minVertex;
SimdVector3 minA,minB;
for (int i=-N;i<N;i++)
{
for (int j = -N;j<N;j++)
{
for (int k=-N;k<N;k++)
{
if (i | j | k)
{
SimdVector3 norm(i,j,k);
norm.normalize();
{
SimdVector3 seperatingAxisInA = (-norm)* transA.getBasis();
SimdVector3 seperatingAxisInB = norm* transB.getBasis();
SimdVector3 pInA = convexA->LocalGetSupportingVertex(seperatingAxisInA);
SimdVector3 qInB = convexB->LocalGetSupportingVertex(seperatingAxisInB);
SimdPoint3 pWorld = transA(pInA);
SimdPoint3 qWorld = transB(qInB);
SimdVector3 w = qWorld - pWorld;
float delta = norm.dot(w);
//find smallest delta
if (delta < minProj)
{
minProj = delta;
minNorm = norm;
minA = pWorld;
minB = qWorld;
}
}
{
SimdVector3 seperatingAxisInA = (norm)* transA.getBasis();
SimdVector3 seperatingAxisInB = -norm* transB.getBasis();
SimdVector3 pInA = convexA->LocalGetSupportingVertex(seperatingAxisInA);
SimdVector3 qInB = convexB->LocalGetSupportingVertex(seperatingAxisInB);
SimdPoint3 pWorld = transA(pInA);
SimdPoint3 qWorld = transB(qInB);
SimdVector3 w = qWorld - pWorld;
float delta = (-norm).dot(w);
//find smallest delta
if (delta < minProj)
{
minProj = delta ;
minNorm = -norm;
minA = pWorld;
minB = qWorld;
}
}
}
}
}
}
SimdTransform ident;
ident.setIdentity();
GjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0);
v = minNorm * minProj;
GjkPairDetector::ClosestPointInput input;
SimdVector3 newOrg = transA.getOrigin() + v + v;
SimdTransform displacedTrans = transA;
displacedTrans.setOrigin(newOrg);
input.m_transformA = displacedTrans;
input.m_transformB = transB;
input.m_maximumDistanceSquared = 1e30f;
MyResult res;
gjkdet.GetClosestPoints(input,res);
SimdVector3 halfV = v*0.5f;
//approximate pa and pb
pa = res.m_pointInWorld - halfV;
pb = res.m_pointInWorld +halfV;
return true;
}

View File

@@ -0,0 +1,20 @@
#ifndef MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
#define MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
#include "ConvexPenetrationDepthSolver.h"
///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation.
///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points.
class MinkowskiPenetrationDepthSolver : public ConvexPenetrationDepthSolver
{
public:
virtual bool CalcPenDepth( SimplexSolverInterface& simplexSolver,
ConvexShape* convexA,ConvexShape* convexB,
const SimdTransform& transA,const SimdTransform& transB,
SimdVector3& v, SimdPoint3& pa, SimdPoint3& pb);
};
#endif //MINKOWSKI_PENETRATION_DEPTH_SOLVER_H

View File

@@ -0,0 +1,182 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "PersistentManifold.h"
#include "SimdTransform.h"
#include <assert.h>
PersistentManifold::PersistentManifold()
:m_body0(0),
m_body1(0),
m_cachedPoints (0),
m_index1(0)
{
}
void PersistentManifold::ClearManifold()
{
m_cachedPoints = 0;
}
int PersistentManifold::SortCachedPoints(const ManifoldPoint& pt)
{
//calculate 4 possible cases areas, and take biggest area
SimdScalar res0,res1,res2,res3;
{
SimdVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
SimdVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
SimdVector3 cross = a0.cross(b0);
res0 = cross.length2();
}
{
SimdVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
SimdVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
SimdVector3 cross = a1.cross(b1);
res1 = cross.length2();
}
{
SimdVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
SimdVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
SimdVector3 cross = a2.cross(b2);
res2 = cross.length2();
}
{
SimdVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
SimdVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
SimdVector3 cross = a3.cross(b3);
res3 = cross.length2();
}
SimdVector4 maxvec(res0,res1,res2,res3);
int biggestarea = maxvec.closestAxis4();
return biggestarea;
}
int PersistentManifold::GetCacheEntry(const ManifoldPoint& newPoint) const
{
SimdScalar shortestDist = GetManifoldMargin() * GetManifoldMargin();
int size = GetNumContacts();
int nearestPoint = -1;
for( int i = 0; i < size; i++ )
{
const ManifoldPoint &mp = m_pointCache[i];
SimdVector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
const SimdScalar distToManiPoint = diffA.dot(diffA);
if( distToManiPoint < shortestDist )
{
shortestDist = distToManiPoint;
nearestPoint = i;
}
}
return nearestPoint;
}
void PersistentManifold::AddManifoldPoint(const ManifoldPoint& newPoint)
{
assert(ValidContactDistance(newPoint));
int insertIndex = GetNumContacts();
if (insertIndex == MANIFOLD_CACHE_SIZE)
{
//sort cache so best points come first
insertIndex = SortCachedPoints(newPoint);
} else
{
m_cachedPoints++;
}
ReplaceContactPoint(newPoint,insertIndex);
}
void PersistentManifold::RefreshContactPoints(const SimdTransform& trA,const SimdTransform& trB)
{
int i;
/// first refresh worldspace positions and distance
for (i=GetNumContacts()-1;i>=0;i--)
{
ManifoldPoint &manifoldPoint = m_pointCache[i];
manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
}
/// then
SimdScalar distance2d;
SimdVector3 projectedDifference,projectedPoint;
for (i=GetNumContacts()-1;i>=0;i--)
{
ManifoldPoint &manifoldPoint = m_pointCache[i];
//contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
if (!ValidContactDistance(manifoldPoint))
{
RemoveContactPoint(i);
} else
{
//contact also becomes invalid when relative movement orthogonal to normal exceeds margin
projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
distance2d = projectedDifference.dot(projectedDifference);
if (distance2d > GetManifoldMargin()*GetManifoldMargin() )
{
RemoveContactPoint(i);
}
}
}
}
//todo: remove this treshold
float gPenetrationDistanceCheck = -0.05f;
float PersistentManifold::GetCollisionImpulse() const
{
float averageImpulse = 0.f;
if (GetNumContacts() > 0)
{
float totalImpulse = 0.f;
//return the sum of the applied impulses on the box
for (int i=0;i<GetNumContacts();i++)
{
const ManifoldPoint& cp = GetContactPoint(i);
//avoid conflic noice
if ( cp.GetDistance() <gPenetrationDistanceCheck)
return 0.f;
totalImpulse += cp.m_appliedImpulse;
}
averageImpulse = totalImpulse / ((float)GetNumContacts());
}
return averageImpulse;
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef PERSISTENT_MANIFOLD_H
#define PERSISTENT_MANIFOLD_H
#include "SimdVector3.h"
#include "SimdTransform.h"
#include "ManifoldPoint.h"
struct CollisionResult;
#define MANIFOLD_CACHE_SIZE 4
///PersistentManifold maintains contact points, and reduces them to 4
class PersistentManifold
{
ManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
/// this two body pointers can point to the physics rigidbody class.
/// void* will allow any rigidbody class
void* m_body0;
void* m_body1;
int m_cachedPoints;
/// sort cached points so most isolated points come first
int SortCachedPoints(const ManifoldPoint& pt);
public:
int m_index1;
PersistentManifold();
PersistentManifold(void* body0,void* body1)
: m_body0(body0),m_body1(body1),m_cachedPoints(0)
{
}
inline void* GetBody0() { return m_body0;}
inline void* GetBody1() { return m_body1;}
inline const void* GetBody0() const { return m_body0;}
inline const void* GetBody1() const { return m_body1;}
void SetBodies(void* body0,void* body1)
{
m_body0 = body0;
m_body1 = body1;
}
inline int GetNumContacts() const { return m_cachedPoints;}
inline const ManifoldPoint& GetContactPoint(int index) const
{
ASSERT(index < m_cachedPoints);
return m_pointCache[index];
}
inline ManifoldPoint& GetContactPoint(int index)
{
ASSERT(index < m_cachedPoints);
return m_pointCache[index];
}
/// todo: get this margin from the current physics / collision environment
inline float GetManifoldMargin() const
{
return 0.02f;
}
int GetCacheEntry(const ManifoldPoint& newPoint) const;
void AddManifoldPoint( const ManifoldPoint& newPoint);
void RemoveContactPoint (int index)
{
m_pointCache[index] = m_pointCache[GetNumContacts() - 1];
m_cachedPoints--;
}
void ReplaceContactPoint(const ManifoldPoint& newPoint,int insertIndex)
{
assert(ValidContactDistance(newPoint));
m_pointCache[insertIndex] = newPoint;
}
bool ValidContactDistance(const ManifoldPoint& pt) const
{
return pt.m_distance1 < GetManifoldMargin();
}
/// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
void RefreshContactPoints( const SimdTransform& trA,const SimdTransform& trB);
void ClearManifold();
float GetCollisionImpulse() const;
};
#endif //PERSISTENT_MANIFOLD_H

View File

@@ -0,0 +1,36 @@
#ifndef POINT_COLLECTOR_H
#define POINT_COLLECTOR_H
#include "DiscreteCollisionDetectorInterface.h"
struct PointCollector : public DiscreteCollisionDetectorInterface::Result
{
SimdVector3 m_normalOnBInWorld;
SimdVector3 m_pointInWorld;
SimdScalar m_distance;//negative means penetration
bool m_hasResult;
PointCollector ()
: m_hasResult(false),m_distance(1e30f)
{
}
virtual void AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth)
{
if (depth< m_distance)
{
m_hasResult = true;
m_normalOnBInWorld = normalOnBInWorld;
m_pointInWorld = pointInWorld;
//negative means penetration
m_distance = depth;
}
}
};
#endif //POINT_COLLECTOR_H

View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "RaycastCallback.h"
RaycastCallback::RaycastCallback(const SimdVector3& from,const SimdVector3& to)
:
m_from(from),
m_to(to),
m_hitFraction(1.f),
m_hitProxy(0)
{
}
void RaycastCallback::ProcessTriangle(SimdVector3* triangle)
{
int hits_found=0;
const SimdVector3 &vert0=triangle[0];
const SimdVector3 &vert1=triangle[1];
const SimdVector3 &vert2=triangle[2];
SimdVector3 v10; v10 = vert1 - vert0 ;
SimdVector3 v20; v20 = vert2 - vert0 ;
SimdVector3 triangleNormal; triangleNormal = v10.cross( v20 );
const float dist = vert0.dot(triangleNormal);
float dist_a = triangleNormal.dot(m_from) ;
dist_a-= dist;
float dist_b = triangleNormal.dot(m_to);
dist_b -= dist;
if ( dist_a * dist_b >= 0.0f)
{
return ; // same sign
}
const float proj_length=dist_a-dist_b;
const float distance = (dist_a)/(proj_length);
// Now we have the intersection point on the plane, we'll see if it's inside the triangle
// Add an epsilon as a tolerance for the raycast,
// in case the ray hits exacly on the edge of the triangle.
// It must be scaled for the triangle size.
if(distance < m_hitFraction)
{
float edge_tolerance =triangleNormal.length2();
edge_tolerance *= -0.0001f;
SimdVector3 point; point.setInterpolate3( m_from, m_to, distance);
{
SimdVector3 v0p; v0p = vert0 - point;
SimdVector3 v1p; v1p = vert1 - point;
SimdVector3 cp0; cp0 = v0p.cross( v1p );
if ( (float)(cp0.dot(triangleNormal)) >=edge_tolerance)
{
SimdVector3 v2p; v2p = vert2 - point;
SimdVector3 cp1;
cp1 = v1p.cross( v2p);
if ( (float)(cp1.dot(triangleNormal)) >=edge_tolerance)
{
SimdVector3 cp2;
cp2 = v2p.cross(v0p);
if ( (float)(cp2.dot(triangleNormal)) >=edge_tolerance)
{
m_hitFraction = distance;
if ( dist_a > 0 )
{
m_hitNormalWorld = triangleNormal;
}
else
{
m_hitNormalWorld = -triangleNormal;
}
hits_found = 1;
}
}
}
}
}
//return hits_found;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef RAYCAST_TRI_CALLBACK_H
#define RAYCAST_TRI_CALLBACK_H
#include "CollisionShapes/TriangleCallback.h"
struct BroadphaseProxy;
class RaycastCallback: public TriangleCallback
{
public:
//input
SimdVector3 m_from;
SimdVector3 m_to;
//input / output
SimdScalar m_hitFraction;
BroadphaseProxy* m_hitProxy;
//output
SimdVector3 m_hitNormalWorld;
RaycastCallback(const SimdVector3& from,const SimdVector3& to);
virtual void ProcessTriangle(SimdVector3* triangle);
};
#endif //RAYCAST_TRI_CALLBACK_H

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef SIMPLEX_SOLVER_INTERFACE_H
#define SIMPLEX_SOLVER_INTERFACE_H
#include "SimdVector3.h"
#include "SimdPoint3.h"
#define NO_VIRTUAL_INTERFACE
#ifdef NO_VIRTUAL_INTERFACE
#include "VoronoiSimplexSolver.h"
#define SimplexSolverInterface VoronoiSimplexSolver
#else
/// for simplices from 1 to 4 vertices
/// for example Johnson-algorithm or alternative approaches based on
/// voronoi regions or barycentric coordinates
class SimplexSolverInterface
{
public:
virtual ~SimplexSolverInterface() {};
virtual void reset() = 0;
virtual void addVertex(const SimdVector3& w, const SimdPoint3& p, const SimdPoint3& q) = 0;
virtual bool closest(SimdVector3& v) = 0;
virtual SimdScalar maxVertex() = 0;
virtual bool fullSimplex() const = 0;
virtual int getSimplex(SimdPoint3 *pBuf, SimdPoint3 *qBuf, SimdVector3 *yBuf) const = 0;
virtual bool inSimplex(const SimdVector3& w) = 0;
virtual void backup_closest(SimdVector3& v) = 0;
virtual bool emptySimplex() const = 0;
virtual void compute_points(SimdPoint3& p1, SimdPoint3& p2) = 0;
virtual int numVertices() const =0;
};
#endif
#endif //SIMPLEX_SOLVER_INTERFACE_H

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "SubSimplexConvexCast.h"
#include "CollisionShapes/ConvexShape.h"
#include "CollisionShapes/MinkowskiSumShape.h"
#include "NarrowPhaseCollision/SimplexSolverInterface.h"
SubsimplexConvexCast::SubsimplexConvexCast (ConvexShape* convexA,ConvexShape* convexB,SimplexSolverInterface* simplexSolver)
:m_simplexSolver(simplexSolver),
m_convexA(convexA),m_convexB(convexB)
{
}
#define MAX_ITERATIONS 1000
bool SubsimplexConvexCast::calcTimeOfImpact(
const SimdTransform& fromA,
const SimdTransform& toA,
const SimdTransform& fromB,
const SimdTransform& toB,
CastResult& result)
{
MinkowskiSumShape combi(m_convexA,m_convexB);
MinkowskiSumShape* convex = &combi;
SimdTransform rayFromLocalA;
SimdTransform rayToLocalA;
rayFromLocalA = fromA.inverse()* fromB;
rayToLocalA = toA.inverse()* toB;
m_simplexSolver->reset();
convex->SetTransformB(SimdTransform(rayFromLocalA.getBasis()));
float radius = 0.01f;
SimdScalar lambda = 0.f;
SimdVector3 s = rayFromLocalA.getOrigin();
SimdVector3 r = rayToLocalA.getOrigin()-rayFromLocalA.getOrigin();
SimdVector3 x = s;
SimdVector3 v;
SimdVector3 arbitraryPoint = convex->LocalGetSupportingVertex(r);
v = x - arbitraryPoint;
int maxIter = MAX_ITERATIONS;
SimdVector3 n;
n.setValue(0.f,0.f,0.f);
bool hasResult = false;
SimdVector3 c;
float lastLambda = lambda;
float dist2 = v.length2();
float epsilon = 0.0001f;
SimdVector3 w,p;
float VdotR;
while ( (dist2 > epsilon) && maxIter--)
{
p = convex->LocalGetSupportingVertex( v);
w = x - p;
float VdotW = v.dot(w);
if ( VdotW > 0.f)
{
VdotR = v.dot(r);
if (VdotR >= 0.f)
return false;
else
{
lambda = lambda - VdotW / VdotR;
x = s + lambda * r;
m_simplexSolver->reset();
//check next line
w = x-p;
lastLambda = lambda;
n = v;
hasResult = true;
}
}
m_simplexSolver->addVertex( w, x , p);
if (m_simplexSolver->closest(v))
{
dist2 = v.length2();
hasResult = true;
//printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
//printf("DIST2=%f\n",dist2);
//printf("numverts = %i\n",m_simplexSolver->numVertices());
} else
{
dist2 = 0.f;
}
}
int numiter = MAX_ITERATIONS - maxIter;
// printf("number of iterations: %d", numiter);
result.m_fraction = lambda;
result.m_normal = n;
return true;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef SUBSIMPLEX_CONVEX_CAST_H
#define SUBSIMPLEX_CONVEX_CAST_H
#include "ConvexCast.h"
#include "SimplexSolverInterface.h"
class ConvexShape;
/// SubsimplexConvexCast implements Gino van den Bergens' paper
/// GJK based Ray Cast, optimized version
class SubsimplexConvexCast : public ConvexCast
{
SimplexSolverInterface* m_simplexSolver;
ConvexShape* m_convexA;
ConvexShape* m_convexB;
public:
SubsimplexConvexCast (ConvexShape* shapeA,ConvexShape* shapeB,SimplexSolverInterface* simplexSolver);
//virtual ~SubsimplexConvexCast();
virtual bool calcTimeOfImpact(
const SimdTransform& fromA,
const SimdTransform& toA,
const SimdTransform& fromB,
const SimdTransform& toB,
CastResult& result);
};
#endif //SUBSIMPLEX_CONVEX_CAST_H

View File

@@ -0,0 +1,582 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "VoronoiSimplexSolver.h"
#include <assert.h>
#include <stdio.h>
#define VERTA 0
#define VERTB 1
#define VERTC 2
#define VERTD 3
#define CATCH_DEGENERATE_TETRAHEDRON 1
void VoronoiSimplexSolver::removeVertex(int index)
{
assert(m_numVertices>0);
m_numVertices--;
m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
}
void VoronoiSimplexSolver::ReduceVertices (const UsageBitfield& usedVerts)
{
if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
removeVertex(3);
if ((numVertices() >= 3) && (!usedVerts.usedVertexC))
removeVertex(2);
if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
removeVertex(1);
if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
removeVertex(0);
}
//clear the simplex, remove all the vertices
void VoronoiSimplexSolver::reset()
{
m_cachedValidClosest = false;
m_numVertices = 0;
m_needsUpdate = true;
m_lastW = SimdVector3(1e30f,1e30f,1e30f);
m_cachedBC.Reset();
}
//add a vertex
void VoronoiSimplexSolver::addVertex(const SimdVector3& w, const SimdPoint3& p, const SimdPoint3& q)
{
m_lastW = w;
m_needsUpdate = true;
m_simplexVectorW[m_numVertices] = w;
m_simplexPointsP[m_numVertices] = p;
m_simplexPointsQ[m_numVertices] = q;
m_numVertices++;
}
bool VoronoiSimplexSolver::UpdateClosestVectorAndPoints()
{
if (m_needsUpdate)
{
m_cachedBC.Reset();
m_needsUpdate = false;
switch (numVertices())
{
case 0:
m_cachedValidClosest = false;
break;
case 1:
{
m_cachedP1 = m_simplexPointsP[0];
m_cachedP2 = m_simplexPointsQ[0];
m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0]
m_cachedBC.Reset();
m_cachedBC.SetBarycentricCoordinates(1.f,0.f,0.f,0.f);
m_cachedValidClosest = m_cachedBC.IsValid();
break;
};
case 2:
{
//closest point origin from line segment
const SimdVector3& from = m_simplexVectorW[0];
const SimdVector3& to = m_simplexVectorW[1];
SimdVector3 nearest;
SimdVector3 p (0.f,0.f,0.f);
SimdVector3 diff = p - from;
SimdVector3 v = to - from;
float t = v.dot(diff);
if (t > 0) {
float dotVV = v.dot(v);
if (t < dotVV) {
t /= dotVV;
diff -= t*v;
m_cachedBC.m_usedVertices.usedVertexA = true;
m_cachedBC.m_usedVertices.usedVertexB = true;
} else {
t = 1;
diff -= v;
//reduce to 1 point
m_cachedBC.m_usedVertices.usedVertexB = true;
}
} else
{
t = 0;
//reduce to 1 point
m_cachedBC.m_usedVertices.usedVertexA = true;
}
m_cachedBC.SetBarycentricCoordinates(1-t,t);
nearest = from + t*v;
m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
m_cachedV = m_cachedP1 - m_cachedP2;
ReduceVertices(m_cachedBC.m_usedVertices);
m_cachedValidClosest = m_cachedBC.IsValid();
break;
}
case 3:
{
//closest point origin from triangle
SimdVector3 p (0.f,0.f,0.f);
const SimdVector3& a = m_simplexVectorW[0];
const SimdVector3& b = m_simplexVectorW[1];
const SimdVector3& c = m_simplexVectorW[2];
ClosestPtPointTriangle(p,a,b,c,m_cachedBC);
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
m_cachedV = m_cachedP1-m_cachedP2;
ReduceVertices (m_cachedBC.m_usedVertices);
m_cachedValidClosest = m_cachedBC.IsValid();
break;
}
case 4:
{
SimdVector3 p (0.f,0.f,0.f);
const SimdVector3& a = m_simplexVectorW[0];
const SimdVector3& b = m_simplexVectorW[1];
const SimdVector3& c = m_simplexVectorW[2];
const SimdVector3& d = m_simplexVectorW[3];
bool hasSeperation = ClosestPtPointTetrahedron(p,a,b,c,d,m_cachedBC);
if (hasSeperation)
{
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
m_cachedV = m_cachedP1-m_cachedP2;
ReduceVertices (m_cachedBC.m_usedVertices);
} else
{
// printf("sub distance got penetration\n");
if (m_cachedBC.m_degenerate)
{
m_cachedValidClosest = false;
} else
{
m_cachedValidClosest = true;
//degenerate case == false, penetration = true + zero
m_cachedV.setValue(0.f,0.f,0.f);
}
break;
}
m_cachedValidClosest = m_cachedBC.IsValid();
//closest point origin from tetrahedron
break;
}
default:
{
m_cachedValidClosest = false;
}
};
}
return m_cachedValidClosest;
}
//return/calculate the closest vertex
bool VoronoiSimplexSolver::closest(SimdVector3& v)
{
bool succes = UpdateClosestVectorAndPoints();
v = m_cachedV;
return succes;
}
SimdScalar VoronoiSimplexSolver::maxVertex()
{
int i, numverts = numVertices();
SimdScalar maxV = 0.f;
for (i=0;i<numverts;i++)
{
SimdScalar curLen2 = m_simplexVectorW[i].length2();
if (maxV < curLen2)
maxV = curLen2;
}
return maxV;
}
//return the current simplex
int VoronoiSimplexSolver::getSimplex(SimdPoint3 *pBuf, SimdPoint3 *qBuf, SimdVector3 *yBuf) const
{
int i;
for (i=0;i<numVertices();i++)
{
yBuf[i] = m_simplexVectorW[i];
pBuf[i] = m_simplexPointsP[i];
qBuf[i] = m_simplexPointsQ[i];
}
return numVertices();
}
bool VoronoiSimplexSolver::inSimplex(const SimdVector3& w)
{
bool found = false;
int i, numverts = numVertices();
SimdScalar maxV = 0.f;
//w is in the current (reduced) simplex
for (i=0;i<numverts;i++)
{
if (m_simplexVectorW[i] == w)
found = true;
}
//check in case lastW is already removed
if (w == m_lastW)
return true;
return found;
}
void VoronoiSimplexSolver::backup_closest(SimdVector3& v)
{
v = m_cachedV;
}
bool VoronoiSimplexSolver::emptySimplex() const
{
return (numVertices() == 0);
}
void VoronoiSimplexSolver::compute_points(SimdPoint3& p1, SimdPoint3& p2)
{
UpdateClosestVectorAndPoints();
p1 = m_cachedP1;
p2 = m_cachedP2;
}
bool VoronoiSimplexSolver::ClosestPtPointTriangle(const SimdPoint3& p, const SimdPoint3& a, const SimdPoint3& b, const SimdPoint3& c,SubSimplexClosestResult& result)
{
result.m_usedVertices.reset();
// Check if P in vertex region outside A
SimdVector3 ab = b - a;
SimdVector3 ac = c - a;
SimdVector3 ap = p - a;
float d1 = ab.dot(ap);
float d2 = ac.dot(ap);
if (d1 <= 0.0f && d2 <= 0.0f)
{
result.m_closestPointOnSimplex = a;
result.m_usedVertices.usedVertexA = true;
result.SetBarycentricCoordinates(1,0,0);
return true;// a; // barycentric coordinates (1,0,0)
}
// Check if P in vertex region outside B
SimdVector3 bp = p - b;
float d3 = ab.dot(bp);
float d4 = ac.dot(bp);
if (d3 >= 0.0f && d4 <= d3)
{
result.m_closestPointOnSimplex = b;
result.m_usedVertices.usedVertexB = true;
result.SetBarycentricCoordinates(0,1,0);
return true; // b; // barycentric coordinates (0,1,0)
}
// Check if P in edge region of AB, if so return projection of P onto AB
float vc = d1*d4 - d3*d2;
if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
float v = d1 / (d1 - d3);
result.m_closestPointOnSimplex = a + v * ab;
result.m_usedVertices.usedVertexA = true;
result.m_usedVertices.usedVertexB = true;
result.SetBarycentricCoordinates(1-v,v,0);
return true;
//return a + v * ab; // barycentric coordinates (1-v,v,0)
}
// Check if P in vertex region outside C
SimdVector3 cp = p - c;
float d5 = ab.dot(cp);
float d6 = ac.dot(cp);
if (d6 >= 0.0f && d5 <= d6)
{
result.m_closestPointOnSimplex = c;
result.m_usedVertices.usedVertexC = true;
result.SetBarycentricCoordinates(0,0,1);
return true;//c; // barycentric coordinates (0,0,1)
}
// Check if P in edge region of AC, if so return projection of P onto AC
float vb = d5*d2 - d1*d6;
if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
float w = d2 / (d2 - d6);
result.m_closestPointOnSimplex = a + w * ac;
result.m_usedVertices.usedVertexA = true;
result.m_usedVertices.usedVertexC = true;
result.SetBarycentricCoordinates(1-w,0,w);
return true;
//return a + w * ac; // barycentric coordinates (1-w,0,w)
}
// Check if P in edge region of BC, if so return projection of P onto BC
float va = d3*d6 - d5*d4;
if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
float w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
result.m_closestPointOnSimplex = b + w * (c - b);
result.m_usedVertices.usedVertexB = true;
result.m_usedVertices.usedVertexC = true;
result.SetBarycentricCoordinates(0,1-w,w);
return true;
// return b + w * (c - b); // barycentric coordinates (0,1-w,w)
}
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
float denom = 1.0f / (va + vb + vc);
float v = vb * denom;
float w = vc * denom;
result.m_closestPointOnSimplex = a + ab * v + ac * w;
result.m_usedVertices.usedVertexA = true;
result.m_usedVertices.usedVertexB = true;
result.m_usedVertices.usedVertexC = true;
result.SetBarycentricCoordinates(1-v-w,v,w);
return true;
// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = 1.0f - v - w
}
/// Test if point p and d lie on opposite sides of plane through abc
int VoronoiSimplexSolver::PointOutsideOfPlane(const SimdPoint3& p, const SimdPoint3& a, const SimdPoint3& b, const SimdPoint3& c, const SimdPoint3& d)
{
SimdVector3 normal = (b-a).cross(c-a);
float signp = (p - a).dot(normal); // [AP AB AC]
float signd = (d - a).dot( normal); // [AD AB AC]
#ifdef CATCH_DEGENERATE_TETRAHEDRON
if (signd * signd < (1e-4f * 1e-4f))
{
// printf("affine dependent/degenerate\n");//
return -1;
}
#endif
// Points on opposite sides if expression signs are opposite
return signp * signd < 0.f;
}
bool VoronoiSimplexSolver::ClosestPtPointTetrahedron(const SimdPoint3& p, const SimdPoint3& a, const SimdPoint3& b, const SimdPoint3& c, const SimdPoint3& d, SubSimplexClosestResult& finalResult)
{
SubSimplexClosestResult tempResult;
// Start out assuming point inside all halfspaces, so closest to itself
finalResult.m_closestPointOnSimplex = p;
finalResult.m_usedVertices.reset();
finalResult.m_usedVertices.usedVertexA = true;
finalResult.m_usedVertices.usedVertexB = true;
finalResult.m_usedVertices.usedVertexC = true;
finalResult.m_usedVertices.usedVertexD = true;
int pointOutsideABC = PointOutsideOfPlane(p, a, b, c, d);
int pointOutsideACD = PointOutsideOfPlane(p, a, c, d, b);
int pointOutsideADB = PointOutsideOfPlane(p, a, d, b, c);
int pointOutsideBDC = PointOutsideOfPlane(p, b, d, c, a);
if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
{
finalResult.m_degenerate = true;
return false;
}
if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
{
return false;
}
float bestSqDist = FLT_MAX;
// If point outside face abc then compute closest point on abc
if (pointOutsideABC)
{
ClosestPtPointTriangle(p, a, b, c,tempResult);
SimdPoint3 q = tempResult.m_closestPointOnSimplex;
float sqDist = (q - p).dot( q - p);
// Update best closest point if (squared) distance is less than current best
if (sqDist < bestSqDist) {
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
//convert result bitmask!
finalResult.m_usedVertices.reset();
finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
finalResult.SetBarycentricCoordinates(
tempResult.m_barycentricCoords[VERTA],
tempResult.m_barycentricCoords[VERTB],
tempResult.m_barycentricCoords[VERTC],
0
);
}
}
// Repeat test for face acd
if (pointOutsideACD)
{
ClosestPtPointTriangle(p, a, c, d,tempResult);
SimdPoint3 q = tempResult.m_closestPointOnSimplex;
//convert result bitmask!
float sqDist = (q - p).dot( q - p);
if (sqDist < bestSqDist)
{
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
finalResult.m_usedVertices.reset();
finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
finalResult.SetBarycentricCoordinates(
tempResult.m_barycentricCoords[VERTA],
0,
tempResult.m_barycentricCoords[VERTB],
tempResult.m_barycentricCoords[VERTC]
);
}
}
// Repeat test for face adb
if (pointOutsideADB)
{
ClosestPtPointTriangle(p, a, d, b,tempResult);
SimdPoint3 q = tempResult.m_closestPointOnSimplex;
//convert result bitmask!
float sqDist = (q - p).dot( q - p);
if (sqDist < bestSqDist)
{
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
finalResult.m_usedVertices.reset();
finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
finalResult.SetBarycentricCoordinates(
tempResult.m_barycentricCoords[VERTA],
tempResult.m_barycentricCoords[VERTC],
0,
tempResult.m_barycentricCoords[VERTB]
);
}
}
// Repeat test for face bdc
if (pointOutsideBDC)
{
ClosestPtPointTriangle(p, b, d, c,tempResult);
SimdPoint3 q = tempResult.m_closestPointOnSimplex;
//convert result bitmask!
float sqDist = (q - p).dot( q - p);
if (sqDist < bestSqDist)
{
bestSqDist = sqDist;
finalResult.m_closestPointOnSimplex = q;
finalResult.m_usedVertices.reset();
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
finalResult.SetBarycentricCoordinates(
0,
tempResult.m_barycentricCoords[VERTA],
tempResult.m_barycentricCoords[VERTC],
tempResult.m_barycentricCoords[VERTB]
);
}
}
//help! we ended up full !
if (finalResult.m_usedVertices.usedVertexA &&
finalResult.m_usedVertices.usedVertexB &&
finalResult.m_usedVertices.usedVertexC &&
finalResult.m_usedVertices.usedVertexD)
{
return true;
}
return true;
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef VoronoiSimplexSolver_H
#define VoronoiSimplexSolver_H
#include "SimplexSolverInterface.h"
#define VORONOI_SIMPLEX_MAX_VERTS 5
struct UsageBitfield{
UsageBitfield()
{
reset();
}
void reset()
{
usedVertexA = false;
usedVertexB = false;
usedVertexC = false;
usedVertexD = false;
}
unsigned short usedVertexA : 1;
unsigned short usedVertexB : 1;
unsigned short usedVertexC : 1;
unsigned short usedVertexD : 1;
unsigned short unused1 : 1;
unsigned short unused2 : 1;
unsigned short unused3 : 1;
unsigned short unused4 : 1;
};
struct SubSimplexClosestResult
{
SimdPoint3 m_closestPointOnSimplex;
//MASK for m_usedVertices
//stores the simplex vertex-usage, using the MASK,
// if m_usedVertices & MASK then the related vertex is used
UsageBitfield m_usedVertices;
float m_barycentricCoords[4];
bool m_degenerate;
void Reset()
{
m_degenerate = false;
SetBarycentricCoordinates();
m_usedVertices.reset();
}
bool IsValid()
{
bool valid = (m_barycentricCoords[0] >= 0.f) &&
(m_barycentricCoords[1] >= 0.f) &&
(m_barycentricCoords[2] >= 0.f) &&
(m_barycentricCoords[3] >= 0.f);
return valid;
}
void SetBarycentricCoordinates(float a=0.f,float b=0.f,float c=0.f,float d=0.f)
{
m_barycentricCoords[0] = a;
m_barycentricCoords[1] = b;
m_barycentricCoords[2] = c;
m_barycentricCoords[3] = d;
}
};
/// VoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
/// Can be used with GJK, as an alternative to Johnson distance algorithm.
#ifdef NO_VIRTUAL_INTERFACE
class VoronoiSimplexSolver
#else
class VoronoiSimplexSolver : public SimplexSolverInterface
#endif
{
public:
int m_numVertices;
SimdVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
SimdPoint3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
SimdPoint3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
SimdPoint3 m_cachedP1;
SimdPoint3 m_cachedP2;
SimdVector3 m_cachedV;
SimdVector3 m_lastW;
bool m_cachedValidClosest;
SubSimplexClosestResult m_cachedBC;
bool m_needsUpdate;
void removeVertex(int index);
void ReduceVertices (const UsageBitfield& usedVerts);
bool UpdateClosestVectorAndPoints();
bool ClosestPtPointTetrahedron(const SimdPoint3& p, const SimdPoint3& a, const SimdPoint3& b, const SimdPoint3& c, const SimdPoint3& d, SubSimplexClosestResult& finalResult);
int PointOutsideOfPlane(const SimdPoint3& p, const SimdPoint3& a, const SimdPoint3& b, const SimdPoint3& c, const SimdPoint3& d);
bool ClosestPtPointTriangle(const SimdPoint3& p, const SimdPoint3& a, const SimdPoint3& b, const SimdPoint3& c,SubSimplexClosestResult& result);
public:
void reset();
void addVertex(const SimdVector3& w, const SimdPoint3& p, const SimdPoint3& q);
bool closest(SimdVector3& v);
SimdScalar maxVertex();
bool fullSimplex() const
{
return (m_numVertices == 4);
}
int getSimplex(SimdPoint3 *pBuf, SimdPoint3 *qBuf, SimdVector3 *yBuf) const;
bool inSimplex(const SimdVector3& w);
void backup_closest(SimdVector3& v) ;
bool emptySimplex() const ;
void compute_points(SimdPoint3& p1, SimdPoint3& p2) ;
int numVertices() const
{
return m_numVertices;
}
};
#endif //VoronoiSimplexSolver

View File

@@ -0,0 +1,236 @@
# Microsoft Developer Studio Project File - Name="BulletDynamics" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=BulletDynamics - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "BulletDynamics.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "BulletDynamics.mak" CFG="BulletDynamics - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "BulletDynamics - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "BulletDynamics - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "BulletDynamics - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "BulletDynamics___Win32_Release"
# PROP BASE Intermediate_Dir "BulletDynamics___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "BulletDynamics___Win32_Release"
# PROP Intermediate_Dir "BulletDynamics___Win32_Release"
# PROP Target_Dir ""
LINK32=link.exe -lib
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "../LinearMath" /I "../Bullet" /I "../BulletDynamics" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "BulletDynamics - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "BulletDynamics___Win32_Debug"
# PROP BASE Intermediate_Dir "BulletDynamics___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "BulletDynamics___Win32_Debug"
# PROP Intermediate_Dir "BulletDynamics___Win32_Debug"
# PROP Target_Dir ""
LINK32=link.exe -lib
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../LinearMath" /I "../Bullet" /I "../BulletDynamics" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "BulletDynamics - Win32 Release"
# Name "BulletDynamics - Win32 Debug"
# Begin Group "ConstraintSolver"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\ConstraintSolver\ConstraintSolver.h
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\ContactConstraint.cpp
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\ContactConstraint.h
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\ContactSolverInfo.h
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\JacobianEntry.h
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\OdeConstraintSolver.cpp
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\OdeConstraintSolver.h
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\Point2PointConstraint.cpp
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\Point2PointConstraint.h
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\SimpleConstraintSolver.cpp
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\SimpleConstraintSolver.h
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\Solve2LinearConstraint.cpp
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\Solve2LinearConstraint.h
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\SorLcp.cpp
# End Source File
# Begin Source File
SOURCE=.\ConstraintSolver\SorLcp.h
# End Source File
# End Group
# Begin Group "CollisionDispatch"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\CollisionDispatch\ConvexConcaveCollisionAlgorithm.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\ConvexConcaveCollisionAlgorithm.h
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\ConvexConvexAlgorithm.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\ConvexConvexAlgorithm.h
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\EmptyCollisionAlgorithm.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\EmptyCollisionAlgorithm.h
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\ManifoldResult.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\ManifoldResult.h
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\ToiContactDispatcher.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\ToiContactDispatcher.h
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\UnionFind.cpp
# End Source File
# Begin Source File
SOURCE=.\CollisionDispatch\UnionFind.h
# End Source File
# End Group
# Begin Group "Dynamics"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\Dynamics\BU_Joint.cpp
# End Source File
# Begin Source File
SOURCE=.\Dynamics\BU_Joint.h
# End Source File
# Begin Source File
SOURCE=.\Dynamics\ContactJoint.cpp
# End Source File
# Begin Source File
SOURCE=.\Dynamics\ContactJoint.h
# End Source File
# Begin Source File
SOURCE=.\Dynamics\MassProps.h
# End Source File
# Begin Source File
SOURCE=.\Dynamics\RigidBody.cpp
# End Source File
# Begin Source File
SOURCE=.\Dynamics\RigidBody.h
# End Source File
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,231 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="Bullet3Dynamics"
ProjectGUID="{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\LinearMath;..\Bullet;..\BulletDynamics"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/BulletDynamics.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\LinearMath;..\Bullet;..\BulletDynamics"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="..\..\..\..\build\msvc_7\libs\extern\BulletDynamics.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="ECHO Copying header files
IF NOT EXIST ..\..\..\..\build\msvc_7\extern\bullet\include MKDIR ..\..\..\..\build\msvc_7\extern\bullet\include
IF NOT EXIST ..\..\..\..\build\msvc_7\extern\bullet\include\CollisionDispatch MKDIR ..\..\..\..\build\msvc_7\extern\bullet\include\CollisionDispatch
IF NOT EXIST ..\..\..\..\build\msvc_7\extern\bullet\include\ConstraintSolver MKDIR ..\..\..\..\build\msvc_7\extern\bullet\include\ConstraintSolver
IF NOT EXIST ..\..\..\..\build\msvc_7\extern\bullet\include\Dynamics MKDIR ..\..\..\..\build\msvc_7\extern\bullet\include\Dynamics
XCOPY /Y ..\LinearMath\*.h ..\..\..\..\build\msvc_7\extern\bullet\include
XCOPY /Y ..\BulletDynamics\CollisionDispatch\*.h ..\..\..\..\build\msvc_7\extern\bullet\include\CollisionDispatch
XCOPY /Y ..\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\build\msvc_7\extern\bullet\include\ConstraintSolver
XCOPY /Y ..\BulletDynamics\Dynamics\*.h ..\..\..\..\build\msvc_7\extern\bullet\include\Dynamics
ECHO Done
"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="ConstraintSolver"
Filter="">
<File
RelativePath=".\ConstraintSolver\ConstraintSolver.h">
</File>
<File
RelativePath=".\ConstraintSolver\ContactConstraint.cpp">
</File>
<File
RelativePath=".\ConstraintSolver\ContactConstraint.h">
</File>
<File
RelativePath=".\ConstraintSolver\ContactSolverInfo.h">
</File>
<File
RelativePath=".\ConstraintSolver\JacobianEntry.h">
</File>
<File
RelativePath=".\ConstraintSolver\OdeConstraintSolver.cpp">
</File>
<File
RelativePath=".\ConstraintSolver\OdeConstraintSolver.h">
</File>
<File
RelativePath=".\ConstraintSolver\Point2PointConstraint.cpp">
</File>
<File
RelativePath=".\ConstraintSolver\Point2PointConstraint.h">
</File>
<File
RelativePath=".\ConstraintSolver\SimpleConstraintSolver.cpp">
</File>
<File
RelativePath=".\ConstraintSolver\SimpleConstraintSolver.h">
</File>
<File
RelativePath=".\ConstraintSolver\Solve2LinearConstraint.cpp">
</File>
<File
RelativePath=".\ConstraintSolver\Solve2LinearConstraint.h">
</File>
<File
RelativePath=".\ConstraintSolver\SorLcp.cpp">
</File>
<File
RelativePath=".\ConstraintSolver\SorLcp.h">
</File>
</Filter>
<Filter
Name="CollisionDispatch"
Filter="">
<File
RelativePath=".\CollisionDispatch\ConvexConcaveCollisionAlgorithm.cpp">
</File>
<File
RelativePath=".\CollisionDispatch\ConvexConcaveCollisionAlgorithm.h">
</File>
<File
RelativePath=".\CollisionDispatch\ConvexConvexAlgorithm.cpp">
</File>
<File
RelativePath=".\CollisionDispatch\ConvexConvexAlgorithm.h">
</File>
<File
RelativePath=".\CollisionDispatch\EmptyCollisionAlgorithm.cpp">
</File>
<File
RelativePath=".\CollisionDispatch\EmptyCollisionAlgorithm.h">
</File>
<File
RelativePath=".\CollisionDispatch\ManifoldResult.cpp">
</File>
<File
RelativePath=".\CollisionDispatch\ManifoldResult.h">
</File>
<File
RelativePath=".\CollisionDispatch\ToiContactDispatcher.cpp">
</File>
<File
RelativePath=".\CollisionDispatch\ToiContactDispatcher.h">
</File>
<File
RelativePath=".\CollisionDispatch\UnionFind.cpp">
</File>
<File
RelativePath=".\CollisionDispatch\UnionFind.h">
</File>
</Filter>
<Filter
Name="Dynamics"
Filter="">
<File
RelativePath=".\Dynamics\BU_Joint.cpp">
</File>
<File
RelativePath=".\Dynamics\BU_Joint.h">
</File>
<File
RelativePath=".\Dynamics\ContactJoint.cpp">
</File>
<File
RelativePath=".\Dynamics\ContactJoint.h">
</File>
<File
RelativePath=".\Dynamics\MassProps.h">
</File>
<File
RelativePath=".\Dynamics\RigidBody.cpp">
</File>
<File
RelativePath=".\Dynamics\RigidBody.h">
</File>
</Filter>
<File
RelativePath=".\ReadMe.txt">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,301 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="Bullet3Dynamics"
ProjectGUID="{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="4"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\LinearMath;..\Bullet;..\BulletDynamics"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/BulletDynamics.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="4"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\LinearMath;..\Bullet;..\BulletDynamics"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/BulletDynamics.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="ConstraintSolver"
>
<File
RelativePath=".\ConstraintSolver\ConstraintSolver.h"
>
</File>
<File
RelativePath=".\ConstraintSolver\ContactConstraint.cpp"
>
</File>
<File
RelativePath=".\ConstraintSolver\ContactConstraint.h"
>
</File>
<File
RelativePath=".\ConstraintSolver\ContactSolverInfo.h"
>
</File>
<File
RelativePath=".\ConstraintSolver\JacobianEntry.h"
>
</File>
<File
RelativePath=".\ConstraintSolver\OdeConstraintSolver.cpp"
>
</File>
<File
RelativePath=".\ConstraintSolver\OdeConstraintSolver.h"
>
</File>
<File
RelativePath=".\ConstraintSolver\Point2PointConstraint.cpp"
>
</File>
<File
RelativePath=".\ConstraintSolver\Point2PointConstraint.h"
>
</File>
<File
RelativePath=".\ConstraintSolver\SimpleConstraintSolver.cpp"
>
</File>
<File
RelativePath=".\ConstraintSolver\SimpleConstraintSolver.h"
>
</File>
<File
RelativePath=".\ConstraintSolver\Solve2LinearConstraint.cpp"
>
</File>
<File
RelativePath=".\ConstraintSolver\Solve2LinearConstraint.h"
>
</File>
<File
RelativePath=".\ConstraintSolver\SorLcp.cpp"
>
</File>
<File
RelativePath=".\ConstraintSolver\SorLcp.h"
>
</File>
</Filter>
<Filter
Name="CollisionDispatch"
>
<File
RelativePath=".\CollisionDispatch\ConvexConcaveCollisionAlgorithm.cpp"
>
</File>
<File
RelativePath=".\CollisionDispatch\ConvexConcaveCollisionAlgorithm.h"
>
</File>
<File
RelativePath=".\CollisionDispatch\ConvexConvexAlgorithm.cpp"
>
</File>
<File
RelativePath=".\CollisionDispatch\ConvexConvexAlgorithm.h"
>
</File>
<File
RelativePath=".\CollisionDispatch\EmptyCollisionAlgorithm.cpp"
>
</File>
<File
RelativePath=".\CollisionDispatch\EmptyCollisionAlgorithm.h"
>
</File>
<File
RelativePath=".\CollisionDispatch\ManifoldResult.cpp"
>
</File>
<File
RelativePath=".\CollisionDispatch\ManifoldResult.h"
>
</File>
<File
RelativePath=".\CollisionDispatch\ToiContactDispatcher.cpp"
>
</File>
<File
RelativePath=".\CollisionDispatch\ToiContactDispatcher.h"
>
</File>
<File
RelativePath=".\CollisionDispatch\UnionFind.cpp"
>
</File>
<File
RelativePath=".\CollisionDispatch\UnionFind.h"
>
</File>
</Filter>
<Filter
Name="Dynamics"
>
<File
RelativePath=".\Dynamics\BU_Joint.cpp"
>
</File>
<File
RelativePath=".\Dynamics\BU_Joint.h"
>
</File>
<File
RelativePath=".\Dynamics\ContactJoint.cpp"
>
</File>
<File
RelativePath=".\Dynamics\ContactJoint.h"
>
</File>
<File
RelativePath=".\Dynamics\MassProps.h"
>
</File>
<File
RelativePath=".\Dynamics\RigidBody.cpp"
>
</File>
<File
RelativePath=".\Dynamics\RigidBody.h"
>
</File>
</Filter>
<File
RelativePath=".\ReadMe.txt"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,212 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "ConvexConcaveCollisionAlgorithm.h"
#include "Dynamics/RigidBody.h"
#include "CollisionShapes/MultiSphereShape.h"
#include "ConstraintSolver/ContactConstraint.h"
#include "CollisionShapes/BoxShape.h"
#include "ConvexConvexAlgorithm.h"
#include "BroadphaseCollision/BroadphaseProxy.h"
#include "CollisionShapes/TriangleShape.h"
#include "ConstraintSolver/ConstraintSolver.h"
#include "ConstraintSolver/ContactSolverInfo.h"
#include "CollisionDispatch/ManifoldResult.h"
#include "NarrowphaseCollision/RaycastCallback.h"
#include "CollisionShapes/TriangleMeshShape.h"
ConvexConcaveCollisionAlgorithm::ConvexConcaveCollisionAlgorithm( const CollisionAlgorithmConstructionInfo& ci,BroadphaseProxy* proxy0,BroadphaseProxy* proxy1)
: CollisionAlgorithm(ci),m_convex(*proxy0),m_concave(*proxy1),
m_boxTriangleCallback(ci.m_dispatcher,proxy0,proxy1)
{
}
ConvexConcaveCollisionAlgorithm::~ConvexConcaveCollisionAlgorithm()
{
}
BoxTriangleCallback::BoxTriangleCallback(Dispatcher* dispatcher,BroadphaseProxy* proxy0,BroadphaseProxy* proxy1):
m_boxProxy(proxy0),m_triangleProxy(*proxy1),m_dispatcher(dispatcher),
m_timeStep(0.f),
m_stepCount(-1)
{
m_triangleProxy.SetClientObjectType(TRIANGLE_SHAPE_PROXYTYPE);
//
// create the manifold from the dispatcher 'manifold pool'
//
m_manifoldPtr = m_dispatcher->GetNewManifold(proxy0->m_clientObject,proxy1->m_clientObject);
ClearCache();
}
BoxTriangleCallback::~BoxTriangleCallback()
{
ClearCache();
m_dispatcher->ReleaseManifold( m_manifoldPtr );
}
void BoxTriangleCallback::ClearCache()
{
m_manifoldPtr->ClearManifold();
};
void BoxTriangleCallback::ProcessTriangle(SimdVector3* triangle)
{
RigidBody* triangleBody = (RigidBody*)m_triangleProxy.m_clientObject;
//aabb filter is already applied!
CollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher = m_dispatcher;
ConvexShape* tmp = static_cast<ConvexShape*>(triangleBody->GetCollisionShape());
if (m_boxProxy->IsConvexShape())
{
TriangleShape tm(triangle[0],triangle[1],triangle[2]);
RigidBody* triangleBody = (RigidBody* )m_triangleProxy.m_clientObject;
triangleBody->SetCollisionShape(&tm);
ConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_boxProxy,&m_triangleProxy);
triangleBody->SetCollisionShape(&tm);
cvxcvxalgo.ProcessCollision(m_boxProxy,&m_triangleProxy,m_timeStep,m_stepCount,m_useContinuous);
}
triangleBody->SetCollisionShape(tmp);
}
void BoxTriangleCallback::SetTimeStepAndCounters(float timeStep,int stepCount,bool useContinuous)
{
m_timeStep = timeStep;
m_stepCount = stepCount;
m_useContinuous = useContinuous;
//recalc aabbs
RigidBody* boxBody = (RigidBody* )m_boxProxy->m_clientObject;
RigidBody* triBody = (RigidBody* )m_triangleProxy.m_clientObject;
SimdTransform boxInTriangleSpace;
boxInTriangleSpace = triBody->getCenterOfMassTransform().inverse() * boxBody->getCenterOfMassTransform();
boxBody->GetCollisionShape()->GetAabb(boxInTriangleSpace,m_aabbMin,m_aabbMax);
float extraMargin = CONVEX_DISTANCE_MARGIN+0.1f;
SimdVector3 extra(extraMargin,extraMargin,extraMargin);
m_aabbMax += extra;
m_aabbMin -= extra;
}
void ConvexConcaveCollisionAlgorithm::ClearCache()
{
m_boxTriangleCallback.ClearCache();
}
void ConvexConcaveCollisionAlgorithm::ProcessCollision (BroadphaseProxy* ,BroadphaseProxy* ,float timeStep,int stepCount,bool useContinuous)
{
if (m_concave.GetClientObjectType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
RigidBody* convexbody = (RigidBody* )m_convex.m_clientObject;
RigidBody* concavebody = (RigidBody* )m_concave.m_clientObject;
TriangleMeshShape* triangleMesh = (TriangleMeshShape*) concavebody->GetCollisionShape();
if (m_convex.IsConvexShape())
{
m_boxTriangleCallback.SetTimeStepAndCounters(timeStep,stepCount, useContinuous);
#ifdef USE_BOX_TRIANGLE
m_boxTriangleCallback.m_manifoldPtr->ClearManifold();
#endif
m_boxTriangleCallback.m_manifoldPtr->SetBodies(convexbody,concavebody);
triangleMesh->ProcessAllTriangles( &m_boxTriangleCallback,m_boxTriangleCallback.GetAabbMin(),m_boxTriangleCallback.GetAabbMax());
}
}
}
float ConvexConcaveCollisionAlgorithm::CalculateTimeOfImpact(BroadphaseProxy* ,BroadphaseProxy* ,float timeStep,int stepCount)
{
//quick approximation using raycast, todo: use proper continuou collision detection
RigidBody* convexbody = (RigidBody* )m_convex.m_clientObject;
const SimdVector3& from = convexbody->getCenterOfMassPosition();
SimdVector3 radVec(0,0,0);
float minradius = 0.05f;
float lenSqr = convexbody->getLinearVelocity().length2();
if (lenSqr > SIMD_EPSILON)
{
radVec = convexbody->getLinearVelocity();
radVec.normalize();
radVec *= minradius;
}
SimdVector3 to = from + radVec + convexbody->getLinearVelocity() * timeStep*1.01f;
//only do if the motion exceeds the 'radius'
RaycastCallback raycastCallback(from,to);
raycastCallback.m_hitFraction = convexbody->m_hitFraction;
SimdVector3 aabbMin (-1e30f,-1e30f,-1e30f);
SimdVector3 aabbMax (SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
if (m_concave.GetClientObjectType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
RigidBody* concavebody = (RigidBody* )m_concave.m_clientObject;
TriangleMeshShape* triangleMesh = (TriangleMeshShape*) concavebody->GetCollisionShape();
if (triangleMesh)
{
triangleMesh->ProcessAllTriangles(&raycastCallback,aabbMin,aabbMax);
}
}
if (raycastCallback.m_hitFraction < convexbody->m_hitFraction)
{
convexbody->m_hitFraction = raycastCallback.m_hitFraction;
return raycastCallback.m_hitFraction;
}
return 1.f;
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H
#define CONVEX_CONCAVE_COLLISION_ALGORITHM_H
#include "BroadphaseCollision/CollisionAlgorithm.h"
#include "BroadphaseCollision/CollisionDispatcher.h"
#include "BroadphaseCollision/BroadphaseInterface.h"
#include "CollisionShapes/TriangleCallback.h"
#include "NarrowPhaseCollision/PersistentManifold.h"
class Dispatcher;
#include "BroadphaseCollision/BroadphaseProxy.h"
class BoxTriangleCallback : public TriangleCallback
{
BroadphaseProxy* m_boxProxy;
BroadphaseProxy m_triangleProxy;
SimdVector3 m_aabbMin;
SimdVector3 m_aabbMax ;
Dispatcher* m_dispatcher;
float m_timeStep;
int m_stepCount;
bool m_useContinuous;
public:
PersistentManifold* m_manifoldPtr;
BoxTriangleCallback(Dispatcher* dispatcher,BroadphaseProxy* proxy0,BroadphaseProxy* proxy1);
void SetTimeStepAndCounters(float timeStep,int stepCount, bool useContinuous);
virtual ~BoxTriangleCallback();
virtual void ProcessTriangle(SimdVector3* triangle);
void ClearCache();
inline const SimdVector3& GetAabbMin() const
{
return m_aabbMin;
}
inline const SimdVector3& GetAabbMax() const
{
return m_aabbMax;
}
};
/// ConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes.
class ConvexConcaveCollisionAlgorithm : public CollisionAlgorithm
{
BroadphaseProxy m_convex;
BroadphaseProxy m_concave;
BoxTriangleCallback m_boxTriangleCallback;
public:
ConvexConcaveCollisionAlgorithm( const CollisionAlgorithmConstructionInfo& ci,BroadphaseProxy* proxy0,BroadphaseProxy* proxy1);
virtual ~ConvexConcaveCollisionAlgorithm();
virtual void ProcessCollision (BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep,int stepCount, bool useContinuous);
float CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep,int stepCount);
void ClearCache();
};
#endif //CONVEX_CONCAVE_COLLISION_ALGORITHM_H

View File

@@ -0,0 +1,250 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "ConvexConvexAlgorithm.h"
#include <stdio.h>
#include "NarrowPhaseCollision/DiscreteCollisionDetectorInterface.h"
#include "BroadphaseCollision/BroadphaseInterface.h"
#include "Dynamics/RigidBody.h"
#include "CollisionShapes/ConvexShape.h"
#include "NarrowPhaseCollision/GjkPairDetector.h"
#include "BroadphaseCollision/BroadphaseProxy.h"
#include "BroadphaseCollision/CollisionDispatcher.h"
#include "CollisionShapes/BoxShape.h"
#include "CollisionDispatch/ManifoldResult.h"
#include "NarrowPhaseCollision/ConvexPenetrationDepthSolver.h"
#include "NarrowPhaseCollision/ContinuousConvexCollision.h"
#include "NarrowPhaseCollision/SubsimplexConvexCast.h"
#include "NarrowPhaseCollision/GjkConvexCast.h"
#include "CollisionShapes/MinkowskiSumShape.h"
#include "NarrowPhaseCollision/VoronoiSimplexSolver.h"
#include "CollisionShapes/SphereShape.h"
#ifdef WIN32
void DrawRasterizerLine(const float* from,const float* to,int color);
#endif
//#define PROCESS_SINGLE_CONTACT
#ifdef WIN32
bool gForceBoxBox = false;//false;//true;
#else
bool gForceBoxBox = false;//false;//true;
#endif
bool gBoxBoxUseGjk = true;//true;//false;
bool gDisableConvexCollision = false;
ConvexConvexAlgorithm::ConvexConvexAlgorithm(PersistentManifold* mf,const CollisionAlgorithmConstructionInfo& ci,BroadphaseProxy* proxy0,BroadphaseProxy* proxy1)
: CollisionAlgorithm(ci),
m_gjkPairDetector(0,0,&m_simplexSolver,&m_penetrationDepthSolver),
m_box0(*proxy0),
m_box1(*proxy1),
m_collisionImpulse(0.f),
m_ownManifold (false),
m_manifoldPtr(mf),
m_lowLevelOfDetail(false)
{
RigidBody* body0 = (RigidBody*)m_box0.m_clientObject;
RigidBody* body1 = (RigidBody*)m_box1.m_clientObject;
if ((body0->getInvMass() != 0.f) ||
(body1->getInvMass() != 0.f))
{
if (!m_manifoldPtr)
{
m_manifoldPtr = m_dispatcher->GetNewManifold(proxy0->m_clientObject,proxy1->m_clientObject);
m_ownManifold = true;
}
}
}
ConvexConvexAlgorithm::~ConvexConvexAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->ReleaseManifold(m_manifoldPtr);
}
}
void ConvexConvexAlgorithm ::SetLowLevelOfDetail(bool useLowLevel)
{
m_lowLevelOfDetail = useLowLevel;
}
float ConvexConvexAlgorithm::GetCollisionImpulse() const
{
if (m_manifoldPtr)
return m_manifoldPtr->GetCollisionImpulse();
return 0.f;
}
class FlippedContactResult : public DiscreteCollisionDetectorInterface::Result
{
DiscreteCollisionDetectorInterface::Result* m_org;
public:
FlippedContactResult(DiscreteCollisionDetectorInterface::Result* org)
: m_org(org)
{
}
virtual void AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth)
{
SimdVector3 flippedNormal = -normalOnBInWorld;
m_org->AddContactPoint(flippedNormal,pointInWorld,depth);
}
};
bool extra = false;
float gFriction = 0.5f;
//
// box-box collision algorithm, for simplicity also applies resolution-impulse
//
void ConvexConvexAlgorithm ::ProcessCollision (BroadphaseProxy* ,BroadphaseProxy* ,float timeStep,int stepCount, bool useContinuous)
{
// printf("ConvexConvexAlgorithm::ProcessCollision\n");
m_collisionImpulse = 0.f;
RigidBody* body0 = (RigidBody*)m_box0.m_clientObject;
RigidBody* body1 = (RigidBody*)m_box1.m_clientObject;
if (!m_manifoldPtr)
return;
if ((body0->getInvMass() == 0.f) &&
(body1->getInvMass() == 0.f))
{
return;
}
ManifoldResult output(body0,body1,m_manifoldPtr);
ConvexShape* min0 = static_cast<ConvexShape*>(body0->GetCollisionShape());
ConvexShape* min1 = static_cast<ConvexShape*>(body1->GetCollisionShape());
GjkPairDetector::ClosestPointInput input;
SphereShape sphere(0.2f);
MinkowskiSumShape expanded0(min0,&sphere);
MinkowskiSumShape expanded1(min1,&sphere);
if (useContinuous)
{
m_gjkPairDetector.SetMinkowskiA(&expanded0);
m_gjkPairDetector.SetMinkowskiB(&expanded1);
input.m_maximumDistanceSquared = expanded0.GetMargin()+expanded1.GetMargin();
input.m_maximumDistanceSquared *= input.m_maximumDistanceSquared;
}
else
{
m_gjkPairDetector.SetMinkowskiA(min0);
m_gjkPairDetector.SetMinkowskiB(min1);
input.m_maximumDistanceSquared = min0->GetMargin() + min1->GetMargin() + m_manifoldPtr->GetManifoldMargin();
input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
}
input.m_transformA = body0->getCenterOfMassTransform();
input.m_transformB = body1->getCenterOfMassTransform();
m_gjkPairDetector.GetClosestPoints(input,output);
}
bool disableCcd = false;
float ConvexConvexAlgorithm::CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep,int stepCount)
{
m_collisionImpulse = 0.f;
RigidBody* body0 = (RigidBody*)m_box0.m_clientObject;
RigidBody* body1 = (RigidBody*)m_box1.m_clientObject;
if (!m_manifoldPtr)
return 1.f;
if ((body0->getInvMass() == 0.f) &&
(body1->getInvMass() == 0.f))
{
return 1.f;
}
ConvexShape* min0 = static_cast<ConvexShape*>(body0->GetCollisionShape());
ConvexShape* min1 = static_cast<ConvexShape*>(body1->GetCollisionShape());
GjkPairDetector::ClosestPointInput input;
input.m_transformA = body0->getCenterOfMassTransform();
input.m_transformB = body1->getCenterOfMassTransform();
SimdTransform predictA,predictB;
body0->predictIntegratedTransform(timeStep,predictA);
body1->predictIntegratedTransform(timeStep,predictB);
ConvexCast::CastResult result;
VoronoiSimplexSolver voronoiSimplex;
//SubsimplexConvexCast ccd(&voronoiSimplex);
//GjkConvexCast ccd(&voronoiSimplex);
ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,&m_penetrationDepthSolver);
if (disableCcd)
return 1.f;
if (ccd.calcTimeOfImpact(input.m_transformA,predictA,input.m_transformB,predictB,result))
{
//store result.m_fraction in both bodies
int i;
i=0;
// if (result.m_fraction< 0.1f)
// result.m_fraction = 0.1f;
if (body0->m_hitFraction > result.m_fraction)
body0->m_hitFraction = result.m_fraction;
if (body1->m_hitFraction > result.m_fraction)
body1->m_hitFraction = result.m_fraction;
return result.m_fraction;
}
return 1.f;
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONVEX_CONVEX_ALGORITHM_H
#define CONVEX_CONVEX_ALGORITHM_H
#include "BroadphaseCollision/CollisionAlgorithm.h"
#include "NarrowPhaseCollision/GjkPairDetector.h"
#include "NarrowPhaseCollision/PersistentManifold.h"
#include "BroadphaseCollision/BroadphaseProxy.h"
#include "NarrowPhaseCollision/VoronoiSimplexSolver.h"
#include "NarrowPhaseCollision/MinkowskiPenetrationDepthSolver.h"
class ConvexPenetrationDepthSolver;
///ConvexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations.
class ConvexConvexAlgorithm : public CollisionAlgorithm
{
//hardcoded penetration and simplex solver, its easy to make this flexible later
MinkowskiPenetrationDepthSolver m_penetrationDepthSolver;
VoronoiSimplexSolver m_simplexSolver;
GjkPairDetector m_gjkPairDetector;
public:
BroadphaseProxy m_box0;
BroadphaseProxy m_box1;
float m_collisionImpulse;
bool m_ownManifold;
PersistentManifold* m_manifoldPtr;
bool m_lowLevelOfDetail;
public:
ConvexConvexAlgorithm(PersistentManifold* mf,const CollisionAlgorithmConstructionInfo& ci,BroadphaseProxy* proxy0,BroadphaseProxy* proxy1);
virtual ~ConvexConvexAlgorithm();
virtual void ProcessCollision (BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep,int stepCount, bool useContinuous);
virtual float CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep,int stepCount);
void SetLowLevelOfDetail(bool useLowLevel);
float GetCollisionImpulse() const;
const PersistentManifold* GetManifold()
{
return m_manifoldPtr;
}
};
#endif //CONVEX_CONVEX_ALGORITHM_H

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "EmptyCollisionAlgorithm.h"
EmptyAlgorithm::EmptyAlgorithm(const CollisionAlgorithmConstructionInfo& ci)
: CollisionAlgorithm(ci)
{
}
void EmptyAlgorithm::ProcessCollision (BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep, int stepCount,bool useContinuous)
{
}
float EmptyAlgorithm::CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep,int stepCount)
{
return 1.f;
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef EMPTY_ALGORITH
#define EMPTY_ALGORITH
#include "BroadphaseCollision/CollisionAlgorithm.h"
#define ATTRIBUTE_ALIGNED(a)
///EmptyAlgorithm is a stub for unsupported collision pairs.
///The dispatcher can dispatch a persistent EmptyAlgorithm to avoid a search every frame.
class EmptyAlgorithm : public CollisionAlgorithm
{
public:
EmptyAlgorithm(const CollisionAlgorithmConstructionInfo& ci);
virtual void ProcessCollision (BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep, int stepCount, bool useContinuous);
virtual float CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,float timeStep,int stepCount);
} ATTRIBUTE_ALIGNED(16);
#endif //EMPTY_ALGORITH

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "ManifoldResult.h"
#include "NarrowPhaseCollision/PersistentManifold.h"
#include "Dynamics/RigidBody.h"
ManifoldResult::ManifoldResult(RigidBody* body0,RigidBody* body1,PersistentManifold* manifoldPtr)
:m_manifoldPtr(manifoldPtr),
m_body0(body0),
m_body1(body1)
{
}
void ManifoldResult::AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth)
{
if (depth > m_manifoldPtr->GetManifoldMargin())
return;
SimdTransform transAInv = m_body0->getCenterOfMassTransform().inverse();
SimdTransform transBInv= m_body1->getCenterOfMassTransform().inverse();
SimdVector3 pointA = pointInWorld + normalOnBInWorld * depth;
SimdVector3 localA = transAInv(pointA );
SimdVector3 localB = transBInv(pointInWorld);
ManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
int insertIndex = m_manifoldPtr->GetCacheEntry(newPt);
if (insertIndex >= 0)
{
m_manifoldPtr->ReplaceContactPoint(newPt,insertIndex);
} else
{
m_manifoldPtr->AddManifoldPoint(newPt);
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef MANIFOLD_RESULT_H
#define MANIFOLD_RESULT_H
#include "NarrowPhaseCollision/DiscreteCollisionDetectorInterface.h"
class RigidBody;
class PersistentManifold;
class ManifoldResult : public DiscreteCollisionDetectorInterface::Result
{
PersistentManifold* m_manifoldPtr;
RigidBody* m_body0;
RigidBody* m_body1;
public:
ManifoldResult(RigidBody* body0,RigidBody* body1,PersistentManifold* manifoldPtr);
virtual void AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth);
};
#endif //MANIFOLD_RESULT_H

View File

@@ -0,0 +1,221 @@
#include "ToiContactDispatcher.h"
#include "ConstraintSolver/ConstraintSolver.h"
#include "Dynamics/RigidBody.h"
#include "BroadphaseCollision/CollisionAlgorithm.h"
#include "ConstraintSolver/ContactSolverInfo.h"
#include "CollisionDispatch/ConvexConvexAlgorithm.h"
#include "CollisionDispatch/EmptyCollisionAlgorithm.h"
#include "CollisionDispatch/ConvexConcaveCollisionAlgorithm.h"
#define MAX_RIGIDBODIES 128
void ToiContactDispatcher::FindUnions()
{
if (m_useIslands)
{
for (int i=0;i<GetNumManifolds();i++)
{
const PersistentManifold* manifold = this->GetManifoldByIndexInternal(i);
//static objects (invmass 0.f) don't merge !
if ((((RigidBody*)manifold->GetBody0()) && (((RigidBody*)manifold->GetBody0())->mergesSimulationIslands())) &&
(((RigidBody*)manifold->GetBody1()) && (((RigidBody*)manifold->GetBody1())->mergesSimulationIslands())))
{
m_unionFind.unite(((RigidBody*)manifold->GetBody0())->m_islandTag1,
((RigidBody*)manifold->GetBody1())->m_islandTag1);
}
}
}
}
ToiContactDispatcher::ToiContactDispatcher (ConstraintSolver* solver):
m_useIslands(true),
m_unionFind(MAX_RIGIDBODIES),
m_solver(solver),
m_count(0)
{
int i;
for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
{
for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
{
m_doubleDispatch[i][j] = 0;
}
}
};
PersistentManifold* ToiContactDispatcher::GetNewManifold(void* b0,void* b1)
{
RigidBody* body0 = (RigidBody*)b0;
RigidBody* body1 = (RigidBody*)b1;
PersistentManifold* manifold = new PersistentManifold (body0,body1);
m_manifoldsPtr.push_back(manifold);
return manifold;
}
#include <algorithm>
void ToiContactDispatcher::ReleaseManifold(PersistentManifold* manifold)
{
manifold->ClearManifold();
std::vector<PersistentManifold*>::iterator i =
std::find(m_manifoldsPtr.begin(), m_manifoldsPtr.end(), manifold);
if (!(i == m_manifoldsPtr.end()))
{
std::swap(*i, m_manifoldsPtr.back());
m_manifoldsPtr.pop_back();
}
}
//
// todo: this is random access, it can be walked 'cache friendly'!
//
void ToiContactDispatcher::SolveConstraints(float timeStep, int numIterations,int numRigidBodies)
{
int i;
int numManifolds;
for (int islandId=0;islandId<numRigidBodies;islandId++)
{
numManifolds = 0;
PersistentManifold* manifolds[MAX_MANIFOLDS];
//int numSleeping = 0;
bool allSleeping = true;
for (i=0;i<GetNumManifolds();i++)
{
PersistentManifold* manifold = this->GetManifoldByIndexInternal(i);
if ((((RigidBody*)manifold->GetBody0()) && ((RigidBody*)manifold->GetBody0())->m_islandTag1 == (islandId)) ||
(((RigidBody*)manifold->GetBody1()) && ((RigidBody*)manifold->GetBody1())->m_islandTag1 == (islandId)))
{
if ((((RigidBody*)manifold->GetBody0()) && ((RigidBody*)manifold->GetBody0())->GetActivationState()== ACTIVE_TAG) ||
(((RigidBody*)manifold->GetBody1()) && ((RigidBody*)manifold->GetBody1())->GetActivationState() == ACTIVE_TAG))
{
allSleeping = false;
}
manifolds[numManifolds] = manifold;
numManifolds++;
}
}
if (allSleeping)
{
//tag all as 'ISLAND_SLEEPING'
for (i=0;i<numManifolds;i++)
{
PersistentManifold* manifold = manifolds[i];
if (((RigidBody*)manifold->GetBody0()))
{
((RigidBody*)manifold->GetBody0())->SetActivationState( ISLAND_SLEEPING );
}
if (((RigidBody*)manifold->GetBody1()))
{
((RigidBody*)manifold->GetBody1())->SetActivationState( ISLAND_SLEEPING);
}
}
} else
{
//tag all as 'ISLAND_SLEEPING'
for (i=0;i<numManifolds;i++)
{
PersistentManifold* manifold = manifolds[i];
if (((RigidBody*)manifold->GetBody0()))
{
if ( ((RigidBody*)manifold->GetBody0())->GetActivationState() == ISLAND_SLEEPING)
{
((RigidBody*)manifold->GetBody0())->SetActivationState( WANTS_DEACTIVATION );//ACTIVE_TAG;
}
}
if (((RigidBody*)manifold->GetBody1()))
{
if ( ((RigidBody*)manifold->GetBody1())->GetActivationState() == ISLAND_SLEEPING)
{
((RigidBody*)manifold->GetBody1())->SetActivationState(WANTS_DEACTIVATION);//ACTIVE_TAG;
}
}
}
///This island solving can all be scheduled in parallel
ContactSolverInfo info;
info.m_damping = 0.9f;
info.m_friction = 0.9f;
info.m_numIterations = numIterations;
info.m_timeStep = timeStep;
info.m_tau = 0.4f;
info.m_restitution = 0.1f;//m_restitution;
/*
int numManifolds = 0;
for (i=0;i<m_firstFreeManifold;i++)
{
PersistentManifold* manifold = &m_manifolds[m_freeManifolds[i]];
//ASSERT(((RigidBody*)manifold->GetBody0()));
//ASSERT(((RigidBody*)manifold->GetBody1()));
manifolds[i] = manifold;
numManifolds++;
}
*/
m_solver->SolveGroup( manifolds, numManifolds,info );
}
}
}
CollisionAlgorithm* ToiContactDispatcher::InternalFindAlgorithm(BroadphaseProxy& proxy0,BroadphaseProxy& proxy1)
{
m_count++;
CollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher = this;
if (proxy0.IsConvexShape() && proxy1.IsConvexShape() )
{
return new ConvexConvexAlgorithm(0,ci,&proxy0,&proxy1);
}
if (proxy0.IsConvexShape() && proxy1.IsConcaveShape())
{
return new ConvexConcaveCollisionAlgorithm(ci,&proxy0,&proxy1);
}
if (proxy1.IsConvexShape() && proxy0.IsConcaveShape())
{
return new ConvexConcaveCollisionAlgorithm(ci,&proxy1,&proxy0);
}
//failed to find an algorithm
return new EmptyAlgorithm(ci);
}

View File

@@ -0,0 +1,105 @@
#ifndef TOI_CONTACT_DISPATCHER_H
#define TOI_CONTACT_DISPATCHER_H
#include "BroadphaseCollision/CollisionDispatcher.h"
#include "NarrowPhaseCollision/PersistentManifold.h"
#include "CollisionDispatch/UnionFind.h"
#include "BroadphaseCollision/BroadphaseProxy.h"
class ConstraintSolver;
//island management
#define ACTIVE_TAG 1
#define ISLAND_SLEEPING 2
#define WANTS_DEACTIVATION 3
#define MAX_MANIFOLDS 512
struct CollisionAlgorithmCreateFunc
{
bool m_swapped;
CollisionAlgorithmCreateFunc()
:m_swapped(false)
{
}
virtual CollisionAlgorithm* CreateCollisionAlgorithm(BroadphaseProxy& proxy0,BroadphaseProxy& proxy1)
{
return 0;
}
};
#include <vector>
///ToiContactDispatcher (Time of Impact) is the main collision dispatcher.
///Basic implementation supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
///Time of Impact, Closest Points and Penetration Depth.
class ToiContactDispatcher : public Dispatcher
{
bool m_useIslands;
std::vector<PersistentManifold*> m_manifoldsPtr;
// PersistentManifold m_manifolds[MAX_MANIFOLDS];
// int m_freeManifolds[MAX_MANIFOLDS];
UnionFind m_unionFind;
ConstraintSolver* m_solver;
CollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
public:
UnionFind& GetUnionFind() { return m_unionFind;}
// int m_firstFreeManifold;
// const PersistentManifold* GetManifoldByIndexInternal(int index)
// {
// return &m_manifolds[index];
// }
int GetNumManifolds() { return m_manifoldsPtr.size();}
PersistentManifold* GetManifoldByIndexInternal(int index)
{
return m_manifoldsPtr[index];
}
void InitUnionFind()
{
if (m_useIslands)
m_unionFind.reset();
}
void FindUnions();
int m_count;
ToiContactDispatcher (ConstraintSolver* solver);
virtual PersistentManifold* GetNewManifold(void* b0,void* b1);
virtual void ReleaseManifold(PersistentManifold* manifold);
//
// todo: this is random access, it can be walked 'cache friendly'!
//
virtual void SolveConstraints(float timeStep, int numIterations,int numRigidBodies);
CollisionAlgorithm* FindAlgorithm(BroadphaseProxy& proxy0,BroadphaseProxy& proxy1)
{
CollisionAlgorithm* algo = InternalFindAlgorithm(proxy0,proxy1);
return algo;
}
CollisionAlgorithm* InternalFindAlgorithm(BroadphaseProxy& proxy0,BroadphaseProxy& proxy1);
virtual int GetUniqueId() { return RIGIDBODY_DISPATCHER;}
};
#endif //TOI_CONTACT_DISPATCHER_H

View File

@@ -0,0 +1,54 @@
#include "UnionFind.h"
#include <assert.h>
int UnionFind::find(int x)
{
assert(x < m_N);
assert(x >= 0);
while (x != id[x])
{
x = id[x];
assert(x < m_N);
assert(x >= 0);
}
return x;
}
UnionFind::UnionFind(int N)
:m_N(N)
{
id = new int[N]; sz = new int[N];
reset();
}
void UnionFind::reset()
{
for (int i = 0; i < m_N; i++)
{
id[i] = i; sz[i] = 1;
}
}
int UnionFind ::find(int p, int q)
{
return (find(p) == find(q));
}
void UnionFind ::unite(int p, int q)
{
int i = find(p), j = find(q);
if (i == j)
return;
if (sz[i] < sz[j])
{
id[i] = j; sz[j] += sz[i];
}
else
{
id[j] = i; sz[i] += sz[j];
}
}

View File

@@ -0,0 +1,21 @@
#ifndef UNION_FIND_H
#define UNION_FIND_H
///UnionFind calculates connected subsets
class UnionFind
{
private:
int *id, *sz;
int m_N;
public:
int find(int x);
UnionFind(int N);
void reset();
int find(int p, int q);
void unite(int p, int q);
};
#endif //UNION_FIND_H

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONSTRAINT_SOLVER_H
#define CONSTRAINT_SOLVER_H
class PersistentManifold;
class RigidBody;
struct ContactSolverInfo;
struct BroadphaseProxy;
/// ConstraintSolver provides solver interface
class ConstraintSolver
{
public:
virtual ~ConstraintSolver() {}
virtual float SolveGroup(PersistentManifold** manifold,int numManifolds,const ContactSolverInfo& info) = 0;
};
#endif //CONSTRAINT_SOLVER_H

View File

@@ -0,0 +1,324 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "ContactConstraint.h"
#include "Dynamics/RigidBody.h"
#include "SimdVector3.h"
#include "JacobianEntry.h"
#include "ContactSolverInfo.h"
#include "GEN_minmax.h"
#define ASSERT2 assert
static SimdScalar ContactThreshold = -10.0f;
float useGlobalSettingContacts = false;//true;
SimdScalar contactDamping = 0.9f;
SimdScalar contactTau = .2f;//0.02f;//*0.02f;
SimdScalar restitutionCurve(SimdScalar rel_vel, SimdScalar restitution)
{
return restitution;
// return restitution * GEN_min(1.0f, rel_vel / ContactThreshold);
}
void applyFrictionInContactPointOld(RigidBody& body1, const SimdVector3& pos1,
RigidBody& body2, const SimdVector3& pos2,
const SimdVector3& normal,float normalImpulse,
const ContactSolverInfo& solverInfo)
{
if (normalImpulse>0.f)
{
SimdVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
SimdVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
SimdVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
SimdVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
SimdVector3 vel = vel1 - vel2;
SimdScalar rel_vel = normal.dot(vel);
#define PER_CONTACT_FRICTION
#ifdef PER_CONTACT_FRICTION
SimdVector3 lat_vel = vel - normal * rel_vel;
SimdScalar lat_rel_vel = lat_vel.length();
if (lat_rel_vel > SIMD_EPSILON)
{
lat_vel /= lat_rel_vel;
SimdVector3 temp1 = body1.getInvInertiaTensorWorld() * rel_pos1.cross(lat_vel);
SimdVector3 temp2 = body2.getInvInertiaTensorWorld() * rel_pos2.cross(lat_vel);
SimdScalar frictionMaxImpulse = lat_rel_vel /
(body1.getInvMass() + body2.getInvMass() + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2)));
SimdScalar frictionImpulse = (normalImpulse) * solverInfo.m_friction;
GEN_set_min(frictionImpulse,frictionMaxImpulse );
body1.applyImpulse(lat_vel * -frictionImpulse, rel_pos1);
body2.applyImpulse(lat_vel * frictionImpulse, rel_pos2);
}
#endif
}
}
//bilateral constraint between two dynamic objects
void resolveSingleBilateral(RigidBody& body1, const SimdVector3& pos1,
RigidBody& body2, const SimdVector3& pos2,
SimdScalar depth, const SimdVector3& normal,SimdScalar& impulse ,float timeStep)
{
float normalLenSqr = normal.length2();
ASSERT2(fabs(normalLenSqr) < 1.1f);
if (normalLenSqr > 1.1f)
{
impulse = 0.f;
return;
}
SimdVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
SimdVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
//this jacobian entry could be re-used for all iterations
SimdVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
SimdVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
SimdVector3 vel = vel1 - vel2;
SimdScalar rel_vel;
/*
JacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(),
body2.getCenterOfMassTransform().getBasis().transpose(),
rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(),
body2.getInvInertiaDiagLocal(),body2.getInvMass());
SimdScalar jacDiagAB = jac.getDiagonal();
SimdScalar jacDiagABInv = 1.f / jacDiagAB;
SimdScalar rel_vel = jac.getRelativeVelocity(
body1.getLinearVelocity(),
body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(),
body2.getLinearVelocity(),
body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity());
float a;
a=jacDiagABInv;
*/
rel_vel = normal.dot(vel);
/*int color = 255+255*256;
DrawRasterizerLine(pos1,pos1+normal,color);
*/
SimdScalar massTerm = 1.f / (body1.getInvMass() + body2.getInvMass());
float contactDamping = 0.9f;
impulse = - contactDamping * rel_vel * massTerm;//jacDiagABInv;
//SimdScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
//impulse = velocityImpulse;
}
//velocity + friction
//response between two dynamic objects with friction
float resolveSingleCollision(RigidBody& body1, const SimdVector3& pos1,
RigidBody& body2, const SimdVector3& pos2,
SimdScalar depth, const SimdVector3& normal,
const ContactSolverInfo& solverInfo
)
{
float normalLenSqr = normal.length2();
ASSERT2(fabs(normalLenSqr) < 1.1f);
if (normalLenSqr > 1.1f)
return 0.f;
SimdVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
SimdVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
//this jacobian entry could be re-used for all iterations
SimdVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
SimdVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
SimdVector3 vel = vel1 - vel2;
SimdScalar rel_vel;
rel_vel = normal.dot(vel);
// if (rel_vel< 0.f)//-SIMD_EPSILON)
// {
SimdScalar rest = restitutionCurve(rel_vel, solverInfo.m_restitution);
SimdScalar timeCorrection = 1.f;///timeStep;
float damping = solverInfo.m_damping ;
float tau = solverInfo.m_tau;
if (useGlobalSettingContacts)
{
damping = contactDamping;
tau = contactTau;
}
if (depth < 0.f)
return 0.f;//bdepth = 0.f;
SimdScalar penetrationImpulse = (depth*tau*timeCorrection);// * massTerm;//jacDiagABInv
SimdScalar velocityImpulse = -(1.0f + rest) * damping * rel_vel;
SimdScalar impulse = penetrationImpulse + velocityImpulse;
SimdVector3 temp1 = body1.getInvInertiaTensorWorld() * rel_pos1.cross(normal);
SimdVector3 temp2 = body2.getInvInertiaTensorWorld() * rel_pos2.cross(normal);
impulse /=
(body1.getInvMass() + body2.getInvMass() + normal.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2)));
if (impulse > 0.f)
{
body1.applyImpulse(normal*(impulse), rel_pos1);
body2.applyImpulse(-normal*(impulse), rel_pos2);
} else
{
impulse = 0.f;
}
return impulse;//velocityImpulse;//impulse;
}
//velocity + friction
//response between two dynamic objects with friction
float resolveSingleCollisionWithFriction(
RigidBody& body1,
const SimdVector3& pos1,
RigidBody& body2,
const SimdVector3& pos2,
SimdScalar depth,
const SimdVector3& normal,
const ContactSolverInfo& solverInfo
)
{
float normalLenSqr = normal.length2();
ASSERT2(fabs(normalLenSqr) < 1.1f);
if (normalLenSqr > 1.1f)
return 0.f;
SimdVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
SimdVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
//this jacobian entry could be re-used for all iterations
JacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(),
body2.getCenterOfMassTransform().getBasis().transpose(),
rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(),
body2.getInvInertiaDiagLocal(),body2.getInvMass());
SimdScalar jacDiagAB = jac.getDiagonal();
SimdScalar jacDiagABInv = 1.f / jacDiagAB;
SimdVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
SimdVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
SimdVector3 vel = vel1 - vel2;
SimdScalar rel_vel;
/* rel_vel = jac.getRelativeVelocity(
body1.getLinearVelocity(),
body1.getTransform().getBasis().transpose() * body1.getAngularVelocity(),
body2.getLinearVelocity(),
body2.getTransform().getBasis().transpose() * body2.getAngularVelocity());
*/
rel_vel = normal.dot(vel);
// if (rel_vel< 0.f)//-SIMD_EPSILON)
// {
SimdScalar rest = restitutionCurve(rel_vel, solverInfo.m_restitution);
// SimdScalar massTerm = 1.f / (body1.getInvMass() + body2.getInvMass());
SimdScalar timeCorrection = 0.5f / solverInfo.m_timeStep ;
float damping = solverInfo.m_damping ;
float tau = solverInfo.m_tau;
if (useGlobalSettingContacts)
{
damping = contactDamping;
tau = contactTau;
}
SimdScalar penetrationImpulse = (depth* tau *timeCorrection) * jacDiagABInv;
if (penetrationImpulse < 0.f)
penetrationImpulse = 0.f;
SimdScalar velocityImpulse = -(1.0f + rest) * damping * rel_vel * jacDiagABInv;
SimdScalar friction_impulse = 0.f;
if (velocityImpulse <= 0.f)
velocityImpulse = 0.f;
// SimdScalar impulse = penetrationImpulse + velocityImpulse;
//if (impulse > 0.f)
{
// SimdVector3 impulse_vector = normal * impulse;
body1.applyImpulse(normal*(velocityImpulse+penetrationImpulse), rel_pos1);
body2.applyImpulse(-normal*(velocityImpulse+penetrationImpulse), rel_pos2);
//friction
{
SimdVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
SimdVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
SimdVector3 vel = vel1 - vel2;
rel_vel = normal.dot(vel);
#define PER_CONTACT_FRICTION
#ifdef PER_CONTACT_FRICTION
SimdVector3 lat_vel = vel - normal * rel_vel;
SimdScalar lat_rel_vel = lat_vel.length();
if (lat_rel_vel > SIMD_EPSILON)
{
lat_vel /= lat_rel_vel;
SimdVector3 temp1 = body1.getInvInertiaTensorWorld() * rel_pos1.cross(lat_vel);
SimdVector3 temp2 = body2.getInvInertiaTensorWorld() * rel_pos2.cross(lat_vel);
friction_impulse = lat_rel_vel /
(body1.getInvMass() + body2.getInvMass() + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2)));
SimdScalar normal_impulse = (penetrationImpulse+
velocityImpulse) * solverInfo.m_friction;
GEN_set_min(friction_impulse, normal_impulse);
body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1);
body2.applyImpulse(lat_vel * friction_impulse, rel_pos2);
}
#endif
}
}
return velocityImpulse + friction_impulse;
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONTACT_CONSTRAINT_H
#define CONTACT_CONSTRAINT_H
//todo: make into a proper class working with the iterative constraint solver
class RigidBody;
#include "SimdVector3.h"
#include "SimdScalar.h"
struct ContactSolverInfo;
///bilateral constraint between two dynamic objects
void resolveSingleBilateral(RigidBody& body1, const SimdVector3& pos1,
RigidBody& body2, const SimdVector3& pos2,
SimdScalar depth, const SimdVector3& normal,SimdScalar& impulse ,float timeStep);
//contact constraint resolution:
//calculate and apply impulse to satisfy non-penetration and non-negative relative velocity constraint
float resolveSingleCollision(RigidBody& body1, const SimdVector3& pos1,
RigidBody& body2, const SimdVector3& pos2,
SimdScalar depth, const SimdVector3& normal,
const ContactSolverInfo& info);
/// apply friction force to simulate friction in a contact point related to the normal impulse
void applyFrictionInContactPointOld(RigidBody& body1, const SimdVector3& pos1,
RigidBody& body2, const SimdVector3& pos2,
const SimdVector3& normal,float normalImpulse,
const ContactSolverInfo& info);
//contact constraint resolution:
//calculate and apply impulse to satisfy non-penetration and non-negative relative velocity constraint
float resolveSingleCollisionWithFriction(RigidBody& body1, const SimdVector3& pos1,
RigidBody& body2, const SimdVector3& pos2,
SimdScalar depth, const SimdVector3& normal,
const ContactSolverInfo& info);
#endif //CONTACT_CONSTRAINT_H

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef CONTACT_SOLVER_INFO
#define CONTACT_SOLVER_INFO
struct ContactSolverInfo
{
inline ContactSolverInfo()
{
m_tau = 0.4f;
m_damping = 0.9f;
m_friction = 0.3f;
m_restitution = 0.f;
m_maxErrorReduction = 20.f;
m_numIterations = 10;
}
float m_tau;
float m_damping;
float m_friction;
float m_timeStep;
float m_restitution;
int m_numIterations;
float m_maxErrorReduction;
};
#endif //CONTACT_SOLVER_INFO

View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef JACOBIAN_ENTRY_H
#define JACOBIAN_ENTRY_H
#include "SimdVector3.h"
#include "Dynamics/RigidBody.h"
//notes:
// Another memory optimization would be to store m_MbJ in the remaining 3 w components
// which makes the JacobianEntry memory layout 16 bytes
// if you only are interested in angular part, just feed massInvA and massInvB zero
/// Jacobian entry is an abstraction that allows to describe constraints
/// it can be used in combination with a constraint solver
/// Can be used to relate the effect of an impulse to the constraint error
class JacobianEntry
{
public:
JacobianEntry() {};
//constraint between two different rigidbodies
JacobianEntry(
const SimdMatrix3x3& world2A,
const SimdMatrix3x3& world2B,
const SimdVector3& rel_pos1,const SimdVector3& rel_pos2,
const SimdVector3& normal,
const SimdVector3& inertiaInvA,
const SimdScalar massInvA,
const SimdVector3& inertiaInvB,
const SimdScalar massInvB)
:m_normalAxis(normal)
{
m_aJ = world2A*(rel_pos1.cross(normal));
m_bJ = world2B*(rel_pos2.cross(normal));
m_MaJ = inertiaInvA * m_aJ;
m_MbJ = inertiaInvB * m_bJ;
m_jacDiagAB = massInvA + m_MaJ.dot(m_aJ) + massInvB + m_MbJ.dot(m_bJ);
}
//angular constraint between two different rigidbodies
JacobianEntry(const SimdVector3& normal,
const SimdMatrix3x3& world2A,
const SimdMatrix3x3& world2B,
const SimdVector3& inertiaInvA,
const SimdVector3& inertiaInvB)
:m_normalAxis(normal)
{
m_aJ= world2A*normal;
m_bJ = world2B*-normal;
m_MaJ = inertiaInvA * m_aJ;
m_MbJ = inertiaInvB * m_bJ;
m_jacDiagAB = m_MaJ.dot(m_aJ) + m_MbJ.dot(m_bJ);
}
//constraint on one rigidbody
JacobianEntry(
const SimdMatrix3x3& world2A,
const SimdVector3& rel_pos1,const SimdVector3& rel_pos2,
const SimdVector3& normal,
const SimdVector3& inertiaInvA,
const SimdScalar massInvA)
:m_normalAxis(normal)
{
m_aJ= world2A*(rel_pos1.cross(normal));
m_bJ = world2A*(rel_pos2.cross(normal));
m_MaJ = inertiaInvA * m_aJ;
m_MbJ = SimdVector3(0.f,0.f,0.f);
m_jacDiagAB = massInvA + m_MaJ.dot(m_aJ);
}
SimdScalar getDiagonal() const { return m_jacDiagAB; }
// for two constraints on the same rigidbody (for example vehicle friction)
SimdScalar getNonDiagonal(const JacobianEntry& jacB, const SimdScalar massInvA) const
{
const JacobianEntry& jacA = *this;
SimdScalar lin = massInvA * jacA.m_normalAxis.dot(jacB.m_normalAxis);
SimdScalar ang = jacA.m_MaJ.dot(jacB.m_aJ);
return lin + ang;
}
// for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
SimdScalar getNonDiagonal(const JacobianEntry& jacB,const SimdScalar massInvA,const SimdScalar massInvB) const
{
const JacobianEntry& jacA = *this;
SimdVector3 lin = jacA.m_normalAxis * jacB.m_normalAxis;
SimdVector3 ang0 = jacA.m_MaJ * jacB.m_aJ;
SimdVector3 ang1 = jacA.m_MbJ * jacB.m_bJ;
SimdVector3 lin0 = massInvA * lin ;
SimdVector3 lin1 = massInvB * lin;
SimdVector3 sum = ang0+ang1+lin0+lin1;
return sum[0]+sum[1]+sum[2];
}
SimdScalar getRelativeVelocity(const SimdVector3& linvelA,const SimdVector3& angvelA,const SimdVector3& linvelB,const SimdVector3& angvelB)
{
SimdVector3 linrel = linvelA - linvelB;
SimdVector3 angvela = angvelA * m_aJ;
SimdVector3 angvelb = angvelB * m_bJ;
linrel *= m_normalAxis;
angvela += angvelb;
angvela += linrel;
SimdScalar rel_vel2 = angvela[0]+angvela[1]+angvela[2];
return rel_vel2 + SIMD_EPSILON;
}
//private:
SimdVector3 m_normalAxis;
SimdVector3 m_aJ;
SimdVector3 m_bJ;
SimdVector3 m_MaJ;
SimdVector3 m_MbJ;
//Optimization: can be stored in the w/last component of one of the vectors
SimdScalar m_jacDiagAB;
};
#endif //JACOBIAN_ENTRY_H

View File

@@ -0,0 +1,256 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "OdeConstraintSolver.h"
#include "NarrowPhaseCollision/PersistentManifold.h"
#include "Dynamics/RigidBody.h"
#include "ContactConstraint.h"
#include "Solve2LinearConstraint.h"
#include "ContactSolverInfo.h"
#include "Dynamics/BU_Joint.h"
#include "Dynamics/ContactJoint.h"
#define USE_SOR_SOLVER
#include "SorLcp.h"
#include <math.h>
#include <float.h>//FLT_MAX
#ifdef WIN32
#include <memory.h>
#endif
#include <string.h>
#include <stdio.h>
#ifdef WIN32
#include <malloc.h>
#else
#include <alloca.h>
#endif
class BU_Joint;
//see below
int gCurBody = 0;
int gCurJoint= 0;
int ConvertBody(RigidBody* body,RigidBody** bodies,int& numBodies);
void ConvertConstraint(PersistentManifold* manifold,BU_Joint** joints,int& numJoints,
RigidBody** bodies,int bodyId0,int bodyId1);
//iterative lcp and penalty method
float OdeConstraintSolver::SolveGroup(PersistentManifold** manifoldPtr, int numManifolds,const ContactSolverInfo& infoGlobal)
{
gCurBody = 0;
gCurJoint = 0;
float cfm = 1e-5f;
float erp = 0.2f;
RigidBody* bodies [128];
int numBodies = 0;
BU_Joint* joints [128*5];
int numJoints = 0;
for (int j=0;j<numManifolds;j++)
{
int body0=-1,body1=-1;
PersistentManifold* manifold = manifoldPtr[j];
if (manifold->GetNumContacts() > 0)
{
body0 = ConvertBody((RigidBody*)manifold->GetBody0(),bodies,numBodies);
body1 = ConvertBody((RigidBody*)manifold->GetBody1(),bodies,numBodies);
ConvertConstraint(manifold,joints,numJoints,bodies,body0,body1);
}
}
SolveInternal1(cfm,erp,bodies,numBodies,joints,numJoints,infoGlobal);
return 0.f;
}
/////////////////////////////////////////////////////////////////////////////////
typedef SimdScalar dQuaternion[4];
#define _R(i,j) R[(i)*4+(j)]
void dRfromQ1 (dMatrix3 R, const dQuaternion q)
{
// q = (s,vx,vy,vz)
SimdScalar qq1 = 2*q[1]*q[1];
SimdScalar qq2 = 2*q[2]*q[2];
SimdScalar qq3 = 2*q[3]*q[3];
_R(0,0) = 1 - qq2 - qq3;
_R(0,1) = 2*(q[1]*q[2] - q[0]*q[3]);
_R(0,2) = 2*(q[1]*q[3] + q[0]*q[2]);
_R(1,0) = 2*(q[1]*q[2] + q[0]*q[3]);
_R(1,1) = 1 - qq1 - qq3;
_R(1,2) = 2*(q[2]*q[3] - q[0]*q[1]);
_R(2,0) = 2*(q[1]*q[3] - q[0]*q[2]);
_R(2,1) = 2*(q[2]*q[3] + q[0]*q[1]);
_R(2,2) = 1 - qq1 - qq2;
}
int ConvertBody(RigidBody* body,RigidBody** bodies,int& numBodies)
{
if (!body || (body->getInvMass() == 0.f) )
{
return -1;
}
//first try to find
int i,j;
for (i=0;i<numBodies;i++)
{
if (bodies[i] == body)
return i;
}
//if not found, create a new body
bodies[numBodies++] = body;
//convert data
body->m_facc.setValue(0,0,0);
body->m_tacc.setValue(0,0,0);
//are the indices the same ?
for (i=0;i<4;i++)
{
for ( j=0;j<3;j++)
{
body->m_invI[i+4*j] = 0.f;
body->m_I[i+4*j] = 0.f;
}
}
body->m_invI[0+4*0] = body->getInvInertiaDiagLocal()[0];
body->m_invI[1+4*1] = body->getInvInertiaDiagLocal()[1];
body->m_invI[2+4*2] = body->getInvInertiaDiagLocal()[2];
body->m_I[0+0*4] = body->getInvInertiaDiagLocal()[0];
body->m_I[1+1*4] = body->getInvInertiaDiagLocal()[1];
body->m_I[2+2*4] = body->getInvInertiaDiagLocal()[2];
/*
SimdMatrix3x3 invI;
invI.setIdentity();
invI[0][0] = body->getInvInertiaDiagLocal()[0];
invI[1][1] = body->getInvInertiaDiagLocal()[1];
invI[2][2] = body->getInvInertiaDiagLocal()[2];
SimdMatrix3x3 inertia = invI.inverse();
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
body->m_I[i+4*j] = inertia[i][j];
}
}
*/
// body->m_I[3+0*4] = 0.f;
// body->m_I[3+1*4] = 0.f;
// body->m_I[3+2*4] = 0.f;
// body->m_I[3+3*4] = 0.f;
dQuaternion q;
q[1] = body->getOrientation()[0];
q[2] = body->getOrientation()[1];
q[3] = body->getOrientation()[2];
q[0] = body->getOrientation()[3];
dRfromQ1(body->m_R,q);
return numBodies-1;
}
#define MAX_JOINTS_1 8192
static ContactJoint gJointArray[MAX_JOINTS_1];
void ConvertConstraint(PersistentManifold* manifold,BU_Joint** joints,int& numJoints,
RigidBody** bodies,int _bodyId0,int _bodyId1)
{
manifold->RefreshContactPoints(((RigidBody*)manifold->GetBody0())->getCenterOfMassTransform(),
((RigidBody*)manifold->GetBody1())->getCenterOfMassTransform());
int bodyId0 = _bodyId0,bodyId1 = _bodyId1;
int i,numContacts = manifold->GetNumContacts();
bool swapBodies = (bodyId0 < 0);
RigidBody* body0,*body1;
if (swapBodies)
{
bodyId0 = _bodyId1;
bodyId1 = _bodyId0;
body0 = (RigidBody*)manifold->GetBody1();
body1 = (RigidBody*)manifold->GetBody0();
} else
{
body0 = (RigidBody*)manifold->GetBody0();
body1 = (RigidBody*)manifold->GetBody1();
}
assert(bodyId0 >= 0);
for (i=0;i<numContacts;i++)
{
assert (gCurJoint < MAX_JOINTS_1);
if (manifold->GetContactPoint(i).GetDistance() < 0.f)
{
ContactJoint* cont = new (&gJointArray[gCurJoint++]) ContactJoint( manifold ,i, swapBodies,body0,body1);
cont->node[0].joint = cont;
cont->node[0].body = bodyId0 >= 0 ? bodies[bodyId0] : 0;
cont->node[1].joint = cont;
cont->node[1].body = bodyId1 >= 0 ? bodies[bodyId1] : 0;
joints[numJoints++] = cont;
for (int i=0;i<6;i++)
cont->lambda[i] = 0.f;
cont->flags = 0;
}
}
//create a new contact constraint
};

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef ODE_CONSTRAINT_SOLVER_H
#define ODE_CONSTRAINT_SOLVER_H
#include "ConstraintSolver.h"
class OdeConstraintSolver : public ConstraintSolver
{
public:
virtual ~OdeConstraintSolver() {}
virtual float SolveGroup(PersistentManifold** manifold,int numManifolds,const ContactSolverInfo& info);
};
#endif //ODE_CONSTRAINT_SOLVER_H

View File

@@ -0,0 +1,246 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "OdeConstraintSolver.h"
#include "NarrowPhaseCollision/PersistentManifold.h"
#include "Dynamics/RigidBody.h"
#include "ContactConstraint.h"
#include "Solve2LinearConstraint.h"
#include "ContactSolverInfo.h"
#include "Dynamics/BU_Joint.h"
#include "Dynamics/ContactJoint.h"
#define USE_SOR_SOLVER
#include "SorLcp.h"
#include <math.h>
#include <float.h>//FLT_MAX
#ifdef WIN32
#include <memory.h>
#endif
#include <string.h>
#include <stdio.h>
#ifdef WIN32
#include <malloc.h>
#else
#include <alloca.h>
#endif
class BU_Joint;
//see below
int gCurBody = 0;
int gCurJoint= 0;
int ConvertBody(RigidBody* body,RigidBody** bodies,int& numBodies);
void ConvertConstraint(PersistentManifold* manifold,BU_Joint** joints,int& numJoints,
RigidBody** bodies,int bodyId0,int bodyId1);
//iterative lcp and penalty method
float OdeConstraintSolver::SolveGroup(PersistentManifold** manifoldPtr, int numManifolds,const ContactSolverInfo& infoGlobal)
{
gCurBody = 0;
gCurJoint = 0;
float cfm = 1e-5f;
float erp = 0.2f;
RigidBody* bodies [128];
int numBodies = 0;
BU_Joint* joints [128*5];
int numJoints = 0;
for (int j=0;j<numManifolds;j++)
{
int body0=-1,body1=-1;
PersistentManifold* manifold = manifoldPtr[j];
if (manifold->GetNumContacts() > 0)
{
body0 = ConvertBody((RigidBody*)manifold->GetBody0(),bodies,numBodies);
body1 = ConvertBody((RigidBody*)manifold->GetBody1(),bodies,numBodies);
ConvertConstraint(manifold,joints,numJoints,bodies,body0,body1);
}
}
SolveInternal1(cfm,erp,bodies,numBodies,joints,numJoints,infoGlobal);
return 0.f;
}
/////////////////////////////////////////////////////////////////////////////////
typedef SimdScalar dQuaternion[4];
#define _R(i,j) R[(i)*4+(j)]
void dRfromQ1 (dMatrix3 R, const dQuaternion q)
{
// q = (s,vx,vy,vz)
SimdScalar qq1 = 2*q[1]*q[1];
SimdScalar qq2 = 2*q[2]*q[2];
SimdScalar qq3 = 2*q[3]*q[3];
_R(0,0) = 1 - qq2 - qq3;
_R(0,1) = 2*(q[1]*q[2] - q[0]*q[3]);
_R(0,2) = 2*(q[1]*q[3] + q[0]*q[2]);
_R(1,0) = 2*(q[1]*q[2] + q[0]*q[3]);
_R(1,1) = 1 - qq1 - qq3;
_R(1,2) = 2*(q[2]*q[3] - q[0]*q[1]);
_R(2,0) = 2*(q[1]*q[3] - q[0]*q[2]);
_R(2,1) = 2*(q[2]*q[3] + q[0]*q[1]);
_R(2,2) = 1 - qq1 - qq2;
}
int ConvertBody(RigidBody* body,RigidBody** bodies,int& numBodies)
{
if (!body || (body->getInvMass() == 0.f) )
{
return -1;
}
//first try to find
int i,j;
for (i=0;i<numBodies;i++)
{
if (bodies[i] == body)
return i;
}
//if not found, create a new body
bodies[numBodies++] = body;
//convert data
body->m_facc.setValue(0,0,0);
body->m_tacc.setValue(0,0,0);
//are the indices the same ?
for (i=0;i<4;i++)
{
for ( j=0;j<3;j++)
{
body->m_invI[i+4*j] = 0.f;
}
}
body->m_invI[0+4*0] = body->getInvInertiaDiagLocal()[0];
body->m_invI[1+4*1] = body->getInvInertiaDiagLocal()[1];
body->m_invI[2+4*2] = body->getInvInertiaDiagLocal()[2];
SimdMatrix3x3 invI;
invI.setIdentity();
invI[0][0] = body->getInvInertiaDiagLocal()[0];
invI[1][1] = body->getInvInertiaDiagLocal()[1];
invI[2][2] = body->getInvInertiaDiagLocal()[2];
SimdMatrix3x3 inertia = invI.inverse();
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
body->m_I[i+4*j] = inertia[i][j];
}
}
body->m_I[3+0*4] = 0.f;
body->m_I[3+1*4] = 0.f;
body->m_I[3+2*4] = 0.f;
body->m_I[3+3*4] = 0.f;
dQuaternion q;
q[1] = body->getOrientation()[0];
q[2] = body->getOrientation()[1];
q[3] = body->getOrientation()[2];
q[0] = body->getOrientation()[3];
dRfromQ1(body->m_R,q);
return numBodies-1;
}
#define MAX_JOINTS_1 8192
static ContactJoint gJointArray[MAX_JOINTS_1];
void ConvertConstraint(PersistentManifold* manifold,BU_Joint** joints,int& numJoints,
RigidBody** bodies,int _bodyId0,int _bodyId1)
{
manifold->RefreshContactPoints(((RigidBody*)manifold->GetBody0())->getCenterOfMassTransform(),
((RigidBody*)manifold->GetBody1())->getCenterOfMassTransform());
int bodyId0 = _bodyId0,bodyId1 = _bodyId1;
int i,numContacts = manifold->GetNumContacts();
bool swapBodies = (bodyId0 < 0);
RigidBody* body0,*body1;
if (swapBodies)
{
bodyId0 = _bodyId1;
bodyId1 = _bodyId0;
body0 = (RigidBody*)manifold->GetBody1();
body1 = (RigidBody*)manifold->GetBody0();
} else
{
body0 = (RigidBody*)manifold->GetBody0();
body1 = (RigidBody*)manifold->GetBody1();
}
assert(bodyId0 >= 0);
for (i=0;i<numContacts;i++)
{
assert (gCurJoint < MAX_JOINTS_1);
ContactJoint* cont = new (&gJointArray[gCurJoint++]) ContactJoint( manifold ,i, swapBodies,body0,body1);
cont->node[0].joint = cont;
cont->node[0].body = bodyId0 >= 0 ? bodies[bodyId0] : 0;
cont->node[1].joint = cont;
cont->node[1].body = bodyId1 >= 0 ? bodies[bodyId1] : 0;
joints[numJoints++] = cont;
for (int i=0;i<6;i++)
cont->lambda[i] = 0.f;
cont->flags = 0;
}
//create a new contact constraint
};

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef ODE_CONSTRAINT_SOLVER_H
#define ODE_CONSTRAINT_SOLVER_H
#include "ConstraintSolver.h"
class OdeConstraintSolver : public ConstraintSolver
{
public:
virtual ~OdeConstraintSolver() {}
virtual float SolveGroup(PersistentManifold** manifold,int numManifolds,const ContactSolverInfo& info);
};
#endif //ODE_CONSTRAINT_SOLVER_H

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "Point2PointConstraint.h"
#include "Dynamics/RigidBody.h"
#include "Dynamics/MassProps.h"
static RigidBody s_fixed(MassProps(0,SimdVector3(0.f,0.f,0.f)),0.f,0.f);
Point2PointConstraint::Point2PointConstraint():
m_rbA(s_fixed),m_rbB(s_fixed)
{
s_fixed.setMassProps(0.f,SimdVector3(0.f,0.f,0.f));
}
Point2PointConstraint::Point2PointConstraint(RigidBody& rbA,RigidBody& rbB, const SimdVector3& pivotInA,const SimdVector3& pivotInB)
:m_rbA(rbA),m_rbB(rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB)
{
}
Point2PointConstraint::Point2PointConstraint(RigidBody& rbA,const SimdVector3& pivotInA)
:m_rbA(rbA),m_rbB(s_fixed),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA))
{
s_fixed.setMassProps(0.f,SimdVector3(1e10f,1e10f,1e10f));
}
void Point2PointConstraint::BuildJacobian()
{
SimdVector3 normal(0,0,0);
for (int i=0;i<3;i++)
{
normal[i] = 1;
new (&m_jac[i]) JacobianEntry(
m_rbA.getCenterOfMassTransform().getBasis().transpose(),
m_rbB.getCenterOfMassTransform().getBasis().transpose(),
m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(),
m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(),
normal,
m_rbA.getInvInertiaDiagLocal(),
m_rbA.getInvMass(),
m_rbB.getInvInertiaDiagLocal(),
m_rbB.getInvMass());
normal[i] = 0;
}
}
void Point2PointConstraint::SolveConstraint(SimdScalar timeStep)
{
SimdVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA;
SimdVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB;
SimdVector3 normal(0,0,0);
SimdScalar tau = 0.3f;
SimdScalar damping = 1.f;
// SimdVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity();
// SimdVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity();
for (int i=0;i<3;i++)
{
normal[i] = 1;
SimdScalar jacDiagABInv = 1.f / m_jac[i].getDiagonal();
SimdVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
SimdVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
//this jacobian entry could be re-used for all iterations
SimdVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1);
SimdVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2);
SimdVector3 vel = vel1 - vel2;
SimdScalar rel_vel;
rel_vel = normal.dot(vel);
/*
//velocity error (first order error)
SimdScalar rel_vel = m_jac[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA,
m_rbB.getLinearVelocity(),angvelB);
*/
//positional error (zeroth order error)
SimdScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
SimdScalar impulse = depth*tau/timeStep * jacDiagABInv - damping * rel_vel * jacDiagABInv * damping;
SimdVector3 impulse_vector = normal * impulse;
m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition());
m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition());
normal[i] = 0;
}
}
void Point2PointConstraint::UpdateRHS(SimdScalar timeStep)
{
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef POINT2POINTCONSTRAINT_H
#define POINT2POINTCONSTRAINT_H
#include "SimdVector3.h"
#include "ConstraintSolver/JacobianEntry.h"
class RigidBody;
/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
class Point2PointConstraint
{
JacobianEntry m_jac[3]; //3 orthogonal linear constraints
RigidBody& m_rbA;
RigidBody& m_rbB;
SimdVector3 m_pivotInA;
SimdVector3 m_pivotInB;
public:
Point2PointConstraint(RigidBody& rbA,RigidBody& rbB, const SimdVector3& pivotInA,const SimdVector3& pivotInB);
Point2PointConstraint(RigidBody& rbA,const SimdVector3& pivotInA);
Point2PointConstraint();
void BuildJacobian();
void SolveConstraint(SimdScalar timeStep);
void UpdateRHS(SimdScalar timeStep);
const RigidBody& GetRigidBodyA() const
{
return m_rbA;
}
const RigidBody& GetRigidBodyB() const
{
return m_rbB;
}
};
#endif //POINT2POINTCONSTRAINT_H

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "SimpleConstraintSolver.h"
#include "NarrowPhaseCollision/PersistentManifold.h"
#include "Dynamics/RigidBody.h"
#include "ContactConstraint.h"
#include "Solve2LinearConstraint.h"
#include "ContactSolverInfo.h"
#include "Dynamics/BU_Joint.h"
#include "Dynamics/ContactJoint.h"
//debugging
bool doApplyImpulse = true;
bool useImpulseFriction = true;//true;//false;
//iterative lcp and penalty method
float SimpleConstraintSolver::SolveGroup(PersistentManifold** manifoldPtr, int numManifolds,const ContactSolverInfo& infoGlobal)
{
ContactSolverInfo info = infoGlobal;
int numiter = infoGlobal.m_numIterations;
float substep = infoGlobal.m_timeStep / float(numiter);
for (int i = 0;i<numiter;i++)
{
for (int j=0;j<numManifolds;j++)
{
Solve(manifoldPtr[j],info,i);
}
}
return 0.f;
}
float penetrationResolveFactor = 0.9f;
float SimpleConstraintSolver::Solve(PersistentManifold* manifoldPtr, const ContactSolverInfo& info,int iter)
{
RigidBody* body0 = (RigidBody*)manifoldPtr->GetBody0();
RigidBody* body1 = (RigidBody*)manifoldPtr->GetBody1();
float maxImpulse = 0.f;
float invNumIterFl = 1.f / float(info.m_numIterations);
float timeSubStep = info.m_timeStep * invNumIterFl;
//only necessary to refresh the manifold once (first iteration). The integration is done outside the loop
if (iter == 0)
{
manifoldPtr->RefreshContactPoints(body0->getCenterOfMassTransform(),body1->getCenterOfMassTransform());
}
{
const int numpoints = manifoldPtr->GetNumContacts();
for (int i=0;i<numpoints ;i++)
{
int j=i;
if (iter % 2)
j = numpoints-1-i;
else
j=i;
ManifoldPoint& cp = manifoldPtr->GetContactPoint(j);
{
float dist = invNumIterFl * cp.GetDistance() * penetrationResolveFactor / info.m_timeStep;// / timeStep;//penetrationResolveFactor*cp.m_solveDistance /timeStep;//cp.GetDistance();
float impulse = 0.f;
if (doApplyImpulse)
{
impulse = resolveSingleCollision(*body0,
cp.GetPositionWorldOnA(),
*body1,
cp.GetPositionWorldOnB(),
-dist,
cp.m_normalWorldOnB,
info);
if (useImpulseFriction)
{
applyFrictionInContactPointOld(
*body0,cp.GetPositionWorldOnA(),*body1,cp.GetPositionWorldOnB(),
cp.m_normalWorldOnB,impulse,info) ;
}
}
if (iter == 0)
{
cp.m_appliedImpulse = impulse;
} else
{
cp.m_appliedImpulse += impulse;
}
if (maxImpulse < impulse)
maxImpulse = impulse;
}
}
}
return maxImpulse;
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef SIMPLE_CONSTRAINT_SOLVER_H
#define SIMPLE_CONSTRAINT_SOLVER_H
#include "ConstraintSolver.h"
class SimpleConstraintSolver : public ConstraintSolver
{
float Solve(PersistentManifold* manifold, const ContactSolverInfo& info,int iter);
public:
virtual ~SimpleConstraintSolver() {}
virtual float SolveGroup(PersistentManifold** manifold,int numManifolds,const ContactSolverInfo& info);
};
#endif //SIMPLE_CONSTRAINT_SOLVER_H

View File

@@ -0,0 +1,234 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "Solve2LinearConstraint.h"
#include "Dynamics/RigidBody.h"
#include "SimdVector3.h"
#include "JacobianEntry.h"
void Solve2LinearConstraint::resolveUnilateralPairConstraint(
RigidBody* body1,
RigidBody* body2,
const SimdMatrix3x3& world2A,
const SimdMatrix3x3& world2B,
const SimdVector3& invInertiaADiag,
const SimdScalar invMassA,
const SimdVector3& linvelA,const SimdVector3& angvelA,
const SimdVector3& rel_posA1,
const SimdVector3& invInertiaBDiag,
const SimdScalar invMassB,
const SimdVector3& linvelB,const SimdVector3& angvelB,
const SimdVector3& rel_posA2,
SimdScalar depthA, const SimdVector3& normalA,
const SimdVector3& rel_posB1,const SimdVector3& rel_posB2,
SimdScalar depthB, const SimdVector3& normalB,
SimdScalar& imp0,SimdScalar& imp1)
{
imp0 = 0.f;
imp1 = 0.f;
SimdScalar len = fabs(normalA.length())-1.f;
if (fabs(len) >= SIMD_EPSILON)
return;
ASSERT(len < SIMD_EPSILON);
//this jacobian entry could be re-used for all iterations
JacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA,
invInertiaBDiag,invMassB);
JacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA,
invInertiaBDiag,invMassB);
//const SimdScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
//const SimdScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
const SimdScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1));
const SimdScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1));
// SimdScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv
SimdScalar massTerm = 1.f / (invMassA + invMassB);
// calculate rhs (or error) terms
const SimdScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping;
const SimdScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping;
// dC/dv * dv = -C
// jacobian * impulse = -error
//
//impulse = jacobianInverse * -error
// inverting 2x2 symmetric system (offdiagonal are equal!)
//
SimdScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB);
SimdScalar invDet = 1.0f / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag );
//imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
//imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
//[a b] [d -c]
//[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
//[jA nD] * [imp0] = [dv0]
//[nD jB] [imp1] [dv1]
}
void Solve2LinearConstraint::resolveBilateralPairConstraint(
RigidBody* body1,
RigidBody* body2,
const SimdMatrix3x3& world2A,
const SimdMatrix3x3& world2B,
const SimdVector3& invInertiaADiag,
const SimdScalar invMassA,
const SimdVector3& linvelA,const SimdVector3& angvelA,
const SimdVector3& rel_posA1,
const SimdVector3& invInertiaBDiag,
const SimdScalar invMassB,
const SimdVector3& linvelB,const SimdVector3& angvelB,
const SimdVector3& rel_posA2,
SimdScalar depthA, const SimdVector3& normalA,
const SimdVector3& rel_posB1,const SimdVector3& rel_posB2,
SimdScalar depthB, const SimdVector3& normalB,
SimdScalar& imp0,SimdScalar& imp1)
{
imp0 = 0.f;
imp1 = 0.f;
SimdScalar len = fabs(normalA.length())-1.f;
if (fabs(len) >= SIMD_EPSILON)
return;
ASSERT(len < SIMD_EPSILON);
//this jacobian entry could be re-used for all iterations
JacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA,
invInertiaBDiag,invMassB);
JacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA,
invInertiaBDiag,invMassB);
//const SimdScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
//const SimdScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
const SimdScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1));
const SimdScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1));
// calculate rhs (or error) terms
const SimdScalar dv0 = depthA * m_tau - vel0 * m_damping;
const SimdScalar dv1 = depthB * m_tau - vel1 * m_damping;
// dC/dv * dv = -C
// jacobian * impulse = -error
//
//impulse = jacobianInverse * -error
// inverting 2x2 symmetric system (offdiagonal are equal!)
//
SimdScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB);
SimdScalar invDet = 1.0f / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag );
//imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
//imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
//[a b] [d -c]
//[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
//[jA nD] * [imp0] = [dv0]
//[nD jB] [imp1] [dv1]
if ( imp0 > 0.0f)
{
if ( imp1 > 0.0f )
{
//both positive
}
else
{
imp1 = 0.f;
// now imp0>0 imp1<0
imp0 = dv0 / jacA.getDiagonal();
if ( imp0 > 0.0f )
{
} else
{
imp0 = 0.f;
}
}
}
else
{
imp0 = 0.f;
imp1 = dv1 / jacB.getDiagonal();
if ( imp1 <= 0.0f )
{
imp1 = 0.f;
// now imp0>0 imp1<0
imp0 = dv0 / jacA.getDiagonal();
if ( imp0 > 0.0f )
{
} else
{
imp0 = 0.f;
}
} else
{
}
}
}
void Solve2LinearConstraint::resolveAngularConstraint( const SimdMatrix3x3& invInertiaAWS,
const SimdScalar invMassA,
const SimdVector3& linvelA,const SimdVector3& angvelA,
const SimdVector3& rel_posA1,
const SimdMatrix3x3& invInertiaBWS,
const SimdScalar invMassB,
const SimdVector3& linvelB,const SimdVector3& angvelB,
const SimdVector3& rel_posA2,
SimdScalar depthA, const SimdVector3& normalA,
const SimdVector3& rel_posB1,const SimdVector3& rel_posB2,
SimdScalar depthB, const SimdVector3& normalB,
SimdScalar& imp0,SimdScalar& imp1)
{
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef SOLVE_2LINEAR_CONSTRAINT_H
#define SOLVE_2LINEAR_CONSTRAINT_H
#include "SimdMatrix3x3.h"
#include "SimdVector3.h"
class RigidBody;
/// constraint class used for lateral tyre friction.
class Solve2LinearConstraint
{
SimdScalar m_tau;
SimdScalar m_damping;
public:
Solve2LinearConstraint(SimdScalar tau,SimdScalar damping)
{
m_tau = tau;
m_damping = damping;
}
//
// solve unilateral constraint (equality, direct method)
//
void resolveUnilateralPairConstraint(
RigidBody* body0,
RigidBody* body1,
const SimdMatrix3x3& world2A,
const SimdMatrix3x3& world2B,
const SimdVector3& invInertiaADiag,
const SimdScalar invMassA,
const SimdVector3& linvelA,const SimdVector3& angvelA,
const SimdVector3& rel_posA1,
const SimdVector3& invInertiaBDiag,
const SimdScalar invMassB,
const SimdVector3& linvelB,const SimdVector3& angvelB,
const SimdVector3& rel_posA2,
SimdScalar depthA, const SimdVector3& normalA,
const SimdVector3& rel_posB1,const SimdVector3& rel_posB2,
SimdScalar depthB, const SimdVector3& normalB,
SimdScalar& imp0,SimdScalar& imp1);
//
// solving 2x2 lcp problem (inequality, direct solution )
//
void resolveBilateralPairConstraint(
RigidBody* body0,
RigidBody* body1,
const SimdMatrix3x3& world2A,
const SimdMatrix3x3& world2B,
const SimdVector3& invInertiaADiag,
const SimdScalar invMassA,
const SimdVector3& linvelA,const SimdVector3& angvelA,
const SimdVector3& rel_posA1,
const SimdVector3& invInertiaBDiag,
const SimdScalar invMassB,
const SimdVector3& linvelB,const SimdVector3& angvelB,
const SimdVector3& rel_posA2,
SimdScalar depthA, const SimdVector3& normalA,
const SimdVector3& rel_posB1,const SimdVector3& rel_posB2,
SimdScalar depthB, const SimdVector3& normalB,
SimdScalar& imp0,SimdScalar& imp1);
void resolveAngularConstraint( const SimdMatrix3x3& invInertiaAWS,
const SimdScalar invMassA,
const SimdVector3& linvelA,const SimdVector3& angvelA,
const SimdVector3& rel_posA1,
const SimdMatrix3x3& invInertiaBWS,
const SimdScalar invMassB,
const SimdVector3& linvelB,const SimdVector3& angvelB,
const SimdVector3& rel_posA2,
SimdScalar depthA, const SimdVector3& normalA,
const SimdVector3& rel_posB1,const SimdVector3& rel_posB2,
SimdScalar depthB, const SimdVector3& normalB,
SimdScalar& imp0,SimdScalar& imp1);
};
#endif //SOLVE_2LINEAR_CONSTRAINT_H

View File

@@ -0,0 +1,821 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "SorLcp.h"
#ifdef USE_SOR_SOLVER
// SOR LCP taken from ode quickstep,
// todo: write own successive overrelaxation gauss-seidel, or jacobi iterative solver
#include "SimdScalar.h"
#include "Dynamics/RigidBody.h"
#include <math.h>
#include <float.h>//FLT_MAX
#ifdef WIN32
#include <memory.h>
#endif
#include <string.h>
#include <stdio.h>
#ifdef WIN32
#include <malloc.h>
#else
#include <alloca.h>
#endif
#include "Dynamics/BU_Joint.h"
#include "ContactSolverInfo.h"
////////////////////////////////////////////////////////////////////
//math stuff
typedef SimdScalar dVector4[4];
typedef SimdScalar dMatrix3[4*3];
#define dInfinity FLT_MAX
#define dRecip(x) ((float)(1.0f/(x))) /* reciprocal */
#define dMULTIPLY0_331NEW(A,op,B,C) \
{\
float tmp[3];\
tmp[0] = C.getX();\
tmp[1] = C.getY();\
tmp[2] = C.getZ();\
dMULTIPLYOP0_331(A,op,B,tmp);\
}
#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
#define dMULTIPLYOP0_331(A,op,B,C) \
(A)[0] op dDOT1((B),(C)); \
(A)[1] op dDOT1((B+4),(C)); \
(A)[2] op dDOT1((B+8),(C));
#define dAASSERT ASSERT
#define dIASSERT ASSERT
#define REAL float
#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
SimdScalar dDOT1 (const SimdScalar *a, const SimdScalar *b) { return dDOTpq(a,b,1,1); }
#define dDOT14(a,b) dDOTpq(a,b,1,4)
#define dCROSS(a,op,b,c) \
(a)[0] op ((b)[1]*(c)[2] - (b)[2]*(c)[1]); \
(a)[1] op ((b)[2]*(c)[0] - (b)[0]*(c)[2]); \
(a)[2] op ((b)[0]*(c)[1] - (b)[1]*(c)[0]);
#define dMULTIPLYOP2_333(A,op,B,C) \
(A)[0] op dDOT1((B),(C)); \
(A)[1] op dDOT1((B),(C+4)); \
(A)[2] op dDOT1((B),(C+8)); \
(A)[4] op dDOT1((B+4),(C)); \
(A)[5] op dDOT1((B+4),(C+4)); \
(A)[6] op dDOT1((B+4),(C+8)); \
(A)[8] op dDOT1((B+8),(C)); \
(A)[9] op dDOT1((B+8),(C+4)); \
(A)[10] op dDOT1((B+8),(C+8));
#define dMULTIPLYOP0_333(A,op,B,C) \
(A)[0] op dDOT14((B),(C)); \
(A)[1] op dDOT14((B),(C+1)); \
(A)[2] op dDOT14((B),(C+2)); \
(A)[4] op dDOT14((B+4),(C)); \
(A)[5] op dDOT14((B+4),(C+1)); \
(A)[6] op dDOT14((B+4),(C+2)); \
(A)[8] op dDOT14((B+8),(C)); \
(A)[9] op dDOT14((B+8),(C+1)); \
(A)[10] op dDOT14((B+8),(C+2));
#define dMULTIPLY2_333(A,B,C) dMULTIPLYOP2_333(A,=,B,C)
#define dMULTIPLY0_333(A,B,C) dMULTIPLYOP0_333(A,=,B,C)
#define dMULTIPLYADD0_331(A,B,C) dMULTIPLYOP0_331(A,+=,B,C)
////////////////////////////////////////////////////////////////////
#define EFFICIENT_ALIGNMENT 16
#define dEFFICIENT_SIZE(x) ((((x)-1)|(EFFICIENT_ALIGNMENT-1))+1)
/* alloca aligned to the EFFICIENT_ALIGNMENT. note that this can waste
* up to 15 bytes per allocation, depending on what alloca() returns.
*/
#define dALLOCA16(n) \
((char*)dEFFICIENT_SIZE(((size_t)(alloca((n)+(EFFICIENT_ALIGNMENT-1))))))
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
#ifdef DEBUG
#define ANSI_FTOL 1
extern "C" {
__declspec(naked) void _ftol2() {
__asm {
#if ANSI_FTOL
fnstcw WORD PTR [esp-2]
mov ax, WORD PTR [esp-2]
OR AX, 0C00h
mov WORD PTR [esp-4], ax
fldcw WORD PTR [esp-4]
fistp QWORD PTR [esp-12]
fldcw WORD PTR [esp-2]
mov eax, DWORD PTR [esp-12]
mov edx, DWORD PTR [esp-8]
#else
fistp DWORD PTR [esp-12]
mov eax, DWORD PTR [esp-12]
mov ecx, DWORD PTR [esp-8]
#endif
ret
}
}
}
#endif //DEBUG
#define ALLOCA dALLOCA16
typedef const SimdScalar *dRealPtr;
typedef SimdScalar *dRealMutablePtr;
#define dRealArray(name,n) SimdScalar name[n];
#define dRealAllocaArray(name,n) SimdScalar *name = (SimdScalar*) ALLOCA ((n)*sizeof(SimdScalar));
void dSetZero1 (SimdScalar *a, int n)
{
dAASSERT (a && n >= 0);
while (n > 0) {
*(a++) = 0;
n--;
}
}
void dSetValue1 (SimdScalar *a, int n, SimdScalar value)
{
dAASSERT (a && n >= 0);
while (n > 0) {
*(a++) = value;
n--;
}
}
//***************************************************************************
// configuration
// for the SOR and CG methods:
// uncomment the following line to use warm starting. this definitely
// help for motor-driven joints. unfortunately it appears to hurt
// with high-friction contacts using the SOR method. use with care
//#define WARM_STARTING 1
// for the SOR method:
// uncomment the following line to randomly reorder constraint rows
// during the solution. depending on the situation, this can help a lot
// or hardly at all, but it doesn't seem to hurt.
//#define RANDOMLY_REORDER_CONSTRAINTS 1
//***************************************************************************
// various common computations involving the matrix J
// compute iMJ = inv(M)*J'
static void compute_invM_JT (int m, dRealMutablePtr J, dRealMutablePtr iMJ, int *jb,
RigidBody * const *body, dRealPtr invI)
{
int i,j;
dRealMutablePtr iMJ_ptr = iMJ;
dRealMutablePtr J_ptr = J;
for (i=0; i<m; i++) {
int b1 = jb[i*2];
int b2 = jb[i*2+1];
SimdScalar k = body[b1]->getInvMass();
for (j=0; j<3; j++) iMJ_ptr[j] = k*J_ptr[j];
dMULTIPLY0_331 (iMJ_ptr + 3, invI + 12*b1, J_ptr + 3);
if (b2 >= 0) {
k = body[b2]->getInvMass();
for (j=0; j<3; j++) iMJ_ptr[j+6] = k*J_ptr[j+6];
dMULTIPLY0_331 (iMJ_ptr + 9, invI + 12*b2, J_ptr + 9);
}
J_ptr += 12;
iMJ_ptr += 12;
}
}
static void multiply_invM_JTSpecial (int m, int nb, dRealMutablePtr iMJ, int *jb,
dRealMutablePtr in, dRealMutablePtr out,int onlyBody1,int onlyBody2)
{
int i,j;
dRealMutablePtr out_ptr1 = out + onlyBody1*6;
for (j=0; j<6; j++)
out_ptr1[j] = 0;
if (onlyBody2 >= 0)
{
out_ptr1 = out + onlyBody2*6;
for (j=0; j<6; j++)
out_ptr1[j] = 0;
}
dRealPtr iMJ_ptr = iMJ;
for (i=0; i<m; i++) {
int b1 = jb[i*2];
dRealMutablePtr out_ptr = out + b1*6;
if ((b1 == onlyBody1) || (b1 == onlyBody2))
{
for (j=0; j<6; j++)
out_ptr[j] += iMJ_ptr[j] * in[i] ;
}
iMJ_ptr += 6;
int b2 = jb[i*2+1];
if ((b2 == onlyBody1) || (b2 == onlyBody2))
{
if (b2 >= 0)
{
out_ptr = out + b2*6;
for (j=0; j<6; j++)
out_ptr[j] += iMJ_ptr[j] * in[i];
}
}
iMJ_ptr += 6;
}
}
// compute out = inv(M)*J'*in.
static void multiply_invM_JT (int m, int nb, dRealMutablePtr iMJ, int *jb,
dRealMutablePtr in, dRealMutablePtr out)
{
int i,j;
dSetZero1 (out,6*nb);
dRealPtr iMJ_ptr = iMJ;
for (i=0; i<m; i++) {
int b1 = jb[i*2];
int b2 = jb[i*2+1];
dRealMutablePtr out_ptr = out + b1*6;
for (j=0; j<6; j++)
out_ptr[j] += iMJ_ptr[j] * in[i];
iMJ_ptr += 6;
if (b2 >= 0) {
out_ptr = out + b2*6;
for (j=0; j<6; j++) out_ptr[j] += iMJ_ptr[j] * in[i];
}
iMJ_ptr += 6;
}
}
// compute out = J*in.
static void multiply_J (int m, dRealMutablePtr J, int *jb,
dRealMutablePtr in, dRealMutablePtr out)
{
int i,j;
dRealPtr J_ptr = J;
for (i=0; i<m; i++) {
int b1 = jb[i*2];
int b2 = jb[i*2+1];
SimdScalar sum = 0;
dRealMutablePtr in_ptr = in + b1*6;
for (j=0; j<6; j++) sum += J_ptr[j] * in_ptr[j];
J_ptr += 6;
if (b2 >= 0) {
in_ptr = in + b2*6;
for (j=0; j<6; j++) sum += J_ptr[j] * in_ptr[j];
}
J_ptr += 6;
out[i] = sum;
}
}
//***************************************************************************
// SOR-LCP method
// nb is the number of bodies in the body array.
// J is an m*12 matrix of constraint rows
// jb is an array of first and second body numbers for each constraint row
// invI is the global frame inverse inertia for each body (stacked 3x3 matrices)
//
// this returns lambda and fc (the constraint force).
// note: fc is returned as inv(M)*J'*lambda, the constraint force is actually J'*lambda
//
// b, lo and hi are modified on exit
struct IndexError {
SimdScalar error; // error to sort on
int findex;
int index; // row index
};
static unsigned long seed2 = 0;
unsigned long dRand2()
{
seed2 = (1664525L*seed2 + 1013904223L) & 0xffffffff;
return seed2;
}
int dRandInt2 (int n)
{
float a = float(n) / 4294967296.0f;
return (int) (float(dRand2()) * a);
}
static void SOR_LCP (int m, int nb, dRealMutablePtr J, int *jb, RigidBody * const *body,
dRealPtr invI, dRealMutablePtr lambda, dRealMutablePtr invMforce, dRealMutablePtr rhs,
dRealMutablePtr lo, dRealMutablePtr hi, dRealPtr cfm, int *findex,
int numiter,float overRelax)
{
const int num_iterations = numiter;
const float sor_w = overRelax; // SOR over-relaxation parameter
int i,j;
#ifdef WARM_STARTING
// for warm starting, this seems to be necessary to prevent
// jerkiness in motor-driven joints. i have no idea why this works.
for (i=0; i<m; i++) lambda[i] *= 0.9;
#else
dSetZero1 (lambda,m);
#endif
// the lambda computed at the previous iteration.
// this is used to measure error for when we are reordering the indexes.
dRealAllocaArray (last_lambda,m);
// a copy of the 'hi' vector in case findex[] is being used
dRealAllocaArray (hicopy,m);
memcpy (hicopy,hi,m*sizeof(float));
// precompute iMJ = inv(M)*J'
dRealAllocaArray (iMJ,m*12);
compute_invM_JT (m,J,iMJ,jb,body,invI);
// compute fc=(inv(M)*J')*lambda. we will incrementally maintain fc
// as we change lambda.
#ifdef WARM_STARTING
multiply_invM_JT (m,nb,iMJ,jb,lambda,fc);
#else
dSetZero1 (invMforce,nb*6);
#endif
// precompute 1 / diagonals of A
dRealAllocaArray (Ad,m);
dRealPtr iMJ_ptr = iMJ;
dRealMutablePtr J_ptr = J;
for (i=0; i<m; i++) {
float sum = 0;
for (j=0; j<6; j++) sum += iMJ_ptr[j] * J_ptr[j];
if (jb[i*2+1] >= 0) {
for (j=6; j<12; j++) sum += iMJ_ptr[j] * J_ptr[j];
}
iMJ_ptr += 12;
J_ptr += 12;
Ad[i] = sor_w / (sum + cfm[i]);
}
// scale J and b by Ad
J_ptr = J;
for (i=0; i<m; i++) {
for (j=0; j<12; j++) {
J_ptr[0] *= Ad[i];
J_ptr++;
}
rhs[i] *= Ad[i];
}
// scale Ad by CFM
for (i=0; i<m; i++) Ad[i] *= cfm[i];
// order to solve constraint rows in
IndexError *order = (IndexError*) alloca (m*sizeof(IndexError));
#ifndef REORDER_CONSTRAINTS
// make sure constraints with findex < 0 come first.
j=0;
for (i=0; i<m; i++) if (findex[i] < 0) order[j++].index = i;
for (i=0; i<m; i++) if (findex[i] >= 0) order[j++].index = i;
dIASSERT (j==m);
#endif
for (int iteration=0; iteration < num_iterations; iteration++) {
#ifdef REORDER_CONSTRAINTS
// constraints with findex < 0 always come first.
if (iteration < 2) {
// for the first two iterations, solve the constraints in
// the given order
for (i=0; i<m; i++) {
order[i].error = i;
order[i].findex = findex[i];
order[i].index = i;
}
}
else {
// sort the constraints so that the ones converging slowest
// get solved last. use the absolute (not relative) error.
for (i=0; i<m; i++) {
float v1 = dFabs (lambda[i]);
float v2 = dFabs (last_lambda[i]);
float max = (v1 > v2) ? v1 : v2;
if (max > 0) {
//@@@ relative error: order[i].error = dFabs(lambda[i]-last_lambda[i])/max;
order[i].error = dFabs(lambda[i]-last_lambda[i]);
}
else {
order[i].error = dInfinity;
}
order[i].findex = findex[i];
order[i].index = i;
}
}
qsort (order,m,sizeof(IndexError),&compare_index_error);
#endif
#ifdef RANDOMLY_REORDER_CONSTRAINTS
if ((iteration & 7) == 0) {
for (i=1; i<m; ++i) {
IndexError tmp = order[i];
int swapi = dRandInt2(i+1);
order[i] = order[swapi];
order[swapi] = tmp;
}
}
#endif
//@@@ potential optimization: swap lambda and last_lambda pointers rather
// than copying the data. we must make sure lambda is properly
// returned to the caller
memcpy (last_lambda,lambda,m*sizeof(float));
for (int i=0; i<m; i++) {
// @@@ potential optimization: we could pre-sort J and iMJ, thereby
// linearizing access to those arrays. hmmm, this does not seem
// like a win, but we should think carefully about our memory
// access pattern.
int index = order[i].index;
J_ptr = J + index*12;
iMJ_ptr = iMJ + index*12;
// set the limits for this constraint. note that 'hicopy' is used.
// this is the place where the QuickStep method differs from the
// direct LCP solving method, since that method only performs this
// limit adjustment once per time step, whereas this method performs
// once per iteration per constraint row.
// the constraints are ordered so that all lambda[] values needed have
// already been computed.
if (findex[index] >= 0) {
hi[index] = fabsf (hicopy[index] * lambda[findex[index]]);
lo[index] = -hi[index];
}
int b1 = jb[index*2];
int b2 = jb[index*2+1];
float delta = rhs[index] - lambda[index]*Ad[index];
dRealMutablePtr fc_ptr = invMforce + 6*b1;
// @@@ potential optimization: SIMD-ize this and the b2 >= 0 case
delta -=fc_ptr[0] * J_ptr[0] + fc_ptr[1] * J_ptr[1] +
fc_ptr[2] * J_ptr[2] + fc_ptr[3] * J_ptr[3] +
fc_ptr[4] * J_ptr[4] + fc_ptr[5] * J_ptr[5];
// @@@ potential optimization: handle 1-body constraints in a separate
// loop to avoid the cost of test & jump?
if (b2 >= 0) {
fc_ptr = invMforce + 6*b2;
delta -=fc_ptr[0] * J_ptr[6] + fc_ptr[1] * J_ptr[7] +
fc_ptr[2] * J_ptr[8] + fc_ptr[3] * J_ptr[9] +
fc_ptr[4] * J_ptr[10] + fc_ptr[5] * J_ptr[11];
}
// compute lambda and clamp it to [lo,hi].
// @@@ potential optimization: does SSE have clamping instructions
// to save test+jump penalties here?
float new_lambda = lambda[index] + delta;
if (new_lambda < lo[index]) {
delta = lo[index]-lambda[index];
lambda[index] = lo[index];
}
else if (new_lambda > hi[index]) {
delta = hi[index]-lambda[index];
lambda[index] = hi[index];
}
else {
lambda[index] = new_lambda;
}
//@@@ a trick that may or may not help
//float ramp = (1-((float)(iteration+1)/(float)num_iterations));
//delta *= ramp;
// update invMforce.
// @@@ potential optimization: SIMD for this and the b2 >= 0 case
fc_ptr = invMforce + 6*b1;
fc_ptr[0] += delta * iMJ_ptr[0];
fc_ptr[1] += delta * iMJ_ptr[1];
fc_ptr[2] += delta * iMJ_ptr[2];
fc_ptr[3] += delta * iMJ_ptr[3];
fc_ptr[4] += delta * iMJ_ptr[4];
fc_ptr[5] += delta * iMJ_ptr[5];
// @@@ potential optimization: handle 1-body constraints in a separate
// loop to avoid the cost of test & jump?
if (b2 >= 0) {
fc_ptr = invMforce + 6*b2;
fc_ptr[0] += delta * iMJ_ptr[6];
fc_ptr[1] += delta * iMJ_ptr[7];
fc_ptr[2] += delta * iMJ_ptr[8];
fc_ptr[3] += delta * iMJ_ptr[9];
fc_ptr[4] += delta * iMJ_ptr[10];
fc_ptr[5] += delta * iMJ_ptr[11];
}
}
}
}
void SolveInternal1 (float global_cfm,
float global_erp,
RigidBody * const *body, int nb,
BU_Joint * const *_joint,
int nj,
const ContactSolverInfo& solverInfo)
{
int numIter = 30;
float sOr = 1.3f;
int i,j;
SimdScalar stepsize1 = dRecip(solverInfo.m_timeStep);
// number all bodies in the body list - set their tag values
for (i=0; i<nb; i++)
body[i]->m_odeTag = i;
// make a local copy of the joint array, because we might want to modify it.
// (the "BU_Joint *const*" declaration says we're allowed to modify the joints
// but not the joint array, because the caller might need it unchanged).
//@@@ do we really need to do this? we'll be sorting constraint rows individually, not joints
BU_Joint **joint = (BU_Joint**) alloca (nj * sizeof(BU_Joint*));
memcpy (joint,_joint,nj * sizeof(BU_Joint*));
// for all bodies, compute the inertia tensor and its inverse in the global
// frame, and compute the rotational force and add it to the torque
// accumulator. I and invI are a vertical stack of 3x4 matrices, one per body.
dRealAllocaArray (I,3*4*nb);
dRealAllocaArray (invI,3*4*nb);
/* for (i=0; i<nb; i++) {
dMatrix3 tmp;
// compute inertia tensor in global frame
dMULTIPLY2_333 (tmp,body[i]->m_I,body[i]->m_R);
// compute inverse inertia tensor in global frame
dMULTIPLY2_333 (tmp,body[i]->m_invI,body[i]->m_R);
dMULTIPLY0_333 (invI+i*12,body[i]->m_R,tmp);
// compute rotational force
dCROSS (body[i]->m_tacc,-=,body[i]->getAngularVelocity(),tmp);
}
*/
for (i=0; i<nb; i++) {
dMatrix3 tmp;
// compute inertia tensor in global frame
dMULTIPLY2_333 (tmp,body[i]->m_I,body[i]->m_R);
dMULTIPLY0_333 (I+i*12,body[i]->m_R,tmp);
// compute inverse inertia tensor in global frame
dMULTIPLY2_333 (tmp,body[i]->m_invI,body[i]->m_R);
dMULTIPLY0_333 (invI+i*12,body[i]->m_R,tmp);
// compute rotational force
dMULTIPLY0_331 (tmp,I+i*12,body[i]->getAngularVelocity());
//dCROSS (body[i]->tacc,-=,body[i]->avel,tmp);
dCROSS (body[i]->m_tacc,-=,body[i]->getAngularVelocity(),tmp);
}
// get joint information (m = total constraint dimension, nub = number of unbounded variables).
// joints with m=0 are inactive and are removed from the joints array
// entirely, so that the code that follows does not consider them.
//@@@ do we really need to save all the info1's
BU_Joint::Info1 *info = (BU_Joint::Info1*) alloca (nj*sizeof(BU_Joint::Info1));
for (i=0, j=0; j<nj; j++) { // i=dest, j=src
joint[j]->GetInfo1 (info+i);
dIASSERT (info[i].m >= 0 && info[i].m <= 6 && info[i].nub >= 0 && info[i].nub <= info[i].m);
if (info[i].m > 0) {
joint[i] = joint[j];
i++;
}
}
nj = i;
// create the row offset array
int m = 0;
int *ofs = (int*) alloca (nj*sizeof(int));
for (i=0; i<nj; i++) {
ofs[i] = m;
m += info[i].m;
}
// if there are constraints, compute the constraint force
dRealAllocaArray (J,m*12);
int *jb = (int*) alloca (m*2*sizeof(int));
if (m > 0) {
// create a constraint equation right hand side vector `c', a constraint
// force mixing vector `cfm', and LCP low and high bound vectors, and an
// 'findex' vector.
dRealAllocaArray (c,m);
dRealAllocaArray (cfm,m);
dRealAllocaArray (lo,m);
dRealAllocaArray (hi,m);
int *findex = (int*) alloca (m*sizeof(int));
dSetZero1 (c,m);
dSetValue1 (cfm,m,global_cfm);
dSetValue1 (lo,m,-dInfinity);
dSetValue1 (hi,m, dInfinity);
for (i=0; i<m; i++) findex[i] = -1;
// get jacobian data from constraints. an m*12 matrix will be created
// to store the two jacobian blocks from each constraint. it has this
// format:
//
// l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 \ .
// l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 }-- jacobian for joint 0, body 1 and body 2 (3 rows)
// l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 /
// l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 }--- jacobian for joint 1, body 1 and body 2 (3 rows)
// etc...
//
// (lll) = linear jacobian data
// (aaa) = angular jacobian data
//
dSetZero1 (J,m*12);
BU_Joint::Info2 Jinfo;
Jinfo.rowskip = 12;
Jinfo.fps = stepsize1;
Jinfo.erp = global_erp;
for (i=0; i<nj; i++) {
Jinfo.J1l = J + ofs[i]*12;
Jinfo.J1a = Jinfo.J1l + 3;
Jinfo.J2l = Jinfo.J1l + 6;
Jinfo.J2a = Jinfo.J1l + 9;
Jinfo.c = c + ofs[i];
Jinfo.cfm = cfm + ofs[i];
Jinfo.lo = lo + ofs[i];
Jinfo.hi = hi + ofs[i];
Jinfo.findex = findex + ofs[i];
joint[i]->GetInfo2 (&Jinfo);
if (Jinfo.c[0] > solverInfo.m_maxErrorReduction)
Jinfo.c[0] = solverInfo.m_maxErrorReduction;
// adjust returned findex values for global index numbering
for (j=0; j<info[i].m; j++) {
if (findex[ofs[i] + j] >= 0)
findex[ofs[i] + j] += ofs[i];
}
}
// create an array of body numbers for each joint row
int *jb_ptr = jb;
for (i=0; i<nj; i++) {
int b1 = (joint[i]->node[0].body) ? (joint[i]->node[0].body->m_odeTag) : -1;
int b2 = (joint[i]->node[1].body) ? (joint[i]->node[1].body->m_odeTag) : -1;
for (j=0; j<info[i].m; j++) {
jb_ptr[0] = b1;
jb_ptr[1] = b2;
jb_ptr += 2;
}
}
dIASSERT (jb_ptr == jb+2*m);
// compute the right hand side `rhs'
dRealAllocaArray (tmp1,nb*6);
// put v/h + invM*fe into tmp1
for (i=0; i<nb; i++) {
SimdScalar body_invMass = body[i]->getInvMass();
for (j=0; j<3; j++) tmp1[i*6+j] = body[i]->m_facc[j] * body_invMass + body[i]->getLinearVelocity()[j] * stepsize1;
dMULTIPLY0_331NEW (tmp1 + i*6 + 3,=,invI + i*12,body[i]->m_tacc);
for (j=0; j<3; j++) tmp1[i*6+3+j] += body[i]->getAngularVelocity()[j] * stepsize1;
}
// put J*tmp1 into rhs
dRealAllocaArray (rhs,m);
multiply_J (m,J,jb,tmp1,rhs);
// complete rhs
for (i=0; i<m; i++) rhs[i] = c[i]*stepsize1 - rhs[i];
// scale CFM
for (i=0; i<m; i++)
cfm[i] =0;//*= stepsize1;
// load lambda from the value saved on the previous iteration
dRealAllocaArray (lambda,m);
#ifdef WARM_STARTING
dSetZero1 (lambda,m); //@@@ shouldn't be necessary
for (i=0; i<nj; i++) {
memcpy (lambda+ofs[i],joint[i]->lambda,info[i].m * sizeof(SimdScalar));
}
#endif
// solve the LCP problem and get lambda and invM*constraint_force
dRealAllocaArray (cforce,nb*6);
SOR_LCP (m,nb,J,jb,body,invI,lambda,cforce,rhs,lo,hi,cfm,findex,numIter,sOr);
#ifdef WARM_STARTING
// save lambda for the next iteration
//@@@ note that this doesn't work for contact joints yet, as they are
// recreated every iteration
for (i=0; i<nj; i++) {
memcpy (joint[i]->lambda,lambda+ofs[i],info[i].m * sizeof(SimdScalar));
}
#endif
// note that the SOR method overwrites rhs and J at this point, so
// they should not be used again.
// add stepsize * cforce to the body velocity
for (i=0; i<nb; i++) {
SimdVector3 linvel = body[i]->getLinearVelocity();
SimdVector3 angvel = body[i]->getAngularVelocity();
for (j=0; j<3; j++)
linvel[j] += solverInfo.m_timeStep* cforce[i*6+j];
for (j=0; j<3; j++)
angvel[j] += solverInfo.m_timeStep* cforce[i*6+3+j];
body[i]->setLinearVelocity(linvel);
body[i]->setAngularVelocity(angvel);
}
}
// compute the velocity update:
// add stepsize * invM * fe to the body velocity
for (i=0; i<nb; i++) {
SimdScalar body_invMass = body[i]->getInvMass();
SimdVector3 linvel = body[i]->getLinearVelocity();
SimdVector3 angvel = body[i]->getAngularVelocity();
for (j=0; j<3; j++)
{
linvel[j] += solverInfo.m_timeStep * body_invMass * body[i]->m_facc[j];
}
for (j=0; j<3; j++)
{
body[i]->m_tacc[j] *= solverInfo.m_timeStep;
}
dMULTIPLY0_331NEW(angvel,+=,invI + i*12,body[i]->m_tacc);
body[i]->setAngularVelocity(angvel);
}
}
#endif //USE_SOR_SOLVER

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#define USE_SOR_SOLVER
#ifdef USE_SOR_SOLVER
#ifndef SOR_LCP_H
#define SOR_LCP_H
class RigidBody;
class BU_Joint;
#include "SimdScalar.h"
struct ContactSolverInfo;
void SolveInternal1 (float global_cfm,
float global_erp,
RigidBody * const *body, int nb,
BU_Joint * const *_joint, int nj, const ContactSolverInfo& info);
int dRandInt2 (int n);
#endif //SOR_LCP_H
#endif //USE_SOR_SOLVER

View File

@@ -0,0 +1,10 @@
#include "BU_Joint.h"
BU_Joint::BU_Joint()
{
}
BU_Joint::~BU_Joint()
{
}

View File

@@ -0,0 +1,78 @@
#ifndef BU_Joint_H
#define BU_Joint_H
class RigidBody;
class BU_Joint;
#include "SimdScalar.h"
struct BU_ContactJointNode {
BU_Joint *joint; // pointer to enclosing BU_Joint object
RigidBody*body; // *other* body this joint is connected to
};
typedef SimdScalar dVector3[4];
class BU_Joint {
public:
// naming convention: the "first" body this is connected to is node[0].body,
// and the "second" body is node[1].body. if this joint is only connected
// to one body then the second body is 0.
// info returned by getInfo1 function. the constraint dimension is m (<=6).
// i.e. that is the total number of rows in the jacobian. `nub' is the
// number of unbounded variables (which have lo,hi = -/+ infinity).
BU_Joint();
virtual ~BU_Joint();
struct Info1 {
int m,nub;
};
// info returned by getInfo2 function
struct Info2 {
// integrator parameters: frames per second (1/stepsize), default error
// reduction parameter (0..1).
SimdScalar fps,erp;
// for the first and second body, pointers to two (linear and angular)
// n*3 jacobian sub matrices, stored by rows. these matrices will have
// been initialized to 0 on entry. if the second body is zero then the
// J2xx pointers may be 0.
SimdScalar *J1l,*J1a,*J2l,*J2a;
// elements to jump from one row to the next in J's
int rowskip;
// right hand sides of the equation J*v = c + cfm * lambda. cfm is the
// "constraint force mixing" vector. c is set to zero on entry, cfm is
// set to a constant value (typically very small or zero) value on entry.
SimdScalar *c,*cfm;
// lo and hi limits for variables (set to -/+ infinity on entry).
SimdScalar *lo,*hi;
// findex vector for variables. see the LCP solver interface for a
// description of what this does. this is set to -1 on entry.
// note that the returned indexes are relative to the first index of
// the constraint.
int *findex;
};
// virtual function table: size of the joint structure, function pointers.
// we do it this way instead of using C++ virtual functions because
// sometimes we need to allocate joints ourself within a memory pool.
virtual void GetInfo1 (Info1 *info)=0;
virtual void GetInfo2 (Info2 *info)=0;
int flags; // dJOINT_xxx flags
BU_ContactJointNode node[2]; // connections to bodies. node[1].body can be 0
SimdScalar lambda[6]; // lambda generated by last step
};
#endif //BU_Joint_H

View File

@@ -0,0 +1,233 @@
#include "ContactJoint.h"
#include "RigidBody.h"
#include "NarrowPhaseCollision/PersistentManifold.h"
ContactJoint::ContactJoint(PersistentManifold* manifold,int index,bool swap,RigidBody* body0,RigidBody* body1)
:m_manifold(manifold),
m_index(index),
m_swapBodies(swap),
m_body0(body0),
m_body1(body1)
{
}
int m_numRows = 3;
float gContactFrictionFactor = 30.5f;//100.f;//1e30f;//2.9f;
void ContactJoint::GetInfo1(Info1 *info)
{
info->m = m_numRows;
//friction adds another 2...
info->nub = 0;
}
#define dCROSS(a,op,b,c) \
(a)[0] op ((b)[1]*(c)[2] - (b)[2]*(c)[1]); \
(a)[1] op ((b)[2]*(c)[0] - (b)[0]*(c)[2]); \
(a)[2] op ((b)[0]*(c)[1] - (b)[1]*(c)[0]);
#define M_SQRT12 SimdScalar(0.7071067811865475244008443621048490)
#define dRecipSqrt(x) ((float)(1.0f/sqrtf(float(x)))) /* reciprocal square root */
void dPlaneSpace1 (const dVector3 n, dVector3 p, dVector3 q)
{
if (fabsf(n[2]) > M_SQRT12) {
// choose p in y-z plane
SimdScalar a = n[1]*n[1] + n[2]*n[2];
SimdScalar k = dRecipSqrt (a);
p[0] = 0;
p[1] = -n[2]*k;
p[2] = n[1]*k;
// set q = n x p
q[0] = a*k;
q[1] = -n[0]*p[2];
q[2] = n[0]*p[1];
}
else {
// choose p in x-y plane
SimdScalar a = n[0]*n[0] + n[1]*n[1];
SimdScalar k = dRecipSqrt (a);
p[0] = -n[1]*k;
p[1] = n[0]*k;
p[2] = 0;
// set q = n x p
q[0] = -n[2]*p[1];
q[1] = n[2]*p[0];
q[2] = a*k;
}
}
void ContactJoint::GetInfo2(Info2 *info)
{
int s = info->rowskip;
int s2 = 2*s;
float swapFactor = m_swapBodies ? -1.f : 1.f;
// get normal, with sign adjusted for body1/body2 polarity
dVector3 normal;
ManifoldPoint& point = m_manifold->GetContactPoint(m_index);
normal[0] = swapFactor*point.m_normalWorldOnB[0];
normal[1] = swapFactor*point.m_normalWorldOnB[1];
normal[2] = swapFactor*point.m_normalWorldOnB[2];
normal[3] = 0; // @@@ hmmm
// if (GetBody0())
SimdVector3 ccc1;
{
ccc1 = point.GetPositionWorldOnA() - m_body0->getCenterOfMassPosition();
dVector3 c1;
c1[0] = ccc1[0];
c1[1] = ccc1[1];
c1[2] = ccc1[2];
// set jacobian for normal
info->J1l[0] = normal[0];
info->J1l[1] = normal[1];
info->J1l[2] = normal[2];
dCROSS (info->J1a,=,c1,normal);
}
// if (GetBody1())
SimdVector3 ccc2;
{
dVector3 c2;
ccc2 = point.GetPositionWorldOnB() - m_body1->getCenterOfMassPosition();
// for (i=0; i<3; i++) c2[i] = j->contact.geom.pos[i] -
// j->node[1].body->pos[i];
c2[0] = ccc2[0];
c2[1] = ccc2[1];
c2[2] = ccc2[2];
info->J2l[0] = -normal[0];
info->J2l[1] = -normal[1];
info->J2l[2] = -normal[2];
dCROSS (info->J2a,= -,c2,normal);
}
SimdScalar k = info->fps * info->erp;
float depth = -point.GetDistance();
if (depth < 0.f)
depth = 0.f;
info->c[0] = k * depth;
// set LCP limits for normal
info->lo[0] = 0;
info->hi[0] = 1e30f;//dInfinity;
#define DO_THE_FRICTION_2
#ifdef DO_THE_FRICTION_2
// now do jacobian for tangential forces
dVector3 t1,t2; // two vectors tangential to normal
dVector3 c1;
c1[0] = ccc1[0];
c1[1] = ccc1[1];
c1[2] = ccc1[2];
dVector3 c2;
c2[0] = ccc2[0];
c2[1] = ccc2[1];
c2[2] = ccc2[2];
// first friction direction
if (m_numRows >= 2)
{
dPlaneSpace1 (normal,t1,t2);
info->J1l[s+0] = t1[0];
info->J1l[s+1] = t1[1];
info->J1l[s+2] = t1[2];
dCROSS (info->J1a+s,=,c1,t1);
if (1) { //j->node[1].body) {
info->J2l[s+0] = -t1[0];
info->J2l[s+1] = -t1[1];
info->J2l[s+2] = -t1[2];
dCROSS (info->J2a+s,= -,c2,t1);
}
// set right hand side
if (0) {//j->contact.surface.mode & dContactMotion1) {
//info->c[1] = j->contact.surface.motion1;
}
// set LCP bounds and friction index. this depends on the approximation
// mode
//1e30f
info->lo[1] = -gContactFrictionFactor;//-j->contact.surface.mu;
info->hi[1] = gContactFrictionFactor;//j->contact.surface.mu;
if (0)//j->contact.surface.mode & dContactApprox1_1)
info->findex[1] = 0;
// set slip (constraint force mixing)
if (0)//j->contact.surface.mode & dContactSlip1)
{
// info->cfm[1] = j->contact.surface.slip1;
}
}
// second friction direction
if (m_numRows >= 3) {
info->J1l[s2+0] = t2[0];
info->J1l[s2+1] = t2[1];
info->J1l[s2+2] = t2[2];
dCROSS (info->J1a+s2,=,c1,t2);
if (1) { //j->node[1].body) {
info->J2l[s2+0] = -t2[0];
info->J2l[s2+1] = -t2[1];
info->J2l[s2+2] = -t2[2];
dCROSS (info->J2a+s2,= -,c2,t2);
}
// set right hand side
if (0){//j->contact.surface.mode & dContactMotion2) {
//info->c[2] = j->contact.surface.motion2;
}
// set LCP bounds and friction index. this depends on the approximation
// mode
if (0){//j->contact.surface.mode & dContactMu2) {
//info->lo[2] = -j->contact.surface.mu2;
//info->hi[2] = j->contact.surface.mu2;
}
else {
info->lo[2] = -gContactFrictionFactor;
info->hi[2] = gContactFrictionFactor;
}
if (0)//j->contact.surface.mode & dContactApprox1_2)
{
info->findex[2] = 0;
}
// set slip (constraint force mixing)
if (0) //j->contact.surface.mode & dContactSlip2)
{
//info->cfm[2] = j->contact.surface.slip2;
}
}
#endif //DO_THE_FRICTION_2
}

View File

@@ -0,0 +1,33 @@
#ifndef CONTACT_JOINT_H
#define CONTACT_JOINT_H
#include "BU_Joint.h"
class RigidBody;
class PersistentManifold;
class ContactJoint : public BU_Joint
{
PersistentManifold* m_manifold;
int m_index;
bool m_swapBodies;
RigidBody* m_body0;
RigidBody* m_body1;
public:
ContactJoint() {};
ContactJoint(PersistentManifold* manifold,int index,bool swap,RigidBody* body0,RigidBody* body1);
//BU_Joint interface for solver
virtual void GetInfo1(Info1 *info);
virtual void GetInfo2(Info2 *info);
};
#endif //CONTACT_JOINT_H

View File

@@ -0,0 +1,18 @@
#ifndef MASS_PROPS_H
#define MASS_PROPS_H
#include <SimdVector3.h>
struct MassProps {
MassProps(float mass,const SimdVector3& inertiaLocal):
m_mass(mass),
m_inertiaLocal(inertiaLocal)
{
}
float m_mass;
SimdVector3 m_inertiaLocal;
};
#endif

View File

@@ -0,0 +1,157 @@
#include "RigidBody.h"
#include "MassProps.h"
#include "CollisionShapes/ConvexShape.h"
#include "GEN_minmax.h"
#include <SimdTransformUtil.h>
float gRigidBodyDamping = 0.5f;
static int uniqueId = 0;
RigidBody::RigidBody( const MassProps& massProps,SimdScalar linearDamping,SimdScalar angularDamping)
: m_collisionShape(0),
m_activationState1(1),
m_hitFraction(1.f),
m_gravity(0.0f, 0.0f, 0.0f),
m_linearDamping(0.f),
m_angularDamping(0.5f),
m_totalForce(0.0f, 0.0f, 0.0f),
m_totalTorque(0.0f, 0.0f, 0.0f),
m_linearVelocity(0.0f, 0.0f, 0.0f),
m_angularVelocity(0.f,0.f,0.f)
{
m_debugBodyId = uniqueId++;
setMassProps(massProps.m_mass, massProps.m_inertiaLocal);
setDamping(linearDamping, angularDamping);
updateInertiaTensor();
m_worldTransform.setIdentity();
}
void RigidBody::setLinearVelocity(const SimdVector3& lin_vel)
{
m_linearVelocity = lin_vel;
}
void RigidBody::predictIntegratedTransform(SimdScalar timeStep,SimdTransform& predictedTransform) const
{
SimdTransformUtil::IntegrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform);
}
void RigidBody::getAabb(SimdVector3& aabbMin,SimdVector3& aabbMax) const
{
m_collisionShape ->GetAabb(m_worldTransform,aabbMin,aabbMax);
}
void RigidBody::SetCollisionShape(CollisionShape* mink)
{
m_collisionShape = mink;
SimdTransform ident;
ident.setIdentity();
SimdVector3 aabbMin,aabbMax;
m_collisionShape ->GetAabb(ident,aabbMin,aabbMax);
SimdVector3 diag = (aabbMax-aabbMin)*0.5f;
}
void RigidBody::setGravity(const SimdVector3& acceleration)
{
if (m_inverseMass != 0.0f)
{
m_gravity = acceleration * (1.0f / m_inverseMass);
}
}
bool RigidBody::mergesSimulationIslands() const
{
return ( getInvMass() != 0) ;
}
void RigidBody::SetActivationState(int newState)
{
m_activationState1 = newState;
}
void RigidBody::setDamping(SimdScalar lin_damping, SimdScalar ang_damping)
{
m_linearDamping = GEN_clamped(lin_damping, 0.0f, 1.0f);
m_angularDamping = GEN_clamped(ang_damping, 0.0f, 1.0f);
}
#include <stdio.h>
void RigidBody::applyForces(SimdScalar step)
{
applyCentralForce(m_gravity);
m_linearVelocity *= GEN_clamped((1.f - step * m_linearDamping), 0.0f, 1.0f);
m_angularVelocity *= GEN_clamped((1.f - step * m_angularDamping), 0.0f, 1.0f);
}
void RigidBody::proceedToTransform(const SimdTransform& newTrans)
{
setCenterOfMassTransform( newTrans );
}
void RigidBody::setMassProps(SimdScalar mass, const SimdVector3& inertia)
{
m_inverseMass = mass != 0.0f ? 1.0f / mass : 0.0f;
m_invInertiaLocal.setValue(inertia[0] != 0.0f ? 1.0f / inertia[0]: 0.0f,
inertia[1] != 0.0f ? 1.0f / inertia[1]: 0.0f,
inertia[2] != 0.0f ? 1.0f / inertia[2]: 0.0f);
}
void RigidBody::updateInertiaTensor()
{
m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose();
}
void RigidBody::integrateVelocities(SimdScalar step)
{
m_linearVelocity += m_totalForce * (m_inverseMass * step);
m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step;
#define MAX_ANGVEL SIMD_HALF_PI
/// clamp angular velocity. collision calculations will fail on higher angular velocities
float angvel = m_angularVelocity.length();
if (angvel*step > MAX_ANGVEL)
{
m_angularVelocity *= (MAX_ANGVEL/step) /angvel;
}
clearForces();
}
SimdQuaternion RigidBody::getOrientation() const
{
SimdQuaternion orn;
m_worldTransform.getBasis().getRotation(orn);
return orn;
}
void RigidBody::setCenterOfMassTransform(const SimdTransform& xform)
{
m_worldTransform = xform;
// m_worldTransform.getBasis().getRotation(m_orn1);
updateInertiaTensor();
}

View File

@@ -0,0 +1,165 @@
#ifndef RIGIDBODY_H
#define RIGIDBODY_H
#include <vector>
#include <SimdPoint3.h>
#include <SimdTransform.h>
class CollisionShape;
struct MassProps;
typedef SimdScalar dMatrix3[4*3];
/// RigidBody class for RigidBody Dynamics
///
class RigidBody {
public:
RigidBody(const MassProps& massProps,SimdScalar linearDamping,SimdScalar angularDamping);
void proceedToTransform(const SimdTransform& newTrans);
bool mergesSimulationIslands() const;
/// continuous collision detection needs prediction
void predictIntegratedTransform(SimdScalar step, SimdTransform& predictedTransform) const;
void applyForces(SimdScalar step);
void setGravity(const SimdVector3& acceleration);
void setDamping(SimdScalar lin_damping, SimdScalar ang_damping);
CollisionShape* GetCollisionShape() { return m_collisionShape; }
void setMassProps(SimdScalar mass, const SimdVector3& inertia);
SimdScalar getInvMass() const { return m_inverseMass; }
const SimdMatrix3x3& getInvInertiaTensorWorld() const { return m_invInertiaTensorWorld; }
void integrateVelocities(SimdScalar step);
void setCenterOfMassTransform(const SimdTransform& xform);
void applyCentralForce(const SimdVector3& force)
{
m_totalForce += force;
}
const SimdVector3& getInvInertiaDiagLocal()
{
return m_invInertiaLocal;
};
void setInvInertiaDiagLocal(const SimdVector3& diagInvInertia)
{
m_invInertiaLocal = diagInvInertia;
}
void applyTorque(const SimdVector3& torque)
{
m_totalTorque += torque;
}
void applyForce(const SimdVector3& force, const SimdVector3& rel_pos)
{
applyCentralForce(force);
applyTorque(rel_pos.cross(force));
}
void applyCentralImpulse(const SimdVector3& impulse)
{
m_linearVelocity += impulse * m_inverseMass;
}
void applyTorqueImpulse(const SimdVector3& torque)
{
m_angularVelocity += m_invInertiaTensorWorld * torque;
}
void applyImpulse(const SimdVector3& impulse, const SimdVector3& rel_pos)
{
if (m_inverseMass != 0.f)
{
applyCentralImpulse(impulse);
applyTorqueImpulse(rel_pos.cross(impulse));
}
}
void clearForces()
{
m_totalForce.setValue(0.0f, 0.0f, 0.0f);
m_totalTorque.setValue(0.0f, 0.0f, 0.0f);
}
void updateInertiaTensor();
const SimdPoint3& getCenterOfMassPosition() const { return m_worldTransform.getOrigin(); }
SimdQuaternion getOrientation() const;
const SimdTransform& getCenterOfMassTransform() const { return m_worldTransform; }
const SimdVector3& getLinearVelocity() const { return m_linearVelocity; }
const SimdVector3& getAngularVelocity() const { return m_angularVelocity; }
void setLinearVelocity(const SimdVector3& lin_vel);
void setAngularVelocity(const SimdVector3& ang_vel) { m_angularVelocity = ang_vel; }
SimdVector3 getVelocityInLocalPoint(const SimdVector3& rel_pos) const
{
return m_linearVelocity + m_angularVelocity.cross(rel_pos);
}
void translate(const SimdVector3& v)
{
m_worldTransform.getOrigin() += v;
}
void SetCollisionShape(CollisionShape* mink);
void getAabb(SimdVector3& aabbMin,SimdVector3& aabbMax) const;
int GetActivationState() const { return m_activationState1;}
void SetActivationState(int newState);
private:
SimdTransform m_worldTransform;
SimdMatrix3x3 m_invInertiaTensorWorld;
SimdVector3 m_gravity;
SimdVector3 m_invInertiaLocal;
SimdVector3 m_totalForce;
SimdVector3 m_totalTorque;
SimdQuaternion m_orn1;
SimdVector3 m_linearVelocity;
SimdVector3 m_angularVelocity;
SimdScalar m_linearDamping;
SimdScalar m_angularDamping;
SimdScalar m_inverseMass;
CollisionShape* m_collisionShape;
public:
/// for ode solver-binding
dMatrix3 m_R;//temp
dMatrix3 m_I;
dMatrix3 m_invI;
int m_islandTag1;//temp
int m_activationState1;//temp
int m_odeTag;
SimdVector3 m_tacc;//temp
SimdVector3 m_facc;
SimdScalar m_hitFraction; //time of impact calculation
int m_debugBodyId;
};
#endif

14
extern/bullet/BulletLicense.txt vendored Normal file
View File

@@ -0,0 +1,14 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
Free for commercial use, but please mail bullet@erwincoumans.com to report projects, and join the forum at
www.continuousphysics.com/Bullet/phpBB2

View File

@@ -0,0 +1,112 @@
# Microsoft Developer Studio Project File - Name="CcdPhysics" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=CcdPhysics - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "CcdPhysics.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "CcdPhysics.mak" CFG="CcdPhysics - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "CcdPhysics - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "CcdPhysics - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "CcdPhysics - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "CcdPhysics___Win32_Release"
# PROP BASE Intermediate_Dir "CcdPhysics___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "CcdPhysics___Win32_Release"
# PROP Intermediate_Dir "CcdPhysics___Win32_Release"
# PROP Target_Dir ""
LINK32=link.exe -lib
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\Bullet" /I "..\..\..\LinearMath" /I "..\..\..\BulletDynamics" /I "..\..\..\Extras\PhysicsInterface\Common" /I "..\..\..\Extras\PhysicsInterface\CcdPhysics" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "CcdPhysics - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "CcdPhysics___Win32_Debug"
# PROP BASE Intermediate_Dir "CcdPhysics___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "CcdPhysics___Win32_Debug"
# PROP Intermediate_Dir "CcdPhysics___Win32_Debug"
# PROP Target_Dir ""
LINK32=link.exe -lib
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\Bullet" /I "..\..\..\LinearMath" /I "..\..\..\BulletDynamics" /I "..\..\..\Extras\PhysicsInterface\Common" /I "..\..\..\Extras\PhysicsInterface\CcdPhysics" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "CcdPhysics - Win32 Release"
# Name "CcdPhysics - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\CcdPhysicsController.cpp
# End Source File
# Begin Source File
SOURCE=.\CcdPhysicsEnvironment.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\CcdPhysicsController.h
# End Source File
# Begin Source File
SOURCE=.\CcdPhysicsEnvironment.h
# End Source File
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,230 @@
#include "CcdPhysicsController.h"
#include "Dynamics/RigidBody.h"
#include "PHY_IMotionState.h"
#include "BroadphaseCollision/BroadphaseProxy.h"
#include "CollisionShapes/ConvexShape.h"
class BP_Proxy;
bool gEnableSleeping = true;//false;//true;
#include "Dynamics/MassProps.h"
SimdVector3 startVel(0,0,0);//-10000);
CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
{
m_collisionDelay = 0;
m_sleepingCounter = 0;
m_MotionState = ci.m_MotionState;
SimdTransform trans;
float tmp[3];
m_MotionState->getWorldPosition(tmp[0],tmp[1],tmp[2]);
trans.setOrigin(SimdVector3(tmp[0],tmp[1],tmp[2]));
SimdQuaternion orn;
m_MotionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
trans.setRotation(orn);
MassProps mp(ci.m_mass, ci.m_localInertiaTensor);
m_body = new RigidBody(mp,0,0);
m_broadphaseHandle = ci.m_broadphaseHandle;
m_collisionShape = ci.m_collisionShape;
//
// init the rigidbody properly
//
m_body->setMassProps(ci.m_mass, ci.m_localInertiaTensor);
m_body->setGravity( ci.m_gravity);
m_friction = ci.m_friction;
m_restitution = ci.m_restitution;
m_body->setDamping(ci.m_linearDamping, ci.m_angularDamping);
m_body->setCenterOfMassTransform( trans );
#ifdef WIN32
if (m_body->getInvMass())
m_body->setLinearVelocity(startVel);
#endif
}
CcdPhysicsController::~CcdPhysicsController()
{
//will be reference counted, due to sharing
//delete m_collisionShape;
delete m_MotionState;
delete m_body;
}
/**
SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
*/
bool CcdPhysicsController::SynchronizeMotionStates(float time)
{
const SimdVector3& worldPos = m_body->getCenterOfMassPosition();
m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
const SimdQuaternion& worldquat = m_body->getOrientation();
m_MotionState->setWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]);
m_MotionState->calculateWorldTransformations();
float scale[3];
m_MotionState->getWorldScaling(scale[0],scale[1],scale[2]);
SimdVector3 scaling(scale[0],scale[1],scale[2]);
m_collisionShape->setLocalScaling(scaling);
return true;
}
/**
WriteMotionStateToDynamics synchronizes dynas, kinematic and deformable entities (and do 'late binding')
*/
void CcdPhysicsController::WriteMotionStateToDynamics(bool nondynaonly)
{
}
void CcdPhysicsController::WriteDynamicsToMotionState()
{
}
// controller replication
void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)
{
}
// kinematic methods
void CcdPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)
{
SimdTransform xform = m_body->getCenterOfMassTransform();
xform.setOrigin(xform.getOrigin() + SimdVector3(dlocX,dlocY,dlocZ));
this->m_body->setCenterOfMassTransform(xform);
}
void CcdPhysicsController::RelativeRotate(const float drot[9],bool local)
{
}
void CcdPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)
{
}
void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)
{
}
void CcdPhysicsController::setPosition(float posX,float posY,float posZ)
{
}
void CcdPhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ)
{
}
void CcdPhysicsController::getPosition(PHY__Vector3& pos) const
{
assert(0);
}
void CcdPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ)
{
}
// physics methods
void CcdPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)
{
}
void CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local)
{
}
void CcdPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)
{
SimdVector3 angvel(ang_velX,ang_velY,ang_velZ);
m_body->setAngularVelocity(angvel);
}
void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)
{
SimdVector3 linVel(lin_velX,lin_velY,lin_velZ);
m_body->setLinearVelocity(linVel);
}
void CcdPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)
{
}
void CcdPhysicsController::SetActive(bool active)
{
}
// reading out information from physics
void CcdPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ)
{
}
void CcdPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)
{
}
void CcdPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
{
}
// dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted
void CcdPhysicsController::setRigidBody(bool rigid)
{
}
// clientinfo for raycasts for example
void* CcdPhysicsController::getNewClientInfo()
{
return 0;
}
void CcdPhysicsController::setNewClientInfo(void* clientinfo)
{
}
#ifdef WIN32
float gSleepingTreshold = 0.8f;
float gAngularSleepingTreshold = 1.f;
#else
float gSleepingTreshold = 0.8f;
float gAngularSleepingTreshold = 1.0f;
#endif
bool CcdPhysicsController::wantsSleeping()
{
if (!gEnableSleeping)
return false;
if ( (m_body->GetActivationState() == 3) || (m_body->GetActivationState() == 2))
return true;
if ((m_body->getLinearVelocity().length2() < gSleepingTreshold*gSleepingTreshold) &&
(m_body->getAngularVelocity().length2() < gAngularSleepingTreshold*gAngularSleepingTreshold))
{
m_sleepingCounter++;
} else
{
m_sleepingCounter=0;
}
if (m_sleepingCounter> 150)
{
return true;
}
return false;
}

View File

@@ -0,0 +1,133 @@
#ifndef BULLET2_PHYSICSCONTROLLER_H
#define BULLET2_PHYSICSCONTROLLER_H
#include "PHY_IPhysicsController.h"
/// PHY_IPhysicsController is the abstract simplified Interface to a physical object.
/// It contains the IMotionState and IDeformableMesh Interfaces.
#include "SimdVector3.h"
#include "SimdScalar.h"
class CollisionShape;
struct CcdConstructionInfo
{
CcdConstructionInfo()
: m_gravity(0,0,0),
m_mass(0.f),
m_friction(0.1f),
m_restitution(0.1f),
m_linearDamping(0.1f),
m_angularDamping(0.1f),
m_MotionState(0),
m_collisionShape(0)
{
}
SimdVector3 m_localInertiaTensor;
SimdVector3 m_gravity;
SimdScalar m_mass;
SimdScalar m_friction;
SimdScalar m_restitution;
SimdScalar m_linearDamping;
SimdScalar m_angularDamping;
void* m_broadphaseHandle;
class PHY_IMotionState* m_MotionState;
CollisionShape* m_collisionShape;
};
class RigidBody;
///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution.
class CcdPhysicsController : public PHY_IPhysicsController
{
RigidBody* m_body;
class PHY_IMotionState* m_MotionState;
CollisionShape* m_collisionShape;
int m_sleepingCounter;
public:
int m_collisionDelay;
SimdScalar m_friction;
SimdScalar m_restitution;
void* m_broadphaseHandle;
CcdPhysicsController (const CcdConstructionInfo& ci);
virtual ~CcdPhysicsController();
RigidBody* GetRigidBody() { return m_body;}
CollisionShape* GetCollisionShape() { return m_collisionShape;}
////////////////////////////////////
// PHY_IPhysicsController interface
////////////////////////////////////
/**
SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
*/
virtual bool SynchronizeMotionStates(float time);
/**
WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
*/
virtual void WriteMotionStateToDynamics(bool nondynaonly);
virtual void WriteDynamicsToMotionState();
// controller replication
virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl);
// kinematic methods
virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local);
virtual void RelativeRotate(const float drot[9],bool local);
virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal);
virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal);
virtual void setPosition(float posX,float posY,float posZ);
virtual void getPosition(PHY__Vector3& pos) const;
virtual void setScaling(float scaleX,float scaleY,float scaleZ);
// physics methods
virtual void ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local);
virtual void ApplyForce(float forceX,float forceY,float forceZ,bool local);
virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local);
virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local);
virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ);
virtual void SetActive(bool active);
// reading out information from physics
virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ);
virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ);
virtual void getReactionForce(float& forceX,float& forceY,float& forceZ);
// dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted
virtual void setRigidBody(bool rigid);
virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ);
// clientinfo for raycasts for example
virtual void* getNewClientInfo();
virtual void setNewClientInfo(void* clientinfo);
virtual PHY_IPhysicsController* GetReplica() {return 0;}
virtual void calcXform() {} ;
virtual void SetMargin(float margin) {};
virtual float GetMargin() const {return 0.f;};
bool wantsSleeping();
void SetAabb(const SimdVector3& aabbMin,const SimdVector3& aabbMax);
};
#endif //BULLET2_PHYSICSCONTROLLER_H

View File

@@ -0,0 +1,121 @@
#ifndef CCDPHYSICSENVIRONMENT
#define CCDPHYSICSENVIRONMENT
#include "PHY_IPhysicsEnvironment.h"
#include <vector>
class CcdPhysicsController;
#include "SimdVector3.h"
struct PHY_IPhysicsDebugDraw
{
virtual void DrawLine(const SimdVector3& from,const SimdVector3& to,const SimdVector3& color)=0;
};
class Point2PointConstraint;
class ToiContactDispatcher;
class Dispatcher;
//#include "BroadphaseInterface.h"
class Vehicle;
class PersistentManifold;
class BroadphaseInterface;
/// Physics Environment takes care of stepping the simulation and is a container for physics entities.
/// It stores rigidbodies,constraints, materials etc.
/// A derived class may be able to 'construct' entities by loading and/or converting
class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment
{
SimdVector3 m_gravity;
BroadphaseInterface* m_broadphase;
PHY_IPhysicsDebugDraw* m_debugDrawer;
public:
CcdPhysicsEnvironment(ToiContactDispatcher* dispatcher=0, BroadphaseInterface* broadphase=0);
virtual ~CcdPhysicsEnvironment();
/////////////////////////////////////
//PHY_IPhysicsEnvironment interface
/////////////////////////////////////
/// Perform an integration step of duration 'timeStep'.
virtual void setDebugDrawer(PHY_IPhysicsDebugDraw* debugDrawer)
{
m_debugDrawer = debugDrawer;
}
virtual void beginFrame() {};
virtual void endFrame() {};
/// Perform an integration step of duration 'timeStep'.
virtual bool proceedDeltaTime(double curTime,float timeStep);
virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep){};
//returns 0.f if no fixed timestep is used
virtual float getFixedTimeStep(){ return 0.f;};
virtual void setGravity(float x,float y,float z);
virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
float pivotX,float pivotY,float pivotZ,
float axisX,float axisY,float axisZ);
virtual void removeConstraint(int constraintid);
virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ);
//Methods for gamelogic collision/physics callbacks
//todo:
virtual void addSensor(PHY_IPhysicsController* ctrl) {};
virtual void removeSensor(PHY_IPhysicsController* ctrl){};
virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user){};
virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl){};
virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;};
virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight){ return 0;};
virtual int getNumContactPoints();
virtual void getContactPoint(int i,float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ);
//////////////////////
//CcdPhysicsEnvironment interface
////////////////////////
void addCcdPhysicsController(CcdPhysicsController* ctrl);
void removeCcdPhysicsController(CcdPhysicsController* ctrl);
BroadphaseInterface* GetBroadphase() { return m_broadphase; }
Dispatcher* GetDispatcher();
int GetNumControllers();
CcdPhysicsController* GetPhysicsController( int index);
int GetNumManifolds() const;
const PersistentManifold* GetManifold(int index) const;
private:
void UpdateActivationState();
void SyncMotionStates(float timeStep);
std::vector<CcdPhysicsController*> m_controllers;
std::vector<Point2PointConstraint*> m_p2pConstraints;
std::vector<Vehicle*> m_vehicles;
class ToiContactDispatcher* m_dispatcher;
bool m_scalingPropagated;
};
#endif //CCDPHYSICSENVIRONMENT

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="CcdPhysics"
ProjectGUID="{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\Common;..\..\..\LinearMath;..\..\..\Bullet;..\..\..\BulletDynamics"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/CcdPhysics.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\Common;..\..\..\LinearMath;..\..\..\Bullet;..\..\..\BulletDynamics"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/CcdPhysics.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\CcdPhysicsController.cpp">
</File>
<File
RelativePath=".\CcdPhysicsEnvironment.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\CcdPhysicsController.h">
</File>
<File
RelativePath=".\CcdPhysicsEnvironment.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
<File
RelativePath=".\ReadMe.txt">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="CcdPhysics"
ProjectGUID="{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="4"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\Common;..\..\..\LinearMath;..\..\..\Bullet;..\..\..\BulletDynamics"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/CcdPhysics.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="4"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\Common;..\..\..\LinearMath;..\..\..\Bullet;..\..\..\BulletDynamics"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/CcdPhysics.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\CcdPhysicsController.cpp"
>
</File>
<File
RelativePath=".\CcdPhysicsEnvironment.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\CcdPhysicsController.h"
>
</File>
<File
RelativePath=".\CcdPhysicsEnvironment.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<File
RelativePath=".\ReadMe.txt"
>
</File>
</Files>
</VisualStudioProject>

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2001-2005 Erwin Coumans <phy@erwincoumans.com>
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Erwin Coumans makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef __PHY_DYNAMIC_TYPES
#define __PHY_DYNAMIC_TYPES
class PHY_ResponseTable;
class PHY_Shape;
struct PHY__Vector3
{
float m_vec[4];
operator const float* () const
{
return &m_vec[0];
}
operator float* ()
{
return &m_vec[0];
}
};
//typedef float PHY__Vector3[4];
typedef enum
{
PHY_FH_RESPONSE,
PHY_SENSOR_RESPONSE, /* Touch Sensors */
PHY_CAMERA_RESPONSE, /* Visibility Culling */
PHY_OBJECT_RESPONSE, /* Object Dynamic Geometry Response */
PHY_STATIC_RESPONSE, /* Static Geometry Response */
PHY_NUM_RESPONSE
};
typedef struct PHY_CollData {
PHY__Vector3 m_point1; /* Point in object1 in world coordinates */
PHY__Vector3 m_point2; /* Point in object2 in world coordinates */
PHY__Vector3 m_normal; /* point2 - point1 */
} PHY_CollData;
typedef bool (*PHY_ResponseCallback)(void *client_data,
void *client_object1,
void *client_object2,
const PHY_CollData *coll_data);
/// PHY_PhysicsType enumerates all possible Physics Entities.
/// It is mainly used to create/add Physics Objects
typedef enum PHY_PhysicsType {
PHY_CONVEX_RIGIDBODY=16386,
PHY_CONCAVE_RIGIDBODY=16399,
PHY_CONVEX_FIXEDBODY=16388,//'collision object'
PHY_CONCAVE_FIXEDBODY=16401,
PHY_CONVEX_KINEMATICBODY=16387,//
PHY_CONCAVE_KINEMATICBODY=16400,
PHY_CONVEX_PHANTOMBODY=16398,
PHY_CONCAVE_PHANTOMBODY=16402
} PHY_PhysicsType;
/// PHY_ConstraintType enumerates all supported Constraint Types
typedef enum PHY_ConstraintType {
PHY_POINT2POINT_CONSTRAINT=1,
PHY_LINEHINGE_CONSTRAINT,
PHY_VEHICLE_CONSTRAINT
} PHY_ConstraintType;
typedef float PHY_Vector3[3];
#endif //__PHY_DYNAMIC_TYPES

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 2001-2005 Erwin Coumans <phy@erwincoumans.com>
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Erwin Coumans makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#include "PHY_IMotionState.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
PHY_IMotionState::~PHY_IMotionState()
{
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2001-2005 Erwin Coumans <phy@erwincoumans.com>
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Erwin Coumans makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef PHY__MOTIONSTATE_H
#define PHY__MOTIONSTATE_H
/**
PHY_IMotionState is the Interface to explicitly synchronize the world transformation.
Default implementations for mayor graphics libraries like OpenGL and DirectX can be provided.
*/
class PHY_IMotionState
{
public:
virtual ~PHY_IMotionState();
virtual void getWorldPosition(float& posX,float& posY,float& posZ)=0;
virtual void getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)=0;
virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)=0;
virtual void setWorldPosition(float posX,float posY,float posZ)=0;
virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)=0;
virtual void calculateWorldTransformations()=0;
};
#endif //PHY__MOTIONSTATE_H

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 2001-2005 Erwin Coumans <phy@erwincoumans.com>
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Erwin Coumans makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#include "PHY_IPhysicsController.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
PHY_IPhysicsController::~PHY_IPhysicsController()
{
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2001-2005 Erwin Coumans <phy@erwincoumans.com>
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Erwin Coumans makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef PHY_IPHYSICSCONTROLLER_H
#define PHY_IPHYSICSCONTROLLER_H
#include "PHY_DynamicTypes.h"
/**
PHY_IPhysicsController is the abstract simplified Interface to a physical object.
It contains the IMotionState and IDeformableMesh Interfaces.
*/
class PHY_IPhysicsController
{
public:
virtual ~PHY_IPhysicsController();
/**
SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
*/
virtual bool SynchronizeMotionStates(float time)=0;
/**
WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
*/
virtual void WriteMotionStateToDynamics(bool nondynaonly)=0;
virtual void WriteDynamicsToMotionState()=0;
// controller replication
virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)=0;
// kinematic methods
virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)=0;
virtual void RelativeRotate(const float drot[12],bool local)=0;
virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)=0;
virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)=0;
virtual void setPosition(float posX,float posY,float posZ)=0;
virtual void getPosition(PHY__Vector3& pos) const=0;
virtual void setScaling(float scaleX,float scaleY,float scaleZ)=0;
// physics methods
virtual void ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)=0;
virtual void ApplyForce(float forceX,float forceY,float forceZ,bool local)=0;
virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)=0;
virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)=0;
virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)=0;
virtual void SetActive(bool active)=0;
// reading out information from physics
virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ)=0;
virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)=0;
virtual void getReactionForce(float& forceX,float& forceY,float& forceZ)=0;
// dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted
virtual void setRigidBody(bool rigid)=0;
// clientinfo for raycasts for example
virtual void* getNewClientInfo()=0;
virtual void setNewClientInfo(void* clientinfo)=0;
virtual PHY_IPhysicsController* GetReplica() {return 0;}
virtual void calcXform() =0;
virtual void SetMargin(float margin) =0;
virtual float GetMargin() const=0;
virtual float GetRadius() const { return 0.f;}
PHY__Vector3 GetWorldPosition(PHY__Vector3& localpos);
};
#endif //PHY_IPHYSICSCONTROLLER_H

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2001-2005 Erwin Coumans <phy@erwincoumans.com>
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Erwin Coumans makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#include "PHY_IPhysicsEnvironment.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/**
* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
* A derived class may be able to 'construct' entities by loading and/or converting
*/
PHY_IPhysicsEnvironment::~PHY_IPhysicsEnvironment()
{
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2001-2005 Erwin Coumans <phy@erwincoumans.com>
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Erwin Coumans makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef _IPHYSICSENVIRONMENT
#define _IPHYSICSENVIRONMENT
#include <vector>
#include "PHY_DynamicTypes.h"
/**
* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
* A derived class may be able to 'construct' entities by loading and/or converting
*/
class PHY_IPhysicsEnvironment
{
public:
virtual ~PHY_IPhysicsEnvironment();
/// Perform an integration step of duration 'timeStep'.
virtual bool proceedDeltaTime(double curTime,float timeStep)=0;
virtual void setGravity(float x,float y,float z)=0;
virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
float pivotX,float pivotY,float pivotZ,
float axisX,float axisY,float axisZ)=0;
virtual void removeConstraint(int constraintid)=0;
virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)=0;
//Methods for gamelogic collision/physics callbacks
//todo:
virtual void addSensor(PHY_IPhysicsController* ctrl)=0;
virtual void removeSensor(PHY_IPhysicsController* ctrl)=0;
virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)=0;
virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl)=0;
virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) =0;
virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight)=0;
};
#endif //_IPHYSICSENVIRONMENT

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2001-2005 Erwin Coumans <phy@erwincoumans.com>
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Erwin Coumans makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef PHY_PROPSH
#define PHY_PROPSH
class CollisionShape;
// Properties of dynamic objects
struct PHY_ShapeProps {
float m_mass; // Total mass
float m_inertia; // Inertia, should be a tensor some time
float m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum
float m_ang_drag; // Angular drag
float m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
bool m_do_anisotropic; // Should I do anisotropic friction?
bool m_do_fh; // Should the object have a linear Fh spring?
bool m_do_rot_fh; // Should the object have an angular Fh spring?
CollisionShape* m_shape;
};
// Properties of collidable objects (non-ghost objects)
struct PHY_MaterialProps {
float m_restitution; // restitution of energie after a collision 0 = inelastic, 1 = elastic
float m_friction; // Coulomb friction (= ratio between the normal en maximum friction force)
float m_fh_spring; // Spring constant (both linear and angular)
float m_fh_damping; // Damping factor (linear and angular) in range [0, 1]
float m_fh_distance; // The range above the surface where Fh is active.
bool m_fh_normal; // Should the object slide off slopes?
};
#endif //PHY_PROPSH

View File

@@ -0,0 +1,128 @@
# Microsoft Developer Studio Project File - Name="PhysicsInterface" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=PhysicsInterface - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "PhysicsInterface.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "PhysicsInterface.mak" CFG="PhysicsInterface - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "PhysicsInterface - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "PhysicsInterface - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "PhysicsInterface - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
LINK32=link.exe -lib
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\LinearMath" /I "..\..\..\Extras\PhysicsInterface\Common" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "PhysicsInterface - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
LINK32=link.exe -lib
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\LinearMath" /I "..\..\..\Extras\PhysicsInterface\Common" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "PhysicsInterface - Win32 Release"
# Name "PhysicsInterface - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\PHY_IMotionState.cpp
# End Source File
# Begin Source File
SOURCE=.\PHY_IPhysicsController.cpp
# End Source File
# Begin Source File
SOURCE=.\PHY_IPhysicsEnvironment.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\PHY_DynamicTypes.h
# End Source File
# Begin Source File
SOURCE=.\PHY_IMotionState.h
# End Source File
# Begin Source File
SOURCE=.\PHY_IPhysicsController.h
# End Source File
# Begin Source File
SOURCE=.\PHY_IPhysicsEnvironment.h
# End Source File
# Begin Source File
SOURCE=.\PHY_Pro.h
# End Source File
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="PhysicsInterfaceCommon"
ProjectGUID="{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\..\LinearMath"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/PhysicsInterfaceCommon.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\..\..\LinearMath"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/PhysicsInterfaceCommon.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\PHY_IMotionState.cpp">
</File>
<File
RelativePath="..\PHY_IPhysicsController.cpp">
</File>
<File
RelativePath="..\PHY_IPhysicsEnvironment.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath="..\PHY_DynamicTypes.h">
</File>
<File
RelativePath="..\PHY_IMotionState.h">
</File>
<File
RelativePath="..\PHY_IPhysicsController.h">
</File>
<File
RelativePath="..\PHY_IPhysicsEnvironment.h">
</File>
<File
RelativePath="..\PHY_Pro.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
<File
RelativePath=".\ReadMe.txt">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,201 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="PhysicsInterfaceCommon"
ProjectGUID="{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="4"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\..\LinearMath"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/PhysicsInterfaceCommon.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="4"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\..\..\LinearMath"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/PhysicsInterfaceCommon.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\PHY_IMotionState.cpp"
>
</File>
<File
RelativePath="..\PHY_IPhysicsController.cpp"
>
</File>
<File
RelativePath="..\PHY_IPhysicsEnvironment.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\PHY_DynamicTypes.h"
>
</File>
<File
RelativePath="..\PHY_IMotionState.h"
>
</File>
<File
RelativePath="..\PHY_IPhysicsController.h"
>
</File>
<File
RelativePath="..\PHY_IPhysicsEnvironment.h"
>
</File>
<File
RelativePath="..\PHY_Pro.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<File
RelativePath=".\ReadMe.txt"
>
</File>
</Files>
</VisualStudioProject>

67
extern/bullet/LinearMath/AabbUtil2.h vendored Normal file
View File

@@ -0,0 +1,67 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef AABB_UTIL2
#define AABB_UTIL2
#include "SimdVector3.h"
#define SimdMin(a,b) ((a < b ? a : b))
#define SimdMax(a,b) ((a > b ? a : b))
/// conservative test for overlap between two aabbs
SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const SimdVector3 &aabbMin1, const SimdVector3 &aabbMax1,
const SimdVector3 &aabbMin2, const SimdVector3 &aabbMax2)
{
if (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) return false;
if (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) return false;
if (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) return false;
return true;
}
/// conservative test for overlap between triangle and aabb
SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const SimdVector3 *vertices,
const SimdVector3 &aabbMin, const SimdVector3 &aabbMax)
{
const SimdVector3 &p1 = vertices[0];
const SimdVector3 &p2 = vertices[1];
const SimdVector3 &p3 = vertices[2];
if (SimdMin(SimdMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
if (SimdMax(SimdMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
if (SimdMin(SimdMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
if (SimdMax(SimdMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
if (SimdMin(SimdMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
if (SimdMax(SimdMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
return true;
}
#endif

85
extern/bullet/LinearMath/GEN_List.h vendored Normal file
View File

@@ -0,0 +1,85 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef GEN_LIST_H
#define GEN_LIST_H
class GEN_Link {
public:
GEN_Link() : m_next(0), m_prev(0) {}
GEN_Link(GEN_Link *next, GEN_Link *prev) : m_next(next), m_prev(prev) {}
GEN_Link *getNext() const { return m_next; }
GEN_Link *getPrev() const { return m_prev; }
bool isHead() const { return m_prev == 0; }
bool isTail() const { return m_next == 0; }
void insertBefore(GEN_Link *link) {
m_next = link;
m_prev = link->m_prev;
m_next->m_prev = this;
m_prev->m_next = this;
}
void insertAfter(GEN_Link *link) {
m_next = link->m_next;
m_prev = link;
m_next->m_prev = this;
m_prev->m_next = this;
}
void remove() {
m_next->m_prev = m_prev;
m_prev->m_next = m_next;
}
private:
GEN_Link *m_next;
GEN_Link *m_prev;
};
class GEN_List {
public:
GEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
GEN_Link *getHead() const { return m_head.getNext(); }
GEN_Link *getTail() const { return m_tail.getPrev(); }
void addHead(GEN_Link *link) { link->insertAfter(&m_head); }
void addTail(GEN_Link *link) { link->insertBefore(&m_tail); }
private:
GEN_Link m_head;
GEN_Link m_tail;
};
#endif

81
extern/bullet/LinearMath/GEN_MinMax.h vendored Normal file
View File

@@ -0,0 +1,81 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef GEN_MINMAX_H
#define GEN_MINMAX_H
template <class T>
SIMD_FORCE_INLINE const T& GEN_min(const T& a, const T& b)
{
return b < a ? b : a;
}
template <class T>
SIMD_FORCE_INLINE const T& GEN_max(const T& a, const T& b)
{
return a < b ? b : a;
}
template <class T>
SIMD_FORCE_INLINE const T& GEN_clamped(const T& a, const T& lb, const T& ub)
{
return a < lb ? lb : (ub < a ? ub : a);
}
template <class T>
SIMD_FORCE_INLINE void GEN_set_min(T& a, const T& b)
{
if (b < a)
{
a = b;
}
}
template <class T>
SIMD_FORCE_INLINE void GEN_set_max(T& a, const T& b)
{
if (a < b)
{
a = b;
}
}
template <class T>
SIMD_FORCE_INLINE void GEN_clamp(T& a, const T& lb, const T& ub)
{
if (a < lb)
{
a = lb;
}
else if (ub < a)
{
a = ub;
}
}
#endif

54
extern/bullet/LinearMath/GEN_random.h vendored Normal file
View File

@@ -0,0 +1,54 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef GEN_RANDOM_H
#define GEN_RANDOM_H
#ifdef MT19937
#include <limits.h>
#include <mt19937.h>
#define GEN_RAND_MAX UINT_MAX
SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); }
SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); }
#else
#include <stdlib.h>
#define GEN_RAND_MAX RAND_MAX
SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); }
SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); }
#endif
#endif

407
extern/bullet/LinearMath/SimdMatrix3x3.h vendored Normal file
View File

@@ -0,0 +1,407 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef SimdMatrix3x3_H
#define SimdMatrix3x3_H
#include "SimdScalar.h"
#include "SimdVector3.h"
#include "SimdQuaternion.h"
class SimdMatrix3x3 {
public:
SimdMatrix3x3 () {}
// explicit SimdMatrix3x3(const SimdScalar *m) { setFromOpenGLSubMatrix(m); }
explicit SimdMatrix3x3(const SimdQuaternion& q) { setRotation(q); }
/*
template <typename SimdScalar>
Matrix3x3(const SimdScalar& yaw, const SimdScalar& pitch, const SimdScalar& roll)
{
setEulerYPR(yaw, pitch, roll);
}
*/
SimdMatrix3x3(const SimdScalar& xx, const SimdScalar& xy, const SimdScalar& xz,
const SimdScalar& yx, const SimdScalar& yy, const SimdScalar& yz,
const SimdScalar& zx, const SimdScalar& zy, const SimdScalar& zz)
{
setValue(xx, xy, xz,
yx, yy, yz,
zx, zy, zz);
}
SimdVector3 getColumn(int i) const
{
return SimdVector3(m_el[0][i],m_el[1][i],m_el[2][i]);
}
const SimdVector3& getRow(int i) const
{
return m_el[i];
}
SIMD_FORCE_INLINE SimdVector3& operator[](int i)
{
assert(0 <= i && i < 3);
return m_el[i];
}
const SimdVector3& operator[](int i) const
{
assert(0 <= i && i < 3);
return m_el[i];
}
SimdMatrix3x3& operator*=(const SimdMatrix3x3& m);
void setFromOpenGLSubMatrix(const SimdScalar *m)
{
m_el[0][0] = (m[0]);
m_el[1][0] = (m[1]);
m_el[2][0] = (m[2]);
m_el[0][1] = (m[4]);
m_el[1][1] = (m[5]);
m_el[2][1] = (m[6]);
m_el[0][2] = (m[8]);
m_el[1][2] = (m[9]);
m_el[2][2] = (m[10]);
}
void setValue(const SimdScalar& xx, const SimdScalar& xy, const SimdScalar& xz,
const SimdScalar& yx, const SimdScalar& yy, const SimdScalar& yz,
const SimdScalar& zx, const SimdScalar& zy, const SimdScalar& zz)
{
m_el[0][0] = SimdScalar(xx);
m_el[0][1] = SimdScalar(xy);
m_el[0][2] = SimdScalar(xz);
m_el[1][0] = SimdScalar(yx);
m_el[1][1] = SimdScalar(yy);
m_el[1][2] = SimdScalar(yz);
m_el[2][0] = SimdScalar(zx);
m_el[2][1] = SimdScalar(zy);
m_el[2][2] = SimdScalar(zz);
}
void setRotation(const SimdQuaternion& q)
{
SimdScalar d = q.length2();
assert(d != SimdScalar(0.0));
SimdScalar s = SimdScalar(2.0) / d;
SimdScalar xs = q[0] * s, ys = q[1] * s, zs = q[2] * s;
SimdScalar wx = q[3] * xs, wy = q[3] * ys, wz = q[3] * zs;
SimdScalar xx = q[0] * xs, xy = q[0] * ys, xz = q[0] * zs;
SimdScalar yy = q[1] * ys, yz = q[1] * zs, zz = q[2] * zs;
setValue(SimdScalar(1.0) - (yy + zz), xy - wz, xz + wy,
xy + wz, SimdScalar(1.0) - (xx + zz), yz - wx,
xz - wy, yz + wx, SimdScalar(1.0) - (xx + yy));
}
void setEulerYPR(const SimdScalar& yaw, const SimdScalar& pitch, const SimdScalar& roll)
{
SimdScalar cy(cosf(yaw));
SimdScalar sy(sinf(yaw));
SimdScalar cp(cosf(pitch));
SimdScalar sp(sinf(pitch));
SimdScalar cr(cosf(roll));
SimdScalar sr(sinf(roll));
SimdScalar cc = cy * cr;
SimdScalar cs = cy * sr;
SimdScalar sc = sy * cr;
SimdScalar ss = sy * sr;
setValue(cc - sp * ss, -cs - sp * sc, -sy * cp,
cp * sr, cp * cr, -sp,
sc + sp * cs, -ss + sp * cc, cy * cp);
}
/**
* setEulerZYX
* @param euler a const reference to a SimdVector3 of euler angles
* These angles are used to produce a rotation matrix. The euler
* angles are applied in ZYX order. I.e a vector is first rotated
* about X then Y and then Z
**/
void setEulerZYX(SimdScalar eulerX,SimdScalar eulerY,SimdScalar eulerZ) {
SimdScalar ci ( cosf(eulerX));
SimdScalar cj ( cosf(eulerY));
SimdScalar ch ( cosf(eulerZ));
SimdScalar si ( sinf(eulerX));
SimdScalar sj ( sinf(eulerY));
SimdScalar sh ( sinf(eulerZ));
SimdScalar cc = ci * ch;
SimdScalar cs = ci * sh;
SimdScalar sc = si * ch;
SimdScalar ss = si * sh;
setValue(cj * ch, sj * sc - cs, sj * cc + ss,
cj * sh, sj * ss + cc, sj * cs - sc,
-sj, cj * si, cj * ci);
}
void setIdentity()
{
setValue(SimdScalar(1.0), SimdScalar(0.0), SimdScalar(0.0),
SimdScalar(0.0), SimdScalar(1.0), SimdScalar(0.0),
SimdScalar(0.0), SimdScalar(0.0), SimdScalar(1.0));
}
void getOpenGLSubMatrix(SimdScalar *m) const
{
m[0] = SimdScalar(m_el[0][0]);
m[1] = SimdScalar(m_el[1][0]);
m[2] = SimdScalar(m_el[2][0]);
m[3] = SimdScalar(0.0);
m[4] = SimdScalar(m_el[0][1]);
m[5] = SimdScalar(m_el[1][1]);
m[6] = SimdScalar(m_el[2][1]);
m[7] = SimdScalar(0.0);
m[8] = SimdScalar(m_el[0][2]);
m[9] = SimdScalar(m_el[1][2]);
m[10] = SimdScalar(m_el[2][2]);
m[11] = SimdScalar(0.0);
}
void getRotation(SimdQuaternion& q) const
{
SimdScalar trace = m_el[0][0] + m_el[1][1] + m_el[2][2];
if (trace > SimdScalar(0.0))
{
SimdScalar s = sqrtf(trace + SimdScalar(1.0));
q[3] = s * SimdScalar(0.5);
s = SimdScalar(0.5) / s;
q[0] = (m_el[2][1] - m_el[1][2]) * s;
q[1] = (m_el[0][2] - m_el[2][0]) * s;
q[2] = (m_el[1][0] - m_el[0][1]) * s;
}
else
{
int i = m_el[0][0] < m_el[1][1] ?
(m_el[1][1] < m_el[2][2] ? 2 : 1) :
(m_el[0][0] < m_el[2][2] ? 2 : 0);
int j = (i + 1) % 3;
int k = (i + 2) % 3;
SimdScalar s = sqrtf(m_el[i][i] - m_el[j][j] - m_el[k][k] + SimdScalar(1.0));
q[i] = s * SimdScalar(0.5);
s = SimdScalar(0.5) / s;
q[3] = (m_el[k][j] - m_el[j][k]) * s;
q[j] = (m_el[j][i] + m_el[i][j]) * s;
q[k] = (m_el[k][i] + m_el[i][k]) * s;
}
}
void getEuler(SimdScalar& yaw, SimdScalar& pitch, SimdScalar& roll) const
{
pitch = SimdScalar(asinf(-m_el[2][0]));
if (pitch < SIMD_2_PI)
{
if (pitch > SIMD_2_PI)
{
yaw = SimdScalar(atan2f(m_el[1][0], m_el[0][0]));
roll = SimdScalar(atan2f(m_el[2][1], m_el[2][2]));
}
else
{
yaw = SimdScalar(-atan2f(-m_el[0][1], m_el[0][2]));
roll = SimdScalar(0.0);
}
}
else
{
yaw = SimdScalar(atan2f(-m_el[0][1], m_el[0][2]));
roll = SimdScalar(0.0);
}
}
SimdVector3 getScaling() const
{
return SimdVector3(m_el[0][0] * m_el[0][0] + m_el[1][0] * m_el[1][0] + m_el[2][0] * m_el[2][0],
m_el[0][1] * m_el[0][1] + m_el[1][1] * m_el[1][1] + m_el[2][1] * m_el[2][1],
m_el[0][2] * m_el[0][2] + m_el[1][2] * m_el[1][2] + m_el[2][2] * m_el[2][2]);
}
SimdMatrix3x3 scaled(const SimdVector3& s) const
{
return SimdMatrix3x3(m_el[0][0] * s[0], m_el[0][1] * s[1], m_el[0][2] * s[2],
m_el[1][0] * s[0], m_el[1][1] * s[1], m_el[1][2] * s[2],
m_el[2][0] * s[0], m_el[2][1] * s[1], m_el[2][2] * s[2]);
}
SimdScalar determinant() const;
SimdMatrix3x3 adjoint() const;
SimdMatrix3x3 absolute() const;
SimdMatrix3x3 transpose() const;
SimdMatrix3x3 inverse() const;
SimdMatrix3x3 transposeTimes(const SimdMatrix3x3& m) const;
SimdMatrix3x3 timesTranspose(const SimdMatrix3x3& m) const;
SimdScalar tdot(int c, const SimdVector3& v) const
{
return m_el[0][c] * v[0] + m_el[1][c] * v[1] + m_el[2][c] * v[2];
}
protected:
SimdScalar cofac(int r1, int c1, int r2, int c2) const
{
return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
}
SimdVector3 m_el[3];
};
SIMD_FORCE_INLINE SimdMatrix3x3&
SimdMatrix3x3::operator*=(const SimdMatrix3x3& m)
{
setValue(m.tdot(0, m_el[0]), m.tdot(1, m_el[0]), m.tdot(2, m_el[0]),
m.tdot(0, m_el[1]), m.tdot(1, m_el[1]), m.tdot(2, m_el[1]),
m.tdot(0, m_el[2]), m.tdot(1, m_el[2]), m.tdot(2, m_el[2]));
return *this;
}
SIMD_FORCE_INLINE SimdScalar
SimdMatrix3x3::determinant() const
{
return triple((*this)[0], (*this)[1], (*this)[2]);
}
SIMD_FORCE_INLINE SimdMatrix3x3
SimdMatrix3x3::absolute() const
{
return SimdMatrix3x3(
fabsf(m_el[0][0]), fabsf(m_el[0][1]), fabsf(m_el[0][2]),
fabsf(m_el[1][0]), fabsf(m_el[1][1]), fabsf(m_el[1][2]),
fabsf(m_el[2][0]), fabsf(m_el[2][1]), fabsf(m_el[2][2]));
}
SIMD_FORCE_INLINE SimdMatrix3x3
SimdMatrix3x3::transpose() const
{
return SimdMatrix3x3(m_el[0][0], m_el[1][0], m_el[2][0],
m_el[0][1], m_el[1][1], m_el[2][1],
m_el[0][2], m_el[1][2], m_el[2][2]);
}
SIMD_FORCE_INLINE SimdMatrix3x3
SimdMatrix3x3::adjoint() const
{
return SimdMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
}
SIMD_FORCE_INLINE SimdMatrix3x3
SimdMatrix3x3::inverse() const
{
SimdVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
SimdScalar det = (*this)[0].dot(co);
assert(det != SimdScalar(0.0f));
SimdScalar s = SimdScalar(1.0f) / det;
return SimdMatrix3x3(co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
}
SIMD_FORCE_INLINE SimdMatrix3x3
SimdMatrix3x3::transposeTimes(const SimdMatrix3x3& m) const
{
return SimdMatrix3x3(
m_el[0][0] * m[0][0] + m_el[1][0] * m[1][0] + m_el[2][0] * m[2][0],
m_el[0][0] * m[0][1] + m_el[1][0] * m[1][1] + m_el[2][0] * m[2][1],
m_el[0][0] * m[0][2] + m_el[1][0] * m[1][2] + m_el[2][0] * m[2][2],
m_el[0][1] * m[0][0] + m_el[1][1] * m[1][0] + m_el[2][1] * m[2][0],
m_el[0][1] * m[0][1] + m_el[1][1] * m[1][1] + m_el[2][1] * m[2][1],
m_el[0][1] * m[0][2] + m_el[1][1] * m[1][2] + m_el[2][1] * m[2][2],
m_el[0][2] * m[0][0] + m_el[1][2] * m[1][0] + m_el[2][2] * m[2][0],
m_el[0][2] * m[0][1] + m_el[1][2] * m[1][1] + m_el[2][2] * m[2][1],
m_el[0][2] * m[0][2] + m_el[1][2] * m[1][2] + m_el[2][2] * m[2][2]);
}
SIMD_FORCE_INLINE SimdMatrix3x3
SimdMatrix3x3::timesTranspose(const SimdMatrix3x3& m) const
{
return SimdMatrix3x3(
m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
}
SIMD_FORCE_INLINE SimdVector3
operator*(const SimdMatrix3x3& m, const SimdVector3& v)
{
return SimdVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
}
SIMD_FORCE_INLINE SimdVector3
operator*(const SimdVector3& v, const SimdMatrix3x3& m)
{
return SimdVector3(m.tdot(0, v), m.tdot(1, v), m.tdot(2, v));
}
SIMD_FORCE_INLINE SimdMatrix3x3
operator*(const SimdMatrix3x3& m1, const SimdMatrix3x3& m2)
{
return SimdMatrix3x3(
m2.tdot(0, m1[0]), m2.tdot(1, m1[0]), m2.tdot(2, m1[0]),
m2.tdot(0, m1[1]), m2.tdot(1, m1[1]), m2.tdot(2, m1[1]),
m2.tdot(0, m1[2]), m2.tdot(1, m1[2]), m2.tdot(2, m1[2]));
}
SIMD_FORCE_INLINE SimdMatrix3x3 SimdMultTransposeLeft(const SimdMatrix3x3& m1, const SimdMatrix3x3& m2) {
return SimdMatrix3x3(
m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
}
#endif

52
extern/bullet/LinearMath/SimdMinMax.h vendored Normal file
View File

@@ -0,0 +1,52 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef SIMD_MINMAX_H
#define SIMD_MINMAX_H
template <class T>
SIMD_FORCE_INLINE const T& SimdMin(const T& a, const T& b) {
return b < a ? b : a;
}
template <class T>
SIMD_FORCE_INLINE const T& SimdMax(const T& a, const T& b) {
return a < b ? b : a;
}
template <class T>
SIMD_FORCE_INLINE void SimdSetMin(T& a, const T& b) {
if (a > b) a = b;
}
template <class T>
SIMD_FORCE_INLINE void SimdSetMax(T& a, const T& b) {
if (a < b) a = b;
}
#endif

36
extern/bullet/LinearMath/SimdPoint3.h vendored Normal file
View File

@@ -0,0 +1,36 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef SimdPoint3_H
#define SimdPoint3_H
#include "SimdVector3.h"
typedef SimdVector3 SimdPoint3;
#endif

113
extern/bullet/LinearMath/SimdQuadWord.h vendored Normal file
View File

@@ -0,0 +1,113 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef SIMD_QUADWORD_H
#define SIMD_QUADWORD_H
#include "SimdScalar.h"
class SimdQuadWord
{
protected:
ATTRIBUTE_ALIGNED16 (SimdScalar m_x);
SimdScalar m_y;
SimdScalar m_z;
SimdScalar m_unusedW;
public:
SIMD_FORCE_INLINE SimdScalar& operator[](int i) { return (&m_x)[i]; }
SIMD_FORCE_INLINE const SimdScalar& operator[](int i) const { return (&m_x)[i]; }
SIMD_FORCE_INLINE const SimdScalar& getX() const { return m_x; }
SIMD_FORCE_INLINE const SimdScalar& getY() const { return m_y; }
SIMD_FORCE_INLINE const SimdScalar& getZ() const { return m_z; }
SIMD_FORCE_INLINE void setX(float x) { m_x = x;};
SIMD_FORCE_INLINE void setY(float y) { m_y = y;};
SIMD_FORCE_INLINE void setZ(float z) { m_z = z;};
SIMD_FORCE_INLINE const SimdScalar& x() const { return m_x; }
SIMD_FORCE_INLINE const SimdScalar& y() const { return m_y; }
SIMD_FORCE_INLINE const SimdScalar& z() const { return m_z; }
operator SimdScalar *() { return &m_x; }
operator const SimdScalar *() const { return &m_x; }
SIMD_FORCE_INLINE void setValue(const SimdScalar& x, const SimdScalar& y, const SimdScalar& z)
{
m_x=x;
m_y=y;
m_z=z;
}
/* void getValue(SimdScalar *m) const
{
m[0] = m_x;
m[1] = m_y;
m[2] = m_z;
}
*/
SIMD_FORCE_INLINE void setValue(const SimdScalar& x, const SimdScalar& y, const SimdScalar& z,const SimdScalar& w)
{
m_x=x;
m_y=y;
m_z=z;
m_unusedW=w;
}
SIMD_FORCE_INLINE SimdQuadWord()
{
}
SIMD_FORCE_INLINE SimdQuadWord(const SimdScalar& x, const SimdScalar& y, const SimdScalar& z)
:m_x(x),m_y(y),m_z(z)
//todo, remove this in release/simd ?
,m_unusedW(1e30f)
{
}
SIMD_FORCE_INLINE SimdQuadWord(const SimdScalar& x, const SimdScalar& y, const SimdScalar& z,const SimdScalar& w)
:m_x(x),m_y(y),m_z(z),m_unusedW(w)
{
}
};
#endif //SIMD_QUADWORD_H

View File

@@ -0,0 +1,302 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef SIMD__QUATERNION_H_
#define SIMD__QUATERNION_H_
#include "SimdVector3.h"
class SimdQuaternion : public SimdQuadWord {
public:
SimdQuaternion() {}
// template <typename SimdScalar>
// explicit Quaternion(const SimdScalar *v) : Tuple4<SimdScalar>(v) {}
SimdQuaternion(const SimdScalar& x, const SimdScalar& y, const SimdScalar& z, const SimdScalar& w)
: SimdQuadWord(x, y, z, w)
{}
SimdQuaternion(const SimdVector3& axis, const SimdScalar& angle)
{
setRotation(axis, angle);
}
SimdQuaternion(const SimdScalar& yaw, const SimdScalar& pitch, const SimdScalar& roll)
{
setEuler(yaw, pitch, roll);
}
void setRotation(const SimdVector3& axis, const SimdScalar& angle)
{
SimdScalar d = axis.length();
assert(d != SimdScalar(0.0));
SimdScalar s = sinf(angle * SimdScalar(0.5)) / d;
setValue(axis.x() * s, axis.y() * s, axis.z() * s,
cosf(angle * SimdScalar(0.5)));
}
void setEuler(const SimdScalar& yaw, const SimdScalar& pitch, const SimdScalar& roll)
{
SimdScalar halfYaw = SimdScalar(yaw) * SimdScalar(0.5);
SimdScalar halfPitch = SimdScalar(pitch) * SimdScalar(0.5);
SimdScalar halfRoll = SimdScalar(roll) * SimdScalar(0.5);
SimdScalar cosYaw = cosf(halfYaw);
SimdScalar sinYaw = sinf(halfYaw);
SimdScalar cosPitch = cosf(halfPitch);
SimdScalar sinPitch = sinf(halfPitch);
SimdScalar cosRoll = cosf(halfRoll);
SimdScalar sinRoll = sinf(halfRoll);
setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
}
SimdQuaternion& operator+=(const SimdQuaternion& q)
{
m_x += q.x(); m_y += q.y(); m_z += q.z(); m_unusedW += q[3];
return *this;
}
SimdQuaternion& operator-=(const SimdQuaternion& q)
{
m_x -= q.x(); m_y -= q.y(); m_z -= q.z(); m_unusedW -= q[3];
return *this;
}
SimdQuaternion& operator*=(const SimdScalar& s)
{
m_x *= s; m_y *= s; m_z *= s; m_unusedW *= s;
return *this;
}
SimdQuaternion& operator*=(const SimdQuaternion& q)
{
setValue(m_unusedW * q.x() + m_x * q[3] + m_y * q.z() - m_z * q.y(),
m_unusedW * q.y() + m_y * q[3] + m_z * q.x() - m_x * q.z(),
m_unusedW * q.z() + m_z * q[3] + m_x * q.y() - m_y * q.x(),
m_unusedW * q[3] - m_x * q.x() - m_y * q.y() - m_z * q.z());
return *this;
}
SimdScalar dot(const SimdQuaternion& q) const
{
return m_x * q.x() + m_y * q.y() + m_z * q.z() + m_unusedW * q[3];
}
SimdScalar length2() const
{
return dot(*this);
}
SimdScalar length() const
{
return sqrtf(length2());
}
SimdQuaternion& normalize()
{
return *this /= length();
}
SIMD_FORCE_INLINE SimdQuaternion
operator*(const SimdScalar& s) const
{
return SimdQuaternion(x() * s, y() * s, z() * s, m_unusedW * s);
}
SimdQuaternion operator/(const SimdScalar& s) const
{
assert(s != SimdScalar(0.0));
return *this * (SimdScalar(1.0) / s);
}
SimdQuaternion& operator/=(const SimdScalar& s)
{
assert(s != SimdScalar(0.0));
return *this *= SimdScalar(1.0) / s;
}
SimdQuaternion normalized() const
{
return *this / length();
}
SimdScalar angle(const SimdQuaternion& q) const
{
SimdScalar s = sqrtf(length2() * q.length2());
assert(s != SimdScalar(0.0));
return acosf(dot(q) / s);
}
SimdScalar getAngle() const
{
SimdScalar s = 2.f * acosf(m_unusedW);
return s;
}
SimdQuaternion inverse() const
{
return SimdQuaternion(m_x, m_y, m_z, -m_unusedW);
}
SIMD_FORCE_INLINE SimdQuaternion
operator+(const SimdQuaternion& q2) const
{
const SimdQuaternion& q1 = *this;
return SimdQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1[3] + q2[3]);
}
SIMD_FORCE_INLINE SimdQuaternion
operator-(const SimdQuaternion& q2) const
{
const SimdQuaternion& q1 = *this;
return SimdQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1[3] - q2[3]);
}
SIMD_FORCE_INLINE SimdQuaternion operator-() const
{
const SimdQuaternion& q2 = *this;
return SimdQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2[3]);
}
SIMD_FORCE_INLINE SimdQuaternion farthest( const SimdQuaternion& qd) const
{
SimdQuaternion diff,sum;
diff = *this - qd;
sum = *this + qd;
if( diff.dot(diff) > sum.dot(sum) )
return qd;
return (-qd);
}
SimdQuaternion slerp(const SimdQuaternion& q, const SimdScalar& t) const
{
SimdScalar theta = angle(q);
if (theta != SimdScalar(0.0))
{
SimdScalar d = SimdScalar(1.0) / sinf(theta);
SimdScalar s0 = sinf((SimdScalar(1.0) - t) * theta);
SimdScalar s1 = sinf(t * theta);
return SimdQuaternion((m_x * s0 + q.x() * s1) * d,
(m_y * s0 + q.y() * s1) * d,
(m_z * s0 + q.z() * s1) * d,
(m_unusedW * s0 + q[3] * s1) * d);
}
else
{
return *this;
}
}
};
SIMD_FORCE_INLINE SimdQuaternion
operator-(const SimdQuaternion& q)
{
return SimdQuaternion(-q.x(), -q.y(), -q.z(), -q[3]);
}
SIMD_FORCE_INLINE SimdQuaternion
operator*(const SimdQuaternion& q1, const SimdQuaternion& q2) {
return SimdQuaternion(q1[3] * q2.x() + q1.x() * q2[3] + q1.y() * q2.z() - q1.z() * q2.y(),
q1[3] * q2.y() + q1.y() * q2[3] + q1.z() * q2.x() - q1.x() * q2.z(),
q1[3] * q2.z() + q1.z() * q2[3] + q1.x() * q2.y() - q1.y() * q2.x(),
q1[3] * q2[3] - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z());
}
SIMD_FORCE_INLINE SimdQuaternion
operator*(const SimdQuaternion& q, const SimdVector3& w)
{
return SimdQuaternion( q[3] * w.x() + q.y() * w.z() - q.z() * w.y(),
q[3] * w.y() + q.z() * w.x() - q.x() * w.z(),
q[3] * w.z() + q.x() * w.y() - q.y() * w.x(),
-q.x() * w.x() - q.y() * w.y() - q.z() * w.z());
}
SIMD_FORCE_INLINE SimdQuaternion
operator*(const SimdVector3& w, const SimdQuaternion& q)
{
return SimdQuaternion( w.x() * q[3] + w.y() * q.z() - w.z() * q.y(),
w.y() * q[3] + w.z() * q.x() - w.x() * q.z(),
w.z() * q[3] + w.x() * q.y() - w.y() * q.x(),
-w.x() * q.x() - w.y() * q.y() - w.z() * q.z());
}
SIMD_FORCE_INLINE SimdScalar
dot(const SimdQuaternion& q1, const SimdQuaternion& q2)
{
return q1.dot(q2);
}
SIMD_FORCE_INLINE SimdScalar
length(const SimdQuaternion& q)
{
return q.length();
}
SIMD_FORCE_INLINE SimdScalar
angle(const SimdQuaternion& q1, const SimdQuaternion& q2)
{
return q1.angle(q2);
}
SIMD_FORCE_INLINE SimdQuaternion
inverse(const SimdQuaternion& q)
{
return q.inverse();
}
SIMD_FORCE_INLINE SimdQuaternion
slerp(const SimdQuaternion& q1, const SimdQuaternion& q2, const SimdScalar& t)
{
return q1.slerp(q2, t);
}
#endif

95
extern/bullet/LinearMath/SimdScalar.h vendored Normal file
View File

@@ -0,0 +1,95 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef SIMD___SCALAR_H
#define SIMD___SCALAR_H
#include <math.h>
#undef max
#include <cstdlib>
#include <cfloat>
#include <float.h>
#ifdef WIN32
#define SIMD_FORCE_INLINE __forceinline
//#define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
#define ATTRIBUTE_ALIGNED16(a) a
#include <assert.h>
#define ASSERT assert
#else
#define SIMD_FORCE_INLINE inline
#define ATTRIBUTE_ALIGNED16(a) a
#ifndef assert
#include <assert.h>
#endif
#define ASSERT assert
#endif
typedef float SimdScalar;
const SimdScalar SIMD_2_PI = 6.283185307179586232f;
const SimdScalar SIMD_PI = SIMD_2_PI * SimdScalar(0.5f);
const SimdScalar SIMD_HALF_PI = SIMD_2_PI * SimdScalar(0.25f);
const SimdScalar SIMD_RADS_PER_DEG = SIMD_2_PI / SimdScalar(360.0f);
const SimdScalar SIMD_DEGS_PER_RAD = SimdScalar(360.0f) / SIMD_2_PI;
const SimdScalar SIMD_EPSILON = FLT_EPSILON;
const SimdScalar SIMD_INFINITY = FLT_MAX;
SIMD_FORCE_INLINE bool SimdFuzzyZero(SimdScalar x) { return fabsf(x) < SIMD_EPSILON; }
SIMD_FORCE_INLINE bool SimdEqual(SimdScalar a, SimdScalar eps) {
return (((a) <= eps) && !((a) < -eps));
}
SIMD_FORCE_INLINE bool SimdGreaterEqual (SimdScalar a, SimdScalar eps) {
return (!((a) <= eps));
}
SIMD_FORCE_INLINE SimdScalar SimdCos(SimdScalar x) { return cosf(x); }
SIMD_FORCE_INLINE SimdScalar SimdSin(SimdScalar x) { return sinf(x); }
SIMD_FORCE_INLINE SimdScalar SimdTan(SimdScalar x) { return tanf(x); }
SIMD_FORCE_INLINE int SimdSign(SimdScalar x) {
return x < 0.0f ? -1 : x > 0.0f ? 1 : 0;
}
SIMD_FORCE_INLINE SimdScalar SimdAcos(SimdScalar x) { return acosf(x); }
SIMD_FORCE_INLINE SimdScalar SimdAsin(SimdScalar x) { return asinf(x); }
SIMD_FORCE_INLINE SimdScalar SimdAtan(SimdScalar x) { return atanf(x); }
SIMD_FORCE_INLINE SimdScalar SimdAtan2(SimdScalar x, SimdScalar y) { return atan2f(x, y); }
SIMD_FORCE_INLINE SimdScalar SimdRadians(SimdScalar x) { return x * SIMD_RADS_PER_DEG; }
SIMD_FORCE_INLINE SimdScalar SimdDegrees(SimdScalar x) { return x * SIMD_DEGS_PER_RAD; }
#endif

248
extern/bullet/LinearMath/SimdTransform.h vendored Normal file
View File

@@ -0,0 +1,248 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef SimdTransform_H
#define SimdTransform_H
#include "SimdVector3.h"
#include "SimdMatrix3x3.h"
class SimdTransform {
enum {
TRANSLATION = 0x01,
ROTATION = 0x02,
RIGID = TRANSLATION | ROTATION,
SCALING = 0x04,
LINEAR = ROTATION | SCALING,
AFFINE = TRANSLATION | LINEAR
};
public:
SimdTransform() {}
// template <typename Scalar2>
// explicit Transform(const Scalar2 *m) { setValue(m); }
explicit SIMD_FORCE_INLINE SimdTransform(const SimdQuaternion& q,
const SimdVector3& c = SimdVector3(SimdScalar(0), SimdScalar(0), SimdScalar(0)))
: m_basis(q),
m_origin(c),
m_type(RIGID)
{}
explicit SIMD_FORCE_INLINE SimdTransform(const SimdMatrix3x3& b,
const SimdVector3& c = SimdVector3(SimdScalar(0), SimdScalar(0), SimdScalar(0)),
unsigned int type = AFFINE)
: m_basis(b),
m_origin(c),
m_type(type)
{}
SIMD_FORCE_INLINE void mult(const SimdTransform& t1, const SimdTransform& t2) {
m_basis = t1.m_basis * t2.m_basis;
m_origin = t1(t2.m_origin);
m_type = t1.m_type | t2.m_type;
}
void multInverseLeft(const SimdTransform& t1, const SimdTransform& t2) {
SimdVector3 v = t2.m_origin - t1.m_origin;
if (t1.m_type & SCALING) {
SimdMatrix3x3 inv = t1.m_basis.inverse();
m_basis = inv * t2.m_basis;
m_origin = inv * v;
}
else {
m_basis = SimdMultTransposeLeft(t1.m_basis, t2.m_basis);
m_origin = v * t1.m_basis;
}
m_type = t1.m_type | t2.m_type;
}
SIMD_FORCE_INLINE SimdVector3 operator()(const SimdVector3& x) const
{
return SimdVector3(m_basis[0].dot(x) + m_origin[0],
m_basis[1].dot(x) + m_origin[1],
m_basis[2].dot(x) + m_origin[2]);
}
SIMD_FORCE_INLINE SimdVector3 operator*(const SimdVector3& x) const
{
return (*this)(x);
}
SIMD_FORCE_INLINE SimdMatrix3x3& getBasis() { return m_basis; }
SIMD_FORCE_INLINE const SimdMatrix3x3& getBasis() const { return m_basis; }
SIMD_FORCE_INLINE SimdVector3& getOrigin() { return m_origin; }
SIMD_FORCE_INLINE const SimdVector3& getOrigin() const { return m_origin; }
SimdQuaternion getRotation() const {
SimdQuaternion q;
m_basis.getRotation(q);
return q;
}
template <typename Scalar2>
void setValue(const Scalar2 *m)
{
m_basis.setValue(m);
m_origin.setValue(&m[12]);
m_type = AFFINE;
}
void setFromOpenGLMatrix(const SimdScalar *m)
{
m_basis.setFromOpenGLSubMatrix(m);
m_origin[0] = m[12];
m_origin[1] = m[13];
m_origin[2] = m[14];
}
void getOpenGLMatrix(SimdScalar *m) const
{
m_basis.getOpenGLSubMatrix(m);
m[12] = m_origin[0];
m[13] = m_origin[1];
m[14] = m_origin[2];
m[15] = SimdScalar(1.0f);
}
SIMD_FORCE_INLINE void setOrigin(const SimdVector3& origin)
{
m_origin = origin;
m_type |= TRANSLATION;
}
SIMD_FORCE_INLINE SimdVector3 invXform(const SimdVector3& inVec) const;
SIMD_FORCE_INLINE void setBasis(const SimdMatrix3x3& basis)
{
m_basis = basis;
m_type |= LINEAR;
}
SIMD_FORCE_INLINE void setRotation(const SimdQuaternion& q)
{
m_basis.setRotation(q);
m_type = (m_type & ~LINEAR) | ROTATION;
}
SIMD_FORCE_INLINE void scale(const SimdVector3& scaling)
{
m_basis = m_basis.scaled(scaling);
m_type |= SCALING;
}
void setIdentity()
{
m_basis.setIdentity();
m_origin.setValue(SimdScalar(0.0), SimdScalar(0.0), SimdScalar(0.0));
m_type = 0x0;
}
SIMD_FORCE_INLINE bool isIdentity() const { return m_type == 0x0; }
SimdTransform& operator*=(const SimdTransform& t)
{
m_origin += m_basis * t.m_origin;
m_basis *= t.m_basis;
m_type |= t.m_type;
return *this;
}
SimdTransform inverse() const
{
if (m_type)
{
SimdMatrix3x3 inv = (m_type & SCALING) ?
m_basis.inverse() :
m_basis.transpose();
return SimdTransform(inv, inv * -m_origin, m_type);
}
return *this;
}
SimdTransform inverseTimes(const SimdTransform& t) const;
SimdTransform operator*(const SimdTransform& t) const;
private:
SimdMatrix3x3 m_basis;
SimdVector3 m_origin;
unsigned int m_type;
};
SIMD_FORCE_INLINE SimdVector3
SimdTransform::invXform(const SimdVector3& inVec) const
{
SimdVector3 v = inVec - m_origin;
return (m_basis.transpose() * v);
}
SIMD_FORCE_INLINE SimdTransform
SimdTransform::inverseTimes(const SimdTransform& t) const
{
SimdVector3 v = t.getOrigin() - m_origin;
if (m_type & SCALING)
{
SimdMatrix3x3 inv = m_basis.inverse();
return SimdTransform(inv * t.getBasis(), inv * v,
m_type | t.m_type);
}
else
{
return SimdTransform(m_basis.transposeTimes(t.m_basis),
v * m_basis, m_type | t.m_type);
}
}
SIMD_FORCE_INLINE SimdTransform
SimdTransform::operator*(const SimdTransform& t) const
{
return SimdTransform(m_basis * t.m_basis,
(*this)(t.m_origin),
m_type | t.m_type);
}
#endif

View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#ifndef SIMD_TRANSFORM_UTIL_H
#define SIMD_TRANSFORM_UTIL_H
#include "SimdTransform.h"
#define ANGULAR_MOTION_TRESHOLD 0.5f*SIMD_HALF_PI
/// Utils related to temporal transforms
class SimdTransformUtil
{
public:
static void IntegrateTransform(const SimdTransform& curTrans,const SimdVector3& linvel,const SimdVector3& angvel,SimdScalar timeStep,SimdTransform& predictedTransform)
{
predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
// #define QUATERNION_DERIVATIVE
#ifdef QUATERNION_DERIVATIVE
SimdQuaternion orn = curTrans.getRotation();
orn += (angvel * orn) * (timeStep * 0.5f);
orn.normalize();
#else
//exponential map
SimdVector3 axis;
SimdScalar fAngle = angvel.length();
//limit the angular motion
if (fAngle*timeStep > ANGULAR_MOTION_TRESHOLD)
{
fAngle = ANGULAR_MOTION_TRESHOLD / timeStep;
}
if ( fAngle < 0.001f )
{
// use Taylor's expansions of sync function
axis = angvel*( 0.5f*timeStep-(timeStep*timeStep*timeStep)*(0.020833333333f)*fAngle*fAngle );
}
else
{
// sync(fAngle) = sin(c*fAngle)/t
axis = angvel*( sinf(0.5f*fAngle*timeStep)/fAngle );
}
SimdQuaternion dorn (axis.x(),axis.y(),axis.z(),cosf( fAngle*timeStep*0.5f ));
SimdQuaternion orn0 = curTrans.getRotation();
SimdQuaternion predictedOrn = dorn * orn0;
#endif
predictedTransform.setRotation(predictedOrn);
}
static void CalculateVelocity(const SimdTransform& transform0,const SimdTransform& transform1,SimdScalar timeStep,SimdVector3& linVel,SimdVector3& angVel)
{
linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
#ifdef USE_QUATERNION_DIFF
SimdQuaternion orn0 = transform0.getRotation();
SimdQuaternion orn1a = transform1.getRotation();
SimdQuaternion orn1 = orn0.farthest(orn1a);
SimdQuaternion dorn = orn1 * orn0.inverse();
#else
SimdMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
SimdQuaternion dorn;
dmat.getRotation(dorn);
#endif//USE_QUATERNION_DIFF
SimdVector3 axis;
SimdScalar angle;
angle = dorn.getAngle();
axis = SimdVector3(dorn.x(),dorn.y(),dorn.z());
axis[3] = 0.f;
//check for axis length
SimdScalar len = axis.length2();
if (len < 0.001f)
axis = SimdVector3(1.f,0.f,0.f);
else
axis /= sqrtf(len);
angVel = axis * angle / timeStep;
}
};
#endif //SIMD_TRANSFORM_UTIL_H

396
extern/bullet/LinearMath/SimdVector3.h vendored Normal file
View File

@@ -0,0 +1,396 @@
/*
Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef SIMD__VECTOR3_H
#define SIMD__VECTOR3_H
#include "SimdQuadWord.h"
///SimdVector3 is 16byte aligned, and has an extra unused component m_w
///this extra component can be used by derived classes (Quaternion?) or by user
class SimdVector3 : public SimdQuadWord {
public:
SIMD_FORCE_INLINE SimdVector3() {}
SIMD_FORCE_INLINE SimdVector3(const SimdScalar& x, const SimdScalar& y, const SimdScalar& z)
:SimdQuadWord(x,y,z,0.f)
{
}
// SIMD_FORCE_INLINE SimdVector3(const SimdScalar& x, const SimdScalar& y, const SimdScalar& z,const SimdScalar& w)
// : SimdQuadWord(x,y,z,w)
// {
// }
SIMD_FORCE_INLINE SimdVector3& operator+=(const SimdVector3& v)
{
m_x += v.x(); m_y += v.y(); m_z += v.z();
return *this;
}
SIMD_FORCE_INLINE SimdVector3& operator-=(const SimdVector3& v)
{
m_x -= v.x(); m_y -= v.y(); m_z -= v.z();
return *this;
}
SIMD_FORCE_INLINE SimdVector3& operator*=(const SimdScalar& s)
{
m_x *= s; m_y *= s; m_z *= s;
return *this;
}
SIMD_FORCE_INLINE SimdVector3& operator/=(const SimdScalar& s)
{
assert(s != SimdScalar(0.0));
return *this *= SimdScalar(1.0) / s;
}
SIMD_FORCE_INLINE SimdScalar dot(const SimdVector3& v) const
{
return m_x * v.x() + m_y * v.y() + m_z * v.z();
}
SIMD_FORCE_INLINE SimdScalar length2() const
{
return dot(*this);
}
SIMD_FORCE_INLINE SimdScalar length() const
{
return sqrtf(length2());
}
SIMD_FORCE_INLINE SimdScalar distance2(const SimdVector3& v) const;
SIMD_FORCE_INLINE SimdScalar distance(const SimdVector3& v) const;
SIMD_FORCE_INLINE SimdVector3& normalize()
{
return *this /= length();
}
SIMD_FORCE_INLINE SimdVector3 normalized() const;
SIMD_FORCE_INLINE SimdScalar angle(const SimdVector3& v) const
{
SimdScalar s = sqrtf(length2() * v.length2());
assert(s != SimdScalar(0.0));
return acosf(dot(v) / s);
}
SIMD_FORCE_INLINE SimdVector3 absolute() const
{
return SimdVector3(
fabsf(m_x),
fabsf(m_y),
fabsf(m_z));
}
SIMD_FORCE_INLINE SimdVector3 cross(const SimdVector3& v) const
{
return SimdVector3(
m_y * v.z() - m_z * v.y(),
m_z * v.x() - m_x * v.z(),
m_x * v.y() - m_y * v.x());
}
SIMD_FORCE_INLINE SimdScalar triple(const SimdVector3& v1, const SimdVector3& v2) const
{
return m_x * (v1.y() * v2.z() - v1.z() * v2.y()) +
m_y * (v1.z() * v2.x() - v1.x() * v2.z()) +
m_z * (v1.x() * v2.y() - v1.y() * v2.x());
}
SIMD_FORCE_INLINE int minAxis() const
{
return m_x < m_y ? (m_x < m_z ? 0 : 2) : (m_y < m_z ? 1 : 2);
}
SIMD_FORCE_INLINE int maxAxis() const
{
return m_x < m_y ? (m_y < m_z ? 2 : 1) : (m_x < m_z ? 2 : 0);
}
SIMD_FORCE_INLINE int furthestAxis() const
{
return absolute().minAxis();
}
SIMD_FORCE_INLINE int closestAxis() const
{
return absolute().maxAxis();
}
SIMD_FORCE_INLINE void setInterpolate3(const SimdVector3& v0, const SimdVector3& v1, SimdScalar rt)
{
SimdScalar s = 1.0f - rt;
m_x = s * v0[0] + rt * v1.x();
m_y = s * v0[1] + rt * v1.y();
m_z = s * v0[2] + rt * v1.z();
//don't do the unused w component
// m_co[3] = s * v0[3] + rt * v1[3];
}
SIMD_FORCE_INLINE SimdVector3 lerp(const SimdVector3& v, const SimdScalar& t) const
{
return SimdVector3(m_x + (v.x() - m_x) * t,
m_y + (v.y() - m_y) * t,
m_z + (v.z() - m_z) * t);
}
SIMD_FORCE_INLINE SimdVector3& operator*=(const SimdVector3& v)
{
m_x *= v.x(); m_y *= v.y(); m_z *= v.z();
return *this;
}
};
SIMD_FORCE_INLINE SimdVector3
operator+(const SimdVector3& v1, const SimdVector3& v2)
{
return SimdVector3(v1.x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z());
}
SIMD_FORCE_INLINE SimdVector3
operator*(const SimdVector3& v1, const SimdVector3& v2)
{
return SimdVector3(v1.x() * v2.x(), v1.y() * v2.y(), v1.z() *+ v2.z());
}
SIMD_FORCE_INLINE SimdVector3
operator-(const SimdVector3& v1, const SimdVector3& v2)
{
return SimdVector3(v1.x() - v2.x(), v1.y() - v2.y(), v1.z() - v2.z());
}
SIMD_FORCE_INLINE SimdVector3
operator-(const SimdVector3& v)
{
return SimdVector3(-v.x(), -v.y(), -v.z());
}
SIMD_FORCE_INLINE SimdVector3
operator*(const SimdVector3& v, const SimdScalar& s)
{
return SimdVector3(v.x() * s, v.y() * s, v.z() * s);
}
SIMD_FORCE_INLINE SimdVector3
operator*(const SimdScalar& s, const SimdVector3& v)
{
return v * s;
}
SIMD_FORCE_INLINE SimdVector3
operator/(const SimdVector3& v, const SimdScalar& s)
{
assert(s != SimdScalar(0.0));
return v * (SimdScalar(1.0) / s);
}
SIMD_FORCE_INLINE SimdScalar
dot(const SimdVector3& v1, const SimdVector3& v2)
{
return v1.dot(v2);
}
SIMD_FORCE_INLINE SimdScalar
distance2(const SimdVector3& v1, const SimdVector3& v2)
{
return v1.distance2(v2);
}
SIMD_FORCE_INLINE SimdScalar
distance(const SimdVector3& v1, const SimdVector3& v2)
{
return v1.distance(v2);
}
SIMD_FORCE_INLINE SimdScalar
angle(const SimdVector3& v1, const SimdVector3& v2)
{
return v1.angle(v2);
}
SIMD_FORCE_INLINE SimdVector3
cross(const SimdVector3& v1, const SimdVector3& v2)
{
return v1.cross(v2);
}
SIMD_FORCE_INLINE SimdScalar
triple(const SimdVector3& v1, const SimdVector3& v2, const SimdVector3& v3)
{
return v1.triple(v2, v3);
}
SIMD_FORCE_INLINE SimdVector3
lerp(const SimdVector3& v1, const SimdVector3& v2, const SimdScalar& t)
{
return v1.lerp(v2, t);
}
SIMD_FORCE_INLINE bool operator==(const SimdVector3& p1, const SimdVector3& p2)
{
return p1[0] == p2[0] && p1[1] == p2[1] && p1[2] == p2[2];
}
SIMD_FORCE_INLINE SimdScalar SimdVector3::distance2(const SimdVector3& v) const
{
return (v - *this).length2();
}
SIMD_FORCE_INLINE SimdScalar SimdVector3::distance(const SimdVector3& v) const
{
return (v - *this).length();
}
SIMD_FORCE_INLINE SimdVector3 SimdVector3::normalized() const
{
return *this / length();
}
class SimdVector4 : public SimdVector3
{
public:
SIMD_FORCE_INLINE SimdVector4() {}
SIMD_FORCE_INLINE SimdVector4(const SimdScalar& x, const SimdScalar& y, const SimdScalar& z,const SimdScalar& w)
: SimdVector3(x,y,z)
{
m_unusedW = w;
}
SIMD_FORCE_INLINE SimdVector4 absolute4() const
{
return SimdVector4(
fabsf(m_x),
fabsf(m_y),
fabsf(m_z),
fabsf(m_unusedW));
}
float getW() const { return m_unusedW;}
SIMD_FORCE_INLINE int maxAxis4() const
{
int maxIndex = -1;
float maxVal = -1e30f;
if (m_x > maxVal)
{
maxIndex = 0;
maxVal = m_x;
}
if (m_y > maxVal)
{
maxIndex = 1;
maxVal = m_y;
}
if (m_z > maxVal)
{
maxIndex = 2;
maxVal = m_z;
}
if (m_unusedW > maxVal)
{
maxIndex = 3;
maxVal = m_unusedW;
}
return maxIndex;
}
SIMD_FORCE_INLINE int minAxis4() const
{
int minIndex = -1;
float minVal = 1e30f;
if (m_x < minVal)
{
minIndex = 0;
minVal = m_x;
}
if (m_y < minVal)
{
minIndex = 1;
minVal = m_y;
}
if (m_z < minVal)
{
minIndex = 2;
minVal = m_z;
}
if (m_unusedW < minVal)
{
minIndex = 3;
minVal = m_unusedW;
}
return minIndex;
}
SIMD_FORCE_INLINE int closestAxis4() const
{
return absolute4().maxAxis4();
}
};
#endif //SIMD__VECTOR3_H

239
extern/bullet/continuous.dsw vendored Normal file
View File

@@ -0,0 +1,239 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "Bullet"=.\Bullet\Bullet3.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "BulletDynamics"=.\BulletDynamics\BulletDynamics.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "CcdPhysics"=.\EXTRAS\PHYSICSINTERFACE\CcdPhysics\CcdPhysics.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "CcdPhysicsDemo"=.\Demos\CcdPhysicsDemo\CcdPhysicsDemo.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Bullet
End Project Dependency
Begin Project Dependency
Project_Dep_Name BulletDynamics
End Project Dependency
Begin Project Dependency
Project_Dep_Name OpenGL
End Project Dependency
Begin Project Dependency
Project_Dep_Name CcdPhysics
End Project Dependency
Begin Project Dependency
Project_Dep_Name PhysicsInterface
End Project Dependency
}}}
###############################################################################
Project: "CollisionDemo"=.\Demos\CollisionDemo\CollisionDemo.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Bullet
End Project Dependency
Begin Project Dependency
Project_Dep_Name OpenGL
End Project Dependency
}}}
###############################################################################
Project: "ConcaveDemo"=.\DEMOS\ConcaveDemo\ConcaveDemo.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Bullet
End Project Dependency
Begin Project Dependency
Project_Dep_Name BulletDynamics
End Project Dependency
Begin Project Dependency
Project_Dep_Name CcdPhysics
End Project Dependency
Begin Project Dependency
Project_Dep_Name OpenGL
End Project Dependency
Begin Project Dependency
Project_Dep_Name PhysicsInterface
End Project Dependency
}}}
###############################################################################
Project: "ContinuousConvexCollision"=.\Demos\ContinuousConvexCollision\ContinuousConvexCollision.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Bullet
End Project Dependency
Begin Project Dependency
Project_Dep_Name OpenGL
End Project Dependency
}}}
###############################################################################
Project: "ConvexHullDistance"=.\DEMOS\ConvexHullDistance\ConvexHullDistance.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Bullet
End Project Dependency
Begin Project Dependency
Project_Dep_Name OpenGL
End Project Dependency
}}}
###############################################################################
Project: "GjkConvexCastDemo"=.\Demos\GjkConvexCastDemo\GjkConvexCastDemo.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Bullet
End Project Dependency
Begin Project Dependency
Project_Dep_Name OpenGL
End Project Dependency
}}}
###############################################################################
Project: "OpenGL"=.\Demos\OpenGL\OpenGL.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "PhysicsInterface"=.\EXTRAS\PHYSICSINTERFACE\Common\PhysicsInterface.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "Raytracer"=.\Demos\Raytracer\Raytracer.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Bullet
End Project Dependency
Begin Project Dependency
Project_Dep_Name OpenGL
End Project Dependency
}}}
###############################################################################
Project: "SimplexDemo"=.\Demos\SimplexDemo\SimplexDemo.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Bullet
End Project Dependency
Begin Project Dependency
Project_Dep_Name OpenGL
End Project Dependency
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

140
extern/bullet/continuous_vc7.sln vendored Normal file
View File

@@ -0,0 +1,140 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenGLSupport", "Demos\OpenGL\OpenGL_vc7.vcproj", "{47328C1E-54A4-4065-B3DA-F88EE281D1E5}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bullet3ContinuousCollision", "Bullet\Bullet3_vc7.vcproj", "{FFD3C64A-30E2-4BC7-BC8F-51818C320400}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimplexDemo", "Demos\SimplexDemo\SimplexDemo_vc7.vcproj", "{F6B9DD8D-8C40-4F2B-B492-56B167D01CC0}"
ProjectSection(ProjectDependencies) = postProject
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CollisionDemo", "Demos\CollisionDemo\CollisionDemo_vc7.vcproj", "{F43EFC77-3CFA-4669-BAEA-1E2BC8ABA897}"
ProjectSection(ProjectDependencies) = postProject
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinearConvexCastDemo", "Demos\GjkConvexCastDemo\GjkConvexCastDemo_vc7.vcproj", "{B395AFF6-94FE-4A2C-9E26-58E5BE85083C}"
ProjectSection(ProjectDependencies) = postProject
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ContinuousConvexCollisionDemo", "Demos\ContinuousConvexCollision\ContinuousConvexCollision_vc7.vcproj", "{6A4E3433-D0CD-4A10-BE09-78C9A5F7508B}"
ProjectSection(ProjectDependencies) = postProject
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Raytracer", "Demos\Raytracer\Raytracer_vc7.vcproj", "{F8B0A298-14C9-4006-8D53-51032892BEDD}"
ProjectSection(ProjectDependencies) = postProject
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bullet3Dynamics", "BulletDynamics\BulletDynamics_vc7.vcproj", "{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CcdPhysics", "Extras\PhysicsInterface\CcdPhysics\CcdPhysics_vc7.vcproj", "{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PhysicsInterfaceCommon", "Extras\PhysicsInterface\Common\PhysicsInterfaceCommon\PhysicsInterfaceCommon_vc7.vcproj", "{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CcdPhysicsDemo", "Demos\CcdPhysicsDemo\CcdPhysicsDemo_vc7.vcproj", "{E9C93159-EC18-4121-9D73-1DE7053D81D7}"
ProjectSection(ProjectDependencies) = postProject
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580} = {87D8C006-6DCC-4156-A03E-8CEA1B4C0580}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE} = {E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4} = {3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConcaveDemo", "Demos\ConcaveDemo\ConcaveDemo.vcproj", "{F20F38CC-CFA7-40C7-81AE-945C8C09E473}"
ProjectSection(ProjectDependencies) = postProject
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580} = {87D8C006-6DCC-4156-A03E-8CEA1B4C0580}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE} = {E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4} = {3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConvexHullDistance", "Demos\ConvexHullDistance\ConvexHullDistance_vc7.vcproj", "{AF9E7C2B-BE49-4101-B056-4A628B276389}"
ProjectSection(ProjectDependencies) = postProject
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{47328C1E-54A4-4065-B3DA-F88EE281D1E5}.Debug.ActiveCfg = Debug|Win32
{47328C1E-54A4-4065-B3DA-F88EE281D1E5}.Debug.Build.0 = Debug|Win32
{47328C1E-54A4-4065-B3DA-F88EE281D1E5}.Release.ActiveCfg = Release|Win32
{47328C1E-54A4-4065-B3DA-F88EE281D1E5}.Release.Build.0 = Release|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Debug.ActiveCfg = Debug|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Debug.Build.0 = Debug|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Release.ActiveCfg = Release|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Release.Build.0 = Release|Win32
{F6B9DD8D-8C40-4F2B-B492-56B167D01CC0}.Debug.ActiveCfg = Debug|Win32
{F6B9DD8D-8C40-4F2B-B492-56B167D01CC0}.Debug.Build.0 = Debug|Win32
{F6B9DD8D-8C40-4F2B-B492-56B167D01CC0}.Release.ActiveCfg = Release|Win32
{F6B9DD8D-8C40-4F2B-B492-56B167D01CC0}.Release.Build.0 = Release|Win32
{F43EFC77-3CFA-4669-BAEA-1E2BC8ABA897}.Debug.ActiveCfg = Debug|Win32
{F43EFC77-3CFA-4669-BAEA-1E2BC8ABA897}.Debug.Build.0 = Debug|Win32
{F43EFC77-3CFA-4669-BAEA-1E2BC8ABA897}.Release.ActiveCfg = Release|Win32
{F43EFC77-3CFA-4669-BAEA-1E2BC8ABA897}.Release.Build.0 = Release|Win32
{B395AFF6-94FE-4A2C-9E26-58E5BE85083C}.Debug.ActiveCfg = Debug|Win32
{B395AFF6-94FE-4A2C-9E26-58E5BE85083C}.Debug.Build.0 = Debug|Win32
{B395AFF6-94FE-4A2C-9E26-58E5BE85083C}.Release.ActiveCfg = Release|Win32
{B395AFF6-94FE-4A2C-9E26-58E5BE85083C}.Release.Build.0 = Release|Win32
{6A4E3433-D0CD-4A10-BE09-78C9A5F7508B}.Debug.ActiveCfg = Debug|Win32
{6A4E3433-D0CD-4A10-BE09-78C9A5F7508B}.Debug.Build.0 = Debug|Win32
{6A4E3433-D0CD-4A10-BE09-78C9A5F7508B}.Release.ActiveCfg = Release|Win32
{6A4E3433-D0CD-4A10-BE09-78C9A5F7508B}.Release.Build.0 = Release|Win32
{F8B0A298-14C9-4006-8D53-51032892BEDD}.Debug.ActiveCfg = Debug|Win32
{F8B0A298-14C9-4006-8D53-51032892BEDD}.Debug.Build.0 = Debug|Win32
{F8B0A298-14C9-4006-8D53-51032892BEDD}.Release.ActiveCfg = Release|Win32
{F8B0A298-14C9-4006-8D53-51032892BEDD}.Release.Build.0 = Release|Win32
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}.Debug.ActiveCfg = Debug|Win32
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}.Debug.Build.0 = Debug|Win32
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}.Release.ActiveCfg = Release|Win32
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}.Release.Build.0 = Release|Win32
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}.Debug.ActiveCfg = Debug|Win32
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}.Debug.Build.0 = Debug|Win32
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}.Release.ActiveCfg = Release|Win32
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}.Release.Build.0 = Release|Win32
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}.Debug.ActiveCfg = Debug|Win32
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}.Debug.Build.0 = Debug|Win32
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}.Release.ActiveCfg = Release|Win32
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}.Release.Build.0 = Release|Win32
{E9C93159-EC18-4121-9D73-1DE7053D81D7}.Debug.ActiveCfg = Debug|Win32
{E9C93159-EC18-4121-9D73-1DE7053D81D7}.Debug.Build.0 = Debug|Win32
{E9C93159-EC18-4121-9D73-1DE7053D81D7}.Release.ActiveCfg = Release|Win32
{E9C93159-EC18-4121-9D73-1DE7053D81D7}.Release.Build.0 = Release|Win32
{F20F38CC-CFA7-40C7-81AE-945C8C09E473}.Debug.ActiveCfg = Debug|Win32
{F20F38CC-CFA7-40C7-81AE-945C8C09E473}.Debug.Build.0 = Debug|Win32
{F20F38CC-CFA7-40C7-81AE-945C8C09E473}.Release.ActiveCfg = Release|Win32
{F20F38CC-CFA7-40C7-81AE-945C8C09E473}.Release.Build.0 = Release|Win32
{AF9E7C2B-BE49-4101-B056-4A628B276389}.Debug.ActiveCfg = Debug|Win32
{AF9E7C2B-BE49-4101-B056-4A628B276389}.Debug.Build.0 = Debug|Win32
{AF9E7C2B-BE49-4101-B056-4A628B276389}.Release.ActiveCfg = Release|Win32
{AF9E7C2B-BE49-4101-B056-4A628B276389}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

129
extern/bullet/continuous_vc8.sln vendored Normal file
View File

@@ -0,0 +1,129 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenGLSupport", "Demos\OpenGL\OpenGL_vc8.vcproj", "{47328C1E-54A4-4065-B3DA-F88EE281D1E5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bullet3ContinuousCollision", "Bullet\Bullet3_vc8.vcproj", "{FFD3C64A-30E2-4BC7-BC8F-51818C320400}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimplexDemo", "Demos\SimplexDemo\SimplexDemo_vc8.vcproj", "{F6B9DD8D-8C40-4F2B-B492-56B167D01CC0}"
ProjectSection(ProjectDependencies) = postProject
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CollisionDemo", "Demos\CollisionDemo\CollisionDemo_vc8.vcproj", "{F43EFC77-3CFA-4669-BAEA-1E2BC8ABA897}"
ProjectSection(ProjectDependencies) = postProject
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinearConvexCastDemo", "Demos\GjkConvexCastDemo\GjkConvexCastDemo_vc8.vcproj", "{B395AFF6-94FE-4A2C-9E26-58E5BE85083C}"
ProjectSection(ProjectDependencies) = postProject
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ContinuousConvexCollisionDemo", "Demos\ContinuousConvexCollision\ContinuousConvexCollision_vc8.vcproj", "{6A4E3433-D0CD-4A10-BE09-78C9A5F7508B}"
ProjectSection(ProjectDependencies) = postProject
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Raytracer", "Demos\Raytracer\Raytracer_vc8.vcproj", "{F8B0A298-14C9-4006-8D53-51032892BEDD}"
ProjectSection(ProjectDependencies) = postProject
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bullet3Dynamics", "BulletDynamics\BulletDynamics_vc8.vcproj", "{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CcdPhysicsDemo", "Demos\CcdPhysicsDemo\CcdPhysicsDemo_vc8.vcproj", "{E9C93159-EC18-4121-9D73-1DE7053D81D7}"
ProjectSection(ProjectDependencies) = postProject
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4} = {3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE} = {E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580} = {87D8C006-6DCC-4156-A03E-8CEA1B4C0580}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CcdPhysics", "Extras\PhysicsInterface\CcdPhysics\CcdPhysics_vc8.vcproj", "{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PhysicsInterfaceCommon", "Extras\PhysicsInterface\Common\PhysicsInterfaceCommon\PhysicsInterfaceCommon_vc8.vcproj", "{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConvexHullDistance", "Demos\ConvexHullDistance\ConvexHullDistance_vc8.vcproj", "{39A0C0E0-773B-498D-B9B1-B54525FB6223}"
ProjectSection(ProjectDependencies) = postProject
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConcaveDemo", "Demos\ConcaveDemo\ConcaveDemo_vc8.vcproj", "{F20F38CC-CFA7-40C7-81AE-945C8C09E473}"
ProjectSection(ProjectDependencies) = postProject
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580} = {87D8C006-6DCC-4156-A03E-8CEA1B4C0580}
{47328C1E-54A4-4065-B3DA-F88EE281D1E5} = {47328C1E-54A4-4065-B3DA-F88EE281D1E5}
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE} = {E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}
{FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4} = {3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{47328C1E-54A4-4065-B3DA-F88EE281D1E5}.Debug|Win32.ActiveCfg = Debug|Win32
{47328C1E-54A4-4065-B3DA-F88EE281D1E5}.Debug|Win32.Build.0 = Debug|Win32
{47328C1E-54A4-4065-B3DA-F88EE281D1E5}.Release|Win32.ActiveCfg = Release|Win32
{47328C1E-54A4-4065-B3DA-F88EE281D1E5}.Release|Win32.Build.0 = Release|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Debug|Win32.ActiveCfg = Debug|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Debug|Win32.Build.0 = Debug|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Release|Win32.ActiveCfg = Release|Win32
{FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Release|Win32.Build.0 = Release|Win32
{F6B9DD8D-8C40-4F2B-B492-56B167D01CC0}.Debug|Win32.ActiveCfg = Debug|Win32
{F6B9DD8D-8C40-4F2B-B492-56B167D01CC0}.Debug|Win32.Build.0 = Debug|Win32
{F6B9DD8D-8C40-4F2B-B492-56B167D01CC0}.Release|Win32.ActiveCfg = Release|Win32
{F6B9DD8D-8C40-4F2B-B492-56B167D01CC0}.Release|Win32.Build.0 = Release|Win32
{F43EFC77-3CFA-4669-BAEA-1E2BC8ABA897}.Debug|Win32.ActiveCfg = Debug|Win32
{F43EFC77-3CFA-4669-BAEA-1E2BC8ABA897}.Debug|Win32.Build.0 = Debug|Win32
{F43EFC77-3CFA-4669-BAEA-1E2BC8ABA897}.Release|Win32.ActiveCfg = Release|Win32
{F43EFC77-3CFA-4669-BAEA-1E2BC8ABA897}.Release|Win32.Build.0 = Release|Win32
{B395AFF6-94FE-4A2C-9E26-58E5BE85083C}.Debug|Win32.ActiveCfg = Debug|Win32
{B395AFF6-94FE-4A2C-9E26-58E5BE85083C}.Debug|Win32.Build.0 = Debug|Win32
{B395AFF6-94FE-4A2C-9E26-58E5BE85083C}.Release|Win32.ActiveCfg = Release|Win32
{B395AFF6-94FE-4A2C-9E26-58E5BE85083C}.Release|Win32.Build.0 = Release|Win32
{6A4E3433-D0CD-4A10-BE09-78C9A5F7508B}.Debug|Win32.ActiveCfg = Debug|Win32
{6A4E3433-D0CD-4A10-BE09-78C9A5F7508B}.Debug|Win32.Build.0 = Debug|Win32
{6A4E3433-D0CD-4A10-BE09-78C9A5F7508B}.Release|Win32.ActiveCfg = Release|Win32
{6A4E3433-D0CD-4A10-BE09-78C9A5F7508B}.Release|Win32.Build.0 = Release|Win32
{F8B0A298-14C9-4006-8D53-51032892BEDD}.Debug|Win32.ActiveCfg = Debug|Win32
{F8B0A298-14C9-4006-8D53-51032892BEDD}.Debug|Win32.Build.0 = Debug|Win32
{F8B0A298-14C9-4006-8D53-51032892BEDD}.Release|Win32.ActiveCfg = Release|Win32
{F8B0A298-14C9-4006-8D53-51032892BEDD}.Release|Win32.Build.0 = Release|Win32
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}.Debug|Win32.ActiveCfg = Debug|Win32
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}.Debug|Win32.Build.0 = Debug|Win32
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}.Release|Win32.ActiveCfg = Release|Win32
{3427A9EF-FF84-4B3E-9AE5-C37CF44D7DA4}.Release|Win32.Build.0 = Release|Win32
{E9C93159-EC18-4121-9D73-1DE7053D81D7}.Debug|Win32.ActiveCfg = Debug|Win32
{E9C93159-EC18-4121-9D73-1DE7053D81D7}.Debug|Win32.Build.0 = Debug|Win32
{E9C93159-EC18-4121-9D73-1DE7053D81D7}.Release|Win32.ActiveCfg = Release|Win32
{E9C93159-EC18-4121-9D73-1DE7053D81D7}.Release|Win32.Build.0 = Release|Win32
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}.Debug|Win32.ActiveCfg = Debug|Win32
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}.Debug|Win32.Build.0 = Debug|Win32
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}.Release|Win32.ActiveCfg = Release|Win32
{E3D57F36-36AC-4E9A-B0E0-2AE4510FCBFE}.Release|Win32.Build.0 = Release|Win32
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}.Debug|Win32.ActiveCfg = Debug|Win32
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}.Debug|Win32.Build.0 = Debug|Win32
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}.Release|Win32.ActiveCfg = Release|Win32
{87D8C006-6DCC-4156-A03E-8CEA1B4C0580}.Release|Win32.Build.0 = Release|Win32
{39A0C0E0-773B-498D-B9B1-B54525FB6223}.Debug|Win32.ActiveCfg = Debug|Win32
{39A0C0E0-773B-498D-B9B1-B54525FB6223}.Debug|Win32.Build.0 = Debug|Win32
{39A0C0E0-773B-498D-B9B1-B54525FB6223}.Release|Win32.ActiveCfg = Release|Win32
{39A0C0E0-773B-498D-B9B1-B54525FB6223}.Release|Win32.Build.0 = Release|Win32
{F20F38CC-CFA7-40C7-81AE-945C8C09E473}.Debug|Win32.ActiveCfg = Debug|Win32
{F20F38CC-CFA7-40C7-81AE-945C8C09E473}.Debug|Win32.Build.0 = Debug|Win32
{F20F38CC-CFA7-40C7-81AE-945C8C09E473}.Release|Win32.ActiveCfg = Release|Win32
{F20F38CC-CFA7-40C7-81AE-945C8C09E473}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal