Merge pull request #4500 from AndrewMeadows/inertia

avatar can jump when using CharacterController
This commit is contained in:
Seth Alves 2015-03-25 14:48:54 -07:00
commit c0b1ff4a57
8 changed files with 455 additions and 483 deletions

View file

@ -1909,8 +1909,6 @@ void Application::init() {
_physicsEngine.init(&_entityEditSender); _physicsEngine.init(&_entityEditSender);
_physicsEngine.setAvatarData(_myAvatar);
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
connect(&_physicsEngine, &EntitySimulation::entityCollisionWithEntity, connect(&_physicsEngine, &EntitySimulation::entityCollisionWithEntity,
@ -2197,6 +2195,7 @@ void Application::update(float deltaTime) {
{ {
PerformanceTimer perfTimer("physics"); PerformanceTimer perfTimer("physics");
_myAvatar->preSimulation();
_physicsEngine.stepSimulation(); _physicsEngine.stepSimulation();
} }
@ -4208,7 +4207,7 @@ void Application::checkSkeleton() {
_myAvatar->setSkeletonModelURL(DEFAULT_BODY_MODEL_URL); _myAvatar->setSkeletonModelURL(DEFAULT_BODY_MODEL_URL);
_myAvatar->sendIdentityPacket(); _myAvatar->sendIdentityPacket();
} else { } else {
_myAvatar->updateLocalAABox(); _myAvatar->updateCharacterController();
_physicsEngine.setAvatarData(_myAvatar); _physicsEngine.setCharacterController(_myAvatar->getCharacterController());
} }
} }

View file

@ -70,7 +70,6 @@ MyAvatar::MyAvatar() :
Avatar(), Avatar(),
_turningKeyPressTime(0.0f), _turningKeyPressTime(0.0f),
_gravity(0.0f, 0.0f, 0.0f), _gravity(0.0f, 0.0f, 0.0f),
_shouldJump(false),
_wasPushing(false), _wasPushing(false),
_isPushing(false), _isPushing(false),
_isBraking(false), _isBraking(false),
@ -82,6 +81,8 @@ MyAvatar::MyAvatar() :
_scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE), _scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE),
_scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME), _scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME),
_motionBehaviors(AVATAR_MOTION_DEFAULTS), _motionBehaviors(AVATAR_MOTION_DEFAULTS),
_enablePhysics(false),
_characterController(this),
_lookAtTargetAvatar(), _lookAtTargetAvatar(),
_shouldRender(true), _shouldRender(true),
_billboardValid(false), _billboardValid(false),
@ -954,15 +955,15 @@ glm::vec3 MyAvatar::getSkeletonPosition() const {
return Avatar::getPosition(); return Avatar::getPosition();
} }
void MyAvatar::updateLocalAABox() { void MyAvatar::updateCharacterController() {
// compute localAABox
const CapsuleShape& capsule = _skeletonModel.getBoundingShape(); const CapsuleShape& capsule = _skeletonModel.getBoundingShape();
float radius = capsule.getRadius(); float radius = capsule.getRadius();
float height = 2.0f * (capsule.getHalfHeight() + radius); float height = 2.0f * (capsule.getHalfHeight() + radius);
glm::vec3 offset = _skeletonModel.getBoundingShapeOffset();
glm::vec3 corner(-radius, -0.5f * height, -radius); glm::vec3 corner(-radius, -0.5f * height, -radius);
corner += offset; corner += _skeletonModel.getBoundingShapeOffset();
glm::vec3 scale(2.0f * radius, height, 2.0f * radius); glm::vec3 scale(2.0f * radius, height, 2.0f * radius);
_localAABox.setBox(corner, scale); _characterController.setLocalBoundingBox(corner, scale);
} }
QString MyAvatar::getScriptedMotorFrame() const { QString MyAvatar::getScriptedMotorFrame() const {
@ -1580,6 +1581,10 @@ glm::vec3 MyAvatar::getLaserPointerTipPosition(const PalmData* palm) {
return palm->getPosition(); return palm->getPosition();
} }
void MyAvatar::preSimulation() {
_characterController.setEnabled(_enablePhysics);
}
void MyAvatar::clearDriveKeys() { void MyAvatar::clearDriveKeys() {
for (int i = 0; i < MAX_DRIVE_KEYS; ++i) { for (int i = 0; i < MAX_DRIVE_KEYS; ++i) {
_driveKeys[i] = 0.0f; _driveKeys[i] = 0.0f;

View file

@ -13,6 +13,7 @@
#define hifi_MyAvatar_h #define hifi_MyAvatar_h
#include <SettingHandle.h> #include <SettingHandle.h>
#include <CharacterController.h>
#include "Avatar.h" #include "Avatar.h"
@ -88,7 +89,7 @@ public:
void clearDriveKeys(); void clearDriveKeys();
void setDriveKeys(int key, float val) { _driveKeys[key] = val; }; void setDriveKeys(int key, float val) { _driveKeys[key] = val; };
bool getDriveKeys(int key) { return _driveKeys[key] != 0.0f; }; bool getDriveKeys(int key) { return _driveKeys[key] != 0.0f; };
void jump() { _shouldJump = true; }; void jump() { _characterController.jump(); }
bool isMyAvatar() { return true; } bool isMyAvatar() { return true; }
@ -122,6 +123,8 @@ public:
virtual glm::vec3 getSkeletonPosition() const; virtual glm::vec3 getSkeletonPosition() const;
void updateLocalAABox(); void updateLocalAABox();
CharacterController* getCharacterController() { return &_characterController; }
void updateCharacterController();
void clearJointAnimationPriorities(); void clearJointAnimationPriorities();
@ -145,6 +148,11 @@ public:
const RecorderPointer getRecorder() const { return _recorder; } const RecorderPointer getRecorder() const { return _recorder; }
const PlayerPointer getPlayer() const { return _player; } const PlayerPointer getPlayer() const { return _player; }
void togglePhysicsEnabled() { _enablePhysics = !_enablePhysics; }
bool isPhysicsEnabled() { return _enablePhysics; }
void setPhysicsEnabled(bool enablePhysics) { _enablePhysics = enablePhysics; }
void preSimulation();
public slots: public slots:
void increaseSize(); void increaseSize();
@ -186,7 +194,6 @@ private:
float _turningKeyPressTime; float _turningKeyPressTime;
glm::vec3 _gravity; glm::vec3 _gravity;
bool _shouldJump;
float _driveKeys[MAX_DRIVE_KEYS]; float _driveKeys[MAX_DRIVE_KEYS];
bool _wasPushing; bool _wasPushing;
bool _isPushing; bool _isPushing;
@ -202,6 +209,9 @@ private:
int _scriptedMotorFrame; int _scriptedMotorFrame;
quint32 _motionBehaviors; quint32 _motionBehaviors;
bool _enablePhysics;
CharacterController _characterController;
QWeakPointer<AvatarData> _lookAtTargetAvatar; QWeakPointer<AvatarData> _lookAtTargetAvatar;
glm::vec3 _targetAvatarPosition; glm::vec3 _targetAvatarPosition;
bool _shouldRender; bool _shouldRender;

View file

@ -300,16 +300,6 @@ public:
const AABox& getLocalAABox() const { return _localAABox; } const AABox& getLocalAABox() const { return _localAABox; }
const Referential* getReferential() const { return _referential; } const Referential* getReferential() const { return _referential; }
void togglePhysicsEnabled() { _enablePhysics = !_enablePhysics; }
bool isPhysicsEnabled() { return _enablePhysics; }
void setPhysicsEnabled(bool enablePhysics) { _enablePhysics = enablePhysics; }
void lockForRead() { _lock.lockForRead(); }
bool tryLockForRead() { return _lock.tryLockForRead(); }
void lockForWrite() { _lock.lockForWrite(); }
bool tryLockForWrite() { return _lock.tryLockForWrite(); }
void unlock() { _lock.unlock(); }
void setVelocity(const glm::vec3 velocity) { _velocity = velocity; } void setVelocity(const glm::vec3 velocity) { _velocity = velocity; }
Q_INVOKABLE glm::vec3 getVelocity() const { return _velocity; } Q_INVOKABLE glm::vec3 getVelocity() const { return _velocity; }
@ -409,9 +399,6 @@ private:
// privatize the copy constructor and assignment operator so they cannot be called // privatize the copy constructor and assignment operator so they cannot be called
AvatarData(const AvatarData&); AvatarData(const AvatarData&);
AvatarData& operator= (const AvatarData&); AvatarData& operator= (const AvatarData&);
QReadWriteLock _lock;
bool _enablePhysics = false;
}; };
Q_DECLARE_METATYPE(AvatarData*) Q_DECLARE_METATYPE(AvatarData*)

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
/* /*
Bullet Continuous Collision Detection and Physics Library Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
2015.03.25 -- modified by Andrew Meadows andrew@highfidelity.io
This software is provided 'as-is', without any express or implied warranty. 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. In no event will the authors be held liable for any damages arising from the use of this software.
@ -37,59 +38,57 @@ class btPairCachingGhostObject;
///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations. ///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user. ///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
ATTRIBUTE_ALIGNED16(class) CharacterController : public btCharacterControllerInterface ATTRIBUTE_ALIGNED16(class) CharacterController : public btCharacterControllerInterface
{ {
protected: protected:
AvatarData* m_avatarData = NULL; AvatarData* _avatarData = NULL;
btPairCachingGhostObject* m_ghostObject; btPairCachingGhostObject* _ghostObject;
glm::vec3 m_shapeLocalOffset;
btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast btConvexShape* _convexShape;//is also in _ghostObject, but it needs to be convex, so we store it here to avoid upcast
btScalar m_radius; btScalar _radius;
btScalar m_halfHeight; btScalar _halfHeight;
btScalar m_verticalVelocity; btScalar _verticalVelocity;
btScalar m_verticalOffset; // fall distance from velocity this frame btScalar _verticalOffset; // fall distance from velocity this frame
btScalar m_maxFallSpeed; btScalar _maxFallSpeed;
btScalar m_jumpSpeed; btScalar _jumpSpeed;
btScalar m_maxJumpHeight; btScalar _maxJumpHeight;
btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value) btScalar _maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization) btScalar _maxSlopeCosine; // Cosine equivalent of _maxSlopeRadians (calculated once when set, for optimization)
btScalar m_gravity; btScalar _gravity;
btScalar m_turnAngle; btScalar _stepHeight; // height of stepUp prior to stepForward
btScalar m_stepHeight; // height of stepUp prior to stepForward btScalar _addedMargin;//@todo: remove this and fix the code
btScalar m_addedMargin;//@todo: remove this and fix the code
///this is the desired walk direction, set by the user ///this is the desired walk direction, set by the user
btVector3 m_walkDirection; btVector3 _walkDirection;
btVector3 m_normalizedDirection; btVector3 _normalizedDirection;
//some internal variables //some internal variables
btVector3 m_currentPosition; btVector3 _currentPosition;
btVector3 m_targetPosition; btQuaternion _currentRotation;
btScalar m_lastStepUp; btVector3 _targetPosition;
btScalar _lastStepUp;
///keep track of the contact manifolds ///keep track of the contact manifolds
btManifoldArray m_manifoldArray; btManifoldArray _manifoldArray;
bool m_touchingContact; bool _touchingContact;
btVector3 m_floorNormal; // points from object to character btVector3 _floorNormal; // points from object to character
bool m_enabled; bool _enabled;
bool m_wasOnGround; bool _wasOnGround;
bool m_wasJumping; bool _wasJumping;
bool m_useWalkDirection; btScalar _velocityTimeInterval;
btScalar m_velocityTimeInterval; uint32_t _pendingFlags;
int m_upAxis;
static btVector3* getUpAxisDirections(); glm::vec3 _shapeLocalOffset;
bool m_interpolateUp; glm::vec3 _boxScale; // used to compute capsule shape
bool full_drop;
bool bounce_fix; btDynamicsWorld* _dynamicsWorld = NULL;
btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal); btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal);
btVector3 parallelComponent(const btVector3& direction, const btVector3& normal); btVector3 parallelComponent(const btVector3& direction, const btVector3& normal);
@ -118,14 +117,6 @@ public:
///btActionInterface interface ///btActionInterface interface
void debugDraw(btIDebugDraw* debugDrawer); void debugDraw(btIDebugDraw* debugDrawer);
void setUpAxis(int axis) {
if (axis < 0)
axis = 0;
if (axis > 2)
axis = 2;
m_upAxis = axis;
}
/// This should probably be called setPositionIncrementPerSimulatorStep. /// This should probably be called setPositionIncrementPerSimulatorStep.
/// This is neither a direction nor a velocity, but the amount to /// This is neither a direction nor a velocity, but the amount to
/// increment the position each simulation iteration, regardless /// increment the position each simulation iteration, regardless
@ -141,18 +132,19 @@ public:
virtual void setVelocityForTimeInterval(const btVector3& velocity, virtual void setVelocityForTimeInterval(const btVector3& velocity,
btScalar timeInterval); btScalar timeInterval);
void reset(btCollisionWorld* collisionWorld ); virtual void reset(btCollisionWorld* collisionWorld );
void warp(const btVector3& origin); virtual void warp(const btVector3& origin);
void preStep(btCollisionWorld* collisionWorld); virtual void preStep(btCollisionWorld* collisionWorld);
void playerStep(btCollisionWorld* collisionWorld, btScalar dt); virtual void playerStep(btCollisionWorld* collisionWorld, btScalar dt);
virtual bool canJump() const;
virtual void jump();
virtual bool onGround() const;
void setMaxFallSpeed(btScalar speed); void setMaxFallSpeed(btScalar speed);
void setJumpSpeed(btScalar jumpSpeed); void setJumpSpeed(btScalar jumpSpeed);
void setMaxJumpHeight(btScalar maxJumpHeight); void setMaxJumpHeight(btScalar maxJumpHeight);
bool canJump() const;
void jump();
void setGravity(btScalar gravity); void setGravity(btScalar gravity);
btScalar getGravity() const; btScalar getGravity() const;
@ -164,11 +156,16 @@ public:
btPairCachingGhostObject* getGhostObject(); btPairCachingGhostObject* getGhostObject();
bool onGround() const;
void setUpInterpolate(bool value); void setUpInterpolate(bool value);
bool needsShapeUpdate(); bool needsRemoval() const;
void updateShape(); bool needsAddition() const;
void setEnabled(bool enabled);
void setDynamicsWorld(btDynamicsWorld* world);
void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale);
bool needsShapeUpdate() const;
void updateShapeIfNecessary();
void preSimulation(btScalar timeStep); void preSimulation(btScalar timeStep);
void postSimulation(); void postSimulation();

View file

@ -280,12 +280,12 @@ void PhysicsEngine::init(EntityEditPacketSender* packetSender) {
void PhysicsEngine::stepSimulation() { void PhysicsEngine::stepSimulation() {
lock(); lock();
// NOTE: the grand order of operations is: // NOTE: the grand order of operations is:
// (1) relay incoming changes // (1) pull incoming changes
// (2) step simulation // (2) step simulation
// (3) synchronize outgoing motion states // (3) synchronize outgoing motion states
// (4) send outgoing packets // (4) send outgoing packets
// This is step (1). // This is step (1) pull incoming changes
relayIncomingChangesToSimulation(); relayIncomingChangesToSimulation();
const int MAX_NUM_SUBSTEPS = 4; const int MAX_NUM_SUBSTEPS = 4;
@ -294,16 +294,25 @@ void PhysicsEngine::stepSimulation() {
_clock.reset(); _clock.reset();
float timeStep = btMin(dt, MAX_TIMESTEP); float timeStep = btMin(dt, MAX_TIMESTEP);
// This is step (2). // TODO: move character->preSimulation() into relayIncomingChanges
if (_characterController) { if (_characterController) {
if (_characterController->needsRemoval()) {
_characterController->setDynamicsWorld(NULL);
}
_characterController->updateShapeIfNecessary();
if (_characterController->needsAddition()) {
_characterController->setDynamicsWorld(_dynamicsWorld);
}
_characterController->preSimulation(timeStep); _characterController->preSimulation(timeStep);
} }
// This is step (2) step simulation
int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP); int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP);
_numSubsteps += (uint32_t)numSubsteps; _numSubsteps += (uint32_t)numSubsteps;
stepNonPhysicalKinematics(usecTimestampNow()); stepNonPhysicalKinematics(usecTimestampNow());
unlock(); unlock();
// TODO: make all of this harvest stuff into one function: relayOutgoingChanges()
if (numSubsteps > 0) { if (numSubsteps > 0) {
// This is step (3) which is done outside of stepSimulation() so we can lock _entityTree. // This is step (3) which is done outside of stepSimulation() so we can lock _entityTree.
// //
@ -598,34 +607,10 @@ bool PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motio
return true; return true;
} }
void PhysicsEngine::setAvatarData(AvatarData *avatarData) { void PhysicsEngine::setCharacterController(CharacterController* character) {
if (_characterController) { if (!_characterController) {
bool needsShapeUpdate = _characterController->needsShapeUpdate();
if (needsShapeUpdate) {
lock();
// remove old info
_dynamicsWorld->removeCollisionObject(_characterController->getGhostObject());
_dynamicsWorld->removeAction(_characterController);
// update shape
_characterController->updateShape();
// insert new info
_dynamicsWorld->addCollisionObject(_characterController->getGhostObject(),
btBroadphaseProxy::CharacterFilter,
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
_dynamicsWorld->addAction(_characterController);
_characterController->reset(_dynamicsWorld);
unlock();
}
} else {
// initialize _characterController
assert(avatarData); // don't pass NULL argument
lock(); lock();
_characterController = new CharacterController(avatarData); _characterController = character;
_dynamicsWorld->addCollisionObject(_characterController->getGhostObject(),
btBroadphaseProxy::CharacterFilter,
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
_dynamicsWorld->addAction(_characterController);
_characterController->reset(_dynamicsWorld);
unlock(); unlock();
} }
} }

View file

@ -17,9 +17,7 @@
#include <QSet> #include <QSet>
#include <btBulletDynamicsCommon.h> #include <btBulletDynamicsCommon.h>
#include <BulletCollision/CollisionDispatch/btGhostObject.h> #include <BulletCollision/CollisionDispatch/btGhostObject.h>
//#include <BulletCollision/CollisionShapes/btCapsuleShape.h>
#include <AvatarData.h>
#include <EntityItem.h> #include <EntityItem.h>
#include <EntitySimulation.h> #include <EntitySimulation.h>
@ -86,7 +84,7 @@ public:
/// process queue of changed from external sources /// process queue of changed from external sources
void relayIncomingChangesToSimulation(); void relayIncomingChangesToSimulation();
void setAvatarData(AvatarData *avatarData); void setCharacterController(CharacterController* character);
private: private:
/// \param motionState pointer to Object's MotionState /// \param motionState pointer to Object's MotionState