1) Updated to bullet 2.66, which (among others)
- fixes the bug of resetting the forces after each internal simulation step, causing slower physics behaviour on slower FPS. - improves raycast performance 2) Added script to copy all necessary source files from a full bullet installation into STK. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1374 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
e0a96abe15
commit
8c453e472e
@ -1,6 +1,79 @@
|
|||||||
Bullet Continuous Collision Detection and Physics Library
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
Primary author and maintainer: Erwin Coumans
|
Primary author and maintainer: Erwin Coumans
|
||||||
|
|
||||||
|
2007 Dec 16
|
||||||
|
- Added btRigidBodyConstructionInfo, to make it easier to set individual setting (and leave other untouched) during rigid body construction.
|
||||||
|
Thanks Vangelis Kokkevis for pointing this out.
|
||||||
|
- Fixed memoryleak in the ConstraintDemo and Raytracer demo.
|
||||||
|
- Fixed issue with clearing forces/gravity at the end of the stepSimulation, instead of during internalSingleStepSimulation.
|
||||||
|
Thanks chunky for pointing this out: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1780
|
||||||
|
- Disabled additional damping in rigid body by default, but enable it in most demos. Set btRigidBodyConstructionInfo m_additionalDamping to true to enable this.
|
||||||
|
- Removed obsolete QUICKPROF BEGIN/END_PROFILE, and enabled BT_PROFILE. Profiling is enabled by default (see Bullet/Demos/OpenGL/DemoApplication.cpp how to use this).
|
||||||
|
User can switch off profiling by enabling define BT_NO_PROFILE in Bullet/src/btQuickprof.h.
|
||||||
|
|
||||||
|
2007 Dec 14
|
||||||
|
- Added Hello World and BulletMultiThreaded demos
|
||||||
|
- Add portable version of BulletMultiThreaded, through SequentialThreadSupport (non-parallel but sharing the same code-path)
|
||||||
|
- Add Cmake support for AllBulletDemos
|
||||||
|
|
||||||
|
|
||||||
|
2007 Dec 11
|
||||||
|
- Moved the 'btRigidBody::clearForce' to the end of the stepSimulation, instead of in each substep.
|
||||||
|
See discussion http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1601
|
||||||
|
- Added btConvexPlaneCollisionAlgorithm, makes planes perform better, and prevents tunneling
|
||||||
|
Thanks Andy O'Neil for reporting the performance/functionality issue
|
||||||
|
- Fixes for IBM Cell SDK 3.0
|
||||||
|
Thanks to Jochen Roth for the patch.
|
||||||
|
|
||||||
|
2007 Dec 10
|
||||||
|
- Fixes in btHeightfieldTerrainShape
|
||||||
|
Thanks to Jay Lee for the patch.
|
||||||
|
|
||||||
|
2007 Dec 9
|
||||||
|
- Only update aabb of active objects
|
||||||
|
Thanks Peter Tchernev for reporting (http://bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1764 )
|
||||||
|
- Added workaround to compile libxml under Visual Studio 2008 Beta 2
|
||||||
|
- Make glui compile under MSVC 9.0 beta (vsnprintf is already defined)
|
||||||
|
|
||||||
|
2007 Dec 6
|
||||||
|
- Added DynamicControlDemo, showing dynamic control through constraint motors
|
||||||
|
Thanks to Eddy Boxerman
|
||||||
|
- Add support for generic concave shapes for convex cast.
|
||||||
|
- Added convex cast query to collision world.
|
||||||
|
- Added workaround for OpenGL bug in Mac OS X 10.5.0 (Leopard)
|
||||||
|
- Added concave raycast demo
|
||||||
|
All above thanks to John McCutchan (JMC)
|
||||||
|
- Fixed issues that prevent Linux version to compile.
|
||||||
|
Thanks to Enrico for reporting and patch, see
|
||||||
|
- Fixed misleading name 'numTriangleIndices' into 'numTriangles'
|
||||||
|
Thanks Sean Tasker for reporting:
|
||||||
|
|
||||||
|
2007 Nov 28:
|
||||||
|
- Added raycast against trianglemesh. Will be extended to object cast soon.
|
||||||
|
Thanks John McCutchan (JMC)
|
||||||
|
- make getNumPoints const correct, add const getPoints().
|
||||||
|
Thanks Dirk Gregorius
|
||||||
|
- Bugfix: allow btCollisionObjects (non-btRigidBody) to interact properly with btRigidBody for cache-friendly btSequentialImpulseConstraintSolver.
|
||||||
|
Thanks Andy O'Neil for pointing this out.
|
||||||
|
- Bugfix: don't fail if spheres have identical center, use arbitrary separating normal (1,0,0)
|
||||||
|
Thanks Sean Tasker for reporting! http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1681
|
||||||
|
|
||||||
|
|
||||||
|
2007, November 20
|
||||||
|
- Added hierarchical profiling
|
||||||
|
- Fixed memory leak in btMultiSapBroadphase,
|
||||||
|
- Fixed hash function (typo, should use 2 proxies)
|
||||||
|
Thanks to Stephen (shatcher) for reporting and fixes! http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1696
|
||||||
|
|
||||||
|
2007 Nov 11
|
||||||
|
- Fixed parallel solver (BulletMultiThreaded) friction issue
|
||||||
|
- Terminate Win32 Threads when closing the CcdPhysicsDemo (when USE_PARALLEL_SOLVER/USE_PARALLEL_DISPATCHER is defined)
|
||||||
|
|
||||||
|
2007 Nov 6
|
||||||
|
- Added support for 16-bit indices for triangle meshes
|
||||||
|
- Added support for multiple mesh parts using btBvhTriangleMeshShape.
|
||||||
|
Thanks to Tim Johansson
|
||||||
|
|
||||||
2007 Oct 22
|
2007 Oct 22
|
||||||
- All memory allocations go through btAlignedAlloc/btAlignedFree. User can override this to verify memory leaks
|
- All memory allocations go through btAlignedAlloc/btAlignedFree. User can override this to verify memory leaks
|
||||||
- added a few more demos to AllBulletDemos
|
- added a few more demos to AllBulletDemos
|
||||||
|
@ -29,6 +29,7 @@ subject to the following restrictions:
|
|||||||
#include "LinearMath/btQuickprof.h"
|
#include "LinearMath/btQuickprof.h"
|
||||||
#include "LinearMath/btDefaultMotionState.h"
|
#include "LinearMath/btDefaultMotionState.h"
|
||||||
|
|
||||||
|
|
||||||
#include "BMF_Api.h"
|
#include "BMF_Api.h"
|
||||||
|
|
||||||
extern bool gDisableDeactivation;
|
extern bool gDisableDeactivation;
|
||||||
@ -71,12 +72,15 @@ m_shootBoxShape(0),
|
|||||||
m_singleStep(false),
|
m_singleStep(false),
|
||||||
m_idle(false)
|
m_idle(false)
|
||||||
{
|
{
|
||||||
|
m_profileIterator = CProfileManager::Get_Iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DemoApplication::~DemoApplication()
|
DemoApplication::~DemoApplication()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
CProfileManager::Release_Iterator(m_profileIterator);
|
||||||
if (m_shootBoxShape)
|
if (m_shootBoxShape)
|
||||||
delete m_shootBoxShape;
|
delete m_shootBoxShape;
|
||||||
|
|
||||||
@ -231,8 +235,6 @@ void DemoApplication::reshape(int w, int h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DemoApplication::keyboardCallback(unsigned char key, int x, int y)
|
void DemoApplication::keyboardCallback(unsigned char key, int x, int y)
|
||||||
{
|
{
|
||||||
(void)x;
|
(void)x;
|
||||||
@ -240,9 +242,27 @@ void DemoApplication::keyboardCallback(unsigned char key, int x, int y)
|
|||||||
|
|
||||||
m_lastKey = 0;
|
m_lastKey = 0;
|
||||||
|
|
||||||
|
if (key >= 0x31 && key < 0x37)
|
||||||
|
{
|
||||||
|
int child = key-0x31;
|
||||||
|
m_profileIterator->Enter_Child(child);
|
||||||
|
}
|
||||||
|
if (key==0x30)
|
||||||
|
{
|
||||||
|
m_profileIterator->Enter_Parent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case 'q' : exit(0); break;
|
case 'q' :
|
||||||
|
#ifdef BT_USE_FREEGLUT
|
||||||
|
//return from glutMainLoop(), detect memory leaks etc.
|
||||||
|
glutLeaveMainLoop();
|
||||||
|
#else
|
||||||
|
exit(0);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
case 'l' : stepLeft(); break;
|
case 'l' : stepLeft(); break;
|
||||||
case 'r' : stepRight(); break;
|
case 'r' : stepRight(); break;
|
||||||
@ -469,7 +489,7 @@ void DemoApplication::shootBox(const btVector3& destination)
|
|||||||
|
|
||||||
if (m_dynamicsWorld)
|
if (m_dynamicsWorld)
|
||||||
{
|
{
|
||||||
float mass = 100.f;
|
float mass = 10.f;
|
||||||
btTransform startTransform;
|
btTransform startTransform;
|
||||||
startTransform.setIdentity();
|
startTransform.setIdentity();
|
||||||
btVector3 camPos = getCameraPosition();
|
btVector3 camPos = getCameraPosition();
|
||||||
@ -482,7 +502,7 @@ void DemoApplication::shootBox(const btVector3& destination)
|
|||||||
btConvexShape* childShape = new btBoxShape(btVector3(1.f,1.f,1.f));
|
btConvexShape* childShape = new btBoxShape(btVector3(1.f,1.f,1.f));
|
||||||
m_shootBoxShape = new btUniformScalingShape(childShape,0.5f);
|
m_shootBoxShape = new btUniformScalingShape(childShape,0.5f);
|
||||||
#else
|
#else
|
||||||
m_shootBoxShape = new btBoxShape(btVector3(0.5f,0.5f,0.5f));
|
m_shootBoxShape = new btBoxShape(btVector3(1.f,1.f,1.f));
|
||||||
#endif//
|
#endif//
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,7 +736,7 @@ btRigidBody* DemoApplication::localCreateRigidBody(float mass, const btTransform
|
|||||||
#define USE_MOTIONSTATE 1
|
#define USE_MOTIONSTATE 1
|
||||||
#ifdef USE_MOTIONSTATE
|
#ifdef USE_MOTIONSTATE
|
||||||
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
|
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
|
||||||
btRigidBody* body = new btRigidBody(mass,myMotionState,shape,localInertia);
|
btRigidBody* body = new btRigidBody(btRigidBody::btRigidBodyConstructionInfo(mass,myMotionState,shape,localInertia));
|
||||||
|
|
||||||
#else
|
#else
|
||||||
btRigidBody* body = new btRigidBody(mass,0,shape,localInertia);
|
btRigidBody* body = new btRigidBody(mass,0,shape,localInertia);
|
||||||
@ -756,6 +776,88 @@ void DemoApplication::resetPerspectiveProjection()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern CProfileIterator * m_profileIterator;
|
||||||
|
|
||||||
|
void DemoApplication::displayProfileString(int xOffset,int yStart,char* message)
|
||||||
|
{
|
||||||
|
glRasterPos3f(xOffset,yStart,0);
|
||||||
|
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DemoApplication::showProfileInfo(float& xOffset,float& yStart, float yIncr)
|
||||||
|
{
|
||||||
|
|
||||||
|
static double time_since_reset = 0.f;
|
||||||
|
if (!m_idle)
|
||||||
|
{
|
||||||
|
time_since_reset = CProfileManager::Get_Time_Since_Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
//recompute profiling data, and store profile strings
|
||||||
|
|
||||||
|
char blockTime[128];
|
||||||
|
|
||||||
|
double totalTime = 0;
|
||||||
|
|
||||||
|
int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
|
||||||
|
|
||||||
|
m_profileIterator->First();
|
||||||
|
|
||||||
|
double parent_time = m_profileIterator->Is_Root() ? time_since_reset : m_profileIterator->Get_Current_Parent_Total_Time();
|
||||||
|
|
||||||
|
{
|
||||||
|
sprintf(blockTime,"--- Profiling: %s (total running time: %.3f ms) ---", m_profileIterator->Get_Current_Parent_Name(), parent_time );
|
||||||
|
displayProfileString(xOffset,yStart,blockTime);
|
||||||
|
yStart += yIncr;
|
||||||
|
sprintf(blockTime,"press number (1,2...) to display child timings, or 0 to go up to parent" );
|
||||||
|
displayProfileString(xOffset,yStart,blockTime);
|
||||||
|
yStart += yIncr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double accumulated_time = 0.f;
|
||||||
|
|
||||||
|
for (int i = 0; !m_profileIterator->Is_Done(); m_profileIterator->Next())
|
||||||
|
{
|
||||||
|
double current_total_time = m_profileIterator->Get_Current_Total_Time();
|
||||||
|
accumulated_time += current_total_time;
|
||||||
|
double fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
|
||||||
|
|
||||||
|
sprintf(blockTime,"%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)",
|
||||||
|
++i, m_profileIterator->Get_Current_Name(), fraction,
|
||||||
|
(current_total_time / (double)frames_since_reset),m_profileIterator->Get_Current_Total_Calls());
|
||||||
|
displayProfileString(xOffset,yStart,blockTime);
|
||||||
|
yStart += yIncr;
|
||||||
|
totalTime += current_total_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(blockTime,"%s (%.3f %%) :: %.3f ms", "Unaccounted",
|
||||||
|
// (min(0, time_since_reset - totalTime) / time_since_reset) * 100);
|
||||||
|
parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
|
||||||
|
|
||||||
|
displayProfileString(xOffset,yStart,blockTime);
|
||||||
|
yStart += yIncr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sprintf(blockTime,"-------------------------------------------------");
|
||||||
|
displayProfileString(xOffset,yStart,blockTime);
|
||||||
|
yStart += yIncr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DemoApplication::renderme()
|
void DemoApplication::renderme()
|
||||||
{
|
{
|
||||||
updateCamera();
|
updateCamera();
|
||||||
@ -823,6 +925,8 @@ void DemoApplication::renderme()
|
|||||||
{
|
{
|
||||||
setOrthographicProjection();
|
setOrthographicProjection();
|
||||||
|
|
||||||
|
showProfileInfo(xOffset,yStart,yIncr);
|
||||||
|
|
||||||
#ifdef USE_QUICKPROF
|
#ifdef USE_QUICKPROF
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,18 +17,7 @@ subject to the following restrictions:
|
|||||||
#define DEMO_APPLICATION_H
|
#define DEMO_APPLICATION_H
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32//for glut.h
|
#include "GlutStuff.h"
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//think different
|
|
||||||
#if defined(__APPLE__) && !defined (VMDMESA)
|
|
||||||
#include <OpenGL/gl.h>
|
|
||||||
#include <OpenGL/glu.h>
|
|
||||||
#include <GLUT/glut.h>
|
|
||||||
#else
|
|
||||||
#include <GL/glut.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -39,15 +28,21 @@ subject to the following restrictions:
|
|||||||
#include "LinearMath/btMatrix3x3.h"
|
#include "LinearMath/btMatrix3x3.h"
|
||||||
#include "LinearMath/btTransform.h"
|
#include "LinearMath/btTransform.h"
|
||||||
#include "LinearMath/btQuickprof.h"
|
#include "LinearMath/btQuickprof.h"
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
class btCollisionShape;
|
class btCollisionShape;
|
||||||
class btDynamicsWorld;
|
class btDynamicsWorld;
|
||||||
class btRigidBody;
|
class btRigidBody;
|
||||||
class btTypedConstraint;
|
class btTypedConstraint;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DemoApplication
|
class DemoApplication
|
||||||
{
|
{
|
||||||
|
void displayProfileString(int xOffset,int yStart,char* message);
|
||||||
|
class CProfileIterator* m_profileIterator;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
btClock m_clock;
|
btClock m_clock;
|
||||||
@ -82,7 +77,10 @@ class DemoApplication
|
|||||||
bool m_singleStep;
|
bool m_singleStep;
|
||||||
bool m_idle;
|
bool m_idle;
|
||||||
int m_lastKey;
|
int m_lastKey;
|
||||||
|
|
||||||
|
void showProfileInfo(float& xOffset,float& yStart, float yIncr);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DemoApplication();
|
DemoApplication();
|
||||||
|
@ -66,7 +66,6 @@ static void glutDisplayCallback(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int glutmain(int argc, char **argv,int width,int height,const char* title,DemoApplication* demoApp) {
|
int glutmain(int argc, char **argv,int width,int height,const char* title,DemoApplication* demoApp) {
|
||||||
|
|
||||||
gDemoApplication = demoApp;
|
gDemoApplication = demoApp;
|
||||||
@ -76,7 +75,10 @@ int glutmain(int argc, char **argv,int width,int height,const char* title,DemoAp
|
|||||||
glutInitWindowPosition(0, 0);
|
glutInitWindowPosition(0, 0);
|
||||||
glutInitWindowSize(width, height);
|
glutInitWindowSize(width, height);
|
||||||
glutCreateWindow(title);
|
glutCreateWindow(title);
|
||||||
|
#ifdef BT_USE_FREEGLUT
|
||||||
|
glutSetOption (GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
|
||||||
|
#endif
|
||||||
|
|
||||||
gDemoApplication->myinit();
|
gDemoApplication->myinit();
|
||||||
|
|
||||||
glutKeyboardFunc(glutKeyboardCallback);
|
glutKeyboardFunc(glutKeyboardCallback);
|
||||||
|
@ -15,6 +15,24 @@ subject to the following restrictions:
|
|||||||
#ifndef GLUT_STUFF_H
|
#ifndef GLUT_STUFF_H
|
||||||
#define GLUT_STUFF_H
|
#define GLUT_STUFF_H
|
||||||
|
|
||||||
|
#ifdef WIN32//for glut.h
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//think different
|
||||||
|
#if defined(__APPLE__) && !defined (VMDMESA)
|
||||||
|
#include <OpenGL/gl.h>
|
||||||
|
#include <OpenGL/glu.h>
|
||||||
|
#include <GLUT/glut.h>
|
||||||
|
#else
|
||||||
|
#include <GL/glut.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BT_USE_FREEGLUT
|
||||||
|
#include "GL/freeglut_ext.h" //to be able to return from glutMainLoop()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class DemoApplication;
|
class DemoApplication;
|
||||||
|
|
||||||
int glutmain(int argc, char **argv,int width,int height,const char* title,DemoApplication* demoApp);
|
int glutmain(int argc, char **argv,int width,int height,const char* title,DemoApplication* demoApp);
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
Bullet Collision Detection and Physics Library version 2.64
|
Bullet Collision Detection and Physics Library version 2.66
|
||||||
http://bullet.sourceforge.net
|
http://bullet.sourceforge.net
|
||||||
|
|
||||||
|
28
src/bullet/copy_bullet_files
Executable file
28
src/bullet/copy_bullet_files
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
LOCATION=$1
|
||||||
|
cp $LOCATION/AUTHORS .
|
||||||
|
cp $LOCATION/BulletLicense.txt .
|
||||||
|
cp $LOCATION/ChangeLog.txt .
|
||||||
|
cp $LOCATION/LICENSE .
|
||||||
|
cp $LOCATION/Makefile.am .
|
||||||
|
cp $LOCATION/README .
|
||||||
|
cp $LOCATION/VERSION .
|
||||||
|
cp $LOCATION/src/*.h src
|
||||||
|
cp $LOCATION/src/LinearMath/*.h src/LinearMath/
|
||||||
|
cp $LOCATION/src/LinearMath/*.cpp src/LinearMath/
|
||||||
|
cp $LOCATION/src/BulletCollision/BroadphaseCollision/*.h src/BulletCollision/BroadphaseCollision
|
||||||
|
cp $LOCATION/src/BulletCollision/BroadphaseCollision/*.cpp src/BulletCollision/BroadphaseCollision
|
||||||
|
cp $LOCATION/src/BulletCollision/CollisionDispatch/*.h src/BulletCollision/CollisionDispatch
|
||||||
|
cp $LOCATION/src/BulletCollision/CollisionDispatch/*.cpp src/BulletCollision/CollisionDispatch
|
||||||
|
cp $LOCATION/src/BulletCollision/CollisionShapes/*.h src/BulletCollision/CollisionShapes
|
||||||
|
cp $LOCATION/src/BulletCollision/CollisionShapes/*.cpp src/BulletCollision/CollisionShapes
|
||||||
|
cp $LOCATION/src/BulletCollision/NarrowPhaseCollision/*.h src/BulletCollision/NarrowPhaseCollision
|
||||||
|
cp $LOCATION/src/BulletCollision/NarrowPhaseCollision/*.cpp src/BulletCollision/NarrowPhaseCollision
|
||||||
|
cp $LOCATION/src/BulletDynamics/ConstraintSolver/*.h src/BulletDynamics/ConstraintSolver
|
||||||
|
cp $LOCATION/src/BulletDynamics/ConstraintSolver/*.cpp src/BulletDynamics/ConstraintSolver
|
||||||
|
cp $LOCATION/src/BulletDynamics/Dynamics/*.h src/BulletDynamics/Dynamics
|
||||||
|
cp $LOCATION/src/BulletDynamics/Dynamics/*.cpp src/BulletDynamics/Dynamics
|
||||||
|
cp $LOCATION/src/BulletDynamics/Vehicle/*.h src/BulletDynamics/Vehicle
|
||||||
|
cp $LOCATION/src/BulletDynamics/Vehicle/*.cpp src/BulletDynamics/Vehicle
|
||||||
|
cp $LOCATION/Demos/OpenGL/*.h Demos/OpenGL
|
||||||
|
cp $LOCATION/Demos/OpenGL/*.cpp Demos/OpenGL
|
||||||
|
|
@ -80,7 +80,7 @@ btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin,
|
|||||||
simpleProxy->m_multiSapParentProxy = proxy;
|
simpleProxy->m_multiSapParentProxy = proxy;
|
||||||
|
|
||||||
mem = btAlignedAlloc(sizeof(btChildProxy),16);
|
mem = btAlignedAlloc(sizeof(btChildProxy),16);
|
||||||
btChildProxy* childProxyRef = new btChildProxy();
|
btChildProxy* childProxyRef = new(mem) btChildProxy();
|
||||||
childProxyRef->m_proxy = simpleProxy;
|
childProxyRef->m_proxy = simpleProxy;
|
||||||
childProxyRef->m_childBroadphase = m_simpleBroadphase;
|
childProxyRef->m_childBroadphase = m_simpleBroadphase;
|
||||||
proxy->m_childProxies.push_back(childProxyRef);
|
proxy->m_childProxies.push_back(childProxyRef);
|
||||||
|
@ -177,7 +177,7 @@ private:
|
|||||||
|
|
||||||
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
|
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
|
||||||
{
|
{
|
||||||
int key = ((unsigned int)proxyId1) | (((unsigned int)proxyId1) <<16);
|
int key = ((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16);
|
||||||
// Thomas Wang's hash
|
// Thomas Wang's hash
|
||||||
|
|
||||||
key += ~(key << 15);
|
key += ~(key << 15);
|
||||||
|
@ -14,8 +14,8 @@ subject to the following restrictions:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "btSimpleBroadphase.h"
|
#include "btSimpleBroadphase.h"
|
||||||
#include <BulletCollision/BroadphaseCollision/btDispatcher.h>
|
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
|
||||||
#include <BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h>
|
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||||
|
|
||||||
#include "LinearMath/btVector3.h"
|
#include "LinearMath/btVector3.h"
|
||||||
#include "LinearMath/btTransform.h"
|
#include "LinearMath/btTransform.h"
|
||||||
|
@ -35,6 +35,7 @@ int gNumManifold = 0;
|
|||||||
btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
|
btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
|
||||||
m_count(0),
|
m_count(0),
|
||||||
m_useIslands(true),
|
m_useIslands(true),
|
||||||
|
m_staticWarningReported(false),
|
||||||
m_collisionConfiguration(collisionConfiguration)
|
m_collisionConfiguration(collisionConfiguration)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -117,7 +118,7 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
|
|||||||
manifold->~btPersistentManifold();
|
manifold->~btPersistentManifold();
|
||||||
if (m_persistentManifoldPoolAllocator->validPtr(manifold))
|
if (m_persistentManifoldPoolAllocator->validPtr(manifold))
|
||||||
{
|
{
|
||||||
m_persistentManifoldPoolAllocator->free(manifold);
|
m_persistentManifoldPoolAllocator->freeMemory(manifold);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
btAlignedFree(manifold);
|
btAlignedFree(manifold);
|
||||||
@ -161,13 +162,19 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO
|
|||||||
|
|
||||||
bool needsCollision = true;
|
bool needsCollision = true;
|
||||||
|
|
||||||
//broadphase filtering already deals with this
|
#ifdef BT_DEBUG
|
||||||
if ((body0->isStaticObject() || body0->isKinematicObject()) &&
|
if (!m_staticWarningReported)
|
||||||
(body1->isStaticObject() || body1->isKinematicObject()))
|
|
||||||
{
|
{
|
||||||
printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
|
//broadphase filtering already deals with this
|
||||||
|
if ((body0->isStaticObject() || body0->isKinematicObject()) &&
|
||||||
|
(body1->isStaticObject() || body1->isKinematicObject()))
|
||||||
|
{
|
||||||
|
m_staticWarningReported = true;
|
||||||
|
printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif //BT_DEBUG
|
||||||
|
|
||||||
if ((!body0->isActive()) && (!body1->isActive()))
|
if ((!body0->isActive()) && (!body1->isActive()))
|
||||||
needsCollision = false;
|
needsCollision = false;
|
||||||
else if (!body0->checkCollideWith(body1))
|
else if (!body0->checkCollideWith(body1))
|
||||||
@ -279,7 +286,7 @@ void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
|
|||||||
{
|
{
|
||||||
if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
|
if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
|
||||||
{
|
{
|
||||||
m_collisionAlgorithmPoolAllocator->free(ptr);
|
m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
btAlignedFree(ptr);
|
btAlignedFree(ptr);
|
||||||
|
@ -47,6 +47,8 @@ class btCollisionDispatcher : public btDispatcher
|
|||||||
btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
|
btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
|
||||||
|
|
||||||
bool m_useIslands;
|
bool m_useIslands;
|
||||||
|
|
||||||
|
bool m_staticWarningReported;
|
||||||
|
|
||||||
btManifoldResult m_defaultManifoldResult;
|
btManifoldResult m_defaultManifoldResult;
|
||||||
|
|
||||||
|
@ -19,11 +19,13 @@ subject to the following restrictions:
|
|||||||
btCollisionObject::btCollisionObject()
|
btCollisionObject::btCollisionObject()
|
||||||
: m_broadphaseHandle(0),
|
: m_broadphaseHandle(0),
|
||||||
m_collisionShape(0),
|
m_collisionShape(0),
|
||||||
m_collisionFlags(0),
|
m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
|
||||||
m_islandTag1(-1),
|
m_islandTag1(-1),
|
||||||
m_companionId(-1),
|
m_companionId(-1),
|
||||||
m_activationState1(1),
|
m_activationState1(1),
|
||||||
m_deactivationTime(btScalar(0.)),
|
m_deactivationTime(btScalar(0.)),
|
||||||
|
m_friction(btScalar(0.5)),
|
||||||
|
m_restitution(btScalar(0.)),
|
||||||
m_userObjectPointer(0),
|
m_userObjectPointer(0),
|
||||||
m_internalOwner(0),
|
m_internalOwner(0),
|
||||||
m_hitFraction(btScalar(1.)),
|
m_hitFraction(btScalar(1.)),
|
||||||
|
@ -20,7 +20,7 @@ subject to the following restrictions:
|
|||||||
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||||
|
|
||||||
#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
|
#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
|
||||||
#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" //for raycasting
|
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
|
||||||
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
|
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
|
||||||
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
|
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
|
||||||
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
|
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
|
||||||
@ -32,6 +32,7 @@ subject to the following restrictions:
|
|||||||
#include "LinearMath/btQuickprof.h"
|
#include "LinearMath/btQuickprof.h"
|
||||||
#include "LinearMath/btStackAlloc.h"
|
#include "LinearMath/btStackAlloc.h"
|
||||||
|
|
||||||
|
|
||||||
//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
|
//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
|
||||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||||
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
|
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
|
||||||
@ -40,7 +41,8 @@ subject to the following restrictions:
|
|||||||
|
|
||||||
btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
|
btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
|
||||||
:m_dispatcher1(dispatcher),
|
:m_dispatcher1(dispatcher),
|
||||||
m_broadphasePairCache(pairCache)
|
m_broadphasePairCache(pairCache),
|
||||||
|
m_debugDrawer(0)
|
||||||
{
|
{
|
||||||
m_stackAlloc = collisionConfiguration->getStackAllocator();
|
m_stackAlloc = collisionConfiguration->getStackAllocator();
|
||||||
m_dispatchInfo.m_stackAllocator = m_stackAlloc;
|
m_dispatchInfo.m_stackAllocator = m_stackAlloc;
|
||||||
@ -111,36 +113,68 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void btCollisionWorld::updateAabbs()
|
||||||
|
{
|
||||||
|
BT_PROFILE("updateAabbs");
|
||||||
|
|
||||||
|
btTransform predictedTrans;
|
||||||
|
for ( int i=0;i<m_collisionObjects.size();i++)
|
||||||
|
{
|
||||||
|
btCollisionObject* colObj = m_collisionObjects[i];
|
||||||
|
|
||||||
|
//only update aabb of active objects
|
||||||
|
if (colObj->isActive())
|
||||||
|
{
|
||||||
|
btPoint3 minAabb,maxAabb;
|
||||||
|
colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
|
||||||
|
btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
|
||||||
|
|
||||||
|
//moving objects should be moderately sized, probably something wrong if not
|
||||||
|
if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
|
||||||
|
{
|
||||||
|
bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//something went wrong, investigate
|
||||||
|
//this assert is unwanted in 3D modelers (danger of loosing work)
|
||||||
|
colObj->setActivationState(DISABLE_SIMULATION);
|
||||||
|
|
||||||
|
static bool reportMe = true;
|
||||||
|
if (reportMe && m_debugDrawer)
|
||||||
|
{
|
||||||
|
reportMe = false;
|
||||||
|
m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
|
||||||
|
m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
|
||||||
|
m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
|
||||||
|
m_debugDrawer->reportErrorWarning("Thanks.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void btCollisionWorld::performDiscreteCollisionDetection()
|
void btCollisionWorld::performDiscreteCollisionDetection()
|
||||||
{
|
{
|
||||||
|
BT_PROFILE("performDiscreteCollisionDetection");
|
||||||
|
|
||||||
btDispatcherInfo& dispatchInfo = getDispatchInfo();
|
btDispatcherInfo& dispatchInfo = getDispatchInfo();
|
||||||
|
|
||||||
BEGIN_PROFILE("perform Broadphase Collision Detection");
|
updateAabbs();
|
||||||
|
|
||||||
|
|
||||||
//update aabb (of all moved objects)
|
|
||||||
|
|
||||||
btVector3 aabbMin,aabbMax;
|
|
||||||
for (int i=0;i<m_collisionObjects.size();i++)
|
|
||||||
{
|
{
|
||||||
m_collisionObjects[i]->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax);
|
m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
|
||||||
m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax,m_dispatcher1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
|
|
||||||
|
|
||||||
END_PROFILE("perform Broadphase Collision Detection");
|
|
||||||
|
|
||||||
BEGIN_PROFILE("performDiscreteCollisionDetection");
|
|
||||||
|
|
||||||
btDispatcher* dispatcher = getDispatcher();
|
btDispatcher* dispatcher = getDispatcher();
|
||||||
if (dispatcher)
|
{
|
||||||
dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
|
BT_PROFILE("dispatchAllCollisionPairs");
|
||||||
|
if (dispatcher)
|
||||||
END_PROFILE("performDiscreteCollisionDetection");
|
dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,155 +214,367 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
|
|||||||
const btTransform& colObjWorldTransform,
|
const btTransform& colObjWorldTransform,
|
||||||
RayResultCallback& resultCallback,short int collisionFilterMask)
|
RayResultCallback& resultCallback,short int collisionFilterMask)
|
||||||
{
|
{
|
||||||
|
|
||||||
btSphereShape pointShape(btScalar(0.0));
|
btSphereShape pointShape(btScalar(0.0));
|
||||||
pointShape.setMargin(0.f);
|
pointShape.setMargin(0.f);
|
||||||
|
const btConvexShape* castShape = &pointShape;
|
||||||
objectQuerySingle(&pointShape,rayFromTrans,rayToTrans,
|
|
||||||
collisionObject,
|
|
||||||
collisionShape,
|
|
||||||
colObjWorldTransform,
|
|
||||||
resultCallback,collisionFilterMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans,
|
|
||||||
btCollisionObject* collisionObject,
|
|
||||||
const btCollisionShape* collisionShape,
|
|
||||||
const btTransform& colObjWorldTransform,
|
|
||||||
RayResultCallback& resultCallback,short int collisionFilterMask)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
if (collisionShape->isConvex())
|
if (collisionShape->isConvex())
|
||||||
{
|
{
|
||||||
btConvexCast::CastResult castResult;
|
btConvexCast::CastResult castResult;
|
||||||
castResult.m_fraction = btScalar(1.);//??
|
castResult.m_fraction = resultCallback.m_closestHitFraction;
|
||||||
|
|
||||||
btConvexShape* convexShape = (btConvexShape*) collisionShape;
|
btConvexShape* convexShape = (btConvexShape*) collisionShape;
|
||||||
btVoronoiSimplexSolver simplexSolver;
|
btVoronoiSimplexSolver simplexSolver;
|
||||||
#define USE_SUBSIMPLEX_CONVEX_CAST 1
|
#define USE_SUBSIMPLEX_CONVEX_CAST 1
|
||||||
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
|
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
|
||||||
btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
|
btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
|
||||||
#else
|
#else
|
||||||
//btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
|
//btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
|
||||||
//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
|
//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
|
||||||
#endif //#USE_SUBSIMPLEX_CONVEX_CAST
|
#endif //#USE_SUBSIMPLEX_CONVEX_CAST
|
||||||
|
|
||||||
if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
|
if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
|
||||||
|
{
|
||||||
|
//add hit
|
||||||
|
if (castResult.m_normal.length2() > btScalar(0.0001))
|
||||||
|
{
|
||||||
|
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
|
||||||
{
|
{
|
||||||
//add hit
|
|
||||||
if (castResult.m_normal.length2() > btScalar(0.0001))
|
|
||||||
{
|
|
||||||
|
|
||||||
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
|
|
||||||
{
|
|
||||||
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
|
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
|
||||||
//rotate normal into worldspace
|
//rotate normal into worldspace
|
||||||
castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
|
castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
|
||||||
#endif //USE_SUBSIMPLEX_CONVEX_CAST
|
#endif //USE_SUBSIMPLEX_CONVEX_CAST
|
||||||
|
|
||||||
castResult.m_normal.normalize();
|
castResult.m_normal.normalize();
|
||||||
btCollisionWorld::LocalRayResult localRayResult
|
btCollisionWorld::LocalRayResult localRayResult
|
||||||
|
(
|
||||||
|
collisionObject,
|
||||||
|
0,
|
||||||
|
castResult.m_normal,
|
||||||
|
castResult.m_fraction
|
||||||
|
);
|
||||||
|
|
||||||
|
bool normalInWorldSpace = true;
|
||||||
|
resultCallback.AddSingleResult(localRayResult, normalInWorldSpace);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (collisionShape->isConcave())
|
||||||
|
{
|
||||||
|
if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
|
||||||
|
{
|
||||||
|
///optimized version for btBvhTriangleMeshShape
|
||||||
|
btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
|
||||||
|
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
|
||||||
|
btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
|
||||||
|
btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
|
||||||
|
|
||||||
|
//ConvexCast::CastResult
|
||||||
|
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
|
||||||
|
{
|
||||||
|
btCollisionWorld::RayResultCallback* m_resultCallback;
|
||||||
|
btCollisionObject* m_collisionObject;
|
||||||
|
btTriangleMeshShape* m_triangleMesh;
|
||||||
|
|
||||||
|
BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
|
||||||
|
btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
|
||||||
|
btTriangleRaycastCallback(from,to),
|
||||||
|
m_resultCallback(resultCallback),
|
||||||
|
m_collisionObject(collisionObject),
|
||||||
|
m_triangleMesh(triangleMesh)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
|
||||||
|
{
|
||||||
|
btCollisionWorld::LocalShapeInfo shapeInfo;
|
||||||
|
shapeInfo.m_shapePart = partId;
|
||||||
|
shapeInfo.m_triangleIndex = triangleIndex;
|
||||||
|
|
||||||
|
btCollisionWorld::LocalRayResult rayResult
|
||||||
|
(m_collisionObject,
|
||||||
|
&shapeInfo,
|
||||||
|
hitNormalLocal,
|
||||||
|
hitFraction);
|
||||||
|
|
||||||
|
bool normalInWorldSpace = false;
|
||||||
|
return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh);
|
||||||
|
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
|
||||||
|
triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
|
||||||
|
|
||||||
|
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
|
||||||
|
|
||||||
|
btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
|
||||||
|
btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
|
||||||
|
|
||||||
|
//ConvexCast::CastResult
|
||||||
|
|
||||||
|
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
|
||||||
|
{
|
||||||
|
btCollisionWorld::RayResultCallback* m_resultCallback;
|
||||||
|
btCollisionObject* m_collisionObject;
|
||||||
|
btTriangleMeshShape* m_triangleMesh;
|
||||||
|
|
||||||
|
BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
|
||||||
|
btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
|
||||||
|
btTriangleRaycastCallback(from,to),
|
||||||
|
m_resultCallback(resultCallback),
|
||||||
|
m_collisionObject(collisionObject),
|
||||||
|
m_triangleMesh(triangleMesh)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
|
||||||
|
{
|
||||||
|
btCollisionWorld::LocalShapeInfo shapeInfo;
|
||||||
|
shapeInfo.m_shapePart = partId;
|
||||||
|
shapeInfo.m_triangleIndex = triangleIndex;
|
||||||
|
|
||||||
|
btCollisionWorld::LocalRayResult rayResult
|
||||||
|
(m_collisionObject,
|
||||||
|
&shapeInfo,
|
||||||
|
hitNormalLocal,
|
||||||
|
hitFraction);
|
||||||
|
|
||||||
|
bool normalInWorldSpace = false;
|
||||||
|
return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh);
|
||||||
|
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
|
||||||
|
|
||||||
|
btVector3 rayAabbMinLocal = rayFromLocal;
|
||||||
|
rayAabbMinLocal.setMin(rayToLocal);
|
||||||
|
btVector3 rayAabbMaxLocal = rayFromLocal;
|
||||||
|
rayAabbMaxLocal.setMax(rayToLocal);
|
||||||
|
|
||||||
|
triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//todo: use AABB tree or other BVH acceleration structure!
|
||||||
|
if (collisionShape->isCompound())
|
||||||
|
{
|
||||||
|
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
|
||||||
|
int i=0;
|
||||||
|
for (i=0;i<compoundShape->getNumChildShapes();i++)
|
||||||
|
{
|
||||||
|
btTransform childTrans = compoundShape->getChildTransform(i);
|
||||||
|
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
|
||||||
|
btTransform childWorldTrans = colObjWorldTransform * childTrans;
|
||||||
|
rayTestSingle(rayFromTrans,rayToTrans,
|
||||||
|
collisionObject,
|
||||||
|
childCollisionShape,
|
||||||
|
childWorldTrans,
|
||||||
|
resultCallback, collisionFilterMask);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
|
||||||
|
btCollisionObject* collisionObject,
|
||||||
|
const btCollisionShape* collisionShape,
|
||||||
|
const btTransform& colObjWorldTransform,
|
||||||
|
ConvexResultCallback& resultCallback,short int collisionFilterMask)
|
||||||
|
{
|
||||||
|
if (collisionShape->isConvex())
|
||||||
|
{
|
||||||
|
btConvexCast::CastResult castResult;
|
||||||
|
castResult.m_fraction = btScalar(1.);//??
|
||||||
|
|
||||||
|
btConvexShape* convexShape = (btConvexShape*) collisionShape;
|
||||||
|
btVoronoiSimplexSolver simplexSolver;
|
||||||
|
btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
|
||||||
|
|
||||||
|
if (convexCaster.calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
|
||||||
|
{
|
||||||
|
//add hit
|
||||||
|
if (castResult.m_normal.length2() > btScalar(0.0001))
|
||||||
|
{
|
||||||
|
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
|
||||||
|
{
|
||||||
|
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
|
||||||
|
//rotate normal into worldspace
|
||||||
|
castResult.m_normal = convexFromTrans.getBasis() * castResult.m_normal;
|
||||||
|
#endif //USE_SUBSIMPLEX_CONVEX_CAST
|
||||||
|
|
||||||
|
castResult.m_normal.normalize();
|
||||||
|
btCollisionWorld::LocalConvexResult localConvexResult
|
||||||
(
|
(
|
||||||
collisionObject,
|
collisionObject,
|
||||||
0,
|
0,
|
||||||
castResult.m_normal,
|
castResult.m_normal,
|
||||||
|
castResult.m_hitPoint,
|
||||||
castResult.m_fraction
|
castResult.m_fraction
|
||||||
);
|
);
|
||||||
|
|
||||||
bool normalInWorldSpace = true;
|
bool normalInWorldSpace = true;
|
||||||
resultCallback.AddSingleResult(localRayResult, normalInWorldSpace);
|
resultCallback.AddSingleResult(localConvexResult, normalInWorldSpace);
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
} else {
|
||||||
|
if (collisionShape->isConcave())
|
||||||
|
{
|
||||||
|
if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
|
||||||
{
|
{
|
||||||
|
btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
|
||||||
if (collisionShape->isConcave())
|
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
|
||||||
{
|
btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
|
||||||
|
btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
|
||||||
|
// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
|
||||||
|
btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
|
||||||
|
|
||||||
btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
|
//ConvexCast::CastResult
|
||||||
|
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
|
||||||
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
|
{
|
||||||
|
btCollisionWorld::ConvexResultCallback* m_resultCallback;
|
||||||
|
btCollisionObject* m_collisionObject;
|
||||||
|
btTriangleMeshShape* m_triangleMesh;
|
||||||
|
|
||||||
btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
|
BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
|
||||||
btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
|
btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
|
||||||
|
btTriangleConvexcastCallback(castShape, from,to, triangleToWorld),
|
||||||
//ConvexCast::CastResult
|
m_resultCallback(resultCallback),
|
||||||
|
m_collisionObject(collisionObject),
|
||||||
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
|
m_triangleMesh(triangleMesh)
|
||||||
{
|
{
|
||||||
btCollisionWorld::RayResultCallback* m_resultCallback;
|
|
||||||
btCollisionObject* m_collisionObject;
|
|
||||||
btTriangleMeshShape* m_triangleMesh;
|
|
||||||
|
|
||||||
BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
|
|
||||||
btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
|
|
||||||
btTriangleRaycastCallback(from,to),
|
|
||||||
m_resultCallback(resultCallback),
|
|
||||||
m_collisionObject(collisionObject),
|
|
||||||
m_triangleMesh(triangleMesh)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
|
|
||||||
{
|
|
||||||
btCollisionWorld::LocalShapeInfo shapeInfo;
|
|
||||||
shapeInfo.m_shapePart = partId;
|
|
||||||
shapeInfo.m_triangleIndex = triangleIndex;
|
|
||||||
|
|
||||||
btCollisionWorld::LocalRayResult rayResult
|
|
||||||
(m_collisionObject,
|
|
||||||
&shapeInfo,
|
|
||||||
hitNormalLocal,
|
|
||||||
hitFraction);
|
|
||||||
|
|
||||||
bool normalInWorldSpace = false;
|
|
||||||
return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh);
|
|
||||||
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
|
|
||||||
|
|
||||||
btVector3 rayAabbMinLocal = rayFromLocal;
|
|
||||||
rayAabbMinLocal.setMin(rayToLocal);
|
|
||||||
btVector3 rayAabbMaxLocal = rayFromLocal;
|
|
||||||
rayAabbMaxLocal.setMax(rayToLocal);
|
|
||||||
|
|
||||||
triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
|
|
||||||
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
//todo: use AABB tree or other BVH acceleration structure!
|
|
||||||
if (collisionShape->isCompound())
|
|
||||||
{
|
|
||||||
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
|
|
||||||
int i=0;
|
|
||||||
for (i=0;i<compoundShape->getNumChildShapes();i++)
|
|
||||||
{
|
|
||||||
btTransform childTrans = compoundShape->getChildTransform(i);
|
|
||||||
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
|
|
||||||
btTransform childWorldTrans = colObjWorldTransform * childTrans;
|
|
||||||
objectQuerySingle(castShape, rayFromTrans,rayToTrans,
|
|
||||||
collisionObject,
|
|
||||||
childCollisionShape,
|
|
||||||
childWorldTrans,
|
|
||||||
resultCallback, collisionFilterMask);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
|
||||||
|
{
|
||||||
|
btCollisionWorld::LocalShapeInfo shapeInfo;
|
||||||
|
shapeInfo.m_shapePart = partId;
|
||||||
|
shapeInfo.m_triangleIndex = triangleIndex;
|
||||||
|
if (hitFraction <= m_resultCallback->m_closestHitFraction)
|
||||||
|
{
|
||||||
|
|
||||||
|
btCollisionWorld::LocalConvexResult convexResult
|
||||||
|
(m_collisionObject,
|
||||||
|
&shapeInfo,
|
||||||
|
hitNormalLocal,
|
||||||
|
hitPointLocal,
|
||||||
|
hitFraction);
|
||||||
|
|
||||||
|
bool normalInWorldSpace = false;
|
||||||
|
|
||||||
|
|
||||||
|
return m_resultCallback->AddSingleResult(convexResult,normalInWorldSpace);
|
||||||
|
}
|
||||||
|
return hitFraction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
|
||||||
|
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
|
||||||
|
btVector3 boxMinLocal, boxMaxLocal;
|
||||||
|
castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
|
||||||
|
triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
|
||||||
|
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
|
||||||
|
btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
|
||||||
|
btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
|
||||||
|
// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
|
||||||
|
btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
|
||||||
|
|
||||||
|
//ConvexCast::CastResult
|
||||||
|
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
|
||||||
|
{
|
||||||
|
btCollisionWorld::ConvexResultCallback* m_resultCallback;
|
||||||
|
btCollisionObject* m_collisionObject;
|
||||||
|
btTriangleMeshShape* m_triangleMesh;
|
||||||
|
|
||||||
|
BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
|
||||||
|
btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
|
||||||
|
btTriangleConvexcastCallback(castShape, from,to, triangleToWorld),
|
||||||
|
m_resultCallback(resultCallback),
|
||||||
|
m_collisionObject(collisionObject),
|
||||||
|
m_triangleMesh(triangleMesh)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
|
||||||
|
{
|
||||||
|
btCollisionWorld::LocalShapeInfo shapeInfo;
|
||||||
|
shapeInfo.m_shapePart = partId;
|
||||||
|
shapeInfo.m_triangleIndex = triangleIndex;
|
||||||
|
if (hitFraction <= m_resultCallback->m_closestHitFraction)
|
||||||
|
{
|
||||||
|
|
||||||
|
btCollisionWorld::LocalConvexResult convexResult
|
||||||
|
(m_collisionObject,
|
||||||
|
&shapeInfo,
|
||||||
|
hitNormalLocal,
|
||||||
|
hitPointLocal,
|
||||||
|
hitFraction);
|
||||||
|
|
||||||
|
bool normalInWorldSpace = false;
|
||||||
|
|
||||||
|
return m_resultCallback->AddSingleResult(convexResult,normalInWorldSpace);
|
||||||
|
}
|
||||||
|
return hitFraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
|
||||||
|
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
|
||||||
|
btVector3 boxMinLocal, boxMaxLocal;
|
||||||
|
castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
|
||||||
|
|
||||||
|
btVector3 rayAabbMinLocal = convexFromLocal;
|
||||||
|
rayAabbMinLocal.setMin(convexToLocal);
|
||||||
|
btVector3 rayAabbMaxLocal = convexFromLocal;
|
||||||
|
rayAabbMaxLocal.setMax(convexToLocal);
|
||||||
|
rayAabbMinLocal += boxMinLocal;
|
||||||
|
rayAabbMaxLocal += boxMaxLocal;
|
||||||
|
triangleMesh->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
//todo: use AABB tree or other BVH acceleration structure!
|
||||||
|
if (collisionShape->isCompound())
|
||||||
|
{
|
||||||
|
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
|
||||||
|
int i=0;
|
||||||
|
for (i=0;i<compoundShape->getNumChildShapes();i++)
|
||||||
|
{
|
||||||
|
btTransform childTrans = compoundShape->getChildTransform(i);
|
||||||
|
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
|
||||||
|
btTransform childWorldTrans = colObjWorldTransform * childTrans;
|
||||||
|
objectQuerySingle(castShape, convexFromTrans,convexToTrans,
|
||||||
|
collisionObject,
|
||||||
|
childCollisionShape,
|
||||||
|
childWorldTrans,
|
||||||
|
resultCallback, collisionFilterMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask)
|
void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask)
|
||||||
@ -347,6 +593,10 @@ void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r
|
|||||||
int i;
|
int i;
|
||||||
for (i=0;i<m_collisionObjects.size();i++)
|
for (i=0;i<m_collisionObjects.size();i++)
|
||||||
{
|
{
|
||||||
|
///terminate further ray tests, once the closestHitFraction reached zero
|
||||||
|
if (resultCallback.m_closestHitFraction == btScalar(0.f))
|
||||||
|
break;
|
||||||
|
|
||||||
btCollisionObject* collisionObject= m_collisionObjects[i];
|
btCollisionObject* collisionObject= m_collisionObjects[i];
|
||||||
//only perform raycast if filterMask matches
|
//only perform raycast if filterMask matches
|
||||||
if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) {
|
if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) {
|
||||||
@ -354,7 +604,7 @@ void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r
|
|||||||
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
|
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
|
||||||
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
|
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
|
||||||
|
|
||||||
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
|
btScalar hitLambda = resultCallback.m_closestHitFraction;
|
||||||
btVector3 hitNormal;
|
btVector3 hitNormal;
|
||||||
if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
|
if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
|
||||||
{
|
{
|
||||||
@ -365,6 +615,46 @@ void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r
|
|||||||
resultCallback);
|
resultCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void btCollisionWorld::convexTest(const btConvexShape* castShape, const btVector3& convexFromWorld, const btVector3& convexToWorld, ConvexResultCallback& resultCallback,short int collisionFilterMask)
|
||||||
|
{
|
||||||
|
btTransform convexFromTrans,convexToTrans;
|
||||||
|
convexFromTrans.setIdentity();
|
||||||
|
convexFromTrans.setOrigin(convexFromWorld);
|
||||||
|
convexToTrans.setIdentity();
|
||||||
|
convexToTrans.setOrigin(convexToWorld);
|
||||||
|
btVector3 castShapeAabbMin, castShapeAabbMax;
|
||||||
|
btTransform I;
|
||||||
|
I.setIdentity();
|
||||||
|
castShape->getAabb (I, castShapeAabbMin, castShapeAabbMax);
|
||||||
|
|
||||||
|
/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
|
||||||
|
// do a ray-shape query using convexCaster (CCD)
|
||||||
|
int i;
|
||||||
|
for (i=0;i<m_collisionObjects.size();i++)
|
||||||
|
{
|
||||||
|
btCollisionObject* collisionObject= m_collisionObjects[i];
|
||||||
|
//only perform raycast if filterMask matches
|
||||||
|
if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) {
|
||||||
|
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
|
||||||
|
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
|
||||||
|
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
|
||||||
|
AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
|
||||||
|
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
|
||||||
|
btVector3 hitNormal;
|
||||||
|
if (btRayAabb(convexFromWorld,convexToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
|
||||||
|
{
|
||||||
|
objectQuerySingle(castShape, convexFromTrans,convexToTrans,
|
||||||
|
collisionObject,
|
||||||
|
collisionObject->getCollisionShape(),
|
||||||
|
collisionObject->getWorldTransform(),
|
||||||
|
resultCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,9 @@ protected:
|
|||||||
btStackAlloc* m_stackAlloc;
|
btStackAlloc* m_stackAlloc;
|
||||||
|
|
||||||
btBroadphaseInterface* m_broadphasePairCache;
|
btBroadphaseInterface* m_broadphasePairCache;
|
||||||
|
|
||||||
|
btIDebugDraw* m_debugDrawer;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -116,6 +119,19 @@ public:
|
|||||||
return m_dispatcher1;
|
return m_dispatcher1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void updateAabbs();
|
||||||
|
|
||||||
|
virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
|
||||||
|
{
|
||||||
|
m_debugDrawer = debugDrawer;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual btIDebugDraw* getDebugDrawer()
|
||||||
|
{
|
||||||
|
return m_debugDrawer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///LocalShapeInfo gives extra information for complex shapes
|
///LocalShapeInfo gives extra information for complex shapes
|
||||||
///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
|
///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
|
||||||
struct LocalShapeInfo
|
struct LocalShapeInfo
|
||||||
@ -150,17 +166,20 @@ public:
|
|||||||
///RayResultCallback is used to report new raycast results
|
///RayResultCallback is used to report new raycast results
|
||||||
struct RayResultCallback
|
struct RayResultCallback
|
||||||
{
|
{
|
||||||
|
btScalar m_closestHitFraction;
|
||||||
|
btCollisionObject* m_collisionObject;
|
||||||
|
|
||||||
virtual ~RayResultCallback()
|
virtual ~RayResultCallback()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
btScalar m_closestHitFraction;
|
|
||||||
bool HasHit()
|
bool HasHit()
|
||||||
{
|
{
|
||||||
return (m_closestHitFraction < btScalar(1.));
|
return (m_collisionObject != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
RayResultCallback()
|
RayResultCallback()
|
||||||
:m_closestHitFraction(btScalar(1.))
|
:m_closestHitFraction(btScalar(1.)),
|
||||||
|
m_collisionObject(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
|
virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
|
||||||
@ -170,8 +189,7 @@ public:
|
|||||||
{
|
{
|
||||||
ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
|
ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
|
||||||
:m_rayFromWorld(rayFromWorld),
|
:m_rayFromWorld(rayFromWorld),
|
||||||
m_rayToWorld(rayToWorld),
|
m_rayToWorld(rayToWorld)
|
||||||
m_collisionObject(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,13 +198,11 @@ public:
|
|||||||
|
|
||||||
btVector3 m_hitNormalWorld;
|
btVector3 m_hitNormalWorld;
|
||||||
btVector3 m_hitPointWorld;
|
btVector3 m_hitPointWorld;
|
||||||
btCollisionObject* m_collisionObject;
|
|
||||||
|
|
||||||
virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
|
virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
|
||||||
{
|
{
|
||||||
|
//caller already does the filter on the m_closestHitFraction
|
||||||
//caller already does the filter on the m_closestHitFraction
|
btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
|
||||||
assert(rayResult.m_hitFraction <= m_closestHitFraction);
|
|
||||||
|
|
||||||
m_closestHitFraction = rayResult.m_hitFraction;
|
m_closestHitFraction = rayResult.m_hitFraction;
|
||||||
m_collisionObject = rayResult.m_collisionObject;
|
m_collisionObject = rayResult.m_collisionObject;
|
||||||
@ -204,7 +220,83 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct LocalConvexResult
|
||||||
|
{
|
||||||
|
LocalConvexResult(btCollisionObject* hitCollisionObject,
|
||||||
|
LocalShapeInfo* localShapeInfo,
|
||||||
|
const btVector3& hitNormalLocal,
|
||||||
|
const btVector3& hitPointLocal,
|
||||||
|
btScalar hitFraction
|
||||||
|
)
|
||||||
|
:m_hitCollisionObject(hitCollisionObject),
|
||||||
|
m_localShapeInfo(localShapeInfo),
|
||||||
|
m_hitNormalLocal(hitNormalLocal),
|
||||||
|
m_hitPointLocal(hitPointLocal),
|
||||||
|
m_hitFraction(hitFraction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
btCollisionObject* m_hitCollisionObject;
|
||||||
|
LocalShapeInfo* m_localShapeInfo;
|
||||||
|
btVector3 m_hitNormalLocal;
|
||||||
|
btVector3 m_hitPointLocal;
|
||||||
|
btScalar m_hitFraction;
|
||||||
|
};
|
||||||
|
|
||||||
|
///RayResultCallback is used to report new raycast results
|
||||||
|
struct ConvexResultCallback
|
||||||
|
{
|
||||||
|
virtual ~ConvexResultCallback()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
btScalar m_closestHitFraction;
|
||||||
|
bool HasHit()
|
||||||
|
{
|
||||||
|
return (m_closestHitFraction < btScalar(1.));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvexResultCallback()
|
||||||
|
:m_closestHitFraction(btScalar(1.))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual btScalar AddSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClosestConvexResultCallback : public ConvexResultCallback
|
||||||
|
{
|
||||||
|
ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld)
|
||||||
|
:m_convexFromWorld(convexFromWorld),
|
||||||
|
m_convexToWorld(convexToWorld),
|
||||||
|
m_hitCollisionObject(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction
|
||||||
|
btVector3 m_convexToWorld;
|
||||||
|
|
||||||
|
btVector3 m_hitNormalWorld;
|
||||||
|
btVector3 m_hitPointWorld;
|
||||||
|
btCollisionObject* m_hitCollisionObject;
|
||||||
|
|
||||||
|
virtual btScalar AddSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
|
||||||
|
{
|
||||||
|
//caller already does the filter on the m_closestHitFraction
|
||||||
|
btAssert(convexResult.m_hitFraction <= m_closestHitFraction);
|
||||||
|
|
||||||
|
m_closestHitFraction = convexResult.m_hitFraction;
|
||||||
|
m_hitCollisionObject = convexResult.m_hitCollisionObject;
|
||||||
|
if (normalInWorldSpace)
|
||||||
|
{
|
||||||
|
m_hitNormalWorld = convexResult.m_hitNormalLocal;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
///need to transform normal into worldspace
|
||||||
|
m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
|
||||||
|
}
|
||||||
|
m_hitPointWorld = convexResult.m_hitPointLocal;
|
||||||
|
return convexResult.m_hitFraction;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
int getNumCollisionObjects() const
|
int getNumCollisionObjects() const
|
||||||
{
|
{
|
||||||
@ -215,6 +307,10 @@ public:
|
|||||||
/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
|
/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
|
||||||
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1);
|
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1);
|
||||||
|
|
||||||
|
// convexTest performs a linear convex cast on all objects in the btCollisionWorld, and calls the resultCallback
|
||||||
|
// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback.
|
||||||
|
void convexTest (const btConvexShape* castShape, const btVector3& from, const btVector3& to, ConvexResultCallback& resultCallback, short int collisionFilterMask=-1);
|
||||||
|
|
||||||
/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
|
/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
|
||||||
/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
|
/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
|
||||||
/// This allows more customization.
|
/// This allows more customization.
|
||||||
@ -229,7 +325,7 @@ public:
|
|||||||
btCollisionObject* collisionObject,
|
btCollisionObject* collisionObject,
|
||||||
const btCollisionShape* collisionShape,
|
const btCollisionShape* collisionShape,
|
||||||
const btTransform& colObjWorldTransform,
|
const btTransform& colObjWorldTransform,
|
||||||
RayResultCallback& resultCallback, short int collisionFilterMask=-1);
|
ConvexResultCallback& resultCallback, short int collisionFilterMask=-1);
|
||||||
|
|
||||||
void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1);
|
void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1);
|
||||||
|
|
||||||
|
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btConvexPlaneCollisionAlgorithm.h"
|
||||||
|
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
|
||||||
|
|
||||||
|
//#include <stdio.h>
|
||||||
|
|
||||||
|
btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
|
||||||
|
: btCollisionAlgorithm(ci),
|
||||||
|
m_ownManifold(false),
|
||||||
|
m_manifoldPtr(mf),
|
||||||
|
m_isSwapped(isSwapped)
|
||||||
|
{
|
||||||
|
btCollisionObject* convexObj = m_isSwapped? col1 : col0;
|
||||||
|
btCollisionObject* planeObj = m_isSwapped? col0 : col1;
|
||||||
|
|
||||||
|
if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj))
|
||||||
|
{
|
||||||
|
m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj);
|
||||||
|
m_ownManifold = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
|
||||||
|
{
|
||||||
|
if (m_ownManifold)
|
||||||
|
{
|
||||||
|
if (m_manifoldPtr)
|
||||||
|
m_dispatcher->releaseManifold(m_manifoldPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||||
|
{
|
||||||
|
(void)dispatchInfo;
|
||||||
|
(void)resultOut;
|
||||||
|
if (!m_manifoldPtr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
btCollisionObject* convexObj = m_isSwapped? body1 : body0;
|
||||||
|
btCollisionObject* planeObj = m_isSwapped? body0: body1;
|
||||||
|
|
||||||
|
btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
|
||||||
|
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
|
||||||
|
|
||||||
|
bool hasCollision = false;
|
||||||
|
const btVector3& planeNormal = planeShape->getPlaneNormal();
|
||||||
|
const btScalar& planeConstant = planeShape->getPlaneConstant();
|
||||||
|
btTransform planeInConvex;
|
||||||
|
planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform();
|
||||||
|
btTransform convexInPlaneTrans;
|
||||||
|
convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform();
|
||||||
|
|
||||||
|
btVector3 vtx = convexShape->localGetSupportingVertexWithoutMargin(planeInConvex.getBasis()*-planeNormal);
|
||||||
|
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
|
||||||
|
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant) - convexShape->getMargin();
|
||||||
|
|
||||||
|
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
|
||||||
|
btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
|
||||||
|
|
||||||
|
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
|
||||||
|
resultOut->setPersistentManifold(m_manifoldPtr);
|
||||||
|
if (hasCollision)
|
||||||
|
{
|
||||||
|
/// report a contact. internally this will be kept persistent, and contact reduction is done
|
||||||
|
btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal;
|
||||||
|
btVector3 pOnB = vtxInPlaneWorld;
|
||||||
|
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
|
||||||
|
}
|
||||||
|
if (m_ownManifold)
|
||||||
|
{
|
||||||
|
if (m_manifoldPtr->getNumContacts())
|
||||||
|
{
|
||||||
|
resultOut->refreshContactPoints();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||||
|
{
|
||||||
|
(void)resultOut;
|
||||||
|
(void)dispatchInfo;
|
||||||
|
(void)col0;
|
||||||
|
(void)col1;
|
||||||
|
|
||||||
|
//not yet
|
||||||
|
return btScalar(1.);
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONVEX_PLANE_COLLISION_ALGORITHM_H
|
||||||
|
#define CONVEX_PLANE_COLLISION_ALGORITHM_H
|
||||||
|
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
|
||||||
|
class btPersistentManifold;
|
||||||
|
#include "btCollisionDispatcher.h"
|
||||||
|
|
||||||
|
#include "LinearMath/btVector3.h"
|
||||||
|
|
||||||
|
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
|
||||||
|
/// Other features are frame-coherency (persistent data) and collision response.
|
||||||
|
class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
|
||||||
|
{
|
||||||
|
bool m_ownManifold;
|
||||||
|
btPersistentManifold* m_manifoldPtr;
|
||||||
|
bool m_isSwapped;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
|
||||||
|
|
||||||
|
virtual ~btConvexPlaneCollisionAlgorithm();
|
||||||
|
|
||||||
|
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||||
|
|
||||||
|
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||||
|
|
||||||
|
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||||
|
{
|
||||||
|
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||||
|
{
|
||||||
|
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
|
||||||
|
if (!m_swapped)
|
||||||
|
{
|
||||||
|
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //CONVEX_PLANE_COLLISION_ALGORITHM_H
|
||||||
|
|
@ -20,6 +20,8 @@ subject to the following restrictions:
|
|||||||
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
|
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
|
||||||
#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
|
#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
|
||||||
#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
|
#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h"
|
||||||
|
|
||||||
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
|
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
|
||||||
#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
|
#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
|
||||||
#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
|
#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
|
||||||
@ -58,7 +60,7 @@ btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* s
|
|||||||
m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
|
m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
|
||||||
mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
|
mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
|
||||||
m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
|
m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
|
||||||
|
|
||||||
mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
|
mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
|
||||||
m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
|
m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
|
||||||
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
|
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
|
||||||
@ -72,7 +74,13 @@ btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* s
|
|||||||
m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
|
m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
|
||||||
m_triangleSphereCF->m_swapped = true;
|
m_triangleSphereCF->m_swapped = true;
|
||||||
|
|
||||||
|
//convex versus plane
|
||||||
|
mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
|
||||||
|
mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
|
||||||
|
m_planeConvexCF->m_swapped = true;
|
||||||
|
|
||||||
///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
|
///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
|
||||||
int maxSize = sizeof(btConvexConvexAlgorithm);
|
int maxSize = sizeof(btConvexConvexAlgorithm);
|
||||||
int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
|
int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
|
||||||
@ -167,6 +175,11 @@ btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
|
|||||||
m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
|
m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
|
||||||
btAlignedFree( m_triangleSphereCF);
|
btAlignedFree( m_triangleSphereCF);
|
||||||
|
|
||||||
|
m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_convexPlaneCF);
|
||||||
|
m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_planeConvexCF);
|
||||||
|
|
||||||
m_simplexSolver->~btVoronoiSimplexSolver();
|
m_simplexSolver->~btVoronoiSimplexSolver();
|
||||||
btAlignedFree(m_simplexSolver);
|
btAlignedFree(m_simplexSolver);
|
||||||
m_pdSolver->~btGjkEpaPenetrationDepthSolver();
|
m_pdSolver->~btGjkEpaPenetrationDepthSolver();
|
||||||
@ -178,7 +191,8 @@ btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
|
|||||||
|
|
||||||
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
|
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
|
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
|
||||||
{
|
{
|
||||||
@ -205,6 +219,15 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
|
|||||||
return m_triangleSphereCF;
|
return m_triangleSphereCF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
|
||||||
|
{
|
||||||
|
return m_convexPlaneCF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
|
||||||
|
{
|
||||||
|
return m_planeConvexCF;
|
||||||
|
}
|
||||||
|
|
||||||
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
|
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,9 @@ class btDefaultCollisionConfiguration : public btCollisionConfiguration
|
|||||||
btCollisionAlgorithmCreateFunc* m_boxSphereCF;
|
btCollisionAlgorithmCreateFunc* m_boxSphereCF;
|
||||||
btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
|
btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
|
||||||
btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
|
btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_planeConvexCF;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
btDefaultCollisionConfiguration(btStackAlloc* stackAlloc=0,btPoolAllocator* persistentManifoldPool=0,btPoolAllocator* collisionAlgorithmPool=0);
|
btDefaultCollisionConfiguration(btStackAlloc* stackAlloc=0,btPoolAllocator* persistentManifoldPool=0,btPoolAllocator* collisionAlgorithmPool=0);
|
||||||
|
@ -138,7 +138,7 @@ class btPersistentManifoldSortPredicate
|
|||||||
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback)
|
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback)
|
||||||
{
|
{
|
||||||
|
|
||||||
BEGIN_PROFILE("islandUnionFindAndHeapSort");
|
BT_PROFILE("islandUnionFindAndHeapSort");
|
||||||
|
|
||||||
//we are going to sort the unionfind array, and store the element id in the size
|
//we are going to sort the unionfind array, and store the element id in the size
|
||||||
//afterwards, we clean unionfind, to make sure no-one uses it anymore
|
//afterwards, we clean unionfind, to make sure no-one uses it anymore
|
||||||
@ -295,8 +295,6 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
|
|||||||
|
|
||||||
//int islandId;
|
//int islandId;
|
||||||
|
|
||||||
END_PROFILE("islandUnionFindAndHeapSort");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// printf("Start Islands\n");
|
// printf("Start Islands\n");
|
||||||
|
@ -66,7 +66,12 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0
|
|||||||
///distance (negative means penetration)
|
///distance (negative means penetration)
|
||||||
btScalar dist = len - (radius0+radius1);
|
btScalar dist = len - (radius0+radius1);
|
||||||
|
|
||||||
btVector3 normalOnSurfaceB = diff / len;
|
btVector3 normalOnSurfaceB(1,0,0);
|
||||||
|
if (len > SIMD_EPSILON)
|
||||||
|
{
|
||||||
|
normalOnSurfaceB = diff / len;
|
||||||
|
}
|
||||||
|
|
||||||
///point on A (worldspace)
|
///point on A (worldspace)
|
||||||
btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
|
btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
|
||||||
///point on B (worldspace)
|
///point on B (worldspace)
|
||||||
|
@ -18,7 +18,6 @@ subject to the following restrictions:
|
|||||||
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
|
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
|
||||||
#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
|
#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
|
||||||
|
|
||||||
|
|
||||||
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
|
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
|
||||||
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
|
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
|
||||||
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
|
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
|
||||||
@ -92,6 +91,126 @@ btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void btBvhTriangleMeshShape::performRaycast (btTriangleRaycastCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
|
||||||
|
{
|
||||||
|
struct MyNodeOverlapCallback : public btNodeOverlapCallback
|
||||||
|
{
|
||||||
|
btStridingMeshInterface* m_meshInterface;
|
||||||
|
btTriangleRaycastCallback* m_callback;
|
||||||
|
|
||||||
|
MyNodeOverlapCallback(btTriangleRaycastCallback* callback,btStridingMeshInterface* meshInterface)
|
||||||
|
:m_meshInterface(meshInterface),
|
||||||
|
m_callback(callback)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
|
||||||
|
{
|
||||||
|
btVector3 m_triangle[3];
|
||||||
|
const unsigned char *vertexbase;
|
||||||
|
int numverts;
|
||||||
|
PHY_ScalarType type;
|
||||||
|
int stride;
|
||||||
|
const unsigned char *indexbase;
|
||||||
|
int indexstride;
|
||||||
|
int numfaces;
|
||||||
|
PHY_ScalarType indicestype;
|
||||||
|
|
||||||
|
m_meshInterface->getLockedReadOnlyVertexIndexBase(
|
||||||
|
&vertexbase,
|
||||||
|
numverts,
|
||||||
|
type,
|
||||||
|
stride,
|
||||||
|
&indexbase,
|
||||||
|
indexstride,
|
||||||
|
numfaces,
|
||||||
|
indicestype,
|
||||||
|
nodeSubPart);
|
||||||
|
|
||||||
|
int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
|
||||||
|
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
|
||||||
|
|
||||||
|
const btVector3& meshScaling = m_meshInterface->getScaling();
|
||||||
|
for (int j=2;j>=0;j--)
|
||||||
|
{
|
||||||
|
int graphicsindex = indicestype==PHY_SHORT?((short*)gfxbase)[j]:gfxbase[j];
|
||||||
|
|
||||||
|
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
|
||||||
|
|
||||||
|
m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform ray vs. triangle collision here */
|
||||||
|
m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
|
||||||
|
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
|
||||||
|
|
||||||
|
m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void btBvhTriangleMeshShape::performConvexcast (btTriangleConvexcastCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
|
||||||
|
{
|
||||||
|
struct MyNodeOverlapCallback : public btNodeOverlapCallback
|
||||||
|
{
|
||||||
|
btStridingMeshInterface* m_meshInterface;
|
||||||
|
btTriangleConvexcastCallback* m_callback;
|
||||||
|
|
||||||
|
MyNodeOverlapCallback(btTriangleConvexcastCallback* callback,btStridingMeshInterface* meshInterface)
|
||||||
|
:m_meshInterface(meshInterface),
|
||||||
|
m_callback(callback)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
|
||||||
|
{
|
||||||
|
btVector3 m_triangle[3];
|
||||||
|
const unsigned char *vertexbase;
|
||||||
|
int numverts;
|
||||||
|
PHY_ScalarType type;
|
||||||
|
int stride;
|
||||||
|
const unsigned char *indexbase;
|
||||||
|
int indexstride;
|
||||||
|
int numfaces;
|
||||||
|
PHY_ScalarType indicestype;
|
||||||
|
|
||||||
|
m_meshInterface->getLockedReadOnlyVertexIndexBase(
|
||||||
|
&vertexbase,
|
||||||
|
numverts,
|
||||||
|
type,
|
||||||
|
stride,
|
||||||
|
&indexbase,
|
||||||
|
indexstride,
|
||||||
|
numfaces,
|
||||||
|
indicestype,
|
||||||
|
nodeSubPart);
|
||||||
|
|
||||||
|
int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
|
||||||
|
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
|
||||||
|
|
||||||
|
const btVector3& meshScaling = m_meshInterface->getScaling();
|
||||||
|
for (int j=2;j>=0;j--)
|
||||||
|
{
|
||||||
|
int graphicsindex = indicestype==PHY_SHORT?((short*)gfxbase)[j]:gfxbase[j];
|
||||||
|
|
||||||
|
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
|
||||||
|
|
||||||
|
m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform ray vs. triangle collision here */
|
||||||
|
m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
|
||||||
|
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
|
||||||
|
|
||||||
|
m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
|
||||||
|
}
|
||||||
|
|
||||||
//perform bvh tree traversal and report overlapping triangles to 'callback'
|
//perform bvh tree traversal and report overlapping triangles to 'callback'
|
||||||
void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
|
void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
|
||||||
{
|
{
|
||||||
@ -141,12 +260,13 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co
|
|||||||
nodeSubPart);
|
nodeSubPart);
|
||||||
|
|
||||||
int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
|
int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
|
||||||
|
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
|
||||||
|
|
||||||
const btVector3& meshScaling = m_meshInterface->getScaling();
|
const btVector3& meshScaling = m_meshInterface->getScaling();
|
||||||
for (int j=2;j>=0;j--)
|
for (int j=2;j>=0;j--)
|
||||||
{
|
{
|
||||||
|
|
||||||
int graphicsindex = gfxbase[j];
|
int graphicsindex = indicestype==PHY_SHORT?((short*)gfxbase)[j]:gfxbase[j];
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG_TRIANGLE_MESH
|
#ifdef DEBUG_TRIANGLE_MESH
|
||||||
|
@ -19,6 +19,7 @@ subject to the following restrictions:
|
|||||||
#include "btTriangleMeshShape.h"
|
#include "btTriangleMeshShape.h"
|
||||||
#include "btOptimizedBvh.h"
|
#include "btOptimizedBvh.h"
|
||||||
#include "LinearMath/btAlignedAllocator.h"
|
#include "LinearMath/btAlignedAllocator.h"
|
||||||
|
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
|
||||||
|
|
||||||
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
|
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
|
||||||
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
|
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
|
||||||
@ -27,7 +28,7 @@ ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape
|
|||||||
|
|
||||||
btOptimizedBvh* m_bvh;
|
btOptimizedBvh* m_bvh;
|
||||||
bool m_useQuantizedAabbCompression;
|
bool m_useQuantizedAabbCompression;
|
||||||
bool m_ownsBvh;
|
bool m_ownsBvh;
|
||||||
bool m_pad[11];////need padding due to alignment
|
bool m_pad[11];////need padding due to alignment
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -42,15 +43,13 @@ public:
|
|||||||
|
|
||||||
virtual ~btBvhTriangleMeshShape();
|
virtual ~btBvhTriangleMeshShape();
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
virtual int getShapeType() const
|
virtual int getShapeType() const
|
||||||
{
|
{
|
||||||
return TRIANGLE_MESH_SHAPE_PROXYTYPE;
|
return TRIANGLE_MESH_SHAPE_PROXYTYPE;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
void performRaycast (btTriangleRaycastCallback* callback, const btVector3& raySource, const btVector3& rayTarget);
|
||||||
|
void performConvexcast (btTriangleConvexcastCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
|
||||||
|
|
||||||
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
|
||||||
|
@ -44,7 +44,12 @@ public:
|
|||||||
return &m_points[0];
|
return &m_points[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
int getNumPoints()
|
const btPoint3* getPoints() const
|
||||||
|
{
|
||||||
|
return &m_points[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
int getNumPoints() const
|
||||||
{
|
{
|
||||||
return m_points.size();
|
return m_points.size();
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,11 @@ subject to the following restrictions:
|
|||||||
#include "LinearMath/btTransformUtil.h"
|
#include "LinearMath/btTransformUtil.h"
|
||||||
|
|
||||||
|
|
||||||
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int width,int length,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
|
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
|
||||||
:m_width(width),
|
: m_heightStickWidth(heightStickWidth),
|
||||||
m_length(length),
|
m_heightStickLength(heightStickLength),
|
||||||
|
m_width((btScalar)heightStickWidth-1),
|
||||||
|
m_length((btScalar)heightStickLength-1),
|
||||||
m_maxHeight(maxHeight),
|
m_maxHeight(maxHeight),
|
||||||
m_heightfieldDataUnknown(heightfieldData),
|
m_heightfieldDataUnknown(heightfieldData),
|
||||||
m_useFloatData(useFloatData),
|
m_useFloatData(useFloatData),
|
||||||
@ -44,7 +46,7 @@ m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
|
|||||||
{
|
{
|
||||||
halfExtents.setValue(
|
halfExtents.setValue(
|
||||||
btScalar(m_maxHeight),
|
btScalar(m_maxHeight),
|
||||||
btScalar(m_width),
|
btScalar(m_width), //?? don't know if this should change
|
||||||
btScalar(m_length));
|
btScalar(m_length));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -114,11 +116,11 @@ btScalar btHeightfieldTerrainShape::getHeightFieldValue(int x,int y) const
|
|||||||
btScalar val = 0.f;
|
btScalar val = 0.f;
|
||||||
if (m_useFloatData)
|
if (m_useFloatData)
|
||||||
{
|
{
|
||||||
val = m_heightfieldDataFloat[(y*m_width)+x];
|
val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
//assume unsigned short int
|
//assume unsigned short int
|
||||||
unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_width)+x];
|
unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
|
||||||
val = heightFieldValue* (m_maxHeight/btScalar(65535));
|
val = heightFieldValue* (m_maxHeight/btScalar(65535));
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
@ -133,8 +135,8 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
|
|||||||
|
|
||||||
btAssert(x>=0);
|
btAssert(x>=0);
|
||||||
btAssert(y>=0);
|
btAssert(y>=0);
|
||||||
btAssert(x<m_width);
|
btAssert(x<m_heightStickWidth);
|
||||||
btAssert(y<m_length);
|
btAssert(y<m_heightStickLength);
|
||||||
|
|
||||||
|
|
||||||
btScalar height = getHeightFieldValue(x,y);
|
btScalar height = getHeightFieldValue(x,y);
|
||||||
@ -218,18 +220,18 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
|
|||||||
|
|
||||||
|
|
||||||
int startX=0;
|
int startX=0;
|
||||||
int endX=m_width-1;
|
int endX=m_heightStickWidth-1;
|
||||||
int startJ=0;
|
int startJ=0;
|
||||||
int endJ=m_length-1;
|
int endJ=m_heightStickLength-1;
|
||||||
|
|
||||||
switch (m_upAxis)
|
switch (m_upAxis)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
quantizedAabbMin[1]+=m_width/2-1;
|
quantizedAabbMin[1]+=m_heightStickWidth/2-1;
|
||||||
quantizedAabbMax[1]+=m_width/2+1;
|
quantizedAabbMax[1]+=m_heightStickWidth/2+1;
|
||||||
quantizedAabbMin[2]+=m_length/2-1;
|
quantizedAabbMin[2]+=m_heightStickLength/2-1;
|
||||||
quantizedAabbMax[2]+=m_length/2+1;
|
quantizedAabbMax[2]+=m_heightStickLength/2+1;
|
||||||
|
|
||||||
if (quantizedAabbMin[1]>startX)
|
if (quantizedAabbMin[1]>startX)
|
||||||
startX = quantizedAabbMin[1];
|
startX = quantizedAabbMin[1];
|
||||||
@ -243,10 +245,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
|
|||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
quantizedAabbMin[0]+=m_width/2-1;
|
quantizedAabbMin[0]+=m_heightStickWidth/2-1;
|
||||||
quantizedAabbMax[0]+=m_width/2+1;
|
quantizedAabbMax[0]+=m_heightStickWidth/2+1;
|
||||||
quantizedAabbMin[2]+=m_length/2-1;
|
quantizedAabbMin[2]+=m_heightStickLength/2-1;
|
||||||
quantizedAabbMax[2]+=m_length/2+1;
|
quantizedAabbMax[2]+=m_heightStickLength/2+1;
|
||||||
|
|
||||||
if (quantizedAabbMin[0]>startX)
|
if (quantizedAabbMin[0]>startX)
|
||||||
startX = quantizedAabbMin[0];
|
startX = quantizedAabbMin[0];
|
||||||
@ -260,10 +262,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
|
|||||||
};
|
};
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
quantizedAabbMin[0]+=m_width/2-1;
|
quantizedAabbMin[0]+=m_heightStickWidth/2-1;
|
||||||
quantizedAabbMax[0]+=m_width/2+1;
|
quantizedAabbMax[0]+=m_heightStickWidth/2+1;
|
||||||
quantizedAabbMin[1]+=m_length/2-1;
|
quantizedAabbMin[1]+=m_heightStickLength/2-1;
|
||||||
quantizedAabbMax[1]+=m_length/2+1;
|
quantizedAabbMax[1]+=m_heightStickLength/2+1;
|
||||||
|
|
||||||
if (quantizedAabbMin[0]>startX)
|
if (quantizedAabbMin[0]>startX)
|
||||||
startX = quantizedAabbMin[0];
|
startX = quantizedAabbMin[0];
|
||||||
@ -290,7 +292,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
|
|||||||
for(int x=startX; x<endX; x++)
|
for(int x=startX; x<endX; x++)
|
||||||
{
|
{
|
||||||
btVector3 vertices[3];
|
btVector3 vertices[3];
|
||||||
if (m_flipQuadEdges || (m_useDiamondSubdivision && ((j+x) & 1)))
|
if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
|
||||||
{
|
{
|
||||||
//first triangle
|
//first triangle
|
||||||
getVertex(x,j,vertices[0]);
|
getVertex(x,j,vertices[0]);
|
||||||
|
@ -1,88 +1,90 @@
|
|||||||
/*
|
/*
|
||||||
Bullet Continuous Collision Detection and Physics Library
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied warranty.
|
This software is provided 'as-is', without any express or implied warranty.
|
||||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it freely,
|
including commercial applications, and to alter it and redistribute it freely,
|
||||||
subject to the following restrictions:
|
subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HEIGHTFIELD_TERRAIN_SHAPE_H
|
#ifndef HEIGHTFIELD_TERRAIN_SHAPE_H
|
||||||
#define HEIGHTFIELD_TERRAIN_SHAPE_H
|
#define HEIGHTFIELD_TERRAIN_SHAPE_H
|
||||||
|
|
||||||
#include "btConcaveShape.h"
|
#include "btConcaveShape.h"
|
||||||
|
|
||||||
///btHeightfieldTerrainShape simulates a 2D heightfield terrain
|
///btHeightfieldTerrainShape simulates a 2D heightfield terrain
|
||||||
class btHeightfieldTerrainShape : public btConcaveShape
|
class btHeightfieldTerrainShape : public btConcaveShape
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
btVector3 m_localAabbMin;
|
btVector3 m_localAabbMin;
|
||||||
btVector3 m_localAabbMax;
|
btVector3 m_localAabbMax;
|
||||||
|
|
||||||
///terrain data
|
///terrain data
|
||||||
int m_width;
|
int m_heightStickWidth;
|
||||||
int m_length;
|
int m_heightStickLength;
|
||||||
btScalar m_maxHeight;
|
btScalar m_maxHeight;
|
||||||
union
|
btScalar m_width;
|
||||||
{
|
btScalar m_length;
|
||||||
unsigned char* m_heightfieldDataUnsignedChar;
|
union
|
||||||
btScalar* m_heightfieldDataFloat;
|
{
|
||||||
void* m_heightfieldDataUnknown;
|
unsigned char* m_heightfieldDataUnsignedChar;
|
||||||
};
|
btScalar* m_heightfieldDataFloat;
|
||||||
|
void* m_heightfieldDataUnknown;
|
||||||
bool m_useFloatData;
|
};
|
||||||
bool m_flipQuadEdges;
|
|
||||||
bool m_useDiamondSubdivision;
|
bool m_useFloatData;
|
||||||
|
bool m_flipQuadEdges;
|
||||||
int m_upAxis;
|
bool m_useDiamondSubdivision;
|
||||||
|
|
||||||
btVector3 m_localScaling;
|
int m_upAxis;
|
||||||
|
|
||||||
virtual btScalar getHeightFieldValue(int x,int y) const;
|
btVector3 m_localScaling;
|
||||||
void quantizeWithClamp(int* out, const btVector3& point) const;
|
|
||||||
void getVertex(int x,int y,btVector3& vertex) const;
|
virtual btScalar getHeightFieldValue(int x,int y) const;
|
||||||
|
void quantizeWithClamp(int* out, const btVector3& point) const;
|
||||||
inline bool testQuantizedAabbAgainstQuantizedAabb(int* aabbMin1, int* aabbMax1,const int* aabbMin2,const int* aabbMax2) const
|
void getVertex(int x,int y,btVector3& vertex) const;
|
||||||
{
|
|
||||||
bool overlap = true;
|
inline bool testQuantizedAabbAgainstQuantizedAabb(int* aabbMin1, int* aabbMax1,const int* aabbMin2,const int* aabbMax2) const
|
||||||
overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
|
{
|
||||||
overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
|
bool overlap = true;
|
||||||
overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
|
overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
|
||||||
return overlap;
|
overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
|
||||||
}
|
overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
|
||||||
|
return overlap;
|
||||||
public:
|
}
|
||||||
btHeightfieldTerrainShape(int width,int height,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
|
|
||||||
|
public:
|
||||||
virtual ~btHeightfieldTerrainShape();
|
btHeightfieldTerrainShape(int heightStickWidth,int heightStickHeight,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
|
||||||
|
|
||||||
|
virtual ~btHeightfieldTerrainShape();
|
||||||
void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;}
|
|
||||||
|
|
||||||
virtual int getShapeType() const
|
void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;}
|
||||||
{
|
|
||||||
return TERRAIN_SHAPE_PROXYTYPE;
|
virtual int getShapeType() const
|
||||||
}
|
{
|
||||||
|
return TERRAIN_SHAPE_PROXYTYPE;
|
||||||
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
}
|
||||||
|
|
||||||
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
||||||
|
|
||||||
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
|
||||||
virtual void setLocalScaling(const btVector3& scaling);
|
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
||||||
|
|
||||||
virtual const btVector3& getLocalScaling() const;
|
virtual void setLocalScaling(const btVector3& scaling);
|
||||||
|
|
||||||
//debugging
|
virtual const btVector3& getLocalScaling() const;
|
||||||
virtual const char* getName()const {return "HEIGHTFIELD";}
|
|
||||||
|
//debugging
|
||||||
};
|
virtual const char* getName()const {return "HEIGHTFIELD";}
|
||||||
|
|
||||||
#endif //HEIGHTFIELD_TERRAIN_SHAPE_H
|
};
|
||||||
|
|
||||||
|
#endif //HEIGHTFIELD_TERRAIN_SHAPE_H
|
||||||
|
@ -47,7 +47,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons
|
|||||||
|
|
||||||
btVector3 vec = vec0;
|
btVector3 vec = vec0;
|
||||||
btScalar lenSqr = vec.length2();
|
btScalar lenSqr = vec.length2();
|
||||||
if (lenSqr < btScalar(0.0001))
|
if (lenSqr < (SIMD_EPSILON*SIMD_EPSILON))
|
||||||
{
|
{
|
||||||
vec.setValue(1,0,0);
|
vec.setValue(1,0,0);
|
||||||
} else
|
} else
|
||||||
|
@ -12,6 +12,7 @@ subject to the following restrictions:
|
|||||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "btOptimizedBvh.h"
|
#include "btOptimizedBvh.h"
|
||||||
#include "btStridingMeshInterface.h"
|
#include "btStridingMeshInterface.h"
|
||||||
#include "LinearMath/btAabbUtil2.h"
|
#include "LinearMath/btAabbUtil2.h"
|
||||||
@ -95,7 +96,9 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
|
|||||||
|
|
||||||
virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
|
virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
|
||||||
{
|
{
|
||||||
btAssert(partId==0);
|
// The partId and triangle index must fit in the same (positive) integer
|
||||||
|
btAssert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
|
||||||
|
btAssert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
|
||||||
//negative indices are reserved for escapeIndex
|
//negative indices are reserved for escapeIndex
|
||||||
btAssert(triangleIndex>=0);
|
btAssert(triangleIndex>=0);
|
||||||
|
|
||||||
@ -132,7 +135,7 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
|
|||||||
m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMin[0],aabbMin);
|
m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMin[0],aabbMin);
|
||||||
m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMax[0],aabbMax);
|
m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMax[0],aabbMax);
|
||||||
|
|
||||||
node.m_escapeIndexOrTriangleIndex = triangleIndex;
|
node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
|
||||||
|
|
||||||
m_triangleNodes.push_back(node);
|
m_triangleNodes.push_back(node);
|
||||||
}
|
}
|
||||||
@ -256,7 +259,7 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
|
|||||||
|
|
||||||
btAssert(m_useQuantization);
|
btAssert(m_useQuantization);
|
||||||
|
|
||||||
int nodeSubPart=0;
|
int curNodeSubPart=-1;
|
||||||
|
|
||||||
//get access info to trianglemesh data
|
//get access info to trianglemesh data
|
||||||
const unsigned char *vertexbase;
|
const unsigned char *vertexbase;
|
||||||
@ -267,7 +270,6 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
|
|||||||
int indexstride;
|
int indexstride;
|
||||||
int numfaces;
|
int numfaces;
|
||||||
PHY_ScalarType indicestype;
|
PHY_ScalarType indicestype;
|
||||||
meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
|
|
||||||
|
|
||||||
btVector3 triangleVerts[3];
|
btVector3 triangleVerts[3];
|
||||||
btVector3 aabbMin,aabbMax;
|
btVector3 aabbMin,aabbMax;
|
||||||
@ -282,7 +284,15 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
|
|||||||
if (curNode.isLeafNode())
|
if (curNode.isLeafNode())
|
||||||
{
|
{
|
||||||
//recalc aabb from triangle data
|
//recalc aabb from triangle data
|
||||||
|
int nodeSubPart = curNode.getPartId();
|
||||||
int nodeTriangleIndex = curNode.getTriangleIndex();
|
int nodeTriangleIndex = curNode.getTriangleIndex();
|
||||||
|
if (nodeSubPart != curNodeSubPart)
|
||||||
|
{
|
||||||
|
if (curNodeSubPart >= 0)
|
||||||
|
meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
|
||||||
|
meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
|
||||||
|
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
|
||||||
|
}
|
||||||
//triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
|
//triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
|
||||||
|
|
||||||
int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
|
int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
|
||||||
@ -291,7 +301,7 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
|
|||||||
for (int j=2;j>=0;j--)
|
for (int j=2;j>=0;j--)
|
||||||
{
|
{
|
||||||
|
|
||||||
int graphicsindex = gfxbase[j];
|
int graphicsindex = indicestype==PHY_SHORT?((short*)gfxbase)[j]:gfxbase[j];
|
||||||
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
|
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
|
||||||
#ifdef DEBUG_PATCH_COLORS
|
#ifdef DEBUG_PATCH_COLORS
|
||||||
btVector3 mycolor = color[index&3];
|
btVector3 mycolor = color[index&3];
|
||||||
@ -347,7 +357,8 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
|
if (curNodeSubPart >= 0)
|
||||||
|
meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -713,7 +724,7 @@ void btOptimizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantize
|
|||||||
{
|
{
|
||||||
if (isLeafNode)
|
if (isLeafNode)
|
||||||
{
|
{
|
||||||
nodeCallback->processNode(0,currentNode->getTriangleIndex());
|
nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex());
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
//process left and right children
|
//process left and right children
|
||||||
@ -730,7 +741,124 @@ void btOptimizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantize
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void btOptimizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
|
||||||
|
{
|
||||||
|
btAssert(m_useQuantization);
|
||||||
|
|
||||||
|
int curIndex = startNodeIndex;
|
||||||
|
int walkIterations = 0;
|
||||||
|
int subTreeSize = endNodeIndex - startNodeIndex;
|
||||||
|
|
||||||
|
const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
|
||||||
|
int escapeIndex;
|
||||||
|
|
||||||
|
bool isLeafNode;
|
||||||
|
//PCK: unsigned instead of bool
|
||||||
|
unsigned boxBoxOverlap = 0;
|
||||||
|
unsigned rayBoxOverlap = 0;
|
||||||
|
|
||||||
|
btScalar lambda_max = 1.0;
|
||||||
|
#define RAYAABB2
|
||||||
|
#ifdef RAYAABB2
|
||||||
|
btVector3 rayFrom = raySource;
|
||||||
|
btVector3 rayDirection = (rayTarget-raySource);
|
||||||
|
rayDirection.normalize ();
|
||||||
|
lambda_max = rayDirection.dot(rayTarget-raySource);
|
||||||
|
rayDirection[0] = btScalar(1.0) / rayDirection[0];
|
||||||
|
rayDirection[1] = btScalar(1.0) / rayDirection[1];
|
||||||
|
rayDirection[2] = btScalar(1.0) / rayDirection[2];
|
||||||
|
unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Quick pruning by quantized box */
|
||||||
|
btVector3 rayAabbMin = raySource;
|
||||||
|
btVector3 rayAabbMax = raySource;
|
||||||
|
rayAabbMin.setMin(rayTarget);
|
||||||
|
rayAabbMax.setMax(rayTarget);
|
||||||
|
|
||||||
|
/* Add box cast extents to bounding box */
|
||||||
|
rayAabbMin += aabbMin;
|
||||||
|
rayAabbMax += aabbMax;
|
||||||
|
|
||||||
|
unsigned short int quantizedQueryAabbMin[3];
|
||||||
|
unsigned short int quantizedQueryAabbMax[3];
|
||||||
|
quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin);
|
||||||
|
quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax);
|
||||||
|
|
||||||
|
while (curIndex < endNodeIndex)
|
||||||
|
{
|
||||||
|
|
||||||
|
//#define VISUALLY_ANALYZE_BVH 1
|
||||||
|
#ifdef VISUALLY_ANALYZE_BVH
|
||||||
|
//some code snippet to debugDraw aabb, to visually analyze bvh structure
|
||||||
|
static int drawPatch = 0;
|
||||||
|
//need some global access to a debugDrawer
|
||||||
|
extern btIDebugDraw* debugDrawerPtr;
|
||||||
|
if (curIndex==drawPatch)
|
||||||
|
{
|
||||||
|
btVector3 aabbMin,aabbMax;
|
||||||
|
aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
|
||||||
|
aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
|
||||||
|
btVector3 color(1,0,0);
|
||||||
|
debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
|
||||||
|
}
|
||||||
|
#endif//VISUALLY_ANALYZE_BVH
|
||||||
|
|
||||||
|
//catch bugs in tree data
|
||||||
|
assert (walkIterations < subTreeSize);
|
||||||
|
|
||||||
|
walkIterations++;
|
||||||
|
//PCK: unsigned instead of bool
|
||||||
|
// only interested if this is closer than any previous hit
|
||||||
|
btScalar param = 1.0;
|
||||||
|
rayBoxOverlap = 0;
|
||||||
|
boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
|
||||||
|
isLeafNode = rootNode->isLeafNode();
|
||||||
|
if (boxBoxOverlap)
|
||||||
|
{
|
||||||
|
btVector3 bounds[2];
|
||||||
|
bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
|
||||||
|
bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
|
||||||
|
/* Add box cast extents */
|
||||||
|
bounds[0] += aabbMin;
|
||||||
|
bounds[1] += aabbMax;
|
||||||
|
btVector3 normal;
|
||||||
|
#if 0
|
||||||
|
bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
|
||||||
|
bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
|
||||||
|
if (ra2 != ra)
|
||||||
|
{
|
||||||
|
printf("functions don't match\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef RAYAABB2
|
||||||
|
rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
|
||||||
|
#else
|
||||||
|
rayBoxOverlap = btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLeafNode && rayBoxOverlap)
|
||||||
|
{
|
||||||
|
nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
//PCK: unsigned instead of bool
|
||||||
|
if ((rayBoxOverlap != 0) || isLeafNode)
|
||||||
|
{
|
||||||
|
rootNode++;
|
||||||
|
curIndex++;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
escapeIndex = rootNode->getEscapeIndex();
|
||||||
|
rootNode += escapeIndex;
|
||||||
|
curIndex += escapeIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxIterations < walkIterations)
|
||||||
|
maxIterations = walkIterations;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
|
void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
|
||||||
{
|
{
|
||||||
@ -776,7 +904,7 @@ void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallb
|
|||||||
|
|
||||||
if (isLeafNode && aabbOverlap)
|
if (isLeafNode && aabbOverlap)
|
||||||
{
|
{
|
||||||
nodeCallback->processNode(0,rootNode->getTriangleIndex());
|
nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
//PCK: unsigned instead of bool
|
//PCK: unsigned instead of bool
|
||||||
@ -820,15 +948,40 @@ void btOptimizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallba
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btOptimizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
|
||||||
|
|
||||||
void btOptimizedBvh::reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
|
|
||||||
{
|
{
|
||||||
(void)nodeCallback;
|
bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS;
|
||||||
(void)aabbMin;
|
if (fast_path)
|
||||||
(void)aabbMax;
|
{
|
||||||
//not yet, please use aabb
|
walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0), 0, m_curNodeIndex);
|
||||||
btAssert(0);
|
} else {
|
||||||
|
/* Otherwise fallback to AABB overlap test */
|
||||||
|
btVector3 aabbMin = raySource;
|
||||||
|
btVector3 aabbMax = raySource;
|
||||||
|
aabbMin.setMin(rayTarget);
|
||||||
|
aabbMax.setMax(rayTarget);
|
||||||
|
reportAabbOverlappingNodex(nodeCallback,aabbMin,aabbMax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btOptimizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const
|
||||||
|
{
|
||||||
|
bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS;
|
||||||
|
if (fast_path)
|
||||||
|
{
|
||||||
|
walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
|
||||||
|
} else {
|
||||||
|
/* Slow path:
|
||||||
|
Construct the bounding box for the entire box cast and send that down the tree */
|
||||||
|
btVector3 qaabbMin = raySource;
|
||||||
|
btVector3 qaabbMax = raySource;
|
||||||
|
qaabbMin.setMin(rayTarget);
|
||||||
|
qaabbMax.setMax(rayTarget);
|
||||||
|
qaabbMin += aabbMin;
|
||||||
|
qaabbMax += aabbMax;
|
||||||
|
reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1064,7 +1217,7 @@ bool btOptimizedBvh::serialize(void *o_alignedDataBuffer, unsigned i_dataBufferS
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
btOptimizedBvh *btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian)
|
btOptimizedBvh *btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
|
if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
|
||||||
@ -1085,7 +1238,7 @@ btOptimizedBvh *btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, un
|
|||||||
bvh->m_subtreeHeaderCount = btSwapEndian(bvh->m_subtreeHeaderCount);
|
bvh->m_subtreeHeaderCount = btSwapEndian(bvh->m_subtreeHeaderCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
int calculatedBufSize = bvh->calculateSerializeBufferSize();
|
unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
|
||||||
btAssert(calculatedBufSize <= i_dataBufferSize);
|
btAssert(calculatedBufSize <= i_dataBufferSize);
|
||||||
|
|
||||||
if (calculatedBufSize > i_dataBufferSize)
|
if (calculatedBufSize > i_dataBufferSize)
|
||||||
@ -1176,6 +1329,8 @@ m_bvhAabbMin(self.m_bvhAabbMin),
|
|||||||
m_bvhAabbMax(self.m_bvhAabbMax),
|
m_bvhAabbMax(self.m_bvhAabbMax),
|
||||||
m_bvhQuantization(self.m_bvhQuantization)
|
m_bvhQuantization(self.m_bvhQuantization)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,9 @@ class btStridingMeshInterface;
|
|||||||
//Note: currently we have 16 bytes per quantized node
|
//Note: currently we have 16 bytes per quantized node
|
||||||
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
|
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
|
||||||
|
|
||||||
|
// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
|
||||||
|
// actually) triangles each (since the sign bit is reserved
|
||||||
|
#define MAX_NUM_PARTS_IN_BITS 10
|
||||||
|
|
||||||
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
|
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
|
||||||
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
|
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
|
||||||
@ -57,7 +60,14 @@ ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
|
|||||||
int getTriangleIndex() const
|
int getTriangleIndex() const
|
||||||
{
|
{
|
||||||
btAssert(isLeafNode());
|
btAssert(isLeafNode());
|
||||||
return m_escapeIndexOrTriangleIndex;
|
// Get only the lower bits where the triangle index is stored
|
||||||
|
return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
|
||||||
|
}
|
||||||
|
int getPartId() const
|
||||||
|
{
|
||||||
|
btAssert(isLeafNode());
|
||||||
|
// Get only the highest bits where the part index is stored
|
||||||
|
return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -276,6 +286,7 @@ protected:
|
|||||||
|
|
||||||
void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
|
||||||
|
void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
|
||||||
void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
|
void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
|
||||||
|
|
||||||
///tree traversal designed for small-memory processors like PS3 SPU
|
///tree traversal designed for small-memory processors like PS3 SPU
|
||||||
@ -319,8 +330,8 @@ public:
|
|||||||
void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
|
void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
|
||||||
|
|
||||||
void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
|
||||||
void reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
|
||||||
SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point) const
|
SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point) const
|
||||||
{
|
{
|
||||||
@ -370,7 +381,7 @@ public:
|
|||||||
bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian);
|
bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian);
|
||||||
|
|
||||||
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
|
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
|
||||||
static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian);
|
static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
|
||||||
|
|
||||||
static unsigned int getAlignmentSerializationPadding();
|
static unsigned int getAlignmentSerializationPadding();
|
||||||
|
|
||||||
@ -391,3 +402,4 @@ private:
|
|||||||
|
|
||||||
#endif //OPTIMIZED_BVH_H
|
#endif //OPTIMIZED_BVH_H
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ subject to the following restrictions:
|
|||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <BulletCollision/CollisionShapes/btPolyhedralConvexShape.h>
|
#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
|
||||||
|
|
||||||
btPolyhedralConvexShape::btPolyhedralConvexShape()
|
btPolyhedralConvexShape::btPolyhedralConvexShape()
|
||||||
:m_localAabbMin(1,1,1),
|
:m_localAabbMin(1,1,1),
|
||||||
|
@ -51,6 +51,15 @@ public:
|
|||||||
virtual void setLocalScaling(const btVector3& scaling);
|
virtual void setLocalScaling(const btVector3& scaling);
|
||||||
virtual const btVector3& getLocalScaling() const;
|
virtual const btVector3& getLocalScaling() const;
|
||||||
|
|
||||||
|
const btVector3& getPlaneNormal() const
|
||||||
|
{
|
||||||
|
return m_planeNormal;
|
||||||
|
}
|
||||||
|
|
||||||
|
const btScalar& getPlaneConstant() const
|
||||||
|
{
|
||||||
|
return m_planeConstant;
|
||||||
|
}
|
||||||
|
|
||||||
//debugging
|
//debugging
|
||||||
virtual const char* getName()const {return "STATICPLANE";}
|
virtual const char* getName()const {return "STATICPLANE";}
|
||||||
|
@ -54,7 +54,7 @@ void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertex
|
|||||||
|
|
||||||
(*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
|
(*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
|
||||||
indexstride = mesh.m_triangleIndexStride;
|
indexstride = mesh.m_triangleIndexStride;
|
||||||
indicestype = PHY_INTEGER;
|
indicestype = mesh.m_indexType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
|
void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
|
||||||
@ -73,6 +73,6 @@ void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned
|
|||||||
numfaces = mesh.m_numTriangles;
|
numfaces = mesh.m_numTriangles;
|
||||||
(*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
|
(*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
|
||||||
indexstride = mesh.m_triangleIndexStride;
|
indexstride = mesh.m_triangleIndexStride;
|
||||||
indicestype = PHY_INTEGER;
|
indicestype = mesh.m_indexType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,10 @@ ATTRIBUTE_ALIGNED16( struct) btIndexedMesh
|
|||||||
int m_numVertices;
|
int m_numVertices;
|
||||||
const unsigned char * m_vertexBase;
|
const unsigned char * m_vertexBase;
|
||||||
int m_vertexStride;
|
int m_vertexStride;
|
||||||
int pad[2];
|
// The index type is set when adding an indexed mesh to the
|
||||||
|
// btTriangleIndexVertexArray, do not set it manually
|
||||||
|
PHY_ScalarType m_indexType;
|
||||||
|
int pad;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -62,11 +65,12 @@ public:
|
|||||||
virtual ~btTriangleIndexVertexArray();
|
virtual ~btTriangleIndexVertexArray();
|
||||||
|
|
||||||
//just to be backwards compatible
|
//just to be backwards compatible
|
||||||
btTriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride);
|
btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride);
|
||||||
|
|
||||||
void addIndexedMesh(const btIndexedMesh& mesh)
|
void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
|
||||||
{
|
{
|
||||||
m_indexedMeshes.push_back(mesh);
|
m_indexedMeshes.push_back(mesh);
|
||||||
|
m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,11 +46,6 @@ public:
|
|||||||
|
|
||||||
void recalcLocalAabb();
|
void recalcLocalAabb();
|
||||||
|
|
||||||
virtual int getShapeType() const
|
|
||||||
{
|
|
||||||
return TRIANGLE_MESH_SHAPE_PROXYTYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
||||||
|
|
||||||
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
@ -174,6 +174,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
|||||||
result.m_fraction = lastLambda;
|
result.m_fraction = lastLambda;
|
||||||
n = pointCollector.m_normalOnBInWorld;
|
n = pointCollector.m_normalOnBInWorld;
|
||||||
result.m_normal=n;//.setValue(1,1,1);// = n;
|
result.m_normal=n;//.setValue(1,1,1);// = n;
|
||||||
|
result.m_hitPoint = pointCollector.m_pointInWorld;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
c = pointCollector.m_pointInWorld;
|
c = pointCollector.m_pointInWorld;
|
||||||
@ -189,6 +190,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
|||||||
|
|
||||||
result.m_fraction = lambda;
|
result.m_fraction = lambda;
|
||||||
result.m_normal = n;
|
result.m_normal = n;
|
||||||
|
result.m_hitPoint = c;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ public:
|
|||||||
virtual ~CastResult() {};
|
virtual ~CastResult() {};
|
||||||
|
|
||||||
btVector3 m_normal;
|
btVector3 m_normal;
|
||||||
|
btVector3 m_hitPoint;
|
||||||
btScalar m_fraction;
|
btScalar m_fraction;
|
||||||
btTransform m_hitTransformA;
|
btTransform m_hitTransformA;
|
||||||
btTransform m_hitTransformB;
|
btTransform m_hitTransformB;
|
||||||
|
@ -148,6 +148,7 @@ bool btGjkConvexCast::calcTimeOfImpact(
|
|||||||
//degeneracy, report a hit
|
//degeneracy, report a hit
|
||||||
result.m_fraction = lastLambda;
|
result.m_fraction = lastLambda;
|
||||||
result.m_normal = n;
|
result.m_normal = n;
|
||||||
|
result.m_hitPoint = pointCollector.m_pointInWorld;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
c = pointCollector.m_pointInWorld;
|
c = pointCollector.m_pointInWorld;
|
||||||
@ -165,6 +166,7 @@ bool btGjkConvexCast::calcTimeOfImpact(
|
|||||||
|
|
||||||
result.m_fraction = lastLambda;
|
result.m_fraction = lastLambda;
|
||||||
result.m_normal = n;
|
result.m_normal = n;
|
||||||
|
result.m_hitPoint = c;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ Nov.2006
|
|||||||
|
|
||||||
#include "btGjkEpa.h"
|
#include "btGjkEpa.h"
|
||||||
#include <string.h> //for memset
|
#include <string.h> //for memset
|
||||||
#include <LinearMath/btStackAlloc.h>
|
#include "LinearMath/btStackAlloc.h"
|
||||||
|
|
||||||
#if defined(DEBUG) || defined (_DEBUG)
|
#if defined(DEBUG) || defined (_DEBUG)
|
||||||
#include <stdio.h> //for debug printf
|
#include <stdio.h> //for debug printf
|
||||||
|
@ -70,6 +70,7 @@ public:
|
|||||||
btPersistentManifold(void* body0,void* body1,int bla)
|
btPersistentManifold(void* body0,void* body1,int bla)
|
||||||
: m_body0(body0),m_body1(body1),m_cachedPoints(0)
|
: m_body0(body0),m_body1(body1),m_cachedPoints(0)
|
||||||
{
|
{
|
||||||
|
(void)bla;
|
||||||
}
|
}
|
||||||
|
|
||||||
SIMD_FORCE_INLINE void* getBody0() { return m_body0;}
|
SIMD_FORCE_INLINE void* getBody0() { return m_body0;}
|
||||||
|
@ -13,7 +13,14 @@ subject to the following restrictions:
|
|||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
|
||||||
|
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
|
||||||
|
#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
|
||||||
|
#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
|
||||||
#include "btRaycastCallback.h"
|
#include "btRaycastCallback.h"
|
||||||
|
|
||||||
btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to)
|
btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to)
|
||||||
@ -29,8 +36,6 @@ btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const
|
|||||||
|
|
||||||
void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
|
void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
const btVector3 &vert0=triangle[0];
|
const btVector3 &vert0=triangle[0];
|
||||||
const btVector3 &vert1=triangle[1];
|
const btVector3 &vert1=triangle[1];
|
||||||
const btVector3 &vert2=triangle[2];
|
const btVector3 &vert2=triangle[2];
|
||||||
@ -99,3 +104,55 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld)
|
||||||
|
{
|
||||||
|
m_convexShape = convexShape;
|
||||||
|
m_convexShapeFrom = convexShapeFrom;
|
||||||
|
m_convexShapeTo = convexShapeTo;
|
||||||
|
m_triangleToWorld = triangleToWorld;
|
||||||
|
m_hitFraction = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex)
|
||||||
|
{
|
||||||
|
btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]);
|
||||||
|
|
||||||
|
btVoronoiSimplexSolver simplexSolver;
|
||||||
|
|
||||||
|
|
||||||
|
//#define USE_SUBSIMPLEX_CONVEX_CAST 1
|
||||||
|
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
|
||||||
|
btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver);
|
||||||
|
#else
|
||||||
|
//btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver);
|
||||||
|
btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,NULL);
|
||||||
|
#endif //#USE_SUBSIMPLEX_CONVEX_CAST
|
||||||
|
|
||||||
|
btConvexCast::CastResult castResult;
|
||||||
|
castResult.m_fraction = btScalar(1.);
|
||||||
|
if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult))
|
||||||
|
{
|
||||||
|
//add hit
|
||||||
|
if (castResult.m_normal.length2() > btScalar(0.0001))
|
||||||
|
{
|
||||||
|
if (castResult.m_fraction < m_hitFraction)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
|
||||||
|
//rotate normal into worldspace
|
||||||
|
castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal;
|
||||||
|
#endif //USE_SUBSIMPLEX_CONVEX_CAST
|
||||||
|
castResult.m_normal.normalize();
|
||||||
|
|
||||||
|
reportHit (castResult.m_normal,
|
||||||
|
castResult.m_hitPoint,
|
||||||
|
castResult.m_fraction,
|
||||||
|
partId,
|
||||||
|
triangleIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,14 +17,15 @@ subject to the following restrictions:
|
|||||||
#define RAYCAST_TRI_CALLBACK_H
|
#define RAYCAST_TRI_CALLBACK_H
|
||||||
|
|
||||||
#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
|
#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
|
||||||
|
#include "LinearMath/btTransform.h"
|
||||||
struct btBroadphaseProxy;
|
struct btBroadphaseProxy;
|
||||||
|
class btConvexShape;
|
||||||
|
|
||||||
class btTriangleRaycastCallback: public btTriangleCallback
|
class btTriangleRaycastCallback: public btTriangleCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//input
|
//input
|
||||||
btVector3 m_from;
|
btVector3 m_from;
|
||||||
btVector3 m_to;
|
btVector3 m_to;
|
||||||
|
|
||||||
@ -38,5 +39,21 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class btTriangleConvexcastCallback : public btTriangleCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const btConvexShape* m_convexShape;
|
||||||
|
btTransform m_convexShapeFrom;
|
||||||
|
btTransform m_convexShapeTo;
|
||||||
|
btTransform m_triangleToWorld;
|
||||||
|
btScalar m_hitFraction;
|
||||||
|
|
||||||
|
btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld);
|
||||||
|
|
||||||
|
virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex);
|
||||||
|
|
||||||
|
virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
#endif //RAYCAST_TRI_CALLBACK_H
|
#endif //RAYCAST_TRI_CALLBACK_H
|
||||||
|
|
||||||
|
@ -109,6 +109,17 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btScalar getLowerLimit() const
|
||||||
|
{
|
||||||
|
return m_lowerLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
btScalar getUpperLimit() const
|
||||||
|
{
|
||||||
|
return m_upperLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
btScalar getHingeAngle();
|
btScalar getHingeAngle();
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,11 +33,9 @@ subject to the following restrictions:
|
|||||||
#include "btSolverBody.h"
|
#include "btSolverBody.h"
|
||||||
#include "btSolverConstraint.h"
|
#include "btSolverConstraint.h"
|
||||||
|
|
||||||
|
|
||||||
#include "LinearMath/btAlignedObjectArray.h"
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
#ifdef USE_PROFILE
|
|
||||||
#include "LinearMath/btQuickprof.h"
|
|
||||||
#endif //USE_PROFILE
|
|
||||||
|
|
||||||
int totalCpd = 0;
|
int totalCpd = 0;
|
||||||
|
|
||||||
@ -129,23 +127,28 @@ btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initSolverBody(btSolverBody* solverBody, btRigidBody* rigidbody)
|
void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject)
|
||||||
{
|
{
|
||||||
/* int size = sizeof(btSolverBody);
|
btRigidBody* rb = btRigidBody::upcast(collisionObject);
|
||||||
int sizeofrb = sizeof(btRigidBody);
|
if (rb)
|
||||||
int sizemanifold = sizeof(btPersistentManifold);
|
{
|
||||||
int sizeofmp = sizeof(btManifoldPoint);
|
solverBody->m_angularVelocity = rb->getAngularVelocity() ;
|
||||||
int sizeofPersistData = sizeof (btConstraintPersistentData);
|
solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin();
|
||||||
*/
|
solverBody->m_friction = collisionObject->getFriction();
|
||||||
|
solverBody->m_invMass = rb->getInvMass();
|
||||||
solverBody->m_angularVelocity = rigidbody->getAngularVelocity();
|
solverBody->m_linearVelocity = rb->getLinearVelocity();
|
||||||
solverBody->m_centerOfMassPosition = rigidbody->getCenterOfMassPosition();
|
solverBody->m_originalBody = rb;
|
||||||
solverBody->m_friction = rigidbody->getFriction();
|
solverBody->m_angularFactor = rb->getAngularFactor();
|
||||||
// solverBody->m_invInertiaWorld = rigidbody->getInvInertiaTensorWorld();
|
} else
|
||||||
solverBody->m_invMass = rigidbody->getInvMass();
|
{
|
||||||
solverBody->m_linearVelocity = rigidbody->getLinearVelocity();
|
solverBody->m_angularVelocity.setValue(0,0,0);
|
||||||
solverBody->m_originalBody = rigidbody;
|
solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin();
|
||||||
solverBody->m_angularFactor = rigidbody->getAngularFactor();
|
solverBody->m_friction = collisionObject->getFriction();
|
||||||
|
solverBody->m_invMass = 0.f;
|
||||||
|
solverBody->m_linearVelocity.setValue(0,0,0);
|
||||||
|
solverBody->m_originalBody = 0;
|
||||||
|
solverBody->m_angularFactor = 1.f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btScalar penetrationResolveFactor = btScalar(0.9);
|
btScalar penetrationResolveFactor = btScalar(0.9);
|
||||||
@ -368,9 +371,12 @@ btScalar resolveSingleFrictionCacheFriendly(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btRigidBody* rb0,btRigidBody* rb1, btScalar relaxation)
|
void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
btRigidBody* body0=btRigidBody::upcast(colObj0);
|
||||||
|
btRigidBody* body1=btRigidBody::upcast(colObj1);
|
||||||
|
|
||||||
btSolverConstraint& solverConstraint = m_tmpSolverFrictionConstraintPool.expand();
|
btSolverConstraint& solverConstraint = m_tmpSolverFrictionConstraintPool.expand();
|
||||||
solverConstraint.m_contactNormal = normalAxis;
|
solverConstraint.m_contactNormal = normalAxis;
|
||||||
|
|
||||||
@ -387,12 +393,12 @@ void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3&
|
|||||||
{
|
{
|
||||||
btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal);
|
btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal);
|
||||||
solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
|
solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
|
||||||
solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis1;
|
solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal);
|
btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal);
|
||||||
solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
|
solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
|
||||||
solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis1;
|
solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef COMPUTE_IMPULSE_DENOM
|
#ifdef COMPUTE_IMPULSE_DENOM
|
||||||
@ -400,21 +406,32 @@ void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3&
|
|||||||
btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal);
|
btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal);
|
||||||
#else
|
#else
|
||||||
btVector3 vec;
|
btVector3 vec;
|
||||||
vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
|
btScalar denom0 = 0.f;
|
||||||
btScalar denom0 = rb0->getInvMass() + normalAxis.dot(vec);
|
btScalar denom1 = 0.f;
|
||||||
vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2);
|
if (body0)
|
||||||
btScalar denom1 = rb1->getInvMass() + normalAxis.dot(vec);
|
{
|
||||||
|
vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
|
||||||
|
denom0 = body0->getInvMass() + normalAxis.dot(vec);
|
||||||
|
}
|
||||||
|
if (body1)
|
||||||
|
{
|
||||||
|
vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2);
|
||||||
|
denom1 = body1->getInvMass() + normalAxis.dot(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif //COMPUTE_IMPULSE_DENOM
|
#endif //COMPUTE_IMPULSE_DENOM
|
||||||
btScalar denom = relaxation/(denom0+denom1);
|
btScalar denom = relaxation/(denom0+denom1);
|
||||||
solverConstraint.m_jacDiagABInv = denom;
|
solverConstraint.m_jacDiagABInv = denom;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
|
btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
|
||||||
{
|
{
|
||||||
|
BT_PROFILE("solveGroupCacheFriendlySetup");
|
||||||
(void)stackAlloc;
|
(void)stackAlloc;
|
||||||
(void)debugDrawer;
|
(void)debugDrawer;
|
||||||
|
|
||||||
@ -424,7 +441,10 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
|||||||
return 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
btPersistentManifold* manifold = 0;
|
btPersistentManifold* manifold = 0;
|
||||||
btRigidBody* rb0=0,*rb1=0;
|
btCollisionObject* colObj0=0,*colObj1=0;
|
||||||
|
|
||||||
|
//btRigidBody* rb0=0,*rb1=0;
|
||||||
|
|
||||||
|
|
||||||
#ifdef FORCE_REFESH_CONTACT_MANIFOLDS
|
#ifdef FORCE_REFESH_CONTACT_MANIFOLDS
|
||||||
|
|
||||||
@ -450,7 +470,6 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
|||||||
btVector3 color(0,1,0);
|
btVector3 color(0,1,0);
|
||||||
|
|
||||||
|
|
||||||
BEGIN_PROFILE("gatherSolverData");
|
|
||||||
|
|
||||||
//int sizeofSB = sizeof(btSolverBody);
|
//int sizeofSB = sizeof(btSolverBody);
|
||||||
//int sizeofSC = sizeof(btSolverConstraint);
|
//int sizeofSC = sizeof(btSolverConstraint);
|
||||||
@ -498,10 +517,8 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
|||||||
for (i=0;i<numManifolds;i++)
|
for (i=0;i<numManifolds;i++)
|
||||||
{
|
{
|
||||||
manifold = manifoldPtr[i];
|
manifold = manifoldPtr[i];
|
||||||
rb1 = (btRigidBody*)manifold->getBody1();
|
colObj0 = (btCollisionObject*)manifold->getBody0();
|
||||||
|
colObj1 = (btCollisionObject*)manifold->getBody1();
|
||||||
rb0 = (btRigidBody*)manifold->getBody0();
|
|
||||||
|
|
||||||
|
|
||||||
int solverBodyIdA=-1;
|
int solverBodyIdA=-1;
|
||||||
int solverBodyIdB=-1;
|
int solverBodyIdB=-1;
|
||||||
@ -511,45 +528,45 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (rb0->getIslandTag() >= 0)
|
if (colObj0->getIslandTag() >= 0)
|
||||||
{
|
{
|
||||||
if (rb0->getCompanionId() >= 0)
|
if (colObj0->getCompanionId() >= 0)
|
||||||
{
|
{
|
||||||
//body has already been converted
|
//body has already been converted
|
||||||
solverBodyIdA = rb0->getCompanionId();
|
solverBodyIdA = colObj0->getCompanionId();
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
solverBodyIdA = m_tmpSolverBodyPool.size();
|
solverBodyIdA = m_tmpSolverBodyPool.size();
|
||||||
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
|
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
|
||||||
initSolverBody(&solverBody,rb0);
|
initSolverBody(&solverBody,colObj0);
|
||||||
rb0->setCompanionId(solverBodyIdA);
|
colObj0->setCompanionId(solverBodyIdA);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
//create a static body
|
//create a static body
|
||||||
solverBodyIdA = m_tmpSolverBodyPool.size();
|
solverBodyIdA = m_tmpSolverBodyPool.size();
|
||||||
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
|
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
|
||||||
initSolverBody(&solverBody,rb0);
|
initSolverBody(&solverBody,colObj0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rb1->getIslandTag() >= 0)
|
if (colObj1->getIslandTag() >= 0)
|
||||||
{
|
{
|
||||||
if (rb1->getCompanionId() >= 0)
|
if (colObj1->getCompanionId() >= 0)
|
||||||
{
|
{
|
||||||
solverBodyIdB = rb1->getCompanionId();
|
solverBodyIdB = colObj1->getCompanionId();
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
solverBodyIdB = m_tmpSolverBodyPool.size();
|
solverBodyIdB = m_tmpSolverBodyPool.size();
|
||||||
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
|
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
|
||||||
initSolverBody(&solverBody,rb1);
|
initSolverBody(&solverBody,colObj1);
|
||||||
rb1->setCompanionId(solverBodyIdB);
|
colObj1->setCompanionId(solverBodyIdB);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
//create a static body
|
//create a static body
|
||||||
solverBodyIdB = m_tmpSolverBodyPool.size();
|
solverBodyIdB = m_tmpSolverBodyPool.size();
|
||||||
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
|
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
|
||||||
initSolverBody(&solverBody,rb1);
|
initSolverBody(&solverBody,colObj1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,8 +589,8 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
|||||||
const btVector3& pos1 = cp.getPositionWorldOnA();
|
const btVector3& pos1 = cp.getPositionWorldOnA();
|
||||||
const btVector3& pos2 = cp.getPositionWorldOnB();
|
const btVector3& pos2 = cp.getPositionWorldOnB();
|
||||||
|
|
||||||
rel_pos1 = pos1 - rb0->getCenterOfMassPosition();
|
rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
|
||||||
rel_pos2 = pos2 - rb1->getCenterOfMassPosition();
|
rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
|
||||||
|
|
||||||
|
|
||||||
relaxation = 1.f;
|
relaxation = 1.f;
|
||||||
@ -584,25 +601,35 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
|||||||
|
|
||||||
{
|
{
|
||||||
btSolverConstraint& solverConstraint = m_tmpSolverConstraintPool.expand();
|
btSolverConstraint& solverConstraint = m_tmpSolverConstraintPool.expand();
|
||||||
|
btRigidBody* rb0 = btRigidBody::upcast(colObj0);
|
||||||
|
btRigidBody* rb1 = btRigidBody::upcast(colObj1);
|
||||||
|
|
||||||
solverConstraint.m_solverBodyIdA = solverBodyIdA;
|
solverConstraint.m_solverBodyIdA = solverBodyIdA;
|
||||||
solverConstraint.m_solverBodyIdB = solverBodyIdB;
|
solverConstraint.m_solverBodyIdB = solverBodyIdB;
|
||||||
solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_CONTACT_1D;
|
solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_CONTACT_1D;
|
||||||
|
|
||||||
btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
|
btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
|
||||||
solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*torqueAxis0;
|
solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0 : btVector3(0,0,0);
|
||||||
btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
|
btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
|
||||||
solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*torqueAxis1;
|
solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*torqueAxis1 : btVector3(0,0,0);
|
||||||
{
|
{
|
||||||
#ifdef COMPUTE_IMPULSE_DENOM
|
#ifdef COMPUTE_IMPULSE_DENOM
|
||||||
btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB);
|
btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB);
|
||||||
btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB);
|
btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB);
|
||||||
#else
|
#else
|
||||||
btVector3 vec;
|
btVector3 vec;
|
||||||
vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
|
btScalar denom0 = 0.f;
|
||||||
btScalar denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
|
btScalar denom1 = 0.f;
|
||||||
vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2);
|
if (rb0)
|
||||||
btScalar denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
|
{
|
||||||
|
vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
|
||||||
|
denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
|
||||||
|
}
|
||||||
|
if (rb1)
|
||||||
|
{
|
||||||
|
vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2);
|
||||||
|
denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
|
||||||
|
}
|
||||||
#endif //COMPUTE_IMPULSE_DENOM
|
#endif //COMPUTE_IMPULSE_DENOM
|
||||||
|
|
||||||
btScalar denom = relaxation/(denom0+denom1);
|
btScalar denom = relaxation/(denom0+denom1);
|
||||||
@ -614,8 +641,8 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
|||||||
solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(cp.m_normalWorldOnB);
|
solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(cp.m_normalWorldOnB);
|
||||||
|
|
||||||
|
|
||||||
btVector3 vel1 = rb0->getVelocityInLocalPoint(rel_pos1);
|
btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0);
|
||||||
btVector3 vel2 = rb1->getVelocityInLocalPoint(rel_pos2);
|
btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
|
||||||
|
|
||||||
vel = vel1 - vel2;
|
vel = vel1 - vel2;
|
||||||
|
|
||||||
@ -647,36 +674,35 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
btVector3 frictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
|
btVector3 frictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
|
||||||
btScalar lat_rel_vel = frictionDir1.length2();
|
btScalar lat_rel_vel = frictionDir1.length2();
|
||||||
if (lat_rel_vel > SIMD_EPSILON)//0.0f)
|
if (lat_rel_vel > SIMD_EPSILON)//0.0f)
|
||||||
{
|
{
|
||||||
frictionDir1 /= btSqrt(lat_rel_vel);
|
frictionDir1 /= btSqrt(lat_rel_vel);
|
||||||
addFrictionConstraint(frictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation);
|
addFrictionConstraint(frictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||||
btVector3 frictionDir2 = frictionDir1.cross(cp.m_normalWorldOnB);
|
btVector3 frictionDir2 = frictionDir1.cross(cp.m_normalWorldOnB);
|
||||||
frictionDir2.normalize();//??
|
frictionDir2.normalize();//??
|
||||||
addFrictionConstraint(frictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation);
|
addFrictionConstraint(frictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
//re-calculate friction direction every frame, todo: check if this is really needed
|
//re-calculate friction direction every frame, todo: check if this is really needed
|
||||||
btVector3 frictionDir1,frictionDir2;
|
btVector3 frictionDir1,frictionDir2;
|
||||||
btPlaneSpace1(cp.m_normalWorldOnB,frictionDir1,frictionDir2);
|
btPlaneSpace1(cp.m_normalWorldOnB,frictionDir1,frictionDir2);
|
||||||
addFrictionConstraint(frictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation);
|
addFrictionConstraint(frictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||||
addFrictionConstraint(frictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation);
|
addFrictionConstraint(frictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_PROFILE("gatherSolverData");
|
|
||||||
|
|
||||||
BEGIN_PROFILE("prepareConstraints");
|
|
||||||
|
|
||||||
btContactSolverInfo info = infoGlobal;
|
btContactSolverInfo info = infoGlobal;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -710,15 +736,13 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
END_PROFILE("prepareConstraints");
|
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
|
btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
|
||||||
{
|
{
|
||||||
BEGIN_PROFILE("solveConstraintsIterations");
|
BT_PROFILE("solveGroupCacheFriendlyIterations");
|
||||||
int numConstraintPool = m_tmpSolverConstraintPool.size();
|
int numConstraintPool = m_tmpSolverConstraintPool.size();
|
||||||
int numFrictionPool = m_tmpSolverFrictionConstraintPool.size();
|
int numFrictionPool = m_tmpSolverFrictionConstraintPool.size();
|
||||||
|
|
||||||
@ -750,6 +774,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
|
|||||||
|
|
||||||
for (j=0;j<numConstraints;j++)
|
for (j=0;j<numConstraints;j++)
|
||||||
{
|
{
|
||||||
|
BT_PROFILE("solveConstraint");
|
||||||
btTypedConstraint* constraint = constraints[j];
|
btTypedConstraint* constraint = constraints[j];
|
||||||
///todo: use solver bodies, so we don't need to copy from/to btRigidBody
|
///todo: use solver bodies, so we don't need to copy from/to btRigidBody
|
||||||
|
|
||||||
@ -776,9 +801,11 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
BT_PROFILE("resolveSingleCollisionCombinedCacheFriendly");
|
||||||
int numPoolConstraints = m_tmpSolverConstraintPool.size();
|
int numPoolConstraints = m_tmpSolverConstraintPool.size();
|
||||||
for (j=0;j<numPoolConstraints;j++)
|
for (j=0;j<numPoolConstraints;j++)
|
||||||
{
|
{
|
||||||
|
|
||||||
const btSolverConstraint& solveManifold = m_tmpSolverConstraintPool[m_orderTmpConstraintPool[j]];
|
const btSolverConstraint& solveManifold = m_tmpSolverConstraintPool[m_orderTmpConstraintPool[j]];
|
||||||
resolveSingleCollisionCombinedCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],
|
resolveSingleCollisionCombinedCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],
|
||||||
m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,infoGlobal);
|
m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,infoGlobal);
|
||||||
@ -786,6 +813,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
BT_PROFILE("resolveSingleFrictionCacheFriendly");
|
||||||
int numFrictionPoolConstraints = m_tmpSolverFrictionConstraintPool.size();
|
int numFrictionPoolConstraints = m_tmpSolverFrictionConstraintPool.size();
|
||||||
|
|
||||||
for (j=0;j<numFrictionPoolConstraints;j++)
|
for (j=0;j<numFrictionPoolConstraints;j++)
|
||||||
@ -804,8 +832,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
END_PROFILE("solveConstraintsIterations");
|
|
||||||
|
|
||||||
return 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -817,14 +844,12 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio
|
|||||||
solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
|
solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
|
||||||
solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
|
solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
|
||||||
|
|
||||||
BEGIN_PROFILE("solveWriteBackVelocity");
|
|
||||||
|
|
||||||
for ( i=0;i<m_tmpSolverBodyPool.size();i++)
|
for ( i=0;i<m_tmpSolverBodyPool.size();i++)
|
||||||
{
|
{
|
||||||
m_tmpSolverBodyPool[i].writebackVelocity();
|
m_tmpSolverBodyPool[i].writebackVelocity();
|
||||||
}
|
}
|
||||||
|
|
||||||
END_PROFILE("solveWriteBackVelocity");
|
|
||||||
|
|
||||||
// printf("m_tmpSolverConstraintPool.size() = %i\n",m_tmpSolverConstraintPool.size());
|
// printf("m_tmpSolverConstraintPool.size() = %i\n",m_tmpSolverConstraintPool.size());
|
||||||
|
|
||||||
@ -850,7 +875,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio
|
|||||||
/// btSequentialImpulseConstraintSolver Sequentially applies impulses
|
/// btSequentialImpulseConstraintSolver Sequentially applies impulses
|
||||||
btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* dispatcher)
|
btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* dispatcher)
|
||||||
{
|
{
|
||||||
|
BT_PROFILE("solveGroup");
|
||||||
if (getSolverMode() & SOLVER_CACHE_FRIENDLY)
|
if (getSolverMode() & SOLVER_CACHE_FRIENDLY)
|
||||||
{
|
{
|
||||||
//you need to provide at least some bodies
|
//you need to provide at least some bodies
|
||||||
@ -860,16 +885,11 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
|
|||||||
return solveGroupCacheFriendly(bodies,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc);
|
return solveGroupCacheFriendly(bodies,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BEGIN_PROFILE("prepareConstraints");
|
|
||||||
|
|
||||||
|
|
||||||
btContactSolverInfo info = infoGlobal;
|
btContactSolverInfo info = infoGlobal;
|
||||||
|
|
||||||
int numiter = infoGlobal.m_numIterations;
|
int numiter = infoGlobal.m_numIterations;
|
||||||
#ifdef USE_PROFILE
|
|
||||||
btProfiler::beginBlock("solve");
|
|
||||||
#endif //USE_PROFILE
|
|
||||||
|
|
||||||
int totalPoints = 0;
|
int totalPoints = 0;
|
||||||
|
|
||||||
@ -899,10 +919,6 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
END_PROFILE("prepareConstraints");
|
|
||||||
|
|
||||||
|
|
||||||
BEGIN_PROFILE("solveConstraints");
|
|
||||||
|
|
||||||
//should traverse the contacts random order...
|
//should traverse the contacts random order...
|
||||||
int iteration;
|
int iteration;
|
||||||
@ -947,13 +963,6 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
END_PROFILE("solveConstraints");
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_PROFILE
|
|
||||||
btProfiler::endBlock("solve");
|
|
||||||
#endif //USE_PROFILE
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ protected:
|
|||||||
btScalar solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer);
|
btScalar solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer);
|
||||||
btScalar solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer);
|
btScalar solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer);
|
||||||
void prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer);
|
void prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer);
|
||||||
void addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btRigidBody* rb0,btRigidBody* rb1, btScalar relaxation);
|
void addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation);
|
||||||
|
|
||||||
ContactSolverFunc m_contactDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES];
|
ContactSolverFunc m_contactDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES];
|
||||||
ContactSolverFunc m_frictionDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES];
|
ContactSolverFunc m_frictionDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES];
|
||||||
|
@ -127,7 +127,8 @@ plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionSh
|
|||||||
shape->calculateLocalInertia(mass,localInertia);
|
shape->calculateLocalInertia(mass,localInertia);
|
||||||
}
|
}
|
||||||
void* mem = btAlignedAlloc(sizeof(btRigidBody),16);
|
void* mem = btAlignedAlloc(sizeof(btRigidBody),16);
|
||||||
btRigidBody* body = new (mem)btRigidBody(mass, 0,shape,localInertia);
|
btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia);
|
||||||
|
btRigidBody* body = new (mem)btRigidBody(rbci);
|
||||||
body->setWorldTransform(trans);
|
body->setWorldTransform(trans);
|
||||||
body->setUserPointer(user_data);
|
body->setUserPointer(user_data);
|
||||||
return (plRigidBodyHandle) body;
|
return (plRigidBodyHandle) body;
|
||||||
|
@ -47,6 +47,7 @@ void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
|
|||||||
{
|
{
|
||||||
|
|
||||||
startProfiling(timeStep);
|
startProfiling(timeStep);
|
||||||
|
|
||||||
|
|
||||||
///update aabbs information
|
///update aabbs information
|
||||||
updateAabbs();
|
updateAabbs();
|
||||||
@ -115,14 +116,11 @@ void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep)
|
|||||||
|
|
||||||
///calculate time of impact for overlapping pairs
|
///calculate time of impact for overlapping pairs
|
||||||
|
|
||||||
BEGIN_PROFILE("performContinuousCollisionDetection");
|
|
||||||
|
|
||||||
btDispatcher* dispatcher = getDispatcher();
|
btDispatcher* dispatcher = getDispatcher();
|
||||||
if (dispatcher)
|
if (dispatcher)
|
||||||
dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
|
dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
|
||||||
|
|
||||||
END_PROFILE("performContinuousCollisionDetection");
|
|
||||||
|
|
||||||
toi = dispatchInfo.m_timeOfImpact;
|
toi = dispatchInfo.m_timeOfImpact;
|
||||||
|
|
||||||
dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE;
|
dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE;
|
||||||
@ -131,7 +129,6 @@ void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep)
|
|||||||
|
|
||||||
void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep)
|
void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep)
|
||||||
{
|
{
|
||||||
BEGIN_PROFILE("perform Temporal Broadphase Collision Detection");
|
|
||||||
|
|
||||||
btVector3 temporalAabbMin,temporalAabbMax;
|
btVector3 temporalAabbMin,temporalAabbMax;
|
||||||
|
|
||||||
@ -186,7 +183,6 @@ void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep)
|
|||||||
|
|
||||||
m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
|
m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
|
||||||
|
|
||||||
END_PROFILE("perform Temporal Broadphase Collision Detection");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,8 @@ subject to the following restrictions:
|
|||||||
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
|
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
|
||||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||||
#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
|
#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
|
||||||
#include <LinearMath/btTransformUtil.h>
|
#include "LinearMath/btTransformUtil.h"
|
||||||
|
#include "LinearMath/btQuickprof.h"
|
||||||
|
|
||||||
//rigidbody & constraints
|
//rigidbody & constraints
|
||||||
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||||
@ -60,7 +61,6 @@ subject to the following restrictions:
|
|||||||
btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
|
btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
|
||||||
:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
|
:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
|
||||||
m_constraintSolver(constraintSolver),
|
m_constraintSolver(constraintSolver),
|
||||||
m_debugDrawer(0),
|
|
||||||
m_gravity(0,-10,0),
|
m_gravity(0,-10,0),
|
||||||
m_localTime(btScalar(1.)/btScalar(60.)),
|
m_localTime(btScalar(1.)/btScalar(60.)),
|
||||||
m_profileTimings(0)
|
m_profileTimings(0)
|
||||||
@ -122,14 +122,14 @@ void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void btDiscreteDynamicsWorld::synchronizeMotionStates()
|
void btDiscreteDynamicsWorld::debugDrawWorld()
|
||||||
{
|
{
|
||||||
//debug vehicle wheels
|
if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
//todo: iterate over awake simulation islands!
|
//todo: iterate over awake simulation islands!
|
||||||
for ( int i=0;i<m_collisionObjects.size();i++)
|
for ( i=0;i<m_collisionObjects.size();i++)
|
||||||
{
|
{
|
||||||
btCollisionObject* colObj = m_collisionObjects[i];
|
btCollisionObject* colObj = m_collisionObjects[i];
|
||||||
if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe)
|
if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe)
|
||||||
@ -155,6 +155,88 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates()
|
|||||||
|
|
||||||
debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color);
|
debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color);
|
||||||
}
|
}
|
||||||
|
if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
|
||||||
|
{
|
||||||
|
btPoint3 minAabb,maxAabb;
|
||||||
|
btVector3 colorvec(1,0,0);
|
||||||
|
colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
|
||||||
|
m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i=0;i<this->m_vehicles.size();i++)
|
||||||
|
{
|
||||||
|
for (int v=0;v<m_vehicles[i]->getNumWheels();v++)
|
||||||
|
{
|
||||||
|
btVector3 wheelColor(0,255,255);
|
||||||
|
if (m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact)
|
||||||
|
{
|
||||||
|
wheelColor.setValue(0,0,255);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
wheelColor.setValue(255,0,255);
|
||||||
|
}
|
||||||
|
|
||||||
|
btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin();
|
||||||
|
|
||||||
|
btVector3 axle = btVector3(
|
||||||
|
m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[0][m_vehicles[i]->getRightAxis()],
|
||||||
|
m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[1][m_vehicles[i]->getRightAxis()],
|
||||||
|
m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[2][m_vehicles[i]->getRightAxis()]);
|
||||||
|
|
||||||
|
|
||||||
|
//m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_wheelAxleWS
|
||||||
|
//debug wheels (cylinders)
|
||||||
|
m_debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor);
|
||||||
|
m_debugDrawer->drawLine(wheelPosWS,m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void btDiscreteDynamicsWorld::clearForces()
|
||||||
|
{
|
||||||
|
//todo: iterate over awake simulation islands!
|
||||||
|
for ( int i=0;i<m_collisionObjects.size();i++)
|
||||||
|
{
|
||||||
|
btCollisionObject* colObj = m_collisionObjects[i];
|
||||||
|
|
||||||
|
btRigidBody* body = btRigidBody::upcast(colObj);
|
||||||
|
if (body)
|
||||||
|
{
|
||||||
|
body->clearForces();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///apply gravity, call this once per timestep
|
||||||
|
void btDiscreteDynamicsWorld::applyGravity()
|
||||||
|
{
|
||||||
|
//todo: iterate over awake simulation islands!
|
||||||
|
for ( int i=0;i<m_collisionObjects.size();i++)
|
||||||
|
{
|
||||||
|
btCollisionObject* colObj = m_collisionObjects[i];
|
||||||
|
|
||||||
|
btRigidBody* body = btRigidBody::upcast(colObj);
|
||||||
|
if (body && body->isActive())
|
||||||
|
{
|
||||||
|
body->applyGravity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void btDiscreteDynamicsWorld::synchronizeMotionStates()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
//todo: iterate over awake simulation islands!
|
||||||
|
for ( int i=0;i<m_collisionObjects.size();i++)
|
||||||
|
{
|
||||||
|
btCollisionObject* colObj = m_collisionObjects[i];
|
||||||
|
|
||||||
btRigidBody* body = btRigidBody::upcast(colObj);
|
btRigidBody* body = btRigidBody::upcast(colObj);
|
||||||
if (body && body->getMotionState() && !body->isStaticOrKinematicObject())
|
if (body && body->getMotionState() && !body->isStaticOrKinematicObject())
|
||||||
{
|
{
|
||||||
@ -178,31 +260,8 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates()
|
|||||||
{
|
{
|
||||||
for (int v=0;v<m_vehicles[i]->getNumWheels();v++)
|
for (int v=0;v<m_vehicles[i]->getNumWheels();v++)
|
||||||
{
|
{
|
||||||
btVector3 wheelColor(0,255,255);
|
|
||||||
if (m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact)
|
|
||||||
{
|
|
||||||
wheelColor.setValue(0,0,255);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
wheelColor.setValue(255,0,255);
|
|
||||||
}
|
|
||||||
|
|
||||||
//synchronize the wheels with the (interpolated) chassis worldtransform
|
//synchronize the wheels with the (interpolated) chassis worldtransform
|
||||||
m_vehicles[i]->updateWheelTransform(v,true);
|
m_vehicles[i]->updateWheelTransform(v,true);
|
||||||
|
|
||||||
btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin();
|
|
||||||
|
|
||||||
btVector3 axle = btVector3(
|
|
||||||
m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[0][m_vehicles[i]->getRightAxis()],
|
|
||||||
m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[1][m_vehicles[i]->getRightAxis()],
|
|
||||||
m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[2][m_vehicles[i]->getRightAxis()]);
|
|
||||||
|
|
||||||
|
|
||||||
//m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_wheelAxleWS
|
|
||||||
//debug wheels (cylinders)
|
|
||||||
m_debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor);
|
|
||||||
m_debugDrawer->drawLine(wheelPosWS,m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,6 +271,10 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates()
|
|||||||
|
|
||||||
int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
|
int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
|
||||||
{
|
{
|
||||||
|
startProfiling(timeStep);
|
||||||
|
|
||||||
|
BT_PROFILE("stepSimulation");
|
||||||
|
|
||||||
int numSimulationSubSteps = 0;
|
int numSimulationSubSteps = 0;
|
||||||
|
|
||||||
if (maxSubSteps)
|
if (maxSubSteps)
|
||||||
@ -249,6 +312,8 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
|
|||||||
|
|
||||||
saveKinematicState(fixedTimeStep);
|
saveKinematicState(fixedTimeStep);
|
||||||
|
|
||||||
|
applyGravity();
|
||||||
|
|
||||||
//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
|
//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
|
||||||
int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
|
int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
|
||||||
|
|
||||||
@ -262,16 +327,17 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
|
|||||||
|
|
||||||
synchronizeMotionStates();
|
synchronizeMotionStates();
|
||||||
|
|
||||||
|
clearForces();
|
||||||
|
|
||||||
|
CProfileManager::Increment_Frame_Counter();
|
||||||
|
|
||||||
return numSimulationSubSteps;
|
return numSimulationSubSteps;
|
||||||
}
|
}
|
||||||
|
|
||||||
void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
|
void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
|
||||||
{
|
{
|
||||||
|
|
||||||
startProfiling(timeStep);
|
BT_PROFILE("internalSingleStepSimulation");
|
||||||
|
|
||||||
///update aabbs information
|
|
||||||
updateAabbs();
|
|
||||||
|
|
||||||
///apply gravity, predict motion
|
///apply gravity, predict motion
|
||||||
predictUnconstraintMotion(timeStep);
|
predictUnconstraintMotion(timeStep);
|
||||||
@ -306,8 +372,6 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
|
|||||||
|
|
||||||
updateActivationState( timeStep );
|
updateActivationState( timeStep );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
|
void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
|
||||||
@ -363,19 +427,18 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short
|
|||||||
|
|
||||||
void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep)
|
void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep)
|
||||||
{
|
{
|
||||||
BEGIN_PROFILE("updateVehicles");
|
BT_PROFILE("updateVehicles");
|
||||||
|
|
||||||
for ( int i=0;i<m_vehicles.size();i++)
|
for ( int i=0;i<m_vehicles.size();i++)
|
||||||
{
|
{
|
||||||
btRaycastVehicle* vehicle = m_vehicles[i];
|
btRaycastVehicle* vehicle = m_vehicles[i];
|
||||||
vehicle->updateVehicle( timeStep);
|
vehicle->updateVehicle( timeStep);
|
||||||
}
|
}
|
||||||
END_PROFILE("updateVehicles");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
|
void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
|
||||||
{
|
{
|
||||||
BEGIN_PROFILE("updateActivationState");
|
BT_PROFILE("updateActivationState");
|
||||||
|
|
||||||
for ( int i=0;i<m_collisionObjects.size();i++)
|
for ( int i=0;i<m_collisionObjects.size();i++)
|
||||||
{
|
{
|
||||||
@ -402,7 +465,6 @@ void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_PROFILE("updateActivationState");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies)
|
void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies)
|
||||||
@ -462,6 +524,7 @@ class btSortConstraintOnIslandPredicate
|
|||||||
|
|
||||||
void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
|
void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
|
||||||
{
|
{
|
||||||
|
BT_PROFILE("solveConstraints");
|
||||||
|
|
||||||
struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
|
struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
|
||||||
{
|
{
|
||||||
@ -569,7 +632,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
|
|||||||
|
|
||||||
void btDiscreteDynamicsWorld::calculateSimulationIslands()
|
void btDiscreteDynamicsWorld::calculateSimulationIslands()
|
||||||
{
|
{
|
||||||
BEGIN_PROFILE("calculateSimulationIslands");
|
BT_PROFILE("calculateSimulationIslands");
|
||||||
|
|
||||||
getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
|
getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
|
||||||
|
|
||||||
@ -599,66 +662,14 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands()
|
|||||||
//Store the island id in each body
|
//Store the island id in each body
|
||||||
getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
|
getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
|
||||||
|
|
||||||
END_PROFILE("calculateSimulationIslands");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void btDiscreteDynamicsWorld::updateAabbs()
|
|
||||||
{
|
|
||||||
BEGIN_PROFILE("updateAabbs");
|
|
||||||
|
|
||||||
btVector3 colorvec(1,0,0);
|
|
||||||
btTransform predictedTrans;
|
|
||||||
for ( int i=0;i<m_collisionObjects.size();i++)
|
|
||||||
{
|
|
||||||
btCollisionObject* colObj = m_collisionObjects[i];
|
|
||||||
|
|
||||||
btRigidBody* body = btRigidBody::upcast(colObj);
|
|
||||||
if (body)
|
|
||||||
{
|
|
||||||
// if (body->IsActive() && (!body->IsStatic()))
|
|
||||||
{
|
|
||||||
btPoint3 minAabb,maxAabb;
|
|
||||||
colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
|
|
||||||
btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
|
|
||||||
|
|
||||||
//moving objects should be moderately sized, probably something wrong if not
|
|
||||||
if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
|
|
||||||
{
|
|
||||||
bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
//something went wrong, investigate
|
|
||||||
//this assert is unwanted in 3D modelers (danger of loosing work)
|
|
||||||
body->setActivationState(DISABLE_SIMULATION);
|
|
||||||
|
|
||||||
static bool reportMe = true;
|
|
||||||
if (reportMe && m_debugDrawer)
|
|
||||||
{
|
|
||||||
reportMe = false;
|
|
||||||
m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
|
|
||||||
m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
|
|
||||||
m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
|
|
||||||
m_debugDrawer->reportErrorWarning("Thanks.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
|
|
||||||
{
|
|
||||||
m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
END_PROFILE("updateAabbs");
|
|
||||||
}
|
|
||||||
|
|
||||||
void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
|
void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
|
||||||
{
|
{
|
||||||
BEGIN_PROFILE("integrateTransforms");
|
BT_PROFILE("integrateTransforms");
|
||||||
btTransform predictedTrans;
|
btTransform predictedTrans;
|
||||||
for ( int i=0;i<m_collisionObjects.size();i++)
|
for ( int i=0;i<m_collisionObjects.size();i++)
|
||||||
{
|
{
|
||||||
@ -673,14 +684,13 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_PROFILE("integrateTransforms");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
|
void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
|
||||||
{
|
{
|
||||||
BEGIN_PROFILE("predictUnconstraintMotion");
|
BT_PROFILE("predictUnconstraintMotion");
|
||||||
for ( int i=0;i<m_collisionObjects.size();i++)
|
for ( int i=0;i<m_collisionObjects.size();i++)
|
||||||
{
|
{
|
||||||
btCollisionObject* colObj = m_collisionObjects[i];
|
btCollisionObject* colObj = m_collisionObjects[i];
|
||||||
@ -691,20 +701,25 @@ void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
|
|||||||
{
|
{
|
||||||
if (body->isActive())
|
if (body->isActive())
|
||||||
{
|
{
|
||||||
body->applyForces( timeStep);
|
|
||||||
body->integrateVelocities( timeStep);
|
body->integrateVelocities( timeStep);
|
||||||
|
//damping
|
||||||
|
body->applyDamping(timeStep);
|
||||||
|
|
||||||
body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
|
body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_PROFILE("predictUnconstraintMotion");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
|
void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
|
||||||
{
|
{
|
||||||
(void)timeStep;
|
(void)timeStep;
|
||||||
|
|
||||||
|
CProfileManager::Reset();
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_QUICKPROF
|
#ifdef USE_QUICKPROF
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,164 +1,161 @@
|
|||||||
/*
|
/*
|
||||||
Bullet Continuous Collision Detection and Physics Library
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied warranty.
|
This software is provided 'as-is', without any express or implied warranty.
|
||||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it freely,
|
including commercial applications, and to alter it and redistribute it freely,
|
||||||
subject to the following restrictions:
|
subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BT_DISCRETE_DYNAMICS_WORLD_H
|
#ifndef BT_DISCRETE_DYNAMICS_WORLD_H
|
||||||
#define BT_DISCRETE_DYNAMICS_WORLD_H
|
#define BT_DISCRETE_DYNAMICS_WORLD_H
|
||||||
|
|
||||||
#include "btDynamicsWorld.h"
|
#include "btDynamicsWorld.h"
|
||||||
|
|
||||||
class btDispatcher;
|
class btDispatcher;
|
||||||
class btOverlappingPairCache;
|
class btOverlappingPairCache;
|
||||||
class btConstraintSolver;
|
class btConstraintSolver;
|
||||||
class btSimulationIslandManager;
|
class btSimulationIslandManager;
|
||||||
class btTypedConstraint;
|
class btTypedConstraint;
|
||||||
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
|
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
|
||||||
|
|
||||||
class btRaycastVehicle;
|
class btRaycastVehicle;
|
||||||
class btIDebugDraw;
|
class btIDebugDraw;
|
||||||
#include "LinearMath/btAlignedObjectArray.h"
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
|
||||||
///btDiscreteDynamicsWorld provides discrete rigid body simulation
|
///btDiscreteDynamicsWorld provides discrete rigid body simulation
|
||||||
///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
|
///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
|
||||||
class btDiscreteDynamicsWorld : public btDynamicsWorld
|
class btDiscreteDynamicsWorld : public btDynamicsWorld
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
btConstraintSolver* m_constraintSolver;
|
btConstraintSolver* m_constraintSolver;
|
||||||
|
|
||||||
btSimulationIslandManager* m_islandManager;
|
btSimulationIslandManager* m_islandManager;
|
||||||
|
|
||||||
btAlignedObjectArray<btTypedConstraint*> m_constraints;
|
btAlignedObjectArray<btTypedConstraint*> m_constraints;
|
||||||
|
|
||||||
btIDebugDraw* m_debugDrawer;
|
|
||||||
|
btVector3 m_gravity;
|
||||||
btVector3 m_gravity;
|
|
||||||
|
//for variable timesteps
|
||||||
//for variable timesteps
|
btScalar m_localTime;
|
||||||
btScalar m_localTime;
|
//for variable timesteps
|
||||||
//for variable timesteps
|
|
||||||
|
bool m_ownsIslandManager;
|
||||||
bool m_ownsIslandManager;
|
bool m_ownsConstraintSolver;
|
||||||
bool m_ownsConstraintSolver;
|
|
||||||
|
btContactSolverInfo m_solverInfo;
|
||||||
btContactSolverInfo m_solverInfo;
|
|
||||||
|
|
||||||
|
btAlignedObjectArray<btRaycastVehicle*> m_vehicles;
|
||||||
btAlignedObjectArray<btRaycastVehicle*> m_vehicles;
|
|
||||||
|
int m_profileTimings;
|
||||||
int m_profileTimings;
|
|
||||||
|
virtual void predictUnconstraintMotion(btScalar timeStep);
|
||||||
void predictUnconstraintMotion(btScalar timeStep);
|
|
||||||
|
void integrateTransforms(btScalar timeStep);
|
||||||
void integrateTransforms(btScalar timeStep);
|
|
||||||
|
void calculateSimulationIslands();
|
||||||
void calculateSimulationIslands();
|
|
||||||
|
void solveConstraints(btContactSolverInfo& solverInfo);
|
||||||
void solveConstraints(btContactSolverInfo& solverInfo);
|
|
||||||
|
void updateActivationState(btScalar timeStep);
|
||||||
void updateActivationState(btScalar timeStep);
|
|
||||||
|
void updateVehicles(btScalar timeStep);
|
||||||
void updateVehicles(btScalar timeStep);
|
|
||||||
|
void startProfiling(btScalar timeStep);
|
||||||
void startProfiling(btScalar timeStep);
|
|
||||||
|
virtual void internalSingleStepSimulation( btScalar timeStep);
|
||||||
virtual void internalSingleStepSimulation( btScalar timeStep);
|
|
||||||
|
void synchronizeMotionStates();
|
||||||
void synchronizeMotionStates();
|
|
||||||
|
void saveKinematicState(btScalar timeStep);
|
||||||
void saveKinematicState(btScalar timeStep);
|
|
||||||
|
void debugDrawSphere(btScalar radius, const btTransform& transform, const btVector3& color);
|
||||||
void debugDrawSphere(btScalar radius, const btTransform& transform, const btVector3& color);
|
|
||||||
|
public:
|
||||||
public:
|
|
||||||
|
|
||||||
|
///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
|
||||||
///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
|
btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
|
||||||
btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
|
|
||||||
|
virtual ~btDiscreteDynamicsWorld();
|
||||||
virtual ~btDiscreteDynamicsWorld();
|
|
||||||
|
///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
|
||||||
///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
|
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
|
||||||
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
|
|
||||||
|
|
||||||
virtual void updateAabbs();
|
void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false);
|
||||||
|
|
||||||
void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false);
|
void removeConstraint(btTypedConstraint* constraint);
|
||||||
|
|
||||||
void removeConstraint(btTypedConstraint* constraint);
|
void addVehicle(btRaycastVehicle* vehicle);
|
||||||
|
|
||||||
void addVehicle(btRaycastVehicle* vehicle);
|
void removeVehicle(btRaycastVehicle* vehicle);
|
||||||
|
|
||||||
void removeVehicle(btRaycastVehicle* vehicle);
|
btSimulationIslandManager* getSimulationIslandManager()
|
||||||
|
{
|
||||||
btSimulationIslandManager* getSimulationIslandManager()
|
return m_islandManager;
|
||||||
{
|
}
|
||||||
return m_islandManager;
|
|
||||||
}
|
const btSimulationIslandManager* getSimulationIslandManager() const
|
||||||
|
{
|
||||||
const btSimulationIslandManager* getSimulationIslandManager() const
|
return m_islandManager;
|
||||||
{
|
}
|
||||||
return m_islandManager;
|
|
||||||
}
|
btCollisionWorld* getCollisionWorld()
|
||||||
|
{
|
||||||
btCollisionWorld* getCollisionWorld()
|
return this;
|
||||||
{
|
}
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
virtual void setGravity(const btVector3& gravity);
|
||||||
virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
|
|
||||||
{
|
virtual void addRigidBody(btRigidBody* body);
|
||||||
m_debugDrawer = debugDrawer;
|
|
||||||
}
|
virtual void addRigidBody(btRigidBody* body, short group, short mask);
|
||||||
|
|
||||||
virtual btIDebugDraw* getDebugDrawer()
|
virtual void removeRigidBody(btRigidBody* body);
|
||||||
{
|
|
||||||
return m_debugDrawer;
|
void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
|
||||||
}
|
|
||||||
|
virtual void debugDrawWorld();
|
||||||
virtual void setGravity(const btVector3& gravity);
|
|
||||||
|
virtual void setConstraintSolver(btConstraintSolver* solver);
|
||||||
virtual void addRigidBody(btRigidBody* body);
|
|
||||||
|
virtual btConstraintSolver* getConstraintSolver();
|
||||||
virtual void addRigidBody(btRigidBody* body, short group, short mask);
|
|
||||||
|
virtual int getNumConstraints() const;
|
||||||
virtual void removeRigidBody(btRigidBody* body);
|
|
||||||
|
virtual btTypedConstraint* getConstraint(int index) ;
|
||||||
void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
|
|
||||||
|
virtual const btTypedConstraint* getConstraint(int index) const;
|
||||||
virtual void setConstraintSolver(btConstraintSolver* solver);
|
|
||||||
|
btContactSolverInfo& getSolverInfo()
|
||||||
virtual btConstraintSolver* getConstraintSolver();
|
{
|
||||||
|
return m_solverInfo;
|
||||||
virtual int getNumConstraints() const;
|
}
|
||||||
|
|
||||||
virtual btTypedConstraint* getConstraint(int index) ;
|
virtual btDynamicsWorldType getWorldType() const
|
||||||
|
{
|
||||||
virtual const btTypedConstraint* getConstraint(int index) const;
|
return BT_DISCRETE_DYNAMICS_WORLD;
|
||||||
|
}
|
||||||
btContactSolverInfo& getSolverInfo()
|
|
||||||
{
|
///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep.
|
||||||
return m_solverInfo;
|
virtual void clearForces();
|
||||||
}
|
|
||||||
|
///apply gravity, call this once per timestep
|
||||||
virtual btDynamicsWorldType getWorldType() const
|
virtual void applyGravity();
|
||||||
{
|
|
||||||
return BT_DISCRETE_DYNAMICS_WORLD;
|
|
||||||
}
|
};
|
||||||
|
|
||||||
|
#endif //BT_DISCRETE_DYNAMICS_WORLD_H
|
||||||
};
|
|
||||||
|
|
||||||
#endif //BT_DISCRETE_DYNAMICS_WORLD_H
|
|
||||||
|
@ -1,89 +1,87 @@
|
|||||||
/*
|
/*
|
||||||
Bullet Continuous Collision Detection and Physics Library
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied warranty.
|
This software is provided 'as-is', without any express or implied warranty.
|
||||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it freely,
|
including commercial applications, and to alter it and redistribute it freely,
|
||||||
subject to the following restrictions:
|
subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BT_DYNAMICS_WORLD_H
|
#ifndef BT_DYNAMICS_WORLD_H
|
||||||
#define BT_DYNAMICS_WORLD_H
|
#define BT_DYNAMICS_WORLD_H
|
||||||
|
|
||||||
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
|
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
|
||||||
class btTypedConstraint;
|
class btTypedConstraint;
|
||||||
class btRaycastVehicle;
|
class btRaycastVehicle;
|
||||||
class btConstraintSolver;
|
class btConstraintSolver;
|
||||||
|
|
||||||
|
|
||||||
enum btDynamicsWorldType
|
enum btDynamicsWorldType
|
||||||
{
|
{
|
||||||
BT_SIMPLE_DYNAMICS_WORLD=1,
|
BT_SIMPLE_DYNAMICS_WORLD=1,
|
||||||
BT_DISCRETE_DYNAMICS_WORLD=2,
|
BT_DISCRETE_DYNAMICS_WORLD=2,
|
||||||
BT_CONTINUOUS_DYNAMICS_WORLD=3
|
BT_CONTINUOUS_DYNAMICS_WORLD=3
|
||||||
};
|
};
|
||||||
|
|
||||||
///btDynamicsWorld is the baseclass for several dynamics implementation, basic, discrete, parallel, and continuous
|
///btDynamicsWorld is the baseclass for several dynamics implementation, basic, discrete, parallel, and continuous
|
||||||
class btDynamicsWorld : public btCollisionWorld
|
class btDynamicsWorld : public btCollisionWorld
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
|
btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
|
||||||
:btCollisionWorld(dispatcher,broadphase,collisionConfiguration)
|
:btCollisionWorld(dispatcher,broadphase,collisionConfiguration)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~btDynamicsWorld()
|
virtual ~btDynamicsWorld()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
///stepSimulation proceeds the simulation over timeStep units
|
///stepSimulation proceeds the simulation over timeStep units
|
||||||
///if maxSubSteps > 0, it will interpolate time steps
|
///if maxSubSteps > 0, it will interpolate time steps
|
||||||
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0;
|
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0;
|
||||||
|
|
||||||
virtual void updateAabbs() = 0;
|
virtual void debugDrawWorld() = 0;
|
||||||
|
|
||||||
virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) { (void)constraint;};
|
virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) { (void)constraint;};
|
||||||
|
|
||||||
virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;};
|
virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;};
|
||||||
|
|
||||||
virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;};
|
virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;};
|
||||||
|
|
||||||
virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;};
|
virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;};
|
||||||
|
|
||||||
|
//once a rigidbody is added to the dynamics world, it will get this gravity assigned
|
||||||
virtual void setDebugDrawer(btIDebugDraw* debugDrawer) = 0;
|
//existing rigidbodies in the world get gravity assigned too, during this method
|
||||||
|
virtual void setGravity(const btVector3& gravity) = 0;
|
||||||
virtual btIDebugDraw* getDebugDrawer() = 0;
|
|
||||||
|
virtual void addRigidBody(btRigidBody* body) = 0;
|
||||||
//once a rigidbody is added to the dynamics world, it will get this gravity assigned
|
|
||||||
//existing rigidbodies in the world get gravity assigned too, during this method
|
virtual void removeRigidBody(btRigidBody* body) = 0;
|
||||||
virtual void setGravity(const btVector3& gravity) = 0;
|
|
||||||
|
virtual void setConstraintSolver(btConstraintSolver* solver) = 0;
|
||||||
virtual void addRigidBody(btRigidBody* body) = 0;
|
|
||||||
|
virtual btConstraintSolver* getConstraintSolver() = 0;
|
||||||
virtual void removeRigidBody(btRigidBody* body) = 0;
|
|
||||||
|
virtual int getNumConstraints() const { return 0; }
|
||||||
virtual void setConstraintSolver(btConstraintSolver* solver) = 0;
|
|
||||||
|
virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; }
|
||||||
virtual btConstraintSolver* getConstraintSolver() = 0;
|
|
||||||
|
virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; }
|
||||||
virtual int getNumConstraints() const { return 0; }
|
|
||||||
|
virtual btDynamicsWorldType getWorldType() const=0;
|
||||||
virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; }
|
|
||||||
|
virtual void clearForces() = 0;
|
||||||
virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; }
|
|
||||||
|
|
||||||
virtual btDynamicsWorldType getWorldType() const=0;
|
};
|
||||||
|
|
||||||
};
|
#endif //BT_DYNAMICS_WORLD_H
|
||||||
|
|
||||||
#endif //BT_DYNAMICS_WORLD_H
|
|
||||||
|
|
||||||
|
@ -20,38 +20,51 @@ subject to the following restrictions:
|
|||||||
#include "LinearMath/btMotionState.h"
|
#include "LinearMath/btMotionState.h"
|
||||||
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
|
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
|
||||||
|
|
||||||
btScalar gLinearAirDamping = btScalar(1.);
|
|
||||||
//'temporarily' global variables
|
//'temporarily' global variables
|
||||||
btScalar gDeactivationTime = btScalar(2.);
|
btScalar gDeactivationTime = btScalar(2.);
|
||||||
bool gDisableDeactivation = false;
|
bool gDisableDeactivation = false;
|
||||||
|
|
||||||
btScalar gLinearSleepingThreshold = btScalar(0.8);
|
|
||||||
btScalar gAngularSleepingThreshold = btScalar(1.0);
|
|
||||||
static int uniqueId = 0;
|
static int uniqueId = 0;
|
||||||
|
|
||||||
btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution)
|
|
||||||
:
|
btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
|
||||||
m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
|
{
|
||||||
m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)),
|
setupRigidBody(constructionInfo);
|
||||||
m_angularFactor(btScalar(1.)),
|
}
|
||||||
m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
|
|
||||||
m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
|
btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia)
|
||||||
m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
|
{
|
||||||
m_linearDamping(btScalar(0.)),
|
btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia);
|
||||||
m_angularDamping(btScalar(0.5)),
|
setupRigidBody(cinfo);
|
||||||
m_linearSleepingThreshold(gLinearSleepingThreshold),
|
}
|
||||||
m_angularSleepingThreshold(gAngularSleepingThreshold),
|
|
||||||
m_optionalMotionState(motionState),
|
void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
|
||||||
m_contactSolverType(0),
|
|
||||||
m_frictionSolverType(0)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (motionState)
|
m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
|
||||||
|
m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||||
|
m_angularFactor = btScalar(1.);
|
||||||
|
m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
|
||||||
|
m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
|
||||||
|
m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
|
||||||
|
m_linearDamping = btScalar(0.);
|
||||||
|
m_angularDamping = btScalar(0.5);
|
||||||
|
m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold;
|
||||||
|
m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold;
|
||||||
|
m_optionalMotionState = constructionInfo.m_motionState;
|
||||||
|
m_contactSolverType = 0;
|
||||||
|
m_frictionSolverType = 0;
|
||||||
|
m_additionalDamping = constructionInfo.m_additionalDamping;
|
||||||
|
|
||||||
|
m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr;
|
||||||
|
m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr;
|
||||||
|
m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor;
|
||||||
|
|
||||||
|
if (m_optionalMotionState)
|
||||||
{
|
{
|
||||||
motionState->getWorldTransform(m_worldTransform);
|
m_optionalMotionState->getWorldTransform(m_worldTransform);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
m_worldTransform = btTransform::getIdentity();
|
m_worldTransform = constructionInfo.m_startWorldTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_interpolationWorldTransform = m_worldTransform;
|
m_interpolationWorldTransform = m_worldTransform;
|
||||||
@ -59,93 +72,24 @@ btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionS
|
|||||||
m_interpolationAngularVelocity.setValue(0,0,0);
|
m_interpolationAngularVelocity.setValue(0,0,0);
|
||||||
|
|
||||||
//moved to btCollisionObject
|
//moved to btCollisionObject
|
||||||
m_friction = friction;
|
m_friction = constructionInfo.m_friction;
|
||||||
m_restitution = restitution;
|
m_restitution = constructionInfo.m_restitution;
|
||||||
|
|
||||||
m_collisionShape = collisionShape;
|
m_collisionShape = constructionInfo.m_collisionShape;
|
||||||
m_debugBodyId = uniqueId++;
|
m_debugBodyId = uniqueId++;
|
||||||
|
|
||||||
//m_internalOwner is to allow upcasting from collision object to rigid body
|
//m_internalOwner is to allow upcasting from collision object to rigid body
|
||||||
m_internalOwner = this;
|
m_internalOwner = this;
|
||||||
|
|
||||||
setMassProps(mass, localInertia);
|
setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
|
||||||
setDamping(linearDamping, angularDamping);
|
setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
|
||||||
updateInertiaTensor();
|
updateInertiaTensor();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OBSOLETE_MOTIONSTATE_LESS
|
|
||||||
btRigidBody::btRigidBody( btScalar mass,const btTransform& worldTransform,btCollisionShape* collisionShape,const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution)
|
|
||||||
:
|
|
||||||
m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
|
|
||||||
m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
|
|
||||||
m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
|
|
||||||
m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
|
|
||||||
m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)),
|
|
||||||
m_linearSleepingThreshold(gLinearSleepingThreshold),
|
|
||||||
m_angularSleepingThreshold(gAngularSleepingThreshold),
|
|
||||||
m_linearDamping(btScalar(0.)),
|
|
||||||
m_angularDamping(btScalar(0.5)),
|
|
||||||
m_optionalMotionState(0),
|
|
||||||
m_contactSolverType(0),
|
|
||||||
m_frictionSolverType(0)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
m_worldTransform = worldTransform;
|
|
||||||
m_interpolationWorldTransform = m_worldTransform;
|
|
||||||
m_interpolationLinearVelocity.setValue(0,0,0);
|
|
||||||
m_interpolationAngularVelocity.setValue(0,0,0);
|
|
||||||
|
|
||||||
//moved to btCollisionObject
|
|
||||||
m_friction = friction;
|
|
||||||
m_restitution = restitution;
|
|
||||||
|
|
||||||
m_collisionShape = collisionShape;
|
|
||||||
m_debugBodyId = uniqueId++;
|
|
||||||
|
|
||||||
//m_internalOwner is to allow upcasting from collision object to rigid body
|
|
||||||
m_internalOwner = this;
|
|
||||||
|
|
||||||
setMassProps(mass, localInertia);
|
|
||||||
setDamping(linearDamping, angularDamping);
|
|
||||||
updateInertiaTensor();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //OBSOLETE_MOTIONSTATE_LESS
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define EXPERIMENTAL_JITTER_REMOVAL 1
|
|
||||||
#ifdef EXPERIMENTAL_JITTER_REMOVAL
|
|
||||||
//Bullet 2.20b has experimental damping code to reduce jitter just before objects fall asleep/deactivate
|
|
||||||
//doesn't work very well yet (value 0 disabled this damping)
|
|
||||||
//note there this influences deactivation thresholds!
|
|
||||||
btScalar gClippedAngvelThresholdSqr = btScalar(0.01);
|
|
||||||
btScalar gClippedLinearThresholdSqr = btScalar(0.01);
|
|
||||||
#endif //EXPERIMENTAL_JITTER_REMOVAL
|
|
||||||
|
|
||||||
btScalar gJitterVelocityDampingFactor = btScalar(0.7);
|
|
||||||
|
|
||||||
void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform)
|
void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_JITTER_REMOVAL
|
|
||||||
//if (wantsSleeping())
|
|
||||||
{
|
|
||||||
//clip to avoid jitter
|
|
||||||
if ((m_angularVelocity.length2() < gClippedAngvelThresholdSqr) &&
|
|
||||||
(m_linearVelocity.length2() < gClippedLinearThresholdSqr))
|
|
||||||
{
|
|
||||||
m_angularVelocity *= gJitterVelocityDampingFactor;
|
|
||||||
m_linearVelocity *= gJitterVelocityDampingFactor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //EXPERIMENTAL_JITTER_REMOVAL
|
|
||||||
|
|
||||||
btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform);
|
btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,50 +140,63 @@ void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
|
||||||
|
void btRigidBody::applyDamping(btScalar timeStep)
|
||||||
|
{
|
||||||
|
m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
|
||||||
|
m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
|
||||||
|
|
||||||
|
if (m_additionalDamping)
|
||||||
|
{
|
||||||
|
//Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
|
||||||
|
//Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
|
||||||
|
if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) &&
|
||||||
|
(m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr))
|
||||||
|
{
|
||||||
|
m_angularVelocity *= m_additionalDampingFactor;
|
||||||
|
m_linearVelocity *= m_additionalDampingFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btScalar speed = m_linearVelocity.length();
|
||||||
|
if (speed < m_linearDamping)
|
||||||
|
{
|
||||||
|
btScalar dampVel = btScalar(0.005);
|
||||||
|
if (speed > dampVel)
|
||||||
|
{
|
||||||
|
btVector3 dir = m_linearVelocity.normalized();
|
||||||
|
m_linearVelocity -= dir * dampVel;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btScalar angSpeed = m_angularVelocity.length();
|
||||||
|
if (angSpeed < m_angularDamping)
|
||||||
|
{
|
||||||
|
btScalar angDampVel = btScalar(0.005);
|
||||||
|
if (angSpeed > angDampVel)
|
||||||
|
{
|
||||||
|
btVector3 dir = m_angularVelocity.normalized();
|
||||||
|
m_angularVelocity -= dir * angDampVel;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void btRigidBody::applyForces(btScalar step)
|
void btRigidBody::applyGravity()
|
||||||
{
|
{
|
||||||
if (isStaticOrKinematicObject())
|
if (isStaticOrKinematicObject())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
applyCentralForce(m_gravity);
|
applyCentralForce(m_gravity);
|
||||||
|
|
||||||
m_linearVelocity *= GEN_clamped((btScalar(1.) - step * gLinearAirDamping * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
|
|
||||||
m_angularVelocity *= GEN_clamped((btScalar(1.) - step * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
|
|
||||||
|
|
||||||
#define FORCE_VELOCITY_DAMPING 1
|
|
||||||
#ifdef FORCE_VELOCITY_DAMPING
|
|
||||||
btScalar speed = m_linearVelocity.length();
|
|
||||||
if (speed < m_linearDamping)
|
|
||||||
{
|
|
||||||
btScalar dampVel = btScalar(0.005);
|
|
||||||
if (speed > dampVel)
|
|
||||||
{
|
|
||||||
btVector3 dir = m_linearVelocity.normalized();
|
|
||||||
m_linearVelocity -= dir * dampVel;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
btScalar angSpeed = m_angularVelocity.length();
|
|
||||||
if (angSpeed < m_angularDamping)
|
|
||||||
{
|
|
||||||
btScalar angDampVel = btScalar(0.005);
|
|
||||||
if (angSpeed > angDampVel)
|
|
||||||
{
|
|
||||||
btVector3 dir = m_angularVelocity.normalized();
|
|
||||||
m_angularVelocity -= dir * angDampVel;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif //FORCE_VELOCITY_DAMPING
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void btRigidBody::proceedToTransform(const btTransform& newTrans)
|
void btRigidBody::proceedToTransform(const btTransform& newTrans)
|
||||||
@ -290,7 +247,6 @@ void btRigidBody::integrateVelocities(btScalar step)
|
|||||||
m_angularVelocity *= (MAX_ANGVEL/step) /angvel;
|
m_angularVelocity *= (MAX_ANGVEL/step) /angvel;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearForces();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
btQuaternion btRigidBody::getOrientation() const
|
btQuaternion btRigidBody::getOrientation() const
|
||||||
|
@ -27,16 +27,18 @@ class btMotionState;
|
|||||||
class btTypedConstraint;
|
class btTypedConstraint;
|
||||||
|
|
||||||
|
|
||||||
extern btScalar gLinearAirDamping;
|
|
||||||
|
|
||||||
extern btScalar gDeactivationTime;
|
extern btScalar gDeactivationTime;
|
||||||
extern bool gDisableDeactivation;
|
extern bool gDisableDeactivation;
|
||||||
extern btScalar gLinearSleepingThreshold;
|
|
||||||
extern btScalar gAngularSleepingThreshold;
|
|
||||||
|
|
||||||
|
|
||||||
/// btRigidBody class for btRigidBody Dynamics
|
///btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape.
|
||||||
///
|
///It is recommended for performance and memory use to share btCollisionShape objects whenever possible.
|
||||||
|
///There are 3 types of rigid bodies:
|
||||||
|
///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics.
|
||||||
|
///- B) Fixed objects with zero mass. They are not moving (basically collision objects)
|
||||||
|
///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform.
|
||||||
|
///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time.
|
||||||
|
///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects)
|
||||||
class btRigidBody : public btCollisionObject
|
class btRigidBody : public btCollisionObject
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -54,9 +56,15 @@ class btRigidBody : public btCollisionObject
|
|||||||
btScalar m_linearDamping;
|
btScalar m_linearDamping;
|
||||||
btScalar m_angularDamping;
|
btScalar m_angularDamping;
|
||||||
|
|
||||||
|
bool m_additionalDamping;
|
||||||
|
btScalar m_additionalDampingFactor;
|
||||||
|
btScalar m_additionalLinearDampingThresholdSqr;
|
||||||
|
btScalar m_additionalAngularDampingThresholdSqr;
|
||||||
|
btScalar m_additionalAngularDampingFactor;
|
||||||
|
|
||||||
|
|
||||||
btScalar m_linearSleepingThreshold;
|
btScalar m_linearSleepingThreshold;
|
||||||
btScalar m_angularSleepingThreshold;
|
btScalar m_angularSleepingThreshold;
|
||||||
|
|
||||||
|
|
||||||
//m_optionalMotionState allows to automatic synchronize the world transform for active objects
|
//m_optionalMotionState allows to automatic synchronize the world transform for active objects
|
||||||
btMotionState* m_optionalMotionState;
|
btMotionState* m_optionalMotionState;
|
||||||
@ -66,20 +74,85 @@ class btRigidBody : public btCollisionObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#ifdef OBSOLETE_MOTIONSTATE_LESS
|
|
||||||
//not supported, please use btMotionState
|
|
||||||
btRigidBody(btScalar mass, const btTransform& worldTransform, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.));
|
|
||||||
#endif //OBSOLETE_MOTIONSTATE_LESS
|
|
||||||
|
|
||||||
btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.));
|
///btRigidBodyConstructionInfo provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body.
|
||||||
|
///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument)
|
||||||
|
///You can use the motion state to synchronize the world transform between physics and graphics objects.
|
||||||
|
///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state,
|
||||||
|
///m_startWorldTransform is only used when you don't provide a motion state.
|
||||||
|
struct btRigidBodyConstructionInfo
|
||||||
|
{
|
||||||
|
btScalar m_mass;
|
||||||
|
|
||||||
virtual ~btRigidBody()
|
///When a motionState is provided, the rigid body will initialize its world transform from the motion state
|
||||||
|
///In this case, m_startWorldTransform is ignored.
|
||||||
|
btMotionState* m_motionState;
|
||||||
|
btTransform m_startWorldTransform;
|
||||||
|
|
||||||
|
btCollisionShape* m_collisionShape;
|
||||||
|
btVector3 m_localInertia;
|
||||||
|
btScalar m_linearDamping;
|
||||||
|
btScalar m_angularDamping;
|
||||||
|
|
||||||
|
///best simulation results when friction is non-zero
|
||||||
|
btScalar m_friction;
|
||||||
|
///best simulation results using zero restitution.
|
||||||
|
btScalar m_restitution;
|
||||||
|
|
||||||
|
btScalar m_linearSleepingThreshold;
|
||||||
|
btScalar m_angularSleepingThreshold;
|
||||||
|
|
||||||
|
//Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
|
||||||
|
//Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
|
||||||
|
bool m_additionalDamping;
|
||||||
|
btScalar m_additionalDampingFactor;
|
||||||
|
btScalar m_additionalLinearDampingThresholdSqr;
|
||||||
|
btScalar m_additionalAngularDampingThresholdSqr;
|
||||||
|
btScalar m_additionalAngularDampingFactor;
|
||||||
|
|
||||||
|
|
||||||
|
btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)):
|
||||||
|
m_mass(mass),
|
||||||
|
m_motionState(motionState),
|
||||||
|
m_collisionShape(collisionShape),
|
||||||
|
m_localInertia(localInertia),
|
||||||
|
m_linearDamping(btScalar(0.)),
|
||||||
|
m_angularDamping(btScalar(0.)),
|
||||||
|
m_friction(btScalar(0.5)),
|
||||||
|
m_restitution(btScalar(0.)),
|
||||||
|
m_linearSleepingThreshold(btScalar(0.8)),
|
||||||
|
m_angularSleepingThreshold(btScalar(1.f)),
|
||||||
|
m_additionalDamping(false),
|
||||||
|
m_additionalDampingFactor(btScalar(0.005)),
|
||||||
|
m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
|
||||||
|
m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
|
||||||
|
m_additionalAngularDampingFactor(btScalar(0.01))
|
||||||
|
{
|
||||||
|
m_startWorldTransform.setIdentity();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
///btRigidBody constructor using construction info
|
||||||
|
btRigidBody( const btRigidBodyConstructionInfo& constructionInfo);
|
||||||
|
|
||||||
|
///btRigidBody constructor for backwards compatibility.
|
||||||
|
///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo)
|
||||||
|
btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0));
|
||||||
|
|
||||||
|
|
||||||
|
virtual ~btRigidBody()
|
||||||
{
|
{
|
||||||
//No constraints should point to this rigidbody
|
//No constraints should point to this rigidbody
|
||||||
//Remove constraints from the dynamics world before you delete the related rigidbodies.
|
//Remove constraints from the dynamics world before you delete the related rigidbodies.
|
||||||
btAssert(m_constraintRefs.size()==0);
|
btAssert(m_constraintRefs.size()==0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
///setupRigidBody is only used internally by the constructor
|
||||||
|
void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
void proceedToTransform(const btTransform& newTrans);
|
void proceedToTransform(const btTransform& newTrans);
|
||||||
|
|
||||||
@ -99,8 +172,7 @@ public:
|
|||||||
|
|
||||||
void saveKinematicState(btScalar step);
|
void saveKinematicState(btScalar step);
|
||||||
|
|
||||||
|
void applyGravity();
|
||||||
void applyForces(btScalar step);
|
|
||||||
|
|
||||||
void setGravity(const btVector3& acceleration);
|
void setGravity(const btVector3& acceleration);
|
||||||
|
|
||||||
@ -110,7 +182,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setDamping(btScalar lin_damping, btScalar ang_damping);
|
void setDamping(btScalar lin_damping, btScalar ang_damping);
|
||||||
|
|
||||||
|
void applyDamping(btScalar timeStep);
|
||||||
|
|
||||||
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const {
|
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const {
|
||||||
return m_collisionShape;
|
return m_collisionShape;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadpha
|
|||||||
:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
|
:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
|
||||||
m_constraintSolver(constraintSolver),
|
m_constraintSolver(constraintSolver),
|
||||||
m_ownsConstraintSolver(false),
|
m_ownsConstraintSolver(false),
|
||||||
m_debugDrawer(0),
|
|
||||||
m_gravity(0,0,-10)
|
m_gravity(0,0,-10)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -86,10 +85,27 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b
|
|||||||
|
|
||||||
synchronizeMotionStates();
|
synchronizeMotionStates();
|
||||||
|
|
||||||
|
clearForces();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void btSimpleDynamicsWorld::clearForces()
|
||||||
|
{
|
||||||
|
//todo: iterate over awake simulation islands!
|
||||||
|
for ( int i=0;i<m_collisionObjects.size();i++)
|
||||||
|
{
|
||||||
|
btCollisionObject* colObj = m_collisionObjects[i];
|
||||||
|
|
||||||
|
btRigidBody* body = btRigidBody::upcast(colObj);
|
||||||
|
if (body)
|
||||||
|
{
|
||||||
|
body->clearForces();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
|
void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
|
||||||
{
|
{
|
||||||
@ -172,8 +188,9 @@ void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
|
|||||||
{
|
{
|
||||||
if (body->isActive())
|
if (body->isActive())
|
||||||
{
|
{
|
||||||
body->applyForces( timeStep);
|
body->applyGravity();
|
||||||
body->integrateVelocities( timeStep);
|
body->integrateVelocities( timeStep);
|
||||||
|
body->applyDamping(timeStep);
|
||||||
body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
|
body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,6 @@ protected:
|
|||||||
|
|
||||||
bool m_ownsConstraintSolver;
|
bool m_ownsConstraintSolver;
|
||||||
|
|
||||||
btIDebugDraw* m_debugDrawer;
|
|
||||||
|
|
||||||
void predictUnconstraintMotion(btScalar timeStep);
|
void predictUnconstraintMotion(btScalar timeStep);
|
||||||
|
|
||||||
void integrateTransforms(btScalar timeStep);
|
void integrateTransforms(btScalar timeStep);
|
||||||
@ -52,16 +50,6 @@ public:
|
|||||||
///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead
|
///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead
|
||||||
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
|
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
|
||||||
|
|
||||||
virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
|
|
||||||
{
|
|
||||||
m_debugDrawer = debugDrawer;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual btIDebugDraw* getDebugDrawer()
|
|
||||||
{
|
|
||||||
return m_debugDrawer;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setGravity(const btVector3& gravity);
|
virtual void setGravity(const btVector3& gravity);
|
||||||
|
|
||||||
virtual void addRigidBody(btRigidBody* body);
|
virtual void addRigidBody(btRigidBody* body);
|
||||||
@ -81,6 +69,8 @@ public:
|
|||||||
return BT_SIMPLE_DYNAMICS_WORLD;
|
return BT_SIMPLE_DYNAMICS_WORLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void clearForces();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //BT_SIMPLE_DYNAMICS_WORLD_H
|
#endif //BT_SIMPLE_DYNAMICS_WORLD_H
|
||||||
|
@ -23,8 +23,6 @@
|
|||||||
|
|
||||||
#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
|
#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static btRigidBody s_fixedObject( 0,0,0);
|
static btRigidBody s_fixedObject( 0,0,0);
|
||||||
|
|
||||||
btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster )
|
btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster )
|
||||||
@ -526,15 +524,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
|
|||||||
if (!numWheel)
|
if (!numWheel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_forwardWS.resize(numWheel);
|
||||||
void* mem = btAlignedAlloc(numWheel*sizeof(btVector3),16);
|
m_axle.resize(numWheel);
|
||||||
btVector3* forwardWS = new (mem)btVector3[numWheel];
|
m_forwardImpulse.resize(numWheel);
|
||||||
mem = btAlignedAlloc(numWheel*sizeof(btVector3),16);
|
m_sideImpulse.resize(numWheel);
|
||||||
btVector3* axle = new (mem)btVector3[numWheel];
|
|
||||||
mem = btAlignedAlloc(numWheel*sizeof(btScalar),16);
|
|
||||||
btScalar* forwardImpulse = new (mem)btScalar[numWheel];
|
|
||||||
mem = btAlignedAlloc(numWheel*sizeof(btScalar),16);
|
|
||||||
btScalar* sideImpulse = new(mem) btScalar[numWheel];
|
|
||||||
|
|
||||||
int numWheelsOnGround = 0;
|
int numWheelsOnGround = 0;
|
||||||
|
|
||||||
@ -546,8 +539,8 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
|
|||||||
class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
|
class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
|
||||||
if (groundObject)
|
if (groundObject)
|
||||||
numWheelsOnGround++;
|
numWheelsOnGround++;
|
||||||
sideImpulse[i] = btScalar(0.);
|
m_sideImpulse[i] = btScalar(0.);
|
||||||
forwardImpulse[i] = btScalar(0.);
|
m_forwardImpulse[i] = btScalar(0.);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,25 +559,25 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
|
|||||||
const btTransform& wheelTrans = getWheelTransformWS( i );
|
const btTransform& wheelTrans = getWheelTransformWS( i );
|
||||||
|
|
||||||
btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
|
btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
|
||||||
axle[i] = btVector3(
|
m_axle[i] = btVector3(
|
||||||
wheelBasis0[0][m_indexRightAxis],
|
wheelBasis0[0][m_indexRightAxis],
|
||||||
wheelBasis0[1][m_indexRightAxis],
|
wheelBasis0[1][m_indexRightAxis],
|
||||||
wheelBasis0[2][m_indexRightAxis]);
|
wheelBasis0[2][m_indexRightAxis]);
|
||||||
|
|
||||||
const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
|
const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
|
||||||
btScalar proj = axle[i].dot(surfNormalWS);
|
btScalar proj = m_axle[i].dot(surfNormalWS);
|
||||||
axle[i] -= surfNormalWS * proj;
|
m_axle[i] -= surfNormalWS * proj;
|
||||||
axle[i] = axle[i].normalize();
|
m_axle[i] = m_axle[i].normalize();
|
||||||
|
|
||||||
forwardWS[i] = surfNormalWS.cross(axle[i]);
|
m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
|
||||||
forwardWS[i].normalize();
|
m_forwardWS[i].normalize();
|
||||||
|
|
||||||
|
|
||||||
resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS,
|
resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS,
|
||||||
*groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
|
*groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
|
||||||
btScalar(0.), axle[i],sideImpulse[i],timeStep);
|
btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep);
|
||||||
|
|
||||||
sideImpulse[i] *= sideFrictionStiffness2;
|
m_sideImpulse[i] *= sideFrictionStiffness2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,7 +606,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
|
|||||||
{
|
{
|
||||||
btScalar defaultRollingFrictionImpulse = 0.f;
|
btScalar defaultRollingFrictionImpulse = 0.f;
|
||||||
btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
|
btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
|
||||||
btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,forwardWS[wheel],maxImpulse);
|
btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
|
||||||
rollingFriction = calcRollingFriction(contactPt);
|
rollingFriction = calcRollingFriction(contactPt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -623,7 +616,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
forwardImpulse[wheel] = btScalar(0.);
|
m_forwardImpulse[wheel] = btScalar(0.);
|
||||||
m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
|
m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
|
||||||
|
|
||||||
if (groundObject)
|
if (groundObject)
|
||||||
@ -636,10 +629,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
|
|||||||
btScalar maximpSquared = maximp * maximpSide;
|
btScalar maximpSquared = maximp * maximpSide;
|
||||||
|
|
||||||
|
|
||||||
forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
|
m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
|
||||||
|
|
||||||
btScalar x = (forwardImpulse[wheel] ) * fwdFactor;
|
btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
|
||||||
btScalar y = (sideImpulse[wheel] ) * sideFactor;
|
btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
|
||||||
|
|
||||||
btScalar impulseSquared = (x*x + y*y);
|
btScalar impulseSquared = (x*x + y*y);
|
||||||
|
|
||||||
@ -663,12 +656,12 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
|
|||||||
{
|
{
|
||||||
for (int wheel = 0;wheel < getNumWheels(); wheel++)
|
for (int wheel = 0;wheel < getNumWheels(); wheel++)
|
||||||
{
|
{
|
||||||
if (sideImpulse[wheel] != btScalar(0.))
|
if (m_sideImpulse[wheel] != btScalar(0.))
|
||||||
{
|
{
|
||||||
if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.))
|
if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.))
|
||||||
{
|
{
|
||||||
forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
|
m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
|
||||||
sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
|
m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -683,11 +676,11 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
|
|||||||
btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
|
btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
|
||||||
m_chassisBody->getCenterOfMassPosition();
|
m_chassisBody->getCenterOfMassPosition();
|
||||||
|
|
||||||
if (forwardImpulse[wheel] != btScalar(0.))
|
if (m_forwardImpulse[wheel] != btScalar(0.))
|
||||||
{
|
{
|
||||||
m_chassisBody->applyImpulse(forwardWS[wheel]*(forwardImpulse[wheel]),rel_pos);
|
m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos);
|
||||||
}
|
}
|
||||||
if (sideImpulse[wheel] != btScalar(0.))
|
if (m_sideImpulse[wheel] != btScalar(0.))
|
||||||
{
|
{
|
||||||
class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
|
class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
|
||||||
|
|
||||||
@ -695,7 +688,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
|
|||||||
groundObject->getCenterOfMassPosition();
|
groundObject->getCenterOfMassPosition();
|
||||||
|
|
||||||
|
|
||||||
btVector3 sideImp = axle[wheel] * sideImpulse[wheel];
|
btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
|
||||||
|
|
||||||
rel_pos[2] *= wheelInfo.m_rollInfluence;
|
rel_pos[2] *= wheelInfo.m_rollInfluence;
|
||||||
m_chassisBody->applyImpulse(sideImp,rel_pos);
|
m_chassisBody->applyImpulse(sideImp,rel_pos);
|
||||||
@ -706,10 +699,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btAlignedFree(forwardWS);
|
|
||||||
btAlignedFree(axle);
|
|
||||||
btAlignedFree(forwardImpulse);
|
|
||||||
btAlignedFree(sideImpulse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,6 +23,12 @@ class btVehicleTuning;
|
|||||||
///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle.
|
///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle.
|
||||||
class btRaycastVehicle : public btTypedConstraint
|
class btRaycastVehicle : public btTypedConstraint
|
||||||
{
|
{
|
||||||
|
|
||||||
|
btAlignedObjectArray<btVector3> m_forwardWS;
|
||||||
|
btAlignedObjectArray<btVector3> m_axle;
|
||||||
|
btAlignedObjectArray<btScalar> m_forwardImpulse;
|
||||||
|
btAlignedObjectArray<btScalar> m_sideImpulse;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class btVehicleTuning
|
class btVehicleTuning
|
||||||
{
|
{
|
||||||
@ -114,7 +120,7 @@ public:
|
|||||||
|
|
||||||
void updateSuspension(btScalar deltaTime);
|
void updateSuspension(btScalar deltaTime);
|
||||||
|
|
||||||
void updateFriction(btScalar timeStep);
|
virtual void updateFriction(btScalar timeStep);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,7 +20,14 @@ subject to the following restrictions:
|
|||||||
#include "btVector3.h"
|
#include "btVector3.h"
|
||||||
#include "btMinMax.h"
|
#include "btMinMax.h"
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin,
|
||||||
|
btVector3& aabbMax,
|
||||||
|
const btVector3& expansionMin,
|
||||||
|
const btVector3& expansionMax)
|
||||||
|
{
|
||||||
|
aabbMin = aabbMin + expansionMin;
|
||||||
|
aabbMax = aabbMax + expansionMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// conservative test for overlap between two aabbs
|
/// conservative test for overlap between two aabbs
|
||||||
@ -65,6 +72,41 @@ SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
|
||||||
|
const btVector3& rayInvDirection,
|
||||||
|
const unsigned int raySign[3],
|
||||||
|
const btVector3 bounds[2],
|
||||||
|
btScalar& tmin,
|
||||||
|
btScalar lambda_min,
|
||||||
|
btScalar lambda_max)
|
||||||
|
{
|
||||||
|
btScalar tmax, tymin, tymax, tzmin, tzmax;
|
||||||
|
tmin = (bounds[raySign[0]][0] - rayFrom[0]) * rayInvDirection[0];
|
||||||
|
tmax = (bounds[1-raySign[0]][0] - rayFrom[0]) * rayInvDirection[0];
|
||||||
|
tymin = (bounds[raySign[1]][1] - rayFrom[1]) * rayInvDirection[1];
|
||||||
|
tymax = (bounds[1-raySign[1]][1] - rayFrom[1]) * rayInvDirection[1];
|
||||||
|
|
||||||
|
if ( (tmin > tymax) || (tymin > tmax) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (tymin > tmin)
|
||||||
|
tmin = tymin;
|
||||||
|
|
||||||
|
if (tymax < tmax)
|
||||||
|
tmax = tymax;
|
||||||
|
|
||||||
|
tzmin = (bounds[raySign[2]][2] - rayFrom[2]) * rayInvDirection[2];
|
||||||
|
tzmax = (bounds[1-raySign[2]][2] - rayFrom[2]) * rayInvDirection[2];
|
||||||
|
|
||||||
|
if ( (tmin > tzmax) || (tzmin > tmax) )
|
||||||
|
return false;
|
||||||
|
if (tzmin > tmin)
|
||||||
|
tmin = tzmin;
|
||||||
|
if (tzmax < tmax)
|
||||||
|
tmax = tzmax;
|
||||||
|
return ( (tmin < lambda_max) && (tmax > lambda_min) );
|
||||||
|
}
|
||||||
|
|
||||||
SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
|
SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
|
||||||
const btVector3& rayTo,
|
const btVector3& rayTo,
|
||||||
const btVector3& aabbMin,
|
const btVector3& aabbMin,
|
||||||
@ -123,3 +165,4 @@ SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filen
|
|||||||
gTotalBytesAlignedAllocs += size;
|
gTotalBytesAlignedAllocs += size;
|
||||||
gNumAlignedAllocs++;
|
gNumAlignedAllocs++;
|
||||||
|
|
||||||
printf("allocation#%d from %s,line %d, size %d\n",gNumAlignedAllocs,filename,line,size);
|
|
||||||
real = (char *)malloc(size + 2*sizeof(void *) + (alignment-1));
|
real = (char *)malloc(size + 2*sizeof(void *) + (alignment-1));
|
||||||
if (real) {
|
if (real) {
|
||||||
offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) &
|
offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) &
|
||||||
@ -44,6 +44,9 @@ void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filen
|
|||||||
} else {
|
} else {
|
||||||
ret = (void *)(real);//??
|
ret = (void *)(real);//??
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size);
|
||||||
|
|
||||||
int* ptr = (int*)ret;
|
int* ptr = (int*)ret;
|
||||||
*ptr = 12;
|
*ptr = 12;
|
||||||
return (ret);
|
return (ret);
|
||||||
@ -60,7 +63,7 @@ void btAlignedFreeInternal (void* ptr,int line,char* filename)
|
|||||||
int size = *((int*)(ptr)-2);
|
int size = *((int*)(ptr)-2);
|
||||||
gTotalBytesAlignedAllocs -= size;
|
gTotalBytesAlignedAllocs -= size;
|
||||||
|
|
||||||
printf("free #%d from %s,line %d, size %d\n",gNumAlignedFree,filename,line,size);
|
printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size);
|
||||||
|
|
||||||
free(real);
|
free(real);
|
||||||
} else
|
} else
|
||||||
|
@ -77,7 +77,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free(void* ptr)
|
void freeMemory(void* ptr)
|
||||||
{
|
{
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
|
btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
|
||||||
|
@ -1,38 +1,268 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2006 Tyler Streeter
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied warranty.
|
/***************************************************************************************************
|
||||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
**
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
** profile.cpp
|
||||||
including commercial applications, and to alter it and redistribute it freely,
|
**
|
||||||
subject to the following restrictions:
|
** Real-Time Hierarchical Profiling for Game Programming Gems 3
|
||||||
|
**
|
||||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
** by Greg Hjelstrom & Byon Garrabrant
|
||||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
**
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
***************************************************************************************************/
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Please visit the project website (http://quickprof.sourceforge.net)
|
|
||||||
// for usage instructions.
|
|
||||||
|
|
||||||
// Credits: The Clock class was inspired by the Timer classes in
|
// Credits: The Clock class was inspired by the Timer classes in
|
||||||
// Ogre (www.ogre3d.org).
|
// Ogre (www.ogre3d.org).
|
||||||
|
|
||||||
#include "LinearMath/btQuickprof.h"
|
#include "LinearMath/btQuickprof.h"
|
||||||
|
|
||||||
#ifdef USE_QUICKPROF
|
static btClock gProfileClock;
|
||||||
|
|
||||||
|
inline void Profile_Get_Ticks(unsigned long int * ticks)
|
||||||
|
{
|
||||||
|
*ticks = gProfileClock.getTimeMicroseconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float Profile_Get_Tick_Rate(void)
|
||||||
|
{
|
||||||
|
// return 1000000.f;
|
||||||
|
return 1000.f;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
**
|
||||||
|
** CProfileNode
|
||||||
|
**
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************************************
|
||||||
|
* INPUT: *
|
||||||
|
* name - pointer to a static string which is the name of this profile node *
|
||||||
|
* parent - parent pointer *
|
||||||
|
* *
|
||||||
|
* WARNINGS: *
|
||||||
|
* The name is assumed to be a static pointer, only the pointer is stored and compared for *
|
||||||
|
* efficiency reasons. *
|
||||||
|
*=============================================================================================*/
|
||||||
|
CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
|
||||||
|
Name( name ),
|
||||||
|
TotalCalls( 0 ),
|
||||||
|
TotalTime( 0 ),
|
||||||
|
StartTime( 0 ),
|
||||||
|
RecursionCounter( 0 ),
|
||||||
|
Parent( parent ),
|
||||||
|
Child( NULL ),
|
||||||
|
Sibling( NULL )
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CProfileNode::~CProfileNode( void )
|
||||||
|
{
|
||||||
|
delete Child;
|
||||||
|
delete Sibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************************************
|
||||||
|
* INPUT: *
|
||||||
|
* name - static string pointer to the name of the node we are searching for *
|
||||||
|
* *
|
||||||
|
* WARNINGS: *
|
||||||
|
* All profile names are assumed to be static strings so this function uses pointer compares *
|
||||||
|
* to find the named node. *
|
||||||
|
*=============================================================================================*/
|
||||||
|
CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
|
||||||
|
{
|
||||||
|
// Try to find this sub node
|
||||||
|
CProfileNode * child = Child;
|
||||||
|
while ( child ) {
|
||||||
|
if ( child->Name == name ) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
child = child->Sibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We didn't find it, so add it
|
||||||
|
CProfileNode * node = new CProfileNode( name, this );
|
||||||
|
node->Sibling = Child;
|
||||||
|
Child = node;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CProfileNode::Reset( void )
|
||||||
|
{
|
||||||
|
TotalCalls = 0;
|
||||||
|
TotalTime = 0.0f;
|
||||||
|
gProfileClock.reset();
|
||||||
|
|
||||||
|
if ( Child ) {
|
||||||
|
Child->Reset();
|
||||||
|
}
|
||||||
|
if ( Sibling ) {
|
||||||
|
Sibling->Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CProfileNode::Call( void )
|
||||||
|
{
|
||||||
|
TotalCalls++;
|
||||||
|
if (RecursionCounter++ == 0) {
|
||||||
|
Profile_Get_Ticks(&StartTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CProfileNode::Return( void )
|
||||||
|
{
|
||||||
|
if ( --RecursionCounter == 0 && TotalCalls != 0 ) {
|
||||||
|
unsigned long int time;
|
||||||
|
Profile_Get_Ticks(&time);
|
||||||
|
time-=StartTime;
|
||||||
|
TotalTime += (float)time / Profile_Get_Tick_Rate();
|
||||||
|
}
|
||||||
|
return ( RecursionCounter == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
**
|
||||||
|
** CProfileIterator
|
||||||
|
**
|
||||||
|
***************************************************************************************************/
|
||||||
|
CProfileIterator::CProfileIterator( CProfileNode * start )
|
||||||
|
{
|
||||||
|
CurrentParent = start;
|
||||||
|
CurrentChild = CurrentParent->Get_Child();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CProfileIterator::First(void)
|
||||||
|
{
|
||||||
|
CurrentChild = CurrentParent->Get_Child();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CProfileIterator::Next(void)
|
||||||
|
{
|
||||||
|
CurrentChild = CurrentChild->Get_Sibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CProfileIterator::Is_Done(void)
|
||||||
|
{
|
||||||
|
return CurrentChild == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CProfileIterator::Enter_Child( int index )
|
||||||
|
{
|
||||||
|
CurrentChild = CurrentParent->Get_Child();
|
||||||
|
while ( (CurrentChild != NULL) && (index != 0) ) {
|
||||||
|
index--;
|
||||||
|
CurrentChild = CurrentChild->Get_Sibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( CurrentChild != NULL ) {
|
||||||
|
CurrentParent = CurrentChild;
|
||||||
|
CurrentChild = CurrentParent->Get_Child();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CProfileIterator::Enter_Parent( void )
|
||||||
|
{
|
||||||
|
if ( CurrentParent->Get_Parent() != NULL ) {
|
||||||
|
CurrentParent = CurrentParent->Get_Parent();
|
||||||
|
}
|
||||||
|
CurrentChild = CurrentParent->Get_Child();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
**
|
||||||
|
** CProfileManager
|
||||||
|
**
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
CProfileNode CProfileManager::Root( "Root", NULL );
|
||||||
|
CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root;
|
||||||
|
int CProfileManager::FrameCounter = 0;
|
||||||
|
unsigned long int CProfileManager::ResetTime = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************************************
|
||||||
|
* CProfileManager::Start_Profile -- Begin a named profile *
|
||||||
|
* *
|
||||||
|
* Steps one level deeper into the tree, if a child already exists with the specified name *
|
||||||
|
* then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
|
||||||
|
* *
|
||||||
|
* INPUT: *
|
||||||
|
* name - name of this profiling record *
|
||||||
|
* *
|
||||||
|
* WARNINGS: *
|
||||||
|
* The string used is assumed to be a static string; pointer compares are used throughout *
|
||||||
|
* the profiling code for efficiency. *
|
||||||
|
*=============================================================================================*/
|
||||||
|
void CProfileManager::Start_Profile( const char * name )
|
||||||
|
{
|
||||||
|
if (name != CurrentNode->Get_Name()) {
|
||||||
|
CurrentNode = CurrentNode->Get_Sub_Node( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentNode->Call();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************************************
|
||||||
|
* CProfileManager::Stop_Profile -- Stop timing and record the results. *
|
||||||
|
*=============================================================================================*/
|
||||||
|
void CProfileManager::Stop_Profile( void )
|
||||||
|
{
|
||||||
|
// Return will indicate whether we should back up to our parent (we may
|
||||||
|
// be profiling a recursive function)
|
||||||
|
if (CurrentNode->Return()) {
|
||||||
|
CurrentNode = CurrentNode->Get_Parent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************************************
|
||||||
|
* CProfileManager::Reset -- Reset the contents of the profiling system *
|
||||||
|
* *
|
||||||
|
* This resets everything except for the tree structure. All of the timing data is reset. *
|
||||||
|
*=============================================================================================*/
|
||||||
|
void CProfileManager::Reset( void )
|
||||||
|
{
|
||||||
|
Root.Reset();
|
||||||
|
Root.Call();
|
||||||
|
FrameCounter = 0;
|
||||||
|
Profile_Get_Ticks(&ResetTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************************************
|
||||||
|
* CProfileManager::Increment_Frame_Counter -- Increment the frame counter *
|
||||||
|
*=============================================================================================*/
|
||||||
|
void CProfileManager::Increment_Frame_Counter( void )
|
||||||
|
{
|
||||||
|
FrameCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************************************
|
||||||
|
* CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
|
||||||
|
*=============================================================================================*/
|
||||||
|
float CProfileManager::Get_Time_Since_Reset( void )
|
||||||
|
{
|
||||||
|
unsigned long int time;
|
||||||
|
Profile_Get_Ticks(&time);
|
||||||
|
time -= ResetTime;
|
||||||
|
return (float)time / Profile_Get_Tick_Rate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Note: We must declare these private static variables again here to
|
|
||||||
// avoid link errors.
|
|
||||||
bool btProfiler::mEnabled = false;
|
|
||||||
btClock btProfiler::mClock;
|
|
||||||
unsigned long int btProfiler::mCurrentCycleStartMicroseconds = 0;
|
|
||||||
unsigned long int btProfiler::mLastCycleDurationMicroseconds = 0;
|
|
||||||
std::map<std::string, hidden::ProfileBlock*> btProfiler::mProfileBlocks;
|
|
||||||
std::ofstream btProfiler::mOutputFile;
|
|
||||||
bool btProfiler::mFirstFileOutput = true;
|
|
||||||
btProfiler::BlockTimingMethod btProfiler::mFileOutputMethod;
|
|
||||||
unsigned long int btProfiler::mCycleNumber = 0;
|
|
||||||
#endif //USE_QUICKPROF
|
|
||||||
|
@ -1,20 +1,11 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2006 Tyler Streeter
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied warranty.
|
|
||||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it freely,
|
|
||||||
subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Please visit the project website (http://quickprof.sourceforge.net)
|
/***************************************************************************************************
|
||||||
// for usage instructions.
|
**
|
||||||
|
** Real-Time Hierarchical Profiling for Game Programming Gems 3
|
||||||
|
**
|
||||||
|
** by Greg Hjelstrom & Byon Garrabrant
|
||||||
|
**
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
// Credits: The Clock class was inspired by the Timer classes in
|
// Credits: The Clock class was inspired by the Timer classes in
|
||||||
// Ogre (www.ogre3d.org).
|
// Ogre (www.ogre3d.org).
|
||||||
@ -24,8 +15,8 @@ subject to the following restrictions:
|
|||||||
|
|
||||||
#include "btScalar.h"
|
#include "btScalar.h"
|
||||||
|
|
||||||
//#define USE_QUICKPROF 1
|
//To disable built-in profiling, please comment out next line
|
||||||
//Don't use quickprof for now, because it contains STL. TODO: replace STL by Bullet container classes.
|
//#define BT_NO_PROFILE 1
|
||||||
|
|
||||||
|
|
||||||
//if you don't need btClock, you can comment next line
|
//if you don't need btClock, you can comment next line
|
||||||
@ -235,477 +226,129 @@ class btClock
|
|||||||
#endif //USE_BT_CLOCK
|
#endif //USE_BT_CLOCK
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_QUICKPROF
|
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
/*
|
||||||
#include <fstream>
|
** A node in the Profile Hierarchy Tree
|
||||||
#include <string>
|
*/
|
||||||
#include <map>
|
class CProfileNode {
|
||||||
|
|
||||||
|
public:
|
||||||
|
CProfileNode( const char * name, CProfileNode * parent );
|
||||||
|
~CProfileNode( void );
|
||||||
|
|
||||||
|
CProfileNode * Get_Sub_Node( const char * name );
|
||||||
|
|
||||||
|
CProfileNode * Get_Parent( void ) { return Parent; }
|
||||||
|
CProfileNode * Get_Sibling( void ) { return Sibling; }
|
||||||
|
CProfileNode * Get_Child( void ) { return Child; }
|
||||||
|
|
||||||
namespace hidden
|
void Reset( void );
|
||||||
{
|
void Call( void );
|
||||||
/// A simple data structure representing a single timed block
|
bool Return( void );
|
||||||
/// of code.
|
|
||||||
struct ProfileBlock
|
|
||||||
{
|
|
||||||
ProfileBlock()
|
|
||||||
{
|
|
||||||
currentBlockStartMicroseconds = 0;
|
|
||||||
currentCycleTotalMicroseconds = 0;
|
|
||||||
lastCycleTotalMicroseconds = 0;
|
|
||||||
totalMicroseconds = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The starting time (in us) of the current block update.
|
const char * Get_Name( void ) { return Name; }
|
||||||
unsigned long int currentBlockStartMicroseconds;
|
int Get_Total_Calls( void ) { return TotalCalls; }
|
||||||
|
float Get_Total_Time( void ) { return TotalTime; }
|
||||||
|
|
||||||
/// The accumulated time (in us) spent in this block during the
|
protected:
|
||||||
/// current profiling cycle.
|
|
||||||
unsigned long int currentCycleTotalMicroseconds;
|
|
||||||
|
|
||||||
/// The accumulated time (in us) spent in this block during the
|
const char * Name;
|
||||||
/// past profiling cycle.
|
int TotalCalls;
|
||||||
unsigned long int lastCycleTotalMicroseconds;
|
float TotalTime;
|
||||||
|
unsigned long int StartTime;
|
||||||
/// The total accumulated time (in us) spent in this block.
|
int RecursionCounter;
|
||||||
unsigned long int totalMicroseconds;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
CProfileNode * Parent;
|
||||||
|
CProfileNode * Child;
|
||||||
|
CProfileNode * Sibling;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A static class that manages timing for a set of profiling blocks.
|
/*
|
||||||
class btProfiler
|
** An iterator to navigate through the tree
|
||||||
|
*/
|
||||||
|
class CProfileIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// A set of ways to retrieve block timing data.
|
// Access all the children of the current parent
|
||||||
enum BlockTimingMethod
|
void First(void);
|
||||||
{
|
void Next(void);
|
||||||
/// The total time spent in the block (in seconds) since the
|
bool Is_Done(void);
|
||||||
/// profiler was initialized.
|
bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
|
||||||
BLOCK_TOTAL_SECONDS,
|
|
||||||
|
|
||||||
/// The total time spent in the block (in ms) since the
|
void Enter_Child( int index ); // Make the given child the new parent
|
||||||
/// profiler was initialized.
|
void Enter_Largest_Child( void ); // Make the largest child the new parent
|
||||||
BLOCK_TOTAL_MILLISECONDS,
|
void Enter_Parent( void ); // Make the current parent's parent the new parent
|
||||||
|
|
||||||
/// The total time spent in the block (in us) since the
|
// Access the current child
|
||||||
/// profiler was initialized.
|
const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); }
|
||||||
BLOCK_TOTAL_MICROSECONDS,
|
int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
|
||||||
|
float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
|
||||||
|
|
||||||
/// The total time spent in the block, as a % of the total
|
// Access the current parent
|
||||||
/// elapsed time since the profiler was initialized.
|
const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
|
||||||
BLOCK_TOTAL_PERCENT,
|
int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
|
||||||
|
float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
|
||||||
|
|
||||||
/// The time spent in the block (in seconds) in the most recent
|
protected:
|
||||||
/// profiling cycle.
|
|
||||||
BLOCK_CYCLE_SECONDS,
|
|
||||||
|
|
||||||
/// The time spent in the block (in ms) in the most recent
|
CProfileNode * CurrentParent;
|
||||||
/// profiling cycle.
|
CProfileNode * CurrentChild;
|
||||||
BLOCK_CYCLE_MILLISECONDS,
|
|
||||||
|
|
||||||
/// The time spent in the block (in us) in the most recent
|
CProfileIterator( CProfileNode * start );
|
||||||
/// profiling cycle.
|
friend class CProfileManager;
|
||||||
BLOCK_CYCLE_MICROSECONDS,
|
|
||||||
|
|
||||||
/// The time spent in the block (in seconds) in the most recent
|
|
||||||
/// profiling cycle, as a % of the total cycle time.
|
|
||||||
BLOCK_CYCLE_PERCENT
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Initializes the profiler. This must be called first. If this is
|
|
||||||
/// never called, the profiler is effectively disabled; all other
|
|
||||||
/// functions will return immediately. The first parameter
|
|
||||||
/// is the name of an output data file; if this string is not empty,
|
|
||||||
/// data will be saved on every profiling cycle; if this string is
|
|
||||||
/// empty, no data will be saved to a file. The second parameter
|
|
||||||
/// determines which timing method is used when printing data to the
|
|
||||||
/// output file.
|
|
||||||
inline static void init(const std::string outputFilename="",
|
|
||||||
BlockTimingMethod outputMethod=BLOCK_CYCLE_MILLISECONDS);
|
|
||||||
|
|
||||||
/// Cleans up allocated memory.
|
|
||||||
inline static void destroy();
|
|
||||||
|
|
||||||
/// Begins timing the named block of code.
|
|
||||||
inline static void beginBlock(const std::string& name);
|
|
||||||
|
|
||||||
/// Updates the accumulated time spent in the named block by adding
|
|
||||||
/// the elapsed time since the last call to startBlock for this block
|
|
||||||
/// name.
|
|
||||||
inline static void endBlock(const std::string& name);
|
|
||||||
|
|
||||||
/// Returns the time spent in the named block according to the
|
|
||||||
/// given timing method. See comments on BlockTimingMethod for details.
|
|
||||||
inline static double getBlockTime(const std::string& name,
|
|
||||||
BlockTimingMethod method=BLOCK_CYCLE_MILLISECONDS);
|
|
||||||
|
|
||||||
/// Defines the end of a profiling cycle. Use this regularly if you
|
|
||||||
/// want to generate detailed timing information. This must not be
|
|
||||||
/// called within a timing block.
|
|
||||||
inline static void endProfilingCycle();
|
|
||||||
|
|
||||||
/// A helper function that creates a string of statistics for
|
|
||||||
/// each timing block. This is mainly for printing an overall
|
|
||||||
/// summary to the command line.
|
|
||||||
inline static std::string createStatsString(
|
|
||||||
BlockTimingMethod method=BLOCK_TOTAL_PERCENT);
|
|
||||||
|
|
||||||
//private:
|
|
||||||
inline btProfiler();
|
|
||||||
|
|
||||||
inline ~btProfiler();
|
|
||||||
|
|
||||||
/// Prints an error message to standard output.
|
|
||||||
inline static void printError(const std::string& msg)
|
|
||||||
{
|
|
||||||
//btAssert(0);
|
|
||||||
std::cout << "[QuickProf error] " << msg << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Determines whether the profiler is enabled.
|
|
||||||
static bool mEnabled;
|
|
||||||
|
|
||||||
/// The clock used to time profile blocks.
|
|
||||||
static btClock mClock;
|
|
||||||
|
|
||||||
/// The starting time (in us) of the current profiling cycle.
|
|
||||||
static unsigned long int mCurrentCycleStartMicroseconds;
|
|
||||||
|
|
||||||
/// The duration (in us) of the most recent profiling cycle.
|
|
||||||
static unsigned long int mLastCycleDurationMicroseconds;
|
|
||||||
|
|
||||||
/// Internal map of named profile blocks.
|
|
||||||
static std::map<std::string, hidden::ProfileBlock*> mProfileBlocks;
|
|
||||||
|
|
||||||
/// The data file used if this feature is enabled in 'init.'
|
|
||||||
static std::ofstream mOutputFile;
|
|
||||||
|
|
||||||
/// Tracks whether we have begun print data to the output file.
|
|
||||||
static bool mFirstFileOutput;
|
|
||||||
|
|
||||||
/// The method used when printing timing data to an output file.
|
|
||||||
static BlockTimingMethod mFileOutputMethod;
|
|
||||||
|
|
||||||
/// The number of the current profiling cycle.
|
|
||||||
static unsigned long int mCycleNumber;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
btProfiler::btProfiler()
|
/*
|
||||||
{
|
** The Manager for the Profile system
|
||||||
// This never gets called because a btProfiler instance is never
|
*/
|
||||||
// created.
|
class CProfileManager {
|
||||||
}
|
public:
|
||||||
|
static void Start_Profile( const char * name );
|
||||||
|
static void Stop_Profile( void );
|
||||||
|
|
||||||
btProfiler::~btProfiler()
|
static void Reset( void );
|
||||||
{
|
static void Increment_Frame_Counter( void );
|
||||||
// This never gets called because a btProfiler instance is never
|
static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; }
|
||||||
// created.
|
static float Get_Time_Since_Reset( void );
|
||||||
}
|
|
||||||
|
|
||||||
void btProfiler::init(const std::string outputFilename,
|
static CProfileIterator * Get_Iterator( void ) { return new CProfileIterator( &Root ); }
|
||||||
BlockTimingMethod outputMethod)
|
static void Release_Iterator( CProfileIterator * iterator ) { delete iterator; }
|
||||||
{
|
|
||||||
mEnabled = true;
|
private:
|
||||||
|
static CProfileNode Root;
|
||||||
|
static CProfileNode * CurrentNode;
|
||||||
|
static int FrameCounter;
|
||||||
|
static unsigned long int ResetTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** ProfileSampleClass is a simple way to profile a function's scope
|
||||||
|
** Use the BT_PROFILE macro at the start of scope to time
|
||||||
|
*/
|
||||||
|
class CProfileSample {
|
||||||
|
public:
|
||||||
|
CProfileSample( const char * name )
|
||||||
|
{
|
||||||
|
CProfileManager::Start_Profile( name );
|
||||||
|
}
|
||||||
|
|
||||||
if (!outputFilename.empty())
|
~CProfileSample( void )
|
||||||
{
|
{
|
||||||
mOutputFile.open(outputFilename.c_str());
|
CProfileManager::Stop_Profile();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
mFileOutputMethod = outputMethod;
|
#if !defined(BT_NO_PROFILE)
|
||||||
|
#define BT_PROFILE( name ) CProfileSample __profile( name )
|
||||||
mClock.reset();
|
#else
|
||||||
|
#define BT_PROFILE( name )
|
||||||
// Set the start time for the first cycle.
|
#endif
|
||||||
mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
void btProfiler::destroy()
|
|
||||||
{
|
|
||||||
if (!mEnabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mOutputFile.is_open())
|
|
||||||
{
|
|
||||||
mOutputFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy all ProfileBlocks.
|
|
||||||
while (!mProfileBlocks.empty())
|
|
||||||
{
|
|
||||||
delete (*mProfileBlocks.begin()).second;
|
|
||||||
mProfileBlocks.erase(mProfileBlocks.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void btProfiler::beginBlock(const std::string& name)
|
|
||||||
{
|
|
||||||
if (!mEnabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.empty())
|
|
||||||
{
|
|
||||||
printError("Cannot allow unnamed profile blocks.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hidden::ProfileBlock* block = mProfileBlocks[name];
|
|
||||||
|
|
||||||
if (!block)
|
|
||||||
{
|
|
||||||
// Create a new ProfileBlock.
|
|
||||||
mProfileBlocks[name] = new hidden::ProfileBlock();
|
|
||||||
block = mProfileBlocks[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
// We do this at the end to get more accurate results.
|
|
||||||
block->currentBlockStartMicroseconds = mClock.getTimeMicroseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
void btProfiler::endBlock(const std::string& name)
|
|
||||||
{
|
|
||||||
if (!mEnabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We do this at the beginning to get more accurate results.
|
|
||||||
unsigned long int endTick = mClock.getTimeMicroseconds();
|
|
||||||
|
|
||||||
hidden::ProfileBlock* block = mProfileBlocks[name];
|
|
||||||
|
|
||||||
if (!block)
|
|
||||||
{
|
|
||||||
// The named block does not exist. Print an error.
|
|
||||||
printError("The profile block named '" + name +
|
|
||||||
"' does not exist.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long int blockDuration = endTick -
|
|
||||||
block->currentBlockStartMicroseconds;
|
|
||||||
block->currentCycleTotalMicroseconds += blockDuration;
|
|
||||||
block->totalMicroseconds += blockDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
double btProfiler::getBlockTime(const std::string& name,
|
|
||||||
BlockTimingMethod method)
|
|
||||||
{
|
|
||||||
if (!mEnabled)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hidden::ProfileBlock* block = mProfileBlocks[name];
|
|
||||||
|
|
||||||
if (!block)
|
|
||||||
{
|
|
||||||
// The named block does not exist. Print an error.
|
|
||||||
printError("The profile block named '" + name +
|
|
||||||
"' does not exist.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double result = 0;
|
|
||||||
|
|
||||||
switch(method)
|
|
||||||
{
|
|
||||||
case BLOCK_TOTAL_SECONDS:
|
|
||||||
result = (double)block->totalMicroseconds * (double)0.000001;
|
|
||||||
break;
|
|
||||||
case BLOCK_TOTAL_MILLISECONDS:
|
|
||||||
result = (double)block->totalMicroseconds * (double)0.001;
|
|
||||||
break;
|
|
||||||
case BLOCK_TOTAL_MICROSECONDS:
|
|
||||||
result = (double)block->totalMicroseconds;
|
|
||||||
break;
|
|
||||||
case BLOCK_TOTAL_PERCENT:
|
|
||||||
{
|
|
||||||
double timeSinceInit = (double)mClock.getTimeMicroseconds();
|
|
||||||
if (timeSinceInit <= 0)
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = 100.0 * (double)block->totalMicroseconds /
|
|
||||||
timeSinceInit;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BLOCK_CYCLE_SECONDS:
|
|
||||||
result = (double)block->lastCycleTotalMicroseconds *
|
|
||||||
(double)0.000001;
|
|
||||||
break;
|
|
||||||
case BLOCK_CYCLE_MILLISECONDS:
|
|
||||||
result = (double)block->lastCycleTotalMicroseconds *
|
|
||||||
(double)0.001;
|
|
||||||
break;
|
|
||||||
case BLOCK_CYCLE_MICROSECONDS:
|
|
||||||
result = (double)block->lastCycleTotalMicroseconds;
|
|
||||||
break;
|
|
||||||
case BLOCK_CYCLE_PERCENT:
|
|
||||||
{
|
|
||||||
if (0 == mLastCycleDurationMicroseconds)
|
|
||||||
{
|
|
||||||
// We have not yet finished a cycle, so just return zero
|
|
||||||
// percent to avoid a divide by zero error.
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = 100.0 * (double)block->lastCycleTotalMicroseconds /
|
|
||||||
mLastCycleDurationMicroseconds;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void btProfiler::endProfilingCycle()
|
|
||||||
{
|
|
||||||
if (!mEnabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the duration of the cycle that just finished.
|
|
||||||
mLastCycleDurationMicroseconds = mClock.getTimeMicroseconds() -
|
|
||||||
mCurrentCycleStartMicroseconds;
|
|
||||||
|
|
||||||
// For each block, update data for the cycle that just finished.
|
|
||||||
std::map<std::string, hidden::ProfileBlock*>::iterator iter;
|
|
||||||
for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter)
|
|
||||||
{
|
|
||||||
hidden::ProfileBlock* block = (*iter).second;
|
|
||||||
block->lastCycleTotalMicroseconds =
|
|
||||||
block->currentCycleTotalMicroseconds;
|
|
||||||
block->currentCycleTotalMicroseconds = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mOutputFile.is_open())
|
|
||||||
{
|
|
||||||
// Print data to the output file.
|
|
||||||
if (mFirstFileOutput)
|
|
||||||
{
|
|
||||||
// On the first iteration, print a header line that shows the
|
|
||||||
// names of each profiling block.
|
|
||||||
mOutputFile << "#cycle, ";
|
|
||||||
|
|
||||||
for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end();
|
|
||||||
++iter)
|
|
||||||
{
|
|
||||||
mOutputFile << (*iter).first << ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
mOutputFile << std::endl;
|
|
||||||
mFirstFileOutput = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mOutputFile << mCycleNumber << ", ";
|
|
||||||
|
|
||||||
for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end();
|
|
||||||
++iter)
|
|
||||||
{
|
|
||||||
mOutputFile << getBlockTime((*iter).first, mFileOutputMethod)
|
|
||||||
<< ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
mOutputFile << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
++mCycleNumber;
|
|
||||||
mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string btProfiler::createStatsString(BlockTimingMethod method)
|
|
||||||
{
|
|
||||||
if (!mEnabled)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string s;
|
|
||||||
std::string suffix;
|
|
||||||
|
|
||||||
switch(method)
|
|
||||||
{
|
|
||||||
case BLOCK_TOTAL_SECONDS:
|
|
||||||
suffix = "s";
|
|
||||||
break;
|
|
||||||
case BLOCK_TOTAL_MILLISECONDS:
|
|
||||||
suffix = "ms";
|
|
||||||
break;
|
|
||||||
case BLOCK_TOTAL_MICROSECONDS:
|
|
||||||
suffix = "us";
|
|
||||||
break;
|
|
||||||
case BLOCK_TOTAL_PERCENT:
|
|
||||||
{
|
|
||||||
suffix = "%";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BLOCK_CYCLE_SECONDS:
|
|
||||||
suffix = "s";
|
|
||||||
break;
|
|
||||||
case BLOCK_CYCLE_MILLISECONDS:
|
|
||||||
suffix = "ms";
|
|
||||||
break;
|
|
||||||
case BLOCK_CYCLE_MICROSECONDS:
|
|
||||||
suffix = "us";
|
|
||||||
break;
|
|
||||||
case BLOCK_CYCLE_PERCENT:
|
|
||||||
{
|
|
||||||
suffix = "%";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<std::string, hidden::ProfileBlock*>::iterator iter;
|
|
||||||
for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter)
|
|
||||||
{
|
|
||||||
if (iter != mProfileBlocks.begin())
|
|
||||||
{
|
|
||||||
s += "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
char blockTime[64];
|
|
||||||
sprintf(blockTime, "%lf", getBlockTime((*iter).first, method));
|
|
||||||
|
|
||||||
s += (*iter).first;
|
|
||||||
s += ": ";
|
|
||||||
s += blockTime;
|
|
||||||
s += " ";
|
|
||||||
s += suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define BEGIN_PROFILE(a) btProfiler::beginBlock(a)
|
|
||||||
#define END_PROFILE(a) btProfiler::endBlock(a)
|
|
||||||
|
|
||||||
#else //USE_QUICKPROF
|
|
||||||
#define BEGIN_PROFILE(a)
|
|
||||||
#define END_PROFILE(a)
|
|
||||||
|
|
||||||
#endif //USE_QUICKPROF
|
|
||||||
|
|
||||||
#endif //QUICK_PROF_H
|
#endif //QUICK_PROF_H
|
||||||
|
|
||||||
|
@ -23,12 +23,18 @@ subject to the following restrictions:
|
|||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
|
#define BT_BULLET_VERSION 266
|
||||||
|
|
||||||
inline int btGetVersion()
|
inline int btGetVersion()
|
||||||
{
|
{
|
||||||
return 264;
|
return BT_BULLET_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined (_DEBUG)
|
||||||
|
#define BT_DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
||||||
#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
|
#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
|
||||||
@ -110,6 +116,8 @@ inline int btGetVersion()
|
|||||||
#define btAssert assert
|
#define btAssert assert
|
||||||
//btFullAssert is optional, slows down a lot
|
//btFullAssert is optional, slows down a lot
|
||||||
#define btFullAssert(x)
|
#define btFullAssert(x)
|
||||||
|
#define btLikely(_c) _c
|
||||||
|
#define btUnlikely(_c) _c
|
||||||
|
|
||||||
|
|
||||||
#endif // LIBSPE2
|
#endif // LIBSPE2
|
||||||
|
@ -41,6 +41,8 @@ libbulletcollision_a_SOURCES := \
|
|||||||
BulletCollision/CollisionDispatch/btCollisionWorld.h \
|
BulletCollision/CollisionDispatch/btCollisionWorld.h \
|
||||||
BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp \
|
BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp \
|
||||||
BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h \
|
BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h \
|
||||||
|
BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp \
|
||||||
|
BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm..h \
|
||||||
BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp \
|
BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp \
|
||||||
BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h \
|
BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h \
|
||||||
BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp \
|
BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp \
|
||||||
|
@ -226,6 +226,10 @@
|
|||||||
RelativePath="..\..\bullet\src\BulletCollision\CollisionDispatch\btConvexConvexAlgorithm.cpp"
|
RelativePath="..\..\bullet\src\BulletCollision\CollisionDispatch\btConvexConvexAlgorithm.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\bullet\src\BulletCollision\CollisionDispatch\btConvexPlaneCollisionAlgorithm.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\bullet\src\BulletCollision\CollisionDispatch\btDefaultCollisionConfiguration.cpp"
|
RelativePath="..\..\bullet\src\BulletCollision\CollisionDispatch\btDefaultCollisionConfiguration.cpp"
|
||||||
>
|
>
|
||||||
@ -744,6 +748,10 @@
|
|||||||
RelativePath="..\..\bullet\src\BulletCollision\CollisionDispatch\btConvexConvexAlgorithm.h"
|
RelativePath="..\..\bullet\src\BulletCollision\CollisionDispatch\btConvexConvexAlgorithm.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\bullet\src\BulletCollision\CollisionDispatch\btConvexPlaneCollisionAlgorithm.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\bullet\src\BulletCollision\CollisionDispatch\btDefaultCollisionConfiguration.h"
|
RelativePath="..\..\bullet\src\BulletCollision\CollisionDispatch\btDefaultCollisionConfiguration.h"
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user