void MyCharacterController::setAvatarPositionAndOrientation(
        const glm::vec3& position, 
        const glm::quat& orientation) {
    // TODO: update gravity if up has changed
    updateUpAxis(orientation);

    btQuaternion bodyOrientation = glmToBullet(orientation);
    btVector3 bodyPosition = glmToBullet(position + orientation * _shapeLocalOffset);
    _avatarBodyTransform = btTransform(bodyOrientation, bodyPosition);
}
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);
            }
        }
    }
}