rename ObsoleteDemos back to Demos
fix some relative path issues for loading assets
This commit is contained in:
59
Demos/CharacterDemo/CMakeLists.txt
Normal file
59
Demos/CharacterDemo/CMakeLists.txt
Normal file
@@ -0,0 +1,59 @@
|
||||
# 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
|
||||
########################################################
|
||||
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
../OpenGL
|
||||
${GLUT_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
LINK_LIBRARIES(
|
||||
OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}
|
||||
)
|
||||
SET(CharacterDemo_SRCS
|
||||
|
||||
DynamicCharacterController.cpp
|
||||
DynamicCharacterController.h
|
||||
CharacterDemo.cpp
|
||||
CharacterDemo.h
|
||||
../BspDemo/BspConverter.cpp
|
||||
../BspDemo/BspConverter.h
|
||||
../BspDemo/BspLoader.cpp
|
||||
../BspDemo/BspLoader.h
|
||||
main.cpp
|
||||
)
|
||||
|
||||
IF (WIN32)
|
||||
ADD_EXECUTABLE(AppCharacterDemo
|
||||
${CharacterDemo_SRCS}
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/build3/bullet.rc
|
||||
)
|
||||
ELSE()
|
||||
ADD_EXECUTABLE(AppCharacterDemo
|
||||
${CharacterDemo_SRCS}
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ADD_CUSTOM_COMMAND(
|
||||
TARGET AppCharacterDemo
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/BspDemo/BspDemo.bsp ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
|
||||
|
||||
|
||||
IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
|
||||
SET_TARGET_PROPERTIES(AppCharacterDemo PROPERTIES DEBUG_POSTFIX "_Debug")
|
||||
SET_TARGET_PROPERTIES(AppCharacterDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel")
|
||||
SET_TARGET_PROPERTIES(AppCharacterDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo")
|
||||
ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
|
||||
526
Demos/CharacterDemo/CharacterDemo.cpp
Normal file
526
Demos/CharacterDemo/CharacterDemo.cpp
Normal file
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
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 "btBulletDynamicsCommon.h"
|
||||
#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||
|
||||
#include "GLDebugDrawer.h"
|
||||
#include <stdio.h> //printf debugging
|
||||
|
||||
#include "GL_ShapeDrawer.h"
|
||||
|
||||
#include "GlutStuff.h"
|
||||
#include "CharacterDemo.h"
|
||||
#ifdef DYNAMIC_CHARACTER_CONTROLLER
|
||||
#include "DynamicCharacterController.h"
|
||||
#else
|
||||
#include "BulletDynamics/Character/btKinematicCharacterController.h"
|
||||
#endif
|
||||
|
||||
const int maxProxies = 32766;
|
||||
const int maxOverlap = 65535;
|
||||
|
||||
static int gForward = 0;
|
||||
static int gBackward = 0;
|
||||
static int gLeft = 0;
|
||||
static int gRight = 0;
|
||||
static int gJump = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
CharacterDemo::CharacterDemo()
|
||||
:
|
||||
m_indexVertexArrays(0),
|
||||
m_vertices(0),
|
||||
m_cameraHeight(4.f),
|
||||
m_minCameraDistance(3.f),
|
||||
m_maxCameraDistance(10.f)
|
||||
{
|
||||
m_character = 0;
|
||||
m_cameraPosition = btVector3(30,30,30);
|
||||
}
|
||||
|
||||
|
||||
void CharacterDemo::initPhysics()
|
||||
{
|
||||
btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50));
|
||||
m_collisionShapes.push_back(groundShape);
|
||||
m_collisionConfiguration = new btDefaultCollisionConfiguration();
|
||||
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
|
||||
btVector3 worldMin(-1000,-1000,-1000);
|
||||
btVector3 worldMax(1000,1000,1000);
|
||||
btAxisSweep3* sweepBP = new btAxisSweep3(worldMin,worldMax);
|
||||
m_overlappingPairCache = sweepBP;
|
||||
|
||||
m_constraintSolver = new btSequentialImpulseConstraintSolver();
|
||||
m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration);
|
||||
m_dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration=0.0001f;
|
||||
|
||||
#ifdef DYNAMIC_CHARACTER_CONTROLLER
|
||||
m_character = new DynamicCharacterController ();
|
||||
#else
|
||||
|
||||
btTransform startTransform;
|
||||
startTransform.setIdentity ();
|
||||
//startTransform.setOrigin (btVector3(0.0, 4.0, 0.0));
|
||||
startTransform.setOrigin (btVector3(10.210098,-1.6433364,16.453260));
|
||||
|
||||
|
||||
m_ghostObject = new btPairCachingGhostObject();
|
||||
m_ghostObject->setWorldTransform(startTransform);
|
||||
sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
|
||||
btScalar characterHeight=1.75;
|
||||
btScalar characterWidth =1.75;
|
||||
btConvexShape* capsule = new btCapsuleShape(characterWidth,characterHeight);
|
||||
m_ghostObject->setCollisionShape (capsule);
|
||||
m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);
|
||||
|
||||
btScalar stepHeight = btScalar(0.35);
|
||||
m_character = new btKinematicCharacterController (m_ghostObject,capsule,stepHeight);
|
||||
#endif
|
||||
|
||||
////////////////
|
||||
|
||||
/// Create some basic environment from a Quake level
|
||||
|
||||
//m_dynamicsWorld->setGravity(btVector3(0,0,0));
|
||||
btTransform tr;
|
||||
tr.setIdentity();
|
||||
|
||||
const char* filename = "BspDemo.bsp";
|
||||
|
||||
const char* prefix[]={"./","../","../../","../../../","../../../../", "BspDemo/", "Demos/BspDemo/",
|
||||
"../Demos/BspDemo/","../../Demos/BspDemo/"};
|
||||
int numPrefixes = sizeof(prefix)/sizeof(const char*);
|
||||
char relativeFileName[1024];
|
||||
FILE* file=0;
|
||||
|
||||
for (int i=0;i<numPrefixes;i++)
|
||||
{
|
||||
sprintf(relativeFileName,"%s%s",prefix[i],filename);
|
||||
file = fopen(relativeFileName,"r");
|
||||
if (file)
|
||||
break;
|
||||
}
|
||||
void* memoryBuffer = 0;
|
||||
|
||||
|
||||
if (file)
|
||||
{
|
||||
BspLoader bspLoader;
|
||||
int size=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);
|
||||
} else
|
||||
{
|
||||
//how to detect file size?
|
||||
memoryBuffer = malloc(size+1);
|
||||
fread(memoryBuffer,1,size,file);
|
||||
bspLoader.loadBSPFile( memoryBuffer);
|
||||
|
||||
BspToBulletConverter bsp2bullet(this);
|
||||
float bspScaling = 0.1f;
|
||||
bsp2bullet.convertBsp(bspLoader,bspScaling);
|
||||
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
///only collide with static for now (no interaction with dynamic objects)
|
||||
m_dynamicsWorld->addCollisionObject(m_ghostObject,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
|
||||
|
||||
m_dynamicsWorld->addAction(m_character);
|
||||
|
||||
|
||||
///////////////
|
||||
|
||||
clientResetScene();
|
||||
|
||||
setCameraDistance(56.f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//to be implemented by the demo
|
||||
void CharacterDemo::renderme()
|
||||
{
|
||||
updateCamera();
|
||||
|
||||
DemoApplication::renderme();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CharacterDemo::debugDrawContacts()
|
||||
{
|
||||
// printf("numPairs = %d\n",m_customPairCallback->getOverlappingPairArray().size());
|
||||
{
|
||||
btManifoldArray manifoldArray;
|
||||
btBroadphasePairArray& pairArray = m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray();
|
||||
int numPairs = pairArray.size();
|
||||
|
||||
for (int i=0;i<numPairs;i++)
|
||||
{
|
||||
manifoldArray.clear();
|
||||
|
||||
const btBroadphasePair& pair = pairArray[i];
|
||||
|
||||
btBroadphasePair* collisionPair = m_overlappingPairCache->getOverlappingPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
|
||||
if (!collisionPair)
|
||||
continue;
|
||||
|
||||
if (collisionPair->m_algorithm)
|
||||
collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
|
||||
|
||||
for (int j=0;j<manifoldArray.size();j++)
|
||||
{
|
||||
btPersistentManifold* manifold = manifoldArray[j];
|
||||
for (int p=0;p<manifold->getNumContacts();p++)
|
||||
{
|
||||
const btManifoldPoint&pt = manifold->getContactPoint(p);
|
||||
|
||||
btVector3 color(255,255,255);
|
||||
m_dynamicsWorld->getDebugDrawer()->drawContactPoint(pt.getPositionWorldOnB(),pt.m_normalWorldOnB,pt.getDistance(),pt.getLifeTime(),color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CharacterDemo::clientMoveAndDisplay()
|
||||
{
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
float dt = getDeltaTimeMicroseconds() * 0.000001f;
|
||||
|
||||
/* Character stuff &*/
|
||||
if (m_character)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
debugDrawContacts();
|
||||
|
||||
|
||||
if (m_dynamicsWorld)
|
||||
{
|
||||
//during idle mode, just run 1 simulation step maximum
|
||||
int maxSimSubSteps = m_idle ? 1 : 2;
|
||||
if (m_idle)
|
||||
dt = 1.0/420.f;
|
||||
|
||||
///set walkDirection for our character
|
||||
btTransform xform;
|
||||
xform = m_ghostObject->getWorldTransform ();
|
||||
|
||||
btVector3 forwardDir = xform.getBasis()[2];
|
||||
// printf("forwardDir=%f,%f,%f\n",forwardDir[0],forwardDir[1],forwardDir[2]);
|
||||
btVector3 upDir = xform.getBasis()[1];
|
||||
btVector3 strafeDir = xform.getBasis()[0];
|
||||
forwardDir.normalize ();
|
||||
upDir.normalize ();
|
||||
strafeDir.normalize ();
|
||||
|
||||
btVector3 walkDirection = btVector3(0.0, 0.0, 0.0);
|
||||
btScalar walkVelocity = btScalar(1.1) * 4.0; // 4 km/h -> 1.1 m/s
|
||||
btScalar walkSpeed = walkVelocity * dt;
|
||||
|
||||
//rotate view
|
||||
if (gLeft)
|
||||
{
|
||||
btMatrix3x3 orn = m_ghostObject->getWorldTransform().getBasis();
|
||||
orn *= btMatrix3x3(btQuaternion(btVector3(0,1,0),0.01));
|
||||
m_ghostObject->getWorldTransform ().setBasis(orn);
|
||||
}
|
||||
|
||||
if (gRight)
|
||||
{
|
||||
btMatrix3x3 orn = m_ghostObject->getWorldTransform().getBasis();
|
||||
orn *= btMatrix3x3(btQuaternion(btVector3(0,1,0),-0.01));
|
||||
m_ghostObject->getWorldTransform ().setBasis(orn);
|
||||
}
|
||||
|
||||
if (gForward)
|
||||
walkDirection += forwardDir;
|
||||
|
||||
if (gBackward)
|
||||
walkDirection -= forwardDir;
|
||||
|
||||
|
||||
m_character->setWalkDirection(walkDirection*walkSpeed);
|
||||
|
||||
|
||||
int numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps);
|
||||
|
||||
//optional but useful: debug drawing
|
||||
if (m_dynamicsWorld)
|
||||
m_dynamicsWorld->debugDrawWorld();
|
||||
|
||||
//#define VERBOSE_FEEDBACK
|
||||
#ifdef VERBOSE_FEEDBACK
|
||||
if (!numSimSteps)
|
||||
printf("Interpolated transforms\n");
|
||||
else
|
||||
{
|
||||
if (numSimSteps > maxSimSubSteps)
|
||||
{
|
||||
//detect dropping frames
|
||||
printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps);
|
||||
} else
|
||||
{
|
||||
printf("Simulated (%i) steps\n",numSimSteps);
|
||||
}
|
||||
}
|
||||
#endif //VERBOSE_FEEDBACK
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef USE_QUICKPROF
|
||||
btProfiler::beginBlock("render");
|
||||
#endif //USE_QUICKPROF
|
||||
|
||||
|
||||
renderme();
|
||||
|
||||
#ifdef USE_QUICKPROF
|
||||
btProfiler::endBlock("render");
|
||||
#endif
|
||||
|
||||
|
||||
glFlush();
|
||||
glutSwapBuffers();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CharacterDemo::displayCallback(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
renderme();
|
||||
|
||||
//optional but useful: debug drawing
|
||||
if (m_dynamicsWorld)
|
||||
m_dynamicsWorld->debugDrawWorld();
|
||||
|
||||
debugDrawContacts();
|
||||
|
||||
glFlush();
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
void CharacterDemo::clientResetScene()
|
||||
{
|
||||
m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_ghostObject->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher());
|
||||
|
||||
m_character->reset (m_dynamicsWorld);
|
||||
///WTF
|
||||
m_character->warp (btVector3(10.210001,-2.0306311,16.576973));
|
||||
|
||||
}
|
||||
|
||||
void CharacterDemo::specialKeyboardUp(int key, int x, int y)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case GLUT_KEY_UP:
|
||||
{
|
||||
gForward = 0;
|
||||
}
|
||||
break;
|
||||
case GLUT_KEY_DOWN:
|
||||
{
|
||||
gBackward = 0;
|
||||
}
|
||||
break;
|
||||
case GLUT_KEY_LEFT:
|
||||
{
|
||||
gLeft = 0;
|
||||
}
|
||||
break;
|
||||
case GLUT_KEY_RIGHT:
|
||||
{
|
||||
gRight = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DemoApplication::specialKeyboardUp(key,x,y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CharacterDemo::specialKeyboard(int key, int x, int y)
|
||||
{
|
||||
|
||||
// printf("key = %i x=%i y=%i\n",key,x,y);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case GLUT_KEY_UP:
|
||||
{
|
||||
gForward = 1;
|
||||
}
|
||||
break;
|
||||
case GLUT_KEY_DOWN:
|
||||
{
|
||||
gBackward = 1;
|
||||
}
|
||||
break;
|
||||
case GLUT_KEY_LEFT:
|
||||
{
|
||||
gLeft = 1;
|
||||
}
|
||||
break;
|
||||
case GLUT_KEY_RIGHT:
|
||||
{
|
||||
gRight = 1;
|
||||
}
|
||||
break;
|
||||
case GLUT_KEY_F1:
|
||||
{
|
||||
if (m_character && m_character->canJump())
|
||||
gJump = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DemoApplication::specialKeyboard(key,x,y);
|
||||
break;
|
||||
}
|
||||
|
||||
// glutPostRedisplay();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CharacterDemo::updateCamera()
|
||||
{
|
||||
|
||||
//#define DISABLE_CAMERA 1
|
||||
#ifdef DISABLE_CAMERA
|
||||
DemoApplication::updateCamera();
|
||||
return;
|
||||
#endif //DISABLE_CAMERA
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
btTransform characterWorldTrans;
|
||||
|
||||
//look at the vehicle
|
||||
characterWorldTrans = m_ghostObject->getWorldTransform();
|
||||
btVector3 up = characterWorldTrans.getBasis()[1];
|
||||
btVector3 backward = -characterWorldTrans.getBasis()[2];
|
||||
up.normalize ();
|
||||
backward.normalize ();
|
||||
|
||||
m_cameraTargetPosition = characterWorldTrans.getOrigin();
|
||||
m_cameraPosition = m_cameraTargetPosition + up * 10.0 + backward * 12.0;
|
||||
|
||||
//use the convex sweep test to find a safe position for the camera (not blocked by static geometry)
|
||||
btSphereShape cameraSphere(0.2f);
|
||||
btTransform cameraFrom,cameraTo;
|
||||
cameraFrom.setIdentity();
|
||||
cameraFrom.setOrigin(characterWorldTrans.getOrigin());
|
||||
cameraTo.setIdentity();
|
||||
cameraTo.setOrigin(m_cameraPosition);
|
||||
|
||||
btCollisionWorld::ClosestConvexResultCallback cb( characterWorldTrans.getOrigin(), cameraTo.getOrigin() );
|
||||
cb.m_collisionFilterMask = btBroadphaseProxy::StaticFilter;
|
||||
|
||||
m_dynamicsWorld->convexSweepTest(&cameraSphere,cameraFrom,cameraTo,cb);
|
||||
if (cb.hasHit())
|
||||
{
|
||||
|
||||
btScalar minFraction = cb.m_closestHitFraction;//btMax(btScalar(0.3),cb.m_closestHitFraction);
|
||||
m_cameraPosition.setInterpolate3(cameraFrom.getOrigin(),cameraTo.getOrigin(),minFraction);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//update OpenGL camera settings
|
||||
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10000.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
gluLookAt(m_cameraPosition[0],m_cameraPosition[1],m_cameraPosition[2],
|
||||
m_cameraTargetPosition[0],m_cameraTargetPosition[1], m_cameraTargetPosition[2],
|
||||
m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ());
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
CharacterDemo::~CharacterDemo()
|
||||
{
|
||||
//cleanup in the reverse order of creation/initialization
|
||||
if (m_character)
|
||||
{
|
||||
m_dynamicsWorld->removeCollisionObject(m_ghostObject);
|
||||
}
|
||||
//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.size();j++)
|
||||
{
|
||||
btCollisionShape* shape = m_collisionShapes[j];
|
||||
delete shape;
|
||||
}
|
||||
|
||||
delete m_indexVertexArrays;
|
||||
delete m_vertices;
|
||||
|
||||
//delete dynamics world
|
||||
delete m_dynamicsWorld;
|
||||
|
||||
//delete solver
|
||||
delete m_constraintSolver;
|
||||
|
||||
//delete broadphase
|
||||
delete m_overlappingPairCache;
|
||||
|
||||
//delete dispatcher
|
||||
delete m_dispatcher;
|
||||
|
||||
delete m_collisionConfiguration;
|
||||
|
||||
}
|
||||
|
||||
153
Demos/CharacterDemo/CharacterDemo.h
Normal file
153
Demos/CharacterDemo/CharacterDemo.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
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 CHARACTER_DEMO_H
|
||||
#define CHARACTER_DEMO_H
|
||||
|
||||
|
||||
///DYNAMIC_CHARACTER_CONTROLLER is not fully implemented yet at the moment
|
||||
//#define DYNAMIC_CHARACTER_CONTROLLER 1
|
||||
|
||||
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
|
||||
|
||||
class btCharacterControllerInterface;
|
||||
class btDynamicCharacterController;
|
||||
class btKinematicCharacterController;
|
||||
|
||||
class btCollisionShape;
|
||||
|
||||
|
||||
#include "GlutDemoApplication.h"
|
||||
|
||||
///CharacterDemo shows how to setup and use the built-in raycast vehicle
|
||||
class CharacterDemo : public GlutDemoApplication
|
||||
{
|
||||
public:
|
||||
|
||||
#ifdef DYNAMIC_CHARACTER_CONTROLLER
|
||||
btCharacterControllerInterface* m_character;
|
||||
#else
|
||||
btKinematicCharacterController* m_character;
|
||||
class btPairCachingGhostObject* m_ghostObject;
|
||||
#endif
|
||||
|
||||
|
||||
btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
|
||||
|
||||
class btBroadphaseInterface* m_overlappingPairCache;
|
||||
|
||||
class btCollisionDispatcher* m_dispatcher;
|
||||
|
||||
class btConstraintSolver* m_constraintSolver;
|
||||
|
||||
class btDefaultCollisionConfiguration* m_collisionConfiguration;
|
||||
|
||||
class btTriangleIndexVertexArray* m_indexVertexArrays;
|
||||
|
||||
btVector3* m_vertices;
|
||||
|
||||
void debugDrawContacts();
|
||||
|
||||
float m_cameraHeight;
|
||||
|
||||
float m_minCameraDistance;
|
||||
float m_maxCameraDistance;
|
||||
|
||||
|
||||
CharacterDemo();
|
||||
|
||||
virtual ~CharacterDemo();
|
||||
|
||||
virtual void clientMoveAndDisplay();
|
||||
|
||||
virtual void clientResetScene();
|
||||
|
||||
virtual void displayCallback();
|
||||
|
||||
///a very basic camera following the character
|
||||
virtual void updateCamera();
|
||||
|
||||
virtual void specialKeyboard(int key, int x, int y);
|
||||
|
||||
virtual void specialKeyboardUp(int key, int x, int y);
|
||||
|
||||
void renderme();
|
||||
|
||||
void initPhysics();
|
||||
|
||||
static DemoApplication* Create()
|
||||
{
|
||||
CharacterDemo* demo = new CharacterDemo();
|
||||
demo->myinit();
|
||||
demo->initPhysics();
|
||||
return demo;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define QUAKE_BSP_IMPORTING 1
|
||||
#ifdef QUAKE_BSP_IMPORTING
|
||||
#include "../BspDemo/BspLoader.h"
|
||||
#include "../BspDemo/BspConverter.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class BspToBulletConverter : public BspConverter
|
||||
{
|
||||
CharacterDemo* m_demoApp;
|
||||
|
||||
public:
|
||||
|
||||
BspToBulletConverter(CharacterDemo* demoApp)
|
||||
:m_demoApp(demoApp)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void addConvexVerticesCollider(btAlignedObjectArray<btVector3>& vertices, bool isEntity, const btVector3& entityTargetLocation)
|
||||
{
|
||||
///perhaps we can do something special with entities (isEntity)
|
||||
///like adding a collision Triggering (as example)
|
||||
|
||||
if (vertices.size() > 0)
|
||||
{
|
||||
float mass = 0.f;
|
||||
btTransform startTransform;
|
||||
//can use a shift
|
||||
startTransform.setIdentity();
|
||||
startTransform.setOrigin(btVector3(0,-10.0f,0.0f));
|
||||
//this create an internal copy of the vertices
|
||||
for (int i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
vertices[i] *= btScalar(0.5);
|
||||
float t = vertices[i].getZ() * btScalar(0.75);
|
||||
vertices[i].setZ(-vertices[i].getY());
|
||||
vertices[i].setY(t);
|
||||
}
|
||||
|
||||
btCollisionShape* shape = new btConvexHullShape(&(vertices[0].getX()),vertices.size());
|
||||
m_demoApp->m_collisionShapes.push_back(shape);
|
||||
|
||||
//btRigidBody* body = m_demoApp->localCreateRigidBody(mass, startTransform,shape);
|
||||
m_demoApp->localCreateRigidBody(mass, startTransform,shape);
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif //QUAKE_BSP_IMPORTING
|
||||
|
||||
|
||||
#endif //CHARACTER_DEMO_H
|
||||
|
||||
|
||||
204
Demos/CharacterDemo/DynamicCharacterController.cpp
Normal file
204
Demos/CharacterDemo/DynamicCharacterController.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
|
||||
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
|
||||
#include "LinearMath/btDefaultMotionState.h"
|
||||
#include "DynamicCharacterController.h"
|
||||
|
||||
DynamicCharacterController::DynamicCharacterController ()
|
||||
{
|
||||
m_rayLambda[0] = 1.0;
|
||||
m_rayLambda[1] = 1.0;
|
||||
m_halfHeight = 1.0;
|
||||
m_turnAngle = 0.0;
|
||||
m_maxLinearVelocity = 10.0;
|
||||
m_walkVelocity = 8.0; // meters/sec
|
||||
m_turnVelocity = 1.0; // radians/sec
|
||||
m_shape = NULL;
|
||||
m_rigidBody = NULL;
|
||||
}
|
||||
|
||||
DynamicCharacterController::~DynamicCharacterController ()
|
||||
{
|
||||
}
|
||||
|
||||
void DynamicCharacterController::setup (btScalar height, btScalar width, btScalar stepHeight)
|
||||
{
|
||||
btVector3 spherePositions[2];
|
||||
btScalar sphereRadii[2];
|
||||
|
||||
sphereRadii[0] = width;
|
||||
sphereRadii[1] = width;
|
||||
spherePositions[0] = btVector3 (0.0, (height/btScalar(2.0) - width), 0.0);
|
||||
spherePositions[1] = btVector3 (0.0, (-height/btScalar(2.0) + width), 0.0);
|
||||
|
||||
m_halfHeight = height/btScalar(2.0);
|
||||
|
||||
m_shape = new btMultiSphereShape (&spherePositions[0], &sphereRadii[0], 2);
|
||||
|
||||
btTransform startTransform;
|
||||
startTransform.setIdentity ();
|
||||
startTransform.setOrigin (btVector3(0.0, 2.0, 0.0));
|
||||
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
|
||||
btRigidBody::btRigidBodyConstructionInfo cInfo(1.0, myMotionState, m_shape);
|
||||
m_rigidBody = new btRigidBody(cInfo);
|
||||
// kinematic vs. static doesn't work
|
||||
//m_rigidBody->setCollisionFlags( m_rigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
m_rigidBody->setSleepingThresholds (0.0, 0.0);
|
||||
m_rigidBody->setAngularFactor (0.0);
|
||||
|
||||
}
|
||||
|
||||
void DynamicCharacterController::destroy ()
|
||||
{
|
||||
if (m_shape)
|
||||
{
|
||||
delete m_shape;
|
||||
}
|
||||
|
||||
if (m_rigidBody)
|
||||
{
|
||||
delete m_rigidBody;
|
||||
m_rigidBody = 0;
|
||||
}
|
||||
}
|
||||
|
||||
btCollisionObject* DynamicCharacterController::getCollisionObject ()
|
||||
{
|
||||
return m_rigidBody;
|
||||
}
|
||||
|
||||
void DynamicCharacterController::preStep (const btCollisionWorld* collisionWorld)
|
||||
{
|
||||
btTransform xform;
|
||||
m_rigidBody->getMotionState()->getWorldTransform (xform);
|
||||
btVector3 down = -xform.getBasis()[1];
|
||||
btVector3 forward = xform.getBasis()[2];
|
||||
down.normalize ();
|
||||
forward.normalize();
|
||||
|
||||
m_raySource[0] = xform.getOrigin();
|
||||
m_raySource[1] = xform.getOrigin();
|
||||
|
||||
m_rayTarget[0] = m_raySource[0] + down * m_halfHeight * btScalar(1.1);
|
||||
m_rayTarget[1] = m_raySource[1] + forward * m_halfHeight * btScalar(1.1);
|
||||
|
||||
class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback
|
||||
{
|
||||
public:
|
||||
ClosestNotMe (btRigidBody* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
|
||||
{
|
||||
m_me = me;
|
||||
}
|
||||
|
||||
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
|
||||
{
|
||||
if (rayResult.m_collisionObject == m_me)
|
||||
return 1.0;
|
||||
|
||||
return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace
|
||||
);
|
||||
}
|
||||
protected:
|
||||
btRigidBody* m_me;
|
||||
};
|
||||
|
||||
ClosestNotMe rayCallback(m_rigidBody);
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
rayCallback.m_closestHitFraction = 1.0;
|
||||
collisionWorld->rayTest (m_raySource[i], m_rayTarget[i], rayCallback);
|
||||
if (rayCallback.hasHit())
|
||||
{
|
||||
m_rayLambda[i] = rayCallback.m_closestHitFraction;
|
||||
} else {
|
||||
m_rayLambda[i] = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicCharacterController::playerStep (const btCollisionWorld* dynaWorld,btScalar dt,
|
||||
int forward,
|
||||
int backward,
|
||||
int left,
|
||||
int right,
|
||||
int jump)
|
||||
{
|
||||
btTransform xform;
|
||||
m_rigidBody->getMotionState()->getWorldTransform (xform);
|
||||
|
||||
/* Handle turning */
|
||||
if (left)
|
||||
m_turnAngle -= dt * m_turnVelocity;
|
||||
if (right)
|
||||
m_turnAngle += dt * m_turnVelocity;
|
||||
|
||||
xform.setRotation (btQuaternion (btVector3(0.0, 1.0, 0.0), m_turnAngle));
|
||||
|
||||
btVector3 linearVelocity = m_rigidBody->getLinearVelocity();
|
||||
btScalar speed = m_rigidBody->getLinearVelocity().length();
|
||||
|
||||
btVector3 forwardDir = xform.getBasis()[2];
|
||||
forwardDir.normalize ();
|
||||
btVector3 walkDirection = btVector3(0.0, 0.0, 0.0);
|
||||
btScalar walkSpeed = m_walkVelocity * dt;
|
||||
|
||||
if (forward)
|
||||
walkDirection += forwardDir;
|
||||
if (backward)
|
||||
walkDirection -= forwardDir;
|
||||
|
||||
|
||||
|
||||
if (!forward && !backward && onGround())
|
||||
{
|
||||
/* Dampen when on the ground and not being moved by the player */
|
||||
linearVelocity *= btScalar(0.2);
|
||||
m_rigidBody->setLinearVelocity (linearVelocity);
|
||||
} else {
|
||||
if (speed < m_maxLinearVelocity)
|
||||
{
|
||||
btVector3 velocity = linearVelocity + walkDirection * walkSpeed;
|
||||
m_rigidBody->setLinearVelocity (velocity);
|
||||
}
|
||||
}
|
||||
|
||||
m_rigidBody->getMotionState()->setWorldTransform (xform);
|
||||
m_rigidBody->setCenterOfMassTransform (xform);
|
||||
}
|
||||
|
||||
bool DynamicCharacterController::canJump () const
|
||||
{
|
||||
return onGround();
|
||||
}
|
||||
|
||||
void DynamicCharacterController::jump ()
|
||||
{
|
||||
if (!canJump())
|
||||
return;
|
||||
|
||||
btTransform xform;
|
||||
m_rigidBody->getMotionState()->getWorldTransform (xform);
|
||||
btVector3 up = xform.getBasis()[1];
|
||||
up.normalize ();
|
||||
btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
|
||||
m_rigidBody->applyCentralImpulse (up * magnitude);
|
||||
}
|
||||
|
||||
bool DynamicCharacterController::onGround () const
|
||||
{
|
||||
return m_rayLambda[0] < btScalar(1.0);
|
||||
}
|
||||
|
||||
void DynamicCharacterController::reset ()
|
||||
{
|
||||
}
|
||||
void DynamicCharacterController::warp (const btVector3& origin)
|
||||
{
|
||||
}
|
||||
void DynamicCharacterController::registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
55
Demos/CharacterDemo/DynamicCharacterController.h
Normal file
55
Demos/CharacterDemo/DynamicCharacterController.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef CHARACTER_CONTROLLER_H
|
||||
#define CHARACTER_CONTROLLER_H
|
||||
|
||||
#include "LinearMath/btVector3.h"
|
||||
|
||||
#include "BulletDynamics/Character/btCharacterControllerInterface.h"
|
||||
|
||||
class btCollisionShape;
|
||||
class btRigidBody;
|
||||
class btCollisionWorld;
|
||||
|
||||
///DynamicCharacterController is obsolete/unsupported at the moment
|
||||
class DynamicCharacterController : public btCharacterControllerInterface
|
||||
{
|
||||
protected:
|
||||
btScalar m_halfHeight;
|
||||
btCollisionShape* m_shape;
|
||||
btRigidBody* m_rigidBody;
|
||||
|
||||
btVector3 m_raySource[2];
|
||||
btVector3 m_rayTarget[2];
|
||||
btScalar m_rayLambda[2];
|
||||
btVector3 m_rayNormal[2];
|
||||
|
||||
btScalar m_turnAngle;
|
||||
|
||||
btScalar m_maxLinearVelocity;
|
||||
btScalar m_walkVelocity;
|
||||
btScalar m_turnVelocity;
|
||||
public:
|
||||
DynamicCharacterController ();
|
||||
~DynamicCharacterController ();
|
||||
void setup (btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25);
|
||||
void destroy ();
|
||||
|
||||
virtual void reset ();
|
||||
virtual void warp (const btVector3& origin);
|
||||
virtual void registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher);
|
||||
|
||||
btCollisionObject* getCollisionObject ();
|
||||
|
||||
void preStep (const btCollisionWorld* collisionWorld);
|
||||
void playerStep (const btCollisionWorld* collisionWorld,btScalar dt,
|
||||
int forward,
|
||||
int backward,
|
||||
int left,
|
||||
int right,
|
||||
int jump);
|
||||
bool canJump () const;
|
||||
void jump ();
|
||||
|
||||
bool onGround () const;
|
||||
};
|
||||
|
||||
#endif
|
||||
19
Demos/CharacterDemo/main.cpp
Normal file
19
Demos/CharacterDemo/main.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
#include "CharacterDemo.h"
|
||||
#include "GlutStuff.h"
|
||||
#include "GLDebugDrawer.h"
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
|
||||
GLDebugDrawer gDebugDrawer;
|
||||
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
|
||||
CharacterDemo* characterDemo = new CharacterDemo;
|
||||
|
||||
characterDemo->initPhysics();
|
||||
characterDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer);
|
||||
|
||||
return glutmain(argc, argv,640,480,"Bullet Character Demo. http://www.continuousphysics.com/Bullet/phpBB2/", characterDemo);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user