From eb4dee0495d292eb97e4193c592c2cf044e21e3f Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Fri, 10 Mar 2017 23:37:29 +0000 Subject: [PATCH 01/22] create audioMuteOverlay.js client scipt that creates an overlay to provide mute feedback --- scripts/system/audioMuteOverlay.js | 122 +++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 scripts/system/audioMuteOverlay.js diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js new file mode 100644 index 0000000000..bb1eb70aa9 --- /dev/null +++ b/scripts/system/audioMuteOverlay.js @@ -0,0 +1,122 @@ +"use strict"; +/* jslint vars: true, plusplus: true, forin: true*/ +/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */ +/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ +// +// audioMuteOverlay.js +// +// client scipt that creates an overlay to provide mute feedback +// +// Created by Triplelexx on 17/03/09 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { // BEGIN LOCAL_SCOPE + var TWEEN_SPEED = 0.025; + var LERP_AMOUNT = 0.25; + + var overlayPosition = Vec3.ZERO; + var tweenPosition = 0; + var startColor = { + red: 150, + green: 150, + blue: 150 + }; + var endColor = { + red: 255, + green: 0, + blue: 0 + }; + var overlayID; + + AudioDevice.muteToggled.connect(onMuteToggled); + Script.update.connect(update); + Script.scriptEnding.connect(cleanup); + + function update(dt) { + if (!AudioDevice.getMuted()) { + return; + } + updateTween(); + } + + function lerp(a, b, val) { + return (1 - val) * a + val * b; + } + + function getOffsetPosition() { + return Vec3.sum(MyAvatar.getHeadPosition(), Quat.getFront(MyAvatar.headOrientation)); + } + + function updateTween() { + // increase the tween value based on speed till it's complete + if (tweenPosition < 1) { + tweenPosition += TWEEN_SPEED; + } else { + // after tween completion reset to zero and flip values to ping pong + tweenPosition = 0; + var buf = startColor.red; + startColor.red = endColor.red; + endColor.red = buf; + buf = startColor.green; + startColor.green = endColor.green; + endColor.green = buf; + buf = startColor.blue; + startColor.blue = endColor.blue; + endColor.blue = buf; + } + + // update position based on LERP_AMOUNT + var offsetPosition = getOffsetPosition(); + overlayPosition.x = lerp(overlayPosition.x, offsetPosition.x, LERP_AMOUNT); + overlayPosition.y = lerp(overlayPosition.y, offsetPosition.y, LERP_AMOUNT); + overlayPosition.z = lerp(overlayPosition.z, offsetPosition.z, LERP_AMOUNT); + + Overlays.editOverlay(overlayID, { + color: { + red: lerp(startColor.red, endColor.red, tweenPosition), + green: lerp(startColor.green, endColor.green, tweenPosition), + blue: lerp(startColor.blue, endColor.blue, tweenPosition) + }, + position: overlayPosition, + rotation: MyAvatar.orientation, + }); + } + + function onMuteToggled() { + if (AudioDevice.getMuted()) { + createOverlay(); + } else { + deleteOverlay(); + } + } + + function createOverlay() { + overlayPosition = getOffsetPosition(); + overlayID = Overlays.addOverlay("sphere", { + name: "muteSphere", + position: overlayPosition, + rotation: MyAvatar.orientation, + alpha: 0.9, + dimensions: 0.1, + solid: true, + ignoreRayIntersection: true, + visible: true + }); + } + + function deleteOverlay() { + Overlays.deleteOverlay(overlayID); + } + + function cleanup() { + if (overlayID) { + deleteOverlay(); + } + AudioDevice.muteToggled.disconnect(onMuteToggled); + Script.update.disconnect(update); + } +}()); // END LOCAL_SCOPE From 8a0dd55275879480db31736b33b7efd1f5dd727f Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sat, 11 Mar 2017 00:19:02 +0000 Subject: [PATCH 02/22] change naming and comment --- scripts/system/audioMuteOverlay.js | 53 +++++++++++++++--------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index bb1eb70aa9..8ffa1655b7 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -40,7 +40,7 @@ if (!AudioDevice.getMuted()) { return; } - updateTween(); + updateOverlay(); } function lerp(a, b, val) { @@ -49,10 +49,31 @@ function getOffsetPosition() { return Vec3.sum(MyAvatar.getHeadPosition(), Quat.getFront(MyAvatar.headOrientation)); - } - - function updateTween() { - // increase the tween value based on speed till it's complete + } + + function onMuteToggled() { + if (AudioDevice.getMuted()) { + createOverlay(); + } else { + deleteOverlay(); + } + } + + function createOverlay() { + overlayPosition = getOffsetPosition(); + overlayID = Overlays.addOverlay("sphere", { + position: overlayPosition, + rotation: MyAvatar.orientation, + alpha: 0.9, + dimensions: 0.1, + solid: true, + ignoreRayIntersection: true, + visible: true + }); + } + + function updateOverlay() { + // increase by TWEEN_SPEED until completion if (tweenPosition < 1) { tweenPosition += TWEEN_SPEED; } else { @@ -86,28 +107,6 @@ }); } - function onMuteToggled() { - if (AudioDevice.getMuted()) { - createOverlay(); - } else { - deleteOverlay(); - } - } - - function createOverlay() { - overlayPosition = getOffsetPosition(); - overlayID = Overlays.addOverlay("sphere", { - name: "muteSphere", - position: overlayPosition, - rotation: MyAvatar.orientation, - alpha: 0.9, - dimensions: 0.1, - solid: true, - ignoreRayIntersection: true, - visible: true - }); - } - function deleteOverlay() { Overlays.deleteOverlay(overlayID); } From 873a9aa39ec0f5b8ceb85a3641b84adc2acfa9de Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sat, 11 Mar 2017 07:40:32 +0000 Subject: [PATCH 03/22] change color swapping to be more concise --- scripts/system/audioMuteOverlay.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index 8ffa1655b7..973faa57a8 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -79,15 +79,11 @@ } else { // after tween completion reset to zero and flip values to ping pong tweenPosition = 0; - var buf = startColor.red; - startColor.red = endColor.red; - endColor.red = buf; - buf = startColor.green; - startColor.green = endColor.green; - endColor.green = buf; - buf = startColor.blue; - startColor.blue = endColor.blue; - endColor.blue = buf; + for (var color in startColor) { + var storedColor = startColor[color]; + startColor[color] = endColor[color]; + endColor[color] = storedColor; + } } // update position based on LERP_AMOUNT From 95fcb1df7a57b3350520eb08b5ca9513bf2692cd Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Mon, 13 Mar 2017 18:32:53 +0000 Subject: [PATCH 04/22] fix spelling mistake --- scripts/system/audioMuteOverlay.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index 973faa57a8..f112381040 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -5,7 +5,7 @@ // // audioMuteOverlay.js // -// client scipt that creates an overlay to provide mute feedback +// client script that creates an overlay to provide mute feedback // // Created by Triplelexx on 17/03/09 // Copyright 2017 High Fidelity, Inc. From 8bd155cb86191a7c48b0adee4fec4625c79cfa3b Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 14 Mar 2017 01:23:04 +0000 Subject: [PATCH 05/22] change offsetPosition to use Camera.orientation --- scripts/system/audioMuteOverlay.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index f112381040..db2b706b32 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -48,7 +48,7 @@ } function getOffsetPosition() { - return Vec3.sum(MyAvatar.getHeadPosition(), Quat.getFront(MyAvatar.headOrientation)); + return Vec3.sum(MyAvatar.getHeadPosition(), Quat.getFront(Camera.orientation)); } function onMuteToggled() { @@ -63,12 +63,11 @@ overlayPosition = getOffsetPosition(); overlayID = Overlays.addOverlay("sphere", { position: overlayPosition, - rotation: MyAvatar.orientation, + rotation: Camera.orientation, alpha: 0.9, dimensions: 0.1, solid: true, - ignoreRayIntersection: true, - visible: true + ignoreRayIntersection: true }); } @@ -99,7 +98,7 @@ blue: lerp(startColor.blue, endColor.blue, tweenPosition) }, position: overlayPosition, - rotation: MyAvatar.orientation, + rotation: Camera.orientation }); } From 2e0cac4676f902db8732481db90ee8e01d0d84e6 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 14 Mar 2017 01:25:39 +0000 Subject: [PATCH 06/22] add extra safeguards --- scripts/system/audioMuteOverlay.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index db2b706b32..a037e9ac72 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -38,9 +38,16 @@ function update(dt) { if (!AudioDevice.getMuted()) { + if (overlayID) { + deleteOverlay(); + } return; } - updateOverlay(); + if (!overlayID) { + createOverlay(); + } else { + updateOverlay(); + } } function lerp(a, b, val) { From c729ceccb5a4491bda3d0caa63a2a038bd651e7e Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 14 Mar 2017 03:59:24 +0000 Subject: [PATCH 07/22] change color lerp to use HSV color --- scripts/system/audioMuteOverlay.js | 61 +++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index a037e9ac72..f83a3871ff 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -20,15 +20,16 @@ var overlayPosition = Vec3.ZERO; var tweenPosition = 0; + // colors are in HSV, h needs to be a value from 0-1 var startColor = { - red: 150, - green: 150, - blue: 150 + h: 0, + s: 0, + v: 0.67 }; var endColor = { - red: 255, - green: 0, - blue: 0 + h: 0, + s: 1, + v: 1 }; var overlayID; @@ -43,17 +44,39 @@ } return; } - if (!overlayID) { - createOverlay(); - } else { - updateOverlay(); - } + updateOverlay(); } function lerp(a, b, val) { return (1 - val) * a + val * b; } + // hsv conversion expects 0-1 values + function hsvToRgb(h, s, v) { + var r, g, b; + + var i = Math.floor(h * 6); + var f = h * 6 - i; + var p = v * (1 - s); + var q = v * (1 - f * s); + var t = v * (1 - (1 - f) * s); + + switch (i % 6) { + case 0: r = v, g = t, b = p; break; + case 1: r = q, g = v, b = p; break; + case 2: r = p, g = v, b = t; break; + case 3: r = p, g = q, b = v; break; + case 4: r = t, g = p, b = v; break; + case 5: r = v, g = p, b = q; break; + } + + return { + red: r * 255, + green: g * 255, + blue: b * 255 + } + } + function getOffsetPosition() { return Vec3.sum(MyAvatar.getHeadPosition(), Quat.getFront(Camera.orientation)); } @@ -98,11 +121,17 @@ overlayPosition.y = lerp(overlayPosition.y, offsetPosition.y, LERP_AMOUNT); overlayPosition.z = lerp(overlayPosition.z, offsetPosition.z, LERP_AMOUNT); + var rgbColor = hsvToRgb( + lerp(startColor.h, endColor.h, tweenPosition), + lerp(startColor.s, endColor.s, tweenPosition), + lerp(startColor.v, endColor.v, tweenPosition) + ); + Overlays.editOverlay(overlayID, { color: { - red: lerp(startColor.red, endColor.red, tweenPosition), - green: lerp(startColor.green, endColor.green, tweenPosition), - blue: lerp(startColor.blue, endColor.blue, tweenPosition) + red: rgbColor.red, + green: rgbColor.green, + blue: rgbColor.blue }, position: overlayPosition, rotation: Camera.orientation @@ -114,9 +143,7 @@ } function cleanup() { - if (overlayID) { - deleteOverlay(); - } + deleteOverlay(); AudioDevice.muteToggled.disconnect(onMuteToggled); Script.update.disconnect(update); } From 30c16984c06c5c16dae7e646560bfcad42ea4c47 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 14 Mar 2017 06:07:22 +0000 Subject: [PATCH 08/22] change offsetPosition to use Camera.position --- scripts/system/audioMuteOverlay.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index f83a3871ff..49f2b5c618 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -78,7 +78,7 @@ } function getOffsetPosition() { - return Vec3.sum(MyAvatar.getHeadPosition(), Quat.getFront(Camera.orientation)); + return Vec3.sum(Camera.position, Quat.getFront(Camera.orientation)); } function onMuteToggled() { From 4dd9a7c37fdd93c4b97f9f27c547fa8c87999faa Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 14 Mar 2017 16:51:43 +0000 Subject: [PATCH 09/22] add simple easing function --- scripts/system/audioMuteOverlay.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index 49f2b5c618..8cf86c4395 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -122,9 +122,6 @@ overlayPosition.z = lerp(overlayPosition.z, offsetPosition.z, LERP_AMOUNT); var rgbColor = hsvToRgb( - lerp(startColor.h, endColor.h, tweenPosition), - lerp(startColor.s, endColor.s, tweenPosition), - lerp(startColor.v, endColor.v, tweenPosition) ); Overlays.editOverlay(overlayID, { From 8a39ce16bdc7a0d296f8c89f0fa2bbee5c2949d2 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 14 Mar 2017 16:57:45 +0000 Subject: [PATCH 10/22] add simple easing function dodgy add push --- scripts/system/audioMuteOverlay.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index 8cf86c4395..826498d909 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -51,6 +51,10 @@ return (1 - val) * a + val * b; } + function easeIn(t) { + return Math.pow(t / 1, 5); + } + // hsv conversion expects 0-1 values function hsvToRgb(h, s, v) { var r, g, b; @@ -122,6 +126,9 @@ overlayPosition.z = lerp(overlayPosition.z, offsetPosition.z, LERP_AMOUNT); var rgbColor = hsvToRgb( + lerp(startColor.h, endColor.h, easeIn(tweenPosition)), + lerp(startColor.s, endColor.s, easeIn(tweenPosition)), + lerp(startColor.v, endColor.v, easeIn(tweenPosition)) ); Overlays.editOverlay(overlayID, { From 6971aeb081f8d81869959dfb797a461f16001245 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 14 Mar 2017 17:18:11 +0000 Subject: [PATCH 11/22] additional reference information --- scripts/system/audioMuteOverlay.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index 826498d909..c72b62f1f7 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -55,7 +55,10 @@ return Math.pow(t / 1, 5); } - // hsv conversion expects 0-1 values + // Adapted from a blog post on http://mjijackson.com + // Michael J. I. Jackson + // Converts an HSV color value to RGB. Conversion formula adapted from http: //en.wikipedia.org/wiki/HSV_color_space. + // Assumes h, s, and v are contained in the set[0, 1] function hsvToRgb(h, s, v) { var r, g, b; From 84d157ab18503c188457d3febdab35e7058c2b18 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Wed, 15 Mar 2017 10:31:09 +0000 Subject: [PATCH 12/22] handle overlay lifetime during update, remove color conv --- scripts/system/audioMuteOverlay.js | 77 ++++++++---------------------- 1 file changed, 19 insertions(+), 58 deletions(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index c72b62f1f7..458efad6d0 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -20,31 +20,31 @@ var overlayPosition = Vec3.ZERO; var tweenPosition = 0; - // colors are in HSV, h needs to be a value from 0-1 var startColor = { - h: 0, - s: 0, - v: 0.67 + red: 170, + green: 170, + blue: 170 }; var endColor = { - h: 0, - s: 1, - v: 1 + red: 255, + green: 0, + blue: 0 }; var overlayID; - AudioDevice.muteToggled.connect(onMuteToggled); Script.update.connect(update); Script.scriptEnding.connect(cleanup); function update(dt) { if (!AudioDevice.getMuted()) { - if (overlayID) { + if (hasOverlay()) { deleteOverlay(); } - return; - } - updateOverlay(); + } else if (!hasOverlay()) { + createOverlay(); + } else { + updateOverlay(); + } } function lerp(a, b, val) { @@ -55,47 +55,10 @@ return Math.pow(t / 1, 5); } - // Adapted from a blog post on http://mjijackson.com - // Michael J. I. Jackson - // Converts an HSV color value to RGB. Conversion formula adapted from http: //en.wikipedia.org/wiki/HSV_color_space. - // Assumes h, s, and v are contained in the set[0, 1] - function hsvToRgb(h, s, v) { - var r, g, b; - - var i = Math.floor(h * 6); - var f = h * 6 - i; - var p = v * (1 - s); - var q = v * (1 - f * s); - var t = v * (1 - (1 - f) * s); - - switch (i % 6) { - case 0: r = v, g = t, b = p; break; - case 1: r = q, g = v, b = p; break; - case 2: r = p, g = v, b = t; break; - case 3: r = p, g = q, b = v; break; - case 4: r = t, g = p, b = v; break; - case 5: r = v, g = p, b = q; break; - } - - return { - red: r * 255, - green: g * 255, - blue: b * 255 - } - } - function getOffsetPosition() { return Vec3.sum(Camera.position, Quat.getFront(Camera.orientation)); } - function onMuteToggled() { - if (AudioDevice.getMuted()) { - createOverlay(); - } else { - deleteOverlay(); - } - } - function createOverlay() { overlayPosition = getOffsetPosition(); overlayID = Overlays.addOverlay("sphere", { @@ -108,6 +71,10 @@ }); } + function hasOverlay() { + return Overlays.getProperty(overlayID, "position") !== undefined; + } + function updateOverlay() { // increase by TWEEN_SPEED until completion if (tweenPosition < 1) { @@ -128,17 +95,11 @@ overlayPosition.y = lerp(overlayPosition.y, offsetPosition.y, LERP_AMOUNT); overlayPosition.z = lerp(overlayPosition.z, offsetPosition.z, LERP_AMOUNT); - var rgbColor = hsvToRgb( - lerp(startColor.h, endColor.h, easeIn(tweenPosition)), - lerp(startColor.s, endColor.s, easeIn(tweenPosition)), - lerp(startColor.v, endColor.v, easeIn(tweenPosition)) - ); - Overlays.editOverlay(overlayID, { color: { - red: rgbColor.red, - green: rgbColor.green, - blue: rgbColor.blue + red: lerp(startColor.red, endColor.red, easeIn(tweenPosition)), + green: lerp(startColor.green, endColor.green, easeIn(tweenPosition)), + blue: lerp(startColor.blue, endColor.blue, easeIn(tweenPosition)) }, position: overlayPosition, rotation: Camera.orientation From 9e0091ebe07c77683cce149e24e6b6ef91fff9fc Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Wed, 15 Mar 2017 11:08:54 +0000 Subject: [PATCH 13/22] use utils.js, move easing function, use mixes some cleanup --- scripts/developer/libraries/utils.js | 3 +++ scripts/system/audioMuteOverlay.js | 27 ++++++--------------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/scripts/developer/libraries/utils.js b/scripts/developer/libraries/utils.js index f39f4d7913..0da9703c87 100644 --- a/scripts/developer/libraries/utils.js +++ b/scripts/developer/libraries/utils.js @@ -311,3 +311,6 @@ clamp = function(val, min, max){ return Math.max(min, Math.min(max, val)) } +easeIn = function(t) { + return Math.pow(t / 1, 5); +} diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index 458efad6d0..d08fafc88d 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -15,8 +15,10 @@ // (function() { // BEGIN LOCAL_SCOPE + Script.include(utilsPath); + var TWEEN_SPEED = 0.025; - var LERP_AMOUNT = 0.25; + var MIX_AMOUNT = 0.25; var overlayPosition = Vec3.ZERO; var tweenPosition = 0; @@ -47,14 +49,6 @@ } } - function lerp(a, b, val) { - return (1 - val) * a + val * b; - } - - function easeIn(t) { - return Math.pow(t / 1, 5); - } - function getOffsetPosition() { return Vec3.sum(Camera.position, Quat.getFront(Camera.orientation)); } @@ -88,19 +82,10 @@ endColor[color] = storedColor; } } - - // update position based on LERP_AMOUNT - var offsetPosition = getOffsetPosition(); - overlayPosition.x = lerp(overlayPosition.x, offsetPosition.x, LERP_AMOUNT); - overlayPosition.y = lerp(overlayPosition.y, offsetPosition.y, LERP_AMOUNT); - overlayPosition.z = lerp(overlayPosition.z, offsetPosition.z, LERP_AMOUNT); - + // mix previous position with new and mix colors + overlayPosition = Vec3.mix(overlayPosition, getOffsetPosition(), MIX_AMOUNT); Overlays.editOverlay(overlayID, { - color: { - red: lerp(startColor.red, endColor.red, easeIn(tweenPosition)), - green: lerp(startColor.green, endColor.green, easeIn(tweenPosition)), - blue: lerp(startColor.blue, endColor.blue, easeIn(tweenPosition)) - }, + color: colorMix(startColor, endColor, easeIn(tweenPosition)), position: overlayPosition, rotation: Camera.orientation }); From 41041c711f8752f96b7fb0c18a65ed9d1c9364ab Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Wed, 15 Mar 2017 11:09:13 +0000 Subject: [PATCH 14/22] use utils.js --- scripts/system/audioMuteOverlay.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index d08fafc88d..d7bb843561 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -15,6 +15,7 @@ // (function() { // BEGIN LOCAL_SCOPE + var utilsPath = Script.resolvePath('../developer/libraries/utils.js?v='+ Date.now()); Script.include(utilsPath); var TWEEN_SPEED = 0.025; From 5883bd39dc255fcdb28e282c52fdbb664d6f6ff0 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Wed, 15 Mar 2017 11:17:27 +0000 Subject: [PATCH 15/22] rename color to component --- scripts/system/audioMuteOverlay.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index d7bb843561..473e06b556 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -77,10 +77,10 @@ } else { // after tween completion reset to zero and flip values to ping pong tweenPosition = 0; - for (var color in startColor) { - var storedColor = startColor[color]; - startColor[color] = endColor[color]; - endColor[color] = storedColor; + for (var component in startColor) { + var storedColor = startColor[component]; + startColor[component] = endColor[component]; + endColor[component] = storedColor; } } // mix previous position with new and mix colors From 36619cd2e4bc2ceb1d0ec153e3f17cfa95815f01 Mon Sep 17 00:00:00 2001 From: trent Date: Wed, 22 Mar 2017 15:07:29 -0400 Subject: [PATCH 16/22] Fixed issue with duplicate physics status icons per sub-object. --- interface/src/avatar/CauterizedModel.cpp | 6 +- libraries/render-utils/src/Model.cpp | 82 ++++++++++++------------ libraries/render-utils/src/Model.h | 10 +-- 3 files changed, 49 insertions(+), 49 deletions(-) diff --git a/interface/src/avatar/CauterizedModel.cpp b/interface/src/avatar/CauterizedModel.cpp index d8db83fbb7..f479ed9a35 100644 --- a/interface/src/avatar/CauterizedModel.cpp +++ b/interface/src/avatar/CauterizedModel.cpp @@ -56,9 +56,9 @@ void CauterizedModel::createVisibleRenderItemSet() { } // We should not have any existing renderItems if we enter this section of code - Q_ASSERT(_modelMeshRenderItemsSet.isEmpty()); + Q_ASSERT(_modelMeshRenderItems.isEmpty()); - _modelMeshRenderItemsSet.clear(); + _modelMeshRenderItems.clear(); Transform transform; transform.setTranslation(_translation); @@ -81,7 +81,7 @@ void CauterizedModel::createVisibleRenderItemSet() { int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { auto ptr = std::make_shared(this, i, partIndex, shapeID, transform, offset); - _modelMeshRenderItemsSet << std::static_pointer_cast(ptr); + _modelMeshRenderItems << std::static_pointer_cast(ptr); shapeID++; } } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c584b0bc21..3448c9e8da 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -176,11 +176,11 @@ void Model::setOffset(const glm::vec3& offset) { } void Model::calculateTextureInfo() { - if (!_hasCalculatedTextureInfo && isLoaded() && getGeometry()->areTexturesLoaded() && !_modelMeshRenderItems.isEmpty()) { + if (!_hasCalculatedTextureInfo && isLoaded() && getGeometry()->areTexturesLoaded() && !_modelMeshRenderItemsMap.isEmpty()) { size_t textureSize = 0; int textureCount = 0; bool allTexturesLoaded = true; - foreach(auto renderItem, _modelMeshRenderItemsSet) { + foreach(auto renderItem, _modelMeshRenderItems) { auto meshPart = renderItem.get(); textureSize += meshPart->getMaterialTextureSize(); textureCount += meshPart->getMaterialTextureCount(); @@ -236,7 +236,7 @@ void Model::updateRenderItems() { uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; render::PendingChanges pendingChanges; - foreach (auto itemID, self->_modelMeshRenderItems.keys()) { + foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) { pendingChanges.updateItem(itemID, [deleteGeometryCounter](ModelMeshPartPayload& data) { if (data._model && data._model->isLoaded()) { // Ensure the model geometry was not reset between frames @@ -259,7 +259,7 @@ void Model::updateRenderItems() { Transform collisionMeshOffset; collisionMeshOffset.setIdentity(); Transform modelTransform = self->getTransform(); - foreach (auto itemID, self->_collisionRenderItems.keys()) { + foreach(auto itemID, self->_collisionRenderItemsMap.keys()) { pendingChanges.updateItem(itemID, [modelTransform, collisionMeshOffset](MeshPartPayload& data) { // update the model transform for this render item. data.updateTransform(modelTransform, collisionMeshOffset); @@ -539,11 +539,11 @@ void Model::setVisibleInScene(bool newValue, std::shared_ptr scen _isVisible = newValue; render::PendingChanges pendingChanges; - foreach (auto item, _modelMeshRenderItems.keys()) { - pendingChanges.resetItem(item, _modelMeshRenderItems[item]); + foreach (auto item, _modelMeshRenderItemsMap.keys()) { + pendingChanges.resetItem(item, _modelMeshRenderItemsMap[item]); } - foreach (auto item, _collisionRenderItems.keys()) { - pendingChanges.resetItem(item, _collisionRenderItems[item]); + foreach(auto item, _collisionRenderItemsMap.keys()) { + pendingChanges.resetItem(item, _collisionRenderItemsMap[item]); } scene->enqueuePendingChanges(pendingChanges); } @@ -555,11 +555,11 @@ void Model::setLayeredInFront(bool layered, std::shared_ptr scene _isLayeredInFront = layered; render::PendingChanges pendingChanges; - foreach(auto item, _modelMeshRenderItems.keys()) { - pendingChanges.resetItem(item, _modelMeshRenderItems[item]); + foreach(auto item, _modelMeshRenderItemsMap.keys()) { + pendingChanges.resetItem(item, _modelMeshRenderItemsMap[item]); } - foreach(auto item, _collisionRenderItems.keys()) { - pendingChanges.resetItem(item, _collisionRenderItems[item]); + foreach(auto item, _collisionRenderItemsMap.keys()) { + pendingChanges.resetItem(item, _collisionRenderItemsMap[item]); } scene->enqueuePendingChanges(pendingChanges); } @@ -576,39 +576,39 @@ bool Model::addToScene(std::shared_ptr scene, bool somethingAdded = false; if (_collisionGeometry) { if (_collisionRenderItems.empty()) { - foreach (auto renderItem, _collisionRenderItemsSet) { + foreach (auto renderItem, _collisionRenderItems) { auto item = scene->allocateID(); auto renderPayload = std::make_shared(renderItem); - if (statusGetters.size()) { + if (_collisionRenderItems.empty() && statusGetters.size()) { renderPayload->addStatusGetters(statusGetters); } pendingChanges.resetItem(item, renderPayload); - _collisionRenderItems.insert(item, renderPayload); + _collisionRenderItemsMap.insert(item, renderPayload); } somethingAdded = !_collisionRenderItems.empty(); } } else { - if (_modelMeshRenderItems.empty()) { + if (_modelMeshRenderItemsMap.empty()) { bool hasTransparent = false; size_t verticesCount = 0; - foreach(auto renderItem, _modelMeshRenderItemsSet) { + foreach(auto renderItem, _modelMeshRenderItems) { auto item = scene->allocateID(); auto renderPayload = std::make_shared(renderItem); - if (statusGetters.size()) { + if (_modelMeshRenderItemsMap.empty() && statusGetters.size()) { renderPayload->addStatusGetters(statusGetters); } pendingChanges.resetItem(item, renderPayload); hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent(); verticesCount += renderItem.get()->getVerticesCount(); - _modelMeshRenderItems.insert(item, renderPayload); + _modelMeshRenderItemsMap.insert(item, renderPayload); _modelMeshRenderItemIDs.emplace_back(item); } - somethingAdded = !_modelMeshRenderItems.empty(); + somethingAdded = !_modelMeshRenderItemsMap.empty(); _renderInfoVertexCount = verticesCount; - _renderInfoDrawCalls = _modelMeshRenderItems.count(); + _renderInfoDrawCalls = _modelMeshRenderItemsMap.count(); _renderInfoHasTransparent = hasTransparent; } } @@ -623,18 +623,18 @@ bool Model::addToScene(std::shared_ptr scene, } void Model::removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { - foreach (auto item, _modelMeshRenderItems.keys()) { + foreach (auto item, _modelMeshRenderItemsMap.keys()) { pendingChanges.removeItem(item); } _modelMeshRenderItemIDs.clear(); + _modelMeshRenderItemsMap.clear(); _modelMeshRenderItems.clear(); - _modelMeshRenderItemsSet.clear(); - foreach (auto item, _collisionRenderItems.keys()) { + foreach(auto item, _collisionRenderItemsMap.keys()) { pendingChanges.removeItem(item); } _collisionRenderItems.clear(); - _collisionRenderItemsSet.clear(); + _collisionRenderItems.clear(); _addedToScene = false; _renderInfoVertexCount = 0; @@ -1052,8 +1052,8 @@ void Model::updateRig(float deltaTime, glm::mat4 parentTransform) { } void Model::computeMeshPartLocalBounds() { - for (auto& part : _modelMeshRenderItemsSet) { - assert(part->_meshIndex < _modelMeshRenderItemsSet.size()); + for (auto& part : _modelMeshRenderItems) { + assert(part->_meshIndex < _modelMeshRenderItems.size()); const Model::MeshState& state = _meshStates.at(part->_meshIndex); part->computeAdjustedLocalBound(state.clusterMatrices); } @@ -1167,7 +1167,7 @@ AABox Model::getRenderableMeshBound() const { } else { // Build a bound using the last known bound from all the renderItems. AABox totalBound; - for (auto& renderItem : _modelMeshRenderItemsSet) { + for (auto& renderItem : _modelMeshRenderItems) { totalBound += renderItem->getBound(); } return totalBound; @@ -1180,11 +1180,11 @@ const render::ItemIDs& Model::fetchRenderItemIDs() const { void Model::createRenderItemSet() { if (_collisionGeometry) { - if (_collisionRenderItemsSet.empty()) { + if (_collisionRenderItems.empty()) { createCollisionRenderItemSet(); } } else { - if (_modelMeshRenderItemsSet.empty()) { + if (_modelMeshRenderItems.empty()) { createVisibleRenderItemSet(); } } @@ -1201,9 +1201,9 @@ void Model::createVisibleRenderItemSet() { } // We should not have any existing renderItems if we enter this section of code - Q_ASSERT(_modelMeshRenderItemsSet.isEmpty()); + Q_ASSERT(_modelMeshRenderItems.isEmpty()); - _modelMeshRenderItemsSet.clear(); + _modelMeshRenderItems.clear(); Transform transform; transform.setTranslation(_translation); @@ -1225,7 +1225,7 @@ void Model::createVisibleRenderItemSet() { // Create the render payloads int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { - _modelMeshRenderItemsSet << std::make_shared(this, i, partIndex, shapeID, transform, offset); + _modelMeshRenderItems << std::make_shared(this, i, partIndex, shapeID, transform, offset); shapeID++; } } @@ -1241,7 +1241,7 @@ void Model::createCollisionRenderItemSet() { const auto& meshes = _collisionGeometry->getMeshes(); // We should not have any existing renderItems if we enter this section of code - Q_ASSERT(_collisionRenderItemsSet.isEmpty()); + Q_ASSERT(_collisionRenderItems.isEmpty()); Transform identity; identity.setIdentity(); @@ -1262,7 +1262,7 @@ void Model::createCollisionRenderItemSet() { model::MaterialPointer& material = _collisionMaterials[partIndex % NUM_COLLISION_HULL_COLORS]; auto payload = std::make_shared(mesh, partIndex, material); payload->updateTransform(identity, offset); - _collisionRenderItemsSet << payload; + _collisionRenderItems << payload; } } } @@ -1283,28 +1283,28 @@ bool Model::initWhenReady(render::ScenePointer scene) { bool addedPendingChanges = false; if (_collisionGeometry) { - foreach (auto renderItem, _collisionRenderItemsSet) { + foreach (auto renderItem, _collisionRenderItems) { auto item = scene->allocateID(); auto renderPayload = std::make_shared(renderItem); - _collisionRenderItems.insert(item, renderPayload); + _collisionRenderItemsMap.insert(item, renderPayload); pendingChanges.resetItem(item, renderPayload); } addedPendingChanges = !_collisionRenderItems.empty(); } else { bool hasTransparent = false; size_t verticesCount = 0; - foreach (auto renderItem, _modelMeshRenderItemsSet) { + foreach (auto renderItem, _modelMeshRenderItems) { auto item = scene->allocateID(); auto renderPayload = std::make_shared(renderItem); hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent(); verticesCount += renderItem.get()->getVerticesCount(); - _modelMeshRenderItems.insert(item, renderPayload); + _modelMeshRenderItemsMap.insert(item, renderPayload); pendingChanges.resetItem(item, renderPayload); } - addedPendingChanges = !_modelMeshRenderItems.empty(); + addedPendingChanges = !_modelMeshRenderItemsMap.empty(); _renderInfoVertexCount = verticesCount; - _renderInfoDrawCalls = _modelMeshRenderItems.count(); + _renderInfoDrawCalls = _modelMeshRenderItemsMap.count(); _renderInfoHasTransparent = hasTransparent; } _addedToScene = addedPendingChanges; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 41821736f7..bb283cce1f 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -248,7 +248,7 @@ public: const MeshState& getMeshState(int index) { return _meshStates.at(index); } uint32_t getGeometryCounter() const { return _deleteGeometryCounter; } - const QMap& getRenderItems() const { return _modelMeshRenderItems; } + const QMap& getRenderItems() const { return _modelMeshRenderItemsMap; } void renderDebugMeshBoxes(gpu::Batch& batch); @@ -373,11 +373,11 @@ protected: static AbstractViewStateInterface* _viewState; - QSet> _collisionRenderItemsSet; - QMap _collisionRenderItems; + QVector> _collisionRenderItems; + QMap _collisionRenderItemsMap; - QSet> _modelMeshRenderItemsSet; - QMap _modelMeshRenderItems; + QVector> _modelMeshRenderItems; + QMap _modelMeshRenderItemsMap; render::ItemIDs _modelMeshRenderItemIDs; From c71e57753be6ff9daf31e8404b84f53b7978206c Mon Sep 17 00:00:00 2001 From: trent Date: Wed, 22 Mar 2017 15:23:40 -0400 Subject: [PATCH 17/22] Removing changes (albeit benign ones) from another PR. --- libraries/fbx/src/OBJReader.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index c1bb72dff8..0cb932b375 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -267,7 +267,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { } if (token == "map_Kd") { currentMaterial.diffuseTextureFilename = filename; - } else if( token == "map_Ks" ) { + } else { currentMaterial.specularTextureFilename = filename; } } @@ -612,9 +612,6 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, if (!objMaterial.diffuseTextureFilename.isEmpty()) { fbxMaterial.albedoTexture.filename = objMaterial.diffuseTextureFilename; } - if (!objMaterial.specularTextureFilename.isEmpty()) { - fbxMaterial.specularTexture.filename = objMaterial.specularTextureFilename; - } modelMaterial->setEmissive(fbxMaterial.emissiveColor); modelMaterial->setAlbedo(fbxMaterial.diffuseColor); From 56c5f06365d1ad043293af1d06cd93d3a85e2805 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Mar 2017 16:29:08 -0700 Subject: [PATCH 18/22] Fix Oculus Touch + Remote not being detected after initial launch --- .../oculus/src/OculusControllerManager.cpp | 23 ++++++++++++++----- plugins/oculus/src/OculusControllerManager.h | 2 ++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index ce59eafd50..87c52de3e7 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -20,6 +20,8 @@ #include #include +#include + #include "OculusHelpers.h" Q_DECLARE_LOGGING_CATEGORY(oculus) @@ -42,26 +44,33 @@ bool OculusControllerManager::activate() { } Q_ASSERT(_session); - // register with UserInputMapper - auto userInputMapper = DependencyManager::get(); + checkForConnectedDevices(); + + return true; +} + +void OculusControllerManager::checkForConnectedDevices() { + if (_touch && _remote) { + return; + } unsigned int controllerConnected = ovr_GetConnectedControllerTypes(_session); - if ((controllerConnected & ovrControllerType_Remote) == ovrControllerType_Remote) { + if (!_remote && (controllerConnected & ovrControllerType_Remote) == ovrControllerType_Remote) { if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Remote, &_inputState))) { + auto userInputMapper = DependencyManager::get(); _remote = std::make_shared(*this); userInputMapper->registerDevice(_remote); } } - if ((controllerConnected & ovrControllerType_Touch) != 0) { + if (!_touch && (controllerConnected & ovrControllerType_Touch) != 0) { if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) { + auto userInputMapper = DependencyManager::get(); _touch = std::make_shared(*this); userInputMapper->registerDevice(_touch); } } - - return true; } void OculusControllerManager::deactivate() { @@ -85,6 +94,8 @@ void OculusControllerManager::deactivate() { void OculusControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { PerformanceTimer perfTimer("OculusControllerManager::TouchDevice::update"); + checkForConnectedDevices(); + if (_touch) { if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) { _touch->update(deltaTime, inputCalibrationData); diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 98e0e3d650..23ef52ab64 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -91,6 +91,8 @@ private: friend class OculusControllerManager; }; + void checkForConnectedDevices(); + ovrSession _session { nullptr }; ovrInputState _inputState {}; RemoteDevice::Pointer _remote; From 4f8d9b190b4a8f2d04409c4b953e46cf5929dda0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Mar 2017 17:49:55 -0700 Subject: [PATCH 19/22] Show green box when model entity has bad url --- .../src/RenderableModelEntityItem.cpp | 211 +++++++++--------- .../src/RenderableModelEntityItem.h | 2 +- 2 files changed, 109 insertions(+), 104 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 935dd4e796..613bd5d543 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -371,109 +371,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { _model->updateRenderItems(); } - if (hasModel()) { - // Prepare the current frame - { - if (!_model || _needsModelReload) { - // TODO: this getModel() appears to be about 3% of model render time. We should optimize - PerformanceTimer perfTimer("getModel"); - auto renderer = qSharedPointerCast(args->_renderer); - getModel(renderer); - - // Remap textures immediately after loading to avoid flicker - remapTextures(); - } - - if (_model) { - if (hasRenderAnimation()) { - if (!jointsMapped()) { - QStringList modelJointNames = _model->getJointNames(); - mapJoints(modelJointNames); - } - } - - _jointDataLock.withWriteLock([&] { - getAnimationFrame(); - - // relay any inbound joint changes from scripts/animation/network to the model/rig - for (int index = 0; index < _localJointRotations.size(); index++) { - if (_localJointRotationsDirty[index]) { - glm::quat rotation = _localJointRotations[index]; - _model->setJointRotation(index, true, rotation, 1.0f); - _localJointRotationsDirty[index] = false; - } - } - for (int index = 0; index < _localJointTranslations.size(); index++) { - if (_localJointTranslationsDirty[index]) { - glm::vec3 translation = _localJointTranslations[index]; - _model->setJointTranslation(index, true, translation, 1.0f); - _localJointTranslationsDirty[index] = false; - } - } - }); - updateModelBounds(); - } - } - - // Enqueue updates for the next frame - if (_model) { - -#ifdef WANT_EXTRA_RENDER_DEBUGGING - // debugging... - gpu::Batch& batch = *args->_batch; - _model->renderDebugMeshBoxes(batch); -#endif - - render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - - // FIXME: this seems like it could be optimized if we tracked our last known visible state in - // the renderable item. As it stands now the model checks it's visible/invisible state - // so most of the time we don't do anything in this function. - _model->setVisibleInScene(getVisible(), scene); - - // Remap textures for the next frame to avoid flicker - remapTextures(); - - // update whether the model should be showing collision mesh (this may flag for fixupInScene) - bool showingCollisionGeometry = (bool)(args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS); - if (showingCollisionGeometry != _showCollisionGeometry) { - ShapeType type = getShapeType(); - _showCollisionGeometry = showingCollisionGeometry; - if (_showCollisionGeometry && type != SHAPE_TYPE_STATIC_MESH && type != SHAPE_TYPE_NONE) { - // NOTE: it is OK if _collisionMeshKey is nullptr - model::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey); - // NOTE: the model will render the collisionGeometry if it has one - _model->setCollisionMesh(mesh); - } else { - // release mesh - if (_collisionMeshKey) { - collisionMeshCache.releaseMesh(_collisionMeshKey); - } - // clear model's collision geometry - model::MeshPointer mesh = nullptr; - _model->setCollisionMesh(mesh); - } - } - - if (_model->needsFixupInScene()) { - render::PendingChanges pendingChanges; - - _model->removeFromScene(scene, pendingChanges); - - render::Item::Status::Getters statusGetters; - makeEntityItemStatusGetters(getThisPointer(), statusGetters); - _model->addToScene(scene, pendingChanges, statusGetters); - - scene->enqueuePendingChanges(pendingChanges); - } - - auto& currentURL = getParsedModelURL(); - if (currentURL != _model->getURL()) { - // Defer setting the url to the render thread - getModel(_myRenderer); - } - } - } else { + if (!hasModel() || (_model && _model->didVisualGeometryRequestFail())) { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); gpu::Batch& batch = *args->_batch; bool success; @@ -482,6 +380,109 @@ void RenderableModelEntityItem::render(RenderArgs* args) { batch.setModelTransform(shapeTransform); // we want to include the scale as well DependencyManager::get()->renderWireCubeInstance(batch, greenColor); } + return; + } + + // Prepare the current frame + { + if (!_model || _needsModelReload) { + // TODO: this getModel() appears to be about 3% of model render time. We should optimize + PerformanceTimer perfTimer("getModel"); + auto renderer = qSharedPointerCast(args->_renderer); + getModel(renderer); + + // Remap textures immediately after loading to avoid flicker + remapTextures(); + } + + if (_model) { + if (hasRenderAnimation()) { + if (!jointsMapped()) { + QStringList modelJointNames = _model->getJointNames(); + mapJoints(modelJointNames); + } + } + + _jointDataLock.withWriteLock([&] { + getAnimationFrame(); + + // relay any inbound joint changes from scripts/animation/network to the model/rig + for (int index = 0; index < _localJointRotations.size(); index++) { + if (_localJointRotationsDirty[index]) { + glm::quat rotation = _localJointRotations[index]; + _model->setJointRotation(index, true, rotation, 1.0f); + _localJointRotationsDirty[index] = false; + } + } + for (int index = 0; index < _localJointTranslations.size(); index++) { + if (_localJointTranslationsDirty[index]) { + glm::vec3 translation = _localJointTranslations[index]; + _model->setJointTranslation(index, true, translation, 1.0f); + _localJointTranslationsDirty[index] = false; + } + } + }); + updateModelBounds(); + } + } + + // Enqueue updates for the next frame + if (_model) { + +#ifdef WANT_EXTRA_RENDER_DEBUGGING + // debugging... + gpu::Batch& batch = *args->_batch; + _model->renderDebugMeshBoxes(batch); +#endif + + render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); + + // FIXME: this seems like it could be optimized if we tracked our last known visible state in + // the renderable item. As it stands now the model checks it's visible/invisible state + // so most of the time we don't do anything in this function. + _model->setVisibleInScene(getVisible(), scene); + + // Remap textures for the next frame to avoid flicker + remapTextures(); + + // update whether the model should be showing collision mesh (this may flag for fixupInScene) + bool showingCollisionGeometry = (bool)(args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS); + if (showingCollisionGeometry != _showCollisionGeometry) { + ShapeType type = getShapeType(); + _showCollisionGeometry = showingCollisionGeometry; + if (_showCollisionGeometry && type != SHAPE_TYPE_STATIC_MESH && type != SHAPE_TYPE_NONE) { + // NOTE: it is OK if _collisionMeshKey is nullptr + model::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey); + // NOTE: the model will render the collisionGeometry if it has one + _model->setCollisionMesh(mesh); + } else { + // release mesh + if (_collisionMeshKey) { + collisionMeshCache.releaseMesh(_collisionMeshKey); + } + // clear model's collision geometry + model::MeshPointer mesh = nullptr; + _model->setCollisionMesh(mesh); + } + } + + if (_model->needsFixupInScene()) { + render::PendingChanges pendingChanges; + + _model->removeFromScene(scene, pendingChanges); + + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(getThisPointer(), statusGetters); + _model->addToScene(scene, pendingChanges, statusGetters); + + scene->enqueuePendingChanges(pendingChanges); + } + + auto& currentURL = getParsedModelURL(); + if (currentURL != _model->getURL()) { + // Defer setting the url to the render thread + getModel(_myRenderer); + } } } @@ -587,6 +588,10 @@ EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlag return properties; } +bool RenderableModelEntityItem::supportsDetailedRayIntersection() const { + return _model && _model->isLoaded(); +} + bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index bac2118326..057ca36e13 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -46,7 +46,7 @@ public: void updateModelBounds(); virtual void render(RenderArgs* args) override; - virtual bool supportsDetailedRayIntersection() const override { return true; } + virtual bool supportsDetailedRayIntersection() const override; virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, From e1e51614d9549f000b9db43b78445118c4d8d527 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 24 Mar 2017 11:16:54 -0700 Subject: [PATCH 20/22] don't hang loop if entity isDead --- libraries/physics/src/PhysicalEntitySimulation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index bd76b2d70f..6f5b474810 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -208,6 +208,7 @@ void PhysicalEntitySimulation::getObjectsToAddToPhysics(VectorOfMotionStates& re assert(!entity->getPhysicsInfo()); if (entity->isDead()) { prepareEntityForDelete(entity); + entityItr = _entitiesToAddToPhysics.erase(entityItr); } else if (!entity->shouldBePhysical()) { // this entity should no longer be on the internal _entitiesToAddToPhysics entityItr = _entitiesToAddToPhysics.erase(entityItr); From aaa78d108b380726fe374a782d30f7ffdb38e284 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 24 Mar 2017 11:17:24 -0700 Subject: [PATCH 21/22] if a model has too many meshes, give up. --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 935dd4e796..f865e39b21 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -807,6 +807,13 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { auto& meshes = _model->getGeometry()->getMeshes(); int32_t numMeshes = (int32_t)(meshes.size()); + const int MAX_ALLOWED_MESH_COUNT = 500; + if (numMeshes > MAX_ALLOWED_MESH_COUNT) { + // too many will cause the deadlock timer to throw... + shapeInfo.setParams(SHAPE_TYPE_BOX, 0.5f * dimensions); + return; + } + ShapeInfo::PointCollection& pointCollection = shapeInfo.getPointCollection(); pointCollection.clear(); if (type == SHAPE_TYPE_SIMPLE_COMPOUND) { From fa606446a794bdfec7b7ce430df8a62f56ad681b Mon Sep 17 00:00:00 2001 From: Lexx Date: Fri, 24 Mar 2017 18:27:38 +0000 Subject: [PATCH 22/22] remove cache buster --- scripts/system/audioMuteOverlay.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/audioMuteOverlay.js b/scripts/system/audioMuteOverlay.js index 473e06b556..cf07402d64 100644 --- a/scripts/system/audioMuteOverlay.js +++ b/scripts/system/audioMuteOverlay.js @@ -15,7 +15,7 @@ // (function() { // BEGIN LOCAL_SCOPE - var utilsPath = Script.resolvePath('../developer/libraries/utils.js?v='+ Date.now()); + var utilsPath = Script.resolvePath('../developer/libraries/utils.js'); Script.include(utilsPath); var TWEEN_SPEED = 0.025;