diff --git a/examples/controllers/reticleHandTest.js b/examples/controllers/reticleHandTest.js index 5d0e2f238a..4132c80d85 100644 --- a/examples/controllers/reticleHandTest.js +++ b/examples/controllers/reticleHandTest.js @@ -9,23 +9,83 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -function moveReticle(pitch, yaw) { - //print("pitch:" + pitch); - //print("yaw:" + yaw); - var globalPos = Controller.getReticlePosition(); - globalPos.x += yaw; - globalPos.y += pitch; - Controller.setReticlePosition(globalPos); +function msecTimestampNow() { + var d = new Date(); + return d.getTime(); } +function length(posA, posB) { + var dx = posA.x - posB.x; + var dy = posA.y - posB.y; + var length = Math.sqrt((dx*dx) + (dy*dy)) + return length; +} + +var EXPECTED_CHANGE = 50; +var lastPos = Controller.getReticlePosition(); +function moveReticle(dX, dY) { + var globalPos = Controller.getReticlePosition(); + + // some debugging to see if position is jumping around on us... + var distanceSinceLastMove = length(lastPos, globalPos); + if (distanceSinceLastMove > EXPECTED_CHANGE) { + print("distanceSinceLastMove:" + distanceSinceLastMove + "----------------------------"); + } + + if (Math.abs(dX) > EXPECTED_CHANGE) { + print("surpressing unexpectedly large change dX:" + dX + "----------------------------"); + dX = 0; + } + if (Math.abs(dY) > EXPECTED_CHANGE) { + print("surpressing unexpectedly large change dY:" + dY + "----------------------------"); + dY = 0; + } + + globalPos.x += dX; + globalPos.y += dY; + Controller.setReticlePosition(globalPos); + lastPos = globalPos; +} + +var lastTime = msecTimestampNow(); + var MAPPING_NAME = "com.highfidelity.testing.reticleWithHand"; var mapping = Controller.newMapping(MAPPING_NAME); mapping.from(Controller.Standard.RightHand).peek().to(function(pose) { - var angularVelocityEADs = Quat.safeEulerAngles(pose.angularVelocity); // degrees - var yaw = isNaN(angularVelocityEADs.y) ? 0 : (-angularVelocityEADs.y / 10); - var pitch = isNaN(angularVelocityEADs.x) ? 0 : (-angularVelocityEADs.x / 10); - moveReticle(pitch, yaw); + + + // pose.angularVelocity - is the angularVelocity in a "physics" sense, that + // means the direction of the vector is the axis of symetry of rotation + // and the scale of the vector is the speed in radians/second of rotation + // around that axis. + // + // we want to deconstruct that in the portion of the rotation on the Y axis + // and make that portion move our reticle in the horizontal/X direction + // and the portion of the rotation on the X axis and make that portion + // move our reticle in the veritcle/Y direction + var xPart = -pose.angularVelocity.y; + var yPart = -pose.angularVelocity.x; + + + var MOVE_SCALE = 1; + var MSECS_PER_SECOND = 1000; + var now = msecTimestampNow(); + var secondsSinceLast = (now - lastTime) / MSECS_PER_SECOND; + lastTime = now; + + //print("secondsSinceLast:" + secondsSinceLast); + + //print("x part:" + xPart); + //print("y part:" + yPart); + + var dX = (xPart * MOVE_SCALE) / secondsSinceLast; + var dY = (yPart * MOVE_SCALE) / secondsSinceLast; + + //print("dX:" + dX); + //print("dY:" + dY); + + moveReticle(dX, dY); }); mapping.enable(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fa5565417d..045b8beb40 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -686,13 +686,37 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : } else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) { VrMenu::toggle(); // show context menu even on non-stereo displays } else if (action == controller::toInt(controller::Action::RETICLE_X)) { - auto globalPos = QCursor::pos(); - globalPos.setX(globalPos.x() + state); - QCursor::setPos(globalPos); + auto oldPos = QCursor::pos(); + auto newPos = oldPos; + newPos.setX(oldPos.x() + state); + QCursor::setPos(newPos); + + + // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, + // remove it after we're done + const float REASONABLE_CHANGE = 50.0f; + glm::vec2 oldPosG = { oldPos.x(), oldPos.y() }; + glm::vec2 newPosG = { newPos.x(), newPos.y() }; + auto distance = glm::distance(oldPosG, newPosG); + if (distance > REASONABLE_CHANGE) { + qDebug() << "Action::RETICLE_X... UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPosG << " newPos:" << newPosG; + } + } else if (action == controller::toInt(controller::Action::RETICLE_Y)) { - auto globalPos = QCursor::pos(); - globalPos.setY(globalPos.y() + state); - QCursor::setPos(globalPos); + auto oldPos = QCursor::pos(); + auto newPos = oldPos; + newPos.setY(oldPos.y() + state); + QCursor::setPos(newPos); + + // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, + // remove it after we're done + const float REASONABLE_CHANGE = 50.0f; + glm::vec2 oldPosG = { oldPos.x(), oldPos.y() }; + glm::vec2 newPosG = { newPos.x(), newPos.y() }; + auto distance = glm::distance(oldPosG, newPosG); + if (distance > REASONABLE_CHANGE) { + qDebug() << "Action::RETICLE_Y... UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPosG << " newPos:" << newPosG; + } } } }); diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index 9d3942cd55..52ec52e852 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -30,6 +30,7 @@ #include #include +#include #include "UserInputMapper.h" #include "StandardControls.h" @@ -88,8 +89,21 @@ namespace controller { Q_INVOKABLE QObject* parseMapping(const QString& json); Q_INVOKABLE QObject* loadMapping(const QString& jsonUrl); - Q_INVOKABLE glm::vec2 getReticlePosition() { return toGlm(QCursor::pos()); } - Q_INVOKABLE void setReticlePosition(glm::vec2 position) { QCursor::setPos(position.x, position.y); } + Q_INVOKABLE glm::vec2 getReticlePosition() { + return toGlm(QCursor::pos()); + } + Q_INVOKABLE void setReticlePosition(glm::vec2 position) { + // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, + // remove it after we're done + const float REASONABLE_CHANGE = 50.0f; + glm::vec2 oldPos = toGlm(QCursor::pos()); + auto distance = glm::distance(oldPos, position); + if (distance > REASONABLE_CHANGE) { + qDebug() << "Contrller::ScriptingInterface ---- UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPos << " newPos:" << position; + } + + QCursor::setPos(position.x, position.y); + } //Q_INVOKABLE bool isPrimaryButtonPressed() const; //Q_INVOKABLE glm::vec2 getPrimaryJoystickPosition() const;