From e516281da8c3993be8a702e766145eef0153556a Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 30 Sep 2015 16:15:52 -0700 Subject: [PATCH 1/8] Added closePaint script and removed no longer used spray paint scripts --- examples/closePaint.js | 258 ++++++++++++++++++++++++ examples/entityScripts/sprayPaintCan.js | 252 ----------------------- examples/sprayPaintSpawner.js | 41 ---- 3 files changed, 258 insertions(+), 293 deletions(-) create mode 100644 examples/closePaint.js delete mode 100644 examples/entityScripts/sprayPaintCan.js delete mode 100644 examples/sprayPaintSpawner.js diff --git a/examples/closePaint.js b/examples/closePaint.js new file mode 100644 index 0000000000..dc3e567823 --- /dev/null +++ b/examples/closePaint.js @@ -0,0 +1,258 @@ +// +// closePaint.js +// examples +// +// Created by Eric Levina on 9/30/15. +// Copyright 2015 High Fidelity, Inc. +// +// Run this script to be able to paint on entities you are close to, with hydras. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +var RIGHT_HAND = 1; +var LEFT_HAND = 0; + +var MIN_POINT_DISTANCE = 0.01; +var MAX_POINT_DISTANCE = 0.5; + +var SPATIAL_CONTROLLERS_PER_PALM = 2; +var TIP_CONTROLLER_OFFSET = 1; + +var TRIGGER_ON_VALUE = 0.3; + +var MAX_DISTANCE = 10; + +var STROKE_WIDTH = 0.02 +var MAX_POINTS_PER_LINE = 60; + + +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(Camera.getOrientation()))); + + + +function MyController(hand, triggerAction) { + this.hand = hand; + this.strokes = []; + this.painting = false; + + if (this.hand === RIGHT_HAND) { + this.getHandPosition = MyAvatar.getRightPalmPosition; + this.getHandRotation = MyAvatar.getRightPalmRotation; + } else { + this.getHandPosition = MyAvatar.getLeftPalmPosition; + this.getHandRotation = MyAvatar.getLeftPalmRotation; + } + + this.triggerAction = triggerAction; + this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand; + this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; + + + this.strokeColor = { + red: 200, + green: 20, + blue: 40 + }; + + this.laserPointer = Overlays.addOverlay("circle3d", { + size: { + x: STROKE_WIDTH / 2, + y: STROKE_WIDTH / 2 + }, + color: this.strokeColor, + solid: true, + position: center + }) + this.triggerValue = 0; + this.prevTriggerValue = 0; + var _this = this; + + + this.update = function() { + this.updateControllerState() + this.search(); + if (this.canPaint === true) { + this.paint(this.intersection.intersection, this.intersection.surfaceNormal); + } + }; + + this.paint = function(position, normal) { + // print("POSITION " + position.z) + if (this.painting === false) { + if (this.oldPosition) { + this.newStroke(this.oldPosition); + } else { + this.newStroke(position); + } + this.painting = true; + } + + + + var localPoint = Vec3.subtract(position, this.strokeBasePosition); + //Move stroke a bit forward along normal so it doesnt zfight with mesh its drawing on + localPoint = Vec3.sum(localPoint, Vec3.multiply(normal, 0.001 + Math.random() * .001)); //rand avoid z fighting + + var distance = Vec3.distance(localPoint, this.strokePoints[this.strokePoints.length - 1]); + if (this.strokePoints.length > 0 && distance < MIN_POINT_DISTANCE) { + //need a minimum distance to avoid binormal NANs + return; + } + if(this.strokePoints.length > 0 && distance > MAX_POINT_DISTANCE) { + //Prevents drawing lines accross models + this.painting = false; + return; + } + if(this.strokePoints.length === 0) { + localPoint = {x: 0, y: 0, z: 0}; + } + + this.strokePoints.push(localPoint); + this.strokeNormals.push(normal); + this.strokeWidths.push(STROKE_WIDTH); + Entities.editEntity(this.currentStroke, { + linePoints: this.strokePoints, + normals: this.strokeNormals, + strokeWidths: this.strokeWidths + }); + if (this.strokePoints.length === MAX_POINTS_PER_LINE) { + this.painting = false; + return; + } + this.oldPosition = position + + } + + this.newStroke = function(position) { + this.strokeBasePosition = position; + this.currentStroke = Entities.addEntity({ + position: position, + type: "PolyLine", + color: this.strokeColor, + dimensions: { + x: 50, + y: 50, + z: 50 + }, + lifetime: 100 + }); + this.strokePoints = []; + this.strokeNormals = []; + this.strokeWidths = []; + + this.strokes.push(this.currentStroke); + + } + + this.updateControllerState = function() { + var triggerValue = Controller.getActionValue(this.triggerAction); + if (triggerValue > TRIGGER_ON_VALUE && this.prevTriggerValue <= TRIGGER_ON_VALUE) { + this.squeeze(); + } else if (triggerValue < TRIGGER_ON_VALUE && this.prevTriggerValue >= TRIGGER_ON_VALUE) { + this.release() + } + + this.prevTriggerValue = triggerValue; + } + + this.squeeze = function() { + this.tryPainting = true; + + } + this.release = function() { + this.painting = false; + this.tryPainting = false; + this.canPaint = false; + this.oldPosition = null; + } + this.search = function() { + + // the trigger is being pressed, do a ray test + var handPosition = this.getHandPosition(); + var pickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()) + }; + + + this.intersection = Entities.findRayIntersection(pickRay, true); + if (this.intersection.intersects) { + var distance = Vec3.distance(handPosition, this.intersection.intersection); + if (distance < MAX_DISTANCE) { + var displayPoint = this.intersection.intersection; + displayPoint = Vec3.sum(displayPoint, Vec3.multiply(this.intersection.surfaceNormal, .001)); + if (this.tryPainting) { + this.canPaint = true; + } + Overlays.editOverlay(this.laserPointer, { + visible: true, + position: displayPoint, + rotation: orientationOf(this.intersection.surfaceNormal) + }); + + } else { + this.hitFail(); + } + } else { + this.hitFail(); + } + }; + + this.hitFail = function() { + this.canPaint = false; + + Overlays.editOverlay(this.laserPointer, { + visible: false + }); + + } + + this.cleanup = function() { + Overlays.deleteOverlay(this.laserPointer); + this.strokes.forEach(function(stroke) { + Entities.deleteEntity(stroke); + }); + } +} + +var rightController = new MyController(RIGHT_HAND, Controller.findAction("RIGHT_HAND_CLICK")); +var leftController = new MyController(LEFT_HAND, Controller.findAction("LEFT_HAND_CLICK")); + +function update() { + rightController.update(); + leftController.update(); +} + +function cleanup() { + rightController.cleanup(); + leftController.cleanup(); +} + +Script.scriptEnding.connect(cleanup); +Script.update.connect(update); + + +function orientationOf(vector) { + var Y_AXIS = { + x: 0, + y: 1, + z: 0 + }; + var X_AXIS = { + x: 1, + y: 0, + z: 0 + }; + + var theta = 0.0; + + var RAD_TO_DEG = 180.0 / Math.PI; + 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); +} \ No newline at end of file diff --git a/examples/entityScripts/sprayPaintCan.js b/examples/entityScripts/sprayPaintCan.js deleted file mode 100644 index 21613bdeb5..0000000000 --- a/examples/entityScripts/sprayPaintCan.js +++ /dev/null @@ -1,252 +0,0 @@ -(function() { - // Script.include("../libraries/utils.js"); - //Need absolute path for now, for testing before PR merge and s3 cloning. Will change post-merge - - Script.include("../libraries/utils.js"); - GRAB_FRAME_USER_DATA_KEY = "grabFrame"; - this.userData = {}; - - var TIP_OFFSET_Z = 0.14; - var TIP_OFFSET_Y = 0.04; - - var ZERO_VEC = { - x: 0, - y: 0, - z: 0 - } - - var MAX_POINTS_PER_LINE = 40; - var MIN_POINT_DISTANCE = 0.01; - var STROKE_WIDTH = 0.02; - - var self = this; - - var timeSinceLastMoved = 0; - var RESET_TIME_THRESHOLD = 5; - var DISTANCE_FROM_HOME_THRESHOLD = 0.5; - var HOME_POSITION = { - x: 549.12, - y: 495.555, - z: 503.77 - }; - this.getUserData = function() { - - - if (this.properties.userData) { - this.userData = JSON.parse(this.properties.userData); - } - } - - this.updateUserData = function() { - Entities.editEntity(this.entityId, { - userData: JSON.stringify(this.userData) - }); - } - - this.update = function(deltaTime) { - self.getUserData(); - self.properties = Entities.getEntityProperties(self.entityId); - - if (Vec3.length(self.properties.velocity) < 0.1 && Vec3.distance(HOME_POSITION, self.properties.position) > DISTANCE_FROM_HOME_THRESHOLD) { - timeSinceLastMoved += deltaTime; - if (timeSinceLastMoved > RESET_TIME_THRESHOLD) { - self.reset(); - timeSinceLastMoved = 0; - } - } else { - timeSinceLastMoved = 0; - } - - //Only activate for the user who grabbed the object - if (self.userData.grabKey && self.userData.grabKey.activated === true && self.userData.grabKey.avatarId == MyAvatar.sessionUUID) { - if (self.activated !== true) { - //We were just grabbed, so create a particle system - self.grab(); - } - //Move emitter to where entity is always when its activated - self.sprayStream(); - } else if (self.userData.grabKey && self.userData.grabKey.activated === false && self.activated) { - self.letGo(); - } - } - - this.grab = function() { - this.activated = true; - var animationSettings = JSON.stringify({ - fps: 30, - loop: true, - firstFrame: 1, - lastFrame: 10000, - running: true - }); - var PI = 3.141593; - var DEG_TO_RAD = PI / 180.0; - - this.paintStream = Entities.addEntity({ - type: "ParticleEffect", - animationSettings: animationSettings, - position: this.properties.position, - textures: "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png", - emitSpeed: 0, - speedSpread: 0.02, - polarFinish: 2 * DEG_TO_RAD, - emitAcceleration: ZERO_VEC, - emitRate: 100, - particleRadius: 0.01, - color: { - red: 170, - green: 20, - blue: 150 - }, - lifetime: 50, //probably wont be holding longer than this straight - }); - } - - this.letGo = function() { - this.activated = false; - Entities.deleteEntity(this.paintStream); - this.paintStream = null; - } - - this.reset = function() { - Entities.editEntity(self.entityId, { - position: HOME_POSITION, - rotation: Quat.fromPitchYawRollDegrees(0, 0, 0), - angularVelocity: ZERO_VEC, - velocity: ZERO_VEC - }); - } - - this.sprayStream = function() { - var forwardVec = Quat.getFront(Quat.multiply(self.properties.rotation , Quat.fromPitchYawRollDegrees(0, 90, 0))); - forwardVec = Vec3.normalize(forwardVec); - - var upVec = Quat.getUp(self.properties.rotation); - var position = Vec3.sum(self.properties.position, Vec3.multiply(forwardVec, TIP_OFFSET_Z)); - position = Vec3.sum(position, Vec3.multiply(upVec, TIP_OFFSET_Y)) - Entities.editEntity(self.paintStream, { - position: position, - emitOrientation: forwardVec, - emitSpeed: 5 - }); - - //Now check for an intersection with an entity - //move forward so ray doesnt intersect with gun - var origin = Vec3.sum(position, forwardVec); - var pickRay = { - origin: origin, - direction: Vec3.multiply(forwardVec, 2) - } - - var intersection = Entities.findRayIntersection(pickRay, true); - if (intersection.intersects) { - var normal = Vec3.multiply(-1, Quat.getFront(intersection.properties.rotation)); - this.paint(intersection.intersection, normal); - } - - - } - - this.paint = function(position, normal) { - if (!this.painting) { - - this.newStroke(position); - this.painting = true; - } - - if (this.strokePoints.length > MAX_POINTS_PER_LINE) { - this.painting = false; - return; - } - - var localPoint = Vec3.subtract(position, this.strokeBasePosition); - //Move stroke a bit forward along normal so it doesnt zfight with mesh its drawing on - localPoint = Vec3.sum(localPoint, Vec3.multiply(normal, .1)); - - if (this.strokePoints.length > 0 && Vec3.distance(localPoint, this.strokePoints[this.strokePoints.length - 1]) < MIN_POINT_DISTANCE) { - //need a minimum distance to avoid binormal NANs - return; - } - - this.strokePoints.push(localPoint); - this.strokeNormals.push(normal); - this.strokeWidths.push(STROKE_WIDTH); - Entities.editEntity(this.currentStroke, { - linePoints: this.strokePoints, - normals: this.strokeNormals, - strokeWidths: this.strokeWidths - }); - - - } - - this.newStroke = function(position) { - this.strokeBasePosition = position; - this.currentStroke = Entities.addEntity({ - position: position, - type: "PolyLine", - color: { - red: randInt(160, 250), - green: randInt(10, 20), - blue: randInt(190, 250) - }, - dimensions: { - x: 50, - y: 50, - z: 50 - }, - lifetime: 100 - }); - this.strokePoints = []; - this.strokeNormals = []; - this.strokeWidths = []; - - this.strokes.push(this.currentStroke); - } - - this.preload = function(entityId) { - this.strokes = []; - this.activated = false; - this.entityId = entityId; - this.properties = Entities.getEntityProperties(self.entityId); - this.getUserData(); - - //Only activate for the avatar who is grabbing the can! - if (this.userData.grabKey && this.userData.grabKey.activated) { - this.activated = true; - } - if (!this.userData.grabFrame) { - var data = { - relativePosition: { - x: 0, - y: 0, - z: 0 - }, - relativeRotation: Quat.fromPitchYawRollDegrees(0, 0, 0) - } - setEntityCustomData(GRAB_FRAME_USER_DATA_KEY, this.entityId, data); - } - } - - - this.unload = function() { - Script.update.disconnect(this.update); - if(this.paintStream) { - Entities.deleteEntity(this.paintStream); - } - this.strokes.forEach(function(stroke) { - Entities.deleteEntity(stroke); - }); - } - Script.update.connect(this.update); -}); - - - -function randFloat(min, max) { - return Math.random() * (max - min) + min; -} - -function randInt(min, max) { - return Math.floor(Math.random() * (max - min)) + min; -} \ No newline at end of file diff --git a/examples/sprayPaintSpawner.js b/examples/sprayPaintSpawner.js deleted file mode 100644 index 3b9cee6ef4..0000000000 --- a/examples/sprayPaintSpawner.js +++ /dev/null @@ -1,41 +0,0 @@ -// sprayPaintSpawner.js -// -// Created by Eric Levin on 9/3/15 -// Copyright 2015 High Fidelity, Inc. -// -// This is script spwans a spreay paint can model with the sprayPaintCan.js entity script attached -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -//Just temporarily using my own bucket here so others can test the entity. Once PR is tested and merged, then the entity script will appear in its proper place in S3, and I wil switch it -// var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v6 "; -var scriptURL = Script.resolvePath("entityScripts/sprayPaintCan.js?v2"); -var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; - -var sprayCan = Entities.addEntity({ - type: "Model", - name: "spraycan", - modelURL: modelURL, - position: {x: 549.12, y:495.55, z:503.77}, - rotation: {x: 0, y: 0, z: 0, w: 1}, - dimensions: { - x: 0.07, - y: 0.17, - z: 0.07 - }, - collisionsWillMove: true, - shapeType: 'box', - script: scriptURL, - gravity: {x: 0, y: -0.5, z: 0}, - velocity: {x: 0, y: -1, z: 0} -}); - -function cleanup() { - - // Uncomment the below line to delete sprayCan on script reload- for faster iteration during development - // Entities.deleteEntity(sprayCan); -} - -Script.scriptEnding.connect(cleanup); - From 3592b78b2b1ea4e2c646a8f6385a8bafe4cfc022 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 30 Sep 2015 16:35:43 -0700 Subject: [PATCH 2/8] less points per line --- examples/closePaint.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/closePaint.js b/examples/closePaint.js index dc3e567823..fdd7d7cac6 100644 --- a/examples/closePaint.js +++ b/examples/closePaint.js @@ -26,7 +26,7 @@ var TRIGGER_ON_VALUE = 0.3; var MAX_DISTANCE = 10; var STROKE_WIDTH = 0.02 -var MAX_POINTS_PER_LINE = 60; +var MAX_POINTS_PER_LINE = 40; var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(Camera.getOrientation()))); @@ -221,6 +221,10 @@ function MyController(hand, triggerAction) { var rightController = new MyController(RIGHT_HAND, Controller.findAction("RIGHT_HAND_CLICK")); var leftController = new MyController(LEFT_HAND, Controller.findAction("LEFT_HAND_CLICK")); +Controller.actionEvent.connect(function(action, state) { + print("ACTION " + action) +}); + function update() { rightController.update(); leftController.update(); From 2899962d43f61990b36e78ed977a8e5443b9e579 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 30 Sep 2015 17:14:17 -0700 Subject: [PATCH 3/8] can now cycle colors with 4 and 2 buttons on hydra --- examples/closePaint.js | 100 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 12 deletions(-) diff --git a/examples/closePaint.js b/examples/closePaint.js index fdd7d7cac6..fba2aa0e80 100644 --- a/examples/closePaint.js +++ b/examples/closePaint.js @@ -28,6 +28,14 @@ var MAX_DISTANCE = 10; var STROKE_WIDTH = 0.02 var MAX_POINTS_PER_LINE = 40; +var RIGHT_4_ACTION = 18; +var RIGHT_2_ACTION = 16; + +var LEFT_4_ACTION = 17; +var LEFT_2_ACTION = 16; + +var HUE_INCREMENT = 0.01; + var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(Camera.getOrientation()))); @@ -52,9 +60,9 @@ function MyController(hand, triggerAction) { this.strokeColor = { - red: 200, - green: 20, - blue: 40 + h: 0.8, + s: 0.9, + l: 0.4 }; this.laserPointer = Overlays.addOverlay("circle3d", { @@ -62,7 +70,7 @@ function MyController(hand, triggerAction) { x: STROKE_WIDTH / 2, y: STROKE_WIDTH / 2 }, - color: this.strokeColor, + color: hslToRgb(this.strokeColor), solid: true, position: center }) @@ -80,7 +88,6 @@ function MyController(hand, triggerAction) { }; this.paint = function(position, normal) { - // print("POSITION " + position.z) if (this.painting === false) { if (this.oldPosition) { this.newStroke(this.oldPosition); @@ -101,13 +108,17 @@ function MyController(hand, triggerAction) { //need a minimum distance to avoid binormal NANs return; } - if(this.strokePoints.length > 0 && distance > MAX_POINT_DISTANCE) { + if (this.strokePoints.length > 0 && distance > MAX_POINT_DISTANCE) { //Prevents drawing lines accross models this.painting = false; return; } - if(this.strokePoints.length === 0) { - localPoint = {x: 0, y: 0, z: 0}; + if (this.strokePoints.length === 0) { + localPoint = { + x: 0, + y: 0, + z: 0 + }; } this.strokePoints.push(localPoint); @@ -122,8 +133,7 @@ function MyController(hand, triggerAction) { this.painting = false; return; } - this.oldPosition = position - + this.oldPosition = position } this.newStroke = function(position) { @@ -131,7 +141,7 @@ function MyController(hand, triggerAction) { this.currentStroke = Entities.addEntity({ position: position, type: "PolyLine", - color: this.strokeColor, + color: hslToRgb(this.strokeColor), dimensions: { x: 50, y: 50, @@ -216,13 +226,39 @@ function MyController(hand, triggerAction) { Entities.deleteEntity(stroke); }); } + + this.cycleColorDown = function() { + this.strokeColor.h -= HUE_INCREMENT; + if (this.strokeColor.h < 0) { + this.strokeColor = 1; + } + } + + this.cycleColorUp = function() { + this.strokeColor.h += HUE_INCREMENT; + if (this.strokeColor.h > 1) { + this.strokeColor.h = 0; + } + } } var rightController = new MyController(RIGHT_HAND, Controller.findAction("RIGHT_HAND_CLICK")); var leftController = new MyController(LEFT_HAND, Controller.findAction("LEFT_HAND_CLICK")); Controller.actionEvent.connect(function(action, state) { - print("ACTION " + action) + if (state === 0) { + return; + } + if (action === RIGHT_4_ACTION) { + rightController.cycleColorUp(); + } else if (action === RIGHT_2_ACTION) { + rightController.cycleColorDown(); + } + if (action === LEFT_4_ACTION) { + leftController.cycleColorUp(); + } else if (action === LEFT_2_ACTION) { + leftController.cycleColorDown(); + } }); function update() { @@ -259,4 +295,44 @@ function orientationOf(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); +} + +/** + * Converts an HSL color value to RGB. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes h, s, and l are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 255]. + * + * @param Number h The hue + * @param Number s The saturation + * @param Number l The lightness + * @return Array The RGB representation + */ +function hslToRgb(hsl) { + var r, g, b; + + if (hsl.s == 0) { + r = g = b = hsl.l; // achromatic + } else { + var hue2rgb = function hue2rgb(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + + var q = hsl.l < 0.5 ? hsl.l * (1 + hsl.s) : hsl.l + hsl.s - hsl.l * hsl.s; + var p = 2 * hsl.l - q; + r = hue2rgb(p, q, hsl.h + 1 / 3); + g = hue2rgb(p, q, hsl.h); + b = hue2rgb(p, q, hsl.h - 1 / 3); + } + + return { + red: Math.round(r * 255), + green: Math.round(g * 255), + blue: Math.round(b * 255) + }; } \ No newline at end of file From 191a4740a392905e148238aa60198749ea2b11fb Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 1 Oct 2015 09:50:58 -0700 Subject: [PATCH 4/8] laser color matches paint color --- examples/acScripts/rain.js | 6 ++++-- examples/closePaint.js | 17 +++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/examples/acScripts/rain.js b/examples/acScripts/rain.js index 3f38b8d36a..fc02b7163f 100644 --- a/examples/acScripts/rain.js +++ b/examples/acScripts/rain.js @@ -18,7 +18,7 @@ var RainSquall = function (properties) { dropFallSpeed = 1, // m/s dropLifetime = 60, // Seconds dropSpinMax = 0, // Maximum angular velocity per axis; deg/s - debug = false, // Display origin circle; don't use running on Stack Manager + debug = true, // Display origin circle; don't use running on Stack Manager // Other squallCircle, SQUALL_CIRCLE_COLOR = { red: 255, green: 0, blue: 0 }, @@ -151,8 +151,10 @@ var RainSquall = function (properties) { }; }; +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation()))); +center.y += 10; var rainSquall1 = new RainSquall({ - origin: { x: 1195, y: 1223, z: 1020 }, + origin:center, radius: 25, dropsPerMinute: 120, dropSize: { x: 0.1, y: 0.1, z: 0.1 }, diff --git a/examples/closePaint.js b/examples/closePaint.js index fba2aa0e80..c17402857b 100644 --- a/examples/closePaint.js +++ b/examples/closePaint.js @@ -34,7 +34,7 @@ var RIGHT_2_ACTION = 16; var LEFT_4_ACTION = 17; var LEFT_2_ACTION = 16; -var HUE_INCREMENT = 0.01; +var HUE_INCREMENT = 0.02; var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(Camera.getOrientation()))); @@ -61,16 +61,17 @@ function MyController(hand, triggerAction) { this.strokeColor = { h: 0.8, - s: 0.9, + s: 0.8, l: 0.4 }; + this.laserPointer = Overlays.addOverlay("circle3d", { size: { x: STROKE_WIDTH / 2, y: STROKE_WIDTH / 2 }, - color: hslToRgb(this.strokeColor), + color: hslToRgb(this.strokeColor ), solid: true, position: center }) @@ -78,7 +79,6 @@ function MyController(hand, triggerAction) { this.prevTriggerValue = 0; var _this = this; - this.update = function() { this.updateControllerState() this.search(); @@ -232,6 +232,9 @@ function MyController(hand, triggerAction) { if (this.strokeColor.h < 0) { this.strokeColor = 1; } + Overlays.editOverlay(this.laserPointer, { + color: hslToRgb(this.strokeColor) + }); } this.cycleColorUp = function() { @@ -239,6 +242,9 @@ function MyController(hand, triggerAction) { if (this.strokeColor.h > 1) { this.strokeColor.h = 0; } + Overlays.editOverlay(this.laserPointer, { + color: hslToRgb(this.strokeColor) + }); } } @@ -308,9 +314,8 @@ function orientationOf(vector) { * @param Number l The lightness * @return Array The RGB representation */ -function hslToRgb(hsl) { +function hslToRgb(hsl, hueOffset) { var r, g, b; - if (hsl.s == 0) { r = g = b = hsl.l; // achromatic } else { From ef5ad9eeb3eea43592872ec6a139898f00e32749 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 1 Oct 2015 11:02:22 -0700 Subject: [PATCH 5/8] Laser stays visible when further away from surfaces --- examples/closePaint.js | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/examples/closePaint.js b/examples/closePaint.js index c17402857b..fa692e0bbc 100644 --- a/examples/closePaint.js +++ b/examples/closePaint.js @@ -21,11 +21,10 @@ var MAX_POINT_DISTANCE = 0.5; var SPATIAL_CONTROLLERS_PER_PALM = 2; var TIP_CONTROLLER_OFFSET = 1; -var TRIGGER_ON_VALUE = 0.3; +var TRIGGER_ON_VALUE = 0.1; var MAX_DISTANCE = 10; -var STROKE_WIDTH = 0.02 var MAX_POINTS_PER_LINE = 40; var RIGHT_4_ACTION = 18; @@ -36,6 +35,9 @@ var LEFT_2_ACTION = 16; var HUE_INCREMENT = 0.02; +var MIN_STROKE_WIDTH = 0.005; +var MAX_STROKE_WIDTH = 0.03; + var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(Camera.getOrientation()))); @@ -45,6 +47,7 @@ function MyController(hand, triggerAction) { this.hand = hand; this.strokes = []; this.painting = false; + this.currentStrokeWidth = MIN_STROKE_WIDTH; if (this.hand === RIGHT_HAND) { this.getHandPosition = MyAvatar.getRightPalmPosition; @@ -67,11 +70,7 @@ function MyController(hand, triggerAction) { this.laserPointer = Overlays.addOverlay("circle3d", { - size: { - x: STROKE_WIDTH / 2, - y: STROKE_WIDTH / 2 - }, - color: hslToRgb(this.strokeColor ), + color: hslToRgb(this.strokeColor), solid: true, position: center }) @@ -123,7 +122,7 @@ function MyController(hand, triggerAction) { this.strokePoints.push(localPoint); this.strokeNormals.push(normal); - this.strokeWidths.push(STROKE_WIDTH); + this.strokeWidths.push(this.currentStrokeWidth); Entities.editEntity(this.currentStroke, { linePoints: this.strokePoints, normals: this.strokeNormals, @@ -158,14 +157,14 @@ function MyController(hand, triggerAction) { } this.updateControllerState = function() { - var triggerValue = Controller.getActionValue(this.triggerAction); - if (triggerValue > TRIGGER_ON_VALUE && this.prevTriggerValue <= TRIGGER_ON_VALUE) { + this.triggerValue = Controller.getActionValue(this.triggerAction); + if (this.triggerValue > TRIGGER_ON_VALUE && this.prevTriggerValue <= TRIGGER_ON_VALUE) { this.squeeze(); - } else if (triggerValue < TRIGGER_ON_VALUE && this.prevTriggerValue >= TRIGGER_ON_VALUE) { + } else if (this.triggerValue < TRIGGER_ON_VALUE && this.prevTriggerValue >= TRIGGER_ON_VALUE) { this.release() } - this.prevTriggerValue = triggerValue; + this.prevTriggerValue = this.triggerValue; } this.squeeze = function() { @@ -193,14 +192,21 @@ function MyController(hand, triggerAction) { var distance = Vec3.distance(handPosition, this.intersection.intersection); if (distance < MAX_DISTANCE) { var displayPoint = this.intersection.intersection; - displayPoint = Vec3.sum(displayPoint, Vec3.multiply(this.intersection.surfaceNormal, .001)); + displayPoint = Vec3.sum(displayPoint, Vec3.multiply(this.intersection.surfaceNormal, .01)); if (this.tryPainting) { this.canPaint = true; } + this.currentStrokeWidth = map(this.triggerValue, 0, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH); + var laserSize = map(distance, 1, MAX_DISTANCE, 0.001, 0.1); + laserSize += this.currentStrokeWidth/2; Overlays.editOverlay(this.laserPointer, { visible: true, position: displayPoint, - rotation: orientationOf(this.intersection.surfaceNormal) + rotation: orientationOf(this.intersection.surfaceNormal), + size: { + x: laserSize, + y: laserSize + } }); } else { @@ -340,4 +346,8 @@ function hslToRgb(hsl, hueOffset) { green: Math.round(g * 255), blue: Math.round(b * 255) }; +} + +function map(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); } \ No newline at end of file From 290659b9f6650c01e04721e19b16f4f66989b1bf Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 1 Oct 2015 11:46:37 -0700 Subject: [PATCH 6/8] increased lifetime --- examples/closePaint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/closePaint.js b/examples/closePaint.js index fa692e0bbc..136237d4b7 100644 --- a/examples/closePaint.js +++ b/examples/closePaint.js @@ -146,7 +146,7 @@ function MyController(hand, triggerAction) { y: 50, z: 50 }, - lifetime: 100 + lifetime: 200 }); this.strokePoints = []; this.strokeNormals = []; From 7ee26c5d4a8366b2f3399b2bcbe1e40108ce0176 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 1 Oct 2015 14:26:22 -0700 Subject: [PATCH 7/8] tweaked settings --- examples/closePaint.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/closePaint.js b/examples/closePaint.js index 136237d4b7..6590d7e14e 100644 --- a/examples/closePaint.js +++ b/examples/closePaint.js @@ -15,13 +15,13 @@ var RIGHT_HAND = 1; var LEFT_HAND = 0; -var MIN_POINT_DISTANCE = 0.01; +var MIN_POINT_DISTANCE = 0.02; var MAX_POINT_DISTANCE = 0.5; var SPATIAL_CONTROLLERS_PER_PALM = 2; var TIP_CONTROLLER_OFFSET = 1; -var TRIGGER_ON_VALUE = 0.1; +var TRIGGER_ON_VALUE = 0.3; var MAX_DISTANCE = 10; @@ -35,8 +35,8 @@ var LEFT_2_ACTION = 16; var HUE_INCREMENT = 0.02; -var MIN_STROKE_WIDTH = 0.005; -var MAX_STROKE_WIDTH = 0.03; +var MIN_STROKE_WIDTH = 0.002; +var MAX_STROKE_WIDTH = 0.04; var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(Camera.getOrientation()))); @@ -196,7 +196,7 @@ function MyController(hand, triggerAction) { if (this.tryPainting) { this.canPaint = true; } - this.currentStrokeWidth = map(this.triggerValue, 0, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH); + this.currentStrokeWidth = map(this.triggerValue, TRIGGER_ON_VALUE, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH); var laserSize = map(distance, 1, MAX_DISTANCE, 0.001, 0.1); laserSize += this.currentStrokeWidth/2; Overlays.editOverlay(this.laserPointer, { From e1b720d338b9acd15862340dd4ea2ef193e58a68 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 1 Oct 2015 15:18:44 -0700 Subject: [PATCH 8/8] Moved some functions to utils, fixed formatting --- examples/closePaint.js | 490 ++++++++++++++++-------------------- examples/libraries/utils.js | 66 +++++ 2 files changed, 279 insertions(+), 277 deletions(-) diff --git a/examples/closePaint.js b/examples/closePaint.js index 6590d7e14e..d9f70aab3c 100644 --- a/examples/closePaint.js +++ b/examples/closePaint.js @@ -11,6 +11,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +Script.include("libraries/utils.js"); + var RIGHT_HAND = 1; var LEFT_HAND = 0; @@ -44,310 +46,244 @@ var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(Camera.g function MyController(hand, triggerAction) { - this.hand = hand; - this.strokes = []; - this.painting = false; - this.currentStrokeWidth = MIN_STROKE_WIDTH; - - if (this.hand === RIGHT_HAND) { - this.getHandPosition = MyAvatar.getRightPalmPosition; - this.getHandRotation = MyAvatar.getRightPalmRotation; - } else { - this.getHandPosition = MyAvatar.getLeftPalmPosition; - this.getHandRotation = MyAvatar.getLeftPalmRotation; - } - - this.triggerAction = triggerAction; - this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand; - this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; - - - this.strokeColor = { - h: 0.8, - s: 0.8, - l: 0.4 - }; - - - this.laserPointer = Overlays.addOverlay("circle3d", { - color: hslToRgb(this.strokeColor), - solid: true, - position: center - }) - this.triggerValue = 0; - this.prevTriggerValue = 0; - var _this = this; - - this.update = function() { - this.updateControllerState() - this.search(); - if (this.canPaint === true) { - this.paint(this.intersection.intersection, this.intersection.surfaceNormal); - } - }; - - this.paint = function(position, normal) { - if (this.painting === false) { - if (this.oldPosition) { - this.newStroke(this.oldPosition); - } else { - this.newStroke(position); - } - this.painting = true; - } - - - - var localPoint = Vec3.subtract(position, this.strokeBasePosition); - //Move stroke a bit forward along normal so it doesnt zfight with mesh its drawing on - localPoint = Vec3.sum(localPoint, Vec3.multiply(normal, 0.001 + Math.random() * .001)); //rand avoid z fighting - - var distance = Vec3.distance(localPoint, this.strokePoints[this.strokePoints.length - 1]); - if (this.strokePoints.length > 0 && distance < MIN_POINT_DISTANCE) { - //need a minimum distance to avoid binormal NANs - return; - } - if (this.strokePoints.length > 0 && distance > MAX_POINT_DISTANCE) { - //Prevents drawing lines accross models - this.painting = false; - return; - } - if (this.strokePoints.length === 0) { - localPoint = { - x: 0, - y: 0, - z: 0 - }; - } - - this.strokePoints.push(localPoint); - this.strokeNormals.push(normal); - this.strokeWidths.push(this.currentStrokeWidth); - Entities.editEntity(this.currentStroke, { - linePoints: this.strokePoints, - normals: this.strokeNormals, - strokeWidths: this.strokeWidths - }); - if (this.strokePoints.length === MAX_POINTS_PER_LINE) { - this.painting = false; - return; - } - this.oldPosition = position - } - - this.newStroke = function(position) { - this.strokeBasePosition = position; - this.currentStroke = Entities.addEntity({ - position: position, - type: "PolyLine", - color: hslToRgb(this.strokeColor), - dimensions: { - x: 50, - y: 50, - z: 50 - }, - lifetime: 200 - }); - this.strokePoints = []; - this.strokeNormals = []; - this.strokeWidths = []; - - this.strokes.push(this.currentStroke); - - } - - this.updateControllerState = function() { - this.triggerValue = Controller.getActionValue(this.triggerAction); - if (this.triggerValue > TRIGGER_ON_VALUE && this.prevTriggerValue <= TRIGGER_ON_VALUE) { - this.squeeze(); - } else if (this.triggerValue < TRIGGER_ON_VALUE && this.prevTriggerValue >= TRIGGER_ON_VALUE) { - this.release() - } - - this.prevTriggerValue = this.triggerValue; - } - - this.squeeze = function() { - this.tryPainting = true; - - } - this.release = function() { + this.hand = hand; + this.strokes = []; this.painting = false; - this.tryPainting = false; - this.canPaint = false; - this.oldPosition = null; - } - this.search = function() { + this.currentStrokeWidth = MIN_STROKE_WIDTH; - // the trigger is being pressed, do a ray test - var handPosition = this.getHandPosition(); - var pickRay = { - origin: handPosition, - direction: Quat.getUp(this.getHandRotation()) + if (this.hand === RIGHT_HAND) { + this.getHandPosition = MyAvatar.getRightPalmPosition; + this.getHandRotation = MyAvatar.getRightPalmRotation; + } else { + this.getHandPosition = MyAvatar.getLeftPalmPosition; + this.getHandRotation = MyAvatar.getLeftPalmRotation; + } + + this.triggerAction = triggerAction; + this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand; + this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; + + + this.strokeColor = { + h: 0.8, + s: 0.8, + l: 0.4 }; - this.intersection = Entities.findRayIntersection(pickRay, true); - if (this.intersection.intersects) { - var distance = Vec3.distance(handPosition, this.intersection.intersection); - if (distance < MAX_DISTANCE) { - var displayPoint = this.intersection.intersection; - displayPoint = Vec3.sum(displayPoint, Vec3.multiply(this.intersection.surfaceNormal, .01)); - if (this.tryPainting) { - this.canPaint = true; + this.laserPointer = Overlays.addOverlay("circle3d", { + color: hslToRgb(this.strokeColor), + solid: true, + position: center + }); + this.triggerValue = 0; + this.prevTriggerValue = 0; + var _this = this; + + this.update = function() { + this.updateControllerState(); + this.search(); + if (this.canPaint === true) { + this.paint(this.intersection.intersection, this.intersection.surfaceNormal); } - this.currentStrokeWidth = map(this.triggerValue, TRIGGER_ON_VALUE, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH); - var laserSize = map(distance, 1, MAX_DISTANCE, 0.001, 0.1); - laserSize += this.currentStrokeWidth/2; + }; + + this.paint = function(position, normal) { + if (this.painting === false) { + if (this.oldPosition) { + this.newStroke(this.oldPosition); + } else { + this.newStroke(position); + } + this.painting = true; + } + + + + var localPoint = Vec3.subtract(position, this.strokeBasePosition); + //Move stroke a bit forward along normal so it doesnt zfight with mesh its drawing on + localPoint = Vec3.sum(localPoint, Vec3.multiply(normal, 0.001 + Math.random() * .001)); //rand avoid z fighting + + var distance = Vec3.distance(localPoint, this.strokePoints[this.strokePoints.length - 1]); + if (this.strokePoints.length > 0 && distance < MIN_POINT_DISTANCE) { + //need a minimum distance to avoid binormal NANs + return; + } + if (this.strokePoints.length > 0 && distance > MAX_POINT_DISTANCE) { + //Prevents drawing lines accross models + this.painting = false; + return; + } + if (this.strokePoints.length === 0) { + localPoint = { + x: 0, + y: 0, + z: 0 + }; + } + + this.strokePoints.push(localPoint); + this.strokeNormals.push(normal); + this.strokeWidths.push(this.currentStrokeWidth); + Entities.editEntity(this.currentStroke, { + linePoints: this.strokePoints, + normals: this.strokeNormals, + strokeWidths: this.strokeWidths + }); + if (this.strokePoints.length === MAX_POINTS_PER_LINE) { + this.painting = false; + return; + } + this.oldPosition = position; + } + + this.newStroke = function(position) { + this.strokeBasePosition = position; + this.currentStroke = Entities.addEntity({ + position: position, + type: "PolyLine", + color: hslToRgb(this.strokeColor), + dimensions: { + x: 50, + y: 50, + z: 50 + }, + lifetime: 200 + }); + this.strokePoints = []; + this.strokeNormals = []; + this.strokeWidths = []; + + this.strokes.push(this.currentStroke); + + } + + this.updateControllerState = function() { + this.triggerValue = Controller.getActionValue(this.triggerAction); + if (this.triggerValue > TRIGGER_ON_VALUE && this.prevTriggerValue <= TRIGGER_ON_VALUE) { + this.squeeze(); + } else if (this.triggerValue < TRIGGER_ON_VALUE && this.prevTriggerValue >= TRIGGER_ON_VALUE) { + this.release(); + } + + this.prevTriggerValue = this.triggerValue; + } + + this.squeeze = function() { + this.tryPainting = true; + + } + this.release = function() { + this.painting = false; + this.tryPainting = false; + this.canPaint = false; + this.oldPosition = null; + } + this.search = function() { + + // the trigger is being pressed, do a ray test + var handPosition = this.getHandPosition(); + var pickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()) + }; + + + this.intersection = Entities.findRayIntersection(pickRay, true); + if (this.intersection.intersects) { + var distance = Vec3.distance(handPosition, this.intersection.intersection); + if (distance < MAX_DISTANCE) { + var displayPoint = this.intersection.intersection; + displayPoint = Vec3.sum(displayPoint, Vec3.multiply(this.intersection.surfaceNormal, .01)); + if (this.tryPainting) { + this.canPaint = true; + } + this.currentStrokeWidth = map(this.triggerValue, TRIGGER_ON_VALUE, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH); + var laserSize = map(distance, 1, MAX_DISTANCE, 0.01, 0.1); + laserSize += this.currentStrokeWidth / 2; + Overlays.editOverlay(this.laserPointer, { + visible: true, + position: displayPoint, + rotation: orientationOf(this.intersection.surfaceNormal), + size: { + x: laserSize, + y: laserSize + } + }); + + } else { + this.hitFail(); + } + } else { + this.hitFail(); + } + }; + + this.hitFail = function() { + this.canPaint = false; + Overlays.editOverlay(this.laserPointer, { - visible: true, - position: displayPoint, - rotation: orientationOf(this.intersection.surfaceNormal), - size: { - x: laserSize, - y: laserSize - } + visible: false }); - } else { - this.hitFail(); - } - } else { - this.hitFail(); } - }; - this.hitFail = function() { - this.canPaint = false; - - Overlays.editOverlay(this.laserPointer, { - visible: false - }); - - } - - this.cleanup = function() { - Overlays.deleteOverlay(this.laserPointer); - this.strokes.forEach(function(stroke) { - Entities.deleteEntity(stroke); - }); - } - - this.cycleColorDown = function() { - this.strokeColor.h -= HUE_INCREMENT; - if (this.strokeColor.h < 0) { - this.strokeColor = 1; + this.cleanup = function() { + Overlays.deleteOverlay(this.laserPointer); + this.strokes.forEach(function(stroke) { + Entities.deleteEntity(stroke); + }); } - Overlays.editOverlay(this.laserPointer, { - color: hslToRgb(this.strokeColor) - }); - } - this.cycleColorUp = function() { - this.strokeColor.h += HUE_INCREMENT; - if (this.strokeColor.h > 1) { - this.strokeColor.h = 0; + this.cycleColorDown = function() { + this.strokeColor.h -= HUE_INCREMENT; + if (this.strokeColor.h < 0) { + this.strokeColor = 1; + } + Overlays.editOverlay(this.laserPointer, { + color: hslToRgb(this.strokeColor) + }); + } + + this.cycleColorUp = function() { + this.strokeColor.h += HUE_INCREMENT; + if (this.strokeColor.h > 1) { + this.strokeColor.h = 0; + } + Overlays.editOverlay(this.laserPointer, { + color: hslToRgb(this.strokeColor) + }); } - Overlays.editOverlay(this.laserPointer, { - color: hslToRgb(this.strokeColor) - }); - } } var rightController = new MyController(RIGHT_HAND, Controller.findAction("RIGHT_HAND_CLICK")); var leftController = new MyController(LEFT_HAND, Controller.findAction("LEFT_HAND_CLICK")); Controller.actionEvent.connect(function(action, state) { - if (state === 0) { - return; - } - if (action === RIGHT_4_ACTION) { - rightController.cycleColorUp(); - } else if (action === RIGHT_2_ACTION) { - rightController.cycleColorDown(); - } - if (action === LEFT_4_ACTION) { - leftController.cycleColorUp(); - } else if (action === LEFT_2_ACTION) { - leftController.cycleColorDown(); - } + if (state === 0) { + return; + } + if (action === RIGHT_4_ACTION) { + rightController.cycleColorUp(); + } else if (action === RIGHT_2_ACTION) { + rightController.cycleColorDown(); + } + if (action === LEFT_4_ACTION) { + leftController.cycleColorUp(); + } else if (action === LEFT_2_ACTION) { + leftController.cycleColorDown(); + } }); function update() { - rightController.update(); - leftController.update(); + rightController.update(); + leftController.update(); } function cleanup() { - rightController.cleanup(); - leftController.cleanup(); + rightController.cleanup(); + leftController.cleanup(); } Script.scriptEnding.connect(cleanup); Script.update.connect(update); - - -function orientationOf(vector) { - var Y_AXIS = { - x: 0, - y: 1, - z: 0 - }; - var X_AXIS = { - x: 1, - y: 0, - z: 0 - }; - - var theta = 0.0; - - var RAD_TO_DEG = 180.0 / Math.PI; - 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); -} - -/** - * Converts an HSL color value to RGB. Conversion formula - * adapted from http://en.wikipedia.org/wiki/HSL_color_space. - * Assumes h, s, and l are contained in the set [0, 1] and - * returns r, g, and b in the set [0, 255]. - * - * @param Number h The hue - * @param Number s The saturation - * @param Number l The lightness - * @return Array The RGB representation - */ -function hslToRgb(hsl, hueOffset) { - var r, g, b; - if (hsl.s == 0) { - r = g = b = hsl.l; // achromatic - } else { - var hue2rgb = function hue2rgb(p, q, t) { - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1 / 6) return p + (q - p) * 6 * t; - if (t < 1 / 2) return q; - if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; - return p; - } - - var q = hsl.l < 0.5 ? hsl.l * (1 + hsl.s) : hsl.l + hsl.s - hsl.l * hsl.s; - var p = 2 * hsl.l - q; - r = hue2rgb(p, q, hsl.h + 1 / 3); - g = hue2rgb(p, q, hsl.h); - b = hue2rgb(p, q, hsl.h - 1 / 3); - } - - return { - red: Math.round(r * 255), - green: Math.round(g * 255), - blue: Math.round(b * 255) - }; -} - -function map(value, min1, max1, min2, max2) { - return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); -} \ No newline at end of file diff --git a/examples/libraries/utils.js b/examples/libraries/utils.js index f6f635c73a..fa0f36cbb1 100644 --- a/examples/libraries/utils.js +++ b/examples/libraries/utils.js @@ -179,3 +179,69 @@ pointInExtents = function(point, minPoint, maxPoint) { (point.y >= minPoint.y && point.y <= maxPoint.y) && (point.z >= minPoint.z && point.z <= maxPoint.z); } + +/** + * Converts an HSL color value to RGB. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes h, s, and l are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 255]. + * + * @param Number h The hue + * @param Number s The saturation + * @param Number l The lightness + * @return Array The RGB representation + */ +hslToRgb = function(hsl, hueOffset) { + var r, g, b; + if (hsl.s == 0) { + r = g = b = hsl.l; // achromatic + } else { + var hue2rgb = function hue2rgb(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + + var q = hsl.l < 0.5 ? hsl.l * (1 + hsl.s) : hsl.l + hsl.s - hsl.l * hsl.s; + var p = 2 * hsl.l - q; + r = hue2rgb(p, q, hsl.h + 1 / 3); + g = hue2rgb(p, q, hsl.h); + b = hue2rgb(p, q, hsl.h - 1 / 3); + } + + return { + red: Math.round(r * 255), + green: Math.round(g * 255), + blue: Math.round(b * 255) + }; +} + +map = function(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); +} + +orientationOf = function(vector) { + var Y_AXIS = { + x: 0, + y: 1, + z: 0 + }; + var X_AXIS = { + x: 1, + y: 0, + z: 0 + }; + + var theta = 0.0; + + var RAD_TO_DEG = 180.0 / Math.PI; + 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); +} +