void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
    bool gotLock = false;
    glm::quat rotation;
    glm::vec3 position;
    std::shared_ptr<Avatar> holdingAvatar = nullptr;

    gotLock = withTryReadLock([&] {
        QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
        AvatarSharedPointer holdingAvatarData = avatarManager->getAvatarBySessionID(_holderID);
        holdingAvatar = std::static_pointer_cast<Avatar>(holdingAvatarData);

        if (holdingAvatar) {
            glm::vec3 offset;
            glm::vec3 palmPosition;
            glm::quat palmRotation;
            if (_hand == "right") {
                palmPosition = holdingAvatar->getRightPalmPosition();
                palmRotation = holdingAvatar->getRightPalmRotation();
            } else {
                palmPosition = holdingAvatar->getLeftPalmPosition();
                palmRotation = holdingAvatar->getLeftPalmRotation();
            }

            rotation = palmRotation * _relativeRotation;
            offset = rotation * _relativePosition;
            position = palmPosition + offset;
        }
    });

    if (holdingAvatar) {
        if (gotLock) {
            gotLock = withTryWriteLock([&] {
                _positionalTarget = position;
                _rotationalTarget = rotation;
                _positionalTargetSet = true;
                _rotationalTargetSet = true;
                _active = true;
            });
            if (gotLock) {
                if (_kinematic) {
                    doKinematicUpdate(deltaTimeStep);
                } else {
                    activateBody();
                    ObjectActionSpring::updateActionWorker(deltaTimeStep);
                }
            }
        }
    }
}
Beispiel #2
0
void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
    if (!_mine) {
        // if a local script isn't updating this, then we are just getting spring-action data over the wire.
        // let the super-class handle it.
        ObjectActionSpring::updateActionWorker(deltaTimeStep);
        return;
    }

    glm::quat rotation;
    glm::vec3 position;
    glm::vec3 offset;
    bool gotLock = withTryReadLock([&]{
        auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
        glm::vec3 palmPosition;
        glm::quat palmRotation;
        if (_hand == "right") {
            palmPosition = myAvatar->getRightPalmPosition();
            palmRotation = myAvatar->getRightPalmRotation();
        } else {
            palmPosition = myAvatar->getLeftPalmPosition();
            palmRotation = myAvatar->getLeftPalmRotation();
        }

        rotation = palmRotation * _relativeRotation;
        offset = rotation * _relativePosition;
        position = palmPosition + offset;
    });

    if (gotLock) {
        gotLock = withTryWriteLock([&]{
            if (_positionalTarget != position || _rotationalTarget != rotation) {
                auto ownerEntity = _ownerEntity.lock();
                if (ownerEntity) {
                    ownerEntity->setActionDataDirty(true);
                }
                _positionalTarget = position;
                _rotationalTarget = rotation;
            }
        });
    }

    if (gotLock) {
        ObjectActionSpring::updateActionWorker(deltaTimeStep);
    }
}
Beispiel #3
0
void ObjectActionOffset::updateActionWorker(btScalar deltaTimeStep) {
    withTryReadLock([&] {
        auto ownerEntity = _ownerEntity.lock();
        if (!ownerEntity) {
            return;
        }

        void* physicsInfo = ownerEntity->getPhysicsInfo();
        if (!physicsInfo) {
            return;
        }

        ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
        btRigidBody* rigidBody = motionState->getRigidBody();
        if (!rigidBody) {
            qDebug() << "ObjectActionOffset::updateActionWorker no rigidBody";
            return;
        }

        const float MAX_LINEAR_TIMESCALE = 600.0f;  // 10 minutes is a long time
        if (_positionalTargetSet && _linearTimeScale < MAX_LINEAR_TIMESCALE) {
            glm::vec3 objectPosition = bulletToGLM(rigidBody->getCenterOfMassPosition());
            glm::vec3 springAxis = objectPosition - _pointToOffsetFrom; // from anchor to object
            float distance = glm::length(springAxis);
            if (distance > FLT_EPSILON) {
                springAxis /= distance;  // normalize springAxis

                // compute (critically damped) target velocity of spring relaxation
                glm::vec3 offset = (distance - _linearDistance) * springAxis;
                glm::vec3 targetVelocity = (-1.0f / _linearTimeScale) * offset;

                // compute current velocity and its parallel component
                glm::vec3 currentVelocity = bulletToGLM(rigidBody->getLinearVelocity());
                glm::vec3 parallelVelocity = glm::dot(currentVelocity, springAxis) * springAxis;

                // we blend the parallel component with the spring's target velocity to get the new velocity
                float blend = deltaTimeStep / _linearTimeScale;
                if (blend > 1.0f) {
                    blend = 1.0f;
                }
                rigidBody->setLinearVelocity(glmToBullet(currentVelocity + blend * (targetVelocity - parallelVelocity)));
            }
        }
    });
}
Beispiel #4
0
void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
    bool gotLock = false;
    glm::quat rotation;
    glm::vec3 position;
    glm::vec3 offset;

    gotLock = withTryReadLock([&]{
        auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
        glm::vec3 palmPosition;
        glm::quat palmRotation;
        if (_hand == "right") {
            palmPosition = myAvatar->getRightPalmPosition();
            palmRotation = myAvatar->getRightPalmRotation();
        } else {
            palmPosition = myAvatar->getLeftPalmPosition();
            palmRotation = myAvatar->getLeftPalmRotation();
        }

        rotation = palmRotation * _relativeRotation;
        offset = rotation * _relativePosition;
        position = palmPosition + offset;
    });

    if (gotLock) {
        gotLock = withTryWriteLock([&]{
            _positionalTarget = position;
            _rotationalTarget = rotation;
            _positionalTargetSet = true;
            _rotationalTargetSet = true;
            auto ownerEntity = _ownerEntity.lock();
            if (ownerEntity) {
                ownerEntity->setActionDataDirty(true);
            }
        });
    }
    if (gotLock) {
        ObjectActionSpring::updateActionWorker(deltaTimeStep);
    }
}
Beispiel #5
0
void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
    // don't risk hanging the thread running the physics simulation
    auto lockResult = withTryReadLock([&]{
        auto ownerEntity = _ownerEntity.lock();
        if (!ownerEntity) {
            return;
        }

        void* physicsInfo = ownerEntity->getPhysicsInfo();
        if (!physicsInfo) {
            return;
        }
        ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
        btRigidBody* rigidBody = motionState->getRigidBody();
        if (!rigidBody) {
            qDebug() << "ObjectActionSpring::updateActionWorker no rigidBody";
            return;
        }

        const float MAX_TIMESCALE = 600.0f; // 10 min is a long time
        if (_linearTimeScale < MAX_TIMESCALE) {
            btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
            btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget);
            float offsetLength = offset.length();
            if (offsetLength > FLT_EPSILON) {
                float speed = glm::min(offsetLength / _linearTimeScale, SPRING_MAX_SPEED);
                targetVelocity = (-speed / offsetLength) * offset;
                if (speed > rigidBody->getLinearSleepingThreshold()) {
                    rigidBody->activate();
                }
            }
            // this action is aggresively critically damped and defeats the current velocity
            rigidBody->setLinearVelocity(targetVelocity);
        }

        if (_angularTimeScale < MAX_TIMESCALE) {
            btVector3 targetVelocity(0.0f, 0.0f, 0.0f);

            btQuaternion bodyRotation = rigidBody->getOrientation();
            auto alignmentDot = bodyRotation.dot(glmToBullet(_rotationalTarget));
            const float ALMOST_ONE = 0.99999f;
            if (glm::abs(alignmentDot) < ALMOST_ONE) {
                btQuaternion target = glmToBullet(_rotationalTarget);
                if (alignmentDot < 0.0f) {
                    target = -target;
                }
                // if dQ is the incremental rotation that gets an object from Q0 to Q1 then:
                //
                //      Q1 = dQ * Q0
                //
                // solving for dQ gives:
                //
                //      dQ = Q1 * Q0^
                btQuaternion deltaQ = target * bodyRotation.inverse();
                float speed = deltaQ.getAngle() / _angularTimeScale;
                targetVelocity = speed * deltaQ.getAxis();
                if (speed > rigidBody->getAngularSleepingThreshold()) {
                    rigidBody->activate();
                }
            }
            // this action is aggresively critically damped and defeats the current velocity
            rigidBody->setAngularVelocity(targetVelocity);
        }
    });
    if (!lockResult) {
        qDebug() << "ObjectActionSpring::updateActionWorker lock failed";
    }
}