659 lines · 25.2 KB · C++
RawDownload
    btScalar totalWeight = 0.0f;    for (size_t i = 0; i < weights.size(); ++i) {        totalWeight += weights[i];    }    if (totalWeight > 0.0f) {        velocity = btVector3(0.0f, 0.0f, 0.0f);        for (size_t i = 0; i < velocities.size(); ++i) {            velocity += (weights[i] / totalWeight) * velocities[i];        }    }    if (velocity.length2() < MIN_TARGET_SPEED_SQUARED) {        velocity = btVector3(0.0f, 0.0f, 0.0f);    }     // 'thrust' is applied at the very end    velocity += dt * _linearAcceleration;    _targetVelocity = velocity;} void CharacterController::computeNewVelocity(btScalar dt, glm::vec3& velocity) {    btVector3 btVelocity = glmToBullet(velocity);    computeNewVelocity(dt, btVelocity);    velocity = bulletToGLM(btVelocity);} void CharacterController::preSimulation() {    if (_enabled && _dynamicsWorld) {        quint64 now = usecTimestampNow();         // slam body to where it is supposed to be        _rigidBody->setWorldTransform(_characterBodyTransform);        btVector3 velocity = _rigidBody->getLinearVelocity();        _preSimulationVelocity = velocity;         // scan for distant floor        // rayStart is at center of bottom sphere        btVector3 rayStart = _characterBodyTransform.getOrigin() - _halfHeight * _currentUp;         // rayEnd is straight down MAX_FALL_HEIGHT        btScalar rayLength = _radius + MAX_FALL_HEIGHT;        btVector3 rayEnd = rayStart - rayLength * _currentUp;         const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius;        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;        const btScalar MAX_WALKING_SPEED = 2.5f;        const quint64 RAY_HIT_START_PERIOD = 500 * MSECS_PER_SECOND;         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;        } else if ((now - _rayHitStartTime) < RAY_HIT_START_PERIOD) {            rayHasHit = true;        } else {            _floorDistance = FLT_MAX;        }         // record a time stamp when the jump button was first pressed.        if ((_previousFlags & PENDING_FLAG_JUMP) != (_pendingFlags & PENDING_FLAG_JUMP)) {            if (_pendingFlags & PENDING_FLAG_JUMP) {                _jumpButtonDownStartTime = now;                _jumpButtonDownCount++;            }        }         bool jumpButtonHeld = _pendingFlags & PENDING_FLAG_JUMP;         btVector3 actualHorizVelocity = velocity - velocity.dot(_currentUp) * _currentUp;        bool flyingFast = _state == State::Hover && actualHorizVelocity.length() > (MAX_WALKING_SPEED * 0.75f);         switch (_state) {        case State::Ground:            if (!rayHasHit && !_hasSupport) {                SET_STATE(State::Hover, "no ground detected");            } else if (_pendingFlags & PENDING_FLAG_JUMP && _jumpButtonDownCount != _takeoffJumpButtonID) {                _takeoffJumpButtonID = _jumpButtonDownCount;                _takeoffToInAirStartTime = now;                SET_STATE(State::Takeoff, "jump pressed");            } else if (rayHasHit && !_hasSupport && _floorDistance > JUMP_PROXIMITY_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 < JUMP_PROXIMITY_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:            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;        }    }     _previousFlags = _pendingFlags;    _pendingFlags &= ~PENDING_FLAG_JUMP;     _followTime = 0.0f;    _followLinearDisplacement = btVector3(0, 0, 0);    _followAngularDisplacement = btQuaternion::getIdentity();} void CharacterController::postSimulation() {    // postSimulation() exists for symmetry and just in case we need to do something here later     btVector3 velocity = _rigidBody->getLinearVelocity();    _velocityChange = velocity - _preSimulationVelocity;}  bool CharacterController::getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation) {    if (!_rigidBody) {        return false;    }     const btTransform& worldTrans = _rigidBody->getCenterOfMassTransform();    avatarRigidBodyPosition = bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset();    avatarRigidBodyRotation = bulletToGLM(worldTrans.getRotation());    return true;} void CharacterController::setFlyingAllowed(bool value) {    if (_flyingAllowed != value) {        _flyingAllowed = value;         if (!_flyingAllowed && _state == State::Hover) {            SET_STATE(State::InAir, "flying not allowed");        }    }}

Lines 501–659 of 659. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t