From e9ab2b8f27db38a81f114c89fd0d66308c76d1c9 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 20 Jul 2018 16:48:15 -0700 Subject: [PATCH 01/45] enable LOD manager on android --- interface/src/Application.cpp | 2 -- interface/src/LODManager.h | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 311c08b858..0da3d9445e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5803,9 +5803,7 @@ void Application::update(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::update()"); -#if !defined(Q_OS_ANDROID) updateLOD(deltaTime); -#endif // TODO: break these out into distinct perfTimers when they prove interesting { diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 8f88da63a8..8cae179f1e 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -19,7 +19,11 @@ #include #include +#ifdef Q_OS_ANDROID +const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 10.0f; +#else const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 30.0f; +#endif const float DEFAULT_HMD_LOD_DOWN_FPS = 34.0f; const float DEFAULT_DESKTOP_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_DESKTOP_LOD_DOWN_FPS; // msec const float DEFAULT_HMD_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_HMD_LOD_DOWN_FPS; // msec From c2612af7a8550e301a4861302cb6a9ae0cd9fc46 Mon Sep 17 00:00:00 2001 From: amantley Date: Fri, 10 Aug 2018 17:10:33 -0700 Subject: [PATCH 02/45] changed the spine stretch limit, will check the scale implications next --- interface/src/avatar/MyAvatar.cpp | 1 + libraries/shared/src/AvatarConstants.h | 2 +- scripts/developer/objectOrientedStep.js | 683 ++++++++++++++++++++++++ 3 files changed, 685 insertions(+), 1 deletion(-) create mode 100644 scripts/developer/objectOrientedStep.js diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0d7b00da78..db0c683632 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3692,6 +3692,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat setForceActivateRotation(false); } if (!isActive(Horizontal) && getForceActivateHorizontal()) { + qCDebug(interfaceapp) << "called the recentering from script"; activate(Horizontal); setForceActivateHorizontal(false); } diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index d9b26927e2..6b35a45f4c 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -34,7 +34,7 @@ const float DEFAULT_HANDS_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 3.3f; const float DEFAULT_HEAD_VELOCITY_STEPPING_THRESHOLD = 0.18f; const float DEFAULT_HEAD_PITCH_STEPPING_TOLERANCE = 7.0f; const float DEFAULT_HEAD_ROLL_STEPPING_TOLERANCE = 7.0f; -const float DEFAULT_AVATAR_SPINE_STRETCH_LIMIT = 0.07f; +const float DEFAULT_AVATAR_SPINE_STRETCH_LIMIT = 0.03f; const float DEFAULT_AVATAR_FORWARD_DAMPENING_FACTOR = 0.5f; const float DEFAULT_AVATAR_LATERAL_DAMPENING_FACTOR = 2.0f; const float DEFAULT_AVATAR_HIPS_MASS = 40.0f; diff --git a/scripts/developer/objectOrientedStep.js b/scripts/developer/objectOrientedStep.js new file mode 100644 index 0000000000..4eca1fb115 --- /dev/null +++ b/scripts/developer/objectOrientedStep.js @@ -0,0 +1,683 @@ +/* jslint bitwise: true */ + +/* global Script, Vec3, MyAvatar, Tablet, Messages, Quat, +DebugDraw, Mat4, Entities, Xform, Controller, Camera, console, document*/ + +Script.registerValue("STEPAPP", true); +var CENTIMETERSPERMETER = 100.0; +var LEFT = 0; +var RIGHT = 1; +var INCREASING = 1.0; +var DECREASING = -1.0; +var DEFAULT_AVATAR_HEIGHT = 1.64; +var TABLET_BUTTON_NAME = "STEP"; +var CHANGE_OF_BASIS_ROTATION = { x: 0, y: 1, z: 0, w: 0 }; +// in meters (mostly) +var DEFAULT_ANTERIOR = 0.04; +var DEFAULT_POSTERIOR = 0.06; +var DEFAULT_LATERAL = 0.10; +var DEFAULT_HEIGHT_DIFFERENCE = 0.02; +var DEFAULT_ANGULAR_VELOCITY = 0.3; +var DEFAULT_HAND_VELOCITY = 0.4; +var DEFAULT_ANGULAR_HAND_VELOCITY = 3.3; +var DEFAULT_HEAD_VELOCITY = 0.14; +var DEFAULT_LEVEL_PITCH = 7; +var DEFAULT_LEVEL_ROLL = 7; +var DEFAULT_DIFF = 0.0; +var DEFAULT_DIFF_EULERS = { x: 0.0, y: 0.0, z: 0.0 }; +var DEFAULT_HIPS_POSITION; +var DEFAULT_HEAD_POSITION; +var DEFAULT_TORSO_LENGTH; +var SPINE_STRETCH_LIMIT = 0.02; + +var VELOCITY_EPSILON = 0.02; +var AVERAGING_RATE = 0.03; +var HEIGHT_AVERAGING_RATE = 0.01; +var STEP_TIME_SECS = 0.2; +var MODE_SAMPLE_LENGTH = 100; +var RESET_MODE = false; +var HEAD_TURN_THRESHOLD = 25.0; +var NO_SHARED_DIRECTION = -0.98; +var LOADING_DELAY = 500; +var FAILSAFE_TIMEOUT = 2.5; + +var debugDrawBase = true; +var activated = false; +var documentLoaded = false; +var failsafeFlag = false; +var failsafeSignalTimer = -1.0; +var stepTimer = -1.0; + + +var modeArray = new Array(MODE_SAMPLE_LENGTH); +var modeHeight = -10.0; + +var handPosition; +var handOrientation; +var hands = []; +var hipToHandAverage = []; +var handDotHead = []; +var headAverageOrientation = MyAvatar.orientation; +var headPoseAverageOrientation = { x: 0, y: 0, z: 0, w: 1 }; +var averageHeight = 1.0; +var headEulers = { x: 0.0, y: 0.0, z: 0.0 }; +var headAverageEulers = { x: 0.0, y: 0.0, z: 0.0 }; +var headAveragePosition = { x: 0, y: 0.4, z: 0 }; +var frontLeft = { x: -DEFAULT_LATERAL, y: 0, z: -DEFAULT_ANTERIOR }; +var frontRight = { x: DEFAULT_LATERAL, y: 0, z: -DEFAULT_ANTERIOR }; +var backLeft = { x: -DEFAULT_LATERAL, y: 0, z: DEFAULT_POSTERIOR }; +var backRight = { x: DEFAULT_LATERAL, y: 0, z: DEFAULT_POSTERIOR }; + + +// define state readings constructor +function StateReading(headPose, rhandPose, lhandPose, backLength, diffFromMode, diffFromAverageHeight, diffFromAveragePosition, + diffFromAverageEulers) { + this.headPose = headPose; + this.rhandPose = rhandPose; + this.lhandPose = lhandPose; + this.backLength = backLength; + this.diffFromMode = diffFromMode; + this.diffFromAverageHeight = diffFromAverageHeight; + this.diffFromAveragePosition = diffFromAveragePosition; + this.diffFromAverageEulers = diffFromAverageEulers; +} + +// define current state readings object for holding tracker readings and current differences from averages +var currentStateReadings = new StateReading(Controller.getPoseValue(Controller.Standard.Head), + Controller.getPoseValue(Controller.Standard.RightHand), Controller.getPoseValue(Controller.Standard.LeftHand), + DEFAULT_TORSO_LENGTH, DEFAULT_DIFF, DEFAULT_DIFF, DEFAULT_DIFF, DEFAULT_DIFF_EULERS); + +// declare the checkbox constructor +function AppCheckbox(type,id,eventType,isChecked) { + this.type = type; + this.id = id; + this.eventType = eventType; + this.data = {value: isChecked}; +} + +// define the checkboxes in the html file +var usingAverageHeight = new AppCheckbox("checkboxtick", "runningAverageHeightCheck", "onRunningAverageHeightCheckBox", + false); +var usingModeHeight = new AppCheckbox("checkboxtick","modeCheck","onModeCheckBox",true); +var usingBaseOfSupport = new AppCheckbox("checkboxtick","baseOfSupportCheck","onBaseOfSupportCheckBox",true); +var usingAverageHeadPosition = new AppCheckbox("checkboxtick", "headAveragePositionCheck", "onHeadAveragePositionCheckBox", + false); + +var checkBoxArray = new Array(usingAverageHeight,usingModeHeight,usingBaseOfSupport,usingAverageHeadPosition); + +// declare the html slider constructor +function AppProperty(name, type, eventType, signalType, setFunction, initValue, convertToThreshold, convertToSlider, signalOn) { + this.name = name; + this.type = type; + this.eventType = eventType; + this.signalType = signalType; + this.setValue = setFunction; + this.value = initValue; + this.get = function () { + return this.value; + }; + this.convertToThreshold = convertToThreshold; + this.convertToSlider = convertToSlider; + this.signalOn = signalOn; +} + +// define the sliders +var frontBaseProperty = new AppProperty("#anteriorBase-slider", "slider", "onAnteriorBaseSlider", "frontSignal", + setAnteriorDistance, DEFAULT_ANTERIOR, function (num) { + return convertToMeters(num); + }, function (num) { + return convertToCentimeters(num); + },true); +var backBaseProperty = new AppProperty("#posteriorBase-slider", "slider", "onPosteriorBaseSlider", "backSignal", + setPosteriorDistance, DEFAULT_POSTERIOR, function (num) { + return convertToMeters(num); + }, function (num) { + return convertToCentimeters(num); + }, true); +var lateralBaseProperty = new AppProperty("#lateralBase-slider", "slider", "onLateralBaseSlider", "lateralSignal", + setLateralDistance, DEFAULT_LATERAL, function (num) { + return convertToMeters(num); + }, function (num) { + return convertToCentimeters(num); + }, true); +var headAngularVelocityProperty = new AppProperty("#angularVelocityHead-slider", "slider", "onAngularVelocitySlider", + "angularHeadSignal", setAngularThreshold, DEFAULT_ANGULAR_VELOCITY, function (num) { + var base = 4; + var shift = 2; + return convertExponential(base, num, DECREASING, shift); + }, function (num) { + var base = 4; + var shift = 2; + return convertLog(base, num, DECREASING, shift); + }, true); +var heightDifferenceProperty = new AppProperty("#heightDifference-slider", "slider", "onHeightDifferenceSlider", "heightSignal", + setHeightThreshold, DEFAULT_HEIGHT_DIFFERENCE, function (num) { + return convertToMeters(-num); + }, function (num) { + return convertToCentimeters(-num); + }, true); +var handsVelocityProperty = new AppProperty("#handsVelocity-slider", "slider", "onHandsVelocitySlider", "handVelocitySignal", + setHandVelocityThreshold, DEFAULT_HAND_VELOCITY, function (num) { + return num; + }, function (num) { + return num; + }, true); +var handsAngularVelocityProperty = new AppProperty("#handsAngularVelocity-slider", "slider", "onHandsAngularVelocitySlider", + "handAngularSignal", setHandAngularVelocityThreshold, DEFAULT_ANGULAR_HAND_VELOCITY, function (num) { + var base = 7; + var shift = 2; + return convertExponential(base, num, DECREASING, shift); + }, function (num) { + var base = 7; + var shift = 2; + return convertLog(base, num, DECREASING, shift); + }, true); +var headVelocityProperty = new AppProperty("#headVelocity-slider", "slider", "onHeadVelocitySlider", "headVelocitySignal", + setHeadVelocityThreshold, DEFAULT_HEAD_VELOCITY, function (num) { + var base = 2; + var shift = 0; + return convertExponential(base, num, INCREASING, shift); + }, function (num) { + var base = 2; + var shift = 0; + return convertLog(base, num, INCREASING, shift); + }, true); +var headPitchProperty = new AppProperty("#headPitch-slider", "slider", "onHeadPitchSlider", "headPitchSignal", + setHeadPitchThreshold, DEFAULT_LEVEL_PITCH, function (num) { + var base = 2.5; + var shift = 5; + return convertExponential(base, num, DECREASING, shift); + }, function (num) { + var base = 2.5; + var shift = 5; + return convertLog(base, num, DECREASING, shift); + }, true); +var headRollProperty = new AppProperty("#headRoll-slider", "slider", "onHeadRollSlider", "headRollSignal", setHeadRollThreshold, + DEFAULT_LEVEL_ROLL, function (num) { + var base = 2.5; + var shift = 5; + return convertExponential(base, num, DECREASING, shift); + }, function (num) { + var base = 2.5; + var shift = 5; + return convertLog(base, num, DECREASING, shift); + }, true); + +var propArray = new Array(frontBaseProperty, backBaseProperty, lateralBaseProperty, headAngularVelocityProperty, + heightDifferenceProperty, handsVelocityProperty, handsAngularVelocityProperty, headVelocityProperty, headPitchProperty, + headRollProperty); + +// var HTML_URL = Script.resolvePath("http://hifi-content.s3.amazonaws.com/angus/stepApp/stepApp.html"); +var HTML_URL = Script.resolvePath("http://hifi-content.s3.amazonaws.com/angus/stepApp/stepAppExtra.html"); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + +function manageClick() { + if (activated) { + tablet.gotoHomeScreen(); + } else { + tablet.gotoWebScreen(HTML_URL); + } +} + +var tabletButton = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: Script.resolvePath("http://hifi-content.s3.amazonaws.com/angus/stepApp/foot.svg"), + activeIcon: Script.resolvePath("http://hifi-content.s3.amazonaws.com/angus/stepApp/foot.svg") +}); + +function drawBase() { + // transform corners into world space, for rendering. + var worldPointLf = Vec3.sum(MyAvatar.position,Vec3.multiplyQbyV(MyAvatar.orientation, frontLeft)); + var worldPointRf = Vec3.sum(MyAvatar.position,Vec3.multiplyQbyV(MyAvatar.orientation, frontRight)); + var worldPointLb = Vec3.sum(MyAvatar.position,Vec3.multiplyQbyV(MyAvatar.orientation, backLeft)); + var worldPointRb = Vec3.sum(MyAvatar.position,Vec3.multiplyQbyV(MyAvatar.orientation, backRight)); + + var GREEN = { r: 0, g: 1, b: 0, a: 1 }; + // draw border + DebugDraw.drawRay(worldPointLf, worldPointRf, GREEN); + DebugDraw.drawRay(worldPointRf, worldPointRb, GREEN); + DebugDraw.drawRay(worldPointRb, worldPointLb, GREEN); + DebugDraw.drawRay(worldPointLb, worldPointLf, GREEN); +} + +function onKeyPress(event) { + if (event.text === "'") { + // when the sensors are reset, then reset the mode. + RESET_MODE = false; + } +} + +function onWebEventReceived(msg) { + var message = JSON.parse(msg); + print(" we have a message from html dialog " + message.type); + propArray.forEach(function (prop) { + if (prop.eventType === message.type) { + prop.setValue(prop.convertToThreshold(message.data.value)); + print("message from " + prop.name); + // break; + } + }); + checkBoxArray.forEach(function(cbox) { + if (cbox.eventType === message.type) { + cbox.data.value = message.data.value; + // break; + } + }); + if (message.type === "onCreateStepApp") { + print("document loaded"); + documentLoaded = true; + Script.setTimeout(initAppForm, LOADING_DELAY); + } +} + +function initAppForm() { + print("step app is loaded: " + documentLoaded); + if (documentLoaded === true) { + propArray.forEach(function (prop) { + tablet.emitScriptEvent(JSON.stringify({ + "type": "trigger", + "id": prop.signalType, + "data": { "value": "green" } + })); + tablet.emitScriptEvent(JSON.stringify({ + "type": "slider", + "id": prop.name, + "data": { "value": prop.convertToSlider(prop.value) } + })); + }); + checkBoxArray.forEach(function (cbox) { + tablet.emitScriptEvent(JSON.stringify({ + "type": "checkboxtick", + "id": cbox.id, + "data": { "value": cbox.data.value } + })); + }); + } +} + +function updateSignalColors() { + + // force the updates by running the threshold comparisons + withinBaseOfSupport(currentStateReadings.headPose.translation); + withinThresholdOfStandingHeightMode(currentStateReadings.diffFromMode); + headAngularVelocityBelowThreshold(currentStateReadings.headPose.angularVelocity); + handDirectionMatchesHeadDirection(currentStateReadings.lhandPose, currentStateReadings.rhandPose); + handAngularVelocityBelowThreshold(currentStateReadings.lhandPose, currentStateReadings.rhandPose); + headVelocityGreaterThanThreshold(Vec3.length(currentStateReadings.headPose.velocity)); + headMovedAwayFromAveragePosition(currentStateReadings.diffFromAveragePosition); + headLowerThanHeightAverage(currentStateReadings.diffFromAverageHeight); + isHeadLevel(currentStateReadings.diffFromAverageEulers); + + propArray.forEach(function (prop) { + if (prop.signalOn) { + tablet.emitScriptEvent(JSON.stringify({ "type": "trigger", "id": prop.signalType, "data": { "value": "green" } })); + } else { + tablet.emitScriptEvent(JSON.stringify({ "type": "trigger", "id": prop.signalType, "data": { "value": "red" } })); + } + }); +} + +function onScreenChanged(type, url) { + print("Screen changed"); + if (type === "Web" && url === HTML_URL) { + if (!activated) { + // hook up to event bridge + tablet.webEventReceived.connect(onWebEventReceived); + print("after connect web event"); + MyAvatar.hmdLeanRecenterEnabled = false; + + } + activated = true; + } else { + if (activated) { + // disconnect from event bridge + tablet.webEventReceived.disconnect(onWebEventReceived); + documentLoaded = false; + } + activated = false; + } +} + +function getLog(x, y) { + return Math.log(y) / Math.log(x); +} + +function noConversion(num) { + return num; +} + +function convertLog(base, num, direction, shift) { + return direction * getLog(base, (num + 1.0)) + shift; +} + +function convertExponential(base, num, direction, shift) { + return Math.pow(base, (direction*num + shift)) - 1.0; +} + +function convertToCentimeters(num) { + return num * CENTIMETERSPERMETER; +} + +function convertToMeters(num) { + print("convert to meters " + num); + return num / CENTIMETERSPERMETER; +} + +function isInsideLine(a, b, c) { + return (((b.x - a.x)*(c.z - a.z) - (b.z - a.z)*(c.x - a.x)) > 0); +} + +function setAngularThreshold(num) { + headAngularVelocityProperty.value = num; + print("angular threshold " + headAngularVelocityProperty.get()); +} + +function setHeadRollThreshold(num) { + headRollProperty.value = num; + print("head roll threshold " + headRollProperty.get()); +} + +function setHeadPitchThreshold(num) { + headPitchProperty.value = num; + print("head pitch threshold " + headPitchProperty.get()); +} + +function setHeightThreshold(num) { + heightDifferenceProperty.value = num; + print("height threshold " + heightDifferenceProperty.get()); +} + +function setLateralDistance(num) { + lateralBaseProperty.value = num; + frontLeft.x = -lateralBaseProperty.get(); + frontRight.x = lateralBaseProperty.get(); + backLeft.x = -lateralBaseProperty.get(); + backRight.x = lateralBaseProperty.get(); + print("lateral distance " + lateralBaseProperty.get()); +} + +function setAnteriorDistance(num) { + frontBaseProperty.value = num; + frontLeft.z = -frontBaseProperty.get(); + frontRight.z = -frontBaseProperty.get(); + print("anterior distance " + frontBaseProperty.get()); +} + +function setPosteriorDistance(num) { + backBaseProperty.value = num; + backLeft.z = backBaseProperty.get(); + backRight.z = backBaseProperty.get(); + print("posterior distance " + backBaseProperty.get()); +} + +function setHandAngularVelocityThreshold(num) { + handsAngularVelocityProperty.value = num; + print("hand angular velocity threshold " + handsAngularVelocityProperty.get()); +} + +function setHandVelocityThreshold(num) { + handsVelocityProperty.value = num; + print("hand velocity threshold " + handsVelocityProperty.get()); +} + +function setHeadVelocityThreshold(num) { + headVelocityProperty.value = num; + print("headvelocity threshold " + headVelocityProperty.get()); +} + +function withinBaseOfSupport(pos) { + var userScale = 1.0; + frontBaseProperty.signalOn = !(isInsideLine(Vec3.multiply(userScale, frontLeft), Vec3.multiply(userScale, frontRight), pos)); + backBaseProperty.signalOn = !(isInsideLine(Vec3.multiply(userScale, backRight), Vec3.multiply(userScale, backLeft), pos)); + lateralBaseProperty.signalOn = !(isInsideLine(Vec3.multiply(userScale, frontRight), Vec3.multiply(userScale, backRight), pos) + && isInsideLine(Vec3.multiply(userScale, backLeft), Vec3.multiply(userScale, frontLeft), pos)); + return (!frontBaseProperty.signalOn && !backBaseProperty.signalOn && !lateralBaseProperty.signalOn); +} + +function withinThresholdOfStandingHeightMode(heightDiff) { + if (usingModeHeight.data.value) { + heightDifferenceProperty.signalOn = heightDiff < heightDifferenceProperty.get(); + return heightDifferenceProperty.signalOn; + } else { + return true; + } +} + +function headAngularVelocityBelowThreshold(headAngularVelocity) { + var angVel = Vec3.length({ x: headAngularVelocity.x, y: 0, z: headAngularVelocity.z }); + headAngularVelocityProperty.signalOn = angVel < headAngularVelocityProperty.get(); + return headAngularVelocityProperty.signalOn; +} + +function handDirectionMatchesHeadDirection(lhPose, rhPose) { + handsVelocityProperty.signalOn = ((handsVelocityProperty.get() < NO_SHARED_DIRECTION) || + ((!lhPose.valid || ((handDotHead[LEFT] > handsVelocityProperty.get()) && + (Vec3.length(lhPose.velocity) > VELOCITY_EPSILON))) && + (!rhPose.valid || ((handDotHead[RIGHT] > handsVelocityProperty.get()) && + (Vec3.length(rhPose.velocity) > VELOCITY_EPSILON))))); + return handsVelocityProperty.signalOn; +} + +function handAngularVelocityBelowThreshold(lhPose, rhPose) { + var xzRHandAngularVelocity = Vec3.length({ x: rhPose.angularVelocity.x, y: 0.0, z: rhPose.angularVelocity.z }); + var xzLHandAngularVelocity = Vec3.length({ x: lhPose.angularVelocity.x, y: 0.0, z: lhPose.angularVelocity.z }); + handsAngularVelocityProperty.signalOn = ((!rhPose.valid ||(xzRHandAngularVelocity < handsAngularVelocityProperty.get())) + && (!lhPose.valid || (xzLHandAngularVelocity < handsAngularVelocityProperty.get()))); + return handsAngularVelocityProperty.signalOn; +} + +function headVelocityGreaterThanThreshold(headVel) { + headVelocityProperty.signalOn = (headVel > headVelocityProperty.get()) || (headVelocityProperty.get() < VELOCITY_EPSILON); + return headVelocityProperty.signalOn; +} + +function headMovedAwayFromAveragePosition(headDelta) { + return !withinBaseOfSupport(headDelta) || !usingAverageHeadPosition.data.value; +} + +function headLowerThanHeightAverage(heightDiff) { + if (usingAverageHeight.data.value) { + print("head lower than height average"); + heightDifferenceProperty.signalOn = heightDiff < heightDifferenceProperty.get(); + return heightDifferenceProperty.signalOn; + } else { + return true; + } +} + +function isHeadLevel(diffEulers) { + headRollProperty.signalOn = Math.abs(diffEulers.z) < headRollProperty.get(); + headPitchProperty.signalOn = Math.abs(diffEulers.x) < headPitchProperty.get(); + return (headRollProperty.signalOn && headPitchProperty.signalOn); +} + +function findAverage(arr) { + var sum = arr.reduce(function (acc, val) { + return acc + val; + },0); + return sum / arr.length; +} + +function addToModeArray(arr,num) { + for (var i = 0 ;i < (arr.length - 1); i++) { + arr[i] = arr[i+1]; + } + arr[arr.length - 1] = (Math.floor(num*CENTIMETERSPERMETER))/CENTIMETERSPERMETER; +} + +function findMode(ary, currentMode, backLength, defaultBack, currentHeight) { + var numMapping = {}; + var greatestFreq = 0; + var mode; + ary.forEach(function (number) { + numMapping[number] = (numMapping[number] || 0) + 1; + if ((greatestFreq < numMapping[number]) || ((numMapping[number] === MODE_SAMPLE_LENGTH) && (number > currentMode) )) { + greatestFreq = numMapping[number]; + mode = number; + } + }); + if (mode > currentMode) { + return Number(mode); + } else { + if (!RESET_MODE && HMD.active) { + print("resetting the mode............................................. "); + print("resetting the mode............................................. "); + RESET_MODE = true; + var correction = 0.02; + return currentHeight - correction; + } else { + return currentMode; + } + } +} + +function update(dt) { + if (debugDrawBase) { + drawBase(); + } + // Update current state information + currentStateReadings.headPose = Controller.getPoseValue(Controller.Standard.Head); + currentStateReadings.rhandPose = Controller.getPoseValue(Controller.Standard.RightHand); + currentStateReadings.lhandPose = Controller.getPoseValue(Controller.Standard.LeftHand); + + // back length + var headMinusHipLean = Vec3.subtract(currentStateReadings.headPose.translation, DEFAULT_HIPS_POSITION); + currentStateReadings.backLength = Vec3.length(headMinusHipLean); + // print("back length and default " + currentStateReadings.backLength + " " + DEFAULT_TORSO_LENGTH); + + // mode height + addToModeArray(modeArray, currentStateReadings.headPose.translation.y); + modeHeight = findMode(modeArray, modeHeight, currentStateReadings.backLength, DEFAULT_TORSO_LENGTH, + currentStateReadings.headPose.translation.y); + currentStateReadings.diffFromMode = modeHeight - currentStateReadings.headPose.translation.y; + + // hand direction + var leftHandLateralPoseVelocity = currentStateReadings.lhandPose.velocity; + leftHandLateralPoseVelocity.y = 0.0; + var rightHandLateralPoseVelocity = currentStateReadings.rhandPose.velocity; + rightHandLateralPoseVelocity.y = 0.0; + var headLateralPoseVelocity = currentStateReadings.headPose.velocity; + headLateralPoseVelocity.y = 0.0; + handDotHead[LEFT] = Vec3.dot(Vec3.normalize(leftHandLateralPoseVelocity), Vec3.normalize(headLateralPoseVelocity)); + handDotHead[RIGHT] = Vec3.dot(Vec3.normalize(rightHandLateralPoseVelocity), Vec3.normalize(headLateralPoseVelocity)); + + // average head position + headAveragePosition = Vec3.mix(headAveragePosition, currentStateReadings.headPose.translation, AVERAGING_RATE); + currentStateReadings.diffFromAveragePosition = Vec3.subtract(currentStateReadings.headPose.translation, + headAveragePosition); + + // average height + averageHeight = currentStateReadings.headPose.translation.y * HEIGHT_AVERAGING_RATE + + averageHeight * (1.0 - HEIGHT_AVERAGING_RATE); + currentStateReadings.diffFromAverageHeight = Math.abs(currentStateReadings.headPose.translation.y - averageHeight); + + // eulers diff + headEulers = Quat.safeEulerAngles(currentStateReadings.headPose.rotation); + headAverageOrientation = Quat.slerp(headAverageOrientation, currentStateReadings.headPose.rotation, AVERAGING_RATE); + headAverageEulers = Quat.safeEulerAngles(headAverageOrientation); + currentStateReadings.diffFromAverageEulers = Vec3.subtract(headAverageEulers, headEulers); + + // headpose rig space is for determining when to recenter rotation. + var headPoseRigSpace = Quat.multiply(CHANGE_OF_BASIS_ROTATION, currentStateReadings.headPose.rotation); + headPoseAverageOrientation = Quat.slerp(headPoseAverageOrientation, headPoseRigSpace, AVERAGING_RATE); + var headPoseAverageEulers = Quat.safeEulerAngles(headPoseAverageOrientation); + + // make the signal colors reflect the current thresholds that have been crossed + updateSignalColors(); + print("the current back length is " + currentStateReadings.backLength + " " + DEFAULT_TORSO_LENGTH); + // Conditions for taking a step. + // 1. off the base of support. front, lateral, back edges. + // 2. head is not lower than the height mode value by more than the maxHeightChange tolerance + // 3. the angular velocity of the head is not greater than the threshold value + // ie this reflects the speed the head is rotating away from having up = (0,1,0) in Avatar frame.. + // 4. the hands velocity vector has the same direction as the head, within the given tolerance + // the tolerance is an acos value, -1 means the hands going in any direction will not block translating + // up to 1 where the hands velocity direction must exactly match that of the head. -1 threshold disables this condition. + // 5. the angular velocity xz magnitude for each hand is below the threshold value + // ie here this reflects the speed that each hand is rotating away from having up = (0,1,0) in Avatar frame. + // 6. head velocity is below step threshold + // 7. head has moved further than the threshold from the running average position of the head. + // 8. head height is not lower than the running average head height with a difference of maxHeightChange. + // 9. head's rotation in avatar space is not pitching or rolling greater than the pitch or roll thresholds + if (!withinBaseOfSupport(currentStateReadings.headPose.translation) && + withinThresholdOfStandingHeightMode(currentStateReadings.diffFromMode) && + headAngularVelocityBelowThreshold(currentStateReadings.headPose.angularVelocity) && + handDirectionMatchesHeadDirection(currentStateReadings.lhandPose, currentStateReadings.rhandPose) && + handAngularVelocityBelowThreshold(currentStateReadings.lhandPose, currentStateReadings.rhandPose) && + headVelocityGreaterThanThreshold(Vec3.length(currentStateReadings.headPose.velocity)) && + headMovedAwayFromAveragePosition(currentStateReadings.diffFromAveragePosition) && + headLowerThanHeightAverage(currentStateReadings.diffFromAverageHeight) && + isHeadLevel(currentStateReadings.diffFromAverageEulers)) { + + if (stepTimer < 0.0) { //!MyAvatar.isRecenteringHorizontally() + print("trigger recenter========================================================"); + MyAvatar.triggerHorizontalRecenter(); + stepTimer = STEP_TIME_SECS; + } + } else if ((currentStateReadings.backLength > (DEFAULT_TORSO_LENGTH + SPINE_STRETCH_LIMIT)) && + (failsafeSignalTimer < 0.0) && HMD.active) { + // do the failsafe recenter. + // failsafeFlag stops repeated setting of failsafe button color. + // RESET_MODE false forces a reset of the height + RESET_MODE = false; + failsafeFlag = true; + failsafeSignalTimer = FAILSAFE_TIMEOUT; + MyAvatar.triggerHorizontalRecenter(); + tablet.emitScriptEvent(JSON.stringify({ "type": "failsafe", "id": "failsafeSignal", "data": { "value": "green" } })); + // in fail safe we debug print the values that were blocking us. + print("failsafe debug---------------------------------------------------------------"); + propArray.forEach(function (prop) { + print(prop.name); + if (!prop.signalOn) { + print(prop.signalType + " contributed to failsafe call"); + } + }); + print("end failsafe debug---------------------------------------------------------------"); + + } + + if ((failsafeSignalTimer < 0.0) && failsafeFlag) { + failsafeFlag = false; + tablet.emitScriptEvent(JSON.stringify({ "type": "failsafe", "id": "failsafeSignal", "data": { "value": "orange" } })); + } + + stepTimer -= dt; + failsafeSignalTimer -= dt; + + if (!HMD.active) { + RESET_MODE = false; + } + + if (Math.abs(headPoseAverageEulers.y) > HEAD_TURN_THRESHOLD) { + // Turn feet + // MyAvatar.triggerRotationRecenter(); + // headPoseAverageOrientation = { x: 0, y: 0, z: 0, w: 1 }; + } +} + +function shutdownTabletApp() { + // GlobalDebugger.stop(); + tablet.removeButton(tabletButton); + if (activated) { + tablet.webEventReceived.disconnect(onWebEventReceived); + tablet.gotoHomeScreen(); + } + tablet.screenChanged.disconnect(onScreenChanged); +} + +tabletButton.clicked.connect(manageClick); +tablet.screenChanged.connect(onScreenChanged); + +Script.setTimeout(function() { + DEFAULT_HIPS_POSITION = MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(MyAvatar.getJointIndex("Hips")); + DEFAULT_HEAD_POSITION = MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(MyAvatar.getJointIndex("Head")); + DEFAULT_TORSO_LENGTH = Vec3.length(Vec3.subtract(DEFAULT_HEAD_POSITION, DEFAULT_HIPS_POSITION)); +},(4*LOADING_DELAY)); + +Script.update.connect(update); +Controller.keyPressEvent.connect(onKeyPress); +Script.scriptEnding.connect(function () { + MyAvatar.hmdLeanRecenterEnabled = true; + Script.update.disconnect(update); + shutdownTabletApp(); +}); From 9f289711cee9a850b643278b2c23da76a6c36665 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 17 Aug 2018 14:33:21 -0700 Subject: [PATCH 03/45] fixing scripting window visiblity and size issues --- scripts/developer/debugging/debugWindow.js | 25 ++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/scripts/developer/debugging/debugWindow.js b/scripts/developer/debugging/debugWindow.js index 9522676007..993ca49a40 100644 --- a/scripts/developer/debugging/debugWindow.js +++ b/scripts/developer/debugging/debugWindow.js @@ -23,7 +23,7 @@ if (scripts.length >= 2) { var qml = Script.resolvePath('debugWindow.qml'); var HMD_DEBUG_WINDOW_GEOMETRY_KEY = 'hmdDebugWindowGeometry'; -var hmdDebugWindowGeometryValue = Settings.getValue(HMD_DEBUG_WINDOW_GEOMETRY_KEY) +var hmdDebugWindowGeometryValue = Settings.getValue(HMD_DEBUG_WINDOW_GEOMETRY_KEY); var windowWidth = 400; var windowHeight = 900; @@ -34,12 +34,13 @@ var windowY = 0; if (hmdDebugWindowGeometryValue !== '') { var geometry = JSON.parse(hmdDebugWindowGeometryValue); - - windowWidth = geometry.width - windowHeight = geometry.height - windowX = geometry.x - windowY = geometry.y - hasPosition = true; + if ((geometry.x !== 0) && (geometry.y !== 0)) { + windowWidth = geometry.width; + windowHeight = geometry.height; + windowX = geometry.x; + windowY = geometry.y; + hasPosition = true; + } } var window = new OverlayWindow({ @@ -52,6 +53,12 @@ if (hasPosition) { window.setPosition(windowX, windowY); } +window.visibleChanged.connect(function() { + if (!window.visible) { + window.setVisible(true); + } +}); + window.closed.connect(function () { Script.stop(); }); var getFormattedDate = function() { @@ -93,10 +100,10 @@ Script.scriptEnding.connect(function () { y: window.position.y, width: window.size.x, height: window.size.y - }) + }); Settings.setValue(HMD_DEBUG_WINDOW_GEOMETRY_KEY, geometry); window.close(); -}) +}); }()); From 2dcdd607508eaa9dd98799915102913701a54cb3 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 20 Aug 2018 17:32:52 -0700 Subject: [PATCH 04/45] added new AvatarConstants and more frequent horizontal recentering to deal with lurching walk in large tracked volumes --- interface/src/avatar/MyAvatar.cpp | 19 +++++++++++-------- libraries/shared/src/AvatarConstants.h | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index d69ba21f6d..d1147cc796 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3557,10 +3557,10 @@ static bool headAngularVelocityBelowThreshold(const controller::Pose& head) { return isBelowThreshold; } -static bool isWithinThresholdHeightMode(const controller::Pose& head,const float& newMode) { +static bool isWithinThresholdHeightMode(const controller::Pose& head, const float& newMode, const float& scale) { bool isWithinThreshold = true; if (head.isValid()) { - isWithinThreshold = (head.getTranslation().y - newMode) > DEFAULT_AVATAR_MODE_HEIGHT_STEPPING_THRESHOLD; + isWithinThreshold = (head.getTranslation().y - newMode) > DEFAULT_AVATAR_MODE_HEIGHT_STEPPING_THRESHOLD * scale; } return isWithinThreshold; } @@ -3791,8 +3791,7 @@ void MyAvatar::lateUpdatePalms() { Avatar::updatePalms(); } - -static const float FOLLOW_TIME = 0.5f; +static const float FOLLOW_TIME = 0.1f; MyAvatar::FollowHelper::FollowHelper() { deactivate(); @@ -3883,9 +3882,10 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons controller::Pose currentRightHandPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::RIGHT_HAND); bool stepDetected = false; + float myScale = myAvatar.getAvatarScale(); if (!withinBaseOfSupport(currentHeadPose) && headAngularVelocityBelowThreshold(currentHeadPose) && - isWithinThresholdHeightMode(currentHeadPose, myAvatar.getCurrentStandingHeight()) && + isWithinThresholdHeightMode(currentHeadPose, myAvatar.getCurrentStandingHeight(), myScale) && handDirectionMatchesHeadDirection(currentLeftHandPose, currentRightHandPose, currentHeadPose) && handAngularVelocityBelowThreshold(currentLeftHandPose, currentRightHandPose) && headVelocityGreaterThanThreshold(currentHeadPose) && @@ -3897,8 +3897,8 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons glm::vec3 defaultHeadPosition = myAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar.getJointIndex("Head")); glm::vec3 currentHeadPosition = currentHeadPose.getTranslation(); float anatomicalHeadToHipsDistance = glm::length(defaultHeadPosition - defaultHipsPosition); - if (!isActive(Horizontal) && - (glm::length(currentHeadPosition - defaultHipsPosition) > (anatomicalHeadToHipsDistance + DEFAULT_AVATAR_SPINE_STRETCH_LIMIT))) { + if (!isActive(Horizontal) && + (glm::length(currentHeadPosition - defaultHipsPosition) > (anatomicalHeadToHipsDistance + (DEFAULT_AVATAR_SPINE_STRETCH_LIMIT * anatomicalHeadToHipsDistance * myAvatar.getAvatarScale())))) { myAvatar.setResetMode(true); stepDetected = true; } @@ -3918,6 +3918,9 @@ bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, co void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput) { + const float VELOCITY_THRESHHOLD = 0.5f; + float currentVelocity = glm::length(myAvatar.getLocalVelocity() / myAvatar.getSensorToWorldScale()); + if (myAvatar.getHMDLeanRecenterEnabled() && qApp->getCamera().getMode() != CAMERA_MODE_MIRROR) { if (!isActive(Rotation) && (shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { @@ -3925,7 +3928,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat myAvatar.setHeadControllerFacingMovingAverage(myAvatar._headControllerFacing); } if (myAvatar.getCenterOfGravityModelEnabled()) { - if (!isActive(Horizontal) && (shouldActivateHorizontalCG(myAvatar) || hasDriveInput)) { + if ((!isActive(Horizontal) && (shouldActivateHorizontalCG(myAvatar) || hasDriveInput)) || ( isActive(Horizontal) && (currentVelocity > VELOCITY_THRESHHOLD))) { activate(Horizontal); } } else { diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index cdc571d1aa..c3e8a3f173 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -34,7 +34,7 @@ const float DEFAULT_HANDS_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 3.3f; const float DEFAULT_HEAD_VELOCITY_STEPPING_THRESHOLD = 0.18f; const float DEFAULT_HEAD_PITCH_STEPPING_TOLERANCE = 7.0f; const float DEFAULT_HEAD_ROLL_STEPPING_TOLERANCE = 7.0f; -const float DEFAULT_AVATAR_SPINE_STRETCH_LIMIT = 0.03f; +const float DEFAULT_AVATAR_SPINE_STRETCH_LIMIT = 0.04f; const float DEFAULT_AVATAR_FORWARD_DAMPENING_FACTOR = 0.5f; const float DEFAULT_AVATAR_LATERAL_DAMPENING_FACTOR = 2.0f; const float DEFAULT_AVATAR_HIPS_MASS = 40.0f; From 1e2ca579c776287652c60399ab0703539cc4a85e Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 20 Aug 2018 18:06:34 -0700 Subject: [PATCH 05/45] widened base of support and put head angular and hand angular back to normal --- libraries/shared/src/AvatarConstants.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index c3e8a3f173..4e6fa67c9f 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -24,10 +24,10 @@ const float DEFAULT_AVATAR_SUPPORT_BASE_LEFT = -0.25f; const float DEFAULT_AVATAR_SUPPORT_BASE_RIGHT = 0.25f; const float DEFAULT_AVATAR_SUPPORT_BASE_FRONT = -0.20f; const float DEFAULT_AVATAR_SUPPORT_BASE_BACK = 0.12f; -const float DEFAULT_AVATAR_LATERAL_STEPPING_THRESHOLD = 0.10f; -const float DEFAULT_AVATAR_ANTERIOR_STEPPING_THRESHOLD = 0.04f; -const float DEFAULT_AVATAR_POSTERIOR_STEPPING_THRESHOLD = 0.05f; -const float DEFAULT_AVATAR_HEAD_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 0.3f; +const float DEFAULT_AVATAR_LATERAL_STEPPING_THRESHOLD = 0.15f; +const float DEFAULT_AVATAR_ANTERIOR_STEPPING_THRESHOLD = 0.07f; +const float DEFAULT_AVATAR_POSTERIOR_STEPPING_THRESHOLD = 0.08f; +const float DEFAULT_AVATAR_HEAD_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 0.6f; const float DEFAULT_AVATAR_MODE_HEIGHT_STEPPING_THRESHOLD = -0.02f; const float DEFAULT_HANDS_VELOCITY_DIRECTION_STEPPING_THRESHOLD = 0.4f; const float DEFAULT_HANDS_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 3.3f; From 1fabc77244d2546979e0ed5d95979714b89fc481 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 21 Aug 2018 12:34:05 -0700 Subject: [PATCH 06/45] latest update to stop lurching, and allow leaning, and stop perma leans --- interface/src/avatar/MyAvatar.cpp | 9 ++++++--- libraries/shared/src/AvatarConstants.h | 8 ++++---- scripts/developer/objectOrientedStep.js | 7 ++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index d1147cc796..ba4636bfa6 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3560,7 +3560,7 @@ static bool headAngularVelocityBelowThreshold(const controller::Pose& head) { static bool isWithinThresholdHeightMode(const controller::Pose& head, const float& newMode, const float& scale) { bool isWithinThreshold = true; if (head.isValid()) { - isWithinThreshold = (head.getTranslation().y - newMode) > DEFAULT_AVATAR_MODE_HEIGHT_STEPPING_THRESHOLD * scale; + isWithinThreshold = (head.getTranslation().y - newMode) > (DEFAULT_AVATAR_MODE_HEIGHT_STEPPING_THRESHOLD * scale); } return isWithinThreshold; } @@ -3881,6 +3881,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons controller::Pose currentLeftHandPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::LEFT_HAND); controller::Pose currentRightHandPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::RIGHT_HAND); + bool stepDetected = false; float myScale = myAvatar.getAvatarScale(); if (!withinBaseOfSupport(currentHeadPose) && @@ -3898,10 +3899,12 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons glm::vec3 currentHeadPosition = currentHeadPose.getTranslation(); float anatomicalHeadToHipsDistance = glm::length(defaultHeadPosition - defaultHipsPosition); if (!isActive(Horizontal) && - (glm::length(currentHeadPosition - defaultHipsPosition) > (anatomicalHeadToHipsDistance + (DEFAULT_AVATAR_SPINE_STRETCH_LIMIT * anatomicalHeadToHipsDistance * myAvatar.getAvatarScale())))) { + (glm::length(currentHeadPosition - defaultHipsPosition) > (anatomicalHeadToHipsDistance + (DEFAULT_AVATAR_SPINE_STRETCH_LIMIT * anatomicalHeadToHipsDistance)))) { myAvatar.setResetMode(true); + qCDebug(interfaceapp) << "failsafe called, default back " << anatomicalHeadToHipsDistance << " scale " << myAvatar.getAvatarScale() << " current length " << glm::length(currentHeadPosition - defaultHipsPosition); stepDetected = true; } + qCDebug(interfaceapp) << "current head height " << currentHeadPose.getTranslation().y << " scale " << myAvatar.getAvatarScale() << " anatomical " << anatomicalHeadToHipsDistance; } return stepDetected; } @@ -3918,7 +3921,7 @@ bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, co void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput) { - const float VELOCITY_THRESHHOLD = 0.5f; + const float VELOCITY_THRESHHOLD = 1.0f; float currentVelocity = glm::length(myAvatar.getLocalVelocity() / myAvatar.getSensorToWorldScale()); if (myAvatar.getHMDLeanRecenterEnabled() && diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 4e6fa67c9f..6f807a4115 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -24,17 +24,17 @@ const float DEFAULT_AVATAR_SUPPORT_BASE_LEFT = -0.25f; const float DEFAULT_AVATAR_SUPPORT_BASE_RIGHT = 0.25f; const float DEFAULT_AVATAR_SUPPORT_BASE_FRONT = -0.20f; const float DEFAULT_AVATAR_SUPPORT_BASE_BACK = 0.12f; -const float DEFAULT_AVATAR_LATERAL_STEPPING_THRESHOLD = 0.15f; +const float DEFAULT_AVATAR_LATERAL_STEPPING_THRESHOLD = 0.10f; const float DEFAULT_AVATAR_ANTERIOR_STEPPING_THRESHOLD = 0.07f; -const float DEFAULT_AVATAR_POSTERIOR_STEPPING_THRESHOLD = 0.08f; -const float DEFAULT_AVATAR_HEAD_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 0.6f; +const float DEFAULT_AVATAR_POSTERIOR_STEPPING_THRESHOLD = 0.06f; +const float DEFAULT_AVATAR_HEAD_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 0.4f; const float DEFAULT_AVATAR_MODE_HEIGHT_STEPPING_THRESHOLD = -0.02f; const float DEFAULT_HANDS_VELOCITY_DIRECTION_STEPPING_THRESHOLD = 0.4f; const float DEFAULT_HANDS_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 3.3f; const float DEFAULT_HEAD_VELOCITY_STEPPING_THRESHOLD = 0.18f; const float DEFAULT_HEAD_PITCH_STEPPING_TOLERANCE = 7.0f; const float DEFAULT_HEAD_ROLL_STEPPING_TOLERANCE = 7.0f; -const float DEFAULT_AVATAR_SPINE_STRETCH_LIMIT = 0.04f; +const float DEFAULT_AVATAR_SPINE_STRETCH_LIMIT = 0.05f; const float DEFAULT_AVATAR_FORWARD_DAMPENING_FACTOR = 0.5f; const float DEFAULT_AVATAR_LATERAL_DAMPENING_FACTOR = 2.0f; const float DEFAULT_AVATAR_HIPS_MASS = 40.0f; diff --git a/scripts/developer/objectOrientedStep.js b/scripts/developer/objectOrientedStep.js index 4eca1fb115..a5c27e36b9 100644 --- a/scripts/developer/objectOrientedStep.js +++ b/scripts/developer/objectOrientedStep.js @@ -584,7 +584,11 @@ function update(dt) { // make the signal colors reflect the current thresholds that have been crossed updateSignalColors(); - print("the current back length is " + currentStateReadings.backLength + " " + DEFAULT_TORSO_LENGTH); + + SPINE_STRETCH_LIMIT = (0.04) * DEFAULT_TORSO_LENGTH * MyAvatar.scale; + + //print("the spine stretch limit is " + SPINE_STRETCH_LIMIT + " head avatar space is " + currentStateReadings.headPose.translation.y); + //print("the current back length is " + currentStateReadings.backLength + " " + DEFAULT_TORSO_LENGTH); // Conditions for taking a step. // 1. off the base of support. front, lateral, back edges. // 2. head is not lower than the height mode value by more than the maxHeightChange tolerance @@ -672,6 +676,7 @@ Script.setTimeout(function() { DEFAULT_HIPS_POSITION = MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(MyAvatar.getJointIndex("Hips")); DEFAULT_HEAD_POSITION = MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(MyAvatar.getJointIndex("Head")); DEFAULT_TORSO_LENGTH = Vec3.length(Vec3.subtract(DEFAULT_HEAD_POSITION, DEFAULT_HIPS_POSITION)); + SPINE_STRETCH_LIMIT = (0.04) * DEFAULT_TORSO_LENGTH * MyAvatar.scale; },(4*LOADING_DELAY)); Script.update.connect(update); From e08d8e904651afe946a6400b3027aae9c6de09b9 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 22 Aug 2018 21:03:29 +0200 Subject: [PATCH 07/45] only show InteractiveWindow on top of interface window --- libraries/ui/src/InteractiveWindow.cpp | 30 ++++++++++++++++++++++++++ libraries/ui/src/InteractiveWindow.h | 4 ++++ libraries/ui/src/MainWindow.cpp | 13 +++++++++++ libraries/ui/src/MainWindow.h | 2 ++ libraries/ui/src/OffscreenUi.cpp | 16 ++------------ 5 files changed, 51 insertions(+), 14 deletions(-) diff --git a/libraries/ui/src/InteractiveWindow.cpp b/libraries/ui/src/InteractiveWindow.cpp index 5078fcb602..b4d5a068eb 100644 --- a/libraries/ui/src/InteractiveWindow.cpp +++ b/libraries/ui/src/InteractiveWindow.cpp @@ -13,12 +13,19 @@ #include #include +#include +#include #include #include #include "OffscreenUi.h" #include "shared/QtHelpers.h" +#include "MainWindow.h" + +#ifdef Q_OS_WIN +#include +#endif static auto CONTENT_WINDOW_QML = QUrl("InteractiveWindow.qml"); @@ -87,6 +94,11 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap connect(object, SIGNAL(windowClosed()), this, SIGNAL(closed()), Qt::QueuedConnection); connect(object, SIGNAL(selfDestruct()), this, SLOT(close()), Qt::QueuedConnection); +#ifdef Q_OS_WIN + connect(object, SIGNAL(nativeWindowChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection); + connect(object, SIGNAL(interactiveWindowVisibleChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection); +#endif + QUrl sourceURL{ sourceUrl }; // If the passed URL doesn't correspond to a known scheme, assume it's a local file path if (!KNOWN_SCHEMES.contains(sourceURL.scheme(), Qt::CaseInsensitive)) { @@ -279,6 +291,24 @@ int InteractiveWindow::getPresentationMode() const { return _qmlWindow->property(PRESENTATION_MODE_PROPERTY).toInt(); } +#ifdef Q_OS_WIN +void InteractiveWindow::parentNativeWindowToMainWindow() { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "parentNativeWindowToMainWindow"); + return; + } + if (_qmlWindow.isNull()) { + return; + } + const auto nativeWindowProperty = _qmlWindow->property("nativeWindow"); + if (nativeWindowProperty.isNull() || !nativeWindowProperty.isValid()) { + return; + } + const auto nativeWindow = qvariant_cast(nativeWindowProperty); + SetWindowLongPtr((HWND)nativeWindow->winId(), GWLP_HWNDPARENT, (LONG)MainWindow::findMainWindow()->winId()); +} +#endif + void InteractiveWindow::setPresentationMode(int presentationMode) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "setPresentationMode", Q_ARG(int, presentationMode)); diff --git a/libraries/ui/src/InteractiveWindow.h b/libraries/ui/src/InteractiveWindow.h index bf832550b5..f456b32e8d 100644 --- a/libraries/ui/src/InteractiveWindow.h +++ b/libraries/ui/src/InteractiveWindow.h @@ -84,6 +84,10 @@ private: Q_INVOKABLE void setPresentationMode(int presentationMode); Q_INVOKABLE int getPresentationMode() const; +#ifdef Q_OS_WIN + Q_INVOKABLE void parentNativeWindowToMainWindow(); +#endif + public slots: /**jsdoc diff --git a/libraries/ui/src/MainWindow.cpp b/libraries/ui/src/MainWindow.cpp index f9fc71e417..1a13194974 100644 --- a/libraries/ui/src/MainWindow.cpp +++ b/libraries/ui/src/MainWindow.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "ui/Logging.h" @@ -39,6 +40,18 @@ MainWindow::~MainWindow() { qCDebug(uiLogging) << "Destroying main window"; } +QWindow* MainWindow::findMainWindow() { + auto windows = qApp->topLevelWindows(); + QWindow* result = nullptr; + for (auto window : windows) { + if (window->objectName().contains("MainWindow")) { + result = window; + break; + } + } + return result; +} + void MainWindow::restoreGeometry() { // Did not use setGeometry() on purpose, // see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application diff --git a/libraries/ui/src/MainWindow.h b/libraries/ui/src/MainWindow.h index 75421340a2..fbd48e5eb1 100644 --- a/libraries/ui/src/MainWindow.h +++ b/libraries/ui/src/MainWindow.h @@ -21,6 +21,8 @@ class MainWindow : public QMainWindow { public: explicit MainWindow(QWidget* parent = NULL); ~MainWindow(); + + static QWindow* findMainWindow(); public slots: void restoreGeometry(); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index a5ef1457db..d82cfbbf3f 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -29,6 +29,7 @@ #include "ui/Logging.h" #include +#include "MainWindow.h" /**jsdoc * @namespace OffscreenFlags @@ -649,20 +650,7 @@ public: } private: - - static QWindow* findMainWindow() { - auto windows = qApp->topLevelWindows(); - QWindow* result = nullptr; - for (auto window : windows) { - if (window->objectName().contains("MainWindow")) { - result = window; - break; - } - } - return result; - } - - QWindow* const _mainWindow { findMainWindow() }; + QWindow* const _mainWindow { MainWindow::findMainWindow() }; QWindow* _hackWindow { nullptr }; }; From efa3fa7907a1490f095cc704141fd28139da9708 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 27 Aug 2018 20:42:06 +0200 Subject: [PATCH 08/45] Don't always on top InteractiveWindows (Windows OS) --- interface/resources/qml/InteractiveWindow.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/InteractiveWindow.qml b/interface/resources/qml/InteractiveWindow.qml index 800026710d..1c41dd189b 100644 --- a/interface/resources/qml/InteractiveWindow.qml +++ b/interface/resources/qml/InteractiveWindow.qml @@ -146,7 +146,8 @@ Windows.Window { Qt.WindowCloseButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowMinimizeButtonHint; - if ((flags & Desktop.ALWAYS_ON_TOP) === Desktop.ALWAYS_ON_TOP) { + // only use the always on top feature for non Windows OS + if (Qt.platform.os !== "windows" && (flags & Desktop.ALWAYS_ON_TOP) === Desktop.ALWAYS_ON_TOP) { nativeWindowFlags |= Qt.WindowStaysOnTopHint; } nativeWindow.flags = nativeWindowFlags; From c4d43b3fbc5238ff50838faba1e02ea6d0f4df41 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 28 Aug 2018 19:43:59 +0200 Subject: [PATCH 09/45] CR fixes --- interface/resources/qml/InteractiveWindow.qml | 2 +- libraries/ui/src/MainWindow.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/InteractiveWindow.qml b/interface/resources/qml/InteractiveWindow.qml index 1c41dd189b..e8ddbf823d 100644 --- a/interface/resources/qml/InteractiveWindow.qml +++ b/interface/resources/qml/InteractiveWindow.qml @@ -147,7 +147,7 @@ Windows.Window { Qt.WindowMaximizeButtonHint | Qt.WindowMinimizeButtonHint; // only use the always on top feature for non Windows OS - if (Qt.platform.os !== "windows" && (flags & Desktop.ALWAYS_ON_TOP) === Desktop.ALWAYS_ON_TOP) { + if (Qt.platform.os !== "windows" && (flags & Desktop.ALWAYS_ON_TOP)) { nativeWindowFlags |= Qt.WindowStaysOnTopHint; } nativeWindow.flags = nativeWindowFlags; diff --git a/libraries/ui/src/MainWindow.cpp b/libraries/ui/src/MainWindow.cpp index 1a13194974..680433b2f9 100644 --- a/libraries/ui/src/MainWindow.cpp +++ b/libraries/ui/src/MainWindow.cpp @@ -43,7 +43,7 @@ MainWindow::~MainWindow() { QWindow* MainWindow::findMainWindow() { auto windows = qApp->topLevelWindows(); QWindow* result = nullptr; - for (auto window : windows) { + for (const auto& window : windows) { if (window->objectName().contains("MainWindow")) { result = window; break; From 07b24b47688763d1cab3979264713837ee54b38c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 30 Aug 2018 17:22:27 -0700 Subject: [PATCH 10/45] send kill packet to ignored node for ignorer --- assignment-client/src/avatars/AvatarMixer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index edbba20dc7..0289a8aa3f 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -654,6 +654,12 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer if (addToIgnore) { senderNode->addIgnoredNode(ignoredUUID); + + // send a reliable kill packet to remove the sending avatar for the ignored avatar + auto killPacket = NLPacket::create(PacketType::KillAvatar, NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason), true); + killPacket->write(senderNode->getUUID().toRfc4122()); + killPacket->writePrimitive(KillAvatarReason::AvatarDisconnected); + nodeList->sendPacket(std::move(killPacket), *ignoredNode); } else { senderNode->removeIgnoredNode(ignoredUUID); } From 49e48f5ea0ac96da722b1849332020117e7e3202 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 31 Aug 2018 16:00:27 -0700 Subject: [PATCH 11/45] enable workload regulation by default --- libraries/workload/src/workload/ViewTask.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index 7c1e4944f5..207bc04276 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -192,7 +192,7 @@ namespace workload { struct Data { - bool regulateViewRanges{ false }; // regulation is OFF by default + bool regulateViewRanges{ true }; // regulation is ON by default } data; struct DataExport { From fff6a10bcd4ecc7a272ec8ac481fdc6b9a3b3586 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 4 Sep 2018 10:58:40 -0700 Subject: [PATCH 12/45] Remove some debug logging from safe landing additions --- interface/src/octree/SafeLanding.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 60b660f66a..cfb0a2c753 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -75,7 +75,6 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) { if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) { // Only track entities with downloaded collision bodies. _trackedEntities.emplace(entityID, entity); - qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName(); } } } @@ -110,7 +109,6 @@ bool SafeLanding::isLoadSequenceComplete() { _initialEnd = INVALID_SEQUENCE; _entityTree = nullptr; EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority); - qCDebug(interfaceapp) << "Safe Landing: load sequence complete"; } return !_trackingEntities; From 7af69b54501f5989de5bab6d606d69021a9bdf56 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 4 Sep 2018 13:53:25 -0700 Subject: [PATCH 13/45] Check that a requested listened port is used in NodeList --- libraries/networking/src/LimitedNodeList.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index b6b2369703..db6ed15792 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -56,13 +56,20 @@ LimitedNodeList::LimitedNodeList(int socketListenPort, int dtlsListenPort) : qRegisterMetaType("ConnectionStep"); auto port = (socketListenPort != INVALID_PORT) ? socketListenPort : LIMITED_NODELIST_LOCAL_PORT.get(); _nodeSocket.bind(QHostAddress::AnyIPv4, port); - qCDebug(networking) << "NodeList socket is listening on" << _nodeSocket.localPort(); + quint16 assignedPort = _nodeSocket.localPort(); + if (socketListenPort != INVALID_PORT && socketListenPort != 0 && socketListenPort != assignedPort) { + qCCritical(networking) << "NodeList is unable to assign requested port of" << socketListenPort; + } + qCDebug(networking) << "NodeList socket is listening on" << assignedPort; if (dtlsListenPort != INVALID_PORT) { // only create the DTLS socket during constructor if a custom port is passed _dtlsSocket = new QUdpSocket(this); _dtlsSocket->bind(QHostAddress::AnyIPv4, dtlsListenPort); + if (dtlsListenPort != 0 && _dtlsSocket->localPort() != dtlsListenPort) { + qCDebug(networking) << "NodeList is unable to assign requested DTLS port of" << dtlsListenPort; + } qCDebug(networking) << "NodeList DTLS socket is listening on" << _dtlsSocket->localPort(); } From 198ec294acd8ee96596a833f64388db7535e5779 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 5 Sep 2018 20:13:48 +0200 Subject: [PATCH 14/45] restore window parent on presentationMode switch --- libraries/ui/src/InteractiveWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/ui/src/InteractiveWindow.cpp b/libraries/ui/src/InteractiveWindow.cpp index b4d5a068eb..6c7f2d503f 100644 --- a/libraries/ui/src/InteractiveWindow.cpp +++ b/libraries/ui/src/InteractiveWindow.cpp @@ -97,6 +97,7 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap #ifdef Q_OS_WIN connect(object, SIGNAL(nativeWindowChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection); connect(object, SIGNAL(interactiveWindowVisibleChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection); + connect(object, SIGNAL(presentationModeChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection); #endif QUrl sourceURL{ sourceUrl }; From b022697dfa245bcaadaf31c169b4d071d1e5fd17 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 5 Sep 2018 15:36:07 -0700 Subject: [PATCH 15/45] volume slider on users fixed --- interface/resources/qml/hifi/NameCard.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index abcceae295..dfa6555150 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -530,9 +530,7 @@ Item { maximumValue: 20.0 stepSize: 5 updateValueWhileDragging: true - Component.onCompleted: { - value = Users.getAvatarGain(uuid); - } + value: Users.getAvatarGain(uuid) onValueChanged: { updateGainFromQML(uuid, value, false); } From e8ce1526876cfbba3c883891e9aa1165ea24adb6 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Wed, 5 Sep 2018 14:46:07 -0700 Subject: [PATCH 16/45] Scale collision picks relative to parent by adding and using more specialized transform nodes. --- .../src/raypick/PickScriptingInterface.cpp | 16 ++++++++-- .../src/ui/overlays/OverlayTransformNode.cpp | 30 +++++++++++++++++++ .../src/ui/overlays/OverlayTransformNode.h | 26 ++++++++++++++++ .../avatars-renderer/AvatarTransformNode.cpp | 30 +++++++++++++++++++ .../avatars-renderer/AvatarTransformNode.h | 25 ++++++++++++++++ .../entities/src/EntityTransformNode.cpp | 30 +++++++++++++++++++ libraries/entities/src/EntityTransformNode.h | 25 ++++++++++++++++ 7 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 interface/src/ui/overlays/OverlayTransformNode.cpp create mode 100644 interface/src/ui/overlays/OverlayTransformNode.h create mode 100644 libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp create mode 100644 libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h create mode 100644 libraries/entities/src/EntityTransformNode.cpp create mode 100644 libraries/entities/src/EntityTransformNode.h diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index 6dedf3fca1..c3a783a72b 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -24,11 +24,13 @@ #include "CollisionPick.h" #include "SpatialParentFinder.h" -#include "NestableTransformNode.h" #include "PickTransformNode.h" #include "MouseTransformNode.h" #include "avatar/MyAvatarHeadTransformNode.h" #include "avatar/AvatarManager.h" +#include "avatars-renderer/AvatarTransformNode.h" +#include "ui/overlays/OverlayTransformNode.h" +#include "EntityTransformNode.h" #include @@ -375,6 +377,16 @@ std::shared_ptr PickScriptingInterface::createTransformNode(const } auto sharedNestablePointer = nestablePointer.lock(); if (success && sharedNestablePointer) { + NestableType nestableType = sharedNestablePointer->getNestableType(); + if (nestableType == NestableType::Avatar) { + return std::make_shared(std::static_pointer_cast(sharedNestablePointer), parentJointIndex); + } + if (nestableType == NestableType::Overlay) { + return std::make_shared(std::static_pointer_cast(sharedNestablePointer), parentJointIndex); + } + if (nestableType == NestableType::Entity) { + return std::make_shared(std::static_pointer_cast(sharedNestablePointer), parentJointIndex); + } return std::make_shared(nestablePointer, parentJointIndex); } } @@ -394,7 +406,7 @@ std::shared_ptr PickScriptingInterface::createTransformNode(const } else if (!joint.isNull()) { auto myAvatar = DependencyManager::get()->getMyAvatar(); int jointIndex = myAvatar->getJointIndex(joint); - return std::make_shared(myAvatar, jointIndex); + return std::make_shared(myAvatar, jointIndex); } } diff --git a/interface/src/ui/overlays/OverlayTransformNode.cpp b/interface/src/ui/overlays/OverlayTransformNode.cpp new file mode 100644 index 0000000000..64f5be932c --- /dev/null +++ b/interface/src/ui/overlays/OverlayTransformNode.cpp @@ -0,0 +1,30 @@ +// +// Created by Sabrina Shanman 9/5/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "OverlayTransformNode.h" + +OverlayTransformNode::OverlayTransformNode(std::weak_ptr overlay, int jointIndex) : + _overlay(overlay), + _jointIndex(jointIndex) +{} + +Transform OverlayTransformNode::getTransform() { + auto overlay = _overlay.lock(); + if (!overlay) { + return Transform(); + } + + bool success; + Transform jointWorldTransform = overlay->getTransform(_jointIndex, success); + if (!success) { + jointWorldTransform = Transform(); + } + + jointWorldTransform.setScale(overlay->getBounds().getScale()); + + return jointWorldTransform; +} \ No newline at end of file diff --git a/interface/src/ui/overlays/OverlayTransformNode.h b/interface/src/ui/overlays/OverlayTransformNode.h new file mode 100644 index 0000000000..79e6a37f45 --- /dev/null +++ b/interface/src/ui/overlays/OverlayTransformNode.h @@ -0,0 +1,26 @@ +// +// Created by Sabrina Shanman 9/5/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_OverlayTransformNode_h +#define hifi_OverlayTransformNode_h + +#include "NestableTransformNode.h" + +#include "Base3DOverlay.h" + +// For 3D overlays only +class OverlayTransformNode : public TransformNode { +public: + OverlayTransformNode(std::weak_ptr overlay, int jointIndex); + Transform getTransform() override; + +protected: + std::weak_ptr _overlay; + int _jointIndex; +}; + +#endif // hifi_OverlayTransformNode_h \ No newline at end of file diff --git a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp new file mode 100644 index 0000000000..2f198e8917 --- /dev/null +++ b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp @@ -0,0 +1,30 @@ +// +// Created by Sabrina Shanman 9/5/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "AvatarTransformNode.h" + +AvatarTransformNode::AvatarTransformNode(AvatarWeakPointer avatar, int jointIndex) : + _avatar(avatar), + _jointIndex(jointIndex) +{} + +Transform AvatarTransformNode::getTransform() { + auto avatar = _avatar.lock(); + if (!avatar) { + return Transform(); + } + + bool success; + Transform jointWorldTransform = avatar->getTransform(_jointIndex, success); + if (!success) { + jointWorldTransform = Transform(); + } + + jointWorldTransform.setScale(avatar->scaleForChildren()); + + return jointWorldTransform; +} \ No newline at end of file diff --git a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h new file mode 100644 index 0000000000..9036d42639 --- /dev/null +++ b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h @@ -0,0 +1,25 @@ +// +// Created by Sabrina Shanman 9/5/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_AvatarTransformNode_h +#define hifi_AvatarTransformNode_h + +#include "NestableTransformNode.h" + +#include "Avatar.h" + +class AvatarTransformNode : public TransformNode { +public: + AvatarTransformNode(AvatarWeakPointer avatar, int jointIndex); + Transform getTransform() override; + +protected: + AvatarWeakPointer _avatar; + int _jointIndex; +}; + +#endif // hifi_AvatarTransformNode_h \ No newline at end of file diff --git a/libraries/entities/src/EntityTransformNode.cpp b/libraries/entities/src/EntityTransformNode.cpp new file mode 100644 index 0000000000..42b60759db --- /dev/null +++ b/libraries/entities/src/EntityTransformNode.cpp @@ -0,0 +1,30 @@ +// +// Created by Sabrina Shanman 9/5/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "EntityTransformNode.h" + +EntityTransformNode::EntityTransformNode(EntityItemWeakPointer entity, int jointIndex) : + _entity(entity), + _jointIndex(jointIndex) +{} + +Transform EntityTransformNode::getTransform() { + auto entity = _entity.lock(); + if (!entity) { + return Transform(); + } + + bool success; + Transform jointWorldTransform = entity->getTransform(_jointIndex, success); + if (!success) { + jointWorldTransform = Transform(); + } + + jointWorldTransform.setScale(entity->getScaledDimensions()); + + return jointWorldTransform; +} \ No newline at end of file diff --git a/libraries/entities/src/EntityTransformNode.h b/libraries/entities/src/EntityTransformNode.h new file mode 100644 index 0000000000..fc5eeff652 --- /dev/null +++ b/libraries/entities/src/EntityTransformNode.h @@ -0,0 +1,25 @@ +// +// Created by Sabrina Shanman 9/5/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_EntityTransformNode_h +#define hifi_EntityTransformNode_h + +#include "NestableTransformNode.h" + +#include "EntityItem.h" + +class EntityTransformNode : public TransformNode { +public: + EntityTransformNode(EntityItemWeakPointer entity, int jointIndex); + Transform getTransform() override; + +protected: + EntityItemWeakPointer _entity; + int _jointIndex; +}; + +#endif // hifi_EntityTransformNode_h \ No newline at end of file From 84a2512f315d581edd54400ecb2cf457b69fc5b7 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Wed, 5 Sep 2018 16:50:39 -0700 Subject: [PATCH 17/45] Fix collision pick scale not being used --- interface/src/raypick/CollisionPick.cpp | 18 +++++++++--------- interface/src/raypick/CollisionPick.h | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/interface/src/raypick/CollisionPick.cpp b/interface/src/raypick/CollisionPick.cpp index 7d0276875b..d183aecfeb 100644 --- a/interface/src/raypick/CollisionPick.cpp +++ b/interface/src/raypick/CollisionPick.cpp @@ -86,23 +86,23 @@ bool CollisionPick::isLoaded() const { return !_mathPick.shouldComputeShapeInfo() || (_cachedResource && _cachedResource->isLoaded()); } -bool CollisionPick::getShapeInfoReady() { +bool CollisionPick::getShapeInfoReady(const CollisionRegion& pick) { if (_mathPick.shouldComputeShapeInfo()) { if (_cachedResource && _cachedResource->isLoaded()) { - computeShapeInfo(_mathPick, *_mathPick.shapeInfo, _cachedResource); + computeShapeInfo(pick, *_mathPick.shapeInfo, _cachedResource); _mathPick.loaded = true; } else { _mathPick.loaded = false; } } else { - computeShapeInfoDimensionsOnly(_mathPick, *_mathPick.shapeInfo, _cachedResource); + computeShapeInfoDimensionsOnly(pick, *_mathPick.shapeInfo, _cachedResource); _mathPick.loaded = true; } return _mathPick.loaded; } -void CollisionPick::computeShapeInfoDimensionsOnly(CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource) { +void CollisionPick::computeShapeInfoDimensionsOnly(const CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource) { ShapeType type = shapeInfo.getType(); glm::vec3 dimensions = pick.transform.getScale(); QString modelURL = (resource ? resource->getURL().toString() : ""); @@ -115,7 +115,7 @@ void CollisionPick::computeShapeInfoDimensionsOnly(CollisionRegion& pick, ShapeI } } -void CollisionPick::computeShapeInfo(CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource) { +void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource) { // This code was copied and modified from RenderableModelEntityItem::computeShapeInfo // TODO: Move to some shared code area (in entities-renderer? model-networking?) // after we verify this is working and do a diff comparison with RenderableModelEntityItem::computeShapeInfo @@ -393,9 +393,9 @@ PickResultPointer CollisionPick::getEntityIntersection(const CollisionRegion& pi // Cannot compute result return std::make_shared(pick.toVariantMap(), std::vector(), std::vector()); } - getShapeInfoReady(); + getShapeInfoReady(pick); - auto entityIntersections = _physicsEngine->contactTest(USER_COLLISION_MASK_ENTITIES, *pick.shapeInfo, pick.transform, USER_COLLISION_GROUP_DYNAMIC, pick.threshold); + auto entityIntersections = _physicsEngine->contactTest(USER_COLLISION_MASK_ENTITIES, *_mathPick.shapeInfo, pick.transform, USER_COLLISION_GROUP_DYNAMIC, pick.threshold); filterIntersections(entityIntersections); return std::make_shared(pick, entityIntersections, std::vector()); } @@ -409,9 +409,9 @@ PickResultPointer CollisionPick::getAvatarIntersection(const CollisionRegion& pi // Cannot compute result return std::make_shared(pick, std::vector(), std::vector()); } - getShapeInfoReady(); + getShapeInfoReady(pick); - auto avatarIntersections = _physicsEngine->contactTest(USER_COLLISION_MASK_AVATARS, *pick.shapeInfo, pick.transform, USER_COLLISION_GROUP_DYNAMIC, pick.threshold); + auto avatarIntersections = _physicsEngine->contactTest(USER_COLLISION_MASK_AVATARS, *_mathPick.shapeInfo, pick.transform, USER_COLLISION_GROUP_DYNAMIC, pick.threshold); filterIntersections(avatarIntersections); return std::make_shared(pick, std::vector(), avatarIntersections); } diff --git a/interface/src/raypick/CollisionPick.h b/interface/src/raypick/CollisionPick.h index ce8b3bd199..fe0e5a6337 100644 --- a/interface/src/raypick/CollisionPick.h +++ b/interface/src/raypick/CollisionPick.h @@ -62,9 +62,9 @@ protected: // Returns true if the resource for _mathPick.shapeInfo is loaded or if a resource is not needed. bool isLoaded() const; // Returns true if _mathPick.shapeInfo is valid. Otherwise, attempts to get the _mathPick ready for use. - bool getShapeInfoReady(); - void computeShapeInfo(CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource); - void computeShapeInfoDimensionsOnly(CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource); + bool getShapeInfoReady(const CollisionRegion& pick); + void computeShapeInfo(const CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource); + void computeShapeInfoDimensionsOnly(const CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource); void filterIntersections(std::vector& intersections) const; CollisionRegion _mathPick; From cde2dc2eaa4ffe696c80682b632617527eb1fd5c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 5 Sep 2018 17:04:05 -0700 Subject: [PATCH 18/45] please work --- libraries/render-utils/src/CauterizedModel.cpp | 4 ++-- libraries/render-utils/src/CauterizedModel.h | 2 +- libraries/render-utils/src/Model.cpp | 11 +++++++---- libraries/render-utils/src/Model.h | 7 +++++-- libraries/render-utils/src/SoftAttachmentModel.cpp | 4 ++-- libraries/render-utils/src/SoftAttachmentModel.h | 2 +- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 2754697db7..c4631c3676 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -102,7 +102,7 @@ void CauterizedModel::createRenderItemSet() { } } -void CauterizedModel::updateClusterMatrices(bool triggerBlendshapes) { +void CauterizedModel::updateClusterMatrices() { PerformanceTimer perfTimer("CauterizedModel::updateClusterMatrices"); if (!_needsUpdateClusterMatrices || !isLoaded()) { @@ -175,7 +175,7 @@ void CauterizedModel::updateClusterMatrices(bool triggerBlendshapes) { // post the blender if we're not currently waiting for one to finish auto modelBlender = DependencyManager::get(); - if (triggerBlendshapes && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { + if (_blendedVertexBuffersInitialized && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { _blendedBlendshapeCoefficients = _blendshapeCoefficients; modelBlender->noteRequiresBlend(getThisPointer()); } diff --git a/libraries/render-utils/src/CauterizedModel.h b/libraries/render-utils/src/CauterizedModel.h index 12cf921e5b..36a96fb006 100644 --- a/libraries/render-utils/src/CauterizedModel.h +++ b/libraries/render-utils/src/CauterizedModel.h @@ -33,7 +33,7 @@ public: void createRenderItemSet() override; - virtual void updateClusterMatrices(bool triggerBlendshapes = true) override; + virtual void updateClusterMatrices() override; void updateRenderItems() override; const Model::MeshState& getCauterizeMeshState(int index) const; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 8287b9cca6..ba2bd28852 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -976,7 +976,7 @@ bool Model::addToScene(const render::ScenePointer& scene, render::Transaction& transaction, render::Item::Status::Getters& statusGetters) { if (!_addedToScene && isLoaded()) { - updateClusterMatrices(false); + updateClusterMatrices(); if (_modelMeshRenderItems.empty()) { createRenderItemSet(); } @@ -1307,6 +1307,7 @@ void Blender::run() { if (mesh.blendshapes.isEmpty()) { continue; } + vertices += mesh.vertices; normalsAndTangents += mesh.normalsAndTangents; glm::vec3* meshVertices = vertices.data() + offset; @@ -1486,7 +1487,7 @@ void Model::computeMeshPartLocalBounds() { } // virtual -void Model::updateClusterMatrices(bool triggerBlendshapes) { +void Model::updateClusterMatrices() { DETAILED_PERFORMANCE_TIMER("Model::updateClusterMatrices"); if (!_needsUpdateClusterMatrices || !isLoaded()) { @@ -1515,7 +1516,7 @@ void Model::updateClusterMatrices(bool triggerBlendshapes) { // post the blender if we're not currently waiting for one to finish auto modelBlender = DependencyManager::get(); - if (triggerBlendshapes && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { + if (_blendedVertexBuffersInitialized && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { _blendedBlendshapeCoefficients = _blendshapeCoefficients; modelBlender->noteRequiresBlend(getThisPointer()); } @@ -1552,7 +1553,7 @@ void Model::setBlendedVertices(int blendNumber, const Geometry::WeakPointer& geo const auto vertexCount = mesh.vertices.size(); const auto verticesSize = vertexCount * sizeof(glm::vec3); const auto& buffer = _blendedVertexBuffers[i]; - assert(buffer); + assert(buffer && _blendedVertexBuffersInitialized); buffer->resize(mesh.vertices.size() * sizeof(glm::vec3) + mesh.normalsAndTangents.size() * sizeof(NormalType)); buffer->setSubData(0, verticesSize, (gpu::Byte*) vertices.constData() + index * sizeof(glm::vec3)); buffer->setSubData(verticesSize, mesh.normalsAndTangents.size() * sizeof(NormalType), (const gpu::Byte*) normalsAndTangents.data() + normalAndTangentIndex * sizeof(NormalType)); @@ -1565,6 +1566,7 @@ void Model::setBlendedVertices(int blendNumber, const Geometry::WeakPointer& geo void Model::deleteGeometry() { _deleteGeometryCounter++; _blendedVertexBuffers.clear(); + _blendedVertexBuffersInitialized = false; _meshStates.clear(); _rig.destroyAnimGraph(); _blendedBlendshapeCoefficients.clear(); @@ -1630,6 +1632,7 @@ void Model::initializeBlendshapes(const FBXMesh& mesh, int index) { _blendedVertexBuffers[index]->setSubData(0, verticesSize, (const gpu::Byte*) mesh.vertices.constData()); _blendedVertexBuffers[index]->setSubData(verticesSize, normalsAndTangents.size() * sizeof(NormalType), (const gpu::Byte*) normalsAndTangents.data()); mesh.normalsAndTangents = normalsAndTangents; + _blendedVertexBuffersInitialized = true; } void Model::createRenderItemSet() { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 5ab50da162..e7534f5b89 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -159,7 +159,7 @@ public: bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; } virtual void simulate(float deltaTime, bool fullUpdate = true); - virtual void updateClusterMatrices(bool triggerBlendshapes = true); + virtual void updateClusterMatrices(); /// Returns a reference to the shared geometry. const Geometry::Pointer& getGeometry() const { return _renderGeometry; } @@ -345,6 +345,8 @@ public: void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName); + bool areBlendedVertexBuffersInitialized(int index) { return _blendedVertexBuffersInitialized; } + public slots: void loadURLFinished(bool success); @@ -424,8 +426,9 @@ protected: QUrl _url; std::unordered_map _blendedVertexBuffers; + bool _blendedVertexBuffersInitialized { false }; - QVector > > _dilatedTextures; + QVector>> _dilatedTextures; QVector _blendedBlendshapeCoefficients; int _blendNumber; diff --git a/libraries/render-utils/src/SoftAttachmentModel.cpp b/libraries/render-utils/src/SoftAttachmentModel.cpp index 93ce8f595a..b9a6581f1d 100644 --- a/libraries/render-utils/src/SoftAttachmentModel.cpp +++ b/libraries/render-utils/src/SoftAttachmentModel.cpp @@ -31,7 +31,7 @@ int SoftAttachmentModel::getJointIndexOverride(int i) const { // virtual // use the _rigOverride matrices instead of the Model::_rig -void SoftAttachmentModel::updateClusterMatrices(bool triggerBlendshapes) { +void SoftAttachmentModel::updateClusterMatrices() { if (!_needsUpdateClusterMatrices) { return; } @@ -78,7 +78,7 @@ void SoftAttachmentModel::updateClusterMatrices(bool triggerBlendshapes) { // post the blender if we're not currently waiting for one to finish auto modelBlender = DependencyManager::get(); - if (triggerBlendshapes && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { + if (_blendedVertexBuffersInitialized && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { _blendedBlendshapeCoefficients = _blendshapeCoefficients; modelBlender->noteRequiresBlend(getThisPointer()); } diff --git a/libraries/render-utils/src/SoftAttachmentModel.h b/libraries/render-utils/src/SoftAttachmentModel.h index 03038c35f3..4335c1634e 100644 --- a/libraries/render-utils/src/SoftAttachmentModel.h +++ b/libraries/render-utils/src/SoftAttachmentModel.h @@ -27,7 +27,7 @@ public: ~SoftAttachmentModel(); void updateRig(float deltaTime, glm::mat4 parentTransform) override; - void updateClusterMatrices(bool triggerBlendshapes = true) override; + void updateClusterMatrices() override; protected: int getJointIndexOverride(int i) const; From 6fb335429de5b9db88c76d5d825e5d4dfb8530c6 Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 5 Sep 2018 17:55:27 -0700 Subject: [PATCH 19/45] starting to re-implement the walking state detection for smoothwalking --- interface/src/avatar/MyAvatar.cpp | 15 +++++++++++++-- interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4fa41809d0..8a29d3f9c7 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -516,6 +516,10 @@ void MyAvatar::update(float deltaTime) { head->relax(deltaTime); updateFromTrackers(deltaTime); + if (_isInWalkingState && glm::length(getControllerPoseInAvatarFrame(controller::Action::HEAD).getVelocity()) < 0.15f) { + _isInWalkingState = false; + } + // Get audio loudness data from audio input device // Also get the AudioClient so we can update the avatar bounding box data // on the AudioClient side. @@ -3912,7 +3916,7 @@ void MyAvatar::lateUpdatePalms() { Avatar::updatePalms(); } -static const float FOLLOW_TIME = 0.1f; +static const float FOLLOW_TIME = 0.5f; MyAvatar::FollowHelper::FollowHelper() { deactivate(); @@ -4002,7 +4006,8 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons controller::Pose currentLeftHandPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::LEFT_HAND); controller::Pose currentRightHandPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::RIGHT_HAND); - + qCDebug(interfaceapp) << "currentVelocity is " < 0.15f) { + myAvatar._isInWalkingState = true; + } } else { glm::vec3 defaultHipsPosition = myAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar.getJointIndex("Hips")); glm::vec3 defaultHeadPosition = myAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar.getJointIndex("Head")); @@ -4024,6 +4032,9 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons myAvatar.setResetMode(true); qCDebug(interfaceapp) << "failsafe called, default back " << anatomicalHeadToHipsDistance << " scale " << myAvatar.getAvatarScale() << " current length " << glm::length(currentHeadPosition - defaultHipsPosition); stepDetected = true; + if (glm::length(currentHeadPose.velocity) > 0.15f) { + myAvatar._isInWalkingState = true; + } } qCDebug(interfaceapp) << "current head height " << currentHeadPose.getTranslation().y << " scale " << myAvatar.getAvatarScale() << " anatomical " << anatomicalHeadToHipsDistance; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 06267b3819..aa76e29b14 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1788,6 +1788,7 @@ private: ThreadSafeValueCache _walkBackwardSpeed { DEFAULT_AVATAR_MAX_WALKING_BACKWARD_SPEED }; ThreadSafeValueCache _sprintSpeed { AVATAR_SPRINT_SPEED_SCALAR }; float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; + bool _isInWalkingState { false }; // load avatar scripts once when rig is ready bool _shouldLoadScripts { false }; From 3a3ffcc98c792736ef7bfa0495606a11e3c99f7d Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Wed, 5 Sep 2018 18:14:06 -0700 Subject: [PATCH 20/45] First pass at improving anim stats. --- interface/resources/qml/Stats.qml | 61 ++++++++++-- interface/src/ui/Stats.cpp | 92 ++++++++++++++++++- interface/src/ui/Stats.h | 25 +++-- libraries/animation/src/AnimBlendLinear.cpp | 10 +- .../animation/src/AnimBlendLinearMove.cpp | 18 +--- libraries/animation/src/AnimContext.h | 42 +++++++++ libraries/animation/src/AnimNode.cpp | 4 - libraries/animation/src/AnimNode.h | 18 +--- libraries/animation/src/AnimStateMachine.cpp | 25 +---- libraries/animation/src/AnimStateMachine.h | 1 - libraries/animation/src/AnimVariant.cpp | 41 +++++++++ libraries/animation/src/AnimVariant.h | 3 + libraries/animation/src/Rig.cpp | 2 + libraries/animation/src/Rig.h | 7 +- 14 files changed, 264 insertions(+), 85 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index d5cfcff1e2..26682d3db8 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -193,18 +193,63 @@ Item { text: "Yaw: " + root.yaw.toFixed(1) } StatText { - visible: root.animStackNames.length > 0; - text: "Anim Stack Names:" + visible: root.animAlphaValues.length > 0; + text: "Anim Alpha Values:" } ListView { width: geoCol.width - height: root.animStackNames.length * 15 - visible: root.animStackNames.length > 0; - model: root.animStackNames + height: root.animAlphaValues.length * 15 + visible: root.animAlphaValues.length > 0; + model: root.animAlphaValues delegate: StatText { - text: modelData.length > 30 - ? modelData.substring(0, 5) + "..." + modelData.substring(modelData.length - 22) - : modelData + text: { + var actualText = modelData.split("|")[1]; + if (actualText) { + if (actualText.length > 30) { + return actualText.substring(0, 5) + "..." + actualText.substring(actualText.length - 22); + } else { + return actualText; + } + } else { + return modelData; + } + } + color: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.3 * grayScale + 0.7, + 0.3 * grayScale + 0.7, + 0.3 * grayScale + 0.7, 1.0); + } + } + } + StatText { + visible: root.animVars.length > 0; + text: "AnimVars:" + } + ListView { + width: geoCol.width + height: root.animVars.length * 15 + visible: root.animVars.length > 0; + model: root.animVars + delegate: StatText { + text: { + var actualText = modelData.split("|")[1]; + if (actualText) { + if (actualText.length > 30) { + return actualText.substring(0, 5) + "..." + actualText.substring(actualText.length - 22); + } else { + return actualText; + } + } else { + return modelData; + } + } + color: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.3 * grayScale + 0.7, + 0.3 * grayScale + 0.7, + 0.3 * grayScale + 0.7, 1.0); + } } } StatText { diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 1b26c9b621..62e44645b9 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -207,13 +207,94 @@ void Stats::updateStats(bool force) { // Third column, avatar stats auto myAvatar = avatarManager->getMyAvatar(); - auto animStack = myAvatar->getSkeletonModel()->getRig().getAnimStack(); + auto debugAlphaMap = myAvatar->getSkeletonModel()->getRig().getDebugAlphaMap(); - _animStackNames.clear(); - for (auto animStackIterator = animStack.begin(); animStackIterator != animStack.end(); ++animStackIterator) { - _animStackNames << animStackIterator->first + ": " + QString::number(animStackIterator->second,'f',3); + // update animation debug alpha values + QStringList newAnimAlphaValues; + qint64 now = usecTimestampNow(); + for (auto& iter : debugAlphaMap) { + QString key = iter.first; + float alpha = std::get<0>(iter.second); + + auto prevIter = _prevDebugAlphaMap.find(key); + if (prevIter != _prevDebugAlphaMap.end()) { + float prevAlpha = std::get<0>(iter.second); + if (prevAlpha != alpha) { + // change detected: reset timer + _animAlphaValueChangedTimers[key] = now; + } + } else { + // new value: start timer + _animAlphaValueChangedTimers[key] = now; + } + + AnimNodeType type = std::get<1>(iter.second); + if (type == AnimNodeType::Clip) { + + // figure out the grayScale color of this line. + const float LIT_TIME = 2.0f; + const float FADE_OUT_TIME = 1.0f; + float grayScale = 0.0f; + float secondsElapsed = (float)(now - _animAlphaValueChangedTimers[key]) / (float)USECS_PER_SECOND; + if (secondsElapsed < LIT_TIME) { + grayScale = 1.0f; + } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { + grayScale = (LIT_TIME - (secondsElapsed - FADE_OUT_TIME)) / LIT_TIME; + } else { + grayScale = 0.0f; + } + + if (grayScale > 0.0f) { + // append grayScaleColor to start of debug string + newAnimAlphaValues << QString::number(grayScale, 'f', 2) + "|" + key + ": " + QString::number(alpha, 'f', 3); + } + } } - emit animStackNamesChanged(); + + _animAlphaValues = newAnimAlphaValues; + _prevDebugAlphaMap = debugAlphaMap; + + emit animAlphaValuesChanged(); + + // update animation anim vars + _animVarsList.clear(); + auto animVars = myAvatar->getSkeletonModel()->getRig().getAnimVars().toDebugMap(); + for (auto& iter : animVars) { + QString key = iter.first; + QString value = iter.second; + + auto prevIter = _prevAnimVars.find(key); + if (prevIter != _prevAnimVars.end()) { + QString prevValue = prevIter->second; + if (value != prevValue) { + // change detected: reset timer + _animVarChangedTimers[key] = now; + } + } else { + // new value: start timer + _animVarChangedTimers[key] = now; + } + + // figure out the grayScale color of this line. + const float LIT_TIME = 2.0f; + const float FADE_OUT_TIME = 0.5f; + float grayScale = 0.0f; + float secondsElapsed = (float)(now - _animVarChangedTimers[key]) / (float)USECS_PER_SECOND; + if (secondsElapsed < LIT_TIME) { + grayScale = 1.0f; + } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { + grayScale = (LIT_TIME - (secondsElapsed - FADE_OUT_TIME)) / LIT_TIME; + } else { + grayScale = 0.0f; + } + + if (grayScale > 0.0f) { + // append grayScaleColor to start of debug string + _animVarsList << QString::number(grayScale, 'f', 2) + "|" + key + ": " + value; + } + } + _prevAnimVars = animVars; + emit animVarsChanged(); glm::vec3 avatarPos = myAvatar->getWorldPosition(); STAT_UPDATE(position, QVector3D(avatarPos.x, avatarPos.y, avatarPos.z)); @@ -347,6 +428,7 @@ void Stats::updateStats(bool force) { } sendingModeStream << "] " << serverCount << " servers"; if (movingServerCount > 0) { + sendingModeStream << " "; } else { sendingModeStream << " "; diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index a0453a09c5..3e71c75da1 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -14,6 +14,7 @@ #include #include #include +#include #define STATS_PROPERTY(type, name, initialValue) \ Q_PROPERTY(type name READ name NOTIFY name##Changed) \ @@ -134,7 +135,6 @@ private: \ * @property {number} batchFrameTime - Read-only. * @property {number} engineFrameTime - Read-only. * @property {number} avatarSimulationTime - Read-only. - * @property {string[]} animStackNames - Read-only. * * * @property {number} x @@ -292,7 +292,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(float, batchFrameTime, 0) STATS_PROPERTY(float, engineFrameTime, 0) STATS_PROPERTY(float, avatarSimulationTime, 0) - Q_PROPERTY(QStringList animStackNames READ animStackNames NOTIFY animStackNamesChanged) + Q_PROPERTY(QStringList animAlphaValues READ animAlphaValues NOTIFY animAlphaValuesChanged) + Q_PROPERTY(QStringList animVars READ animVars NOTIFY animVarsChanged) STATS_PROPERTY(int, stylusPicksCount, 0) STATS_PROPERTY(int, rayPicksCount, 0) @@ -326,7 +327,8 @@ public: } QStringList downloadUrls () { return _downloadUrls; } - QStringList animStackNames() { return _animStackNames; } + QStringList animAlphaValues() { return _animAlphaValues; } + QStringList animVars() { return _animVarsList; } public slots: void forceUpdateStats() { updateStats(true); } @@ -1028,12 +1030,8 @@ signals: */ void avatarSimulationTimeChanged(); - /**jsdoc - * Triggered when the value of the animStackNames property changes. - * @function Stats.animStackNamesChanged - * @returns {Signal} - */ - void animStackNamesChanged(); + void animAlphaValuesChanged(); + void animVarsChanged(); /**jsdoc * Triggered when the value of the rectifiedTextureCount property changes. @@ -1336,7 +1334,14 @@ private: QString _monospaceFont; const AudioIOStats* _audioStats; QStringList _downloadUrls = QStringList(); - QStringList _animStackNames = QStringList(); + + QStringList _animAlphaValues = QStringList(); + AnimContext::DebugAlphaMap _prevDebugAlphaMap; // alpha values from previous frame + std::map _animAlphaValueChangedTimers; // last time alpha value has changed + + QStringList _animVarsList = QStringList(); + std::map _prevAnimVars; // anim vars from previous frame + std::map _animVarChangedTimers; // last time animVar value has changed. }; #endif // hifi_Stats_h diff --git a/libraries/animation/src/AnimBlendLinear.cpp b/libraries/animation/src/AnimBlendLinear.cpp index e2d79f864d..17ca88123f 100644 --- a/libraries/animation/src/AnimBlendLinear.cpp +++ b/libraries/animation/src/AnimBlendLinear.cpp @@ -27,7 +27,7 @@ AnimBlendLinear::~AnimBlendLinear() { const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) { _alpha = animVars.lookup(_alphaVar, _alpha); - float parentAlpha = _animStack[_id]; + float parentDebugAlpha = context.getDebugAlpha(_id); if (_children.size() == 0) { for (auto&& pose : _poses) { @@ -35,7 +35,7 @@ const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, con } } else if (_children.size() == 1) { _poses = _children[0]->evaluate(animVars, context, dt, triggersOut); - _animStack[_children[0]->getID()] = parentAlpha; + context.setDebugAlpha(_children[0]->getID(), parentDebugAlpha, _children[0]->getType()); } else { float clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); size_t prevPoseIndex = glm::floor(clampedAlpha); @@ -48,12 +48,12 @@ const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, con float weight2 = 0.0f; if (prevPoseIndex == nextPoseIndex) { weight2 = 1.0f; - _animStack[_children[nextPoseIndex]->getID()] = weight2 * parentAlpha; + context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); } else { weight2 = alpha; weight1 = 1.0f - weight2; - _animStack[_children[prevPoseIndex]->getID()] = weight1 * parentAlpha; - _animStack[_children[nextPoseIndex]->getID()] = weight2 * parentAlpha; + context.setDebugAlpha(_children[prevPoseIndex]->getID(), weight1 * parentDebugAlpha, _children[prevPoseIndex]->getType()); + context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); } } processOutputJoints(triggersOut); diff --git a/libraries/animation/src/AnimBlendLinearMove.cpp b/libraries/animation/src/AnimBlendLinearMove.cpp index 42098eb072..07e1c17f77 100644 --- a/libraries/animation/src/AnimBlendLinearMove.cpp +++ b/libraries/animation/src/AnimBlendLinearMove.cpp @@ -62,9 +62,7 @@ const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars, speed = animVars.lookup("moveForwardSpeed", speed); } _alpha = calculateAlpha(speed, _characteristicSpeeds); - float parentAlpha = _animStack[_id]; - - _animStack["speed"] = speed; + float parentDebugAlpha = context.getDebugAlpha(_id); if (_children.size() == 0) { for (auto&& pose : _poses) { @@ -77,7 +75,7 @@ const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars, float prevDeltaTime, nextDeltaTime; setFrameAndPhase(dt, alpha, prevPoseIndex, nextPoseIndex, &prevDeltaTime, &nextDeltaTime, triggersOut); evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, prevDeltaTime, nextDeltaTime); - _animStack[_children[0]->getID()] = parentAlpha; + context.setDebugAlpha(_children[0]->getID(), parentDebugAlpha, _children[0]->getType()); } else { auto clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); auto prevPoseIndex = glm::floor(clampedAlpha); @@ -87,17 +85,11 @@ const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars, setFrameAndPhase(dt, alpha, prevPoseIndex, nextPoseIndex, &prevDeltaTime, &nextDeltaTime, triggersOut); evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, prevDeltaTime, nextDeltaTime); - // weights are for animation stack debug purposes only. - float weight1 = 0.0f; - float weight2 = 0.0f; if (prevPoseIndex == nextPoseIndex) { - weight2 = 1.0f; - _animStack[_children[nextPoseIndex]->getID()] = weight2 * parentAlpha; + context.setDebugAlpha(_children[nextPoseIndex]->getID(), parentDebugAlpha, _children[nextPoseIndex]->getType()); } else { - weight2 = alpha; - weight1 = 1.0f - weight2; - _animStack[_children[prevPoseIndex]->getID()] = weight1 * parentAlpha; - _animStack[_children[nextPoseIndex]->getID()] = weight2 * parentAlpha; + context.setDebugAlpha(_children[prevPoseIndex]->getID(), (1.0f - alpha) * parentDebugAlpha, _children[prevPoseIndex]->getType()); + context.setDebugAlpha(_children[nextPoseIndex]->getID(), alpha * parentDebugAlpha, _children[nextPoseIndex]->getType()); } } diff --git a/libraries/animation/src/AnimContext.h b/libraries/animation/src/AnimContext.h index e8bf5c34eb..ecfb94a28e 100644 --- a/libraries/animation/src/AnimContext.h +++ b/libraries/animation/src/AnimContext.h @@ -14,8 +14,27 @@ #include #include +#include +#include +#include + +enum class AnimNodeType { + Clip = 0, + BlendLinear, + BlendLinearMove, + Overlay, + StateMachine, + Manipulator, + InverseKinematics, + DefaultPose, + TwoBoneIK, + PoleVectorConstraint, + NumTypes +}; + class AnimContext { public: + AnimContext() {} AnimContext(bool enableDebugDrawIKTargets, bool enableDebugDrawIKConstraints, bool enableDebugDrawIKChains, const glm::mat4& geometryToRigMatrix, const glm::mat4& rigToWorldMatrix); @@ -25,6 +44,26 @@ public: const glm::mat4& getGeometryToRigMatrix() const { return _geometryToRigMatrix; } const glm::mat4& getRigToWorldMatrix() const { return _rigToWorldMatrix; } + float getDebugAlpha(const QString& key) const { + auto it = _debugAlphaMap.find(key); + if (it != _debugAlphaMap.end()) { + return std::get<0>(it->second); + } else { + return 1.0f; + } + } + + using DebugAlphaMapValue = std::tuple; + using DebugAlphaMap = std::map; + + void setDebugAlpha(const QString& key, float alpha, AnimNodeType type) const { + _debugAlphaMap[key] = DebugAlphaMapValue(alpha, type); + } + + const DebugAlphaMap& getDebugAlphaMap() const { + return _debugAlphaMap; + } + protected: bool _enableDebugDrawIKTargets { false }; @@ -32,6 +71,9 @@ protected: bool _enableDebugDrawIKChains { false }; glm::mat4 _geometryToRigMatrix; glm::mat4 _rigToWorldMatrix; + + // used for debugging internal state of animation system. + mutable DebugAlphaMap _debugAlphaMap; }; #endif // hifi_AnimContext_h diff --git a/libraries/animation/src/AnimNode.cpp b/libraries/animation/src/AnimNode.cpp index a8e76617ae..f055e6b473 100644 --- a/libraries/animation/src/AnimNode.cpp +++ b/libraries/animation/src/AnimNode.cpp @@ -12,10 +12,6 @@ #include -std::map AnimNode::_animStack = { - {"none", 0.0f} -}; - AnimNode::Pointer AnimNode::getParent() { return _parent.lock(); } diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index 1f14889ce4..1a12bb8ddb 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -36,19 +36,7 @@ class QJsonObject; class AnimNode : public std::enable_shared_from_this { public: - enum class Type { - Clip = 0, - BlendLinear, - BlendLinearMove, - Overlay, - StateMachine, - Manipulator, - InverseKinematics, - DefaultPose, - TwoBoneIK, - PoleVectorConstraint, - NumTypes - }; + using Type = AnimNodeType; using Pointer = std::shared_ptr; using ConstPointer = std::shared_ptr; @@ -84,7 +72,6 @@ public: } void setCurrentFrame(float frame); - const std::map getAnimStack() { return _animStack; } template bool traverse(F func) { @@ -127,9 +114,6 @@ protected: std::weak_ptr _parent; std::vector _outputJointNames; - // global available to Stats.h - static std::map _animStack; - // no copies AnimNode(const AnimNode&) = delete; AnimNode& operator=(const AnimNode&) = delete; diff --git a/libraries/animation/src/AnimStateMachine.cpp b/libraries/animation/src/AnimStateMachine.cpp index 90fd425ae5..00ae5e6d39 100644 --- a/libraries/animation/src/AnimStateMachine.cpp +++ b/libraries/animation/src/AnimStateMachine.cpp @@ -23,9 +23,7 @@ AnimStateMachine::~AnimStateMachine() { const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) { - if (_id.contains("userAnimStateMachine")) { - _animStack.clear(); - } + float parentDebugAlpha = context.getDebugAlpha(_id); QString desiredStateID = animVars.lookup(_currentStateVar, _currentState->getID()); if (_currentState->getID() != desiredStateID) { @@ -33,8 +31,6 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co bool foundState = false; for (auto& state : _states) { if (state->getID() == desiredStateID) { - // parenthesis means previous state, which is a snapshot. - _previousStateID = "(" + _currentState->getID() + ")"; switchState(animVars, context, state); foundState = true; break; @@ -48,8 +44,6 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co // evaluate currentState transitions auto desiredState = evaluateTransitions(animVars); if (desiredState != _currentState) { - // parenthesis means previous state, which is a snapshot. - _previousStateID = "(" + _currentState->getID() + ")"; switchState(animVars, context, desiredState); } @@ -57,17 +51,8 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co auto currentStateNode = _children[_currentState->getChildIndex()]; assert(currentStateNode); - if (!_previousStateID.contains("none")) { - _animStack[_previousStateID] = 1.0f - _alpha; - } - if (_duringInterp) { _alpha += _alphaVel * dt; - if (_alpha > 1.0f) { - _animStack[_currentState->getID()] = 1.0f; - } else { - _animStack[_currentState->getID()] = _alpha; - } if (_alpha < 1.0f) { AnimPoseVec* nextPoses = nullptr; AnimPoseVec* prevPoses = nullptr; @@ -88,18 +73,16 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co if (_poses.size() > 0 && nextPoses && prevPoses && nextPoses->size() > 0 && prevPoses->size() > 0) { ::blend(_poses.size(), &(prevPoses->at(0)), &(nextPoses->at(0)), _alpha, &_poses[0]); } + context.setDebugAlpha(_currentState->getID(), _alpha * parentDebugAlpha, _children[_currentState->getChildIndex()]->getType()); } else { _duringInterp = false; - if (_animStack.count(_previousStateID) > 0) { - _animStack.erase(_previousStateID); - } - _previousStateID = "none"; _prevPoses.clear(); _nextPoses.clear(); } } + if (!_duringInterp) { - _animStack[_currentState->getID()] = 1.0f; + context.setDebugAlpha(_currentState->getID(), parentDebugAlpha, _children[_currentState->getChildIndex()]->getType()); _poses = currentStateNode->evaluate(animVars, context, dt, triggersOut); } processOutputJoints(triggersOut); diff --git a/libraries/animation/src/AnimStateMachine.h b/libraries/animation/src/AnimStateMachine.h index b20e5203a1..8e1e1b7bd8 100644 --- a/libraries/animation/src/AnimStateMachine.h +++ b/libraries/animation/src/AnimStateMachine.h @@ -138,7 +138,6 @@ protected: float _alpha = 0.0f; AnimPoseVec _prevPoses; AnimPoseVec _nextPoses; - QString _previousStateID { "none" }; State::Pointer _currentState; std::vector _states; diff --git a/libraries/animation/src/AnimVariant.cpp b/libraries/animation/src/AnimVariant.cpp index 483a7999c9..509462984a 100644 --- a/libraries/animation/src/AnimVariant.cpp +++ b/libraries/animation/src/AnimVariant.cpp @@ -67,6 +67,7 @@ QScriptValue AnimVariantMap::animVariantMapToScriptValue(QScriptEngine* engine, } return target; } + void AnimVariantMap::copyVariantsFrom(const AnimVariantMap& other) { for (auto& pair : other._map) { _map[pair.first] = pair.second; @@ -124,3 +125,43 @@ void AnimVariantMap::animVariantMapFromScriptValue(const QScriptValue& source) { } } } + +std::map AnimVariantMap::toDebugMap() const { + std::map result; + for (auto& pair : _map) { + switch (pair.second.getType()) { + case AnimVariant::Type::Bool: + result[pair.first] = QString("%1").arg(pair.second.getBool()); + break; + case AnimVariant::Type::Int: + result[pair.first] = QString("%1").arg(pair.second.getInt()); + break; + case AnimVariant::Type::Float: + result[pair.first] = QString::number(pair.second.getFloat(), 'f', 3); + break; + case AnimVariant::Type::Vec3: { + glm::vec3 value = pair.second.getVec3(); + result[pair.first] = QString("(%1, %2, %3)"). + arg(QString::number(value.x, 'f', 3)). + arg(QString::number(value.y, 'f', 3)). + arg(QString::number(value.z, 'f', 3)); + break; + } + case AnimVariant::Type::Quat: { + glm::quat value = pair.second.getQuat(); + result[pair.first] = QString("(%1, %2, %3, %4)"). + arg(QString::number(value.x, 'f', 3)). + arg(QString::number(value.y, 'f', 3)). + arg(QString::number(value.z, 'f', 3)). + arg(QString::number(value.w, 'f', 3)); + break; + } + case AnimVariant::Type::String: + result[pair.first] = pair.second.getString(); + break; + default: + assert(("invalid AnimVariant::Type", false)); + } + } + return result; +} diff --git a/libraries/animation/src/AnimVariant.h b/libraries/animation/src/AnimVariant.h index d383b5abb8..0f921984b1 100644 --- a/libraries/animation/src/AnimVariant.h +++ b/libraries/animation/src/AnimVariant.h @@ -235,6 +235,9 @@ public: void animVariantMapFromScriptValue(const QScriptValue& object); void copyVariantsFrom(const AnimVariantMap& other); + // For stat debugging. + std::map toDebugMap() const; + #ifdef NDEBUG void dump() const { qCDebug(animation) << "AnimVariantMap ="; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 13cf165dac..91d4e0f9d3 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1061,8 +1061,10 @@ void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, cons // animations haven't fully loaded yet. _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); } + _lastAnimVars = _animVars; _animVars.clearTriggers(); _animVars = triggersOut; + _lastContext = context; } applyOverridePoses(); buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index accbcccbbc..95a4b6f40d 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -222,7 +222,9 @@ public: // input assumed to be in rig space void computeHeadFromHMD(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut) const; - const std::map getAnimStack() { return _animNode->getAnimStack(); } + // used to debug animation playback + const AnimContext::DebugAlphaMap& getDebugAlphaMap() const { return _lastContext.getDebugAlphaMap(); } + const AnimVariantMap& getAnimVars() const { return _lastAnimVars; } void toggleSmoothPoleVectors() { _smoothPoleVectors = !_smoothPoleVectors; }; signals: @@ -388,6 +390,9 @@ protected: int _rigId; bool _headEnabled { false }; + + AnimContext _lastContext; + AnimVariantMap _lastAnimVars; }; #endif /* defined(__hifi__Rig__) */ From 69ae04ab095f6619ed65d4c6ac2a1b73923c7766 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Sep 2018 09:03:28 -0700 Subject: [PATCH 21/45] protect Base3DOverlay::_name with a mutex --- interface/src/ui/overlays/Base3DOverlay.cpp | 20 ++++++++++++++++++-- interface/src/ui/overlays/Base3DOverlay.h | 5 +++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 6bce9d9283..767afca3e7 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -238,7 +238,9 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) { */ QVariant Base3DOverlay::getProperty(const QString& property) { if (property == "name") { - return _name; + return _nameLock.resultWithReadLock([&] { + return _name; + } } if (property == "position" || property == "start" || property == "p1" || property == "point") { return vec3toVariant(getWorldPosition()); @@ -346,6 +348,20 @@ void Base3DOverlay::setVisible(bool visible) { notifyRenderVariableChange(); } +QString Base3DOverlay::getName() const { + return _nameLock.resultWithReadLock([&] { + return QString("Overlay:") + _name; + } +} + +void Base3DOverlay::setName(QString name) { + _nameLock.withWriteLock([&] { + _name = name; + }); +} + + + render::ItemKey Base3DOverlay::getKey() { auto builder = render::ItemKey::Builder(Overlay::getKey()); @@ -364,4 +380,4 @@ render::ItemKey Base3DOverlay::getKey() { } return builder.build(); -} \ No newline at end of file +} diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index d44c193055..6f6092a42e 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -29,8 +29,8 @@ public: virtual OverlayID getOverlayID() const override { return OverlayID(getID().toString()); } void setOverlayID(OverlayID overlayID) override { setID(overlayID); } - virtual QString getName() const override { return QString("Overlay:") + _name; } - void setName(QString name) { _name = name; } + virtual QString getName() const override; + void setName(QString name); // getters virtual bool is3D() const override { return true; } @@ -107,6 +107,7 @@ protected: mutable bool _renderVariableDirty { true }; QString _name; + mutable ReadWriteLockable _nameLock; }; #endif // hifi_Base3DOverlay_h From 5a0a259c214b4a3a4fc7dc2467f3b7d3a1935159 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Sep 2018 09:37:01 -0700 Subject: [PATCH 22/45] dammit --- interface/src/ui/overlays/Base3DOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 767afca3e7..89e6fac3dc 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -240,7 +240,7 @@ QVariant Base3DOverlay::getProperty(const QString& property) { if (property == "name") { return _nameLock.resultWithReadLock([&] { return _name; - } + }); } if (property == "position" || property == "start" || property == "p1" || property == "point") { return vec3toVariant(getWorldPosition()); From 042044ceaf061aa9c4b6d7f1eed4965718f36ae3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Sep 2018 09:38:12 -0700 Subject: [PATCH 23/45] dammit --- interface/src/ui/overlays/Base3DOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 89e6fac3dc..1d8db69e26 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -351,7 +351,7 @@ void Base3DOverlay::setVisible(bool visible) { QString Base3DOverlay::getName() const { return _nameLock.resultWithReadLock([&] { return QString("Overlay:") + _name; - } + }); } void Base3DOverlay::setName(QString name) { From f7226757ad0d901adf02859e20025b616dd4b058 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 10:03:05 -0700 Subject: [PATCH 24/45] Just import TransformNode in AvatarTransformNode.h and similar --- interface/src/ui/overlays/OverlayTransformNode.h | 2 +- .../avatars-renderer/src/avatars-renderer/AvatarTransformNode.h | 2 +- libraries/entities/src/EntityTransformNode.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/overlays/OverlayTransformNode.h b/interface/src/ui/overlays/OverlayTransformNode.h index 79e6a37f45..b9ea9f72c4 100644 --- a/interface/src/ui/overlays/OverlayTransformNode.h +++ b/interface/src/ui/overlays/OverlayTransformNode.h @@ -8,7 +8,7 @@ #ifndef hifi_OverlayTransformNode_h #define hifi_OverlayTransformNode_h -#include "NestableTransformNode.h" +#include "TransformNode.h" #include "Base3DOverlay.h" diff --git a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h index 9036d42639..03191b8dbe 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h +++ b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h @@ -8,7 +8,7 @@ #ifndef hifi_AvatarTransformNode_h #define hifi_AvatarTransformNode_h -#include "NestableTransformNode.h" +#include "TransformNode.h" #include "Avatar.h" diff --git a/libraries/entities/src/EntityTransformNode.h b/libraries/entities/src/EntityTransformNode.h index fc5eeff652..b7388600df 100644 --- a/libraries/entities/src/EntityTransformNode.h +++ b/libraries/entities/src/EntityTransformNode.h @@ -8,7 +8,7 @@ #ifndef hifi_EntityTransformNode_h #define hifi_EntityTransformNode_h -#include "NestableTransformNode.h" +#include "TransformNode.h" #include "EntityItem.h" From 390e89a64ddfa8cecead7f1b2e3403d80e63939b Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 10:20:26 -0700 Subject: [PATCH 25/45] Fix missing NestableTransformNode import --- interface/src/raypick/PickScriptingInterface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index c3a783a72b..41dd3bb6de 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -28,6 +28,7 @@ #include "MouseTransformNode.h" #include "avatar/MyAvatarHeadTransformNode.h" #include "avatar/AvatarManager.h" +#include "NestableTransformNode.h" #include "avatars-renderer/AvatarTransformNode.h" #include "ui/overlays/OverlayTransformNode.h" #include "EntityTransformNode.h" From e8ea95e3758ec5893100d49eae30549d94dbb6c5 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 10:21:48 -0700 Subject: [PATCH 26/45] Use elseifs in PickScriptingInterface::createTransformNode --- interface/src/raypick/PickScriptingInterface.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index 41dd3bb6de..6b8a2d0d7a 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -381,14 +381,13 @@ std::shared_ptr PickScriptingInterface::createTransformNode(const NestableType nestableType = sharedNestablePointer->getNestableType(); if (nestableType == NestableType::Avatar) { return std::make_shared(std::static_pointer_cast(sharedNestablePointer), parentJointIndex); - } - if (nestableType == NestableType::Overlay) { + } else if (nestableType == NestableType::Overlay) { return std::make_shared(std::static_pointer_cast(sharedNestablePointer), parentJointIndex); - } - if (nestableType == NestableType::Entity) { + } else if (nestableType == NestableType::Entity) { return std::make_shared(std::static_pointer_cast(sharedNestablePointer), parentJointIndex); + } else { + return std::make_shared(nestablePointer, parentJointIndex); } - return std::make_shared(nestablePointer, parentJointIndex); } } From 3f7a7fb11ab1bf4877f59e93381a3df8bbf0dc56 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 10:29:01 -0700 Subject: [PATCH 27/45] Return early from AvatarTransformNode and similar when getTransform fails --- interface/src/ui/overlays/OverlayTransformNode.cpp | 2 +- .../src/avatars-renderer/AvatarTransformNode.cpp | 2 +- libraries/entities/src/EntityTransformNode.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/overlays/OverlayTransformNode.cpp b/interface/src/ui/overlays/OverlayTransformNode.cpp index 64f5be932c..d0a6618e37 100644 --- a/interface/src/ui/overlays/OverlayTransformNode.cpp +++ b/interface/src/ui/overlays/OverlayTransformNode.cpp @@ -21,7 +21,7 @@ Transform OverlayTransformNode::getTransform() { bool success; Transform jointWorldTransform = overlay->getTransform(_jointIndex, success); if (!success) { - jointWorldTransform = Transform(); + return Transform(); } jointWorldTransform.setScale(overlay->getBounds().getScale()); diff --git a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp index 2f198e8917..fc5ba5bc1a 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp @@ -21,7 +21,7 @@ Transform AvatarTransformNode::getTransform() { bool success; Transform jointWorldTransform = avatar->getTransform(_jointIndex, success); if (!success) { - jointWorldTransform = Transform(); + return Transform(); } jointWorldTransform.setScale(avatar->scaleForChildren()); diff --git a/libraries/entities/src/EntityTransformNode.cpp b/libraries/entities/src/EntityTransformNode.cpp index 42b60759db..5b0a690619 100644 --- a/libraries/entities/src/EntityTransformNode.cpp +++ b/libraries/entities/src/EntityTransformNode.cpp @@ -21,7 +21,7 @@ Transform EntityTransformNode::getTransform() { bool success; Transform jointWorldTransform = entity->getTransform(_jointIndex, success); if (!success) { - jointWorldTransform = Transform(); + return Transform(); } jointWorldTransform.setScale(entity->getScaledDimensions()); From 7839ba42db01d7b5b755a961830530f731602148 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 10:37:48 -0700 Subject: [PATCH 28/45] Make the Collision Pick threshold scale with the largest dimension of the parent --- interface/src/raypick/CollisionPick.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/raypick/CollisionPick.cpp b/interface/src/raypick/CollisionPick.cpp index d183aecfeb..c21ee69b74 100644 --- a/interface/src/raypick/CollisionPick.cpp +++ b/interface/src/raypick/CollisionPick.cpp @@ -357,12 +357,14 @@ CollisionPick::CollisionPick(const PickFilter& filter, float maxDistance, bool e CollisionRegion CollisionPick::getMathematicalPick() const { CollisionRegion mathPick = _mathPick; mathPick.loaded = isLoaded(); - if (!parentTransform) { - return mathPick; - } else { - mathPick.transform = parentTransform->getTransform().worldTransform(mathPick.transform); - return mathPick; + if (parentTransform) { + Transform parentTransformValue = parentTransform->getTransform(); + mathPick.transform = parentTransformValue.worldTransform(mathPick.transform); + glm::vec3 scale = parentTransformValue.getScale(); + float largestDimension = glm::max(glm::max(scale.x, scale.y), scale.z); + mathPick.threshold *= largestDimension; } + return mathPick; } void CollisionPick::filterIntersections(std::vector& intersections) const { From 727b62144fb939501af03a4034850f4474f9a222 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 12:03:13 -0700 Subject: [PATCH 29/45] Fix MyAvatarHeadTransformNode not using avatar scale --- interface/src/avatar/MyAvatarHeadTransformNode.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatarHeadTransformNode.cpp b/interface/src/avatar/MyAvatarHeadTransformNode.cpp index 9c202ba94a..1e83a17dd3 100644 --- a/interface/src/avatar/MyAvatarHeadTransformNode.cpp +++ b/interface/src/avatar/MyAvatarHeadTransformNode.cpp @@ -16,8 +16,9 @@ Transform MyAvatarHeadTransformNode::getTransform() { auto myAvatar = DependencyManager::get()->getMyAvatar(); glm::vec3 pos = myAvatar->getHeadPosition(); + glm::vec3 scale = glm::vec3(myAvatar->scaleForChildren()); glm::quat headOri = myAvatar->getHeadOrientation(); glm::quat ori = headOri * glm::angleAxis(-PI / 2.0f, Vectors::RIGHT); - return Transform(ori, glm::vec3(1.0f), pos); + return Transform(ori, scale, pos); } \ No newline at end of file From 714cfc5ef12f0cac1966306f0ec047edcf800f4b Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 12:08:27 -0700 Subject: [PATCH 30/45] Add scaling information to CollisionRegion jsdoc and missing info to CollisionPickProperties jsdoc --- interface/src/raypick/PickScriptingInterface.cpp | 13 ++++++++++--- libraries/shared/src/RegisteredMetaTypes.h | 5 +++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index 6b8a2d0d7a..b892c6da8e 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -263,9 +263,16 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti * A set of properties that can be passed to {@link Picks.createPick} to create a new Collision Pick. * @typedef {object} Picks.CollisionPickProperties -* @property {Shape} shape - The information about the collision region's size and shape. -* @property {Vec3} position - The position of the collision region. -* @property {Quat} orientation - The orientation of the collision region. +* @property {boolean} [enabled=false] If this Pick should start enabled or not. Disabled Picks do not updated their pick results. +* @property {number} [filter=Picks.PICK_NOTHING] The filter for this Pick to use, constructed using filter flags combined using bitwise OR. +* @property {Shape} shape - The information about the collision region's size and shape. Dimensions are relative to a parent if defined. +* @property {Vec3} position - The position of the collision region, relative to a parent if defined. +* @property {Quat} orientation - The orientation of the collision region, relative to a parent if defined. +* @property {float} threshold - The approximate minimum penetration depth for a test object to be considered in contact with the collision region, relative to a parent if defined. +* For overlay and entity parents, this is relative to the parent's largest dimension. +* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or an overlay. +* @property {number} parentJointIndex - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint) +* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar. */ unsigned int PickScriptingInterface::createCollisionPick(const QVariant& properties) { QVariantMap propMap = properties.toMap(); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 02f5fa570c..79adce0a39 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -259,10 +259,11 @@ public: * A CollisionRegion defines a volume for checking collisions in the physics simulation. * @typedef {object} CollisionRegion -* @property {Shape} shape - The information about the collision region's size and shape. +* @property {Shape} shape - The information about the collision region's size and shape. Dimensions are relative to a parent if defined. * @property {Vec3} position - The position of the collision region, relative to a parent if defined. * @property {Quat} orientation - The orientation of the collision region, relative to a parent if defined. -* @property {float} threshold - The approximate minimum penetration depth for a test object to be considered in contact with the collision region. +* @property {float} threshold - The approximate minimum penetration depth for a test object to be considered in contact with the collision region, relative to a parent if defined. +* For overlay and entity parents, this is relative to the parent's largest dimension. * @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or an overlay. * @property {number} parentJointIndex - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint) * @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar. From 90a51e618134faf605074afb2785d0962dfa4121 Mon Sep 17 00:00:00 2001 From: amantley Date: Thu, 6 Sep 2018 13:12:48 -0700 Subject: [PATCH 31/45] added walk velocity threshold, this determines if we are in the walk state. when we are then we don't do cg leaning calculation. this will smooth out the walking in a large tracked area --- interface/src/avatar/MyAvatar.cpp | 59 +++++++++++++----------- interface/src/avatar/MyAvatar.h | 2 + interface/src/avatar/MySkeletonModel.cpp | 2 +- libraries/shared/src/AvatarConstants.h | 7 +-- 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8a29d3f9c7..c8af792d8f 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -516,8 +516,8 @@ void MyAvatar::update(float deltaTime) { head->relax(deltaTime); updateFromTrackers(deltaTime); - if (_isInWalkingState && glm::length(getControllerPoseInAvatarFrame(controller::Action::HEAD).getVelocity()) < 0.15f) { - _isInWalkingState = false; + if (getIsInWalkingState() && glm::length(getControllerPoseInAvatarFrame(controller::Action::HEAD).getVelocity()) < DEFAULT_AVATAR_WALK_SPEED_THRESHOLD) { + setIsInWalkingState(false); } // Get audio loudness data from audio input device @@ -3806,6 +3806,10 @@ float MyAvatar::getUserEyeHeight() const { return userHeight - userHeight * ratio; } +bool MyAvatar::getIsInWalkingState() const { + return _isInWalkingState; +} + float MyAvatar::getWalkSpeed() const { return _walkSpeed.get() * _walkSpeedScalar; } @@ -3822,6 +3826,10 @@ void MyAvatar::setSprintMode(bool sprint) { _walkSpeedScalar = sprint ? _sprintSpeed.get() : AVATAR_WALK_SPEED_SCALAR; } +void MyAvatar::setIsInWalkingState(bool isWalking) { + _isInWalkingState = isWalking; +} + void MyAvatar::setWalkSpeed(float value) { _walkSpeed.set(value); } @@ -4006,37 +4014,38 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontalCG(MyAvatar& myAvatar) cons controller::Pose currentLeftHandPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::LEFT_HAND); controller::Pose currentRightHandPose = myAvatar.getControllerPoseInAvatarFrame(controller::Action::RIGHT_HAND); - qCDebug(interfaceapp) << "currentVelocity is " < 0.15f) { - myAvatar._isInWalkingState = true; - } - } else { - glm::vec3 defaultHipsPosition = myAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar.getJointIndex("Hips")); - glm::vec3 defaultHeadPosition = myAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar.getJointIndex("Head")); - glm::vec3 currentHeadPosition = currentHeadPose.getTranslation(); - float anatomicalHeadToHipsDistance = glm::length(defaultHeadPosition - defaultHipsPosition); - if (!isActive(Horizontal) && - (glm::length(currentHeadPosition - defaultHipsPosition) > (anatomicalHeadToHipsDistance + (DEFAULT_AVATAR_SPINE_STRETCH_LIMIT * anatomicalHeadToHipsDistance)))) { - myAvatar.setResetMode(true); - qCDebug(interfaceapp) << "failsafe called, default back " << anatomicalHeadToHipsDistance << " scale " << myAvatar.getAvatarScale() << " current length " << glm::length(currentHeadPosition - defaultHipsPosition); + // a step is detected stepDetected = true; - if (glm::length(currentHeadPose.velocity) > 0.15f) { - myAvatar._isInWalkingState = true; + if (glm::length(currentHeadPose.velocity) > DEFAULT_AVATAR_WALK_SPEED_THRESHOLD) { + myAvatar.setIsInWalkingState(true); + } + } else { + glm::vec3 defaultHipsPosition = myAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar.getJointIndex("Hips")); + glm::vec3 defaultHeadPosition = myAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar.getJointIndex("Head")); + glm::vec3 currentHeadPosition = currentHeadPose.getTranslation(); + float anatomicalHeadToHipsDistance = glm::length(defaultHeadPosition - defaultHipsPosition); + if (!isActive(Horizontal) && + (glm::length(currentHeadPosition - defaultHipsPosition) > (anatomicalHeadToHipsDistance + (DEFAULT_AVATAR_SPINE_STRETCH_LIMIT * anatomicalHeadToHipsDistance)))) { + myAvatar.setResetMode(true); + stepDetected = true; + if (glm::length(currentHeadPose.velocity) > DEFAULT_AVATAR_WALK_SPEED_THRESHOLD) { + myAvatar.setIsInWalkingState(true); + } } } - qCDebug(interfaceapp) << "current head height " << currentHeadPose.getTranslation().y << " scale " << myAvatar.getAvatarScale() << " anatomical " << anatomicalHeadToHipsDistance; } return stepDetected; } @@ -4053,9 +4062,6 @@ bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, co void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput) { - const float VELOCITY_THRESHHOLD = 1.0f; - float currentVelocity = glm::length(myAvatar.getLocalVelocity() / myAvatar.getSensorToWorldScale()); - if (myAvatar.getHMDLeanRecenterEnabled() && qApp->getCamera().getMode() != CAMERA_MODE_MIRROR) { if (!isActive(Rotation) && (shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { @@ -4063,7 +4069,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat myAvatar.setHeadControllerFacingMovingAverage(myAvatar.getHeadControllerFacing()); } if (myAvatar.getCenterOfGravityModelEnabled()) { - if ((!isActive(Horizontal) && (shouldActivateHorizontalCG(myAvatar) || hasDriveInput)) || ( isActive(Horizontal) && (currentVelocity > VELOCITY_THRESHHOLD))) { + if (!isActive(Horizontal) && (shouldActivateHorizontalCG(myAvatar) || hasDriveInput)) { activate(Horizontal); if (myAvatar.getEnableStepResetRotation()) { activate(Rotation); @@ -4089,7 +4095,6 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat setForceActivateRotation(false); } if (!isActive(Horizontal) && getForceActivateHorizontal()) { - qCDebug(interfaceapp) << "called the recentering from script"; activate(Horizontal); setForceActivateHorizontal(false); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index aa76e29b14..5008190c33 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1086,6 +1086,8 @@ public: const QUuid& getSelfID() const { return AVATAR_SELF_ID; } + void setIsInWalkingState(bool isWalking); + bool getIsInWalkingState() const; void setWalkSpeed(float value); float getWalkSpeed() const; void setWalkBackwardSpeed(float value); diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 77d1a87195..3084542472 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -46,7 +46,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) { } glm::mat4 hipsMat; - if (myAvatar->getCenterOfGravityModelEnabled() && !isFlying) { + if (myAvatar->getCenterOfGravityModelEnabled() && !isFlying && !(myAvatar->getIsInWalkingState())) { // then we use center of gravity model hipsMat = myAvatar->deriveBodyUsingCgModel(); } else { diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 80676b6a51..6c38d08c96 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -25,9 +25,9 @@ const float DEFAULT_AVATAR_SUPPORT_BASE_RIGHT = 0.25f; const float DEFAULT_AVATAR_SUPPORT_BASE_FRONT = -0.20f; const float DEFAULT_AVATAR_SUPPORT_BASE_BACK = 0.12f; const float DEFAULT_AVATAR_LATERAL_STEPPING_THRESHOLD = 0.10f; -const float DEFAULT_AVATAR_ANTERIOR_STEPPING_THRESHOLD = 0.07f; -const float DEFAULT_AVATAR_POSTERIOR_STEPPING_THRESHOLD = 0.06f; -const float DEFAULT_AVATAR_HEAD_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 0.4f; +const float DEFAULT_AVATAR_ANTERIOR_STEPPING_THRESHOLD = 0.04f; +const float DEFAULT_AVATAR_POSTERIOR_STEPPING_THRESHOLD = 0.05f; +const float DEFAULT_AVATAR_HEAD_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 0.3f; const float DEFAULT_AVATAR_MODE_HEIGHT_STEPPING_THRESHOLD = -0.02f; const float DEFAULT_HANDS_VELOCITY_DIRECTION_STEPPING_THRESHOLD = 0.4f; const float DEFAULT_HANDS_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 3.3f; @@ -68,6 +68,7 @@ const glm::quat DEFAULT_AVATAR_RIGHTFOOT_ROT { -0.4016716778278351f, 0.915461599 const float DEFAULT_AVATAR_MAX_WALKING_SPEED = 2.6f; // meters / second const float DEFAULT_AVATAR_MAX_WALKING_BACKWARD_SPEED = 2.2f; // meters / second const float DEFAULT_AVATAR_MAX_FLYING_SPEED = 30.0f; // meters / second +const float DEFAULT_AVATAR_WALK_SPEED_THRESHOLD = 0.15f; const float DEFAULT_AVATAR_GRAVITY = -5.0f; // meters / second^2 const float DEFAULT_AVATAR_JUMP_SPEED = 3.5f; // meters / second From c986d55d8b9050eda0c1a48031ccd62d5f3ac5e1 Mon Sep 17 00:00:00 2001 From: amantley Date: Thu, 6 Sep 2018 13:18:54 -0700 Subject: [PATCH 32/45] removed step script from repo --- scripts/developer/objectOrientedStep.js | 688 ------------------------ 1 file changed, 688 deletions(-) delete mode 100644 scripts/developer/objectOrientedStep.js diff --git a/scripts/developer/objectOrientedStep.js b/scripts/developer/objectOrientedStep.js deleted file mode 100644 index a5c27e36b9..0000000000 --- a/scripts/developer/objectOrientedStep.js +++ /dev/null @@ -1,688 +0,0 @@ -/* jslint bitwise: true */ - -/* global Script, Vec3, MyAvatar, Tablet, Messages, Quat, -DebugDraw, Mat4, Entities, Xform, Controller, Camera, console, document*/ - -Script.registerValue("STEPAPP", true); -var CENTIMETERSPERMETER = 100.0; -var LEFT = 0; -var RIGHT = 1; -var INCREASING = 1.0; -var DECREASING = -1.0; -var DEFAULT_AVATAR_HEIGHT = 1.64; -var TABLET_BUTTON_NAME = "STEP"; -var CHANGE_OF_BASIS_ROTATION = { x: 0, y: 1, z: 0, w: 0 }; -// in meters (mostly) -var DEFAULT_ANTERIOR = 0.04; -var DEFAULT_POSTERIOR = 0.06; -var DEFAULT_LATERAL = 0.10; -var DEFAULT_HEIGHT_DIFFERENCE = 0.02; -var DEFAULT_ANGULAR_VELOCITY = 0.3; -var DEFAULT_HAND_VELOCITY = 0.4; -var DEFAULT_ANGULAR_HAND_VELOCITY = 3.3; -var DEFAULT_HEAD_VELOCITY = 0.14; -var DEFAULT_LEVEL_PITCH = 7; -var DEFAULT_LEVEL_ROLL = 7; -var DEFAULT_DIFF = 0.0; -var DEFAULT_DIFF_EULERS = { x: 0.0, y: 0.0, z: 0.0 }; -var DEFAULT_HIPS_POSITION; -var DEFAULT_HEAD_POSITION; -var DEFAULT_TORSO_LENGTH; -var SPINE_STRETCH_LIMIT = 0.02; - -var VELOCITY_EPSILON = 0.02; -var AVERAGING_RATE = 0.03; -var HEIGHT_AVERAGING_RATE = 0.01; -var STEP_TIME_SECS = 0.2; -var MODE_SAMPLE_LENGTH = 100; -var RESET_MODE = false; -var HEAD_TURN_THRESHOLD = 25.0; -var NO_SHARED_DIRECTION = -0.98; -var LOADING_DELAY = 500; -var FAILSAFE_TIMEOUT = 2.5; - -var debugDrawBase = true; -var activated = false; -var documentLoaded = false; -var failsafeFlag = false; -var failsafeSignalTimer = -1.0; -var stepTimer = -1.0; - - -var modeArray = new Array(MODE_SAMPLE_LENGTH); -var modeHeight = -10.0; - -var handPosition; -var handOrientation; -var hands = []; -var hipToHandAverage = []; -var handDotHead = []; -var headAverageOrientation = MyAvatar.orientation; -var headPoseAverageOrientation = { x: 0, y: 0, z: 0, w: 1 }; -var averageHeight = 1.0; -var headEulers = { x: 0.0, y: 0.0, z: 0.0 }; -var headAverageEulers = { x: 0.0, y: 0.0, z: 0.0 }; -var headAveragePosition = { x: 0, y: 0.4, z: 0 }; -var frontLeft = { x: -DEFAULT_LATERAL, y: 0, z: -DEFAULT_ANTERIOR }; -var frontRight = { x: DEFAULT_LATERAL, y: 0, z: -DEFAULT_ANTERIOR }; -var backLeft = { x: -DEFAULT_LATERAL, y: 0, z: DEFAULT_POSTERIOR }; -var backRight = { x: DEFAULT_LATERAL, y: 0, z: DEFAULT_POSTERIOR }; - - -// define state readings constructor -function StateReading(headPose, rhandPose, lhandPose, backLength, diffFromMode, diffFromAverageHeight, diffFromAveragePosition, - diffFromAverageEulers) { - this.headPose = headPose; - this.rhandPose = rhandPose; - this.lhandPose = lhandPose; - this.backLength = backLength; - this.diffFromMode = diffFromMode; - this.diffFromAverageHeight = diffFromAverageHeight; - this.diffFromAveragePosition = diffFromAveragePosition; - this.diffFromAverageEulers = diffFromAverageEulers; -} - -// define current state readings object for holding tracker readings and current differences from averages -var currentStateReadings = new StateReading(Controller.getPoseValue(Controller.Standard.Head), - Controller.getPoseValue(Controller.Standard.RightHand), Controller.getPoseValue(Controller.Standard.LeftHand), - DEFAULT_TORSO_LENGTH, DEFAULT_DIFF, DEFAULT_DIFF, DEFAULT_DIFF, DEFAULT_DIFF_EULERS); - -// declare the checkbox constructor -function AppCheckbox(type,id,eventType,isChecked) { - this.type = type; - this.id = id; - this.eventType = eventType; - this.data = {value: isChecked}; -} - -// define the checkboxes in the html file -var usingAverageHeight = new AppCheckbox("checkboxtick", "runningAverageHeightCheck", "onRunningAverageHeightCheckBox", - false); -var usingModeHeight = new AppCheckbox("checkboxtick","modeCheck","onModeCheckBox",true); -var usingBaseOfSupport = new AppCheckbox("checkboxtick","baseOfSupportCheck","onBaseOfSupportCheckBox",true); -var usingAverageHeadPosition = new AppCheckbox("checkboxtick", "headAveragePositionCheck", "onHeadAveragePositionCheckBox", - false); - -var checkBoxArray = new Array(usingAverageHeight,usingModeHeight,usingBaseOfSupport,usingAverageHeadPosition); - -// declare the html slider constructor -function AppProperty(name, type, eventType, signalType, setFunction, initValue, convertToThreshold, convertToSlider, signalOn) { - this.name = name; - this.type = type; - this.eventType = eventType; - this.signalType = signalType; - this.setValue = setFunction; - this.value = initValue; - this.get = function () { - return this.value; - }; - this.convertToThreshold = convertToThreshold; - this.convertToSlider = convertToSlider; - this.signalOn = signalOn; -} - -// define the sliders -var frontBaseProperty = new AppProperty("#anteriorBase-slider", "slider", "onAnteriorBaseSlider", "frontSignal", - setAnteriorDistance, DEFAULT_ANTERIOR, function (num) { - return convertToMeters(num); - }, function (num) { - return convertToCentimeters(num); - },true); -var backBaseProperty = new AppProperty("#posteriorBase-slider", "slider", "onPosteriorBaseSlider", "backSignal", - setPosteriorDistance, DEFAULT_POSTERIOR, function (num) { - return convertToMeters(num); - }, function (num) { - return convertToCentimeters(num); - }, true); -var lateralBaseProperty = new AppProperty("#lateralBase-slider", "slider", "onLateralBaseSlider", "lateralSignal", - setLateralDistance, DEFAULT_LATERAL, function (num) { - return convertToMeters(num); - }, function (num) { - return convertToCentimeters(num); - }, true); -var headAngularVelocityProperty = new AppProperty("#angularVelocityHead-slider", "slider", "onAngularVelocitySlider", - "angularHeadSignal", setAngularThreshold, DEFAULT_ANGULAR_VELOCITY, function (num) { - var base = 4; - var shift = 2; - return convertExponential(base, num, DECREASING, shift); - }, function (num) { - var base = 4; - var shift = 2; - return convertLog(base, num, DECREASING, shift); - }, true); -var heightDifferenceProperty = new AppProperty("#heightDifference-slider", "slider", "onHeightDifferenceSlider", "heightSignal", - setHeightThreshold, DEFAULT_HEIGHT_DIFFERENCE, function (num) { - return convertToMeters(-num); - }, function (num) { - return convertToCentimeters(-num); - }, true); -var handsVelocityProperty = new AppProperty("#handsVelocity-slider", "slider", "onHandsVelocitySlider", "handVelocitySignal", - setHandVelocityThreshold, DEFAULT_HAND_VELOCITY, function (num) { - return num; - }, function (num) { - return num; - }, true); -var handsAngularVelocityProperty = new AppProperty("#handsAngularVelocity-slider", "slider", "onHandsAngularVelocitySlider", - "handAngularSignal", setHandAngularVelocityThreshold, DEFAULT_ANGULAR_HAND_VELOCITY, function (num) { - var base = 7; - var shift = 2; - return convertExponential(base, num, DECREASING, shift); - }, function (num) { - var base = 7; - var shift = 2; - return convertLog(base, num, DECREASING, shift); - }, true); -var headVelocityProperty = new AppProperty("#headVelocity-slider", "slider", "onHeadVelocitySlider", "headVelocitySignal", - setHeadVelocityThreshold, DEFAULT_HEAD_VELOCITY, function (num) { - var base = 2; - var shift = 0; - return convertExponential(base, num, INCREASING, shift); - }, function (num) { - var base = 2; - var shift = 0; - return convertLog(base, num, INCREASING, shift); - }, true); -var headPitchProperty = new AppProperty("#headPitch-slider", "slider", "onHeadPitchSlider", "headPitchSignal", - setHeadPitchThreshold, DEFAULT_LEVEL_PITCH, function (num) { - var base = 2.5; - var shift = 5; - return convertExponential(base, num, DECREASING, shift); - }, function (num) { - var base = 2.5; - var shift = 5; - return convertLog(base, num, DECREASING, shift); - }, true); -var headRollProperty = new AppProperty("#headRoll-slider", "slider", "onHeadRollSlider", "headRollSignal", setHeadRollThreshold, - DEFAULT_LEVEL_ROLL, function (num) { - var base = 2.5; - var shift = 5; - return convertExponential(base, num, DECREASING, shift); - }, function (num) { - var base = 2.5; - var shift = 5; - return convertLog(base, num, DECREASING, shift); - }, true); - -var propArray = new Array(frontBaseProperty, backBaseProperty, lateralBaseProperty, headAngularVelocityProperty, - heightDifferenceProperty, handsVelocityProperty, handsAngularVelocityProperty, headVelocityProperty, headPitchProperty, - headRollProperty); - -// var HTML_URL = Script.resolvePath("http://hifi-content.s3.amazonaws.com/angus/stepApp/stepApp.html"); -var HTML_URL = Script.resolvePath("http://hifi-content.s3.amazonaws.com/angus/stepApp/stepAppExtra.html"); -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - -function manageClick() { - if (activated) { - tablet.gotoHomeScreen(); - } else { - tablet.gotoWebScreen(HTML_URL); - } -} - -var tabletButton = tablet.addButton({ - text: TABLET_BUTTON_NAME, - icon: Script.resolvePath("http://hifi-content.s3.amazonaws.com/angus/stepApp/foot.svg"), - activeIcon: Script.resolvePath("http://hifi-content.s3.amazonaws.com/angus/stepApp/foot.svg") -}); - -function drawBase() { - // transform corners into world space, for rendering. - var worldPointLf = Vec3.sum(MyAvatar.position,Vec3.multiplyQbyV(MyAvatar.orientation, frontLeft)); - var worldPointRf = Vec3.sum(MyAvatar.position,Vec3.multiplyQbyV(MyAvatar.orientation, frontRight)); - var worldPointLb = Vec3.sum(MyAvatar.position,Vec3.multiplyQbyV(MyAvatar.orientation, backLeft)); - var worldPointRb = Vec3.sum(MyAvatar.position,Vec3.multiplyQbyV(MyAvatar.orientation, backRight)); - - var GREEN = { r: 0, g: 1, b: 0, a: 1 }; - // draw border - DebugDraw.drawRay(worldPointLf, worldPointRf, GREEN); - DebugDraw.drawRay(worldPointRf, worldPointRb, GREEN); - DebugDraw.drawRay(worldPointRb, worldPointLb, GREEN); - DebugDraw.drawRay(worldPointLb, worldPointLf, GREEN); -} - -function onKeyPress(event) { - if (event.text === "'") { - // when the sensors are reset, then reset the mode. - RESET_MODE = false; - } -} - -function onWebEventReceived(msg) { - var message = JSON.parse(msg); - print(" we have a message from html dialog " + message.type); - propArray.forEach(function (prop) { - if (prop.eventType === message.type) { - prop.setValue(prop.convertToThreshold(message.data.value)); - print("message from " + prop.name); - // break; - } - }); - checkBoxArray.forEach(function(cbox) { - if (cbox.eventType === message.type) { - cbox.data.value = message.data.value; - // break; - } - }); - if (message.type === "onCreateStepApp") { - print("document loaded"); - documentLoaded = true; - Script.setTimeout(initAppForm, LOADING_DELAY); - } -} - -function initAppForm() { - print("step app is loaded: " + documentLoaded); - if (documentLoaded === true) { - propArray.forEach(function (prop) { - tablet.emitScriptEvent(JSON.stringify({ - "type": "trigger", - "id": prop.signalType, - "data": { "value": "green" } - })); - tablet.emitScriptEvent(JSON.stringify({ - "type": "slider", - "id": prop.name, - "data": { "value": prop.convertToSlider(prop.value) } - })); - }); - checkBoxArray.forEach(function (cbox) { - tablet.emitScriptEvent(JSON.stringify({ - "type": "checkboxtick", - "id": cbox.id, - "data": { "value": cbox.data.value } - })); - }); - } -} - -function updateSignalColors() { - - // force the updates by running the threshold comparisons - withinBaseOfSupport(currentStateReadings.headPose.translation); - withinThresholdOfStandingHeightMode(currentStateReadings.diffFromMode); - headAngularVelocityBelowThreshold(currentStateReadings.headPose.angularVelocity); - handDirectionMatchesHeadDirection(currentStateReadings.lhandPose, currentStateReadings.rhandPose); - handAngularVelocityBelowThreshold(currentStateReadings.lhandPose, currentStateReadings.rhandPose); - headVelocityGreaterThanThreshold(Vec3.length(currentStateReadings.headPose.velocity)); - headMovedAwayFromAveragePosition(currentStateReadings.diffFromAveragePosition); - headLowerThanHeightAverage(currentStateReadings.diffFromAverageHeight); - isHeadLevel(currentStateReadings.diffFromAverageEulers); - - propArray.forEach(function (prop) { - if (prop.signalOn) { - tablet.emitScriptEvent(JSON.stringify({ "type": "trigger", "id": prop.signalType, "data": { "value": "green" } })); - } else { - tablet.emitScriptEvent(JSON.stringify({ "type": "trigger", "id": prop.signalType, "data": { "value": "red" } })); - } - }); -} - -function onScreenChanged(type, url) { - print("Screen changed"); - if (type === "Web" && url === HTML_URL) { - if (!activated) { - // hook up to event bridge - tablet.webEventReceived.connect(onWebEventReceived); - print("after connect web event"); - MyAvatar.hmdLeanRecenterEnabled = false; - - } - activated = true; - } else { - if (activated) { - // disconnect from event bridge - tablet.webEventReceived.disconnect(onWebEventReceived); - documentLoaded = false; - } - activated = false; - } -} - -function getLog(x, y) { - return Math.log(y) / Math.log(x); -} - -function noConversion(num) { - return num; -} - -function convertLog(base, num, direction, shift) { - return direction * getLog(base, (num + 1.0)) + shift; -} - -function convertExponential(base, num, direction, shift) { - return Math.pow(base, (direction*num + shift)) - 1.0; -} - -function convertToCentimeters(num) { - return num * CENTIMETERSPERMETER; -} - -function convertToMeters(num) { - print("convert to meters " + num); - return num / CENTIMETERSPERMETER; -} - -function isInsideLine(a, b, c) { - return (((b.x - a.x)*(c.z - a.z) - (b.z - a.z)*(c.x - a.x)) > 0); -} - -function setAngularThreshold(num) { - headAngularVelocityProperty.value = num; - print("angular threshold " + headAngularVelocityProperty.get()); -} - -function setHeadRollThreshold(num) { - headRollProperty.value = num; - print("head roll threshold " + headRollProperty.get()); -} - -function setHeadPitchThreshold(num) { - headPitchProperty.value = num; - print("head pitch threshold " + headPitchProperty.get()); -} - -function setHeightThreshold(num) { - heightDifferenceProperty.value = num; - print("height threshold " + heightDifferenceProperty.get()); -} - -function setLateralDistance(num) { - lateralBaseProperty.value = num; - frontLeft.x = -lateralBaseProperty.get(); - frontRight.x = lateralBaseProperty.get(); - backLeft.x = -lateralBaseProperty.get(); - backRight.x = lateralBaseProperty.get(); - print("lateral distance " + lateralBaseProperty.get()); -} - -function setAnteriorDistance(num) { - frontBaseProperty.value = num; - frontLeft.z = -frontBaseProperty.get(); - frontRight.z = -frontBaseProperty.get(); - print("anterior distance " + frontBaseProperty.get()); -} - -function setPosteriorDistance(num) { - backBaseProperty.value = num; - backLeft.z = backBaseProperty.get(); - backRight.z = backBaseProperty.get(); - print("posterior distance " + backBaseProperty.get()); -} - -function setHandAngularVelocityThreshold(num) { - handsAngularVelocityProperty.value = num; - print("hand angular velocity threshold " + handsAngularVelocityProperty.get()); -} - -function setHandVelocityThreshold(num) { - handsVelocityProperty.value = num; - print("hand velocity threshold " + handsVelocityProperty.get()); -} - -function setHeadVelocityThreshold(num) { - headVelocityProperty.value = num; - print("headvelocity threshold " + headVelocityProperty.get()); -} - -function withinBaseOfSupport(pos) { - var userScale = 1.0; - frontBaseProperty.signalOn = !(isInsideLine(Vec3.multiply(userScale, frontLeft), Vec3.multiply(userScale, frontRight), pos)); - backBaseProperty.signalOn = !(isInsideLine(Vec3.multiply(userScale, backRight), Vec3.multiply(userScale, backLeft), pos)); - lateralBaseProperty.signalOn = !(isInsideLine(Vec3.multiply(userScale, frontRight), Vec3.multiply(userScale, backRight), pos) - && isInsideLine(Vec3.multiply(userScale, backLeft), Vec3.multiply(userScale, frontLeft), pos)); - return (!frontBaseProperty.signalOn && !backBaseProperty.signalOn && !lateralBaseProperty.signalOn); -} - -function withinThresholdOfStandingHeightMode(heightDiff) { - if (usingModeHeight.data.value) { - heightDifferenceProperty.signalOn = heightDiff < heightDifferenceProperty.get(); - return heightDifferenceProperty.signalOn; - } else { - return true; - } -} - -function headAngularVelocityBelowThreshold(headAngularVelocity) { - var angVel = Vec3.length({ x: headAngularVelocity.x, y: 0, z: headAngularVelocity.z }); - headAngularVelocityProperty.signalOn = angVel < headAngularVelocityProperty.get(); - return headAngularVelocityProperty.signalOn; -} - -function handDirectionMatchesHeadDirection(lhPose, rhPose) { - handsVelocityProperty.signalOn = ((handsVelocityProperty.get() < NO_SHARED_DIRECTION) || - ((!lhPose.valid || ((handDotHead[LEFT] > handsVelocityProperty.get()) && - (Vec3.length(lhPose.velocity) > VELOCITY_EPSILON))) && - (!rhPose.valid || ((handDotHead[RIGHT] > handsVelocityProperty.get()) && - (Vec3.length(rhPose.velocity) > VELOCITY_EPSILON))))); - return handsVelocityProperty.signalOn; -} - -function handAngularVelocityBelowThreshold(lhPose, rhPose) { - var xzRHandAngularVelocity = Vec3.length({ x: rhPose.angularVelocity.x, y: 0.0, z: rhPose.angularVelocity.z }); - var xzLHandAngularVelocity = Vec3.length({ x: lhPose.angularVelocity.x, y: 0.0, z: lhPose.angularVelocity.z }); - handsAngularVelocityProperty.signalOn = ((!rhPose.valid ||(xzRHandAngularVelocity < handsAngularVelocityProperty.get())) - && (!lhPose.valid || (xzLHandAngularVelocity < handsAngularVelocityProperty.get()))); - return handsAngularVelocityProperty.signalOn; -} - -function headVelocityGreaterThanThreshold(headVel) { - headVelocityProperty.signalOn = (headVel > headVelocityProperty.get()) || (headVelocityProperty.get() < VELOCITY_EPSILON); - return headVelocityProperty.signalOn; -} - -function headMovedAwayFromAveragePosition(headDelta) { - return !withinBaseOfSupport(headDelta) || !usingAverageHeadPosition.data.value; -} - -function headLowerThanHeightAverage(heightDiff) { - if (usingAverageHeight.data.value) { - print("head lower than height average"); - heightDifferenceProperty.signalOn = heightDiff < heightDifferenceProperty.get(); - return heightDifferenceProperty.signalOn; - } else { - return true; - } -} - -function isHeadLevel(diffEulers) { - headRollProperty.signalOn = Math.abs(diffEulers.z) < headRollProperty.get(); - headPitchProperty.signalOn = Math.abs(diffEulers.x) < headPitchProperty.get(); - return (headRollProperty.signalOn && headPitchProperty.signalOn); -} - -function findAverage(arr) { - var sum = arr.reduce(function (acc, val) { - return acc + val; - },0); - return sum / arr.length; -} - -function addToModeArray(arr,num) { - for (var i = 0 ;i < (arr.length - 1); i++) { - arr[i] = arr[i+1]; - } - arr[arr.length - 1] = (Math.floor(num*CENTIMETERSPERMETER))/CENTIMETERSPERMETER; -} - -function findMode(ary, currentMode, backLength, defaultBack, currentHeight) { - var numMapping = {}; - var greatestFreq = 0; - var mode; - ary.forEach(function (number) { - numMapping[number] = (numMapping[number] || 0) + 1; - if ((greatestFreq < numMapping[number]) || ((numMapping[number] === MODE_SAMPLE_LENGTH) && (number > currentMode) )) { - greatestFreq = numMapping[number]; - mode = number; - } - }); - if (mode > currentMode) { - return Number(mode); - } else { - if (!RESET_MODE && HMD.active) { - print("resetting the mode............................................. "); - print("resetting the mode............................................. "); - RESET_MODE = true; - var correction = 0.02; - return currentHeight - correction; - } else { - return currentMode; - } - } -} - -function update(dt) { - if (debugDrawBase) { - drawBase(); - } - // Update current state information - currentStateReadings.headPose = Controller.getPoseValue(Controller.Standard.Head); - currentStateReadings.rhandPose = Controller.getPoseValue(Controller.Standard.RightHand); - currentStateReadings.lhandPose = Controller.getPoseValue(Controller.Standard.LeftHand); - - // back length - var headMinusHipLean = Vec3.subtract(currentStateReadings.headPose.translation, DEFAULT_HIPS_POSITION); - currentStateReadings.backLength = Vec3.length(headMinusHipLean); - // print("back length and default " + currentStateReadings.backLength + " " + DEFAULT_TORSO_LENGTH); - - // mode height - addToModeArray(modeArray, currentStateReadings.headPose.translation.y); - modeHeight = findMode(modeArray, modeHeight, currentStateReadings.backLength, DEFAULT_TORSO_LENGTH, - currentStateReadings.headPose.translation.y); - currentStateReadings.diffFromMode = modeHeight - currentStateReadings.headPose.translation.y; - - // hand direction - var leftHandLateralPoseVelocity = currentStateReadings.lhandPose.velocity; - leftHandLateralPoseVelocity.y = 0.0; - var rightHandLateralPoseVelocity = currentStateReadings.rhandPose.velocity; - rightHandLateralPoseVelocity.y = 0.0; - var headLateralPoseVelocity = currentStateReadings.headPose.velocity; - headLateralPoseVelocity.y = 0.0; - handDotHead[LEFT] = Vec3.dot(Vec3.normalize(leftHandLateralPoseVelocity), Vec3.normalize(headLateralPoseVelocity)); - handDotHead[RIGHT] = Vec3.dot(Vec3.normalize(rightHandLateralPoseVelocity), Vec3.normalize(headLateralPoseVelocity)); - - // average head position - headAveragePosition = Vec3.mix(headAveragePosition, currentStateReadings.headPose.translation, AVERAGING_RATE); - currentStateReadings.diffFromAveragePosition = Vec3.subtract(currentStateReadings.headPose.translation, - headAveragePosition); - - // average height - averageHeight = currentStateReadings.headPose.translation.y * HEIGHT_AVERAGING_RATE + - averageHeight * (1.0 - HEIGHT_AVERAGING_RATE); - currentStateReadings.diffFromAverageHeight = Math.abs(currentStateReadings.headPose.translation.y - averageHeight); - - // eulers diff - headEulers = Quat.safeEulerAngles(currentStateReadings.headPose.rotation); - headAverageOrientation = Quat.slerp(headAverageOrientation, currentStateReadings.headPose.rotation, AVERAGING_RATE); - headAverageEulers = Quat.safeEulerAngles(headAverageOrientation); - currentStateReadings.diffFromAverageEulers = Vec3.subtract(headAverageEulers, headEulers); - - // headpose rig space is for determining when to recenter rotation. - var headPoseRigSpace = Quat.multiply(CHANGE_OF_BASIS_ROTATION, currentStateReadings.headPose.rotation); - headPoseAverageOrientation = Quat.slerp(headPoseAverageOrientation, headPoseRigSpace, AVERAGING_RATE); - var headPoseAverageEulers = Quat.safeEulerAngles(headPoseAverageOrientation); - - // make the signal colors reflect the current thresholds that have been crossed - updateSignalColors(); - - SPINE_STRETCH_LIMIT = (0.04) * DEFAULT_TORSO_LENGTH * MyAvatar.scale; - - //print("the spine stretch limit is " + SPINE_STRETCH_LIMIT + " head avatar space is " + currentStateReadings.headPose.translation.y); - //print("the current back length is " + currentStateReadings.backLength + " " + DEFAULT_TORSO_LENGTH); - // Conditions for taking a step. - // 1. off the base of support. front, lateral, back edges. - // 2. head is not lower than the height mode value by more than the maxHeightChange tolerance - // 3. the angular velocity of the head is not greater than the threshold value - // ie this reflects the speed the head is rotating away from having up = (0,1,0) in Avatar frame.. - // 4. the hands velocity vector has the same direction as the head, within the given tolerance - // the tolerance is an acos value, -1 means the hands going in any direction will not block translating - // up to 1 where the hands velocity direction must exactly match that of the head. -1 threshold disables this condition. - // 5. the angular velocity xz magnitude for each hand is below the threshold value - // ie here this reflects the speed that each hand is rotating away from having up = (0,1,0) in Avatar frame. - // 6. head velocity is below step threshold - // 7. head has moved further than the threshold from the running average position of the head. - // 8. head height is not lower than the running average head height with a difference of maxHeightChange. - // 9. head's rotation in avatar space is not pitching or rolling greater than the pitch or roll thresholds - if (!withinBaseOfSupport(currentStateReadings.headPose.translation) && - withinThresholdOfStandingHeightMode(currentStateReadings.diffFromMode) && - headAngularVelocityBelowThreshold(currentStateReadings.headPose.angularVelocity) && - handDirectionMatchesHeadDirection(currentStateReadings.lhandPose, currentStateReadings.rhandPose) && - handAngularVelocityBelowThreshold(currentStateReadings.lhandPose, currentStateReadings.rhandPose) && - headVelocityGreaterThanThreshold(Vec3.length(currentStateReadings.headPose.velocity)) && - headMovedAwayFromAveragePosition(currentStateReadings.diffFromAveragePosition) && - headLowerThanHeightAverage(currentStateReadings.diffFromAverageHeight) && - isHeadLevel(currentStateReadings.diffFromAverageEulers)) { - - if (stepTimer < 0.0) { //!MyAvatar.isRecenteringHorizontally() - print("trigger recenter========================================================"); - MyAvatar.triggerHorizontalRecenter(); - stepTimer = STEP_TIME_SECS; - } - } else if ((currentStateReadings.backLength > (DEFAULT_TORSO_LENGTH + SPINE_STRETCH_LIMIT)) && - (failsafeSignalTimer < 0.0) && HMD.active) { - // do the failsafe recenter. - // failsafeFlag stops repeated setting of failsafe button color. - // RESET_MODE false forces a reset of the height - RESET_MODE = false; - failsafeFlag = true; - failsafeSignalTimer = FAILSAFE_TIMEOUT; - MyAvatar.triggerHorizontalRecenter(); - tablet.emitScriptEvent(JSON.stringify({ "type": "failsafe", "id": "failsafeSignal", "data": { "value": "green" } })); - // in fail safe we debug print the values that were blocking us. - print("failsafe debug---------------------------------------------------------------"); - propArray.forEach(function (prop) { - print(prop.name); - if (!prop.signalOn) { - print(prop.signalType + " contributed to failsafe call"); - } - }); - print("end failsafe debug---------------------------------------------------------------"); - - } - - if ((failsafeSignalTimer < 0.0) && failsafeFlag) { - failsafeFlag = false; - tablet.emitScriptEvent(JSON.stringify({ "type": "failsafe", "id": "failsafeSignal", "data": { "value": "orange" } })); - } - - stepTimer -= dt; - failsafeSignalTimer -= dt; - - if (!HMD.active) { - RESET_MODE = false; - } - - if (Math.abs(headPoseAverageEulers.y) > HEAD_TURN_THRESHOLD) { - // Turn feet - // MyAvatar.triggerRotationRecenter(); - // headPoseAverageOrientation = { x: 0, y: 0, z: 0, w: 1 }; - } -} - -function shutdownTabletApp() { - // GlobalDebugger.stop(); - tablet.removeButton(tabletButton); - if (activated) { - tablet.webEventReceived.disconnect(onWebEventReceived); - tablet.gotoHomeScreen(); - } - tablet.screenChanged.disconnect(onScreenChanged); -} - -tabletButton.clicked.connect(manageClick); -tablet.screenChanged.connect(onScreenChanged); - -Script.setTimeout(function() { - DEFAULT_HIPS_POSITION = MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(MyAvatar.getJointIndex("Hips")); - DEFAULT_HEAD_POSITION = MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(MyAvatar.getJointIndex("Head")); - DEFAULT_TORSO_LENGTH = Vec3.length(Vec3.subtract(DEFAULT_HEAD_POSITION, DEFAULT_HIPS_POSITION)); - SPINE_STRETCH_LIMIT = (0.04) * DEFAULT_TORSO_LENGTH * MyAvatar.scale; -},(4*LOADING_DELAY)); - -Script.update.connect(update); -Controller.keyPressEvent.connect(onKeyPress); -Script.scriptEnding.connect(function () { - MyAvatar.hmdLeanRecenterEnabled = true; - Script.update.disconnect(update); - shutdownTabletApp(); -}); From 0e785f9bdb0746888209a8826bd48a1fb6915198 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 6 Sep 2018 15:35:26 -0700 Subject: [PATCH 33/45] Fix MS17877: Persist Connections table sort choice --- interface/resources/qml/hifi/Pal.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index cbab83ea28..35a0078d32 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -780,6 +780,12 @@ Rectangle { headerVisible: true; sortIndicatorColumn: settings.connectionsSortIndicatorColumn; sortIndicatorOrder: settings.connectionsSortIndicatorOrder; + onSortIndicatorColumnChanged: { + settings.connectionsSortIndicatorColumn = sortIndicatorColumn; + } + onSortIndicatorOrderChanged: { + settings.connectionsSortIndicatorOrder = sortIndicatorOrder; + } TableViewColumn { id: connectionsUserNameHeader; From a908c1554f4d1a35d88577cfaf47b09d2948645f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Sep 2018 16:04:54 -0700 Subject: [PATCH 34/45] make sure ignoredNode is available before sending packet --- assignment-client/src/avatars/AvatarMixer.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 0289a8aa3f..561afee296 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -655,11 +655,14 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer if (addToIgnore) { senderNode->addIgnoredNode(ignoredUUID); - // send a reliable kill packet to remove the sending avatar for the ignored avatar - auto killPacket = NLPacket::create(PacketType::KillAvatar, NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason), true); - killPacket->write(senderNode->getUUID().toRfc4122()); - killPacket->writePrimitive(KillAvatarReason::AvatarDisconnected); - nodeList->sendPacket(std::move(killPacket), *ignoredNode); + if (ignoredNode) { + // send a reliable kill packet to remove the sending avatar for the ignored avatar + auto killPacket = NLPacket::create(PacketType::KillAvatar, + NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason), true); + killPacket->write(senderNode->getUUID().toRfc4122()); + killPacket->writePrimitive(KillAvatarReason::AvatarDisconnected); + nodeList->sendPacket(std::move(killPacket), *ignoredNode); + } } else { senderNode->removeIgnoredNode(ignoredUUID); } From acc7f1f168b734e0d58341a241174ee06b1fcd44 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 6 Sep 2018 16:18:01 -0700 Subject: [PATCH 35/45] Moved AnimStats into its own qml panels. Added state machine tracking as well. --- interface/resources/qml/AnimStats.qml | 157 +++++++++++++++++++ interface/resources/qml/Stats.qml | 35 ++++- interface/src/Application.cpp | 4 + interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + interface/src/ui/AnimStats.cpp | 141 +++++++++++++++++ interface/src/ui/AnimStats.h | 55 +++++++ interface/src/ui/Stats.cpp | 12 +- interface/src/ui/Stats.h | 12 +- libraries/animation/src/AnimContext.h | 14 ++ libraries/animation/src/AnimStateMachine.cpp | 5 +- libraries/animation/src/AnimStateMachine.h | 1 + libraries/animation/src/Rig.h | 1 + 13 files changed, 427 insertions(+), 12 deletions(-) create mode 100644 interface/resources/qml/AnimStats.qml create mode 100644 interface/src/ui/AnimStats.cpp create mode 100644 interface/src/ui/AnimStats.h diff --git a/interface/resources/qml/AnimStats.qml b/interface/resources/qml/AnimStats.qml new file mode 100644 index 0000000000..35ed3799a6 --- /dev/null +++ b/interface/resources/qml/AnimStats.qml @@ -0,0 +1,157 @@ +import Hifi 1.0 as Hifi +import QtQuick 2.3 +import '.' + +Item { + id: animStats + + anchors.leftMargin: 300 + objectName: "StatsItem" + property int modality: Qt.NonModal + implicitHeight: row.height + implicitWidth: row.width + + Component.onCompleted: { + animStats.parentChanged.connect(fill); + fill(); + } + Component.onDestruction: { + animStats.parentChanged.disconnect(fill); + } + + function fill() { + // This will cause a warning at shutdown, need to find another way to remove + // the warning other than filling the anchors to the parent + anchors.horizontalCenter = parent.horizontalCenter + } + + Hifi.AnimStats { + id: root + objectName: "AnimStats" + implicitHeight: row.height + implicitWidth: row.width + + anchors.horizontalCenter: parent.horizontalCenter + readonly property string bgColor: "#AA111111" + + Row { + id: row + spacing: 8 + + Rectangle { + width: firstCol.width + 8; + height: firstCol.height + 8; + color: root.bgColor; + + Column { + id: firstCol + spacing: 4; x: 4; y: 4; + + StatText { + text: "State Machines:---------------------------------------------------------------------------" + } + ListView { + width: firstCol.width + height: root.animStateMachines.length * 15 + visible: root.animStateMchines.length > 0; + model: root.animStateMachines + delegate: StatText { + text: { + return modelData; + } + } + } + } + } + + Rectangle { + width: secondCol.width + 8 + height: secondCol.height + 8 + color: root.bgColor; + + Column { + id: secondCol + spacing: 4; x: 4; y: 4; + + StatText { + text: "Anim Vars:--------------------------------------------------------------------------------" + } + + ListView { + width: secondCol.width + height: root.animVars.length * 15 + visible: root.animVars.length > 0; + model: root.animVars + delegate: StatText { + text: { + var actualText = modelData.split("|")[1]; + if (actualText) { + return actualText; + } else { + return modelData; + } + } + color: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(1.0, 1.0, 1.0, grayScale); + } + styleColor: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.0, 0.0, 0.0, grayScale); + } + } + } + } + } + + Rectangle { + width: thirdCol.width + 8 + height: thirdCol.height + 8 + color: root.bgColor; + + Column { + id: thirdCol + spacing: 4; x: 4; y: 4; + + StatText { + text: "Alpha Values:--------------------------------------------------------------------------" + } + + ListView { + width: thirdCol.width + height: root.animAlphaValues.length * 15 + visible: root.animAlphaValues.length > 0; + model: root.animAlphaValues + delegate: StatText { + text: { + var actualText = modelData.split("|")[1]; + if (actualText) { + return actualText; + } else { + return modelData; + } + } + color: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(1.0, 1.0, 1.0, grayScale); + } + styleColor: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.0, 0.0, 0.0, grayScale); + } + } + } + + } + } + } + + Connections { + target: root.parent + onWidthChanged: { + root.x = root.parent.width - root.width; + } + } + } + +} diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 26682d3db8..f74f0539c9 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -192,6 +192,25 @@ Item { StatText { text: "Yaw: " + root.yaw.toFixed(1) } + StatText { + visible: root.animStateMachines.length > 0; + text: "Anim State Machines:" + } + ListView { + width: geoCol.width + height: root.animStateMachines.length * 15 + visible: root.animStateMchines.length > 0; + model: root.animStateMachines + delegate: StatText { + text: { + if (modelData.length > 30) { + return modelData.substring(0, 5) + "..." + modelData.substring(.length - 22); + } else { + return modelData; + } + } + } + } StatText { visible: root.animAlphaValues.length > 0; text: "Anim Alpha Values:" @@ -216,9 +235,11 @@ Item { } color: { var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(0.3 * grayScale + 0.7, - 0.3 * grayScale + 0.7, - 0.3 * grayScale + 0.7, 1.0); + return Qt.rgba(1.0, 1.0, 1.0, grayScale); + } + styleColor: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.0, 0.0, 0.0, grayScale); } } } @@ -246,9 +267,11 @@ Item { } color: { var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(0.3 * grayScale + 0.7, - 0.3 * grayScale + 0.7, - 0.3 * grayScale + 0.7, 1.0); + return Qt.rgba(1.0, 1.0, 1.0, grayScale); + } + styleColor: { + var grayScale = parseFloat(modelData.split("|")[0]); + return Qt.rgba(0.0, 0.0, 0.0, grayScale); } } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2fe67ec5cb..40edcdbd76 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -195,6 +195,7 @@ #include "ui/SnapshotAnimated.h" #include "ui/StandAloneJSConsole.h" #include "ui/Stats.h" +#include "ui/AnimStats.h" #include "ui/UpdateDialog.h" #include "ui/overlays/Overlays.h" #include "ui/DomainConnectionModel.h" @@ -3081,8 +3082,10 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { Stats::show(); + AnimStats::show(); auto surfaceContext = DependencyManager::get()->getSurfaceContext(); surfaceContext->setContextProperty("Stats", Stats::getInstance()); + surfaceContext->setContextProperty("AnimStats", AnimStats::getInstance()); #if !defined(Q_OS_ANDROID) auto offscreenUi = DependencyManager::get(); @@ -4618,6 +4621,7 @@ void Application::idle() { checkChangeCursor(); Stats::getInstance()->updateStats(); + AnimStats::getInstance()->updateStats(); // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a6ba983ab5..f7be6d17ef 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -737,6 +737,7 @@ Menu::Menu() { // Developer > Stats addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats); + addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AnimStats); // Settings > Enable Speech Control API #if defined(Q_OS_MAC) || defined(Q_OS_WIN) diff --git a/interface/src/Menu.h b/interface/src/Menu.h index c4ea3734f5..031ee2561c 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -197,6 +197,7 @@ namespace MenuOption { const QString SMIEyeTracking = "SMI Eye Tracking"; const QString SparseTextureManagement = "Enable Sparse Texture Management"; const QString Stats = "Show Statistics"; + const QString AnimStats = "Show Animation Stats"; const QString StopAllScripts = "Stop All Scripts"; const QString SuppressShortTimings = "Suppress Timings Less than 10ms"; const QString ThirdPerson = "Third Person"; diff --git a/interface/src/ui/AnimStats.cpp b/interface/src/ui/AnimStats.cpp new file mode 100644 index 0000000000..7b4778e365 --- /dev/null +++ b/interface/src/ui/AnimStats.cpp @@ -0,0 +1,141 @@ +// +// Created by Anthony J. Thibault 2018/08/06 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AnimStats.h" + +#include +#include +#include "Menu.h" + +HIFI_QML_DEF(AnimStats) + +static AnimStats* INSTANCE{ nullptr }; + +AnimStats* AnimStats::getInstance() { + Q_ASSERT(INSTANCE); + return INSTANCE; +} + +AnimStats::AnimStats(QQuickItem* parent) : QQuickItem(parent) { + INSTANCE = this; +} + +void AnimStats::updateStats(bool force) { + QQuickItem* parent = parentItem(); + if (!force) { + if (!Menu::getInstance()->isOptionChecked(MenuOption::AnimStats)) { + if (parent->isVisible()) { + parent->setVisible(false); + } + return; + } else if (!parent->isVisible()) { + parent->setVisible(true); + } + } + + auto avatarManager = DependencyManager::get(); + auto myAvatar = avatarManager->getMyAvatar(); + auto debugAlphaMap = myAvatar->getSkeletonModel()->getRig().getDebugAlphaMap(); + + // update animation debug alpha values + QStringList newAnimAlphaValues; + qint64 now = usecTimestampNow(); + for (auto& iter : debugAlphaMap) { + QString key = iter.first; + float alpha = std::get<0>(iter.second); + + auto prevIter = _prevDebugAlphaMap.find(key); + if (prevIter != _prevDebugAlphaMap.end()) { + float prevAlpha = std::get<0>(iter.second); + if (prevAlpha != alpha) { + // change detected: reset timer + _animAlphaValueChangedTimers[key] = now; + } + } else { + // new value: start timer + _animAlphaValueChangedTimers[key] = now; + } + + AnimNodeType type = std::get<1>(iter.second); + if (type == AnimNodeType::Clip) { + + // figure out the grayScale color of this line. + const float LIT_TIME = 2.0f; + const float FADE_OUT_TIME = 1.0f; + float grayScale = 0.0f; + float secondsElapsed = (float)(now - _animAlphaValueChangedTimers[key]) / (float)USECS_PER_SECOND; + if (secondsElapsed < LIT_TIME) { + grayScale = 1.0f; + } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { + grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; + } else { + grayScale = 0.0f; + } + + if (grayScale > 0.0f) { + // append grayScaleColor to start of debug string + newAnimAlphaValues << QString::number(grayScale, 'f', 2) + "|" + key + ": " + QString::number(alpha, 'f', 3); + } + } + } + + _animAlphaValues = newAnimAlphaValues; + _prevDebugAlphaMap = debugAlphaMap; + + emit animAlphaValuesChanged(); + + // update animation anim vars + _animVarsList.clear(); + auto animVars = myAvatar->getSkeletonModel()->getRig().getAnimVars().toDebugMap(); + for (auto& iter : animVars) { + QString key = iter.first; + QString value = iter.second; + + auto prevIter = _prevAnimVars.find(key); + if (prevIter != _prevAnimVars.end()) { + QString prevValue = prevIter->second; + if (value != prevValue) { + // change detected: reset timer + _animVarChangedTimers[key] = now; + } + } else { + // new value: start timer + _animVarChangedTimers[key] = now; + } + + // figure out the grayScale color of this line. + const float LIT_TIME = 2.0f; + const float FADE_OUT_TIME = 0.5f; + float grayScale = 0.0f; + float secondsElapsed = (float)(now - _animVarChangedTimers[key]) / (float)USECS_PER_SECOND; + if (secondsElapsed < LIT_TIME) { + grayScale = 1.0f; + } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { + grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; + } else { + grayScale = 0.0f; + } + + if (grayScale > 0.0f) { + // append grayScaleColor to start of debug string + _animVarsList << QString::number(grayScale, 'f', 2) + "|" + key + ": " + value; + } + } + _prevAnimVars = animVars; + emit animVarsChanged(); + + // animation state machines + _animStateMachines.clear(); + auto stateMachineMap = myAvatar->getSkeletonModel()->getRig().getStateMachineMap(); + for (auto& iter : stateMachineMap) { + _animStateMachines << iter.second; + } + emit animStateMachinesChanged(); +} + + diff --git a/interface/src/ui/AnimStats.h b/interface/src/ui/AnimStats.h new file mode 100644 index 0000000000..1a6795b498 --- /dev/null +++ b/interface/src/ui/AnimStats.h @@ -0,0 +1,55 @@ +// +// Created by Anthony J. Thibault 2018/08/06 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AnimStats_h +#define hifi_AnimStats_h + +#include +#include + +class AnimStats : public QQuickItem { + Q_OBJECT + HIFI_QML_DECL + + Q_PROPERTY(QStringList animAlphaValues READ animAlphaValues NOTIFY animAlphaValuesChanged) + Q_PROPERTY(QStringList animVars READ animVars NOTIFY animVarsChanged) + Q_PROPERTY(QStringList animStateMachines READ animStateMachines NOTIFY animStateMachinesChanged) + +public: + static AnimStats* getInstance(); + + AnimStats(QQuickItem* parent = nullptr); + + void updateStats(bool force = false); + + QStringList animAlphaValues() { return _animAlphaValues; } + QStringList animVars() { return _animVarsList; } + QStringList animStateMachines() { return _animStateMachines; } + +public slots: + void forceUpdateStats() { updateStats(true); } + +signals: + + void animAlphaValuesChanged(); + void animVarsChanged(); + void animStateMachinesChanged(); + +private: + QStringList _animAlphaValues; + AnimContext::DebugAlphaMap _prevDebugAlphaMap; // alpha values from previous frame + std::map _animAlphaValueChangedTimers; // last time alpha value has changed + + QStringList _animVarsList; + std::map _prevAnimVars; // anim vars from previous frame + std::map _animVarChangedTimers; // last time animVar value has changed. + + QStringList _animStateMachines; +}; + +#endif // hifi_AnimStats_h diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 62e44645b9..bfb83f10f8 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -239,7 +239,7 @@ void Stats::updateStats(bool force) { if (secondsElapsed < LIT_TIME) { grayScale = 1.0f; } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { - grayScale = (LIT_TIME - (secondsElapsed - FADE_OUT_TIME)) / LIT_TIME; + grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; } else { grayScale = 0.0f; } @@ -283,7 +283,7 @@ void Stats::updateStats(bool force) { if (secondsElapsed < LIT_TIME) { grayScale = 1.0f; } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { - grayScale = (LIT_TIME - (secondsElapsed - FADE_OUT_TIME)) / LIT_TIME; + grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; } else { grayScale = 0.0f; } @@ -296,6 +296,14 @@ void Stats::updateStats(bool force) { _prevAnimVars = animVars; emit animVarsChanged(); + // animation state machines + _animStateMachines.clear(); + auto stateMachineMap = myAvatar->getSkeletonModel()->getRig().getStateMachineMap(); + for (auto& iter : stateMachineMap) { + _animStateMachines << iter.second; + } + emit animStateMachinesChanged(); + glm::vec3 avatarPos = myAvatar->getWorldPosition(); STAT_UPDATE(position, QVector3D(avatarPos.x, avatarPos.y, avatarPos.z)); STAT_UPDATE_FLOAT(speed, glm::length(myAvatar->getWorldVelocity()), 0.01f); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 3e71c75da1..1febfff8b5 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -184,6 +184,7 @@ class Stats : public QQuickItem { HIFI_QML_DECL Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged) Q_PROPERTY(bool timingExpanded READ isTimingExpanded NOTIFY timingExpandedChanged) + Q_PROPERTY(QString monospaceFont READ monospaceFont CONSTANT) STATS_PROPERTY(int, serverCount, 0) @@ -294,6 +295,7 @@ class Stats : public QQuickItem { STATS_PROPERTY(float, avatarSimulationTime, 0) Q_PROPERTY(QStringList animAlphaValues READ animAlphaValues NOTIFY animAlphaValuesChanged) Q_PROPERTY(QStringList animVars READ animVars NOTIFY animVarsChanged) + Q_PROPERTY(QStringList animStateMachines READ animStateMachines NOTIFY animStateMachinesChanged) STATS_PROPERTY(int, stylusPicksCount, 0) STATS_PROPERTY(int, rayPicksCount, 0) @@ -329,6 +331,7 @@ public: QStringList downloadUrls () { return _downloadUrls; } QStringList animAlphaValues() { return _animAlphaValues; } QStringList animVars() { return _animVarsList; } + QStringList animStateMachines() { return _animStateMachines; } public slots: void forceUpdateStats() { updateStats(true); } @@ -1032,6 +1035,7 @@ signals: void animAlphaValuesChanged(); void animVarsChanged(); + void animStateMachinesChanged(); /**jsdoc * Triggered when the value of the rectifiedTextureCount property changes. @@ -1333,15 +1337,17 @@ private: bool _showGameUpdateStats{ false }; QString _monospaceFont; const AudioIOStats* _audioStats; - QStringList _downloadUrls = QStringList(); + QStringList _downloadUrls; - QStringList _animAlphaValues = QStringList(); + QStringList _animAlphaValues; AnimContext::DebugAlphaMap _prevDebugAlphaMap; // alpha values from previous frame std::map _animAlphaValueChangedTimers; // last time alpha value has changed - QStringList _animVarsList = QStringList(); + QStringList _animVarsList; std::map _prevAnimVars; // anim vars from previous frame std::map _animVarChangedTimers; // last time animVar value has changed. + + QStringList _animStateMachines; }; #endif // hifi_Stats_h diff --git a/libraries/animation/src/AnimContext.h b/libraries/animation/src/AnimContext.h index ecfb94a28e..b30421ae84 100644 --- a/libraries/animation/src/AnimContext.h +++ b/libraries/animation/src/AnimContext.h @@ -64,6 +64,19 @@ public: return _debugAlphaMap; } + using DebugStateMachineMapValue = QString; + using DebugStateMachineMap = std::map; + + void addStateMachineInfo(const QString& stateMachineName, const QString& currentState, const QString& previousState, bool duringInterp, float alpha) const { + if (duringInterp) { + _stateMachineMap[stateMachineName] = QString("%1: %2 -> %3 (%4)").arg(stateMachineName).arg(previousState).arg(currentState).arg(QString::number(alpha, 'f', 2)); + } else { + _stateMachineMap[stateMachineName] = QString("%1: %2").arg(stateMachineName).arg(currentState); + } + } + + const DebugStateMachineMap& getStateMachineMap() const { return _stateMachineMap; } + protected: bool _enableDebugDrawIKTargets { false }; @@ -74,6 +87,7 @@ protected: // used for debugging internal state of animation system. mutable DebugAlphaMap _debugAlphaMap; + mutable DebugStateMachineMap _stateMachineMap; }; #endif // hifi_AnimContext_h diff --git a/libraries/animation/src/AnimStateMachine.cpp b/libraries/animation/src/AnimStateMachine.cpp index 00ae5e6d39..7f46cd614a 100644 --- a/libraries/animation/src/AnimStateMachine.cpp +++ b/libraries/animation/src/AnimStateMachine.cpp @@ -87,10 +87,13 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co } processOutputJoints(triggersOut); + context.addStateMachineInfo(_id, _currentState->getID(), _previousState->getID(), _duringInterp, _alpha); + return _poses; } void AnimStateMachine::setCurrentState(State::Pointer state) { + _previousState = _currentState ? _currentState : state; _currentState = state; } @@ -135,7 +138,7 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimCon qCDebug(animation) << "AnimStateMachine::switchState:" << _currentState->getID() << "->" << desiredState->getID() << "duration =" << duration << "targetFrame =" << desiredState->_interpTarget << "interpType = " << (int)_interpType; #endif - _currentState = desiredState; + setCurrentState(desiredState); } AnimStateMachine::State::Pointer AnimStateMachine::evaluateTransitions(const AnimVariantMap& animVars) const { diff --git a/libraries/animation/src/AnimStateMachine.h b/libraries/animation/src/AnimStateMachine.h index 8e1e1b7bd8..713c659a1d 100644 --- a/libraries/animation/src/AnimStateMachine.h +++ b/libraries/animation/src/AnimStateMachine.h @@ -140,6 +140,7 @@ protected: AnimPoseVec _nextPoses; State::Pointer _currentState; + State::Pointer _previousState; std::vector _states; QString _currentStateVar; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 95a4b6f40d..48f00d4e5d 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -225,6 +225,7 @@ public: // used to debug animation playback const AnimContext::DebugAlphaMap& getDebugAlphaMap() const { return _lastContext.getDebugAlphaMap(); } const AnimVariantMap& getAnimVars() const { return _lastAnimVars; } + const AnimContext::DebugStateMachineMap& getStateMachineMap() const { return _lastContext.getStateMachineMap(); } void toggleSmoothPoleVectors() { _smoothPoleVectors = !_smoothPoleVectors; }; signals: From 836f810c419b1981da284aead6df1187910a7bc0 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 14:11:42 -0700 Subject: [PATCH 36/45] Have OverlayTransformNode and similar define scale relative to nestable scale on creation time, and refactor code --- .../src/raypick/PickScriptingInterface.cpp | 4 ++ .../src/ui/overlays/OverlayTransformNode.cpp | 22 +--------- .../src/ui/overlays/OverlayTransformNode.h | 11 ++--- .../avatars-renderer/AvatarTransformNode.cpp | 22 +--------- .../avatars-renderer/AvatarTransformNode.h | 11 ++--- .../entities/src/EntityTransformNode.cpp | 22 +--------- libraries/entities/src/EntityTransformNode.h | 11 ++--- .../shared/src/NestableTransformNode.cpp | 22 +--------- libraries/shared/src/NestableTransformNode.h | 44 +++++++++++++++++-- 9 files changed, 61 insertions(+), 108 deletions(-) diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index b892c6da8e..247df2b11e 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -383,6 +383,10 @@ std::shared_ptr PickScriptingInterface::createTransformNode(const if (propMap["parentJointIndex"].isValid()) { parentJointIndex = propMap["parentJointIndex"].toInt(); } + glm::vec3 baseScale = glm::vec3(1); + if (propMap["baseScale"].isValid()) { + baseScale = vec3FromVariant(propMap["baseScale"]); + } auto sharedNestablePointer = nestablePointer.lock(); if (success && sharedNestablePointer) { NestableType nestableType = sharedNestablePointer->getNestableType(); diff --git a/interface/src/ui/overlays/OverlayTransformNode.cpp b/interface/src/ui/overlays/OverlayTransformNode.cpp index d0a6618e37..fa499b3ce3 100644 --- a/interface/src/ui/overlays/OverlayTransformNode.cpp +++ b/interface/src/ui/overlays/OverlayTransformNode.cpp @@ -7,24 +7,6 @@ // #include "OverlayTransformNode.h" -OverlayTransformNode::OverlayTransformNode(std::weak_ptr overlay, int jointIndex) : - _overlay(overlay), - _jointIndex(jointIndex) -{} - -Transform OverlayTransformNode::getTransform() { - auto overlay = _overlay.lock(); - if (!overlay) { - return Transform(); - } - - bool success; - Transform jointWorldTransform = overlay->getTransform(_jointIndex, success); - if (!success) { - return Transform(); - } - - jointWorldTransform.setScale(overlay->getBounds().getScale()); - - return jointWorldTransform; +glm::vec3 BaseNestableTransformNode::getActualScale(const std::shared_ptr& nestablePointer) const { + return nestablePointer->getBounds().getScale(); } \ No newline at end of file diff --git a/interface/src/ui/overlays/OverlayTransformNode.h b/interface/src/ui/overlays/OverlayTransformNode.h index b9ea9f72c4..11c3415828 100644 --- a/interface/src/ui/overlays/OverlayTransformNode.h +++ b/interface/src/ui/overlays/OverlayTransformNode.h @@ -8,19 +8,14 @@ #ifndef hifi_OverlayTransformNode_h #define hifi_OverlayTransformNode_h -#include "TransformNode.h" +#include "NestableTransformNode.h" #include "Base3DOverlay.h" // For 3D overlays only -class OverlayTransformNode : public TransformNode { +class OverlayTransformNode : public BaseNestableTransformNode { public: - OverlayTransformNode(std::weak_ptr overlay, int jointIndex); - Transform getTransform() override; - -protected: - std::weak_ptr _overlay; - int _jointIndex; + OverlayTransformNode(std::weak_ptr spatiallyNestable, int jointIndex) : BaseNestableTransformNode(spatiallyNestable, jointIndex) {}; }; #endif // hifi_OverlayTransformNode_h \ No newline at end of file diff --git a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp index fc5ba5bc1a..bc24b8a570 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp @@ -7,24 +7,6 @@ // #include "AvatarTransformNode.h" -AvatarTransformNode::AvatarTransformNode(AvatarWeakPointer avatar, int jointIndex) : - _avatar(avatar), - _jointIndex(jointIndex) -{} - -Transform AvatarTransformNode::getTransform() { - auto avatar = _avatar.lock(); - if (!avatar) { - return Transform(); - } - - bool success; - Transform jointWorldTransform = avatar->getTransform(_jointIndex, success); - if (!success) { - return Transform(); - } - - jointWorldTransform.setScale(avatar->scaleForChildren()); - - return jointWorldTransform; +glm::vec3 BaseNestableTransformNode::getActualScale(const std::shared_ptr& nestablePointer) const { + return nestablePointer->scaleForChildren(); } \ No newline at end of file diff --git a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h index 03191b8dbe..183e4ab05c 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h +++ b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.h @@ -8,18 +8,13 @@ #ifndef hifi_AvatarTransformNode_h #define hifi_AvatarTransformNode_h -#include "TransformNode.h" +#include "NestableTransformNode.h" #include "Avatar.h" -class AvatarTransformNode : public TransformNode { +class AvatarTransformNode : public BaseNestableTransformNode { public: - AvatarTransformNode(AvatarWeakPointer avatar, int jointIndex); - Transform getTransform() override; - -protected: - AvatarWeakPointer _avatar; - int _jointIndex; + AvatarTransformNode(std::weak_ptr spatiallyNestable, int jointIndex) : BaseNestableTransformNode(spatiallyNestable, jointIndex) {}; }; #endif // hifi_AvatarTransformNode_h \ No newline at end of file diff --git a/libraries/entities/src/EntityTransformNode.cpp b/libraries/entities/src/EntityTransformNode.cpp index 5b0a690619..35f4d8e52f 100644 --- a/libraries/entities/src/EntityTransformNode.cpp +++ b/libraries/entities/src/EntityTransformNode.cpp @@ -7,24 +7,6 @@ // #include "EntityTransformNode.h" -EntityTransformNode::EntityTransformNode(EntityItemWeakPointer entity, int jointIndex) : - _entity(entity), - _jointIndex(jointIndex) -{} - -Transform EntityTransformNode::getTransform() { - auto entity = _entity.lock(); - if (!entity) { - return Transform(); - } - - bool success; - Transform jointWorldTransform = entity->getTransform(_jointIndex, success); - if (!success) { - return Transform(); - } - - jointWorldTransform.setScale(entity->getScaledDimensions()); - - return jointWorldTransform; +glm::vec3 BaseNestableTransformNode::getActualScale(const std::shared_ptr& nestablePointer) const { + return nestablePointer->getScaledDimensions(); } \ No newline at end of file diff --git a/libraries/entities/src/EntityTransformNode.h b/libraries/entities/src/EntityTransformNode.h index b7388600df..07818f99f3 100644 --- a/libraries/entities/src/EntityTransformNode.h +++ b/libraries/entities/src/EntityTransformNode.h @@ -8,18 +8,13 @@ #ifndef hifi_EntityTransformNode_h #define hifi_EntityTransformNode_h -#include "TransformNode.h" +#include "NestableTransformNode.h" #include "EntityItem.h" -class EntityTransformNode : public TransformNode { +class EntityTransformNode : public BaseNestableTransformNode { public: - EntityTransformNode(EntityItemWeakPointer entity, int jointIndex); - Transform getTransform() override; - -protected: - EntityItemWeakPointer _entity; - int _jointIndex; + EntityTransformNode(std::weak_ptr spatiallyNestable, int jointIndex) : BaseNestableTransformNode(spatiallyNestable, jointIndex) {}; }; #endif // hifi_EntityTransformNode_h \ No newline at end of file diff --git a/libraries/shared/src/NestableTransformNode.cpp b/libraries/shared/src/NestableTransformNode.cpp index 17456d69ce..9da2c85aa3 100644 --- a/libraries/shared/src/NestableTransformNode.cpp +++ b/libraries/shared/src/NestableTransformNode.cpp @@ -8,24 +8,6 @@ #include "NestableTransformNode.h" -NestableTransformNode::NestableTransformNode(SpatiallyNestableWeakPointer spatiallyNestable, int jointIndex) : - _spatiallyNestable(spatiallyNestable), - _jointIndex(jointIndex) -{ -} - -Transform NestableTransformNode::getTransform() { - auto nestable = _spatiallyNestable.lock(); - if (!nestable) { - return Transform(); - } - - bool success; - Transform jointWorldTransform = nestable->getTransform(_jointIndex, success); - - if (success) { - return jointWorldTransform; - } else { - return Transform(); - } +glm::vec3 BaseNestableTransformNode::getActualScale(const std::shared_ptr& nestablePointer) const { + return nestablePointer->getAbsoluteJointScaleInObjectFrame(_jointIndex); } \ No newline at end of file diff --git a/libraries/shared/src/NestableTransformNode.h b/libraries/shared/src/NestableTransformNode.h index 131de9e786..21efd1c690 100644 --- a/libraries/shared/src/NestableTransformNode.h +++ b/libraries/shared/src/NestableTransformNode.h @@ -12,14 +12,50 @@ #include "SpatiallyNestable.h" -class NestableTransformNode : public TransformNode { +template +class BaseNestableTransformNode : public TransformNode { public: - NestableTransformNode(SpatiallyNestableWeakPointer spatiallyNestable, int jointIndex); - Transform getTransform() override; + BaseNestableTransformNode(std::weak_ptr spatiallyNestable, int jointIndex) : + _spatiallyNestable(spatiallyNestable), + _jointIndex(jointIndex) { + auto nestablePointer = _spatiallyNestable.lock(); + if (nestablePointer) { + glm::vec3 nestableDimensions = getActualScale(nestablePointer); + if (!glm::any(glm::equal(nestableDimensions, glm::vec3(0.0f)))) { + _baseScale = nestableDimensions; + } + } + } + + Transform getTransform() { + std::shared_ptr nestable = _spatiallyNestable.lock(); + if (!nestable) { + return Transform(); + } + + bool success; + Transform jointWorldTransform = nestable->getTransform(_jointIndex, success); + + if (!success) { + return Transform(); + } + + jointWorldTransform.setScale(getActualScale(nestable) / _baseScale); + + return jointWorldTransform; + } + + glm::vec3 getActualScale(const std::shared_ptr& nestablePointer) const; protected: - SpatiallyNestableWeakPointer _spatiallyNestable; + std::weak_ptr _spatiallyNestable; int _jointIndex; + glm::vec3 _baseScale { 1.0f }; +}; + +class NestableTransformNode : public BaseNestableTransformNode { +public: + NestableTransformNode(std::weak_ptr spatiallyNestable, int jointIndex) : BaseNestableTransformNode(spatiallyNestable, jointIndex) {}; }; #endif // hifi_NestableTransformNode_h \ No newline at end of file From 23a6abbaca6f36726d81c3072a74bc0b9f79ce6b Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 16:47:09 -0700 Subject: [PATCH 37/45] Update jsdocs to reflect new collision pick scaling behavior --- interface/src/raypick/PickScriptingInterface.cpp | 6 +++--- libraries/shared/src/RegisteredMetaTypes.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index 247df2b11e..41669c9f0c 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -265,11 +265,11 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti * @typedef {object} Picks.CollisionPickProperties * @property {boolean} [enabled=false] If this Pick should start enabled or not. Disabled Picks do not updated their pick results. * @property {number} [filter=Picks.PICK_NOTHING] The filter for this Pick to use, constructed using filter flags combined using bitwise OR. -* @property {Shape} shape - The information about the collision region's size and shape. Dimensions are relative to a parent if defined. +* @property {Shape} shape - The information about the collision region's size and shape. Dimensions are in world space, but will scale with the parent if defined. * @property {Vec3} position - The position of the collision region, relative to a parent if defined. * @property {Quat} orientation - The orientation of the collision region, relative to a parent if defined. -* @property {float} threshold - The approximate minimum penetration depth for a test object to be considered in contact with the collision region, relative to a parent if defined. -* For overlay and entity parents, this is relative to the parent's largest dimension. +* @property {float} threshold - The approximate minimum penetration depth for a test object to be considered in contact with the collision region. +* The depth is measured in world space, but will scale with the parent if defined. * @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or an overlay. * @property {number} parentJointIndex - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint) * @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar. diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 79adce0a39..d59c58def8 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -259,11 +259,11 @@ public: * A CollisionRegion defines a volume for checking collisions in the physics simulation. * @typedef {object} CollisionRegion -* @property {Shape} shape - The information about the collision region's size and shape. Dimensions are relative to a parent if defined. +* @property {Shape} shape - The information about the collision region's size and shape. Dimensions are in world space, but will scale with the parent if defined. * @property {Vec3} position - The position of the collision region, relative to a parent if defined. * @property {Quat} orientation - The orientation of the collision region, relative to a parent if defined. -* @property {float} threshold - The approximate minimum penetration depth for a test object to be considered in contact with the collision region, relative to a parent if defined. -* For overlay and entity parents, this is relative to the parent's largest dimension. +* @property {float} threshold - The approximate minimum penetration depth for a test object to be considered in contact with the collision region. +* The depth is measured in world space, but will scale with the parent if defined. * @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or an overlay. * @property {number} parentJointIndex - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint) * @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar. From 7a9480723e61f58065acaeaaccdd72ec1b4ef393 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 17:30:29 -0700 Subject: [PATCH 38/45] Remove unused variable in PickScriptingInterface::createTransformNode --- interface/src/raypick/PickScriptingInterface.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index 41669c9f0c..0273b084b2 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -383,10 +383,6 @@ std::shared_ptr PickScriptingInterface::createTransformNode(const if (propMap["parentJointIndex"].isValid()) { parentJointIndex = propMap["parentJointIndex"].toInt(); } - glm::vec3 baseScale = glm::vec3(1); - if (propMap["baseScale"].isValid()) { - baseScale = vec3FromVariant(propMap["baseScale"]); - } auto sharedNestablePointer = nestablePointer.lock(); if (success && sharedNestablePointer) { NestableType nestableType = sharedNestablePointer->getNestableType(); From f40f40e135c8fbe205e9e7a8476304f94c086f30 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 17:35:12 -0700 Subject: [PATCH 39/45] Use more reasonable value for BaseNestableTransformNode::_baseScale when given bad value --- libraries/shared/src/NestableTransformNode.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/shared/src/NestableTransformNode.h b/libraries/shared/src/NestableTransformNode.h index 21efd1c690..e73360d872 100644 --- a/libraries/shared/src/NestableTransformNode.h +++ b/libraries/shared/src/NestableTransformNode.h @@ -21,9 +21,7 @@ public: auto nestablePointer = _spatiallyNestable.lock(); if (nestablePointer) { glm::vec3 nestableDimensions = getActualScale(nestablePointer); - if (!glm::any(glm::equal(nestableDimensions, glm::vec3(0.0f)))) { - _baseScale = nestableDimensions; - } + _baseScale = glm::max(glm::vec3(0.001f), nestableDimensions); } } From 52bc09cd2aa29071d4fa56fb792fcc454be81d29 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 6 Sep 2018 17:44:06 -0700 Subject: [PATCH 40/45] Add override qualifier to BaseNestableTransformNode::getTransform --- libraries/shared/src/NestableTransformNode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/NestableTransformNode.h b/libraries/shared/src/NestableTransformNode.h index e73360d872..2f9bc2e985 100644 --- a/libraries/shared/src/NestableTransformNode.h +++ b/libraries/shared/src/NestableTransformNode.h @@ -25,7 +25,7 @@ public: } } - Transform getTransform() { + Transform getTransform() override { std::shared_ptr nestable = _spatiallyNestable.lock(); if (!nestable) { return Transform(); From 6508533a15fd3035593535ae87bdb6316b8d6eb1 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 6 Sep 2018 17:58:40 -0700 Subject: [PATCH 41/45] Remove anim stats from plain ole stats. There are still present in anim stats tho. --- interface/resources/qml/Stats.qml | 83 -------------------------- interface/src/ui/Stats.cpp | 98 ------------------------------- interface/src/ui/Stats.h | 25 +------- 3 files changed, 1 insertion(+), 205 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index f74f0539c9..1a29ce87df 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -192,89 +192,6 @@ Item { StatText { text: "Yaw: " + root.yaw.toFixed(1) } - StatText { - visible: root.animStateMachines.length > 0; - text: "Anim State Machines:" - } - ListView { - width: geoCol.width - height: root.animStateMachines.length * 15 - visible: root.animStateMchines.length > 0; - model: root.animStateMachines - delegate: StatText { - text: { - if (modelData.length > 30) { - return modelData.substring(0, 5) + "..." + modelData.substring(.length - 22); - } else { - return modelData; - } - } - } - } - StatText { - visible: root.animAlphaValues.length > 0; - text: "Anim Alpha Values:" - } - ListView { - width: geoCol.width - height: root.animAlphaValues.length * 15 - visible: root.animAlphaValues.length > 0; - model: root.animAlphaValues - delegate: StatText { - text: { - var actualText = modelData.split("|")[1]; - if (actualText) { - if (actualText.length > 30) { - return actualText.substring(0, 5) + "..." + actualText.substring(actualText.length - 22); - } else { - return actualText; - } - } else { - return modelData; - } - } - color: { - var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(1.0, 1.0, 1.0, grayScale); - } - styleColor: { - var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(0.0, 0.0, 0.0, grayScale); - } - } - } - StatText { - visible: root.animVars.length > 0; - text: "AnimVars:" - } - ListView { - width: geoCol.width - height: root.animVars.length * 15 - visible: root.animVars.length > 0; - model: root.animVars - delegate: StatText { - text: { - var actualText = modelData.split("|")[1]; - if (actualText) { - if (actualText.length > 30) { - return actualText.substring(0, 5) + "..." + actualText.substring(actualText.length - 22); - } else { - return actualText; - } - } else { - return modelData; - } - } - color: { - var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(1.0, 1.0, 1.0, grayScale); - } - styleColor: { - var grayScale = parseFloat(modelData.split("|")[0]); - return Qt.rgba(0.0, 0.0, 0.0, grayScale); - } - } - } StatText { visible: root.expanded; text: "Avatar Mixer In: " + root.avatarMixerInKbps + " kbps, " + diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index bfb83f10f8..d51b90f15d 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -207,103 +207,6 @@ void Stats::updateStats(bool force) { // Third column, avatar stats auto myAvatar = avatarManager->getMyAvatar(); - auto debugAlphaMap = myAvatar->getSkeletonModel()->getRig().getDebugAlphaMap(); - - // update animation debug alpha values - QStringList newAnimAlphaValues; - qint64 now = usecTimestampNow(); - for (auto& iter : debugAlphaMap) { - QString key = iter.first; - float alpha = std::get<0>(iter.second); - - auto prevIter = _prevDebugAlphaMap.find(key); - if (prevIter != _prevDebugAlphaMap.end()) { - float prevAlpha = std::get<0>(iter.second); - if (prevAlpha != alpha) { - // change detected: reset timer - _animAlphaValueChangedTimers[key] = now; - } - } else { - // new value: start timer - _animAlphaValueChangedTimers[key] = now; - } - - AnimNodeType type = std::get<1>(iter.second); - if (type == AnimNodeType::Clip) { - - // figure out the grayScale color of this line. - const float LIT_TIME = 2.0f; - const float FADE_OUT_TIME = 1.0f; - float grayScale = 0.0f; - float secondsElapsed = (float)(now - _animAlphaValueChangedTimers[key]) / (float)USECS_PER_SECOND; - if (secondsElapsed < LIT_TIME) { - grayScale = 1.0f; - } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { - grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; - } else { - grayScale = 0.0f; - } - - if (grayScale > 0.0f) { - // append grayScaleColor to start of debug string - newAnimAlphaValues << QString::number(grayScale, 'f', 2) + "|" + key + ": " + QString::number(alpha, 'f', 3); - } - } - } - - _animAlphaValues = newAnimAlphaValues; - _prevDebugAlphaMap = debugAlphaMap; - - emit animAlphaValuesChanged(); - - // update animation anim vars - _animVarsList.clear(); - auto animVars = myAvatar->getSkeletonModel()->getRig().getAnimVars().toDebugMap(); - for (auto& iter : animVars) { - QString key = iter.first; - QString value = iter.second; - - auto prevIter = _prevAnimVars.find(key); - if (prevIter != _prevAnimVars.end()) { - QString prevValue = prevIter->second; - if (value != prevValue) { - // change detected: reset timer - _animVarChangedTimers[key] = now; - } - } else { - // new value: start timer - _animVarChangedTimers[key] = now; - } - - // figure out the grayScale color of this line. - const float LIT_TIME = 2.0f; - const float FADE_OUT_TIME = 0.5f; - float grayScale = 0.0f; - float secondsElapsed = (float)(now - _animVarChangedTimers[key]) / (float)USECS_PER_SECOND; - if (secondsElapsed < LIT_TIME) { - grayScale = 1.0f; - } else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) { - grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME; - } else { - grayScale = 0.0f; - } - - if (grayScale > 0.0f) { - // append grayScaleColor to start of debug string - _animVarsList << QString::number(grayScale, 'f', 2) + "|" + key + ": " + value; - } - } - _prevAnimVars = animVars; - emit animVarsChanged(); - - // animation state machines - _animStateMachines.clear(); - auto stateMachineMap = myAvatar->getSkeletonModel()->getRig().getStateMachineMap(); - for (auto& iter : stateMachineMap) { - _animStateMachines << iter.second; - } - emit animStateMachinesChanged(); - glm::vec3 avatarPos = myAvatar->getWorldPosition(); STAT_UPDATE(position, QVector3D(avatarPos.x, avatarPos.y, avatarPos.z)); STAT_UPDATE_FLOAT(speed, glm::length(myAvatar->getWorldVelocity()), 0.01f); @@ -436,7 +339,6 @@ void Stats::updateStats(bool force) { } sendingModeStream << "] " << serverCount << " servers"; if (movingServerCount > 0) { - sendingModeStream << " "; } else { sendingModeStream << " "; diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 1febfff8b5..ae608cfddb 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -14,7 +14,6 @@ #include #include #include -#include #define STATS_PROPERTY(type, name, initialValue) \ Q_PROPERTY(type name READ name NOTIFY name##Changed) \ @@ -184,7 +183,6 @@ class Stats : public QQuickItem { HIFI_QML_DECL Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged) Q_PROPERTY(bool timingExpanded READ isTimingExpanded NOTIFY timingExpandedChanged) - Q_PROPERTY(QString monospaceFont READ monospaceFont CONSTANT) STATS_PROPERTY(int, serverCount, 0) @@ -293,9 +291,6 @@ class Stats : public QQuickItem { STATS_PROPERTY(float, batchFrameTime, 0) STATS_PROPERTY(float, engineFrameTime, 0) STATS_PROPERTY(float, avatarSimulationTime, 0) - Q_PROPERTY(QStringList animAlphaValues READ animAlphaValues NOTIFY animAlphaValuesChanged) - Q_PROPERTY(QStringList animVars READ animVars NOTIFY animVarsChanged) - Q_PROPERTY(QStringList animStateMachines READ animStateMachines NOTIFY animStateMachinesChanged) STATS_PROPERTY(int, stylusPicksCount, 0) STATS_PROPERTY(int, rayPicksCount, 0) @@ -329,9 +324,6 @@ public: } QStringList downloadUrls () { return _downloadUrls; } - QStringList animAlphaValues() { return _animAlphaValues; } - QStringList animVars() { return _animVarsList; } - QStringList animStateMachines() { return _animStateMachines; } public slots: void forceUpdateStats() { updateStats(true); } @@ -1033,10 +1025,6 @@ signals: */ void avatarSimulationTimeChanged(); - void animAlphaValuesChanged(); - void animVarsChanged(); - void animStateMachinesChanged(); - /**jsdoc * Triggered when the value of the rectifiedTextureCount property changes. * @function Stats.rectifiedTextureCountChanged @@ -1051,7 +1039,6 @@ signals: */ void decimatedTextureCountChanged(); - // QQuickItem signals. /**jsdoc @@ -1337,17 +1324,7 @@ private: bool _showGameUpdateStats{ false }; QString _monospaceFont; const AudioIOStats* _audioStats; - QStringList _downloadUrls; - - QStringList _animAlphaValues; - AnimContext::DebugAlphaMap _prevDebugAlphaMap; // alpha values from previous frame - std::map _animAlphaValueChangedTimers; // last time alpha value has changed - - QStringList _animVarsList; - std::map _prevAnimVars; // anim vars from previous frame - std::map _animVarChangedTimers; // last time animVar value has changed. - - QStringList _animStateMachines; + QStringList _downloadUrls = QStringList(); }; #endif // hifi_Stats_h From 8d4c47cf8ed70e7ed8c8bd1955ecdbad93cd293d Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Fri, 7 Sep 2018 08:49:44 -0700 Subject: [PATCH 42/45] Make template specialization of BaseNestableTransformNode explicit --- interface/src/ui/overlays/OverlayTransformNode.cpp | 1 + .../src/avatars-renderer/AvatarTransformNode.cpp | 1 + libraries/entities/src/EntityTransformNode.cpp | 1 + libraries/shared/src/NestableTransformNode.cpp | 1 + 4 files changed, 4 insertions(+) diff --git a/interface/src/ui/overlays/OverlayTransformNode.cpp b/interface/src/ui/overlays/OverlayTransformNode.cpp index fa499b3ce3..817b6af305 100644 --- a/interface/src/ui/overlays/OverlayTransformNode.cpp +++ b/interface/src/ui/overlays/OverlayTransformNode.cpp @@ -7,6 +7,7 @@ // #include "OverlayTransformNode.h" +template<> glm::vec3 BaseNestableTransformNode::getActualScale(const std::shared_ptr& nestablePointer) const { return nestablePointer->getBounds().getScale(); } \ No newline at end of file diff --git a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp index bc24b8a570..ca3d4a6062 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/AvatarTransformNode.cpp @@ -7,6 +7,7 @@ // #include "AvatarTransformNode.h" +template<> glm::vec3 BaseNestableTransformNode::getActualScale(const std::shared_ptr& nestablePointer) const { return nestablePointer->scaleForChildren(); } \ No newline at end of file diff --git a/libraries/entities/src/EntityTransformNode.cpp b/libraries/entities/src/EntityTransformNode.cpp index 35f4d8e52f..438ece3840 100644 --- a/libraries/entities/src/EntityTransformNode.cpp +++ b/libraries/entities/src/EntityTransformNode.cpp @@ -7,6 +7,7 @@ // #include "EntityTransformNode.h" +template<> glm::vec3 BaseNestableTransformNode::getActualScale(const std::shared_ptr& nestablePointer) const { return nestablePointer->getScaledDimensions(); } \ No newline at end of file diff --git a/libraries/shared/src/NestableTransformNode.cpp b/libraries/shared/src/NestableTransformNode.cpp index 9da2c85aa3..9723f388f6 100644 --- a/libraries/shared/src/NestableTransformNode.cpp +++ b/libraries/shared/src/NestableTransformNode.cpp @@ -8,6 +8,7 @@ #include "NestableTransformNode.h" +template<> glm::vec3 BaseNestableTransformNode::getActualScale(const std::shared_ptr& nestablePointer) const { return nestablePointer->getAbsoluteJointScaleInObjectFrame(_jointIndex); } \ No newline at end of file From 5a059e93184acc28e21262b8080c6341a7559403 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Fri, 7 Sep 2018 09:44:19 -0700 Subject: [PATCH 43/45] Fix for build failure on linux and android. --- libraries/animation/src/AnimContext.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/animation/src/AnimContext.h b/libraries/animation/src/AnimContext.h index b30421ae84..c455dd9c8f 100644 --- a/libraries/animation/src/AnimContext.h +++ b/libraries/animation/src/AnimContext.h @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #include enum class AnimNodeType { From f9ec53a2e6ac9bcd64d5ab0d53c2c868aa7fde27 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 7 Sep 2018 10:25:26 -0700 Subject: [PATCH 44/45] fix bloom on edges --- libraries/render-utils/src/DeferredFramebuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DeferredFramebuffer.cpp b/libraries/render-utils/src/DeferredFramebuffer.cpp index 2df89b8808..1906375654 100644 --- a/libraries/render-utils/src/DeferredFramebuffer.cpp +++ b/libraries/render-utils/src/DeferredFramebuffer.cpp @@ -73,7 +73,7 @@ void DeferredFramebuffer::allocate() { _deferredFramebufferDepthColor->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); - auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT); + auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP); _lightingTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, gpu::Texture::SINGLE_MIP, smoothSampler); _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("lighting")); From 32e2a244a110a7d16a2afd5e319478d6f0f41ac7 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 7 Sep 2018 11:44:35 -0700 Subject: [PATCH 45/45] detailed profile range for avatar unpacking --- libraries/avatars/src/AvatarHashMap.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index c1246866dc..1383939b8b 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -21,6 +21,7 @@ #include "AvatarLogging.h" #include "AvatarTraits.h" +#include "Profile.h" void AvatarReplicas::addReplica(const QUuid& parentID, AvatarSharedPointer replica) { if (parentID == QUuid()) { @@ -214,6 +215,7 @@ AvatarSharedPointer AvatarHashMap::findAvatar(const QUuid& sessionUUID) const { } void AvatarHashMap::processAvatarDataPacket(QSharedPointer message, SharedNodePointer sendingNode) { + DETAILED_PROFILE_RANGE(network, __FUNCTION__); PerformanceTimer perfTimer("receiveAvatar"); // enumerate over all of the avatars in this packet // only add them if mixerWeakPointer points to something (meaning that mixer is still around)