From 053b16783cdddfa7213c2d5fe6693cfb32acb38d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 6 Nov 2014 16:42:07 -0800 Subject: [PATCH] initial impl of PhysicsWorld::addEntity() --- libraries/entities/src/EntityItem.cpp | 15 ++++ libraries/entities/src/EntityItem.h | 8 ++- libraries/entities/src/EntityMotionState.cpp | 56 +++++++++++++++ libraries/entities/src/EntityMotionState.h | 34 +++++++++ libraries/physics/src/CustomMotionState.cpp | 72 +++++++++----------- libraries/physics/src/CustomMotionState.h | 32 +++++---- libraries/physics/src/PhysicsWorld.cpp | 45 ++++++++---- libraries/physics/src/PhysicsWorld.h | 11 +-- 8 files changed, 199 insertions(+), 74 deletions(-) create mode 100644 libraries/entities/src/EntityMotionState.cpp create mode 100644 libraries/entities/src/EntityMotionState.h diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 346070c567..9d32b17dfb 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -21,6 +21,7 @@ #include "EntityScriptingInterface.h" #include "EntityItem.h" +#include "EntityMotionState.h" #include "EntityTree.h" const float EntityItem::IMMORTAL = -1.0f; /// special lifetime which means the entity lives for ever. default lifetime @@ -87,6 +88,9 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) { _lastEditedFromRemoteInRemoteTime = 0; _lastUpdated = 0; _created = 0; +#ifdef USE_BULLET_PHYSICS + _motionState = NULL; +#endif // USE_BULLET_PHYSICS initFromEntityItemID(entityItemID); } @@ -97,10 +101,21 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert _lastEditedFromRemoteInRemoteTime = 0; _lastUpdated = 0; _created = properties.getCreated(); +#ifdef USE_BULLET_PHYSICS + _motionState = NULL; +#endif // USE_BULLET_PHYSICS initFromEntityItemID(entityItemID); setProperties(properties, true); // force copy } +EntityItem::~EntityItem() { +#ifdef USE_BULLET_PHYSICS + // make sure the _motionState is already deleted (e.g. the entity has been removed + // from the physics simulation) BEFORE you get here + assert(_motionState == NULL); +#endif // USE_BULLET_PHYSICS +} + EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index f1d4e42b81..205dc2f165 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -49,7 +49,7 @@ public: EntityItem(const EntityItemID& entityItemID); EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); - virtual ~EntityItem() { } + virtual ~EntityItem(); // ID and EntityItemID related methods QUuid getID() const { return _id; } @@ -260,8 +260,7 @@ public: virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } #ifdef USE_BULLET_PHYSICS - //EntityMotionState* createMotionState() = 0; - EntityMotionState* createMotionState() { return NULL; } + virtual EntityMotionState* createMotionState() { return NULL; } #endif // USE_BULLET_PHYSICS protected: @@ -304,6 +303,9 @@ protected: void setRadius(float value); AACubeShape _collisionShape; +#ifdef USE_BULLET_PHYSICS + EntityMotionState* _motionState; +#endif // USE_BULLET_PHYSICS }; diff --git a/libraries/entities/src/EntityMotionState.cpp b/libraries/entities/src/EntityMotionState.cpp new file mode 100644 index 0000000000..1c3266a68e --- /dev/null +++ b/libraries/entities/src/EntityMotionState.cpp @@ -0,0 +1,56 @@ +// +// EntityMotionState.cpp +// libraries/entities/src +// +// Created by Andrew Meadows on 2014.11.06 +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include "EntityItem.h" +#include "EntityMotionState.h" + +EntityMotionState::EntityMotionState(EntityItem* entity) : _entity(entity) { + assert(entity != NULL); +} + +EntityMotionState::~EntityMotionState() { +} + +// This callback is invoked by the physics simulation in two cases: +// (1) when the RigidBody is first added to the world +// (irregardless of MotionType: STATIC, DYNAMIC, or KINEMATIC) +// (2) at the beginning of each simulation frame for KINEMATIC RigidBody's -- +// it is an opportunity for outside code to update the position of the object +void EntityMotionState::getWorldTransform (btTransform &worldTrans) const { + btVector3 pos; + glmToBullet(_entity->getPosition(), pos); + btQuaternion rot; + glmToBullet(_entity->getRotation(), rot); + worldTrans.setOrigin(pos); + worldTrans.setRotation(rot); +} + +// This callback is invoked by the physics simulation at the end of each simulation frame... +// iff the corresponding RigidBody is DYNAMIC and has moved. +void EntityMotionState::setWorldTransform (const btTransform &worldTrans) { + glm::vec3 pos; + bulletToGLM(worldTrans.getOrigin(), pos); + _entity->setPositionInMeters(pos); + glm::quat rot; + bulletToGLM(worldTrans.getRotation(), rot); + _entity->setRotation(rot); +} + +void EntityMotionState::computeShapeInfo(ShapeInfo& info) { + // HACK: for now we make everything a box. + glm::vec3 halfExtents = _entity->getDimensionsInMeters(); + btVector3 bulletHalfExtents; + glmToBullet(halfExtents, bulletHalfExtents); + info.setBox(bulletHalfExtents); +} + diff --git a/libraries/entities/src/EntityMotionState.h b/libraries/entities/src/EntityMotionState.h new file mode 100644 index 0000000000..8dbb0720e4 --- /dev/null +++ b/libraries/entities/src/EntityMotionState.h @@ -0,0 +1,34 @@ +// +// EntityMotionState.h +// libraries/entities/src +// +// Created by Andrew Meadows on 2014.11.06 +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_EntityMotionState_h +#define hifi_EntityMotionState_h + +#ifdef USE_BULLET_PHYSICS + +#include + +class EntityMotionState : public CustomMotionState { +public: + EntityMotionState(EntityItem* item); + virtual ~EntityMotionState(); + + virtual void getWorldTransform (btTransform &worldTrans) const; + virtual void setWorldTransform (const btTransform &worldTrans); + + virtual void computeShapeInfo(ShapeInfo& info); + +protected: + EntityItem* _entity; +}; + +#endif // USE_BULLET_PHYSICS +#endif // hifi_EntityMotionState_h diff --git a/libraries/physics/src/CustomMotionState.cpp b/libraries/physics/src/CustomMotionState.cpp index bd9d41011c..40175d1366 100644 --- a/libraries/physics/src/CustomMotionState.cpp +++ b/libraries/physics/src/CustomMotionState.cpp @@ -11,58 +11,50 @@ #ifdef USE_BULLET_PHYSICS +#include + #include "CustomMotionState.h" -CustomMotionState::CustomMotionState() : _motionType(MOTION_TYPE_STATIC), - _inertiaDiagLocal(1.0f, 1.0f, 1.0f), _mass(1.0f), - _shape(NULL), _object(NULL) { +const float MIN_DENSITY = 200.0f; +const float DEFAULT_DENSITY = 1000.0f; +const float MAX_DENSITY = 20000.0f; + +const float MIN_VOLUME = 0.001f; +const float DEFAULT_VOLUME = 1.0f; +const float MAX_VOLUME = 1000000.0f; + +const float DEFAULT_FRICTION = 0.5f; +const float MAX_FRICTION = 10.0f; + +const float DEFAULT_RESTITUTION = 0.0f; + +CustomMotionState::CustomMotionState() : + _density(DEFAULT_DENSITY), + _volume(DEFAULT_VOLUME), + _friction(DEFAULT_FRICTION), + _restitution(DEFAULT_RESTITUTION), + _motionType(MOTION_TYPE_STATIC), + _body(NULL) { } -/* -void CustomMotionState::getWorldTransform (btTransform &worldTrans) const { +CustomMotionState::~CustomMotionState() { + assert(_body == NULL); } -void CustomMotionState::setWorldTransform (const btTransform &worldTrans) { +void CustomMotionState::setDensity(float density) { + _density = btMax(btMin(fabsf(density), MAX_DENSITY), MIN_DENSITY); } -void CustomMotionState::computeMassProperties() { +void CustomMotionState::setFriction(float friction) { + _friction = btMax(btMin(fabsf(friction), MAX_FRICTION), 0.0f); } -void CustomMotionState::getShapeInfo(ShapeInfo& info) { -} -*/ - -bool CustomMotionState::makeStatic() { - if (_motionType == MOTION_TYPE_STATIC) { - return true; - } - if (!_object) { - _motionType = MOTION_TYPE_STATIC; - return true; - } - return false; +void CustomMotionState::setRestitution(float restitution) { + _restitution = btMax(btMin(fabsf(restitution), 1.0f), 0.0f); } -bool CustomMotionState::makeDynamic() { - if (_motionType == MOTION_TYPE_DYNAMIC) { - return true; - } - if (!_object) { - _motionType = MOTION_TYPE_DYNAMIC; - return true; - } - return false; -} - -bool CustomMotionState::makeKinematic() { - if (_motionType == MOTION_TYPE_KINEMATIC) { - return true; - } - if (!_object) { - _motionType = MOTION_TYPE_KINEMATIC; - return true; - } - return false; +void CustomMotionState::setVolume(float volume) { + _volume = btMax(btMin(fabsf(volume), MAX_VOLUME), MIN_VOLUME); } #endif // USE_BULLET_PHYSICS diff --git a/libraries/physics/src/CustomMotionState.h b/libraries/physics/src/CustomMotionState.h index 282c4eaae0..88991a4855 100644 --- a/libraries/physics/src/CustomMotionState.h +++ b/libraries/physics/src/CustomMotionState.h @@ -17,7 +17,6 @@ #include #include "ShapeInfo.h" -#include "UUIDHashKey.h" enum MotionType { MOTION_TYPE_STATIC, // no motion @@ -28,29 +27,34 @@ enum MotionType { class CustomMotionState : public btMotionState { public: CustomMotionState(); + ~CustomMotionState(); //// these override methods of the btMotionState base class //virtual void getWorldTransform (btTransform &worldTrans) const; //virtual void setWorldTransform (const btTransform &worldTrans); - virtual void computeMassProperties() = 0; - virtual void getShapeInfo(ShapeInfo& info) = 0; - - bool makeStatic(); - bool makeDynamic(); - bool makeKinematic(); + virtual void computeShapeInfo(ShapeInfo& info) = 0; MotionType getMotionType() const { return _motionType; } -private: - friend class PhysicsWorld; + void setDensity(float density); + void setFriction(float friction); + void setRestitution(float restitution); + void setVolume(float volume); - //EntityItem* _entity; + float getMass() const { return _volume * _density; } + + friend class PhysicsWorld; +protected: + + float _density; + float _volume; + float _friction; + float _restitution; + + // The data members below have NO setters. They are only changed by a PhysicsWorld instance. MotionType _motionType; - btVector3 _inertiaDiagLocal; - float _mass; - btCollisionShape* _shape; - btCollisionObject* _object; + btRigidBody* _body; }; #endif // USE_BULLET_PHYSICS diff --git a/libraries/physics/src/PhysicsWorld.cpp b/libraries/physics/src/PhysicsWorld.cpp index 14387fba32..8c1492360a 100644 --- a/libraries/physics/src/PhysicsWorld.cpp +++ b/libraries/physics/src/PhysicsWorld.cpp @@ -76,23 +76,44 @@ bool PhysicsWorld::removeVoxel(const glm::vec3& position, float scale) { return false; } -bool PhysicsWorld::addEntity(const QUuid& id, CustomMotionState* motionState) { +bool PhysicsWorld::addEntity(CustomMotionState* motionState, float mass) { assert(motionState); - UUIDHashKey key(id); - CustomMotionState** statePtr = _entities.find(key); - if (!statePtr) { - // BOOKMARK: Andrew to implement this - } else { - assert(*statePtr == motionState); + ShapeInfo info; + motionState->computeShapeInfo(info); + btCollisionShape* shape = _shapeManager.getShape(info); + if (shape) { + btVector3 inertia; + shape->calculateLocalInertia(mass, inertia); + btRigidBody* body = new btRigidBody(mass, motionState, shape, inertia); + _dynamicsWorld->addRigidBody(body); + motionState->_body = body; } return false; } -bool PhysicsWorld::removeEntity(const QUuid& id) { - UUIDHashKey key(id); - CustomMotionState** statePtr = _entities.find(key); - if (statePtr) { - // BOOKMARK: Andrew to implement this +bool PhysicsWorld::removeEntity(CustomMotionState* motionState) { + assert(motionState); + btRigidBody* body = motionState->_body; + if (body) { + const btCollisionShape* shape = body->getCollisionShape(); + ShapeInfo info; + info.collectInfo(shape); + _dynamicsWorld->removeRigidBody(body); + _shapeManager.releaseShape(info); + delete body; + motionState->_body = NULL; } return false; } + +bool PhysicsWorld::updateEntityMotionType(CustomMotionState* motionState, MotionType type) { + // TODO: implement this + assert(motionState); + return false; +} + +bool PhysicsWorld::updateEntityMassProperties(CustomMotionState* motionState, float mass, const glm::vec3& inertiaEigenValues) { + // TODO: implement this + assert(motionState); + return false; +} diff --git a/libraries/physics/src/PhysicsWorld.h b/libraries/physics/src/PhysicsWorld.h index d7ea0436ad..0714c72011 100644 --- a/libraries/physics/src/PhysicsWorld.h +++ b/libraries/physics/src/PhysicsWorld.h @@ -20,7 +20,6 @@ #include "CustomMotionState.h" #include "PositionHashKey.h" #include "ShapeManager.h" -#include "UUIDHashKey.h" #include "VoxelObject.h" class PhysicsWorld { @@ -45,11 +44,15 @@ public: /// \return true if Entity added /// \param info information about collision shapes to create - bool addEntity(const QUuid& id, CustomMotionState* motionState); + bool addEntity(CustomMotionState* motionState, float mass); /// \return true if Entity removed /// \param id UUID of the entity - bool removeEntity(const QUuid& id); + bool removeEntity(CustomMotionState* motionState); + + bool updateEntityMotionType(CustomMotionState* motionState, MotionType type); + + bool updateEntityMassProperties(CustomMotionState* motionState, float mass, const glm::vec3& inertiaEigenValues); protected: btDefaultCollisionConfiguration* _collisionConfig; @@ -57,12 +60,10 @@ protected: btBroadphaseInterface* _broadphaseFilter; btSequentialImpulseConstraintSolver* _constraintSolver; btDiscreteDynamicsWorld* _dynamicsWorld; - ShapeManager _shapeManager; private: btHashMap _voxels; - btHashMap _entities; };