void DynamicCharacterController::preSimulation(btScalar timeStep) { if (_enabled && _dynamicsWorld) { glm::quat rotation = _avatarData->getOrientation(); // TODO: update gravity if up has changed updateUpAxis(rotation); glm::vec3 position = _avatarData->getPosition() + rotation * _shapeLocalOffset; _rigidBody->setWorldTransform(btTransform(glmToBullet(rotation), glmToBullet(position))); // the rotation is dictated by AvatarData btTransform xform = _rigidBody->getWorldTransform(); xform.setRotation(glmToBullet(rotation)); _rigidBody->setWorldTransform(xform); // scan for distant floor // rayStart is at center of bottom sphere btVector3 rayStart = xform.getOrigin() - _halfHeight * _currentUp; // rayEnd is straight down MAX_FALL_HEIGHT btScalar rayLength = _radius + MAX_FALL_HEIGHT; btVector3 rayEnd = rayStart - rayLength * _currentUp; ClosestNotMe rayCallback(_rigidBody); rayCallback.m_closestHitFraction = 1.0f; _dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback); if (rayCallback.hasHit()) { _floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius; const btScalar MIN_HOVER_HEIGHT = 3.0f; if (_isHovering && _floorDistance < MIN_HOVER_HEIGHT && !_isPushingUp) { setHovering(false); } // TODO: use collision events rather than ray-trace test to disable jumping const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius; if (_floorDistance < JUMP_PROXIMITY_THRESHOLD) { _isJumping = false; } } else { _floorDistance = FLT_MAX; setHovering(true); } _walkVelocity = glmToBullet(_avatarData->getTargetVelocity()); if (_pendingFlags & PENDING_FLAG_JUMP) { _pendingFlags &= ~ PENDING_FLAG_JUMP; if (onGround()) { _isJumping = true; btVector3 velocity = _rigidBody->getLinearVelocity(); velocity += _jumpSpeed * _currentUp; _rigidBody->setLinearVelocity(velocity); } } } }
void MyCharacterController::preSimulation() { if (_enabled && _dynamicsWorld) { // slam body to where it is supposed to be _rigidBody->setWorldTransform(_avatarBodyTransform); // scan for distant floor // rayStart is at center of bottom sphere btVector3 rayStart = _avatarBodyTransform.getOrigin() - _halfHeight * _currentUp; // rayEnd is straight down MAX_FALL_HEIGHT btScalar rayLength = _radius + MAX_FALL_HEIGHT; btVector3 rayEnd = rayStart - rayLength * _currentUp; ClosestNotMe rayCallback(_rigidBody); rayCallback.m_closestHitFraction = 1.0f; _dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback); if (rayCallback.hasHit()) { _floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius; const btScalar MIN_HOVER_HEIGHT = 3.0f; if (_isHovering && _floorDistance < MIN_HOVER_HEIGHT && !_isPushingUp) { setHovering(false); } // TODO: use collision events rather than ray-trace test to disable jumping const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius; if (_floorDistance < JUMP_PROXIMITY_THRESHOLD) { _isJumping = false; } } else { _floorDistance = FLT_MAX; setHovering(true); } if (_pendingFlags & PENDING_FLAG_JUMP) { _pendingFlags &= ~ PENDING_FLAG_JUMP; if (onGround()) { _isJumping = true; btVector3 velocity = _rigidBody->getLinearVelocity(); velocity += _jumpSpeed * _currentUp; _rigidBody->setLinearVelocity(velocity); } } } _lastStepDuration = 0.0f; }
void MyCharacterController::setEnabled(bool enabled) { if (enabled != _enabled) { if (enabled) { // Don't bother clearing REMOVE bit since it might be paired with an UPDATE_SHAPE bit. // Setting the ADD bit here works for all cases so we don't even bother checking other bits. _pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION; } else { if (_dynamicsWorld) { _pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION; } _pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION; _isOnGround = false; } setHovering(true); _enabled = enabled; } }
void MyCharacterController::jump() { // check for case where user is holding down "jump" key... // we'll eventually tansition to "hover" if (!_isJumping) { if (!_isHovering) { _jumpToHoverStart = usecTimestampNow(); _pendingFlags |= PENDING_FLAG_JUMP; } } else { quint64 now = usecTimestampNow(); const quint64 JUMP_TO_HOVER_PERIOD = 75 * (USECS_PER_SECOND / 100); if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) { _isPushingUp = true; setHovering(true); } } }