00001
00002 #include <iostream>
00003 #include <vector>
00004 #include <btBulletDynamicsCommon.h>
00005
00006 #include "Physics.h"
00007 #include "Vec3.h"
00008 #include "IShootable.h"
00009 #include "Enemy.h"
00010
00014 class RayCastCallback : public btCollisionWorld::ClosestRayResultCallback {
00015 public:
00016 RayCastCallback(btCollisionObject* ignoredObject, const btVector3& from, const btVector3& to)
00017 : btCollisionWorld::ClosestRayResultCallback(from, to), ignoredObject(ignoredObject) {}
00018 virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &result, bool normal) {
00019 if (result.m_collisionObject == ignoredObject)
00020 return 1.0f;
00021 return btCollisionWorld::ClosestRayResultCallback::addSingleResult(result, normal);
00022 }
00023 private:
00024 btCollisionObject* ignoredObject;
00025 };
00026
00030 Physics::Physics() {
00031
00032 int maxProxies = 1024;
00033
00034 btVector3 worldAabbMin(-5000,-5000,-5000);
00035 btVector3 worldAabbMax(5000,5000,5000);
00036 _broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);
00037
00038
00039 _collisionConfiguration = new btDefaultCollisionConfiguration();
00040 _dispatcher = new btCollisionDispatcher(_collisionConfiguration);
00041
00042
00043
00044 _solver = new btSequentialImpulseConstraintSolver;
00045
00046
00047 _dynamicsWorld = new btDiscreteDynamicsWorld(_dispatcher, _broadphase, _solver, _collisionConfiguration);
00048
00049 _dynamicsWorld->setGravity(btVector3(0,-30,0));
00050 }
00051
00052 Physics::~Physics() {
00053
00054
00055 for(unsigned int i = 0; i < _nonShootableBodies.size(); i++) {
00056 _dynamicsWorld->removeRigidBody(_nonShootableBodies[i]);
00057 }
00058 for(unsigned int i = 0; i < _shootableBodies.size(); i++) {
00059 if(_shootableBodies[i]->getID() >= 0) {
00060 _dynamicsWorld->removeRigidBody(_shootableBodies[i]->getBody());
00061 }
00062 }
00063 _nonShootableBodies.clear();
00064 _shootableBodies.clear();
00065
00066 delete _dynamicsWorld;
00067 delete _solver;
00068 delete _collisionConfiguration;
00069 delete _dispatcher;
00070 delete _broadphase;
00071 }
00072
00078 void Physics::addNonShootable(btRigidBody* body) {
00079
00080 _nonShootableBodies.push_back(body);
00081 _dynamicsWorld->addRigidBody(body);
00082 }
00083
00088 void Physics::addShootable(IShootable* shootable) {
00089 _shootableBodies.push_back(shootable);
00090 _dynamicsWorld->addRigidBody(shootable->getBody());
00091 }
00092
00099 bool Physics::removeShootable(IShootable* shootable) {
00100 for(unsigned int i = 0; i < _shootableBodies.size(); i++) {
00101 if(_shootableBodies[i] == shootable) {
00102 _dynamicsWorld->removeRigidBody(shootable->getBody());
00103 _shootableBodies.erase(_shootableBodies.begin() + i);
00104 return true;
00105 }
00106 }
00107 return false;
00108 }
00109
00113 void Physics::update(float timeStep) {
00114 _dynamicsWorld->stepSimulation(timeStep);
00115 }
00116
00117
00118
00123 bool Physics::castRay(const Vec3& from, const Vec3& to, Vec3& collisionPoint, btRigidBody* ignore) {
00124 btVector3 fromBt(from.x, from.y, from.z);
00125 btVector3 toBt(to.x, to.y, to.z);
00126
00127
00128 RayCastCallback callback(ignore, fromBt, toBt);
00129 _dynamicsWorld->rayTest(fromBt, toBt, callback);
00130
00131 if (callback.hasHit()) {
00132 collisionPoint = Vec3(
00133 callback.m_hitPointWorld.x(),
00134 callback.m_hitPointWorld.y(),
00135 callback.m_hitPointWorld.z());
00136 return true;
00137 }
00138 else
00139 return false;
00140 }
00141
00146 IShootable* Physics::castGunRay(const Vec3& from, const Vec3& to, Vec3& collisionPoint, btRigidBody* ignore) {
00147 btVector3 fromBt(from.x, from.y, from.z);
00148 btVector3 toBt(to.x, to.y, to.z);
00149
00150
00151 RayCastCallback callback(ignore, fromBt, toBt);
00152 _dynamicsWorld->rayTest(fromBt, toBt, callback);
00153
00154
00155 if (callback.hasHit()) {
00156 IShootable* shootable = NULL;
00157
00158 for(unsigned int i = 0; i < _shootableBodies.size(); i++) {
00159
00160 if(callback.m_collisionObject == _shootableBodies[i]->getBody()) {
00161 shootable = _shootableBodies[i];
00162 break;
00163 }
00164 }
00165
00166 if(shootable == NULL) return NULL;
00167
00168
00169 collisionPoint = Vec3(
00170 callback.m_hitPointWorld.x(),
00171 callback.m_hitPointWorld.y(),
00172 callback.m_hitPointWorld.z());
00173 return shootable;
00174 }
00175 return NULL;
00176 }
00177
00181 btCollisionWorld* Physics::getWorld() {
00182 return _dynamicsWorld;
00183 }