mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 11:50:39 +02:00
removed clang induced changes to MyAvatar.cpp
This commit is contained in:
parent
7f5f762208
commit
47110d080f
2 changed files with 248 additions and 407 deletions
|
@ -82,8 +82,7 @@ const int SCRIPTED_MOTOR_AVATAR_FRAME = 1;
|
|||
const int SCRIPTED_MOTOR_WORLD_FRAME = 2;
|
||||
const int SCRIPTED_MOTOR_SIMPLE_MODE = 0;
|
||||
const int SCRIPTED_MOTOR_DYNAMIC_MODE = 1;
|
||||
const QString& DEFAULT_AVATAR_COLLISION_SOUND_URL =
|
||||
"https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/Body_Hits_Impact.wav";
|
||||
const QString& DEFAULT_AVATAR_COLLISION_SOUND_URL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/Body_Hits_Impact.wav";
|
||||
|
||||
const float MyAvatar::ZOOM_MIN = 0.5f;
|
||||
const float MyAvatar::ZOOM_MAX = 25.0f;
|
||||
|
@ -91,15 +90,33 @@ const float MyAvatar::ZOOM_DEFAULT = 1.5f;
|
|||
const float MIN_SCALE_CHANGED_DELTA = 0.001f;
|
||||
|
||||
MyAvatar::MyAvatar(QThread* thread) :
|
||||
Avatar(thread), _yawSpeed(YAW_SPEED_DEFAULT), _pitchSpeed(PITCH_SPEED_DEFAULT),
|
||||
_scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE), _scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME),
|
||||
_scriptedMotorMode(SCRIPTED_MOTOR_SIMPLE_MODE), _motionBehaviors(AVATAR_MOTION_DEFAULTS), _characterController(this),
|
||||
_eyeContactTarget(LEFT_EYE), _realWorldFieldOfView("realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES),
|
||||
Avatar(thread),
|
||||
_yawSpeed(YAW_SPEED_DEFAULT),
|
||||
_pitchSpeed(PITCH_SPEED_DEFAULT),
|
||||
_scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE),
|
||||
_scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME),
|
||||
_scriptedMotorMode(SCRIPTED_MOTOR_SIMPLE_MODE),
|
||||
_motionBehaviors(AVATAR_MOTION_DEFAULTS),
|
||||
_characterController(this),
|
||||
_eyeContactTarget(LEFT_EYE),
|
||||
_realWorldFieldOfView("realWorldFieldOfView",
|
||||
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES),
|
||||
_useAdvancedMovementControls("advancedMovementForHandControllersIsChecked", false),
|
||||
_smoothOrientationTimer(std::numeric_limits<float>::max()), _smoothOrientationInitial(), _smoothOrientationTarget(),
|
||||
_hmdSensorMatrix(), _hmdSensorOrientation(), _hmdSensorPosition(), _bodySensorMatrix(), _goToPending(false),
|
||||
_goToPosition(), _goToOrientation(), _prevShouldDrawHead(true), _audioListenerMode(FROM_HEAD),
|
||||
_hmdAtRestDetector(glm::vec3(0), glm::quat()) {
|
||||
_smoothOrientationTimer(std::numeric_limits<float>::max()),
|
||||
_smoothOrientationInitial(),
|
||||
_smoothOrientationTarget(),
|
||||
_hmdSensorMatrix(),
|
||||
_hmdSensorOrientation(),
|
||||
_hmdSensorPosition(),
|
||||
_bodySensorMatrix(),
|
||||
_goToPending(false),
|
||||
_goToPosition(),
|
||||
_goToOrientation(),
|
||||
_prevShouldDrawHead(true),
|
||||
_audioListenerMode(FROM_HEAD),
|
||||
_hmdAtRestDetector(glm::vec3(0), glm::quat())
|
||||
{
|
||||
|
||||
// give the pointer to our head to inherited _headData variable from AvatarData
|
||||
_headData = new MyHead(this);
|
||||
|
||||
|
@ -131,8 +148,8 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
using SlotType = void(MyAvatar::*)(const glm::vec3&, bool, const glm::quat&, bool);
|
||||
|
||||
// connect to AddressManager signal for location jumps
|
||||
connect(DependencyManager::get<AddressManager>().data(), &AddressManager::locationChangeRequired, this,
|
||||
static_cast<SlotType>(&MyAvatar::goToLocation));
|
||||
connect(DependencyManager::get<AddressManager>().data(), &AddressManager::locationChangeRequired,
|
||||
this, static_cast<SlotType>(&MyAvatar::goToLocation));
|
||||
|
||||
// handle scale constraints imposed on us by the domain-server
|
||||
auto& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
|
||||
|
@ -194,6 +211,7 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
|
||||
if (recordingInterface->getPlayerUseSkeletonModel() && dummyAvatar.getSkeletonModelURL().isValid() &&
|
||||
(dummyAvatar.getSkeletonModelURL() != getSkeletonModelURL())) {
|
||||
|
||||
setSkeletonModelURL(dummyAvatar.getSkeletonModelURL());
|
||||
}
|
||||
|
||||
|
@ -240,8 +258,7 @@ void MyAvatar::setDominantHand(const QString& hand) {
|
|||
}
|
||||
|
||||
void MyAvatar::registerMetaTypes(ScriptEnginePointer engine) {
|
||||
QScriptValue value = engine->newQObject(this, QScriptEngine::QtOwnership,
|
||||
QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
|
||||
QScriptValue value = engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
|
||||
engine->globalObject().setProperty("MyAvatar", value);
|
||||
|
||||
QScriptValue driveKeys = engine->newObject();
|
||||
|
@ -354,6 +371,7 @@ void MyAvatar::clearIKJointLimitHistory() {
|
|||
}
|
||||
|
||||
void MyAvatar::reset(bool andRecenter, bool andReload, bool andHead) {
|
||||
|
||||
assert(QThread::currentThread() == thread());
|
||||
|
||||
// Reset dynamic state.
|
||||
|
@ -394,9 +412,9 @@ void MyAvatar::reset(bool andRecenter, bool andReload, bool andHead) {
|
|||
}
|
||||
|
||||
void MyAvatar::update(float deltaTime) {
|
||||
|
||||
// update moving average of HMD facing in xz plane.
|
||||
const float HMD_FACING_TIMESCALE = getRotationRecenterFilterLength(); //4.0f; // very slow average
|
||||
//qCDebug(interfaceapp) << "rotation recenter value is " << HMD_FACING_TIMESCALE;
|
||||
const float HMD_FACING_TIMESCALE = 4.0f; // very slow average
|
||||
float tau = deltaTime / HMD_FACING_TIMESCALE;
|
||||
_headControllerFacingMovingAverage = lerp(_headControllerFacingMovingAverage, _headControllerFacing, tau);
|
||||
|
||||
|
@ -404,17 +422,12 @@ void MyAvatar::update(float deltaTime) {
|
|||
_rotationChanged = usecTimestampNow();
|
||||
_smoothOrientationTimer += deltaTime;
|
||||
}
|
||||
setStandingHeightMode(computeStandingHeightMode(getControllerPoseInAvatarFrame(controller::Action::HEAD)));
|
||||
setAverageHeadRotation(computeAverageHeadRotation(getControllerPoseInAvatarFrame(controller::Action::HEAD)));
|
||||
|
||||
#ifdef DEBUG_DRAW_HMD_MOVING_AVERAGE
|
||||
auto sensorHeadPose = getControllerPoseInSensorFrame(controller::Action::HEAD);
|
||||
glm::vec3 worldHeadPos = transformPoint(getSensorToWorldMatrix(), sensorHeadPose.getTranslation());
|
||||
glm::vec3 worldFacingAverage =
|
||||
transformVectorFast(getSensorToWorldMatrix(),
|
||||
glm::vec3(_headControllerFacingMovingAverage.x, 0.0f, _headControllerFacingMovingAverage.y));
|
||||
glm::vec3 worldFacing =
|
||||
transformVectorFast(getSensorToWorldMatrix(), glm::vec3(_headControllerFacing.x, 0.0f, _headControllerFacing.y));
|
||||
glm::vec3 worldFacingAverage = transformVectorFast(getSensorToWorldMatrix(), glm::vec3(_headControllerFacingMovingAverage.x, 0.0f, _headControllerFacingMovingAverage.y));
|
||||
glm::vec3 worldFacing = transformVectorFast(getSensorToWorldMatrix(), glm::vec3(_headControllerFacing.x, 0.0f, _headControllerFacing.y));
|
||||
DebugDraw::getInstance().drawRay(worldHeadPos, worldHeadPos + worldFacing, glm::vec4(0.0f, 1.0f, 0.0f, 1.0f));
|
||||
DebugDraw::getInstance().drawRay(worldHeadPos, worldHeadPos + worldFacingAverage, glm::vec4(0.0f, 0.0f, 1.0f, 1.0f));
|
||||
#endif
|
||||
|
@ -451,8 +464,7 @@ void MyAvatar::update(float deltaTime) {
|
|||
setAudioLoudness(audio->getLastInputLoudness());
|
||||
setAudioAverageLoudness(audio->getAudioAverageInputLoudness());
|
||||
|
||||
glm::vec3 halfBoundingBoxDimensions(_characterController.getCapsuleRadius(), _characterController.getCapsuleHalfHeight(),
|
||||
_characterController.getCapsuleRadius());
|
||||
glm::vec3 halfBoundingBoxDimensions(_characterController.getCapsuleRadius(), _characterController.getCapsuleHalfHeight(), _characterController.getCapsuleRadius());
|
||||
// This might not be right! Isn't the capsule local offset in avatar space? -HRS 5/26/17
|
||||
halfBoundingBoxDimensions += _characterController.getCapsuleLocalOffset();
|
||||
QMetaObject::invokeMethod(audio.data(), "setAvatarBoundingBoxParameters",
|
||||
|
@ -479,10 +491,13 @@ void MyAvatar::update(float deltaTime) {
|
|||
}
|
||||
|
||||
void MyAvatar::updateEyeContactTarget(float deltaTime) {
|
||||
|
||||
_eyeContactTargetTimer -= deltaTime;
|
||||
if (_eyeContactTargetTimer < 0.0f) {
|
||||
|
||||
const float CHANCE_OF_CHANGING_TARGET = 0.01f;
|
||||
if (randFloat() < CHANCE_OF_CHANGING_TARGET) {
|
||||
|
||||
float const FIFTY_FIFTY_CHANCE = 0.5f;
|
||||
float const EYE_TO_MOUTH_CHANCE = 0.25f;
|
||||
switch (_eyeContactTarget) {
|
||||
|
@ -686,8 +701,7 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
EntityItemProperties descendantProperties;
|
||||
descendantProperties.setQueryAACube(descendant->getQueryAACube());
|
||||
descendantProperties.setLastEdited(now);
|
||||
packetSender->queueEditEntityMessage(PacketType::EntityEdit, entityTree,
|
||||
entityDescendant->getID(), descendantProperties);
|
||||
packetSender->queueEditEntityMessage(PacketType::EntityEdit, entityTree, entityDescendant->getID(), descendantProperties);
|
||||
entityDescendant->setLastBroadcast(now); // for debug/physics status icons
|
||||
}
|
||||
});
|
||||
|
@ -719,7 +733,8 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
|||
_hmdSensorMatrix = hmdSensorMatrix;
|
||||
auto newHmdSensorPosition = extractTranslation(hmdSensorMatrix);
|
||||
|
||||
if (newHmdSensorPosition != getHMDSensorPosition() && glm::length(newHmdSensorPosition) > MAX_HMD_ORIGIN_DISTANCE) {
|
||||
if (newHmdSensorPosition != getHMDSensorPosition() &&
|
||||
glm::length(newHmdSensorPosition) > MAX_HMD_ORIGIN_DISTANCE) {
|
||||
qWarning() << "Invalid HMD sensor position " << newHmdSensorPosition;
|
||||
// Ignore unreasonable HMD sensor data
|
||||
return;
|
||||
|
@ -751,11 +766,11 @@ void MyAvatar::updateJointFromController(controller::Action poseKey, ThreadSafeV
|
|||
// update sensor to world matrix from current body position and hmd sensor.
|
||||
// This is so the correct camera can be used for rendering.
|
||||
void MyAvatar::updateSensorToWorldMatrix() {
|
||||
|
||||
// update the sensor mat so that the body position will end up in the desired
|
||||
// position when driven from the head.
|
||||
float sensorToWorldScale = getEyeHeight() / getUserEyeHeight();
|
||||
glm::mat4 desiredMat =
|
||||
createMatFromScaleQuatAndPos(glm::vec3(sensorToWorldScale), getWorldOrientation(), getWorldPosition());
|
||||
glm::mat4 desiredMat = createMatFromScaleQuatAndPos(glm::vec3(sensorToWorldScale), getWorldOrientation(), getWorldPosition());
|
||||
_sensorToWorldMatrix = desiredMat * glm::inverse(_bodySensorMatrix);
|
||||
|
||||
bool hasSensorToWorldScaleChanged = false;
|
||||
|
@ -777,6 +792,7 @@ void MyAvatar::updateSensorToWorldMatrix() {
|
|||
if (hasSensorToWorldScaleChanged) {
|
||||
emit sensorToWorldScaleChanged(sensorToWorldScale);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Update avatar head rotation with sensor data
|
||||
|
@ -801,7 +817,8 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
|
|||
const float TRACKER_YAW_TURN_SENSITIVITY = 0.5f;
|
||||
const float TRACKER_MIN_YAW_TURN = 15.0f;
|
||||
const float TRACKER_MAX_YAW_TURN = 50.0f;
|
||||
if ((fabs(estimatedRotation.y) > TRACKER_MIN_YAW_TURN) && (fabs(estimatedRotation.y) < TRACKER_MAX_YAW_TURN)) {
|
||||
if ( (fabs(estimatedRotation.y) > TRACKER_MIN_YAW_TURN) &&
|
||||
(fabs(estimatedRotation.y) < TRACKER_MAX_YAW_TURN) ) {
|
||||
if (estimatedRotation.y > 0.0f) {
|
||||
_bodyYawDelta += (estimatedRotation.y - TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY;
|
||||
} else {
|
||||
|
@ -816,6 +833,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
|
|||
// their head only 30 degrees or so, this may correspond to a 90 degree field of view.
|
||||
// Note that roll is magnified by a constant because it is not related to field of view.
|
||||
|
||||
|
||||
Head* head = getHead();
|
||||
if (inHmd || playing) {
|
||||
head->setDeltaPitch(estimatedRotation.x);
|
||||
|
@ -959,8 +977,8 @@ void MyAvatar::render(RenderArgs* renderArgs) {
|
|||
|
||||
void MyAvatar::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "overrideAnimation", Q_ARG(const QString&, url), Q_ARG(float, fps), Q_ARG(bool, loop),
|
||||
Q_ARG(float, firstFrame), Q_ARG(float, lastFrame));
|
||||
QMetaObject::invokeMethod(this, "overrideAnimation", Q_ARG(const QString&, url), Q_ARG(float, fps),
|
||||
Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame));
|
||||
return;
|
||||
}
|
||||
_skeletonModel->getRig().overrideAnimation(url, fps, loop, firstFrame, lastFrame);
|
||||
|
@ -983,12 +1001,8 @@ QStringList MyAvatar::getAnimationRoles() {
|
|||
return _skeletonModel->getRig().getAnimationRoles();
|
||||
}
|
||||
|
||||
void MyAvatar::overrideRoleAnimation(const QString& role,
|
||||
const QString& url,
|
||||
float fps,
|
||||
bool loop,
|
||||
float firstFrame,
|
||||
float lastFrame) {
|
||||
void MyAvatar::overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop,
|
||||
float firstFrame, float lastFrame) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "overrideRoleAnimation", Q_ARG(const QString&, role), Q_ARG(const QString&, url),
|
||||
Q_ARG(float, fps), Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame));
|
||||
|
@ -1009,9 +1023,10 @@ void MyAvatar::saveAvatarUrl() {
|
|||
Settings settings;
|
||||
settings.beginGroup("Avatar");
|
||||
if (qApp->getSaveAvatarOverrideUrl() || !qApp->getAvatarOverrideUrl().isValid() ) {
|
||||
settings.setValue("fullAvatarURL", _fullAvatarURLFromPreferences == AvatarData::defaultFullAvatarModelUrl()
|
||||
? ""
|
||||
: _fullAvatarURLFromPreferences.toString());
|
||||
settings.setValue("fullAvatarURL",
|
||||
_fullAvatarURLFromPreferences == AvatarData::defaultFullAvatarModelUrl() ?
|
||||
"" :
|
||||
_fullAvatarURLFromPreferences.toString());
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
|
@ -1032,9 +1047,10 @@ void MyAvatar::saveData() {
|
|||
// (so the overrideURL is not valid), or it was overridden _and_ we specified
|
||||
// --replaceAvatarURL (so _saveAvatarOverrideUrl is true)
|
||||
if (qApp->getSaveAvatarOverrideUrl() || !qApp->getAvatarOverrideUrl().isValid() ) {
|
||||
settings.setValue("fullAvatarURL", _fullAvatarURLFromPreferences == AvatarData::defaultFullAvatarModelUrl()
|
||||
? ""
|
||||
: _fullAvatarURLFromPreferences.toString());
|
||||
settings.setValue("fullAvatarURL",
|
||||
_fullAvatarURLFromPreferences == AvatarData::defaultFullAvatarModelUrl() ?
|
||||
"" :
|
||||
_fullAvatarURLFromPreferences.toString());
|
||||
}
|
||||
|
||||
settings.setValue("fullAvatarModelName", _fullAvatarModelName);
|
||||
|
@ -1345,15 +1361,16 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
|||
bool isCurrentTarget = avatar->getIsLookAtTarget();
|
||||
float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition);
|
||||
avatar->setIsLookAtTarget(false);
|
||||
if (!avatar->isMyAvatar() && avatar->isInitialized() && (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getModelScale())) {
|
||||
if (!avatar->isMyAvatar() && avatar->isInitialized() &&
|
||||
(distanceTo < GREATEST_LOOKING_AT_DISTANCE * getModelScale())) {
|
||||
float radius = glm::length(avatar->getHead()->getEyePosition() - avatar->getHead()->getRightEyePosition());
|
||||
float angleTo =
|
||||
coneSphereAngle(getHead()->getEyePosition(), lookForward, avatar->getHead()->getEyePosition(), radius);
|
||||
float angleTo = coneSphereAngle(getHead()->getEyePosition(), lookForward, avatar->getHead()->getEyePosition(), radius);
|
||||
if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) {
|
||||
_lookAtTargetAvatar = avatarPointer;
|
||||
_targetAvatarPosition = avatarPointer->getWorldPosition();
|
||||
}
|
||||
if (_lookAtSnappingEnabled && avatar->getLookAtSnappingEnabled() && isLookingAtMe(avatar)) {
|
||||
|
||||
// Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face.
|
||||
glm::vec3 lookAtPosition = avatar->getHead()->getLookAtPosition(); // A position, in world space, on my avatar.
|
||||
|
||||
|
@ -1510,7 +1527,9 @@ void MyAvatar::clearJointData(const QString& name) {
|
|||
QMetaObject::invokeMethod(this, "clearJointData", Q_ARG(QString, name));
|
||||
return;
|
||||
}
|
||||
writeLockWithNamedJointIndex(name, [&](int index) { _skeletonModel->getRig().clearJointAnimationPriority(index); });
|
||||
writeLockWithNamedJointIndex(name, [&](int index) {
|
||||
_skeletonModel->getRig().clearJointAnimationPriority(index);
|
||||
});
|
||||
}
|
||||
|
||||
void MyAvatar::clearJointsData() {
|
||||
|
@ -1533,9 +1552,9 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
_cauterizationNeedsUpdate = true;
|
||||
|
||||
std::shared_ptr<QMetaObject::Connection> skeletonConnection = std::make_shared<QMetaObject::Connection>();
|
||||
*skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded,
|
||||
[this, skeletonModelChangeCount, skeletonConnection]() {
|
||||
*skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() {
|
||||
if (skeletonModelChangeCount == _skeletonModelChangeCount) {
|
||||
|
||||
if (_fullAvatarModelName.isEmpty()) {
|
||||
// Store the FST file name into preferences
|
||||
const auto& mapping = _skeletonModel->getGeometry()->getMapping();
|
||||
|
@ -1546,8 +1565,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
|
||||
initHeadBones();
|
||||
_skeletonModel->setCauterizeBoneSet(_headBoneSet);
|
||||
_fstAnimGraphOverrideUrl =
|
||||
_skeletonModel->getGeometry()->getAnimGraphOverrideUrl();
|
||||
_fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl();
|
||||
initAnimGraph();
|
||||
}
|
||||
QObject::disconnect(*skeletonConnection);
|
||||
|
@ -1588,6 +1606,7 @@ QVariantList MyAvatar::getAvatarEntitiesVariant() {
|
|||
return avatarEntitiesData;
|
||||
}
|
||||
|
||||
|
||||
void MyAvatar::resetFullAvatarURL() {
|
||||
auto lastAvatarURL = getFullAvatarURLFromPreferences();
|
||||
auto lastAvatarName = getFullAvatarModelName();
|
||||
|
@ -1596,8 +1615,11 @@ void MyAvatar::resetFullAvatarURL() {
|
|||
}
|
||||
|
||||
void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "useFullAvatarURL", Q_ARG(const QUrl&, fullAvatarURL), Q_ARG(const QString&, modelName));
|
||||
BLOCKING_INVOKE_METHOD(this, "useFullAvatarURL",
|
||||
Q_ARG(const QUrl&, fullAvatarURL),
|
||||
Q_ARG(const QString&, modelName));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1617,7 +1639,8 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN
|
|||
|
||||
void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentData", Q_ARG(const QVector<AttachmentData>, attachmentData));
|
||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
||||
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
||||
return;
|
||||
}
|
||||
Avatar::setAttachmentData(attachmentData);
|
||||
|
@ -1722,8 +1745,7 @@ void MyAvatar::updateMotors() {
|
|||
}
|
||||
|
||||
if (_isPushing || _isBraking || !_isBeingPushed) {
|
||||
_characterController.addMotor(_actionMotorVelocity, motorRotation, horizontalMotorTimescale,
|
||||
verticalMotorTimescale);
|
||||
_characterController.addMotor(_actionMotorVelocity, motorRotation, horizontalMotorTimescale, verticalMotorTimescale);
|
||||
} else {
|
||||
// _isBeingPushed must be true --> disable action motor by giving it a long timescale,
|
||||
// otherwise it's attempt to "stand in in place" could defeat scripted motor/thrusts
|
||||
|
@ -1743,8 +1765,7 @@ void MyAvatar::updateMotors() {
|
|||
_characterController.addMotor(_scriptedMotorVelocity, motorRotation, _scriptedMotorTimescale);
|
||||
} else {
|
||||
// dynamic mode
|
||||
_characterController.addMotor(_scriptedMotorVelocity, motorRotation, horizontalMotorTimescale,
|
||||
verticalMotorTimescale);
|
||||
_characterController.addMotor(_scriptedMotorVelocity, motorRotation, horizontalMotorTimescale, verticalMotorTimescale);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1849,7 +1870,8 @@ void MyAvatar::setScriptedMotorVelocity(const glm::vec3& velocity) {
|
|||
void MyAvatar::setScriptedMotorTimescale(float timescale) {
|
||||
// we clamp the timescale on the large side (instead of just the low side) to prevent
|
||||
// obnoxiously large values from introducing NaN into avatar's velocity
|
||||
_scriptedMotorTimescale = glm::clamp(timescale, MIN_SCRIPTED_MOTOR_TIMESCALE, DEFAULT_SCRIPTED_MOTOR_TIMESCALE);
|
||||
_scriptedMotorTimescale = glm::clamp(timescale, MIN_SCRIPTED_MOTOR_TIMESCALE,
|
||||
DEFAULT_SCRIPTED_MOTOR_TIMESCALE);
|
||||
}
|
||||
|
||||
void MyAvatar::setScriptedMotorFrame(QString frame) {
|
||||
|
@ -1890,14 +1912,10 @@ SharedSoundPointer MyAvatar::getCollisionSound() {
|
|||
return _collisionSound;
|
||||
}
|
||||
|
||||
void MyAvatar::attach(const QString& modelURL,
|
||||
const QString& jointName,
|
||||
const glm::vec3& translation,
|
||||
const glm::quat& rotation,
|
||||
float scale,
|
||||
bool isSoft,
|
||||
bool allowDuplicates,
|
||||
bool useSaved) {
|
||||
void MyAvatar::attach(const QString& modelURL, const QString& jointName,
|
||||
const glm::vec3& translation, const glm::quat& rotation,
|
||||
float scale, bool isSoft,
|
||||
bool allowDuplicates, bool useSaved) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
Avatar::attach(modelURL, jointName, translation, rotation, scale, isSoft, allowDuplicates, useSaved);
|
||||
return;
|
||||
|
@ -1905,8 +1923,10 @@ void MyAvatar::attach(const QString& modelURL,
|
|||
if (useSaved) {
|
||||
AttachmentData attachment = loadAttachmentData(modelURL, jointName);
|
||||
if (attachment.isValid()) {
|
||||
Avatar::attach(modelURL, attachment.jointName, attachment.translation, attachment.rotation, attachment.scale,
|
||||
attachment.isSoft, allowDuplicates, useSaved);
|
||||
Avatar::attach(modelURL, attachment.jointName,
|
||||
attachment.translation, attachment.rotation,
|
||||
attachment.scale, attachment.isSoft,
|
||||
allowDuplicates, useSaved);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1959,6 +1979,7 @@ QUrl MyAvatar::getAnimGraphUrl() const {
|
|||
}
|
||||
|
||||
void MyAvatar::setAnimGraphUrl(const QUrl& url) {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setAnimGraphUrl", Q_ARG(QUrl, url));
|
||||
return;
|
||||
|
@ -2003,8 +2024,10 @@ void MyAvatar::animGraphLoaded() {
|
|||
}
|
||||
|
||||
void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
||||
|
||||
Avatar::postUpdate(deltaTime, scene);
|
||||
if (_enableDebugDrawDefaultPose || _enableDebugDrawAnimPose) {
|
||||
|
||||
auto animSkeleton = _skeletonModel->getRig().getAnimSkeleton();
|
||||
|
||||
// the rig is in the skeletonModel frame
|
||||
|
@ -2012,8 +2035,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
|||
|
||||
if (_enableDebugDrawDefaultPose && animSkeleton) {
|
||||
glm::vec4 gray(0.2f, 0.2f, 0.2f, 0.2f);
|
||||
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarDefaultPoses", animSkeleton,
|
||||
_skeletonModel->getRig().getAbsoluteDefaultPoses(), xform, gray);
|
||||
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarDefaultPoses", animSkeleton, _skeletonModel->getRig().getAbsoluteDefaultPoses(), xform, gray);
|
||||
}
|
||||
|
||||
if (_enableDebugDrawAnimPose && animSkeleton) {
|
||||
|
@ -2034,15 +2056,13 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
|||
auto rightHandPose = getControllerPoseInWorldFrame(controller::Action::RIGHT_HAND);
|
||||
|
||||
if (leftHandPose.isValid()) {
|
||||
DebugDraw::getInstance().addMarker("leftHandController", leftHandPose.getRotation(), leftHandPose.getTranslation(),
|
||||
glm::vec4(1));
|
||||
DebugDraw::getInstance().addMarker("leftHandController", leftHandPose.getRotation(), leftHandPose.getTranslation(), glm::vec4(1));
|
||||
} else {
|
||||
DebugDraw::getInstance().removeMarker("leftHandController");
|
||||
}
|
||||
|
||||
if (rightHandPose.isValid()) {
|
||||
DebugDraw::getInstance().addMarker("rightHandController", rightHandPose.getRotation(),
|
||||
rightHandPose.getTranslation(), glm::vec4(1));
|
||||
DebugDraw::getInstance().addMarker("rightHandController", rightHandPose.getRotation(), rightHandPose.getTranslation(), glm::vec4(1));
|
||||
} else {
|
||||
DebugDraw::getInstance().removeMarker("rightHandController");
|
||||
}
|
||||
|
@ -2059,9 +2079,14 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
|||
AnimPose rigToWorldPose(glm::vec3(1.0f), getWorldOrientation() * Quaternions::Y_180, getWorldPosition());
|
||||
const int NUM_DEBUG_COLORS = 8;
|
||||
const glm::vec4 DEBUG_COLORS[NUM_DEBUG_COLORS] = {
|
||||
glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
glm::vec4(0.25f, 0.25f, 1.0f, 1.0f), glm::vec4(1.0f, 1.0f, 0.0f, 1.0f), glm::vec4(0.25f, 1.0f, 1.0f, 1.0f),
|
||||
glm::vec4(1.0f, 0.25f, 1.0f, 1.0f), glm::vec4(1.0f, 0.65f, 0.0f, 1.0f) // Orange you glad I added this color?
|
||||
glm::vec4(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
glm::vec4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
glm::vec4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
glm::vec4(0.25f, 0.25f, 1.0f, 1.0f),
|
||||
glm::vec4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
glm::vec4(0.25f, 1.0f, 1.0f, 1.0f),
|
||||
glm::vec4(1.0f, 0.25f, 1.0f, 1.0f),
|
||||
glm::vec4(1.0f, 0.65f, 0.0f, 1.0f) // Orange you glad I added this color?
|
||||
};
|
||||
|
||||
if (_skeletonModel && _skeletonModel->isLoaded()) {
|
||||
|
@ -2083,6 +2108,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
|||
}
|
||||
|
||||
void MyAvatar::preDisplaySide(const RenderArgs* renderArgs) {
|
||||
|
||||
// toggle using the cauterizedBones depending on where the camera is and the rendering pass type.
|
||||
const bool shouldDrawHead = shouldRenderHead(renderArgs);
|
||||
if (shouldDrawHead != _prevShouldDrawHead) {
|
||||
|
@ -2146,15 +2172,8 @@ void MyAvatar::setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement)
|
|||
_headData->setHasAudioEnabledFaceMovement(hasAudioEnabledFaceMovement);
|
||||
}
|
||||
|
||||
void MyAvatar::setRotationRecenterFilterLength(float length) {
|
||||
_rotationRecenterFilterLength = length;
|
||||
}
|
||||
|
||||
void MyAvatar::setRotationThreshold(float angleRadians) {
|
||||
_rotationThreshold = angleRadians;
|
||||
}
|
||||
|
||||
void MyAvatar::updateOrientation(float deltaTime) {
|
||||
|
||||
// Smoothly rotate body with arrow keys
|
||||
float targetSpeed = getDriveKey(YAW) * _yawSpeed;
|
||||
if (targetSpeed != 0.0f) {
|
||||
|
@ -2181,6 +2200,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
|||
|
||||
float totalBodyYaw = _bodyYawDelta * deltaTime;
|
||||
|
||||
|
||||
// Comfort Mode: If you press any of the left/right rotation drive keys or input, you'll
|
||||
// get an instantaneous 15 degree turn. If you keep holding the key down you'll get another
|
||||
// snap turn every half second.
|
||||
|
@ -2191,8 +2211,8 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
|||
}
|
||||
|
||||
// Use head/HMD roll to turn while flying, but not when standing still.
|
||||
if (qApp->isHMDMode() && getCharacterController()->getState() == CharacterController::State::Hover &&
|
||||
_hmdRollControlEnabled && hasDriveInput()) {
|
||||
if (qApp->isHMDMode() && getCharacterController()->getState() == CharacterController::State::Hover && _hmdRollControlEnabled && hasDriveInput()) {
|
||||
|
||||
// Turn with head roll.
|
||||
const float MIN_CONTROL_SPEED = 2.0f * getSensorToWorldScale(); // meters / sec
|
||||
const glm::vec3 characterForward = getWorldOrientation() * Vectors::UNIT_NEG_Z;
|
||||
|
@ -2200,6 +2220,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
|||
|
||||
// only enable roll-turns if we are moving forward or backward at greater then MIN_CONTROL_SPEED
|
||||
if (fabsf(forwardSpeed) >= MIN_CONTROL_SPEED) {
|
||||
|
||||
float direction = forwardSpeed > 0.0f ? 1.0f : -1.0f;
|
||||
float rollAngle = glm::degrees(asinf(glm::dot(IDENTITY_UP, _hmdSensorOrientation * IDENTITY_RIGHT)));
|
||||
float rollSign = rollAngle < 0.0f ? -1.0f : 1.0f;
|
||||
|
@ -2253,8 +2274,8 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
|||
|
||||
void MyAvatar::updateActionMotor(float deltaTime) {
|
||||
bool thrustIsPushing = (glm::length2(_thrust) > EPSILON);
|
||||
bool scriptedMotorIsPushing =
|
||||
(_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) && _scriptedMotorTimescale < MAX_CHARACTER_MOTOR_TIMESCALE;
|
||||
bool scriptedMotorIsPushing = (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED)
|
||||
&& _scriptedMotorTimescale < MAX_CHARACTER_MOTOR_TIMESCALE;
|
||||
_isBeingPushed = thrustIsPushing || scriptedMotorIsPushing;
|
||||
if (_isPushing || _isBeingPushed) {
|
||||
// we don't want the motor to brake if a script is pushing the avatar around
|
||||
|
@ -2366,13 +2387,8 @@ void MyAvatar::updateCollisionSound(const glm::vec3& penetration, float deltaTim
|
|||
// COLLISION SOUND API in Audio has been removed
|
||||
}
|
||||
|
||||
bool findAvatarAvatarPenetration(const glm::vec3 positionA,
|
||||
float radiusA,
|
||||
float heightA,
|
||||
const glm::vec3 positionB,
|
||||
float radiusB,
|
||||
float heightB,
|
||||
glm::vec3& penetration) {
|
||||
bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float heightA,
|
||||
const glm::vec3 positionB, float radiusB, float heightB, glm::vec3& penetration) {
|
||||
glm::vec3 positionBA = positionB - positionA;
|
||||
float xzDistance = sqrt(positionBA.x * positionBA.x + positionBA.z * positionBA.z);
|
||||
if (xzDistance < (radiusA + radiusB)) {
|
||||
|
@ -2544,9 +2560,9 @@ void MyAvatar::goToLocation(const QVariant& propertiesVar) {
|
|||
}
|
||||
|
||||
void MyAvatar::goToLocation(const glm::vec3& newPosition,
|
||||
bool hasOrientation,
|
||||
const glm::quat& newOrientation,
|
||||
bool hasOrientation, const glm::quat& newOrientation,
|
||||
bool shouldFaceLocation) {
|
||||
|
||||
// Most cases of going to a place or user go through this now. Some possible improvements to think about in the future:
|
||||
// - It would be nice if this used the same teleport steps and smoothing as in the teleport.js script, as long as it
|
||||
// still worked if the target is in the air.
|
||||
|
@ -2560,15 +2576,15 @@ void MyAvatar::goToLocation(const glm::vec3& newPosition,
|
|||
// compute the position (e.g., so that if I'm on stage, going to me would compute an available seat in the audience rather than
|
||||
// being in my face on-stage). Note that this could work for going to an entity as well as to a person.
|
||||
|
||||
qCDebug(interfaceapp).nospace() << "MyAvatar goToLocation - moving to " << newPosition.x << ", " << newPosition.y << ", "
|
||||
<< newPosition.z;
|
||||
qCDebug(interfaceapp).nospace() << "MyAvatar goToLocation - moving to " << newPosition.x << ", "
|
||||
<< newPosition.y << ", " << newPosition.z;
|
||||
|
||||
_goToPending = true;
|
||||
_goToPosition = newPosition;
|
||||
_goToOrientation = getWorldOrientation();
|
||||
if (hasOrientation) {
|
||||
qCDebug(interfaceapp).nospace() << "MyAvatar goToLocation - new orientation is " << newOrientation.x << ", "
|
||||
<< newOrientation.y << ", " << newOrientation.z << ", " << newOrientation.w;
|
||||
qCDebug(interfaceapp).nospace() << "MyAvatar goToLocation - new orientation is "
|
||||
<< newOrientation.x << ", " << newOrientation.y << ", " << newOrientation.z << ", " << newOrientation.w;
|
||||
|
||||
// orient the user to face the target
|
||||
glm::quat quatOrientation = cancelOutRollAndPitch(newOrientation);
|
||||
|
@ -2616,8 +2632,7 @@ bool MyAvatar::safeLanding(const glm::vec3& position) {
|
|||
} else { // If you try to go while stuck, physics will keep you stuck.
|
||||
setCollisionsEnabled(false);
|
||||
// Don't goToLocation just yet. Yield so that physics can act on the above.
|
||||
QMetaObject::invokeMethod(this, "goToLocationAndEnableCollisions",
|
||||
Qt::QueuedConnection, // The equivalent of javascript nextTick
|
||||
QMetaObject::invokeMethod(this, "goToLocationAndEnableCollisions", Qt::QueuedConnection, // The equivalent of javascript nextTick
|
||||
Q_ARG(glm::vec3, better));
|
||||
}
|
||||
return true;
|
||||
|
@ -2625,6 +2640,7 @@ bool MyAvatar::safeLanding(const glm::vec3& position) {
|
|||
|
||||
// If position is not reliably safe from being stuck by physics, answer true and place a candidate better position in betterPositionOut.
|
||||
bool MyAvatar::requiresSafeLanding(const glm::vec3& positionIn, glm::vec3& betterPositionOut) {
|
||||
|
||||
// We begin with utilities and tests. The Algorithm in four parts is below.
|
||||
// NOTE: we use estimated avatar height here instead of the bullet capsule halfHeight, because
|
||||
// the domain avatar height limiting might not have taken effect yet on the actual bullet shape.
|
||||
|
@ -2647,8 +2663,7 @@ bool MyAvatar::requiresSafeLanding(const glm::vec3& positionIn, glm::vec3& bette
|
|||
betterPositionOut = upperIntersection + (up * halfHeight);
|
||||
return true;
|
||||
};
|
||||
auto findIntersection = [&](const glm::vec3& startPointIn, const glm::vec3& directionIn, glm::vec3& intersectionOut,
|
||||
EntityItemID& entityIdOut, glm::vec3& normalOut) {
|
||||
auto findIntersection = [&](const glm::vec3& startPointIn, const glm::vec3& directionIn, glm::vec3& intersectionOut, EntityItemID& entityIdOut, glm::vec3& normalOut) {
|
||||
OctreeElementPointer element;
|
||||
float distance;
|
||||
BoxFace face;
|
||||
|
@ -2662,9 +2677,8 @@ bool MyAvatar::requiresSafeLanding(const glm::vec3& positionIn, glm::vec3& bette
|
|||
bool* accurateResult = NULL;
|
||||
|
||||
QVariantMap extraInfo;
|
||||
EntityItemID entityID = entityTree->findRayIntersection(startPointIn, directionIn, include, ignore, visibleOnly,
|
||||
collidableOnly, precisionPicking, element, distance, face,
|
||||
normalOut, extraInfo, lockType, accurateResult);
|
||||
EntityItemID entityID = entityTree->findRayIntersection(startPointIn, directionIn, include, ignore, visibleOnly, collidableOnly, precisionPicking,
|
||||
element, distance, face, normalOut, extraInfo, lockType, accurateResult);
|
||||
if (entityID.isNull()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2692,8 +2706,7 @@ bool MyAvatar::requiresSafeLanding(const glm::vec3& positionIn, glm::vec3& bette
|
|||
// I.e., we are in a clearing between two objects.
|
||||
if (isDown(upperNormal) && isUp(lowerNormal)) {
|
||||
auto spaceBetween = glm::distance(upperIntersection, lowerIntersection);
|
||||
const float halfHeightFactor =
|
||||
2.25f; // Until case 5003 is fixed (and maybe after?), we need a fudge factor. Also account for content modelers not being precise.
|
||||
const float halfHeightFactor = 2.25f; // Until case 5003 is fixed (and maybe after?), we need a fudge factor. Also account for content modelers not being precise.
|
||||
if (spaceBetween > (halfHeightFactor * halfHeight)) {
|
||||
// There is room for us to fit in that clearing. If there wasn't, physics would oscilate us between the objects above and below.
|
||||
// We're now going to iterate upwards through successive upperIntersections, testing to see if we're contained within the top surface of some entity.
|
||||
|
@ -2732,6 +2745,7 @@ bool MyAvatar::requiresSafeLanding(const glm::vec3& positionIn, glm::vec3& bette
|
|||
}
|
||||
|
||||
void MyAvatar::updateMotionBehaviorFromMenu() {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "updateMotionBehaviorFromMenu");
|
||||
return;
|
||||
|
@ -2781,6 +2795,7 @@ float MyAvatar::getAvatarScale() {
|
|||
}
|
||||
|
||||
void MyAvatar::setAvatarScale(float val) {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setAvatarScale", Q_ARG(float, val));
|
||||
return;
|
||||
|
@ -2790,6 +2805,7 @@ void MyAvatar::setAvatarScale(float val) {
|
|||
}
|
||||
|
||||
void MyAvatar::setCollisionsEnabled(bool enabled) {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setCollisionsEnabled", Q_ARG(bool, enabled));
|
||||
return;
|
||||
|
@ -2996,14 +3012,12 @@ glm::vec3 MyAvatar::computeCounterBalance() const {
|
|||
tposeHead = getAbsoluteDefaultJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint(cgHeadMass.name));
|
||||
}
|
||||
if (_skeletonModel->getRig().indexOfJoint(cgLeftHandMass.name) != -1) {
|
||||
cgLeftHandMass.position =
|
||||
getAbsoluteJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint(cgLeftHandMass.name));
|
||||
cgLeftHandMass.position = getAbsoluteJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint(cgLeftHandMass.name));
|
||||
} else {
|
||||
cgLeftHandMass.position = DEFAULT_AVATAR_LEFTHAND_POS;
|
||||
}
|
||||
if (_skeletonModel->getRig().indexOfJoint(cgRightHandMass.name) != -1) {
|
||||
cgRightHandMass.position =
|
||||
getAbsoluteJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint(cgRightHandMass.name));
|
||||
cgRightHandMass.position = getAbsoluteJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint(cgRightHandMass.name));
|
||||
} else {
|
||||
cgRightHandMass.position = DEFAULT_AVATAR_RIGHTHAND_POS;
|
||||
}
|
||||
|
@ -3012,8 +3026,7 @@ glm::vec3 MyAvatar::computeCounterBalance() const {
|
|||
}
|
||||
|
||||
// find the current center of gravity position based on head and hand moments
|
||||
glm::vec3 sumOfMoments = (cgHeadMass.weight * cgHeadMass.position) + (cgLeftHandMass.weight * cgLeftHandMass.position) +
|
||||
(cgRightHandMass.weight * cgRightHandMass.position);
|
||||
glm::vec3 sumOfMoments = (cgHeadMass.weight * cgHeadMass.position) + (cgLeftHandMass.weight * cgLeftHandMass.position) + (cgRightHandMass.weight * cgRightHandMass.position);
|
||||
float totalMass = cgHeadMass.weight + cgLeftHandMass.weight + cgRightHandMass.weight;
|
||||
|
||||
glm::vec3 currentCg = (1.0f / totalMass) * sumOfMoments;
|
||||
|
@ -3053,6 +3066,7 @@ glm::vec3 MyAvatar::computeCounterBalance() const {
|
|||
// headOrientation, headPosition and hipsPosition are in avatar space
|
||||
// returns the matrix of the hips in Avatar space
|
||||
static glm::mat4 computeNewHipsMatrix(glm::quat headOrientation, glm::vec3 headPosition, glm::vec3 hipsPosition) {
|
||||
|
||||
glm::quat bodyOrientation = computeBodyFacingFromHead(headOrientation, Vectors::UNIT_Y);
|
||||
|
||||
const float MIX_RATIO = 0.3f;
|
||||
|
@ -3062,7 +3076,10 @@ static glm::mat4 computeNewHipsMatrix(glm::quat headOrientation, glm::vec3 headP
|
|||
glm::vec3 spineVec = headPosition - hipsPosition;
|
||||
glm::vec3 u, v, w;
|
||||
generateBasisVectors(glm::normalize(spineVec), hipsFacing, u, v, w);
|
||||
return glm::mat4(glm::vec4(w, 0.0f), glm::vec4(u, 0.0f), glm::vec4(v, 0.0f), glm::vec4(hipsPosition, 1.0f));
|
||||
return glm::mat4(glm::vec4(w, 0.0f),
|
||||
glm::vec4(u, 0.0f),
|
||||
glm::vec4(v, 0.0f),
|
||||
glm::vec4(hipsPosition, 1.0f));
|
||||
}
|
||||
|
||||
static void drawBaseOfSupport(float baseOfSupportScale, float footLocal, glm::mat4 avatarToWorld) {
|
||||
|
@ -3103,8 +3120,7 @@ glm::mat4 MyAvatar::deriveBodyUsingCgModel() const {
|
|||
|
||||
if (_enableDebugDrawBaseOfSupport) {
|
||||
float scaleBaseOfSupport = getUserEyeHeight() / DEFAULT_AVATAR_EYE_HEIGHT;
|
||||
glm::vec3 rightFootPositionLocal =
|
||||
getAbsoluteJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint("RightFoot"));
|
||||
glm::vec3 rightFootPositionLocal = getAbsoluteJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint("RightFoot"));
|
||||
drawBaseOfSupport(scaleBaseOfSupport, rightFootPositionLocal.y, avatarToWorldMat);
|
||||
}
|
||||
|
||||
|
@ -3112,8 +3128,7 @@ glm::mat4 MyAvatar::deriveBodyUsingCgModel() const {
|
|||
const glm::vec3 cgHipsPosition = computeCounterBalance();
|
||||
|
||||
// find the new hips rotation using the new head-hips axis as the up axis
|
||||
glm::mat4 avatarHipsMat =
|
||||
computeNewHipsMatrix(glmExtractRotation(avatarHeadMat), extractTranslation(avatarHeadMat), cgHipsPosition);
|
||||
glm::mat4 avatarHipsMat = computeNewHipsMatrix(glmExtractRotation(avatarHeadMat), extractTranslation(avatarHeadMat), cgHipsPosition);
|
||||
|
||||
// convert hips from avatar to sensor space
|
||||
// The Y_180 is to convert from z forward to -z forward.
|
||||
|
@ -3272,7 +3287,6 @@ static bool isHeadLevel(controller::Pose head, glm::quat averageHeadRotation) {
|
|||
qCDebug(interfaceapp) << " diff from average eulers x " << (fabs(diffFromAverageEulers.x) < DEFAULT_HEAD_PITCH_STEPPING_TOLERANCE) << " and z " << (fabs(diffFromAverageEulers.z) < DEFAULT_HEAD_ROLL_STEPPING_TOLERANCE);
|
||||
return ((fabs(diffFromAverageEulers.x) < DEFAULT_HEAD_PITCH_STEPPING_TOLERANCE) && (fabs(diffFromAverageEulers.z) < DEFAULT_HEAD_ROLL_STEPPING_TOLERANCE));
|
||||
}
|
||||
|
||||
float MyAvatar::getUserHeight() const {
|
||||
return _userHeight.get();
|
||||
}
|
||||
|
@ -3379,10 +3393,12 @@ void driveKeysFromScriptValue(const QScriptValue& object, MyAvatar::DriveKeys& d
|
|||
driveKeys = static_cast<MyAvatar::DriveKeys>(object.toUInt16());
|
||||
}
|
||||
|
||||
|
||||
void MyAvatar::lateUpdatePalms() {
|
||||
Avatar::updatePalms();
|
||||
}
|
||||
|
||||
|
||||
static const float FOLLOW_TIME = 0.5f;
|
||||
|
||||
MyAvatar::FollowHelper::FollowHelper() {
|
||||
|
@ -3436,18 +3452,13 @@ void MyAvatar::FollowHelper::decrementTimeRemaining(float dt) {
|
|||
}
|
||||
}
|
||||
|
||||
bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar,
|
||||
const glm::mat4& desiredBodyMatrix,
|
||||
const glm::mat4& currentBodyMatrix) const {
|
||||
//qCDebug(interfaceapp) << "rotation threshold is " << myAvatar.getRotationThreshold();
|
||||
const float FOLLOW_ROTATION_THRESHOLD = cosf(myAvatar.getRotationThreshold()); //cosf(PI / 6.0f); // 30 degrees
|
||||
bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
||||
const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees
|
||||
glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix);
|
||||
return glm::dot(-myAvatar.getHeadControllerFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD;
|
||||
}
|
||||
|
||||
bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar,
|
||||
const glm::mat4& desiredBodyMatrix,
|
||||
const glm::mat4& currentBodyMatrix) const {
|
||||
bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
||||
// -z axis of currentBodyMatrix in world space.
|
||||
glm::vec3 forward = glm::normalize(glm::vec3(-currentBodyMatrix[0][2], -currentBodyMatrix[1][2], -currentBodyMatrix[2][2]));
|
||||
// x axis of currentBodyMatrix in world space.
|
||||
|
@ -3461,6 +3472,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar,
|
|||
const float MAX_FORWARD_LEAN = 0.15f;
|
||||
const float MAX_BACKWARD_LEAN = 0.1f;
|
||||
|
||||
|
||||
if (forwardLeanAmount > 0 && forwardLeanAmount > MAX_FORWARD_LEAN) {
|
||||
return true;
|
||||
} else if (forwardLeanAmount < 0 && forwardLeanAmount < -MAX_BACKWARD_LEAN) {
|
||||
|
@ -3501,9 +3513,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons
|
|||
return stepDetected;
|
||||
}
|
||||
|
||||
bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar,
|
||||
const glm::mat4& desiredBodyMatrix,
|
||||
const glm::mat4& currentBodyMatrix) const {
|
||||
bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
||||
const float CYLINDER_TOP = 0.1f;
|
||||
const float CYLINDER_BOTTOM = -1.5f;
|
||||
|
||||
|
@ -3512,11 +3522,11 @@ bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar,
|
|||
return (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM);
|
||||
}
|
||||
|
||||
void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar,
|
||||
const glm::mat4& desiredBodyMatrix,
|
||||
const glm::mat4& currentBodyMatrix,
|
||||
bool hasDriveInput) {
|
||||
if (myAvatar.getHMDLeanRecenterEnabled() && qApp->getCamera().getMode() != CAMERA_MODE_MIRROR) {
|
||||
void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix,
|
||||
const glm::mat4& currentBodyMatrix, bool hasDriveInput) {
|
||||
|
||||
if (myAvatar.getHMDLeanRecenterEnabled() &&
|
||||
qApp->getCamera().getMode() != CAMERA_MODE_MIRROR) {
|
||||
if (!isActive(Rotation) && (shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {
|
||||
activate(Rotation);
|
||||
}
|
||||
|
@ -3587,8 +3597,7 @@ glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(const MyAvatar& myAvatar, co
|
|||
glm::mat4 worldToSensorMatrix = glm::inverse(sensorToWorldMatrix);
|
||||
|
||||
glm::vec3 sensorLinearDisplacement = transformVectorFast(worldToSensorMatrix, worldLinearDisplacement);
|
||||
glm::quat sensorAngularDisplacement =
|
||||
glmExtractRotation(worldToSensorMatrix) * worldAngularDisplacement * glmExtractRotation(sensorToWorldMatrix);
|
||||
glm::quat sensorAngularDisplacement = glmExtractRotation(worldToSensorMatrix) * worldAngularDisplacement * glmExtractRotation(sensorToWorldMatrix);
|
||||
|
||||
glm::mat4 newBodyMat = createMatFromQuatAndPos(sensorAngularDisplacement * glmExtractRotation(currentBodyMatrix),
|
||||
sensorLinearDisplacement + extractTranslation(currentBodyMatrix));
|
||||
|
@ -3651,8 +3660,7 @@ bool MyAvatar::didTeleport() {
|
|||
}
|
||||
|
||||
bool MyAvatar::hasDriveInput() const {
|
||||
return fabsf(getDriveKey(TRANSLATE_X)) > 0.0f || fabsf(getDriveKey(TRANSLATE_Y)) > 0.0f ||
|
||||
fabsf(getDriveKey(TRANSLATE_Z)) > 0.0f;
|
||||
return fabsf(getDriveKey(TRANSLATE_X)) > 0.0f || fabsf(getDriveKey(TRANSLATE_Y)) > 0.0f || fabsf(getDriveKey(TRANSLATE_Z)) > 0.0f;
|
||||
}
|
||||
|
||||
void MyAvatar::setAway(bool value) {
|
||||
|
@ -3668,6 +3676,7 @@ void MyAvatar::setAway(bool value) {
|
|||
// Specificly, if we are rendering using a third person camera. We would like to render the hand controllers in front of the camera,
|
||||
// not in front of the avatar.
|
||||
glm::mat4 MyAvatar::computeCameraRelativeHandControllerMatrix(const glm::mat4& controllerSensorMatrix) const {
|
||||
|
||||
// Fetch the current camera transform.
|
||||
glm::mat4 cameraWorldMatrix = qApp->getCamera().getTransform();
|
||||
if (qApp->getCamera().getMode() == CAMERA_MODE_MIRROR) {
|
||||
|
@ -3723,7 +3732,9 @@ glm::quat MyAvatar::getAbsoluteJointRotationInObjectFrame(int index) const {
|
|||
glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix();
|
||||
return glmExtractRotation(invAvatarMat * qApp->getCamera().getTransform());
|
||||
}
|
||||
default: { return Avatar::getAbsoluteJointRotationInObjectFrame(index); }
|
||||
default: {
|
||||
return Avatar::getAbsoluteJointRotationInObjectFrame(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3758,7 +3769,9 @@ glm::vec3 MyAvatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
|
|||
glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix();
|
||||
return extractTranslation(invAvatarMat * qApp->getCamera().getTransform());
|
||||
}
|
||||
default: { return Avatar::getAbsoluteJointTranslationInObjectFrame(index); }
|
||||
default: {
|
||||
return Avatar::getAbsoluteJointTranslationInObjectFrame(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3767,9 +3780,7 @@ glm::mat4 MyAvatar::getCenterEyeCalibrationMat() const {
|
|||
int rightEyeIndex = _skeletonModel->getRig().indexOfJoint("RightEye");
|
||||
int leftEyeIndex = _skeletonModel->getRig().indexOfJoint("LeftEye");
|
||||
if (rightEyeIndex >= 0 && leftEyeIndex >= 0) {
|
||||
auto centerEyePos = (getAbsoluteDefaultJointTranslationInObjectFrame(rightEyeIndex) +
|
||||
getAbsoluteDefaultJointTranslationInObjectFrame(leftEyeIndex)) *
|
||||
0.5f;
|
||||
auto centerEyePos = (getAbsoluteDefaultJointTranslationInObjectFrame(rightEyeIndex) + getAbsoluteDefaultJointTranslationInObjectFrame(leftEyeIndex)) * 0.5f;
|
||||
auto centerEyeRot = Quaternions::Y_180;
|
||||
return createMatFromQuatAndPos(centerEyeRot, centerEyePos / getSensorToWorldScale());
|
||||
} else {
|
||||
|
@ -3837,6 +3848,7 @@ glm::mat4 MyAvatar::getRightFootCalibrationMat() const {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
glm::mat4 MyAvatar::getRightArmCalibrationMat() const {
|
||||
int rightArmIndex = _skeletonModel->getRig().indexOfJoint("RightArm");
|
||||
if (rightArmIndex >= 0) {
|
||||
|
|
|
@ -1,171 +0,0 @@
|
|||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Rotate App</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../../system/html/css/edit-style.css">
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/css/bootstrap-slider.min.css">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
color: purple;
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
height: 90px;
|
||||
background: linear-gradient(#2b2b2b, #1e1e1e);
|
||||
font-family: Raleway-Bold;
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
width: 480px;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 90px;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.slider {
|
||||
margin-left: 70px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-bar">
|
||||
<div style="font-size:300%;color:grey;"><b>Rotate App</b></div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div id="properties-list">
|
||||
<div class="property">
|
||||
<label>Filter Length      </label>
|
||||
<input
|
||||
id="filterLength-slider"
|
||||
type="text"
|
||||
data-provide="slider"
|
||||
data-slider-ticks="[0, 15, 30]"
|
||||
data-slider-ticks-labels='["zero", "15cm", "30cm"]'
|
||||
data-slider-min="0"
|
||||
data-slider-max="30"
|
||||
data-slider-step="1"
|
||||
data-slider-value="14"
|
||||
data-slider-tooltip="show"
|
||||
>
|
||||
</div>
|
||||
<br>
|
||||
<div class="property">
|
||||
<label>Angle Threshold</label>
|
||||
<input
|
||||
id="angleThreshold-slider"
|
||||
type="text"
|
||||
data-provide="slider"
|
||||
data-slider-ticks="[0, 15, 30]"
|
||||
data-slider-ticks-labels='["zero", "15cm", "30cm"]'
|
||||
data-slider-min="0"
|
||||
data-slider-max="30"
|
||||
data-slider-step="1"
|
||||
data-slider-value="14"
|
||||
data-slider-tooltip="show"
|
||||
>
|
||||
</div>
|
||||
<br>
|
||||
<audio id="audio" src="http://hifi-content.s3.amazonaws.com/angus/stepApp/create.wav" autostart="false" ></audio>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/bootstrap-slider.min.js"></script>
|
||||
<script>
|
||||
//
|
||||
// Created by Angus Antley on 6/28/18
|
||||
//
|
||||
//
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* jslint bitwise: true */
|
||||
|
||||
/* global $, EventBridge
|
||||
*/
|
||||
function changeColor(id, shade) {
|
||||
document.getElementById(id).setAttribute("fill", shade);
|
||||
}
|
||||
|
||||
function emit(eventType, eventData) {
|
||||
var eventObject = {
|
||||
"app": "step",
|
||||
"type": eventType,
|
||||
"data": eventData
|
||||
};
|
||||
EventBridge.emitWebEvent(JSON.stringify(eventObject));
|
||||
}
|
||||
|
||||
EventBridge.scriptEventReceived.connect(function (msg) {
|
||||
var message = JSON.parse(msg);
|
||||
if (message.type === "failsafe") {
|
||||
console.log("fail safe called");
|
||||
changeColor(message.id,message.data.value);
|
||||
if (message.data.value === "green") {
|
||||
var sound = document.getElementById("audio");
|
||||
if (sound.paused) {
|
||||
sound.volume = 0.25;
|
||||
sound.play();
|
||||
} else {
|
||||
sound.currentTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (message.type === "trigger") {
|
||||
changeColor(message.id,message.data.value);
|
||||
}
|
||||
if (message.type === "frontBase") {
|
||||
$("#filterLength-slider").data("slider").setValue(message.data.value);
|
||||
var curState = $("#filterLength-slider").data("slider").getValue();
|
||||
console.log("the filter length slider value is " + JSON.stringify(curState));
|
||||
}
|
||||
if (message.type === "backBase") {
|
||||
$("#angleThreshold-slider").data("slider").setValue(message.data.value);
|
||||
var curState = $("#angleThreshold-slider").data("slider").getValue();
|
||||
console.log("the angle threshold slider value is " + JSON.stringify(curState));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
emit("ready", null);
|
||||
|
||||
|
||||
$("#filterLength-slider").slider().on("change", function(e){
|
||||
console.log("filter length " + e.value.newValue);
|
||||
emit("onFilterLengthSlider",{value: e.value.newValue});
|
||||
});
|
||||
|
||||
$("#angleThreshold-slider").slider().on("change", function(e){
|
||||
console.log("angle threshold " + e.value.newValue);
|
||||
emit("onAngleThresholdSlider",{value: e.value.newValue});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
emit("onCreateRotateApp", {value: 10.0});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue