From 0ac4da285c49c1c62500f3c96729e36406ea993e Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 9 Sep 2015 09:48:39 -0700 Subject: [PATCH 01/58] Update bubblewand to not use overlays by default. --- examples/toys/bubblewand/bubble.js | 148 ++++++++++++++---- examples/toys/bubblewand/createWand.js | 37 +++-- examples/toys/bubblewand/wand.js | 204 ++++++++++++++----------- 3 files changed, 256 insertions(+), 133 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index 3cc68fecfa..e5f6d98e28 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -5,48 +5,140 @@ // Copyright 2015 High Fidelity, Inc. // // example of a nested entity. it doesn't do much now besides delete itself if it collides with something (bubbles are fragile! it would be cool if it sometimes merged with other bubbbles it hit) -// todo: play bubble sounds from the bubble itself instead of the wand. +// todo: play bubble sounds & particle bursts from the bubble itself instead of the wand. // blocker: needs some sound fixes and a way to find its own position before unload for spatialization // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - (function() { - // Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); - // Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); + Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); + Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); - //var popSound; + var POP_SOUNDS = [ + SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"), + SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop1.wav"), + SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop2.wav"), + SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop3.wav") + ] + + BUBBLE_PARTICLE_COLOR = { + red: 0, + green: 40, + blue: 255, + } + + var properties; + var checkPositionInterval; this.preload = function(entityID) { // print('bubble preload') - this.entityID = entityID; - // popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav"); + // var _t = this; + // _t.entityID = entityID; + // properties = Entities.getEntityProperties(entityID); + // checkPositionInterval = Script.setInterval(function() { + // properties = Entities.getEntityProperties(entityID); + // // print('properties AT CHECK::' + JSON.stringify(properties)); + // }, 200); + + // _t.loadShader(entityID); + }; + + this.loadShader = function(entityID) { + setEntityUserData(entityID, { + "ProceduralEntity": { + "shaderUrl": "http://localhost:8080/shaders/bubble.fs?" + randInt(0, 10000), + } + }) + }; + + + this.leaveEntity = function(entityID) { + print('LEAVE ENTITY:' + entityID) + }; + + this.collisionWithEntity = function(myID, otherID, collision) { + //Entities.deleteEntity(myID); + // Entities.deleteEntity(otherID); + }; + + // this.beforeUnload = function(entityID) { + // print('BEFORE UNLOAD:' + entityID); + // var properties = Entities.getEntityProperties(entityID); + // var position = properties.position; + // print('BEFOREUNLOAD PROPS' + JSON.stringify(position)); + + // }; + + this.unload = function(entityID) { + // Script.clearInterval(checkPositionInterval); + // var position = properties.position; + // this.endOfBubble(position); + var properties = Entities.getEntityProperties(entityID) + var position = properties.position; + //print('UNLOAD PROPS' + JSON.stringify(position)); + }; + + this.endOfBubble = function(position) { + this.burstBubbleSound(position); + this.createBurstParticles(position); + } + + this.burstBubbleSound = function(position) { + var audioOptions = { + volume: 0.5, + position: position + } + Audio.playSound(POP_SOUNDS[randInt(0, 4)], audioOptions); } - this.collisionWithEntity = function(myID, otherID, collision) { - //if(Entites.getEntityProperties(otherID).userData.objectType==='') { merge bubbles?} - // Entities.deleteEntity(myID); - // this.burstBubbleSound(collision.contactPoint) + this.createBurstParticles = function(position) { + var _t = this; + //get the current position of the bubble + var position = properties.position; + //var orientation = properties.orientation; - }; + var animationSettings = JSON.stringify({ + fps: 30, + frameIndex: 0, + running: true, + firstFrame: 0, + lastFrame: 30, + loop: false + }); - this.unload = function(entityID) { - // this.properties = Entities.getEntityProperties(entityID); - //var location = this.properties.position; - //this.burstBubbleSound(); - }; - - - - this.burstBubbleSound = function(location) { - - // var audioOptions = { - // volume: 0.5, - // position: location - // } - - //Audio.playSound(popSound, audioOptions); + var particleBurst = Entities.addEntity({ + type: "ParticleEffect", + animationSettings: animationSettings, + animationIsPlaying: true, + position: position, + lifetime: 1.0, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + emitVelocity: { + x: 0, + y: -1, + z: 0 + }, + velocitySpread: { + x: 1, + y: 0, + z: 1 + }, + emitAcceleration: { + x: 0, + y: -1, + z: 0 + }, + textures: "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png", + color: BUBBLE_PARTICLE_COLOR, + lifespan: 1.0, + visible: true, + locked: false + }); } diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 15c347d62a..943ea8fdbb 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -4,7 +4,7 @@ // Created by James B. Pollack @imgntn -- 09/03/2015 // Copyright 2015 High Fidelity, Inc. // -// Loads a wand model and attaches the bubble wand behavior. +// Loads a wand model and attaches the bubble wand behavior. // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -13,29 +13,34 @@ Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); -var wandModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx?" + randInt(0, 10000); -var scriptURL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?" + randInt(1, 100500) +var wandModel = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx?' + randInt(0, 10000); +var wandCollisionShape = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj?' + randInt(0, 10000); +var scriptURL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?' + randInt(0, 10000); +//for local testing +//var scriptURL = "http://localhost:8080/scripts/wand.js?" + randInt(0, 10000); //create the wand in front of the avatar var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation()))); + var wand = Entities.addEntity({ - type: "Model", - modelURL: wandModel, - position: center, - dimensions: { - x: 0.1, - y: 1, - z: 0.1 - }, - //must be enabled to be grabbable in the physics engine - collisionsWillMove: true, - shapeType: 'box', - script: scriptURL + type: "Model", + modelURL: wandModel, + position: center, + dimensions: { + x: 0.1, + y: 1, + z: 0.1 + }, + //must be enabled to be grabbable in the physics engine + + collisionsWillMove: true, + compoundShapeURL: wandCollisionShape, + script: scriptURL }); function cleanup() { - Entities.deleteEntity(wand); + Entities.deleteEntity(wand); } diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index be1042ab79..d98e0a8f57 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -20,10 +20,22 @@ function convertRange(value, r1, r2) { Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); var bubbleModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; - var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); var popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav"); + var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); + //for local testing + // var bubbleScript = 'http://localhost:8080/scripts/bubble.js?' + randInt(1, 10000); - var TARGET_SIZE = 0.4; + var POP_SOUNDS = [ + SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"), + SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop1.wav"), + SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop2.wav"), + SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop3.wav") + ] + + var overlays = false; + + //debug overlays for hand position to detect when wand is near avatar head + var TARGET_SIZE = 0.5; var TARGET_COLOR = { red: 128, green: 128, @@ -36,40 +48,46 @@ function convertRange(value, r1, r2) { }; var HAND_SIZE = 0.25; - var leftCubePosition = MyAvatar.getLeftPalmPosition(); - var rightCubePosition = MyAvatar.getRightPalmPosition(); - var leftHand = Overlays.addOverlay("cube", { - position: leftCubePosition, - size: HAND_SIZE, - color: { - red: 0, - green: 0, - blue: 255 - }, - alpha: 1, - solid: false - }); + if (overlays) { - var rightHand = Overlays.addOverlay("cube", { - position: rightCubePosition, - size: HAND_SIZE, - color: { - red: 255, - green: 0, - blue: 0 - }, - alpha: 1, - solid: false - }); - var gustZoneOverlay = Overlays.addOverlay("cube", { - position: getGustDetectorPosition(), - size: TARGET_SIZE, - color: TARGET_COLOR, - alpha: 1, - solid: false - }); + var leftCubePosition = MyAvatar.getLeftPalmPosition(); + var rightCubePosition = MyAvatar.getRightPalmPosition(); + + var leftHand = Overlays.addOverlay("cube", { + position: leftCubePosition, + size: HAND_SIZE, + color: { + red: 0, + green: 0, + blue: 255 + }, + alpha: 1, + solid: false + }); + + var rightHand = Overlays.addOverlay("cube", { + position: rightCubePosition, + size: HAND_SIZE, + color: { + red: 255, + green: 0, + blue: 0 + }, + alpha: 1, + solid: false + }); + + var gustZoneOverlay = Overlays.addOverlay("cube", { + position: getGustDetectorPosition(), + size: TARGET_SIZE, + color: TARGET_COLOR, + alpha: 1, + solid: false + }); + } + function getGustDetectorPosition() { @@ -98,6 +116,11 @@ function convertRange(value, r1, r2) { z: 0 } + var BUBBLE_PARTICLE_COLOR = { + red: 0, + blue: 255, + green: 40 + } var wandEntity = this; @@ -108,9 +131,12 @@ function convertRange(value, r1, r2) { } this.unload = function(entityID) { - Overlays.deleteOverlay(leftHand); - Overlays.deleteOverlay(rightHand); - Overlays.deleteOverlay(gustZoneOverlay) + if (overlays) { + Overlays.deleteOverlay(leftHand); + Overlays.deleteOverlay(rightHand); + Overlays.deleteOverlay(gustZoneOverlay); + } + Entities.editEntity(entityID, { name: "" }); @@ -134,35 +160,45 @@ function convertRange(value, r1, r2) { //get the current position of the wand var properties = Entities.getEntityProperties(wandEntity.entityID); var wandPosition = properties.position; - - //debug overlays for mouth mode - var leftHandPos = MyAvatar.getLeftPalmPosition(); - var rightHandPos = MyAvatar.getRightPalmPosition(); - - Overlays.editOverlay(leftHand, { - position: leftHandPos - }); - Overlays.editOverlay(rightHand, { - position: rightHandPos - }); - //if the wand is in the gust detector, activate mouth mode and change the overlay color var hitTargetWithWand = findSphereSphereHit(wandPosition, HAND_SIZE / 2, getGustDetectorPosition(), TARGET_SIZE / 2) + var velocity = Vec3.subtract(wandPosition, BubbleWand.lastPosition) + var velocityStrength = Vec3.length(velocity) * 100; + var mouthMode; + if (hitTargetWithWand) { + mouthMode = true; + } else { + mouthMode = false; + } + + + + //debug overlays for mouth mode + if (overlays) { + var leftHandPos = MyAvatar.getLeftPalmPosition(); + var rightHandPos = MyAvatar.getRightPalmPosition(); + + Overlays.editOverlay(leftHand, { + position: leftHandPos + }); + Overlays.editOverlay(rightHand, { + position: rightHandPos + }); + } + + if (mouthMode === true && overlays === true) { Overlays.editOverlay(gustZoneOverlay, { position: getGustDetectorPosition(), color: TARGET_COLOR_HIT }) - mouthMode = true; - - } else { + } else if (overlays) { Overlays.editOverlay(gustZoneOverlay, { position: getGustDetectorPosition(), color: TARGET_COLOR }) - mouthMode = false; } var volumeLevel = MyAvatar.audioAverageLoudness; @@ -170,7 +206,6 @@ function convertRange(value, r1, r2) { var convertedVolume = convertRange(volumeLevel, [0, 5000], [0, 10]); // default is 'wave mode', where waving the object around grows the bubbles - var velocity = Vec3.subtract(wandPosition, BubbleWand.lastPosition) //store the last position of the wand for velocity calculations _t.lastPosition = wandPosition; @@ -184,6 +219,8 @@ function convertRange(value, r1, r2) { //actually grow the bubble var dimensions = Entities.getEntityProperties(_t.currentBubble).dimensions; + var avatarFront = Quat.getFront(MyAvatar.orientation); + var forwardOffset = Vec3.multiply(avatarFront, 0.1); if (velocityStrength > 1 || convertedVolume > 1) { @@ -196,21 +233,17 @@ function convertRange(value, r1, r2) { //bubbles pop after existing for a bit -- so set a random lifetime var lifetime = randInt(3, 8); - //sound is somewhat unstable at the moment so this is commented out. really audio should be played by the bubbles, but there's a blocker. - // Script.setTimeout(function() { - // _t.burstBubbleSound(_t.currentBubble) - // }, lifetime * 1000) - - - //todo: angular velocity without the controller -- forward velocity for mouth mode bubbles // var angularVelocity = Controller.getSpatialControlRawAngularVelocity(hands.leftHand.tip); Entities.editEntity(_t.currentBubble, { - velocity: Vec3.normalize(velocity), + // collisionsWillMove:true, + // ignoreForCollisions:false, + velocity: mouthMode ? avatarFront : velocity, // angularVelocity: Controller.getSpatialControlRawAngularVelocity(hands.leftHand.tip), lifetime: lifetime }); + _t.lastBubble = _t.currentBubble; //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble BubbleWand.spawnBubble(); @@ -244,27 +277,18 @@ function convertRange(value, r1, r2) { }); }, - burstBubbleSound: function(bubble) { - //we want to play the sound at the same location and orientation as the bubble - var position = Entities.getEntityProperties(bubble).position; - var orientation = Entities.getEntityProperties(bubble).orientation; - - //set the options for the audio injector - var audioOptions = { - volume: 0.5, - position: position, - orientation: orientation - } - - - //var audioInjector = Audio.playSound(popSound, audioOptions); - - //remove this bubble from the array to keep things clean - var i = BubbleWand.bubbles.indexOf(bubble); - if (i != -1) { - BubbleWand.bubbles.splice(i, 1); - } - + checkForEntitiesNearBubble: function() { + var _t = this; + var arrayFound = Entities.findEntities(_t.wandTipPosition, 1); + var foundLength = arrayFound.length; + print('found length:::' + foundLength); + }, + enableCollisionsForBubble: function(bubble) { + print('enable bubble collisions:' + bubble) + Entities.editEntity(bubble, { + collisionsWillMove: true, + ignoreForCollisions: false, + }) }, spawnBubble: function() { var _t = this; @@ -275,10 +299,11 @@ function convertRange(value, r1, r2) { var wandPosition = properties.position; var upVector = Quat.getUp(properties.rotation); var frontVector = Quat.getFront(properties.rotation); - var upOffset = Vec3.multiply(upVector, 0.5); - var forwardOffset = Vec3.multiply(frontVector, 0.1); - var offsetVector = Vec3.sum(upOffset, forwardOffset); - var wandTipPosition = Vec3.sum(wandPosition, offsetVector); + var upOffset = Vec3.multiply(upVector, 0.4); + // var forwardOffset = Vec3.multiply(frontVector, 0.1); + // var offsetVector = Vec3.sum(upOffset, forwardOffset); + // var wandTipPosition = Vec3.sum(wandPosition, offsetVector); + var wandTipPosition = Vec3.sum(wandPosition, upOffset); _t.wandTipPosition = wandTipPosition; //store the position of the tip on spawn for use in velocity calculations @@ -294,10 +319,10 @@ function convertRange(value, r1, r2) { y: 0.01, z: 0.01 }, - collisionsWillMove: false, - ignoreForCollisions: true, + collisionsWillMove: false, //true + ignoreForCollisions: true, //false gravity: BUBBLE_GRAVITY, - // collisionSoundURL:popSound, + collisionSoundURL: POP_SOUNDS[randInt(0, 4)], shapeType: "sphere", script: bubbleScript, }); @@ -309,6 +334,7 @@ function convertRange(value, r1, r2) { init: function() { this.spawnBubble(); Script.update.connect(BubbleWand.update); + } } From da90b7ff087d7daa87c1e59ce0a090ad8839f1fd Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 9 Sep 2015 09:53:47 -0700 Subject: [PATCH 02/58] remove logging around bubble leave entity --- examples/toys/bubblewand/bubble.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index e5f6d98e28..fe92ea76c8 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -53,7 +53,7 @@ this.leaveEntity = function(entityID) { - print('LEAVE ENTITY:' + entityID) + // print('LEAVE ENTITY:' + entityID) }; this.collisionWithEntity = function(myID, otherID, collision) { From 8f77c0b61cedda9b8c17ec65db486650b6f3297f Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 10 Sep 2015 09:58:31 -0700 Subject: [PATCH 03/58] Update wand to use relative paths, remove some unused position tracking methods, remove cache busting from model file paths --- examples/toys/bubblewand/bubble.js | 23 +++++------------------ examples/toys/bubblewand/createWand.js | 8 ++++---- examples/toys/bubblewand/wand.js | 4 ++-- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index fe92ea76c8..b7967e81ea 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -12,8 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html (function() { - Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); - Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); + Script.include("../utilities.js"); + Script.include("../libraries/utils.js"); var POP_SOUNDS = [ SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"), @@ -35,25 +35,20 @@ // var _t = this; // _t.entityID = entityID; // properties = Entities.getEntityProperties(entityID); - // checkPositionInterval = Script.setInterval(function() { - // properties = Entities.getEntityProperties(entityID); - // // print('properties AT CHECK::' + JSON.stringify(properties)); - // }, 200); - - // _t.loadShader(entityID); + // _t.loadShader(entityID); }; this.loadShader = function(entityID) { setEntityUserData(entityID, { "ProceduralEntity": { - "shaderUrl": "http://localhost:8080/shaders/bubble.fs?" + randInt(0, 10000), + "shaderUrl": "http://hifi-public.s3.amazonaws.com/james/bubblewand/shaders/quora.fs", } }) }; this.leaveEntity = function(entityID) { - // print('LEAVE ENTITY:' + entityID) + // print('LEAVE ENTITY:' + entityID) }; this.collisionWithEntity = function(myID, otherID, collision) { @@ -61,14 +56,6 @@ // Entities.deleteEntity(otherID); }; - // this.beforeUnload = function(entityID) { - // print('BEFORE UNLOAD:' + entityID); - // var properties = Entities.getEntityProperties(entityID); - // var position = properties.position; - // print('BEFOREUNLOAD PROPS' + JSON.stringify(position)); - - // }; - this.unload = function(entityID) { // Script.clearInterval(checkPositionInterval); // var position = properties.position; diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 943ea8fdbb..2c1217d5ce 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -10,11 +10,11 @@ -Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); -Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); +Script.include("../utilities.js"); +Script.include("../libraries/utils.js"); -var wandModel = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx?' + randInt(0, 10000); -var wandCollisionShape = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj?' + randInt(0, 10000); +var wandModel = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx' ; +var wandCollisionShape = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj' ; var scriptURL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?' + randInt(0, 10000); //for local testing diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index d98e0a8f57..648047fbb8 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -16,8 +16,8 @@ function convertRange(value, r1, r2) { } (function() { - Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); - Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); + Script.include("../utilities.js"); +Script.include("../libraries/utils.js"); var bubbleModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; var popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav"); From dfa43e84bf825654a29cf1444edde1c21507dc04 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 10 Sep 2015 10:31:17 -0700 Subject: [PATCH 04/58] bubble update hook --- examples/toys/bubblewand/bubble.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index b7967e81ea..20020855cb 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -28,6 +28,8 @@ blue: 255, } + var _t = this; + var properties; var checkPositionInterval; this.preload = function(entityID) { @@ -36,8 +38,14 @@ // _t.entityID = entityID; // properties = Entities.getEntityProperties(entityID); // _t.loadShader(entityID); + Script.update.connect(_t.internalUpdate); }; + this.internalUpdate = function() { + + properties = Entities.getEntityProperties(_t.entityID) + } + this.loadShader = function(entityID) { setEntityUserData(entityID, { "ProceduralEntity": { @@ -57,12 +65,13 @@ }; this.unload = function(entityID) { - // Script.clearInterval(checkPositionInterval); - // var position = properties.position; - // this.endOfBubble(position); - var properties = Entities.getEntityProperties(entityID) + + Script.update.disconnect(this.internalUpdate); + properties = Entities.getEntityProperties(entityID) var position = properties.position; - //print('UNLOAD PROPS' + JSON.stringify(position)); + // this.endOfBubble(position); + print('UNLOAD PROPS' + JSON.stringify(position)); + }; this.endOfBubble = function(position) { From 5df483b35f3f250da36ce12340ecce38313ede70 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 10 Sep 2015 11:32:21 -0700 Subject: [PATCH 05/58] ignore 0,0,0 positions so we have accurate unload for bubbles --- examples/toys/bubblewand/bubble.js | 19 +++++++++---------- examples/toys/bubblewand/createWand.js | 12 ++++++------ examples/toys/bubblewand/wand.js | 13 ++++++------- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index 20020855cb..edb13c085a 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -12,8 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html (function() { - Script.include("../utilities.js"); - Script.include("../libraries/utils.js"); + Script.include("../../utilities.js"); + Script.include("../../libraries/utils.js"); var POP_SOUNDS = [ SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"), @@ -34,16 +34,17 @@ var checkPositionInterval; this.preload = function(entityID) { // print('bubble preload') - // var _t = this; - // _t.entityID = entityID; - // properties = Entities.getEntityProperties(entityID); + _t.entityID = entityID; + //properties = Entities.getEntityProperties(entityID); // _t.loadShader(entityID); Script.update.connect(_t.internalUpdate); }; this.internalUpdate = function() { - - properties = Entities.getEntityProperties(_t.entityID) + var tmpProperties = Entities.getEntityProperties(_t.entityID); + if (tmpProperties.position.x !== 0 && tmpProperties.position.y !== 0 && tmpProperties.position.z !== 0) { + properties = tmpProperties; + } } this.loadShader = function(entityID) { @@ -65,11 +66,9 @@ }; this.unload = function(entityID) { - Script.update.disconnect(this.internalUpdate); - properties = Entities.getEntityProperties(entityID) var position = properties.position; - // this.endOfBubble(position); + _t.endOfBubble(position); print('UNLOAD PROPS' + JSON.stringify(position)); }; diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 2c1217d5ce..df6127cbcf 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -10,15 +10,15 @@ -Script.include("../utilities.js"); -Script.include("../libraries/utils.js"); +Script.include("../../utilities.js"); +Script.include("../../libraries/utils.js"); -var wandModel = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx' ; -var wandCollisionShape = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj' ; -var scriptURL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?' + randInt(0, 10000); +var wandModel = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; +var wandCollisionShape = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; +//var scriptURL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?' + randInt(0, 10000); //for local testing -//var scriptURL = "http://localhost:8080/scripts/wand.js?" + randInt(0, 10000); +var scriptURL = "http://localhost:8080/wand.js?" + randInt(0, 10000); //create the wand in front of the avatar var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation()))); diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 648047fbb8..3dd6ad5a19 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -16,14 +16,13 @@ function convertRange(value, r1, r2) { } (function() { - Script.include("../utilities.js"); -Script.include("../libraries/utils.js"); - + Script.include("../../utilities.js"); + Script.include("../../libraries/utils.js"); var bubbleModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; var popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav"); - var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); + //var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); //for local testing - // var bubbleScript = 'http://localhost:8080/scripts/bubble.js?' + randInt(1, 10000); + var bubbleScript = 'http://localhost:8080/bubble.js?' + randInt(1, 10000); var POP_SOUNDS = [ SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"), @@ -319,8 +318,8 @@ Script.include("../libraries/utils.js"); y: 0.01, z: 0.01 }, - collisionsWillMove: false, //true - ignoreForCollisions: true, //false + collisionsWillMove: true, //true + ignoreForCollisions: false, //false gravity: BUBBLE_GRAVITY, collisionSoundURL: POP_SOUNDS[randInt(0, 4)], shapeType: "sphere", From ee7e25a137f69eddc7b9c9fc08bae711054e790b Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 10 Sep 2015 11:49:12 -0700 Subject: [PATCH 06/58] remove localhost refs --- examples/toys/bubblewand/bubble.js | 4 ++-- examples/toys/bubblewand/createWand.js | 4 ++-- examples/toys/bubblewand/wand.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index edb13c085a..845ad58e17 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -35,12 +35,13 @@ this.preload = function(entityID) { // print('bubble preload') _t.entityID = entityID; - //properties = Entities.getEntityProperties(entityID); + properties = Entities.getEntityProperties(entityID); // _t.loadShader(entityID); Script.update.connect(_t.internalUpdate); }; this.internalUpdate = function() { + // we want the position at unload but for some reason it keeps getting set to 0,0,0 -- so i just exclude that location. sorry origin bubbles. var tmpProperties = Entities.getEntityProperties(_t.entityID); if (tmpProperties.position.x !== 0 && tmpProperties.position.y !== 0 && tmpProperties.position.z !== 0) { properties = tmpProperties; @@ -62,7 +63,6 @@ this.collisionWithEntity = function(myID, otherID, collision) { //Entities.deleteEntity(myID); - // Entities.deleteEntity(otherID); }; this.unload = function(entityID) { diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index df6127cbcf..50af1b251d 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -15,10 +15,10 @@ Script.include("../../libraries/utils.js"); var wandModel = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; var wandCollisionShape = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; -//var scriptURL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?' + randInt(0, 10000); +var scriptURL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?' + randInt(0, 10000); //for local testing -var scriptURL = "http://localhost:8080/wand.js?" + randInt(0, 10000); +//var scriptURL = "http://localhost:8080/wand.js?" + randInt(0, 10000); //create the wand in front of the avatar var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation()))); diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 3dd6ad5a19..e4a9f7231f 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -20,9 +20,9 @@ function convertRange(value, r1, r2) { Script.include("../../libraries/utils.js"); var bubbleModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; var popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav"); - //var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); + var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); //for local testing - var bubbleScript = 'http://localhost:8080/bubble.js?' + randInt(1, 10000); + //var bubbleScript = 'http://localhost:8080/bubble.js?' + randInt(1, 10000); var POP_SOUNDS = [ SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"), From 387e7b74a96c39f8b6e8ea6f78fa5369824a8691 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 10 Sep 2015 16:58:39 -0700 Subject: [PATCH 07/58] Return wand to its original position if it hasnt moved for 5 seconds, better particles, wand scaled to human size --- examples/toys/bubblewand/bubble.js | 27 +++++---- examples/toys/bubblewand/createWand.js | 18 +++--- examples/toys/bubblewand/wand.js | 80 +++++++++++++++++++------- 3 files changed, 86 insertions(+), 39 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index 845ad58e17..231b1cc7ca 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -12,8 +12,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html (function() { - Script.include("../../utilities.js"); - Script.include("../../libraries/utils.js"); + // Script.include("../../utilities.js"); + // Script.include("../../libraries/utils.js"); + + + Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); + Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); var POP_SOUNDS = [ SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"), @@ -69,7 +73,7 @@ Script.update.disconnect(this.internalUpdate); var position = properties.position; _t.endOfBubble(position); - print('UNLOAD PROPS' + JSON.stringify(position)); + // print('UNLOAD PROPS' + JSON.stringify(position)); }; @@ -107,7 +111,7 @@ animationSettings: animationSettings, animationIsPlaying: true, position: position, - lifetime: 1.0, + lifetime: 0.2, dimensions: { x: 1, y: 1, @@ -115,22 +119,25 @@ }, emitVelocity: { x: 0, - y: -1, + y: 0, z: 0 }, velocitySpread: { - x: 1, - y: 0, - z: 1 + x: 0.45, + y: 0.45, + z: 0.45 }, emitAcceleration: { x: 0, - y: -1, + y: -0.1, z: 0 }, + alphaStart: 1.0, + alpha: 1, + alphaFinish: 0.0, textures: "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png", color: BUBBLE_PARTICLE_COLOR, - lifespan: 1.0, + lifespan: 0.2, visible: true, locked: false }); diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 50af1b251d..24db08d2c1 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -10,30 +10,32 @@ -Script.include("../../utilities.js"); -Script.include("../../libraries/utils.js"); +// Script.include("../../utilities.js"); +// Script.include("../../libraries/utils.js"); + +Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); +Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); var wandModel = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; var wandCollisionShape = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; -var scriptURL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?' + randInt(0, 10000); +var scriptURL = 'http://hifi-public.s3.amazonaws.com/scripts/bubblewand/wand.js?' + randInt(0, 10000); //for local testing //var scriptURL = "http://localhost:8080/wand.js?" + randInt(0, 10000); //create the wand in front of the avatar -var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation()))); +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); var wand = Entities.addEntity({ type: "Model", modelURL: wandModel, position: center, dimensions: { - x: 0.1, - y: 1, - z: 0.1 + x: 0.05, + y: 0.5, + z: 0.05 }, //must be enabled to be grabbable in the physics engine - collisionsWillMove: true, compoundShapeURL: wandCollisionShape, script: scriptURL diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index e4a9f7231f..87bdfc6648 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -16,13 +16,20 @@ function convertRange(value, r1, r2) { } (function() { - Script.include("../../utilities.js"); - Script.include("../../libraries/utils.js"); + + Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); + Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); + + + // Script.include("../../utilities.js"); + // Script.include("../../libraries/utils.js"); + + var bubbleModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; var popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav"); - var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); - //for local testing - //var bubbleScript = 'http://localhost:8080/bubble.js?' + randInt(1, 10000); + var bubbleScript = 'http://hifi-public.s3.amazonaws.com/scripts/toys/bubblewand/bubble.js?' + randInt(1, 10000); + + // var bubbleScript = 'http://localhost:8080/bubble.js?' + randInt(1, 10000); //for local testing var POP_SOUNDS = [ SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"), @@ -127,6 +134,9 @@ function convertRange(value, r1, r2) { // print('PRELOAD') this.entityID = entityID; this.properties = Entities.getEntityProperties(this.entityID); + BubbleWand.originalProperties = this.properties; + print('rotation???' + JSON.stringify(BubbleWand.originalProperties.rotation)); + } this.unload = function(entityID) { @@ -150,11 +160,14 @@ function convertRange(value, r1, r2) { var BubbleWand = { bubbles: [], + timeSinceMoved: 0, + resetAtTime: 5, currentBubble: null, - update: function() { - BubbleWand.internalUpdate(); + update: function(dt) { + BubbleWand.internalUpdate(dt); }, - internalUpdate: function() { + internalUpdate: function(dt) { + var _t = this; //get the current position of the wand var properties = Entities.getEntityProperties(wandEntity.entityID); @@ -162,9 +175,16 @@ function convertRange(value, r1, r2) { //if the wand is in the gust detector, activate mouth mode and change the overlay color var hitTargetWithWand = findSphereSphereHit(wandPosition, HAND_SIZE / 2, getGustDetectorPosition(), TARGET_SIZE / 2) - var velocity = Vec3.subtract(wandPosition, BubbleWand.lastPosition) + var velocity = Vec3.subtract(wandPosition, _t.lastPosition) var velocityStrength = Vec3.length(velocity) * 100; + + var upVector = Quat.getUp(properties.rotation); + var frontVector = Quat.getFront(properties.rotation); + var upOffset = Vec3.multiply(upVector, 0.2); + var wandTipPosition = Vec3.sum(wandPosition, upOffset); + _t.wandTipPosition = wandTipPosition; + var mouthMode; if (hitTargetWithWand) { @@ -172,8 +192,18 @@ function convertRange(value, r1, r2) { } else { mouthMode = false; } + //print('velocityStrength'+velocityStrength) - + //we want to reset the object to its original position if its been a while since it has moved + if (velocityStrength === 0) { + _t.timeSinceMoved = _t.timeSinceMoved + dt; + if (_t.timeSinceMoved > _t.resetAtTime) { + _t.timeSinceMoved = 0; + _t.returnToOriginalLocation(); + } + } else { + _t.timeSinceMoved = 0; + } //debug overlays for mouth mode if (overlays) { @@ -225,7 +255,7 @@ function convertRange(value, r1, r2) { //add some variation in bubble sizes var bubbleSize = randInt(1, 5); - bubbleSize = bubbleSize / 10; + bubbleSize = bubbleSize / 50; //release the bubble if its dimensions are bigger than the bubble size if (dimensions.x > bubbleSize) { @@ -249,14 +279,14 @@ function convertRange(value, r1, r2) { return } else { if (mouthMode) { - dimensions.x += 0.015 * convertedVolume; - dimensions.y += 0.015 * convertedVolume; - dimensions.z += 0.015 * convertedVolume; + dimensions.x += 0.005 * convertedVolume; + dimensions.y += 0.005 * convertedVolume; + dimensions.z += 0.005 * convertedVolume; } else { - dimensions.x += 0.015 * velocityStrength; - dimensions.y += 0.015 * velocityStrength; - dimensions.z += 0.015 * velocityStrength; + dimensions.x += 0.005 * velocityStrength; + dimensions.y += 0.005 * velocityStrength; + dimensions.z += 0.005 * velocityStrength; } } @@ -298,10 +328,7 @@ function convertRange(value, r1, r2) { var wandPosition = properties.position; var upVector = Quat.getUp(properties.rotation); var frontVector = Quat.getFront(properties.rotation); - var upOffset = Vec3.multiply(upVector, 0.4); - // var forwardOffset = Vec3.multiply(frontVector, 0.1); - // var offsetVector = Vec3.sum(upOffset, forwardOffset); - // var wandTipPosition = Vec3.sum(wandPosition, offsetVector); + var upOffset = Vec3.multiply(upVector, 0.2); var wandTipPosition = Vec3.sum(wandPosition, upOffset); _t.wandTipPosition = wandTipPosition; @@ -329,8 +356,19 @@ function convertRange(value, r1, r2) { //add this bubble to an array of bubbles so we can keep track of them _t.bubbles.push(_t.currentBubble) + }, + returnToOriginalLocation: function() { + var _t = this; + Script.update.disconnect(BubbleWand.update) + _t.currentBubble = null; + Entities.deleteEntity(_t.currentBubble); + Entities.editEntity(wandEntity.entityID, _t.originalProperties) + _t.spawnBubble(); + Script.update.connect(BubbleWand.update); + }, init: function() { + var _t = this; this.spawnBubble(); Script.update.connect(BubbleWand.update); From 1cec61ebbad8b1de8f8dc5ef651f2f1bcdda0231 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 10 Sep 2015 17:05:24 -0700 Subject: [PATCH 08/58] fire particles before burst sound --- examples/toys/bubblewand/bubble.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index 231b1cc7ca..eaabf98e44 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -78,8 +78,9 @@ }; this.endOfBubble = function(position) { - this.burstBubbleSound(position); + this.createBurstParticles(position); + this.burstBubbleSound(position); } this.burstBubbleSound = function(position) { From c3ed2d90643b6edabccfd71ce66b1dafcc514b60 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 10 Sep 2015 17:10:55 -0700 Subject: [PATCH 09/58] fix file paths --- examples/toys/bubblewand/createWand.js | 2 +- examples/toys/bubblewand/wand.js | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 24db08d2c1..158bcb3b99 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -18,7 +18,7 @@ Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examp var wandModel = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; var wandCollisionShape = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; -var scriptURL = 'http://hifi-public.s3.amazonaws.com/scripts/bubblewand/wand.js?' + randInt(0, 10000); +var scriptURL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?' + randInt(0, 10000); //for local testing //var scriptURL = "http://localhost:8080/wand.js?" + randInt(0, 10000); diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 87bdfc6648..020fba9b15 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -27,7 +27,7 @@ function convertRange(value, r1, r2) { var bubbleModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; var popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav"); - var bubbleScript = 'http://hifi-public.s3.amazonaws.com/scripts/toys/bubblewand/bubble.js?' + randInt(1, 10000); + var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); // var bubbleScript = 'http://localhost:8080/bubble.js?' + randInt(1, 10000); //for local testing @@ -306,19 +306,6 @@ function convertRange(value, r1, r2) { }); }, - checkForEntitiesNearBubble: function() { - var _t = this; - var arrayFound = Entities.findEntities(_t.wandTipPosition, 1); - var foundLength = arrayFound.length; - print('found length:::' + foundLength); - }, - enableCollisionsForBubble: function(bubble) { - print('enable bubble collisions:' + bubble) - Entities.editEntity(bubble, { - collisionsWillMove: true, - ignoreForCollisions: false, - }) - }, spawnBubble: function() { var _t = this; //create a new bubble at the tip of the wand From 9992f4b5c5bbb557a05a0c7e09c35bf8127e533f Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 16 Sep 2015 01:16:58 +0200 Subject: [PATCH 10/58] Made stopping scripts by hash (path/url) more tolerable and fixed stopping script functionality in ScriptDiscoveryService: made stopScript(string) to stop script by url or path and stopScriptName(string) to stop by filename --- interface/src/Application.cpp | 15 ++++---- interface/src/Application.h | 4 +-- interface/src/ui/RunningScriptsWidget.cpp | 42 ++++++++++++++--------- interface/src/ui/RunningScriptsWidget.h | 8 ++--- 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 89ce392ba0..953c8162fc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -606,7 +606,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _overlays.init(); // do this before scripts load _runningScriptsWidget->setRunningScripts(getRunningScripts()); - connect(_runningScriptsWidget, &RunningScriptsWidget::stopScriptName, this, &Application::stopScript); connect(this, SIGNAL(aboutToQuit()), this, SLOT(saveScripts())); connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); @@ -4328,17 +4327,18 @@ void Application::stopAllScripts(bool restart) { _myAvatar->clearScriptableSettings(); } -void Application::stopScript(const QString &scriptName, bool restart) { - const QString& scriptURLString = QUrl(scriptName).toString(); - if (_scriptEnginesHash.contains(scriptURLString)) { - ScriptEngine* scriptEngine = _scriptEnginesHash[scriptURLString]; +bool Application::stopScript(const QString& scriptHash, bool restart) { + bool stoppedScript = false; + if (_scriptEnginesHash.contains(scriptHash)) { + ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash]; if (restart) { auto scriptCache = DependencyManager::get(); - scriptCache->deleteScript(scriptName); + scriptCache->deleteScript(QUrl(scriptHash)); connect(scriptEngine, SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&))); } scriptEngine->stop(); - qCDebug(interfaceapp) << "stopping script..." << scriptName; + stoppedScript = true; + qCDebug(interfaceapp) << "stopping script..." << scriptHash; // HACK: ATM scripts cannot set/get their animation priorities, so we clear priorities // whenever a script stops in case it happened to have been setting joint rotations. // TODO: expose animation priorities and provide a layered animation control system. @@ -4347,6 +4347,7 @@ void Application::stopScript(const QString &scriptName, bool restart) { if (_scriptEnginesHash.empty()) { _myAvatar->clearScriptableSettings(); } + return stoppedScript; } void Application::reloadAllScripts() { diff --git a/interface/src/Application.h b/interface/src/Application.h index b997fae823..5cb70cf676 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -292,7 +292,7 @@ public: NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } QStringList getRunningScripts() { return _scriptEnginesHash.keys(); } - ScriptEngine* getScriptEngine(QString scriptHash) { return _scriptEnginesHash.contains(scriptHash) ? _scriptEnginesHash[scriptHash] : NULL; } + ScriptEngine* getScriptEngine(const QString& scriptHash) { return _scriptEnginesHash.contains(scriptHash) ? _scriptEnginesHash[scriptHash] : NULL; } bool isLookingAtMyAvatar(AvatarSharedPointer avatar); @@ -395,7 +395,7 @@ public slots: void reloadScript(const QString& scriptName, bool isUserLoaded = true); void scriptFinished(const QString& scriptName); void stopAllScripts(bool restart = false); - void stopScript(const QString& scriptName, bool restart = false); + bool stopScript(const QString& scriptHash, bool restart = false); void reloadAllScripts(); void reloadOneScript(const QString& scriptName); void loadDefaultScripts(); diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 1165de7592..61b03bd610 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -57,16 +57,15 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter); connect(ui->scriptTreeView, &QTreeView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList); - connect(ui->reloadAllButton, &QPushButton::clicked, - Application::getInstance(), &Application::reloadAllScripts); - connect(ui->stopAllButton, &QPushButton::clicked, - this, &RunningScriptsWidget::allScriptsStopped); - connect(ui->loadScriptFromDiskButton, &QPushButton::clicked, - Application::getInstance(), &Application::loadDialog); - connect(ui->loadScriptFromURLButton, &QPushButton::clicked, - Application::getInstance(), &Application::loadScriptURLDialog); - connect(&_reloadSignalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(reloadOneScript(const QString&))); - connect(&_stopSignalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&))); + connect(ui->reloadAllButton, &QPushButton::clicked, Application::getInstance(), &Application::reloadAllScripts); + connect(ui->stopAllButton, &QPushButton::clicked, this, &RunningScriptsWidget::allScriptsStopped); + connect(ui->loadScriptFromDiskButton, &QPushButton::clicked, Application::getInstance(), &Application::loadDialog); + connect(ui->loadScriptFromURLButton, &QPushButton::clicked, Application::getInstance(), &Application::loadScriptURLDialog); + connect(&_reloadSignalMapper, static_cast(&QSignalMapper::mapped), + Application::getInstance(), &Application::reloadOneScript); + + connect(&_stopSignalMapper, static_cast(&QSignalMapper::mapped), + [](const QString& script) { Application::getInstance()->stopScript(script); }); UIUtil::scaleWidgetFontSizes(this); } @@ -217,9 +216,6 @@ void RunningScriptsWidget::keyPressEvent(QKeyEvent *keyEvent) { } } -void RunningScriptsWidget::scriptStopped(const QString& scriptName) { -} - void RunningScriptsWidget::allScriptsStopped() { Application::getInstance()->stopAllScripts(); } @@ -227,15 +223,16 @@ void RunningScriptsWidget::allScriptsStopped() { QVariantList RunningScriptsWidget::getRunning() { const int WINDOWS_DRIVE_LETTER_SIZE = 1; QVariantList result; - QStringList runningScripts = Application::getInstance()->getRunningScripts(); - for (int i = 0; i < runningScripts.size(); i++) { - QUrl runningScriptURL = QUrl(runningScripts.at(i)); + foreach(const QString& runningScript, Application::getInstance()->getRunningScripts()) { + QUrl runningScriptURL = QUrl(runningScript); if (runningScriptURL.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); } QVariantMap resultNode; resultNode.insert("name", runningScriptURL.fileName()); resultNode.insert("url", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); + // The path contains the exact path/URL of the script, which also is used in the stopScript function. + resultNode.insert("path", runningScript); resultNode.insert("local", runningScriptURL.isLocalFile()); result.append(resultNode); } @@ -294,3 +291,16 @@ QVariantList RunningScriptsWidget::getLocal() { } return result; } + +bool RunningScriptsWidget::stopScriptByName(const QString& name) { + foreach (const QString& runningScript, Application::getInstance()->getRunningScripts()) { + if (QUrl(runningScript).fileName().toLower() == name.trimmed().toLower()) { + return Application::getInstance()->stopScript(runningScript, false); + } + } + return false; +} + +bool RunningScriptsWidget::stopScript(const QString& name, bool restart) { + return Application::getInstance()->stopScript(name, restart); +} diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h index c09bce5443..9029b13c56 100644 --- a/interface/src/ui/RunningScriptsWidget.h +++ b/interface/src/ui/RunningScriptsWidget.h @@ -36,7 +36,7 @@ public: const ScriptsModel* getScriptsModel() { return &_scriptsModel; } signals: - void stopScriptName(const QString& name, bool restart = false); + void scriptStopped(const QString& scriptName); protected: virtual bool eventFilter(QObject* sender, QEvent* event); @@ -45,10 +45,11 @@ protected: virtual void showEvent(QShowEvent* event); public slots: - void scriptStopped(const QString& scriptName); QVariantList getRunning(); QVariantList getPublic(); QVariantList getLocal(); + bool stopScript(const QString& name, bool restart = false); + bool stopScriptByName(const QString& name); private slots: void allScriptsStopped(); @@ -63,9 +64,6 @@ private: QSignalMapper _stopSignalMapper; ScriptsModelFilter _scriptsModelFilter; ScriptsModel _scriptsModel; - ScriptsTableWidget* _recentlyLoadedScriptsTable; - QStringList _recentlyLoadedScripts; - QString _lastStoppedScript; QVariantList getPublicChildNodes(TreeNodeFolder* parent); }; From 37f45b57ff19acd8ddfde71498b411c3c373d041 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Tue, 15 Sep 2015 18:40:54 -0700 Subject: [PATCH 11/58] wand updates --- examples/toys/bubblewand/bubble.js | 7 ++- examples/toys/bubblewand/createWand.js | 10 +++-- examples/toys/bubblewand/wand.js | 60 +++++++++++++++++++------- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index eaabf98e44..748c946119 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -15,12 +15,11 @@ // Script.include("../../utilities.js"); // Script.include("../../libraries/utils.js"); - - Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); - Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); +Script.include("http://hifi-public.s3.amazonaws.com/scripts/utilities.js"); +Script.include("http://hifi-public.s3.amazonaws.com/scripts/libraries/utils.js"); var POP_SOUNDS = [ - SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"), + SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav") , SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop1.wav"), SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop2.wav"), SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop3.wav") diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 158bcb3b99..49481b6c1a 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -13,8 +13,8 @@ // Script.include("../../utilities.js"); // Script.include("../../libraries/utils.js"); -Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); -Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); +Script.include("http://hifi-public.s3.amazonaws.com/scripts/utilities.js"); +Script.include("http://hifi-public.s3.amazonaws.com/scripts/libraries/utils.js"); var wandModel = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; var wandCollisionShape = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; @@ -25,7 +25,11 @@ var scriptURL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wa //create the wand in front of the avatar var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); - +var tablePosition = { + x:546.48, + y:495.63, + z:506.25 +} var wand = Entities.addEntity({ type: "Model", modelURL: wandModel, diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 020fba9b15..afee5fab0c 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -11,22 +11,21 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +'use strict' function convertRange(value, r1, r2) { return (value - r1[0]) * (r2[1] - r2[0]) / (r1[1] - r1[0]) + r2[0]; } (function() { - Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); - Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); - + Script.include("http://hifi-public.s3.amazonaws.com/scripts/utilities.js"); + Script.include("http://hifi-public.s3.amazonaws.com/scripts/libraries/utils.js"); // Script.include("../../utilities.js"); // Script.include("../../libraries/utils.js"); var bubbleModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; - var popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav"); var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); // var bubbleScript = 'http://localhost:8080/bubble.js?' + randInt(1, 10000); //for local testing @@ -118,7 +117,7 @@ function convertRange(value, r1, r2) { var BUBBLE_GRAVITY = { x: 0, - y: -0.05, + y: -0.1, z: 0 } @@ -135,8 +134,8 @@ function convertRange(value, r1, r2) { this.entityID = entityID; this.properties = Entities.getEntityProperties(this.entityID); BubbleWand.originalProperties = this.properties; - print('rotation???' + JSON.stringify(BubbleWand.originalProperties.rotation)); - + BubbleWand.init(); + print('initial position' + JSON.stringify(BubbleWand.originalProperties.position)); } this.unload = function(entityID) { @@ -161,8 +160,9 @@ function convertRange(value, r1, r2) { var BubbleWand = { bubbles: [], timeSinceMoved: 0, - resetAtTime: 5, + resetAtTime: 2, currentBubble: null, + atOriginalLocation: true, update: function(dt) { BubbleWand.internalUpdate(dt); }, @@ -176,8 +176,9 @@ function convertRange(value, r1, r2) { var hitTargetWithWand = findSphereSphereHit(wandPosition, HAND_SIZE / 2, getGustDetectorPosition(), TARGET_SIZE / 2) var velocity = Vec3.subtract(wandPosition, _t.lastPosition) - var velocityStrength = Vec3.length(velocity) * 100; + // print('VELOCITY:'+JSON.stringify(velocity)) + var velocityStrength = Vec3.length(velocity) * 100; var upVector = Quat.getUp(properties.rotation); var frontVector = Quat.getFront(properties.rotation); @@ -194,17 +195,43 @@ function convertRange(value, r1, r2) { } //print('velocityStrength'+velocityStrength) + //we want to reset the object to its original position if its been a while since it has moved + // print('wand position ' + JSON.stringify(wandPosition)) + // print('last position ' + JSON.stringify(_t.lastPosition)) + // print('at original location? ' + _t.atOriginalLocation) + + if (velocityStrength < 0.01) { + velocityStrength = 0 + } + var isMoving; if (velocityStrength === 0) { + isMoving = false; + } else { + isMoving = true; + } + + + if (isMoving === true) { + // print('MOVING') + // print('velocityStrength ' + velocityStrength) + + _t.timeSinceMoved = 0; + _t.atOriginalLocation = false; + } else { _t.timeSinceMoved = _t.timeSinceMoved + dt; + } + + if (isMoving === false && _t.atOriginalLocation === false) { if (_t.timeSinceMoved > _t.resetAtTime) { _t.timeSinceMoved = 0; _t.returnToOriginalLocation(); + } - } else { - _t.timeSinceMoved = 0; } + + //debug overlays for mouth mode if (overlays) { var leftHandPos = MyAvatar.getLeftPalmPosition(); @@ -239,8 +266,7 @@ function convertRange(value, r1, r2) { //store the last position of the wand for velocity calculations _t.lastPosition = wandPosition; - // velocity numbers are pretty small, so lets make them a bit bigger - var velocityStrength = Vec3.length(velocity) * 100; + if (velocityStrength > 10) { velocityStrength = 10 @@ -320,7 +346,7 @@ function convertRange(value, r1, r2) { _t.wandTipPosition = wandTipPosition; //store the position of the tip on spawn for use in velocity calculations - _t.lastPosition = wandTipPosition; + _t.lastPosition = wandPosition; //create a bubble at the wand tip _t.currentBubble = Entities.addEntity({ @@ -340,14 +366,16 @@ function convertRange(value, r1, r2) { script: bubbleScript, }); + //print('spawnbubble position' + JSON.stringify(wandTipPosition)); + //add this bubble to an array of bubbles so we can keep track of them _t.bubbles.push(_t.currentBubble) }, returnToOriginalLocation: function() { var _t = this; + _t.atOriginalLocation = true; Script.update.disconnect(BubbleWand.update) - _t.currentBubble = null; Entities.deleteEntity(_t.currentBubble); Entities.editEntity(wandEntity.entityID, _t.originalProperties) _t.spawnBubble(); @@ -362,6 +390,6 @@ function convertRange(value, r1, r2) { } } - BubbleWand.init(); + }) \ No newline at end of file From efc321bc1053d5bd53cdc48ee199b61d778bd701 Mon Sep 17 00:00:00 2001 From: BOB LONG Date: Wed, 16 Sep 2015 00:40:26 -0700 Subject: [PATCH 12/58] Display face blend coefficients Display the face blend coefficients and update the value in real time. --- examples/faceBlendCoefficients.js | 98 ++++++++++++++++++++++++++++++ interface/src/avatar/MyAvatar.h | 2 + libraries/render-utils/src/Model.h | 5 ++ 3 files changed, 105 insertions(+) create mode 100644 examples/faceBlendCoefficients.js diff --git a/examples/faceBlendCoefficients.js b/examples/faceBlendCoefficients.js new file mode 100644 index 0000000000..56fcadca9d --- /dev/null +++ b/examples/faceBlendCoefficients.js @@ -0,0 +1,98 @@ +// +// coefficients.js +// +// version 2.0 +// +// Created by Bob Long, 9/14/2015 +// A simple panel that can display the blending coefficients of Avatar's face model. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +Script.include('utilities/tools/cookies.js') + +var panel; +var coeff; +var interval; +var item = 0; +var DEVELOPER_MENU = "Developer"; +var AVATAR_MENU = DEVELOPER_MENU + " > Avatar"; +var SHOW_FACE_BLEND_COEFFICIENTS = "Show face blend coefficients" + +function MenuConnect(menuItem) { + if (menuItem == SHOW_FACE_BLEND_COEFFICIENTS) { + if(Menu.isOptionChecked(SHOW_FACE_BLEND_COEFFICIENTS)) { + panel.show(); + Overlays.editOverlay(coeff, { visible : true }); + } else { + panel.hide(); + Overlays.editOverlay(coeff, { visible : false }); + } + } +} + +// Add a menu item to show/hide the coefficients +function setupMenu() { + if (!Menu.menuExists(DEVELOPER_MENU)) { + Menu.addMenu(DEVELOPER_MENU); + } + + if (!Menu.menuExists(AVATAR_MENU)) { + Menu.addMenu(AVATAR_MENU); + } + + Menu.addMenuItem({ menuName: AVATAR_MENU, menuItemName: SHOW_FACE_BLEND_COEFFICIENTS, isCheckable: true, isChecked: true }); + Menu.menuItemEvent.connect(MenuConnect); +} + +function setupPanel() { + panel = new Panel(10, 400); + + // Slider to select which coefficient to display + panel.newSlider("Select Coefficient Index", + 0, + 100, + function(value) { item = value.toFixed(0); }, + function() { return item; }, + function(value) { return "index = " + item; } + ); + + // The raw overlay used to show the actual coefficient value + coeff = Overlays.addOverlay("text", { + x: 10, + y: 420, + width: 300, + height: 50, + color: { red: 255, green: 255, blue: 255 }, + alpha: 1.0, + backgroundColor: { red: 127, green: 127, blue: 127 }, + backgroundAlpha: 0.5, + topMargin: 15, + leftMargin: 20, + text: "Coefficient: 0.0" + }); + + // Set up the interval (0.5 sec) to update the coefficient. + interval = Script.setInterval(function() { + Overlays.editOverlay(coeff, { text: "Coefficient: " + MyAvatar.getFaceBlendCoef(item).toFixed(4) }); + }, 500); + + // Mouse event setup + Controller.mouseMoveEvent.connect(function panelMouseMoveEvent(event) { return panel.mouseMoveEvent(event); }); + Controller.mousePressEvent.connect( function panelMousePressEvent(event) { return panel.mousePressEvent(event); }); + Controller.mouseReleaseEvent.connect(function(event) { return panel.mouseReleaseEvent(event); }); +} + +// Clean up +function scriptEnding() { + panel.destroy(); + Overlays.deleteOverlay(coeff); + Script.clearInterval(interval); + + Menu.removeMenuItem(AVATAR_MENU, SHOW_FACE_BLEND_COEFFICIENTS); +} + +setupMenu(); +setupPanel(); +Script.scriptEnding.connect(scriptEnding); \ No newline at end of file diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index bb3c6385f9..5fd5ee4c29 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -110,6 +110,8 @@ public: Q_INVOKABLE float getHeadFinalRoll() const { return getHead()->getFinalRoll(); } Q_INVOKABLE float getHeadFinalPitch() const { return getHead()->getFinalPitch(); } Q_INVOKABLE float getHeadDeltaPitch() const { return getHead()->getDeltaPitch(); } + Q_INVOKABLE int getFaceBlendCoefNum() const { return getHead()->getFaceModel().getBlendshapeCoefficientsNum(); } + Q_INVOKABLE float getFaceBlendCoef(int index) const { return getHead()->getFaceModel().getBlendshapeCoefficient(index); } Q_INVOKABLE glm::vec3 getEyePosition() const { return getHead()->getEyePosition(); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 348e5cf549..d1aa2901c8 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -191,6 +191,11 @@ public: const std::unordered_set& getCauterizeBoneSet() const { return _cauterizeBoneSet; } void setCauterizeBoneSet(const std::unordered_set& boneSet) { _cauterizeBoneSet = boneSet; } + int getBlendshapeCoefficientsNum() const { return _blendshapeCoefficients.size(); } + float getBlendshapeCoefficient(int index) const { + return index >= _blendshapeCoefficients.size() || index < 0 ? + 0.0f : _blendshapeCoefficients.at(index); } + protected: void setPupilDilation(float dilation) { _pupilDilation = dilation; } From 455ed27c2bd40d861a2f71183e26398f90fd2382 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 16 Sep 2015 16:26:09 -0700 Subject: [PATCH 13/58] pre-test with eric --- examples/toys/bubblewand/bubble.js | 116 +++-- examples/toys/bubblewand/createWand.js | 43 +- examples/toys/bubblewand/wand.js | 568 ++++++++++++------------- 3 files changed, 388 insertions(+), 339 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index 3cc68fecfa..2a0690c921 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -1,54 +1,110 @@ // bubble.js // part of bubblewand // +// Script Type: Entity // Created by James B. Pollack @imgntn -- 09/03/2015 // Copyright 2015 High Fidelity, Inc. // // example of a nested entity. it doesn't do much now besides delete itself if it collides with something (bubbles are fragile! it would be cool if it sometimes merged with other bubbbles it hit) -// todo: play bubble sounds from the bubble itself instead of the wand. +// todo: play bubble sounds & particle bursts from the bubble itself instead of the wand. // blocker: needs some sound fixes and a way to find its own position before unload for spatialization // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - (function() { - // Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); - // Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); + Script.include("../../utilities.js"); + Script.include("../../libraries/utils.js"); + + var BUBBLE_PARTICLE_TEXTURE = "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png" + + + BUBBLE_PARTICLE_COLOR = { + red: 0, + green: 40, + blue: 255, + }; + + var _this = this; + + var properties; - //var popSound; this.preload = function(entityID) { // print('bubble preload') - this.entityID = entityID; - // popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav"); - - } - - this.collisionWithEntity = function(myID, otherID, collision) { - //if(Entites.getEntityProperties(otherID).userData.objectType==='') { merge bubbles?} - // Entities.deleteEntity(myID); - // this.burstBubbleSound(collision.contactPoint) + _this.entityID = entityID; + Script.update.connect(_t.internalUpdate); + }; + this.internalUpdate = function() { + // we want the position at unload but for some reason it keeps getting set to 0,0,0 -- so i just exclude that location. sorry origin bubbles. + var tmpProperties = Entities.getEntityProperties(_this.entityID); + if (tmpProperties.position.x !== 0 && tmpProperties.position.y !== 0 && tmpProperties.position.z !== 0) { + properties = tmpProperties; + } }; this.unload = function(entityID) { - // this.properties = Entities.getEntityProperties(entityID); - //var location = this.properties.position; - //this.burstBubbleSound(); + Script.update.disconnect(this.internalUpdate); + var position = properties.position; + _this.endOfBubble(position); + + }; + + this.endOfBubble = function(position) { + this.createBurstParticles(position); + }; + + this.createBurstParticles = function(position) { + //get the current position of the bubble + var position = properties.position; + //var orientation = properties.orientation; + + var animationSettings = JSON.stringify({ + fps: 30, + frameIndex: 0, + running: true, + firstFrame: 0, + lastFrame: 30, + loop: false + }); + + var particleBurst = Entities.addEntity({ + type: "ParticleEffect", + animationSettings: animationSettings, + animationIsPlaying: true, + position: position, + lifetime: 0.2, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + emitVelocity: { + x: 0, + y: 0, + z: 0 + }, + velocitySpread: { + x: 0.45, + y: 0.45, + z: 0.45 + }, + emitAcceleration: { + x: 0, + y: -0.1, + z: 0 + }, + alphaStart: 1.0, + alpha: 1, + alphaFinish: 0.0, + textures: BUBBLE_PARTICLE_TEXTURE, + color: BUBBLE_PARTICLE_COLOR, + lifespan: 0.2, + visible: true, + locked: false + }); + }; - - this.burstBubbleSound = function(location) { - - // var audioOptions = { - // volume: 0.5, - // position: location - // } - - //Audio.playSound(popSound, audioOptions); - - } - - }) \ No newline at end of file diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 15c347d62a..8403ba8516 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -1,41 +1,42 @@ // createWand.js // part of bubblewand // +// Script Type: Entity Spawner // Created by James B. Pollack @imgntn -- 09/03/2015 // Copyright 2015 High Fidelity, Inc. // -// Loads a wand model and attaches the bubble wand behavior. +// Loads a wand model and attaches the bubble wand behavior. // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); -Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); - -var wandModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx?" + randInt(0, 10000); -var scriptURL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?" + randInt(1, 100500) - +Script.include("../../utilities.js"); +Script.include("../../libraries/utils.js"); +var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; +var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; +var WAND_SCRIPT_URL = Script.resolvePath("wand.js?"+randInt(0,4000)); //create the wand in front of the avatar -var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation()))); +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); + var wand = Entities.addEntity({ - type: "Model", - modelURL: wandModel, - position: center, - dimensions: { - x: 0.1, - y: 1, - z: 0.1 - }, - //must be enabled to be grabbable in the physics engine - collisionsWillMove: true, - shapeType: 'box', - script: scriptURL + type: "Model", + modelURL: WAND_MODEL, + position: center, + dimensions: { + x: 0.05, + y: 0.5, + z: 0.05 + }, + //must be enabled to be grabbable in the physics engine + collisionsWillMove: true, + compoundShapeURL: WAND_COLLISION_SHAPE, + script: WAND_SCRIPT_URL }); function cleanup() { - Entities.deleteEntity(wand); + Entities.deleteEntity(wand); } diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index be1042ab79..5edc11d166 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -1,6 +1,7 @@ // wand.js // part of bubblewand // +// Script Type: Entity Script // Created by James B. Pollack @imgntn -- 09/03/2015 // Copyright 2015 High Fidelity, Inc. // @@ -11,307 +12,298 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +'use strict'; + function convertRange(value, r1, r2) { - return (value - r1[0]) * (r2[1] - r2[0]) / (r1[1] - r1[0]) + r2[0]; + return (value - r1[0]) * (r2[1] - r2[0]) / (r1[1] - r1[0]) + r2[0]; } (function() { - Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js"); - Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js"); - var bubbleModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; - var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); - var popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav"); - - var TARGET_SIZE = 0.4; - var TARGET_COLOR = { - red: 128, - green: 128, - blue: 128 - }; - var TARGET_COLOR_HIT = { - red: 0, - green: 255, - blue: 0 - }; - - var HAND_SIZE = 0.25; - var leftCubePosition = MyAvatar.getLeftPalmPosition(); - var rightCubePosition = MyAvatar.getRightPalmPosition(); - - var leftHand = Overlays.addOverlay("cube", { - position: leftCubePosition, - size: HAND_SIZE, - color: { - red: 0, - green: 0, - blue: 255 - }, - alpha: 1, - solid: false - }); - - var rightHand = Overlays.addOverlay("cube", { - position: rightCubePosition, - size: HAND_SIZE, - color: { - red: 255, - green: 0, - blue: 0 - }, - alpha: 1, - solid: false - }); - - var gustZoneOverlay = Overlays.addOverlay("cube", { - position: getGustDetectorPosition(), - size: TARGET_SIZE, - color: TARGET_COLOR, - alpha: 1, - solid: false - }); + Script.include("../../utilities.js"); + Script.include("../../libraries/utils.js"); - function getGustDetectorPosition() { - //put the zone in front of your avatar's face - var DISTANCE_IN_FRONT = 0.2; - var DISTANCE_UP = 0.5; - var DISTANCE_TO_SIDE = 0.0; + var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; + var BUBBLE_SCRIPT = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); + Script.resolvePath('bubble.js?' + randInt(0, 5000)); - var up = Quat.getUp(MyAvatar.orientation); - var front = Quat.getFront(MyAvatar.orientation); - var right = Quat.getRight(MyAvatar.orientation); - - var upOffset = Vec3.multiply(up, DISTANCE_UP); - var rightOffset = Vec3.multiply(right, DISTANCE_TO_SIDE); - var frontOffset = Vec3.multiply(front, DISTANCE_IN_FRONT); - - var offset = Vec3.sum(Vec3.sum(rightOffset, frontOffset), upOffset); - var position = Vec3.sum(MyAvatar.position, offset); - return position; - } + var HAND_SIZE = 0.25; + var TARGET_SIZE = 0.04; - var BUBBLE_GRAVITY = { - x: 0, - y: -0.05, - z: 0 - } + + var BUBBLE_GRAVITY = { + x: 0, + y: -0.1, + z: 0 + } + + var MOUTH_MODE_GROWTH_FACTOR = 0.005; + var WAVE_MODE_GROWTH_FACTOR = 0.005; + var SHRINK_LOWER_LIMIT = 0.02; + var SHRINK_FACTOR = 0.001; + var VELOCITY_STRENGTH_LOWER_LIMIT = 0.01; + var BUBBLE_DIVISOR = 50; + var BUBBLE_LIFETIME_MIN = 3; + var BUBBLE_LIFETIME_MAX = 8; + + function getGustDetectorPosition() { + //put the zone in front of your avatar's face + var DISTANCE_IN_FRONT = 0.2; + var DISTANCE_UP = 0.5; + var DISTANCE_TO_SIDE = 0.0; + + var up = Quat.getUp(MyAvatar.orientation); + var front = Quat.getFront(MyAvatar.orientation); + var right = Quat.getRight(MyAvatar.orientation); + + var upOffset = Vec3.multiply(up, DISTANCE_UP); + var rightOffset = Vec3.multiply(right, DISTANCE_TO_SIDE); + var frontOffset = Vec3.multiply(front, DISTANCE_IN_FRONT); + + var offset = Vec3.sum(Vec3.sum(rightOffset, frontOffset), upOffset); + var position = Vec3.sum(MyAvatar.position, offset); + return position; + } - var wandEntity = this; - - this.preload = function(entityID) { - // print('PRELOAD') - this.entityID = entityID; - this.properties = Entities.getEntityProperties(this.entityID); - } - - this.unload = function(entityID) { - Overlays.deleteOverlay(leftHand); - Overlays.deleteOverlay(rightHand); - Overlays.deleteOverlay(gustZoneOverlay) - Entities.editEntity(entityID, { - name: "" - }); - Script.update.disconnect(BubbleWand.update); - Entities.deleteEntity(BubbleWand.currentBubble); - while (BubbleWand.bubbles.length > 0) { - Entities.deleteEntity(BubbleWand.bubbles.pop()); - } - - }; - - - var BubbleWand = { - bubbles: [], - currentBubble: null, - update: function() { - BubbleWand.internalUpdate(); - }, - internalUpdate: function() { - var _t = this; - //get the current position of the wand - var properties = Entities.getEntityProperties(wandEntity.entityID); - var wandPosition = properties.position; - - //debug overlays for mouth mode - var leftHandPos = MyAvatar.getLeftPalmPosition(); - var rightHandPos = MyAvatar.getRightPalmPosition(); - - Overlays.editOverlay(leftHand, { - position: leftHandPos - }); - Overlays.editOverlay(rightHand, { - position: rightHandPos - }); - - //if the wand is in the gust detector, activate mouth mode and change the overlay color - var hitTargetWithWand = findSphereSphereHit(wandPosition, HAND_SIZE / 2, getGustDetectorPosition(), TARGET_SIZE / 2) - - var mouthMode; - if (hitTargetWithWand) { - Overlays.editOverlay(gustZoneOverlay, { - position: getGustDetectorPosition(), - color: TARGET_COLOR_HIT - }) - mouthMode = true; - - } else { - Overlays.editOverlay(gustZoneOverlay, { - position: getGustDetectorPosition(), - color: TARGET_COLOR - }) - mouthMode = false; - } - - var volumeLevel = MyAvatar.audioAverageLoudness; - //volume numbers are pretty large, so lets scale them down. - var convertedVolume = convertRange(volumeLevel, [0, 5000], [0, 10]); - - // default is 'wave mode', where waving the object around grows the bubbles - var velocity = Vec3.subtract(wandPosition, BubbleWand.lastPosition) - - //store the last position of the wand for velocity calculations - _t.lastPosition = wandPosition; - - // velocity numbers are pretty small, so lets make them a bit bigger - var velocityStrength = Vec3.length(velocity) * 100; - - if (velocityStrength > 10) { - velocityStrength = 10 - } - - //actually grow the bubble - var dimensions = Entities.getEntityProperties(_t.currentBubble).dimensions; - - if (velocityStrength > 1 || convertedVolume > 1) { - - //add some variation in bubble sizes - var bubbleSize = randInt(1, 5); - bubbleSize = bubbleSize / 10; - - //release the bubble if its dimensions are bigger than the bubble size - if (dimensions.x > bubbleSize) { - //bubbles pop after existing for a bit -- so set a random lifetime - var lifetime = randInt(3, 8); - - //sound is somewhat unstable at the moment so this is commented out. really audio should be played by the bubbles, but there's a blocker. - // Script.setTimeout(function() { - // _t.burstBubbleSound(_t.currentBubble) - // }, lifetime * 1000) - - - //todo: angular velocity without the controller -- forward velocity for mouth mode bubbles - // var angularVelocity = Controller.getSpatialControlRawAngularVelocity(hands.leftHand.tip); - - Entities.editEntity(_t.currentBubble, { - velocity: Vec3.normalize(velocity), - // angularVelocity: Controller.getSpatialControlRawAngularVelocity(hands.leftHand.tip), - lifetime: lifetime - }); - - //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble - BubbleWand.spawnBubble(); - - return - } else { - if (mouthMode) { - dimensions.x += 0.015 * convertedVolume; - dimensions.y += 0.015 * convertedVolume; - dimensions.z += 0.015 * convertedVolume; - - } else { - dimensions.x += 0.015 * velocityStrength; - dimensions.y += 0.015 * velocityStrength; - dimensions.z += 0.015 * velocityStrength; - } - - } - } else { - if (dimensions.x >= 0.02) { - dimensions.x -= 0.001; - dimensions.y -= 0.001; - dimensions.z -= 0.001; - } - - } - - //update the bubble to stay with the wand tip - Entities.editEntity(_t.currentBubble, { - position: _t.wandTipPosition, - dimensions: dimensions - }); - - }, - burstBubbleSound: function(bubble) { - //we want to play the sound at the same location and orientation as the bubble - var position = Entities.getEntityProperties(bubble).position; - var orientation = Entities.getEntityProperties(bubble).orientation; - - //set the options for the audio injector - var audioOptions = { - volume: 0.5, - position: position, - orientation: orientation - } - - - //var audioInjector = Audio.playSound(popSound, audioOptions); - - //remove this bubble from the array to keep things clean - var i = BubbleWand.bubbles.indexOf(bubble); - if (i != -1) { - BubbleWand.bubbles.splice(i, 1); - } - - }, - spawnBubble: function() { - var _t = this; - //create a new bubble at the tip of the wand - //the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position - - var properties = Entities.getEntityProperties(wandEntity.entityID); - var wandPosition = properties.position; - var upVector = Quat.getUp(properties.rotation); - var frontVector = Quat.getFront(properties.rotation); - var upOffset = Vec3.multiply(upVector, 0.5); - var forwardOffset = Vec3.multiply(frontVector, 0.1); - var offsetVector = Vec3.sum(upOffset, forwardOffset); - var wandTipPosition = Vec3.sum(wandPosition, offsetVector); - _t.wandTipPosition = wandTipPosition; - - //store the position of the tip on spawn for use in velocity calculations - _t.lastPosition = wandTipPosition; - - //create a bubble at the wand tip - _t.currentBubble = Entities.addEntity({ - type: 'Model', - modelURL: bubbleModel, - position: wandTipPosition, - dimensions: { - x: 0.01, - y: 0.01, - z: 0.01 - }, - collisionsWillMove: false, - ignoreForCollisions: true, - gravity: BUBBLE_GRAVITY, - // collisionSoundURL:popSound, - shapeType: "sphere", - script: bubbleScript, - }); - - //add this bubble to an array of bubbles so we can keep track of them - _t.bubbles.push(_t.currentBubble) - - }, - init: function() { - this.spawnBubble(); - Script.update.connect(BubbleWand.update); - } - } + var wandEntity = this; + this.preload = function(entityID) { + this.entityID = entityID; + this.properties = Entities.getEntityProperties(this.entityID); + BubbleWand.originalProperties = this.properties; BubbleWand.init(); + print('initial position' + JSON.stringify(BubbleWand.originalProperties.position)); + } + + this.unload = function(entityID) { + Entities.editEntity(entityID, { + name: "" + }); + Script.update.disconnect(BubbleWand.update); + Entities.deleteEntity(BubbleWand.currentBubble); + while (BubbleWand.bubbles.length > 0) { + Entities.deleteEntity(BubbleWand.bubbles.pop()); + } + + }; + + + var BubbleWand = { + bubbles: [], + timeSinceMoved: 0, + resetAtTime: 2, + currentBubble: null, + atOriginalLocation: true, + update: function(deltaTime) { + BubbleWand.internalUpdate(deltaTime); + }, + internalUpdate: function(deltaTime) { + var _t = this; + + var GRAB_USER_DATA_KEY = "grabKey"; + var defaultGrabData = { + activated: false, + avatarId: null + }; + + var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, wandEntity.entityID, defaultGrabData); + if (grabData.activated && grabData.avatarId == MyAvatar.sessionUUID) { + + // remember we're being grabbed so we can detect being released + _t.beingGrabbed = true; + + // print out that we're being grabbed + // print("I'm being grabbed..."); + _t.handleGrabbedWand(); + + } else if (_t.beingGrabbed) { + + // if we are not being grabbed, and we previously were, then we were just released, remember that + // and print out a message + _t.beingGrabbed = false; + // print("I'm was released..."); + return + } + + }, + handleGrabbedWand: function() { + var _t = this; + + // print('HANDLE GRAB 1') + var properties = Entities.getEntityProperties(wandEntity.entityID); + var wandPosition = properties.position; + //if the wand is in the gust detector, activate mouth mode and change the overlay color + var hitTargetWithWand = findSphereSphereHit(wandPosition, HAND_SIZE / 2, getGustDetectorPosition(), TARGET_SIZE / 2) + + var velocity = Vec3.subtract(wandPosition, _t.lastPosition) + + // print('VELOCITY:' + JSON.stringify(velocity)); + // print('HANDLE GRAB 2') + var velocityStrength = Vec3.length(velocity) * 100; + + var upVector = Quat.getUp(properties.rotation); + var frontVector = Quat.getFront(properties.rotation); + var upOffset = Vec3.multiply(upVector, 0.2); + var wandTipPosition = Vec3.sum(wandPosition, upOffset); + _t.wandTipPosition = wandTipPosition; + + var mouthMode; + + if (hitTargetWithWand) { + mouthMode = true; + } else { + mouthMode = false; + } + + if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { + velocityStrength = 0 + } + + var isMoving; + if (velocityStrength === 0) { + isMoving = false; + } else { + isMoving = true; + } + // print('MOVING?' + isMoving) + if (isMoving === true) { + _t.timeSinceMoved = 0; + _t.atOriginalLocation = false; + } else { + _t.timeSinceMoved = _t.timeSinceMoved + deltaTime; + } + + if (isMoving === false && _t.atOriginalLocation === false) { + if (_t.timeSinceMoved > _t.resetAtTime) { + _t.timeSinceMoved = 0; + _t.returnToOriginalLocation(); + } + } + + var volumeLevel = MyAvatar.audioAverageLoudness; + //volume numbers are pretty large, so lets scale them down. + var convertedVolume = convertRange(volumeLevel, [0, 5000], [0, 10]); + + // default is 'wave mode', where waving the object around grows the bubbles + + //store the last position of the wand for velocity calculations + _t.lastPosition = wandPosition; + + if (velocityStrength > 10) { + velocityStrength = 10 + } + + //actually grow the bubble + var dimensions = Entities.getEntityProperties(_t.currentBubble).dimensions; + var avatarFront = Quat.getFront(MyAvatar.orientation); + var forwardOffset = Vec3.multiply(avatarFront, 0.1); + + if (velocityStrength > 1 || convertedVolume > 1) { + + //add some variation in bubble sizes + var bubbleSize = randInt(1, 5); + bubbleSize = bubbleSize / BUBBLE_DIVISOR; + + //release the bubble if its dimensions are bigger than the bubble size + if (dimensions.x > bubbleSize) { + //bubbles pop after existing for a bit -- so set a random lifetime + var lifetime = randInt(BUBBLE_LIFETIME_MIN, BUBBLE_LIFETIME_MAX); + + Entities.editEntity(_t.currentBubble, { + velocity: mouthMode ? avatarFront : velocity, + lifetime: lifetime + }); + + //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble + BubbleWand.spawnBubble(); + + return + } else { + + if (mouthMode) { + dimensions.x += WAVE_MODE_GROWTH_FACTOR * convertedVolume; + dimensions.y += WAVE_MODE_GROWTH_FACTOR * convertedVolume; + dimensions.z += WAVE_MODE_GROWTH_FACTOR * convertedVolume; + + } else { + dimensions.x += WAVE_MODE_GROWTH_FACTOR * velocityStrength; + dimensions.y += WAVE_MODE_GROWTH_FACTOR * velocityStrength; + dimensions.z += WAVE_MODE_GROWTH_FACTOR * velocityStrength; + } + + } + } else { + if (dimensions.x >= SHRINK_LOWER_LIMIT) { + dimensions.x -= SHRINK_FACTOR; + dimensions.y -= SHRINK_FACTOR; + dimensions.z -= SHRINK_FACTOR; + } + + } + + //update the bubble to stay with the wand tip + Entities.editEntity(_t.currentBubble, { + position: _t.wandTipPosition, + dimensions: dimensions + }); + }, + spawnBubble: function() { + var _t = this; + //create a new bubble at the tip of the wand + //the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position + + var properties = Entities.getEntityProperties(wandEntity.entityID); + var wandPosition = properties.position; + var upVector = Quat.getUp(properties.rotation); + var frontVector = Quat.getFront(properties.rotation); + var upOffset = Vec3.multiply(upVector, 0.2); + var wandTipPosition = Vec3.sum(wandPosition, upOffset); + _t.wandTipPosition = wandTipPosition; + + //store the position of the tip on spawn for use in velocity calculations + _t.lastPosition = wandPosition; + + //create a bubble at the wand tip + _t.currentBubble = Entities.addEntity({ + type: 'Model', + modelURL: BUBBLE_MODEL, + position: wandTipPosition, + dimensions: { + x: 0.01, + y: 0.01, + z: 0.01 + }, + collisionsWillMove: true, //true + ignoreForCollisions: false, //false + gravity: BUBBLE_GRAVITY, + shapeType: "sphere", + script: BUBBLE_SCRIPT, + }); + //add this bubble to an array of bubbles so we can keep track of them + _t.bubbles.push(_t.currentBubble) + + }, + returnToOriginalLocation: function() { + var _t = this; + _t.atOriginalLocation = true; + Script.update.disconnect(BubbleWand.update) + Entities.deleteEntity(_t.currentBubble); + Entities.editEntity(wandEntity.entityID, _t.originalProperties) + _t.spawnBubble(); + Script.update.connect(BubbleWand.update); + + }, + init: function() { + var _t = this; + this.spawnBubble(); + Script.update.connect(BubbleWand.update); + + } + } + + }) \ No newline at end of file From 5ab8f192578ce72147cca578bed628cbebc22e69 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 16 Sep 2015 16:42:23 -0700 Subject: [PATCH 14/58] fix merge leftovers --- examples/toys/bubblewand/createWand.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 7386c8b26f..f5cb9625a0 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -22,13 +22,10 @@ var WAND_SCRIPT_URL = Script.resolvePath("wand.js?"+randInt(0,4000)); var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); -var wand = Entities.addEntity({ - type: "Model", - modelURL: WAND_MODEL, var wand = Entities.addEntity({ type: "Model", - modelURL: wandModel, + modelURL: WAND_MODEL, position: center, dimensions: { x: 0.05, From 3e7cc7d6eb86e8bd56c97fbe655c59f5d8acf99b Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 16 Sep 2015 17:02:52 -0700 Subject: [PATCH 15/58] remove sounds from bubble --- examples/toys/bubblewand/bubble.js | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index 91a72642d3..29d087176b 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -12,7 +12,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -(function() { << << << < HEAD +(function() { Script.include("../../utilities.js"); Script.include("../../libraries/utils.js"); @@ -32,7 +32,7 @@ this.preload = function(entityID) { // print('bubble preload') _this.entityID = entityID; - Script.update.connect(_t.internalUpdate); + Script.update.connect(_this.internalUpdate); }; this.internalUpdate = function() { @@ -47,24 +47,11 @@ this.unload = function(entityID) { Script.update.disconnect(this.internalUpdate); var position = properties.position; - _t.endOfBubble(position); - // print('UNLOAD PROPS' + JSON.stringify(position)); - + _this.endOfBubble(position); }; this.endOfBubble = function(position) { - this.createBurstParticles(position); - this.burstBubbleSound(position); - } - - this.burstBubbleSound = function(position) { - var audioOptions = { - volume: 0.5, - position: position - } - Audio.playSound(POP_SOUNDS[randInt(0, 4)], audioOptions); - } this.createBurstParticles = function(position) { From e1e567b1b5ecadaf80ce689d1a45e062e1d0c5bf Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 16 Sep 2015 17:09:54 -0700 Subject: [PATCH 16/58] remove mouth mode --- examples/toys/bubblewand/bubble.js | 4 +--- examples/toys/bubblewand/wand.js | 38 +++++------------------------- 2 files changed, 7 insertions(+), 35 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index 29d087176b..e2bbe2b220 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -5,9 +5,7 @@ // Created by James B. Pollack @imgntn -- 09/03/2015 // Copyright 2015 High Fidelity, Inc. // -// example of a nested entity. it doesn't do much now besides delete itself if it collides with something (bubbles are fragile! it would be cool if it sometimes merged with other bubbbles it hit) -// todo: play bubble sounds & particle bursts from the bubble itself instead of the wand. -// blocker: needs some sound fixes and a way to find its own position before unload for spatialization +// example of a nested entity. plays a particle burst at the location where its deleted. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 5edc11d166..06f0381277 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -5,7 +5,7 @@ // Created by James B. Pollack @imgntn -- 09/03/2015 // Copyright 2015 High Fidelity, Inc. // -// Makes bubbles when you wave the object around, or hold it near your mouth and make noise into the microphone. +// Makes bubbles when you wave the object around. // // For the example, it's attached to a wand -- but you can attach it to whatever entity you want. I dream of BubbleBees :) bzzzz...pop! // @@ -14,16 +14,11 @@ 'use strict'; -function convertRange(value, r1, r2) { - return (value - r1[0]) * (r2[1] - r2[0]) / (r1[1] - r1[0]) + r2[0]; -} - (function() { Script.include("../../utilities.js"); Script.include("../../libraries/utils.js"); - var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; var BUBBLE_SCRIPT = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); Script.resolvePath('bubble.js?' + randInt(0, 5000)); @@ -39,7 +34,6 @@ function convertRange(value, r1, r2) { z: 0 } - var MOUTH_MODE_GROWTH_FACTOR = 0.005; var WAVE_MODE_GROWTH_FACTOR = 0.005; var SHRINK_LOWER_LIMIT = 0.02; var SHRINK_FACTOR = 0.001; @@ -135,9 +129,7 @@ function convertRange(value, r1, r2) { // print('HANDLE GRAB 1') var properties = Entities.getEntityProperties(wandEntity.entityID); var wandPosition = properties.position; - //if the wand is in the gust detector, activate mouth mode and change the overlay color - var hitTargetWithWand = findSphereSphereHit(wandPosition, HAND_SIZE / 2, getGustDetectorPosition(), TARGET_SIZE / 2) - + var velocity = Vec3.subtract(wandPosition, _t.lastPosition) // print('VELOCITY:' + JSON.stringify(velocity)); @@ -150,14 +142,6 @@ function convertRange(value, r1, r2) { var wandTipPosition = Vec3.sum(wandPosition, upOffset); _t.wandTipPosition = wandTipPosition; - var mouthMode; - - if (hitTargetWithWand) { - mouthMode = true; - } else { - mouthMode = false; - } - if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { velocityStrength = 0 } @@ -183,9 +167,6 @@ function convertRange(value, r1, r2) { } } - var volumeLevel = MyAvatar.audioAverageLoudness; - //volume numbers are pretty large, so lets scale them down. - var convertedVolume = convertRange(volumeLevel, [0, 5000], [0, 10]); // default is 'wave mode', where waving the object around grows the bubbles @@ -198,10 +179,8 @@ function convertRange(value, r1, r2) { //actually grow the bubble var dimensions = Entities.getEntityProperties(_t.currentBubble).dimensions; - var avatarFront = Quat.getFront(MyAvatar.orientation); - var forwardOffset = Vec3.multiply(avatarFront, 0.1); - if (velocityStrength > 1 || convertedVolume > 1) { + if (velocityStrength > 1) { //add some variation in bubble sizes var bubbleSize = randInt(1, 5); @@ -213,7 +192,7 @@ function convertRange(value, r1, r2) { var lifetime = randInt(BUBBLE_LIFETIME_MIN, BUBBLE_LIFETIME_MAX); Entities.editEntity(_t.currentBubble, { - velocity: mouthMode ? avatarFront : velocity, + velocity: velocity, lifetime: lifetime }); @@ -223,16 +202,11 @@ function convertRange(value, r1, r2) { return } else { - if (mouthMode) { - dimensions.x += WAVE_MODE_GROWTH_FACTOR * convertedVolume; - dimensions.y += WAVE_MODE_GROWTH_FACTOR * convertedVolume; - dimensions.z += WAVE_MODE_GROWTH_FACTOR * convertedVolume; - - } else { + dimensions.x += WAVE_MODE_GROWTH_FACTOR * velocityStrength; dimensions.y += WAVE_MODE_GROWTH_FACTOR * velocityStrength; dimensions.z += WAVE_MODE_GROWTH_FACTOR * velocityStrength; - } + } } else { From 9aa2067e3e8149ee541e6d2fc5877a485aa78594 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 16 Sep 2015 17:26:18 -0700 Subject: [PATCH 17/58] cleanup unused reset stuff --- examples/toys/bubblewand/wand.js | 74 ++++++-------------------------- 1 file changed, 12 insertions(+), 62 deletions(-) diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 06f0381277..60e4752a15 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -20,14 +20,11 @@ Script.include("../../libraries/utils.js"); var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; - var BUBBLE_SCRIPT = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000); - Script.resolvePath('bubble.js?' + randInt(0, 5000)); + var BUBBLE_SCRIPT = Script.resolvePath('bubble.js?' + randInt(0, 5000)); var HAND_SIZE = 0.25; var TARGET_SIZE = 0.04; - - var BUBBLE_GRAVITY = { x: 0, y: -0.1, @@ -38,6 +35,7 @@ var SHRINK_LOWER_LIMIT = 0.02; var SHRINK_FACTOR = 0.001; var VELOCITY_STRENGTH_LOWER_LIMIT = 0.01; + var MAX_VELOCITY_STRENGTH = 10; var BUBBLE_DIVISOR = 50; var BUBBLE_LIFETIME_MIN = 3; var BUBBLE_LIFETIME_MAX = 8; @@ -67,9 +65,7 @@ this.preload = function(entityID) { this.entityID = entityID; this.properties = Entities.getEntityProperties(this.entityID); - BubbleWand.originalProperties = this.properties; BubbleWand.init(); - print('initial position' + JSON.stringify(BubbleWand.originalProperties.position)); } this.unload = function(entityID) { @@ -88,29 +84,23 @@ var BubbleWand = { bubbles: [], timeSinceMoved: 0, - resetAtTime: 2, currentBubble: null, - atOriginalLocation: true, update: function(deltaTime) { BubbleWand.internalUpdate(deltaTime); }, internalUpdate: function(deltaTime) { var _t = this; - var GRAB_USER_DATA_KEY = "grabKey"; var defaultGrabData = { activated: false, avatarId: null }; - var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, wandEntity.entityID, defaultGrabData); if (grabData.activated && grabData.avatarId == MyAvatar.sessionUUID) { - // remember we're being grabbed so we can detect being released _t.beingGrabbed = true; // print out that we're being grabbed - // print("I'm being grabbed..."); _t.handleGrabbedWand(); } else if (_t.beingGrabbed) { @@ -118,7 +108,7 @@ // if we are not being grabbed, and we previously were, then we were just released, remember that // and print out a message _t.beingGrabbed = false; - // print("I'm was released..."); + return } @@ -126,14 +116,10 @@ handleGrabbedWand: function() { var _t = this; - // print('HANDLE GRAB 1') var properties = Entities.getEntityProperties(wandEntity.entityID); var wandPosition = properties.position; - - var velocity = Vec3.subtract(wandPosition, _t.lastPosition) - // print('VELOCITY:' + JSON.stringify(velocity)); - // print('HANDLE GRAB 2') + var velocity = Vec3.subtract(wandPosition, _t.lastPosition) var velocityStrength = Vec3.length(velocity) * 100; var upVector = Quat.getUp(properties.rotation); @@ -146,35 +132,11 @@ velocityStrength = 0 } - var isMoving; - if (velocityStrength === 0) { - isMoving = false; - } else { - isMoving = true; - } - // print('MOVING?' + isMoving) - if (isMoving === true) { - _t.timeSinceMoved = 0; - _t.atOriginalLocation = false; - } else { - _t.timeSinceMoved = _t.timeSinceMoved + deltaTime; - } - - if (isMoving === false && _t.atOriginalLocation === false) { - if (_t.timeSinceMoved > _t.resetAtTime) { - _t.timeSinceMoved = 0; - _t.returnToOriginalLocation(); - } - } - - - // default is 'wave mode', where waving the object around grows the bubbles - //store the last position of the wand for velocity calculations _t.lastPosition = wandPosition; - if (velocityStrength > 10) { - velocityStrength = 10 + if (velocityStrength > MAX_VELOCITY_STRENGTH) { + velocityStrength = MAX_VELOCITY_STRENGTH } //actually grow the bubble @@ -202,11 +164,10 @@ return } else { - - dimensions.x += WAVE_MODE_GROWTH_FACTOR * velocityStrength; - dimensions.y += WAVE_MODE_GROWTH_FACTOR * velocityStrength; - dimensions.z += WAVE_MODE_GROWTH_FACTOR * velocityStrength; - + dimensions.x += WAVE_MODE_GROWTH_FACTOR * velocityStrength; + dimensions.y += WAVE_MODE_GROWTH_FACTOR * velocityStrength; + dimensions.z += WAVE_MODE_GROWTH_FACTOR * velocityStrength; + } } else { @@ -226,9 +187,9 @@ }, spawnBubble: function() { var _t = this; + //create a new bubble at the tip of the wand //the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position - var properties = Entities.getEntityProperties(wandEntity.entityID); var wandPosition = properties.position; var upVector = Quat.getUp(properties.rotation); @@ -237,7 +198,7 @@ var wandTipPosition = Vec3.sum(wandPosition, upOffset); _t.wandTipPosition = wandTipPosition; - //store the position of the tip on spawn for use in velocity calculations + //store the position of the tip for use in velocity calculations _t.lastPosition = wandPosition; //create a bubble at the wand tip @@ -259,22 +220,11 @@ //add this bubble to an array of bubbles so we can keep track of them _t.bubbles.push(_t.currentBubble) - }, - returnToOriginalLocation: function() { - var _t = this; - _t.atOriginalLocation = true; - Script.update.disconnect(BubbleWand.update) - Entities.deleteEntity(_t.currentBubble); - Entities.editEntity(wandEntity.entityID, _t.originalProperties) - _t.spawnBubble(); - Script.update.connect(BubbleWand.update); - }, init: function() { var _t = this; this.spawnBubble(); Script.update.connect(BubbleWand.update); - } } From a8fe3b3edd1be1330ba53f570866ccc0536aec63 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 16 Sep 2015 18:08:56 -0700 Subject: [PATCH 18/58] keep the bubble with the wand, make the wand smaller --- examples/toys/bubblewand/createWand.js | 6 ++-- examples/toys/bubblewand/wand.js | 48 ++++++++++++++++---------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index f5cb9625a0..77ac7686c4 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -28,9 +28,9 @@ var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.g modelURL: WAND_MODEL, position: center, dimensions: { - x: 0.05, - y: 0.5, - z: 0.05 + x: 0.025, + y: 0.125, + z: 0.025 }, //must be enabled to be grabbable in the physics engine collisionsWillMove: true, diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 60e4752a15..62970045fb 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -7,12 +7,11 @@ // // Makes bubbles when you wave the object around. // -// For the example, it's attached to a wand -- but you can attach it to whatever entity you want. I dream of BubbleBees :) bzzzz...pop! // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -'use strict'; +// 'use strict'; (function() { @@ -39,6 +38,10 @@ var BUBBLE_DIVISOR = 50; var BUBBLE_LIFETIME_MIN = 3; var BUBBLE_LIFETIME_MAX = 8; + var WAND_TIP_OFFSET = 0.05; + var BUBBLE_SIZE_MIN = 1; + var BUBBLE_SIZE_MAX = 5; + var VELOCITY_THRESHOLD = 1; function getGustDetectorPosition() { //put the zone in front of your avatar's face @@ -89,6 +92,8 @@ BubbleWand.internalUpdate(deltaTime); }, internalUpdate: function(deltaTime) { + var properties = Entities.getEntityProperties(wandEntity.entityID); + var _t = this; var GRAB_USER_DATA_KEY = "grabKey"; var defaultGrabData = { @@ -101,7 +106,7 @@ _t.beingGrabbed = true; // print out that we're being grabbed - _t.handleGrabbedWand(); + _t.handleGrabbedWand(properties); } else if (_t.beingGrabbed) { @@ -111,23 +116,32 @@ return } + var wandTipPosition = _t.getWandTipPosition(properties); + //update the bubble to stay with the wand tip + Entities.editEntity(_t.currentBubble, { + position: wandTipPosition, + }); }, - handleGrabbedWand: function() { + getWandTipPosition: function(properties) { + print('get wand position') + var upVector = Quat.getUp(properties.rotation); + var frontVector = Quat.getFront(properties.rotation); + var upOffset = Vec3.multiply(upVector, WAND_TIP_OFFSET); + var wandTipPosition = Vec3.sum(properties.position, upOffset); + return wandTipPosition + }, + handleGrabbedWand: function(properties) { var _t = this; - var properties = Entities.getEntityProperties(wandEntity.entityID); var wandPosition = properties.position; + var wandTipPosition = _t.getWandTipPosition(properties) + _t.wandTipPosition = wandTipPosition; + var velocity = Vec3.subtract(wandPosition, _t.lastPosition) var velocityStrength = Vec3.length(velocity) * 100; - var upVector = Quat.getUp(properties.rotation); - var frontVector = Quat.getFront(properties.rotation); - var upOffset = Vec3.multiply(upVector, 0.2); - var wandTipPosition = Vec3.sum(wandPosition, upOffset); - _t.wandTipPosition = wandTipPosition; - if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { velocityStrength = 0 } @@ -142,10 +156,10 @@ //actually grow the bubble var dimensions = Entities.getEntityProperties(_t.currentBubble).dimensions; - if (velocityStrength > 1) { + if (velocityStrength > VELOCITY_THRESHOLD) { //add some variation in bubble sizes - var bubbleSize = randInt(1, 5); + var bubbleSize = randInt(BUBBLE_SIZE_MIN, BUBBLE_SIZE_MAX); bubbleSize = bubbleSize / BUBBLE_DIVISOR; //release the bubble if its dimensions are bigger than the bubble size @@ -163,12 +177,10 @@ return } else { - dimensions.x += WAVE_MODE_GROWTH_FACTOR * velocityStrength; dimensions.y += WAVE_MODE_GROWTH_FACTOR * velocityStrength; dimensions.z += WAVE_MODE_GROWTH_FACTOR * velocityStrength; - } } else { if (dimensions.x >= SHRINK_LOWER_LIMIT) { @@ -192,10 +204,8 @@ //the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position var properties = Entities.getEntityProperties(wandEntity.entityID); var wandPosition = properties.position; - var upVector = Quat.getUp(properties.rotation); - var frontVector = Quat.getFront(properties.rotation); - var upOffset = Vec3.multiply(upVector, 0.2); - var wandTipPosition = Vec3.sum(wandPosition, upOffset); + + wandTipPosition = _t.getWandTipPosition(properties); _t.wandTipPosition = wandTipPosition; //store the position of the tip for use in velocity calculations From 75df4e96e8b16bb13523e71d2e6c80b0b59328ce Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 16 Sep 2015 18:48:06 -0700 Subject: [PATCH 19/58] cleanup --- examples/toys/bubblewand/bubble.js | 2 +- examples/toys/bubblewand/createWand.js | 31 ++++++++++++------------- examples/toys/bubblewand/wand.js | 32 ++++++++++++-------------- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index e2bbe2b220..2629210c96 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -106,4 +106,4 @@ }; -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 77ac7686c4..7b902e2874 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -17,26 +17,25 @@ Script.include("../../libraries/utils.js"); var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; -var WAND_SCRIPT_URL = Script.resolvePath("wand.js?"+randInt(0,4000)); +var WAND_SCRIPT_URL = Script.resolvePath("wand.js?" + randInt(0, 4000)); //create the wand in front of the avatar var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); +var wand = Entities.addEntity({ + type: "Model", + modelURL: WAND_MODEL, + position: center, + dimensions: { + x: 0.025, + y: 0.125, + z: 0.025 + }, + //must be enabled to be grabbable in the physics engine + collisionsWillMove: true, + compoundShapeURL: WAND_COLLISION_SHAPE, + script: WAND_SCRIPT_URL +}); - - var wand = Entities.addEntity({ - type: "Model", - modelURL: WAND_MODEL, - position: center, - dimensions: { - x: 0.025, - y: 0.125, - z: 0.025 - }, - //must be enabled to be grabbable in the physics engine - collisionsWillMove: true, - compoundShapeURL: WAND_COLLISION_SHAPE, - script: WAND_SCRIPT_URL - }); function cleanup() { Entities.deleteEntity(wand); } diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 62970045fb..f43fc0df03 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -11,8 +11,6 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// 'use strict'; - (function() { Script.include("../../utilities.js"); @@ -28,20 +26,21 @@ x: 0, y: -0.1, z: 0 - } + }; var WAVE_MODE_GROWTH_FACTOR = 0.005; var SHRINK_LOWER_LIMIT = 0.02; var SHRINK_FACTOR = 0.001; - var VELOCITY_STRENGTH_LOWER_LIMIT = 0.01; - var MAX_VELOCITY_STRENGTH = 10; var BUBBLE_DIVISOR = 50; var BUBBLE_LIFETIME_MIN = 3; var BUBBLE_LIFETIME_MAX = 8; - var WAND_TIP_OFFSET = 0.05; var BUBBLE_SIZE_MIN = 1; var BUBBLE_SIZE_MAX = 5; - var VELOCITY_THRESHOLD = 1; + var WAND_TIP_OFFSET = 0.05; + var VELOCITY_STRENGTH_LOWER_LIMIT = 0.01; + var MAX_VELOCITY_STRENGTH = 10; + var VELOCITY_THRESHOLD = 1; + var VELOCITY_STRENGTH_MULTIPLIER = 100; function getGustDetectorPosition() { //put the zone in front of your avatar's face @@ -60,7 +59,7 @@ var offset = Vec3.sum(Vec3.sum(rightOffset, frontOffset), upOffset); var position = Vec3.sum(MyAvatar.position, offset); return position; - } + }; var wandEntity = this; @@ -93,7 +92,7 @@ }, internalUpdate: function(deltaTime) { var properties = Entities.getEntityProperties(wandEntity.entityID); - + var _t = this; var GRAB_USER_DATA_KEY = "grabKey"; var defaultGrabData = { @@ -116,15 +115,14 @@ return } - var wandTipPosition = _t.getWandTipPosition(properties); - //update the bubble to stay with the wand tip - Entities.editEntity(_t.currentBubble, { - position: wandTipPosition, + var wandTipPosition = _t.getWandTipPosition(properties); + //update the bubble to stay with the wand tip + Entities.editEntity(_t.currentBubble, { + position: wandTipPosition, - }); + }); }, getWandTipPosition: function(properties) { - print('get wand position') var upVector = Quat.getUp(properties.rotation); var frontVector = Quat.getFront(properties.rotation); var upOffset = Vec3.multiply(upVector, WAND_TIP_OFFSET); @@ -140,7 +138,7 @@ _t.wandTipPosition = wandTipPosition; var velocity = Vec3.subtract(wandPosition, _t.lastPosition) - var velocityStrength = Vec3.length(velocity) * 100; + var velocityStrength = Vec3.length(velocity) * VELOCITY_STRENGTH_MULTIPLIER; if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { velocityStrength = 0 @@ -193,7 +191,7 @@ //update the bubble to stay with the wand tip Entities.editEntity(_t.currentBubble, { - position: _t.wandTipPosition, + dimensions: dimensions }); }, From df0b9e7dbb12b7aa6309b3761eb91393d338ab91 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 17 Sep 2015 15:59:19 -0700 Subject: [PATCH 20/58] refactor bubble wand to prevent duplicate bubbles --- examples/toys/bubblewand/createWand.js | 17 +- examples/toys/bubblewand/wand.js | 403 ++++++++++++------------- 2 files changed, 204 insertions(+), 216 deletions(-) diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 7b902e2874..6548090b74 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -9,7 +9,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - +var IN_TOYBOX = false; Script.include("../../utilities.js"); Script.include("../../libraries/utils.js"); @@ -17,14 +17,25 @@ Script.include("../../libraries/utils.js"); var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; -var WAND_SCRIPT_URL = Script.resolvePath("wand.js?" + randInt(0, 4000)); +var WAND_SCRIPT_URL = Script.resolvePath("wand.js"); //create the wand in front of the avatar var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); +var tablePosition = { + x:546.48, + y:495.63, + z:506.25 +} var wand = Entities.addEntity({ + name:'Bubble Wand', type: "Model", modelURL: WAND_MODEL, - position: center, + position: IN_TOYBOX? tablePosition: center, + gravity: { + x: 0, + y: 0, + z: 0, + }, dimensions: { x: 0.025, y: 0.125, diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index f43fc0df03..2b57ccda78 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -13,229 +13,206 @@ (function() { - Script.include("../../utilities.js"); - Script.include("../../libraries/utils.js"); + Script.include("../../utilities.js"); + Script.include("../../libraries/utils.js"); - var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; - var BUBBLE_SCRIPT = Script.resolvePath('bubble.js?' + randInt(0, 5000)); + var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; + var BUBBLE_SCRIPT = Script.resolvePath('bubble.js'); - var HAND_SIZE = 0.25; - var TARGET_SIZE = 0.04; - - var BUBBLE_GRAVITY = { - x: 0, - y: -0.1, - z: 0 - }; - - var WAVE_MODE_GROWTH_FACTOR = 0.005; - var SHRINK_LOWER_LIMIT = 0.02; - var SHRINK_FACTOR = 0.001; - var BUBBLE_DIVISOR = 50; - var BUBBLE_LIFETIME_MIN = 3; - var BUBBLE_LIFETIME_MAX = 8; - var BUBBLE_SIZE_MIN = 1; - var BUBBLE_SIZE_MAX = 5; - var WAND_TIP_OFFSET = 0.05; - var VELOCITY_STRENGTH_LOWER_LIMIT = 0.01; - var MAX_VELOCITY_STRENGTH = 10; - var VELOCITY_THRESHOLD = 1; - var VELOCITY_STRENGTH_MULTIPLIER = 100; - - function getGustDetectorPosition() { - //put the zone in front of your avatar's face - var DISTANCE_IN_FRONT = 0.2; - var DISTANCE_UP = 0.5; - var DISTANCE_TO_SIDE = 0.0; - - var up = Quat.getUp(MyAvatar.orientation); - var front = Quat.getFront(MyAvatar.orientation); - var right = Quat.getRight(MyAvatar.orientation); - - var upOffset = Vec3.multiply(up, DISTANCE_UP); - var rightOffset = Vec3.multiply(right, DISTANCE_TO_SIDE); - var frontOffset = Vec3.multiply(front, DISTANCE_IN_FRONT); - - var offset = Vec3.sum(Vec3.sum(rightOffset, frontOffset), upOffset); - var position = Vec3.sum(MyAvatar.position, offset); - return position; - }; + var BUBBLE_GRAVITY = { + x: 0, + y: -0.1, + z: 0 + }; + var BUBBLE_DIVISOR = 50; + var BUBBLE_LIFETIME_MIN = 3; + var BUBBLE_LIFETIME_MAX = 8; + var BUBBLE_SIZE_MIN = 1; + var BUBBLE_SIZE_MAX = 5; + var GROWTH_FACTOR = 0.005; + var SHRINK_FACTOR = 0.001; + var SHRINK_LOWER_LIMIT = 0.02; + var WAND_TIP_OFFSET = 0.05; + var VELOCITY_STRENGTH_LOWER_LIMIT = 0.01; + var VELOCITY_STRENGH_MAX = 10; + var VELOCITY_STRENGTH_MULTIPLIER = 100; + var VELOCITY_THRESHOLD = 1; - var wandEntity = this; + var _this; - this.preload = function(entityID) { - this.entityID = entityID; - this.properties = Entities.getEntityProperties(this.entityID); - BubbleWand.init(); - } - - this.unload = function(entityID) { - Entities.editEntity(entityID, { - name: "" - }); - Script.update.disconnect(BubbleWand.update); - Entities.deleteEntity(BubbleWand.currentBubble); - while (BubbleWand.bubbles.length > 0) { - Entities.deleteEntity(BubbleWand.bubbles.pop()); + var BubbleWand = function() { + _this = this; + print('WAND CONSTRUCTOR!') } - }; - - - var BubbleWand = { - bubbles: [], - timeSinceMoved: 0, - currentBubble: null, - update: function(deltaTime) { - BubbleWand.internalUpdate(deltaTime); - }, - internalUpdate: function(deltaTime) { - var properties = Entities.getEntityProperties(wandEntity.entityID); - - var _t = this; - var GRAB_USER_DATA_KEY = "grabKey"; - var defaultGrabData = { - activated: false, - avatarId: null - }; - var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, wandEntity.entityID, defaultGrabData); - if (grabData.activated && grabData.avatarId == MyAvatar.sessionUUID) { - // remember we're being grabbed so we can detect being released - _t.beingGrabbed = true; - - // print out that we're being grabbed - _t.handleGrabbedWand(properties); - - } else if (_t.beingGrabbed) { - - // if we are not being grabbed, and we previously were, then we were just released, remember that - // and print out a message - _t.beingGrabbed = false; - - return - } - var wandTipPosition = _t.getWandTipPosition(properties); - //update the bubble to stay with the wand tip - Entities.editEntity(_t.currentBubble, { - position: wandTipPosition, - - }); - }, - getWandTipPosition: function(properties) { - var upVector = Quat.getUp(properties.rotation); - var frontVector = Quat.getFront(properties.rotation); - var upOffset = Vec3.multiply(upVector, WAND_TIP_OFFSET); - var wandTipPosition = Vec3.sum(properties.position, upOffset); - return wandTipPosition - }, - handleGrabbedWand: function(properties) { - var _t = this; - - var wandPosition = properties.position; - - var wandTipPosition = _t.getWandTipPosition(properties) - _t.wandTipPosition = wandTipPosition; - - var velocity = Vec3.subtract(wandPosition, _t.lastPosition) - var velocityStrength = Vec3.length(velocity) * VELOCITY_STRENGTH_MULTIPLIER; - - if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { - velocityStrength = 0 - } - - //store the last position of the wand for velocity calculations - _t.lastPosition = wandPosition; - - if (velocityStrength > MAX_VELOCITY_STRENGTH) { - velocityStrength = MAX_VELOCITY_STRENGTH - } - - //actually grow the bubble - var dimensions = Entities.getEntityProperties(_t.currentBubble).dimensions; - - if (velocityStrength > VELOCITY_THRESHOLD) { - - //add some variation in bubble sizes - var bubbleSize = randInt(BUBBLE_SIZE_MIN, BUBBLE_SIZE_MAX); - bubbleSize = bubbleSize / BUBBLE_DIVISOR; - - //release the bubble if its dimensions are bigger than the bubble size - if (dimensions.x > bubbleSize) { - //bubbles pop after existing for a bit -- so set a random lifetime - var lifetime = randInt(BUBBLE_LIFETIME_MIN, BUBBLE_LIFETIME_MAX); - - Entities.editEntity(_t.currentBubble, { - velocity: velocity, - lifetime: lifetime - }); - - //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble - BubbleWand.spawnBubble(); - - return - } else { - dimensions.x += WAVE_MODE_GROWTH_FACTOR * velocityStrength; - dimensions.y += WAVE_MODE_GROWTH_FACTOR * velocityStrength; - dimensions.z += WAVE_MODE_GROWTH_FACTOR * velocityStrength; - - } - } else { - if (dimensions.x >= SHRINK_LOWER_LIMIT) { - dimensions.x -= SHRINK_FACTOR; - dimensions.y -= SHRINK_FACTOR; - dimensions.z -= SHRINK_FACTOR; - } - - } - - //update the bubble to stay with the wand tip - Entities.editEntity(_t.currentBubble, { - - dimensions: dimensions - }); - }, - spawnBubble: function() { - var _t = this; - - //create a new bubble at the tip of the wand - //the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position - var properties = Entities.getEntityProperties(wandEntity.entityID); - var wandPosition = properties.position; - - wandTipPosition = _t.getWandTipPosition(properties); - _t.wandTipPosition = wandTipPosition; - - //store the position of the tip for use in velocity calculations - _t.lastPosition = wandPosition; - - //create a bubble at the wand tip - _t.currentBubble = Entities.addEntity({ - type: 'Model', - modelURL: BUBBLE_MODEL, - position: wandTipPosition, - dimensions: { - x: 0.01, - y: 0.01, - z: 0.01 + BubbleWand.prototype = { + bubbles: [], + currentBubble: null, + preload: function(entityID) { + this.entityID = entityID; + this.properties = Entities.getEntityProperties(this.entityID); + Script.update.connect(this.update); }, - collisionsWillMove: true, //true - ignoreForCollisions: false, //false - gravity: BUBBLE_GRAVITY, - shapeType: "sphere", - script: BUBBLE_SCRIPT, - }); - //add this bubble to an array of bubbles so we can keep track of them - _t.bubbles.push(_t.currentBubble) + unload: function(entityID) { + Script.update.disconnect(this.update); + }, + update: function(deltaTime) { + var GRAB_USER_DATA_KEY = "grabKey"; + var defaultGrabData = { + activated: false, + avatarId: null + }; + var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, _this.entityID, defaultGrabData); + if (grabData.activated && grabData.avatarId === MyAvatar.sessionUUID) { + print('being grabbed') + + _this.beingGrabbed = true; + + + if (_this.currentBubble === null) { + _this.spawnBubble(); + } + var properties = Entities.getEntityProperties(_this.entityID); + + // remember we're being grabbed so we can detect being released + + + // print out that we're being grabbed + _this.growBubbleWithWandVelocity(properties); + + var wandTipPosition = _this.getWandTipPosition(properties); + //update the bubble to stay with the wand tip + Entities.editEntity(_this.currentBubble, { + position: wandTipPosition, + + }); + + } else if (_this.beingGrabbed) { + + // if we are not being grabbed, and we previously were, then we were just released, remember that + // and print out a message + _this.beingGrabbed = false; + Entities.deleteEntity(_this.currentBubble); + return + } + + + }, + getWandTipPosition: function(properties) { + var upVector = Quat.getUp(properties.rotation); + var frontVector = Quat.getFront(properties.rotation); + var upOffset = Vec3.multiply(upVector, WAND_TIP_OFFSET); + var wandTipPosition = Vec3.sum(properties.position, upOffset); + this.wandTipPosition = wandTipPosition; + return wandTipPosition + }, + growBubbleWithWandVelocity: function(properties) { + print('grow bubble') + var wandPosition = properties.position; + var wandTipPosition = this.getWandTipPosition(properties) + + + var velocity = Vec3.subtract(wandPosition, this.lastPosition) + var velocityStrength = Vec3.length(velocity) * VELOCITY_STRENGTH_MULTIPLIER; + + + + // if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { + // velocityStrength = 0 + // } + + // if (velocityStrength > VELOCITY_STRENGTH_MAX) { + // velocityStrength = VELOCITY_STRENGTH_MAX + // } + + print('VELOCITY STRENGTH:::'+velocityStrength) + print('V THRESH:'+ VELOCITY_THRESHOLD) + print('debug 1') + //store the last position of the wand for velocity calculations + this.lastPosition = wandPosition; + + //actually grow the bubble + var dimensions = Entities.getEntityProperties(this.currentBubble).dimensions; + print('dim x '+dimensions.x) + if (velocityStrength > VELOCITY_THRESHOLD) { + + //add some variation in bubble sizes + var bubbleSize = randInt(BUBBLE_SIZE_MIN, BUBBLE_SIZE_MAX); + bubbleSize = bubbleSize / BUBBLE_DIVISOR; + + print('bubbleSize '+ bubbleSize) + //release the bubble if its dimensions are bigger than the bubble size + if (dimensions.x > bubbleSize) { + //bubbles pop after existing for a bit -- so set a random lifetime + var lifetime = randInt(BUBBLE_LIFETIME_MIN, BUBBLE_LIFETIME_MAX); + + Entities.editEntity(this.currentBubble, { + velocity: velocity, + lifetime: lifetime + }); + + //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble + this.spawnBubble(); + + return + } else { + dimensions.x += GROWTH_FACTOR * velocityStrength; + dimensions.y += GROWTH_FACTOR * velocityStrength; + dimensions.z += GROWTH_FACTOR * velocityStrength; + + } + } else { + if (dimensions.x >= SHRINK_LOWER_LIMIT) { + dimensions.x -= SHRINK_FACTOR; + dimensions.y -= SHRINK_FACTOR; + dimensions.z -= SHRINK_FACTOR; + } + + } + + //make the bubble bigger + Entities.editEntity(this.currentBubble, { + dimensions: dimensions + }); + }, + spawnBubble: function() { + + //create a new bubble at the tip of the wand + //the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position + var properties = Entities.getEntityProperties(this.entityID); + var wandPosition = properties.position; + + wandTipPosition = this.getWandTipPosition(properties); + this.wandTipPosition = wandTipPosition; + + //store the position of the tip for use in velocity calculations + this.lastPosition = wandPosition; + + //create a bubble at the wand tip + this.currentBubble = Entities.addEntity({ + name:'Bubble', + type: 'Model', + modelURL: BUBBLE_MODEL, + position: wandTipPosition, + dimensions: { + x: 0.01, + y: 0.01, + z: 0.01 + }, + collisionsWillMove: true, //true + ignoreForCollisions: false, //false + gravity: BUBBLE_GRAVITY, + shapeType: "sphere", + script: BUBBLE_SCRIPT, + }); + //add this bubble to an array of bubbles so we can keep track of them + this.bubbles.push(this.currentBubble) + + } - }, - init: function() { - var _t = this; - this.spawnBubble(); - Script.update.connect(BubbleWand.update); } - } - + return new BubbleWand(); }) \ No newline at end of file From 5ac084ad4f8abe2e0c49579f0384844b1566501b Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 17 Sep 2015 20:57:07 -0700 Subject: [PATCH 21/58] Randomize bubble gravity, code cleanup --- examples/toys/bubblewand/bubble.js | 38 ++++++------- examples/toys/bubblewand/createWand.js | 3 +- examples/toys/bubblewand/wand.js | 78 ++++++++++++++------------ 3 files changed, 60 insertions(+), 59 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index 2629210c96..2904ca938f 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -14,7 +14,7 @@ Script.include("../../utilities.js"); Script.include("../../libraries/utils.js"); - var BUBBLE_PARTICLE_TEXTURE = "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png" + var BUBBLE_PARTICLE_TEXTURE = "http://hifi-public.s3.amazonaws.com/james/bubblewand/textures/bubble_particle.png" BUBBLE_PARTICLE_COLOR = { @@ -30,10 +30,10 @@ this.preload = function(entityID) { // print('bubble preload') _this.entityID = entityID; - Script.update.connect(_this.internalUpdate); + Script.update.connect(_this.update); }; - this.internalUpdate = function() { + this.update = function() { // we want the position at unload but for some reason it keeps getting set to 0,0,0 -- so i just exclude that location. sorry origin bubbles. var tmpProperties = Entities.getEntityProperties(_this.entityID); if (tmpProperties.position.x !== 0 && tmpProperties.position.y !== 0 && tmpProperties.position.z !== 0) { @@ -43,20 +43,18 @@ }; this.unload = function(entityID) { - Script.update.disconnect(this.internalUpdate); - var position = properties.position; - _this.endOfBubble(position); + Script.update.disconnect(this.update); + + //TODO: Unload doesn't seem like the right place to do this. We really want to know that our lifetime is over. + _this.createBurstParticles(); }; - this.endOfBubble = function(position) { - this.createBurstParticles(position); - } - this.createBurstParticles = function(position) { - var _t = this; - //get the current position of the bubble + this.createBurstParticles = function() { + //get the current position and dimensions of the bubble var position = properties.position; - //var orientation = properties.orientation; + var dimensions = properties.dimensions; + var animationSettings = JSON.stringify({ fps: 30, @@ -73,15 +71,11 @@ animationIsPlaying: true, position: position, lifetime: 0.2, - dimensions: { - x: 1, - y: 1, - z: 1 - }, + dimensions: dimensions, emitVelocity: { - x: 0, - y: 0, - z: 0 + x: 0.25, + y: 0.25, + z: 0.25 }, velocitySpread: { x: 0.45, @@ -94,7 +88,7 @@ z: 0 }, alphaStart: 1.0, - alpha: 1, + alpha: 0.5, alphaFinish: 0.0, textures: BUBBLE_PARTICLE_TEXTURE, color: BUBBLE_PARTICLE_COLOR, diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 6548090b74..51ac9738f1 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -20,6 +20,7 @@ var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand var WAND_SCRIPT_URL = Script.resolvePath("wand.js"); //create the wand in front of the avatar var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); + var tablePosition = { x:546.48, y:495.63, @@ -33,7 +34,7 @@ var wand = Entities.addEntity({ position: IN_TOYBOX? tablePosition: center, gravity: { x: 0, - y: 0, + y: -9.8, z: 0, }, dimensions: { diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 2b57ccda78..38fbf161b8 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -19,16 +19,17 @@ var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; var BUBBLE_SCRIPT = Script.resolvePath('bubble.js'); - var BUBBLE_GRAVITY = { - x: 0, - y: -0.1, - z: 0 - }; - var BUBBLE_DIVISOR = 50; + var BUBBLE_INITIAL_DIMENSIONS = { + x: 0.01, + y: 0.01, + z: 0.01 + } + var BUBBLE_LIFETIME_MIN = 3; var BUBBLE_LIFETIME_MAX = 8; var BUBBLE_SIZE_MIN = 1; var BUBBLE_SIZE_MAX = 5; + var BUBBLE_DIVISOR = 50; var GROWTH_FACTOR = 0.005; var SHRINK_FACTOR = 0.001; var SHRINK_LOWER_LIMIT = 0.02; @@ -43,7 +44,6 @@ var BubbleWand = function() { _this = this; - print('WAND CONSTRUCTOR!') } BubbleWand.prototype = { @@ -65,9 +65,9 @@ }; var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, _this.entityID, defaultGrabData); if (grabData.activated && grabData.avatarId === MyAvatar.sessionUUID) { - print('being grabbed') - _this.beingGrabbed = true; + // remember we're being grabbed so we can detect being released + _this.beingGrabbed = true; if (_this.currentBubble === null) { @@ -75,13 +75,10 @@ } var properties = Entities.getEntityProperties(_this.entityID); - // remember we're being grabbed so we can detect being released - - - // print out that we're being grabbed _this.growBubbleWithWandVelocity(properties); var wandTipPosition = _this.getWandTipPosition(properties); + //update the bubble to stay with the wand tip Entities.editEntity(_this.currentBubble, { position: wandTipPosition, @@ -91,15 +88,19 @@ } else if (_this.beingGrabbed) { // if we are not being grabbed, and we previously were, then we were just released, remember that - // and print out a message + _this.beingGrabbed = false; + + //remove the current bubble when the wand is released Entities.deleteEntity(_this.currentBubble); return } - }, getWandTipPosition: function(properties) { + + //the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position + var upVector = Quat.getUp(properties.rotation); var frontVector = Quat.getFront(properties.rotation); var upOffset = Vec3.multiply(upVector, WAND_TIP_OFFSET); @@ -107,16 +108,26 @@ this.wandTipPosition = wandTipPosition; return wandTipPosition }, + randomizeBubbleGravity: function() { + + var randomNumber = randInt(0, 3) + var gravity: { + x: 0, + y: -randomNumber / 10, + z: 0 + } + return gravity + }, growBubbleWithWandVelocity: function(properties) { - print('grow bubble') + var wandPosition = properties.position; var wandTipPosition = this.getWandTipPosition(properties) - + var velocity = Vec3.subtract(wandPosition, this.lastPosition) var velocityStrength = Vec3.length(velocity) * VELOCITY_STRENGTH_MULTIPLIER; - + // if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { // velocityStrength = 0 @@ -126,22 +137,19 @@ // velocityStrength = VELOCITY_STRENGTH_MAX // } - print('VELOCITY STRENGTH:::'+velocityStrength) - print('V THRESH:'+ VELOCITY_THRESHOLD) - print('debug 1') + //store the last position of the wand for velocity calculations this.lastPosition = wandPosition; //actually grow the bubble var dimensions = Entities.getEntityProperties(this.currentBubble).dimensions; - print('dim x '+dimensions.x) + if (velocityStrength > VELOCITY_THRESHOLD) { //add some variation in bubble sizes var bubbleSize = randInt(BUBBLE_SIZE_MIN, BUBBLE_SIZE_MAX); bubbleSize = bubbleSize / BUBBLE_DIVISOR; - - print('bubbleSize '+ bubbleSize) + //release the bubble if its dimensions are bigger than the bubble size if (dimensions.x > bubbleSize) { //bubbles pop after existing for a bit -- so set a random lifetime @@ -149,7 +157,8 @@ Entities.editEntity(this.currentBubble, { velocity: velocity, - lifetime: lifetime + lifetime: lifetime, + gravity: this.randomizeBubbleGravity() }); //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble @@ -157,12 +166,15 @@ return } else { + + // if the bubble is not yet full size, make the current bubble bigger dimensions.x += GROWTH_FACTOR * velocityStrength; dimensions.y += GROWTH_FACTOR * velocityStrength; dimensions.z += GROWTH_FACTOR * velocityStrength; } } else { + // if the wand is not moving, make the current bubble smaller if (dimensions.x >= SHRINK_LOWER_LIMIT) { dimensions.x -= SHRINK_FACTOR; dimensions.y -= SHRINK_FACTOR; @@ -171,7 +183,7 @@ } - //make the bubble bigger + //adjust the bubble dimensions Entities.editEntity(this.currentBubble, { dimensions: dimensions }); @@ -179,7 +191,6 @@ spawnBubble: function() { //create a new bubble at the tip of the wand - //the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position var properties = Entities.getEntityProperties(this.entityID); var wandPosition = properties.position; @@ -191,18 +202,13 @@ //create a bubble at the wand tip this.currentBubble = Entities.addEntity({ - name:'Bubble', + name: 'Bubble', type: 'Model', modelURL: BUBBLE_MODEL, position: wandTipPosition, - dimensions: { - x: 0.01, - y: 0.01, - z: 0.01 - }, - collisionsWillMove: true, //true - ignoreForCollisions: false, //false - gravity: BUBBLE_GRAVITY, + dimensions: BUBBLE_INITIAL_DIMENSIONS, + collisionsWillMove: true, + ignoreForCollisions: false, shapeType: "sphere", script: BUBBLE_SCRIPT, }); From 8a7798fcd759eef45cebf18e1a44138145f4fbc9 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 17 Sep 2015 22:00:44 -0700 Subject: [PATCH 22/58] disable bubble particle burst until i know the right for an entity to watch and see if it is deleted. --- examples/toys/bubblewand/bubble.js | 25 ++++++++++++++----------- examples/toys/bubblewand/createWand.js | 5 +++-- examples/toys/bubblewand/wand.js | 19 +++++++++---------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index 2904ca938f..69764c0c97 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -16,7 +16,6 @@ var BUBBLE_PARTICLE_TEXTURE = "http://hifi-public.s3.amazonaws.com/james/bubblewand/textures/bubble_particle.png" - BUBBLE_PARTICLE_COLOR = { red: 0, green: 40, @@ -46,7 +45,7 @@ Script.update.disconnect(this.update); //TODO: Unload doesn't seem like the right place to do this. We really want to know that our lifetime is over. - _this.createBurstParticles(); + // _this.createBurstParticles(); }; @@ -70,12 +69,16 @@ animationSettings: animationSettings, animationIsPlaying: true, position: position, - lifetime: 0.2, - dimensions: dimensions, + lifetime: 0.1, + dimensions: { + x: 10, + y: 10, + z: 10 + }, emitVelocity: { - x: 0.25, - y: 0.25, - z: 0.25 + x: 0.35, + y: 0.35, + z: 0.35 }, velocitySpread: { x: 0.45, @@ -87,12 +90,12 @@ y: -0.1, z: 0 }, - alphaStart: 1.0, + alphaStart: 0.5, alpha: 0.5, - alphaFinish: 0.0, + alphaFinish: 0, textures: BUBBLE_PARTICLE_TEXTURE, - color: BUBBLE_PARTICLE_COLOR, - lifespan: 0.2, + // color: BUBBLE_PARTICLE_COLOR, + lifespan: 0.1, visible: true, locked: false }); diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 51ac9738f1..a54e438e5d 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -19,7 +19,7 @@ var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wa var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; var WAND_SCRIPT_URL = Script.resolvePath("wand.js"); //create the wand in front of the avatar -var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); +var center = Vec3.sum(Vec3.sum(MyAvatar.position, {x: 0, y: 0.5, z: 0}), Vec3.multiply(0.5, Quat.getFront(Camera.getOrientation()))); var tablePosition = { x:546.48, @@ -34,7 +34,8 @@ var wand = Entities.addEntity({ position: IN_TOYBOX? tablePosition: center, gravity: { x: 0, - y: -9.8, + y:0, + // y: -9.8, z: 0, }, dimensions: { diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 38fbf161b8..e0495f5f40 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -7,7 +7,6 @@ // // Makes bubbles when you wave the object around. // -// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -17,7 +16,7 @@ Script.include("../../libraries/utils.js"); var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; - var BUBBLE_SCRIPT = Script.resolvePath('bubble.js'); + var BUBBLE_SCRIPT = Script.resolvePath('bubble.js?'+randInt(0,10000)); var BUBBLE_INITIAL_DIMENSIONS = { x: 0.01, @@ -39,7 +38,6 @@ var VELOCITY_STRENGTH_MULTIPLIER = 100; var VELOCITY_THRESHOLD = 1; - var _this; var BubbleWand = function() { @@ -69,10 +67,11 @@ // remember we're being grabbed so we can detect being released _this.beingGrabbed = true; - + //the first time we want to make a bubble if (_this.currentBubble === null) { - _this.spawnBubble(); + _this.createBubbleAtTipOfWand(); } + var properties = Entities.getEntityProperties(_this.entityID); _this.growBubbleWithWandVelocity(properties); @@ -93,6 +92,7 @@ //remove the current bubble when the wand is released Entities.deleteEntity(_this.currentBubble); + _this.currentBubble=null return } @@ -110,8 +110,8 @@ }, randomizeBubbleGravity: function() { - var randomNumber = randInt(0, 3) - var gravity: { + var randomNumber = randInt(0, 3); + var gravity= { x: 0, y: -randomNumber / 10, z: 0 @@ -137,7 +137,6 @@ // velocityStrength = VELOCITY_STRENGTH_MAX // } - //store the last position of the wand for velocity calculations this.lastPosition = wandPosition; @@ -162,7 +161,7 @@ }); //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble - this.spawnBubble(); + this.createBubbleAtTipOfWand(); return } else { @@ -188,7 +187,7 @@ dimensions: dimensions }); }, - spawnBubble: function() { + createBubbleAtTipOfWand: function() { //create a new bubble at the tip of the wand var properties = Entities.getEntityProperties(this.entityID); From 9a3a87eedf94726882e1896383bc604eb1d4bb01 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 18 Sep 2015 10:03:21 -0700 Subject: [PATCH 23/58] improve velocity calculations for wand --- examples/toys/bubblewand/bubble.js | 7 +++-- examples/toys/bubblewand/createWand.js | 4 +-- examples/toys/bubblewand/wand.js | 39 +++++++++++++++++--------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index 69764c0c97..f69116ef92 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -71,9 +71,9 @@ position: position, lifetime: 0.1, dimensions: { - x: 10, - y: 10, - z: 10 + x: 1, + y: 1, + z: 1 }, emitVelocity: { x: 0.35, @@ -90,6 +90,7 @@ y: -0.1, z: 0 }, + particleRadius:0.1, alphaStart: 0.5, alpha: 0.5, alphaFinish: 0, diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index a54e438e5d..37041fdbf6 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -18,7 +18,7 @@ Script.include("../../libraries/utils.js"); var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; var WAND_SCRIPT_URL = Script.resolvePath("wand.js"); -//create the wand in front of the avatar +//create the wand in front of the avatar blahy var center = Vec3.sum(Vec3.sum(MyAvatar.position, {x: 0, y: 0.5, z: 0}), Vec3.multiply(0.5, Quat.getFront(Camera.getOrientation()))); var tablePosition = { @@ -26,7 +26,7 @@ var tablePosition = { y:495.63, z:506.25 } - +print('test refresh') var wand = Entities.addEntity({ name:'Bubble Wand', type: "Model", diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index e0495f5f40..9da4901d56 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -16,7 +16,7 @@ Script.include("../../libraries/utils.js"); var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; - var BUBBLE_SCRIPT = Script.resolvePath('bubble.js?'+randInt(0,10000)); + var BUBBLE_SCRIPT = Script.resolvePath('bubble.js?' + randInt(0, 10000)); var BUBBLE_INITIAL_DIMENSIONS = { x: 0.01, @@ -29,14 +29,14 @@ var BUBBLE_SIZE_MIN = 1; var BUBBLE_SIZE_MAX = 5; var BUBBLE_DIVISOR = 50; + var BUBBLE_LINEAR_DAMPING = 0.4; var GROWTH_FACTOR = 0.005; var SHRINK_FACTOR = 0.001; var SHRINK_LOWER_LIMIT = 0.02; var WAND_TIP_OFFSET = 0.05; var VELOCITY_STRENGTH_LOWER_LIMIT = 0.01; var VELOCITY_STRENGH_MAX = 10; - var VELOCITY_STRENGTH_MULTIPLIER = 100; - var VELOCITY_THRESHOLD = 1; + var VELOCITY_THRESHOLD = 0.5; var _this; @@ -73,8 +73,8 @@ } var properties = Entities.getEntityProperties(_this.entityID); - - _this.growBubbleWithWandVelocity(properties); + var dt = deltaTime; + _this.growBubbleWithWandVelocity(properties, dt); var wandTipPosition = _this.getWandTipPosition(properties); @@ -92,7 +92,7 @@ //remove the current bubble when the wand is released Entities.deleteEntity(_this.currentBubble); - _this.currentBubble=null + _this.currentBubble = null return } @@ -108,27 +108,34 @@ this.wandTipPosition = wandTipPosition; return wandTipPosition }, + addCollisionsToBubbleAfterCreation: function(bubble) { + Entities.editEntity(bubble, { + collisionsWillMove: true + }) + + }, randomizeBubbleGravity: function() { var randomNumber = randInt(0, 3); - var gravity= { + var gravity = { x: 0, y: -randomNumber / 10, z: 0 } return gravity }, - growBubbleWithWandVelocity: function(properties) { - + growBubbleWithWandVelocity: function(properties, deltaTime) { var wandPosition = properties.position; var wandTipPosition = this.getWandTipPosition(properties) - var velocity = Vec3.subtract(wandPosition, this.lastPosition) - var velocityStrength = Vec3.length(velocity) * VELOCITY_STRENGTH_MULTIPLIER; - - - + var distance = Vec3.subtract(wandPosition, this.lastPosition); + var velocity = Vec3.multiply(distance,1/deltaTime); + + + var velocityStrength = Vec3.length(velocity); + print('velocityStrength' +velocityStrength) + // if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { // velocityStrength = 0 // } @@ -187,6 +194,9 @@ dimensions: dimensions }); }, + setBubbleOwner:function(bubble){ + setEntityCustomData(BUBBLE_USER_DATA_KEY, bubble, { avatarID: MyAvatar.sessionUUID }); + }, createBubbleAtTipOfWand: function() { //create a new bubble at the tip of the wand @@ -208,6 +218,7 @@ dimensions: BUBBLE_INITIAL_DIMENSIONS, collisionsWillMove: true, ignoreForCollisions: false, + linearDamping: BUBBLE_LINEAR_DAMPING, shapeType: "sphere", script: BUBBLE_SCRIPT, }); From 15ea9219d6c9110a26ceb8f615eef11c5e61c438 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 18 Sep 2015 10:41:44 -0700 Subject: [PATCH 24/58] collision timeouts --- examples/toys/bubblewand/bubble.js | 16 +++++++++++++--- examples/toys/bubblewand/wand.js | 25 +++++++++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index f69116ef92..ebb5a36d2d 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -16,6 +16,8 @@ var BUBBLE_PARTICLE_TEXTURE = "http://hifi-public.s3.amazonaws.com/james/bubblewand/textures/bubble_particle.png" + var BUBBLE_USER_DATA_KEY = "BubbleKey"; + BUBBLE_PARTICLE_COLOR = { red: 0, green: 40, @@ -44,8 +46,16 @@ this.unload = function(entityID) { Script.update.disconnect(this.update); - //TODO: Unload doesn't seem like the right place to do this. We really want to know that our lifetime is over. - // _this.createBurstParticles(); + var defaultGrabData = { + avatarId: null + }; + + var bubbleCreator = getEntityCustomData(BUBBLE_USER_DATA_KEY, entityID, defaultGrabData); + + if (bubbleCreator === MyAvatar.sessionUUID) { + this.createBurstParticles(); + } + }; @@ -90,7 +100,7 @@ y: -0.1, z: 0 }, - particleRadius:0.1, + particleRadius: 0.1, alphaStart: 0.5, alpha: 0.5, alphaFinish: 0, diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 9da4901d56..0e960f1f64 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -10,6 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + (function() { Script.include("../../utilities.js"); @@ -18,6 +19,7 @@ var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; var BUBBLE_SCRIPT = Script.resolvePath('bubble.js?' + randInt(0, 10000)); + var BUBBLE_USER_DATA_KEY = "BubbleKey"; var BUBBLE_INITIAL_DIMENSIONS = { x: 0.01, y: 0.01, @@ -109,6 +111,8 @@ return wandTipPosition }, addCollisionsToBubbleAfterCreation: function(bubble) { + + print('adding collisions to bubble' + bubble); Entities.editEntity(bubble, { collisionsWillMove: true }) @@ -130,12 +134,12 @@ var distance = Vec3.subtract(wandPosition, this.lastPosition); - var velocity = Vec3.multiply(distance,1/deltaTime); - - + var velocity = Vec3.multiply(distance, 1 / deltaTime); + + var velocityStrength = Vec3.length(velocity); - print('velocityStrength' +velocityStrength) - + print('velocityStrength' + velocityStrength) + // if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { // velocityStrength = 0 // } @@ -167,6 +171,9 @@ gravity: this.randomizeBubbleGravity() }); + //wait to make the bubbles collidable, so that they dont hit each other and the wand + Script.setTimeout(this.addCollisionsToBubbleAfterCreation(this.currentBubble), lifetime / 2); + //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble this.createBubbleAtTipOfWand(); @@ -194,8 +201,10 @@ dimensions: dimensions }); }, - setBubbleOwner:function(bubble){ - setEntityCustomData(BUBBLE_USER_DATA_KEY, bubble, { avatarID: MyAvatar.sessionUUID }); + setBubbleOwner: function(bubble) { + setEntityCustomData(BUBBLE_USER_DATA_KEY, bubble, { + avatarID: MyAvatar.sessionUUID + }); }, createBubbleAtTipOfWand: function() { @@ -216,7 +225,7 @@ modelURL: BUBBLE_MODEL, position: wandTipPosition, dimensions: BUBBLE_INITIAL_DIMENSIONS, - collisionsWillMove: true, + collisionsWillMove: false, ignoreForCollisions: false, linearDamping: BUBBLE_LINEAR_DAMPING, shapeType: "sphere", From 031761fa57104875bb36fd2446cd6e850c0f80e6 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 18 Sep 2015 14:27:57 -0700 Subject: [PATCH 25/58] added some logging while things were broken --- examples/toys/bubblewand/bubble.js | 56 ++++++++++++++------------ examples/toys/bubblewand/createWand.js | 14 +++---- examples/toys/bubblewand/wand.js | 27 ++++++++----- 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index ebb5a36d2d..b52f0d326a 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -18,12 +18,6 @@ var BUBBLE_USER_DATA_KEY = "BubbleKey"; - BUBBLE_PARTICLE_COLOR = { - red: 0, - green: 40, - blue: 255, - }; - var _this = this; var properties; @@ -41,18 +35,28 @@ properties = tmpProperties; } + // var defaultBubbleData={ + // avatarID:'noAvatar' + // } + + var entityData = getEntityCustomData(BUBBLE_USER_DATA_KEY, _this.entityID); + + if (entityData && entityData.avatarID && entityData.avatarID === MyAvatar.sessionUUID) { + _this.bubbleCreator = true + + } + + + }; this.unload = function(entityID) { Script.update.disconnect(this.update); - var defaultGrabData = { - avatarId: null - }; + print('bubble unload') - var bubbleCreator = getEntityCustomData(BUBBLE_USER_DATA_KEY, entityID, defaultGrabData); - - if (bubbleCreator === MyAvatar.sessionUUID) { + if (this.bubbleCreator) { + print('PLAYING BURST') this.createBurstParticles(); } @@ -77,36 +81,36 @@ var particleBurst = Entities.addEntity({ type: "ParticleEffect", animationSettings: animationSettings, + emitRate: 100, animationIsPlaying: true, position: position, - lifetime: 0.1, + lifespan: 1, dimensions: { x: 1, y: 1, z: 1 }, emitVelocity: { - x: 0.35, - y: 0.35, - z: 0.35 + x: 1, + y: 1, + z: 1 }, velocitySpread: { - x: 0.45, - y: 0.45, - z: 0.45 + x: 1, + y: 1, + z: 1 }, emitAcceleration: { - x: 0, - y: -0.1, - z: 0 + x: 0.25, + y: 0.25, + z: 0.25 }, - particleRadius: 0.1, - alphaStart: 0.5, + radiusSpread: 0.01, + particleRadius: 0.02, + alphaStart: 1.0, alpha: 0.5, alphaFinish: 0, textures: BUBBLE_PARTICLE_TEXTURE, - // color: BUBBLE_PARTICLE_COLOR, - lifespan: 0.1, visible: true, locked: false }); diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 37041fdbf6..a50b7185f6 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -4,20 +4,20 @@ // Script Type: Entity Spawner // Created by James B. Pollack @imgntn -- 09/03/2015 // Copyright 2015 High Fidelity, Inc. -// +// // Loads a wand model and attaches the bubble wand behavior. // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html var IN_TOYBOX = false; -Script.include("../../utilities.js"); +Script.include("../../utilities.js"); Script.include("../../libraries/utils.js"); var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; -var WAND_SCRIPT_URL = Script.resolvePath("wand.js"); +var WAND_SCRIPT_URL = Script.resolvePath("wand.js?"+randInt(0,500)); //create the wand in front of the avatar blahy var center = Vec3.sum(Vec3.sum(MyAvatar.position, {x: 0, y: 0.5, z: 0}), Vec3.multiply(0.5, Quat.getFront(Camera.getOrientation()))); @@ -26,7 +26,7 @@ var tablePosition = { y:495.63, z:506.25 } -print('test refresh') + var wand = Entities.addEntity({ name:'Bubble Wand', type: "Model", @@ -39,9 +39,9 @@ var wand = Entities.addEntity({ z: 0, }, dimensions: { - x: 0.025, - y: 0.125, - z: 0.025 + x: 0.05, + y: 0.25, + z: 0.05 }, //must be enabled to be grabbable in the physics engine collisionsWillMove: true, diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 0e960f1f64..3d574d89ca 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -17,8 +17,8 @@ Script.include("../../libraries/utils.js"); var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; - var BUBBLE_SCRIPT = Script.resolvePath('bubble.js?' + randInt(0, 10000)); - + var BUBBLE_SCRIPT = Script.resolvePath('bubble.js'); +//test var BUBBLE_USER_DATA_KEY = "BubbleKey"; var BUBBLE_INITIAL_DIMENSIONS = { x: 0.01, @@ -35,7 +35,7 @@ var GROWTH_FACTOR = 0.005; var SHRINK_FACTOR = 0.001; var SHRINK_LOWER_LIMIT = 0.02; - var WAND_TIP_OFFSET = 0.05; + var WAND_TIP_OFFSET = 0.095; var VELOCITY_STRENGTH_LOWER_LIMIT = 0.01; var VELOCITY_STRENGH_MAX = 10; var VELOCITY_THRESHOLD = 0.5; @@ -58,17 +58,19 @@ Script.update.disconnect(this.update); }, update: function(deltaTime) { + print('BW update') var GRAB_USER_DATA_KEY = "grabKey"; var defaultGrabData = { activated: false, avatarId: null }; var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, _this.entityID, defaultGrabData); + print('grabData'+JSON.stringify(grabData)) if (grabData.activated && grabData.avatarId === MyAvatar.sessionUUID) { // remember we're being grabbed so we can detect being released _this.beingGrabbed = true; - + print('being grabbed') //the first time we want to make a bubble if (_this.currentBubble === null) { _this.createBubbleAtTipOfWand(); @@ -87,9 +89,8 @@ }); } else if (_this.beingGrabbed) { - // if we are not being grabbed, and we previously were, then we were just released, remember that - + print('let go') _this.beingGrabbed = false; //remove the current bubble when the wand is released @@ -97,6 +98,7 @@ _this.currentBubble = null return } + print('not grabbed') }, getWandTipPosition: function(properties) { @@ -129,6 +131,7 @@ return gravity }, growBubbleWithWandVelocity: function(properties, deltaTime) { + print('grow bubble') var wandPosition = properties.position; var wandTipPosition = this.getWandTipPosition(properties) @@ -138,8 +141,7 @@ var velocityStrength = Vec3.length(velocity); - print('velocityStrength' + velocityStrength) - + velocityStrength = velocityStrength; // if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { // velocityStrength = 0 // } @@ -155,13 +157,15 @@ var dimensions = Entities.getEntityProperties(this.currentBubble).dimensions; if (velocityStrength > VELOCITY_THRESHOLD) { - + print('velocity over threshold') //add some variation in bubble sizes var bubbleSize = randInt(BUBBLE_SIZE_MIN, BUBBLE_SIZE_MAX); bubbleSize = bubbleSize / BUBBLE_DIVISOR; //release the bubble if its dimensions are bigger than the bubble size if (dimensions.x > bubbleSize) { + + print('release the bubble') //bubbles pop after existing for a bit -- so set a random lifetime var lifetime = randInt(BUBBLE_LIFETIME_MIN, BUBBLE_LIFETIME_MAX); @@ -174,9 +178,9 @@ //wait to make the bubbles collidable, so that they dont hit each other and the wand Script.setTimeout(this.addCollisionsToBubbleAfterCreation(this.currentBubble), lifetime / 2); + this.setBubbleOwner(this.currentBubble); //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble this.createBubbleAtTipOfWand(); - return } else { @@ -202,8 +206,9 @@ }); }, setBubbleOwner: function(bubble) { + print('SET BUBBLE OWNER', bubble) setEntityCustomData(BUBBLE_USER_DATA_KEY, bubble, { - avatarID: MyAvatar.sessionUUID + avatarID: MyAvatar.sessionUUID, }); }, createBubbleAtTipOfWand: function() { From ccf125c047426a2c481d3ee8c58a05fc6048fdde Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 18 Sep 2015 15:40:39 -0700 Subject: [PATCH 26/58] Cleanup comments --- examples/toys/bubblewand/bubble.js | 15 +++---------- examples/toys/bubblewand/createWand.js | 2 +- examples/toys/bubblewand/wand.js | 30 +++++++------------------- 3 files changed, 12 insertions(+), 35 deletions(-) diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js index b52f0d326a..b6356d4025 100644 --- a/examples/toys/bubblewand/bubble.js +++ b/examples/toys/bubblewand/bubble.js @@ -23,7 +23,6 @@ var properties; this.preload = function(entityID) { - // print('bubble preload') _this.entityID = entityID; Script.update.connect(_this.update); }; @@ -35,28 +34,20 @@ properties = tmpProperties; } - // var defaultBubbleData={ - // avatarID:'noAvatar' - // } - + //we want to play the particle burst exactly once, so we make sure that this is a bubble we own. var entityData = getEntityCustomData(BUBBLE_USER_DATA_KEY, _this.entityID); if (entityData && entityData.avatarID && entityData.avatarID === MyAvatar.sessionUUID) { _this.bubbleCreator = true - } - - }; this.unload = function(entityID) { Script.update.disconnect(this.update); - print('bubble unload') - + //only play particle burst for our bubbles if (this.bubbleCreator) { - print('PLAYING BURST') this.createBurstParticles(); } @@ -84,7 +75,7 @@ emitRate: 100, animationIsPlaying: true, position: position, - lifespan: 1, + lifespan: 0.2, dimensions: { x: 1, y: 1, diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index a50b7185f6..c99f648e04 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -17,7 +17,7 @@ Script.include("../../libraries/utils.js"); var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; -var WAND_SCRIPT_URL = Script.resolvePath("wand.js?"+randInt(0,500)); +var WAND_SCRIPT_URL = Script.resolvePath("wand.js"); //create the wand in front of the avatar blahy var center = Vec3.sum(Vec3.sum(MyAvatar.position, {x: 0, y: 0.5, z: 0}), Vec3.multiply(0.5, Quat.getFront(Camera.getOrientation()))); diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 3d574d89ca..67b5b43573 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -18,7 +18,7 @@ var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; var BUBBLE_SCRIPT = Script.resolvePath('bubble.js'); -//test + var BUBBLE_USER_DATA_KEY = "BubbleKey"; var BUBBLE_INITIAL_DIMENSIONS = { x: 0.01, @@ -36,10 +36,10 @@ var SHRINK_FACTOR = 0.001; var SHRINK_LOWER_LIMIT = 0.02; var WAND_TIP_OFFSET = 0.095; - var VELOCITY_STRENGTH_LOWER_LIMIT = 0.01; - var VELOCITY_STRENGH_MAX = 10; var VELOCITY_THRESHOLD = 0.5; + var GRAB_USER_DATA_KEY = "grabKey"; + var _this; var BubbleWand = function() { @@ -58,19 +58,16 @@ Script.update.disconnect(this.update); }, update: function(deltaTime) { - print('BW update') - var GRAB_USER_DATA_KEY = "grabKey"; var defaultGrabData = { activated: false, avatarId: null }; var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, _this.entityID, defaultGrabData); - print('grabData'+JSON.stringify(grabData)) - if (grabData.activated && grabData.avatarId === MyAvatar.sessionUUID) { + if (grabData.activated && grabData.avatarId === MyAvatar.sessionUUID) { // remember we're being grabbed so we can detect being released _this.beingGrabbed = true; - print('being grabbed') + //the first time we want to make a bubble if (_this.currentBubble === null) { _this.createBubbleAtTipOfWand(); @@ -90,7 +87,6 @@ } else if (_this.beingGrabbed) { // if we are not being grabbed, and we previously were, then we were just released, remember that - print('let go') _this.beingGrabbed = false; //remove the current bubble when the wand is released @@ -98,7 +94,7 @@ _this.currentBubble = null return } - print('not grabbed') + }, getWandTipPosition: function(properties) { @@ -114,7 +110,6 @@ }, addCollisionsToBubbleAfterCreation: function(bubble) { - print('adding collisions to bubble' + bubble); Entities.editEntity(bubble, { collisionsWillMove: true }) @@ -131,7 +126,6 @@ return gravity }, growBubbleWithWandVelocity: function(properties, deltaTime) { - print('grow bubble') var wandPosition = properties.position; var wandTipPosition = this.getWandTipPosition(properties) @@ -142,13 +136,6 @@ var velocityStrength = Vec3.length(velocity); velocityStrength = velocityStrength; - // if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) { - // velocityStrength = 0 - // } - - // if (velocityStrength > VELOCITY_STRENGTH_MAX) { - // velocityStrength = VELOCITY_STRENGTH_MAX - // } //store the last position of the wand for velocity calculations this.lastPosition = wandPosition; @@ -157,7 +144,6 @@ var dimensions = Entities.getEntityProperties(this.currentBubble).dimensions; if (velocityStrength > VELOCITY_THRESHOLD) { - print('velocity over threshold') //add some variation in bubble sizes var bubbleSize = randInt(BUBBLE_SIZE_MIN, BUBBLE_SIZE_MAX); bubbleSize = bubbleSize / BUBBLE_DIVISOR; @@ -165,7 +151,6 @@ //release the bubble if its dimensions are bigger than the bubble size if (dimensions.x > bubbleSize) { - print('release the bubble') //bubbles pop after existing for a bit -- so set a random lifetime var lifetime = randInt(BUBBLE_LIFETIME_MIN, BUBBLE_LIFETIME_MAX); @@ -178,7 +163,9 @@ //wait to make the bubbles collidable, so that they dont hit each other and the wand Script.setTimeout(this.addCollisionsToBubbleAfterCreation(this.currentBubble), lifetime / 2); + //we want to pop the bubble for just one person this.setBubbleOwner(this.currentBubble); + //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble this.createBubbleAtTipOfWand(); return @@ -206,7 +193,6 @@ }); }, setBubbleOwner: function(bubble) { - print('SET BUBBLE OWNER', bubble) setEntityCustomData(BUBBLE_USER_DATA_KEY, bubble, { avatarID: MyAvatar.sessionUUID, }); From c2a2abe615b7ba3298547ca189403269f4eeb0de Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 21 Sep 2015 11:05:51 -0700 Subject: [PATCH 27/58] Remove nested bubble entities and related code --- examples/toys/bubblewand/bubble.js | 112 ------------------------- examples/toys/bubblewand/createWand.js | 23 +++-- examples/toys/bubblewand/wand.js | 19 +---- 3 files changed, 12 insertions(+), 142 deletions(-) delete mode 100644 examples/toys/bubblewand/bubble.js diff --git a/examples/toys/bubblewand/bubble.js b/examples/toys/bubblewand/bubble.js deleted file mode 100644 index b6356d4025..0000000000 --- a/examples/toys/bubblewand/bubble.js +++ /dev/null @@ -1,112 +0,0 @@ -// bubble.js -// part of bubblewand -// -// Script Type: Entity -// Created by James B. Pollack @imgntn -- 09/03/2015 -// Copyright 2015 High Fidelity, Inc. -// -// example of a nested entity. plays a particle burst at the location where its deleted. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -(function() { - Script.include("../../utilities.js"); - Script.include("../../libraries/utils.js"); - - var BUBBLE_PARTICLE_TEXTURE = "http://hifi-public.s3.amazonaws.com/james/bubblewand/textures/bubble_particle.png" - - var BUBBLE_USER_DATA_KEY = "BubbleKey"; - - var _this = this; - - var properties; - - this.preload = function(entityID) { - _this.entityID = entityID; - Script.update.connect(_this.update); - }; - - this.update = function() { - // we want the position at unload but for some reason it keeps getting set to 0,0,0 -- so i just exclude that location. sorry origin bubbles. - var tmpProperties = Entities.getEntityProperties(_this.entityID); - if (tmpProperties.position.x !== 0 && tmpProperties.position.y !== 0 && tmpProperties.position.z !== 0) { - properties = tmpProperties; - } - - //we want to play the particle burst exactly once, so we make sure that this is a bubble we own. - var entityData = getEntityCustomData(BUBBLE_USER_DATA_KEY, _this.entityID); - - if (entityData && entityData.avatarID && entityData.avatarID === MyAvatar.sessionUUID) { - _this.bubbleCreator = true - } - - }; - - this.unload = function(entityID) { - Script.update.disconnect(this.update); - - //only play particle burst for our bubbles - if (this.bubbleCreator) { - this.createBurstParticles(); - } - - }; - - - this.createBurstParticles = function() { - //get the current position and dimensions of the bubble - var position = properties.position; - var dimensions = properties.dimensions; - - - var animationSettings = JSON.stringify({ - fps: 30, - frameIndex: 0, - running: true, - firstFrame: 0, - lastFrame: 30, - loop: false - }); - - var particleBurst = Entities.addEntity({ - type: "ParticleEffect", - animationSettings: animationSettings, - emitRate: 100, - animationIsPlaying: true, - position: position, - lifespan: 0.2, - dimensions: { - x: 1, - y: 1, - z: 1 - }, - emitVelocity: { - x: 1, - y: 1, - z: 1 - }, - velocitySpread: { - x: 1, - y: 1, - z: 1 - }, - emitAcceleration: { - x: 0.25, - y: 0.25, - z: 0.25 - }, - radiusSpread: 0.01, - particleRadius: 0.02, - alphaStart: 1.0, - alpha: 0.5, - alphaFinish: 0, - textures: BUBBLE_PARTICLE_TEXTURE, - visible: true, - locked: false - }); - - }; - - -}); \ No newline at end of file diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index c99f648e04..9ca018ea16 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -11,31 +11,28 @@ var IN_TOYBOX = false; -Script.include("../../utilities.js"); +Script.include("../../utilities.js"); Script.include("../../libraries/utils.js"); - var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj'; var WAND_SCRIPT_URL = Script.resolvePath("wand.js"); -//create the wand in front of the avatar blahy -var center = Vec3.sum(Vec3.sum(MyAvatar.position, {x: 0, y: 0.5, z: 0}), Vec3.multiply(0.5, Quat.getFront(Camera.getOrientation()))); -var tablePosition = { - x:546.48, - y:495.63, - z:506.25 -} +//create the wand in front of the avatar +var center = Vec3.sum(Vec3.sum(MyAvatar.position, { + x: 0, + y: 0.5, + z: 0 +}), Vec3.multiply(0.5, Quat.getFront(Camera.getOrientation()))); var wand = Entities.addEntity({ - name:'Bubble Wand', + name: 'Bubble Wand', type: "Model", modelURL: WAND_MODEL, - position: IN_TOYBOX? tablePosition: center, + position: center, gravity: { x: 0, - y:0, - // y: -9.8, + y: -9.8, z: 0, }, dimensions: { diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 67b5b43573..064d045f35 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -17,9 +17,7 @@ Script.include("../../libraries/utils.js"); var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx"; - var BUBBLE_SCRIPT = Script.resolvePath('bubble.js'); - var BUBBLE_USER_DATA_KEY = "BubbleKey"; var BUBBLE_INITIAL_DIMENSIONS = { x: 0.01, y: 0.01, @@ -47,7 +45,6 @@ } BubbleWand.prototype = { - bubbles: [], currentBubble: null, preload: function(entityID) { this.entityID = entityID; @@ -129,11 +126,9 @@ var wandPosition = properties.position; var wandTipPosition = this.getWandTipPosition(properties) - var distance = Vec3.subtract(wandPosition, this.lastPosition); var velocity = Vec3.multiply(distance, 1 / deltaTime); - var velocityStrength = Vec3.length(velocity); velocityStrength = velocityStrength; @@ -163,9 +158,6 @@ //wait to make the bubbles collidable, so that they dont hit each other and the wand Script.setTimeout(this.addCollisionsToBubbleAfterCreation(this.currentBubble), lifetime / 2); - //we want to pop the bubble for just one person - this.setBubbleOwner(this.currentBubble); - //release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble this.createBubbleAtTipOfWand(); return @@ -192,11 +184,6 @@ dimensions: dimensions }); }, - setBubbleOwner: function(bubble) { - setEntityCustomData(BUBBLE_USER_DATA_KEY, bubble, { - avatarID: MyAvatar.sessionUUID, - }); - }, createBubbleAtTipOfWand: function() { //create a new bubble at the tip of the wand @@ -219,11 +206,9 @@ collisionsWillMove: false, ignoreForCollisions: false, linearDamping: BUBBLE_LINEAR_DAMPING, - shapeType: "sphere", - script: BUBBLE_SCRIPT, + shapeType: "sphere" }); - //add this bubble to an array of bubbles so we can keep track of them - this.bubbles.push(this.currentBubble) + } From f3eef9322c73824a1f48d65c80a42f17e196c07c Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 21 Sep 2015 11:10:42 -0700 Subject: [PATCH 28/58] Remove toybox reference in spawner script --- examples/toys/bubblewand/createWand.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 9ca018ea16..76681a50d7 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -9,8 +9,6 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -var IN_TOYBOX = false; - Script.include("../../utilities.js"); Script.include("../../libraries/utils.js"); From e21c1cb67cbb94fd9efb627457b9159ba633d180 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 21 Sep 2015 11:51:53 -0700 Subject: [PATCH 29/58] make sure server/mixers are first in FIFO --- domain-server/src/DomainServer.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 49b7f2e183..7a57780fd1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1744,9 +1744,22 @@ void DomainServer::addStaticAssignmentsToQueue() { // if the domain-server has just restarted, // check if there are static assignments that we need to throw into the assignment queue - QHash staticHashCopy = _allAssignments; - QHash::iterator staticAssignment = staticHashCopy.begin(); - while (staticAssignment != staticHashCopy.end()) { + auto sharedAssignments = _allAssignments.values(); + + // sort the assignments to put the server/mixer assignments first + qSort(sharedAssignments.begin(), sharedAssignments.end(), [](SharedAssignmentPointer a, SharedAssignmentPointer b){ + if (a->getType() == b->getType()) { + return true; + } else if (a->getType() != Assignment::AgentType && b->getType() != Assignment::AgentType) { + return a->getType() < b->getType(); + } else { + return a->getType() != Assignment::AgentType; + } + }); + + auto staticAssignment = sharedAssignments.begin(); + + while (staticAssignment != sharedAssignments.end()) { // add any of the un-matched static assignments to the queue // enumerate the nodes and check if there is one with an attached assignment with matching UUID From 030404157e9f144c8d723ba102026568e68f588e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 21 Sep 2015 11:54:41 -0700 Subject: [PATCH 30/58] cleanup Assignment grab from iterator --- domain-server/src/DomainServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 7a57780fd1..614b0a1528 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1763,7 +1763,7 @@ void DomainServer::addStaticAssignmentsToQueue() { // add any of the un-matched static assignments to the queue // enumerate the nodes and check if there is one with an attached assignment with matching UUID - if (!DependencyManager::get()->nodeWithUUID(staticAssignment->data()->getUUID())) { + if (!DependencyManager::get()->nodeWithUUID((*staticAssignment)->getUUID())) { // this assignment has not been fulfilled - reset the UUID and add it to the assignment queue refreshStaticAssignmentAndAddToQueue(*staticAssignment); } From cd6ad306acde014a5262c1ef862031df8587f65a Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 21 Sep 2015 16:45:23 -0700 Subject: [PATCH 31/58] start transitioning to new grab methods --- examples/toys/bubblewand/createWand.js | 5 ++-- examples/toys/bubblewand/wand.js | 34 +++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 76681a50d7..9938acb63f 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -30,7 +30,7 @@ var wand = Entities.addEntity({ position: center, gravity: { x: 0, - y: -9.8, + y: 0, z: 0, }, dimensions: { @@ -45,7 +45,8 @@ var wand = Entities.addEntity({ }); function cleanup() { - Entities.deleteEntity(wand); +// the line below this is commented out to make the wand that you create persistent. + Entities.deleteEntity(wand); } diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 064d045f35..ae9a43eefc 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -45,6 +45,7 @@ } BubbleWand.prototype = { + timePassed:null, currentBubble: null, preload: function(entityID) { this.entityID = entityID; @@ -55,6 +56,7 @@ Script.update.disconnect(this.update); }, update: function(deltaTime) { + this.timePassed=deltaTime; var defaultGrabData = { activated: false, avatarId: null @@ -210,7 +212,37 @@ }); - } + }, + startNearGrab: function() { + print('START NEAR GRAB') + if (_this.currentBubble === null) { + _this.createBubbleAtTipOfWand(); + } + }, + continueNearGrab: function() { + + if (this.timePassed === null) { + this.timePassed = Date.now(); + } else { + var newTime = = Date.now() - this.timePassed; + // this.timePassed = newTime; + } + print('CONTINUE NEAR GRAB::' + this.timePassed); + + + }, + releaseGrab: function() { + //delete the lights and reset state + if (this.hasSpotlight) { + Entities.deleteEntity(this.spotlight); + Entities.deleteEntity(this.glowLight); + this.hasSpotlight = false; + this.glowLight = null; + this.spotlight = null; + this.whichHand = null; + + } + }, } From 81358b7f14c04bd695046e786abcee25e27bb5fb Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 21 Sep 2015 17:01:31 -0700 Subject: [PATCH 32/58] wand changes --- examples/toys/bubblewand/wand.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index ae9a43eefc..1541985315 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -40,12 +40,26 @@ var _this; + function interval() { + var lastTime = new Date().getTime() / 1000; + + return function getInterval() { + var newTime = new Date().getTime() / 1000; + var delta = newTime - lastTime; + lastTime = newTime; + return delta; + }; + } + + var checkInterval = interval(); + + var BubbleWand = function() { _this = this; } BubbleWand.prototype = { - timePassed:null, + timePassed: null, currentBubble: null, preload: function(entityID) { this.entityID = entityID; @@ -56,7 +70,7 @@ Script.update.disconnect(this.update); }, update: function(deltaTime) { - this.timePassed=deltaTime; + this.timePassed = deltaTime; var defaultGrabData = { activated: false, avatarId: null @@ -220,7 +234,7 @@ } }, continueNearGrab: function() { - + print('time passed:::' + checkInterval()); if (this.timePassed === null) { this.timePassed = Date.now(); } else { From e6776ef5ebe41cbe121ce672faa7f9197ba0d83c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 21 Sep 2015 17:29:39 -0700 Subject: [PATCH 33/58] split AnimIK::evaluate() into sub-functions also IK targets now in model-frame instead of root-frame --- .../animation/src/AnimInverseKinematics.cpp | 306 +++++++++--------- .../animation/src/AnimInverseKinematics.h | 10 +- libraries/animation/src/AnimNode.h | 17 + libraries/animation/src/Rig.cpp | 18 +- 4 files changed, 186 insertions(+), 165 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 6af58e89a1..1ccf984815 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -82,22 +82,8 @@ static int findRootJointInSkeleton(AnimSkeleton::ConstPointer skeleton, int inde return rootIndex; } -struct IKTarget { - AnimPose pose; - int index; - int rootIndex; -}; - -//virtual -const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVars, float dt, AnimNode::Triggers& triggersOut) { - - // NOTE: we assume that _relativePoses are up to date (e.g. loadPoses() was just called) - if (_relativePoses.empty()) { - return _relativePoses; - } - - // build a list of targets from _targetVarVec - std::vector targets; +void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::vector& targets) { + // build a list of valid targets from _targetVarVec and animVars bool removeUnfoundJoints = false; for (auto& targetVar : _targetVarVec) { if (targetVar.jointIndex == -1) { @@ -141,154 +127,160 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar } } } +} - if (targets.empty()) { - // no IK targets but still need to enforce constraints - std::map::iterator constraintItr = _constraints.begin(); - while (constraintItr != _constraints.end()) { - int index = constraintItr->first; - glm::quat rotation = _relativePoses[index].rot; - constraintItr->second->apply(rotation); - _relativePoses[index].rot = rotation; - ++constraintItr; - } - } else { - // clear the accumulators before we start the IK solver - for (auto& accumulatorPair: _accumulators) { - accumulatorPair.second.clear(); - } +void AnimInverseKinematics::solveWithCyclicCoordinateDescent(std::vector& targets) { + // compute absolute poses that correspond to relative target poses + AnimPoseVec absolutePoses; + computeAbsolutePoses(absolutePoses); - // compute absolute poses that correspond to relative target poses - AnimPoseVec absolutePoses; - computeAbsolutePoses(absolutePoses); + // clear the accumulators before we start the IK solver + for (auto& accumulatorPair: _accumulators) { + accumulatorPair.second.clear(); + } - float largestError = 0.0f; - const float ACCEPTABLE_RELATIVE_ERROR = 1.0e-3f; - int numLoops = 0; - const int MAX_IK_LOOPS = 16; - const quint64 MAX_IK_TIME = 10 * USECS_PER_MSEC; - quint64 expiry = usecTimestampNow() + MAX_IK_TIME; - do { - largestError = 0.0f; - int lowestMovedIndex = _relativePoses.size(); - for (auto& target: targets) { - int tipIndex = target.index; - AnimPose targetPose = target.pose; - int rootIndex = target.rootIndex; - if (rootIndex != -1) { - // transform targetPose into skeleton's absolute frame - AnimPose& rootPose = _relativePoses[rootIndex]; - targetPose.trans = rootPose.trans + rootPose.rot * targetPose.trans; - targetPose.rot = rootPose.rot * targetPose.rot; - } - - glm::vec3 tip = absolutePoses[tipIndex].trans; - float error = glm::length(targetPose.trans - tip); - - // descend toward root, pivoting each joint to get tip closer to target - int pivotIndex = _skeleton->getParentIndex(tipIndex); - while (pivotIndex != -1 && error > ACCEPTABLE_RELATIVE_ERROR) { - // compute the two lines that should be aligned - glm::vec3 jointPosition = absolutePoses[pivotIndex].trans; - glm::vec3 leverArm = tip - jointPosition; - glm::vec3 targetLine = targetPose.trans - jointPosition; - - // compute the axis of the rotation that would align them - glm::vec3 axis = glm::cross(leverArm, targetLine); - float axisLength = glm::length(axis); - if (axisLength > EPSILON) { - // compute deltaRotation for alignment (brings tip closer to target) - axis /= axisLength; - float angle = acosf(glm::dot(leverArm, targetLine) / (glm::length(leverArm) * glm::length(targetLine))); - - // NOTE: even when axisLength is not zero (e.g. lever-arm and pivot-arm are not quite aligned) it is - // still possible for the angle to be zero so we also check that to avoid unnecessary calculations. - if (angle > EPSILON) { - // reduce angle by half: slows convergence but adds stability to IK solution - angle = 0.5f * angle; - glm::quat deltaRotation = glm::angleAxis(angle, axis); - - int parentIndex = _skeleton->getParentIndex(pivotIndex); - if (parentIndex == -1) { - // TODO? apply constraints to root? - // TODO? harvest the root's transform as movement of entire skeleton? - } else { - // compute joint's new parent-relative rotation - // Q' = dQ * Q and Q = Qp * q --> q' = Qp^ * dQ * Q - glm::quat newRot = glm::normalize(glm::inverse( - absolutePoses[parentIndex].rot) * - deltaRotation * - absolutePoses[pivotIndex].rot); - RotationConstraint* constraint = getConstraint(pivotIndex); - if (constraint) { - bool constrained = constraint->apply(newRot); - if (constrained) { - // the constraint will modify the movement of the tip so we have to compute the modified - // model-frame deltaRotation - // Q' = Qp^ * dQ * Q --> dQ = Qp * Q' * Q^ - deltaRotation = absolutePoses[parentIndex].rot * - newRot * - glm::inverse(absolutePoses[pivotIndex].rot); - } - } - // store the rotation change in the accumulator - _accumulators[pivotIndex].add(newRot); - } - // this joint has been changed so we check to see if it has the lowest index - if (pivotIndex < lowestMovedIndex) { - lowestMovedIndex = pivotIndex; - } - - // keep track of tip's new position as we descend towards root - tip = jointPosition + deltaRotation * leverArm; - error = glm::length(targetPose.trans - tip); - } - } - pivotIndex = _skeleton->getParentIndex(pivotIndex); - } - if (largestError < error) { - largestError = error; - } - } - ++numLoops; - - // harvest accumulated rotations and apply the average - for (auto& accumulatorPair: _accumulators) { - RotationAccumulator& accumulator = accumulatorPair.second; - if (accumulator.size() > 0) { - _relativePoses[accumulatorPair.first].rot = accumulator.getAverage(); - accumulator.clear(); - } - } - - // only update the absolutePoses that need it: those between lowestMovedIndex and _maxTargetIndex - for (int i = lowestMovedIndex; i <= _maxTargetIndex; ++i) { - int parentIndex = _skeleton->getParentIndex(i); - if (parentIndex != -1) { - absolutePoses[i] = absolutePoses[parentIndex] * _relativePoses[i]; - } - } - } while (largestError > ACCEPTABLE_RELATIVE_ERROR && numLoops < MAX_IK_LOOPS && usecTimestampNow() < expiry); - - // finally set the relative rotation of each tip to agree with absolute target rotation + float largestError = 0.0f; + const float ACCEPTABLE_RELATIVE_ERROR = 1.0e-3f; + int numLoops = 0; + const int MAX_IK_LOOPS = 16; + const quint64 MAX_IK_TIME = 10 * USECS_PER_MSEC; + quint64 expiry = usecTimestampNow() + MAX_IK_TIME; + do { + largestError = 0.0f; + int lowestMovedIndex = _relativePoses.size(); for (auto& target: targets) { int tipIndex = target.index; - int parentIndex = _skeleton->getParentIndex(tipIndex); - if (parentIndex != -1) { - AnimPose targetPose = target.pose; - // compute tip's new parent-relative rotation - // Q = Qp * q --> q' = Qp^ * Q - glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot) * targetPose.rot; - RotationConstraint* constraint = getConstraint(tipIndex); - if (constraint) { - constraint->apply(newRelativeRotation); - // TODO: ATM the final rotation target just fails but we need to provide - // feedback to the IK system so that it can adjust the bones up the skeleton - // to help this rotation target get met. + AnimPose targetPose = target.pose; + + glm::vec3 tip = absolutePoses[tipIndex].trans; + float error = glm::length(targetPose.trans - tip); + + // descend toward root, pivoting each joint to get tip closer to target + int pivotIndex = _skeleton->getParentIndex(tipIndex); + while (pivotIndex != -1 && error > ACCEPTABLE_RELATIVE_ERROR) { + // compute the two lines that should be aligned + glm::vec3 jointPosition = absolutePoses[pivotIndex].trans; + glm::vec3 leverArm = tip - jointPosition; + glm::vec3 targetLine = targetPose.trans - jointPosition; + + // compute the axis of the rotation that would align them + glm::vec3 axis = glm::cross(leverArm, targetLine); + float axisLength = glm::length(axis); + if (axisLength > EPSILON) { + // compute deltaRotation for alignment (brings tip closer to target) + axis /= axisLength; + float angle = acosf(glm::dot(leverArm, targetLine) / (glm::length(leverArm) * glm::length(targetLine))); + + // NOTE: even when axisLength is not zero (e.g. lever-arm and pivot-arm are not quite aligned) it is + // still possible for the angle to be zero so we also check that to avoid unnecessary calculations. + if (angle > EPSILON) { + // reduce angle by half: slows convergence but adds stability to IK solution + angle = 0.5f * angle; + glm::quat deltaRotation = glm::angleAxis(angle, axis); + + int parentIndex = _skeleton->getParentIndex(pivotIndex); + if (parentIndex == -1) { + // TODO? apply constraints to root? + // TODO? harvest the root's transform as movement of entire skeleton? + } else { + // compute joint's new parent-relative rotation + // Q' = dQ * Q and Q = Qp * q --> q' = Qp^ * dQ * Q + glm::quat newRot = glm::normalize(glm::inverse( + absolutePoses[parentIndex].rot) * + deltaRotation * + absolutePoses[pivotIndex].rot); + RotationConstraint* constraint = getConstraint(pivotIndex); + if (constraint) { + bool constrained = constraint->apply(newRot); + if (constrained) { + // the constraint will modify the movement of the tip so we have to compute the modified + // model-frame deltaRotation + // Q' = Qp^ * dQ * Q --> dQ = Qp * Q' * Q^ + deltaRotation = absolutePoses[parentIndex].rot * + newRot * + glm::inverse(absolutePoses[pivotIndex].rot); + } + } + // store the rotation change in the accumulator + _accumulators[pivotIndex].add(newRot); + } + // this joint has been changed so we check to see if it has the lowest index + if (pivotIndex < lowestMovedIndex) { + lowestMovedIndex = pivotIndex; + } + + // keep track of tip's new position as we descend towards root + tip = jointPosition + deltaRotation * leverArm; + error = glm::length(targetPose.trans - tip); + } } - _relativePoses[tipIndex].rot = newRelativeRotation; - absolutePoses[tipIndex].rot = targetPose.rot; + pivotIndex = _skeleton->getParentIndex(pivotIndex); } + if (largestError < error) { + largestError = error; + } + } + ++numLoops; + + // harvest accumulated rotations and apply the average + for (auto& accumulatorPair: _accumulators) { + RotationAccumulator& accumulator = accumulatorPair.second; + if (accumulator.size() > 0) { + _relativePoses[accumulatorPair.first].rot = accumulator.getAverage(); + accumulator.clear(); + } + } + + // only update the absolutePoses that need it: those between lowestMovedIndex and _maxTargetIndex + for (int i = lowestMovedIndex; i <= _maxTargetIndex; ++i) { + int parentIndex = _skeleton->getParentIndex(i); + if (parentIndex != -1) { + absolutePoses[i] = absolutePoses[parentIndex] * _relativePoses[i]; + } + } + } while (largestError > ACCEPTABLE_RELATIVE_ERROR && numLoops < MAX_IK_LOOPS && usecTimestampNow() < expiry); + + // finally set the relative rotation of each tip to agree with absolute target rotation + for (auto& target: targets) { + int tipIndex = target.index; + int parentIndex = _skeleton->getParentIndex(tipIndex); + if (parentIndex != -1) { + AnimPose targetPose = target.pose; + // compute tip's new parent-relative rotation + // Q = Qp * q --> q' = Qp^ * Q + glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot) * targetPose.rot; + RotationConstraint* constraint = getConstraint(tipIndex); + if (constraint) { + constraint->apply(newRelativeRotation); + // TODO: ATM the final rotation target just fails but we need to provide + // feedback to the IK system so that it can adjust the bones up the skeleton + // to help this rotation target get met. + } + _relativePoses[tipIndex].rot = newRelativeRotation; + absolutePoses[tipIndex].rot = targetPose.rot; + } + } +} + +//virtual +const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVars, float dt, AnimNode::Triggers& triggersOut) { + if (!_relativePoses.empty()) { + // build a list of targets from _targetVarVec + std::vector targets; + computeTargets(animVars, targets); + + if (targets.empty()) { + // no IK targets but still need to enforce constraints + std::map::iterator constraintItr = _constraints.begin(); + while (constraintItr != _constraints.end()) { + int index = constraintItr->first; + glm::quat rotation = _relativePoses[index].rot; + constraintItr->second->apply(rotation); + _relativePoses[index].rot = rotation; + ++constraintItr; + } + } else { + solveWithCyclicCoordinateDescent(targets); } } return _relativePoses; diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index c4bda1be89..f2073c01b8 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -37,6 +37,14 @@ public: virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override; protected: + struct IKTarget { + AnimPose pose; + int index; + int rootIndex; + }; + + void computeTargets(const AnimVariantMap& animVars, std::vector& targets); + void solveWithCyclicCoordinateDescent(std::vector& targets); virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton); // for AnimDebugDraw rendering @@ -64,7 +72,7 @@ protected: }; std::map _constraints; - std::map _accumulators; + std::map _accumulators; // class-member to exploit temporal coherency std::vector _targetVarVec; AnimPoseVec _defaultRelativePoses; // poses of the relaxed state AnimPoseVec _relativePoses; // current relative poses diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index 9325ef3835..b6f9987f33 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -87,6 +87,23 @@ public: return evaluate(animVars, dt, triggersOut); } + const AnimPose getRootPose(int jointIndex) const { + AnimPose pose = AnimPose::identity; + if (_skeleton && jointIndex != -1) { + const AnimPoseVec& poses = getPosesInternal(); + int numJoints = (int)(poses.size()); + if (jointIndex < numJoints) { + int parentIndex = _skeleton->getParentIndex(jointIndex); + while (parentIndex != -1 && parentIndex < numJoints) { + jointIndex = parentIndex; + parentIndex = _skeleton->getParentIndex(jointIndex); + } + pose = poses[jointIndex]; + } + } + return pose; + } + protected: void setCurrentFrame(float frame) { diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index b0ffd081c2..29d0bc011b 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -986,7 +986,7 @@ void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, floa void Rig::updateNeckJoint(int index, const HeadParameters& params) { if (index >= 0 && _jointStates[index].getParentIndex() >= 0) { - if (_enableAnimGraph && _animSkeleton) { + if (_enableAnimGraph && _animSkeleton && _animNode) { // the params.localHeadOrientation is composed incorrectly, so re-compose it correctly from pitch, yaw and roll. glm::quat realLocalHeadOrientation = (glm::angleAxis(glm::radians(-params.localHeadRoll), Z_AXIS) * glm::angleAxis(glm::radians(params.localHeadYaw), Y_AXIS) * @@ -995,7 +995,9 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) { // There's a theory that when not in hmd, we should _animVars.unset("headPosition"). // However, until that works well, let's always request head be positioned where requested by hmd, camera, or default. - _animVars.set("headPosition", params.localHeadPosition); + int headIndex = _animSkeleton->nameToJointIndex("Head"); + AnimPose rootPose = _animNode->getRootPose(headIndex); + _animVars.set("headPosition", rootPose.trans + rootPose.rot * params.localHeadPosition); } else if (!_enableAnimGraph) { auto& state = _jointStates[index]; @@ -1044,20 +1046,22 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm void Rig::updateFromHandParameters(const HandParameters& params, float dt) { - if (_enableAnimGraph && _animSkeleton) { + if (_enableAnimGraph && _animSkeleton && _animNode) { // TODO: figure out how to obtain the yFlip from where it is actually stored glm::quat yFlipHACK = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); + int leftHandIndex = _animSkeleton->nameToJointIndex("LeftHand"); + AnimPose rootPose = _animNode->getRootPose(leftHandIndex); if (params.isLeftEnabled) { - _animVars.set("leftHandPosition", yFlipHACK * params.leftPosition); - _animVars.set("leftHandRotation", yFlipHACK * params.leftOrientation); + _animVars.set("leftHandPosition", rootPose.trans + rootPose.rot * yFlipHACK * params.leftPosition); + _animVars.set("leftHandRotation", rootPose.rot * yFlipHACK * params.leftOrientation); } else { _animVars.unset("leftHandPosition"); _animVars.unset("leftHandRotation"); } if (params.isRightEnabled) { - _animVars.set("rightHandPosition", yFlipHACK * params.rightPosition); - _animVars.set("rightHandRotation", yFlipHACK * params.rightOrientation); + _animVars.set("rightHandPosition", rootPose.trans + rootPose.rot * yFlipHACK * params.rightPosition); + _animVars.set("rightHandRotation", rootPose.rot * yFlipHACK * params.rightOrientation); } else { _animVars.unset("rightHandPosition"); _animVars.unset("rightHandRotation"); From f8d743aff0700f81d7f2ace92b8718e1e5e64978 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 21 Sep 2015 17:38:49 -0700 Subject: [PATCH 34/58] Update to use new grab methods, only specifically request properties that we are actually using --- examples/toys/bubblewand/createWand.js | 46 +++++------ examples/toys/bubblewand/wand.js | 104 ++++++------------------- 2 files changed, 47 insertions(+), 103 deletions(-) diff --git a/examples/toys/bubblewand/createWand.js b/examples/toys/bubblewand/createWand.js index 9938acb63f..632037ff7c 100644 --- a/examples/toys/bubblewand/createWand.js +++ b/examples/toys/bubblewand/createWand.js @@ -18,35 +18,35 @@ var WAND_SCRIPT_URL = Script.resolvePath("wand.js"); //create the wand in front of the avatar var center = Vec3.sum(Vec3.sum(MyAvatar.position, { - x: 0, - y: 0.5, - z: 0 + x: 0, + y: 0.5, + z: 0 }), Vec3.multiply(0.5, Quat.getFront(Camera.getOrientation()))); var wand = Entities.addEntity({ - name: 'Bubble Wand', - type: "Model", - modelURL: WAND_MODEL, - position: center, - gravity: { - x: 0, - y: 0, - z: 0, - }, - dimensions: { - x: 0.05, - y: 0.25, - z: 0.05 - }, - //must be enabled to be grabbable in the physics engine - collisionsWillMove: true, - compoundShapeURL: WAND_COLLISION_SHAPE, - script: WAND_SCRIPT_URL + name: 'Bubble Wand', + type: "Model", + modelURL: WAND_MODEL, + position: center, + gravity: { + x: 0, + y: 0, + z: 0, + }, + dimensions: { + x: 0.05, + y: 0.25, + z: 0.05 + }, + //must be enabled to be grabbable in the physics engine + collisionsWillMove: true, + compoundShapeURL: WAND_COLLISION_SHAPE, + script: WAND_SCRIPT_URL }); function cleanup() { -// the line below this is commented out to make the wand that you create persistent. - Entities.deleteEntity(wand); + // the line below this is commented out to make the wand that you create persistent. + // Entities.deleteEntity(wand); } diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index 1541985315..f8e484bbde 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -36,10 +36,6 @@ var WAND_TIP_OFFSET = 0.095; var VELOCITY_THRESHOLD = 0.5; - var GRAB_USER_DATA_KEY = "grabKey"; - - var _this; - function interval() { var lastTime = new Date().getTime() / 1000; @@ -53,6 +49,7 @@ var checkInterval = interval(); + var _this; var BubbleWand = function() { _this = this; @@ -63,73 +60,27 @@ currentBubble: null, preload: function(entityID) { this.entityID = entityID; - this.properties = Entities.getEntityProperties(this.entityID); Script.update.connect(this.update); }, - unload: function(entityID) { + unload: function() { Script.update.disconnect(this.update); - }, - update: function(deltaTime) { - this.timePassed = deltaTime; - var defaultGrabData = { - activated: false, - avatarId: null - }; - var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, _this.entityID, defaultGrabData); - - if (grabData.activated && grabData.avatarId === MyAvatar.sessionUUID) { - // remember we're being grabbed so we can detect being released - _this.beingGrabbed = true; - - //the first time we want to make a bubble - if (_this.currentBubble === null) { - _this.createBubbleAtTipOfWand(); - } - - var properties = Entities.getEntityProperties(_this.entityID); - var dt = deltaTime; - _this.growBubbleWithWandVelocity(properties, dt); - - var wandTipPosition = _this.getWandTipPosition(properties); - - //update the bubble to stay with the wand tip - Entities.editEntity(_this.currentBubble, { - position: wandTipPosition, - - }); - - } else if (_this.beingGrabbed) { - // if we are not being grabbed, and we previously were, then we were just released, remember that - _this.beingGrabbed = false; - - //remove the current bubble when the wand is released - Entities.deleteEntity(_this.currentBubble); - _this.currentBubble = null - return - } - - }, getWandTipPosition: function(properties) { - //the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position - var upVector = Quat.getUp(properties.rotation); var frontVector = Quat.getFront(properties.rotation); var upOffset = Vec3.multiply(upVector, WAND_TIP_OFFSET); var wandTipPosition = Vec3.sum(properties.position, upOffset); - this.wandTipPosition = wandTipPosition; return wandTipPosition }, addCollisionsToBubbleAfterCreation: function(bubble) { - + //if the bubble collide immediately, we get weird effects. so we add collisions after release Entities.editEntity(bubble, { collisionsWillMove: true }) - }, randomizeBubbleGravity: function() { - + //change up the gravity a little bit for variation in floating effects var randomNumber = randInt(0, 3); var gravity = { x: 0, @@ -139,9 +90,11 @@ return gravity }, growBubbleWithWandVelocity: function(properties, deltaTime) { + //get the wand and tip position for calculations var wandPosition = properties.position; var wandTipPosition = this.getWandTipPosition(properties) + // velocity = distance / time var distance = Vec3.subtract(wandPosition, this.lastPosition); var velocity = Vec3.multiply(distance, 1 / deltaTime); @@ -152,7 +105,7 @@ this.lastPosition = wandPosition; //actually grow the bubble - var dimensions = Entities.getEntityProperties(this.currentBubble).dimensions; + var dimensions = Entities.getEntityProperties(this.currentBubble, "dimensions").dimensions; if (velocityStrength > VELOCITY_THRESHOLD) { //add some variation in bubble sizes @@ -165,6 +118,7 @@ //bubbles pop after existing for a bit -- so set a random lifetime var lifetime = randInt(BUBBLE_LIFETIME_MIN, BUBBLE_LIFETIME_MAX); + //edit the bubble properties at release Entities.editEntity(this.currentBubble, { velocity: velocity, lifetime: lifetime, @@ -178,8 +132,7 @@ this.createBubbleAtTipOfWand(); return } else { - - // if the bubble is not yet full size, make the current bubble bigger + //grow small bubbles dimensions.x += GROWTH_FACTOR * velocityStrength; dimensions.y += GROWTH_FACTOR * velocityStrength; dimensions.z += GROWTH_FACTOR * velocityStrength; @@ -203,11 +156,10 @@ createBubbleAtTipOfWand: function() { //create a new bubble at the tip of the wand - var properties = Entities.getEntityProperties(this.entityID); + var properties = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); var wandPosition = properties.position; wandTipPosition = this.getWandTipPosition(properties); - this.wandTipPosition = wandTipPosition; //store the position of the tip for use in velocity calculations this.lastPosition = wandPosition; @@ -225,37 +177,29 @@ shapeType: "sphere" }); - }, startNearGrab: function() { - print('START NEAR GRAB') - if (_this.currentBubble === null) { - _this.createBubbleAtTipOfWand(); + if (this.currentBubble === null) { + this.createBubbleAtTipOfWand(); } }, continueNearGrab: function() { - print('time passed:::' + checkInterval()); - if (this.timePassed === null) { - this.timePassed = Date.now(); - } else { - var newTime = = Date.now() - this.timePassed; - // this.timePassed = newTime; - } - print('CONTINUE NEAR GRAB::' + this.timePassed); + var deltaTime = checkInterval() + var properties = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); + this.growBubbleWithWandVelocity(properties, deltaTime); + var wandTipPosition = this.getWandTipPosition(properties); + + //update the bubble to stay with the wand tip + Entities.editEntity(this.currentBubble, { + position: wandTipPosition, + }); }, releaseGrab: function() { - //delete the lights and reset state - if (this.hasSpotlight) { - Entities.deleteEntity(this.spotlight); - Entities.deleteEntity(this.glowLight); - this.hasSpotlight = false; - this.glowLight = null; - this.spotlight = null; - this.whichHand = null; - - } + //delete the current buble and reset state when the wand is released + Entities.deleteEntity(this.currentBubble); + this.currentBubble = null }, } From 3869887610e10e69ecfb7d2368448905f9b4776b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 21 Sep 2015 17:53:59 -0700 Subject: [PATCH 35/58] splitting AnimNode implementation into two files --- libraries/animation/src/AnimNode.cpp | 54 ++++++++++++++++++++++++++++ libraries/animation/src/AnimNode.h | 48 ++++--------------------- 2 files changed, 61 insertions(+), 41 deletions(-) create mode 100644 libraries/animation/src/AnimNode.cpp diff --git a/libraries/animation/src/AnimNode.cpp b/libraries/animation/src/AnimNode.cpp new file mode 100644 index 0000000000..02d0e1b283 --- /dev/null +++ b/libraries/animation/src/AnimNode.cpp @@ -0,0 +1,54 @@ +// +// AnimNode.cpp +// +// Created by Anthony J. Thibault on 9/2/15. +// Copyright (c) 2015 High Fidelity, Inc. All rights reserved. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AnimNode.h" + +void AnimNode::removeChild(AnimNode::Pointer child) { + auto iter = std::find(_children.begin(), _children.end(), child); + if (iter != _children.end()) { + _children.erase(iter); + } +} + +AnimNode::Pointer AnimNode::getChild(int i) const { + assert(i >= 0 && i < (int)_children.size()); + return _children[i]; +} + +void AnimNode::setSkeleton(const AnimSkeleton::Pointer skeleton) { + setSkeletonInternal(skeleton); + for (auto&& child : _children) { + child->setSkeleton(skeleton); + } +} + +const AnimPose AnimNode::getRootPose(int jointIndex) const { + AnimPose pose = AnimPose::identity; + if (_skeleton && jointIndex != -1) { + const AnimPoseVec& poses = getPosesInternal(); + int numJoints = (int)(poses.size()); + if (jointIndex < numJoints) { + int parentIndex = _skeleton->getParentIndex(jointIndex); + while (parentIndex != -1 && parentIndex < numJoints) { + jointIndex = parentIndex; + parentIndex = _skeleton->getParentIndex(jointIndex); + } + pose = poses[jointIndex]; + } + } + return pose; +} + +void AnimNode::setCurrentFrame(float frame) { + setCurrentFrameInternal(frame); + for (auto&& child : _children) { + child->setCurrentFrameInternal(frame); + } +} diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index b6f9987f33..d5da552a0f 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -60,25 +60,13 @@ public: // hierarchy accessors void addChild(Pointer child) { _children.push_back(child); } - void removeChild(Pointer child) { - auto iter = std::find(_children.begin(), _children.end(), child); - if (iter != _children.end()) { - _children.erase(iter); - } - } - Pointer getChild(int i) const { - assert(i >= 0 && i < (int)_children.size()); - return _children[i]; - } + void removeChild(Pointer child); + + Pointer getChild(int i) const; int getChildCount() const { return (int)_children.size(); } // pair this AnimNode graph with a skeleton. - void setSkeleton(const AnimSkeleton::Pointer skeleton) { - setSkeletonInternal(skeleton); - for (auto&& child : _children) { - child->setSkeleton(skeleton); - } - } + void setSkeleton(const AnimSkeleton::Pointer skeleton); AnimSkeleton::ConstPointer getSkeleton() const { return _skeleton; } @@ -87,36 +75,14 @@ public: return evaluate(animVars, dt, triggersOut); } - const AnimPose getRootPose(int jointIndex) const { - AnimPose pose = AnimPose::identity; - if (_skeleton && jointIndex != -1) { - const AnimPoseVec& poses = getPosesInternal(); - int numJoints = (int)(poses.size()); - if (jointIndex < numJoints) { - int parentIndex = _skeleton->getParentIndex(jointIndex); - while (parentIndex != -1 && parentIndex < numJoints) { - jointIndex = parentIndex; - parentIndex = _skeleton->getParentIndex(jointIndex); - } - pose = poses[jointIndex]; - } - } - return pose; - } + const AnimPose getRootPose(int jointIndex) const; protected: - void setCurrentFrame(float frame) { - setCurrentFrameInternal(frame); - for (auto&& child : _children) { - child->setCurrentFrameInternal(frame); - } - } + void setCurrentFrame(float frame); virtual void setCurrentFrameInternal(float frame) {} - virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) { - _skeleton = skeleton; - } + virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) { _skeleton = skeleton; } // for AnimDebugDraw rendering virtual const AnimPoseVec& getPosesInternal() const = 0; From a23a90bf5f99dbf4b1d7c2e4ed108b97b667e4a8 Mon Sep 17 00:00:00 2001 From: BOB LONG Date: Mon, 21 Sep 2015 19:11:13 -0700 Subject: [PATCH 36/58] Code simplification Simplify the code a bit as suggested: 1) Use unsigned int instead of signed int, so we can avoid checking the negative case 2) Merge two lines into a single line so we can inline the implementation Correct the js sample file header. testing done: - Build locally - Pass -1 as index from js and the code still can correctly handle the input. --- examples/faceBlendCoefficients.js | 4 ++-- libraries/render-utils/src/Model.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/faceBlendCoefficients.js b/examples/faceBlendCoefficients.js index 56fcadca9d..6756be548f 100644 --- a/examples/faceBlendCoefficients.js +++ b/examples/faceBlendCoefficients.js @@ -1,10 +1,10 @@ // -// coefficients.js +// faceBlendCoefficients.js // // version 2.0 // // Created by Bob Long, 9/14/2015 -// A simple panel that can display the blending coefficients of Avatar's face model. +// A simple panel that can select and display the blending coefficient of the Avatar's face model. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index d1aa2901c8..e8f158be08 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -192,9 +192,9 @@ public: void setCauterizeBoneSet(const std::unordered_set& boneSet) { _cauterizeBoneSet = boneSet; } int getBlendshapeCoefficientsNum() const { return _blendshapeCoefficients.size(); } - float getBlendshapeCoefficient(int index) const { - return index >= _blendshapeCoefficients.size() || index < 0 ? - 0.0f : _blendshapeCoefficients.at(index); } + float getBlendshapeCoefficient(unsigned int index) const { + return index >= _blendshapeCoefficients.size() ? 0.0f : _blendshapeCoefficients.at(index); + } protected: From f38bb77d0a9fc2bb46d717e0e86f7cf8e069c86b Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 22 Sep 2015 18:48:46 +0200 Subject: [PATCH 37/58] less calls to QHash --- interface/src/Application.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index 30f89d8421..2a5138638e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -292,7 +292,7 @@ public: NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } QStringList getRunningScripts() { return _scriptEnginesHash.keys(); } - ScriptEngine* getScriptEngine(const QString& scriptHash) { return _scriptEnginesHash.contains(scriptHash) ? _scriptEnginesHash[scriptHash] : NULL; } + ScriptEngine* getScriptEngine(const QString& scriptHash) { return _scriptEnginesHash.value(scriptHash, NULL); } bool isLookingAtMyAvatar(AvatarSharedPointer avatar); From 8f1dde69cc1e98d98fc6ef237a09268f8e4cea5f Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 22 Sep 2015 10:10:29 -0700 Subject: [PATCH 38/58] Always keep targets, even when both position and rotation are unset. (Get from underpose.) Filtering these was necessary before when the underpose coordinate was wrong, but now that we have that working, there shouldn't be any need to filter. --- .../animation/src/AnimInverseKinematics.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 1ccf984815..57459abacb 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -99,15 +99,13 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std:: } } else { // TODO: get this done without a double-lookup of each var in animVars - if (animVars.hasKey(targetVar.positionVar) || animVars.hasKey(targetVar.rotationVar)) { - IKTarget target; - AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, _relativePoses); - target.pose.trans = animVars.lookup(targetVar.positionVar, defaultPose.trans); - target.pose.rot = animVars.lookup(targetVar.rotationVar, defaultPose.rot); - target.rootIndex = targetVar.rootIndex; - target.index = targetVar.jointIndex; - targets.push_back(target); - } + IKTarget target; + AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, _relativePoses); + target.pose.trans = animVars.lookup(targetVar.positionVar, defaultPose.trans); + target.pose.rot = animVars.lookup(targetVar.rotationVar, defaultPose.rot); + target.rootIndex = targetVar.rootIndex; + target.index = targetVar.jointIndex; + targets.push_back(target); } } From 7e52d38870d296ead5bf9b3053cfbcaf6686c0fa Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 22 Sep 2015 10:12:59 -0700 Subject: [PATCH 39/58] Don't include the root rot, because it seems that this is already accounted for in the head params. Restore the hmd conditional on setting head position. This had been removed when failing to pin it cause lean. I believe that lean was being caused by coordinate system issues that are now addressed by the above and Andrew's big cleanup. --- libraries/animation/src/Rig.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 29d0bc011b..a74560114a 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -993,11 +993,13 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) { glm::angleAxis(glm::radians(-params.localHeadPitch), X_AXIS)); _animVars.set("headRotation", realLocalHeadOrientation); - // There's a theory that when not in hmd, we should _animVars.unset("headPosition"). - // However, until that works well, let's always request head be positioned where requested by hmd, camera, or default. - int headIndex = _animSkeleton->nameToJointIndex("Head"); - AnimPose rootPose = _animNode->getRootPose(headIndex); - _animVars.set("headPosition", rootPose.trans + rootPose.rot * params.localHeadPosition); + if (params.isInHMD) { + int headIndex = _animSkeleton->nameToJointIndex("Head"); + AnimPose rootPose = _animNode->getRootPose(headIndex); + _animVars.set("headPosition", rootPose.trans + params.localHeadPosition); // rootPose.rot is handled in params?d + } else { + _animVars.unset("headPosition"); + } } else if (!_enableAnimGraph) { auto& state = _jointStates[index]; From fed5e8e573320ce27dee28c96dd7e5d4f06dbd4e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 22 Sep 2015 11:35:34 -0700 Subject: [PATCH 40/58] Don't run Script Editor scripts from the cache --- interface/src/ui/ScriptEditorWidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ScriptEditorWidget.cpp b/interface/src/ui/ScriptEditorWidget.cpp index 6d66e04bc6..fa829d4ace 100644 --- a/interface/src/ui/ScriptEditorWidget.cpp +++ b/interface/src/ui/ScriptEditorWidget.cpp @@ -97,7 +97,8 @@ bool ScriptEditorWidget::setRunning(bool run) { if (run) { const QString& scriptURLString = QUrl(_currentScript).toString(); - _scriptEngine = Application::getInstance()->loadScript(scriptURLString, true, true); + // Reload script so that an out of date copy is not retrieved from the cache + _scriptEngine = Application::getInstance()->loadScript(scriptURLString, true, true, false, true); connect(_scriptEngine, &ScriptEngine::runningStateChanged, this, &ScriptEditorWidget::runningStateChanged); connect(_scriptEngine, &ScriptEngine::errorMessage, this, &ScriptEditorWidget::onScriptError); connect(_scriptEngine, &ScriptEngine::printedMessage, this, &ScriptEditorWidget::onScriptPrint); From 5bb908f081f9f41a01160205cfd8458eaacfc908 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 22 Sep 2015 12:34:47 -0700 Subject: [PATCH 41/58] remove dead code and fix warning --- libraries/model/src/model/Material.cpp | 12 ------------ libraries/model/src/model/Material.h | 2 -- 2 files changed, 14 deletions(-) diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index cf91836254..c2ff828af3 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -15,18 +15,6 @@ using namespace model; using namespace gpu; -float componentSRGBToLinear(float cs) { - if (cs > 0.04045) { - return pow(((cs + 0.055)/1.055), 2.4); - } else { - return cs / 12.92; - } -} - -glm::vec3 convertSRGBToLinear(const glm::vec3& srgb) { - return glm::vec3(componentSRGBToLinear(srgb.x), componentSRGBToLinear(srgb.y), componentSRGBToLinear(srgb.z)); -} - Material::Material() : _key(0), _schemaBuffer(), diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index 0e7388f722..b0725d9908 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -20,8 +20,6 @@ namespace model { -static glm::vec3 convertSRGBToLinear(const glm::vec3& srgb); - class TextureMap; typedef std::shared_ptr< TextureMap > TextureMapPointer; From 561b4ca8e121cd8f09130944555248595031baa7 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Tue, 22 Sep 2015 12:52:24 -0700 Subject: [PATCH 42/58] Remove update loop refs, remove unload method --- examples/toys/bubblewand/wand.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/toys/bubblewand/wand.js b/examples/toys/bubblewand/wand.js index f8e484bbde..b71932b500 100644 --- a/examples/toys/bubblewand/wand.js +++ b/examples/toys/bubblewand/wand.js @@ -60,10 +60,6 @@ currentBubble: null, preload: function(entityID) { this.entityID = entityID; - Script.update.connect(this.update); - }, - unload: function() { - Script.update.disconnect(this.update); }, getWandTipPosition: function(properties) { //the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position @@ -179,12 +175,14 @@ }, startNearGrab: function() { + //create a bubble to grow at the start of the grab if (this.currentBubble === null) { this.createBubbleAtTipOfWand(); } }, continueNearGrab: function() { var deltaTime = checkInterval() + //only get the properties that we need var properties = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); this.growBubbleWithWandVelocity(properties, deltaTime); From eda12fd3af56cd91632904b71aae509a1bd6092a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 22 Sep 2015 16:15:54 -0700 Subject: [PATCH 43/58] Don't look straight ahead in fullscreen mirror --- interface/src/Application.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1deb45cf90..c359275d8a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2614,20 +2614,19 @@ void Application::updateMyAvatarLookAtPosition() { bool isLookingAtSomeone = false; bool isHMD = _avatarUpdate->isHMDMode(); glm::vec3 lookAtSpot; - if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - // When I am in mirror mode, just look right at the camera (myself); don't switch gaze points because when physically - // looking in a mirror one's eyes appear steady. - lookAtSpot = _myCamera.getPosition(); - } else if (eyeTracker->isTracking() && (isHMD || eyeTracker->isSimulating())) { + if (eyeTracker->isTracking() && (isHMD || eyeTracker->isSimulating())) { // Look at the point that the user is looking at. + glm::vec3 lookAtPosition = eyeTracker->getLookAtPosition(); + if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + lookAtPosition.x = -lookAtPosition.x; + } if (isHMD) { glm::mat4 headPose = getActiveDisplayPlugin()->getHeadPose(); glm::quat hmdRotation = glm::quat_cast(headPose); - lookAtSpot = _myCamera.getPosition() + - _myAvatar->getOrientation() * (hmdRotation * eyeTracker->getLookAtPosition()); + lookAtSpot = _myCamera.getPosition() + _myAvatar->getOrientation() * (hmdRotation * lookAtPosition); } else { - lookAtSpot = _myAvatar->getHead()->getEyePosition() + - (_myAvatar->getHead()->getFinalOrientationInWorldFrame() * eyeTracker->getLookAtPosition()); + lookAtSpot = _myAvatar->getHead()->getEyePosition() + + (_myAvatar->getHead()->getFinalOrientationInWorldFrame() * lookAtPosition); } } else { AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().lock(); From efda1216195a41c4596126fe011ee7f44c60e0d3 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 22 Sep 2015 16:37:54 -0700 Subject: [PATCH 44/58] fix a bunch of warnings on windows --- examples/edit.js | 2 +- examples/html/entityProperties.html | 219 +++++++++--------- .../src/model-networking/ModelCache.cpp | 4 +- .../src/model-networking/ModelCache.h | 2 +- .../networking/src/udt/ConnectionStats.cpp | 12 +- libraries/render-utils/src/GeometryCache.cpp | 2 +- libraries/render-utils/src/Model.h | 4 +- 7 files changed, 123 insertions(+), 122 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index d28d51df9d..0d1164685a 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -1320,7 +1320,7 @@ PropertiesTool = function(opts) { if (data.action == "moveSelectionToGrid") { if (selectionManager.hasSelection()) { selectionManager.saveProperties(); - var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2), + var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2); var diff = { x: 0, y: dY, z: 0 }; for (var i = 0; i < selectionManager.selections.length; i++) { var properties = selectionManager.savedProperties[selectionManager.selections[i]]; diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index ad489afddf..268a2fb7f2 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -1,5 +1,6 @@ + Properties @@ -961,7 +962,7 @@
-
@@ -970,7 +971,7 @@
Name
- +
@@ -1003,13 +1004,13 @@
Href
- +
Description
- +
@@ -1021,9 +1022,9 @@
Position
-
X
-
Y
-
Z
+
X
+
Y
+
Z
@@ -1034,26 +1035,26 @@
Registration
-
X
-
Y
-
Z
+
X
+
Y
+
Z
Dimensions
-
X
-
Y
-
Z
+
X
+
Y
+
Z
- % + %
- +
@@ -1061,9 +1062,9 @@
Voxel Volume Size
-
X
-
Y
-
Z
+
X
+
Y
+
Z
Surface Extractor
@@ -1078,26 +1079,26 @@
X-axis Texture URL
- +
Y-axis Texture URL
- +
Z-axis Texture URL
- +
Rotation
-
Pitch
-
Yaw
-
Roll
+
Pitch
+
Yaw
+
Roll
@@ -1109,66 +1110,66 @@
Linear Velocity
-
X
-
Y
-
Z
+
X
+
Y
+
Z
Linear Damping
- +
Angular Velocity
-
Pitch
-
Yaw
-
Roll
+
Pitch
+
Yaw
+
Roll
Angular Damping
- +
Restitution
- +
Friction
- +
Gravity
-
X
-
Y
-
Z
+
X
+
Y
+
Z
Acceleration
-
X
-
Y
-
Z
+
X
+
Y
+
Z
Density
- +
@@ -1176,9 +1177,9 @@
Color
-
R
-
G
-
B
+
R
+
G
+
B
@@ -1190,38 +1191,38 @@
Ignore For Collisions - +
Collisions Will Move - +
Collision Sound URL
- +
Lifetime
- +
Script URL - - + +
- +
@@ -1233,14 +1234,14 @@
Model URL
- +
Shape Type
- @@ -1251,13 +1252,13 @@
Compound Shape URL
- +
Animation URL
- +
@@ -1269,13 +1270,13 @@
Animation FPS
- +
Animation Frame
- +
@@ -1305,7 +1306,7 @@
Source URL
- +
@@ -1317,45 +1318,45 @@
Max Particles
- +
Particle Life Span
- +
Particle Emission Rate
- +
Particle Emission Direction
-
X
-
Y
-
Z
+
X
+
Y
+
Z
Particle Emission Strength
- +
Particle Local Gravity
- +
Particle Radius
- +
@@ -1367,31 +1368,31 @@
Text Content
- +
Line Height
- +
Text Color
-
R
-
G
-
B
+
R
+
G
+
B
Background Color
-
R
-
G
-
B
+
R
+
G
+
B
@@ -1410,27 +1411,27 @@
Color
-
R
-
G
-
B
+
R
+
G
+
B
Intensity
- +
Spot Light Exponent
- +
Spot Light Cutoff (degrees)
- +
@@ -1450,48 +1451,48 @@
Key Light Color
-
R
-
G
-
B
+
R
+
G
+
B
Key Light Intensity
- +
Key Light Ambient Intensity
- +
Key Light Direction
-
Pitch
-
Yaw
-
Roll
+
Pitch
+
Yaw
+
Roll
Stage Latitude
- +
Stage Longitude
- +
Stage Altitude
- +
@@ -1505,20 +1506,20 @@
Stage Day
- +
Stage Hour
- +
Background Mode
- @@ -1535,15 +1536,15 @@
Skybox Color
-
R
-
G
-
B
+
R
+
G
+
B
Skybox URL
- +
@@ -1555,9 +1556,9 @@
Atmosphere Center
-
X
-
Y
-
Z
+
X
+
Y
+
Z
@@ -1566,33 +1567,33 @@
Atmosphere Inner Radius
- +
Atmosphere Outer Radius
- +
Atmosphere Mie Scattering
- +
Atmosphere Rayleigh Scattering
- +
Atmosphere Scattering Wavelenghts
-
X
-
Y
-
Z
+
X
+
Y
+
Z