diff --git a/Demos/CMakeLists.txt b/Demos/CMakeLists.txt index c8b6d5fae..90b97af0c 100644 --- a/Demos/CMakeLists.txt +++ b/Demos/CMakeLists.txt @@ -12,7 +12,7 @@ IF (USE_GLUT) SET(SharedDemoSubdirs OpenGL AllBulletDemos ConvexDecompositionDemo CcdPhysicsDemo ConstraintDemo SliderConstraintDemo GenericJointDemo Raytracer - RagdollDemo ForkLiftDemo BasicDemo VoronoiFractureDemo FractureDemo Box2dDemo BspDemo MovingConcaveDemo VehicleDemo + RagdollDemo ForkLiftDemo BasicDemo RaytestDemo VoronoiFractureDemo FractureDemo Box2dDemo BspDemo MovingConcaveDemo VehicleDemo UserCollisionAlgorithm CharacterDemo SoftDemo CollisionInterfaceDemo ConcaveConvexcastDemo SimplexDemo DynamicControlDemo ConvexHullDistance @@ -40,7 +40,8 @@ ELSE (USE_GLUT) IF (WIN32) SUBDIRS( OpenGL - BasicDemo + BasicDemo + RaytestDemo FractureDemo Benchmarks Box2dDemo diff --git a/Demos/RaytestDemo/CMakeLists.txt b/Demos/RaytestDemo/CMakeLists.txt new file mode 100644 index 000000000..ad60c3502 --- /dev/null +++ b/Demos/RaytestDemo/CMakeLists.txt @@ -0,0 +1,87 @@ +# 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 +######################################################## + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + +IF (WIN32) +ADD_EXECUTABLE(AppRaytestDemo + main.cpp + RaytestDemo.cpp + RaytestDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/build/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppBasicDemo + main.cpp + BasicDemo.cpp + BasicDemo.h + ) +ENDIF() + + + + + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppRaytestDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppRaytestDemo + POST_BUILD +# COMMAND copy /Y ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + + ENDIF(WIN32) +ELSE (USE_GLUT) + + + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + + ADD_EXECUTABLE(AppRaytestDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + Win32BasicDemo.cpp + RaytestDemo.cpp + RaytestDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/build/bullet.rc + ) + + +ENDIF (USE_GLUT) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppRaytestDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppRaytestDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppRaytestDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/RaytestDemo/Makefile.am b/Demos/RaytestDemo/Makefile.am new file mode 100644 index 000000000..a73e4fb9e --- /dev/null +++ b/Demos/RaytestDemo/Makefile.am @@ -0,0 +1,5 @@ +noinst_PROGRAMS=BasicDemo + +BasicDemo_SOURCES=BasicDemo.cpp BasicDemo.h main.cpp +BasicDemo_CXXFLAGS=-I@top_builddir@/src -I@top_builddir@/Demos/OpenGL $(CXXFLAGS) +BasicDemo_LDADD=-L../OpenGL -lbulletopenglsupport -L../../src -lBulletDynamics -lBulletCollision -lLinearMath @opengl_LIBS@ diff --git a/Demos/RaytestDemo/RaytestDemo.cpp b/Demos/RaytestDemo/RaytestDemo.cpp new file mode 100644 index 000000000..fa6aacdcd --- /dev/null +++ b/Demos/RaytestDemo/RaytestDemo.cpp @@ -0,0 +1,322 @@ +/* +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 "RaytestDemo.h" +#include "GlutStuff.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" + +#include //printf debugging +#include "GLDebugDrawer.h" +static GLDebugDrawer sDebugDraw; + + + +void RaytestDemo::castRays() +{ + + static float up = 0.f; + static float dir = 1.f; + //add some simple animation + if (!m_idle) + { + up+=0.01*dir; + + if (btFabs(up)>2) + { + dir*=-1.f; + } + + btTransform tr = m_dynamicsWorld->getCollisionObjectArray()[1]->getWorldTransform(); + static float angle = 0.f; + angle+=0.01f; + tr.setRotation(btQuaternion(btVector3(0,1,0),angle)); + m_dynamicsWorld->getCollisionObjectArray()[1]->setWorldTransform(tr); + } + + + ///step the simulation + if (m_dynamicsWorld) + { + + m_dynamicsWorld->updateAabbs(); + m_dynamicsWorld->computeOverlappingPairs(); + + btVector3 red(1,0,0); + btVector3 blue(0,0,1); + + ///all hits + { + btVector3 from(-30,1+up,0); + btVector3 to(30,1,0); + sDebugDraw.drawLine(from,to,btVector4(0,0,0,1)); + btCollisionWorld::AllHitsRayResultCallback allResults(from,to); + allResults.m_flags |= btTriangleRaycastCallback::kF_KeepUnflippedNormal; + m_dynamicsWorld->rayTest(from,to,allResults); + + for (int i=0;irayTest(from,to,closestResults); + + + if (closestResults.hasHit()) + { + + btVector3 p = from.lerp(to,closestResults.m_closestHitFraction); + sDebugDraw.drawSphere(p,0.1,blue); + sDebugDraw.drawLine(p,p+closestResults.m_hitNormalWorld,blue); + + } + } + } + +} + + +void RaytestDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + castRays(); + + if (m_dynamicsWorld) + { + float ms = getDeltaTimeMicroseconds(); + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + + m_dynamicsWorld->debugDrawWorld(); + } + + + + renderme(); + + glFlush(); + + swapBuffers(); + +} + + + +void RaytestDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + castRays(); + + renderme(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + swapBuffers(); +} + + + + + +void RaytestDemo::initPhysics() +{ + m_ele = 10; + m_azi = 75; + + setTexturing(true); + setShadows(true); + + setCameraDistance(btScalar(20.)); + + ///collision configuration contains default setup for memory, collision setup + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + //m_collisionConfiguration->setConvexConvexMultipointIterations(); + + ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + m_broadphase = new btDbvtBroadphase(); + + ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) + btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; + m_solver = sol; + + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld ->setDebugDrawer(&sDebugDraw); + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + ///create a few basic rigid bodies + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); +// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + { + btScalar mass(0.); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0,0,0); + if (isDynamic) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + + + { + btVector3 convexPoints[]={ btVector3(-1,-1,-1),btVector3(-1,-1,1),btVector3(-1,1,1),btVector3(-1,1,-1), + btVector3(2,0,0)}; + + btVector3 quad[] = { + btVector3(0,1,-1), + btVector3(0,1,1), + btVector3(0,-1,1), + btVector3(0,-1,-1)}; + + btTriangleMesh* mesh = new btTriangleMesh(); + mesh->addTriangle(quad[0],quad[1],quad[2],true); + mesh->addTriangle(quad[0],quad[2],quad[3],true); + + btBvhTriangleMeshShape* trimesh = new btBvhTriangleMeshShape(mesh,true,true); + +#define NUM_SHAPES 6 + btCollisionShape* colShapes[NUM_SHAPES] = { + trimesh, + new btConvexHullShape(&convexPoints[0].getX(),sizeof(convexPoints)/sizeof(btVector3),sizeof(btVector3)), + new btSphereShape(1), + new btCapsuleShape(0.2,1), + new btCylinderShape(btVector3(0.2,1,0.2)), + new btBoxShape(btVector3(1,1,1)) + }; + + for (int i=0;icalculateLocalInertia(mass,localInertia); + + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia); + rbInfo.m_startWorldTransform = startTransform; + btRigidBody* body = new btRigidBody(rbInfo); + + m_dynamicsWorld->addRigidBody(body); + + } + + } +} +void RaytestDemo::clientResetScene() +{ + exitPhysics(); + initPhysics(); +} + + +void RaytestDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int i; + for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + m_dynamicsWorld->removeCollisionObject( obj ); + delete obj; + } + + //delete collision shapes + for (int j=0;j m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + public: + + RaytestDemo() + { + } + virtual ~RaytestDemo() + { + exitPhysics(); + } + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + void castRays(); + virtual void displayCallback(); + virtual void clientResetScene(); + + static DemoApplication* Create() + { + RaytestDemo* demo = new RaytestDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + +}; + +#endif //BT_RAYTEST_DEMO_H + diff --git a/Demos/RaytestDemo/Win32RaytestDemo.cpp b/Demos/RaytestDemo/Win32RaytestDemo.cpp new file mode 100644 index 000000000..a55fb67eb --- /dev/null +++ b/Demos/RaytestDemo/Win32RaytestDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "BasicDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new BasicDemo(); +} + +#endif diff --git a/Demos/RaytestDemo/main.cpp b/Demos/RaytestDemo/main.cpp new file mode 100644 index 000000000..b951ad432 --- /dev/null +++ b/Demos/RaytestDemo/main.cpp @@ -0,0 +1,41 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 "RaytestDemo.h" +#include "GlutStuff.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + + + + + +int main(int argc,char** argv) +{ + + RaytestDemo ccdDemo; + ccdDemo.initPhysics(); + + +#ifdef CHECK_MEMORY_LEAKS + ccdDemo.exitPhysics(); +#else + return glutmain(argc, argv,1024,600,"Bullet Physics Demo. http://bulletphysics.org",&ccdDemo); +#endif + + //default glut doesn't return from mainloop + return 0; +} + diff --git a/Demos/premake4.lua b/Demos/premake4.lua index b0d874e13..e7f75972e 100644 --- a/Demos/premake4.lua +++ b/Demos/premake4.lua @@ -70,6 +70,7 @@ end "MultiMaterialDemo", "RagdollDemo", "Raytracer", + "RaytestDemo", "SimplexDemo", "SliderConstraintDemo", "TerrainDemo", diff --git a/build/vs2008.bat b/build/vs2008.bat index c516f8462..855a33d14 100644 --- a/build/vs2008.bat +++ b/build/vs2008.bat @@ -4,7 +4,7 @@ rem premake4 --no-pedemos vs2008 rem premake4 --no-bulletlibs --no-pelibs vs2008 rem premake4 --with-nacl vs2008 -premake4 --with-demos vs2008 +premake4 vs2008 pause \ No newline at end of file diff --git a/build/vs2010.bat b/build/vs2010.bat index c606584cb..8ffe31ddc 100644 --- a/build/vs2010.bat +++ b/build/vs2010.bat @@ -1,4 +1,4 @@ -premake4 --with-demos vs2010 +premake4 vs2010 pause \ No newline at end of file diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index f88234fe9..91f4c6200 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -208,6 +208,11 @@ void btCollisionWorld::updateAabbs() } +void btCollisionWorld::computeOverlappingPairs() +{ + BT_PROFILE("calculateOverlappingPairs"); + m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); +} void btCollisionWorld::performDiscreteCollisionDetection() { @@ -217,11 +222,7 @@ void btCollisionWorld::performDiscreteCollisionDetection() updateAabbs(); - { - BT_PROFILE("calculateOverlappingPairs"); - m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); - } - + computeOverlappingPairs(); btDispatcher* dispatcher = getDispatcher(); { @@ -456,6 +457,7 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,con : m_userCallback(user), m_i(i) { m_closestHitFraction = m_userCallback->m_closestHitFraction; + m_flags = m_userCallback->m_flags; } virtual bool needsCollision(btBroadphaseProxy* p) const { diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index 26220e160..9412242e8 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -144,6 +144,11 @@ public: void updateSingleAabb(btCollisionObject* colObj); virtual void updateAabbs(); + + ///the computeOverlappingPairs is usually already called by performDiscreteCollisionDetection (or stepSimulation) + ///it can be useful to use if you perform ray tests without collision detection/simulation + virtual void computeOverlappingPairs(); + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) { @@ -198,8 +203,8 @@ public: const btCollisionObject* m_collisionObject; short int m_collisionFilterGroup; short int m_collisionFilterMask; - //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback - unsigned int m_flags; + //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke. + unsigned int m_flags; virtual ~RayResultCallback() { @@ -214,8 +219,8 @@ public: m_collisionObject(0), m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), m_collisionFilterMask(btBroadphaseProxy::AllFilter), - //@BP Mod - m_flags(0) + //@BP Mod + m_flags(0) { } diff --git a/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp index fbe579ce1..786efd182 100644 --- a/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp +++ b/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp @@ -57,12 +57,13 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, { return ; // same sign } - //@BP Mod - Backface filtering - if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a > btScalar(0.0))) - { - // Backface, skip check - return; - } + + if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a <= btScalar(0.0))) + { + // Backface, skip check + return; + } + const btScalar proj_length=dist_a-dist_b; const btScalar distance = (dist_a)/(proj_length); @@ -97,18 +98,18 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) { - //@BP Mod - // Triangle normal isn't normalized + //@BP Mod + // Triangle normal isn't normalized triangleNormal.normalize(); - //@BP Mod - Allow for unflipped normal when raycasting against backfaces - if (((m_flags & kF_KeepUnflippedNormal) != 0) || (dist_a <= btScalar(0.0))) + //@BP Mod - Allow for unflipped normal when raycasting against backfaces + if (((m_flags & kF_KeepUnflippedNormal) == 0) && (dist_a <= btScalar(0.0))) { m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex); } else { - m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex); + m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex); } } }