diff --git a/Bullet/BroadphaseCollision/OverlappingPairCache.cpp b/Bullet/BroadphaseCollision/OverlappingPairCache.cpp index 86ddb41c6..89ee1ee73 100644 --- a/Bullet/BroadphaseCollision/OverlappingPairCache.cpp +++ b/Bullet/BroadphaseCollision/OverlappingPairCache.cpp @@ -101,6 +101,7 @@ void OverlappingPairCache::AddOverlappingPair(BroadphaseProxy* proxy0,Broadphase ///this FindPair becomes really slow. Either sort the list to speedup the query, or ///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. ///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) +///Also we can use a 2D bitmap, which can be useful for a future GPU implementation BroadphasePair* OverlappingPairCache::FindPair(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1) { BroadphasePair* foundPair = 0; diff --git a/Bullet/CollisionDispatch/CollisionWorld.cpp b/Bullet/CollisionDispatch/CollisionWorld.cpp index bc4413c34..63960bf2d 100644 --- a/Bullet/CollisionDispatch/CollisionWorld.cpp +++ b/Bullet/CollisionDispatch/CollisionWorld.cpp @@ -103,6 +103,8 @@ void CollisionWorld::PerformDiscreteCollisionDetection() m_pairCache->SetAabb(m_collisionObjects[i]->m_broadphaseHandle,aabbMin,aabbMax); } + m_pairCache->RefreshOverlappingPairs(); + Dispatcher* dispatcher = GetDispatcher(); if (dispatcher) dispatcher->DispatchAllCollisionPairs(&m_pairCache->GetOverlappingPair(0),m_pairCache->GetNumOverlappingPairs(),dispatchInfo); @@ -140,11 +142,11 @@ void CollisionWorld::RemoveCollisionObject(CollisionObject* collisionObject) } } -void RayTestSingle(const SimdTransform& rayFromTrans,const SimdTransform& rayToTrans, +void CollisionWorld::RayTestSingle(const SimdTransform& rayFromTrans,const SimdTransform& rayToTrans, CollisionObject* collisionObject, const CollisionShape* collisionShape, const SimdTransform& colObjWorldTransform, - CollisionWorld::RayResultCallback& resultCallback) + RayResultCallback& resultCallback) { SphereShape pointShape(0.0f); diff --git a/Bullet/CollisionDispatch/CollisionWorld.h b/Bullet/CollisionDispatch/CollisionWorld.h index d05fcc4a0..9a35a1035 100644 --- a/Bullet/CollisionDispatch/CollisionWorld.h +++ b/Bullet/CollisionDispatch/CollisionWorld.h @@ -204,8 +204,18 @@ public: return m_collisionObjects.size(); } + /// RayTest performs a raycast on all objects in the CollisionWorld, and calls the resultCallback + /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. void RayTest(const SimdVector3& rayFromWorld, const SimdVector3& rayToWorld, RayResultCallback& resultCallback); + /// 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 CollisionShape. + /// This allows more customization. + void RayTestSingle(const SimdTransform& rayFromTrans,const SimdTransform& rayToTrans, + CollisionObject* collisionObject, + const CollisionShape* collisionShape, + const SimdTransform& colObjWorldTransform, + RayResultCallback& resultCallback); void AddCollisionObject(CollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1); diff --git a/Bullet/CollisionShapes/OptimizedBvh.cpp b/Bullet/CollisionShapes/OptimizedBvh.cpp index 1b30bfbcb..498c29e50 100644 --- a/Bullet/CollisionShapes/OptimizedBvh.cpp +++ b/Bullet/CollisionShapes/OptimizedBvh.cpp @@ -85,6 +85,11 @@ void OptimizedBvh::Build(StridingMeshInterface* triangles) // OptimizedBvhNode* leafNodes = new OptimizedBvhNode; } +OptimizedBvh::~OptimizedBvh() +{ + if (m_contiguousNodes) + delete m_contiguousNodes; +} OptimizedBvhNode* OptimizedBvh::BuildTree (NodeArray& leafNodes,int startIndex,int endIndex) { diff --git a/Bullet/CollisionShapes/OptimizedBvh.h b/Bullet/CollisionShapes/OptimizedBvh.h index ec550e467..5fef1695c 100644 --- a/Bullet/CollisionShapes/OptimizedBvh.h +++ b/Bullet/CollisionShapes/OptimizedBvh.h @@ -69,7 +69,7 @@ class OptimizedBvh public: OptimizedBvh() :m_rootNode1(0), m_numNodes(0) { } - virtual ~OptimizedBvh() {}; + virtual ~OptimizedBvh(); void Build(StridingMeshInterface* triangles); diff --git a/Demos/CMakeLists.txt b/Demos/CMakeLists.txt index f7455cacf..d7af0a95f 100644 --- a/Demos/CMakeLists.txt +++ b/Demos/CMakeLists.txt @@ -1,2 +1,2 @@ -SUBDIRS( OpenGL CcdPhysicsDemo BspDemo ColladaDemo ) +SUBDIRS( OpenGL CcdPhysicsDemo BspDemo ColladaDemo VehicleDemo ) diff --git a/Demos/Jamfile b/Demos/Jamfile index aebee01de..5c49ae204 100644 --- a/Demos/Jamfile +++ b/Demos/Jamfile @@ -77,6 +77,7 @@ SubInclude TOP Demos BspDemo ; SubInclude TOP Demos ConvexDecompositionDemo ; SubInclude TOP Demos ColladaDemo ; SubInclude TOP Demos BspDemo ; +SubInclude TOP Demos VehicleDemo ; SubInclude TOP Demos CollisionDemo ; SubInclude TOP Demos CollisionInterfaceDemo ; SubInclude TOP Demos ConcaveDemo ; diff --git a/Demos/VehicleDemo/CMakeLists.txt b/Demos/VehicleDemo/CMakeLists.txt new file mode 100644 index 000000000..b78163b08 --- /dev/null +++ b/Demos/VehicleDemo/CMakeLists.txt @@ -0,0 +1,61 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + + +# This is the shortcut to finding GLU, GLUT and OpenGL if they are properly installed on your system +# This should be the case. +INCLUDE (${CMAKE_ROOT}/Modules/FindGLU.cmake) +INCLUDE (${CMAKE_ROOT}/Modules/FindGLUT.cmake) +INCLUDE (${CMAKE_ROOT}/Modules/FindOpenGL.cmake) + + +IF (WIN32) + # This is the Windows code for which Opengl, and Glut are not properly installed + # since I can't install them I must cheat and copy libraries around + INCLUDE_DIRECTORIES(${GLUT_ROOT}) + # LINK_DIRECTORIES(${GLUT_ROOT}\\lib) + IF (${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND") + SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut32.lib) + # LINK_LIBRARIES(${GLUT_ROOT}\\lib\\glut32 ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY}) + # TARGET_LINK_LIBRARIES(table ${GLUT_ROOT}\\lib\\glut32) +# +# ADD_CUSTOM_COMMAND(TARGET table POST_BUILD COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs2005\\Debug +# COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs2003\\Debug +# COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs6\\Debug) + ELSE (${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND") +# LINK_LIBRARIES(${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY}) +# TARGET_LINK_LIBRARIES(table ${GLUT_glut_LIBRARY}) + ENDIF(${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND") +# TARGET_LINK_LIBRARIES(table ${OPENGL_gl_LIBRARY}) +# TARGET_LINK_LIBRARIES(table ${OPENGL_glu_LIBRARY}) +ELSE (WIN32) + # This is the lines for linux. This should always work if everything is installed and working fine. +# SET(CMAKE_BUILD_TYPE Debug) +# SET(CMAKE_CXX_FLAGS_DEBUG "-g") + INCLUDE_DIRECTORIES(/usr/include /usr/local/include ${GLUT_INCLUDE_DIR}) +# TARGET_LINK_LIBRARIES(table ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY}) +# TARGET_LINK_LIBRARIES(checker ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY}) +ENDIF (WIN32) + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/LinearMath ${BULLET_PHYSICS_SOURCE_DIR}/Bullet ${BULLET_PHYSICS_SOURCE_DIR}/BulletDynamics ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL ${BULLET_PHYSICS_SOURCE_DIR}/Extras/PhysicsInterface/Common ${BULLET_PHYSICS_SOURCE_DIR}/Extras/PhysicsInterface/CcdPhysics } +) + +LINK_LIBRARIES( +LibCcdPhysicsInterface LibOpenGLSupport LibBulletDynamics LibPhysicsCommonInterface LibBulletCollision LibLinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY} +) + +ADD_EXECUTABLE(VehicleDemo + VehicleDemo.cpp +) + diff --git a/Demos/VehicleDemo/Jamfile b/Demos/VehicleDemo/Jamfile new file mode 100644 index 000000000..ad48d0ee9 --- /dev/null +++ b/Demos/VehicleDemo/Jamfile @@ -0,0 +1,3 @@ +SubDir TOP Demos VehicleDemo ; + +BulletDemo VehicleDemo : [ Wildcard *.h *.cpp ] ; diff --git a/Demos/VehicleDemo/VehicleDemo.cpp b/Demos/VehicleDemo/VehicleDemo.cpp new file mode 100644 index 000000000..27d055361 --- /dev/null +++ b/Demos/VehicleDemo/VehicleDemo.cpp @@ -0,0 +1,1044 @@ +/* +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. +*/ + +//#define USE_PARALLEL_DISPATCHER 1 + + +#include "CcdPhysicsEnvironment.h" +#include "ParallelPhysicsEnvironment.h" + +#include "CcdPhysicsController.h" +#include "MyMotionState.h" +//#include "GL_LineSegmentShape.h" +#include "CollisionShapes/BoxShape.h" +#include "CollisionShapes/SphereShape.h" +#include "CollisionShapes/ConeShape.h" +#include "CollisionShapes/StaticPlaneShape.h" +#include "CollisionShapes/CompoundShape.h" +#include "CollisionShapes/Simplex1to4Shape.h" +#include "CollisionShapes/EmptyShape.h" +#include "CollisionShapes/TriangleMeshShape.h" +#include "CollisionShapes/TriangleIndexVertexArray.h" +#include "CollisionShapes/BvhTriangleMeshShape.h" +#include "CollisionShapes/TriangleMesh.h" + +#include "Dynamics/RigidBody.h" +#include "CollisionDispatch/CollisionDispatcher.h" + +#include "ParallelIslandDispatcher.h" + +#include "BroadphaseCollision/SimpleBroadphase.h" +#include "BroadphaseCollision/AxisSweep3.h" +#include "ConstraintSolver/Point2PointConstraint.h" +#include "ConstraintSolver/HingeConstraint.h" + +#include "quickprof.h" +#include "IDebugDraw.h" + +#include "GLDebugDrawer.h" + + + + +#include "PHY_Pro.h" +#include "BMF_Api.h" +#include //printf debugging + +float deltaTime = 1.f/60.f; +float bulletSpeed = 40.f; + +#ifdef WIN32 +#if _MSC_VER >= 1310 +//only use SIMD Hull code under Win32 +#define USE_HULL 1 +#include "NarrowPhaseCollision/Hull.h" +#endif //_MSC_VER +#endif //WIN32 + + +#ifdef WIN32 //needed for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#else +#include +#endif + +#include "GL_ShapeDrawer.h" + +#include "GlutStuff.h" + + +extern float eye[3]; +extern int glutScreenWidth; +extern int glutScreenHeight; + +const int maxProxies = 32766; +const int maxOverlap = 65535; + +bool createConstraint = true;//false; +bool useCompound = true;//false; + + +#ifdef _DEBUG +const int numObjects = 50; +#else +const int numObjects = 120; +#endif + +const int maxNumObjects = 32760; + +MyMotionState ms[maxNumObjects]; +CcdPhysicsController* physObjects[maxNumObjects] = {0,0,0,0}; +int shapeIndex[maxNumObjects]; + +#ifdef USE_PARALLEL_DISPATCHER +ParallelPhysicsEnvironment* physicsEnvironmentPtr = 0; +#else +CcdPhysicsEnvironment* physicsEnvironmentPtr = 0; +#endif + +#define CUBE_HALF_EXTENTS 1 + +#define EXTRA_HEIGHT -20.f +//GL_LineSegmentShape shapeE(SimdPoint3(-50,0,0), +// SimdPoint3(50,0,0)); +static const int numShapes = 4; + +CollisionShape* shapePtr[numShapes] = +{ + ///Please don't make the box sizes larger then 1000: the collision detection will be inaccurate. + ///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=346 + +//#define USE_GROUND_PLANE 1 +#ifdef USE_GROUND_PLANE + new StaticPlaneShape(SimdVector3(0,1,0),10), +#else + new BoxShape (SimdVector3(50,10,50)), +#endif + + new BoxShape (SimdVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)), + new SphereShape (CUBE_HALF_EXTENTS- 0.05f), + + //new ConeShape(CUBE_HALF_EXTENTS,2.f*CUBE_HALF_EXTENTS), + //new BU_Simplex1to4(SimdPoint3(-1,-1,-1),SimdPoint3(1,-1,-1),SimdPoint3(-1,1,-1),SimdPoint3(0,0,1)), + + //new EmptyShape(), + + new BoxShape (SimdVector3(0.4,1,0.8)) + +}; + + + +//////////////////////////////////// + + + + + + +GLDebugDrawer debugDrawer; + +int main(int argc,char** argv) +{ + + + CollisionDispatcher* dispatcher = new CollisionDispatcher(); + ParallelIslandDispatcher* dispatcher2 = new ParallelIslandDispatcher(); + + SimdVector3 worldAabbMin(-30000,-30000,-30000); + SimdVector3 worldAabbMax(30000,30000,30000); + + OverlappingPairCache* broadphase = new AxisSweep3(worldAabbMin,worldAabbMax,maxProxies,maxOverlap); + //OverlappingPairCache* broadphase = new SimpleBroadphase(maxProxies,maxOverlap); + +#ifdef USE_PARALLEL_DISPATCHER + physicsEnvironmentPtr = new ParallelPhysicsEnvironment(dispatcher2,broadphase); +#else + physicsEnvironmentPtr = new CcdPhysicsEnvironment(dispatcher,broadphase); +#endif + physicsEnvironmentPtr->setDeactivationTime(2.f); + + physicsEnvironmentPtr->setGravity(0,-10,0);//0,0);//-10,0); + int i; + +//#define USE_TRIMESH_GROUND 1 +#ifdef USE_TRIMESH_GROUND + + +const float TRIANGLE_SIZE=20.f; + + //create a triangle-mesh ground + int vertStride = sizeof(SimdVector3); + int indexStride = 3*sizeof(int); + + const int NUM_VERTS_X = 50; + const int NUM_VERTS_Y = 50; + const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + + const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); + + SimdVector3* gVertices = new SimdVector3[totalVerts]; + int* gIndices = new int[totalTriangles*3]; + + + + for ( i=0;i0) + { + shapeIndex[i] = 1;//sphere + } + else + shapeIndex[i] = 0; + } + + if (useCompound) + { + CompoundShape* compoundShape = new CompoundShape(); + CollisionShape* oldShape = shapePtr[1]; + shapePtr[1] = compoundShape; + + SimdTransform ident; + ident.setIdentity(); + ident.setOrigin(SimdVector3(0,0,0)); + compoundShape->AddChildShape(ident,oldShape);// + ident.setOrigin(SimdVector3(0,0,2)); + compoundShape->AddChildShape(ident,new SphereShape(0.9));// + } + + for (i=0;iSetMargin(0.05f); + + + + bool isDyna = i>0; + //if (i==1) + // isDyna=false; + + if (0)//i==1) + { + SimdQuaternion orn(0,0,0.1*SIMD_HALF_PI); + ms[i].setWorldOrientation(orn.x(),orn.y(),orn.z(),orn[3]); + } + + + if (i>0) + { + + switch (i) + { + case 1: + { + ms[i].setWorldPosition(0,10,0); + //for testing, rotate the ground cube so the stack has to recover a bit + + break; + } + case 2: + { + ms[i].setWorldPosition(0,8,2); + break; + } + default: + ms[i].setWorldPosition(0,i*CUBE_HALF_EXTENTS*2 - CUBE_HALF_EXTENTS,0); + } + + float quatIma0,quatIma1,quatIma2,quatReal; + SimdQuaternion quat; + SimdVector3 axis(0,0,1); + SimdScalar angle=0.5f; + + quat.setRotation(axis,angle); + + ms[i].setWorldOrientation(quat.getX(),quat.getY(),quat.getZ(),quat[3]); + + + + } else + { + ms[i].setWorldPosition(0,-10+EXTRA_HEIGHT,0); + + } + + ccdObjectCi.m_MotionState = &ms[i]; + ccdObjectCi.m_gravity = SimdVector3(0,0,0); + ccdObjectCi.m_localInertiaTensor =SimdVector3(0,0,0); + if (!isDyna) + { + shapeProps.m_mass = 0.f; + ccdObjectCi.m_mass = shapeProps.m_mass; + ccdObjectCi.m_collisionFlags = CollisionObject::isStatic; + + ccdObjectCi.m_collisionFilterGroup = CcdConstructionInfo::StaticFilter; + ccdObjectCi.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter; + } + else + { + shapeProps.m_mass = 1.f; + ccdObjectCi.m_mass = shapeProps.m_mass; + ccdObjectCi.m_collisionFlags = 0; + + } + + + SimdVector3 localInertia(0.f,0.f,0.f); + if (shapeIndex[i]) + { + if (shapePtr[shapeIndex[i]]->GetShapeType() == EMPTY_SHAPE_PROXYTYPE) + { + //take inertia from first shape + shapePtr[1]->CalculateLocalInertia(shapeProps.m_mass,localInertia); + } else + { + shapePtr[shapeIndex[i]]->CalculateLocalInertia(shapeProps.m_mass,localInertia); + } + + } + ccdObjectCi.m_localInertiaTensor = localInertia; + + ccdObjectCi.m_collisionShape = shapePtr[shapeIndex[i]]; + + + physObjects[i]= new CcdPhysicsController( ccdObjectCi); + + // Only do CCD if motion in one timestep (1.f/60.f) exceeds CUBE_HALF_EXTENTS + physObjects[i]->GetRigidBody()->m_ccdSquareMotionTreshold = CUBE_HALF_EXTENTS; + + //Experimental: better estimation of CCD Time of Impact: + physObjects[i]->GetRigidBody()->m_ccdSweptShereRadius = 0.2*CUBE_HALF_EXTENTS; + + physicsEnvironmentPtr->addCcdPhysicsController( physObjects[i]); + + if (i==1) + { + //physObjects[i]->SetAngularVelocity(0,0,-2,true); + } + + physicsEnvironmentPtr->setDebugDrawer(&debugDrawer); + + } + + + clientResetScene(); + physicsEnvironmentPtr->SyncMotionStates(0.f); + + if (createConstraint) + { + //physObjects[i]->SetAngularVelocity(0,0,-2,true); + int constraintId; + + float pivotX=CUBE_HALF_EXTENTS, + pivotY=CUBE_HALF_EXTENTS, + pivotZ=CUBE_HALF_EXTENTS; + float axisX=0,axisY=1,axisZ=0; + + + constraintId =physicsEnvironmentPtr->createConstraint( + physObjects[1], + //0, + physObjects[2], + ////PHY_POINT2POINT_CONSTRAINT, + PHY_GENERIC_6DOF_CONSTRAINT,//can leave any of the 6 degree of freedom 'free' or 'locked' + //PHY_LINEHINGE_CONSTRAINT, + pivotX,pivotY,pivotZ, + axisX,axisY,axisZ + ); + + } + + + setCameraDistance(26.f); + + return glutmain(argc, argv,640,480,"Bullet Vehicle Demo. http://www.continuousphysics.com/Bullet/phpBB2/"); +} + +//to be implemented by the demo +void renderme() +{ + debugDrawer.SetDebugMode(getDebugMode()); + + //render the hinge axis + if (createConstraint) + { + SimdVector3 color(1,0,0); + SimdVector3 dirLocal(0,1,0); + SimdVector3 pivotInA(CUBE_HALF_EXTENTS,-CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS); + SimdVector3 pivotInB(-CUBE_HALF_EXTENTS,-CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS); + SimdVector3 from = physObjects[1]->GetRigidBody()->getCenterOfMassTransform()(pivotInA); + SimdVector3 fromB = physObjects[2]->GetRigidBody()->getCenterOfMassTransform()(pivotInB); + SimdVector3 dirWorldA = physObjects[1]->GetRigidBody()->getCenterOfMassTransform().getBasis() * dirLocal ; + SimdVector3 dirWorldB = physObjects[2]->GetRigidBody()->getCenterOfMassTransform().getBasis() * dirLocal ; + debugDrawer.DrawLine(from,from+dirWorldA,color); + debugDrawer.DrawLine(fromB,fromB+dirWorldB,color); + } + + float m[16]; + int i; + + + if (getDebugMode() & IDebugDraw::DBG_DisableBulletLCP) + { + //don't use Bullet, use quickstep + physicsEnvironmentPtr->setSolverType(0); + } else + { + //Bullet LCP solver + physicsEnvironmentPtr->setSolverType(1); + } + + if (getDebugMode() & IDebugDraw::DBG_EnableCCD) + { + physicsEnvironmentPtr->setCcdMode(3); + } else + { + physicsEnvironmentPtr->setCcdMode(0); + } + + + bool isSatEnabled = (getDebugMode() & IDebugDraw::DBG_EnableSatComparison); + + physicsEnvironmentPtr->EnableSatCollisionDetection(isSatEnabled); + + +#ifdef USE_HULL + //some testing code for SAT + if (isSatEnabled) + { + for (int s=0;sIsPolyhedral()) + { + PolyhedralConvexShape* polyhedron = static_cast(shape); + if (!polyhedron->m_optionalHull) + { + //first convert vertices in 'Point3' format + int numPoints = polyhedron->GetNumVertices(); + Point3* points = new Point3[numPoints+1]; + //first 4 points should not be co-planar, so add central point to satisfy MakeHull + points[0] = Point3(0.f,0.f,0.f); + + SimdVector3 vertex; + for (int p=0;pGetVertex(p,vertex); + points[p+1] = Point3(vertex.getX(),vertex.getY(),vertex.getZ()); + } + + Hull* hull = Hull::MakeHull(numPoints+1,points); + polyhedron->m_optionalHull = hull; + } + + } + } + + } +#endif //USE_HULL + + + for (i=0;iGetRigidBody()->GetActivationState() == 1) //active + { + if (i & 1) + { + wireColor += SimdVector3 (1.f,0.f,0.f); + } else + { + wireColor += SimdVector3 (.5f,0.f,0.f); + } + } + if (physObjects[i]->GetRigidBody()->GetActivationState() == 2) //ISLAND_SLEEPING + { + if (i & 1) + { + wireColor += SimdVector3 (0.f,1.f, 0.f); + } else + { + wireColor += SimdVector3 (0.f,0.5f,0.f); + } + } + + char extraDebug[125]; + sprintf(extraDebug,"islId, Body=%i , %i",physObjects[i]->GetRigidBody()->m_islandTag1,physObjects[i]->GetRigidBody()->m_debugBodyId); + physObjects[i]->GetRigidBody()->GetCollisionShape()->SetExtraDebugInfo(extraDebug); + + float vec[16]; + SimdTransform ident; + ident.setIdentity(); + ident.getOpenGLMatrix(vec); + glPushMatrix(); + + glLoadMatrixf(vec); + + GL_ShapeDrawer::DrawOpenGL(m,physObjects[i]->GetRigidBody()->GetCollisionShape(),wireColor,getDebugMode()); + + glPopMatrix(); + + ///this block is just experimental code to show some internal issues with replacing shapes on the fly. + if (getDebugMode()!=0 && (i>0)) + { + if (physObjects[i]->GetRigidBody()->GetCollisionShape()->GetShapeType() == EMPTY_SHAPE_PROXYTYPE) + { + physObjects[i]->GetRigidBody()->SetCollisionShape(shapePtr[1]); + + //remove the persistent collision pairs that were created based on the previous shape + + BroadphaseProxy* bpproxy = physObjects[i]->GetRigidBody()->m_broadphaseHandle; + + physicsEnvironmentPtr->GetBroadphase()->CleanProxyFromPairs(bpproxy); + + SimdVector3 newinertia; + SimdScalar newmass = 10.f; + physObjects[i]->GetRigidBody()->GetCollisionShape()->CalculateLocalInertia(newmass,newinertia); + physObjects[i]->GetRigidBody()->setMassProps(newmass,newinertia); + physObjects[i]->GetRigidBody()->updateInertiaTensor(); + + } + + } + + + } + + if (!(getDebugMode() & IDebugDraw::DBG_NoHelpText)) + { + + float xOffset = 10.f; + float yStart = 20.f; + + float yIncr = -2.f; + + char buf[124]; + + glColor3f(0, 0, 0); + +#ifdef USE_QUICKPROF + + + if ( getDebugMode() & IDebugDraw::DBG_ProfileTimings) + { + static int counter = 0; + counter++; + std::map::iterator iter; + for (iter = Profiler::mProfileBlocks.begin(); iter != Profiler::mProfileBlocks.end(); ++iter) + { + char blockTime[128]; + sprintf(blockTime, "%s: %lf",&((*iter).first[0]),Profiler::getBlockTime((*iter).first, Profiler::BLOCK_CYCLE_SECONDS));//BLOCK_TOTAL_PERCENT)); + glRasterPos3f(xOffset,yStart,0); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),blockTime); + yStart += yIncr; + + } + } +#endif //USE_QUICKPROF + //profiling << Profiler::createStatsString(Profiler::BLOCK_TOTAL_PERCENT); + //<< std::endl; + + + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"mouse to interact"); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"space to reset"); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"cursor keys and z,x to navigate"); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"i to toggle simulation, s single step"); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"q to quit"); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"d to toggle deactivation"); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"a to draw temporal AABBs"); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"h to toggle help text"); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + bool useBulletLCP = !(getDebugMode() & IDebugDraw::DBG_DisableBulletLCP); + + bool useCCD = (getDebugMode() & IDebugDraw::DBG_EnableCCD); + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"m Bullet GJK = %i",!isSatEnabled); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"n Bullet LCP = %i",useBulletLCP); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"1 CCD mode (adhoc) = %i",useCCD); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"+- shooting speed = %10.2f",bulletSpeed); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + yStart += yIncr; + + } + +} + +void clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + + physicsEnvironmentPtr->proceedDeltaTime(0.f,deltaTime); + +#ifdef USE_QUICKPROF + Profiler::beginBlock("render"); +#endif //USE_QUICKPROF + + renderme(); + +#ifdef USE_QUICKPROF + Profiler::endBlock("render"); +#endif + glFlush(); + glutSwapBuffers(); + +} + + + +void clientDisplay(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + physicsEnvironmentPtr->UpdateAabbs(deltaTime); + //draw contactpoints + physicsEnvironmentPtr->CallbackTriggers(); + + + renderme(); + + + glFlush(); + glutSwapBuffers(); +} + + + +///make this positive to show stack falling from a distance +///this shows the penalty tresholds in action, springy/spungy look + +void clientResetScene() +{ + + int i; + for (i=0;i0) + { + + if ((getDebugMode() & IDebugDraw::DBG_NoHelpText)) + { + if (physObjects[i]->GetRigidBody()->GetCollisionShape()->GetShapeType() == BOX_SHAPE_PROXYTYPE) + { + physObjects[i]->GetRigidBody()->SetCollisionShape(shapePtr[2]); + } else + { + physObjects[i]->GetRigidBody()->SetCollisionShape(shapePtr[1]); + } + + BroadphaseProxy* bpproxy = physObjects[i]->GetRigidBody()->m_broadphaseHandle; + physicsEnvironmentPtr->GetBroadphase()->CleanProxyFromPairs(bpproxy); + } + + //stack them + int colsize = 10; + int row = (i*CUBE_HALF_EXTENTS*2)/(colsize*2*CUBE_HALF_EXTENTS); + int row2 = row; + int col = (i)%(colsize)-colsize/2; + + + if (col>3) + { + col=11; + row2 |=1; + } + physObjects[i]->setPosition(col*2*CUBE_HALF_EXTENTS + (row2%2)*CUBE_HALF_EXTENTS, + row*2*CUBE_HALF_EXTENTS+CUBE_HALF_EXTENTS+EXTRA_HEIGHT,0); + physObjects[i]->setOrientation(0,0,0,1); + physObjects[i]->SetLinearVelocity(0,0,0,false); + physObjects[i]->SetAngularVelocity(0,0,0,false); + } + } +} + + + +void shootBox(const SimdVector3& destination) +{ + int i = numObjects-1; + + + + SimdVector3 linVel(destination[0]-eye[0],destination[1]-eye[1],destination[2]-eye[2]); + linVel.normalize(); + linVel*=bulletSpeed; + + physObjects[i]->setPosition(eye[0],eye[1],eye[2]); + physObjects[i]->setOrientation(0,0,0,1); + physObjects[i]->SetLinearVelocity(linVel[0],linVel[1],linVel[2],false); + physObjects[i]->SetAngularVelocity(0,0,0,false); +} + +void clientKeyboard(unsigned char key, int x, int y) +{ + + if (key == '.') + { + shootBox(SimdVector3(0,0,0)); + } + + if (key == '+') + { + bulletSpeed += 10.f; + } + if (key == '-') + { + bulletSpeed -= 10.f; + } + + defaultKeyboard(key, x, y); +} + +int gPickingConstraintId = 0; +SimdVector3 gOldPickingPos; +float gOldPickingDist = 0.f; +RigidBody* pickedBody = 0;//for deactivation state + + +SimdVector3 GetRayTo(int x,int y) +{ + float top = 1.f; + float bottom = -1.f; + float nearPlane = 1.f; + float tanFov = (top-bottom)*0.5f / nearPlane; + float fov = 2.0 * atanf (tanFov); + + SimdVector3 rayFrom(eye[0],eye[1],eye[2]); + SimdVector3 rayForward = -rayFrom; + rayForward.normalize(); + float farPlane = 600.f; + rayForward*= farPlane; + + SimdVector3 rightOffset; + SimdVector3 vertical(0.f,1.f,0.f); + SimdVector3 hor; + hor = rayForward.cross(vertical); + hor.normalize(); + vertical = hor.cross(rayForward); + vertical.normalize(); + + float tanfov = tanf(0.5f*fov); + hor *= 2.f * farPlane * tanfov; + vertical *= 2.f * farPlane * tanfov; + SimdVector3 rayToCenter = rayFrom + rayForward; + SimdVector3 dHor = hor * 1.f/float(glutScreenWidth); + SimdVector3 dVert = vertical * 1.f/float(glutScreenHeight); + SimdVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical; + rayTo += x * dHor; + rayTo -= y * dVert; + return rayTo; +} +void clientMouseFunc(int button, int state, int x, int y) +{ + //printf("button %i, state %i, x=%i,y=%i\n",button,state,x,y); + //button 0, state 0 means left mouse down + + SimdVector3 rayTo = GetRayTo(x,y); + + switch (button) + { + case 2: + { + if (state==0) + { + shootBox(rayTo); + } + break; + }; + case 1: + { + if (state==0) + { + //apply an impulse + if (physicsEnvironmentPtr) + { + float hit[3]; + float normal[3]; + PHY_IPhysicsController* hitObj = physicsEnvironmentPtr->rayTest(0,eye[0],eye[1],eye[2],rayTo.getX(),rayTo.getY(),rayTo.getZ(),hit[0],hit[1],hit[2],normal[0],normal[1],normal[2]); + if (hitObj) + { + CcdPhysicsController* physCtrl = static_cast(hitObj); + RigidBody* body = physCtrl->GetRigidBody(); + if (body) + { + body->SetActivationState(ACTIVE_TAG); + SimdVector3 impulse = rayTo; + impulse.normalize(); + float impulseStrength = 10.f; + impulse *= impulseStrength; + SimdVector3 relPos( + hit[0] - body->getCenterOfMassPosition().getX(), + hit[1] - body->getCenterOfMassPosition().getY(), + hit[2] - body->getCenterOfMassPosition().getZ()); + + body->applyImpulse(impulse,relPos); + } + + } + + } + + } else + { + + } + break; + } + case 0: + { + if (state==0) + { + //add a point to point constraint for picking + if (physicsEnvironmentPtr) + { + float hit[3]; + float normal[3]; + PHY_IPhysicsController* hitObj = physicsEnvironmentPtr->rayTest(0,eye[0],eye[1],eye[2],rayTo.getX(),rayTo.getY(),rayTo.getZ(),hit[0],hit[1],hit[2],normal[0],normal[1],normal[2]); + if (hitObj) + { + + CcdPhysicsController* physCtrl = static_cast(hitObj); + RigidBody* body = physCtrl->GetRigidBody(); + + if (body && !body->IsStatic()) + { + pickedBody = body; + pickedBody->SetActivationState(DISABLE_DEACTIVATION); + + SimdVector3 pickPos(hit[0],hit[1],hit[2]); + + SimdVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos; + + gPickingConstraintId = physicsEnvironmentPtr->createConstraint(physCtrl,0,PHY_POINT2POINT_CONSTRAINT, + localPivot.getX(), + localPivot.getY(), + localPivot.getZ(), + 0,0,0); + //printf("created constraint %i",gPickingConstraintId); + + //save mouse position for dragging + gOldPickingPos = rayTo; + + + SimdVector3 eyePos(eye[0],eye[1],eye[2]); + + gOldPickingDist = (pickPos-eyePos).length(); + + Point2PointConstraint* p2p = static_cast(physicsEnvironmentPtr->getConstraintById(gPickingConstraintId)); + if (p2p) + { + //very weak constraint for picking + p2p->m_setting.m_tau = 0.1f; + } + } + } + } + } else + { + if (gPickingConstraintId && physicsEnvironmentPtr) + { + physicsEnvironmentPtr->removeConstraint(gPickingConstraintId); + //printf("removed constraint %i",gPickingConstraintId); + gPickingConstraintId = 0; + pickedBody->ForceActivationState(ACTIVE_TAG); + pickedBody->m_deactivationTime = 0.f; + pickedBody = 0; + + + } + } + + break; + + } + default: + { + } + } + +} + +void clientMotionFunc(int x,int y) +{ + + if (gPickingConstraintId && physicsEnvironmentPtr) + { + + //move the constraint pivot + + Point2PointConstraint* p2p = static_cast(physicsEnvironmentPtr->getConstraintById(gPickingConstraintId)); + if (p2p) + { + //keep it at the same picking distance + + SimdVector3 newRayTo = GetRayTo(x,y); + SimdVector3 eyePos(eye[0],eye[1],eye[2]); + SimdVector3 dir = newRayTo-eyePos; + dir.normalize(); + dir *= gOldPickingDist; + + SimdVector3 newPos = eyePos + dir; + p2p->SetPivotB(newPos); + } + + } +}