From 8a0c1cab1e2cb7e4bb65912de809b74717974eea Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 21 May 2015 15:31:30 -0700 Subject: [PATCH] inspect now uses accurate picking and camera slerps to looks at target. pointer does not show u when user is inspecting --- examples/defaultScripts.js | 1 + examples/inspect.js | 424 ++++++++++++++++++++----------------- examples/pointer.js | 114 ++++++---- 3 files changed, 301 insertions(+), 238 deletions(-) diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index 89d4094856..ff22f68cb5 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -18,3 +18,4 @@ Script.load("notifications.js"); Script.load("look.js"); Script.load("users.js"); Script.load("grab.js"); +Script.load("pointer.js"); diff --git a/examples/inspect.js b/examples/inspect.js index d730a7e53f..e1f941497b 100644 --- a/examples/inspect.js +++ b/examples/inspect.js @@ -25,8 +25,18 @@ var ALTITUDE_RATE = 200.0; var RADIUS_RATE = 1.0 / 100.0; var PAN_RATE = 50.0; -var Y_AXIS = { x: 0, y: 1, z: 0 }; -var X_AXIS = { x: 1, y: 0, z: 0 }; +var Y_AXIS = { + x: 0, + y: 1, + z: 0 +}; +var X_AXIS = { + x: 1, + y: 0, + z: 0 +}; + +var LOOK_AT_TIME = 500; var alt = false; var shift = false; @@ -46,9 +56,21 @@ var mouseLastX = 0; var mouseLastY = 0; -var center = { x: 0, y: 0, z: 0 }; -var position = { x: 0, y: 0, z: 0 }; -var vector = { x: 0, y: 0, z: 0 }; +var center = { + x: 0, + y: 0, + z: 0 +}; +var position = { + x: 0, + y: 0, + z: 0 +}; +var vector = { + x: 0, + y: 0, + z: 0 +}; var radius = 0.0; var azimuth = 0.0; var altitude = 0.0; @@ -56,244 +78,262 @@ var altitude = 0.0; var avatarPosition; var avatarOrientation; +var rotatingTowardsTarget = false; +var targetCamOrientation; +var oldPosition, oldOrientation; + function orientationOf(vector) { - var direction, - yaw, - pitch; + var direction, + yaw, + pitch; - direction = Vec3.normalize(vector); - yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS); - pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS); - return Quat.multiply(yaw, pitch); + direction = Vec3.normalize(vector); + yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS); + pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS); + return Quat.multiply(yaw, pitch); } function handleRadialMode(dx, dy) { - azimuth += dx / AZIMUTH_RATE; - radius += radius * dy * RADIUS_RATE; - if (radius < 1) { - radius = 1; - } - - vector = { x: (Math.cos(altitude) * Math.cos(azimuth)) * radius, - y: Math.sin(altitude) * radius, - z: (Math.cos(altitude) * Math.sin(azimuth)) * radius }; - position = Vec3.sum(center, vector); - Camera.setPosition(position); - Camera.setOrientation(orientationOf(vector)); + azimuth += dx / AZIMUTH_RATE; + radius += radius * dy * RADIUS_RATE; + if (radius < 1) { + radius = 1; + } + + vector = { + x: (Math.cos(altitude) * Math.cos(azimuth)) * radius, + y: Math.sin(altitude) * radius, + z: (Math.cos(altitude) * Math.sin(azimuth)) * radius + }; + position = Vec3.sum(center, vector); + Camera.setPosition(position); + Camera.setOrientation(orientationOf(vector)); } function handleOrbitMode(dx, dy) { - azimuth += dx / AZIMUTH_RATE; - altitude += dy / ALTITUDE_RATE; - if (altitude > PI / 2.0) { - altitude = PI / 2.0; - } - if (altitude < -PI / 2.0) { - altitude = -PI / 2.0; - } - - vector = { x:(Math.cos(altitude) * Math.cos(azimuth)) * radius, - y:Math.sin(altitude) * radius, - z:(Math.cos(altitude) * Math.sin(azimuth)) * radius }; - position = Vec3.sum(center, vector); - Camera.setPosition(position); - Camera.setOrientation(orientationOf(vector)); + azimuth += dx / AZIMUTH_RATE; + altitude += dy / ALTITUDE_RATE; + if (altitude > PI / 2.0) { + altitude = PI / 2.0; + } + if (altitude < -PI / 2.0) { + altitude = -PI / 2.0; + } + + vector = { + x: (Math.cos(altitude) * Math.cos(azimuth)) * radius, + y: Math.sin(altitude) * radius, + z: (Math.cos(altitude) * Math.sin(azimuth)) * radius + }; + position = Vec3.sum(center, vector); + Camera.setPosition(position); + Camera.setOrientation(orientationOf(vector)); } function handlePanMode(dx, dy) { - var up = Quat.getUp(Camera.getOrientation()); - var right = Quat.getRight(Camera.getOrientation()); - var distance = Vec3.length(vector); - - var dv = Vec3.sum(Vec3.multiply(up, - distance * dy / PAN_RATE), Vec3.multiply(right, distance * dx / PAN_RATE)); - - center = Vec3.sum(center, dv); - position = Vec3.sum(position, dv); - - Camera.setPosition(position); - Camera.setOrientation(orientationOf(vector)); + var up = Quat.getUp(Camera.getOrientation()); + var right = Quat.getRight(Camera.getOrientation()); + var distance = Vec3.length(vector); + + var dv = Vec3.sum(Vec3.multiply(up, -distance * dy / PAN_RATE), Vec3.multiply(right, distance * dx / PAN_RATE)); + + center = Vec3.sum(center, dv); + position = Vec3.sum(position, dv); + + Camera.setPosition(position); + Camera.setOrientation(orientationOf(vector)); } function saveCameraState() { - oldMode = Camera.mode; - var oldPosition = Camera.getPosition(); - Camera.mode = "independent"; - Camera.setPosition(oldPosition); + oldMode = Camera.mode; + oldPosition = Camera.getPosition(); + oldOrientation = Camera.getOrientation(); + + Camera.mode = "independent"; + Camera.setPosition(oldPosition); } function restoreCameraState() { - Camera.mode = oldMode; + Camera.mode = oldMode; + Camera.setPosition(oldPosition); + Camera.setOrientation(oldOrientation); } function handleModes() { - var newMode = (mode == noMode) ? noMode : detachedMode; - if (alt) { - if (control) { - if (shift) { - newMode = panningMode; - } else { - newMode = orbitMode; - } - } else { - newMode = radialMode; - } - } - - // if entering detachMode - if (newMode == detachedMode && mode != detachedMode) { - avatarPosition = MyAvatar.position; - avatarOrientation = MyAvatar.orientation; - } - // if leaving detachMode - if (mode == detachedMode && newMode == detachedMode && - (avatarPosition.x != MyAvatar.position.x || - avatarPosition.y != MyAvatar.position.y || - avatarPosition.z != MyAvatar.position.z || - avatarOrientation.x != MyAvatar.orientation.x || - avatarOrientation.y != MyAvatar.orientation.y || - avatarOrientation.z != MyAvatar.orientation.z || - avatarOrientation.w != MyAvatar.orientation.w)) { - newMode = noMode; + var newMode = (mode == noMode) ? noMode : detachedMode; + if (alt) { + if (control) { + if (shift) { + newMode = panningMode; + } else { + newMode = orbitMode; + } + } else { + newMode = radialMode; } + } - if (mode == noMode && newMode != noMode && Camera.mode == "independent") { - newMode = noMode; - } + // if entering detachMode + if (newMode == detachedMode && mode != detachedMode) { + avatarPosition = MyAvatar.position; + avatarOrientation = MyAvatar.orientation; + } + // if leaving detachMode + if (mode == detachedMode && newMode == detachedMode && + (avatarPosition.x != MyAvatar.position.x || + avatarPosition.y != MyAvatar.position.y || + avatarPosition.z != MyAvatar.position.z || + avatarOrientation.x != MyAvatar.orientation.x || + avatarOrientation.y != MyAvatar.orientation.y || + avatarOrientation.z != MyAvatar.orientation.z || + avatarOrientation.w != MyAvatar.orientation.w)) { + newMode = noMode; + } - // if leaving noMode - if (mode == noMode && newMode != noMode) { - saveCameraState(); - } - // if entering noMode - if (newMode == noMode && mode != noMode) { - restoreCameraState(); - } - - mode = newMode; + if (mode == noMode && newMode != noMode && Camera.mode == "independent") { + newMode = noMode; + } + + // if leaving noMode + if (mode == noMode && newMode != noMode) { + saveCameraState(); + } + // if entering noMode + if (newMode == noMode && mode != noMode) { + restoreCameraState(); + } + + mode = newMode; } function keyPressEvent(event) { - var changed = false; - - if (event.text == "ALT") { - alt = true; - changed = true; - } - if (event.text == "CONTROL") { - control = true; - changed = true; - } - if (event.text == "SHIFT") { - shift = true; - changed = true; - } - - if (changed) { - handleModes(); - } + var changed = false; + + if (event.text == "ALT") { + alt = true; + changed = true; + } + if (event.text == "CONTROL") { + control = true; + changed = true; + } + if (event.text == "SHIFT") { + shift = true; + changed = true; + } + + if (changed) { + handleModes(); + } } function keyReleaseEvent(event) { - var changed = false; - - if (event.text == "ALT") { - alt = false; - changed = true; - } - if (event.text == "CONTROL") { - control = false; - changed = true; - } - if (event.text == "SHIFT") { - shift = false; - changed = true; - } - - if (changed) { - handleModes(); - } + var changed = false; + + if (event.text == "ALT") { + alt = false; + changed = true; + mode = noMode; + restoreCameraState(); + } + if (event.text == "CONTROL") { + control = false; + changed = true; + } + if (event.text == "SHIFT") { + shift = false; + changed = true; + } + + if (changed) { + handleModes(); + } } function mousePressEvent(event) { - if (alt && !isActive) { - mouseLastX = event.x; - mouseLastY = event.y; - - // Compute trajectories related values - var pickRay = Camera.computePickRay(mouseLastX, mouseLastY); - var modelIntersection = Entities.findRayIntersection(pickRay); - - position = Camera.getPosition(); - - var avatarTarget = MyAvatar.getTargetAvatarPosition(); - - - var distance = -1; - var string; - - if (modelIntersection.intersects && modelIntersection.accurate) { - distance = modelIntersection.distance; - center = modelIntersection.properties.position; - string = "Inspecting model"; - } - - if ((distance == -1 || Vec3.length(Vec3.subtract(avatarTarget, position)) < distance) && - (avatarTarget.x != 0 || avatarTarget.y != 0 || avatarTarget.z != 0)) { - distance = Vec3.length(Vec3.subtract(avatarTarget, position)); - center = avatarTarget; - string = "Inspecting avatar"; - } - - if (distance == -1) { - return; - } - - vector = Vec3.subtract(position, center); - radius = Vec3.length(vector); - azimuth = Math.atan2(vector.z, vector.x); - altitude = Math.asin(vector.y / Vec3.length(vector)); - - print(string); - isActive = true; + if (alt && !isActive) { + mouseLastX = event.x; + mouseLastY = event.y; + + // Compute trajectories related values + var pickRay = Camera.computePickRay(mouseLastX, mouseLastY); + var modelIntersection = Entities.findRayIntersection(pickRay, true); + + position = Camera.getPosition(); + + var avatarTarget = MyAvatar.getTargetAvatarPosition(); + + + var distance = -1; + var string; + + if (modelIntersection.intersects && modelIntersection.accurate) { + distance = modelIntersection.distance; + center = modelIntersection.intersection; + string = "Inspecting model"; + //We've selected our target, now orbit towards it automatically + rotatingTowardsTarget = true; + //calculate our target cam rotation + Script.setTimeout(function() { + rotatingTowardsTarget = false; + }, LOOK_AT_TIME); + + vector = Vec3.subtract(position, center); + targetCamOrientation = orientationOf(vector); + radius = Vec3.length(vector); + azimuth = Math.atan2(vector.z, vector.x); + altitude = Math.asin(vector.y / Vec3.length(vector)); + + isActive = true; } + + } } function mouseReleaseEvent(event) { - if (isActive) { - isActive = false; - } + if (isActive) { + isActive = false; + } } function mouseMoveEvent(event) { - if (isActive && mode != noMode) { - if (mode == radialMode) { - handleRadialMode(event.x - mouseLastX, event.y - mouseLastY); - } - if (mode == orbitMode) { - handleOrbitMode(event.x - mouseLastX, event.y - mouseLastY); - } - if (mode == panningMode) { - handlePanMode(event.x - mouseLastX, event.y - mouseLastY); - } - - mouseLastX = event.x; - mouseLastY = event.y; + if (isActive && mode != noMode && !rotatingTowardsTarget) { + if (mode == radialMode) { + handleRadialMode(event.x - mouseLastX, event.y - mouseLastY); } + if (mode == orbitMode) { + handleOrbitMode(event.x - mouseLastX, event.y - mouseLastY); + } + if (mode == panningMode) { + handlePanMode(event.x - mouseLastX, event.y - mouseLastY); + } + + } + mouseLastX = event.x; + mouseLastY = event.y; } function update() { - handleModes(); + handleModes(); + if (rotatingTowardsTarget) { + rotateTowardsTarget(); + } +} + +function rotateTowardsTarget() { + var newOrientation = Quat.mix(Camera.getOrientation(), targetCamOrientation, .1); + Camera.setOrientation(newOrientation); } function scriptEnding() { - if (mode != noMode) { - restoreCameraState(); - } + if (mode != noMode) { + restoreCameraState(); + } } Controller.keyPressEvent.connect(keyPressEvent); diff --git a/examples/pointer.js b/examples/pointer.js index dfb79569f7..cdfb93f2d3 100644 --- a/examples/pointer.js +++ b/examples/pointer.js @@ -1,77 +1,99 @@ - var lineEntityID = null; var lineIsRezzed = false; - +var altHeld = false; +var lineCreated = false; function nearLinePoint(targetPosition) { - var handPosition = MyAvatar.getRightPalmPosition(); - var along = Vec3.subtract(targetPosition, handPosition); - along = Vec3.normalize(along); - along = Vec3.multiply(along, 0.4); - return Vec3.sum(handPosition, along); + var handPosition = MyAvatar.getRightPalmPosition(); + var along = Vec3.subtract(targetPosition, handPosition); + along = Vec3.normalize(along); + along = Vec3.multiply(along, 0.4); + return Vec3.sum(handPosition, along); } function removeLine() { - if (lineIsRezzed) { - Entities.deleteEntity(lineEntityID); - lineEntityID = null; - lineIsRezzed = false; - } + if (lineIsRezzed) { + Entities.deleteEntity(lineEntityID); + lineEntityID = null; + lineIsRezzed = false; + } } function createOrUpdateLine(event) { - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking - var props = Entities.getEntityProperties(intersection.entityID); + var pickRay = Camera.computePickRay(event.x, event.y); + var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking + var props = Entities.getEntityProperties(intersection.entityID); - if (intersection.intersects) { - var dim = Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection)); - if (lineIsRezzed) { - Entities.editEntity(lineEntityID, { - position: nearLinePoint(intersection.intersection), - dimensions: dim, - lifetime: 15 + props.lifespan // renew lifetime - }); - } else { - lineIsRezzed = true; - lineEntityID = Entities.addEntity({ - type: "Line", - position: nearLinePoint(intersection.intersection), - dimensions: dim, - color: { red: 255, green: 255, blue: 255 }, - lifetime: 15 // if someone crashes while pointing, don't leave the line there forever. - }); - } + if (intersection.intersects) { + var dim = Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection)); + if (lineIsRezzed) { + Entities.editEntity(lineEntityID, { + position: nearLinePoint(intersection.intersection), + dimensions: dim, + lifetime: 15 + props.lifespan // renew lifetime + }); } else { - removeLine(); + lineIsRezzed = true; + lineEntityID = Entities.addEntity({ + type: "Line", + position: nearLinePoint(intersection.intersection), + dimensions: dim, + color: { + red: 255, + green: 255, + blue: 255 + }, + lifetime: 15 // if someone crashes while pointing, don't leave the line there forever. + }); } + } else { + removeLine(); + } } function mousePressEvent(event) { - if (!event.isLeftButton) { - return; - } - Controller.mouseMoveEvent.connect(mouseMoveEvent); - createOrUpdateLine(event); - } + if (!event.isLeftButton || altHeld) { + return; + } + Controller.mouseMoveEvent.connect(mouseMoveEvent); + createOrUpdateLine(event); + lineCreated = true; +} function mouseMoveEvent(event) { - createOrUpdateLine(event); + createOrUpdateLine(event); } function mouseReleaseEvent(event) { - if (!event.isLeftButton) { - return; - } - Controller.mouseMoveEvent.disconnect(mouseMoveEvent); - removeLine(); + if (!lineCreated) { + return; + } + Controller.mouseMoveEvent.disconnect(mouseMoveEvent); + removeLine(); + lineCreated = false; +} + +function keyPressEvent(event) { + if (event.text == "ALT") { + altHeld = true; + } +} + +function keyReleaseEvent(event) { + if (event.text == "ALT") { + altHeld = false; + } + } Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); + +Controller.keyPressEvent.connect(keyPressEvent); +Controller.keyReleaseEvent.connect(keyReleaseEvent); \ No newline at end of file