| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- /*
- Copyright (C) 2011 by Ivan Safrin
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- #include "PolyPhysicsScene.h"
- #include "btBulletCollisionCommon.h"
- #include "BulletCollision/CollisionDispatch/btGhostObject.h"
- #include "BulletDynamics/Character/btKinematicCharacterController.h"
- #include "PolyCollisionScene.h"
- #include "PolyCoreServices.h"
- #include "PolyVector3.h"
- #include "PolyPhysicsSceneEntity.h"
- #include "PolyCore.h"
- using namespace Polycode;
- PhysicsSceneEvent::PhysicsSceneEvent() : Event () {
- eventType = "PhysicsSceneEvent";
- }
- PhysicsSceneEvent::~PhysicsSceneEvent() {
- }
- PhysicsScene::PhysicsScene(int maxSubSteps, Vector3 size, bool virtualScene) : CollisionScene(size, virtualScene, true), physicsWorld(NULL), solver(NULL), broadphase(NULL), ghostPairCallback(NULL) {
- this->maxSubSteps = maxSubSteps;
- initPhysicsScene(size);
- }
- PhysicsScene::~PhysicsScene() {
- for(int i=0; i < collisionChildren.size(); i++) {
- delete collisionChildren[i];
- }
- delete physicsWorld;
-
- // Prevent double free by ~CollisionScene
- collisionChildren.clear();
- world = NULL;
-
- delete solver;
- delete broadphase;
- delete ghostPairCallback;
- }
- void worldTickCallback(btDynamicsWorld *world, btScalar timeStep) {
- PhysicsScene *physicsScene = (PhysicsScene*)world->getWorldUserInfo();
- physicsScene->processWorldCollisions();
- }
- void PhysicsScene::initPhysicsScene(Vector3 size) {
-
- collisionConfiguration = new btDefaultCollisionConfiguration();
- btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
-
- solver = new btSequentialImpulseConstraintSolver();
-
- btVector3 worldMin(-size.x * 0.5, -size.y * 0.5, -size.z * 0.5);
- btVector3 worldMax(size.x * 0.5, size.y * 0.5, size.z * 0.5);
- axisSweep = new btAxisSweep3(worldMin,worldMax);
-
- broadphase = new btDbvtBroadphase();
- physicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
-
- // physicsWorld->getSolverInfo().m_solverMode |= SOLVER_RANDMIZE_ORDER;
- physicsWorld->setGravity(btVector3(0,-10,0));
- axisSweep->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
-
- world = physicsWorld;
-
- physicsWorld->setInternalTickCallback(worldTickCallback, this);
- }
- void PhysicsScene::setGravity(Vector3 gravity) {
- physicsWorld->setGravity(btVector3(gravity.x, gravity.y, gravity.z));
- }
- PhysicsSceneEntity *PhysicsScene::getPhysicsEntityByCollisionObject(btCollisionObject *object) {
- for(int i=0; i < physicsChildren.size(); i++) {
- PhysicsSceneEntity *entity = physicsChildren[i];
- if(entity->rigidBody == object) {
- return entity;
- }
- }
- return NULL;
- }
- void PhysicsScene::processWorldCollisions() {
- int numManifolds = physicsWorld->getDispatcher()->getNumManifolds();
- for (int i=0;i<numManifolds;i++)
- {
- btPersistentManifold* contactManifold = world->getDispatcher()->getManifoldByIndexInternal(i);
- btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
- btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
-
-
- int numContacts = contactManifold->getNumContacts();
- for (int j=0;j<numContacts;j++)
- {
- btManifoldPoint& pt = contactManifold->getContactPoint(j);
- if (pt.getDistance()<0.f)
- {
- const btVector3& ptA = pt.getPositionWorldOnA();
- const btVector3& ptB = pt.getPositionWorldOnB();
- const btVector3& normalOnB = pt.m_normalWorldOnB;
- const btScalar appliedImpulse = pt.m_appliedImpulse;
-
- PhysicsSceneEvent *event = new PhysicsSceneEvent();
- event->positionOnA = Vector3(ptA.x(), ptA.y(), ptA.z());
- event->positionOnB = Vector3(ptB.x(), ptB.y(), ptB.z());
- event->worldNormalOnB = Vector3(normalOnB.x(), normalOnB.y(), normalOnB.z());
- event->appliedImpulse = appliedImpulse;
-
- event->entityA = getPhysicsEntityByCollisionObject(obA);
- event->entityB = getPhysicsEntityByCollisionObject(obB);
-
- dispatchEvent(event, PhysicsSceneEvent::COLLISION_EVENT);
- }
- }
- }
- }
- void PhysicsScene::Update() {
-
- for(int i=0; i < physicsChildren.size(); i++) {
- // if(physicsChildren[i]->enabled)
- physicsChildren[i]->Update();
- }
-
-
- Number elapsed = CoreServices::getInstance()->getCore()->getElapsed();
- if(maxSubSteps > 0) {
- physicsWorld->stepSimulation(elapsed, maxSubSteps);
- } else {
- physicsWorld->stepSimulation(elapsed);
- }
- CollisionScene::Update();
-
- }
- void PhysicsScene::setVelocity(SceneEntity *entity, Vector3 velocity) {
- PhysicsSceneEntity *physicsEntity = getPhysicsEntityBySceneEntity(entity);
- if(physicsEntity) {
- physicsEntity->setVelocity(velocity);
- }
- }
- void PhysicsScene::warpEntity(SceneEntity *entity, Vector3 position, bool resetRotation) {
- PhysicsSceneEntity *physicsEntity = getPhysicsEntityBySceneEntity(entity);
- if(physicsEntity) {
- physicsEntity->warpTo(position, resetRotation);
- }
- }
- PhysicsCharacter *PhysicsScene::addCharacterChild(SceneEntity *newEntity,Number mass, Number friction, Number stepSize, int group) {
- addEntity(newEntity);
- PhysicsCharacter *newPhysicsEntity = new PhysicsCharacter(newEntity, mass, friction, stepSize);
-
- physicsWorld->addCollisionObject(newPhysicsEntity->ghostObject,group, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
- physicsWorld->addAction(newPhysicsEntity->character);
-
-
- physicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(newPhysicsEntity->ghostObject->getBroadphaseHandle(),physicsWorld->getDispatcher());
-
- newPhysicsEntity->character->reset ();
-
- newPhysicsEntity->character->setUseGhostSweepTest(false);
-
- physicsChildren.push_back(newPhysicsEntity);
- collisionChildren.push_back(newPhysicsEntity);
- return newPhysicsEntity;
-
- }
- void PhysicsScene::removeCharacterChild(PhysicsCharacter *character) {
- physicsWorld->removeAction(character->character);
- physicsWorld->removeCollisionObject(character->ghostObject);
- for(int i=0; i < physicsChildren.size(); i++) {
- if(physicsChildren[i] == character) {
- physicsChildren.erase(physicsChildren.begin()+i);
- }
- }
- for(int i=0; i < collisionChildren.size(); i++) {
- if(collisionChildren[i] == character) {
- collisionChildren.erase(collisionChildren.begin()+i);
- }
- }
-
- }
- PhysicsVehicle *PhysicsScene::addVehicleChild(SceneEntity *newEntity, Number mass, Number friction, int group) {
- addEntity(newEntity);
-
- btDefaultVehicleRaycaster *m_vehicleRayCaster = new btDefaultVehicleRaycaster(physicsWorld);
-
- PhysicsVehicle *newPhysicsEntity = new PhysicsVehicle(newEntity, mass, friction,m_vehicleRayCaster);
- physicsWorld->addRigidBody(newPhysicsEntity->rigidBody, group, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
-
- newPhysicsEntity->vehicle = new btRaycastVehicle(newPhysicsEntity->tuning,newPhysicsEntity->rigidBody,m_vehicleRayCaster);
-
- newPhysicsEntity->rigidBody->setActivationState(DISABLE_DEACTIVATION);
-
-
- int rightIndex = 0;
- int upIndex = 1;
- int forwardIndex = 2;
-
- physicsWorld->addVehicle(newPhysicsEntity->vehicle);
-
- newPhysicsEntity->vehicle->setCoordinateSystem(rightIndex,upIndex,forwardIndex);
- newPhysicsEntity->vehicle->resetSuspension();
- physicsChildren.push_back(newPhysicsEntity);
- collisionChildren.push_back(newPhysicsEntity);
-
- return newPhysicsEntity;
- }
- void PhysicsScene::removePhysicsChild(SceneEntity *entity) {
- PhysicsSceneEntity *ent = getPhysicsEntityBySceneEntity(entity);
- if(ent) {
- if(ent->getType() == PhysicsSceneEntity::CHARACTER_CONTROLLER) {
- removeCharacterChild((PhysicsCharacter *)ent);
- } else {
-
- if(ent->rigidBody)
- physicsWorld->removeRigidBody(ent->rigidBody);
- physicsWorld->removeCollisionObject(ent->collisionObject);
- for(int i=0; i < physicsChildren.size(); i++) {
- if(physicsChildren[i] == ent) {
- physicsChildren.erase(physicsChildren.begin()+i);
- }
- }
- for(int i=0; i < collisionChildren.size(); i++) {
- if(collisionChildren[i] == ent) {
- collisionChildren.erase(collisionChildren.begin()+i);
- }
- }
- }
- }
- delete ent;
- CollisionScene::removeEntity(entity);
- }
- void PhysicsScene::removeEntity(SceneEntity *entity) {
- PhysicsSceneEntity *ent = getPhysicsEntityBySceneEntity(entity);
- if(ent) {
- removePhysicsChild(entity);
- } else {
- CollisionScene::removeEntity(entity);
- }
- }
- void PhysicsHingeConstraint::setLimits(Number minLimit, Number maxLimit) {
- btConstraint->setLimit(minLimit, maxLimit);
- }
- Number PhysicsHingeConstraint::getAngle() {
- return btConstraint->getHingeAngle();
- }
- PhysicsHingeConstraint * PhysicsScene::createHingeConstraint(SceneEntity *entity, Vector3 pivot, Vector3 axis, Number minLimit, Number maxLimit) {
- PhysicsSceneEntity *pEnt = getPhysicsEntityBySceneEntity(entity);
- if(!pEnt) {
- return NULL;
- }
-
- PhysicsHingeConstraint *constraint = new PhysicsHingeConstraint();
- btVector3 btPivot = btVector3(pivot.x, pivot.y, pivot.z);
- btVector3 btAxis = btVector3(axis.x, axis.y, axis.z);
-
- btHingeConstraint *hingeConstraint = new btHingeConstraint( *pEnt->rigidBody, btPivot, btAxis );
- hingeConstraint->setLimit(minLimit, maxLimit);
- physicsWorld->addConstraint(hingeConstraint);
-
- constraint->btConstraint = hingeConstraint;
-
- return constraint;
- }
- PhysicsHingeConstraint *PhysicsScene::createHingeJoint(SceneEntity *entity1, SceneEntity *entity2, Vector3 pivot1, Vector3 axis1, Vector3 pivot2, Vector3 axis2, Number minLimit, Number maxLimit) {
-
- PhysicsSceneEntity *pEnt1 = getPhysicsEntityBySceneEntity(entity1);
- PhysicsSceneEntity *pEnt2 = getPhysicsEntityBySceneEntity(entity2);
-
- if(!pEnt1 || !pEnt2) {
- return NULL;
- }
-
- PhysicsHingeConstraint *constraint = new PhysicsHingeConstraint();
- btVector3 btPivot1 = btVector3(pivot1.x, pivot1.y, pivot1.z);
- btVector3 btAxis1 = btVector3(axis1.x, axis1.y, axis1.z);
- btVector3 btPivot2 = btVector3(pivot2.x, pivot2.y, pivot2.z);
- btVector3 btAxis2 = btVector3(axis2.x, axis2.y, axis2.z);
- btHingeConstraint *hingeConstraint = new btHingeConstraint(*pEnt1->rigidBody, *pEnt2->rigidBody, btPivot1, btPivot2, btAxis1, btAxis2 );
- hingeConstraint->setLimit(minLimit, maxLimit);
- physicsWorld->addConstraint(hingeConstraint);
-
- constraint->btConstraint = hingeConstraint;
-
- return constraint;
-
- }
- PhysicsSceneEntity *PhysicsScene::getPhysicsEntityBySceneEntity(SceneEntity *entity) {
- PhysicsSceneEntity *retEntity = NULL;
- for(int i=0; i < physicsChildren.size(); i++) {
- if(physicsChildren[i]->getSceneEntity() == entity) {
- retEntity = physicsChildren[i];
- }
- }
- return retEntity;
- }
- void PhysicsScene::wakeUp(SceneEntity *entity) {
- PhysicsSceneEntity *pEnt = getPhysicsEntityBySceneEntity(entity);
- if(!pEnt) {
- return;
- }
- pEnt->rigidBody->setActivationState(DISABLE_DEACTIVATION);
- }
- PhysicsSceneEntity *PhysicsScene::trackPhysicsChild(SceneEntity *newEntity, int type, Number mass, Number friction, Number restitution, int group, bool compoundChildren) {
- PhysicsSceneEntity *newPhysicsEntity = new PhysicsSceneEntity(newEntity, type, mass, friction,restitution, compoundChildren);
- physicsWorld->addRigidBody(newPhysicsEntity->rigidBody, group, btBroadphaseProxy::AllFilter); //btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
- // world->addCollisionObject(newPhysicsEntity->collisionObject, group);
- //newPhysicsEntity->rigidBody->setActivationState(ISLAND_SLEEPING);
- physicsChildren.push_back(newPhysicsEntity);
- collisionChildren.push_back(newPhysicsEntity);
- return newPhysicsEntity;
- }
- PhysicsSceneEntity *PhysicsScene::addPhysicsChild(SceneEntity *newEntity, int type, Number mass, Number friction, Number restitution, int group, bool compoundChildren) {
- addEntity(newEntity);
- return trackPhysicsChild(newEntity, type, mass, friction, restitution, group, compoundChildren);
- }
|