mirror of
https://github.com/overte-org/overte.git
synced 2025-04-18 00:26:33 +02:00
CharacterController: better debug support of internal state machine
Head is no longer visible when flying fast, in first-person HMD mode.
This commit is contained in:
parent
8b5cf3e49a
commit
c4e1509aa2
3 changed files with 40 additions and 24 deletions
|
@ -1311,21 +1311,23 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
|
|||
_prevShouldDrawHead = shouldDrawHead;
|
||||
}
|
||||
|
||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.5f;
|
||||
|
||||
bool MyAvatar::cameraInsideHead() const {
|
||||
const Head* head = getHead();
|
||||
const glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
|
||||
return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale());
|
||||
return glm::length(cameraPosition - getDefaultEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale());
|
||||
}
|
||||
|
||||
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||
return ((renderArgs->_renderMode != RenderArgs::DEFAULT_RENDER_MODE) ||
|
||||
(qApp->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
||||
!cameraInsideHead());
|
||||
bool defaultMode = renderArgs->_renderMode == RenderArgs::DEFAULT_RENDER_MODE;
|
||||
bool firstPerson = qApp->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON;
|
||||
bool insideHead = cameraInsideHead();
|
||||
return !defaultMode || !firstPerson || !insideHead;
|
||||
}
|
||||
|
||||
void MyAvatar::updateOrientation(float deltaTime) {
|
||||
|
||||
// Smoothly rotate body with arrow keys
|
||||
float targetSpeed = _driveKeys[YAW] * _yawSpeed;
|
||||
if (targetSpeed != 0.0f) {
|
||||
|
|
|
@ -21,7 +21,11 @@ const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f);
|
|||
const float JUMP_SPEED = 3.5f;
|
||||
const float MAX_FALL_HEIGHT = 20.0f;
|
||||
|
||||
#define DEBUG_STATE_CHANGE
|
||||
#ifdef DEBUG_STATE_CHANGE
|
||||
#define SET_STATE(desiredState, reason) setState(desiredState, reason)
|
||||
#else
|
||||
#define SET_STATE(desiredState, reason) setState(desiredState)
|
||||
#endif
|
||||
|
||||
// helper class for simple ray-traces from character
|
||||
class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback {
|
||||
|
@ -65,7 +69,6 @@ CharacterController::CharacterController() {
|
|||
_hasSupport = false;
|
||||
|
||||
_pendingFlags = PENDING_FLAG_UPDATE_SHAPE;
|
||||
|
||||
}
|
||||
|
||||
bool CharacterController::needsRemoval() const {
|
||||
|
@ -274,10 +277,14 @@ static const char* stateToStr(CharacterController::State state) {
|
|||
}
|
||||
#endif // #ifdef DEBUG_STATE_CHANGE
|
||||
|
||||
#ifdef DEBUG_STATE_CHANGE
|
||||
void CharacterController::setState(State desiredState, const char* reason) {
|
||||
#else
|
||||
void CharacterController::setState(State desiredState) {
|
||||
#endif
|
||||
if (desiredState != _state) {
|
||||
#ifdef DEBUG_STATE_CHANGE
|
||||
qCDebug(physics) << "CharacterController::setState" << stateToStr(desiredState) << "<-" << stateToStr(_state);
|
||||
qCDebug(physics) << "CharacterController::setState" << stateToStr(desiredState) << "from" << stateToStr(_state) << "," << reason;
|
||||
#endif
|
||||
if (desiredState == State::Hover && _state != State::Hover) {
|
||||
// hover enter
|
||||
|
@ -339,7 +346,7 @@ void CharacterController::setEnabled(bool enabled) {
|
|||
}
|
||||
_pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION;
|
||||
}
|
||||
setState(State::Hover);
|
||||
SET_STATE(State::Hover, "setEnabled");
|
||||
_enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
@ -438,8 +445,8 @@ void CharacterController::preSimulation() {
|
|||
const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 200 * MSECS_PER_SECOND;
|
||||
const btScalar MIN_HOVER_HEIGHT = 2.5f;
|
||||
const quint64 JUMP_TO_HOVER_PERIOD = 750 * MSECS_PER_SECOND;
|
||||
const btScalar UPWARD_VELOCITY_THRESHOLD = 0.05f;
|
||||
const btScalar MAX_FLYING_SPEED = 30.0f;
|
||||
const btScalar UPWARD_VELOCITY_THRESHOLD = 0.1f;
|
||||
const btScalar MAX_WALKING_SPEED = 2.5f;
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
|
@ -452,23 +459,22 @@ void CharacterController::preSimulation() {
|
|||
}
|
||||
|
||||
bool jumpButtonHeld = _pendingFlags & PENDING_FLAG_JUMP;
|
||||
bool wantsToGoUp = !jumpButtonHeld && _walkVelocity.dot(_currentUp) > UPWARD_VELOCITY_THRESHOLD;
|
||||
bool tooFast = actualHorizVelocity.length() > (MAX_FLYING_SPEED / 2.0f);
|
||||
bool flyingFast = _state == State::Hover && actualHorizVelocity.length() > (MAX_WALKING_SPEED * 0.75f);
|
||||
|
||||
switch (_state) {
|
||||
case State::Ground:
|
||||
if (!rayCallback.hasHit() && !_hasSupport) {
|
||||
setState(State::Hover);
|
||||
SET_STATE(State::Hover, "no ground");
|
||||
} else if (_pendingFlags & PENDING_FLAG_JUMP) {
|
||||
_takeOffJumpButtonID = _jumpButtonDownCount;
|
||||
setState(State::Takeoff);
|
||||
SET_STATE(State::Takeoff, "jump pressed");
|
||||
}
|
||||
break;
|
||||
case State::Takeoff:
|
||||
if (!rayCallback.hasHit() && !_hasSupport) {
|
||||
setState(State::Hover);
|
||||
SET_STATE(State::Hover, "no ground");
|
||||
} else if ((now - _takeoffToInAirStart) > TAKE_OFF_TO_IN_AIR_PERIOD) {
|
||||
setState(State::InAir);
|
||||
SET_STATE(State::InAir, "takeoff done");
|
||||
_takeoffToInAirStart = now + USECS_PER_SECOND * 86500.0f;
|
||||
velocity += _jumpSpeed * _currentUp;
|
||||
_rigidBody->setLinearVelocity(velocity);
|
||||
|
@ -476,17 +482,19 @@ void CharacterController::preSimulation() {
|
|||
break;
|
||||
case State::InAir: {
|
||||
if ((velocity.dot(_currentUp) <= (JUMP_SPEED / 2.0f)) && ((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport)) {
|
||||
setState(State::Ground);
|
||||
} else if ((jumpButtonHeld && ((_takeOffJumpButtonID != _jumpButtonDownCount) || (now - _jumpButtonDownStart) > JUMP_TO_HOVER_PERIOD)) || wantsToGoUp) {
|
||||
setState(State::Hover);
|
||||
SET_STATE(State::Ground, "hit ground");
|
||||
} else if (jumpButtonHeld && (_takeOffJumpButtonID != _jumpButtonDownCount)) {
|
||||
SET_STATE(State::Hover, "double jump button");
|
||||
} else if (jumpButtonHeld && (now - _jumpButtonDownStart) > JUMP_TO_HOVER_PERIOD) {
|
||||
SET_STATE(State::Hover, "jump button held");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case State::Hover:
|
||||
if (!jumpButtonHeld && !wantsToGoUp && _floorDistance < MIN_HOVER_HEIGHT && !tooFast) {
|
||||
setState(State::InAir);
|
||||
} else if (((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport) && !tooFast) {
|
||||
setState(State::Ground);
|
||||
if ((_floorDistance < MIN_HOVER_HEIGHT) && !jumpButtonHeld && !flyingFast) {
|
||||
SET_STATE(State::InAir, "near ground");
|
||||
} else if (((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport) && !flyingFast) {
|
||||
SET_STATE(State::Ground, "touching ground");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ class btRigidBody;
|
|||
class btCollisionWorld;
|
||||
class btDynamicsWorld;
|
||||
|
||||
//#define DEBUG_STATE_CHANGE
|
||||
|
||||
class CharacterController : public btCharacterControllerInterface {
|
||||
public:
|
||||
CharacterController();
|
||||
|
@ -92,7 +94,11 @@ public:
|
|||
bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);
|
||||
|
||||
protected:
|
||||
#ifdef DEBUG_STATE_CHANGE
|
||||
void setState(State state, const char* reason);
|
||||
#else
|
||||
void setState(State state);
|
||||
#endif
|
||||
|
||||
void updateUpAxis(const glm::quat& rotation);
|
||||
bool checkForSupport(btCollisionWorld* collisionWorld) const;
|
||||
|
|
Loading…
Reference in a new issue