diff --git a/Demos/CMakeLists.txt b/Demos/CMakeLists.txt index 5d71e358a..d71d84e23 100644 --- a/Demos/CMakeLists.txt +++ b/Demos/CMakeLists.txt @@ -1,4 +1,17 @@ -SUBDIRS( OpenGL BasicDemo Benchmarks Box2dDemo CollisionInterfaceDemo ConcaveDemo ConstraintDemo ConvexDecompositionDemo GimpactTestDemo GenericJointDemo SerializeDemo ) +SUBDIRS( +OpenGL +BasicDemo +Benchmarks +Box2dDemo +CollisionInterfaceDemo +ConcaveDemo +ConstraintDemo +ConvexDecompositionDemo +InternalEdgeDemo +GimpactTestDemo +GenericJointDemo +SerializeDemo +) #todo: re-enable the rest of the demos again diff --git a/Demos/CollisionInterfaceDemo/CMakeLists.txt b/Demos/CollisionInterfaceDemo/CMakeLists.txt index b97966ed1..406fecc21 100644 --- a/Demos/CollisionInterfaceDemo/CMakeLists.txt +++ b/Demos/CollisionInterfaceDemo/CMakeLists.txt @@ -25,6 +25,21 @@ IF (USE_GLUT) main.cpp ) + IF (WIN32) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppCollisionInterfaceDemo + 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 AppCollisionInterfaceDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF(WIN32) ELSE (USE_GLUT) INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL diff --git a/Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.cpp b/Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.cpp index ebfdc1515..857ef7ddc 100644 --- a/Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.cpp +++ b/Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.cpp @@ -36,12 +36,9 @@ const int numObjects = 2; GL_Simplex1to4 simplex; - btCollisionObject objects[maxNumObjects]; btCollisionWorld* collisionWorld = 0; -int screenWidth = 640; -int screenHeight = 480; GLDebugDrawer debugDrawer; diff --git a/Demos/CollisionInterfaceDemo/main.cpp b/Demos/CollisionInterfaceDemo/main.cpp index bb09a6a03..4c0f65120 100644 --- a/Demos/CollisionInterfaceDemo/main.cpp +++ b/Demos/CollisionInterfaceDemo/main.cpp @@ -3,6 +3,10 @@ #include "GlutStuff.h" #include "btBulletDynamicsCommon.h" +int screenWidth = 640; +int screenHeight = 480; + + int main(int argc,char** argv) { CollisionInterfaceDemo* collisionInterfaceDemo = new CollisionInterfaceDemo(); diff --git a/Demos/ConcaveDemo/CMakeLists.txt b/Demos/ConcaveDemo/CMakeLists.txt index ad973e811..deef32839 100644 --- a/Demos/ConcaveDemo/CMakeLists.txt +++ b/Demos/ConcaveDemo/CMakeLists.txt @@ -22,20 +22,20 @@ IF (USE_GLUT) ConcavePhysicsDemo.cpp main.cpp ) - IF (WIN32) - IF (CMAKE_CL_64) - ADD_CUSTOM_COMMAND( - TARGET AppConcaveDemo - 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 AppConcaveDemo - POST_BUILD - COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} - ) - ENDIF(CMAKE_CL_64) + IF (WIN32) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConcaveDemo + 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 AppConcaveDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) ENDIF(WIN32) ELSE (USE_GLUT) diff --git a/Demos/InternalEdgeDemo/CMakeLists.txt b/Demos/InternalEdgeDemo/CMakeLists.txt new file mode 100644 index 000000000..826dd6780 --- /dev/null +++ b/Demos/InternalEdgeDemo/CMakeLists.txt @@ -0,0 +1,60 @@ +# 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. + + + +# You shouldn't have to modify anything below this line +######################################################## + +IF (USE_GLUT) + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppInternalEdgeDemo + InternalEdgeDemo.cpp + InternalEdgeDemo.h + main.cpp + ) + IF (WIN32) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET InternalEdgeDemo + 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 InternalEdgeDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF(WIN32) +ELSE (USE_GLUT) + + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppInternalEdgeDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + InternalEdgeDemo.cpp + InternalEdgeDemo.h + Win32InternalEdgeDemo.cpp + ) + +ENDIF (USE_GLUT) + diff --git a/Demos/InternalEdgeDemo/InternalEdgeDemo.cpp b/Demos/InternalEdgeDemo/InternalEdgeDemo.cpp new file mode 100644 index 000000000..9a9c58272 --- /dev/null +++ b/Demos/InternalEdgeDemo/InternalEdgeDemo.cpp @@ -0,0 +1,565 @@ +/* +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 SHIFT_INDICES 1 +#define SWAP_WINDING 1 +//#define ROTATE_GROUND 1 +bool enable=true; + +#if defined (SHIFT_INDICES) && !defined (SWAP_WINDING) +//#define TEST_INCONSISTENT_WINDING +#endif + + +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h" + + +#include "LinearMath/btIDebugDraw.h" +#include "GLDebugDrawer.h" +#include "InternalEdgeDemo.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "GLDebugDrawer.h" +GLDebugDrawer gDebugDrawer; + +static btVector3* gVertices=0; +static int* gIndices=0; +static btBvhTriangleMeshShape* trimeshShape =0; +static btRigidBody* staticBody = 0; +static float waveheight = 0.f; + +const float TRIANGLE_SIZE=20.f; + + + +///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedFriction(float friction0,float friction1) +{ + return 0.f; + btScalar friction = friction0 * friction1; + + const btScalar MAX_FRICTION = 10.f; + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +inline btScalar calculateCombinedRestitution(float restitution0,float restitution1) +{ + return restitution0 * restitution1; +} + + +/////////////////////////////////////////////////////////////// + + +static bool CustomMaterialCombinerCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) +{ + + if (enable) + { + btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1); + } + + float friction0 = colObj0->getFriction(); + float friction1 = colObj1->getFriction(); + float restitution0 = colObj0->getRestitution(); + float restitution1 = colObj1->getRestitution(); + + if (colObj0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) + { + friction0 = 1.0;//partId0,index0 + restitution0 = 0.f; + } + if (colObj1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) + { + if (index1&1) + { + friction1 = 1.0f;//partId1,index1 + } else + { + friction1 = 0.f; + } + restitution1 = 0.f; + } + + cp.m_combinedFriction = calculateCombinedFriction(friction0,friction1); + cp.m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1); + + //this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction + return true; +} + +extern ContactAddedCallback gContactAddedCallback; + + const int NUM_VERTS_X = 2; + const int NUM_VERTS_Y = 2; + const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + +void InternalEdgeDemo::setVertexPositions(float waveheight, float offset) +{ + int i; + int j; + + for ( i=0;isetCollisionFlags( staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->setActivationState(DISABLE_DEACTIVATION); + } else + { + staticBody->setCollisionFlags( staticBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->forceActivationState(ACTIVE_TAG); + } + } + + DemoApplication::keyboardCallback(key,x,y); + +} + + + +void InternalEdgeDemo::initPhysics() +{ + + setTexturing(true); + setShadows(false);//true); + + #define TRISIZE 10.f + + gContactAddedCallback = CustomMaterialCombinerCallback; + +#define USE_TRIMESH_SHAPE 1 +#ifdef USE_TRIMESH_SHAPE + + int vertStride = sizeof(btVector3); + int indexStride = 3*sizeof(int); + + + const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); + + gVertices = new btVector3[totalVerts]; + gIndices = new int[totalTriangles*3]; + + int i; + + + setVertexPositions(waveheight,0.f); + + + //gVertices[1].setY(21.1); + //gVertices[1].setY(121.1); + gVertices[1].setY(.1); + +#ifdef ROTATE_GROUND + //gVertices[1].setY(-1.1); +#else + //gVertices[1].setY(0.1); + //gVertices[1].setY(-0.1); + //gVertices[1].setY(-20.1); + //gVertices[1].setY(-20); +#endif + + int index=0; + for ( i=0;igetOptimizedBvh()->calculateSerializeBufferSize(); + buffer = btAlignedAlloc(numBytes,16); + bool swapEndian = false; + trimeshShape->getOptimizedBvh()->serialize(buffer,numBytes,swapEndian); + FILE* file = fopen("bvh.bin","wb"); + fwrite(buffer,1,numBytes,file); + fclose(file); + btAlignedFree(buffer); + + + +#else + + trimeshShape = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,false); + + char* fileName = "bvh.bin"; + + FILE* file = fopen(fileName,"rb"); + int size=0; + btOptimizedBvh* bvh = 0; + + if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */ + printf("Error: cannot get filesize from %s\n", fileName); + exit(0); + } else + { + + fseek(file, 0, SEEK_SET); + + int buffersize = size+btOptimizedBvh::getAlignmentSerializationPadding(); + + void* buffer = btAlignedAlloc(buffersize,16); + int read = fread(buffer,1,size,file); + fclose(file); + bool swapEndian = false; + bvh = btOptimizedBvh::deSerializeInPlace(buffer,buffersize,swapEndian); + } + + trimeshShape->setOptimizedBvh(bvh); + +#endif + + btCollisionShape* groundShape = trimeshShape; + + btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap(); + + + btGenerateInternalEdgeInfo(trimeshShape,triangleInfoMap); + + + +#else + btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50)); + + m_collisionShapes.push_back(groundShape); + +#endif //USE_TRIMESH_SHAPE + + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + m_collisionConfiguration->setConvexConvexMultipointIterations(10,5); + + + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + + btVector3 worldMin(-1000,-1000,-1000); + btVector3 worldMax(1000,1000,1000); + m_broadphase = new btAxisSweep3(worldMin,worldMax); + m_solver = new btSequentialImpulseConstraintSolver(); + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld->getSolverInfo().m_splitImpulse = true; + m_dynamicsWorld->getSolverInfo().m_splitImpulsePenetrationThreshold = 1e30f; + m_dynamicsWorld->getSolverInfo().m_maxErrorReduction = 1e30; + m_dynamicsWorld->getSolverInfo().m_erp =1.f; + m_dynamicsWorld->getSolverInfo().m_erp2 = 1.f; + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + + float mass = 0.f; + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,-2,0)); + + btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1)); + //colShape->setMargin(0.f); + colShape->setMargin(0.1f); + + + m_collisionShapes.push_back(colShape); + + { + for (int i=0;i<1;i++) + { + startTransform.setOrigin(btVector3(-10+i*3,1+i*0.1,-1.3)); + btRigidBody* body = localCreateRigidBody(100, startTransform,colShape); + body->setLinearVelocity(btVector3(0,0,-1)); + } + } + + startTransform.setIdentity(); +#ifdef ROTATE_GROUND + btQuaternion orn(btVector3(0,0,1),SIMD_PI); + startTransform.setOrigin(btVector3(-20,0,0)); + startTransform.setRotation(orn); +#endif //ROTATE_GROUND + + staticBody = localCreateRigidBody(mass, startTransform,groundShape); + //staticBody->setContactProcessingThreshold(-0.031f); + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);//STATIC_OBJECT); + + //enable custom material callback + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + + getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btSetDebugDrawer(&gDebugDrawer); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + +} + + +void InternalEdgeDemo::clientResetScene() +{ + DemoApplication::clientResetScene(); + for (int i=0;igetNumCollisionObjects();i++) + { + btCollisionObject* colobj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(colobj); + if (body && body->getInvMass() != 0.f) + { + + body->setLinearVelocity(btVector3(0,0,-1)); + } + + } +} + +void InternalEdgeDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + if (m_animatedMesh) + { + static float offset=0.f; + offset+=0.01f; + + // setVertexPositions(waveheight,offset); +#if 0 ///not currently supported, we need to update the btInternalTriangleInfoMap + int i; + int j; + btVector3 aabbMin(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + btVector3 aabbMax(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + + for ( i=NUM_VERTS_X/2-3;ipartialRefitTree(aabbMin,aabbMax); +#else + btVector3 aabbMin,aabbMax; + trimeshShape->getMeshInterface()->calculateAabbBruteForce(aabbMin,aabbMax); + trimeshShape->refitTree(aabbMin,aabbMax); + +#endif + + //clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation. + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(staticBody->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + } + + + + //m_dynamicsWorld->stepSimulation(dt); + ///enable one of the following to debug (render debug lines each frame) + //m_dynamicsWorld->stepSimulation(1./800.,0); + m_dynamicsWorld->stepSimulation(1./60.,100,1./800.); + //m_dynamicsWorld->stepSimulation(1./60.,0); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + + renderme(); + + glFlush(); + glutSwapBuffers(); + +} + + + + +void InternalEdgeDemo::displayCallback(void) { + + clientMoveAndDisplay(); + /* + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + + glFlush(); + glutSwapBuffers(); + */ + +} + + + +void InternalEdgeDemo::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; + + btTriangleIndexVertexArray* m_indexVertexArrays; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + bool m_animatedMesh; + + public: + + InternalEdgeDemo() : m_animatedMesh(true) + { + + } + void initPhysics(); + + void exitPhysics(); + + virtual ~InternalEdgeDemo() + { + exitPhysics(); + } + + virtual void clientResetScene(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + //to show refit works + void setVertexPositions(float waveheight, float offset); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + static DemoApplication* Create() + { + InternalEdgeDemo* demo = new InternalEdgeDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + }; +}; + +#endif //CONCAVE_DEMO_H + diff --git a/Demos/InternalEdgeDemo/Win32InternalEdgeDemo.cpp b/Demos/InternalEdgeDemo/Win32InternalEdgeDemo.cpp new file mode 100644 index 000000000..e91d9f7c0 --- /dev/null +++ b/Demos/InternalEdgeDemo/Win32InternalEdgeDemo.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 "InternalEdgeDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new InternalEdgeDemo.cpp(); +} + +#endif diff --git a/Demos/InternalEdgeDemo/main.cpp b/Demos/InternalEdgeDemo/main.cpp new file mode 100644 index 000000000..596ecb385 --- /dev/null +++ b/Demos/InternalEdgeDemo/main.cpp @@ -0,0 +1,19 @@ + +#include "InternalEdgeDemo.h" +#include "GlutStuff.h" + +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + + +int main(int argc,char** argv) +{ + + InternalEdgeDemo* internalEdgeDemo = new InternalEdgeDemo(); + internalEdgeDemo->initPhysics(); + internalEdgeDemo->setCameraDistance(30.f); + + + return glutmain(argc, argv,640,480,"Internal Edge Demo",internalEdgeDemo); +} + diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index 831f319f3..5a2bdacee 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -938,6 +938,16 @@ public: wv0 = m_worldTrans*triangle[0]; wv1 = m_worldTrans*triangle[1]; wv2 = m_worldTrans*triangle[2]; + btVector3 center = (wv0+wv1+wv2)*btScalar(1./3.); + + btVector3 normal = (wv1-wv0).cross(wv2-wv0); + normal.normalize(); + btVector3 normalColor(1,1,0); + m_debugDrawer->drawLine(center,center+normal,normalColor); + + + + m_debugDrawer->drawLine(wv0,wv1,m_color); m_debugDrawer->drawLine(wv1,wv2,m_color); m_debugDrawer->drawLine(wv2,wv0,m_color); diff --git a/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp index 20c0bc522..7601efd89 100644 --- a/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp +++ b/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp @@ -6,6 +6,11 @@ #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" #include "LinearMath/btIDebugDraw.h" +//#define DEBUG_INTERNAL_EDGE + +#ifdef DEBUG_INTERNAL_EDGE +#include +#endif //DEBUG_INTERNAL_EDGE #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW @@ -79,9 +84,9 @@ struct btConnectivityProcessor : public btTriangleCallback triangle[2].getX(),triangle[2].getY(),triangle[2].getZ()); #endif - for (int j=0;j<3;j++) + for (int i=0;i<3;i++) { - for (int i=0;i<3;i++) + for (int j=0;j<3;j++) { if ( (m_triangleVerticesA[i]-triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold) { @@ -128,6 +133,7 @@ struct btConnectivityProcessor : public btTriangleCallback int sumvertsA = sharedVertsA[0]+sharedVertsA[1]; int otherIndexA = 3-sumvertsA; + btVector3 edge(m_triangleVerticesA[sharedVertsA[1]]-m_triangleVerticesA[sharedVertsA[0]]); btTriangleShape tA(m_triangleVerticesA[0],m_triangleVerticesA[1],m_triangleVerticesA[2]); @@ -208,12 +214,22 @@ struct btConnectivityProcessor : public btTriangleCallback case 1: { btVector3 edge = m_triangleVerticesA[0]-m_triangleVerticesA[1]; - btQuaternion orn(edge,correctedAngle); + btQuaternion orn(edge,-correctedAngle); btVector3 computedNormalB = quatRotate(orn,normalA); - if (computedNormalB.dot(calculatedNormalB)<0) + btScalar bla = computedNormalB.dot(normalB); + if (bla<0) + { + computedNormalB*=-1; info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB; + } +#ifdef DEBUG_INTERNAL_EDGE + if ((computedNormalB-normalB).length()>0.0001) + { + printf("warning: normals not identical\n"); + } +#endif//DEBUG_INTERNAL_EDGE - info->m_edgeV0V1Angle = correctedAngle; + info->m_edgeV0V1Angle = -correctedAngle; if (isConvex) info->m_flags |= TRI_INFO_V0V1_CONVEX; @@ -222,12 +238,21 @@ struct btConnectivityProcessor : public btTriangleCallback case 2: { btVector3 edge = m_triangleVerticesA[2]-m_triangleVerticesA[0]; - btQuaternion orn(edge,correctedAngle); + btQuaternion orn(edge,-correctedAngle); btVector3 computedNormalB = quatRotate(orn,normalA); - if (computedNormalB.dot(calculatedNormalB)<0) + if (computedNormalB.dot(normalB)<0) + { + computedNormalB*=-1; info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB; + } - info->m_edgeV2V0Angle = correctedAngle; +#ifdef DEBUG_INTERNAL_EDGE + if ((computedNormalB-normalB).length()>0.0001) + { + printf("warning: normals not identical\n"); + } +#endif //DEBUG_INTERNAL_EDGE + info->m_edgeV2V0Angle = -correctedAngle; if (isConvex) info->m_flags |= TRI_INFO_V2V0_CONVEX; break; @@ -235,12 +260,20 @@ struct btConnectivityProcessor : public btTriangleCallback case 3: { btVector3 edge = m_triangleVerticesA[1]-m_triangleVerticesA[2]; - btQuaternion orn(edge,correctedAngle); + btQuaternion orn(edge,-correctedAngle); btVector3 computedNormalB = quatRotate(orn,normalA); - if (computedNormalB.dot(calculatedNormalB)<0) + if (computedNormalB.dot(normalB)<0) + { info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB; - - info->m_edgeV1V2Angle = correctedAngle; + computedNormalB*=-1; + } +#ifdef DEBUG_INTERNAL_EDGE + if ((computedNormalB-normalB).length()>0.0001) + { + printf("warning: normals not identical\n"); + } +#endif //DEBUG_INTERNAL_EDGE + info->m_edgeV1V2Angle = -correctedAngle; if (isConvex) info->m_flags |= TRI_INFO_V1V2_CONVEX; @@ -371,30 +404,26 @@ bool btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const b btVector3 edgeCross = edge.cross(tri_normal).normalize(); btScalar curAngle = btGetAngle(edgeCross,tri_normal,localContactNormalOnB); + + if (correctedEdgeAngle<0) { - if (curAngle < -correctedEdgeAngle) + if (curAngle < correctedEdgeAngle) { btScalar diffAngle = correctedEdgeAngle-curAngle; btQuaternion rotation(edge,diffAngle ); clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; return true; + } + } - } else + if (correctedEdgeAngle>=0) + { + if (curAngle > correctedEdgeAngle) { - if (curAngle < correctedEdgeAngle) - { - //printf("angle within valid convex range, don't clamp it!\n"); - return false; - } else - { - // printf("too large angle\n"); - btScalar diffAngle = correctedEdgeAngle-curAngle; - - btQuaternion rotation(edge,diffAngle ); - clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; - //clamp it? - return true; - } + btScalar diffAngle = correctedEdgeAngle-curAngle; + btQuaternion rotation(edge,diffAngle ); + clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; + return true; } } return false; @@ -482,12 +511,20 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* btVector3 computedNormalB = quatRotate(orn,tri_normal); if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB) computedNormalB*=-1; - btVector3 nB = computedNormalB; + btVector3 nB = swapFactor*computedNormalB; btScalar NdotA = localContactNormalOnB.dot(nA); btScalar NdotB = localContactNormalOnB.dot(nB); bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotBm_convexEpsilon); +#ifdef DEBUG_INTERNAL_EDGE + { + + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); + } +#endif //DEBUG_INTERNAL_EDGE + + if (backFacingNormal) { numConcaveEdgeHits++; @@ -496,7 +533,7 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* { numConvexEdgeHits++; btVector3 clampedLocalNormal; - bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, swapFactor*info->m_edgeV0V1Angle,clampedLocalNormal); + bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV0V1Angle,clampedLocalNormal); if (isClamped) { btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; @@ -553,7 +590,14 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* btVector3 computedNormalB = quatRotate(orn,tri_normal); if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB) computedNormalB*=-1; - btVector3 nB = computedNormalB; + btVector3 nB = swapFactor*computedNormalB; + +#ifdef DEBUG_INTERNAL_EDGE + { + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); + } +#endif //DEBUG_INTERNAL_EDGE + btScalar NdotA = localContactNormalOnB.dot(nA); btScalar NdotB = localContactNormalOnB.dot(nB); @@ -568,7 +612,7 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* numConvexEdgeHits++; btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; btVector3 clampedLocalNormal; - bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, swapFactor*info->m_edgeV1V2Angle,clampedLocalNormal); + bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV1V2Angle,clampedLocalNormal); if (isClamped) { btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; @@ -622,7 +666,13 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* btVector3 computedNormalB = quatRotate(orn,tri_normal); if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB) computedNormalB*=-1; - btVector3 nB = computedNormalB; + btVector3 nB = swapFactor*computedNormalB; + +#ifdef DEBUG_INTERNAL_EDGE + { + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); + } +#endif //DEBUG_INTERNAL_EDGE btScalar NdotA = localContactNormalOnB.dot(nA); btScalar NdotB = localContactNormalOnB.dot(nB); @@ -640,7 +690,7 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; btVector3 clampedLocalNormal; - bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,swapFactor* info->m_edgeV2V0Angle,clampedLocalNormal); + bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,info->m_edgeV2V0Angle,clampedLocalNormal); if (isClamped) { btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; @@ -657,6 +707,12 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* } } +#ifdef DEBUG_INTERNAL_EDGE + { + btVector3 color(0,1,1); + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+cp.m_normalWorldOnB*10,color); + } +#endif //DEBUG_INTERNAL_EDGE if (isNearEdge) { diff --git a/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h index 3cd88147a..e7e25e609 100644 --- a/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h +++ b/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h @@ -75,7 +75,7 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* ///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly. ///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap -#define BT_INTERNAL_EDGE_DEBUG_DRAW +//#define BT_INTERNAL_EDGE_DEBUG_DRAW #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW void btSetDebugDrawer(btIDebugDraw* debugDrawer);