mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 12:04:18 +02:00
Merge pull request #4500 from AndrewMeadows/inertia
avatar can jump when using CharacterController
This commit is contained in:
commit
c0b1ff4a57
8 changed files with 455 additions and 483 deletions
|
@ -1909,8 +1909,6 @@ void Application::init() {
|
|||
_physicsEngine.init(&_entityEditSender);
|
||||
|
||||
|
||||
_physicsEngine.setAvatarData(_myAvatar);
|
||||
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
|
||||
connect(&_physicsEngine, &EntitySimulation::entityCollisionWithEntity,
|
||||
|
@ -2197,6 +2195,7 @@ void Application::update(float deltaTime) {
|
|||
|
||||
{
|
||||
PerformanceTimer perfTimer("physics");
|
||||
_myAvatar->preSimulation();
|
||||
_physicsEngine.stepSimulation();
|
||||
}
|
||||
|
||||
|
@ -4208,7 +4207,7 @@ void Application::checkSkeleton() {
|
|||
_myAvatar->setSkeletonModelURL(DEFAULT_BODY_MODEL_URL);
|
||||
_myAvatar->sendIdentityPacket();
|
||||
} else {
|
||||
_myAvatar->updateLocalAABox();
|
||||
_physicsEngine.setAvatarData(_myAvatar);
|
||||
_myAvatar->updateCharacterController();
|
||||
_physicsEngine.setCharacterController(_myAvatar->getCharacterController());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,6 @@ MyAvatar::MyAvatar() :
|
|||
Avatar(),
|
||||
_turningKeyPressTime(0.0f),
|
||||
_gravity(0.0f, 0.0f, 0.0f),
|
||||
_shouldJump(false),
|
||||
_wasPushing(false),
|
||||
_isPushing(false),
|
||||
_isBraking(false),
|
||||
|
@ -82,6 +81,8 @@ MyAvatar::MyAvatar() :
|
|||
_scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE),
|
||||
_scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME),
|
||||
_motionBehaviors(AVATAR_MOTION_DEFAULTS),
|
||||
_enablePhysics(false),
|
||||
_characterController(this),
|
||||
_lookAtTargetAvatar(),
|
||||
_shouldRender(true),
|
||||
_billboardValid(false),
|
||||
|
@ -954,15 +955,15 @@ glm::vec3 MyAvatar::getSkeletonPosition() const {
|
|||
return Avatar::getPosition();
|
||||
}
|
||||
|
||||
void MyAvatar::updateLocalAABox() {
|
||||
void MyAvatar::updateCharacterController() {
|
||||
// compute localAABox
|
||||
const CapsuleShape& capsule = _skeletonModel.getBoundingShape();
|
||||
float radius = capsule.getRadius();
|
||||
float height = 2.0f * (capsule.getHalfHeight() + radius);
|
||||
glm::vec3 offset = _skeletonModel.getBoundingShapeOffset();
|
||||
glm::vec3 corner(-radius, -0.5f * height, -radius);
|
||||
corner += offset;
|
||||
corner += _skeletonModel.getBoundingShapeOffset();
|
||||
glm::vec3 scale(2.0f * radius, height, 2.0f * radius);
|
||||
_localAABox.setBox(corner, scale);
|
||||
_characterController.setLocalBoundingBox(corner, scale);
|
||||
}
|
||||
|
||||
QString MyAvatar::getScriptedMotorFrame() const {
|
||||
|
@ -1580,6 +1581,10 @@ glm::vec3 MyAvatar::getLaserPointerTipPosition(const PalmData* palm) {
|
|||
return palm->getPosition();
|
||||
}
|
||||
|
||||
void MyAvatar::preSimulation() {
|
||||
_characterController.setEnabled(_enablePhysics);
|
||||
}
|
||||
|
||||
void MyAvatar::clearDriveKeys() {
|
||||
for (int i = 0; i < MAX_DRIVE_KEYS; ++i) {
|
||||
_driveKeys[i] = 0.0f;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define hifi_MyAvatar_h
|
||||
|
||||
#include <SettingHandle.h>
|
||||
#include <CharacterController.h>
|
||||
|
||||
#include "Avatar.h"
|
||||
|
||||
|
@ -88,7 +89,7 @@ public:
|
|||
void clearDriveKeys();
|
||||
void setDriveKeys(int key, float val) { _driveKeys[key] = val; };
|
||||
bool getDriveKeys(int key) { return _driveKeys[key] != 0.0f; };
|
||||
void jump() { _shouldJump = true; };
|
||||
void jump() { _characterController.jump(); }
|
||||
|
||||
bool isMyAvatar() { return true; }
|
||||
|
||||
|
@ -122,6 +123,8 @@ public:
|
|||
|
||||
virtual glm::vec3 getSkeletonPosition() const;
|
||||
void updateLocalAABox();
|
||||
CharacterController* getCharacterController() { return &_characterController; }
|
||||
void updateCharacterController();
|
||||
|
||||
void clearJointAnimationPriorities();
|
||||
|
||||
|
@ -145,6 +148,11 @@ public:
|
|||
|
||||
const RecorderPointer getRecorder() const { return _recorder; }
|
||||
const PlayerPointer getPlayer() const { return _player; }
|
||||
|
||||
void togglePhysicsEnabled() { _enablePhysics = !_enablePhysics; }
|
||||
bool isPhysicsEnabled() { return _enablePhysics; }
|
||||
void setPhysicsEnabled(bool enablePhysics) { _enablePhysics = enablePhysics; }
|
||||
void preSimulation();
|
||||
|
||||
public slots:
|
||||
void increaseSize();
|
||||
|
@ -186,7 +194,6 @@ private:
|
|||
float _turningKeyPressTime;
|
||||
glm::vec3 _gravity;
|
||||
|
||||
bool _shouldJump;
|
||||
float _driveKeys[MAX_DRIVE_KEYS];
|
||||
bool _wasPushing;
|
||||
bool _isPushing;
|
||||
|
@ -202,6 +209,9 @@ private:
|
|||
int _scriptedMotorFrame;
|
||||
quint32 _motionBehaviors;
|
||||
|
||||
bool _enablePhysics;
|
||||
CharacterController _characterController;
|
||||
|
||||
QWeakPointer<AvatarData> _lookAtTargetAvatar;
|
||||
glm::vec3 _targetAvatarPosition;
|
||||
bool _shouldRender;
|
||||
|
|
|
@ -300,16 +300,6 @@ public:
|
|||
const AABox& getLocalAABox() const { return _localAABox; }
|
||||
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; }
|
||||
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
|
||||
AvatarData(const AvatarData&);
|
||||
AvatarData& operator= (const AvatarData&);
|
||||
|
||||
QReadWriteLock _lock;
|
||||
bool _enablePhysics = false;
|
||||
};
|
||||
Q_DECLARE_METATYPE(AvatarData*)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
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.
|
||||
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.
|
||||
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
|
||||
|
||||
|
||||
ATTRIBUTE_ALIGNED16(class) CharacterController : public btCharacterControllerInterface
|
||||
{
|
||||
protected:
|
||||
|
||||
AvatarData* m_avatarData = NULL;
|
||||
btPairCachingGhostObject* m_ghostObject;
|
||||
glm::vec3 m_shapeLocalOffset;
|
||||
AvatarData* _avatarData = NULL;
|
||||
btPairCachingGhostObject* _ghostObject;
|
||||
|
||||
btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
|
||||
btScalar m_radius;
|
||||
btScalar m_halfHeight;
|
||||
btConvexShape* _convexShape;//is also in _ghostObject, but it needs to be convex, so we store it here to avoid upcast
|
||||
btScalar _radius;
|
||||
btScalar _halfHeight;
|
||||
|
||||
btScalar m_verticalVelocity;
|
||||
btScalar m_verticalOffset; // fall distance from velocity this frame
|
||||
btScalar m_maxFallSpeed;
|
||||
btScalar m_jumpSpeed;
|
||||
btScalar m_maxJumpHeight;
|
||||
btScalar m_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 m_gravity;
|
||||
btScalar _verticalVelocity;
|
||||
btScalar _verticalOffset; // fall distance from velocity this frame
|
||||
btScalar _maxFallSpeed;
|
||||
btScalar _jumpSpeed;
|
||||
btScalar _maxJumpHeight;
|
||||
btScalar _maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
|
||||
btScalar _maxSlopeCosine; // Cosine equivalent of _maxSlopeRadians (calculated once when set, for optimization)
|
||||
btScalar _gravity;
|
||||
|
||||
btScalar m_turnAngle;
|
||||
btScalar _stepHeight; // height of stepUp prior to stepForward
|
||||
|
||||
btScalar m_stepHeight; // height of stepUp prior to stepForward
|
||||
|
||||
btScalar m_addedMargin;//@todo: remove this and fix the code
|
||||
btScalar _addedMargin;//@todo: remove this and fix the code
|
||||
|
||||
///this is the desired walk direction, set by the user
|
||||
btVector3 m_walkDirection;
|
||||
btVector3 m_normalizedDirection;
|
||||
btVector3 _walkDirection;
|
||||
btVector3 _normalizedDirection;
|
||||
|
||||
//some internal variables
|
||||
btVector3 m_currentPosition;
|
||||
btVector3 m_targetPosition;
|
||||
btScalar m_lastStepUp;
|
||||
btVector3 _currentPosition;
|
||||
btQuaternion _currentRotation;
|
||||
btVector3 _targetPosition;
|
||||
btScalar _lastStepUp;
|
||||
|
||||
///keep track of the contact manifolds
|
||||
btManifoldArray m_manifoldArray;
|
||||
btManifoldArray _manifoldArray;
|
||||
|
||||
bool m_touchingContact;
|
||||
btVector3 m_floorNormal; // points from object to character
|
||||
bool _touchingContact;
|
||||
btVector3 _floorNormal; // points from object to character
|
||||
|
||||
bool m_enabled;
|
||||
bool m_wasOnGround;
|
||||
bool m_wasJumping;
|
||||
bool m_useWalkDirection;
|
||||
btScalar m_velocityTimeInterval;
|
||||
int m_upAxis;
|
||||
bool _enabled;
|
||||
bool _wasOnGround;
|
||||
bool _wasJumping;
|
||||
btScalar _velocityTimeInterval;
|
||||
uint32_t _pendingFlags;
|
||||
|
||||
static btVector3* getUpAxisDirections();
|
||||
bool m_interpolateUp;
|
||||
bool full_drop;
|
||||
bool bounce_fix;
|
||||
glm::vec3 _shapeLocalOffset;
|
||||
glm::vec3 _boxScale; // used to compute capsule shape
|
||||
|
||||
btDynamicsWorld* _dynamicsWorld = NULL;
|
||||
|
||||
btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal);
|
||||
btVector3 parallelComponent(const btVector3& direction, const btVector3& normal);
|
||||
|
@ -118,14 +117,6 @@ public:
|
|||
///btActionInterface interface
|
||||
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 is neither a direction nor a velocity, but the amount to
|
||||
/// increment the position each simulation iteration, regardless
|
||||
|
@ -141,18 +132,19 @@ public:
|
|||
virtual void setVelocityForTimeInterval(const btVector3& velocity,
|
||||
btScalar timeInterval);
|
||||
|
||||
void reset(btCollisionWorld* collisionWorld );
|
||||
void warp(const btVector3& origin);
|
||||
virtual void reset(btCollisionWorld* collisionWorld );
|
||||
virtual void warp(const btVector3& origin);
|
||||
|
||||
void preStep(btCollisionWorld* collisionWorld);
|
||||
void playerStep(btCollisionWorld* collisionWorld, btScalar dt);
|
||||
virtual void preStep(btCollisionWorld* collisionWorld);
|
||||
virtual void playerStep(btCollisionWorld* collisionWorld, btScalar dt);
|
||||
|
||||
virtual bool canJump() const;
|
||||
virtual void jump();
|
||||
virtual bool onGround() const;
|
||||
|
||||
void setMaxFallSpeed(btScalar speed);
|
||||
void setJumpSpeed(btScalar jumpSpeed);
|
||||
void setMaxJumpHeight(btScalar maxJumpHeight);
|
||||
bool canJump() const;
|
||||
|
||||
void jump();
|
||||
|
||||
void setGravity(btScalar gravity);
|
||||
btScalar getGravity() const;
|
||||
|
@ -164,11 +156,16 @@ public:
|
|||
|
||||
btPairCachingGhostObject* getGhostObject();
|
||||
|
||||
bool onGround() const;
|
||||
void setUpInterpolate(bool value);
|
||||
|
||||
bool needsShapeUpdate();
|
||||
void updateShape();
|
||||
bool needsRemoval() const;
|
||||
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 postSimulation();
|
||||
|
|
|
@ -280,12 +280,12 @@ void PhysicsEngine::init(EntityEditPacketSender* packetSender) {
|
|||
void PhysicsEngine::stepSimulation() {
|
||||
lock();
|
||||
// NOTE: the grand order of operations is:
|
||||
// (1) relay incoming changes
|
||||
// (1) pull incoming changes
|
||||
// (2) step simulation
|
||||
// (3) synchronize outgoing motion states
|
||||
// (4) send outgoing packets
|
||||
|
||||
// This is step (1).
|
||||
// This is step (1) pull incoming changes
|
||||
relayIncomingChangesToSimulation();
|
||||
|
||||
const int MAX_NUM_SUBSTEPS = 4;
|
||||
|
@ -294,16 +294,25 @@ void PhysicsEngine::stepSimulation() {
|
|||
_clock.reset();
|
||||
float timeStep = btMin(dt, MAX_TIMESTEP);
|
||||
|
||||
// This is step (2).
|
||||
// TODO: move character->preSimulation() into relayIncomingChanges
|
||||
if (_characterController) {
|
||||
if (_characterController->needsRemoval()) {
|
||||
_characterController->setDynamicsWorld(NULL);
|
||||
}
|
||||
_characterController->updateShapeIfNecessary();
|
||||
if (_characterController->needsAddition()) {
|
||||
_characterController->setDynamicsWorld(_dynamicsWorld);
|
||||
}
|
||||
_characterController->preSimulation(timeStep);
|
||||
}
|
||||
|
||||
// This is step (2) step simulation
|
||||
int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP);
|
||||
_numSubsteps += (uint32_t)numSubsteps;
|
||||
stepNonPhysicalKinematics(usecTimestampNow());
|
||||
unlock();
|
||||
|
||||
// TODO: make all of this harvest stuff into one function: relayOutgoingChanges()
|
||||
if (numSubsteps > 0) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
void PhysicsEngine::setAvatarData(AvatarData *avatarData) {
|
||||
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
|
||||
void PhysicsEngine::setCharacterController(CharacterController* character) {
|
||||
if (!_characterController) {
|
||||
lock();
|
||||
_characterController = new CharacterController(avatarData);
|
||||
_dynamicsWorld->addCollisionObject(_characterController->getGhostObject(),
|
||||
btBroadphaseProxy::CharacterFilter,
|
||||
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
|
||||
_dynamicsWorld->addAction(_characterController);
|
||||
_characterController->reset(_dynamicsWorld);
|
||||
_characterController = character;
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
#include <QSet>
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
|
||||
//#include <BulletCollision/CollisionShapes/btCapsuleShape.h>
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include <EntityItem.h>
|
||||
#include <EntitySimulation.h>
|
||||
|
||||
|
@ -86,7 +84,7 @@ public:
|
|||
/// process queue of changed from external sources
|
||||
void relayIncomingChangesToSimulation();
|
||||
|
||||
void setAvatarData(AvatarData *avatarData);
|
||||
void setCharacterController(CharacterController* character);
|
||||
|
||||
private:
|
||||
/// \param motionState pointer to Object's MotionState
|
||||
|
|
Loading…
Reference in a new issue