mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
move code into CharacterController::updateState()
This commit is contained in:
parent
8dd5c9b92b
commit
a8af8d6027
2 changed files with 100 additions and 98 deletions
|
@ -581,116 +581,121 @@ void CharacterController::computeNewVelocity(btScalar dt, glm::vec3& velocity) {
|
||||||
velocity = bulletToGLM(btVelocity);
|
velocity = bulletToGLM(btVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::preSimulation() {
|
void CharacterController::updateState() {
|
||||||
if (_dynamicsWorld) {
|
const btScalar FLY_TO_GROUND_THRESHOLD = 0.1f * _radius;
|
||||||
quint64 now = usecTimestampNow();
|
const btScalar GROUND_TO_FLY_THRESHOLD = 0.8f * _radius + _halfHeight;
|
||||||
|
const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 250 * MSECS_PER_SECOND;
|
||||||
|
const btScalar MIN_HOVER_HEIGHT = 2.5f;
|
||||||
|
const quint64 JUMP_TO_HOVER_PERIOD = 1100 * MSECS_PER_SECOND;
|
||||||
|
|
||||||
// slam body transform
|
// scan for distant floor
|
||||||
_rigidBody->setWorldTransform(btTransform(btTransform(_rotation, _position)));
|
// rayStart is at center of bottom sphere
|
||||||
btVector3 velocity = _rigidBody->getLinearVelocity();
|
btVector3 rayStart = _position;
|
||||||
_preSimulationVelocity = velocity;
|
|
||||||
|
|
||||||
// scan for distant floor
|
// rayEnd is straight down MAX_FALL_HEIGHT
|
||||||
// rayStart is at center of bottom sphere
|
btScalar rayLength = _radius + MAX_FALL_HEIGHT;
|
||||||
btVector3 rayStart = _position;
|
btVector3 rayEnd = rayStart - rayLength * _currentUp;
|
||||||
|
|
||||||
// rayEnd is straight down MAX_FALL_HEIGHT
|
ClosestNotMe rayCallback(_rigidBody);
|
||||||
btScalar rayLength = _radius + MAX_FALL_HEIGHT;
|
rayCallback.m_closestHitFraction = 1.0f;
|
||||||
btVector3 rayEnd = rayStart - rayLength * _currentUp;
|
_dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback);
|
||||||
|
bool rayHasHit = rayCallback.hasHit();
|
||||||
const btScalar FLY_TO_GROUND_THRESHOLD = 0.1f * _radius;
|
quint64 now = usecTimestampNow();
|
||||||
const btScalar GROUND_TO_FLY_THRESHOLD = 0.8f * _radius + _halfHeight;
|
if (rayHasHit) {
|
||||||
const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 250 * MSECS_PER_SECOND;
|
_rayHitStartTime = now;
|
||||||
const btScalar MIN_HOVER_HEIGHT = 2.5f;
|
_floorDistance = rayLength * rayCallback.m_closestHitFraction - (_radius + _halfHeight);
|
||||||
const quint64 JUMP_TO_HOVER_PERIOD = 1100 * MSECS_PER_SECOND;
|
} else {
|
||||||
const btScalar MAX_WALKING_SPEED = 2.5f;
|
|
||||||
const quint64 RAY_HIT_START_PERIOD = 500 * MSECS_PER_SECOND;
|
const quint64 RAY_HIT_START_PERIOD = 500 * MSECS_PER_SECOND;
|
||||||
|
if ((now - _rayHitStartTime) < RAY_HIT_START_PERIOD) {
|
||||||
ClosestNotMe rayCallback(_rigidBody);
|
|
||||||
rayCallback.m_closestHitFraction = 1.0f;
|
|
||||||
_dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback);
|
|
||||||
bool rayHasHit = rayCallback.hasHit();
|
|
||||||
if (rayHasHit) {
|
|
||||||
_rayHitStartTime = now;
|
|
||||||
_floorDistance = rayLength * rayCallback.m_closestHitFraction - (_radius + _halfHeight);
|
|
||||||
} else if ((now - _rayHitStartTime) < RAY_HIT_START_PERIOD) {
|
|
||||||
rayHasHit = true;
|
rayHasHit = true;
|
||||||
} else {
|
} else {
|
||||||
_floorDistance = FLT_MAX;
|
_floorDistance = FLT_MAX;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// record a time stamp when the jump button was first pressed.
|
// record a time stamp when the jump button was first pressed.
|
||||||
if ((_previousFlags & PENDING_FLAG_JUMP) != (_pendingFlags & PENDING_FLAG_JUMP)) {
|
bool jumpButtonHeld = _pendingFlags & PENDING_FLAG_JUMP;
|
||||||
if (_pendingFlags & PENDING_FLAG_JUMP) {
|
if ((_previousFlags & PENDING_FLAG_JUMP) != (_pendingFlags & PENDING_FLAG_JUMP)) {
|
||||||
_jumpButtonDownStartTime = now;
|
if (_pendingFlags & PENDING_FLAG_JUMP) {
|
||||||
_jumpButtonDownCount++;
|
_jumpButtonDownStartTime = now;
|
||||||
}
|
_jumpButtonDownCount++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool jumpButtonHeld = _pendingFlags & PENDING_FLAG_JUMP;
|
btVector3 velocity = _preSimulationVelocity;
|
||||||
|
|
||||||
btVector3 actualHorizVelocity = velocity - velocity.dot(_currentUp) * _currentUp;
|
// OUTOFBODY_HACK -- disable normal state transitions while collisionless
|
||||||
bool flyingFast = _state == State::Hover && actualHorizVelocity.length() > (MAX_WALKING_SPEED * 0.75f);
|
if (_collisionGroup == BULLET_COLLISION_GROUP_MY_AVATAR) {
|
||||||
|
switch (_state) {
|
||||||
// OUTOFBODY_HACK -- disable normal state transitions while collisionless
|
case State::Ground:
|
||||||
if (_collisionGroup == BULLET_COLLISION_GROUP_MY_AVATAR) {
|
if (!rayHasHit && !_hasSupport) {
|
||||||
switch (_state) {
|
SET_STATE(State::Hover, "no ground detected");
|
||||||
case State::Ground:
|
} else if (_pendingFlags & PENDING_FLAG_JUMP && _jumpButtonDownCount != _takeoffJumpButtonID) {
|
||||||
if (!rayHasHit && !_hasSupport) {
|
_takeoffJumpButtonID = _jumpButtonDownCount;
|
||||||
SET_STATE(State::Hover, "no ground detected");
|
_takeoffToInAirStartTime = now;
|
||||||
} else if (_pendingFlags & PENDING_FLAG_JUMP && _jumpButtonDownCount != _takeoffJumpButtonID) {
|
SET_STATE(State::Takeoff, "jump pressed");
|
||||||
_takeoffJumpButtonID = _jumpButtonDownCount;
|
} else if (rayHasHit && !_hasSupport && _floorDistance > GROUND_TO_FLY_THRESHOLD) {
|
||||||
_takeoffToInAirStartTime = now;
|
SET_STATE(State::InAir, "falling");
|
||||||
SET_STATE(State::Takeoff, "jump pressed");
|
|
||||||
} else if (rayHasHit && !_hasSupport && _floorDistance > GROUND_TO_FLY_THRESHOLD) {
|
|
||||||
SET_STATE(State::InAir, "falling");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case State::Takeoff:
|
|
||||||
if (!rayHasHit && !_hasSupport) {
|
|
||||||
SET_STATE(State::Hover, "no ground");
|
|
||||||
} else if ((now - _takeoffToInAirStartTime) > TAKE_OFF_TO_IN_AIR_PERIOD) {
|
|
||||||
SET_STATE(State::InAir, "takeoff done");
|
|
||||||
velocity += _jumpSpeed * _currentUp;
|
|
||||||
_rigidBody->setLinearVelocity(velocity);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case State::InAir: {
|
|
||||||
if ((velocity.dot(_currentUp) <= (JUMP_SPEED / 2.0f)) && ((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport)) {
|
|
||||||
SET_STATE(State::Ground, "hit ground");
|
|
||||||
} else {
|
|
||||||
btVector3 desiredVelocity = _targetVelocity;
|
|
||||||
if (desiredVelocity.length2() < MIN_TARGET_SPEED_SQUARED) {
|
|
||||||
desiredVelocity = btVector3(0.0f, 0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
bool vertTargetSpeedIsNonZero = desiredVelocity.dot(_currentUp) > MIN_TARGET_SPEED;
|
|
||||||
if ((jumpButtonHeld || vertTargetSpeedIsNonZero) && (_takeoffJumpButtonID != _jumpButtonDownCount)) {
|
|
||||||
SET_STATE(State::Hover, "double jump button");
|
|
||||||
} else if ((jumpButtonHeld || vertTargetSpeedIsNonZero) && (now - _jumpButtonDownStartTime) > JUMP_TO_HOVER_PERIOD) {
|
|
||||||
SET_STATE(State::Hover, "jump button held");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case State::Hover:
|
break;
|
||||||
if ((_floorDistance < MIN_HOVER_HEIGHT) && !jumpButtonHeld && !flyingFast) {
|
case State::Takeoff:
|
||||||
SET_STATE(State::InAir, "near ground");
|
if (!rayHasHit && !_hasSupport) {
|
||||||
} else if (((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport) && !flyingFast) {
|
SET_STATE(State::Hover, "no ground");
|
||||||
SET_STATE(State::Ground, "touching ground");
|
} else if ((now - _takeoffToInAirStartTime) > TAKE_OFF_TO_IN_AIR_PERIOD) {
|
||||||
}
|
SET_STATE(State::InAir, "takeoff done");
|
||||||
break;
|
velocity += _jumpSpeed * _currentUp;
|
||||||
|
_rigidBody->setLinearVelocity(velocity);
|
||||||
}
|
}
|
||||||
if (_moveKinematically && _ghost.isHovering()) {
|
break;
|
||||||
SET_STATE(State::Hover, "kinematic motion"); // HACK
|
case State::InAir: {
|
||||||
}
|
if ((velocity.dot(_currentUp) <= (JUMP_SPEED / 2.0f)) && ((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport)) {
|
||||||
} else {
|
SET_STATE(State::Ground, "hit ground");
|
||||||
// OUTOFBODY_HACK -- in collisionless state switch between Ground and Hover states
|
|
||||||
if (rayHasHit) {
|
|
||||||
SET_STATE(State::Ground, "collisionless above ground");
|
|
||||||
} else {
|
} else {
|
||||||
SET_STATE(State::Hover, "collisionless in air");
|
btVector3 desiredVelocity = _targetVelocity;
|
||||||
|
if (desiredVelocity.length2() < MIN_TARGET_SPEED_SQUARED) {
|
||||||
|
desiredVelocity = btVector3(0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
bool vertTargetSpeedIsNonZero = desiredVelocity.dot(_currentUp) > MIN_TARGET_SPEED;
|
||||||
|
if ((jumpButtonHeld || vertTargetSpeedIsNonZero) && (_takeoffJumpButtonID != _jumpButtonDownCount)) {
|
||||||
|
SET_STATE(State::Hover, "double jump button");
|
||||||
|
} else if ((jumpButtonHeld || vertTargetSpeedIsNonZero) && (now - _jumpButtonDownStartTime) > JUMP_TO_HOVER_PERIOD) {
|
||||||
|
SET_STATE(State::Hover, "jump button held");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case State::Hover:
|
||||||
|
btVector3 actualHorizVelocity = velocity - velocity.dot(_currentUp) * _currentUp;
|
||||||
|
const btScalar MAX_WALKING_SPEED = 2.5f;
|
||||||
|
bool flyingFast = _state == State::Hover && actualHorizVelocity.length() > (MAX_WALKING_SPEED * 0.75f);
|
||||||
|
|
||||||
|
if ((_floorDistance < MIN_HOVER_HEIGHT) && !jumpButtonHeld && !flyingFast) {
|
||||||
|
SET_STATE(State::InAir, "near ground");
|
||||||
|
} else if (((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport) && !flyingFast) {
|
||||||
|
SET_STATE(State::Ground, "touching ground");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (_moveKinematically && _ghost.isHovering()) {
|
||||||
|
SET_STATE(State::Hover, "kinematic motion"); // HACK
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// OUTOFBODY_HACK -- in collisionless state switch only between Ground and Hover states
|
||||||
|
if (rayHasHit) {
|
||||||
|
SET_STATE(State::Ground, "collisionless above ground");
|
||||||
|
} else {
|
||||||
|
SET_STATE(State::Hover, "collisionless in air");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharacterController::preSimulation() {
|
||||||
|
if (_dynamicsWorld) {
|
||||||
|
// slam body transform and remember velocity
|
||||||
|
_rigidBody->setWorldTransform(btTransform(btTransform(_rotation, _position)));
|
||||||
|
_preSimulationVelocity = _rigidBody->getLinearVelocity();
|
||||||
|
|
||||||
|
updateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
_previousFlags = _pendingFlags;
|
_previousFlags = _pendingFlags;
|
||||||
|
@ -702,13 +707,9 @@ void CharacterController::preSimulation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::postSimulation() {
|
void CharacterController::postSimulation() {
|
||||||
// postSimulation() exists for symmetry and just in case we need to do something here later
|
_velocityChange = _rigidBody->getLinearVelocity() - _preSimulationVelocity;
|
||||||
|
|
||||||
btVector3 velocity = _rigidBody->getLinearVelocity();
|
|
||||||
_velocityChange = velocity - _preSimulationVelocity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CharacterController::getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation) {
|
bool CharacterController::getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation) {
|
||||||
if (!_rigidBody) {
|
if (!_rigidBody) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -109,6 +109,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
State getState() const { return _state; }
|
State getState() const { return _state; }
|
||||||
|
void updateState();
|
||||||
|
|
||||||
void setLocalBoundingBox(const glm::vec3& minCorner, const glm::vec3& scale);
|
void setLocalBoundingBox(const glm::vec3& minCorner, const glm::vec3& scale);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue