From da6986f759860fa619a1d7b9a98ef0d8e60050aa Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 7 Jul 2015 21:06:12 +0200 Subject: [PATCH 001/129] Planky refactorings and basic planky settings --- examples/example/games/planky.js | 282 +++++++++++++++++++++--------- examples/html/plankySettings.html | 112 ++++++++++++ 2 files changed, 312 insertions(+), 82 deletions(-) create mode 100644 examples/html/plankySettings.html diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index 00a4e7f61d..cd4a7295be 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -12,23 +12,28 @@ // HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -const NUM_LAYERS = 16; -const BASE_DIMENSION = { x: 7, y: 2, z: 7 }; -const BLOCKS_PER_LAYER = 3; -const BLOCK_SIZE = {x: 0.2, y: 0.1, z: 0.8}; -const BLOCK_SPACING = BLOCK_SIZE.x / 3; +const DEFAULT_NUM_LAYERS = 16; +const DEFAULT_BASE_DIMENSION = { x: 7, y: 2, z: 7 }; +const DEFAULT_BLOCKS_PER_LAYER = 3; +const DEFAULT_BLOCK_SIZE = {x: 0.2, y: 0.1, z: 0.8}; +const DEFAULT_BLOCK_SPACING = DEFAULT_BLOCK_SIZE.x / DEFAULT_BLOCKS_PER_LAYER; // BLOCK_HEIGHT_VARIATION removes a random percentages of the default block height per block. (for example 0.001 %) -const BLOCK_HEIGHT_VARIATION = 0.001; -const GRAVITY = {x: 0, y: -2.8, z: 0}; -const DENSITY = 2000; -const DAMPING_FACTOR = 0.98; -const ANGULAR_DAMPING_FACTOR = 0.8; -const FRICTION = 0.99; -const RESTITUTION = 0.0; -const SPAWN_DISTANCE = 3; -const BLOCK_YAW_OFFSET = 45; +const DEFAULT_BLOCK_HEIGHT_VARIATION = 0.001; +const DEFAULT_GRAVITY = {x: 0, y: -2.8, z: 0}; +const DEFAULT_DENSITY = 2000; +const DEFAULT_DAMPING_FACTOR = 0.98; +const DEFAULT_ANGULAR_DAMPING_FACTOR = 0.8; +const DEFAULT_FRICTION = 0.99; +const DEFAULT_RESTITUTION = 0.0; +const DEFAULT_SPAWN_DISTANCE = 3; +const DEFAULT_BLOCK_YAW_OFFSET = 45; + +var editMode = false; + const BUTTON_DIMENSIONS = {width: 49, height: 49}; const MAXIMUM_PERCENTAGE = 100.0; +const NO_ANGLE = 0; +const RIGHT_ANGLE = 90; var windowWidth = Window.innerWidth; var size; @@ -36,6 +41,163 @@ var pieces = []; var ground = false; var layerRotated = false; +SettingsWindow = function() { + this.webWindow = null; + this.init = function() { + this.webWindow = new WebWindow('Planky', Script.resolvePath('../../html/plankySettings.html'), 255, 500, true); + this.webWindow.setVisible(false); + }; +}; + +PlankyOptions = function() { + var _this = this; + this.save = function() { + //TODO: save Planky Options here. + }; + this.load = function() { + //TODO: load Planky Options here. + }; + this.setDefaults = function() { + _this.numLayers = DEFAULT_NUM_LAYERS; + _this.baseDimension = DEFAULT_BASE_DIMENSION; + _this.blocksPerLayer = DEFAULT_BLOCKS_PER_LAYER; + _this.blockSize = DEFAULT_BLOCK_SIZE; + _this.blockSpacing = DEFAULT_BLOCK_SPACING; + _this.blockHeightVariation = DEFAULT_BLOCK_HEIGHT_VARIATION; + _this.gravity = DEFAULT_GRAVITY; + _this.density = DEFAULT_DENSITY; + _this.dampingFactor = DEFAULT_DAMPING_FACTOR; + _this.angularDampingFactor = DEFAULT_ANGULAR_DAMPING_FACTOR; + _this.friction = DEFAULT_FRICTION; + _this.restitution = DEFAULT_RESTITUTION; + _this.spawnDistance = DEFAULT_SPAWN_DISTANCE; + _this.blockYawOffset = DEFAULT_BLOCK_YAW_OFFSET; + }; + this.setDefaults(); +}; + +// The PlankyStack exists out of rows and layers +PlankyStack = function() { + var _this = this; + this.planks = []; + this.ground = false; + this.options = new PlankyOptions(); + this.deRez = function() { + _this.planks.forEach(function(plank) { + Entities.deleteEntity(plank.entity); + }); + _this.planks = []; + if (_this.ground) { + Entities.deleteEntity(_this.ground); + } + _this.ground = false; + }; + this.rez = function() { + if (_this.planks.length > 0) { + _this.deRez(); + } + _this.baseRotation = Quat.fromPitchYawRollDegrees(0.0, MyAvatar.bodyYaw, 0.0); + var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(_this.options.spawnDistance, Quat.getFront(_this.baseRotation))); + basePosition.y = grabLowestJointY(); + _this.basePosition = basePosition; + _this.refresh(); + }; + + //private function + var refreshGround = function() { + if (!_this.ground) { + _this.ground = Entities.addEntity({ + type: 'Model', + modelURL: HIFI_PUBLIC_BUCKET + 'eric/models/woodFloor.fbx', + dimensions: _this.options.baseDimension, + position: Vec3.sum(_this.basePosition, {y: -(_this.options.baseDimension.y / 2)}), + rotation: _this.baseRotation, + shapeType: 'box' + }); + return; + } + // move ground to rez position/rotation + Entities.editEntity(_this.ground, {dimensions: _this.options.baseDimension, position: Vec3.sum(_this.basePosition, {y: -(_this.options.baseDimension.y / 2)}), rotation: _this.baseRotation}); + } + var trimDimension = function(dimension, maxIndex) { + _this.planks.forEach(function(plank, index, object) { + if (plank[dimension] > maxIndex) { + Entities.deleteEntity(plank.entity); + object.splice(index, 1); + } + }); + }; + var createOrUpdate = function(layer, row) { + var found = false; + var layerRotated = layer % 2 === 0; + var offset = -(_this.options.blockSpacing); + var layerRotation = Quat.fromPitchYawRollDegrees(0, layerRotated ? NO_ANGLE : RIGHT_ANGLE, 0.0); + var blockPositionXZ = (_this.options.blockSize.x * row) - (((_this.options.blockSize.x * _this.options.blocksPerLayer) / 2) - (_this.options.blockSize.x / 2)); + var localTransform = Vec3.multiplyQbyV(_this.offsetRot, { + x: (layerRotated ? blockPositionXZ + offset: 0), + y: (_this.options.blockSize.y / 2) + (_this.options.blockSize.y * layer), + z: (layerRotated ? 0 : blockPositionXZ + offset) + }); + var newProperties = { + type: 'Model', + modelURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/block.fbx', + shapeType: 'box', + name: 'PlankyBlock' + layer + '-' + row, + dimensions: Vec3.sum(_this.options.blockSize, {x: 0, y: -((_this.options.blockSize.y * (_this.options.blockHeightVariation / MAXIMUM_PERCENTAGE)) * Math.random()), z: 0}), + position: Vec3.sum(_this.basePosition, localTransform), + rotation: Quat.multiply(layerRotation, _this.offsetRot), + //collisionsWillMove: false,//!editMode,//false,//!editMode, + damping: _this.options.dampingFactor, + restitution: _this.options.restitution, + friction: _this.options.friction, + angularDamping: _this.options.angularDampingFactor, + gravity: _this.options.gravity, + density: _this.options.density, + velocity: {x: 0, y: 0, z: 0}, + angularVelocity: Quat.fromPitchYawRollDegrees(0, 0, 0), + ignoreForCollisions: true + }; + _this.planks.forEach(function(plank, index, object) { + if (plank.layer === layer && plank.row === row) { + Entities.editEntity(plank.entity, newProperties); + found = true; + // break loop: + return false; + } + }); + if (!found) { + _this.planks.push({layer: layer, row: row, entity: Entities.addEntity(newProperties)}) + } + }; + this.refresh = function() { + refreshGround(); + trimDimension('layer', _this.options.numLayers); + trimDimension('row', _this.options.blocksPerLayer); + _this.offsetRot = Quat.multiply(_this.baseRotation, Quat.fromPitchYawRollDegrees(0.0, _this.options.blockYawOffset, 0.0)); + for (var layer = 0; layer < _this.options.numLayers; layer++) { + for (var row = 0; row < _this.options.blocksPerLayer; row++) { + createOrUpdate(layer, row); + } + } + if (!editMode) { + _this.planks.forEach(function(plank, index, object) { + print(index + " , " + plank); + Entities.editEntity(plank.entity, {ignoreForCollisions: false, collisionsWillMove: true}); + // Entities.editEntity(plank.entity, {collisionsWillMove: true}); + }); + } + }; + this.isFound = function() { + //TODO: identify entities here until one is found + return _this.planks.length > 0; + }; +}; + +var settingsWindow = new SettingsWindow(); +settingsWindow.init(); + +var plankyStack = new PlankyStack(); + function grabLowestJointY() { var jointNames = MyAvatar.getJointNames(); var floorY = MyAvatar.position.y; @@ -51,6 +213,10 @@ function getButtonPosX() { return windowWidth - ((BUTTON_DIMENSIONS.width / 2) + BUTTON_DIMENSIONS.width); } +function getCogButtonPosX() { + return getButtonPosX() - (BUTTON_DIMENSIONS.width * 1.1); +} + var button = Overlays.addOverlay('image', { x: getButtonPosX(), y: 10, @@ -60,73 +226,26 @@ var button = Overlays.addOverlay('image', { alpha: 0.8 }); - -function resetBlocks() { - pieces.forEach(function(piece) { - Entities.deleteEntity(piece); - }); - pieces = []; - var avatarRot = Quat.fromPitchYawRollDegrees(0.0, MyAvatar.bodyYaw, 0.0); - basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(SPAWN_DISTANCE, Quat.getFront(avatarRot))); - basePosition.y = grabLowestJointY() - (BASE_DIMENSION.y / 2); - if (!ground) { - ground = Entities.addEntity({ - type: 'Model', - modelURL: HIFI_PUBLIC_BUCKET + 'eric/models/woodFloor.fbx', - dimensions: BASE_DIMENSION, - position: basePosition, - rotation: avatarRot, - shapeType: 'box' - }); - } else { - Entities.editEntity(ground, {position: basePosition, rotation: avatarRot}); - } - var offsetRot = Quat.multiply(avatarRot, Quat.fromPitchYawRollDegrees(0.0, BLOCK_YAW_OFFSET, 0.0)); - basePosition.y += (BASE_DIMENSION.y / 2); - for (var layerIndex = 0; layerIndex < NUM_LAYERS; layerIndex++) { - var layerRotated = layerIndex % 2 === 0; - var offset = -(BLOCK_SPACING); - var layerRotation = Quat.fromPitchYawRollDegrees(0, layerRotated ? 0 : 90, 0.0); - for (var blockIndex = 0; blockIndex < BLOCKS_PER_LAYER; blockIndex++) { - var blockPositionXZ = BLOCK_SIZE.x * blockIndex - (BLOCK_SIZE.x * 3 / 2 - BLOCK_SIZE.x / 2); - var localTransform = Vec3.multiplyQbyV(offsetRot, { - x: (layerRotated ? blockPositionXZ + offset: 0), - y: (BLOCK_SIZE.y / 2) + (BLOCK_SIZE.y * layerIndex), - z: (layerRotated ? 0 : blockPositionXZ + offset) - }); - pieces.push(Entities.addEntity({ - type: 'Model', - modelURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/block.fbx', - shapeType: 'box', - name: 'PlankyBlock' + ((layerIndex * BLOCKS_PER_LAYER) + blockIndex), - dimensions: { - x: BLOCK_SIZE.x, - y: BLOCK_SIZE.y - ((BLOCK_SIZE.y * (BLOCK_HEIGHT_VARIATION / MAXIMUM_PERCENTAGE)) * Math.random()), - z: BLOCK_SIZE.z - }, - position: { - x: basePosition.x + localTransform.x, - y: basePosition.y + localTransform.y, - z: basePosition.z + localTransform.z - }, - rotation: Quat.multiply(layerRotation, offsetRot), - collisionsWillMove: true, - damping: DAMPING_FACTOR, - restitution: RESTITUTION, - friction: FRICTION, - angularDamping: ANGULAR_DAMPING_FACTOR, - gravity: GRAVITY, - density: DENSITY - })); - offset += BLOCK_SPACING; - } - } -} +var cogButton = Overlays.addOverlay('image', { + x: getCogButtonPosX(), + y: 10, + width: BUTTON_DIMENSIONS.width, + height: BUTTON_DIMENSIONS.height, + imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg', + alpha: 0.8 +}); function mousePressEvent(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); if (clickedOverlay === button) { - resetBlocks(); + if (!plankyStack.isFound()) { + plankyStack.rez(); + return; + } + editMode = !editMode; + plankyStack.refresh(); + } else if (clickedOverlay === cogButton) { + settingsWindow.webWindow.setVisible(true); } } @@ -134,19 +253,18 @@ Controller.mousePressEvent.connect(mousePressEvent); function cleanup() { Overlays.deleteOverlay(button); + Overlays.deleteOverlay(cogButton); if (ground) { Entities.deleteEntity(ground); } - pieces.forEach(function(piece) { - Entities.deleteEntity(piece); - }); - pieces = []; + plankyStack.deRez(); } function onUpdate() { - if (windowWidth != Window.innerWidth) { + if (windowWidth !== Window.innerWidth) { windowWidth = Window.innerWidth; Overlays.editOverlay(button, {x: getButtonPosX()}); + Overlays.editOverlay(cogButton, {x: getCogButtonPosX()}); } } diff --git a/examples/html/plankySettings.html b/examples/html/plankySettings.html new file mode 100644 index 0000000000..9e2a08c650 --- /dev/null +++ b/examples/html/plankySettings.html @@ -0,0 +1,112 @@ + + + + + + + + +
+ + \ No newline at end of file From 90284b8bb46825aca0aee3bc13969b413af0609b Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 7 Jul 2015 21:33:28 +0200 Subject: [PATCH 002/129] fixes mysterious button display bug --- examples/example/games/planky.js | 41 +++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index cd4a7295be..383e1d57d5 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -40,6 +40,8 @@ var size; var pieces = []; var ground = false; var layerRotated = false; +var button; +var cogButton; SettingsWindow = function() { this.webWindow = null; @@ -217,25 +219,38 @@ function getCogButtonPosX() { return getButtonPosX() - (BUTTON_DIMENSIONS.width * 1.1); } -var button = Overlays.addOverlay('image', { +print(JSON.stringify({ x: getButtonPosX(), y: 10, width: BUTTON_DIMENSIONS.width, height: BUTTON_DIMENSIONS.height, imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/planky_button.svg', alpha: 0.8 -}); +})); -var cogButton = Overlays.addOverlay('image', { - x: getCogButtonPosX(), - y: 10, - width: BUTTON_DIMENSIONS.width, - height: BUTTON_DIMENSIONS.height, - imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg', - alpha: 0.8 -}); +function createButtons() { + button = Overlays.addOverlay('image', { + x: getButtonPosX(), + y: 10, + width: BUTTON_DIMENSIONS.width, + height: BUTTON_DIMENSIONS.height, + imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/planky_button.svg', + alpha: 0.8 + }); -function mousePressEvent(event) { + cogButton = Overlays.addOverlay('image', { + x: getCogButtonPosX(), + y: 10, + width: BUTTON_DIMENSIONS.width, + height: BUTTON_DIMENSIONS.height, + imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg', + alpha: 0.8 + }); +} +// Fixes bug of not showing buttons on startup +Script.setTimeout(createButtons, 1000); + +Controller.mousePressEvent.connect(function(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); if (clickedOverlay === button) { if (!plankyStack.isFound()) { @@ -247,9 +262,7 @@ function mousePressEvent(event) { } else if (clickedOverlay === cogButton) { settingsWindow.webWindow.setVisible(true); } -} - -Controller.mousePressEvent.connect(mousePressEvent); +}); function cleanup() { Overlays.deleteOverlay(button); From c6b3801d0b2b3774678e1b1e2640597f84545f37 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 9 Jul 2015 20:53:09 +0200 Subject: [PATCH 003/129] proper block offset calculations --- examples/example/games/planky.js | 42 ++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index 383e1d57d5..82ae4af9e0 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -83,6 +83,7 @@ PlankyStack = function() { var _this = this; this.planks = []; this.ground = false; + this.editLines = []; this.options = new PlankyOptions(); this.deRez = function() { _this.planks.forEach(function(plank) { @@ -92,7 +93,14 @@ PlankyStack = function() { if (_this.ground) { Entities.deleteEntity(_this.ground); } + this.editLines.forEach(function(line) { + Entities.deleteEntity(line); + }) + if (_this.centerLine) { + Entities.deleteEntity(_this.centerLine); + } _this.ground = false; + _this.centerLine = false; }; this.rez = function() { if (_this.planks.length > 0) { @@ -121,6 +129,20 @@ PlankyStack = function() { // move ground to rez position/rotation Entities.editEntity(_this.ground, {dimensions: _this.options.baseDimension, position: Vec3.sum(_this.basePosition, {y: -(_this.options.baseDimension.y / 2)}), rotation: _this.baseRotation}); } + + var refreshLines = function() { + if (_this.editLines.length === 0) { + _this.editLines.push(Entities.addEntity({ + type: 'Line', + dimensions: {x: 5, y: 21, z: 5}, + position: Vec3.sum(_this.basePosition, {y: -(_this.options.baseDimension.y / 2)}), + lineWidth: 7, + color: {red: 214, green: 91, blue: 67}, + linePoints: [{x: 0, y: 0, z: 0}, {x: 0, y: 10, z: 0}] + })); + return; + } + } var trimDimension = function(dimension, maxIndex) { _this.planks.forEach(function(plank, index, object) { if (plank[dimension] > maxIndex) { @@ -132,13 +154,12 @@ PlankyStack = function() { var createOrUpdate = function(layer, row) { var found = false; var layerRotated = layer % 2 === 0; - var offset = -(_this.options.blockSpacing); - var layerRotation = Quat.fromPitchYawRollDegrees(0, layerRotated ? NO_ANGLE : RIGHT_ANGLE, 0.0); - var blockPositionXZ = (_this.options.blockSize.x * row) - (((_this.options.blockSize.x * _this.options.blocksPerLayer) / 2) - (_this.options.blockSize.x / 2)); + var layerRotation = Quat.fromPitchYawRollDegrees(0, layerRotated ? NO_ANGLE : RIGHT_ANGLE, 0.0); + var blockPositionXZ = ((row - (_this.options.blocksPerLayer / 2) + 0.5) * (_this.options.blockSpacing + _this.options.blockSize.x)); var localTransform = Vec3.multiplyQbyV(_this.offsetRot, { - x: (layerRotated ? blockPositionXZ + offset: 0), + x: (layerRotated ? blockPositionXZ : 0), y: (_this.options.blockSize.y / 2) + (_this.options.blockSize.y * layer), - z: (layerRotated ? 0 : blockPositionXZ + offset) + z: (layerRotated ? 0 : blockPositionXZ) }); var newProperties = { type: 'Model', @@ -173,6 +194,7 @@ PlankyStack = function() { }; this.refresh = function() { refreshGround(); + refreshLines(); trimDimension('layer', _this.options.numLayers); trimDimension('row', _this.options.blocksPerLayer); _this.offsetRot = Quat.multiply(_this.baseRotation, Quat.fromPitchYawRollDegrees(0.0, _this.options.blockYawOffset, 0.0)); @@ -183,7 +205,6 @@ PlankyStack = function() { } if (!editMode) { _this.planks.forEach(function(plank, index, object) { - print(index + " , " + plank); Entities.editEntity(plank.entity, {ignoreForCollisions: false, collisionsWillMove: true}); // Entities.editEntity(plank.entity, {collisionsWillMove: true}); }); @@ -219,15 +240,6 @@ function getCogButtonPosX() { return getButtonPosX() - (BUTTON_DIMENSIONS.width * 1.1); } -print(JSON.stringify({ - x: getButtonPosX(), - y: 10, - width: BUTTON_DIMENSIONS.width, - height: BUTTON_DIMENSIONS.height, - imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/planky_button.svg', - alpha: 0.8 -})); - function createButtons() { button = Overlays.addOverlay('image', { x: getButtonPosX(), From 321447ca6a13292e42f228bf54131f4862f3a28c Mon Sep 17 00:00:00 2001 From: Studio Date: Sun, 12 Jul 2015 14:44:38 -0400 Subject: [PATCH 004/129] Change default value of output buffer size frames to 20 as a default and added functionality to increase to 40. --- libraries/audio-client/src/AudioClient.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index aeea7c07c1..3a85adbc97 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -55,9 +55,9 @@ static const int NUM_AUDIO_CHANNELS = 2; -static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; +static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; -static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; +static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 40; #if defined(Q_OS_ANDROID) || defined(Q_OS_WIN) static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = false; #else From 1f453e07e33e20ccb7cf39bbbbdbe1969466d679 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 14 Jul 2015 02:18:17 +0200 Subject: [PATCH 005/129] connection between planky script and web-window -load settings -include toolbar --- examples/example/games/planky.js | 110 +++++++++------ examples/html/plankySettings.html | 214 ++++++++++++++++-------------- 2 files changed, 183 insertions(+), 141 deletions(-) diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index 82ae4af9e0..60c3b3ad3a 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -12,6 +12,8 @@ // HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; +Script.include("../../libraries/toolBars.js"); + const DEFAULT_NUM_LAYERS = 16; const DEFAULT_BASE_DIMENSION = { x: 7, y: 2, z: 7 }; const DEFAULT_BLOCKS_PER_LAYER = 3; @@ -30,7 +32,7 @@ const DEFAULT_BLOCK_YAW_OFFSET = 45; var editMode = false; -const BUTTON_DIMENSIONS = {width: 49, height: 49}; +const BUTTON_DIMENSIONS = {width: 50, height: 50}; const MAXIMUM_PERCENTAGE = 100.0; const NO_ANGLE = 0; const RIGHT_ANGLE = 90; @@ -42,12 +44,30 @@ var ground = false; var layerRotated = false; var button; var cogButton; +var toolBar; SettingsWindow = function() { + var _this = this; + this.plankyStack = null; this.webWindow = null; - this.init = function() { - this.webWindow = new WebWindow('Planky', Script.resolvePath('../../html/plankySettings.html'), 255, 500, true); - this.webWindow.setVisible(false); + this.init = function(plankyStack) { + _this.webWindow = new WebWindow('Planky', Script.resolvePath('../../html/plankySettings.html'), 255, 500, true); + _this.webWindow.setVisible(false); + _this.webWindow.eventBridge.webEventReceived.connect(_this.onWebEventReceived); + _this.plankyStack = plankyStack; + }; + this.sendData = function(data) { + _this.webWindow.eventBridge.emitScriptEvent(JSON.stringify(data)); + }; + this.onWebEventReceived = function(data) { + data = JSON.parse(data); + switch (data.action) { + case 'loaded': + _this.sendData({action: 'load', options: _this.plankyStack.options.getJSON()}) + break; + default: + Window.alert('unknown action ' + data.action); + } }; }; @@ -59,6 +79,24 @@ PlankyOptions = function() { this.load = function() { //TODO: load Planky Options here. }; + this.getJSON = function() { + return { + numLayers: _this.numLayers, + baseDimension: _this.baseDimension, + blocksPerLayer: _this.blocksPerLayer, + blockSize: _this.blockSize, + blockSpacing: _this.blockSpacing, + blockHeightVariation: _this.blockHeightVariation, + gravity: _this.gravity, + density: _this.density, + dampingFactor: _this.dampingFactor, + angularDampingFactor: _this.angularDampingFactor, + friction: _this.friction, + restitution: _this.restitution, + spawnDistance: _this.spawnDistance, + blockYawOffset: _this.blockYawOffset, + }; + } this.setDefaults = function() { _this.numLayers = DEFAULT_NUM_LAYERS; _this.baseDimension = DEFAULT_BASE_DIMENSION; @@ -74,6 +112,7 @@ PlankyOptions = function() { _this.restitution = DEFAULT_RESTITUTION; _this.spawnDistance = DEFAULT_SPAWN_DISTANCE; _this.blockYawOffset = DEFAULT_BLOCK_YAW_OFFSET; + }; this.setDefaults(); }; @@ -93,7 +132,7 @@ PlankyStack = function() { if (_this.ground) { Entities.deleteEntity(_this.ground); } - this.editLines.forEach(function(line) { + _this.editLines.forEach(function(line) { Entities.deleteEntity(line); }) if (_this.centerLine) { @@ -155,7 +194,7 @@ PlankyStack = function() { var found = false; var layerRotated = layer % 2 === 0; var layerRotation = Quat.fromPitchYawRollDegrees(0, layerRotated ? NO_ANGLE : RIGHT_ANGLE, 0.0); - var blockPositionXZ = ((row - (_this.options.blocksPerLayer / 2) + 0.5) * (_this.options.blockSpacing + _this.options.blockSize.x)); + var blockPositionXZ = (row - (_this.options.blocksPerLayer / 2) + 0.5) * (_this.options.blockSpacing + _this.options.blockSize.x); var localTransform = Vec3.multiplyQbyV(_this.offsetRot, { x: (layerRotated ? blockPositionXZ : 0), y: (_this.options.blockSize.y / 2) + (_this.options.blockSize.y * layer), @@ -217,9 +256,8 @@ PlankyStack = function() { }; var settingsWindow = new SettingsWindow(); -settingsWindow.init(); - var plankyStack = new PlankyStack(); +settingsWindow.init(plankyStack); function grabLowestJointY() { var jointNames = MyAvatar.getJointNames(); @@ -232,66 +270,58 @@ function grabLowestJointY() { return floorY; } -function getButtonPosX() { - return windowWidth - ((BUTTON_DIMENSIONS.width / 2) + BUTTON_DIMENSIONS.width); -} - -function getCogButtonPosX() { - return getButtonPosX() - (BUTTON_DIMENSIONS.width * 1.1); -} - function createButtons() { - button = Overlays.addOverlay('image', { - x: getButtonPosX(), - y: 10, + toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.games.planky", function (windowDimensions, toolbar) { + return { + x: windowDimensions.x - (toolbar.width * 1.1), + y: toolbar.height / 2 + }; + }); + button = toolBar.addTool({ width: BUTTON_DIMENSIONS.width, height: BUTTON_DIMENSIONS.height, imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/planky_button.svg', - alpha: 0.8 + alpha: 0.8, + visible: true }); - cogButton = Overlays.addOverlay('image', { - x: getCogButtonPosX(), - y: 10, + cogButton = toolBar.addTool({ width: BUTTON_DIMENSIONS.width, height: BUTTON_DIMENSIONS.height, imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg', - alpha: 0.8 + alpha: 0.8, + visible: true }); } // Fixes bug of not showing buttons on startup -Script.setTimeout(createButtons, 1000); +Script.setTimeout(createButtons, 2000); Controller.mousePressEvent.connect(function(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - if (clickedOverlay === button) { + if (toolBar.clicked(clickedOverlay) === button) { if (!plankyStack.isFound()) { plankyStack.rez(); return; } editMode = !editMode; plankyStack.refresh(); - } else if (clickedOverlay === cogButton) { + } else if (toolBar.clicked(clickedOverlay) === cogButton) { settingsWindow.webWindow.setVisible(true); } }); - -function cleanup() { - Overlays.deleteOverlay(button); - Overlays.deleteOverlay(cogButton); - if (ground) { - Entities.deleteEntity(ground); - } - plankyStack.deRez(); -} -function onUpdate() { +Script.update.connect(function() { if (windowWidth !== Window.innerWidth) { windowWidth = Window.innerWidth; Overlays.editOverlay(button, {x: getButtonPosX()}); Overlays.editOverlay(cogButton, {x: getCogButtonPosX()}); } -} +}) -Script.update.connect(onUpdate) -Script.scriptEnding.connect(cleanup); +Script.scriptEnding.connect(function() { + toolBar.cleanup(); + if (ground) { + Entities.deleteEntity(ground); + } + plankyStack.deRez(); +}); diff --git a/examples/html/plankySettings.html b/examples/html/plankySettings.html index 9e2a08c650..d5f6f78a71 100644 --- a/examples/html/plankySettings.html +++ b/examples/html/plankySettings.html @@ -1,110 +1,122 @@ - - - + + } + EventBridge.emitWebEvent(JSON.stringify({action: 'loaded'})); + +}); +
From 6d1df036174046d2139702bdf5dc64e882791191 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 14 Jul 2015 03:19:23 +0200 Subject: [PATCH 006/129] planky: load / save settings --- examples/example/games/planky.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index 60c3b3ad3a..abf1e63412 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -74,10 +74,18 @@ SettingsWindow = function() { PlankyOptions = function() { var _this = this; this.save = function() { - //TODO: save Planky Options here. + Settings.setValue('plankyOptions', JSON.stringify(_this.getJSON())); }; this.load = function() { - //TODO: load Planky Options here. + _this.setDefaults(); + var plankyOptions = Settings.getValue('plankyOptions') + if (plankyOptions === null || plankyOptions === '') { + return; + } + var options = JSON.parse(plankyOptions); + options.forEach(function(value, option, object) { + _this[option] = value; + }); }; this.getJSON = function() { return { @@ -112,9 +120,8 @@ PlankyOptions = function() { _this.restitution = DEFAULT_RESTITUTION; _this.spawnDistance = DEFAULT_SPAWN_DISTANCE; _this.blockYawOffset = DEFAULT_BLOCK_YAW_OFFSET; - }; - this.setDefaults(); + this.load(); }; // The PlankyStack exists out of rows and layers From 222234cf1d43576649526cafce4551804f174c26 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 14 Jul 2015 03:40:58 +0200 Subject: [PATCH 007/129] wild planky changes on value change --- examples/example/games/planky.js | 7 +++++++ examples/html/plankySettings.html | 11 +++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index abf1e63412..0849481a61 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -65,6 +65,9 @@ SettingsWindow = function() { case 'loaded': _this.sendData({action: 'load', options: _this.plankyStack.options.getJSON()}) break; + case 'value_change': + _this.plankyStack.onValueChanged(data.option, data.value); + break; default: Window.alert('unknown action ' + data.action); } @@ -238,6 +241,10 @@ PlankyStack = function() { _this.planks.push({layer: layer, row: row, entity: Entities.addEntity(newProperties)}) } }; + this.onValueChanged = function(option, value) { + _this.options[option] = value; + _this.refresh(); + }; this.refresh = function() { refreshGround(); refreshLines(); diff --git a/examples/html/plankySettings.html b/examples/html/plankySettings.html index d5f6f78a71..a5ad2f2939 100644 --- a/examples/html/plankySettings.html +++ b/examples/html/plankySettings.html @@ -38,13 +38,21 @@ PropertyInput = function(key, label, value, attributes) { this.construct(); }; +var valueChangeHandler = function() { + EventBridge.emitWebEvent(JSON.stringify({ + action: 'value_change', + option: $(this).attr('name'), + value: properties[$(this).attr('name')].getValue() + })); +}; + NumberInput = function(key, label, value, attributes) { PropertyInput.call(this, key, label, value, attributes); }; NumberInput.prototype = Object.create(PropertyInput.prototype); NumberInput.prototype.constructor = NumberInput; NumberInput.prototype.createValue = function() { - this.input = $('').attr('name', this.key).attr('type', 'number').val(this.value); + this.input = $('').attr('name', this.key).attr('type', 'number').val(this.value).on('change', valueChangeHandler); if (this.attributes !== undefined) { this.input.attr(this.attributes); } @@ -114,7 +122,6 @@ $(function() { }); } EventBridge.emitWebEvent(JSON.stringify({action: 'loaded'})); - }); From c8453bec671cbec04f7245e6b2878d08900423d2 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 14 Jul 2015 03:50:06 +0200 Subject: [PATCH 008/129] planky: fix layer setting, restraints on values --- examples/html/plankySettings.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/html/plankySettings.html b/examples/html/plankySettings.html index a5ad2f2939..b357e83792 100644 --- a/examples/html/plankySettings.html +++ b/examples/html/plankySettings.html @@ -91,23 +91,23 @@ function addHeader(label) { $(function() { addHeader('Stack Settings'); - properties['numLayers'] = new NumberInput('layers', 'Layers', 17, {'min': 0, 'max': 300, 'step': 1}); + properties['numLayers'] = new NumberInput('numLayers', 'Layers', 17, {'min': 0, 'max': 300, 'step': 1}); properties['baseDimension'] = new CoordinateInput('baseDimension', 'Base dimension', {x: 7, y: 2, z: 7}); - properties['blocksPerLayer'] = new NumberInput('blocksPerLayer', 'Blocks per layer', 4); + properties['blocksPerLayer'] = new NumberInput('blocksPerLayer', 'Blocks per layer', 4, {'min': 1, 'max': 100, 'step': 1}); properties['blockSize'] = new CoordinateInput('blockSize', 'Block size', {x: 0.2, y: 0.1, z: 0.8}); properties['blockSpacing'] = new NumberInput('blockSpacing', 'Block spacing', properties['blockSize'].getValue().x / properties['blocksPerLayer'].getValue()); properties['blockSpacing'].addButton('btn-recalculate-spacing', 'Recalculate spacing'); $('#btn-recalculate-spacing').on('click', function() { properties['blockSpacing'].setValue(properties['blockSize'].getValue().x / properties['blocksPerLayer'].getValue()); }); - properties['blockHeightVariation'] = new NumberInput('blockHeightVariation', 'Block height variation (%)', 0.1); + properties['blockHeightVariation'] = new NumberInput('blockHeightVariation', 'Block height variation (%)', 0.1, {'min': 0, 'max': 1, 'step': 0.01}); addHeader('Physics Settings'); properties['gravity'] = new CoordinateInput('gravity', 'Gravity', {x: 0, y: -2.8, z: 0}); - properties['density'] = new NumberInput('density', 'Density', 4000); - properties['dampingFactor'] = new NumberInput('dampingFactor', 'Damping factor', 0.98); - properties['angularDampingFactor'] = new NumberInput('angularDampingFactor', 'Angular damping factor', 0.8); - properties['friction'] = new NumberInput('friction', 'Friction', 0.99); - properties['restitution'] = new NumberInput('restitution', 'Restitution', 0.0); + properties['density'] = new NumberInput('density', 'Density', 4000, {'min': 0, 'max': 4000, 'step': 1}); + properties['dampingFactor'] = new NumberInput('dampingFactor', 'Damping factor', 0.98, {'min': 0, 'max': 1, 'step': 0.01}); + properties['angularDampingFactor'] = new NumberInput('angularDampingFactor', 'Angular damping factor', 0.8, {'min': 0, 'max': 1, 'step': 0.01}); + properties['friction'] = new NumberInput('friction', 'Friction', 0.99, {'min': 0, 'max': 1, 'step': 0.01}); + properties['restitution'] = new NumberInput('restitution', 'Restitution', 0.0, {'min': 0, 'max': 1, 'step': 0.01}); addHeader('Spawn Settings'); properties['spawnDistance'] = new NumberInput('spawnDistance', 'Spawn distance (meters)', 3); properties['blockYawOffset'] = new NumberInput('blockYawOffset', 'Block yaw offset (degrees)', 45, {'min': 0, 'max': 360, 'step': 1}); From 95948851f1427767e2a8372153a70064aa4d3dda Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 14 Jul 2015 04:36:29 +0200 Subject: [PATCH 009/129] save, clear and reset button --- examples/html/plankySettings.html | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/examples/html/plankySettings.html b/examples/html/plankySettings.html index b357e83792..0a79df6c7b 100644 --- a/examples/html/plankySettings.html +++ b/examples/html/plankySettings.html @@ -5,6 +5,9 @@ From b7110227963d187aca08cfe06de26501c0243546 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 14 Jul 2015 12:28:49 +0200 Subject: [PATCH 010/129] planky: - removed workaround for delayed overlay loading - make buttons functional (reset, cleanup, save-default) - only show live changes for the visual planky properties: blocksize , numLayers etc. (no physical properties) --- examples/example/games/planky.js | 74 +++++++++++++++++++------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index 0849481a61..5232201449 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -68,14 +68,28 @@ SettingsWindow = function() { case 'value_change': _this.plankyStack.onValueChanged(data.option, data.value); break; + case 'factory-reset': + _this.plankyStack.options.factoryReset(); + _this.sendData({action: 'load', options: _this.plankyStack.options.getJSON()}) + break; + case 'save-default': + _this.plankyStack.options.save(); + break; + case 'cleanup': + _this.plankyStack.deRez(); + break; default: - Window.alert('unknown action ' + data.action); + Window.alert('[planky] unknown action ' + data.action); } }; }; PlankyOptions = function() { var _this = this; + this.factoryReset = function() { + _this.setDefaults(); + Settings.setValue('plankyOptions', ''); + }; this.save = function() { Settings.setValue('plankyOptions', JSON.stringify(_this.getJSON())); }; @@ -86,9 +100,9 @@ PlankyOptions = function() { return; } var options = JSON.parse(plankyOptions); - options.forEach(function(value, option, object) { - _this[option] = value; - }); + for (option in options) { + _this[option] = options[option]; + } }; this.getJSON = function() { return { @@ -147,9 +161,10 @@ PlankyStack = function() { }) if (_this.centerLine) { Entities.deleteEntity(_this.centerLine); - } + } _this.ground = false; _this.centerLine = false; + _this.editLines = []; }; this.rez = function() { if (_this.planks.length > 0) { @@ -243,7 +258,9 @@ PlankyStack = function() { }; this.onValueChanged = function(option, value) { _this.options[option] = value; - _this.refresh(); + if (['numLayers', 'blocksPerLayer', 'blockSize', 'blockSpacing', 'blockHeightVariation'].indexOf(option) !== -1) { + _this.refresh(); + } }; this.refresh = function() { refreshGround(); @@ -284,31 +301,28 @@ function grabLowestJointY() { return floorY; } -function createButtons() { - toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.games.planky", function (windowDimensions, toolbar) { - return { - x: windowDimensions.x - (toolbar.width * 1.1), - y: toolbar.height / 2 - }; - }); - button = toolBar.addTool({ - width: BUTTON_DIMENSIONS.width, - height: BUTTON_DIMENSIONS.height, - imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/planky_button.svg', - alpha: 0.8, - visible: true - }); +toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.games.planky", function (windowDimensions, toolbar) { + return { + x: windowDimensions.x - (toolbar.width * 1.1), + y: toolbar.height / 2 + }; +}); - cogButton = toolBar.addTool({ - width: BUTTON_DIMENSIONS.width, - height: BUTTON_DIMENSIONS.height, - imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg', - alpha: 0.8, - visible: true - }); -} -// Fixes bug of not showing buttons on startup -Script.setTimeout(createButtons, 2000); +button = toolBar.addTool({ + width: BUTTON_DIMENSIONS.width, + height: BUTTON_DIMENSIONS.height, + imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/planky_button.svg', + alpha: 0.8, + visible: true +}); + +cogButton = toolBar.addTool({ + width: BUTTON_DIMENSIONS.width, + height: BUTTON_DIMENSIONS.height, + imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg', + alpha: 0.8, + visible: true +}); Controller.mousePressEvent.connect(function(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); From fac497dadc139f3c1e649178c1ccf2fc2c0e4e14 Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Tue, 14 Jul 2015 15:31:56 +0200 Subject: [PATCH 011/129] Removed the file where the directory is stripped off the RelativeFilename, and replace \ with /. However this introduces a new problem with the current fbx files who do not have their textures in the original dir but moved it to the dir where the fbx file lives. Suppose there should be some logic when the texture is not found to look if the texture lives in the dir above the RelativeFilename. In any case it is not obvious when there is a texture missing on a model, it simply renders black. --- libraries/fbx/src/FBXReader.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 236e2979f5..24cbc983ed 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1781,9 +1781,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, TextureParam tex; foreach (const FBXNode& subobject, object.children) { if (subobject.name == "RelativeFilename") { - // trim off any path information QByteArray filename = subobject.properties.at(0).toByteArray(); - filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); + filename = filename.replace('\\', '/'); textureFilenames.insert(getID(object.properties), filename); } else if (subobject.name == "TextureName") { // trim the name from the timestamp From 6926ae9aa3bcdb474360a89dff4f01ba24dbd5cd Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 14 Jul 2015 20:27:51 +0200 Subject: [PATCH 012/129] small planky improvements --- examples/example/games/planky.js | 19 +++++++++++++------ examples/html/plankySettings.html | 21 +++++++++++---------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index 5232201449..6733749317 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -65,7 +65,7 @@ SettingsWindow = function() { case 'loaded': _this.sendData({action: 'load', options: _this.plankyStack.options.getJSON()}) break; - case 'value_change': + case 'value-change': _this.plankyStack.onValueChanged(data.option, data.value); break; case 'factory-reset': @@ -148,6 +148,7 @@ PlankyStack = function() { this.ground = false; this.editLines = []; this.options = new PlankyOptions(); + this.deRez = function() { _this.planks.forEach(function(plank) { Entities.deleteEntity(plank.entity); @@ -159,13 +160,14 @@ PlankyStack = function() { _this.editLines.forEach(function(line) { Entities.deleteEntity(line); }) + _this.editLines = []; if (_this.centerLine) { Entities.deleteEntity(_this.centerLine); } _this.ground = false; _this.centerLine = false; - _this.editLines = []; }; + this.rez = function() { if (_this.planks.length > 0) { _this.deRez(); @@ -192,7 +194,7 @@ PlankyStack = function() { } // move ground to rez position/rotation Entities.editEntity(_this.ground, {dimensions: _this.options.baseDimension, position: Vec3.sum(_this.basePosition, {y: -(_this.options.baseDimension.y / 2)}), rotation: _this.baseRotation}); - } + }; var refreshLines = function() { if (_this.editLines.length === 0) { @@ -206,7 +208,8 @@ PlankyStack = function() { })); return; } - } + }; + var trimDimension = function(dimension, maxIndex) { _this.planks.forEach(function(plank, index, object) { if (plank[dimension] > maxIndex) { @@ -215,6 +218,7 @@ PlankyStack = function() { } }); }; + var createOrUpdate = function(layer, row) { var found = false; var layerRotated = layer % 2 === 0; @@ -256,17 +260,19 @@ PlankyStack = function() { _this.planks.push({layer: layer, row: row, entity: Entities.addEntity(newProperties)}) } }; + this.onValueChanged = function(option, value) { _this.options[option] = value; if (['numLayers', 'blocksPerLayer', 'blockSize', 'blockSpacing', 'blockHeightVariation'].indexOf(option) !== -1) { _this.refresh(); } }; + this.refresh = function() { refreshGround(); refreshLines(); - trimDimension('layer', _this.options.numLayers); - trimDimension('row', _this.options.blocksPerLayer); + trimDimension('layer', _this.options.numLayers - 1); + trimDimension('row', _this.options.blocksPerLayer - 1); _this.offsetRot = Quat.multiply(_this.baseRotation, Quat.fromPitchYawRollDegrees(0.0, _this.options.blockYawOffset, 0.0)); for (var layer = 0; layer < _this.options.numLayers; layer++) { for (var row = 0; row < _this.options.blocksPerLayer; row++) { @@ -280,6 +286,7 @@ PlankyStack = function() { }); } }; + this.isFound = function() { //TODO: identify entities here until one is found return _this.planks.length > 0; diff --git a/examples/html/plankySettings.html b/examples/html/plankySettings.html index 0a79df6c7b..0eea4948ad 100644 --- a/examples/html/plankySettings.html +++ b/examples/html/plankySettings.html @@ -42,10 +42,11 @@ PropertyInput = function(key, label, value, attributes) { }; var valueChangeHandler = function() { + sendWebEvent({ - action: 'value_change', - option: $(this).attr('name'), - value: properties[$(this).attr('name')].getValue() + action: 'value-change', + option: $(this).data('var-name'), + value: properties[$(this).data('var-name')].getValue() }); }; @@ -55,14 +56,14 @@ NumberInput = function(key, label, value, attributes) { NumberInput.prototype = Object.create(PropertyInput.prototype); NumberInput.prototype.constructor = NumberInput; NumberInput.prototype.createValue = function() { - this.input = $('').attr('name', this.key).attr('type', 'number').val(this.value).on('change', valueChangeHandler); + this.input = $('').data('var-name', this.key).attr('name', this.key).attr('type', 'number').val(this.value).on('change', valueChangeHandler); if (this.attributes !== undefined) { this.input.attr(this.attributes); } return this.input; }; NumberInput.prototype.getValue = function() { - return this.input.val(); + return parseFloat(this.input.val()); }; CoordinateInput = function(key, label, value, attributes) { @@ -71,9 +72,9 @@ CoordinateInput = function(key, label, value, attributes) { CoordinateInput.prototype = Object.create(PropertyInput.prototype); CoordinateInput.prototype.constructor = CoordinateInput; CoordinateInput.prototype.createValue = function() { - this.inputX = $('').attr('name', this.key + '-x').attr('type', 'number').addClass('coord').val(this.value.x); - this.inputY = $('').attr('name', this.key + '-y').attr('type', 'number').addClass('coord').val(this.value.y); - this.inputZ = $('').attr('name', this.key + '-z').attr('type', 'number').addClass('coord').val(this.value.z); + this.inputX = $('').data('var-name', this.key).attr('name', this.key + '-x').attr('type', 'number').addClass('coord').val(this.value.x).on('change', valueChangeHandler); + this.inputY = $('').data('var-name', this.key).attr('name', this.key + '-y').attr('type', 'number').addClass('coord').val(this.value.y).on('change', valueChangeHandler); + this.inputZ = $('').data('var-name', this.key).attr('name', this.key + '-z').attr('type', 'number').addClass('coord').val(this.value.z).on('change', valueChangeHandler); if (this.attributes !== undefined) { this.inputX.attr(this.attributes); this.inputY.attr(this.attributes); @@ -82,7 +83,7 @@ CoordinateInput.prototype.createValue = function() { return [encapsulateInput(this.inputX, 'X'), encapsulateInput(this.inputY, 'Y'), encapsulateInput(this.inputZ, 'Z')]; }; CoordinateInput.prototype.getValue = function() { - return {x: this.inputX.val(), y: this.inputY.val(), z: this.inputZ.val()}; + return {x: parseFloat(this.inputX.val()), y: parseFloat(this.inputY.val()), z: parseFloat(this.inputZ.val())}; }; function encapsulateInput(input, label) { return $('
').addClass('input-area').append(label + ' ').append(input); @@ -95,7 +96,6 @@ function addHeader(label) { $(function() { addHeader('Stack Settings'); properties['numLayers'] = new NumberInput('numLayers', 'Layers', 17, {'min': 0, 'max': 300, 'step': 1}); - properties['baseDimension'] = new CoordinateInput('baseDimension', 'Base dimension', {x: 7, y: 2, z: 7}, {'min': 0.5, 'max': 200, 'step': 0.1}); properties['blocksPerLayer'] = new NumberInput('blocksPerLayer', 'Blocks per layer', 4, {'min': 1, 'max': 100, 'step': 1}); properties['blockSize'] = new CoordinateInput('blockSize', 'Block size', {x: 0.2, y: 0.1, z: 0.8}, {'min': 0.05, 'max': 20, 'step': 0.1}); properties['blockSpacing'] = new NumberInput('blockSpacing', 'Block spacing', properties['blockSize'].getValue().x / properties['blocksPerLayer'].getValue(), {'min': 0, 'max': 20, 'step': 0.01}); @@ -114,6 +114,7 @@ $(function() { addHeader('Spawn Settings'); properties['spawnDistance'] = new NumberInput('spawnDistance', 'Spawn distance (meters)', 3); properties['blockYawOffset'] = new NumberInput('blockYawOffset', 'Block yaw offset (degrees)', 45, {'min': 0, 'max': 360, 'step': 1}); + properties['baseDimension'] = new CoordinateInput('baseDimension', 'Base dimension', {x: 7, y: 2, z: 7}, {'min': 0.5, 'max': 200, 'step': 0.1}); addHeader('Actions'); $('#properties-list') .append($('').val('factory reset').attr('type', 'button').on('click', function() { sendWebEvent({action: 'factory-reset'}); })) From 1b13f837bd052cdc9441aff87795c89cb5b237f7 Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Wed, 15 Jul 2015 14:10:17 -0700 Subject: [PATCH 013/129] Porting AO to new pipeline --- interface/src/Application.cpp | 10 +- .../src/AmbientOcclusionEffect.cpp | 121 ++++++++++++++---- .../render-utils/src/AmbientOcclusionEffect.h | 36 +++++- .../render-utils/src/RenderDeferredTask.cpp | 4 + .../render-utils/src/ambient_occlusion.slf | 22 ++++ .../render-utils/src/ambient_occlusion.slv | 25 ++++ 6 files changed, 179 insertions(+), 39 deletions(-) create mode 100644 libraries/render-utils/src/ambient_occlusion.slf create mode 100644 libraries/render-utils/src/ambient_occlusion.slv diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 00a4440920..51aec20481 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2154,7 +2154,6 @@ void Application::init() { _environment.init(); DependencyManager::get()->init(this); - DependencyManager::get()->init(this); // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager DependencyManager::get()->init(); @@ -3479,14 +3478,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderArgs->_debugFlags = renderDebugFlags; _entities.render(renderArgs); } - - // render the ambient occlusion effect if enabled - if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) { - PerformanceTimer perfTimer("ambientOcclusion"); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... AmbientOcclusion..."); - DependencyManager::get()->render(); - } } // Make sure the WorldBox is in the scene @@ -3564,6 +3555,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se sceneInterface->setEngineFeedOverlay3DItems(engineRC->_numFeedOverlay3DItems); sceneInterface->setEngineDrawnOverlay3DItems(engineRC->_numDrawnOverlay3DItems); } + //Render the sixense lasers if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { _myAvatar->renderLaserPointers(*renderArgs->_batch); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index f58419ec6e..82034cad12 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -25,12 +25,17 @@ #include "ProgramObject.h" #include "RenderUtil.h" #include "TextureCache.h" +#include "DependencyManager.h" +#include "ViewFrustum.h" + +#include "ambient_occlusion_vert.h" +#include "ambient_occlusion_frag.h" const int ROTATION_WIDTH = 4; const int ROTATION_HEIGHT = 4; void AmbientOcclusionEffect::init(AbstractViewStateInterface* viewState) { - _viewState = viewState; // we will use this for view state services + /*_viewState = viewState; // we will use this for view state services _occlusionProgram = new ProgramObject(); _occlusionProgram->addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() @@ -93,27 +98,27 @@ void AmbientOcclusionEffect::init(AbstractViewStateInterface* viewState) { _blurProgram->setUniformValue("originalTexture", 0); _blurProgram->release(); - _blurScaleLocation = _blurProgram->uniformLocation("blurScale"); + _blurScaleLocation = _blurProgram->uniformLocation("blurScale");*/ } -void AmbientOcclusionEffect::render() { - glDisable(GL_BLEND); +void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext){ + /*glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimaryDepthTextureID()); - + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, _rotationTextureID); - + // render with the occlusion shader to the secondary/tertiary buffer auto freeFramebuffer = DependencyManager::get()->getFreeFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(freeFramebuffer)); - + float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; - _viewState->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - + AbstractViewStateInterface::instance()->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); const int VIEWPORT_X_INDEX = 0; @@ -122,7 +127,7 @@ void AmbientOcclusionEffect::render() { auto framebufferSize = DependencyManager::get()->getFrameBufferSize(); float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width(); float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width(); - + _occlusionProgram->bind(); _occlusionProgram->setUniformValue(_nearLocation, nearVal); _occlusionProgram->setUniformValue(_farLocation, farVal); @@ -132,37 +137,107 @@ void AmbientOcclusionEffect::render() { framebufferSize.height() / (float)ROTATION_HEIGHT); _occlusionProgram->setUniformValue(_texCoordOffsetLocation, sMin, 0.0f); _occlusionProgram->setUniformValue(_texCoordScaleLocation, sWidth, 1.0f); - + renderFullscreenQuad(); - + _occlusionProgram->release(); - + glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); - + glActiveTexture(GL_TEXTURE0); - + // now render secondary to primary with 4x4 blur auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); glEnable(GL_BLEND); glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE); - + auto freeFramebufferTexture = freeFramebuffer->getRenderBuffer(0); glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(freeFramebufferTexture)); - + _blurProgram->bind(); _blurProgram->setUniformValue(_blurScaleLocation, 1.0f / framebufferSize.width(), 1.0f / framebufferSize.height()); - + renderFullscreenQuad(sMin, sMin + sWidth); - + _blurProgram->release(); - + glBindTexture(GL_TEXTURE_2D, 0); - + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); + glDepthMask(GL_TRUE);*/ } + + +AmbientOcclusion::AmbientOcclusion() { +} + +const gpu::PipelinePointer& AmbientOcclusion::getAOPipeline() { + if (!_AOPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(ambient_occlusion_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(ambient_occlusion_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + //_drawItemBoundPosLoc = program->getUniforms().findLocation("inBoundPos"); + //_drawItemBoundDimLoc = program->getUniforms().findLocation("inBoundDim"); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(true, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + + // Good to go add the brand new pipeline + _AOPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _AOPipeline; +} + +void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { + + // create a simple pipeline that does: + + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + RenderArgs* args = renderContext->args; + auto& scene = sceneContext->_scene; + + // Allright, something to render let's do it + gpu::Batch batch; + + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + batch.setModelTransform(Transform()); + + // bind the one gpu::Pipeline we need + batch.setPipeline(getAOPipeline()); + + //renderFullscreenQuad(); + + args->_context->syncCache(); + renderContext->args->_context->syncCache(); + args->_context->render((batch)); + + // need to fetch forom the z buffer and render something in a new render target a result that combine the z and produce a fake AO result + + + +} + diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index c7acb90133..fbe4a09214 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -14,23 +14,30 @@ #include +#include "render/DrawTask.h" + class AbstractViewStateInterface; class ProgramObject; /// A screen space ambient occlusion effect. See John Chapman's tutorial at /// http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html for reference. + class AmbientOcclusionEffect : public Dependency { SINGLETON_DEPENDENCY - + public: - + void init(AbstractViewStateInterface* viewState); - void render(); - -private: + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + typedef render::Job::Model JobModel; + + AmbientOcclusionEffect() {} virtual ~AmbientOcclusionEffect() {} +private: + ProgramObject* _occlusionProgram; int _nearLocation; int _farLocation; @@ -39,12 +46,27 @@ private: int _noiseScaleLocation; int _texCoordOffsetLocation; int _texCoordScaleLocation; - + ProgramObject* _blurProgram; int _blurScaleLocation; - + GLuint _rotationTextureID; AbstractViewStateInterface* _viewState; }; +class AmbientOcclusion { +public: + + AmbientOcclusion(); + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + typedef render::Job::Model JobModel; + + const gpu::PipelinePointer& AmbientOcclusion::getAOPipeline(); + +private: + + gpu::PipelinePointer _AOPipeline; +}; + #endif // hifi_AmbientOcclusionEffect_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 55f4f72574..e4740cc8de 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -18,6 +18,7 @@ #include "TextureCache.h" #include "render/DrawStatus.h" +#include "AmbientOcclusionEffect.h" #include @@ -71,10 +72,13 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput()))); _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques))); + + _jobs.back().setEnabled(false); _drawStatusJobIndex = _jobs.size() - 1; _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); + _jobs.push_back(Job(new AmbientOcclusion::JobModel("AmbientOcclusion"))); _jobs.push_back(Job(new ResetGLState::JobModel())); // Give ourselves 3 frmaes of timer queries diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf new file mode 100644 index 0000000000..67cf9d3c53 --- /dev/null +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -0,0 +1,22 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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 +// + +<@include DeferredBufferWrite.slh@> + +// the interpolated normal +//varying vec4 interpolatedNormal; + +void main(void) { + gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0); +} diff --git a/libraries/render-utils/src/ambient_occlusion.slv b/libraries/render-utils/src/ambient_occlusion.slv new file mode 100644 index 0000000000..702b1bd59e --- /dev/null +++ b/libraries/render-utils/src/ambient_occlusion.slv @@ -0,0 +1,25 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple.vert +// vertex shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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 +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +// the interpolated normal +//varying vec4 interpolatedNormal; + +void main(void) { + //gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = gl_Vertex; +} \ No newline at end of file From b93ae7b5273dcf305fc9ebdc5e57b7b3261641e2 Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Wed, 15 Jul 2015 19:25:18 -0400 Subject: [PATCH 014/129] Move reload content item to developer menu. --- interface/src/Menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8b14830c2d..6fe3a4dff9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -255,8 +255,6 @@ Menu::Menu() { avatar, SLOT(updateMotionBehavior())); MenuWrapper* viewMenu = addMenu("View"); - - addActionToQMenuAndActionHash(viewMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Fullscreen, @@ -329,6 +327,8 @@ Menu::Menu() { MenuWrapper* developerMenu = addMenu("Developer"); + addActionToQMenuAndActionHash(developerMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); + MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, 0, // QML Qt::SHIFT | Qt::Key_A, From 671263909a6db098f1f28c49d828682e7b9acbfb Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Wed, 15 Jul 2015 19:47:37 -0400 Subject: [PATCH 015/129] Moved reload content item to nested Network menu item. --- interface/src/Menu.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6fe3a4dff9..7315c02825 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -327,8 +327,6 @@ Menu::Menu() { MenuWrapper* developerMenu = addMenu("Developer"); - addActionToQMenuAndActionHash(developerMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); - MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, 0, // QML Qt::SHIFT | Qt::Key_A, @@ -491,6 +489,7 @@ Menu::Menu() { #endif MenuWrapper* networkMenu = developerMenu->addMenu("Network"); + addActionToQMenuAndActionHash(networkMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableNackPackets, 0, false); addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableActivityLogger, From 022529f03f967216c83fc649262df07dbfce0986 Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Thu, 16 Jul 2015 09:46:28 -0700 Subject: [PATCH 016/129] Render depth buffer to quad Useful for graphics debugging --- .../src/AmbientOcclusionEffect.cpp | 13 ++++++++++--- .../render-utils/src/RenderDeferredTask.cpp | 4 +++- .../render-utils/src/ambient_occlusion.slf | 18 ++++++++++++++---- .../render-utils/src/ambient_occlusion.slv | 9 +++++---- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 82034cad12..07832179cc 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -27,6 +27,7 @@ #include "TextureCache.h" #include "DependencyManager.h" #include "ViewFrustum.h" +#include "GeometryCache.h" #include "ambient_occlusion_vert.h" #include "ambient_occlusion_frag.h" @@ -190,10 +191,10 @@ const gpu::PipelinePointer& AmbientOcclusion::getAOPipeline() { gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setDepthTest(false, false, gpu::LESS_EQUAL); // Blend on transparent - state->setBlendFunction(true, + state->setBlendFunction(false, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); @@ -225,11 +226,17 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); + batch.setResourceTexture(0, DependencyManager::get()->getPrimaryDepthTexture()); // bind the one gpu::Pipeline we need batch.setPipeline(getAOPipeline()); - //renderFullscreenQuad(); + glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); + glm::vec2 bottomLeft(0.5f, -1.0f); + glm::vec2 topRight(1.0f, -0.5f); + glm::vec2 texCoordTopLeft(0.0f, 0.0f); + glm::vec2 texCoordBottomRight(1.0f, 1.0f); + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); args->_context->syncCache(); renderContext->args->_context->syncCache(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index e9a5689747..5b4d8e9d4f 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -59,6 +59,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new ResetGLState::JobModel())); _jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred"))); _jobs.push_back(Job(new ResolveDeferred::JobModel("ResolveDeferred"))); + _jobs.push_back(Job(new AmbientOcclusion::JobModel("AmbientOcclusion"))); _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", FetchItems( ItemFilter::Builder::transparentShape().withoutLayered(), @@ -77,8 +78,9 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.back().setEnabled(false); _drawStatusJobIndex = _jobs.size() - 1; + //_jobs.push_back(Job(new AmbientOcclusion::JobModel("AmbientOcclusion"))); _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); - _jobs.push_back(Job(new AmbientOcclusion::JobModel("AmbientOcclusion"))); + _jobs.push_back(Job(new ResetGLState::JobModel())); // Give ourselves 3 frmaes of timer queries diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index 67cf9d3c53..b56e0eb9d5 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -2,11 +2,11 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// simple.frag +// ambient_occlusion.frag // fragment shader // -// Created by Andrzej Kapolka on 9/15/14. -// Copyright 2014 High Fidelity, Inc. +// Created by Niraj Venkat on 7/15/15. +// Copyright 2015 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 @@ -17,6 +17,16 @@ // the interpolated normal //varying vec4 interpolatedNormal; +varying vec2 varTexcoord; + +uniform sampler2D depthTexture; + void main(void) { - gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0); + vec4 depthColor = texture2D(depthTexture, varTexcoord.xy); + float z = depthColor.r; // fetch the z-value from our depth texture + float n = 1.0; // the near plane + float f = 30.0; // the far plane + float c = (2.0 * n) / (f + n - z * (f - n)); // convert to linear values + + gl_FragColor = vec4(c, c, c, 1.0); } diff --git a/libraries/render-utils/src/ambient_occlusion.slv b/libraries/render-utils/src/ambient_occlusion.slv index 702b1bd59e..54cc608129 100644 --- a/libraries/render-utils/src/ambient_occlusion.slv +++ b/libraries/render-utils/src/ambient_occlusion.slv @@ -2,11 +2,11 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// simple.vert +// ambient_occlusion.vert // vertex shader // -// Created by Andrzej Kapolka on 9/15/14. -// Copyright 2014 High Fidelity, Inc. +// Created by Niraj Venkat on 7/15/15. +// Copyright 2015 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 @@ -18,8 +18,9 @@ // the interpolated normal //varying vec4 interpolatedNormal; +varying vec2 varTexcoord; void main(void) { - //gl_TexCoord[0] = gl_MultiTexCoord0; + varTexcoord = gl_MultiTexCoord0.xy; gl_Position = gl_Vertex; } \ No newline at end of file From 9c8e01f3ff64d1401a5706b2c27b644235000753 Mon Sep 17 00:00:00 2001 From: Bing Shearer Date: Fri, 17 Jul 2015 16:10:34 -0700 Subject: [PATCH 017/129] New falling leaf script based on the existing rain.js --- examples/leaves.js | 291 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100755 examples/leaves.js diff --git a/examples/leaves.js b/examples/leaves.js new file mode 100755 index 0000000000..347371ff5b --- /dev/null +++ b/examples/leaves.js @@ -0,0 +1,291 @@ +// +// Leaves.js +// examples +// +// Created by Bing Shearer on 14 Jul 2015 +// Copyright 2015 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 +// +var leafName = "scriptLeaf"; +var leafSquall = function (properties) { + var // Properties + squallOrigin, + squallRadius, + leavesPerMinute = 60, + leafSize = { x: 0.1, y: 0.1, z: 0.1 }, + leafFallSpeed = 1, // m/s + leafLifetime = 60, // Seconds + leafSpinMax = 0, // Maximum angular velocity per axis; deg/s + debug = false, // Display origin circle; don't use running on Stack Manager + // Other + squallCircle, + SQUALL_CIRCLE_COLOR = { red: 255, green: 0, blue: 0 }, + SQUALL_CIRCLE_ALPHA = 0.5, + SQUALL_CIRCLE_ROTATION = Quat.fromPitchYawRollDegrees(90, 0, 0), + leafProperties, + leaf_MODEL_URL = "https://hifi-public.s3.amazonaws.com/ozan/support/forBing/palmLeaf.fbx", + leafTimer, + leaves = [], // HACK: Work around leaves not always getting velocities + leafVelocities = [], // HACK: Work around leaves not always getting velocities + DEGREES_TO_RADIANS = Math.PI / 180, + leafDeleteOnTearDown = true, + maxLeaves, + leafCount, + nearbyEntities, + complexMovement = false, + movementTime = 0, + maxSpinRadians = properties.leafSpinMax * DEGREES_TO_RADIANS, + windFactor, + leafDeleteOnGround = false, + floorHeight = null; + + + function processProperties() { + if (!properties.hasOwnProperty("origin")) { + print("ERROR: Leaf squall origin must be specified"); + return; + } + squallOrigin = properties.origin; + + if (!properties.hasOwnProperty("radius")) { + print("ERROR: Leaf squall radius must be specified"); + return; + } + squallRadius = properties.radius; + + if (properties.hasOwnProperty("leavesPerMinute")) { + leavesPerMinute = properties.leavesPerMinute; + } + + if (properties.hasOwnProperty("leafSize")) { + leafSize = properties.leafSize; + } + + if (properties.hasOwnProperty("leafFallSpeed")) { + leafFallSpeed = properties.leafFallSpeed; + } + + if (properties.hasOwnProperty("leafLifetime")) { + leafLifetime = properties.leafLifetime; + } + + if (properties.hasOwnProperty("leafSpinMax")) { + leafSpinMax = properties.leafSpinMax; + } + + if (properties.hasOwnProperty("debug")) { + debug = properties.debug; + } + if (properties.hasOwnProperty("floorHeight")) { + floorHeight = properties.floorHeight; + } + if (properties.hasOwnProperty("maxLeaves")) { + maxLeaves = properties.maxLeaves; + } + if (properties.hasOwnProperty("complexMovement")) { + complexMovement = properties.complexMovement; + } + if (properties.hasOwnProperty("leafDeleteOnGround")) { + leafDeleteOnGround = properties.leafDeleteOnGround; + } + if (properties.hasOwnProperty("windFactor")) { + windFactor = properties.windFactor; + } + else { + print("ERROR: Wind Factor must be defined for complex movement") + } + + leafProperties = { + type: "Model", + name: leafName, + modelURL: leaf_MODEL_URL, + lifetime: leafLifetime, + dimensions: leafSize, + velocity: { x: 0, y: -leafFallSpeed, z: 0 }, + damping: 0, + angularDamping: 0, + ignoreForCollisions: true + + }; + } + + function createleaf() { + var angle, + radius, + offset, + leaf, + spin = { x: 0, y: 0, z: 0 }, + i; + + // HACK: Work around leaves not always getting velocities set at creation + for (i = 0; i < leaves.length; i += 1) { + Entities.editEntity(leaves[i], leafVelocities[i]); + } + + angle = Math.random() * 10; + radius = Math.random() * squallRadius; + offset = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, angle, 0), { x: 0, y: -0.1, z: radius }); + leafProperties.position = Vec3.sum(squallOrigin, offset); + if (properties.leafSpinMax > 0 && !complexMovement) { + spin = { + x: Math.random() * maxSpinRadians, + y: Math.random() * maxSpinRadians, + z: Math.random() * maxSpinRadians + }; + leafProperties.angularVelocity = spin; + } + else if (complexMovement) { + spin = { x: 0, y: 0, z: 0 }; + leafProperties.angularVelocity = spin + } + leaf = Entities.addEntity(leafProperties); + + // HACK: Work around leaves not always getting velocities set at creation + leaves.push(leaf); + leafVelocities.push({ + velocity: leafProperties.velocity, + angularVelocity: spin + }); + if (leaves.length > 5) { + leaves.shift(); + leafVelocities.shift(); + } + } + + function setUp() { + if (debug) { + squallCircle = Overlays.addOverlay("circle3d", { + size: { x: 2 * squallRadius, y: 2 * squallRadius }, + color: SQUALL_CIRCLE_COLOR, + alpha: SQUALL_CIRCLE_ALPHA, + solid: true, + visible: debug, + position: squallOrigin, + rotation: SQUALL_CIRCLE_ROTATION + }); + } + + leafTimer = Script.setInterval(function () { + if (leafCount <= maxLeaves - 1) { + createleaf() + } + }, 60000 / leavesPerMinute); + } + Script.setInterval(function () { + nearbyEntities = Entities.findEntities(squallOrigin, squallRadius); + newLeafMovement() + }, 100); + + function newLeafMovement() { //new additions to leaf code. Operates at 10 Hz or every 100 ms + movementTime += 0.1; + var currentLeaf, + randomRotationSpeed = { + x: maxSpinRadians * Math.sin(movementTime), + y: maxSpinRadians * Math.random(), + z: maxSpinRadians * Math.sin(movementTime / 7) + }; + for (var i = 0; i < nearbyEntities.length; i++) { + var entityProperties = Entities.getEntityProperties(nearbyEntities[i]); + var entityName = entityProperties.name; + if (leafName === entityName) { + currentLeaf = nearbyEntities[i]; + var leafHeight = entityProperties.position.y; + if (complexMovement && leafHeight > floorHeight || complexMovement && floorHeight == null) { //actual new movement code; + var currentLeafVelocity = entityProperties.velocity, + currentLeafRot = entityProperties.rotation, + yVec = { x: 0, y: 1, z: 0 }, + leafYinWFVec = Vec3.multiplyQbyV(currentLeafRot, yVec), + leafLocalHorVec = Vec3.cross(leafYinWFVec, yVec), + leafMostDownVec = Vec3.cross(leafYinWFVec, leafLocalHorVec), + leafDesiredVel = Vec3.multiply(leafMostDownVec, windFactor); + Entities.editEntity(currentLeaf, { + angularVelocity: randomRotationSpeed, + velocity: { + x: (leafDesiredVel.x - currentLeafVelocity.x) * windFactor + currentLeafVelocity.x, + y: (leafDesiredVel.y - currentLeafVelocity.y) * windFactor + currentLeafVelocity.y, + z: (leafDesiredVel.z - currentLeafVelocity.z) * windFactor + currentLeafVelocity.z + } + }) + } + else if (leafHeight <= floorHeight) { + if (!leafDeleteOnGround) { + Entities.editEntity(nearbyEntities[i], { + locked: false, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }) + } + else { + Entity.deleteEntity(currentLeaf); + } + } + } + } + } + + + + getLeafCount = Script.setInterval(function () { + leafCount = 0 + for (var i = 0; i < nearbyEntities.length; i++) { + var entityName = Entities.getEntityProperties(nearbyEntities[i]).name; + //Stop Leaves at floorHeight + if (leafName === entityName) { + leafCount++; + if (i == nearbyEntities.length - 1) { + //print(leafCount); + } + } + } + }, 1000) + + + + function tearDown() { + Script.clearInterval(leafTimer); + Overlays.deleteOverlay(squallCircle); + if (leafDeleteOnTearDown) { + for (var i = 0; i < nearbyEntities.length; i++) { + var entityName = Entities.getEntityProperties(nearbyEntities[i]).name; + if (leafName === entityName) { + //We have a match - delete this entity + Entities.editEntity(nearbyEntities[i], { + locked: false + }); + Entities.deleteEntity(nearbyEntities[i]); + } + } + } + } + + + + processProperties(); + setUp(); + Script.scriptEnding.connect(tearDown); + + return { + }; +}; + +var leafSquall1 = new leafSquall({ + origin: { x: 3071.5, y: 2170, z: 6765.3 }, + radius: 100, + leavesPerMinute: 30, + leafSize: { x: 0.3, y: 0.00, z: .3}, + leafFallSpeed: .4, + leafLifetime: 100, + leafSpinMax: 30, + debug: false, + maxLeaves: 100, + leafDeleteOnTearDown: true, + complexMovement: true, + floorHeight: 2143.5, + windFactor: .5, + leafDeleteOnGround: false +}); + +// todo +//deal with depth issue \ No newline at end of file From 0580c8477e1c3a89879176e21702765fe2e7eae0 Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Fri, 17 Jul 2015 16:42:03 -0700 Subject: [PATCH 018/129] 3-step groundwork for AO in the pipeline --- interface/src/Application.cpp | 1 - libraries/gpu/src/gpu/GLBackendTexture.cpp | 32 ++++ .../src/AmbientOcclusionEffect.cpp | 149 ++++++++++++++++-- .../render-utils/src/AmbientOcclusionEffect.h | 18 ++- .../render-utils/src/ambient_occlusion.slf | 3 - .../render-utils/src/ambient_occlusion.slv | 4 +- libraries/render-utils/src/gaussian_blur.slf | 42 +++++ .../src/gaussian_blur_horizontal.slv | 41 +++++ .../src/gaussian_blur_vertical.slv | 41 +++++ 9 files changed, 306 insertions(+), 25 deletions(-) create mode 100644 libraries/render-utils/src/gaussian_blur.slf create mode 100644 libraries/render-utils/src/gaussian_blur_horizontal.slv create mode 100644 libraries/render-utils/src/gaussian_blur_vertical.slv diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8b04223463..537003ec02 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -274,7 +274,6 @@ bool setupEssentials(int& argc, char** argv) { auto audio = DependencyManager::set(); auto audioScope = DependencyManager::set(); auto deferredLightingEffect = DependencyManager::set(); - auto ambientOcclusionEffect = DependencyManager::set(); auto textureCache = DependencyManager::set(); auto animationCache = DependencyManager::set(); auto ddeFaceTracker = DependencyManager::set(); diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 72c7de8504..2696d17596 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -144,6 +144,38 @@ public: case gpu::RGB: case gpu::RGBA: texel.internalFormat = GL_RED; + /* switch (dstFormat.getType()) { + case gpu::UINT32: + case gpu::INT32: + case gpu::NUINT32: + case gpu::NINT32: { + texel.internalFormat = GL_DEPTH_COMPONENT32; + break; + } + case gpu::NFLOAT: + case gpu::FLOAT: { + texel.internalFormat = GL_DEPTH_COMPONENT32F; + break; + } + case gpu::UINT16: + case gpu::INT16: + case gpu::NUINT16: + case gpu::NINT16: + case gpu::HALF: + case gpu::NHALF: { + texel.internalFormat = GL_DEPTH_COMPONENT16; + break; + } + case gpu::UINT8: + case gpu::INT8: + case gpu::NUINT8: + case gpu::NINT8: { + texel.internalFormat = GL_DEPTH_COMPONENT24; + break; + } + case gpu::NUM_TYPES: { // quiet compiler + Q_UNREACHABLE(); + }*/ break; case gpu::DEPTH: texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 07832179cc..7e6b5c7e75 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -31,12 +31,16 @@ #include "ambient_occlusion_vert.h" #include "ambient_occlusion_frag.h" +#include "gaussian_blur_vertical_vert.h" +#include "gaussian_blur_horizontal_vert.h" +#include "gaussian_blur_frag.h" const int ROTATION_WIDTH = 4; const int ROTATION_HEIGHT = 4; - + +/* void AmbientOcclusionEffect::init(AbstractViewStateInterface* viewState) { - /*_viewState = viewState; // we will use this for view state services + _viewState = viewState; // we will use this for view state services _occlusionProgram = new ProgramObject(); _occlusionProgram->addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() @@ -99,11 +103,11 @@ void AmbientOcclusionEffect::init(AbstractViewStateInterface* viewState) { _blurProgram->setUniformValue("originalTexture", 0); _blurProgram->release(); - _blurScaleLocation = _blurProgram->uniformLocation("blurScale");*/ + _blurScaleLocation = _blurProgram->uniformLocation("blurScale"); } void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext){ - /*glDisable(GL_BLEND); + glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); @@ -170,15 +174,15 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE);*/ + glDepthMask(GL_TRUE) } - +*/ AmbientOcclusion::AmbientOcclusion() { } -const gpu::PipelinePointer& AmbientOcclusion::getAOPipeline() { - if (!_AOPipeline) { +const gpu::PipelinePointer& AmbientOcclusion::getOcclusionPipeline() { + if (!_occlusionPipeline) { auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(ambient_occlusion_vert))); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(ambient_occlusion_frag))); gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); @@ -198,10 +202,85 @@ const gpu::PipelinePointer& AmbientOcclusion::getAOPipeline() { gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + // Link the occlusion FBO to texture + _occlusionBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = _occlusionBuffer->getWidth(); + auto height = _occlusionBuffer->getHeight(); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _occlusionTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + // Good to go add the brand new pipeline - _AOPipeline.reset(gpu::Pipeline::create(program, state)); + _occlusionPipeline.reset(gpu::Pipeline::create(program, state)); } - return _AOPipeline; + return _occlusionPipeline; +} + +const gpu::PipelinePointer& AmbientOcclusion::getVBlurPipeline() { + if (!_vBlurPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(gaussian_blur_vertical_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(gaussian_blur_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(false, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + + // Link the horizontal blur FBO to texture + _vBlurBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = _vBlurBuffer->getWidth(); + auto height = _vBlurBuffer->getHeight(); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _vBlurTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + + // Good to go add the brand new pipeline + _vBlurPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _vBlurPipeline; +} + +const gpu::PipelinePointer& AmbientOcclusion::getHBlurPipeline() { + if (!_hBlurPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(gaussian_blur_horizontal_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(gaussian_blur_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(false, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + + // Link the horizontal blur FBO to texture + _hBlurBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = _hBlurBuffer->getWidth(); + auto height = _hBlurBuffer->getHeight(); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _hBlurTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + + // Good to go add the brand new pipeline + _hBlurPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _hBlurPipeline; } void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { @@ -226,18 +305,57 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); - batch.setResourceTexture(0, DependencyManager::get()->getPrimaryDepthTexture()); - // bind the one gpu::Pipeline we need - batch.setPipeline(getAOPipeline()); + // Occlusion step + getOcclusionPipeline(); + batch.setResourceTexture(0, DependencyManager::get()->getPrimaryDepthTexture()); + _occlusionBuffer->setRenderBuffer(0, _occlusionTexture); + batch.setFramebuffer(_occlusionBuffer); + + // bind the first gpu::Pipeline we need - for calculating occlusion buffer + batch.setPipeline(getOcclusionPipeline()); glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); - glm::vec2 bottomLeft(0.5f, -1.0f); - glm::vec2 topRight(1.0f, -0.5f); + glm::vec2 bottomLeft(-1.0f, -1.0f); + glm::vec2 topRight(1.0f, 1.0f); glm::vec2 texCoordTopLeft(0.0f, 0.0f); glm::vec2 texCoordBottomRight(1.0f, 1.0f); DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + // Vertical blur step + getVBlurPipeline(); + batch.setResourceTexture(0, _occlusionTexture); + _vBlurBuffer->setRenderBuffer(0, _vBlurTexture); + batch.setFramebuffer(_vBlurBuffer); + + // bind the second gpu::Pipeline we need - for calculating blur buffer + batch.setPipeline(getVBlurPipeline()); + + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + + // Horizontal blur step + getHBlurPipeline(); + batch.setResourceTexture(0, _vBlurTexture); + _hBlurBuffer->setRenderBuffer(0, _hBlurTexture); + batch.setFramebuffer(_hBlurBuffer); + + // bind the second gpu::Pipeline we need - for calculating blur buffer + batch.setPipeline(getHBlurPipeline()); + + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + + // "Blend" step + batch.setResourceTexture(0, _hBlurTexture); + batch.setFramebuffer(DependencyManager::get()->getPrimaryFramebuffer()); + + // bind the second gpu::Pipeline we need + batch.setPipeline(getOcclusionPipeline()); + + glm::vec2 bottomLeftSmall(0.5f, -1.0f); + glm::vec2 topRightSmall(1.0f, -0.5f); + DependencyManager::get()->renderQuad(batch, bottomLeftSmall, topRightSmall, texCoordTopLeft, texCoordBottomRight, color); + + // Ready to render args->_context->syncCache(); renderContext->args->_context->syncCache(); args->_context->render((batch)); @@ -247,4 +365,3 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons } - diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index fbe4a09214..8fce5e3d0c 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -22,6 +22,7 @@ class ProgramObject; /// A screen space ambient occlusion effect. See John Chapman's tutorial at /// http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html for reference. +/* class AmbientOcclusionEffect : public Dependency { SINGLETON_DEPENDENCY @@ -53,6 +54,7 @@ private: GLuint _rotationTextureID; AbstractViewStateInterface* _viewState; }; +*/ class AmbientOcclusion { public: @@ -62,11 +64,23 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); typedef render::Job::Model JobModel; - const gpu::PipelinePointer& AmbientOcclusion::getAOPipeline(); + const gpu::PipelinePointer& AmbientOcclusion::getOcclusionPipeline(); + const gpu::PipelinePointer& AmbientOcclusion::getHBlurPipeline(); + const gpu::PipelinePointer& AmbientOcclusion::getVBlurPipeline(); private: - gpu::PipelinePointer _AOPipeline; + gpu::PipelinePointer _occlusionPipeline; + gpu::PipelinePointer _hBlurPipeline; + gpu::PipelinePointer _vBlurPipeline; + + gpu::FramebufferPointer _occlusionBuffer; + gpu::FramebufferPointer _hBlurBuffer; + gpu::FramebufferPointer _vBlurBuffer; + + gpu::TexturePointer _occlusionTexture; + gpu::TexturePointer _hBlurTexture; + gpu::TexturePointer _vBlurTexture; }; #endif // hifi_AmbientOcclusionEffect_h diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index b56e0eb9d5..bdeb59e82a 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -14,9 +14,6 @@ <@include DeferredBufferWrite.slh@> -// the interpolated normal -//varying vec4 interpolatedNormal; - varying vec2 varTexcoord; uniform sampler2D depthTexture; diff --git a/libraries/render-utils/src/ambient_occlusion.slv b/libraries/render-utils/src/ambient_occlusion.slv index 54cc608129..81f196dd46 100644 --- a/libraries/render-utils/src/ambient_occlusion.slv +++ b/libraries/render-utils/src/ambient_occlusion.slv @@ -16,11 +16,9 @@ <$declareStandardTransform()$> -// the interpolated normal -//varying vec4 interpolatedNormal; varying vec2 varTexcoord; void main(void) { varTexcoord = gl_MultiTexCoord0.xy; gl_Position = gl_Vertex; -} \ No newline at end of file +} diff --git a/libraries/render-utils/src/gaussian_blur.slf b/libraries/render-utils/src/gaussian_blur.slf new file mode 100644 index 0000000000..5b66a0b751 --- /dev/null +++ b/libraries/render-utils/src/gaussian_blur.slf @@ -0,0 +1,42 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// gaussian_blur.frag +// fragment shader +// +// Created by Niraj Venkat on 7/17/15. +// Copyright 2015 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 +// + +<@include DeferredBufferWrite.slh@> + +// the interpolated normal +//varying vec4 interpolatedNormal; + +varying vec2 varTexcoord; +varying vec2 varBlurTexcoords[14]; + +uniform sampler2D occlusionTexture; + +void main(void) { + gl_FragColor = vec4(0.0); + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 0])*0.0044299121055113265; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 1])*0.00895781211794; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 2])*0.0215963866053; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 3])*0.0443683338718; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 4])*0.0776744219933; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 5])*0.115876621105; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 6])*0.147308056121; + gl_FragColor += texture2D(occlusionTexture, varTexcoord )*0.159576912161; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 7])*0.147308056121; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 8])*0.115876621105; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 9])*0.0776744219933; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[10])*0.0443683338718; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[11])*0.0215963866053; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[12])*0.00895781211794; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[13])*0.0044299121055113265; +} diff --git a/libraries/render-utils/src/gaussian_blur_horizontal.slv b/libraries/render-utils/src/gaussian_blur_horizontal.slv new file mode 100644 index 0000000000..94631b4b08 --- /dev/null +++ b/libraries/render-utils/src/gaussian_blur_horizontal.slv @@ -0,0 +1,41 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// guassian_blur_horizontal.vert +// vertex shader +// +// Created by Niraj Venkat on 7/17/15. +// Copyright 2015 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 +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec2 varTexcoord; +varying vec2 varBlurTexcoords[14]; + +void main(void) { + varTexcoord = gl_MultiTexCoord0.xy; + gl_Position = gl_Vertex; + + varBlurTexcoords[ 0] = varTexcoord + vec2(-0.028, 0.0); + varBlurTexcoords[ 1] = varTexcoord + vec2(-0.024, 0.0); + varBlurTexcoords[ 2] = varTexcoord + vec2(-0.020, 0.0); + varBlurTexcoords[ 3] = varTexcoord + vec2(-0.016, 0.0); + varBlurTexcoords[ 4] = varTexcoord + vec2(-0.012, 0.0); + varBlurTexcoords[ 5] = varTexcoord + vec2(-0.008, 0.0); + varBlurTexcoords[ 6] = varTexcoord + vec2(-0.004, 0.0); + varBlurTexcoords[ 7] = varTexcoord + vec2( 0.004, 0.0); + varBlurTexcoords[ 8] = varTexcoord + vec2( 0.008, 0.0); + varBlurTexcoords[ 9] = varTexcoord + vec2( 0.012, 0.0); + varBlurTexcoords[10] = varTexcoord + vec2( 0.016, 0.0); + varBlurTexcoords[11] = varTexcoord + vec2( 0.020, 0.0); + varBlurTexcoords[12] = varTexcoord + vec2( 0.024, 0.0); + varBlurTexcoords[13] = varTexcoord + vec2( 0.028, 0.0); +} + \ No newline at end of file diff --git a/libraries/render-utils/src/gaussian_blur_vertical.slv b/libraries/render-utils/src/gaussian_blur_vertical.slv new file mode 100644 index 0000000000..0d6de35b85 --- /dev/null +++ b/libraries/render-utils/src/gaussian_blur_vertical.slv @@ -0,0 +1,41 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// guassian_blur_vertical.vert +// vertex shader +// +// Created by Niraj Venkat on 7/17/15. +// Copyright 2015 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 +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec2 varTexcoord; +varying vec2 varBlurTexcoords[14]; + +void main(void) { + varTexcoord = gl_MultiTexCoord0.xy; + gl_Position = gl_Vertex; + + varBlurTexcoords[ 0] = varTexcoord + vec2(0.0, -0.028); + varBlurTexcoords[ 1] = varTexcoord + vec2(0.0, -0.024); + varBlurTexcoords[ 2] = varTexcoord + vec2(0.0, -0.020); + varBlurTexcoords[ 3] = varTexcoord + vec2(0.0, -0.016); + varBlurTexcoords[ 4] = varTexcoord + vec2(0.0, -0.012); + varBlurTexcoords[ 5] = varTexcoord + vec2(0.0, -0.008); + varBlurTexcoords[ 6] = varTexcoord + vec2(0.0, -0.004); + varBlurTexcoords[ 7] = varTexcoord + vec2(0.0, 0.004); + varBlurTexcoords[ 8] = varTexcoord + vec2(0.0, 0.008); + varBlurTexcoords[ 9] = varTexcoord + vec2(0.0, 0.012); + varBlurTexcoords[10] = varTexcoord + vec2(0.0, 0.016); + varBlurTexcoords[11] = varTexcoord + vec2(0.0, 0.020); + varBlurTexcoords[12] = varTexcoord + vec2(0.0, 0.024); + varBlurTexcoords[13] = varTexcoord + vec2(0.0, 0.028); +} + \ No newline at end of file From 1d48eeab10085969028092d2d0ffcaf1334a673f Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Sat, 18 Jul 2015 18:32:39 -0400 Subject: [PATCH 019/129] commit 20485 --- examples/afk.js | 120 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 examples/afk.js diff --git a/examples/afk.js b/examples/afk.js new file mode 100644 index 0000000000..5e0c443e11 --- /dev/null +++ b/examples/afk.js @@ -0,0 +1,120 @@ +// +// #20485: AFK - Away From Keyboard Setting +// ***************************************** +// +// Created by Kevin M. Thomas and Thoys 07/16/15. +// Copyright 2015 High Fidelity, Inc. +// kevintown.net +// +// JavaScript for the High Fidelity interface that creates an away from keyboard functionality by providing a UI and keyPressEvent which will mute toggle the connected microphone, face tracking dde and set the avatar to a hand raise pose. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +var originalOutputDevice; +var originalName; +var muted = false; +var wasAudioEnabled; +var afkText = "AFK - I Will Return!\n"; + +// Set up toggleMuteButton text overlay. +var toggleMuteButton = Overlays.addOverlay("text", { + x: 10, + y: 275, + width: 60, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8 +}); + +// Function that overlays text upon state change. +function onMuteStateChanged() { + Overlays.editOverlay(toggleMuteButton, muted ? {text: "Go Live", leftMargin: 5} : {text: "Go AFK", leftMargin: 5}); +} + +// Function that adds mousePressEvent functionality to toggle mic mute, AFK message above display name and toggle avatar arms upward. +function mousePressEvent(event) { + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleMuteButton) { + if (!muted) { + if (!AudioDevice.getMuted()) { + AudioDevice.toggleMute(); + } + originalOutputDevice = AudioDevice.getOutputDevice(); + Menu.setIsOptionChecked("Mute Face Tracking", true); + originalName = MyAvatar.displayName; + AudioDevice.setOutputDevice("none"); + MyAvatar.displayName = afkText + MyAvatar.displayName; + MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(0, 180, 0)); + MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(0, 180, 0)); + } else { + if (AudioDevice.getMuted()) { + AudioDevice.toggleMute(); + } + AudioDevice.setOutputDevice(originalOutputDevice); + Menu.setIsOptionChecked("Mute Face Tracking", false); + MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(0, 0, 0)); + MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(0, 0, 0)); + MyAvatar.clearJointData("LeftShoulder"); + MyAvatar.clearJointData("RightShoulder"); + MyAvatar.displayName = originalName; + } + onMuteStateChanged(); + muted = !muted; + } +} + +// Call functions. +onMuteStateChanged(); + +//AudioDevice.muteToggled.connect(onMuteStateChanged); +Controller.mousePressEvent.connect(mousePressEvent); + +// Function that adds keyPressEvent functionality to toggle mic mute, AFK message above display name and toggle avatar arms upward. +Controller.keyPressEvent.connect(function(event) { + if (event.text == "y") { + if (!muted) { + if (!AudioDevice.getMuted()) { + AudioDevice.toggleMute(); + } + originalOutputDevice = AudioDevice.getOutputDevice(); + Menu.setIsOptionChecked("Mute Face Tracking", true); + originalName = MyAvatar.displayName; + AudioDevice.setOutputDevice("none"); + MyAvatar.displayName = afkText + MyAvatar.displayName; + MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(0, 180, 0)); + MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(0, 180, 0)); + } else { + if (AudioDevice.getMuted()) { + AudioDevice.toggleMute(); + } + AudioDevice.setOutputDevice(originalOutputDevice); + Menu.setIsOptionChecked("Mute Face Tracking", false); + MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(0, 0, 0)); + MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(0, 0, 0)); + MyAvatar.clearJointData("LeftShoulder"); + MyAvatar.clearJointData("RightShoulder"); + MyAvatar.displayName = originalName; + } + onMuteStateChanged(); + muted = !muted; + } +}); + +// Function that sets a timeout value of 1 second so that the display name does not get overwritten in the event of a crash. +Script.setTimeout(function() { + MyAvatar.displayName = MyAvatar.displayName.replace(afkText, ""); +}, 1000); + +// Function that calls upon exit to restore avatar display name to original state. +Script.scriptEnding.connect(function(){ + if (muted) { + AudioDevice.setOutputDevice(originalOutputDevice); + Overlays.deleteOverlay(toggleMuteButton); + MyAvatar.displayName = originalName; + } + Overlays.deleteOverlay(toggleMuteButton); +}); \ No newline at end of file From eb48aa10185e8b5323ea2b3e2365fd1b6259e43d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Sun, 19 Jul 2015 12:10:37 -0700 Subject: [PATCH 020/129] Update edit.js to swing up on activate --- examples/libraries/entityCameraTool.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index d27d95c161..a3b817e300 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -141,7 +141,7 @@ CameraManager = function() { // Pick a point INITIAL_ZOOM_DISTANCE in front of the camera to use as a focal point that.zoomDistance = INITIAL_ZOOM_DISTANCE; - that.targetZoomDistance = that.zoomDistance; + that.targetZoomDistance = that.zoomDistance + 3.0; var focalPoint = Vec3.sum(Camera.getPosition(), Vec3.multiply(that.zoomDistance, Quat.getFront(Camera.getOrientation()))); @@ -150,6 +150,7 @@ CameraManager = function() { var xzDist = Math.sqrt(dPos.x * dPos.x + dPos.z * dPos.z); that.targetPitch = -Math.atan2(dPos.y, xzDist) * 180 / Math.PI; + that.targetPitch += (90 - that.targetPitch) / 3.0; // Swing camera "up" to look down at the focal point that.targetYaw = Math.atan2(dPos.x, dPos.z) * 180 / Math.PI; that.pitch = that.targetPitch; that.yaw = that.targetYaw; From 48524b1c98999326b4b25ee782e16e107a851124 Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Sun, 19 Jul 2015 18:22:58 -0400 Subject: [PATCH 021/129] Reverted changes from other PR. --- libraries/audio-client/src/AudioClient.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 3a85adbc97..aeea7c07c1 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -55,9 +55,9 @@ static const int NUM_AUDIO_CHANNELS = 2; -static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; +static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; -static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 40; +static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; #if defined(Q_OS_ANDROID) || defined(Q_OS_WIN) static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = false; #else From 8ec51f981464eac0dbde60eae033c3ae1092629d Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Sun, 19 Jul 2015 18:24:29 -0400 Subject: [PATCH 022/129] Updated afk.js file based on advise from PR. --- examples/afk.js | 80 +++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 50 deletions(-) diff --git a/examples/afk.js b/examples/afk.js index 5e0c443e11..5977c6384a 100644 --- a/examples/afk.js +++ b/examples/afk.js @@ -36,34 +36,38 @@ function onMuteStateChanged() { Overlays.editOverlay(toggleMuteButton, muted ? {text: "Go Live", leftMargin: 5} : {text: "Go AFK", leftMargin: 5}); } +function toggleMute() { + if (!muted) { + if (!AudioDevice.getMuted()) { + AudioDevice.toggleMute(); + } + originalOutputDevice = AudioDevice.getOutputDevice(); + Menu.setIsOptionChecked("Mute Face Tracking", true); + originalName = MyAvatar.displayName; + AudioDevice.setOutputDevice("none"); + MyAvatar.displayName = afkText + MyAvatar.displayName; + MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(0, 180, 0)); + MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(0, 180, 0)); + } else { + if (AudioDevice.getMuted()) { + AudioDevice.toggleMute(); + } + AudioDevice.setOutputDevice(originalOutputDevice); + Menu.setIsOptionChecked("Mute Face Tracking", false); + MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(0, 0, 0)); + MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(0, 0, 0)); + MyAvatar.clearJointData("LeftShoulder"); + MyAvatar.clearJointData("RightShoulder"); + MyAvatar.displayName = originalName; + } + muted = !muted; + onMuteStateChanged(); +} + // Function that adds mousePressEvent functionality to toggle mic mute, AFK message above display name and toggle avatar arms upward. function mousePressEvent(event) { if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleMuteButton) { - if (!muted) { - if (!AudioDevice.getMuted()) { - AudioDevice.toggleMute(); - } - originalOutputDevice = AudioDevice.getOutputDevice(); - Menu.setIsOptionChecked("Mute Face Tracking", true); - originalName = MyAvatar.displayName; - AudioDevice.setOutputDevice("none"); - MyAvatar.displayName = afkText + MyAvatar.displayName; - MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(0, 180, 0)); - MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(0, 180, 0)); - } else { - if (AudioDevice.getMuted()) { - AudioDevice.toggleMute(); - } - AudioDevice.setOutputDevice(originalOutputDevice); - Menu.setIsOptionChecked("Mute Face Tracking", false); - MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(0, 0, 0)); - MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(0, 0, 0)); - MyAvatar.clearJointData("LeftShoulder"); - MyAvatar.clearJointData("RightShoulder"); - MyAvatar.displayName = originalName; - } - onMuteStateChanged(); - muted = !muted; + toggleMute(); } } @@ -76,31 +80,7 @@ Controller.mousePressEvent.connect(mousePressEvent); // Function that adds keyPressEvent functionality to toggle mic mute, AFK message above display name and toggle avatar arms upward. Controller.keyPressEvent.connect(function(event) { if (event.text == "y") { - if (!muted) { - if (!AudioDevice.getMuted()) { - AudioDevice.toggleMute(); - } - originalOutputDevice = AudioDevice.getOutputDevice(); - Menu.setIsOptionChecked("Mute Face Tracking", true); - originalName = MyAvatar.displayName; - AudioDevice.setOutputDevice("none"); - MyAvatar.displayName = afkText + MyAvatar.displayName; - MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(0, 180, 0)); - MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(0, 180, 0)); - } else { - if (AudioDevice.getMuted()) { - AudioDevice.toggleMute(); - } - AudioDevice.setOutputDevice(originalOutputDevice); - Menu.setIsOptionChecked("Mute Face Tracking", false); - MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(0, 0, 0)); - MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(0, 0, 0)); - MyAvatar.clearJointData("LeftShoulder"); - MyAvatar.clearJointData("RightShoulder"); - MyAvatar.displayName = originalName; - } - onMuteStateChanged(); - muted = !muted; + toggleMute(); } }); From 3439d45e0ee6b53027dcea062adfec2bf1566d93 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 20 Jul 2015 10:44:38 -0700 Subject: [PATCH 023/129] adding hit effect logic --- libraries/render-utils/src/HitEffect.cpp | 105 ++++++++++++++++++ libraries/render-utils/src/HitEffect.h | 34 ++++++ .../render-utils/src/RenderDeferredTask.cpp | 4 + libraries/render-utils/src/hit_effect.slf | 29 +++++ libraries/render-utils/src/hit_effect.slv | 21 ++++ 5 files changed, 193 insertions(+) create mode 100644 libraries/render-utils/src/HitEffect.cpp create mode 100644 libraries/render-utils/src/HitEffect.h create mode 100644 libraries/render-utils/src/hit_effect.slf create mode 100644 libraries/render-utils/src/hit_effect.slv diff --git a/libraries/render-utils/src/HitEffect.cpp b/libraries/render-utils/src/HitEffect.cpp new file mode 100644 index 0000000000..1b81c3b85f --- /dev/null +++ b/libraries/render-utils/src/HitEffect.cpp @@ -0,0 +1,105 @@ +// +// HitEffect.cpp +// interface/src/renderer +// +// Created by Andrzej Kapolka on 7/14/13. +// Copyright 2013 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 +// + +// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL +#include + +#include + +#include + +#include +#include + +#include "AbstractViewStateInterface.h" +#include "HitEffect.h" +#include "ProgramObject.h" +#include "RenderUtil.h" +#include "TextureCache.h" +#include "DependencyManager.h" +#include "ViewFrustum.h" +#include "GeometryCache.h" + +#include "hit_effect_vert.h" +#include "hit_effect_frag.h" + + +HitEffect::HitEffect() { +} + +const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() { + if (!_hitEffectPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(hit_effect_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(hit_effect_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + _screenSizeLocation = program->getUniforms().findLocation("screenSize"); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + + // Good to go add the brand new pipeline + _hitEffectPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _hitEffectPipeline; +} + + + + +void HitEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { + + // create a simple pipeline that does: + + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + RenderArgs* args = renderContext->args; + + // Allright, something to render let's do it + gpu::Batch batch; + + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + batch.setModelTransform(Transform()); + + + + + // bind the first gpu::Pipeline we need - for calculating occlusion buffer + batch.setPipeline(getHitEffectPipeline()); + + + glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); + glm::vec2 bottomLeft(-1.0f, -1.0f); + glm::vec2 topRight(1.0f, 1.0f); + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, color); + + + // Ready to render + renderContext->args->_context->syncCache(); + args->_context->render((batch)); + +} + diff --git a/libraries/render-utils/src/HitEffect.h b/libraries/render-utils/src/HitEffect.h new file mode 100644 index 0000000000..3ee05a27aa --- /dev/null +++ b/libraries/render-utils/src/HitEffect.h @@ -0,0 +1,34 @@ +// +// hitEffect.h +// hifi +// +// Created by eric levin on 7/17/15. +// +// + +#ifndef hifi_hitEffect_h +#define hifi_hitEffect_h + +#include +#include "render/DrawTask.h" + +class AbstractViewStateInterface; +class ProgramObject; + +class HitEffect { +public: + + HitEffect(); + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + typedef render::Job::Model JobModel; + + const gpu::PipelinePointer& getHitEffectPipeline(); + +private: + + gpu::PipelinePointer _hitEffectPipeline; + GLuint _screenSizeLocation; +}; + +#endif diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index fab134913d..95e0344313 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -16,6 +16,7 @@ #include "ViewFrustum.h" #include "RenderArgs.h" #include "TextureCache.h" +#include "HitEffect.h" #include "render/DrawStatus.h" @@ -54,6 +55,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortOpaque", _jobs.back().getOutput()))); auto& renderedOpaques = _jobs.back().getOutput(); _jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", _jobs.back().getOutput()))); + _jobs.push_back(Job(new DrawLight::JobModel("DrawLight"))); _jobs.push_back(Job(new ResetGLState::JobModel())); _jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred"))); @@ -75,7 +77,9 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _drawStatusJobIndex = _jobs.size() - 1; _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); + _jobs.push_back(Job(new HitEffect::JobModel("HitEffect"))); _jobs.push_back(Job(new ResetGLState::JobModel())); + // Give ourselves 3 frmaes of timer queries _timerQueries.push_back(gpu::QueryPointer(new gpu::Query())); diff --git a/libraries/render-utils/src/hit_effect.slf b/libraries/render-utils/src/hit_effect.slf new file mode 100644 index 0000000000..cd94de3620 --- /dev/null +++ b/libraries/render-utils/src/hit_effect.slf @@ -0,0 +1,29 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// ambient_occlusion.frag +// fragment shader +// +// Created by Eric Levin on 7/20 +// Copyright 2015 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 +// +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> +<@include DeferredBufferWrite.slh@> + +void main(void) { + + TransformCamera cam = getTransformCamera(); + vec4 myViewport; + <$transformCameraViewport(cam, myViewport)$> + vec2 center = vec2(myViewport.z/2.0, myViewport.w/2.0); + float distFromCenter = distance(center, gl_FragCoord.xy); + //normalize + distFromCenter = distFromCenter/myViewport.z; + float alpha = mix(0.0, 1.0, distFromCenter); + gl_FragColor = vec4(0.7, 0.0, 0.0, alpha); +} \ No newline at end of file diff --git a/libraries/render-utils/src/hit_effect.slv b/libraries/render-utils/src/hit_effect.slv new file mode 100644 index 0000000000..c12e3e71f8 --- /dev/null +++ b/libraries/render-utils/src/hit_effect.slv @@ -0,0 +1,21 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// ambient_occlusion.vert +// vertex shader +// +// Created by Niraj Venkat on 7/20/15. +// Copyright 2015 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 +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +void main(void) { + gl_Position = gl_Vertex; +} \ No newline at end of file From d76d380512c1f2cc17f125b0cffe35654fbb106d Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Mon, 20 Jul 2015 14:19:16 -0400 Subject: [PATCH 024/129] Added jsstreamplayer. --- examples/html/jsstreamplayer.html | 42 +++++++++ examples/jsstreamplayer.js | 137 ++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 examples/html/jsstreamplayer.html create mode 100644 examples/jsstreamplayer.js diff --git a/examples/html/jsstreamplayer.html b/examples/html/jsstreamplayer.html new file mode 100644 index 0000000000..7cf827309c --- /dev/null +++ b/examples/html/jsstreamplayer.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/jsstreamplayer.js b/examples/jsstreamplayer.js new file mode 100644 index 0000000000..05ebc7d968 --- /dev/null +++ b/examples/jsstreamplayer.js @@ -0,0 +1,137 @@ +// +// #20622: JS Stream Player +// ************************* +// +// Created by Kevin M. Thomas and Thoys 07/17/15. +// Copyright 2015 High Fidelity, Inc. +// kevintown.net +// +// JavaScript for the High Fidelity interface that creates a stream player with a UI and keyPressEvents for adding a stream URL in addition to play, stop and volume functionality. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +// Declare variables and set up new WebWindow. +var stream; +var volume = 1; +var streamWindow = new WebWindow('Stream', "https://dl.dropboxusercontent.com/u/17344741/jsstreamplayer/jsstreamplayer.html", 0, 0, false); + +// Set up toggleStreamURLButton overlay. +var toggleStreamURLButton = Overlays.addOverlay("text", { + x: 76, + y: 275, + width: 40, + height: 28, + backgroundColor: {red: 0, green: 0, blue: 0}, + color: {red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + text: " URL" +}); + +// Set up toggleStreamPlayButton overlay. +var toggleStreamPlayButton = Overlays.addOverlay("text", { + x: 122, + y: 275, + width: 38, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + text: " Play" +}); + +// Set up toggleStreamStopButton overlay. +var toggleStreamStopButton = Overlays.addOverlay("text", { + x: 166, + y: 275, + width: 40, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + text: " Stop" +}); + +// Set up increaseVolumeButton overlay. +var toggleIncreaseVolumeButton = Overlays.addOverlay("text", { + x: 211, + y: 275, + width: 18, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + text: " +" +}); + +// Set up decreaseVolumeButton overlay. +var toggleDecreaseVolumeButton = Overlays.addOverlay("text", { + x: 234, + y: 275, + width: 15, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + text: " -" +}); + +// Function that adds mousePressEvent functionality to connect UI to enter stream URL, play and stop stream. +function mousePressEvent(event) { + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamURLButton) { + stream = Window.prompt("Enter Stream: "); + var streamJSON = { + action: "changeStream", + stream: stream + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamPlayButton) { + var streamJSON = { + action: "changeStream", + stream: stream + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamStopButton) { + var streamJSON = { + action: "changeStream", + stream: "" + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleIncreaseVolumeButton) { + volume += 0.2; + var volumeJSON = { + action: "changeVolume", + volume: volume + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(volumeJSON)); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleDecreaseVolumeButton) { + volume -= 0.2; + var volumeJSON = { + action: "changeVolume", + volume: volume + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(volumeJSON)); + } +} + +// Call function. +Controller.mousePressEvent.connect(mousePressEvent); +streamWindow.setVisible(false); + +// Function to delete overlays upon exit. +function scriptEnding() { + Overlays.deleteOverlay(toggleStreamURLButton); + Overlays.deleteOverlay(toggleStreamPlayButton); + Overlays.deleteOverlay(toggleStreamStopButton); +} \ No newline at end of file From 2c088ec5a98d76f5786439314dcea635c3e7fc4b Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Mon, 20 Jul 2015 14:21:42 -0400 Subject: [PATCH 025/129] Updated overlay clearing functionality. --- examples/jsstreamplayer.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/jsstreamplayer.js b/examples/jsstreamplayer.js index 05ebc7d968..6bd941f677 100644 --- a/examples/jsstreamplayer.js +++ b/examples/jsstreamplayer.js @@ -130,8 +130,13 @@ Controller.mousePressEvent.connect(mousePressEvent); streamWindow.setVisible(false); // Function to delete overlays upon exit. -function scriptEnding() { +function onScriptEnding() { Overlays.deleteOverlay(toggleStreamURLButton); Overlays.deleteOverlay(toggleStreamPlayButton); Overlays.deleteOverlay(toggleStreamStopButton); -} \ No newline at end of file + Overlays.deleteOverlay(toggleIncreaseVolumeButton); + Overlays.deleteOverlay(toggleDecreaseVolumeButton); +} + +// Call function. +Script.scriptEnding.connect(onScriptEnding); \ No newline at end of file From e75a6feafe3fd73fe599e47bdaf814399a70d547 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 20 Jul 2015 11:58:26 -0700 Subject: [PATCH 026/129] can toggle hit effect on and off from a script --- interface/src/Application.cpp | 1 + libraries/render-utils/src/RenderDeferredTask.cpp | 7 +++++++ libraries/render-utils/src/RenderDeferredTask.h | 4 ++++ libraries/render-utils/src/hit_effect.slf | 9 +++++---- libraries/render/src/render/Engine.h | 1 + libraries/script-engine/src/SceneScriptingInterface.h | 5 +++++ 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 342580e03c..0fb4bbcc74 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3570,6 +3570,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems(); renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus(); + renderContext._drawHitEffect = sceneInterface->doEngineDisplayHitEffect(); renderArgs->_shouldRender = LODManager::shouldRender; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 95e0344313..b9767105c3 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -78,6 +78,9 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); _jobs.push_back(Job(new HitEffect::JobModel("HitEffect"))); + _jobs.back().setEnabled(false); + _drawHitEffectJobIndex = _jobs.size() -1; + _jobs.push_back(Job(new ResetGLState::JobModel())); @@ -106,6 +109,10 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend // Make sure we turn the displayItemStatus on/off setDrawItemStatus(renderContext->_drawItemStatus); + + //Make sure we display hit effect on screen, as desired from a script + setDrawHitEffect(renderContext->_drawHitEffect); + renderContext->args->_context->syncCache(); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 4040606c62..b3957fe7dc 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -71,9 +71,13 @@ public: render::Jobs _jobs; int _drawStatusJobIndex = -1; + int _drawHitEffectJobIndex = -1; void setDrawItemStatus(bool draw) { if (_drawStatusJobIndex >= 0) { _jobs[_drawStatusJobIndex].setEnabled(draw); } } bool doDrawItemStatus() const { if (_drawStatusJobIndex >= 0) { return _jobs[_drawStatusJobIndex].isEnabled(); } else { return false; } } + + void setDrawHitEffect(bool draw) { if (_drawHitEffectJobIndex >= 0) { _jobs[_drawHitEffectJobIndex].setEnabled(draw); } } + bool doDrawHitEffect() const { if (_drawHitEffectJobIndex >=0) { return _jobs[_drawHitEffectJobIndex].isEnabled(); } else { return false; } } virtual void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); diff --git a/libraries/render-utils/src/hit_effect.slf b/libraries/render-utils/src/hit_effect.slf index cd94de3620..5a5d85b21f 100644 --- a/libraries/render-utils/src/hit_effect.slf +++ b/libraries/render-utils/src/hit_effect.slf @@ -22,8 +22,9 @@ void main(void) { <$transformCameraViewport(cam, myViewport)$> vec2 center = vec2(myViewport.z/2.0, myViewport.w/2.0); float distFromCenter = distance(center, gl_FragCoord.xy); - //normalize - distFromCenter = distFromCenter/myViewport.z; - float alpha = mix(0.0, 1.0, distFromCenter); - gl_FragColor = vec4(0.7, 0.0, 0.0, alpha); + //normalize distance from center based on average of screen width and height + float normalizationFactor = (myViewport.z + myViewport.w)/2.0; + distFromCenter = distFromCenter/normalizationFactor; + float alpha = mix(0.0, 1.0, pow(distFromCenter, 1.5)); + gl_FragColor = vec4(1.0, 0.0, 0.0, alpha); } \ No newline at end of file diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 1c600b13d6..e12d37118c 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -50,6 +50,7 @@ public: int _maxDrawnOverlay3DItems = -1; bool _drawItemStatus = false; + bool _drawHitEffect = false; RenderContext() {} }; diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 674b452528..a3ce2a7300 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -109,6 +109,9 @@ public: Q_INVOKABLE void setEngineDisplayItemStatus(bool display) { _drawItemStatus = display; } Q_INVOKABLE bool doEngineDisplayItemStatus() { return _drawItemStatus; } + + Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; } + Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; } signals: void shouldRenderAvatarsChanged(bool shouldRenderAvatars); @@ -141,6 +144,8 @@ protected: int _maxDrawnOverlay3DItems = -1; bool _drawItemStatus = false; + + bool _drawHitEffect = false; }; From dcb20120703a48df6a9fa59072db819ea03b2435 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 20 Jul 2015 12:02:01 -0700 Subject: [PATCH 027/129] can toggle hit effect on and off from a script --- examples/example/games/hitEffect.js | 28 +++++++++++++++++++++++ libraries/render-utils/src/hit_effect.slf | 2 +- libraries/render-utils/src/hit_effect.slv | 4 ++-- 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 examples/example/games/hitEffect.js diff --git a/examples/example/games/hitEffect.js b/examples/example/games/hitEffect.js new file mode 100644 index 0000000000..0ba9ea14d1 --- /dev/null +++ b/examples/example/games/hitEffect.js @@ -0,0 +1,28 @@ +// +// hitEffect.js +// examples +// +// Created by Eric Levin on July 20, 2015 +// Copyright 2015 High Fidelity, Inc. +// +// An example of how to toggle a screen-space hit effect using the Scene global object. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +var hitEffectEnabled = false; + +toggleHitEffect(); + +function toggleHitEffect() { + Script.setTimeout(function() { + hitEffectEnabled = !hitEffectEnabled; + Scene.setEngineDisplayHitEffect(hitEffectEnabled); + toggleHitEffect(); + }, 1000); +} + + + + + diff --git a/libraries/render-utils/src/hit_effect.slf b/libraries/render-utils/src/hit_effect.slf index 5a5d85b21f..2c308f3711 100644 --- a/libraries/render-utils/src/hit_effect.slf +++ b/libraries/render-utils/src/hit_effect.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// ambient_occlusion.frag +// hit_effect.frag // fragment shader // // Created by Eric Levin on 7/20 diff --git a/libraries/render-utils/src/hit_effect.slv b/libraries/render-utils/src/hit_effect.slv index c12e3e71f8..e7c3062667 100644 --- a/libraries/render-utils/src/hit_effect.slv +++ b/libraries/render-utils/src/hit_effect.slv @@ -2,10 +2,10 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// ambient_occlusion.vert +// hit_effect.vert // vertex shader // -// Created by Niraj Venkat on 7/20/15. +// Created by Eric Levin on 7/20/15. // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. From 075c9f05de9a3b340554f1792c35a74288ca7fcd Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Mon, 20 Jul 2015 16:34:02 -0700 Subject: [PATCH 028/129] Introducing blend stage in the AO pipeline --- .../src/AmbientOcclusionEffect.cpp | 47 +++++++++++++++++-- .../render-utils/src/AmbientOcclusionEffect.h | 42 +---------------- .../render-utils/src/ambient_occlusion.slf | 4 +- .../render-utils/src/occlusion_blend.slf | 24 ++++++++++ .../render-utils/src/occlusion_blend.slv | 24 ++++++++++ 5 files changed, 94 insertions(+), 47 deletions(-) create mode 100644 libraries/render-utils/src/occlusion_blend.slf create mode 100644 libraries/render-utils/src/occlusion_blend.slv diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 65d7313efb..a6646d8e4a 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -21,7 +21,6 @@ #include "AbstractViewStateInterface.h" #include "AmbientOcclusionEffect.h" -#include "ProgramObject.h" #include "RenderUtil.h" #include "TextureCache.h" #include "DependencyManager.h" @@ -33,6 +32,8 @@ #include "gaussian_blur_vertical_vert.h" #include "gaussian_blur_horizontal_vert.h" #include "gaussian_blur_frag.h" +#include "occlusion_blend_vert.h" +#include "occlusion_blend_frag.h" const int ROTATION_WIDTH = 4; const int ROTATION_HEIGHT = 4; @@ -187,6 +188,9 @@ const gpu::PipelinePointer& AmbientOcclusion::getOcclusionPipeline() { gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("depthTexture"), 0)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalTexture"), 1)); + gpu::Shader::makeProgram(*program, slotBindings); //_drawItemBoundPosLoc = program->getUniforms().findLocation("inBoundPos"); @@ -282,6 +286,39 @@ const gpu::PipelinePointer& AmbientOcclusion::getHBlurPipeline() { return _hBlurPipeline; } +const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { + if (!_blendPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(occlusion_blend_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(occlusion_blend_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + + // Link the horizontal blur FBO to texture + _hBlurBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = _hBlurBuffer->getWidth(); + auto height = _hBlurBuffer->getHeight(); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _hBlurTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + + // Good to go add the brand new pipeline + _blendPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _blendPipeline; +} + void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { // create a simple pipeline that does: @@ -308,7 +345,7 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons // Occlusion step getOcclusionPipeline(); batch.setResourceTexture(0, DependencyManager::get()->getPrimaryDepthTexture()); - batch.setResourceTexture(1, DependencyManager::get()->getPrimaryNormalTexture()); + batch.setResourceTexture(1, DependencyManager::get()->getPrimaryFramebuffer()->getRenderBuffer(0)); _occlusionBuffer->setRenderBuffer(0, _occlusionTexture); batch.setFramebuffer(_occlusionBuffer); @@ -339,7 +376,7 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons _hBlurBuffer->setRenderBuffer(0, _hBlurTexture); batch.setFramebuffer(_hBlurBuffer); - // bind the second gpu::Pipeline we need - for calculating blur buffer + // bind the third gpu::Pipeline we need - for calculating blur buffer batch.setPipeline(getHBlurPipeline()); DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); @@ -348,8 +385,8 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons batch.setResourceTexture(0, _hBlurTexture); batch.setFramebuffer(DependencyManager::get()->getPrimaryFramebuffer()); - // bind the second gpu::Pipeline we need - batch.setPipeline(getOcclusionPipeline()); + // bind the fourth gpu::Pipeline we need - for + batch.setPipeline(getBlendPipeline()); glm::vec2 bottomLeftSmall(0.5f, -1.0f); glm::vec2 topRightSmall(1.0f, -0.5f); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index a8ae33b690..d38624f24c 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -16,46 +16,6 @@ #include "render/DrawTask.h" -class AbstractViewStateInterface; -class ProgramObject; - -/// A screen space ambient occlusion effect. See John Chapman's tutorial at -/// http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html for reference. - -/* -class AmbientOcclusionEffect : public Dependency { - SINGLETON_DEPENDENCY - -public: - - void init(AbstractViewStateInterface* viewState); - - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; - - - AmbientOcclusionEffect() {} - virtual ~AmbientOcclusionEffect() {} - -private: - - ProgramObject* _occlusionProgram; - int _nearLocation; - int _farLocation; - int _leftBottomLocation; - int _rightTopLocation; - int _noiseScaleLocation; - int _texCoordOffsetLocation; - int _texCoordScaleLocation; - - ProgramObject* _blurProgram; - int _blurScaleLocation; - - GLuint _rotationTextureID; - AbstractViewStateInterface* _viewState; -}; -*/ - class AmbientOcclusion { public: @@ -67,12 +27,14 @@ public: const gpu::PipelinePointer& getOcclusionPipeline(); const gpu::PipelinePointer& getHBlurPipeline(); const gpu::PipelinePointer& getVBlurPipeline(); + const gpu::PipelinePointer& getBlendPipeline(); private: gpu::PipelinePointer _occlusionPipeline; gpu::PipelinePointer _hBlurPipeline; gpu::PipelinePointer _vBlurPipeline; + gpu::PipelinePointer _blendPipeline; gpu::FramebufferPointer _occlusionBuffer; gpu::FramebufferPointer _hBlurBuffer; diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index 4b7d6bfe2b..342f4148d2 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -40,9 +40,9 @@ void main(void) { float c = (2.0 * n) / (f + n - z * (f - n)); // convert to linear values //gl_FragColor = vec4(c, c, c, 1.0); - gl_FragColor = normalColor; + gl_FragColor = mix(depthColor, normalColor, normalColor.a); //vec3 p = getPosition(i.uv); //vec3 n = getNormal(i.uv); - vec2 rand = vec2(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx)); + //vec2 rand = vec2(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx)); } diff --git a/libraries/render-utils/src/occlusion_blend.slf b/libraries/render-utils/src/occlusion_blend.slf new file mode 100644 index 0000000000..30d3173f90 --- /dev/null +++ b/libraries/render-utils/src/occlusion_blend.slf @@ -0,0 +1,24 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// occlusion_blend.frag +// fragment shader +// +// Created by Niraj Venkat on 7/20/15. +// Copyright 2015 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 +// + +<@include DeferredBufferWrite.slh@> + +varying vec2 varTexcoord; + +uniform sampler2D blurredOcclusionTexture; + +void main(void) { + vec4 depthColor = texture2D(blurredOcclusionTexture, varTexcoord.xy); + gl_FragColor = depthColor; +} diff --git a/libraries/render-utils/src/occlusion_blend.slv b/libraries/render-utils/src/occlusion_blend.slv new file mode 100644 index 0000000000..53380a494f --- /dev/null +++ b/libraries/render-utils/src/occlusion_blend.slv @@ -0,0 +1,24 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// occlusion_blend.vert +// vertex shader +// +// Created by Niraj Venkat on 7/20/15. +// Copyright 2015 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 +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec2 varTexcoord; + +void main(void) { + varTexcoord = gl_MultiTexCoord0.xy; + gl_Position = gl_Vertex; +} From 0d0f12164a0c529ebd2cee6e42d6319722b28c27 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 21 Jul 2015 16:57:02 +0200 Subject: [PATCH 029/129] planky, enabling properties button --- examples/example/games/planky.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index 6733749317..4181eb541e 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -32,7 +32,7 @@ const DEFAULT_BLOCK_YAW_OFFSET = 45; var editMode = false; -const BUTTON_DIMENSIONS = {width: 50, height: 50}; +const BUTTON_DIMENSIONS = {width: 49, height: 49}; const MAXIMUM_PERCENTAGE = 100.0; const NO_ANGLE = 0; const RIGHT_ANGLE = 90; @@ -326,10 +326,11 @@ button = toolBar.addTool({ cogButton = toolBar.addTool({ width: BUTTON_DIMENSIONS.width, height: BUTTON_DIMENSIONS.height, - imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg', + imageURL: "https://dl.dropboxusercontent.com/u/14997455/hifi/planky/cog.svg", //HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg', + subImage: { x: 0, y: BUTTON_DIMENSIONS.height, width: BUTTON_DIMENSIONS.width, height: BUTTON_DIMENSIONS.height }, alpha: 0.8, visible: true -}); +}, true, false); Controller.mousePressEvent.connect(function(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); @@ -341,6 +342,7 @@ Controller.mousePressEvent.connect(function(event) { editMode = !editMode; plankyStack.refresh(); } else if (toolBar.clicked(clickedOverlay) === cogButton) { + toolBar.selectTool(cogButton, true); settingsWindow.webWindow.setVisible(true); } }); From e0634de4032c7fce30606cf411b5f35ebe935b7f Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Tue, 21 Jul 2015 12:14:09 -0700 Subject: [PATCH 030/129] Turn on/off debug AO from menu item --- interface/src/Application.cpp | 2 ++ interface/src/Menu.h | 2 +- .../render-utils/src/AmbientOcclusionEffect.cpp | 14 ++++++++------ libraries/render-utils/src/RenderDeferredTask.cpp | 8 +++++++- libraries/render-utils/src/RenderDeferredTask.h | 5 +++++ libraries/render-utils/src/ambient_occlusion.slf | 5 +++-- libraries/render/src/render/Engine.h | 2 ++ 7 files changed, 28 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d5ac230f0c..891caa8418 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3336,6 +3336,8 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus(); + renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion); + renderArgs->_shouldRender = LODManager::shouldRender; renderContext.args = renderArgs; diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b6c2e47329..c8685fe714 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -134,7 +134,7 @@ namespace MenuOption { const QString AddressBar = "Show Address Bar"; const QString AlignForearmsWithWrists = "Align Forearms with Wrists"; const QString AlternateIK = "Alternate IK"; - const QString AmbientOcclusion = "Ambient Occlusion"; + const QString AmbientOcclusion = "Debug Ambient Occlusion"; const QString Animations = "Animations..."; const QString Atmosphere = "Atmosphere"; const QString Attachments = "Attachments..."; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index a6646d8e4a..2b1113d61b 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -193,8 +193,10 @@ const gpu::PipelinePointer& AmbientOcclusion::getOcclusionPipeline() { gpu::Shader::makeProgram(*program, slotBindings); - //_drawItemBoundPosLoc = program->getUniforms().findLocation("inBoundPos"); - //_drawItemBoundDimLoc = program->getUniforms().findLocation("inBoundDim"); + _gScaleLoc = program->getUniforms().findLocation("g_scale"); + _gBiasLoc = program->getUniforms().findLocation("g_bias"); + _gSampleRadiusLoc = program->getUniforms().findLocation("g_sample_rad"); + _gIntensityLoc = program->getUniforms().findLocation("g_intensity"); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -345,7 +347,7 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons // Occlusion step getOcclusionPipeline(); batch.setResourceTexture(0, DependencyManager::get()->getPrimaryDepthTexture()); - batch.setResourceTexture(1, DependencyManager::get()->getPrimaryFramebuffer()->getRenderBuffer(0)); + batch.setResourceTexture(1, DependencyManager::get()->getPrimaryNormalTexture()); _occlusionBuffer->setRenderBuffer(0, _occlusionTexture); batch.setFramebuffer(_occlusionBuffer); @@ -380,12 +382,12 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons batch.setPipeline(getHBlurPipeline()); DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); - + // "Blend" step - batch.setResourceTexture(0, _hBlurTexture); + batch.setResourceTexture(0, _occlusionTexture); batch.setFramebuffer(DependencyManager::get()->getPrimaryFramebuffer()); - // bind the fourth gpu::Pipeline we need - for + // bind the fourth gpu::Pipeline we need - for blending the primary framefuffer with blurred occlusion texture batch.setPipeline(getBlendPipeline()); glm::vec2 bottomLeftSmall(0.5f, -1.0f); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 1ab8a4ce01..eea343972e 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -61,6 +61,10 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred"))); _jobs.push_back(Job(new ResolveDeferred::JobModel("ResolveDeferred"))); _jobs.push_back(Job(new AmbientOcclusion::JobModel("AmbientOcclusion"))); + + _jobs.back().setEnabled(false); + _occlusionJobIndex = _jobs.size() - 1; + _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", FetchItems( ItemFilter::Builder::transparentShape().withoutLayered(), @@ -79,7 +83,6 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.back().setEnabled(false); _drawStatusJobIndex = _jobs.size() - 1; - //_jobs.push_back(Job(new AmbientOcclusion::JobModel("AmbientOcclusion"))); _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); _jobs.push_back(Job(new ResetGLState::JobModel())); @@ -110,6 +113,9 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend // Make sure we turn the displayItemStatus on/off setDrawItemStatus(renderContext->_drawItemStatus); + // TODO: turn on/off AO through menu item + setOcclusionStatus(renderContext->_occlusionStatus); + renderContext->args->_context->syncCache(); for (auto job : _jobs) { diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 4040606c62..5c9764eb52 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -75,6 +75,11 @@ public: void setDrawItemStatus(bool draw) { if (_drawStatusJobIndex >= 0) { _jobs[_drawStatusJobIndex].setEnabled(draw); } } bool doDrawItemStatus() const { if (_drawStatusJobIndex >= 0) { return _jobs[_drawStatusJobIndex].isEnabled(); } else { return false; } } + int _occlusionJobIndex = -1; + + void setOcclusionStatus(bool draw) { if (_occlusionJobIndex >= 0) { _jobs[_occlusionJobIndex].setEnabled(draw); } } + bool doOcclusionStatus() const { if (_occlusionJobIndex >= 0) { return _jobs[_occlusionJobIndex].isEnabled(); } else { return false; } } + virtual void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index 342f4148d2..10b687ad1f 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -39,8 +39,9 @@ void main(void) { float f = 30.0; // the far plane float c = (2.0 * n) / (f + n - z * (f - n)); // convert to linear values - //gl_FragColor = vec4(c, c, c, 1.0); - gl_FragColor = mix(depthColor, normalColor, normalColor.a); + vec4 linearizedDepthColor = vec4(c, c, c, 1.0); + gl_FragColor = mix(linearizedDepthColor, normalColor, 0.5); + //gl_FragColor = linearizedDepthColor; //vec3 p = getPosition(i.uv); //vec3 n = getNormal(i.uv); diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 1c600b13d6..5bfece96cc 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -51,6 +51,8 @@ public: bool _drawItemStatus = false; + bool _occlusionStatus = false; + RenderContext() {} }; typedef std::shared_ptr RenderContextPointer; From cd58dc11ceb92bf3a4c0e959a41f2ddaeb3a0f7c Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Tue, 21 Jul 2015 18:10:13 -0400 Subject: [PATCH 031/129] Initial file placement into job. --- .../jsstreamplayerdomain-zone-entity.js | 33 +++ examples/example/jsstreamplayerdomain-zone.js | 203 ++++++++++++++++++ examples/html/jsstreamplayerdomain-zone.html | 42 ++++ 3 files changed, 278 insertions(+) create mode 100644 examples/example/entities/jsstreamplayerdomain-zone-entity.js create mode 100644 examples/example/jsstreamplayerdomain-zone.js create mode 100644 examples/html/jsstreamplayerdomain-zone.html diff --git a/examples/example/entities/jsstreamplayerdomain-zone-entity.js b/examples/example/entities/jsstreamplayerdomain-zone-entity.js new file mode 100644 index 0000000000..9a8cb8b8b4 --- /dev/null +++ b/examples/example/entities/jsstreamplayerdomain-zone-entity.js @@ -0,0 +1,33 @@ +// +// #20628: JS Stream Player Domain-Zone-Entity +// ******************************************** +// +// Created by Kevin M. Thomas and Thoys 07/20/15. +// Copyright 2015 High Fidelity, Inc. +// kevintown.net +// +// JavaScript for the High Fidelity interface that is an entity script to be placed in a chosen entity inside a domain-zone. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +// Function which exists inside of an entity which triggers as a user approches it. +(function() { + const SCRIPT_NAME = "https://dl.dropboxusercontent.com/u/17344741/jsstreamplayer/jsstreamplayerdomain-zone.js"; + function isScriptRunning(script) { + script = script.toLowerCase().trim(); + var runningScripts = ScriptDiscoveryService.getRunning(); + for (i in runningScripts) { + if (runningScripts[i].url.toLowerCase().trim() == script) { + return true; + } + } + return false; + }; + + if (!isScriptRunning(SCRIPT_NAME)) { + Script.load(SCRIPT_NAME); + } +}) \ No newline at end of file diff --git a/examples/example/jsstreamplayerdomain-zone.js b/examples/example/jsstreamplayerdomain-zone.js new file mode 100644 index 0000000000..fab5792dd7 --- /dev/null +++ b/examples/example/jsstreamplayerdomain-zone.js @@ -0,0 +1,203 @@ +// +// #20628: JS Stream Player Domain-Zone +// ************************************* +// +// Created by Kevin M. Thomas and Thoys 07/20/15. +// Copyright 2015 High Fidelity, Inc. +// kevintown.net +// +// JavaScript for the High Fidelity interface that creates a stream player with a UI for playing a domain-zone specificed stream URL in addition to play, stop and volume functionality which is resident only in the domain-zone. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +// Declare variables and set up new WebWindow. +var stream = "http://listen.radionomy.com/80sMixTape"; +var volume; +var streamWindow = new WebWindow('Stream', "https://dl.dropboxusercontent.com/u/17344741/jsstreamplayer/jsstreamplayerdomain-zone.html", 0, 0, false); +var visible = false; + +// Set up toggleStreamPlayButton overlay. +var toggleStreamPlayButton = Overlays.addOverlay("text", { + x: 122, + y: 310, + width: 38, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + visible: false, + text: " Play" +}); + +// Set up toggleStreamStopButton overlay. +var toggleStreamStopButton = Overlays.addOverlay("text", { + x: 166, + y: 310, + width: 40, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + visible: false, + text: " Stop" +}); + +// Set up increaseVolumeButton overlay. +var toggleIncreaseVolumeButton = Overlays.addOverlay("text", { + x: 211, + y: 310, + width: 18, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + visible: false, + text: " +" +}); + +// Set up decreaseVolumeButton overlay. +var toggleDecreaseVolumeButton = Overlays.addOverlay("text", { + x: 234, + y: 310, + width: 15, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + visible: false, + text: " -" +}); + +// Function to change JSON object stream. +function changeStream(stream) { + var streamJSON = { + action: "changeStream", + stream: stream + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); +} + +// Function to change JSON object volume. +function changeVolume(volume) { + var volumeJSON = { + action: "changeVolume", + volume: volume + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(volumeJSON)); +} + +// Function that adds mousePressEvent functionality to connect UI to enter stream URL, play and stop stream. +function mousePressEvent(event) { + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamPlayButton) { + changeStream(stream); + volume = 0.25; + changeVolume(volume); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamStopButton) { + changeStream(""); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleIncreaseVolumeButton) { + volume += 0.25; + changeVolume(volume); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleDecreaseVolumeButton) { + volume -= 0.25; + changeVolume(volume); + } +} + +// Function checking bool if in proper zone. +function isOurZone(properties) { + return properties.type == "Zone" && properties.name == "Zone2"; +} + +// Function checking if avatar is in zone. +function isInZone() { + var entities = Entities.findEntities(MyAvatar.position, 10000); + + for (var i in entities) { + var properties = Entities.getEntityProperties(entities[i]); + + if (isOurZone(properties)) { + var minX = properties.position.x - (properties.dimensions.x / 2); + var maxX = properties.position.x + (properties.dimensions.x / 2); + var minY = properties.position.y - (properties.dimensions.y / 2); + var maxY = properties.position.y + (properties.dimensions.y / 2); + var minZ = properties.position.z - (properties.dimensions.z / 2); + var maxZ = properties.position.z + (properties.dimensions.z / 2); + + if (MyAvatar.position.x >= minX && MyAvatar.position.x <= maxX && MyAvatar.position.y >= minY && MyAvatar.position.y <= maxY && MyAvatar.position.z >= minZ && MyAvatar.position.z <= maxZ) { + return true; + } + } + } + return false; +} + +// Function to toggle visibile the overlay. +function toggleVisible(newVisibility) { + if (newVisibility != visible) { + visible = newVisibility; + Overlays.editOverlay(toggleStreamPlayButton, {visible: visible}); + Overlays.editOverlay(toggleStreamStopButton, {visible: visible}); + Overlays.editOverlay(toggleIncreaseVolumeButton, {visible: visible}); + Overlays.editOverlay(toggleDecreaseVolumeButton, {visible: visible}); + } +} + +// Function to check if avatar is in proper domain. +Window.domainChanged.connect(function() { + if (Window.location.hostname != "Music" && Window.location.hostname != "LiveMusic") { + Script.stop(); + } +}); + +// Function to check if avatar is within zone. +Entities.enterEntity.connect(function(entityID) { + print("Entered..." + JSON.stringify(entityID)); + var properties = Entities.getEntityProperties(entityID); + if (isOurZone(properties)) { + print("Entering Zone!"); + toggleVisible(true); + } +}) + +// Function to check if avatar is leaving zone. +Entities.leaveEntity.connect(function(entityID) { + print("Left..." + JSON.stringify(entityID)); + var properties = Entities.getEntityProperties(entityID); + if (isOurZone(properties)) { + print("Leaving Zone!"); + toggleVisible(false); + changeStream(""); + } +}) + +// Function to delete overlays upon exit. +function onScriptEnding() { + Overlays.deleteOverlay(toggleStreamPlayButton); + Overlays.deleteOverlay(toggleStreamStopButton); + Overlays.deleteOverlay(toggleIncreaseVolumeButton); + Overlays.deleteOverlay(toggleDecreaseVolumeButton); + changeStream(""); + streamWindow.deleteLater(); +} + +// Function call to ensure that if you log in to the zone visibility is true. +if (isInZone()) { + toggleVisible(true); +} + +// Connect mouse and hide WebWindow. +Controller.mousePressEvent.connect(mousePressEvent); +streamWindow.setVisible(false); + +// Call function upon ending script. +Script.scriptEnding.connect(onScriptEnding); \ No newline at end of file diff --git a/examples/html/jsstreamplayerdomain-zone.html b/examples/html/jsstreamplayerdomain-zone.html new file mode 100644 index 0000000000..28b2202591 --- /dev/null +++ b/examples/html/jsstreamplayerdomain-zone.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 75fa789b79591b25d6240479d74c671ba2eb0b2d Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Tue, 21 Jul 2015 18:13:26 -0400 Subject: [PATCH 032/129] Changeable zone var declaration. --- examples/example/jsstreamplayerdomain-zone.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/example/jsstreamplayerdomain-zone.js b/examples/example/jsstreamplayerdomain-zone.js index fab5792dd7..543a95b839 100644 --- a/examples/example/jsstreamplayerdomain-zone.js +++ b/examples/example/jsstreamplayerdomain-zone.js @@ -14,6 +14,7 @@ // Declare variables and set up new WebWindow. +var zone = "Zone2"; var stream = "http://listen.radionomy.com/80sMixTape"; var volume; var streamWindow = new WebWindow('Stream', "https://dl.dropboxusercontent.com/u/17344741/jsstreamplayer/jsstreamplayerdomain-zone.html", 0, 0, false); @@ -115,7 +116,7 @@ function mousePressEvent(event) { // Function checking bool if in proper zone. function isOurZone(properties) { - return properties.type == "Zone" && properties.name == "Zone2"; + return properties.type == "Zone" && properties.name == zone; } // Function checking if avatar is in zone. From 9ac4e2f6877f9bd56112b40d1fc39064427c43a8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 Jul 2015 18:22:27 -0700 Subject: [PATCH 033/129] Render spheres over avatar eyes if they're looking at me --- interface/src/avatar/Avatar.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 3a55e73fa6..f9a1185e24 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -448,36 +448,35 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo } } - // Stack indicator spheres - float indicatorOffset = 0.0f; - if (!_displayName.isEmpty() && _displayNameAlpha != 0.0f) { - const float DISPLAY_NAME_INDICATOR_OFFSET = 0.22f; - indicatorOffset = DISPLAY_NAME_INDICATOR_OFFSET; - } - const float INDICATOR_RADIUS = 0.03f; - const float INDICATOR_INDICATOR_OFFSET = 3.0f * INDICATOR_RADIUS; - // If this is the avatar being looked at, render a little ball above their head if (_isLookAtTarget && Menu::getInstance()->isOptionChecked(MenuOption::RenderFocusIndicator)) { + const float INDICATOR_OFFSET = 0.22f; + const float INDICATOR_RADIUS = 0.03f; const glm::vec4 LOOK_AT_INDICATOR_COLOR = { 0.8f, 0.0f, 0.0f, 0.75f }; - glm::vec3 position = glm::vec3(_position.x, getDisplayNamePosition().y + indicatorOffset, _position.z); + glm::vec3 position = glm::vec3(_position.x, getDisplayNamePosition().y + INDICATOR_OFFSET, _position.z); Transform transform; transform.setTranslation(position); batch.setModelTransform(transform); DependencyManager::get()->renderSolidSphere(batch, INDICATOR_RADIUS, 15, 15, LOOK_AT_INDICATOR_COLOR); - indicatorOffset += INDICATOR_INDICATOR_OFFSET; } - // If the avatar is looking at me, render an indication that they area + // If the avatar is looking at me, indicate that they are if (getHead()->getIsLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { - const glm::vec4 LOOKING_AT_ME_COLOR = { 0.8f, 0.65f, 0.0f, 0.1f }; - glm::vec3 position = glm::vec3(_position.x, getDisplayNamePosition().y + indicatorOffset, _position.z); + const glm::vec3 LOOKING_AT_ME_COLOR = { 1.0f, 1.0f, 1.0f }; + float alpha = 1.0f; + float radius = 0.035f; Transform transform; + glm::vec3 position = getHead()->getLeftEyePosition(); transform.setTranslation(position); batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, INDICATOR_RADIUS, - 15, 15, LOOKING_AT_ME_COLOR); + DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + position = getHead()->getRightEyePosition(); + transform.setTranslation(position); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); } // quick check before falling into the code below: From bed266dfe993469cb6252fccf90a6e48e00767a8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 Jul 2015 18:23:50 -0700 Subject: [PATCH 034/129] Fade looking-at-me eye spheres over half a second --- interface/src/avatar/Avatar.cpp | 31 ++++++++++++++++++------------- interface/src/avatar/Head.cpp | 4 ++++ interface/src/avatar/Head.h | 2 ++ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f9a1185e24..884540bf7c 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -464,19 +464,24 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo // If the avatar is looking at me, indicate that they are if (getHead()->getIsLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { const glm::vec3 LOOKING_AT_ME_COLOR = { 1.0f, 1.0f, 1.0f }; - float alpha = 1.0f; - float radius = 0.035f; - Transform transform; - glm::vec3 position = getHead()->getLeftEyePosition(); - transform.setTranslation(position); - batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); - position = getHead()->getRightEyePosition(); - transform.setTranslation(position); - batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + const float LOOKING_AT_ME_DURATION = 0.5f; // seconds + quint64 now = usecTimestampNow(); + float alpha = 1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) + / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND); + if (alpha > 0.0f) { + float radius = 0.035f; + Transform transform; + glm::vec3 position = getHead()->getLeftEyePosition(); + transform.setTranslation(position); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + position = getHead()->getRightEyePosition(); + transform.setTranslation(position); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + } } // quick check before falling into the code below: diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 43e68557ce..94a163e508 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -55,6 +55,7 @@ Head::Head(Avatar* owningAvatar) : _deltaLeanForward(0.0f), _isCameraMoving(false), _isLookingAtMe(false), + _isLookingAtMeStarted(0), _faceModel(this), _leftEyeLookAtID(DependencyManager::get()->allocateID()), _rightEyeLookAtID(DependencyManager::get()->allocateID()) @@ -323,6 +324,9 @@ glm::vec3 Head::getCorrectedLookAtPosition() { } void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { + if (!_isLookingAtMe) { + _isLookingAtMeStarted = usecTimestampNow(); + } _isLookingAtMe = true; _correctedLookAtPosition = correctedLookAtPosition; } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index d7a8462693..58f6f14b0a 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -53,6 +53,7 @@ public: glm::vec3 getCorrectedLookAtPosition(); void clearCorrectedLookAtPosition() { _isLookingAtMe = false; } bool getIsLookingAtMe() { return _isLookingAtMe; } + quint64 getIsLookingAtMeStarted() { return _isLookingAtMeStarted; } float getScale() const { return _scale; } glm::vec3 getPosition() const { return _position; } @@ -139,6 +140,7 @@ private: bool _isCameraMoving; bool _isLookingAtMe; + quint64 _isLookingAtMeStarted; FaceModel _faceModel; glm::vec3 _correctedLookAtPosition; From 55683e0cd589d353b7367a0aaaace23203d42229 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 Jul 2015 18:24:47 -0700 Subject: [PATCH 035/129] Size looking-at-me eye spheres per avatar model dimensions --- interface/src/avatar/Avatar.cpp | 14 +++++++++----- libraries/fbx/src/FBXReader.cpp | 9 ++++++++- libraries/fbx/src/FBXReader.h | 5 ++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 884540bf7c..ba0e0126ba 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -469,18 +469,22 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo float alpha = 1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND); if (alpha > 0.0f) { - float radius = 0.035f; + const float RADIUS_INCREMENT = 0.005f; Transform transform; + glm::vec3 position = getHead()->getLeftEyePosition(); transform.setTranslation(position); batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + DependencyManager::get()->renderSolidSphere(batch, + getHead()->getFaceModel().getGeometry()->getFBXGeometry().leftEyeSize * _scale / 2.0f + RADIUS_INCREMENT, + 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + position = getHead()->getRightEyePosition(); transform.setTranslation(position); batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + DependencyManager::get()->renderSolidSphere(batch, + getHead()->getFaceModel().getGeometry()->getFBXGeometry().rightEyeSize * _scale / 2.0f + RADIUS_INCREMENT, + 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); } } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 4d7bff4df0..466b3de3ee 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -2616,10 +2616,17 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, buildModelMesh(extracted); # endif + if (extracted.mesh.isEye) { + if (maxJointIndex == geometry.leftEyeJointIndex) { + geometry.leftEyeSize = extracted.mesh.meshExtents.largestDimension() * offsetScale; + } else { + geometry.rightEyeSize = extracted.mesh.meshExtents.largestDimension() * offsetScale; + } + } + geometry.meshes.append(extracted.mesh); int meshIndex = geometry.meshes.size() - 1; meshIDsToMeshIndices.insert(it.key(), meshIndex); - } // now that all joints have been scanned, compute a collision shape for each joint diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 200cd4a121..3b3d90eb05 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -232,7 +232,10 @@ public: int rightHandJointIndex = -1; int leftToeJointIndex = -1; int rightToeJointIndex = -1; - + + float leftEyeSize = 0.0f; // Maximum mesh extents dimension + float rightEyeSize = 0.0f; + QVector humanIKJointIndices; glm::vec3 palmDirection; From 87dbbdb2e8a4c740f9c37b76cdd6fcba2c4983c5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 Jul 2015 18:25:35 -0700 Subject: [PATCH 036/129] Set an initial alpha in anticipation of sphere alpha working --- interface/src/avatar/Avatar.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ba0e0126ba..6aa70196bd 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -464,10 +464,12 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo // If the avatar is looking at me, indicate that they are if (getHead()->getIsLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { const glm::vec3 LOOKING_AT_ME_COLOR = { 1.0f, 1.0f, 1.0f }; + const float LOOKING_AT_ME_ALPHA_START = 0.8f; const float LOOKING_AT_ME_DURATION = 0.5f; // seconds quint64 now = usecTimestampNow(); - float alpha = 1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) - / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND); + float alpha = LOOKING_AT_ME_ALPHA_START + * (1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) + / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND)); if (alpha > 0.0f) { const float RADIUS_INCREMENT = 0.005f; Transform transform; From de116c4e3b35b26f8014641074d84d6f2796d431 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 22 Jul 2015 10:21:13 +0200 Subject: [PATCH 037/129] editMode on and off switch by clicking the COG, proper removal of planks when rows/columns removed --- examples/example/games/planky.js | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/examples/example/games/planky.js b/examples/example/games/planky.js index 4181eb541e..8abc697353 100644 --- a/examples/example/games/planky.js +++ b/examples/example/games/planky.js @@ -203,20 +203,29 @@ PlankyStack = function() { dimensions: {x: 5, y: 21, z: 5}, position: Vec3.sum(_this.basePosition, {y: -(_this.options.baseDimension.y / 2)}), lineWidth: 7, - color: {red: 214, green: 91, blue: 67}, - linePoints: [{x: 0, y: 0, z: 0}, {x: 0, y: 10, z: 0}] + color: {red: 20, green: 20, blue: 20}, + linePoints: [{x: 0, y: 0, z: 0}, {x: 0, y: 10, z: 0}], + visible: editMode })); return; } + _this.editLines.forEach(function(line) { + Entities.editEntity(line, {visible: editMode}); + }) }; var trimDimension = function(dimension, maxIndex) { + var removingPlanks = []; _this.planks.forEach(function(plank, index, object) { if (plank[dimension] > maxIndex) { - Entities.deleteEntity(plank.entity); - object.splice(index, 1); + removingPlanks.push(index); } }); + removingPlanks.reverse(); + for (var i = 0; i < removingPlanks.length; i++) { + Entities.deleteEntity(_this.planks[removingPlanks[i]].entity); + _this.planks.splice(removingPlanks[i], 1); + } }; var createOrUpdate = function(layer, row) { @@ -237,7 +246,6 @@ PlankyStack = function() { dimensions: Vec3.sum(_this.options.blockSize, {x: 0, y: -((_this.options.blockSize.y * (_this.options.blockHeightVariation / MAXIMUM_PERCENTAGE)) * Math.random()), z: 0}), position: Vec3.sum(_this.basePosition, localTransform), rotation: Quat.multiply(layerRotation, _this.offsetRot), - //collisionsWillMove: false,//!editMode,//false,//!editMode, damping: _this.options.dampingFactor, restitution: _this.options.restitution, friction: _this.options.friction, @@ -282,7 +290,6 @@ PlankyStack = function() { if (!editMode) { _this.planks.forEach(function(plank, index, object) { Entities.editEntity(plank.entity, {ignoreForCollisions: false, collisionsWillMove: true}); - // Entities.editEntity(plank.entity, {collisionsWillMove: true}); }); } }; @@ -326,7 +333,7 @@ button = toolBar.addTool({ cogButton = toolBar.addTool({ width: BUTTON_DIMENSIONS.width, height: BUTTON_DIMENSIONS.height, - imageURL: "https://dl.dropboxusercontent.com/u/14997455/hifi/planky/cog.svg", //HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg', + imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg', subImage: { x: 0, y: BUTTON_DIMENSIONS.height, width: BUTTON_DIMENSIONS.width, height: BUTTON_DIMENSIONS.height }, alpha: 0.8, visible: true @@ -339,11 +346,14 @@ Controller.mousePressEvent.connect(function(event) { plankyStack.rez(); return; } - editMode = !editMode; plankyStack.refresh(); } else if (toolBar.clicked(clickedOverlay) === cogButton) { - toolBar.selectTool(cogButton, true); - settingsWindow.webWindow.setVisible(true); + editMode = !editMode; + toolBar.selectTool(cogButton, editMode); + settingsWindow.webWindow.setVisible(editMode); + if(plankyStack.planks.length) { + plankyStack.refresh(); + } } }); From e44cba500dc90ec00af72269be3a6df90dc06502 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 22 Jul 2015 09:52:49 -0700 Subject: [PATCH 038/129] Guard against head model not being available yet --- interface/src/avatar/Avatar.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 6aa70196bd..e30c2ac24d 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -471,22 +471,26 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo * (1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND)); if (alpha > 0.0f) { - const float RADIUS_INCREMENT = 0.005f; - Transform transform; + QSharedPointer geometry = getHead()->getFaceModel().getGeometry(); + if (geometry) { + const float RADIUS_INCREMENT = 0.005f; + Transform transform; - glm::vec3 position = getHead()->getLeftEyePosition(); - transform.setTranslation(position); - batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, - getHead()->getFaceModel().getGeometry()->getFBXGeometry().leftEyeSize * _scale / 2.0f + RADIUS_INCREMENT, - 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + glm::vec3 position = getHead()->getLeftEyePosition(); + transform.setTranslation(position); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphere(batch, + geometry->getFBXGeometry().leftEyeSize * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); - position = getHead()->getRightEyePosition(); - transform.setTranslation(position); - batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, - getHead()->getFaceModel().getGeometry()->getFBXGeometry().rightEyeSize * _scale / 2.0f + RADIUS_INCREMENT, - 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + position = getHead()->getRightEyePosition(); + transform.setTranslation(position); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphere(batch, + geometry->getFBXGeometry().rightEyeSize * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + + } } } From 9d33cfa9650eabbe07e54bcf027a8145ac083f7b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 22 Jul 2015 09:53:37 -0700 Subject: [PATCH 039/129] Allow for look-at positions being not quite up to date as avatars move So that looking-at-me indicators don't flicker on when they shouldn't. --- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/Head.cpp | 17 +++++++++++++---- interface/src/avatar/Head.h | 9 +++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e30c2ac24d..1fee720ad4 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -462,13 +462,13 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo } // If the avatar is looking at me, indicate that they are - if (getHead()->getIsLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { + if (getHead()->isLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { const glm::vec3 LOOKING_AT_ME_COLOR = { 1.0f, 1.0f, 1.0f }; const float LOOKING_AT_ME_ALPHA_START = 0.8f; const float LOOKING_AT_ME_DURATION = 0.5f; // seconds quint64 now = usecTimestampNow(); float alpha = LOOKING_AT_ME_ALPHA_START - * (1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) + * (1.0f - ((float)(usecTimestampNow() - getHead()->getLookingAtMeStarted())) / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND)); if (alpha > 0.0f) { QSharedPointer geometry = getHead()->getFaceModel().getGeometry(); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 94a163e508..d4ef793ab3 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -55,7 +55,8 @@ Head::Head(Avatar* owningAvatar) : _deltaLeanForward(0.0f), _isCameraMoving(false), _isLookingAtMe(false), - _isLookingAtMeStarted(0), + _lookingAtMeStarted(0), + _wasLastLookingAtMe(0), _faceModel(this), _leftEyeLookAtID(DependencyManager::get()->allocateID()), _rightEyeLookAtID(DependencyManager::get()->allocateID()) @@ -316,7 +317,7 @@ glm::quat Head::getFinalOrientationInLocalFrame() const { } glm::vec3 Head::getCorrectedLookAtPosition() { - if (_isLookingAtMe) { + if (isLookingAtMe()) { return _correctedLookAtPosition; } else { return getLookAtPosition(); @@ -324,13 +325,21 @@ glm::vec3 Head::getCorrectedLookAtPosition() { } void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { - if (!_isLookingAtMe) { - _isLookingAtMeStarted = usecTimestampNow(); + if (!isLookingAtMe()) { + _lookingAtMeStarted = usecTimestampNow(); } _isLookingAtMe = true; + _wasLastLookingAtMe = usecTimestampNow(); _correctedLookAtPosition = correctedLookAtPosition; } +bool Head::isLookingAtMe() { + // Allow for outages such as may be encountered during avatar movement + quint64 now = usecTimestampNow(); + const quint64 LOOKING_AT_ME_GAP_ALLOWED = 1000000; // microseconds + return _isLookingAtMe || (now - _wasLastLookingAtMe) < LOOKING_AT_ME_GAP_ALLOWED; +} + glm::quat Head::getCameraOrientation() const { // NOTE: Head::getCameraOrientation() is not used for orienting the camera "view" while in Oculus mode, so // you may wonder why this code is here. This method will be called while in Oculus mode to determine how diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 58f6f14b0a..a8161d1c7b 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -52,9 +52,9 @@ public: void setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition); glm::vec3 getCorrectedLookAtPosition(); void clearCorrectedLookAtPosition() { _isLookingAtMe = false; } - bool getIsLookingAtMe() { return _isLookingAtMe; } - quint64 getIsLookingAtMeStarted() { return _isLookingAtMeStarted; } - + bool isLookingAtMe(); + quint64 getLookingAtMeStarted() { return _lookingAtMeStarted; } + float getScale() const { return _scale; } glm::vec3 getPosition() const { return _position; } const glm::vec3& getEyePosition() const { return _eyePosition; } @@ -140,7 +140,8 @@ private: bool _isCameraMoving; bool _isLookingAtMe; - quint64 _isLookingAtMeStarted; + quint64 _lookingAtMeStarted; + quint64 _wasLastLookingAtMe; FaceModel _faceModel; glm::vec3 _correctedLookAtPosition; From 3cac781cdca985a1a81891f0af40bab61debba4f Mon Sep 17 00:00:00 2001 From: Bing Shearer Date: Wed, 22 Jul 2015 10:47:27 -0700 Subject: [PATCH 040/129] Fixed indentation and number formats, as well as streamlining calculation of leaf velocity to make it more readable. --- examples/leaves.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/examples/leaves.js b/examples/leaves.js index 347371ff5b..e611eb7de6 100755 --- a/examples/leaves.js +++ b/examples/leaves.js @@ -175,7 +175,7 @@ var leafSquall = function (properties) { } Script.setInterval(function () { nearbyEntities = Entities.findEntities(squallOrigin, squallRadius); - newLeafMovement() + newLeafMovement() }, 100); function newLeafMovement() { //new additions to leaf code. Operates at 10 Hz or every 100 ms @@ -193,20 +193,18 @@ var leafSquall = function (properties) { currentLeaf = nearbyEntities[i]; var leafHeight = entityProperties.position.y; if (complexMovement && leafHeight > floorHeight || complexMovement && floorHeight == null) { //actual new movement code; - var currentLeafVelocity = entityProperties.velocity, - currentLeafRot = entityProperties.rotation, + var leafCurrentVel = entityProperties.velocity, + leafCurrentRot = entityProperties.rotation, yVec = { x: 0, y: 1, z: 0 }, - leafYinWFVec = Vec3.multiplyQbyV(currentLeafRot, yVec), + leafYinWFVec = Vec3.multiplyQbyV(leafCurrentRot, yVec), leafLocalHorVec = Vec3.cross(leafYinWFVec, yVec), leafMostDownVec = Vec3.cross(leafYinWFVec, leafLocalHorVec), - leafDesiredVel = Vec3.multiply(leafMostDownVec, windFactor); + leafDesiredVel = Vec3.multiply(leafMostDownVec, windFactor), + leafVelDelt = Vec3.subtract(leafDesiredVel, leafCurrentVel), + leafNewVel = Vec3.sum(leafCurrentVel, Vec3.multiply(leafVelDelt, windFactor)); Entities.editEntity(currentLeaf, { angularVelocity: randomRotationSpeed, - velocity: { - x: (leafDesiredVel.x - currentLeafVelocity.x) * windFactor + currentLeafVelocity.x, - y: (leafDesiredVel.y - currentLeafVelocity.y) * windFactor + currentLeafVelocity.y, - z: (leafDesiredVel.z - currentLeafVelocity.z) * windFactor + currentLeafVelocity.z - } + velocity: leafNewVel }) } else if (leafHeight <= floorHeight) { @@ -274,8 +272,8 @@ var leafSquall1 = new leafSquall({ origin: { x: 3071.5, y: 2170, z: 6765.3 }, radius: 100, leavesPerMinute: 30, - leafSize: { x: 0.3, y: 0.00, z: .3}, - leafFallSpeed: .4, + leafSize: { x: 0.3, y: 0.00, z: 0.3}, + leafFallSpeed: 0.4, leafLifetime: 100, leafSpinMax: 30, debug: false, @@ -283,7 +281,7 @@ var leafSquall1 = new leafSquall({ leafDeleteOnTearDown: true, complexMovement: true, floorHeight: 2143.5, - windFactor: .5, + windFactor: 0.5, leafDeleteOnGround: false }); From 8f0893ba2153b5a10f22aa0cff4cd573de3063cf Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Wed, 22 Jul 2015 22:34:45 +0200 Subject: [PATCH 041/129] Added fileOnUrl to check if a texture exist at the location. It return the correct filename of where the texture lives. Added the url of the fix file to extractFBXGeometry and readFBX and updated the calls to readFBX to include the url of the fix file. So it now does not break existing content. Found a second place in the FBXReader.cpp where the RelativeFileName stripped out the dir location. --- interface/src/ModelPackager.cpp | 2 +- libraries/animation/src/AnimationCache.cpp | 2 +- libraries/fbx/src/FBXReader.cpp | 31 +++++++++++++++----- libraries/fbx/src/FBXReader.h | 4 +-- libraries/render-utils/src/GeometryCache.cpp | 2 +- tools/vhacd-util/src/VHACDUtil.cpp | 2 +- 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index 2864738f9c..09d572c31d 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -106,7 +106,7 @@ bool ModelPackager::loadModel() { } qCDebug(interfaceapp) << "Reading FBX file : " << _fbxInfo.filePath(); QByteArray fbxContents = fbx.readAll(); - _geometry = readFBX(fbxContents, QVariantHash()); + _geometry = readFBX(fbxContents, QVariantHash(), _fbxInfo.filePath()); // make sure we have some basic mappings populateBasicMapping(_mapping, _fbxInfo.filePath(), _geometry); diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 6c02ccbd2b..0aa5c34544 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -65,7 +65,7 @@ void AnimationReader::run() { QSharedPointer animation = _animation.toStrongRef(); if (!animation.isNull()) { QMetaObject::invokeMethod(animation.data(), "setGeometry", - Q_ARG(const FBXGeometry&, readFBX(_reply->readAll(), QVariantHash()))); + Q_ARG(const FBXGeometry&, readFBX(_reply->readAll(), QVariantHash(), _reply->property("url").toString()))); } _reply->deleteLater(); } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 24cbc983ed..554d56ee5a 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -1454,9 +1455,23 @@ void buildModelMesh(ExtractedMesh& extracted) { } #endif // USE_MODEL_MESH +QByteArray fileOnUrl(const QByteArray filenameString,const QString url) { + QString path = QFileInfo(url).path(); + QByteArray filename = filenameString; + QFileInfo checkFile(path + "/" + filename.replace('\\', '/')); + //check if the file exists at the RelativeFileName + if (checkFile.exists() && checkFile.isFile()) { + filename = filename.replace('\\', '/'); + } else { + // there is not texture at the filename. Assume it is in the root dir. + filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); + } + filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); + filename = filename.replace('\\', '/'); + return filename; +} - -FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { +FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QString url, bool loadLightmaps, float lightmapLevel) { QHash meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; @@ -1782,7 +1797,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, foreach (const FBXNode& subobject, object.children) { if (subobject.name == "RelativeFilename") { QByteArray filename = subobject.properties.at(0).toByteArray(); - filename = filename.replace('\\', '/'); + filename = fileOnUrl(filename, url); textureFilenames.insert(getID(object.properties), filename); } else if (subobject.name == "TextureName") { // trim the name from the timestamp @@ -1856,7 +1871,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, foreach (const FBXNode& subobject, object.children) { if (subobject.name == "RelativeFilename") { filename = subobject.properties.at(0).toByteArray(); - filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); + filename = fileOnUrl(filename, url); } else if (subobject.name == "Content" && !subobject.properties.isEmpty()) { content = subobject.properties.at(0).toByteArray(); @@ -2709,12 +2724,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, return geometry; } -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString url, bool loadLightmaps, float lightmapLevel) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); - return readFBX(&buffer, mapping, loadLightmaps, lightmapLevel); + return readFBX(&buffer, mapping, url, loadLightmaps, lightmapLevel); } -FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { - return extractFBXGeometry(parseFBX(device), mapping, loadLightmaps, lightmapLevel); +FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString url, bool loadLightmaps, float lightmapLevel) { + return extractFBXGeometry(parseFBX(device), mapping, url, loadLightmaps, lightmapLevel); } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 200cd4a121..cf86c304ac 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -268,10 +268,10 @@ Q_DECLARE_METATYPE(FBXGeometry) /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f); +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f); +FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); #endif // hifi_FBXReader_h diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 02e59bfa3a..3d32ba74ad 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -2185,7 +2185,7 @@ void GeometryReader::run() { } else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) { lightmapLevel = 3.5f; } - fbxgeo = readFBX(_reply, _mapping, grabLightmaps, lightmapLevel); + fbxgeo = readFBX(_reply, _mapping, _url.path(), grabLightmaps, lightmapLevel); } else if (_url.path().toLower().endsWith(".obj")) { fbxgeo = OBJReader().readOBJ(_reply, _mapping, &_url); } diff --git a/tools/vhacd-util/src/VHACDUtil.cpp b/tools/vhacd-util/src/VHACDUtil.cpp index f1ff0e9e4f..d775244b9c 100644 --- a/tools/vhacd-util/src/VHACDUtil.cpp +++ b/tools/vhacd-util/src/VHACDUtil.cpp @@ -38,7 +38,7 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) { if (filename.toLower().endsWith(".obj")) { result = OBJReader().readOBJ(fbxContents, QVariantHash()); } else if (filename.toLower().endsWith(".fbx")) { - result = readFBX(fbxContents, QVariantHash()); + result = readFBX(fbxContents, QVariantHash(), filename); } else { qDebug() << "unknown file extension"; return false; From 7c4f6b665bcd614cc6739fd1e28531621385cec4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 23 Jul 2015 11:04:58 -0700 Subject: [PATCH 042/129] Use a default eye diameter for models without eyes, e.g., the masks --- interface/src/avatar/Avatar.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index bf41449f13..9f457e558d 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -468,22 +468,29 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { if (alpha > 0.0f) { QSharedPointer geometry = getHead()->getFaceModel().getGeometry(); if (geometry) { + const float DEFAULT_EYE_DIAMETER = 0.048f; // Typical human eye const float RADIUS_INCREMENT = 0.005f; Transform transform; glm::vec3 position = getHead()->getLeftEyePosition(); transform.setTranslation(position); batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, - geometry->getFBXGeometry().leftEyeSize * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + float eyeDiameter = geometry->getFBXGeometry().leftEyeSize; + if (eyeDiameter == 0.0f) { + eyeDiameter = DEFAULT_EYE_DIAMETER; + } + DependencyManager::get()->renderSolidSphere(batch, + eyeDiameter * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); position = getHead()->getRightEyePosition(); transform.setTranslation(position); batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, - geometry->getFBXGeometry().rightEyeSize * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + eyeDiameter = geometry->getFBXGeometry().rightEyeSize; + if (eyeDiameter == 0.0f) { + eyeDiameter = DEFAULT_EYE_DIAMETER; + } + DependencyManager::get()->renderSolidSphere(batch, + eyeDiameter * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); } } From 216c499d1472abecc29968bd9f2ba6b0aa7be7ac Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Thu, 23 Jul 2015 18:53:43 -0700 Subject: [PATCH 043/129] HAO (Horrendous Ambient Occlusion) --- .../src/AmbientOcclusionEffect.cpp | 114 ++++++++++++------ .../render-utils/src/AmbientOcclusionEffect.h | 17 +++ .../render-utils/src/ambient_occlusion.slf | 104 ++++++++++++---- .../render-utils/src/occlusion_blend.slf | 13 +- .../render-utils/src/occlusion_result.slf | 23 ++++ 5 files changed, 211 insertions(+), 60 deletions(-) create mode 100644 libraries/render-utils/src/occlusion_result.slf diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 2b1113d61b..e4220243ff 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -2,7 +2,7 @@ // AmbientOcclusionEffect.cpp // interface/src/renderer // -// Created by Andrzej Kapolka on 7/14/13. +// Created by Niraj Venkat on 7/14/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -19,10 +19,11 @@ #include #include -#include "AbstractViewStateInterface.h" +#include "gpu/StandardShaderLib.h" #include "AmbientOcclusionEffect.h" #include "RenderUtil.h" #include "TextureCache.h" +#include "FramebufferCache.h" #include "DependencyManager.h" #include "ViewFrustum.h" #include "GeometryCache.h" @@ -34,9 +35,8 @@ #include "gaussian_blur_frag.h" #include "occlusion_blend_vert.h" #include "occlusion_blend_frag.h" - -const int ROTATION_WIDTH = 4; -const int ROTATION_HEIGHT = 4; +//#include "occlusion_result_vert.h" +#include "occlusion_result_frag.h" /* void AmbientOcclusionEffect::init(AbstractViewStateInterface* viewState) { @@ -197,6 +197,8 @@ const gpu::PipelinePointer& AmbientOcclusion::getOcclusionPipeline() { _gBiasLoc = program->getUniforms().findLocation("g_bias"); _gSampleRadiusLoc = program->getUniforms().findLocation("g_sample_rad"); _gIntensityLoc = program->getUniforms().findLocation("g_intensity"); + _bufferWidthLoc = program->getUniforms().findLocation("bufferWidth"); + _bufferHeightLoc = program->getUniforms().findLocation("bufferHeight"); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -209,7 +211,7 @@ const gpu::PipelinePointer& AmbientOcclusion::getOcclusionPipeline() { // Link the occlusion FBO to texture _occlusionBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, - DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); auto width = _occlusionBuffer->getWidth(); auto height = _occlusionBuffer->getHeight(); @@ -242,7 +244,7 @@ const gpu::PipelinePointer& AmbientOcclusion::getVBlurPipeline() { // Link the horizontal blur FBO to texture _vBlurBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, - DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); auto width = _vBlurBuffer->getWidth(); auto height = _vBlurBuffer->getHeight(); @@ -275,7 +277,7 @@ const gpu::PipelinePointer& AmbientOcclusion::getHBlurPipeline() { // Link the horizontal blur FBO to texture _hBlurBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, - DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); auto width = _hBlurBuffer->getWidth(); auto height = _hBlurBuffer->getHeight(); @@ -295,6 +297,9 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("blurredOcclusionTexture"), 0)); + slotBindings.insert(gpu::Shader::Binding(std::string("colorTexture"), 1)); + gpu::Shader::makeProgram(*program, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -303,17 +308,16 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { // Blend on transparent state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - // Link the horizontal blur FBO to texture - _hBlurBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, - DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + // Link the blend FBO to texture + _blendBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - auto width = _hBlurBuffer->getWidth(); - auto height = _hBlurBuffer->getHeight(); + auto width = _blendBuffer->getWidth(); + auto height = _blendBuffer->getHeight(); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - _hBlurTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + _blendTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); // Good to go add the brand new pipeline _blendPipeline.reset(gpu::Pipeline::create(program, state)); @@ -321,38 +325,67 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { return _blendPipeline; } +const gpu::PipelinePointer& AmbientOcclusion::getAOResultPipeline() { + if (!_AOResultPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(ambient_occlusion_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(occlusion_result_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + //gpu::ShaderPointer program = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawTransformUnitQuadVS(), gpu::StandardShaderLib::getDrawTexturePS()); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(false, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + // Good to go add the brand new pipeline + _AOResultPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _AOResultPipeline; +} + void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { - - // create a simple pipeline that does: - assert(renderContext->args); assert(renderContext->args->_viewFrustum); RenderArgs* args = renderContext->args; auto& scene = sceneContext->_scene; - // Allright, something to render let's do it gpu::Batch batch; glm::mat4 projMat; Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); - if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); - } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); // Occlusion step getOcclusionPipeline(); - batch.setResourceTexture(0, DependencyManager::get()->getPrimaryDepthTexture()); - batch.setResourceTexture(1, DependencyManager::get()->getPrimaryNormalTexture()); + batch.setResourceTexture(0, DependencyManager::get()->getPrimaryDepthTexture()); + batch.setResourceTexture(1, DependencyManager::get()->getPrimaryNormalTexture()); _occlusionBuffer->setRenderBuffer(0, _occlusionTexture); batch.setFramebuffer(_occlusionBuffer); - // bind the first gpu::Pipeline we need - for calculating occlusion buffer + // Occlusion uniforms + g_scale = 1.0f; + g_bias = 1.0f; + g_sample_rad = 1.0f; + g_intensity = 1.0f; + + // Bind the first gpu::Pipeline we need - for calculating occlusion buffer batch.setPipeline(getOcclusionPipeline()); + batch._glUniform1f(_gScaleLoc, g_scale); + batch._glUniform1f(_gBiasLoc, g_bias); + batch._glUniform1f(_gSampleRadiusLoc, g_sample_rad); + batch._glUniform1f(_gIntensityLoc, g_intensity); + batch._glUniform1f(_bufferWidthLoc, DependencyManager::get()->getFrameBufferSize().width()); + batch._glUniform1f(_bufferHeightLoc, DependencyManager::get()->getFrameBufferSize().height()); glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); glm::vec2 bottomLeft(-1.0f, -1.0f); @@ -367,7 +400,7 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons _vBlurBuffer->setRenderBuffer(0, _vBlurTexture); batch.setFramebuffer(_vBlurBuffer); - // bind the second gpu::Pipeline we need - for calculating blur buffer + // Bind the second gpu::Pipeline we need - for calculating blur buffer batch.setPipeline(getVBlurPipeline()); DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); @@ -378,29 +411,38 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons _hBlurBuffer->setRenderBuffer(0, _hBlurTexture); batch.setFramebuffer(_hBlurBuffer); - // bind the third gpu::Pipeline we need - for calculating blur buffer + // Bind the third gpu::Pipeline we need - for calculating blur buffer batch.setPipeline(getHBlurPipeline()); DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); - // "Blend" step - batch.setResourceTexture(0, _occlusionTexture); - batch.setFramebuffer(DependencyManager::get()->getPrimaryFramebuffer()); + // Blend step + getBlendPipeline(); + batch.setResourceTexture(0, _hBlurTexture); + batch.setResourceTexture(1, DependencyManager::get()->getPrimaryColorTexture()); + batch.setFramebuffer(_blendBuffer); - // bind the fourth gpu::Pipeline we need - for blending the primary framefuffer with blurred occlusion texture + // Bind the fourth gpu::Pipeline we need - for blending the primary color buffer with blurred occlusion texture batch.setPipeline(getBlendPipeline()); + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + + // Final AO result step + getAOResultPipeline(); + batch.setResourceTexture(0, _hBlurTexture); + batch.setFramebuffer(DependencyManager::get()->getPrimaryFramebuffer()); + + // Bind the fifth gpu::Pipeline we need - for displaying the blended texture + batch.setPipeline(getAOResultPipeline()); + glm::vec2 bottomLeftSmall(0.5f, -1.0f); glm::vec2 topRightSmall(1.0f, -0.5f); - DependencyManager::get()->renderQuad(batch, bottomLeftSmall, topRightSmall, texCoordTopLeft, texCoordBottomRight, color); + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); // Ready to render args->_context->syncCache(); - renderContext->args->_context->syncCache(); args->_context->render((batch)); // need to fetch forom the z buffer and render something in a new render target a result that combine the z and produce a fake AO result - - } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index d38624f24c..ec0314016c 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -28,21 +28,38 @@ public: const gpu::PipelinePointer& getHBlurPipeline(); const gpu::PipelinePointer& getVBlurPipeline(); const gpu::PipelinePointer& getBlendPipeline(); + const gpu::PipelinePointer& getAOResultPipeline(); private: + // Uniforms for AO + gpu::int32 _gScaleLoc; + gpu::int32 _gBiasLoc; + gpu::int32 _gSampleRadiusLoc; + gpu::int32 _gIntensityLoc; + gpu::int32 _bufferWidthLoc; + gpu::int32 _bufferHeightLoc; + float g_scale; + float g_bias; + float g_sample_rad; + float g_intensity; + gpu::PipelinePointer _occlusionPipeline; gpu::PipelinePointer _hBlurPipeline; gpu::PipelinePointer _vBlurPipeline; gpu::PipelinePointer _blendPipeline; + gpu::PipelinePointer _AOResultPipeline; gpu::FramebufferPointer _occlusionBuffer; gpu::FramebufferPointer _hBlurBuffer; gpu::FramebufferPointer _vBlurBuffer; + gpu::FramebufferPointer _blendBuffer; gpu::TexturePointer _occlusionTexture; gpu::TexturePointer _hBlurTexture; gpu::TexturePointer _vBlurTexture; + gpu::TexturePointer _blendTexture; + }; #endif // hifi_AmbientOcclusionEffect_h diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index 10b687ad1f..023fe2552c 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -14,36 +14,96 @@ <@include DeferredBufferWrite.slh@> +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + varying vec2 varTexcoord; uniform sampler2D depthTexture; uniform sampler2D normalTexture; -float getRandom(vec2 co) { - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); +uniform float g_scale; +uniform float g_bias; +uniform float g_sample_rad; +uniform float g_intensity; +uniform float bufferWidth; +uniform float bufferHeight; + +#define SAMPLE_COUNT 4 + +float getRandom(vec2 uv) { + return fract(sin(dot(uv.xy ,vec2(12.9898,78.233))) * 43758.5453); } -/* -float doAmbientOcclusion(vec2 tcoord, vec2 uv, vec3 p, vec3 cnorm) { - vec3 diff = getPosition(tcoord + uv) - p; - vec3 v = normalize(diff); - float d = length(diff) * g_scale; - return max(0.0, dot(cnorm, v) - g_bias) * (1.0/(1.0 + d)) * g_intensity; -} -*/ + void main(void) { + vec3 sampleKernel[4] = { vec3(0.2, 0.0, 0.0), + vec3(0.0, 0.2, 0.0), + vec3(0.0, 0.0, 0.2), + vec3(0.2, 0.2, 0.2) }; - vec4 depthColor = texture2D(depthTexture, varTexcoord.xy); - vec4 normalColor = texture2D(normalTexture, varTexcoord.xy); - float z = depthColor.r; // fetch the z-value from our depth texture - float n = 1.0; // the near plane - float f = 30.0; // the far plane - float c = (2.0 * n) / (f + n - z * (f - n)); // convert to linear values + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); - vec4 linearizedDepthColor = vec4(c, c, c, 1.0); - gl_FragColor = mix(linearizedDepthColor, normalColor, 0.5); - //gl_FragColor = linearizedDepthColor; + vec3 eyeDir = vec3(0.0); + vec3 cameraPositionWorldSpace; + <$transformEyeToWorldDir(cam, eyeDir, cameraPositionWorldSpace)$> - //vec3 p = getPosition(i.uv); - //vec3 n = getNormal(i.uv); - //vec2 rand = vec2(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx)); + vec4 depthColor = texture2D(depthTexture, varTexcoord); + + // z in non linear range [0,1] + float depthVal = depthColor.r; + // conversion into NDC [-1,1] + float zNDC = depthVal * 2.0 - 1.0; + float n = 1.0; // the near plane + float f = 30.0; // the far plane + float l = -1.0; // left + float r = 1.0; // right + float b = -1.0; // bottom + float t = 1.0; // top + + // conversion into eye space + float zEye = 2*f*n / (zNDC*(f-n)-(f+n)); + // Converting from pixel coordinates to NDC + float xNDC = gl_FragCoord.x/bufferWidth * 2.0 - 1.0; + float yNDC = gl_FragCoord.y/bufferHeight * 2.0 - 1.0; + // Unprojecting X and Y from NDC to eye space + float xEye = -zEye*(xNDC*(r-l)+(r+l))/(2.0*n); + float yEye = -zEye*(yNDC*(t-b)+(t+b))/(2.0*n); + vec3 currentFragEyeSpace = vec3(xEye, yEye, zEye); + vec3 currentFragWorldSpace; + <$transformEyeToWorldDir(cam, currentFragEyeSpace, currentFragWorldSpace)$> + + vec3 cameraToPositionRay = normalize(currentFragWorldSpace - cameraPositionWorldSpace); + vec3 origin = cameraToPositionRay * depthVal + cameraPositionWorldSpace; + + vec3 normal = normalize(texture2D(normalTexture, varTexcoord).xyz); + //normal = normalize(normal * normalMatrix); + + vec3 rvec = vec3(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx), getRandom(varTexcoord.xx)) * 2.0 - 1.0; + vec3 tangent = normalize(rvec - normal * dot(rvec, normal)); + vec3 bitangent = cross(normal, tangent); + mat3 tbn = mat3(tangent, bitangent, normal); + + float occlusion = 0.0; + + for (int i = 0; i < SAMPLE_COUNT; ++i) { + vec3 samplePos = origin + (tbn * sampleKernel[i]) * g_sample_rad; + vec4 offset = cam._projectionViewUntranslated * vec4(samplePos, 1.0); + + offset.xy = (offset.xy / offset.w) * 0.5 + 0.5; + float depth = length(samplePos - cameraPositionWorldSpace); + + float sampleDepthVal = texture2D(depthTexture, offset.xy).r; + + float rangeDelta = abs(depthVal - sampleDepthVal); + float rangeCheck = smoothstep(0.0, 1.0, g_sample_rad / rangeDelta); + + occlusion += rangeCheck * step(sampleDepthVal, depth); + } + + occlusion = 1.0 - occlusion / float(SAMPLE_COUNT); + occlusion = clamp(pow(occlusion, g_intensity), 0.0, 1.0); + gl_FragColor = vec4(occlusion, occlusion, occlusion, 1.0); } + diff --git a/libraries/render-utils/src/occlusion_blend.slf b/libraries/render-utils/src/occlusion_blend.slf index 30d3173f90..64103e38c9 100644 --- a/libraries/render-utils/src/occlusion_blend.slf +++ b/libraries/render-utils/src/occlusion_blend.slf @@ -17,8 +17,17 @@ varying vec2 varTexcoord; uniform sampler2D blurredOcclusionTexture; +uniform sampler2D colorTexture; void main(void) { - vec4 depthColor = texture2D(blurredOcclusionTexture, varTexcoord.xy); - gl_FragColor = depthColor; + vec4 occlusionColor = texture2D(blurredOcclusionTexture, varTexcoord); + vec4 currentColor = texture2D(colorTexture, varTexcoord); + + if(occlusionColor.r == 1.0) { + gl_FragColor = currentColor; + } + else { + gl_FragColor = mix(occlusionColor, currentColor, 0.5); + } + gl_FragColor = occlusionColor; } diff --git a/libraries/render-utils/src/occlusion_result.slf b/libraries/render-utils/src/occlusion_result.slf new file mode 100644 index 0000000000..3b7e895dc6 --- /dev/null +++ b/libraries/render-utils/src/occlusion_result.slf @@ -0,0 +1,23 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// occlusion_result.frag +// fragment shader +// +// Created by Niraj Venkat on 7/23/15. +// Copyright 2015 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 +// + +<@include DeferredBufferWrite.slh@> + +varying vec2 varTexcoord; + +uniform sampler2D resultTexture; + +void main(void) { + gl_FragColor = texture2D(resultTexture, varTexcoord); +} From 28e6a4ac6331f9810c300eb032b0ae44c4eb6d89 Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Fri, 24 Jul 2015 09:36:35 -0400 Subject: [PATCH 044/129] Updating master as old job related to AudioClient.h was incorretly included with current job. --- libraries/audio-client/src/AudioClient.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 3a85adbc97..aeea7c07c1 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -55,9 +55,9 @@ static const int NUM_AUDIO_CHANNELS = 2; -static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; +static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; -static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 40; +static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; #if defined(Q_OS_ANDROID) || defined(Q_OS_WIN) static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = false; #else From 3893add1487143b6d79f1012f612a250242f29a1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 24 Jul 2015 10:43:24 -0700 Subject: [PATCH 045/129] Fix setting WebWindow's width and height Width and height parameters now set the WebWindow's width and height instead of its minimum size, when not part of a tool window. --- interface/src/scripting/WebWindowClass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index 3bd7e390ec..f187de95d2 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -57,7 +57,7 @@ WebWindowClass::WebWindowClass(const QString& title, const QString& url, int wid } else { auto dialogWidget = new QDialog(Application::getInstance()->getWindow(), Qt::Window); dialogWidget->setWindowTitle(title); - dialogWidget->setMinimumSize(width, height); + dialogWidget->resize(width, height); connect(dialogWidget, &QDialog::finished, this, &WebWindowClass::hasClosed); auto layout = new QVBoxLayout(dialogWidget); From fc612ab8cd03997dc767df3e4e72a0240ab22ffe Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Fri, 24 Jul 2015 11:29:52 -0700 Subject: [PATCH 046/129] Merge conflict fix --- interface/src/Application.cpp | 5 ----- libraries/render-utils/src/AmbientOcclusionEffect.cpp | 1 - 2 files changed, 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4d2fcbce11..3ba66cf2a0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3287,11 +3287,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se sceneInterface->setEngineDrawnOverlay3DItems(engineRC->_numDrawnOverlay3DItems); } - //Render the sixense lasers - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { - _myAvatar->renderLaserPointers(*renderArgs->_batch); - } - if (!selfAvatarOnly) { // give external parties a change to hook in { diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index f46ae1719b..d8b56f5ba1 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -21,7 +21,6 @@ #include "gpu/StandardShaderLib.h" #include "AmbientOcclusionEffect.h" -#include "RenderUtil.h" #include "TextureCache.h" #include "FramebufferCache.h" #include "DependencyManager.h" From 67c9a33cc0a0b57d79d957adb176c56976dbe68e Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Fri, 24 Jul 2015 15:16:02 -0400 Subject: [PATCH 047/129] Update Menu.cpp --- interface/src/Menu.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d5f4d78f5b..91ae6a4d02 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -487,14 +487,10 @@ Menu::Menu() { #endif MenuWrapper* networkMenu = developerMenu->addMenu("Network"); -<<<<<<< HEAD addActionToQMenuAndActionHash(networkMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); - addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableNackPackets, 0, false); -======= addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableNackPackets, 0, false, qApp->getEntityEditPacketSender(), SLOT(toggleNackPackets())); ->>>>>>> f3dc159e336b7b580bbd39b367802b0099e66ccb addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableActivityLogger, 0, From ddada17b08bfa12219eb7f04b5f60966b28c9c46 Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Fri, 24 Jul 2015 15:27:16 -0400 Subject: [PATCH 048/129] move jsstreamplayer.html into example/html move jssstreamplayer.js script into example/example/audio --- examples/jsstreamplayer.js | 142 ------------------------------------- 1 file changed, 142 deletions(-) delete mode 100644 examples/jsstreamplayer.js diff --git a/examples/jsstreamplayer.js b/examples/jsstreamplayer.js deleted file mode 100644 index 6bd941f677..0000000000 --- a/examples/jsstreamplayer.js +++ /dev/null @@ -1,142 +0,0 @@ -// -// #20622: JS Stream Player -// ************************* -// -// Created by Kevin M. Thomas and Thoys 07/17/15. -// Copyright 2015 High Fidelity, Inc. -// kevintown.net -// -// JavaScript for the High Fidelity interface that creates a stream player with a UI and keyPressEvents for adding a stream URL in addition to play, stop and volume functionality. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - - -// Declare variables and set up new WebWindow. -var stream; -var volume = 1; -var streamWindow = new WebWindow('Stream', "https://dl.dropboxusercontent.com/u/17344741/jsstreamplayer/jsstreamplayer.html", 0, 0, false); - -// Set up toggleStreamURLButton overlay. -var toggleStreamURLButton = Overlays.addOverlay("text", { - x: 76, - y: 275, - width: 40, - height: 28, - backgroundColor: {red: 0, green: 0, blue: 0}, - color: {red: 255, green: 255, blue: 0}, - font: {size: 15}, - topMargin: 8, - text: " URL" -}); - -// Set up toggleStreamPlayButton overlay. -var toggleStreamPlayButton = Overlays.addOverlay("text", { - x: 122, - y: 275, - width: 38, - height: 28, - backgroundColor: { red: 0, green: 0, blue: 0}, - color: { red: 255, green: 255, blue: 0}, - font: {size: 15}, - topMargin: 8, - text: " Play" -}); - -// Set up toggleStreamStopButton overlay. -var toggleStreamStopButton = Overlays.addOverlay("text", { - x: 166, - y: 275, - width: 40, - height: 28, - backgroundColor: { red: 0, green: 0, blue: 0}, - color: { red: 255, green: 255, blue: 0}, - font: {size: 15}, - topMargin: 8, - text: " Stop" -}); - -// Set up increaseVolumeButton overlay. -var toggleIncreaseVolumeButton = Overlays.addOverlay("text", { - x: 211, - y: 275, - width: 18, - height: 28, - backgroundColor: { red: 0, green: 0, blue: 0}, - color: { red: 255, green: 255, blue: 0}, - font: {size: 15}, - topMargin: 8, - text: " +" -}); - -// Set up decreaseVolumeButton overlay. -var toggleDecreaseVolumeButton = Overlays.addOverlay("text", { - x: 234, - y: 275, - width: 15, - height: 28, - backgroundColor: { red: 0, green: 0, blue: 0}, - color: { red: 255, green: 255, blue: 0}, - font: {size: 15}, - topMargin: 8, - text: " -" -}); - -// Function that adds mousePressEvent functionality to connect UI to enter stream URL, play and stop stream. -function mousePressEvent(event) { - if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamURLButton) { - stream = Window.prompt("Enter Stream: "); - var streamJSON = { - action: "changeStream", - stream: stream - } - streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); - } - if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamPlayButton) { - var streamJSON = { - action: "changeStream", - stream: stream - } - streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); - } - if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamStopButton) { - var streamJSON = { - action: "changeStream", - stream: "" - } - streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); - } - if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleIncreaseVolumeButton) { - volume += 0.2; - var volumeJSON = { - action: "changeVolume", - volume: volume - } - streamWindow.eventBridge.emitScriptEvent(JSON.stringify(volumeJSON)); - } - if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleDecreaseVolumeButton) { - volume -= 0.2; - var volumeJSON = { - action: "changeVolume", - volume: volume - } - streamWindow.eventBridge.emitScriptEvent(JSON.stringify(volumeJSON)); - } -} - -// Call function. -Controller.mousePressEvent.connect(mousePressEvent); -streamWindow.setVisible(false); - -// Function to delete overlays upon exit. -function onScriptEnding() { - Overlays.deleteOverlay(toggleStreamURLButton); - Overlays.deleteOverlay(toggleStreamPlayButton); - Overlays.deleteOverlay(toggleStreamStopButton); - Overlays.deleteOverlay(toggleIncreaseVolumeButton); - Overlays.deleteOverlay(toggleDecreaseVolumeButton); -} - -// Call function. -Script.scriptEnding.connect(onScriptEnding); \ No newline at end of file From d4d5c9f9359729cf97bec92cd5a920f1730529b6 Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Fri, 24 Jul 2015 15:43:50 -0400 Subject: [PATCH 049/129] Created a folder in examples called "zones" then moved files to location. --- examples/example/jsstreamplayerdomain-zone.js | 204 ------------------ examples/html/jsstreamplayerdomain-zone.html | 42 ---- 2 files changed, 246 deletions(-) delete mode 100644 examples/example/jsstreamplayerdomain-zone.js delete mode 100644 examples/html/jsstreamplayerdomain-zone.html diff --git a/examples/example/jsstreamplayerdomain-zone.js b/examples/example/jsstreamplayerdomain-zone.js deleted file mode 100644 index 543a95b839..0000000000 --- a/examples/example/jsstreamplayerdomain-zone.js +++ /dev/null @@ -1,204 +0,0 @@ -// -// #20628: JS Stream Player Domain-Zone -// ************************************* -// -// Created by Kevin M. Thomas and Thoys 07/20/15. -// Copyright 2015 High Fidelity, Inc. -// kevintown.net -// -// JavaScript for the High Fidelity interface that creates a stream player with a UI for playing a domain-zone specificed stream URL in addition to play, stop and volume functionality which is resident only in the domain-zone. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - - -// Declare variables and set up new WebWindow. -var zone = "Zone2"; -var stream = "http://listen.radionomy.com/80sMixTape"; -var volume; -var streamWindow = new WebWindow('Stream', "https://dl.dropboxusercontent.com/u/17344741/jsstreamplayer/jsstreamplayerdomain-zone.html", 0, 0, false); -var visible = false; - -// Set up toggleStreamPlayButton overlay. -var toggleStreamPlayButton = Overlays.addOverlay("text", { - x: 122, - y: 310, - width: 38, - height: 28, - backgroundColor: { red: 0, green: 0, blue: 0}, - color: { red: 255, green: 255, blue: 0}, - font: {size: 15}, - topMargin: 8, - visible: false, - text: " Play" -}); - -// Set up toggleStreamStopButton overlay. -var toggleStreamStopButton = Overlays.addOverlay("text", { - x: 166, - y: 310, - width: 40, - height: 28, - backgroundColor: { red: 0, green: 0, blue: 0}, - color: { red: 255, green: 255, blue: 0}, - font: {size: 15}, - topMargin: 8, - visible: false, - text: " Stop" -}); - -// Set up increaseVolumeButton overlay. -var toggleIncreaseVolumeButton = Overlays.addOverlay("text", { - x: 211, - y: 310, - width: 18, - height: 28, - backgroundColor: { red: 0, green: 0, blue: 0}, - color: { red: 255, green: 255, blue: 0}, - font: {size: 15}, - topMargin: 8, - visible: false, - text: " +" -}); - -// Set up decreaseVolumeButton overlay. -var toggleDecreaseVolumeButton = Overlays.addOverlay("text", { - x: 234, - y: 310, - width: 15, - height: 28, - backgroundColor: { red: 0, green: 0, blue: 0}, - color: { red: 255, green: 255, blue: 0}, - font: {size: 15}, - topMargin: 8, - visible: false, - text: " -" -}); - -// Function to change JSON object stream. -function changeStream(stream) { - var streamJSON = { - action: "changeStream", - stream: stream - } - streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); -} - -// Function to change JSON object volume. -function changeVolume(volume) { - var volumeJSON = { - action: "changeVolume", - volume: volume - } - streamWindow.eventBridge.emitScriptEvent(JSON.stringify(volumeJSON)); -} - -// Function that adds mousePressEvent functionality to connect UI to enter stream URL, play and stop stream. -function mousePressEvent(event) { - if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamPlayButton) { - changeStream(stream); - volume = 0.25; - changeVolume(volume); - } - if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamStopButton) { - changeStream(""); - } - if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleIncreaseVolumeButton) { - volume += 0.25; - changeVolume(volume); - } - if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleDecreaseVolumeButton) { - volume -= 0.25; - changeVolume(volume); - } -} - -// Function checking bool if in proper zone. -function isOurZone(properties) { - return properties.type == "Zone" && properties.name == zone; -} - -// Function checking if avatar is in zone. -function isInZone() { - var entities = Entities.findEntities(MyAvatar.position, 10000); - - for (var i in entities) { - var properties = Entities.getEntityProperties(entities[i]); - - if (isOurZone(properties)) { - var minX = properties.position.x - (properties.dimensions.x / 2); - var maxX = properties.position.x + (properties.dimensions.x / 2); - var minY = properties.position.y - (properties.dimensions.y / 2); - var maxY = properties.position.y + (properties.dimensions.y / 2); - var minZ = properties.position.z - (properties.dimensions.z / 2); - var maxZ = properties.position.z + (properties.dimensions.z / 2); - - if (MyAvatar.position.x >= minX && MyAvatar.position.x <= maxX && MyAvatar.position.y >= minY && MyAvatar.position.y <= maxY && MyAvatar.position.z >= minZ && MyAvatar.position.z <= maxZ) { - return true; - } - } - } - return false; -} - -// Function to toggle visibile the overlay. -function toggleVisible(newVisibility) { - if (newVisibility != visible) { - visible = newVisibility; - Overlays.editOverlay(toggleStreamPlayButton, {visible: visible}); - Overlays.editOverlay(toggleStreamStopButton, {visible: visible}); - Overlays.editOverlay(toggleIncreaseVolumeButton, {visible: visible}); - Overlays.editOverlay(toggleDecreaseVolumeButton, {visible: visible}); - } -} - -// Function to check if avatar is in proper domain. -Window.domainChanged.connect(function() { - if (Window.location.hostname != "Music" && Window.location.hostname != "LiveMusic") { - Script.stop(); - } -}); - -// Function to check if avatar is within zone. -Entities.enterEntity.connect(function(entityID) { - print("Entered..." + JSON.stringify(entityID)); - var properties = Entities.getEntityProperties(entityID); - if (isOurZone(properties)) { - print("Entering Zone!"); - toggleVisible(true); - } -}) - -// Function to check if avatar is leaving zone. -Entities.leaveEntity.connect(function(entityID) { - print("Left..." + JSON.stringify(entityID)); - var properties = Entities.getEntityProperties(entityID); - if (isOurZone(properties)) { - print("Leaving Zone!"); - toggleVisible(false); - changeStream(""); - } -}) - -// Function to delete overlays upon exit. -function onScriptEnding() { - Overlays.deleteOverlay(toggleStreamPlayButton); - Overlays.deleteOverlay(toggleStreamStopButton); - Overlays.deleteOverlay(toggleIncreaseVolumeButton); - Overlays.deleteOverlay(toggleDecreaseVolumeButton); - changeStream(""); - streamWindow.deleteLater(); -} - -// Function call to ensure that if you log in to the zone visibility is true. -if (isInZone()) { - toggleVisible(true); -} - -// Connect mouse and hide WebWindow. -Controller.mousePressEvent.connect(mousePressEvent); -streamWindow.setVisible(false); - -// Call function upon ending script. -Script.scriptEnding.connect(onScriptEnding); \ No newline at end of file diff --git a/examples/html/jsstreamplayerdomain-zone.html b/examples/html/jsstreamplayerdomain-zone.html deleted file mode 100644 index 28b2202591..0000000000 --- a/examples/html/jsstreamplayerdomain-zone.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 776d4747b2fc17fce67a8a8ef34c6e77f0adfb63 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 24 Jul 2015 14:47:44 -0700 Subject: [PATCH 050/129] Cleaning up the FBO cache and the output stage in general --- libraries/gpu/src/gpu/Batch.cpp | 59 ++++++++------- libraries/gpu/src/gpu/Batch.h | 25 +++---- libraries/gpu/src/gpu/GLBackend.cpp | 67 +---------------- libraries/gpu/src/gpu/GLBackend.h | 3 +- libraries/gpu/src/gpu/GLBackendOutput.cpp | 91 +++++++++++++++++++++-- 5 files changed, 127 insertions(+), 118 deletions(-) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 567ce66cd8..4ac33d8f14 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -106,36 +106,6 @@ void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, ui _params.push_back(nbInstances); } -void Batch::clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor) { - ADD_COMMAND(clearFramebuffer); - - _params.push_back(enableScissor); - _params.push_back(stencil); - _params.push_back(depth); - _params.push_back(color.w); - _params.push_back(color.z); - _params.push_back(color.y); - _params.push_back(color.x); - _params.push_back(targets); -} - -void Batch::clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor) { - clearFramebuffer(targets & Framebuffer::BUFFER_COLORS, color, 1.0f, 0, enableScissor); -} - -void Batch::clearDepthFramebuffer(float depth, bool enableScissor) { - clearFramebuffer(Framebuffer::BUFFER_DEPTH, Vec4(0.0f), depth, 0, enableScissor); -} - -void Batch::clearStencilFramebuffer(int stencil, bool enableScissor) { - clearFramebuffer(Framebuffer::BUFFER_STENCIL, Vec4(0.0f), 1.0f, stencil, enableScissor); -} - -void Batch::clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor) { - clearFramebuffer(Framebuffer::BUFFER_DEPTHSTENCIL, Vec4(0.0f), depth, stencil, enableScissor); -} - - void Batch::setInputFormat(const Stream::FormatPointer& format) { ADD_COMMAND(setInputFormat); @@ -255,6 +225,35 @@ void Batch::setFramebuffer(const FramebufferPointer& framebuffer) { } +void Batch::clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor) { + ADD_COMMAND(clearFramebuffer); + + _params.push_back(enableScissor); + _params.push_back(stencil); + _params.push_back(depth); + _params.push_back(color.w); + _params.push_back(color.z); + _params.push_back(color.y); + _params.push_back(color.x); + _params.push_back(targets); +} + +void Batch::clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor) { + clearFramebuffer(targets & Framebuffer::BUFFER_COLORS, color, 1.0f, 0, enableScissor); +} + +void Batch::clearDepthFramebuffer(float depth, bool enableScissor) { + clearFramebuffer(Framebuffer::BUFFER_DEPTH, Vec4(0.0f), depth, 0, enableScissor); +} + +void Batch::clearStencilFramebuffer(int stencil, bool enableScissor) { + clearFramebuffer(Framebuffer::BUFFER_STENCIL, Vec4(0.0f), 1.0f, stencil, enableScissor); +} + +void Batch::clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor) { + clearFramebuffer(Framebuffer::BUFFER_DEPTHSTENCIL, Vec4(0.0f), depth, stencil, enableScissor); +} + void Batch::blit(const FramebufferPointer& src, const Vec4i& srcViewport, const FramebufferPointer& dst, const Vec4i& dstViewport) { ADD_COMMAND(blit); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index acc1f6fdac..58fe03c9cf 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -54,15 +54,6 @@ public: void drawInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbVertices, uint32 startVertex = 0, uint32 startInstance = 0); void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbIndices, uint32 startIndex = 0, uint32 startInstance = 0); - // Clear framebuffer layers - // Targets can be any of the render buffers contained in the Framebuffer - // Optionally the scissor test can be enabled locally for this command and to restrict the clearing command to the pixels contained in the scissor rectangle - void clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor = false); - void clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, mask out targets to make sure it touches only color targets - void clearDepthFramebuffer(float depth, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only depth target - void clearStencilFramebuffer(int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only stencil target - void clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches depth and stencil target - // Input Stage // InputFormat // InputBuffers @@ -105,8 +96,17 @@ public: // Framebuffer Stage void setFramebuffer(const FramebufferPointer& framebuffer); - void blit(const FramebufferPointer& src, const Vec4i& srcViewport, - const FramebufferPointer& dst, const Vec4i& dstViewport); + + // Clear framebuffer layers + // Targets can be any of the render buffers contained in the currnetly bound Framebuffer + // Optionally the scissor test can be enabled locally for this command and to restrict the clearing command to the pixels contained in the scissor rectangle + void clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor = false); + void clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, mask out targets to make sure it touches only color targets + void clearDepthFramebuffer(float depth, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only depth target + void clearStencilFramebuffer(int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only stencil target + void clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches depth and stencil target + + void blit(const FramebufferPointer& src, const Vec4i& srcViewport, const FramebufferPointer& dst, const Vec4i& dstViewport); // Query Section void beginQuery(const QueryPointer& query); @@ -162,8 +162,6 @@ public: COMMAND_drawInstanced, COMMAND_drawIndexedInstanced, - COMMAND_clearFramebuffer, - COMMAND_setInputFormat, COMMAND_setInputBuffer, COMMAND_setIndexBuffer, @@ -181,6 +179,7 @@ public: COMMAND_setResourceTexture, COMMAND_setFramebuffer, + COMMAND_clearFramebuffer, COMMAND_blit, COMMAND_beginQuery, diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index ae50b96bc5..6b1d552be9 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -21,7 +21,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_drawIndexed), (&::gpu::GLBackend::do_drawInstanced), (&::gpu::GLBackend::do_drawIndexedInstanced), - (&::gpu::GLBackend::do_clearFramebuffer), (&::gpu::GLBackend::do_setInputFormat), (&::gpu::GLBackend::do_setInputBuffer), @@ -40,6 +39,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setResourceTexture), (&::gpu::GLBackend::do_setFramebuffer), + (&::gpu::GLBackend::do_clearFramebuffer), (&::gpu::GLBackend::do_blit), (&::gpu::GLBackend::do_beginQuery), @@ -246,71 +246,6 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } -void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { - - uint32 masks = batch._params[paramOffset + 7]._uint; - Vec4 color; - color.x = batch._params[paramOffset + 6]._float; - color.y = batch._params[paramOffset + 5]._float; - color.z = batch._params[paramOffset + 4]._float; - color.w = batch._params[paramOffset + 3]._float; - float depth = batch._params[paramOffset + 2]._float; - int stencil = batch._params[paramOffset + 1]._int; - int useScissor = batch._params[paramOffset + 0]._int; - - GLuint glmask = 0; - if (masks & Framebuffer::BUFFER_STENCIL) { - glClearStencil(stencil); - glmask |= GL_STENCIL_BUFFER_BIT; - } - - if (masks & Framebuffer::BUFFER_DEPTH) { - glClearDepth(depth); - glmask |= GL_DEPTH_BUFFER_BIT; - } - - std::vector drawBuffers; - if (masks & Framebuffer::BUFFER_COLORS) { - for (unsigned int i = 0; i < Framebuffer::MAX_NUM_RENDER_BUFFERS; i++) { - if (masks & (1 << i)) { - drawBuffers.push_back(GL_COLOR_ATTACHMENT0 + i); - } - } - - if (!drawBuffers.empty()) { - glDrawBuffers(drawBuffers.size(), drawBuffers.data()); - glClearColor(color.x, color.y, color.z, color.w); - glmask |= GL_COLOR_BUFFER_BIT; - } - - // Force the color mask cache to WRITE_ALL if not the case - do_setStateColorWriteMask(State::ColorMask::WRITE_ALL); - } - - // Apply scissor if needed and if not already on - bool doEnableScissor = (useScissor && (!_pipeline._stateCache.scissorEnable)); - if (doEnableScissor) { - glEnable(GL_SCISSOR_TEST); - } - - glClear(glmask); - - // Restore scissor if needed - if (doEnableScissor) { - glDisable(GL_SCISSOR_TEST); - } - - // Restore the color draw buffers only if a frmaebuffer is bound - if (_output._framebuffer && !drawBuffers.empty()) { - auto glFramebuffer = syncGPUObject(*_output._framebuffer); - if (glFramebuffer) { - glDrawBuffers(glFramebuffer->_colorBuffers.size(), glFramebuffer->_colorBuffers.data()); - } - } - - (void) CHECK_GL_ERROR(); -} - // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 894e2c4548..9d8c9ef805 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -241,8 +241,6 @@ protected: void do_drawInstanced(Batch& batch, uint32 paramOffset); void do_drawIndexedInstanced(Batch& batch, uint32 paramOffset); - void do_clearFramebuffer(Batch& batch, uint32 paramOffset); - // Input Stage void do_setInputFormat(Batch& batch, uint32 paramOffset); void do_setInputBuffer(Batch& batch, uint32 paramOffset); @@ -385,6 +383,7 @@ protected: // Output stage void do_setFramebuffer(Batch& batch, uint32 paramOffset); + void do_clearFramebuffer(Batch& batch, uint32 paramOffset); void do_blit(Batch& batch, uint32 paramOffset); // Synchronize the state cache of this Backend with the actual real state of the GL Context diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 1b22649ad6..b37def48e7 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -180,7 +180,6 @@ void GLBackend::syncOutputStateCache() { void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint); - if (_output._framebuffer != framebuffer) { auto newFBO = getFramebufferID(framebuffer); if (_output._drawFBO != newFBO) { @@ -191,6 +190,72 @@ void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { } } +void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { + + uint32 masks = batch._params[paramOffset + 7]._uint; + Vec4 color; + color.x = batch._params[paramOffset + 6]._float; + color.y = batch._params[paramOffset + 5]._float; + color.z = batch._params[paramOffset + 4]._float; + color.w = batch._params[paramOffset + 3]._float; + float depth = batch._params[paramOffset + 2]._float; + int stencil = batch._params[paramOffset + 1]._int; + int useScissor = batch._params[paramOffset + 0]._int; + + GLuint glmask = 0; + if (masks & Framebuffer::BUFFER_STENCIL) { + glClearStencil(stencil); + glmask |= GL_STENCIL_BUFFER_BIT; + } + + if (masks & Framebuffer::BUFFER_DEPTH) { + glClearDepth(depth); + glmask |= GL_DEPTH_BUFFER_BIT; + } + + std::vector drawBuffers; + if (masks & Framebuffer::BUFFER_COLORS) { + for (unsigned int i = 0; i < Framebuffer::MAX_NUM_RENDER_BUFFERS; i++) { + if (masks & (1 << i)) { + drawBuffers.push_back(GL_COLOR_ATTACHMENT0 + i); + } + } + + if (!drawBuffers.empty()) { + glDrawBuffers(drawBuffers.size(), drawBuffers.data()); + glClearColor(color.x, color.y, color.z, color.w); + glmask |= GL_COLOR_BUFFER_BIT; + } + + // Force the color mask cache to WRITE_ALL if not the case + do_setStateColorWriteMask(State::ColorMask::WRITE_ALL); + } + + // Apply scissor if needed and if not already on + bool doEnableScissor = (useScissor && (!_pipeline._stateCache.scissorEnable)); + if (doEnableScissor) { + glEnable(GL_SCISSOR_TEST); + } + + // Clear! + glClear(glmask); + + // Restore scissor if needed + if (doEnableScissor) { + glDisable(GL_SCISSOR_TEST); + } + + // Restore the color draw buffers only if a frmaebuffer is bound + if (_output._framebuffer && !drawBuffers.empty()) { + auto glFramebuffer = syncGPUObject(*_output._framebuffer); + if (glFramebuffer) { + glDrawBuffers(glFramebuffer->_colorBuffers.size(), glFramebuffer->_colorBuffers.data()); + } + } + + (void) CHECK_GL_ERROR(); +} + void GLBackend::do_blit(Batch& batch, uint32 paramOffset) { auto srcframebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint); Vec4i srcvp; @@ -203,19 +268,31 @@ void GLBackend::do_blit(Batch& batch, uint32 paramOffset) { for (size_t i = 0; i < 4; ++i) { dstvp[i] = batch._params[paramOffset + 6 + i]._int; } - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(dstframebuffer)); + + // Assign dest framebuffer if not bound already + auto newDrawFBO = getFramebufferID(dstframebuffer); + if (_output._drawFBO != newDrawFBO) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, newDrawFBO); + } + + // always bind the read fbo glBindFramebuffer(GL_READ_FRAMEBUFFER, getFramebufferID(srcframebuffer)); + + // Blit! glBlitFramebuffer(srcvp.x, srcvp.y, srcvp.z, srcvp.w, dstvp.x, dstvp.y, dstvp.z, dstvp.w, GL_COLOR_BUFFER_BIT, GL_LINEAR); - - (void) CHECK_GL_ERROR(); - if (_output._framebuffer) { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(_output._framebuffer)); + // Always clean the read fbo to 0 + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + // Restore draw fbo if changed + if (_output._drawFBO != newDrawFBO) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _output._drawFBO); } -} + (void) CHECK_GL_ERROR(); +} void GLBackend::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) { auto readFBO = gpu::GLBackend::getFramebufferID(srcFramebuffer); From 5dd16d9f801cb79cbaa786d1582a3eeca16a443a Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Fri, 24 Jul 2015 16:07:30 -0700 Subject: [PATCH 051/129] Blend function applied to reduce one FBO --- .../src/AmbientOcclusionEffect.cpp | 189 +----------------- .../render-utils/src/occlusion_blend.slf | 13 +- .../render-utils/src/occlusion_blend.slv | 24 --- .../render-utils/src/occlusion_result.slf | 23 --- 4 files changed, 8 insertions(+), 241 deletions(-) delete mode 100644 libraries/render-utils/src/occlusion_blend.slv delete mode 100644 libraries/render-utils/src/occlusion_result.slf diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index d8b56f5ba1..da081f7811 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -32,150 +32,8 @@ #include "gaussian_blur_vertical_vert.h" #include "gaussian_blur_horizontal_vert.h" #include "gaussian_blur_frag.h" -#include "occlusion_blend_vert.h" #include "occlusion_blend_frag.h" -//#include "occlusion_result_vert.h" -#include "occlusion_result_frag.h" -/* -void AmbientOcclusionEffect::init(AbstractViewStateInterface* viewState) { - _viewState = viewState; // we will use this for view state services - - _occlusionProgram = new ProgramObject(); - _occlusionProgram->addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() - + "shaders/ambient_occlusion.vert"); - _occlusionProgram->addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() - + "shaders/ambient_occlusion.frag"); - _occlusionProgram->link(); - - // create the sample kernel: an array of hemispherically distributed offset vectors - const int SAMPLE_KERNEL_SIZE = 16; - QVector3D sampleKernel[SAMPLE_KERNEL_SIZE]; - for (int i = 0; i < SAMPLE_KERNEL_SIZE; i++) { - // square the length in order to increase density towards the center - glm::vec3 vector = glm::sphericalRand(1.0f); - float scale = randFloat(); - const float MIN_VECTOR_LENGTH = 0.01f; - const float MAX_VECTOR_LENGTH = 1.0f; - vector *= glm::mix(MIN_VECTOR_LENGTH, MAX_VECTOR_LENGTH, scale * scale); - sampleKernel[i] = QVector3D(vector.x, vector.y, vector.z); - } - - _occlusionProgram->bind(); - _occlusionProgram->setUniformValue("depthTexture", 0); - _occlusionProgram->setUniformValue("rotationTexture", 1); - _occlusionProgram->setUniformValueArray("sampleKernel", sampleKernel, SAMPLE_KERNEL_SIZE); - _occlusionProgram->setUniformValue("radius", 0.1f); - _occlusionProgram->release(); - - _nearLocation = _occlusionProgram->uniformLocation("near"); - _farLocation = _occlusionProgram->uniformLocation("far"); - _leftBottomLocation = _occlusionProgram->uniformLocation("leftBottom"); - _rightTopLocation = _occlusionProgram->uniformLocation("rightTop"); - _noiseScaleLocation = _occlusionProgram->uniformLocation("noiseScale"); - _texCoordOffsetLocation = _occlusionProgram->uniformLocation("texCoordOffset"); - _texCoordScaleLocation = _occlusionProgram->uniformLocation("texCoordScale"); - - // generate the random rotation texture - glGenTextures(1, &_rotationTextureID); - glBindTexture(GL_TEXTURE_2D, _rotationTextureID); - const int ELEMENTS_PER_PIXEL = 3; - unsigned char rotationData[ROTATION_WIDTH * ROTATION_HEIGHT * ELEMENTS_PER_PIXEL]; - unsigned char* rotation = rotationData; - for (int i = 0; i < ROTATION_WIDTH * ROTATION_HEIGHT; i++) { - glm::vec3 vector = glm::sphericalRand(1.0f); - *rotation++ = ((vector.x + 1.0f) / 2.0f) * 255.0f; - *rotation++ = ((vector.y + 1.0f) / 2.0f) * 255.0f; - *rotation++ = ((vector.z + 1.0f) / 2.0f) * 255.0f; - } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ROTATION_WIDTH, ROTATION_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, rotationData); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); - - _blurProgram = new ProgramObject(); - _blurProgram->addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/ambient_occlusion.vert"); - _blurProgram->addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/occlusion_blur.frag"); - _blurProgram->link(); - - _blurProgram->bind(); - _blurProgram->setUniformValue("originalTexture", 0); - _blurProgram->release(); - - _blurScaleLocation = _blurProgram->uniformLocation("blurScale"); -} - -void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext){ - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - - glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimaryDepthTextureID()); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, _rotationTextureID); - - // render with the occlusion shader to the secondary/tertiary buffer - auto freeFramebuffer = nullptr; // DependencyManager::get()->getFreeFramebuffer(); // FIXME - glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(freeFramebuffer)); - - float left, right, bottom, top, nearVal, farVal; - glm::vec4 nearClipPlane, farClipPlane; - AbstractViewStateInterface::instance()->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - - int viewport[4]; - glGetIntegerv(GL_VIEWPORT, viewport); - const int VIEWPORT_X_INDEX = 0; - const int VIEWPORT_WIDTH_INDEX = 2; - - auto framebufferSize = DependencyManager::get()->getFrameBufferSize(); - float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width(); - float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width(); - - _occlusionProgram->bind(); - _occlusionProgram->setUniformValue(_nearLocation, nearVal); - _occlusionProgram->setUniformValue(_farLocation, farVal); - _occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom); - _occlusionProgram->setUniformValue(_rightTopLocation, right, top); - _occlusionProgram->setUniformValue(_noiseScaleLocation, viewport[VIEWPORT_WIDTH_INDEX] / (float)ROTATION_WIDTH, - framebufferSize.height() / (float)ROTATION_HEIGHT); - _occlusionProgram->setUniformValue(_texCoordOffsetLocation, sMin, 0.0f); - _occlusionProgram->setUniformValue(_texCoordScaleLocation, sWidth, 1.0f); - - renderFullscreenQuad(); - - _occlusionProgram->release(); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glBindTexture(GL_TEXTURE_2D, 0); - - glActiveTexture(GL_TEXTURE0); - - // now render secondary to primary with 4x4 blur - auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); - glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); - - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE); - - auto freeFramebufferTexture = freeFramebuffer->getRenderBuffer(0); - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(freeFramebufferTexture)); - - _blurProgram->bind(); - _blurProgram->setUniformValue(_blurScaleLocation, 1.0f / framebufferSize.width(), 1.0f / framebufferSize.height()); - - renderFullscreenQuad(sMin, sMin + sWidth); - - _blurProgram->release(); - - glBindTexture(GL_TEXTURE_2D, 0); - - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE) -} -*/ AmbientOcclusion::AmbientOcclusion() { } @@ -297,7 +155,6 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("blurredOcclusionTexture"), 0)); - slotBindings.insert(gpu::Shader::Binding(std::string("colorTexture"), 1)); gpu::Shader::makeProgram(*program, slotBindings); @@ -306,8 +163,8 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { state->setDepthTest(false, false, gpu::LESS_EQUAL); // Blend on transparent - state->setBlendFunction(false, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + state->setBlendFunction(true, + gpu::State::SRC_COLOR, gpu::State::BLEND_OP_ADD, gpu::State::DEST_COLOR); // Link the blend FBO to texture _blendBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, @@ -324,30 +181,6 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { return _blendPipeline; } -const gpu::PipelinePointer& AmbientOcclusion::getAOResultPipeline() { - if (!_AOResultPipeline) { - auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(ambient_occlusion_vert))); - auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(occlusion_result_frag))); - gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); - //gpu::ShaderPointer program = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawTransformUnitQuadVS(), gpu::StandardShaderLib::getDrawTexturePS()); - - gpu::Shader::BindingSet slotBindings; - gpu::Shader::makeProgram(*program, slotBindings); - - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - - state->setDepthTest(false, false, gpu::LESS_EQUAL); - - // Blend on transparent - state->setBlendFunction(false, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - - // Good to go add the brand new pipeline - _AOResultPipeline.reset(gpu::Pipeline::create(program, state)); - } - return _AOResultPipeline; -} - void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); @@ -418,30 +251,14 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons // Blend step getBlendPipeline(); batch.setResourceTexture(0, _hBlurTexture); - batch.setResourceTexture(1, DependencyManager::get()->getPrimaryColorTexture()); - batch.setFramebuffer(_blendBuffer); + batch.setFramebuffer(DependencyManager::get()->getPrimaryFramebuffer()); // Bind the fourth gpu::Pipeline we need - for blending the primary color buffer with blurred occlusion texture batch.setPipeline(getBlendPipeline()); DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); - - // Final AO result step - getAOResultPipeline(); - batch.setResourceTexture(0, _blendTexture); - batch.setFramebuffer(DependencyManager::get()->getPrimaryFramebuffer()); - - // Bind the fifth gpu::Pipeline we need - for displaying the blended texture - batch.setPipeline(getAOResultPipeline()); - - glm::vec2 bottomLeftSmall(0.5f, -1.0f); - glm::vec2 topRightSmall(1.0f, -0.5f); - DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); // Ready to render args->_context->syncCache(); args->_context->render((batch)); - - // need to fetch forom the z buffer and render something in a new render target a result that combine the z and produce a fake AO result - } diff --git a/libraries/render-utils/src/occlusion_blend.slf b/libraries/render-utils/src/occlusion_blend.slf index 00b09b0cbd..6c0101eb6f 100644 --- a/libraries/render-utils/src/occlusion_blend.slf +++ b/libraries/render-utils/src/occlusion_blend.slf @@ -17,17 +17,14 @@ varying vec2 varTexcoord; uniform sampler2D blurredOcclusionTexture; -uniform sampler2D colorTexture; void main(void) { vec4 occlusionColor = texture2D(blurredOcclusionTexture, varTexcoord); - vec4 currentColor = texture2D(colorTexture, varTexcoord); - /* - if(occlusionColor.r == 1.0) { - gl_FragColor = currentColor; + + if(occlusionColor.r > 0.8 && occlusionColor.r <= 1.0) { + gl_FragColor = vec4(vec3(0.0), 1.0); } else { - gl_FragColor = mix(occlusionColor, currentColor, 0.5); - }*/ - gl_FragColor = currentColor; + gl_FragColor = vec4(vec3(0.2), 1.0); + } } diff --git a/libraries/render-utils/src/occlusion_blend.slv b/libraries/render-utils/src/occlusion_blend.slv deleted file mode 100644 index 53380a494f..0000000000 --- a/libraries/render-utils/src/occlusion_blend.slv +++ /dev/null @@ -1,24 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// occlusion_blend.vert -// vertex shader -// -// Created by Niraj Venkat on 7/20/15. -// Copyright 2015 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 -// - -<@include gpu/Transform.slh@> - -<$declareStandardTransform()$> - -varying vec2 varTexcoord; - -void main(void) { - varTexcoord = gl_MultiTexCoord0.xy; - gl_Position = gl_Vertex; -} diff --git a/libraries/render-utils/src/occlusion_result.slf b/libraries/render-utils/src/occlusion_result.slf deleted file mode 100644 index 3b7e895dc6..0000000000 --- a/libraries/render-utils/src/occlusion_result.slf +++ /dev/null @@ -1,23 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// occlusion_result.frag -// fragment shader -// -// Created by Niraj Venkat on 7/23/15. -// Copyright 2015 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 -// - -<@include DeferredBufferWrite.slh@> - -varying vec2 varTexcoord; - -uniform sampler2D resultTexture; - -void main(void) { - gl_FragColor = texture2D(resultTexture, varTexcoord); -} From 6bc3d65bf4cfe58e3ba12a75979baa13ce3228ce Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Fri, 24 Jul 2015 16:16:18 -0700 Subject: [PATCH 052/129] Fixing build errors --- libraries/render-utils/src/AmbientOcclusionEffect.cpp | 11 +---------- libraries/render-utils/src/AmbientOcclusionEffect.h | 4 ---- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index da081f7811..d7fa88b276 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -149,7 +149,7 @@ const gpu::PipelinePointer& AmbientOcclusion::getHBlurPipeline() { const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { if (!_blendPipeline) { - auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(occlusion_blend_vert))); + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(ambient_occlusion_vert))); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(occlusion_blend_frag))); gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); @@ -166,15 +166,6 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { state->setBlendFunction(true, gpu::State::SRC_COLOR, gpu::State::BLEND_OP_ADD, gpu::State::DEST_COLOR); - // Link the blend FBO to texture - _blendBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, - DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); - auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - auto width = _blendBuffer->getWidth(); - auto height = _blendBuffer->getHeight(); - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - _blendTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); - // Good to go add the brand new pipeline _blendPipeline.reset(gpu::Pipeline::create(program, state)); } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index ec0314016c..76cb0b063d 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -28,7 +28,6 @@ public: const gpu::PipelinePointer& getHBlurPipeline(); const gpu::PipelinePointer& getVBlurPipeline(); const gpu::PipelinePointer& getBlendPipeline(); - const gpu::PipelinePointer& getAOResultPipeline(); private: @@ -48,17 +47,14 @@ private: gpu::PipelinePointer _hBlurPipeline; gpu::PipelinePointer _vBlurPipeline; gpu::PipelinePointer _blendPipeline; - gpu::PipelinePointer _AOResultPipeline; gpu::FramebufferPointer _occlusionBuffer; gpu::FramebufferPointer _hBlurBuffer; gpu::FramebufferPointer _vBlurBuffer; - gpu::FramebufferPointer _blendBuffer; gpu::TexturePointer _occlusionTexture; gpu::TexturePointer _hBlurTexture; gpu::TexturePointer _vBlurTexture; - gpu::TexturePointer _blendTexture; }; From ca8d0d542012f93dea2be32d2ea066d7bd1b1eca Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Sat, 25 Jul 2015 07:56:57 -0400 Subject: [PATCH 053/129] Added files to zone folder and made change to jstreamplayerdomain-zone.js to allow for zone entity data field to load a stream url rather than have it hard coded in the js file. This allows for many zones to be created and simply having to put a new stream url in each data field in each zone to work. --- .../zones/jsstreamplayerdomain-zone-entity.js | 33 ++++ examples/zones/jsstreamplayerdomain-zone.html | 42 +++++ examples/zones/jsstreamplayerdomain-zone.js | 176 ++++++++++++++++++ 3 files changed, 251 insertions(+) create mode 100644 examples/zones/jsstreamplayerdomain-zone-entity.js create mode 100644 examples/zones/jsstreamplayerdomain-zone.html create mode 100644 examples/zones/jsstreamplayerdomain-zone.js diff --git a/examples/zones/jsstreamplayerdomain-zone-entity.js b/examples/zones/jsstreamplayerdomain-zone-entity.js new file mode 100644 index 0000000000..9a8cb8b8b4 --- /dev/null +++ b/examples/zones/jsstreamplayerdomain-zone-entity.js @@ -0,0 +1,33 @@ +// +// #20628: JS Stream Player Domain-Zone-Entity +// ******************************************** +// +// Created by Kevin M. Thomas and Thoys 07/20/15. +// Copyright 2015 High Fidelity, Inc. +// kevintown.net +// +// JavaScript for the High Fidelity interface that is an entity script to be placed in a chosen entity inside a domain-zone. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +// Function which exists inside of an entity which triggers as a user approches it. +(function() { + const SCRIPT_NAME = "https://dl.dropboxusercontent.com/u/17344741/jsstreamplayer/jsstreamplayerdomain-zone.js"; + function isScriptRunning(script) { + script = script.toLowerCase().trim(); + var runningScripts = ScriptDiscoveryService.getRunning(); + for (i in runningScripts) { + if (runningScripts[i].url.toLowerCase().trim() == script) { + return true; + } + } + return false; + }; + + if (!isScriptRunning(SCRIPT_NAME)) { + Script.load(SCRIPT_NAME); + } +}) \ No newline at end of file diff --git a/examples/zones/jsstreamplayerdomain-zone.html b/examples/zones/jsstreamplayerdomain-zone.html new file mode 100644 index 0000000000..28b2202591 --- /dev/null +++ b/examples/zones/jsstreamplayerdomain-zone.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/zones/jsstreamplayerdomain-zone.js b/examples/zones/jsstreamplayerdomain-zone.js new file mode 100644 index 0000000000..33d7364709 --- /dev/null +++ b/examples/zones/jsstreamplayerdomain-zone.js @@ -0,0 +1,176 @@ +// +// #20628: JS Stream Player Domain-Zone +// ************************************* +// +// Created by Kevin M. Thomas, Thoys and Konstantin 07/24/15. +// Copyright 2015 High Fidelity, Inc. +// kevintown.net +// +// JavaScript for the High Fidelity interface that creates a stream player with a UI for playing a domain-zone specificed stream URL in addition to play, stop and volume functionality which is resident only in the domain-zone. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +// Declare variables and set up new WebWindow. +var lastZone = ""; +var volume = 0.5; +var stream = ""; +var streamWindow = new WebWindow('Stream', "https://dl.dropboxusercontent.com/u/17344741/jsstreamplayer/jsstreamplayerdomain-zone.html", 0, 0, false); +var visible = false; + +// Set up toggleStreamPlayButton overlay. +var toggleStreamPlayButton = Overlays.addOverlay("text", { + x: 122, + y: 310, + width: 38, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + visible: false, + text: " Play" +}); + +// Set up toggleStreamStopButton overlay. +var toggleStreamStopButton = Overlays.addOverlay("text", { + x: 166, + y: 310, + width: 40, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + visible: false, + text: " Stop" +}); + +// Set up increaseVolumeButton overlay. +var toggleIncreaseVolumeButton = Overlays.addOverlay("text", { + x: 211, + y: 310, + width: 18, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + visible: false, + text: " +" +}); + +// Set up decreaseVolumeButton overlay. +var toggleDecreaseVolumeButton = Overlays.addOverlay("text", { + x: 234, + y: 310, + width: 15, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + visible: false, + text: " -" +}); + +// Function to change JSON object stream. +function changeStream(stream) { + var streamJSON = { + action: "changeStream", + stream: stream + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); +} + +// Function to change JSON object volume. +function changeVolume(volume) { + var volumeJSON = { + action: "changeVolume", + volume: volume + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(volumeJSON)); +} + +// Function that adds mousePressEvent functionality to connect UI to enter stream URL, play and stop stream. +function mousePressEvent(event) { + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamPlayButton) { + changeStream(stream); + volume = 0.25; + changeVolume(volume); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamStopButton) { + changeStream(""); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleIncreaseVolumeButton) { + volume += 0.25; + changeVolume(volume); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleDecreaseVolumeButton) { + volume -= 0.25; + changeVolume(volume); + } +} + +// Function checking bool if in proper zone. +function isOurZone(properties) { + return stream != "" && properties.type == "Zone"; +} + +// Function to toggle visibile the overlay. +function toggleVisible(newVisibility) { + if (newVisibility != visible) { + visible = newVisibility; + Overlays.editOverlay(toggleStreamPlayButton, {visible: visible}); + Overlays.editOverlay(toggleStreamStopButton, {visible: visible}); + Overlays.editOverlay(toggleIncreaseVolumeButton, {visible: visible}); + Overlays.editOverlay(toggleDecreaseVolumeButton, {visible: visible}); + } +} + +// Function to check if avatar is in proper domain. +Window.domainChanged.connect(function() { + Script.stop(); +}); + +// Function to check if avatar is within zone. +Entities.enterEntity.connect(function(entityID) { + print("Entered..." + JSON.stringify(entityID)); + var properties = Entities.getEntityProperties(entityID); + stream = properties.userData; + if(isOurZone(properties)) + { + lastZone = properties.name; + toggleVisible(true); + } +}) + +// Function to check if avatar is leaving zone. +Entities.leaveEntity.connect(function(entityID) { + print("Left..." + JSON.stringify(entityID)); + var properties = Entities.getEntityProperties(entityID); + if (properties.name == lastZone && properties.type == "Zone") { + print("Leaving Zone!"); + toggleVisible(false); + changeStream(""); + } +}) + +// Function to delete overlays upon exit. +function onScriptEnding() { + Overlays.deleteOverlay(toggleStreamPlayButton); + Overlays.deleteOverlay(toggleStreamStopButton); + Overlays.deleteOverlay(toggleIncreaseVolumeButton); + Overlays.deleteOverlay(toggleDecreaseVolumeButton); + changeStream(""); + streamWindow.deleteLater(); +} + +// Connect mouse and hide WebWindow. +Controller.mousePressEvent.connect(mousePressEvent); +streamWindow.setVisible(false); + +// Call function upon ending script. +Script.scriptEnding.connect(onScriptEnding); \ No newline at end of file From 7be33dcb5845908254950206ce6cff794ff1edde Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Sat, 25 Jul 2015 11:40:58 -0400 Subject: [PATCH 054/129] Limit the amount of time consumed by rendering QML --- .../render-utils/src/OffscreenQmlSurface.cpp | 21 +++++++++++++------ .../render-utils/src/OffscreenQmlSurface.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/OffscreenQmlSurface.cpp b/libraries/render-utils/src/OffscreenQmlSurface.cpp index 3ebc7704a8..056f9dbc6d 100644 --- a/libraries/render-utils/src/OffscreenQmlSurface.cpp +++ b/libraries/render-utils/src/OffscreenQmlSurface.cpp @@ -19,6 +19,7 @@ #include "FboCache.h" #include +#include class QMyQuickRenderControl : public QQuickRenderControl { protected: @@ -44,7 +45,10 @@ Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus") // Time between receiving a request to render the offscreen UI actually triggering // the render. Could possibly be increased depending on the framerate we expect to // achieve. -static const int SMALL_INTERVAL = 5; +static const int MAX_QML_FRAMERATE = 10; +static const int MIN_RENDER_INTERVAL_US = USECS_PER_SECOND / MAX_QML_FRAMERATE; +static const int MIN_TIMER_MS = 5; + OffscreenQmlSurface::OffscreenQmlSurface() : _renderControl(new QMyQuickRenderControl), _fboCache(new FboCache) { @@ -90,7 +94,6 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { // When Quick says there is a need to render, we will not render immediately. Instead, // a timer with a small interval is used to get better performance. _updateTimer.setSingleShot(true); - _updateTimer.setInterval(SMALL_INTERVAL); connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick); // Now hook up the signals. For simplicy we don't differentiate between @@ -170,13 +173,18 @@ QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function MIN_RENDER_INTERVAL_US) { + _updateTimer.setInterval(MIN_TIMER_MS); + } else { + _updateTimer.setInterval((MIN_RENDER_INTERVAL_US - lastInterval) / USECS_PER_MSEC); + } _updateTimer.start(); } } @@ -243,6 +251,7 @@ void OffscreenQmlSurface::updateQuick() { if (_paused) { return; } + if (!makeCurrent()) { return; } @@ -270,11 +279,11 @@ void OffscreenQmlSurface::updateQuick() { // Need a debug context with sync logging to figure out why. // for now just clear the errors glGetError(); -// Q_ASSERT(!glGetError()); _quickWindow->resetOpenGLState(); QOpenGLFramebufferObject::bindDefault(); + _lastRenderTime = usecTimestampNow(); // Force completion of all the operations before we emit the texture as being ready for use glFinish(); diff --git a/libraries/render-utils/src/OffscreenQmlSurface.h b/libraries/render-utils/src/OffscreenQmlSurface.h index b892806c44..1fbf69ef4d 100644 --- a/libraries/render-utils/src/OffscreenQmlSurface.h +++ b/libraries/render-utils/src/OffscreenQmlSurface.h @@ -86,6 +86,7 @@ private: QQuickItem* _rootItem{ nullptr }; QTimer _updateTimer; FboCache* _fboCache; + quint64 _lastRenderTime{ 0 }; bool _polish{ true }; bool _paused{ true }; MouseTranslator _mouseTranslator{ [](const QPointF& p) { return p; } }; From d25e09af74544db662a2e92637439386b00cb284 Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Sun, 26 Jul 2015 00:48:31 +0200 Subject: [PATCH 055/129] removed the last 2 filename lines, they should not be there. --- libraries/fbx/src/FBXReader.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 554d56ee5a..69482a8c81 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1463,11 +1463,9 @@ QByteArray fileOnUrl(const QByteArray filenameString,const QString url) { if (checkFile.exists() && checkFile.isFile()) { filename = filename.replace('\\', '/'); } else { - // there is not texture at the filename. Assume it is in the root dir. + // there is no texture at the fbx dir with the filename added. Assume it is in the fbx dir. filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); } - filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); - filename = filename.replace('\\', '/'); return filename; } From 24fff719c57d2a6daf565b9a5410b29fb8c431f1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 25 Jul 2015 21:11:23 -0700 Subject: [PATCH 056/129] quiet compiler --- interface/src/Application.cpp | 4 ---- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/MyAvatar.cpp | 1 - interface/src/devices/DdeFaceTracker.h | 5 ++--- interface/src/ui/ApplicationCompositor.cpp | 2 +- interface/src/ui/AudioStatsDialog.cpp | 6 ++++-- interface/src/ui/overlays/Cube3DOverlay.cpp | 1 - 7 files changed, 9 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c2be31cfb3..fa2a82ecb4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3389,14 +3389,10 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi // set the bounds of rear mirror view gpu::Vec4i viewport; if (billboard) { - QSize size = DependencyManager::get()->getFrameBufferSize(); viewport = gpu::Vec4i(0, 0, region.width(), region.height()); } else { // if not rendering the billboard, the region is in device independent coordinates; must convert to device - QSize size = DependencyManager::get()->getFrameBufferSize(); float ratio = (float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); - int x = region.x() * ratio; - int y = region.y() * ratio; int width = region.width() * ratio; int height = region.height() * ratio; viewport = gpu::Vec4i(0, 0, width, height); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9f457e558d..095a225952 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -462,8 +462,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { const float LOOKING_AT_ME_ALPHA_START = 0.8f; const float LOOKING_AT_ME_DURATION = 0.5f; // seconds quint64 now = usecTimestampNow(); - float alpha = LOOKING_AT_ME_ALPHA_START - * (1.0f - ((float)(usecTimestampNow() - getHead()->getLookingAtMeStarted())) + float alpha = LOOKING_AT_ME_ALPHA_START + * (1.0f - ((float)(now - getHead()->getLookingAtMeStarted())) / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND)); if (alpha > 0.0f) { QSharedPointer geometry = getHead()->getFaceModel().getGeometry(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c6c6919325..f332173568 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1290,7 +1290,6 @@ bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { void MyAvatar::updateOrientation(float deltaTime) { // Smoothly rotate body with arrow keys - float driveLeft = _driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT]; float targetSpeed = (_driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT]) * YAW_SPEED; if (targetSpeed != 0.0f) { const float ROTATION_RAMP_TIMESCALE = 0.1f; diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 5536fa14bd..9673f541d2 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -91,13 +91,12 @@ private: int _leftBlinkIndex; int _rightBlinkIndex; - int _leftEyeOpenIndex; - int _rightEyeOpenIndex; - int _leftEyeDownIndex; int _rightEyeDownIndex; int _leftEyeInIndex; int _rightEyeInIndex; + int _leftEyeOpenIndex; + int _rightEyeOpenIndex; int _browDownLeftIndex; int _browDownRightIndex; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 54fb4fbd1f..9bda88b3bf 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -495,7 +495,7 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) { glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection(); // Get the angles, scaled between (-0.5,0.5) - float xAngle = (atan2(direction.z, direction.x) + PI_OVER_TWO); + float xAngle = (atan2f(direction.z, direction.x) + PI_OVER_TWO); float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)PI_OVER_TWO)); // Get the pixel range over which the xAngle and yAngle are scaled diff --git a/interface/src/ui/AudioStatsDialog.cpp b/interface/src/ui/AudioStatsDialog.cpp index 116cc60b5e..e57182e251 100644 --- a/interface/src/ui/AudioStatsDialog.cpp +++ b/interface/src/ui/AudioStatsDialog.cpp @@ -125,8 +125,10 @@ void AudioStatsDialog::renderStats() { audioInputBufferLatency = (double)_stats->getAudioInputMsecsReadStats().getWindowAverage(); inputRingBufferLatency = (double)_stats->getInputRungBufferMsecsAvailableStats().getWindowAverage(); networkRoundtripLatency = (double) audioMixerNodePointer->getPingMs(); - mixerRingBufferLatency = (double)_stats->getMixerAvatarStreamStats()._framesAvailableAverage * AudioConstants::NETWORK_FRAME_MSECS; - outputRingBufferLatency = (double)downstreamAudioStreamStats._framesAvailableAverage * AudioConstants::NETWORK_FRAME_MSECS; + mixerRingBufferLatency = (double)_stats->getMixerAvatarStreamStats()._framesAvailableAverage * + (double)AudioConstants::NETWORK_FRAME_MSECS; + outputRingBufferLatency = (double)downstreamAudioStreamStats._framesAvailableAverage * + (double)AudioConstants::NETWORK_FRAME_MSECS; audioOutputBufferLatency = (double)_stats->getAudioOutputMsecsUnplayedStats().getWindowAverage(); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 961d7f765b..200a1a328f 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -36,7 +36,6 @@ void Cube3DOverlay::render(RenderArgs* args) { // TODO: handle registration point?? glm::vec3 position = getPosition(); - glm::vec3 center = getCenter(); glm::vec3 dimensions = getDimensions(); glm::quat rotation = getRotation(); From 5cc0b45850fa489dc0439a2a1c40c4f5a3089bc8 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 15 Jul 2015 18:27:39 -0700 Subject: [PATCH 057/129] Improved ParticleEffectEntityItem rendering and updates * Created custom pipelines and shaders for untextured and textured particle rendering. * Created custom render payload for particles * Moved all particle updates into simulation rather then render. * Uses pendingChanges.updateItem lambda to update the playload with new data for rendering. * ParticleEffectEntityItem now updates its dimensions properly, based on emitter properties. * Bug fix for dt not accumulating properly, during gaps between updates. now we just update all the time. (super cheap tho, if there are no particles animating) --- examples/particles.js | 7 +- libraries/entities-renderer/CMakeLists.txt | 2 + .../RenderableParticleEffectEntityItem.cpp | 327 ++++++++++++++---- .../src/RenderableParticleEffectEntityItem.h | 25 +- .../src/textured_particle.slf | 20 ++ .../src/textured_particle.slv | 28 ++ .../src/untextured_particle.slf | 16 + .../src/untextured_particle.slv | 24 ++ .../entities/src/ParticleEffectEntityItem.cpp | 80 ++++- .../entities/src/ParticleEffectEntityItem.h | 14 +- 10 files changed, 457 insertions(+), 86 deletions(-) create mode 100644 libraries/entities-renderer/src/textured_particle.slf create mode 100644 libraries/entities-renderer/src/textured_particle.slv create mode 100644 libraries/entities-renderer/src/untextured_particle.slf create mode 100644 libraries/entities-renderer/src/untextured_particle.slv diff --git a/examples/particles.js b/examples/particles.js index c26458a9af..deb6228fff 100644 --- a/examples/particles.js +++ b/examples/particles.js @@ -44,6 +44,7 @@ emitStrength: emitStrength, emitDirection: emitDirection, color: color, + lifespan: 1.0, visible: true, locked: false }); @@ -67,13 +68,13 @@ var objs = []; function Init() { objs.push(new TestBox()); - objs.push(new TestFx({ red: 255, blue: 0, green: 0 }, + objs.push(new TestFx({ red: 255, green: 0, blue: 0 }, { x: 0.5, y: 1.0, z: 0.0 }, 100, 3, 1)); - objs.push(new TestFx({ red: 0, blue: 255, green: 0 }, + objs.push(new TestFx({ red: 0, green: 255, blue: 0 }, { x: 0, y: 1, z: 0 }, 1000, 5, 0.5)); - objs.push(new TestFx({ red: 0, blue: 0, green: 255 }, + objs.push(new TestFx({ red: 0, green: 0, blue: 255 }, { x: -0.5, y: 1, z: 0 }, 100, 3, 1)); } diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 810d5f5843..e9adf2b750 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -1,5 +1,7 @@ set(TARGET_NAME entities-renderer) +AUTOSCRIBE_SHADER_LIB(gpu model render) + # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Widgets OpenGL Network Script) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 48ac83dfc2..738a150dc5 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -14,22 +14,141 @@ #include #include #include +#include #include "EntitiesRendererLogging.h" #include "RenderableParticleEffectEntityItem.h" +#include "untextured_particle_vert.h" +#include "untextured_particle_frag.h" +#include "textured_particle_vert.h" +#include "textured_particle_frag.h" + +class ParticlePayload { +public: + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + typedef RenderableParticleEffectEntityItem::Vertex Vertex; + + ParticlePayload() : _vertexFormat(std::make_shared()), + _vertexBuffer(std::make_shared()), + _indexBuffer(std::make_shared()) { + _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC3F_XYZ, 0); + _vertexFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), offsetof(Vertex, uv)); + _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, offsetof(Vertex, rgba)); + } + + void setPipeline(gpu::PipelinePointer pipeline) { _pipeline = pipeline; } + const gpu::PipelinePointer& getPipeline() const { return _pipeline; } + + const Transform& getModelTransform() const { return _modelTransform; } + void setModelTransform(const Transform& modelTransform) { _modelTransform = modelTransform; } + + const AABox& getBound() const { return _bound; } + void setBound(AABox& bound) { _bound = bound; } + + gpu::BufferPointer getVertexBuffer() { return _vertexBuffer; } + const gpu::BufferPointer& getVertexBuffer() const { return _vertexBuffer; } + + gpu::BufferPointer getIndexBuffer() { return _indexBuffer; } + const gpu::BufferPointer& getIndexBuffer() const { return _indexBuffer; } + + void setTexture(gpu::TexturePointer texture) { _texture = texture; } + const gpu::TexturePointer& getTexture() const { return _texture; } + + bool getVisibleFlag() const { return _visibleFlag; } + void setVisibleFlag(bool visibleFlag) { _visibleFlag = visibleFlag; } + + void render(RenderArgs* args) const { + assert(_pipeline); + + gpu::Batch& batch = *args->_batch; + batch.setPipeline(_pipeline); + + if (_texture) { + batch.setResourceTexture(0, _texture); + } + + batch.setModelTransform(_modelTransform); + batch.setInputFormat(_vertexFormat); + batch.setInputBuffer(0, _vertexBuffer, 0, sizeof(Vertex)); + batch.setIndexBuffer(gpu::UINT16, _indexBuffer, 0); + + auto numIndices = _indexBuffer->getSize() / sizeof(uint16_t); + batch.drawIndexed(gpu::TRIANGLES, numIndices); + } + +protected: + Transform _modelTransform; + AABox _bound; + gpu::PipelinePointer _pipeline; + gpu::Stream::FormatPointer _vertexFormat; + gpu::BufferPointer _vertexBuffer; + gpu::BufferPointer _indexBuffer; + gpu::TexturePointer _texture; + bool _visibleFlag = true; +}; + +namespace render { + template <> + const ItemKey payloadGetKey(const ParticlePayload::Pointer& payload) { + if (payload->getVisibleFlag()) { + return ItemKey::Builder::transparentShape(); + } else { + return ItemKey::Builder().withInvisible().build(); + } + } + + template <> + const Item::Bound payloadGetBound(const ParticlePayload::Pointer& payload) { + return payload->getBound(); + } + + template <> + void payloadRender(const ParticlePayload::Pointer& payload, RenderArgs* args) { + payload->render(args); + } +} + +gpu::PipelinePointer RenderableParticleEffectEntityItem::_texturedPipeline; +gpu::PipelinePointer RenderableParticleEffectEntityItem::_untexturedPipeline; + EntityItemPointer RenderableParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return std::make_shared(entityID, properties); } RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : ParticleEffectEntityItem(entityItemID, properties) { - _cacheID = DependencyManager::get()->allocateID(); + + // lazy creation of particle system pipeline + if (!_untexturedPipeline && !_texturedPipeline) { + createPipelines(); + } } -void RenderableParticleEffectEntityItem::render(RenderArgs* args) { - Q_ASSERT(getType() == EntityTypes::ParticleEffect); - PerformanceTimer perfTimer("RenderableParticleEffectEntityItem::render"); +bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, + render::ScenePointer scene, + render::PendingChanges& pendingChanges) { + + auto particlePayload = std::shared_ptr(new ParticlePayload()); + particlePayload->setPipeline(_untexturedPipeline); + _renderItemId = scene->allocateID(); + auto renderData = ParticlePayload::Pointer(particlePayload); + auto renderPayload = render::PayloadPointer(new ParticlePayload::Payload(renderData)); + pendingChanges.resetItem(_renderItemId, renderPayload); + _scene = scene; + return true; +} + +void RenderableParticleEffectEntityItem::removeFromScene(EntityItemPointer self, + render::ScenePointer scene, + render::PendingChanges& pendingChanges) { + pendingChanges.removeItem(_renderItemId); + _scene = nullptr; +}; + +void RenderableParticleEffectEntityItem::update(const quint64& now) { + ParticleEffectEntityItem::update(now); if (_texturesChangedFlag) { if (_textures.isEmpty()) { @@ -42,71 +161,151 @@ void RenderableParticleEffectEntityItem::render(RenderArgs* args) { _texturesChangedFlag = false; } - bool textured = _texture && _texture->isLoaded(); - updateQuads(args, textured); - - Q_ASSERT(args->_batch); - gpu::Batch& batch = *args->_batch; - if (textured) { - batch.setResourceTexture(0, _texture->getGPUTexture()); - } - batch.setModelTransform(getTransformToCenter()); - DependencyManager::get()->bindSimpleProgram(batch, textured); - DependencyManager::get()->renderVertices(batch, gpu::QUADS, _cacheID); -}; + updateRenderItem(); +} static glm::vec3 zSortAxis; static bool zSort(const glm::vec3& rhs, const glm::vec3& lhs) { return glm::dot(rhs, ::zSortAxis) > glm::dot(lhs, ::zSortAxis); } -void RenderableParticleEffectEntityItem::updateQuads(RenderArgs* args, bool textured) { - float particleRadius = getParticleRadius(); - glm::vec4 particleColor(toGlm(getXColor()), getLocalRenderAlpha()); - - glm::vec3 upOffset = args->_viewFrustum->getUp() * particleRadius; - glm::vec3 rightOffset = args->_viewFrustum->getRight() * particleRadius; - - QVector vertices; - QVector positions; - QVector textureCoords; - vertices.reserve(getLivingParticleCount() * VERTS_PER_PARTICLE); - - if (textured) { - textureCoords.reserve(getLivingParticleCount() * VERTS_PER_PARTICLE); - } - positions.reserve(getLivingParticleCount()); - - - for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) { - positions.append(_particlePositions[i]); - if (textured) { - textureCoords.append(glm::vec2(0, 1)); - textureCoords.append(glm::vec2(1, 1)); - textureCoords.append(glm::vec2(1, 0)); - textureCoords.append(glm::vec2(0, 0)); - } - } - - // sort particles back to front - ::zSortAxis = args->_viewFrustum->getDirection(); - qSort(positions.begin(), positions.end(), zSort); - - for (int i = 0; i < positions.size(); i++) { - glm::vec3 pos = (textured) ? positions[i] : _particlePositions[i]; - - // generate corners of quad aligned to face the camera. - vertices.append(pos + rightOffset + upOffset); - vertices.append(pos - rightOffset + upOffset); - vertices.append(pos - rightOffset - upOffset); - vertices.append(pos + rightOffset - upOffset); - - } - - if (textured) { - DependencyManager::get()->updateVertices(_cacheID, vertices, textureCoords, particleColor); - } else { - DependencyManager::get()->updateVertices(_cacheID, vertices, particleColor); - } +uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + return ((uint32_t)r | (uint32_t)g << 8 | (uint32_t)b << 16 | (uint32_t)a << 24); } +void RenderableParticleEffectEntityItem::updateRenderItem() { + + if (!_scene) + return; + + float particleRadius = getParticleRadius(); + auto xcolor = getXColor(); + auto alpha = (uint8_t)(glm::clamp(getLocalRenderAlpha(), 0.0f, 1.0f) * 255.0f); + auto rgba = toRGBA(xcolor.red, xcolor.green, xcolor.blue, alpha); + + // make a copy of each particle position + std::vector positions; + positions.reserve(getLivingParticleCount()); + for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) { + positions.push_back(_particlePositions[i]); + } + + // sort particles back to front + // NOTE: this is view frustum might be one frame out of date. + auto frustum = AbstractViewStateInterface::instance()->getCurrentViewFrustum(); + ::zSortAxis = frustum->getDirection(); + qSort(positions.begin(), positions.end(), zSort); + + // allocate vertices + _vertices.clear(); + + // build vertices from particle positions + const glm::vec3 upOffset = frustum->getUp() * particleRadius; + const glm::vec3 rightOffset = frustum->getRight() * particleRadius; + for (auto&& pos : positions) { + // generate corners of quad aligned to face the camera. + _vertices.emplace_back(pos + rightOffset + upOffset, glm::vec2(1.0f, 1.0f), rgba); + _vertices.emplace_back(pos - rightOffset + upOffset, glm::vec2(0.0f, 1.0f), rgba); + _vertices.emplace_back(pos - rightOffset - upOffset, glm::vec2(0.0f, 0.0f), rgba); + _vertices.emplace_back(pos + rightOffset - upOffset, glm::vec2(1.0f, 0.0f), rgba); + } + + render::PendingChanges pendingChanges; + pendingChanges.updateItem(_renderItemId, [&](ParticlePayload& payload) { + + // update vertex buffer + auto vertexBuffer = payload.getVertexBuffer(); + size_t numBytes = sizeof(Vertex) * _vertices.size(); + vertexBuffer->resize(numBytes); + gpu::Byte* data = vertexBuffer->editData(); + memcpy(data, &(_vertices[0]), numBytes); + + // FIXME, don't update index buffer if num particles has not changed. + // update index buffer + auto indexBuffer = payload.getIndexBuffer(); + auto numQuads = (_vertices.size() / 4); + numBytes = sizeof(uint16_t) * numQuads * 6; + indexBuffer->resize(numBytes); + data = indexBuffer->editData(); + auto indexPtr = reinterpret_cast(data); + for (size_t i = 0; i < numQuads; ++i) { + indexPtr[i * 6 + 0] = i * 4 + 0; + indexPtr[i * 6 + 1] = i * 4 + 1; + indexPtr[i * 6 + 2] = i * 4 + 3; + indexPtr[i * 6 + 3] = i * 4 + 1; + indexPtr[i * 6 + 4] = i * 4 + 2; + indexPtr[i * 6 + 5] = i * 4 + 3; + } + + // update transform + glm::quat rot = _transform.getRotation(); + glm::vec3 pos = _transform.getTranslation(); + Transform t; + t.setRotation(rot); + t.setTranslation(pos); + payload.setModelTransform(t); + + // transform _particleMinBound and _particleMaxBound corners into world coords + glm::vec3 d = _particleMaxBound - _particleMinBound; + glm::vec3 corners[8] = { + pos + rot * (_particleMinBound + glm::vec3(0.0f, 0.0f, 0.0f)), + pos + rot * (_particleMinBound + glm::vec3(d.x, 0.0f, 0.0f)), + pos + rot * (_particleMinBound + glm::vec3(0.0f, d.y, 0.0f)), + pos + rot * (_particleMinBound + glm::vec3(d.x, d.y, 0.0f)), + pos + rot * (_particleMinBound + glm::vec3(0.0f, 0.0f, d.z)), + pos + rot * (_particleMinBound + glm::vec3(d.x, 0.0f, d.z)), + pos + rot * (_particleMinBound + glm::vec3(0.0f, d.y, d.z)), + pos + rot * (_particleMinBound + glm::vec3(d.x, d.y, d.z)) + }; + glm::vec3 min(FLT_MAX, FLT_MAX, FLT_MAX); + glm::vec3 max = -min; + for (int i = 0; i < 8; i++) { + min.x = std::min(min.x, corners[i].x); + min.y = std::min(min.y, corners[i].y); + min.z = std::min(min.z, corners[i].z); + max.x = std::max(max.x, corners[i].x); + max.y = std::max(max.y, corners[i].y); + max.z = std::max(max.z, corners[i].z); + } + AABox bound(min, max - min); + payload.setBound(bound); + + bool textured = _texture && _texture->isLoaded(); + if (textured) { + payload.setTexture(_texture->getGPUTexture()); + payload.setPipeline(_texturedPipeline); + } else { + payload.setTexture(nullptr); + payload.setPipeline(_untexturedPipeline); + } + }); + + _scene->enqueuePendingChanges(pendingChanges); +} + +void RenderableParticleEffectEntityItem::createPipelines() { + if (!_untexturedPipeline) { + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_BACK); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, + gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, + gpu::State::BLEND_OP_ADD, gpu::State::ONE); + auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(untextured_particle_vert))); + auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(untextured_particle_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vertShader, fragShader)); + _untexturedPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); + } + if (!_texturedPipeline) { + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_BACK); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, + gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, + gpu::State::BLEND_OP_ADD, gpu::State::ONE); + auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(textured_particle_vert))); + auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vertShader, fragShader)); + _texturedPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); + } +} diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 4ecea45ad0..9581c43ca5 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -16,20 +16,35 @@ #include "RenderableEntityItem.h" class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem { +friend class ParticlePayload; public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); - virtual void render(RenderArgs* args); - void updateQuads(RenderArgs* args, bool textured); + virtual void update(const quint64& now) override; - SIMPLE_RENDERABLE(); + void updateRenderItem(); + + virtual bool addToScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges); + virtual void removeFromScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges); protected: + render::ItemID _renderItemId; - int _cacheID; - const int VERTS_PER_PARTICLE = 4; + struct Vertex { + Vertex(glm::vec3 xyzIn, glm::vec2 uvIn, uint32_t rgbaIn) : xyz(xyzIn), uv(uvIn), rgba(rgbaIn) {} + glm::vec3 xyz; + glm::vec2 uv; + uint32_t rgba; + }; + static void createPipelines(); + + std::vector _vertices; + static gpu::PipelinePointer _untexturedPipeline; + static gpu::PipelinePointer _texturedPipeline; + + render::ScenePointer _scene; NetworkTexturePointer _texture; }; diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf new file mode 100644 index 0000000000..543aa643aa --- /dev/null +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -0,0 +1,20 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// fragment shader +// +// Copyright 2015 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 +// + +uniform sampler2D colorMap; + +varying vec4 varColor; +varying vec2 varTexCoord; + +void main(void) { + vec4 color = texture2D(colorMap, varTexCoord); + gl_FragColor = color * varColor; +} diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv new file mode 100644 index 0000000000..7564feb1ce --- /dev/null +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -0,0 +1,28 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// particle vertex shader +// +// Copyright 2015 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 +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec4 varColor; +varying vec2 varTexCoord; + +void main(void) { + // pass along the color & uvs to fragment shader + varColor = gl_Color; + varTexCoord = gl_MultiTexCoord0.xy; + + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> +} diff --git a/libraries/entities-renderer/src/untextured_particle.slf b/libraries/entities-renderer/src/untextured_particle.slf new file mode 100644 index 0000000000..bb3ed77e3f --- /dev/null +++ b/libraries/entities-renderer/src/untextured_particle.slf @@ -0,0 +1,16 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// fragment shader +// +// Copyright 2015 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 +// + +varying vec4 varColor; + +void main(void) { + gl_FragColor = varColor; +} diff --git a/libraries/entities-renderer/src/untextured_particle.slv b/libraries/entities-renderer/src/untextured_particle.slv new file mode 100644 index 0000000000..2975dab046 --- /dev/null +++ b/libraries/entities-renderer/src/untextured_particle.slv @@ -0,0 +1,24 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// particle vertex shader +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec4 varColor; + +void main(void) { + // pass along the diffuse color + varColor = gl_Color; + + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> +} \ No newline at end of file diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 95effa2980..a687e2be7a 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -39,6 +39,7 @@ #include "EntityTree.h" #include "EntityTreeElement.h" #include "EntitiesLogging.h" +#include "EntityScriptingInterface.h" #include "ParticleEffectEntityItem.h" const xColor ParticleEffectEntityItem::DEFAULT_COLOR = { 255, 255, 255 }; @@ -92,6 +93,74 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte ParticleEffectEntityItem::~ParticleEffectEntityItem() { } +void ParticleEffectEntityItem::setDimensions(const glm::vec3& value) { + computeAndUpdateDimensions(); +} + +void ParticleEffectEntityItem::setLifespan(float lifespan) { + _lifespan = lifespan; + computeAndUpdateDimensions(); +} + +void ParticleEffectEntityItem::setEmitDirection(glm::vec3 emitDirection) { + _emitDirection = glm::normalize(emitDirection); + computeAndUpdateDimensions(); +} + +void ParticleEffectEntityItem::setEmitStrength(float emitStrength) { + _emitStrength = emitStrength; + computeAndUpdateDimensions(); +} + +void ParticleEffectEntityItem::setLocalGravity(float localGravity) { + _localGravity = localGravity; + computeAndUpdateDimensions(); +} + +void ParticleEffectEntityItem::setParticleRadius(float particleRadius) { + _particleRadius = particleRadius; + computeAndUpdateDimensions(); +} + +void ParticleEffectEntityItem::computeAndUpdateDimensions() { + + const float t = _lifespan * 1.1f; // add 10% extra time, to account for incremental timer accumulation error. + const float maxOffset = (0.5f * 0.25f * _emitStrength) + _particleRadius; + + // bounds for x and z is easy to compute because there is no at^2 term. + float xMax = (_emitDirection.x * _emitStrength + maxOffset) * t; + float xMin = (_emitDirection.x * _emitStrength - maxOffset) * t; + + float zMax = (_emitDirection.z * _emitStrength + maxOffset) * t; + float zMin = (_emitDirection.z * _emitStrength - maxOffset) * t; + + // yEnd is where the particle will end. + float a = _localGravity; + float atSquared = a * t * t; + float v = _emitDirection.y * _emitStrength + maxOffset; + float vt = v * t; + float yEnd = 0.5f * atSquared + vt; + + // yApex is where the particle is at it's apex. + float yApexT = (-v / a); + float yApex = 0.0f; + + // only set apex if it's within the lifespan of the particle. + if (yApexT >= 0.0f && yApexT <= t) { + yApex = -(v * v) / (2.0f * a); + } + + float yMax = std::max(yApex, yEnd); + float yMin = std::min(yApex, yEnd); + + // times 2 because dimensions are diameters not radii. + glm::vec3 dims(2.0f * std::max(fabs(xMin), fabs(xMax)), + 2.0f * std::max(fabs(yMin), fabs(yMax)), + 2.0f * std::max(fabs(zMin), fabs(zMax))); + + EntityItem::setDimensions(dims); +} + EntityItemProperties ParticleEffectEntityItem::getProperties() const { EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class @@ -245,7 +314,7 @@ bool ParticleEffectEntityItem::isAnimatingSomething() const { } bool ParticleEffectEntityItem::needsToCallUpdate() const { - return isAnimatingSomething() ? true : EntityItem::needsToCallUpdate(); + return true; } void ParticleEffectEntityItem::update(const quint64& now) { @@ -260,13 +329,6 @@ void ParticleEffectEntityItem::update(const quint64& now) { if (isAnimatingSomething()) { stepSimulation(deltaTime); - - // update the dimensions - glm::vec3 dims; - dims.x = glm::max(glm::abs(_particleMinBound.x), glm::abs(_particleMaxBound.x)) * 2.0f; - dims.y = glm::max(glm::abs(_particleMinBound.y), glm::abs(_particleMaxBound.y)) * 2.0f; - dims.z = glm::max(glm::abs(_particleMinBound.z), glm::abs(_particleMaxBound.z)) * 2.0f; - setDimensions(dims); } EntityItem::update(now); // let our base class handle it's updates... @@ -319,7 +381,7 @@ void ParticleEffectEntityItem::setAnimationSettings(const QString& value) { qCDebug(entities) << "ParticleEffectEntityItem::setAnimationSettings() calling setAnimationFrameIndex()..."; qCDebug(entities) << " settings:" << value; qCDebug(entities) << " settingsMap[frameIndex]:" << settingsMap["frameIndex"]; - qCDebug(entities" frameIndex: %20.5f", frameIndex); + qCDebug(entities, " frameIndex: %20.5f", frameIndex); } #endif diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 3136ab6c7c..994c609f0f 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -86,12 +86,14 @@ public: void setAnimationLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); } float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } + virtual void setDimensions(const glm::vec3& value) override; + static const quint32 DEFAULT_MAX_PARTICLES; void setMaxParticles(quint32 maxParticles); quint32 getMaxParticles() const { return _maxParticles; } static const float DEFAULT_LIFESPAN; - void setLifespan(float lifespan) { _lifespan = lifespan; } + void setLifespan(float lifespan); float getLifespan() const { return _lifespan; } static const float DEFAULT_EMIT_RATE; @@ -99,21 +101,23 @@ public: float getEmitRate() const { return _emitRate; } static const glm::vec3 DEFAULT_EMIT_DIRECTION; - void setEmitDirection(glm::vec3 emitDirection) { _emitDirection = glm::normalize(emitDirection); } + void setEmitDirection(glm::vec3 emitDirection); const glm::vec3& getEmitDirection() const { return _emitDirection; } static const float DEFAULT_EMIT_STRENGTH; - void setEmitStrength(float emitStrength) { _emitStrength = emitStrength; } + void setEmitStrength(float emitStrength); float getEmitStrength() const { return _emitStrength; } static const float DEFAULT_LOCAL_GRAVITY; - void setLocalGravity(float localGravity) { _localGravity = localGravity; } + void setLocalGravity(float localGravity); float getLocalGravity() const { return _localGravity; } static const float DEFAULT_PARTICLE_RADIUS; - void setParticleRadius(float particleRadius) { _particleRadius = particleRadius; } + void setParticleRadius(float particleRadius); float getParticleRadius() const { return _particleRadius; } + void computeAndUpdateDimensions(); + bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); } float getAnimationFrameIndex() const { return _animationLoop.getFrameIndex(); } float getAnimationFPS() const { return _animationLoop.getFPS(); } From d17ddae53787a3ad094f82f65fc5491c75774a4f Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Mon, 27 Jul 2015 12:14:50 -0400 Subject: [PATCH 058/129] Added .js file to examples/example/audio and added public bucket url functionality. --- examples/example/audio/jsstreamplayer.js | 145 +++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 examples/example/audio/jsstreamplayer.js diff --git a/examples/example/audio/jsstreamplayer.js b/examples/example/audio/jsstreamplayer.js new file mode 100644 index 0000000000..27ed32e3b5 --- /dev/null +++ b/examples/example/audio/jsstreamplayer.js @@ -0,0 +1,145 @@ +// +// #20622: JS Stream Player +// ************************* +// +// Created by Kevin M. Thomas and Thoys 07/17/15. +// Copyright 2015 High Fidelity, Inc. +// kevintown.net +// +// JavaScript for the High Fidelity interface that creates a stream player with a UI and keyPressEvents for adding a stream URL in addition to play, stop and volume functionality. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +// Declare HiFi public bucket. +HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + +// Declare variables and set up new WebWindow. +var stream; +var volume = 1; +var streamWindow = new WebWindow('Stream', HIFI_PUBLIC_BUCKET + "examples/html/jsstreamplayer.html", 0, 0, false); + +// Set up toggleStreamURLButton overlay. +var toggleStreamURLButton = Overlays.addOverlay("text", { + x: 76, + y: 275, + width: 40, + height: 28, + backgroundColor: {red: 0, green: 0, blue: 0}, + color: {red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + text: " URL" +}); + +// Set up toggleStreamPlayButton overlay. +var toggleStreamPlayButton = Overlays.addOverlay("text", { + x: 122, + y: 275, + width: 38, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + text: " Play" +}); + +// Set up toggleStreamStopButton overlay. +var toggleStreamStopButton = Overlays.addOverlay("text", { + x: 166, + y: 275, + width: 40, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + text: " Stop" +}); + +// Set up increaseVolumeButton overlay. +var toggleIncreaseVolumeButton = Overlays.addOverlay("text", { + x: 211, + y: 275, + width: 18, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + text: " +" +}); + +// Set up decreaseVolumeButton overlay. +var toggleDecreaseVolumeButton = Overlays.addOverlay("text", { + x: 234, + y: 275, + width: 15, + height: 28, + backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 255, green: 255, blue: 0}, + font: {size: 15}, + topMargin: 8, + text: " -" +}); + +// Function that adds mousePressEvent functionality to connect UI to enter stream URL, play and stop stream. +function mousePressEvent(event) { + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamURLButton) { + stream = Window.prompt("Enter Stream: "); + var streamJSON = { + action: "changeStream", + stream: stream + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamPlayButton) { + var streamJSON = { + action: "changeStream", + stream: stream + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleStreamStopButton) { + var streamJSON = { + action: "changeStream", + stream: "" + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(streamJSON)); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleIncreaseVolumeButton) { + volume += 0.2; + var volumeJSON = { + action: "changeVolume", + volume: volume + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(volumeJSON)); + } + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleDecreaseVolumeButton) { + volume -= 0.2; + var volumeJSON = { + action: "changeVolume", + volume: volume + } + streamWindow.eventBridge.emitScriptEvent(JSON.stringify(volumeJSON)); + } +} + +// Call function. +Controller.mousePressEvent.connect(mousePressEvent); +streamWindow.setVisible(false); + +// Function to delete overlays upon exit. +function onScriptEnding() { + Overlays.deleteOverlay(toggleStreamURLButton); + Overlays.deleteOverlay(toggleStreamPlayButton); + Overlays.deleteOverlay(toggleStreamStopButton); + Overlays.deleteOverlay(toggleIncreaseVolumeButton); + Overlays.deleteOverlay(toggleDecreaseVolumeButton); +} + +// Call function. +Script.scriptEnding.connect(onScriptEnding); \ No newline at end of file From 5844b594dcfcdee259c9c67d50994cda801cb663 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 27 Jul 2015 09:27:16 -0700 Subject: [PATCH 059/129] Converted magic numbers to constants. --- .../RenderableParticleEffectEntityItem.cpp | 26 +++++++++++-------- .../entities/src/ParticleEffectEntityItem.cpp | 3 ++- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 738a150dc5..2b4626c2c3 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -175,8 +175,9 @@ uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { void RenderableParticleEffectEntityItem::updateRenderItem() { - if (!_scene) + if (!_scene) { return; + } float particleRadius = getParticleRadius(); auto xcolor = getXColor(); @@ -223,18 +224,20 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // FIXME, don't update index buffer if num particles has not changed. // update index buffer auto indexBuffer = payload.getIndexBuffer(); - auto numQuads = (_vertices.size() / 4); - numBytes = sizeof(uint16_t) * numQuads * 6; + const size_t NUM_VERTS_PER_PARTICLE = 4; + const size_t NUM_INDICES_PER_PARTICLE = 6; + auto numQuads = (_vertices.size() / NUM_VERTS_PER_PARTICLE); + numBytes = sizeof(uint16_t) * numQuads * NUM_INDICES_PER_PARTICLE; indexBuffer->resize(numBytes); data = indexBuffer->editData(); auto indexPtr = reinterpret_cast(data); for (size_t i = 0; i < numQuads; ++i) { - indexPtr[i * 6 + 0] = i * 4 + 0; - indexPtr[i * 6 + 1] = i * 4 + 1; - indexPtr[i * 6 + 2] = i * 4 + 3; - indexPtr[i * 6 + 3] = i * 4 + 1; - indexPtr[i * 6 + 4] = i * 4 + 2; - indexPtr[i * 6 + 5] = i * 4 + 3; + indexPtr[i * NUM_INDICES_PER_PARTICLE + 0] = i * NUM_VERTS_PER_PARTICLE + 0; + indexPtr[i * NUM_INDICES_PER_PARTICLE + 1] = i * NUM_VERTS_PER_PARTICLE + 1; + indexPtr[i * NUM_INDICES_PER_PARTICLE + 2] = i * NUM_VERTS_PER_PARTICLE + 3; + indexPtr[i * NUM_INDICES_PER_PARTICLE + 3] = i * NUM_VERTS_PER_PARTICLE + 1; + indexPtr[i * NUM_INDICES_PER_PARTICLE + 4] = i * NUM_VERTS_PER_PARTICLE + 2; + indexPtr[i * NUM_INDICES_PER_PARTICLE + 5] = i * NUM_VERTS_PER_PARTICLE + 3; } // update transform @@ -247,7 +250,8 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // transform _particleMinBound and _particleMaxBound corners into world coords glm::vec3 d = _particleMaxBound - _particleMinBound; - glm::vec3 corners[8] = { + const size_t NUM_BOX_CORNERS = 8; + glm::vec3 corners[NUM_BOX_CORNERS] = { pos + rot * (_particleMinBound + glm::vec3(0.0f, 0.0f, 0.0f)), pos + rot * (_particleMinBound + glm::vec3(d.x, 0.0f, 0.0f)), pos + rot * (_particleMinBound + glm::vec3(0.0f, d.y, 0.0f)), @@ -259,7 +263,7 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { }; glm::vec3 min(FLT_MAX, FLT_MAX, FLT_MAX); glm::vec3 max = -min; - for (int i = 0; i < 8; i++) { + for (size_t i = 0; i < NUM_BOX_CORNERS; i++) { min.x = std::min(min.x, corners[i].x); min.y = std::min(min.y, corners[i].y); min.z = std::min(min.z, corners[i].z); diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index a687e2be7a..71a5f87eb1 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -125,7 +125,8 @@ void ParticleEffectEntityItem::setParticleRadius(float particleRadius) { void ParticleEffectEntityItem::computeAndUpdateDimensions() { const float t = _lifespan * 1.1f; // add 10% extra time, to account for incremental timer accumulation error. - const float maxOffset = (0.5f * 0.25f * _emitStrength) + _particleRadius; + const float MAX_RANDOM_FACTOR = (0.5f * 0.25); + const float maxOffset = (MAX_RANDOM_FACTOR * _emitStrength) + _particleRadius; // bounds for x and z is easy to compute because there is no at^2 term. float xMax = (_emitDirection.x * _emitStrength + maxOffset) * t; From 604ef5dc71311982e25a90bb80eba499b46524c9 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 27 Jul 2015 09:28:56 -0700 Subject: [PATCH 060/129] Fixed float constant. --- libraries/entities/src/ParticleEffectEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 71a5f87eb1..4dfc9dd436 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -125,7 +125,7 @@ void ParticleEffectEntityItem::setParticleRadius(float particleRadius) { void ParticleEffectEntityItem::computeAndUpdateDimensions() { const float t = _lifespan * 1.1f; // add 10% extra time, to account for incremental timer accumulation error. - const float MAX_RANDOM_FACTOR = (0.5f * 0.25); + const float MAX_RANDOM_FACTOR = (0.5f * 0.25f); const float maxOffset = (MAX_RANDOM_FACTOR * _emitStrength) + _particleRadius; // bounds for x and z is easy to compute because there is no at^2 term. From 9c57d1544fdc237fd4476972795e91050cdffa86 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 27 Jul 2015 09:53:27 -0700 Subject: [PATCH 061/129] fix OctreeSceneStat unpacking in Application --- interface/src/Application.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fa2a82ecb4..c213d7629c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3596,19 +3596,13 @@ int Application::processOctreeStats(NLPacket& packet, SharedNodePointer sendingN int statsMessageLength = 0; const QUuid& nodeUUID = sendingNode->getUUID(); - OctreeSceneStats* octreeStats; - + // now that we know the node ID, let's add these stats to the stats for that node... _octreeSceneStatsLock.lockForWrite(); - auto it = _octreeServerSceneStats.find(nodeUUID); - if (it != _octreeServerSceneStats.end()) { - octreeStats = &it->second; - statsMessageLength = octreeStats->unpackFromPacket(packet); - } else { - OctreeSceneStats temp; - statsMessageLength = temp.unpackFromPacket(packet); - octreeStats = &temp; - } + + OctreeSceneStats* octreeStats = &_octreeServerSceneStats[nodeUUID]; + statsMessageLength = octreeStats->unpackFromPacket(packet); + _octreeSceneStatsLock.unlock(); VoxelPositionSize rootDetails; From 615218c77dc7c809a01da4265159805a81101da5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 27 Jul 2015 09:58:58 -0700 Subject: [PATCH 062/129] use a ref in stats unpacking --- interface/src/Application.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c213d7629c..69c10fc0ee 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3600,13 +3600,13 @@ int Application::processOctreeStats(NLPacket& packet, SharedNodePointer sendingN // now that we know the node ID, let's add these stats to the stats for that node... _octreeSceneStatsLock.lockForWrite(); - OctreeSceneStats* octreeStats = &_octreeServerSceneStats[nodeUUID]; - statsMessageLength = octreeStats->unpackFromPacket(packet); + OctreeSceneStats& octreeStats = _octreeServerSceneStats[nodeUUID]; + statsMessageLength = octreeStats.unpackFromPacket(packet); _octreeSceneStatsLock.unlock(); VoxelPositionSize rootDetails; - voxelDetailsForCode(octreeStats->getJurisdictionRoot(), rootDetails); + voxelDetailsForCode(octreeStats.getJurisdictionRoot(), rootDetails); // see if this is the first we've heard of this node... NodeToJurisdictionMap* jurisdiction = NULL; @@ -3631,7 +3631,7 @@ int Application::processOctreeStats(NLPacket& packet, SharedNodePointer sendingN // but OctreeSceneStats thinks it's just returning a reference to its contents. So we need to make a copy of the // details from the OctreeSceneStats to construct the JurisdictionMap JurisdictionMap jurisdictionMap; - jurisdictionMap.copyContents(octreeStats->getJurisdictionRoot(), octreeStats->getJurisdictionEndNodes()); + jurisdictionMap.copyContents(octreeStats.getJurisdictionRoot(), octreeStats.getJurisdictionEndNodes()); jurisdiction->lockForWrite(); (*jurisdiction)[nodeUUID] = jurisdictionMap; jurisdiction->unlock(); From 32d051396262b35956d1cf8b545744ac49861266 Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Mon, 27 Jul 2015 19:04:49 +0200 Subject: [PATCH 063/129] The 3Dconnextion files from https://github.com/highfidelity/hifi/pull/5351 For now without a merge conflict. Updated the menu name. Still have to look at the fast zooming and yaw on windows, probably have to add a var to prevent the button changes to be pushed to fast. Not sure why the yaw thing does not always work, could be that the position is also send at the same time and the input mapper does not not process all those synchronical. Probably will have to do something with masking the postion when the rotation is set for yaw. --- cmake/modules/FindconnexionClient.cmake | 38 + interface/CMakeLists.txt | 2 +- .../connexionclient/Inc/I3dMouseParams.h | 79 ++ interface/external/connexionclient/readme.txt | 4 + interface/src/Application.cpp | 6 + interface/src/Menu.cpp | 6 + interface/src/Menu.h | 1 + interface/src/devices/3Dconnexion.cpp | 1013 +++++++++++++++++ interface/src/devices/3Dconnexion.h | 244 ++++ tests/ui/src/main.cpp | 1 + 10 files changed, 1393 insertions(+), 1 deletion(-) create mode 100644 cmake/modules/FindconnexionClient.cmake create mode 100644 interface/external/connexionclient/Inc/I3dMouseParams.h create mode 100644 interface/external/connexionclient/readme.txt create mode 100755 interface/src/devices/3Dconnexion.cpp create mode 100755 interface/src/devices/3Dconnexion.h diff --git a/cmake/modules/FindconnexionClient.cmake b/cmake/modules/FindconnexionClient.cmake new file mode 100644 index 0000000000..1d6d7d4514 --- /dev/null +++ b/cmake/modules/FindconnexionClient.cmake @@ -0,0 +1,38 @@ +# +# FindconnexionClient.cmake +# +# Once done this will define +# +# 3DCONNEXIONCLIENT_INCLUDE_DIRS +# +# Created on 10/06/2015 by Marcel Verhagen +# Copyright 2015 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 +# + +# setup hints for 3DCONNEXIONCLIENT search +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("connexionclient") + +if (APPLE) + find_library(3DconnexionClient 3DconnexionClient) + if(EXISTS ${3DconnexionClient}) + set(CONNEXIONCLIENT_FOUND true) + set(CONNEXIONCLIENT_INCLUDE_DIR ${3DconnexionClient}) + set(CONNEXIONCLIENT_LIBRARY ${3DconnexionClient}) + set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "-weak_framework 3DconnexionClient") + message(STATUS "Found 3Dconnexion") + mark_as_advanced(CONNEXIONCLIENT_INCLUDE_DIR CONNEXIONCLIENT_LIBRARY) + endif() +endif() + +if (WIN32) + find_path(CONNEXIONCLIENT_INCLUDE_DIRS I3dMouseParams.h PATH_SUFFIXES Inc HINTS ${CONNEXIONCLIENT_SEARCH_DIRS}) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(connexionClient DEFAULT_MSG CONNEXIONCLIENT_INCLUDE_DIRS) + + mark_as_advanced(CONNEXIONCLIENT_INCLUDE_DIRS CONNEXIONCLIENT_SEARCH_DIRS) +endif() diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0c44ac801f..4ee3709f4a 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME interface) project(${TARGET_NAME}) # set a default root dir for each of our optional externals if it was not passed -set(OPTIONAL_EXTERNALS "Faceshift" "Sixense" "LeapMotion" "RtMidi" "SDL2" "RSSDK") +set(OPTIONAL_EXTERNALS "Faceshift" "Sixense" "LeapMotion" "RtMidi" "SDL2" "RSSDK" "connexionClient") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) diff --git a/interface/external/connexionclient/Inc/I3dMouseParams.h b/interface/external/connexionclient/Inc/I3dMouseParams.h new file mode 100644 index 0000000000..f250efe74f --- /dev/null +++ b/interface/external/connexionclient/Inc/I3dMouseParams.h @@ -0,0 +1,79 @@ +// +// 3DConnexion.cpp +// hifi +// +// Created by MarcelEdward Verhagen on 09-06-15. +// Copyright 2015 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 +// + + +#ifndef I3D_MOUSE_PARAMS_H +#define I3D_MOUSE_PARAMS_H + +// Parameters for the 3D mouse based on the SDK from 3Dconnexion + +class I3dMouseSensor { +public: + enum Speed { + SPEED_LOW = 0, + SPEED_MID, + SPEED_HIGH + }; + + virtual bool IsPanZoom() const = 0; + virtual bool IsRotate() const = 0; + virtual Speed GetSpeed() const = 0; + + virtual void SetPanZoom(bool isPanZoom) = 0; + virtual void SetRotate(bool isRotate) = 0; + virtual void SetSpeed(Speed speed) = 0; + +protected: + virtual ~I3dMouseSensor() {} +}; + +class I3dMouseNavigation { +public: + enum Pivot { + PIVOT_MANUAL = 0, + PIVOT_AUTO, + PIVOT_AUTO_OVERRIDE + }; + + enum Navigation { + NAVIGATION_OBJECT_MODE = 0, + NAVIGATION_CAMERA_MODE, + NAVIGATION_FLY_MODE, + NAVIGATION_WALK_MODE, + NAVIGATION_HELICOPTER_MODE + }; + + enum PivotVisibility { + PIVOT_HIDE = 0, + PIVOT_SHOW, + PIVOT_SHOW_MOVING + }; + + virtual Navigation GetNavigationMode() const = 0; + virtual Pivot GetPivotMode() const = 0; + virtual PivotVisibility GetPivotVisibility() const = 0; + virtual bool IsLockHorizon() const = 0; + + virtual void SetLockHorizon(bool bOn) = 0; + virtual void SetNavigationMode(Navigation navigation) = 0; + virtual void SetPivotMode(Pivot pivot) = 0; + virtual void SetPivotVisibility(PivotVisibility visibility) = 0; + +protected: + virtual ~I3dMouseNavigation(){} +}; + +class I3dMouseParam : public I3dMouseSensor, public I3dMouseNavigation { +public: + virtual ~I3dMouseParam() {} +}; + +#endif diff --git a/interface/external/connexionclient/readme.txt b/interface/external/connexionclient/readme.txt new file mode 100644 index 0000000000..dd67a29449 --- /dev/null +++ b/interface/external/connexionclient/readme.txt @@ -0,0 +1,4 @@ +The mac version does not require any files here. 3D connexion should be installed from +http://www.3dconnexion.eu/service/drivers.html + +For windows a header file is required Inc/I3dMouseParams.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fa2a82ecb4..33d88923eb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -115,6 +115,7 @@ #include "devices/MIDIManager.h" #include "devices/OculusManager.h" #include "devices/TV3DManager.h" +#include "devices/3Dconnexion.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" @@ -639,6 +640,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog); applicationUpdater->checkForUpdate(); + // the 3Dconnexion device wants to be initiliazed after a window is displayed. + ConnexionClient::init(); + auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::DomainConnectionDenied, this, "handleDomainConnectionDeniedPacket"); } @@ -750,6 +754,7 @@ Application::~Application() { Leapmotion::destroy(); RealSense::destroy(); + ConnexionClient::destroy(); qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages } @@ -1480,6 +1485,7 @@ void Application::focusOutEvent(QFocusEvent* event) { _keyboardMouseDevice.focusOutEvent(event); SixenseManager::getInstance().focusOutEvent(); SDL2Manager::getInstance()->focusOutEvent(); + ConnexionData::getInstance().focusOutEvent(); // synthesize events for keys currently pressed, since we may not get their release events foreach (int key, _keysPressed) { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 91ae6a4d02..c347fdac67 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -29,6 +29,7 @@ #include "devices/Faceshift.h" #include "devices/RealSense.h" #include "devices/SixenseManager.h" +#include "devices/3Dconnexion.h" #include "MainWindow.h" #include "scripting/MenuScriptingInterface.h" #if defined(Q_OS_MAC) || defined(Q_OS_WIN) @@ -447,6 +448,11 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowWhosLookingAtMe, 0, false); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, + MenuOption::Connexion, + 0, false, + &ConnexionClient::getInstance(), + SLOT(toggleConnexion(bool))); MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands"); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, false); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index bf0f89abb5..0edd93c5a6 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -161,6 +161,7 @@ namespace MenuOption { const QString CenterPlayerInView = "Center Player In View"; const QString Chat = "Chat..."; const QString Collisions = "Collisions"; + const QString Connexion = "Activate 3D Connexion Devices""; const QString Console = "Console..."; const QString ControlWithSpeech = "Control With Speech"; const QString CopyAddress = "Copy Address to Clipboard"; diff --git a/interface/src/devices/3Dconnexion.cpp b/interface/src/devices/3Dconnexion.cpp new file mode 100755 index 0000000000..111e2d5991 --- /dev/null +++ b/interface/src/devices/3Dconnexion.cpp @@ -0,0 +1,1013 @@ +// +// 3DConnexion.cpp +// hifi +// +// Created by MarcelEdward Verhagen on 09-06-15. +// Copyright 2015 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 +// + +#include "3Dconnexion.h" +#include "UserActivityLogger.h" + +const float MAX_AXIS = 75.0f; // max forward = 2x speed + +void ConnexionData::focusOutEvent() { + _axisStateMap.clear(); + _buttonPressedMap.clear(); +}; + +ConnexionData& ConnexionData::getInstance() { + static ConnexionData sharedInstance; + return sharedInstance; +} + +ConnexionData::ConnexionData() { +} + +void ConnexionData::handleAxisEvent() { + //qCWarning(interfaceapp) << "pos state x = " << cc_position.x << " y = " << cc_position.y << " z = " << cc_position.z << " Rotation x = " << cc_rotation.x << " y = " << cc_rotation.y << " z = " << cc_rotation.z; + _axisStateMap[makeInput(ROTATION_AXIS_Y_POS).getChannel()] = (cc_rotation.y > 0.0f) ? cc_rotation.y / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(ROTATION_AXIS_Y_NEG).getChannel()] = (cc_rotation.y < 0.0f) ? -cc_rotation.y / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(POSITION_AXIS_X_POS).getChannel()] = (cc_position.x > 0.0f) ? cc_position.x / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(POSITION_AXIS_X_NEG).getChannel()] = (cc_position.x < 0.0f) ? -cc_position.x / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(POSITION_AXIS_Y_POS).getChannel()] = (cc_position.y > 0.0f) ? cc_position.y / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(POSITION_AXIS_Y_NEG).getChannel()] = (cc_position.y < 0.0f) ? -cc_position.y / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(POSITION_AXIS_Z_POS).getChannel()] = (cc_position.z > 0.0f) ? cc_position.z / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(POSITION_AXIS_Z_NEG).getChannel()] = (cc_position.z < 0.0f) ? -cc_position.z / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(ROTATION_AXIS_X_POS).getChannel()] = (cc_rotation.x > 0.0f) ? cc_rotation.x / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(ROTATION_AXIS_X_NEG).getChannel()] = (cc_rotation.x < 0.0f) ? -cc_rotation.x / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(ROTATION_AXIS_Z_POS).getChannel()] = (cc_rotation.z > 0.0f) ? cc_rotation.z / MAX_AXIS : 0.0f; + _axisStateMap[makeInput(ROTATION_AXIS_Z_NEG).getChannel()] = (cc_rotation.z < 0.0f) ? -cc_rotation.z / MAX_AXIS : 0.0f; +} + +void ConnexionData::setButton(int lastButtonState) { + _buttonPressedMap.clear(); + _buttonPressedMap.insert(lastButtonState); +} + +void ConnexionData::registerToUserInputMapper(UserInputMapper& mapper) { + // Grab the current free device ID + _deviceID = mapper.getFreeDeviceID(); + + auto proxy = UserInputMapper::DeviceProxy::Pointer(new UserInputMapper::DeviceProxy("ConnexionClient")); + proxy->getButton = [this](const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; + proxy->getAxis = [this](const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; + proxy->getAvailabeInputs = [this]() -> QVector { + QVector availableInputs; + + availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_1), "Left button")); + availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_2), "Right button")); + availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_3), "Both buttons")); + + availableInputs.append(UserInputMapper::InputPair(makeInput(POSITION_AXIS_Y_NEG), "Move backward")); + availableInputs.append(UserInputMapper::InputPair(makeInput(POSITION_AXIS_Y_POS), "Move forward")); + availableInputs.append(UserInputMapper::InputPair(makeInput(POSITION_AXIS_X_POS), "Move right")); + availableInputs.append(UserInputMapper::InputPair(makeInput(POSITION_AXIS_X_NEG), "Move Left")); + availableInputs.append(UserInputMapper::InputPair(makeInput(POSITION_AXIS_Z_POS), "Move up")); + availableInputs.append(UserInputMapper::InputPair(makeInput(POSITION_AXIS_Z_NEG), "Move down")); + availableInputs.append(UserInputMapper::InputPair(makeInput(ROTATION_AXIS_Y_NEG), "Rotate backward")); + availableInputs.append(UserInputMapper::InputPair(makeInput(ROTATION_AXIS_Y_POS), "Rotate forward")); + availableInputs.append(UserInputMapper::InputPair(makeInput(ROTATION_AXIS_X_POS), "Rotate right")); + availableInputs.append(UserInputMapper::InputPair(makeInput(ROTATION_AXIS_X_NEG), "Rotate left")); + availableInputs.append(UserInputMapper::InputPair(makeInput(ROTATION_AXIS_Z_POS), "Rotate up")); + availableInputs.append(UserInputMapper::InputPair(makeInput(ROTATION_AXIS_Z_NEG), "Rotate down")); + + return availableInputs; + }; + proxy->resetDeviceBindings = [this, &mapper]() -> bool { + mapper.removeAllInputChannelsForDevice(_deviceID); + this->assignDefaultInputMapping(mapper); + return true; + }; + mapper.registerDevice(_deviceID, proxy); +} + +void ConnexionData::assignDefaultInputMapping(UserInputMapper& mapper) { + const float JOYSTICK_MOVE_SPEED = 1.0f; + //const float DPAD_MOVE_SPEED = 0.5f; + const float JOYSTICK_YAW_SPEED = 0.5f; + const float JOYSTICK_PITCH_SPEED = 0.25f; + const float BOOM_SPEED = 0.1f; + + // Y axes are flipped (up is negative) + // postion: Movement, strafing + mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(POSITION_AXIS_Y_NEG), JOYSTICK_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(POSITION_AXIS_Y_POS), JOYSTICK_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(POSITION_AXIS_X_POS), JOYSTICK_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(POSITION_AXIS_X_NEG), JOYSTICK_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(POSITION_AXIS_Z_NEG), JOYSTICK_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(POSITION_AXIS_Z_POS), JOYSTICK_MOVE_SPEED); + + // Rotation: Camera orientation with button 1 + mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(ROTATION_AXIS_Z_POS), JOYSTICK_YAW_SPEED); + mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(ROTATION_AXIS_Z_NEG), JOYSTICK_YAW_SPEED); + mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(ROTATION_AXIS_Y_NEG), JOYSTICK_PITCH_SPEED); + mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(ROTATION_AXIS_Y_POS), JOYSTICK_PITCH_SPEED); + + // Button controls + // Zoom + mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(BUTTON_1), BOOM_SPEED); + mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(BUTTON_2), BOOM_SPEED); + + // Zoom + // mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(ROTATION_AXIS_Z_NEG), BOOM_SPEED); + // mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(ROTATION_AXIS_Z_POS), BOOM_SPEED); + +} + +float ConnexionData::getButton(int channel) const { + if (!_buttonPressedMap.empty()) { + if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { + return 1.0f; + } else { + return 0.0f; + } + } + return 0.0f; +} + +float ConnexionData::getAxis(int channel) const { + auto axis = _axisStateMap.find(channel); + if (axis != _axisStateMap.end()) { + return (*axis).second; + } else { + return 0.0f; + } +} + +UserInputMapper::Input ConnexionData::makeInput(ConnexionData::ButtonChannel button) { + return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); +} + +UserInputMapper::Input ConnexionData::makeInput(ConnexionData::PositionChannel axis) { + return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); +} + +void ConnexionData::update() { + // the update is done in the ConnexionClient class. + // for windows in the nativeEventFilter the inputmapper is connected or registed or removed when an 3Dconnnexion device is attached or deteched + // for osx the api will call DeviceAddedHandler or DeviceRemoveHandler when a 3Dconnexion device is attached or detached +} + +ConnexionClient& ConnexionClient::getInstance() { + static ConnexionClient sharedInstance; + return sharedInstance; +} + +#ifdef HAVE_CONNEXIONCLIENT + +#ifdef _WIN32 + +static ConnexionClient* gMouseInput = 0; + +void ConnexionClient::toggleConnexion(bool shouldEnable) +{ + ConnexionData& connexiondata = ConnexionData::getInstance(); + if (shouldEnable && connexiondata.getDeviceID() == 0) { + ConnexionClient::init(); + } + if (!shouldEnable && connexiondata.getDeviceID() != 0) { + ConnexionClient::destroy(); + } + +} + +void ConnexionClient::init() { + if (Menu::getInstance()->isOptionChecked(MenuOption::Connexion)) { + ConnexionClient& cclient = ConnexionClient::getInstance(); + cclient.fLast3dmouseInputTime = 0; + + cclient.InitializeRawInput(GetActiveWindow()); + + gMouseInput = &cclient; + + QAbstractEventDispatcher::instance()->installNativeEventFilter(&cclient); + } +} + +void ConnexionClient::destroy() { + ConnexionClient& cclient = ConnexionClient::getInstance(); + QAbstractEventDispatcher::instance()->removeNativeEventFilter(&cclient); + ConnexionData& connexiondata = ConnexionData::getInstance(); + int deviceid = connexiondata.getDeviceID(); + connexiondata.setDeviceID(0); + Application::getUserInputMapper()->removeDevice(deviceid); +} + +#define LOGITECH_VENDOR_ID 0x46d + +#ifndef RIDEV_DEVNOTIFY +#define RIDEV_DEVNOTIFY 0x00002000 +#endif + +const int TRACE_RIDI_DEVICENAME = 0; +const int TRACE_RIDI_DEVICEINFO = 0; + +#ifdef _WIN64 +typedef unsigned __int64 QWORD; +#endif + +// object angular velocity per mouse tick 0.008 milliradians per second per count +static const double k3dmouseAngularVelocity = 8.0e-6; // radians per second per count + +static const int kTimeToLive = 5; + +enum ConnexionPid { + CONNEXIONPID_SPACEPILOT = 0xc625, + CONNEXIONPID_SPACENAVIGATOR = 0xc626, + CONNEXIONPID_SPACEEXPLORER = 0xc627, + CONNEXIONPID_SPACENAVIGATORFORNOTEBOOKS = 0xc628, + CONNEXIONPID_SPACEPILOTPRO = 0xc629 +}; + +// e3dmouse_virtual_key +enum V3dk { + V3DK_INVALID = 0 + , V3DK_MENU = 1, V3DK_FIT + , V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT, V3DK_BOTTOM, V3DK_BACK + , V3DK_CW, V3DK_CCW + , V3DK_ISO1, V3DK_ISO2 + , V3DK_1, V3DK_2, V3DK_3, V3DK_4, V3DK_5, V3DK_6, V3DK_7, V3DK_8, V3DK_9, V3DK_10 + , V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL + , V3DK_ROTATE, V3DK_PANZOOM, V3DK_DOMINANT + , V3DK_PLUS, V3DK_MINUS +}; + +struct tag_VirtualKeys { + ConnexionPid pid; + size_t nKeys; + V3dk *vkeys; +}; + +// e3dmouse_virtual_key +static const V3dk SpaceExplorerKeys[] = { + V3DK_INVALID // there is no button 0 + , V3DK_1, V3DK_2 + , V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT + , V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL + , V3DK_FIT, V3DK_MENU + , V3DK_PLUS, V3DK_MINUS + , V3DK_ROTATE +}; + +//e3dmouse_virtual_key +static const V3dk SpacePilotKeys[] = { + V3DK_INVALID + , V3DK_1, V3DK_2, V3DK_3, V3DK_4, V3DK_5, V3DK_6 + , V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT + , V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL + , V3DK_FIT, V3DK_MENU + , V3DK_PLUS, V3DK_MINUS + , V3DK_DOMINANT, V3DK_ROTATE +}; + +static const struct tag_VirtualKeys _3dmouseVirtualKeys[] = { + CONNEXIONPID_SPACEPILOT + , sizeof(SpacePilotKeys) / sizeof(SpacePilotKeys[0]) + , const_cast(SpacePilotKeys), + CONNEXIONPID_SPACEEXPLORER + , sizeof(SpaceExplorerKeys) / sizeof(SpaceExplorerKeys[0]) + , const_cast(SpaceExplorerKeys) +}; + +// Converts a hid device keycode (button identifier) of a pre-2009 3Dconnexion USB device to the standard 3d mouse virtual key definition. +// pid USB Product ID (PID) of 3D mouse device +// hidKeyCode Hid keycode as retrieved from a Raw Input packet +// return The standard 3d mouse virtual key (button identifier) or zero if an error occurs. + +// Converts a hid device keycode (button identifier) of a pre-2009 3Dconnexion USB device +// to the standard 3d mouse virtual key definition. +unsigned short HidToVirtualKey(unsigned long pid, unsigned short hidKeyCode) { + unsigned short virtualkey = hidKeyCode; + for (size_t i = 0; iremoveDevice(deviceid); + } + + if (!ConnexionClient::Is3dmouseAttached()) { + return false; + } + + MSG* message = (MSG*)(msg); + + if (message->message == WM_INPUT) { + HRAWINPUT hRawInput = reinterpret_cast(message->lParam); + gMouseInput->OnRawInput(RIM_INPUT, hRawInput); + if (result != 0) { + result = 0; + } + return true; + } + return false; +} + +ConnexionClient::ConnexionClient() { + +} + +ConnexionClient::~ConnexionClient() { + ConnexionClient& cclient = ConnexionClient::getInstance(); + QAbstractEventDispatcher::instance()->removeNativeEventFilter(&cclient); +} + +// Access the mouse parameters structure +I3dMouseParam& ConnexionClient::MouseParams() { + return f3dMouseParams; +} + +// Access the mouse parameters structure +const I3dMouseParam& ConnexionClient::MouseParams() const { + return f3dMouseParams; +} + +//Called with the processed motion data when a 3D mouse event is received +void ConnexionClient::Move3d(HANDLE device, std::vector& motionData) { + Q_UNUSED(device); + ConnexionData& connexiondata = ConnexionData::getInstance(); + connexiondata.cc_position = { motionData[0] * 1000, motionData[1] * 1000, motionData[2] * 1000 }; + connexiondata.cc_rotation = { motionData[3] * 1500, motionData[4] * 1500, motionData[5] * 1500 }; + connexiondata.handleAxisEvent(); +} + +//Called when a 3D mouse key is pressed +void ConnexionClient::On3dmouseKeyDown(HANDLE device, int virtualKeyCode) { + Q_UNUSED(device); + ConnexionData& connexiondata = ConnexionData::getInstance(); + connexiondata.setButton(virtualKeyCode); +} + +//Called when a 3D mouse key is released +void ConnexionClient::On3dmouseKeyUp(HANDLE device, int virtualKeyCode) { + Q_UNUSED(device); + ConnexionData& connexiondata = ConnexionData::getInstance(); + connexiondata.setButton(0); +} + +//Get an initialized array of PRAWINPUTDEVICE for the 3D devices +//pNumDevices returns the number of devices to register. Currently this is always 1. +static PRAWINPUTDEVICE GetDevicesToRegister(unsigned int* pNumDevices) { + // Array of raw input devices to register + static RAWINPUTDEVICE sRawInputDevices[] = { + { 0x01, 0x08, 0x00, 0x00 } // Usage Page = 0x01 Generic Desktop Page, Usage Id= 0x08 Multi-axis Controller + }; + + if (pNumDevices) { + *pNumDevices = sizeof(sRawInputDevices) / sizeof(sRawInputDevices[0]); + } + + return sRawInputDevices; +} + +//Detect the 3D mouse +bool ConnexionClient::Is3dmouseAttached() { + unsigned int numDevicesOfInterest = 0; + PRAWINPUTDEVICE devicesToRegister = GetDevicesToRegister(&numDevicesOfInterest); + + unsigned int nDevices = 0; + + if (::GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)) != 0) { + return false; + } + + if (nDevices == 0) { + return false; + } + + std::vector rawInputDeviceList(nDevices); + if (::GetRawInputDeviceList(&rawInputDeviceList[0], &nDevices, sizeof(RAWINPUTDEVICELIST)) == static_cast(-1)) { + return false; + } + + for (unsigned int i = 0; i < nDevices; ++i) { + RID_DEVICE_INFO rdi = { sizeof(rdi) }; + unsigned int cbSize = sizeof(rdi); + + if (GetRawInputDeviceInfo(rawInputDeviceList[i].hDevice, RIDI_DEVICEINFO, &rdi, &cbSize) > 0) { + //skip non HID and non logitec (3DConnexion) devices + if (rdi.dwType != RIM_TYPEHID || rdi.hid.dwVendorId != LOGITECH_VENDOR_ID) { + continue; + } + + //check if devices matches Multi-axis Controller + for (unsigned int j = 0; j < numDevicesOfInterest; ++j) { + if (devicesToRegister[j].usUsage == rdi.hid.usUsage + && devicesToRegister[j].usUsagePage == rdi.hid.usUsagePage) { + return true; + } + } + } + } + return false; +} + +// Initialize the window to recieve raw-input messages +// This needs to be called initially so that Windows will send the messages from the 3D mouse to the window. +bool ConnexionClient::InitializeRawInput(HWND hwndTarget) { + fWindow = hwndTarget; + + // Simply fail if there is no window + if (!hwndTarget) { + return false; + } + + unsigned int numDevices = 0; + PRAWINPUTDEVICE devicesToRegister = GetDevicesToRegister(&numDevices); + + if (numDevices == 0) { + return false; + } + + // Get OS version. + OSVERSIONINFO osvi = { sizeof(OSVERSIONINFO), 0 }; + ::GetVersionEx(&osvi); + + unsigned int cbSize = sizeof(devicesToRegister[0]); + for (size_t i = 0; i < numDevices; i++) { + // Set the target window to use + //devicesToRegister[i].hwndTarget = hwndTarget; + + // If Vista or newer, enable receiving the WM_INPUT_DEVICE_CHANGE message. + if (osvi.dwMajorVersion >= 6) { + devicesToRegister[i].dwFlags |= RIDEV_DEVNOTIFY; + } + } + return (::RegisterRawInputDevices(devicesToRegister, numDevices, cbSize) != FALSE); +} + +//Get the raw input data from Windows +UINT ConnexionClient::GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader) { + //Includes workaround for incorrect alignment of the RAWINPUT structure on x64 os + //when running as Wow64 (copied directly from 3DConnexion code) +#ifdef _WIN64 + return ::GetRawInputBuffer(pData, pcbSize, cbSizeHeader); +#else + BOOL bIsWow64 = FALSE; + ::IsWow64Process(GetCurrentProcess(), &bIsWow64); + if (!bIsWow64 || pData == NULL) { + return ::GetRawInputBuffer(pData, pcbSize, cbSizeHeader); + } else { + HWND hwndTarget = fWindow; + + size_t cbDataSize = 0; + UINT nCount = 0; + PRAWINPUT pri = pData; + + MSG msg; + while (PeekMessage(&msg, hwndTarget, WM_INPUT, WM_INPUT, PM_NOREMOVE)) { + HRAWINPUT hRawInput = reinterpret_cast(msg.lParam); + size_t cbSize = *pcbSize - cbDataSize; + if (::GetRawInputData(hRawInput, RID_INPUT, pri, &cbSize, cbSizeHeader) == static_cast(-1)) { + if (nCount == 0) { + return static_cast(-1); + } else { + break; + } + } + ++nCount; + + // Remove the message for the data just read + PeekMessage(&msg, hwndTarget, WM_INPUT, WM_INPUT, PM_REMOVE); + + pri = NEXTRAWINPUTBLOCK(pri); + cbDataSize = reinterpret_cast(pri)-reinterpret_cast(pData); + if (cbDataSize >= *pcbSize) { + cbDataSize = *pcbSize; + break; + } + } + return nCount; + } +#endif +} + +// Process the raw input device data +// On3dmouseInput() does all the preprocessing of the rawinput device data before +// finally calling the Move3d method. +void ConnexionClient::On3dmouseInput() { + // Don't do any data processing in background + bool bIsForeground = (::GetActiveWindow() != NULL); + if (!bIsForeground) { + // set all cached data to zero so that a zero event is seen and the cached data deleted + for (std::map::iterator it = fDevice2Data.begin(); it != fDevice2Data.end(); it++) { + it->second.fAxes.assign(6, .0); + it->second.fIsDirty = true; + } + } + + DWORD dwNow = ::GetTickCount(); // Current time; + DWORD dwElapsedTime; // Elapsed time since we were last here + + if (0 == fLast3dmouseInputTime) { + dwElapsedTime = 10; // System timer resolution + } else { + dwElapsedTime = dwNow - fLast3dmouseInputTime; + if (fLast3dmouseInputTime > dwNow) { + dwElapsedTime = ~dwElapsedTime + 1; + } + if (dwElapsedTime<1) { + dwElapsedTime = 1; + } else if (dwElapsedTime > 500) { + // Check for wild numbers because the device was removed while sending data + dwElapsedTime = 10; + } + } + + //qDebug("On3DmouseInput() period is %dms\n", dwElapsedTime); + + float mouseData2Rotation = k3dmouseAngularVelocity; + // v = w * r, we don't know r yet so lets assume r=1.) + float mouseData2PanZoom = k3dmouseAngularVelocity; + + // Grab the I3dmouseParam interface + I3dMouseParam& i3dmouseParam = f3dMouseParams; + // Take a look at the users preferred speed setting and adjust the sensitivity accordingly + I3dMouseSensor::Speed speedSetting = i3dmouseParam.GetSpeed(); + // See "Programming for the 3D Mouse", Section 5.1.3 + float speed = (speedSetting == I3dMouseSensor::SPEED_LOW ? 0.25f : speedSetting == I3dMouseSensor::SPEED_HIGH ? 4.f : 1.f); + + // Multiplying by the following will convert the 3d mouse data to real world units + mouseData2PanZoom *= speed; + mouseData2Rotation *= speed; + + std::map::iterator iterator = fDevice2Data.begin(); + while (iterator != fDevice2Data.end()) { + + // If we have not received data for a while send a zero event + if ((--(iterator->second.fTimeToLive)) == 0) { + iterator->second.fAxes.assign(6, .0); + } else if ( !iterator->second.fIsDirty) { //!t_bPoll3dmouse && + // If we are not polling then only handle the data that was actually received + ++iterator; + continue; + } + iterator->second.fIsDirty = false; + + // get a copy of the device + HANDLE hdevice = iterator->first; + + // get a copy of the motion vectors and apply the user filters + std::vector motionData = iterator->second.fAxes; + + // apply the user filters + + // Pan Zoom filter + // See "Programming for the 3D Mouse", Section 5.1.2 + if (!i3dmouseParam.IsPanZoom()) { + // Pan zoom is switched off so set the translation vector values to zero + motionData[0] = motionData[1] = motionData[2] = 0.; + } + + // Rotate filter + // See "Programming for the 3D Mouse", Section 5.1.1 + if (!i3dmouseParam.IsRotate()) { + // Rotate is switched off so set the rotation vector values to zero + motionData[3] = motionData[4] = motionData[5] = 0.; + } + + // convert the translation vector into physical data + for (int axis = 0; axis < 3; axis++) { + motionData[axis] *= mouseData2PanZoom; + } + + // convert the directed Rotate vector into physical data + // See "Programming for the 3D Mouse", Section 7.2.2 + for (int axis = 3; axis < 6; axis++) { + motionData[axis] *= mouseData2Rotation; + } + + // Now that the data has had the filters and sensitivty settings applied + // calculate the displacements since the last view update + for (int axis = 0; axis < 6; axis++) { + motionData[axis] *= dwElapsedTime; + } + + // Now a bit of book keeping before passing on the data + if (iterator->second.IsZero()) { + iterator = fDevice2Data.erase(iterator); + } else { + ++iterator; + } + + // Work out which will be the next device + HANDLE hNextDevice = 0; + if (iterator != fDevice2Data.end()) { + hNextDevice = iterator->first; + } + + // Pass the 3dmouse input to the view controller + Move3d(hdevice, motionData); + + // Because we don't know what happened in the previous call, the cache might have + // changed so reload the iterator + iterator = fDevice2Data.find(hNextDevice); + } + + if (!fDevice2Data.empty()) { + fLast3dmouseInputTime = dwNow; + } else { + fLast3dmouseInputTime = 0; + } +} + +//Called when new raw input data is available +void ConnexionClient::OnRawInput(UINT nInputCode, HRAWINPUT hRawInput) { + const size_t cbSizeOfBuffer = 1024; + BYTE pBuffer[cbSizeOfBuffer]; + + PRAWINPUT pRawInput = reinterpret_cast(pBuffer); + UINT cbSize = cbSizeOfBuffer; + + if (::GetRawInputData(hRawInput, RID_INPUT, pRawInput, &cbSize, sizeof(RAWINPUTHEADER)) == static_cast(-1)) { + return; + } + + bool b3dmouseInput = TranslateRawInputData(nInputCode, pRawInput); + ::DefRawInputProc(&pRawInput, 1, sizeof(RAWINPUTHEADER)); + + // Check for any buffered messages + cbSize = cbSizeOfBuffer; + UINT nCount = this->GetRawInputBuffer(pRawInput, &cbSize, sizeof(RAWINPUTHEADER)); + if (nCount == (UINT)-1) { + qDebug("GetRawInputBuffer returned error %d\n", GetLastError()); + } + + while (nCount>0 && nCount != static_cast(-1)) { + PRAWINPUT pri = pRawInput; + UINT nInput; + for (nInput = 0; nInputGetRawInputBuffer(pRawInput, &cbSize, sizeof(RAWINPUTHEADER)); + } + + // If we have mouse input data for the app then tell tha app about it + if (b3dmouseInput) { + On3dmouseInput(); + } +} + +bool ConnexionClient::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInput) { + bool bIsForeground = (nInputCode == RIM_INPUT); + + //qDebug("Rawinput.header.dwType=0x%x\n", pRawInput->header.dwType); + + // We are not interested in keyboard or mouse data received via raw input + if (pRawInput->header.dwType != RIM_TYPEHID) { + return false; + } + + if (TRACE_RIDI_DEVICENAME == 1) { + UINT dwSize = 0; + if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, NULL, &dwSize) == 0) { + std::vector szDeviceName(dwSize + 1); + if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, &szDeviceName[0], &dwSize) >0) { + qDebug("Device Name = %s\nDevice handle = 0x%x\n", &szDeviceName[0], pRawInput->header.hDevice); + } + } + } + + RID_DEVICE_INFO sRidDeviceInfo; + sRidDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO); + UINT cbSize = sizeof(RID_DEVICE_INFO); + + if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICEINFO, &sRidDeviceInfo, &cbSize) == cbSize) { + if (TRACE_RIDI_DEVICEINFO == 1) { + switch (sRidDeviceInfo.dwType) { + case RIM_TYPEMOUSE: + qDebug("\tsRidDeviceInfo.dwType=RIM_TYPEMOUSE\n"); + break; + case RIM_TYPEKEYBOARD: + qDebug("\tsRidDeviceInfo.dwType=RIM_TYPEKEYBOARD\n"); + break; + case RIM_TYPEHID: + qDebug("\tsRidDeviceInfo.dwType=RIM_TYPEHID\n"); + qDebug("\tVendor=0x%x\n\tProduct=0x%x\n\tUsagePage=0x%x\n\tUsage=0x%x\n", + sRidDeviceInfo.hid.dwVendorId, + sRidDeviceInfo.hid.dwProductId, + sRidDeviceInfo.hid.usUsagePage, + sRidDeviceInfo.hid.usUsage); + break; + } + } + + if (sRidDeviceInfo.hid.dwVendorId == LOGITECH_VENDOR_ID) { + if (pRawInput->data.hid.bRawData[0] == 0x01) { // Translation vector + TInputData& deviceData = fDevice2Data[pRawInput->header.hDevice]; + deviceData.fTimeToLive = kTimeToLive; + if (bIsForeground) { + short* pnRawData = reinterpret_cast(&pRawInput->data.hid.bRawData[1]); + // Cache the pan zoom data + deviceData.fAxes[0] = static_cast(pnRawData[0]); + deviceData.fAxes[1] = static_cast(pnRawData[1]); + deviceData.fAxes[2] = static_cast(pnRawData[2]); + + //qDebug("Pan/Zoom RI Data =\t0x%x,\t0x%x,\t0x%x\n", pnRawData[0], pnRawData[1], pnRawData[2]); + + if (pRawInput->data.hid.dwSizeHid >= 13) { // Highspeed package + // Cache the rotation data + deviceData.fAxes[3] = static_cast(pnRawData[3]); + deviceData.fAxes[4] = static_cast(pnRawData[4]); + deviceData.fAxes[5] = static_cast(pnRawData[5]); + deviceData.fIsDirty = true; + + //qDebug("Rotation RI Data =\t0x%x,\t0x%x,\t0x%x\n", pnRawData[3], pnRawData[4], pnRawData[5]); + return true; + } + } else { // Zero out the data if the app is not in forground + deviceData.fAxes.assign(6, 0.f); + } + } else if (pRawInput->data.hid.bRawData[0] == 0x02) { // Rotation vector + // If we are not in foreground do nothing + // The rotation vector was zeroed out with the translation vector in the previous message + if (bIsForeground) { + TInputData& deviceData = fDevice2Data[pRawInput->header.hDevice]; + deviceData.fTimeToLive = kTimeToLive; + + short* pnRawData = reinterpret_cast(&pRawInput->data.hid.bRawData[1]); + // Cache the rotation data + deviceData.fAxes[3] = static_cast(pnRawData[0]); + deviceData.fAxes[4] = static_cast(pnRawData[1]); + deviceData.fAxes[5] = static_cast(pnRawData[2]); + deviceData.fIsDirty = true; + + //qDebug("Rotation RI Data =\t0x%x,\t0x%x,\t0x%x\n", pnRawData[0], pnRawData[1], pnRawData[2]); + + return true; + } + } else if (pRawInput->data.hid.bRawData[0] == 0x03) { // Keystate change + // this is a package that contains 3d mouse keystate information + // bit0=key1, bit=key2 etc. + + unsigned long dwKeystate = *reinterpret_cast(&pRawInput->data.hid.bRawData[1]); + + //qDebug("ButtonData =0x%x\n", dwKeystate); + + // Log the keystate changes + unsigned long dwOldKeystate = fDevice2Keystate[pRawInput->header.hDevice]; + if (dwKeystate != 0) { + fDevice2Keystate[pRawInput->header.hDevice] = dwKeystate; + } else { + fDevice2Keystate.erase(pRawInput->header.hDevice); + } + + // Only call the keystate change handlers if the app is in foreground + if (bIsForeground) { + unsigned long dwChange = dwKeystate ^ dwOldKeystate; + + for (int nKeycode = 1; nKeycode<33; nKeycode++) { + if (dwChange & 0x01) { + int nVirtualKeyCode = HidToVirtualKey(sRidDeviceInfo.hid.dwProductId, nKeycode); + if (nVirtualKeyCode) { + if (dwKeystate & 0x01) { + On3dmouseKeyDown(pRawInput->header.hDevice, nVirtualKeyCode); + } else { + On3dmouseKeyUp(pRawInput->header.hDevice, nVirtualKeyCode); + } + } + } + dwChange >>= 1; + dwKeystate >>= 1; + } + } + } + } + } + return false; +} + +MouseParameters::MouseParameters() : fNavigation(NAVIGATION_OBJECT_MODE) + , fPivot(PIVOT_AUTO) + , fPivotVisibility(PIVOT_SHOW) + , fIsLockHorizon(true) + , fIsPanZoom(true) + , fIsRotate(true) + , fSpeed(SPEED_LOW) { +} + +MouseParameters::~MouseParameters() { +} + +bool MouseParameters::IsPanZoom() const { + return fIsPanZoom; +} + +bool MouseParameters::IsRotate() const { + return fIsRotate; +} + +MouseParameters::Speed MouseParameters::GetSpeed() const { + return fSpeed; +} + +void MouseParameters::SetPanZoom(bool isPanZoom) { + fIsPanZoom=isPanZoom; +} + +void MouseParameters::SetRotate(bool isRotate) { + fIsRotate=isRotate; +} + +void MouseParameters::SetSpeed(Speed speed) { + fSpeed=speed; +} + +MouseParameters::Navigation MouseParameters::GetNavigationMode() const { + return fNavigation; +} + +MouseParameters::Pivot MouseParameters::GetPivotMode() const { + return fPivot; +} + +MouseParameters::PivotVisibility MouseParameters::GetPivotVisibility() const { + return fPivotVisibility; +} + +bool MouseParameters::IsLockHorizon() const { + return fIsLockHorizon; +} + +void MouseParameters::SetLockHorizon(bool bOn) { + fIsLockHorizon=bOn; +} + +void MouseParameters::SetNavigationMode(Navigation navigation) { + fNavigation=navigation; +} + +void MouseParameters::SetPivotMode(Pivot pivot) { + if (fPivot!=PIVOT_MANUAL || pivot!=PIVOT_AUTO_OVERRIDE) { + fPivot = pivot; + } +} + +void MouseParameters::SetPivotVisibility(PivotVisibility visibility) { + fPivotVisibility = visibility; +} + +#else + +#define WITH_SEPARATE_THREAD false // set to true or false + +// Make the linker happy for the framework check (see link below for more info) +// http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html + +extern int16_t SetConnexionHandlers(ConnexionMessageHandlerProc messageHandler, ConnexionAddedHandlerProc addedHandler, ConnexionRemovedHandlerProc removedHandler, bool useSeparateThread) __attribute__((weak_import)); + +int fConnexionClientID; + +static ConnexionDeviceState lastState; + +static void DeviceAddedHandler(unsigned int connection); +static void DeviceRemovedHandler(unsigned int connection); +static void MessageHandler(unsigned int connection, unsigned int messageType, void *messageArgument); + +void ConnexionClient::toggleConnexion(bool shouldEnable) +{ + if (shouldEnable && !ConnexionClient::Is3dmouseAttached()) { + ConnexionClient::init(); + } + if (!shouldEnable && ConnexionClient::Is3dmouseAttached()) { + ConnexionClient::destroy(); + } + +} + +void ConnexionClient::init() { + // Make sure the framework is installed + if (SetConnexionHandlers != NULL && Menu::getInstance()->isOptionChecked(MenuOption::Connexion)) { + // Install message handler and register our client + InstallConnexionHandlers(MessageHandler, DeviceAddedHandler, DeviceRemovedHandler); + // Either use this to take over in our application only... does not work + // fConnexionClientID = RegisterConnexionClient('MCTt', "\pConnexion Client Test", kConnexionClientModeTakeOver, kConnexionMaskAll); + + // ...or use this to take over system-wide + fConnexionClientID = RegisterConnexionClient(kConnexionClientWildcard, NULL, kConnexionClientModeTakeOver, kConnexionMaskAll); + ConnexionData& connexiondata = ConnexionData::getInstance(); + memcpy(&connexiondata.clientId, &fConnexionClientID, (long)sizeof(int)); + + // A separate API call is required to capture buttons beyond the first 8 + SetConnexionClientButtonMask(fConnexionClientID, kConnexionMaskAllButtons); + + // use default switches + ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchesDisabled, NULL); + + if (ConnexionClient::Is3dmouseAttached() && connexiondata.getDeviceID() == 0) { + connexiondata.registerToUserInputMapper(*Application::getUserInputMapper()); + connexiondata.assignDefaultInputMapping(*Application::getUserInputMapper()); + UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion"); + } + //let one axis be dominant + //ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchDominant | kConnexionSwitchEnableAll, NULL); + } +} + +void ConnexionClient::destroy() { + // Make sure the framework is installed + if (&InstallConnexionHandlers != NULL) { + // Unregister our client and clean up all handlers + if (fConnexionClientID) { + UnregisterConnexionClient(fConnexionClientID); + } + CleanupConnexionHandlers(); + fConnexionClientID = 0; + ConnexionData& connexiondata = ConnexionData::getInstance(); + if (connexiondata.getDeviceID()!=0) { + Application::getUserInputMapper()->removeDevice(connexiondata.getDeviceID()); + connexiondata.setDeviceID(0); + } + } +} + +void DeviceAddedHandler(unsigned int connection) { + ConnexionData& connexiondata = ConnexionData::getInstance(); + if (connexiondata.getDeviceID() == 0) { + qCWarning(interfaceapp) << "3Dconnexion device added "; + connexiondata.registerToUserInputMapper(*Application::getUserInputMapper()); + connexiondata.assignDefaultInputMapping(*Application::getUserInputMapper()); + UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion"); + } +} + +void DeviceRemovedHandler(unsigned int connection) { + ConnexionData& connexiondata = ConnexionData::getInstance(); + if (connexiondata.getDeviceID() != 0) { + qCWarning(interfaceapp) << "3Dconnexion device removed"; + Application::getUserInputMapper()->removeDevice(connexiondata.getDeviceID()); + connexiondata.setDeviceID(0); + } +} + +bool ConnexionClient::Is3dmouseAttached() { + int result; + if (fConnexionClientID) { + if (ConnexionControl(kConnexionCtlGetDeviceID, 0, &result)) { + return false; + } + return true; + } + return false; +} + +void MessageHandler(unsigned int connection, unsigned int messageType, void *messageArgument) { + ConnexionDeviceState *state; + + switch (messageType) { + case kConnexionMsgDeviceState: + state = (ConnexionDeviceState*)messageArgument; + if (state->client == fConnexionClientID) { + ConnexionData& connexiondata = ConnexionData::getInstance(); + connexiondata.cc_position = { state->axis[0], state->axis[1], state->axis[2] }; + connexiondata.cc_rotation = { state->axis[3], state->axis[4], state->axis[5] }; + + connexiondata.handleAxisEvent(); + if (state->buttons != lastState.buttons) { + connexiondata.setButton(state->buttons); + } + memmove(&lastState, state, (long)sizeof(ConnexionDeviceState)); + } + break; + case kConnexionMsgPrefsChanged: + // the prefs have changed, do something + break; + default: + // other messageTypes can happen and should be ignored + break; + } + +} + +#endif // __APPLE__ + +#endif // HAVE_CONNEXIONCLIENT diff --git a/interface/src/devices/3Dconnexion.h b/interface/src/devices/3Dconnexion.h new file mode 100755 index 0000000000..28b4924e44 --- /dev/null +++ b/interface/src/devices/3Dconnexion.h @@ -0,0 +1,244 @@ +// 3DConnexion.h +// hifi +// +// Created by Marcel Verhagen on 09-06-15. +// Copyright 2015 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 +// + +#ifndef hifi_ConnexionClient_h +#define hifi_ConnexionClient_h + +#include +#include +#include "InterfaceLogging.h" +#include "Application.h" + +#include "ui/UserInputMapper.h" + +#ifndef HAVE_CONNEXIONCLIENT +class ConnexionClient : public QObject { + Q_OBJECT +public: + static ConnexionClient& getInstance(); + static void init() {}; + static void destroy() {}; + static bool Is3dmouseAttached() { return false; }; +public slots: + void toggleConnexion(bool shouldEnable) {}; +}; +#endif // NOT_HAVE_CONNEXIONCLIENT + +#ifdef HAVE_CONNEXIONCLIENT +// the windows connexion rawinput +#ifdef _WIN32 + +#include "I3dMouseParams.h" +#include +#include +#include +#include + +// windows rawinput parameters +class MouseParameters : public I3dMouseParam { +public: + MouseParameters(); + ~MouseParameters(); + + // I3dmouseSensor interface + bool IsPanZoom() const; + bool IsRotate() const; + Speed GetSpeed() const; + + void SetPanZoom(bool isPanZoom); + void SetRotate(bool isRotate); + void SetSpeed(Speed speed); + + // I3dmouseNavigation interface + Navigation GetNavigationMode() const; + Pivot GetPivotMode() const; + PivotVisibility GetPivotVisibility() const; + bool IsLockHorizon() const; + + void SetLockHorizon(bool bOn); + void SetNavigationMode(Navigation navigation); + void SetPivotMode(Pivot pivot); + void SetPivotVisibility(PivotVisibility visibility); + + static bool Is3dmouseAttached(); + +private: + MouseParameters(const MouseParameters&); + const MouseParameters& operator = (const MouseParameters&); + + Navigation fNavigation; + Pivot fPivot; + PivotVisibility fPivotVisibility; + bool fIsLockHorizon; + + bool fIsPanZoom; + bool fIsRotate; + Speed fSpeed; +}; + +class ConnexionClient : public QObject, public QAbstractNativeEventFilter { + Q_OBJECT +public: + ConnexionClient(); + ~ConnexionClient(); + + static ConnexionClient& getInstance(); + + ConnexionClient* client; + static void init(); + static void destroy(); + + static bool Is3dmouseAttached(); + + I3dMouseParam& MouseParams(); + const I3dMouseParam& MouseParams() const; + + virtual void Move3d(HANDLE device, std::vector& motionData); + virtual void On3dmouseKeyDown(HANDLE device, int virtualKeyCode); + virtual void On3dmouseKeyUp(HANDLE device, int virtualKeyCode); + + virtual bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) Q_DECL_OVERRIDE + { + MSG* msg = static_cast< MSG * >(message); + return ConnexionClient::RawInputEventFilter(message, result); + } + +public slots: + void toggleConnexion(bool shouldEnable); + +signals: + void Move3d(std::vector& motionData); + void On3dmouseKeyDown(int virtualKeyCode); + void On3dmouseKeyUp(int virtualKeyCode); + +private: + bool InitializeRawInput(HWND hwndTarget); + + static bool RawInputEventFilter(void* msg, long* result); + + void OnRawInput(UINT nInputCode, HRAWINPUT hRawInput); + UINT GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader); + bool TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInput); + void On3dmouseInput(); + + class TInputData { + public: + TInputData() : fAxes(6) {} + + bool IsZero() { + return (0.0f == fAxes[0] && 0.0f == fAxes[1] && 0.0f == fAxes[2] && + 0.0f == fAxes[3] && 0.0f == fAxes[4] && 0.0f == fAxes[5]); + } + + int fTimeToLive; // For telling if the device was unplugged while sending data + bool fIsDirty; + std::vector fAxes; + + }; + + HWND fWindow; + + // Data cache to handle multiple rawinput devices + std::map< HANDLE, TInputData> fDevice2Data; + std::map< HANDLE, unsigned long> fDevice2Keystate; + + // 3dmouse parameters + MouseParameters f3dMouseParams; // Rotate, Pan Zoom etc. + + // use to calculate distance traveled since last event + DWORD fLast3dmouseInputTime; +}; + +// the osx connexion api +#else + +#include +#include "3DconnexionClient/ConnexionClientAPI.h" + +class ConnexionClient : public QObject { + Q_OBJECT +public: + static ConnexionClient& getInstance(); + static bool Is3dmouseAttached(); + static void init(); + static void destroy(); +public slots: + void toggleConnexion(bool shouldEnable); +}; + +#endif // __APPLE__ + +#endif // HAVE_CONNEXIONCLIENT + + +// connnects to the userinputmapper +class ConnexionData : public QObject { + Q_OBJECT + +public: + static ConnexionData& getInstance(); + ConnexionData(); + + enum PositionChannel { + POSITION_AXIS_X_POS = 1, + POSITION_AXIS_X_NEG = 2, + POSITION_AXIS_Y_POS = 3, + POSITION_AXIS_Y_NEG = 4, + POSITION_AXIS_Z_POS = 5, + POSITION_AXIS_Z_NEG = 6, + ROTATION_AXIS_X_POS = 7, + ROTATION_AXIS_X_NEG = 8, + ROTATION_AXIS_Y_POS = 9, + ROTATION_AXIS_Y_NEG = 10, + ROTATION_AXIS_Z_POS = 11, + ROTATION_AXIS_Z_NEG = 12 + }; + + enum ButtonChannel { + BUTTON_1 = 1, + BUTTON_2 = 2, + BUTTON_3 = 3 + }; + + typedef std::unordered_set ButtonPressedMap; + typedef std::map AxisStateMap; + + float getButton(int channel) const; + float getAxis(int channel) const; + + UserInputMapper::Input makeInput(ConnexionData::PositionChannel axis); + UserInputMapper::Input makeInput(ConnexionData::ButtonChannel button); + + void registerToUserInputMapper(UserInputMapper& mapper); + void assignDefaultInputMapping(UserInputMapper& mapper); + + void update(); + void focusOutEvent(); + + int getDeviceID() { return _deviceID; } + void setDeviceID(int deviceID) { _deviceID = deviceID; } + + QString _name; + + glm::vec3 cc_position; + glm::vec3 cc_rotation; + int clientId; + + void setButton(int lastButtonState); + void handleAxisEvent(); + +protected: + int _deviceID = 0; + + ButtonPressedMap _buttonPressedMap; + AxisStateMap _axisStateMap; +}; + +#endif // defined(hifi_ConnexionClient_h) \ No newline at end of file diff --git a/tests/ui/src/main.cpp b/tests/ui/src/main.cpp index f5647bd176..fdc4dbae34 100644 --- a/tests/ui/src/main.cpp +++ b/tests/ui/src/main.cpp @@ -107,6 +107,7 @@ public: CachesSize, Chat, Collisions, + Connexion, Console, ControlWithSpeech, CopyAddress, From d3c6d8b3ccd528297de8f7e517499be4171105ef Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 27 Jul 2015 10:06:34 -0700 Subject: [PATCH 064/129] move call to get VoxelPositionSize inside debug that uses it --- interface/src/Application.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 69c10fc0ee..bb564824b0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3605,9 +3605,6 @@ int Application::processOctreeStats(NLPacket& packet, SharedNodePointer sendingN _octreeSceneStatsLock.unlock(); - VoxelPositionSize rootDetails; - voxelDetailsForCode(octreeStats.getJurisdictionRoot(), rootDetails); - // see if this is the first we've heard of this node... NodeToJurisdictionMap* jurisdiction = NULL; QString serverType; @@ -3619,6 +3616,9 @@ int Application::processOctreeStats(NLPacket& packet, SharedNodePointer sendingN jurisdiction->lockForRead(); if (jurisdiction->find(nodeUUID) == jurisdiction->end()) { jurisdiction->unlock(); + + VoxelPositionSize rootDetails; + voxelDetailsForCode(octreeStats.getJurisdictionRoot(), rootDetails); qCDebug(interfaceapp, "stats from new %s server... [%f, %f, %f, %f]", qPrintable(serverType), From d54543e83cb06f25e2c4d0007d1ea9d664803693 Mon Sep 17 00:00:00 2001 From: Bing Shearer Date: Mon, 27 Jul 2015 10:19:42 -0700 Subject: [PATCH 065/129] Tidied up per Brad's request --- examples/leaves.js | 618 ++++++++++++++++++++++++--------------------- 1 file changed, 330 insertions(+), 288 deletions(-) diff --git a/examples/leaves.js b/examples/leaves.js index e611eb7de6..af3c2f0e23 100755 --- a/examples/leaves.js +++ b/examples/leaves.js @@ -1,289 +1,331 @@ -// -// Leaves.js -// examples -// -// Created by Bing Shearer on 14 Jul 2015 -// Copyright 2015 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 -// -var leafName = "scriptLeaf"; -var leafSquall = function (properties) { - var // Properties - squallOrigin, - squallRadius, - leavesPerMinute = 60, - leafSize = { x: 0.1, y: 0.1, z: 0.1 }, - leafFallSpeed = 1, // m/s - leafLifetime = 60, // Seconds - leafSpinMax = 0, // Maximum angular velocity per axis; deg/s - debug = false, // Display origin circle; don't use running on Stack Manager - // Other - squallCircle, - SQUALL_CIRCLE_COLOR = { red: 255, green: 0, blue: 0 }, - SQUALL_CIRCLE_ALPHA = 0.5, - SQUALL_CIRCLE_ROTATION = Quat.fromPitchYawRollDegrees(90, 0, 0), - leafProperties, - leaf_MODEL_URL = "https://hifi-public.s3.amazonaws.com/ozan/support/forBing/palmLeaf.fbx", - leafTimer, - leaves = [], // HACK: Work around leaves not always getting velocities - leafVelocities = [], // HACK: Work around leaves not always getting velocities - DEGREES_TO_RADIANS = Math.PI / 180, - leafDeleteOnTearDown = true, - maxLeaves, - leafCount, - nearbyEntities, - complexMovement = false, - movementTime = 0, - maxSpinRadians = properties.leafSpinMax * DEGREES_TO_RADIANS, - windFactor, - leafDeleteOnGround = false, - floorHeight = null; - - - function processProperties() { - if (!properties.hasOwnProperty("origin")) { - print("ERROR: Leaf squall origin must be specified"); - return; - } - squallOrigin = properties.origin; - - if (!properties.hasOwnProperty("radius")) { - print("ERROR: Leaf squall radius must be specified"); - return; - } - squallRadius = properties.radius; - - if (properties.hasOwnProperty("leavesPerMinute")) { - leavesPerMinute = properties.leavesPerMinute; - } - - if (properties.hasOwnProperty("leafSize")) { - leafSize = properties.leafSize; - } - - if (properties.hasOwnProperty("leafFallSpeed")) { - leafFallSpeed = properties.leafFallSpeed; - } - - if (properties.hasOwnProperty("leafLifetime")) { - leafLifetime = properties.leafLifetime; - } - - if (properties.hasOwnProperty("leafSpinMax")) { - leafSpinMax = properties.leafSpinMax; - } - - if (properties.hasOwnProperty("debug")) { - debug = properties.debug; - } - if (properties.hasOwnProperty("floorHeight")) { - floorHeight = properties.floorHeight; - } - if (properties.hasOwnProperty("maxLeaves")) { - maxLeaves = properties.maxLeaves; - } - if (properties.hasOwnProperty("complexMovement")) { - complexMovement = properties.complexMovement; - } - if (properties.hasOwnProperty("leafDeleteOnGround")) { - leafDeleteOnGround = properties.leafDeleteOnGround; - } - if (properties.hasOwnProperty("windFactor")) { - windFactor = properties.windFactor; - } - else { - print("ERROR: Wind Factor must be defined for complex movement") - } - - leafProperties = { - type: "Model", - name: leafName, - modelURL: leaf_MODEL_URL, - lifetime: leafLifetime, - dimensions: leafSize, - velocity: { x: 0, y: -leafFallSpeed, z: 0 }, - damping: 0, - angularDamping: 0, - ignoreForCollisions: true - - }; - } - - function createleaf() { - var angle, - radius, - offset, - leaf, - spin = { x: 0, y: 0, z: 0 }, - i; - - // HACK: Work around leaves not always getting velocities set at creation - for (i = 0; i < leaves.length; i += 1) { - Entities.editEntity(leaves[i], leafVelocities[i]); - } - - angle = Math.random() * 10; - radius = Math.random() * squallRadius; - offset = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, angle, 0), { x: 0, y: -0.1, z: radius }); - leafProperties.position = Vec3.sum(squallOrigin, offset); - if (properties.leafSpinMax > 0 && !complexMovement) { - spin = { - x: Math.random() * maxSpinRadians, - y: Math.random() * maxSpinRadians, - z: Math.random() * maxSpinRadians - }; - leafProperties.angularVelocity = spin; - } - else if (complexMovement) { - spin = { x: 0, y: 0, z: 0 }; - leafProperties.angularVelocity = spin - } - leaf = Entities.addEntity(leafProperties); - - // HACK: Work around leaves not always getting velocities set at creation - leaves.push(leaf); - leafVelocities.push({ - velocity: leafProperties.velocity, - angularVelocity: spin - }); - if (leaves.length > 5) { - leaves.shift(); - leafVelocities.shift(); - } - } - - function setUp() { - if (debug) { - squallCircle = Overlays.addOverlay("circle3d", { - size: { x: 2 * squallRadius, y: 2 * squallRadius }, - color: SQUALL_CIRCLE_COLOR, - alpha: SQUALL_CIRCLE_ALPHA, - solid: true, - visible: debug, - position: squallOrigin, - rotation: SQUALL_CIRCLE_ROTATION - }); - } - - leafTimer = Script.setInterval(function () { - if (leafCount <= maxLeaves - 1) { - createleaf() - } - }, 60000 / leavesPerMinute); - } - Script.setInterval(function () { - nearbyEntities = Entities.findEntities(squallOrigin, squallRadius); - newLeafMovement() - }, 100); - - function newLeafMovement() { //new additions to leaf code. Operates at 10 Hz or every 100 ms - movementTime += 0.1; - var currentLeaf, - randomRotationSpeed = { - x: maxSpinRadians * Math.sin(movementTime), - y: maxSpinRadians * Math.random(), - z: maxSpinRadians * Math.sin(movementTime / 7) - }; - for (var i = 0; i < nearbyEntities.length; i++) { - var entityProperties = Entities.getEntityProperties(nearbyEntities[i]); - var entityName = entityProperties.name; - if (leafName === entityName) { - currentLeaf = nearbyEntities[i]; - var leafHeight = entityProperties.position.y; - if (complexMovement && leafHeight > floorHeight || complexMovement && floorHeight == null) { //actual new movement code; - var leafCurrentVel = entityProperties.velocity, - leafCurrentRot = entityProperties.rotation, - yVec = { x: 0, y: 1, z: 0 }, - leafYinWFVec = Vec3.multiplyQbyV(leafCurrentRot, yVec), - leafLocalHorVec = Vec3.cross(leafYinWFVec, yVec), - leafMostDownVec = Vec3.cross(leafYinWFVec, leafLocalHorVec), - leafDesiredVel = Vec3.multiply(leafMostDownVec, windFactor), - leafVelDelt = Vec3.subtract(leafDesiredVel, leafCurrentVel), - leafNewVel = Vec3.sum(leafCurrentVel, Vec3.multiply(leafVelDelt, windFactor)); - Entities.editEntity(currentLeaf, { - angularVelocity: randomRotationSpeed, - velocity: leafNewVel - }) - } - else if (leafHeight <= floorHeight) { - if (!leafDeleteOnGround) { - Entities.editEntity(nearbyEntities[i], { - locked: false, - velocity: { x: 0, y: 0, z: 0 }, - angularVelocity: { x: 0, y: 0, z: 0 } - }) - } - else { - Entity.deleteEntity(currentLeaf); - } - } - } - } - } - - - - getLeafCount = Script.setInterval(function () { - leafCount = 0 - for (var i = 0; i < nearbyEntities.length; i++) { - var entityName = Entities.getEntityProperties(nearbyEntities[i]).name; - //Stop Leaves at floorHeight - if (leafName === entityName) { - leafCount++; - if (i == nearbyEntities.length - 1) { - //print(leafCount); - } - } - } - }, 1000) - - - - function tearDown() { - Script.clearInterval(leafTimer); - Overlays.deleteOverlay(squallCircle); - if (leafDeleteOnTearDown) { - for (var i = 0; i < nearbyEntities.length; i++) { - var entityName = Entities.getEntityProperties(nearbyEntities[i]).name; - if (leafName === entityName) { - //We have a match - delete this entity - Entities.editEntity(nearbyEntities[i], { - locked: false - }); - Entities.deleteEntity(nearbyEntities[i]); - } - } - } - } - - - - processProperties(); - setUp(); - Script.scriptEnding.connect(tearDown); - - return { - }; -}; - -var leafSquall1 = new leafSquall({ - origin: { x: 3071.5, y: 2170, z: 6765.3 }, - radius: 100, - leavesPerMinute: 30, - leafSize: { x: 0.3, y: 0.00, z: 0.3}, - leafFallSpeed: 0.4, - leafLifetime: 100, - leafSpinMax: 30, - debug: false, - maxLeaves: 100, - leafDeleteOnTearDown: true, - complexMovement: true, - floorHeight: 2143.5, - windFactor: 0.5, - leafDeleteOnGround: false -}); - -// todo +// +// Leaves.js +// examples +// +// Created by Bing Shearer on 14 Jul 2015 +// Copyright 2015 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 +// +var leafName = "scriptLeaf"; +var leafSquall = function (properties) { + var // Properties + squallOrigin, + squallRadius, + leavesPerMinute = 60, + leafSize = { + x: 0.1, + y: 0.1, + z: 0.1 + }, + leafFallSpeed = 1, // m/s + leafLifetime = 60, // Seconds + leafSpinMax = 0, // Maximum angular velocity per axis; deg/s + debug = false, // Display origin circle; don't use running on Stack Manager + // Other + squallCircle, + SQUALL_CIRCLE_COLOR = { + red: 255, + green: 0, + blue: 0 + }, + SQUALL_CIRCLE_ALPHA = 0.5, + SQUALL_CIRCLE_ROTATION = Quat.fromPitchYawRollDegrees(90, 0, 0), + leafProperties, + leaf_MODEL_URL = "https://hifi-public.s3.amazonaws.com/ozan/support/forBing/palmLeaf.fbx", + leafTimer, + leaves = [], // HACK: Work around leaves not always getting velocities + leafVelocities = [], // HACK: Work around leaves not always getting velocities + DEGREES_TO_RADIANS = Math.PI / 180, + leafDeleteOnTearDown = true, + maxLeaves, + leafCount, + nearbyEntities, + complexMovement = false, + movementTime = 0, + maxSpinRadians = properties.leafSpinMax * DEGREES_TO_RADIANS, + windFactor, + leafDeleteOnGround = false, + floorHeight = null; + + + function processProperties() { + if (!properties.hasOwnProperty("origin")) { + print("ERROR: Leaf squall origin must be specified"); + return; + } + squallOrigin = properties.origin; + + if (!properties.hasOwnProperty("radius")) { + print("ERROR: Leaf squall radius must be specified"); + return; + } + squallRadius = properties.radius; + + if (properties.hasOwnProperty("leavesPerMinute")) { + leavesPerMinute = properties.leavesPerMinute; + } + + if (properties.hasOwnProperty("leafSize")) { + leafSize = properties.leafSize; + } + + if (properties.hasOwnProperty("leafFallSpeed")) { + leafFallSpeed = properties.leafFallSpeed; + } + + if (properties.hasOwnProperty("leafLifetime")) { + leafLifetime = properties.leafLifetime; + } + + if (properties.hasOwnProperty("leafSpinMax")) { + leafSpinMax = properties.leafSpinMax; + } + + if (properties.hasOwnProperty("debug")) { + debug = properties.debug; + } + if (properties.hasOwnProperty("floorHeight")) { + floorHeight = properties.floorHeight; + } + if (properties.hasOwnProperty("maxLeaves")) { + maxLeaves = properties.maxLeaves; + } + if (properties.hasOwnProperty("complexMovement")) { + complexMovement = properties.complexMovement; + } + if (properties.hasOwnProperty("leafDeleteOnGround")) { + leafDeleteOnGround = properties.leafDeleteOnGround; + } + if (properties.hasOwnProperty("windFactor")) { + windFactor = properties.windFactor; + } else { + print("ERROR: Wind Factor must be defined for complex movement") + } + + leafProperties = { + type: "Model", + name: leafName, + modelURL: leaf_MODEL_URL, + lifetime: leafLifetime, + dimensions: leafSize, + velocity: { + x: 0, + y: -leafFallSpeed, + z: 0 + }, + damping: 0, + angularDamping: 0, + ignoreForCollisions: true + + }; + } + + function createleaf() { + var angle, + radius, + offset, + leaf, + spin = { + x: 0, + y: 0, + z: 0 + }, + i; + + // HACK: Work around leaves not always getting velocities set at creation + for (i = 0; i < leaves.length; i++) { + Entities.editEntity(leaves[i], leafVelocities[i]); + } + + angle = Math.random() * leafSpinMax; + radius = Math.random() * squallRadius; + offset = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, angle, 0), { + x: 0, + y: -0.1, + z: radius + }); + leafProperties.position = Vec3.sum(squallOrigin, offset); + if (properties.leafSpinMax > 0 && !complexMovement) { + spin = { + x: Math.random() * maxSpinRadians, + y: Math.random() * maxSpinRadians, + z: Math.random() * maxSpinRadians + }; + leafProperties.angularVelocity = spin; + } else if (complexMovement) { + spin = { + x: 0, + y: 0, + z: 0 + }; + leafProperties.angularVelocity = spin + } + leaf = Entities.addEntity(leafProperties); + + // HACK: Work around leaves not always getting velocities set at creation + leaves.push(leaf); + leafVelocities.push({ + velocity: leafProperties.velocity, + angularVelocity: spin + }); + if (leaves.length > 5) { + leaves.shift(); + leafVelocities.shift(); + } + } + + function setUp() { + if (debug) { + squallCircle = Overlays.addOverlay("circle3d", { + size: { + x: 2 * squallRadius, + y: 2 * squallRadius + }, + color: SQUALL_CIRCLE_COLOR, + alpha: SQUALL_CIRCLE_ALPHA, + solid: true, + visible: debug, + position: squallOrigin, + rotation: SQUALL_CIRCLE_ROTATION + }); + } + + leafTimer = Script.setInterval(function () { + if (leafCount <= maxLeaves - 1) { + createleaf() + } + }, 60000 / leavesPerMinute); + } + Script.setInterval(function () { + nearbyEntities = Entities.findEntities(squallOrigin, squallRadius); + newLeafMovement() + }, 100); + + function newLeafMovement() { //new additions to leaf code. Operates at 10 Hz or every 100 ms + movementTime += 0.1; + var currentLeaf, + randomRotationSpeed = { + x: maxSpinRadians * Math.sin(movementTime), + y: maxSpinRadians * Math.random(), + z: maxSpinRadians * Math.sin(movementTime / 7) + }; + for (var i = 0; i < nearbyEntities.length; i++) { + var entityProperties = Entities.getEntityProperties(nearbyEntities[i]); + var entityName = entityProperties.name; + if (leafName === entityName) { + currentLeaf = nearbyEntities[i]; + var leafHeight = entityProperties.position.y; + if (complexMovement && leafHeight > floorHeight || complexMovement && floorHeight == null) { //actual new movement code; + var leafCurrentVel = entityProperties.velocity, + leafCurrentRot = entityProperties.rotation, + yVec = { + x: 0, + y: 1, + z: 0 + }, + leafYinWFVec = Vec3.multiplyQbyV(leafCurrentRot, yVec), + leafLocalHorVec = Vec3.cross(leafYinWFVec, yVec), + leafMostDownVec = Vec3.cross(leafYinWFVec, leafLocalHorVec), + leafDesiredVel = Vec3.multiply(leafMostDownVec, windFactor), + leafVelDelt = Vec3.subtract(leafDesiredVel, leafCurrentVel), + leafNewVel = Vec3.sum(leafCurrentVel, Vec3.multiply(leafVelDelt, windFactor)); + Entities.editEntity(currentLeaf, { + angularVelocity: randomRotationSpeed, + velocity: leafNewVel + }) + } else if (leafHeight <= floorHeight) { + if (!leafDeleteOnGround) { + Entities.editEntity(nearbyEntities[i], { + locked: false, + velocity: { + x: 0, + y: 0, + z: 0 + }, + angularVelocity: { + x: 0, + y: 0, + z: 0 + } + }) + } else { + Entity.deleteEntity(currentLeaf); + } + } + } + } + } + + + + getLeafCount = Script.setInterval(function () { + leafCount = 0 + for (var i = 0; i < nearbyEntities.length; i++) { + var entityName = Entities.getEntityProperties(nearbyEntities[i]).name; + //Stop Leaves at floorHeight + if (leafName === entityName) { + leafCount++; + if (i == nearbyEntities.length - 1) { + //print(leafCount); + } + } + } + }, 1000) + + + + function tearDown() { + Script.clearInterval(leafTimer); + Overlays.deleteOverlay(squallCircle); + if (leafDeleteOnTearDown) { + for (var i = 0; i < nearbyEntities.length; i++) { + var entityName = Entities.getEntityProperties(nearbyEntities[i]).name; + if (leafName === entityName) { + //We have a match - delete this entity + Entities.editEntity(nearbyEntities[i], { + locked: false + }); + Entities.deleteEntity(nearbyEntities[i]); + } + } + } + } + + + + processProperties(); + setUp(); + Script.scriptEnding.connect(tearDown); + + return {}; +}; + +var leafSquall1 = new leafSquall({ + origin: { + x: 3071.5, + y: 2170, + z: 6765.3 + }, + radius: 100, + leavesPerMinute: 30, + leafSize: { + x: 0.3, + y: 0.00, + z: 0.3 + }, + leafFallSpeed: 0.4, + leafLifetime: 100, + leafSpinMax: 30, + debug: false, + maxLeaves: 100, + leafDeleteOnTearDown: true, + complexMovement: true, + floorHeight: 2143.5, + windFactor: 0.5, + leafDeleteOnGround: false +}); + +// todo //deal with depth issue \ No newline at end of file From ceffbb6383fae7df2d722a24c39622c87169ee23 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 27 Jul 2015 11:41:53 -0700 Subject: [PATCH 066/129] Update edit.js to show an alert window when new objects would be out of bounds --- examples/edit.js | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index 1af016958f..ec3106e585 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -329,7 +329,7 @@ var toolBar = (function () { Script.setTimeout(resize, RESIZE_INTERVAL); } else { - print("Can't add model: Model would be out of bounds."); + Window.alert("Can't add model: Model would be out of bounds."); } } @@ -374,7 +374,7 @@ var toolBar = (function () { }); } else { - print("Can't create box: Box would be out of bounds."); + Window.alert("Can't create box: Box would be out of bounds."); } return true; } @@ -390,7 +390,7 @@ var toolBar = (function () { color: { red: 255, green: 0, blue: 0 } }); } else { - print("Can't create sphere: Sphere would be out of bounds."); + Window.alert("Can't create sphere: Sphere would be out of bounds."); } return true; } @@ -413,7 +413,7 @@ var toolBar = (function () { cutoff: 180, // in degrees }); } else { - print("Can't create Light: Light would be out of bounds."); + Window.alert("Can't create Light: Light would be out of bounds."); } return true; } @@ -433,7 +433,7 @@ var toolBar = (function () { lineHeight: 0.06 }); } else { - print("Can't create box: Text would be out of bounds."); + Window.alert("Can't create box: Text would be out of bounds."); } return true; } @@ -449,7 +449,7 @@ var toolBar = (function () { sourceUrl: "https://highfidelity.com/", }); } else { - print("Can't create Web Entity: would be out of bounds."); + Window.alert("Can't create Web Entity: would be out of bounds."); } return true; } @@ -464,7 +464,7 @@ var toolBar = (function () { dimensions: { x: 10, y: 10, z: 10 }, }); } else { - print("Can't create box: Text would be out of bounds."); + Window.alert("Can't create box: Text would be out of bounds."); } return true; } @@ -482,7 +482,7 @@ var toolBar = (function () { voxelSurfaceStyle: 1 }); } else { - print("Can't create PolyVox: would be out of bounds."); + Window.alert("Can't create PolyVox: would be out of bounds."); } return true; } @@ -1068,13 +1068,16 @@ function importSVO(importURL) { if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) { position = getPositionToCreateEntity(); } - var pastedEntityIDs = Clipboard.pasteEntities(position); - - if (isActive) { - selectionManager.setSelections(pastedEntityIDs); - } + if (position.x > 0 && position.y > 0 && position.z > 0) { + var pastedEntityIDs = Clipboard.pasteEntities(position); + if (isActive) { + selectionManager.setSelections(pastedEntityIDs); + } Window.raiseMainWindow(); + } else { + Window.alert("Can't import objects: objects would be out of bounds."); + } } else { Window.alert("There was an error importing the entity file."); } From 92595583ec280e81a3e9a5783a696bfce2b17063 Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Mon, 27 Jul 2015 11:55:17 -0700 Subject: [PATCH 067/129] Coding standard and building --- libraries/gpu/src/gpu/GLBackendTexture.cpp | 32 ------------------- .../render-utils/src/ambient_occlusion.slf | 4 +-- .../render-utils/src/occlusion_blend.slf | 7 ++-- 3 files changed, 5 insertions(+), 38 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 2696d17596..72c7de8504 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -144,38 +144,6 @@ public: case gpu::RGB: case gpu::RGBA: texel.internalFormat = GL_RED; - /* switch (dstFormat.getType()) { - case gpu::UINT32: - case gpu::INT32: - case gpu::NUINT32: - case gpu::NINT32: { - texel.internalFormat = GL_DEPTH_COMPONENT32; - break; - } - case gpu::NFLOAT: - case gpu::FLOAT: { - texel.internalFormat = GL_DEPTH_COMPONENT32F; - break; - } - case gpu::UINT16: - case gpu::INT16: - case gpu::NUINT16: - case gpu::NINT16: - case gpu::HALF: - case gpu::NHALF: { - texel.internalFormat = GL_DEPTH_COMPONENT16; - break; - } - case gpu::UINT8: - case gpu::INT8: - case gpu::NUINT8: - case gpu::NINT8: { - texel.internalFormat = GL_DEPTH_COMPONENT24; - break; - } - case gpu::NUM_TYPES: { // quiet compiler - Q_UNREACHABLE(); - }*/ break; case gpu::DEPTH: texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index 023fe2552c..7a80dd559e 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -45,7 +45,7 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - vec3 eyeDir = vec3(0.0); + vec3 eyeDir = vec3(0.0, 0.0, -3.0); vec3 cameraPositionWorldSpace; <$transformEyeToWorldDir(cam, eyeDir, cameraPositionWorldSpace)$> @@ -104,6 +104,6 @@ void main(void) { occlusion = 1.0 - occlusion / float(SAMPLE_COUNT); occlusion = clamp(pow(occlusion, g_intensity), 0.0, 1.0); - gl_FragColor = vec4(occlusion, occlusion, occlusion, 1.0); + gl_FragColor = vec4(vec3(occlusion), 1.0); } diff --git a/libraries/render-utils/src/occlusion_blend.slf b/libraries/render-utils/src/occlusion_blend.slf index 6c0101eb6f..965d806759 100644 --- a/libraries/render-utils/src/occlusion_blend.slf +++ b/libraries/render-utils/src/occlusion_blend.slf @@ -22,9 +22,8 @@ void main(void) { vec4 occlusionColor = texture2D(blurredOcclusionTexture, varTexcoord); if(occlusionColor.r > 0.8 && occlusionColor.r <= 1.0) { - gl_FragColor = vec4(vec3(0.0), 1.0); - } - else { - gl_FragColor = vec4(vec3(0.2), 1.0); + gl_FragColor = vec4(vec3(0.0), 0.0); + } else { + gl_FragColor = vec4(vec3(occlusionColor.r), 1.0); } } From c46e73434c3819d3f2b043be95af123c498d5bd6 Mon Sep 17 00:00:00 2001 From: Bing Shearer Date: Mon, 27 Jul 2015 11:59:09 -0700 Subject: [PATCH 068/129] Added small fix to error message code --- examples/leaves.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/leaves.js b/examples/leaves.js index af3c2f0e23..4610cd2ef0 100755 --- a/examples/leaves.js +++ b/examples/leaves.js @@ -100,7 +100,7 @@ var leafSquall = function (properties) { } if (properties.hasOwnProperty("windFactor")) { windFactor = properties.windFactor; - } else { + } else if (complexMovement == true){ print("ERROR: Wind Factor must be defined for complex movement") } From 1193b89918dba29ab25a0d5d14ee0d2c2b9b525f Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Mon, 27 Jul 2015 12:14:29 -0700 Subject: [PATCH 069/129] Coding standard and tab fixes --- libraries/render-utils/src/AmbientOcclusionEffect.cpp | 6 +++--- libraries/render-utils/src/AmbientOcclusionEffect.h | 6 +++--- libraries/render-utils/src/gaussian_blur.slf | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index d7fa88b276..f19fa6e18a 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -1,9 +1,9 @@ // // AmbientOcclusionEffect.cpp -// interface/src/renderer +// libraries/render-utils/src/ // -// Created by Niraj Venkat on 7/14/13. -// Copyright 2013 High Fidelity, Inc. +// Created by Niraj Venkat on 7/15/15. +// Copyright 2015 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 diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 76cb0b063d..0b695dd2ad 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -1,9 +1,9 @@ // // AmbientOcclusionEffect.h -// interface/src/renderer +// libraries/render-utils/src/ // -// Created by Andrzej Kapolka on 7/14/13. -// Copyright 2013 High Fidelity, Inc. +// Created by Niraj Venkat on 7/15/15. +// Copyright 2015 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 diff --git a/libraries/render-utils/src/gaussian_blur.slf b/libraries/render-utils/src/gaussian_blur.slf index 5b66a0b751..772a80249c 100644 --- a/libraries/render-utils/src/gaussian_blur.slf +++ b/libraries/render-utils/src/gaussian_blur.slf @@ -23,7 +23,7 @@ varying vec2 varBlurTexcoords[14]; uniform sampler2D occlusionTexture; void main(void) { - gl_FragColor = vec4(0.0); + gl_FragColor = vec4(0.0); gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 0])*0.0044299121055113265; gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 1])*0.00895781211794; gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 2])*0.0215963866053; From d2ee74f7c7c844783fd7558771d1aaf51efc22af Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Mon, 27 Jul 2015 12:20:41 -0700 Subject: [PATCH 070/129] Shader code indentation --- .../render-utils/src/ambient_occlusion.slf | 12 ++++---- libraries/render-utils/src/gaussian_blur.slf | 22 +++++++-------- .../src/gaussian_blur_horizontal.slv | 28 +++++++++---------- .../src/gaussian_blur_vertical.slv | 28 +++++++++---------- 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index 7a80dd559e..3a49accf58 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -80,10 +80,10 @@ void main(void) { vec3 normal = normalize(texture2D(normalTexture, varTexcoord).xyz); //normal = normalize(normal * normalMatrix); - vec3 rvec = vec3(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx), getRandom(varTexcoord.xx)) * 2.0 - 1.0; + vec3 rvec = vec3(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx), getRandom(varTexcoord.xx)) * 2.0 - 1.0; vec3 tangent = normalize(rvec - normal * dot(rvec, normal)); - vec3 bitangent = cross(normal, tangent); - mat3 tbn = mat3(tangent, bitangent, normal); + vec3 bitangent = cross(normal, tangent); + mat3 tbn = mat3(tangent, bitangent, normal); float occlusion = 0.0; @@ -91,13 +91,13 @@ void main(void) { vec3 samplePos = origin + (tbn * sampleKernel[i]) * g_sample_rad; vec4 offset = cam._projectionViewUntranslated * vec4(samplePos, 1.0); - offset.xy = (offset.xy / offset.w) * 0.5 + 0.5; + offset.xy = (offset.xy / offset.w) * 0.5 + 0.5; float depth = length(samplePos - cameraPositionWorldSpace); float sampleDepthVal = texture2D(depthTexture, offset.xy).r; - float rangeDelta = abs(depthVal - sampleDepthVal); - float rangeCheck = smoothstep(0.0, 1.0, g_sample_rad / rangeDelta); + float rangeDelta = abs(depthVal - sampleDepthVal); + float rangeCheck = smoothstep(0.0, 1.0, g_sample_rad / rangeDelta); occlusion += rangeCheck * step(sampleDepthVal, depth); } diff --git a/libraries/render-utils/src/gaussian_blur.slf b/libraries/render-utils/src/gaussian_blur.slf index 772a80249c..63ba14a07c 100644 --- a/libraries/render-utils/src/gaussian_blur.slf +++ b/libraries/render-utils/src/gaussian_blur.slf @@ -24,17 +24,17 @@ uniform sampler2D occlusionTexture; void main(void) { gl_FragColor = vec4(0.0); - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 0])*0.0044299121055113265; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 1])*0.00895781211794; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 2])*0.0215963866053; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 3])*0.0443683338718; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 4])*0.0776744219933; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 5])*0.115876621105; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 6])*0.147308056121; - gl_FragColor += texture2D(occlusionTexture, varTexcoord )*0.159576912161; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 7])*0.147308056121; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 8])*0.115876621105; - gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 9])*0.0776744219933; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[0])*0.0044299121055113265; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[1])*0.00895781211794; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[2])*0.0215963866053; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[3])*0.0443683338718; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[4])*0.0776744219933; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[5])*0.115876621105; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[6])*0.147308056121; + gl_FragColor += texture2D(occlusionTexture, varTexcoord)*0.159576912161; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[7])*0.147308056121; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[8])*0.115876621105; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[9])*0.0776744219933; gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[10])*0.0443683338718; gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[11])*0.0215963866053; gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[12])*0.00895781211794; diff --git a/libraries/render-utils/src/gaussian_blur_horizontal.slv b/libraries/render-utils/src/gaussian_blur_horizontal.slv index 94631b4b08..c3f326daac 100644 --- a/libraries/render-utils/src/gaussian_blur_horizontal.slv +++ b/libraries/render-utils/src/gaussian_blur_horizontal.slv @@ -23,19 +23,19 @@ void main(void) { varTexcoord = gl_MultiTexCoord0.xy; gl_Position = gl_Vertex; - varBlurTexcoords[ 0] = varTexcoord + vec2(-0.028, 0.0); - varBlurTexcoords[ 1] = varTexcoord + vec2(-0.024, 0.0); - varBlurTexcoords[ 2] = varTexcoord + vec2(-0.020, 0.0); - varBlurTexcoords[ 3] = varTexcoord + vec2(-0.016, 0.0); - varBlurTexcoords[ 4] = varTexcoord + vec2(-0.012, 0.0); - varBlurTexcoords[ 5] = varTexcoord + vec2(-0.008, 0.0); - varBlurTexcoords[ 6] = varTexcoord + vec2(-0.004, 0.0); - varBlurTexcoords[ 7] = varTexcoord + vec2( 0.004, 0.0); - varBlurTexcoords[ 8] = varTexcoord + vec2( 0.008, 0.0); - varBlurTexcoords[ 9] = varTexcoord + vec2( 0.012, 0.0); - varBlurTexcoords[10] = varTexcoord + vec2( 0.016, 0.0); - varBlurTexcoords[11] = varTexcoord + vec2( 0.020, 0.0); - varBlurTexcoords[12] = varTexcoord + vec2( 0.024, 0.0); - varBlurTexcoords[13] = varTexcoord + vec2( 0.028, 0.0); + varBlurTexcoords[0] = varTexcoord + vec2(-0.028, 0.0); + varBlurTexcoords[1] = varTexcoord + vec2(-0.024, 0.0); + varBlurTexcoords[2] = varTexcoord + vec2(-0.020, 0.0); + varBlurTexcoords[3] = varTexcoord + vec2(-0.016, 0.0); + varBlurTexcoords[4] = varTexcoord + vec2(-0.012, 0.0); + varBlurTexcoords[5] = varTexcoord + vec2(-0.008, 0.0); + varBlurTexcoords[6] = varTexcoord + vec2(-0.004, 0.0); + varBlurTexcoords[7] = varTexcoord + vec2(0.004, 0.0); + varBlurTexcoords[8] = varTexcoord + vec2(0.008, 0.0); + varBlurTexcoords[9] = varTexcoord + vec2(0.012, 0.0); + varBlurTexcoords[10] = varTexcoord + vec2(0.016, 0.0); + varBlurTexcoords[11] = varTexcoord + vec2(0.020, 0.0); + varBlurTexcoords[12] = varTexcoord + vec2(0.024, 0.0); + varBlurTexcoords[13] = varTexcoord + vec2(0.028, 0.0); } \ No newline at end of file diff --git a/libraries/render-utils/src/gaussian_blur_vertical.slv b/libraries/render-utils/src/gaussian_blur_vertical.slv index 0d6de35b85..fc35a96bf0 100644 --- a/libraries/render-utils/src/gaussian_blur_vertical.slv +++ b/libraries/render-utils/src/gaussian_blur_vertical.slv @@ -23,19 +23,19 @@ void main(void) { varTexcoord = gl_MultiTexCoord0.xy; gl_Position = gl_Vertex; - varBlurTexcoords[ 0] = varTexcoord + vec2(0.0, -0.028); - varBlurTexcoords[ 1] = varTexcoord + vec2(0.0, -0.024); - varBlurTexcoords[ 2] = varTexcoord + vec2(0.0, -0.020); - varBlurTexcoords[ 3] = varTexcoord + vec2(0.0, -0.016); - varBlurTexcoords[ 4] = varTexcoord + vec2(0.0, -0.012); - varBlurTexcoords[ 5] = varTexcoord + vec2(0.0, -0.008); - varBlurTexcoords[ 6] = varTexcoord + vec2(0.0, -0.004); - varBlurTexcoords[ 7] = varTexcoord + vec2(0.0, 0.004); - varBlurTexcoords[ 8] = varTexcoord + vec2(0.0, 0.008); - varBlurTexcoords[ 9] = varTexcoord + vec2(0.0, 0.012); - varBlurTexcoords[10] = varTexcoord + vec2(0.0, 0.016); - varBlurTexcoords[11] = varTexcoord + vec2(0.0, 0.020); - varBlurTexcoords[12] = varTexcoord + vec2(0.0, 0.024); - varBlurTexcoords[13] = varTexcoord + vec2(0.0, 0.028); + varBlurTexcoords[0] = varTexcoord + vec2(0.0, -0.028); + varBlurTexcoords[1] = varTexcoord + vec2(0.0, -0.024); + varBlurTexcoords[2] = varTexcoord + vec2(0.0, -0.020); + varBlurTexcoords[3] = varTexcoord + vec2(0.0, -0.016); + varBlurTexcoords[4] = varTexcoord + vec2(0.0, -0.012); + varBlurTexcoords[5] = varTexcoord + vec2(0.0, -0.008); + varBlurTexcoords[6] = varTexcoord + vec2(0.0, -0.004); + varBlurTexcoords[7] = varTexcoord + vec2(0.0, 0.004); + varBlurTexcoords[8] = varTexcoord + vec2(0.0, 0.008); + varBlurTexcoords[9] = varTexcoord + vec2(0.0, 0.012); + varBlurTexcoords[10] = varTexcoord + vec2(0.0, 0.016); + varBlurTexcoords[11] = varTexcoord + vec2(0.0, 0.020); + varBlurTexcoords[12] = varTexcoord + vec2(0.0, 0.024); + varBlurTexcoords[13] = varTexcoord + vec2(0.0, 0.028); } \ No newline at end of file From a5ad40bee97e14a860335f0fb3a1f74d5fc981fd Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 27 Jul 2015 14:07:28 -0700 Subject: [PATCH 071/129] INtroduce the resetStage command to clear up all cache and state in the gpu::Conference and make sure no more resource are linked --- interface/src/Application.cpp | 6 ++ libraries/gpu/src/gpu/Batch.cpp | 4 ++ libraries/gpu/src/gpu/Batch.h | 5 ++ libraries/gpu/src/gpu/Context.cpp | 1 + libraries/gpu/src/gpu/GLBackend.cpp | 20 +++++++ libraries/gpu/src/gpu/GLBackend.h | 45 ++++++++++---- libraries/gpu/src/gpu/GLBackendInput.cpp | 59 ++++++++++++++++--- libraries/gpu/src/gpu/GLBackendOutput.cpp | 5 ++ libraries/gpu/src/gpu/GLBackendPipeline.cpp | 22 +++++++ libraries/gpu/src/gpu/GLBackendQuery.cpp | 4 ++ libraries/gpu/src/gpu/GLBackendState.cpp | 2 +- libraries/gpu/src/gpu/GLBackendTransform.cpp | 4 +- .../render-utils/src/RenderDeferredTask.cpp | 1 - libraries/render/src/render/DrawTask.cpp | 40 ------------- libraries/render/src/render/DrawTask.h | 8 --- 15 files changed, 156 insertions(+), 70 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c2be31cfb3..7bfad60eaf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -996,6 +996,12 @@ void Application::paintGL() { _compositor.displayOverlayTexture(&renderArgs); } + // Reset the gpu::Context Stages + gpu::Batch batch; + batch.resetStages(); + renderArgs._context->render(batch); + + if (!OculusManager::isConnected() || OculusManager::allowSwap()) { PROFILE_RANGE(__FUNCTION__ "/bufferSwap"); _glWidget->swapBuffers(); diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 4ac33d8f14..8815c1bae1 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -288,6 +288,10 @@ void Batch::getQuery(const QueryPointer& query) { _params.push_back(_queries.cache(query)); } +void Batch::resetStages() { + ADD_COMMAND(resetStages); +} + void push_back(Batch::Params& params, const vec3& v) { params.push_back(v.x); params.push_back(v.y); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 58fe03c9cf..5f2c2dd089 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -113,6 +113,9 @@ public: void endQuery(const QueryPointer& query); void getQuery(const QueryPointer& query); + // Reset the stage caches and states + void resetStages(); + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -186,6 +189,8 @@ public: COMMAND_endQuery, COMMAND_getQuery, + COMMAND_resetStages, + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 604f39f46f..6730be33bb 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -45,3 +45,4 @@ void Context::syncCache() { void Context::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) { _backend->downloadFramebuffer(srcFramebuffer, region, destImage); } + diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 6b1d552be9..51637462f1 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -46,6 +46,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_endQuery), (&::gpu::GLBackend::do_getQuery), + (&::gpu::GLBackend::do_resetStages), + (&::gpu::GLBackend::do_glEnable), (&::gpu::GLBackend::do_glDisable), @@ -128,6 +130,8 @@ GLBackend::GLBackend() : } GLBackend::~GLBackend() { + resetStages(); + killInput(); killTransform(); } @@ -246,6 +250,22 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } +void GLBackend::do_resetStages(Batch& batch, uint32 paramOffset) { + resetStages(); +} + +void GLBackend::resetStages() { + resetInputStage(); + resetPipelineStage(); + resetTransformStage(); + resetUniformStage(); + resetResourceStage(); + resetOutputStage(); + resetQueryStage(); + + (void) CHECK_GL_ERROR(); +} + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 9d8c9ef805..59a6c1ee7e 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -195,7 +195,7 @@ public: static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS; static const int MAX_NUM_INPUT_BUFFERS = 16; - uint32 getNumInputBuffers() const { return _input._buffersState.size(); } + uint32 getNumInputBuffers() const { return _input._invalidBuffers.size(); } // The State setters called by the GLState::Commands when a new state is assigned @@ -250,12 +250,16 @@ protected: void killInput(); void syncInputStateCache(); void updateInput(); + void resetInputStage(); struct InputStageState { bool _invalidFormat = true; Stream::FormatPointer _format; + typedef std::bitset ActivationCache; + ActivationCache _attributeActivation; + typedef std::bitset BuffersState; - BuffersState _buffersState; + BuffersState _invalidBuffers; Buffers _buffers; Offsets _bufferOffsets; @@ -266,23 +270,20 @@ protected: Offset _indexBufferOffset; Type _indexBufferType; - typedef std::bitset ActivationCache; - ActivationCache _attributeActivation; - GLuint _defaultVAO; InputStageState() : _invalidFormat(true), _format(0), - _buffersState(0), - _buffers(_buffersState.size(), BufferPointer(0)), - _bufferOffsets(_buffersState.size(), 0), - _bufferStrides(_buffersState.size(), 0), - _bufferVBOs(_buffersState.size(), 0), + _attributeActivation(0), + _invalidBuffers(0), + _buffers(_invalidBuffers.size(), BufferPointer(0)), + _bufferOffsets(_invalidBuffers.size(), 0), + _bufferStrides(_invalidBuffers.size(), 0), + _bufferVBOs(_invalidBuffers.size(), 0), _indexBuffer(0), _indexBufferOffset(0), _indexBufferType(UINT32), - _attributeActivation(0), _defaultVAO(0) {} } _input; @@ -298,6 +299,7 @@ protected: // Synchronize the state cache of this Backend with the actual real state of the GL Context void syncTransformStateCache(); void updateTransform(); + void resetTransformStage(); struct TransformStageState { TransformObject _transformObject; TransformCamera _transformCamera; @@ -330,12 +332,20 @@ protected: // Uniform Stage void do_setUniformBuffer(Batch& batch, uint32 paramOffset); - void do_setResourceTexture(Batch& batch, uint32 paramOffset); + void resetUniformStage(); struct UniformStageState { }; + // Resource Stage + void do_setResourceTexture(Batch& batch, uint32 paramOffset); + + void resetResourceStage(); + struct ResourceStageState { + + }; + // Pipeline Stage void do_setPipeline(Batch& batch, uint32 paramOffset); void do_setStateBlendFactor(Batch& batch, uint32 paramOffset); @@ -349,6 +359,7 @@ protected: void syncPipelineStateCache(); // Grab the actual gl state into it's gpu::State equivalent. THis is used by the above call syncPipleineStateCache() void getCurrentGLState(State::Data& state); + void resetPipelineStage(); struct PipelineStageState { @@ -388,6 +399,7 @@ protected: // Synchronize the state cache of this Backend with the actual real state of the GL Context void syncOutputStateCache(); + void resetOutputStage(); struct OutputStageState { @@ -402,6 +414,15 @@ protected: void do_endQuery(Batch& batch, uint32 paramOffset); void do_getQuery(Batch& batch, uint32 paramOffset); + void resetQueryStage(); + struct QueryStageState { + + }; + + // Reset stages + void do_resetStages(Batch& batch, uint32 paramOffset); + void resetStages(); + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/GLBackendInput.cpp b/libraries/gpu/src/gpu/GLBackendInput.cpp index 229b29cd43..9014024914 100755 --- a/libraries/gpu/src/gpu/GLBackendInput.cpp +++ b/libraries/gpu/src/gpu/GLBackendInput.cpp @@ -52,7 +52,7 @@ void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) { } if (isModified) { - _input._buffersState.set(channel); + _input._invalidBuffers.set(channel); } } } @@ -154,7 +154,7 @@ void GLBackend::updateInput() { _stats._ISNumFormatChanges++; } - if (_input._buffersState.any()) { + if (_input._invalidBuffers.any()) { int numBuffers = _input._buffers.size(); auto buffer = _input._buffers.data(); auto vbo = _input._bufferVBOs.data(); @@ -162,7 +162,7 @@ void GLBackend::updateInput() { auto stride = _input._bufferStrides.data(); for (int bufferNum = 0; bufferNum < numBuffers; bufferNum++) { - if (_input._buffersState.test(bufferNum)) { + if (_input._invalidBuffers.test(bufferNum)) { glBindVertexBuffer(bufferNum, (*vbo), (*offset), (*stride)); } buffer++; @@ -170,11 +170,11 @@ void GLBackend::updateInput() { offset++; stride++; } - _input._buffersState.reset(); + _input._invalidBuffers.reset(); (void) CHECK_GL_ERROR(); } #else - if (_input._invalidFormat || _input._buffersState.any()) { + if (_input._invalidFormat || _input._invalidBuffers.any()) { if (_input._invalidFormat) { InputStageState::ActivationCache newActivation; @@ -232,7 +232,7 @@ void GLBackend::updateInput() { if ((channelIt).first < buffers.size()) { int bufferNum = (channelIt).first; - if (_input._buffersState.test(bufferNum) || _input._invalidFormat) { + if (_input._invalidBuffers.test(bufferNum) || _input._invalidFormat) { // GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); GLuint vbo = _input._bufferVBOs[bufferNum]; if (boundVBO != vbo) { @@ -240,7 +240,7 @@ void GLBackend::updateInput() { (void) CHECK_GL_ERROR(); boundVBO = vbo; } - _input._buffersState[bufferNum] = false; + _input._invalidBuffers[bufferNum] = false; for (unsigned int i = 0; i < channel._slots.size(); i++) { const Stream::Attribute& attrib = attributes.at(channel._slots[i]); @@ -285,6 +285,51 @@ void GLBackend::updateInput() { #endif } +void GLBackend::resetInputStage() { + // Reset index buffer + _input._indexBufferType = UINT32; + _input._indexBufferOffset = 0; + _input._indexBuffer.reset(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + (void) CHECK_GL_ERROR(); + + +#if defined(SUPPORT_VAO) + // TODO +#else + glBindBuffer(GL_ARRAY_BUFFER, 0); + + size_t i = 0; +#if defined(SUPPORT_LEGACY_OPENGL) + for (; i < NUM_CLASSIC_ATTRIBS; i++) { + glDisableClientState(attributeSlotToClassicAttribName[i]); + } + glVertexPointer(4, GL_FLOAT, 0, 0); + glNormalPointer(GL_FLOAT, 0, 0); + glColorPointer(4, GL_FLOAT, 0, 0); + glTexCoordPointer(4, GL_FLOAT, 0, 0); +#endif + + for (; i < _input._attributeActivation.size(); i++) { + glDisableVertexAttribArray(i); + glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, 0); + } +#endif + + // Reset vertex buffer and format + _input._format.reset(); + _input._invalidFormat = false; + _input._attributeActivation.reset(); + + for (int i = 0; i < _input._buffers.size(); i++) { + _input._buffers[i].reset(); + _input._bufferOffsets[i] = 0; + _input._bufferStrides[i] = 0; + _input._bufferVBOs[i] = 0; + } + _input._invalidBuffers.reset(); + +} void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) { _input._indexBufferType = (Type) batch._params[paramOffset + 2]._uint; diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index b37def48e7..6b0bfae635 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -177,6 +177,11 @@ void GLBackend::syncOutputStateCache() { _output._framebuffer.reset(); } +void GLBackend::resetOutputStage() { + _output._framebuffer.reset(); + _output._drawFBO = 0; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint); diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 51a3a24e9b..4a54753af8 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -164,6 +164,24 @@ void GLBackend::updatePipeline() { #endif } +void GLBackend::resetPipelineStage() { + // First reset State to default + State::Signature resetSignature(0); + resetPipelineState(resetSignature); + _pipeline._state = nullptr; + _pipeline._invalidState = false; + + // Second the shader side + _pipeline._invalidProgram = false; + _pipeline._program = 0; + _pipeline._pipeline.reset(); + glUseProgram(0); +} + +void GLBackend::resetUniformStage() { + +} + void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { GLuint slot = batch._params[paramOffset + 3]._uint; BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); @@ -188,6 +206,10 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } +void GLBackend::resetResourceStage() { + +} + void GLBackend::do_setResourceTexture(Batch& batch, uint32 paramOffset) { GLuint slot = batch._params[paramOffset + 1]._uint; TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); diff --git a/libraries/gpu/src/gpu/GLBackendQuery.cpp b/libraries/gpu/src/gpu/GLBackendQuery.cpp index 39db19dafd..2bdf7c86ad 100644 --- a/libraries/gpu/src/gpu/GLBackendQuery.cpp +++ b/libraries/gpu/src/gpu/GLBackendQuery.cpp @@ -104,3 +104,7 @@ void GLBackend::do_getQuery(Batch& batch, uint32 paramOffset) { (void)CHECK_GL_ERROR(); } } + +void GLBackend::resetQueryStage() { +} + diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 18fc9ddd3c..618a13e2c4 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -484,7 +484,7 @@ void GLBackend::syncPipelineStateCache() { glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); getCurrentGLState(state); State::Signature signature = State::evalSignature(state); - + _pipeline._stateCache = state; _pipeline._stateSignatureCache = signature; } diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 65d9c6ed75..e05e0fc1c0 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -184,4 +184,6 @@ void GLBackend::updateTransform() { _transform._invalidView = _transform._invalidProj = _transform._invalidModel = _transform._invalidViewport = false; } - +void GLBackend::resetTransformStage() { + +} diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 0c8d19250b..30c8dffc0e 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -97,7 +97,6 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _drawStatusJobIndex = _jobs.size() - 1; _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); - _jobs.push_back(Job(new ResetGLState::JobModel())); // Give ourselves 3 frmaes of timer queries _timerQueries.push_back(std::make_shared()); diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 0e3eba0b53..0aef913d50 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -216,46 +216,6 @@ void render::renderItems(const SceneContextPointer& sceneContext, const RenderCo } } -void addClearStateCommands(gpu::Batch& batch) { - batch._glDepthMask(true); - batch._glDepthFunc(GL_LESS); - batch._glDisable(GL_CULL_FACE); - - batch._glActiveTexture(GL_TEXTURE0 + 1); - batch._glBindTexture(GL_TEXTURE_2D, 0); - batch._glActiveTexture(GL_TEXTURE0 + 2); - batch._glBindTexture(GL_TEXTURE_2D, 0); - batch._glActiveTexture(GL_TEXTURE0 + 3); - batch._glBindTexture(GL_TEXTURE_2D, 0); - batch._glActiveTexture(GL_TEXTURE0); - batch._glBindTexture(GL_TEXTURE_2D, 0); - - - // deactivate vertex arrays after drawing - batch._glDisableClientState(GL_NORMAL_ARRAY); - batch._glDisableClientState(GL_VERTEX_ARRAY); - batch._glDisableClientState(GL_TEXTURE_COORD_ARRAY); - batch._glDisableClientState(GL_COLOR_ARRAY); - batch._glDisableVertexAttribArray(gpu::Stream::TANGENT); - batch._glDisableVertexAttribArray(gpu::Stream::SKIN_CLUSTER_INDEX); - batch._glDisableVertexAttribArray(gpu::Stream::SKIN_CLUSTER_WEIGHT); - - // bind with 0 to switch back to normal operation - batch._glBindBuffer(GL_ARRAY_BUFFER, 0); - batch._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - batch._glBindTexture(GL_TEXTURE_2D, 0); - - // Back to no program - batch._glUseProgram(0); -} -void ResetGLState::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - - gpu::Batch theBatch; - addClearStateCommands(theBatch); - assert(renderContext->args); - renderContext->args->_context->render(theBatch); -} - void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 62810d47f0..ec6656c0dc 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -260,14 +260,6 @@ public: typedef Job::Model JobModel; }; -class ResetGLState { -public: - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); - - typedef Job::Model JobModel; -}; - - class DrawSceneTask : public Task { public: From 34e400ac67a04983976ec276711ec39ff3816fdf Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Mon, 27 Jul 2015 17:14:09 -0700 Subject: [PATCH 072/129] Changing var name to 'DebugAmbientOcclusion' --- interface/src/Application.cpp | 2 +- interface/src/Menu.cpp | 2 +- interface/src/Menu.h | 2 +- tests/ui/src/main.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9d28e40a66..093f87b494 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3265,7 +3265,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus(); - renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion); + renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion); renderArgs->_shouldRender = LODManager::shouldRender; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 91ae6a4d02..ea284d4f23 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -330,7 +330,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, 0, // QML Qt::SHIFT | Qt::Key_A, true); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DebugAmbientOcclusion); MenuWrapper* ambientLightMenu = renderOptionsMenu->addMenu(MenuOption::RenderAmbientLight); QActionGroup* ambientLightGroup = new QActionGroup(ambientLightMenu); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 8ad71bbdaa..4c3e9332a1 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -134,7 +134,6 @@ namespace MenuOption { const QString AddressBar = "Show Address Bar"; const QString AlignForearmsWithWrists = "Align Forearms with Wrists"; const QString AlternateIK = "Alternate IK"; - const QString AmbientOcclusion = "Debug Ambient Occlusion"; const QString Animations = "Animations..."; const QString Atmosphere = "Atmosphere"; const QString Attachments = "Attachments..."; @@ -165,6 +164,7 @@ namespace MenuOption { const QString ControlWithSpeech = "Control With Speech"; const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyPath = "Copy Path to Clipboard"; + const QString DebugAmbientOcclusion = "Debug Ambient Occlusion"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DeleteBookmark = "Delete Bookmark..."; const QString DisableActivityLogger = "Disable Activity Logger"; diff --git a/tests/ui/src/main.cpp b/tests/ui/src/main.cpp index f5647bd176..919c27f32f 100644 --- a/tests/ui/src/main.cpp +++ b/tests/ui/src/main.cpp @@ -86,7 +86,6 @@ public: AddressBar, AlignForearmsWithWrists, AlternateIK, - AmbientOcclusion, Animations, Atmosphere, Attachments, @@ -111,6 +110,7 @@ public: ControlWithSpeech, CopyAddress, CopyPath, + DebugAmbientOcclusion, DecreaseAvatarSize, DeleteBookmark, DisableActivityLogger, From f525a8a245dd9f3f1fa647d3865f0e24ba88d683 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 27 Jul 2015 17:17:56 -0700 Subject: [PATCH 073/129] Removing all the unecessary calls of Batch from the gl legacy time --- interface/src/Application.cpp | 12 +- interface/src/Stars.cpp | 5 +- interface/src/ui/ApplicationOverlay.cpp | 2 +- .../src/RenderableWebEntityItem.cpp | 3 +- libraries/gpu/src/gpu/Batch.h | 52 +--- libraries/gpu/src/gpu/GLBackend.cpp | 250 +----------------- libraries/gpu/src/gpu/GLBackend.h | 25 +- libraries/gpu/src/gpu/GLBackendOutput.cpp | 8 +- libraries/gpu/src/gpu/GLBackendState.cpp | 5 + 9 files changed, 34 insertions(+), 328 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7bfad60eaf..42868166d0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -995,11 +995,6 @@ void Application::paintGL() { _compositor.displayOverlayTexture(&renderArgs); } - - // Reset the gpu::Context Stages - gpu::Batch batch; - batch.resetStages(); - renderArgs._context->render(batch); if (!OculusManager::isConnected() || OculusManager::allowSwap()) { @@ -1013,6 +1008,13 @@ void Application::paintGL() { _frameCount++; _numFramesSinceLastResize++; Stats::getInstance()->setRenderDetails(renderArgs._details); + + + // Reset the gpu::Context Stages + // Back to the default framebuffer; + gpu::Batch batch; + batch.resetStages(); + renderArgs._context->render(batch); } void Application::runTests() { diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp index ebfddee38c..7d09b9b1c3 100644 --- a/interface/src/Stars.cpp +++ b/interface/src/Stars.cpp @@ -154,6 +154,7 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { auto state = gpu::StatePointer(new gpu::State()); // enable decal blend state->setDepthTest(gpu::State::DepthTest(false)); + state->setAntialiasedLineEnable(true); // line smoothing also smooth points state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); _starsPipeline.reset(gpu::Pipeline::create(program, state)); @@ -217,10 +218,10 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { // Render the stars batch.setPipeline(_starsPipeline); - batch._glEnable(GL_PROGRAM_POINT_SIZE_EXT); + /* batch._glEnable(GL_PROGRAM_POINT_SIZE_EXT); batch._glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); batch._glEnable(GL_POINT_SMOOTH); - + */ batch.setInputFormat(streamFormat); batch.setInputBuffer(VERTICES_SLOT, posView); batch.setInputBuffer(COLOR_SLOT, colView); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index bc10b555e4..acc24ba2be 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -117,7 +117,7 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { batch.setProjectionTransform(mat4()); batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); - batch._glBindTexture(GL_TEXTURE_2D, _uiTexture); + batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _uiTexture); geometryCache->renderUnitQuad(batch, glm::vec4(1)); } diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 7fa615073b..ee1fdfae45 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -178,8 +178,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { batch.setModelTransform(getTransformToCenter()); bool textured = false, culled = false, emissive = false; if (_texture) { - batch._glActiveTexture(GL_TEXTURE0); - batch._glBindTexture(GL_TEXTURE_2D, _texture); + batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture); textured = emissive = true; } diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 5f2c2dd089..5135d1ac4f 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -94,7 +94,7 @@ public: void setResourceTexture(uint32 slot, const TexturePointer& view); void setResourceTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView - // Framebuffer Stage + // Ouput Stage void setFramebuffer(const FramebufferPointer& framebuffer); // Clear framebuffer layers @@ -122,28 +122,8 @@ public: // For now, instead of calling the raw gl Call, use the equivalent call on the batch so the call is beeing recorded // THe implementation of these functions is in GLBackend.cpp - void _glEnable(unsigned int cap); - void _glDisable(unsigned int cap); + void _glActiveBindTexture(unsigned int unit, unsigned int target, unsigned int texture); - void _glEnableClientState(unsigned int array); - void _glDisableClientState(unsigned int array); - - void _glCullFace(unsigned int mode); - void _glAlphaFunc(unsigned int func, float ref); - - void _glDepthFunc(unsigned int func); - void _glDepthMask(unsigned char flag); - void _glDepthRange(float zNear, float zFar); - - void _glBindBuffer(unsigned int target, unsigned int buffer); - - void _glBindTexture(unsigned int target, unsigned int texture); - void _glActiveTexture(unsigned int texture); - void _glTexParameteri(unsigned int target, unsigned int pname, int param); - - void _glDrawBuffers(int n, const unsigned int* bufs); - - void _glUseProgram(unsigned int program); void _glUniform1i(int location, int v0); void _glUniform1f(int location, float v0); void _glUniform2f(int location, float v0, float v1); @@ -153,9 +133,6 @@ public: void _glUniform4iv(int location, int count, const int* value); void _glUniformMatrix4fv(int location, int count, unsigned char transpose, const float* value); - void _glEnableVertexAttribArray(int location); - void _glDisableVertexAttribArray(int location); - void _glColor4f(float red, float green, float blue, float alpha); void _glLineWidth(float width); @@ -194,28 +171,8 @@ public: // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API - COMMAND_glEnable, - COMMAND_glDisable, + COMMAND_glActiveBindTexture, - COMMAND_glEnableClientState, - COMMAND_glDisableClientState, - - COMMAND_glCullFace, - COMMAND_glAlphaFunc, - - COMMAND_glDepthFunc, - COMMAND_glDepthMask, - COMMAND_glDepthRange, - - COMMAND_glBindBuffer, - - COMMAND_glBindTexture, - COMMAND_glActiveTexture, - COMMAND_glTexParameteri, - - COMMAND_glDrawBuffers, - - COMMAND_glUseProgram, COMMAND_glUniform1i, COMMAND_glUniform1f, COMMAND_glUniform2f, @@ -225,9 +182,6 @@ public: COMMAND_glUniform4iv, COMMAND_glUniformMatrix4fv, - COMMAND_glEnableVertexAttribArray, - COMMAND_glDisableVertexAttribArray, - COMMAND_glColor4f, COMMAND_glLineWidth, diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 51637462f1..8db192b827 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -48,28 +48,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_resetStages), - (&::gpu::GLBackend::do_glEnable), - (&::gpu::GLBackend::do_glDisable), + (&::gpu::GLBackend::do_glActiveBindTexture), - (&::gpu::GLBackend::do_glEnableClientState), - (&::gpu::GLBackend::do_glDisableClientState), - - (&::gpu::GLBackend::do_glCullFace), - (&::gpu::GLBackend::do_glAlphaFunc), - - (&::gpu::GLBackend::do_glDepthFunc), - (&::gpu::GLBackend::do_glDepthMask), - (&::gpu::GLBackend::do_glDepthRange), - - (&::gpu::GLBackend::do_glBindBuffer), - - (&::gpu::GLBackend::do_glBindTexture), - (&::gpu::GLBackend::do_glActiveTexture), - (&::gpu::GLBackend::do_glTexParameteri), - - (&::gpu::GLBackend::do_glDrawBuffers), - - (&::gpu::GLBackend::do_glUseProgram), (&::gpu::GLBackend::do_glUniform1i), (&::gpu::GLBackend::do_glUniform1f), (&::gpu::GLBackend::do_glUniform2f), @@ -79,9 +59,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUniform4iv), (&::gpu::GLBackend::do_glUniformMatrix4fv), - (&::gpu::GLBackend::do_glEnableVertexAttribArray), - (&::gpu::GLBackend::do_glDisableVertexAttribArray), - (&::gpu::GLBackend::do_glColor4f), (&::gpu::GLBackend::do_glLineWidth), }; @@ -275,211 +252,24 @@ void GLBackend::resetStages() { //#define DO_IT_NOW(call, offset) runLastCommand(); #define DO_IT_NOW(call, offset) - -void Batch::_glEnable(GLenum cap) { - ADD_COMMAND_GL(glEnable); - - _params.push_back(cap); - - DO_IT_NOW(_glEnable, 1); -} -void GLBackend::do_glEnable(Batch& batch, uint32 paramOffset) { - glEnable(batch._params[paramOffset]._uint); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glDisable(GLenum cap) { - ADD_COMMAND_GL(glDisable); - - _params.push_back(cap); - - DO_IT_NOW(_glDisable, 1); -} -void GLBackend::do_glDisable(Batch& batch, uint32 paramOffset) { - glDisable(batch._params[paramOffset]._uint); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glEnableClientState(GLenum array) { - ADD_COMMAND_GL(glEnableClientState); - - _params.push_back(array); - - DO_IT_NOW(_glEnableClientState, 1); -} -void GLBackend::do_glEnableClientState(Batch& batch, uint32 paramOffset) { - glEnableClientState(batch._params[paramOffset]._uint); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glDisableClientState(GLenum array) { - ADD_COMMAND_GL(glDisableClientState); - - _params.push_back(array); - - DO_IT_NOW(_glDisableClientState, 1); -} -void GLBackend::do_glDisableClientState(Batch& batch, uint32 paramOffset) { - glDisableClientState(batch._params[paramOffset]._uint); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glCullFace(GLenum mode) { - ADD_COMMAND_GL(glCullFace); - - _params.push_back(mode); - - DO_IT_NOW(_glCullFace, 1); -} -void GLBackend::do_glCullFace(Batch& batch, uint32 paramOffset) { - glCullFace(batch._params[paramOffset]._uint); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glAlphaFunc(GLenum func, GLclampf ref) { - ADD_COMMAND_GL(glAlphaFunc); - - _params.push_back(ref); - _params.push_back(func); - - DO_IT_NOW(_glAlphaFunc, 2); -} -void GLBackend::do_glAlphaFunc(Batch& batch, uint32 paramOffset) { - glAlphaFunc( - batch._params[paramOffset + 1]._uint, - batch._params[paramOffset + 0]._float); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glDepthFunc(GLenum func) { - ADD_COMMAND_GL(glDepthFunc); - - _params.push_back(func); - - DO_IT_NOW(_glDepthFunc, 1); -} -void GLBackend::do_glDepthFunc(Batch& batch, uint32 paramOffset) { - glDepthFunc(batch._params[paramOffset]._uint); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glDepthMask(GLboolean flag) { - ADD_COMMAND_GL(glDepthMask); - - _params.push_back(flag); - - DO_IT_NOW(_glDepthMask, 1); -} -void GLBackend::do_glDepthMask(Batch& batch, uint32 paramOffset) { - glDepthMask(batch._params[paramOffset]._uint); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glDepthRange(GLfloat zNear, GLfloat zFar) { - ADD_COMMAND_GL(glDepthRange); - - _params.push_back(zFar); - _params.push_back(zNear); - - DO_IT_NOW(_glDepthRange, 2); -} -void GLBackend::do_glDepthRange(Batch& batch, uint32 paramOffset) { - glDepthRange( - batch._params[paramOffset + 1]._float, - batch._params[paramOffset + 0]._float); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glBindBuffer(GLenum target, GLuint buffer) { - ADD_COMMAND_GL(glBindBuffer); - - _params.push_back(buffer); - _params.push_back(target); - - DO_IT_NOW(_glBindBuffer, 2); -} -void GLBackend::do_glBindBuffer(Batch& batch, uint32 paramOffset) { - glBindBuffer( - batch._params[paramOffset + 1]._uint, - batch._params[paramOffset + 0]._uint); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glBindTexture(GLenum target, GLuint texture) { - ADD_COMMAND_GL(glBindTexture); +void Batch::_glActiveBindTexture(GLenum unit, GLenum target, GLuint texture) { + ADD_COMMAND_GL(glActiveBindTexture); _params.push_back(texture); _params.push_back(target); + _params.push_back(unit); - DO_IT_NOW(_glBindTexture, 2); + + DO_IT_NOW(_glActiveBindTexture, 3); } -void GLBackend::do_glBindTexture(Batch& batch, uint32 paramOffset) { +void GLBackend::do_glActiveBindTexture(Batch& batch, uint32 paramOffset) { + glActiveTexture(batch._params[paramOffset + 2]._uint); glBindTexture( batch._params[paramOffset + 1]._uint, batch._params[paramOffset + 0]._uint); (void) CHECK_GL_ERROR(); } -void Batch::_glActiveTexture(GLenum texture) { - ADD_COMMAND_GL(glActiveTexture); - - _params.push_back(texture); - - DO_IT_NOW(_glActiveTexture, 1); -} -void GLBackend::do_glActiveTexture(Batch& batch, uint32 paramOffset) { - glActiveTexture(batch._params[paramOffset]._uint); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glTexParameteri(GLenum target, GLenum pname, GLint param) { - ADD_COMMAND_GL(glTexParameteri); - - _params.push_back(param); - _params.push_back(pname); - _params.push_back(target); - - DO_IT_NOW(glTexParameteri, 3); -} -void GLBackend::do_glTexParameteri(Batch& batch, uint32 paramOffset) { - glTexParameteri(batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._uint, - batch._params[paramOffset + 0]._int); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glDrawBuffers(GLsizei n, const GLenum* bufs) { - ADD_COMMAND_GL(glDrawBuffers); - - _params.push_back(cacheData(n * sizeof(GLenum), bufs)); - _params.push_back(n); - - DO_IT_NOW(_glDrawBuffers, 2); -} -void GLBackend::do_glDrawBuffers(Batch& batch, uint32 paramOffset) { - glDrawBuffers( - batch._params[paramOffset + 1]._uint, - (const GLenum*)batch.editData(batch._params[paramOffset + 0]._uint)); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glUseProgram(GLuint program) { - ADD_COMMAND_GL(glUseProgram); - - _params.push_back(program); - - DO_IT_NOW(_glUseProgram, 1); -} -void GLBackend::do_glUseProgram(Batch& batch, uint32 paramOffset) { - - _pipeline._program = batch._params[paramOffset]._uint; - // for this call we still want to execute the glUseProgram in the order of the glCOmmand to avoid any issue - _pipeline._invalidProgram = false; - glUseProgram(_pipeline._program); - - (void) CHECK_GL_ERROR(); -} - void Batch::_glUniform1i(GLint location, GLint v0) { if (location < 0) { return; @@ -680,30 +470,6 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } -void Batch::_glEnableVertexAttribArray(GLint location) { - ADD_COMMAND_GL(glEnableVertexAttribArray); - - _params.push_back(location); - - DO_IT_NOW(_glEnableVertexAttribArray, 1); -} -void GLBackend::do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset) { - glEnableVertexAttribArray(batch._params[paramOffset]._uint); - (void) CHECK_GL_ERROR(); -} - -void Batch::_glDisableVertexAttribArray(GLint location) { - ADD_COMMAND_GL(glDisableVertexAttribArray); - - _params.push_back(location); - - DO_IT_NOW(_glDisableVertexAttribArray, 1); -} -void GLBackend::do_glDisableVertexAttribArray(Batch& batch, uint32 paramOffset) { - glDisableVertexAttribArray(batch._params[paramOffset]._uint); - (void) CHECK_GL_ERROR(); -} - void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { ADD_COMMAND_GL(glColor4f); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 59a6c1ee7e..843e5d2006 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -426,28 +426,8 @@ protected: // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API - void do_glEnable(Batch& batch, uint32 paramOffset); - void do_glDisable(Batch& batch, uint32 paramOffset); + void do_glActiveBindTexture(Batch& batch, uint32 paramOffset); - void do_glEnableClientState(Batch& batch, uint32 paramOffset); - void do_glDisableClientState(Batch& batch, uint32 paramOffset); - - void do_glCullFace(Batch& batch, uint32 paramOffset); - void do_glAlphaFunc(Batch& batch, uint32 paramOffset); - - void do_glDepthFunc(Batch& batch, uint32 paramOffset); - void do_glDepthMask(Batch& batch, uint32 paramOffset); - void do_glDepthRange(Batch& batch, uint32 paramOffset); - - void do_glBindBuffer(Batch& batch, uint32 paramOffset); - - void do_glBindTexture(Batch& batch, uint32 paramOffset); - void do_glActiveTexture(Batch& batch, uint32 paramOffset); - void do_glTexParameteri(Batch& batch, uint32 paramOffset); - - void do_glDrawBuffers(Batch& batch, uint32 paramOffset); - - void do_glUseProgram(Batch& batch, uint32 paramOffset); void do_glUniform1i(Batch& batch, uint32 paramOffset); void do_glUniform1f(Batch& batch, uint32 paramOffset); void do_glUniform2f(Batch& batch, uint32 paramOffset); @@ -457,9 +437,6 @@ protected: void do_glUniform4iv(Batch& batch, uint32 paramOffset); void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset); - void do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset); - void do_glDisableVertexAttribArray(Batch& batch, uint32 paramOffset); - void do_glColor4f(Batch& batch, uint32 paramOffset); void do_glLineWidth(Batch& batch, uint32 paramOffset); diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 6b0bfae635..d57ef57d78 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -178,9 +178,11 @@ void GLBackend::syncOutputStateCache() { } void GLBackend::resetOutputStage() { - _output._framebuffer.reset(); - _output._drawFBO = 0; - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + if (_output._framebuffer) { + _output._framebuffer.reset(); + _output._drawFBO = 0; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + } } void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 618a13e2c4..bd683e0136 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -482,6 +482,11 @@ void GLBackend::syncPipelineStateCache() { State::Data state; glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // Point size is always on + glEnable(GL_PROGRAM_POINT_SIZE_EXT); + glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + getCurrentGLState(state); State::Signature signature = State::evalSignature(state); From 66c5aec744273781b735c10b5d625d761d3b95b5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 27 Jul 2015 17:34:46 -0700 Subject: [PATCH 074/129] Remove commented dead code --- interface/src/Stars.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp index 7d09b9b1c3..c1e65086bf 100644 --- a/interface/src/Stars.cpp +++ b/interface/src/Stars.cpp @@ -218,10 +218,6 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { // Render the stars batch.setPipeline(_starsPipeline); - /* batch._glEnable(GL_PROGRAM_POINT_SIZE_EXT); - batch._glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - batch._glEnable(GL_POINT_SMOOTH); - */ batch.setInputFormat(streamFormat); batch.setInputBuffer(VERTICES_SLOT, posView); batch.setInputBuffer(COLOR_SLOT, colView); From f4a23065b4adbd86ec5a674cf5c65b886bad8a6a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 27 Jul 2015 19:06:14 -0700 Subject: [PATCH 075/129] if obj data isn't from a url, don't dereference null url pointer --- libraries/fbx/src/OBJReader.cpp | 72 +++++++++++++++++++-------------- libraries/fbx/src/OBJReader.h | 7 ++-- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 2ec80e3d85..f16c6ba215 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -195,7 +195,10 @@ void OBJFace::addFrom(const OBJFace* face, int index) { // add using data from f } bool OBJReader::isValidTexture(const QByteArray &filename) { - QUrl candidateUrl = url->resolved(QUrl(filename)); + if (!_url) { + return false; + } + QUrl candidateUrl = _url->resolved(QUrl(filename)); QNetworkReply *netReply = request(candidateUrl, true); bool isValid = netReply->isFinished() && (netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200); netReply->deleteLater(); @@ -242,7 +245,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { } else if ((token == "map_Kd") || (token == "map_Ks")) { QByteArray filename = QUrl(tokenizer.getLineAsDatum()).fileName().toUtf8(); if (filename.endsWith(".tga")) { - qCDebug(modelformat) << "OBJ Reader WARNING: currently ignoring tga texture " << filename << " in " << url; + qCDebug(modelformat) << "OBJ Reader WARNING: currently ignoring tga texture " << filename << " in " << _url; break; } if (isValidTexture(filename)) { @@ -252,7 +255,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { currentMaterial.specularTextureFilename = filename; } } else { - qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " ignoring missing texture " << filename; + qCDebug(modelformat) << "OBJ Reader WARNING: " << _url << " ignoring missing texture " << filename; } } } @@ -316,7 +319,7 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi QByteArray groupName = tokenizer.getDatum(); currentGroup = groupName; //qCDebug(modelformat) << "new group:" << groupName; - } else if (token == "mtllib") { + } else if (token == "mtllib" && _url) { if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; } @@ -325,13 +328,15 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi break; // Some files use mtllib over and over again for the same libraryName } librariesSeen[libraryName] = true; - QUrl libraryUrl = url->resolved(QUrl(libraryName).fileName()); // Throw away any path part of libraryName, and merge against original url. + // Throw away any path part of libraryName, and merge against original url. + QUrl libraryUrl = _url->resolved(QUrl(libraryName).fileName()); qCDebug(modelformat) << "OBJ Reader new library:" << libraryName << " at:" << libraryUrl; QNetworkReply* netReply = request(libraryUrl, false); if (netReply->isFinished() && (netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200)) { parseMaterialLibrary(netReply); } else { - qCDebug(modelformat) << "OBJ Reader " << libraryName << " did not answer. Got " << netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); + qCDebug(modelformat) << "OBJ Reader " << libraryName << " did not answer. Got " + << netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); } netReply->deleteLater(); } else if (token == "usemtl") { @@ -406,10 +411,10 @@ FBXGeometry OBJReader::readOBJ(QIODevice* device, const QVariantHash& mapping, Q OBJTokenizer tokenizer(device); float scaleGuess = 1.0f; - this->url = url; + _url = url; geometry.meshExtents.reset(); geometry.meshes.append(FBXMesh()); - + try { // call parseOBJGroup as long as it's returning true. Each successful call will // add a new meshPart to the geometry's single mesh. @@ -417,7 +422,7 @@ FBXGeometry OBJReader::readOBJ(QIODevice* device, const QVariantHash& mapping, Q FBXMesh& mesh = geometry.meshes[0]; mesh.meshIndex = 0; - + geometry.joints.resize(1); geometry.joints[0].isFree = false; geometry.joints[0].parentIndex = -1; @@ -440,37 +445,44 @@ FBXGeometry OBJReader::readOBJ(QIODevice* device, const QVariantHash& mapping, Q 0, 0, 1, 0, 0, 0, 0, 1); mesh.clusters.append(cluster); - - // Some .obj files use the convention that a group with uv coordinates that doesn't define a material, should use a texture with the same basename as the .obj file. - QString filename = url->fileName(); - int extIndex = filename.lastIndexOf('.'); // by construction, this does not fail - QString basename = filename.remove(extIndex + 1, sizeof("obj")); - OBJMaterial& preDefinedMaterial = materials[SMART_DEFAULT_MATERIAL_NAME]; - preDefinedMaterial.diffuseColor = glm::vec3(1.0f); - QVector extensions = {"jpg", "jpeg", "png", "tga"}; - QByteArray base = basename.toUtf8(), textName = ""; - for (int i = 0; i < extensions.count(); i++) { - QByteArray candidateString = base + extensions[i]; - if (isValidTexture(candidateString)) { - textName = candidateString; - break; + + // Some .obj files use the convention that a group with uv coordinates that doesn't define a material, should use + // a texture with the same basename as the .obj file. + if (url) { + QString filename = url->fileName(); + int extIndex = filename.lastIndexOf('.'); // by construction, this does not fail + QString basename = filename.remove(extIndex + 1, sizeof("obj")); + OBJMaterial& preDefinedMaterial = materials[SMART_DEFAULT_MATERIAL_NAME]; + preDefinedMaterial.diffuseColor = glm::vec3(1.0f); + QVector extensions = {"jpg", "jpeg", "png", "tga"}; + QByteArray base = basename.toUtf8(), textName = ""; + for (int i = 0; i < extensions.count(); i++) { + QByteArray candidateString = base + extensions[i]; + if (isValidTexture(candidateString)) { + textName = candidateString; + break; + } } + + if (!textName.isEmpty()) { + preDefinedMaterial.diffuseTextureFilename = textName; + } + materials[SMART_DEFAULT_MATERIAL_NAME] = preDefinedMaterial; } - if (!textName.isEmpty()) { - preDefinedMaterial.diffuseTextureFilename = textName; - } - materials[SMART_DEFAULT_MATERIAL_NAME] = preDefinedMaterial; - + for (int i = 0, meshPartCount = 0; i < mesh.parts.count(); i++, meshPartCount++) { FBXMeshPart& meshPart = mesh.parts[i]; FaceGroup faceGroup = faceGroups[meshPartCount]; OBJFace leadFace = faceGroup[0]; // All the faces in the same group will have the same name and material. QString groupMaterialName = leadFace.materialName; if (groupMaterialName.isEmpty() && (leadFace.textureUVIndices.count() > 0)) { - qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " needs a texture that isn't specified. Using default mechanism."; + qCDebug(modelformat) << "OBJ Reader WARNING: " << url + << " needs a texture that isn't specified. Using default mechanism."; groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; } else if (!groupMaterialName.isEmpty() && !materials.contains(groupMaterialName)) { - qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " specifies a material " << groupMaterialName << " that is not defined. Using default mechanism."; + qCDebug(modelformat) << "OBJ Reader WARNING: " << url + << " specifies a material " << groupMaterialName + << " that is not defined. Using default mechanism."; groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; } if (!groupMaterialName.isEmpty()) { diff --git a/libraries/fbx/src/OBJReader.h b/libraries/fbx/src/OBJReader.h index 771c0b1b63..2e7b050b0a 100644 --- a/libraries/fbx/src/OBJReader.h +++ b/libraries/fbx/src/OBJReader.h @@ -69,12 +69,13 @@ public: QVector faceGroups; QString currentMaterialName; QHash materials; - QUrl* url; - + QNetworkReply* request(QUrl& url, bool isTest); FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping); FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping, QUrl* url); private: + QUrl* _url = nullptr; + QHash librariesSeen; bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess); void parseMaterialLibrary(QIODevice* device); @@ -83,4 +84,4 @@ private: // What are these utilities doing here? One is used by fbx loading code in VHACD Utils, and the other a general debugging utility. void setMeshPartDefaults(FBXMeshPart& meshPart, QString materialID); -void fbxDebugDump(const FBXGeometry& fbxgeo); \ No newline at end of file +void fbxDebugDump(const FBXGeometry& fbxgeo); From 8a7cdb1c64f0fd13f5473252ca13a5df1f59da6d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 27 Jul 2015 19:53:38 -0700 Subject: [PATCH 076/129] Make Throttle FPS If Not Focus be enabled by default --- interface/src/Application.cpp | 2 +- interface/src/Menu.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bb564824b0..161e36d649 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -330,7 +330,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _lastNackTime(usecTimestampNow()), _lastSendDownstreamAudioStats(usecTimestampNow()), _isVSyncOn(true), - _isThrottleFPSEnabled(false), + _isThrottleFPSEnabled(true), _aboutToQuit(false), _notifiedPacketVersionMismatchThisDomain(false), _glWidget(new GLCanvas()), diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 91ae6a4d02..424c9b2227 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -368,7 +368,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true, qApp, SLOT(setVSyncEnabled())); #endif - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, false, + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true, qApp, SLOT(setThrottleFPSEnabled())); } From 81e80996f791ef40a4d701ea38842d91a2be4377 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 28 Jul 2015 11:24:33 -0700 Subject: [PATCH 077/129] Fix large marketplace imports not working --- examples/edit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index ec3106e585..a07779c19d 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -1064,7 +1064,7 @@ function importSVO(importURL) { if (success) { var VERY_LARGE = 10000; - var position = { x: 0, y: 0, z: 0}; + var position = { x: 0.01, y: 0.01, z: 0.01}; if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) { position = getPositionToCreateEntity(); } @@ -1074,7 +1074,7 @@ function importSVO(importURL) { if (isActive) { selectionManager.setSelections(pastedEntityIDs); } - Window.raiseMainWindow(); + Window.raiseMainWindow(); } else { Window.alert("Can't import objects: objects would be out of bounds."); } From 2aa453b6102f0fb092283a5644498fcf7c355aeb Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 28 Jul 2015 12:05:45 -0700 Subject: [PATCH 078/129] fix build errors for shared-tests --- tests/shared/src/AngularConstraintTests.cpp | 1 + tests/shared/src/AngularConstraintTests.h | 7 ++----- tests/shared/src/MovingPercentileTests.cpp | 1 + tests/shared/src/MovingPercentileTests.h | 1 - tests/shared/src/TransformTests.cpp | 4 +++- tests/shared/src/TransformTests.h | 2 -- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/tests/shared/src/AngularConstraintTests.cpp b/tests/shared/src/AngularConstraintTests.cpp index 95c5db18c2..4dcf3d7296 100644 --- a/tests/shared/src/AngularConstraintTests.cpp +++ b/tests/shared/src/AngularConstraintTests.cpp @@ -16,6 +16,7 @@ #include #include "AngularConstraintTests.h" +#include "../QTestExtensions.h" // Computes the error value between two quaternions (using glm::dot) float getErrorDifference(const glm::quat& a, const glm::quat& b) { diff --git a/tests/shared/src/AngularConstraintTests.h b/tests/shared/src/AngularConstraintTests.h index df2fe8e9c3..705639b571 100644 --- a/tests/shared/src/AngularConstraintTests.h +++ b/tests/shared/src/AngularConstraintTests.h @@ -12,6 +12,7 @@ #ifndef hifi_AngularConstraintTests_h #define hifi_AngularConstraintTests_h +#include #include class AngularConstraintTests : public QObject { @@ -21,10 +22,6 @@ private slots: void testConeRollerConstraint(); }; -// Use QCOMPARE_WITH_ABS_ERROR and define it for glm::quat -#include -float getErrorDifference (const glm::quat& a, const glm::quat& b); -QTextStream & operator << (QTextStream& stream, const glm::quat& q); -#include "../QTestExtensions.h" +float getErrorDifference(const glm::quat& a, const glm::quat& b); #endif // hifi_AngularConstraintTests_h diff --git a/tests/shared/src/MovingPercentileTests.cpp b/tests/shared/src/MovingPercentileTests.cpp index b9593fca83..fbbc3c7b9e 100644 --- a/tests/shared/src/MovingPercentileTests.cpp +++ b/tests/shared/src/MovingPercentileTests.cpp @@ -16,6 +16,7 @@ #include #include +#include <../QTestExtensions.h> QTEST_MAIN(MovingPercentileTests) diff --git a/tests/shared/src/MovingPercentileTests.h b/tests/shared/src/MovingPercentileTests.h index 4a1d4b33d2..ffc8ddb0f6 100644 --- a/tests/shared/src/MovingPercentileTests.h +++ b/tests/shared/src/MovingPercentileTests.h @@ -13,7 +13,6 @@ #define hifi_MovingPercentileTests_h #include -#include <../QTestExtensions.h> class MovingPercentileTests : public QObject { Q_OBJECT diff --git a/tests/shared/src/TransformTests.cpp b/tests/shared/src/TransformTests.cpp index 93b0583aa6..be22914b9d 100644 --- a/tests/shared/src/TransformTests.cpp +++ b/tests/shared/src/TransformTests.cpp @@ -8,10 +8,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "TransformTests.h" + #include -#include "TransformTests.h" #include "SharedLogging.h" +#include <../QTestExtensions.h> using namespace glm; diff --git a/tests/shared/src/TransformTests.h b/tests/shared/src/TransformTests.h index ab5c8cf144..a4d9b2a6c0 100644 --- a/tests/shared/src/TransformTests.h +++ b/tests/shared/src/TransformTests.h @@ -40,8 +40,6 @@ inline QTextStream& operator<< (QTextStream& stream, const glm::mat4& matrix) { return stream; } -#include <../QTestExtensions.h> - class TransformTests : public QObject { Q_OBJECT private slots: From d03a7d1b701d0459468ac7d4afe908d973957707 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 28 Jul 2015 12:24:17 -0700 Subject: [PATCH 079/129] fix physics-tests build errors --- tests/physics/src/BulletUtilTests.cpp | 7 +- tests/physics/src/BulletUtilTests.h | 3 - tests/physics/src/CollisionInfoTests.cpp | 70 ------------------- tests/physics/src/CollisionInfoTests.h | 29 -------- tests/physics/src/MeshMassPropertiesTests.cpp | 8 ++- tests/physics/src/MeshMassPropertiesTests.h | 6 -- tests/physics/src/ShapeColliderTests.cpp | 14 ++-- tests/physics/src/ShapeColliderTests.h | 7 -- 8 files changed, 18 insertions(+), 126 deletions(-) delete mode 100644 tests/physics/src/CollisionInfoTests.cpp delete mode 100644 tests/physics/src/CollisionInfoTests.h diff --git a/tests/physics/src/BulletUtilTests.cpp b/tests/physics/src/BulletUtilTests.cpp index bbd88f88b7..181d22327e 100644 --- a/tests/physics/src/BulletUtilTests.cpp +++ b/tests/physics/src/BulletUtilTests.cpp @@ -9,13 +9,16 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "BulletUtilTests.h" + #include -//#include "PhysicsTestUtil.h" #include #include -#include "BulletUtilTests.h" +// Add additional qtest functionality (the include order is important!) +#include "GlmTestUtils.h" +#include "../QTestExtensions.h" // Constants const glm::vec3 origin(0.0f); diff --git a/tests/physics/src/BulletUtilTests.h b/tests/physics/src/BulletUtilTests.h index fd4fe13d09..e8fee1e473 100644 --- a/tests/physics/src/BulletUtilTests.h +++ b/tests/physics/src/BulletUtilTests.h @@ -13,9 +13,6 @@ #define hifi_BulletUtilTests_h #include -// Add additional qtest functionality (the include order is important!) -#include "GlmTestUtils.h" -#include "../QTestExtensions.h" class BulletUtilTests : public QObject { Q_OBJECT diff --git a/tests/physics/src/CollisionInfoTests.cpp b/tests/physics/src/CollisionInfoTests.cpp deleted file mode 100644 index 70e2e14bb0..0000000000 --- a/tests/physics/src/CollisionInfoTests.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// CollisionInfoTests.cpp -// tests/physics/src -// -// Created by Andrew Meadows on 2/21/2014. -// Copyright 2014 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 -// - -#include - -#include -#include - -#include -#include -#include - -#include "CollisionInfoTests.h" - - - -QTEST_MAIN(CollisionInfoTests) -/* -static glm::vec3 xAxis(1.0f, 0.0f, 0.0f); -static glm::vec3 xZxis(0.0f, 1.0f, 0.0f); -static glm::vec3 xYxis(0.0f, 0.0f, 1.0f); - -void CollisionInfoTests::rotateThenTranslate() { - CollisionInfo collision; - collision._penetration = xAxis; - collision._contactPoint = xYxis; - collision._addedVelocity = xAxis + xYxis + xZxis; - - glm::quat rotation = glm::angleAxis(PI_OVER_TWO, zAxis); - float distance = 3.0f; - glm::vec3 translation = distance * xYxis; - - collision.rotateThenTranslate(rotation, translation); - QCOMPARE(collision._penetration, xYxis); - - glm::vec3 expectedContactPoint = -xAxis + translation; - QCOMPARE(collision._contactPoint, expectedContactPoint); - - glm::vec3 expectedAddedVelocity = xYxis - xAxis + xZxis; - QCOMPARE(collision._addedVelocity, expectedAddedVelocity); -} - -void CollisionInfoTests::translateThenRotate() { - CollisionInfo collision; - collision._penetration = xAxis; - collision._contactPoint = xYxis; - collision._addedVelocity = xAxis + xYxis + xZxis; - - glm::quat rotation = glm::angleAxis( -PI_OVER_TWO, zAxis); - float distance = 3.0f; - glm::vec3 translation = distance * xYxis; - - collision.translateThenRotate(translation, rotation); - QCOMPARE(collision._penetration, -xYxis); - - glm::vec3 expectedContactPoint = (1.0f + distance) * xAxis; - QCOMPARE(collision._contactPoint, expectedContactPoint); - - glm::vec3 expectedAddedVelocity = - xYxis + xAxis + xYxis; - QCOMPARE(collision._addedVelocity, expectedAddedVelocity); -}*/ - diff --git a/tests/physics/src/CollisionInfoTests.h b/tests/physics/src/CollisionInfoTests.h deleted file mode 100644 index d26d39be4b..0000000000 --- a/tests/physics/src/CollisionInfoTests.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// CollisionInfoTests.h -// tests/physics/src -// -// Created by Andrew Meadows on 2/21/2014. -// Copyright 2014 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 -// - -#ifndef hifi_CollisionInfoTests_h -#define hifi_CollisionInfoTests_h - -#include - -// Add additional qtest functionality (the include order is important!) -#include "GlmTestUtils.h" -#include "../QTestExtensions.h" - -class CollisionInfoTests : public QObject { - Q_OBJECT - -private slots: -// void rotateThenTranslate(); -// void translateThenRotate(); -}; - -#endif // hifi_CollisionInfoTests_h diff --git a/tests/physics/src/MeshMassPropertiesTests.cpp b/tests/physics/src/MeshMassPropertiesTests.cpp index 794eee0fcf..e88bcae1b7 100644 --- a/tests/physics/src/MeshMassPropertiesTests.cpp +++ b/tests/physics/src/MeshMassPropertiesTests.cpp @@ -9,11 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "MeshMassPropertiesTests.h" + #include -#include #include -#include "MeshMassPropertiesTests.h" +// Add additional qtest functionality (the include order is important!) +#include "BulletTestUtils.h" +#include "GlmTestUtils.h" +#include "../QTestExtensions.h" const btScalar acceptableRelativeError(1.0e-5f); const btScalar acceptableAbsoluteError(1.0e-4f); diff --git a/tests/physics/src/MeshMassPropertiesTests.h b/tests/physics/src/MeshMassPropertiesTests.h index 35471bdbad..b8af9d9db6 100644 --- a/tests/physics/src/MeshMassPropertiesTests.h +++ b/tests/physics/src/MeshMassPropertiesTests.h @@ -13,12 +13,6 @@ #define hifi_MeshMassPropertiesTests_h #include -#include - -// Add additional qtest functionality (the include order is important!) -#include "BulletTestUtils.h" -#include "GlmTestUtils.h" -#include "../QTestExtensions.h" // Relative error macro (see errorTest in BulletTestUtils.h) #define QCOMPARE_WITH_RELATIVE_ERROR(actual, expected, relativeError) \ diff --git a/tests/physics/src/ShapeColliderTests.cpp b/tests/physics/src/ShapeColliderTests.cpp index cb42f534cb..cb51e18fbd 100644 --- a/tests/physics/src/ShapeColliderTests.cpp +++ b/tests/physics/src/ShapeColliderTests.cpp @@ -9,12 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ShapeColliderTests.h" + //#include #include #include #include #include +#include #include #include @@ -25,7 +28,10 @@ #include #include -#include "ShapeColliderTests.h" +// Add additional qtest functionality (the include order is important!) +#include "BulletTestUtils.h" +#include "GlmTestUtils.h" +#include "../QTestExtensions.h" const glm::vec3 origin(0.0f); @@ -1553,8 +1559,6 @@ void ShapeColliderTests::rayHitsCapsule() { intersection._rayDirection = - xAxis; QCOMPARE(capsule.findRayIntersection(intersection), true); float expectedDistance = startDistance - radius * sqrtf(2.0f * delta); // using small angle approximation of cosine -// float relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance; - // for edge cases we allow a LOT of error QCOMPARE_WITH_ABS_ERROR(intersection._hitDistance, expectedDistance, startDistance * EDGE_CASE_SLOP_FACTOR * EPSILON); } @@ -1564,8 +1568,6 @@ void ShapeColliderTests::rayHitsCapsule() { intersection._rayDirection = - xAxis; QCOMPARE(capsule.findRayIntersection(intersection), true); float expectedDistance = startDistance - radius * sqrtf(2.0f * delta); // using small angle approximation of cosine -// float relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance; - // for edge cases we allow a LOT of error QCOMPARE_WITH_ABS_ERROR(intersection._hitDistance, expectedDistance, startDistance * EPSILON * EDGE_CASE_SLOP_FACTOR); } @@ -1575,8 +1577,6 @@ void ShapeColliderTests::rayHitsCapsule() { intersection._rayDirection = - xAxis; QCOMPARE(capsule.findRayIntersection(intersection), true); float expectedDistance = startDistance - radius * sqrtf(2.0f * delta); // using small angle approximation of cosine - float relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance; - // for edge cases we allow a LOT of error QCOMPARE_WITH_ABS_ERROR(intersection._hitDistance, expectedDistance, startDistance * EPSILON * EDGE_CASE_SLOP_FACTOR); } // TODO: test at steep angles near cylinder/cap junction diff --git a/tests/physics/src/ShapeColliderTests.h b/tests/physics/src/ShapeColliderTests.h index 48d9cbd742..73e2b972a9 100644 --- a/tests/physics/src/ShapeColliderTests.h +++ b/tests/physics/src/ShapeColliderTests.h @@ -13,13 +13,6 @@ #define hifi_ShapeColliderTests_h #include -#include - -// Add additional qtest functionality (the include order is important!) -#include "BulletTestUtils.h" -#include "GlmTestUtils.h" -#include "../QTestExtensions.h" - class ShapeColliderTests : public QObject { Q_OBJECT From b46ad0c39780d475de0ed90d2b84029e2616ca96 Mon Sep 17 00:00:00 2001 From: bwent Date: Wed, 15 Jul 2015 11:50:10 -0700 Subject: [PATCH 080/129] Created subpanel panel item --- examples/utilities/tools/cookies.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index 0fdae01c5e..8b4d739c02 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -416,6 +416,8 @@ DirectionBox = function(x,y,width,thumbSize) { this.onValueChanged = function(value) {}; } + + var textFontSize = 12; function PanelItem(name, setter, getter, displayer, x, y, textWidth, valueWidth, height) { @@ -429,7 +431,7 @@ function PanelItem(name, setter, getter, displayer, x, y, textWidth, valueWidth, } else if (value == false) { return "Off"; } - return value.toFixed(2); + return value; }; var topMargin = (height - textFontSize); @@ -616,7 +618,7 @@ Panel = function(x, y) { // print("created Item... colorBox=" + name); }; - this.newDirectionBox= function(name, setValue, getValue, displayValue) { + this.newDirectionBox = function(name, setValue, getValue, displayValue) { var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); @@ -630,6 +632,20 @@ Panel = function(x, y) { // print("created Item... directionBox=" + name); }; + this.newSubPanel = function(name) { + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); + + var panel = new Panel(this.widgetX, this.nextY); + + item.widget = panel; + + item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; + + this.nextY += rawYDelta; + + }; + + this.destroy = function() { for (var i in this.items) { this.items[i].destroy(); From 4ae03184ecfcab1377b9ac7911f792a9b34a0061 Mon Sep 17 00:00:00 2001 From: bwent Date: Tue, 21 Jul 2015 10:23:41 -0700 Subject: [PATCH 081/129] add subpanel functionality --- examples/utilities/tools/cookies.js | 242 +++++++++++++++++++++++++--- 1 file changed, 223 insertions(+), 19 deletions(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index 8b4d739c02..2949626252 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -92,7 +92,6 @@ Slider = function(x,y,width,thumbSize) { this.isMoving = false; }; - // Public members: this.setNormalizedValue = function(value) { if (value < 0.0) { @@ -113,10 +112,19 @@ Slider = function(x,y,width,thumbSize) { this.setNormalizedValue(normValue); }; + this.reset = function(resetValue) { + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; + this.getValue = function() { return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; }; + this.getHeight = function() { + return 1.5 * this.thumbSize; + } + this.onValueChanged = function(value) {}; this.destroy = function() { @@ -130,6 +138,7 @@ Slider = function(x,y,width,thumbSize) { this.setBackgroundColor = function(color) { Overlays.editOverlay(this.background, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); }; + } // The Checkbox class @@ -158,10 +167,12 @@ Checkbox = function(x,y,width,thumbSize) { visible: true }); - + this.thumbSize = thumbSize; var checkX = x + (0.25 * thumbSize); var checkY = y + (0.25 * thumbSize); + var boxCheckStatus; + var clickedBox = false; var checkMark = Overlays.addOverlay("text", { @@ -181,22 +192,22 @@ Checkbox = function(x,y,width,thumbSize) { width: thumbSize / 2.5, height: thumbSize / 2.5, alpha: 1.0, - visible: boxCheckStatus + visible: !boxCheckStatus }); - - var boxCheckStatus; - var clickedBox = false; - this.updateThumb = function() { - if (clickedBox) { - boxCheckStatus = !boxCheckStatus; - if (boxCheckStatus) { - Overlays.editOverlay(unCheckMark, { visible: false }); - } else { - Overlays.editOverlay(unCheckMark, { visible: true }); - } + this.updateThumb = function() { + if(!clickedBox) { + return; + } + + boxCheckStatus = !boxCheckStatus; + if (boxCheckStatus) { + Overlays.editOverlay(unCheckMark, { visible: false }); + } else { + Overlays.editOverlay(unCheckMark, { visible: true }); } + }; this.isClickableOverlayItem = function(item) { @@ -215,10 +226,12 @@ Checkbox = function(x,y,width,thumbSize) { this.onValueChanged(this.getValue()); }; + this.onMouseReleaseEvent = function(event) { this.clickedBox = false; }; + // Public members: this.setNormalizedValue = function(value) { boxCheckStatus = value; @@ -232,10 +245,26 @@ Checkbox = function(x,y,width,thumbSize) { this.setNormalizedValue(value); }; + this.reset = function(resetValue) { + this.setValue(resetValue); + + this.onValueChanged(resetValue); + }; + this.getValue = function() { return boxCheckStatus; }; + this.getHeight = function() { + return 1.5 * this.thumbSize; + } + + this.setterFromWidget = function(value) { + var status = boxCheckStatus; + this.onValueChanged(boxCheckStatus); + this.updateThumb(); + }; + this.onValueChanged = function(value) {}; this.destroy = function() { @@ -267,6 +296,8 @@ ColorBox = function(x,y,width,thumbSize) { this.green.setBackgroundColor({x: 0, y: 1, z: 0}); this.blue.setBackgroundColor({x: 0, y: 0, z: 1}); + + this.isClickableOverlayItem = function(item) { return this.red.isClickableOverlayItem(item) || this.green.isClickableOverlayItem(item) @@ -293,6 +324,7 @@ ColorBox = function(x,y,width,thumbSize) { this.blue.onMousePressEvent(event, clickedOverlay); }; + this.onMouseReleaseEvent = function(event) { this.red.onMouseReleaseEvent(event); this.green.onMouseReleaseEvent(event); @@ -323,11 +355,20 @@ ColorBox = function(x,y,width,thumbSize) { this.updateRGBSliders(value); }; + this.reset = function(resetValue) { + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; + this.getValue = function() { var value = {x:this.red.getValue(), y:this.green.getValue(),z:this.blue.getValue()}; return value; }; + this.getHeight = function() { + return 1.5 * this.thumbSize; + } + this.destroy = function() { this.red.destroy(); this.green.destroy(); @@ -345,6 +386,8 @@ DirectionBox = function(x,y,width,thumbSize) { var sliderWidth = width; this.yaw = new Slider(x, y, width, slideHeight); this.pitch = new Slider(x, y + slideHeight, width, slideHeight); + + this.yaw.setThumbColor({x: 1, y: 0, z: 0}); this.yaw.minValue = -180; @@ -400,6 +443,11 @@ DirectionBox = function(x,y,width,thumbSize) { this.pitch.setValue(direction.y); }; + this.reset = function(resetValue) { + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; + this.getValue = function() { var dirZ = this.pitch.getValue(); var yaw = this.yaw.getValue() * Math.PI / 180; @@ -408,6 +456,10 @@ DirectionBox = function(x,y,width,thumbSize) { return value; }; + this.getHeight = function() { + return 1.5 * this.thumbSize; + } + this.destroy = function() { this.yaw.destroy(); this.pitch.destroy(); @@ -420,6 +472,48 @@ DirectionBox = function(x,y,width,thumbSize) { var textFontSize = 12; +// TODO: Make collapsable +function CollapsablePanelItem(name, x, y, textWidth, height) { + this.name = name; + this.height = height; + + var topMargin = (height - textFontSize); + + this.thumb = Overlays.addOverlay("text", { + backgroundColor: { red: 220, green: 220, blue: 220 }, + textFontSize: 10, + x: x, + y: y, + width: rawHeight, + height: rawHeight, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); + + this.title = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: x + rawHeight, + y: y, + width: textWidth, + height: height, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true, + text: name, + font: {size: textFontSize}, + topMargin: topMargin, + }); + + this.destroy = function() { + Overlays.deleteOverlay(this.title); + Overlays.deleteOverlay(this.thumb); + if (this.widget != null) { + this.widget.destroy(); + } + } +} + function PanelItem(name, setter, getter, displayer, x, y, textWidth, valueWidth, height) { //print("creating panel item: " + name); @@ -548,15 +642,18 @@ Panel = function(x, y) { // Reset panel item upon double-clicking this.mouseDoublePressEvent = function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); for (var i in this.items) { var item = this.items[i]; var widget = item.widget; - if (item.title == clickedOverlay || item.value == clickedOverlay) { - widget.updateThumb(); - widget.onValueChanged(item.resetValue); + if (clickedOverlay == item.title) { + item.activeWidget = widget; + + item.activeWidget.reset(item.resetValue); + break; } } @@ -569,8 +666,56 @@ Panel = function(x, y) { this.activeWidget = null; }; - this.newSlider = function(name, minValue, maxValue, setValue, getValue, displayValue) { + this.onMousePressEvent = function(event, clickedOverlay) { + for (var i in this.items) { + var item = this.items[i]; + if(item.widget.isClickableOverlayItem(clickedOverlay)) { + item.activeWidget = item.widget; + item.activeWidget.onMousePressEvent(event,clickedOverlay); + } + } + } + this.reset = function() { + for (var i in this.items) { + var item = this.items[i]; + if (item.activeWidget) { + item.activeWidget.reset(item.resetValue); + } + } + } + + this.onMouseMoveEvent = function(event) { + for (var i in this.items) { + var item = this.items[i]; + if (item.activeWidget) { + item.activeWidget.onMouseMoveEvent(event); + } + } + } + + this.onMouseReleaseEvent = function(event, clickedOverlay) { + for (var i in this.items) { + var item = this.items[i]; + if (item.activeWidget) { + item.activeWidget.onMouseReleaseEvent(event); + } + item.activeWidget = null; + } + } + + this.onMouseDoublePressEvent = function(event, clickedOverlay) { + + for (var i in this.items) { + var item = this.items[i]; + if (item.activeWidget) { + item.activeWidget.onMouseDoublePressEvent(event); + } + } + } + + this.newSlider = function(name, minValue, maxValue, setValue, getValue, displayValue) { + this.nextY = this.y + this.getHeight(); var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); var slider = new Slider(this.widgetX, this.nextY, widgetWidth, rawHeight); @@ -591,6 +736,8 @@ Panel = function(x, y) { } else if (displayValue == false) { display = function() {return "Off";}; } + + this.nextY = this.y + this.getHeight(); var item = new PanelItem(name, setValue, getValue, display, this.x, this.nextY, textWidth, valueWidth, rawHeight); @@ -600,11 +747,12 @@ Panel = function(x, y) { item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; item.setter(getValue()); this.items[name] = item; - this.nextY += rawYDelta; + //print("created Item... checkbox=" + name); }; this.newColorBox = function(name, setValue, getValue, displayValue) { + this.nextY = this.y + this.getHeight(); var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); @@ -618,7 +766,12 @@ Panel = function(x, y) { // print("created Item... colorBox=" + name); }; +<<<<<<< Updated upstream this.newDirectionBox = function(name, setValue, getValue, displayValue) { +======= + this.newDirectionBox= function(name, setValue, getValue, displayValue) { + this.nextY = this.y + this.getHeight(); +>>>>>>> Stashed changes var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); @@ -632,6 +785,7 @@ Panel = function(x, y) { // print("created Item... directionBox=" + name); }; +<<<<<<< Updated upstream this.newSubPanel = function(name) { var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); @@ -645,6 +799,32 @@ Panel = function(x, y) { }; +======= + var indentation = 30; + + this.newSubPanel = function(name) { + //TODO: make collapsable, fix double-press event + this.nextY = this.y + this.getHeight(); + + var item = new CollapsablePanelItem(name, this.x, this.nextY, textWidth, rawHeight, panel); + item.isSubPanel = true; + + this.nextY += 1.5 * item.height; + + var subPanel = new Panel(this.x + indentation, this.nextY); + + item.widget = subPanel; + this.items[name] = item; + return subPanel; + // print("created Item... subPanel=" + name); + }; + + this.onValueChanged = function(value) { + for (var i in this.items) { + this.items[i].widget.onValueChanged(value); + } + } +>>>>>>> Stashed changes this.destroy = function() { for (var i in this.items) { @@ -652,6 +832,7 @@ Panel = function(x, y) { } } + this.set = function(name, value) { var item = this.items[name]; if (item != null) { @@ -676,6 +857,29 @@ Panel = function(x, y) { return null; } + this.isClickableOverlayItem = function(item) { + for (var i in this.items) { + if (this.items[i].widget.isClickableOverlayItem(item)) { + return true; + } + } + return false; + } + + this.getHeight = function() { + var height = 0; + + for (var i in this.items) { + height += this.items[i].widget.getHeight(); + if(this.items[i].isSubPanel) { + height += 1.5 * rawHeight; + } + } + + + return height; + } + }; From 252780dc5dcebb32866c9b151adcda2f014df260 Mon Sep 17 00:00:00 2001 From: bwent Date: Mon, 27 Jul 2015 13:44:01 -0700 Subject: [PATCH 082/129] fix checkbox class, make subpanels collapsable --- examples/utilities/tools/cookies.js | 1669 ++++++++++++++++----------- 1 file changed, 983 insertions(+), 686 deletions(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index 2949626252..9d064385bf 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -10,663 +10,925 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // // The Slider class -Slider = function(x,y,width,thumbSize) { - this.background = Overlays.addOverlay("text", { - backgroundColor: { red: 200, green: 200, blue: 255 }, - x: x, - y: y, - width: width, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true - }); - this.thumb = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x, - y: y, - width: thumbSize, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); - - - this.thumbSize = thumbSize; - this.thumbHalfSize = 0.5 * thumbSize; - - this.minThumbX = x + this.thumbHalfSize; - this.maxThumbX = x + width - this.thumbHalfSize; - this.thumbX = this.minThumbX; - - this.minValue = 0.0; - this.maxValue = 1.0; - - this.clickOffsetX = 0; - this.isMoving = false; - - this.updateThumb = function() { - thumbTruePos = this.thumbX - 0.5 * this.thumbSize; - Overlays.editOverlay(this.thumb, { x: thumbTruePos } ); - }; - - this.isClickableOverlayItem = function(item) { - return (item == this.thumb) || (item == this.background); - }; - - this.onMouseMoveEvent = function(event) { - if (this.isMoving) { - newThumbX = event.x - this.clickOffsetX; - if (newThumbX < this.minThumbX) { - newThumbX = this.minThumbX; - } - if (newThumbX > this.maxThumbX) { - newThumbX = this.maxThumbX; - } - this.thumbX = newThumbX; - this.updateThumb(); - this.onValueChanged(this.getValue()); - } - }; - - this.onMousePressEvent = function(event, clickedOverlay) { - if (!this.isClickableOverlayItem(clickedOverlay)) { - this.isMoving = false; - return; - } - this.isMoving = true; - var clickOffset = event.x - this.thumbX; - if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { - this.clickOffsetX = clickOffset; - } else { - this.clickOffsetX = 0; - this.thumbX = event.x; - this.updateThumb(); - this.onValueChanged(this.getValue()); - } - - }; - - this.onMouseReleaseEvent = function(event) { - this.isMoving = false; - }; - - // Public members: - this.setNormalizedValue = function(value) { - if (value < 0.0) { - this.thumbX = this.minThumbX; - } else if (value > 1.0) { - this.thumbX = this.maxThumbX; - } else { - this.thumbX = value * (this.maxThumbX - this.minThumbX) + this.minThumbX; - } - this.updateThumb(); - }; - this.getNormalizedValue = function() { - return (this.thumbX - this.minThumbX) / (this.maxThumbX - this.minThumbX); - }; - - this.setValue = function(value) { - var normValue = (value - this.minValue) / (this.maxValue - this.minValue); - this.setNormalizedValue(normValue); - }; - - this.reset = function(resetValue) { - this.setValue(resetValue); - this.onValueChanged(resetValue); - }; - - this.getValue = function() { - return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; - }; - - this.getHeight = function() { - return 1.5 * this.thumbSize; - } - - this.onValueChanged = function(value) {}; - - this.destroy = function() { - Overlays.deleteOverlay(this.background); - Overlays.deleteOverlay(this.thumb); - }; - - this.setThumbColor = function(color) { - Overlays.editOverlay(this.thumb, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); - }; - this.setBackgroundColor = function(color) { - Overlays.editOverlay(this.background, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); - }; - -} - -// The Checkbox class -Checkbox = function(x,y,width,thumbSize) { - - this.background = Overlays.addOverlay("text", { - backgroundColor: { red: 125, green: 125, blue: 255 }, - x: x, - y: y, - width: width, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true - }); - - this.thumb = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - textFontSize: 10, - x: x, - y: y, - width: thumbSize, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); - - - this.thumbSize = thumbSize; - var checkX = x + (0.25 * thumbSize); - var checkY = y + (0.25 * thumbSize); - var boxCheckStatus; - var clickedBox = false; - - - var checkMark = Overlays.addOverlay("text", { - backgroundColor: { red: 0, green: 255, blue: 0 }, - x: checkX, - y: checkY, - width: thumbSize / 2.0, - height: thumbSize / 2.0, - alpha: 1.0, - visible: true - }); - - var unCheckMark = Overlays.addOverlay("image", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: checkX + 1.0, - y: checkY + 1.0, - width: thumbSize / 2.5, - height: thumbSize / 2.5, - alpha: 1.0, - visible: !boxCheckStatus - }); - - - this.updateThumb = function() { - if(!clickedBox) { - return; - } +(function () { + var Slider = function(x,y,width,thumbSize) { - boxCheckStatus = !boxCheckStatus; - if (boxCheckStatus) { - Overlays.editOverlay(unCheckMark, { visible: false }); - } else { - Overlays.editOverlay(unCheckMark, { visible: true }); - } + this.background = Overlays.addOverlay("text", { + backgroundColor: { red: 200, green: 200, blue: 255 }, + x: x, + y: y, + width: width, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true + }); + this.thumb = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: x, + y: y, + width: thumbSize, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); + + this.thumbSize = thumbSize; - }; + this.thumbHalfSize = 0.5 * thumbSize; + + this.minThumbX = x + this.thumbHalfSize; + this.maxThumbX = x + width - this.thumbHalfSize; + this.thumbX = this.minThumbX; + + this.minValue = 0.0; + this.maxValue = 1.0; - this.isClickableOverlayItem = function(item) { - return (item == this.thumb) || (item == checkMark) || (item == unCheckMark); + this.y = y; + + this.clickOffsetX = 0; + this.isMoving = false; + this.visible = true; }; - this.onMousePressEvent = function(event, clickedOverlay) { - if (!this.isClickableOverlayItem(clickedOverlay)) { - this.isMoving = false; - clickedBox = false; - return; - } - - clickedBox = true; - this.updateThumb(); - this.onValueChanged(this.getValue()); - }; - - - this.onMouseReleaseEvent = function(event) { - this.clickedBox = false; - }; - - - // Public members: - this.setNormalizedValue = function(value) { - boxCheckStatus = value; - }; - - this.getNormalizedValue = function() { - return boxCheckStatus; - }; - - this.setValue = function(value) { - this.setNormalizedValue(value); - }; - - this.reset = function(resetValue) { - this.setValue(resetValue); - - this.onValueChanged(resetValue); - }; - - this.getValue = function() { - return boxCheckStatus; - }; - - this.getHeight = function() { - return 1.5 * this.thumbSize; - } - - this.setterFromWidget = function(value) { - var status = boxCheckStatus; - this.onValueChanged(boxCheckStatus); - this.updateThumb(); - }; - - this.onValueChanged = function(value) {}; - - this.destroy = function() { - Overlays.deleteOverlay(this.background); - Overlays.deleteOverlay(this.thumb); - Overlays.deleteOverlay(checkMark); - Overlays.deleteOverlay(unCheckMark); - }; - - this.setThumbColor = function(color) { - Overlays.editOverlay(this.thumb, { red: 255, green: 255, blue: 255 } ); - }; - this.setBackgroundColor = function(color) { - Overlays.editOverlay(this.background, { red: 125, green: 125, blue: 255 }); - }; - -} - -// The ColorBox class -ColorBox = function(x,y,width,thumbSize) { - var self = this; + Slider.prototype.updateThumb = function() { + var thumbTruePos = this.thumbX - 0.5 * this.thumbSize; + Overlays.editOverlay(this.thumb, { x: thumbTruePos } ); + }; - var slideHeight = thumbSize / 3; - var sliderWidth = width; - this.red = new Slider(x, y, width, slideHeight); - this.green = new Slider(x, y + slideHeight, width, slideHeight); - this.blue = new Slider(x, y + 2 * slideHeight, width, slideHeight); - this.red.setBackgroundColor({x: 1, y: 0, z: 0}); - this.green.setBackgroundColor({x: 0, y: 1, z: 0}); - this.blue.setBackgroundColor({x: 0, y: 0, z: 1}); - - - - this.isClickableOverlayItem = function(item) { - return this.red.isClickableOverlayItem(item) - || this.green.isClickableOverlayItem(item) - || this.blue.isClickableOverlayItem(item); - }; - - this.onMouseMoveEvent = function(event) { - this.red.onMouseMoveEvent(event); - this.green.onMouseMoveEvent(event); - this.blue.onMouseMoveEvent(event); - }; - - this.onMousePressEvent = function(event, clickedOverlay) { - this.red.onMousePressEvent(event, clickedOverlay); - if (this.red.isMoving) { - return; - } - - this.green.onMousePressEvent(event, clickedOverlay); - if (this.green.isMoving) { - return; - } - - this.blue.onMousePressEvent(event, clickedOverlay); - }; - - - this.onMouseReleaseEvent = function(event) { - this.red.onMouseReleaseEvent(event); - this.green.onMouseReleaseEvent(event); - this.blue.onMouseReleaseEvent(event); - }; - - this.setterFromWidget = function(value) { - var color = self.getValue(); - self.onValueChanged(color); - self.updateRGBSliders(color); - }; - - this.red.onValueChanged = this.setterFromWidget; - this.green.onValueChanged = this.setterFromWidget; - this.blue.onValueChanged = this.setterFromWidget; - - this.updateRGBSliders = function(color) { - this.red.setThumbColor({x: color.x, y: 0, z: 0}); - this.green.setThumbColor({x: 0, y: color.y, z: 0}); - this.blue.setThumbColor({x: 0, y: 0, z: color.z}); - }; - - // Public members: - this.setValue = function(value) { - this.red.setValue(value.x); - this.green.setValue(value.y); - this.blue.setValue(value.z); - this.updateRGBSliders(value); - }; - - this.reset = function(resetValue) { - this.setValue(resetValue); - this.onValueChanged(resetValue); - }; - - this.getValue = function() { - var value = {x:this.red.getValue(), y:this.green.getValue(),z:this.blue.getValue()}; - return value; - }; - - this.getHeight = function() { - return 1.5 * this.thumbSize; - } - - this.destroy = function() { - this.red.destroy(); - this.green.destroy(); - this.blue.destroy(); - }; - - this.onValueChanged = function(value) {}; -} - -// The DirectionBox class -DirectionBox = function(x,y,width,thumbSize) { - var self = this; + Slider.prototype.isClickableOverlayItem = function(item) { + return (item == this.thumb) || (item == this.background); + }; - var slideHeight = thumbSize / 2; - var sliderWidth = width; - this.yaw = new Slider(x, y, width, slideHeight); - this.pitch = new Slider(x, y + slideHeight, width, slideHeight); - - - - this.yaw.setThumbColor({x: 1, y: 0, z: 0}); - this.yaw.minValue = -180; - this.yaw.maxValue = +180; - - this.pitch.setThumbColor({x: 0, y: 0, z: 1}); - this.pitch.minValue = -1; - this.pitch.maxValue = +1; - - this.isClickableOverlayItem = function(item) { - return this.yaw.isClickableOverlayItem(item) - || this.pitch.isClickableOverlayItem(item); - }; - - this.onMouseMoveEvent = function(event) { - this.yaw.onMouseMoveEvent(event); - this.pitch.onMouseMoveEvent(event); - }; - - this.onMousePressEvent = function(event, clickedOverlay) { - this.yaw.onMousePressEvent(event, clickedOverlay); - if (this.yaw.isMoving) { - return; - } - this.pitch.onMousePressEvent(event, clickedOverlay); - }; - - this.onMouseReleaseEvent = function(event) { - this.yaw.onMouseReleaseEvent(event); - this.pitch.onMouseReleaseEvent(event); - }; - - this.setterFromWidget = function(value) { - var yawPitch = self.getValue(); - self.onValueChanged(yawPitch); - }; - - this.yaw.onValueChanged = this.setterFromWidget; - this.pitch.onValueChanged = this.setterFromWidget; - - // Public members: - this.setValue = function(direction) { - var flatXZ = Math.sqrt(direction.x * direction.x + direction.z * direction.z); - if (flatXZ > 0.0) { - var flatX = direction.x / flatXZ; - var flatZ = direction.z / flatXZ; - var yaw = Math.acos(flatX) * 180 / Math.PI; - if (flatZ < 0) { - yaw = -yaw; + Slider.prototype.onMouseMoveEvent = function(event) { + if (this.isMoving) { + var newThumbX = event.x - this.clickOffsetX; + if (newThumbX < this.minThumbX) { + newThumbX = this.minThumbX; + } + if (newThumbX > this.maxThumbX) { + newThumbX = this.maxThumbX; + } + this.thumbX = newThumbX; + this.updateThumb(); + this.onValueChanged(this.getValue()); } - this.yaw.setValue(yaw); + }; + + Slider.prototype.onMousePressEvent = function(event, clickedOverlay) { + if (!this.isClickableOverlayItem(clickedOverlay)) { + this.isMoving = false; + return; + } + this.isMoving = true; + var clickOffset = event.x - this.thumbX; + if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { + this.clickOffsetX = clickOffset; + } else { + this.clickOffsetX = 0; + this.thumbX = event.x; + this.updateThumb(); + this.onValueChanged(this.getValue()); + } + + }; + + Slider.prototype.onMouseReleaseEvent = function(event) { + this.isMoving = false; + }; + + // Public members: + Slider.prototype.setNormalizedValue = function(value) { + if (value < 0.0) { + this.thumbX = this.minThumbX; + } else if (value > 1.0) { + this.thumbX = this.maxThumbX; + } else { + this.thumbX = value * (this.maxThumbX - this.minThumbX) + this.minThumbX; + } + this.updateThumb(); + }; + Slider.prototype.getNormalizedValue = function() { + return (this.thumbX - this.minThumbX) / (this.maxThumbX - this.minThumbX); + }; + + Slider.prototype.setValue = function(value) { + var normValue = (value - this.minValue) / (this.maxValue - this.minValue); + this.setNormalizedValue(normValue); + }; + + Slider.prototype.reset = function(resetValue) { + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; + + Slider.prototype.getValue = function() { + return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; + }; + + Slider.prototype.getHeight = function() { + if(!this.visible) { + return 0; + } + return 1.5 * this.thumbSize; + }; + + Slider.prototype.moveUp = function(newY) { + Overlays.editOverlay(this.background, {y: newY}); + Overlays.editOverlay(this.thumb, {y: newY}); + }; + + Slider.prototype.moveDown = function() { + Overlays.editOverlay(this.background, {y: this.y}); + Overlays.editOverlay(this.thumb, {y: this.y}); + }; + + Slider.prototype.onValueChanged = function(value) {}; + + Slider.prototype.hide = function() { + Overlays.editOverlay(this.background, {visible: false}); + Overlays.editOverlay(this.thumb, {visible: false}); + this.visible = false; + }; + + Slider.prototype.show = function() { + Overlays.editOverlay(this.background, {visible: true}); + Overlays.editOverlay(this.thumb, {visible: true}); + this.visible = true; + }; + + Slider.prototype.destroy = function() { + Overlays.deleteOverlay(this.background); + Overlays.deleteOverlay(this.thumb); + }; + + Slider.prototype.setThumbColor = function(color) { + Overlays.editOverlay(this.thumb, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); + }; + Slider.prototype.setBackgroundColor = function(color) { + Overlays.editOverlay(this.background, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); + }; + this.Slider = Slider; + + // The Checkbox class + var Checkbox = function(x,y,width,thumbSize) { + + this.background = Overlays.addOverlay("text", { + backgroundColor: { red: 125, green: 125, blue: 255 }, + x: x, + y: y, + width: width, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true + }); + + this.thumb = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + textFontSize: 10, + x: x, + y: y, + width: thumbSize, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); + + + this.thumbSize = thumbSize; + var checkX = x + (0.25 * thumbSize); + var checkY = y + (0.25 * thumbSize); + this.y = y; + this.boxCheckStatus = true; + this.clickedBox = false; + this.visible = true; + + + this.checkMark = Overlays.addOverlay("text", { + backgroundColor: { red: 0, green: 255, blue: 0 }, + x: checkX, + y: checkY, + width: thumbSize / 2.0, + height: thumbSize / 2.0, + alpha: 1.0, + visible: true + }); + + this.unCheckMark = Overlays.addOverlay("image", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: checkX + 1.0, + y: checkY + 1.0, + width: thumbSize / 2.5, + height: thumbSize / 2.5, + alpha: 1.0, + visible: false + }); + }; + + Checkbox.prototype.updateThumb = function() { + + Overlays.editOverlay(this.unCheckMark, { visible: !this.boxCheckStatus }); + + }; + + Checkbox.prototype.isClickableOverlayItem = function(item) { + return (item == this.thumb) || (item == this.checkMark) || (item == this.unCheckMark); + }; + + Checkbox.prototype.onMousePressEvent = function(event, clickedOverlay) { + + if (!this.isClickableOverlayItem(clickedOverlay)) { + return; + } + + this.boxCheckStatus = !this.boxCheckStatus; + this.onValueChanged(this.getValue()); + this.updateThumb(); + }; + + + Checkbox.prototype.onMouseReleaseEvent = function(event) { }; + + + // Public members: + + Checkbox.prototype.setValue = function(value) { + this.boxCheckStatus = value; + }; + + Checkbox.prototype.reset = function(resetValue) { + this.setValue(resetValue); + }; + + Checkbox.prototype.getValue = function() { + return this.boxCheckStatus; + }; + + Checkbox.prototype.getHeight = function() { + if(!this.visible) { + return 0; } - this.pitch.setValue(direction.y); + return 1.5 * this.thumbSize; + }; + + Checkbox.prototype.moveUp = function(newY) { + Overlays.editOverlay(this.background, {y: newY}); + Overlays.editOverlay(this.thumb, {y: newY}); + Overlays.editOverlay(this.checkMark, {y: newY}); + Overlays.editOverlay(this.unCheckMark, {y: newY}); }; - this.reset = function(resetValue) { - this.setValue(resetValue); - this.onValueChanged(resetValue); + Checkbox.prototype.moveDown = function() { + Overlays.editOverlay(this.background, {y: this.y}); + Overlays.editOverlay(this.thumb, {y: this.y}); + Overlays.editOverlay(this.checkMark, {y: this.y}); + Overlays.editOverlay(this.unCheckMark, {y: this.y}); }; + + Checkbox.prototype.setterFromWidget = function(value) { + this.updateThumb(); + }; + + Checkbox.prototype.onValueChanged = function(value) { }; - this.getValue = function() { - var dirZ = this.pitch.getValue(); - var yaw = this.yaw.getValue() * Math.PI / 180; - var cosY = Math.sqrt(1 - dirZ*dirZ); - var value = {x:cosY * Math.cos(yaw), y:dirZ, z: cosY * Math.sin(yaw)}; - return value; - }; - - this.getHeight = function() { - return 1.5 * this.thumbSize; + Checkbox.prototype.hide = function() { + Overlays.editOverlay(this.background, {visible: false}); + Overlays.editOverlay(this.thumb, {visible: false}); + Overlays.editOverlay(this.checkMark, {visible: false}); + Overlays.editOverlay(this.unCheckMark, {visible: false}); + this.visible = false; } - this.destroy = function() { - this.yaw.destroy(); - this.pitch.destroy(); + Checkbox.prototype.show = function() { + Overlays.editOverlay(this.background, {visible: true}); + Overlays.editOverlay(this.thumb, {visible: true}); + Overlays.editOverlay(this.checkMark, {visible: true}); + Overlays.editOverlay(this.unCheckMark, {visible: true}); + this.visible = true; + } + + Checkbox.prototype.destroy = function() { + Overlays.deleteOverlay(this.background); + Overlays.deleteOverlay(this.thumb); + Overlays.deleteOverlay(this.checkMark); + Overlays.deleteOverlay(this.unCheckMark); + }; + + Checkbox.prototype.setThumbColor = function(color) { + Overlays.editOverlay(this.thumb, { red: 255, green: 255, blue: 255 } ); + }; + Checkbox.prototype.setBackgroundColor = function(color) { + Overlays.editOverlay(this.background, { red: 125, green: 125, blue: 255 }); + }; + this.Checkbox = Checkbox; + + // The ColorBox class + var ColorBox = function(x,y,width,thumbSize) { + var self = this; + + var slideHeight = thumbSize / 3; + var sliderWidth = width; + this.red = new Slider(x, y, width, slideHeight); + this.green = new Slider(x, y + slideHeight, width, slideHeight); + this.blue = new Slider(x, y + 2 * slideHeight, width, slideHeight); + this.red.setBackgroundColor({x: 1, y: 0, z: 0}); + this.green.setBackgroundColor({x: 0, y: 1, z: 0}); + this.blue.setBackgroundColor({x: 0, y: 0, z: 1}); + + this.red.onValueChanged = this.setterFromWidget; + this.green.onValueChanged = this.setterFromWidget; + this.blue.onValueChanged = this.setterFromWidget; + + this.visible = true; + }; + + ColorBox.prototype.isClickableOverlayItem = function(item) { + return this.red.isClickableOverlayItem(item) + || this.green.isClickableOverlayItem(item) + || this.blue.isClickableOverlayItem(item); + }; + + ColorBox.prototype.onMouseMoveEvent = function(event) { + this.red.onMouseMoveEvent(event); + this.green.onMouseMoveEvent(event); + this.blue.onMouseMoveEvent(event); + }; + + ColorBox.prototype.onMousePressEvent = function(event, clickedOverlay) { + this.red.onMousePressEvent(event, clickedOverlay); + if (this.red.isMoving) { + return; + } + + this.green.onMousePressEvent(event, clickedOverlay); + if (this.green.isMoving) { + return; + } + + this.blue.onMousePressEvent(event, clickedOverlay); + }; + + + ColorBox.prototype.onMouseReleaseEvent = function(event) { + this.red.onMouseReleaseEvent(event); + this.green.onMouseReleaseEvent(event); + this.blue.onMouseReleaseEvent(event); + }; + + ColorBox.prototype.setterFromWidget = function(value) { + var color = this.getValue(); + this.onValueChanged(color); + this.updateRGBSliders(color); + }; + + ColorBox.prototype.updateRGBSliders = function(color) { + this.red.setThumbColor({x: color.x, y: 0, z: 0}); + this.green.setThumbColor({x: 0, y: color.y, z: 0}); + this.blue.setThumbColor({x: 0, y: 0, z: color.z}); + }; + + // Public members: + ColorBox.prototype.setValue = function(value) { + this.red.setValue(value.x); + this.green.setValue(value.y); + this.blue.setValue(value.z); + this.updateRGBSliders(value); + }; + + ColorBox.prototype.reset = function(resetValue) { + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; + + ColorBox.prototype.getValue = function() { + var value = {x:this.red.getValue(), y:this.green.getValue(),z:this.blue.getValue()}; + return value; + }; + + ColorBox.prototype.getHeight = function() { + if(!this.visible) { + return 0; + } + return 1.5 * this.thumbSize; + }; + + ColorBox.prototype.moveUp = function(newY) { + this.red.moveUp(newY); + this.green.moveUp(newY); + this.blue.moveUp(newY); }; - this.onValueChanged = function(value) {}; -} + ColorBox.prototype.moveDown = function() { + this.red.moveDown(); + this.green.moveDown(); + this.blue.moveDown(); + }; + ColorBox.prototype.hide = function() { + this.red.hide(); + this.green.hide(); + this.blue.hide(); + this.visible = false; + } - -var textFontSize = 12; - -// TODO: Make collapsable -function CollapsablePanelItem(name, x, y, textWidth, height) { - this.name = name; - this.height = height; - - var topMargin = (height - textFontSize); - - this.thumb = Overlays.addOverlay("text", { - backgroundColor: { red: 220, green: 220, blue: 220 }, - textFontSize: 10, - x: x, - y: y, - width: rawHeight, - height: rawHeight, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); + ColorBox.prototype.show = function() { + this.red.show(); + this.green.show(); + this.blue.show(); + this.visible = true; + } - this.title = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x + rawHeight, - y: y, - width: textWidth, - height: height, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true, - text: name, - font: {size: textFontSize}, - topMargin: topMargin, - }); + ColorBox.prototype.destroy = function() { + this.red.destroy(); + this.green.destroy(); + this.blue.destroy(); + }; + + ColorBox.prototype.onValueChanged = function(value) {}; + this.ColorBox = ColorBox; + + // The DirectionBox class + var DirectionBox = function(x,y,width,thumbSize) { + var self = this; + + var slideHeight = thumbSize / 2; + var sliderWidth = width; + this.yaw = new Slider(x, y, width, slideHeight); + this.pitch = new Slider(x, y + slideHeight, width, slideHeight); + + + this.yaw.setThumbColor({x: 1, y: 0, z: 0}); + this.yaw.minValue = -180; + this.yaw.maxValue = +180; + + this.pitch.setThumbColor({x: 0, y: 0, z: 1}); + this.pitch.minValue = -1; + this.pitch.maxValue = +1; + + this.yaw.onValueChanged = this.setterFromWidget; + this.pitch.onValueChanged = this.setterFromWidget; - this.destroy = function() { + this.visible = true; + }; + + DirectionBox.prototype.isClickableOverlayItem = function(item) { + return this.yaw.isClickableOverlayItem(item) + || this.pitch.isClickableOverlayItem(item); + }; + + DirectionBox.prototype.onMouseMoveEvent = function(event) { + this.yaw.onMouseMoveEvent(event); + this.pitch.onMouseMoveEvent(event); + }; + + DirectionBox.prototype.onMousePressEvent = function(event, clickedOverlay) { + this.yaw.onMousePressEvent(event, clickedOverlay); + if (this.yaw.isMoving) { + return; + } + this.pitch.onMousePressEvent(event, clickedOverlay); + }; + + DirectionBox.prototype.onMouseReleaseEvent = function(event) { + this.yaw.onMouseReleaseEvent(event); + this.pitch.onMouseReleaseEvent(event); + }; + + DirectionBox.prototype.setterFromWidget = function(value) { + var yawPitch = this.getValue(); + this.onValueChanged(yawPitch); + }; + + // Public members: + DirectionBox.prototype.setValue = function(direction) { + var flatXZ = Math.sqrt(direction.x * direction.x + direction.z * direction.z); + if (flatXZ > 0.0) { + var flatX = direction.x / flatXZ; + var flatZ = direction.z / flatXZ; + var yaw = Math.acos(flatX) * 180 / Math.PI; + if (flatZ < 0) { + yaw = -yaw; + } + this.yaw.setValue(yaw); + } + this.pitch.setValue(direction.y); + }; + + DirectionBox.prototype.reset = function(resetValue) { + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; + + DirectionBox.prototype.getValue = function() { + var dirZ = this.pitch.getValue(); + var yaw = this.yaw.getValue() * Math.PI / 180; + var cosY = Math.sqrt(1 - dirZ*dirZ); + var value = {x:cosY * Math.cos(yaw), y:dirZ, z: cosY * Math.sin(yaw)}; + return value; + }; + + DirectionBox.prototype.getHeight = function() { + if(!this.visible) { + return 0; + } + return 1.5 * this.thumbSize; + }; + + DirectionBox.prototype.moveUp = function(newY) { + this.pitch.moveUp(newY); + this.yaw.moveUp(newY); + }; + + DirectionBox.prototype.moveDown = function(newY) { + this.pitch.moveDown(); + this.yaw.moveDown(); + }; + + DirectionBox.prototype.hide = function() { + this.pitch.hide(); + this.yaw.hide(); + this.visible = false; + } + + DirectionBox.prototype.show = function() { + this.pitch.show(); + this.yaw.show(); + this.visible = true; + } + + DirectionBox.prototype.destroy = function() { + this.yaw.destroy(); + this.pitch.destroy(); + }; + + DirectionBox.prototype.onValueChanged = function(value) {}; + this.DirectionBox = DirectionBox; + + var textFontSize = 12; + + var CollapsablePanelItem = function (name, x, y, textWidth, height) { + this.name = name; + this.height = height; + this.y = y; + this.isCollapsable = true; + + var topMargin = (height - 1.5 * textFontSize); + + this.thumb = Overlays.addOverlay("text", { + backgroundColor: { red: 220, green: 220, blue: 220 }, + textFontSize: 10, + x: x, + y: y, + width: rawHeight, + height: rawHeight, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); + + this.title = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: x + rawHeight * 1.5, + y: y, + width: textWidth, + height: height, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true, + text: " " + name, + font: {size: textFontSize}, + topMargin: topMargin + }); + }; + + CollapsablePanelItem.prototype.destroy = function() { Overlays.deleteOverlay(this.title); Overlays.deleteOverlay(this.thumb); - if (this.widget != null) { - this.widget.destroy(); - } - } -} - -function PanelItem(name, setter, getter, displayer, x, y, textWidth, valueWidth, height) { - //print("creating panel item: " + name); + }; - this.name = name; - - this.displayer = typeof displayer !== 'undefined' ? displayer : function(value) { - if(value == true) { - return "On"; - } else if (value == false) { - return "Off"; - } - return value; - }; - - var topMargin = (height - textFontSize); - this.title = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x, - y: y, - width: textWidth, - height: height, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true, - text: name, - font: {size: textFontSize}, - topMargin: topMargin, - }); - - this.value = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x + textWidth, - y: y, - width: valueWidth, - height: height, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true, - text: this.displayer(getter()), - font: {size: textFontSize}, - topMargin: topMargin - }); - - this.getter = getter; - this.resetValue = getter(); - - this.setter = function(value) { - - setter(value); - - Overlays.editOverlay(this.value, {text: this.displayer(getter())}); - - if (this.widget) { - this.widget.setValue(value); - } - - //print("successfully set value of widget to " + value); - }; - this.setterFromWidget = function(value) { - setter(value); - // ANd loop back the value after the final setter has been called - var value = getter(); - - if (this.widget) { - this.widget.setValue(value); - } - Overlays.editOverlay(this.value, {text: this.displayer(value)}); - }; - - this.widget = null; + CollapsablePanelItem.prototype.hide = function() { + Overlays.editOverlay(this.title, {visible: false}); + Overlays.editOverlay(this.thumb, {visible: false}); - this.destroy = function() { - Overlays.deleteOverlay(this.title); - Overlays.deleteOverlay(this.value); if (this.widget != null) { - this.widget.destroy(); + this.widget.hide(); + } + }; + + CollapsablePanelItem.prototype.show = function() { + Overlays.editOverlay(this.title, {visible: true}); + Overlays.editOverlay(this.thumb, {visible: true}); + + if (this.widget != null) { + this.widget.show(); + } + }; + + CollapsablePanelItem.prototype.moveUp = function(newY) { + Overlays.editOverlay(this.title, {y: newY}); + Overlays.editOverlay(this.thumb, {y: newY}); + + if (this.widget != null) { + this.widget.moveUp(newY); } } -} -var textWidth = 180; -var valueWidth = 100; -var widgetWidth = 300; -var rawHeight = 20; -var rawYDelta = rawHeight * 1.5; + CollapsablePanelItem.prototype.moveDown = function() { + Overlays.editOverlay(this.title, {y: this.y}); + Overlays.editOverlay(this.thumb, {y: this.y}); -Panel = function(x, y) { + if (this.widget != null) { + this.widget.moveDown(); + } - this.x = x; - this.y = y; - this.nextY = y; + } - this.widgetX = x + textWidth + valueWidth; + this.CollapsablePanelItem = CollapsablePanelItem; + + var PanelItem = function (name, setter, getter, displayer, x, y, textWidth, valueWidth, height) { + //print("creating panel item: " + name); + this.isCollapsable = false; + this.name = name; + this.y = y; + this.isCollapsed = false; + + this.displayer = typeof displayer !== 'undefined' ? displayer : function(value) { + if(value == true) { + return "On"; + } else if (value == false) { + return "Off"; + } + return value.toFixed(2); + }; + + var topMargin = (height - 1.5 * textFontSize); + this.title = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: x, + y: y, + width: textWidth, + height: height, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true, + text: " " + name, + font: {size: textFontSize}, + topMargin: topMargin + }); + + this.value = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: x + textWidth, + y: y, + width: valueWidth, + height: height, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true, + text: this.displayer(getter()), + font: {size: textFontSize}, + topMargin: topMargin + }); + + this.getter = getter; + this.resetValue = getter(); + + this.setter = function(value) { + + setter(value); - this.items = new Array(); - this.activeWidget = null; + Overlays.editOverlay(this.value, {text: this.displayer(getter())}); - this.mouseMoveEvent = function(event) { + if (this.widget) { + this.widget.setValue(value); + } + + //print("successfully set value of widget to " + value); + }; + this.setterFromWidget = function(value) { + setter(value); + // ANd loop back the value after the final setter has been called + var value = getter(); + + if (this.widget) { + this.widget.setValue(value); + } + Overlays.editOverlay(this.value, {text: this.displayer(value)}); + }; + + this.widget = null; + }; + + PanelItem.prototype.hide = function() { + Overlays.editOverlay(this.title, {visible: false}); + Overlays.editOverlay(this.value, {visible: false}); + + if (this.widget != null) { + this.widget.hide(); + } + }; + + + PanelItem.prototype.show = function() { + Overlays.editOverlay(this.title, {visible: true}); + Overlays.editOverlay(this.value, {visible: true}); + + if (this.widget != null) { + this.widget.show(); + } + + }; + + PanelItem.prototype.moveUp = function(newY) { + + Overlays.editOverlay(this.title, {y: newY}); + Overlays.editOverlay(this.value, {y: newY}); + + if (this.widget != null) { + this.widget.moveUp(newY); + } + + }; + + PanelItem.prototype.moveDown = function() { + + Overlays.editOverlay(this.title, {y: this.y}); + Overlays.editOverlay(this.value, {y: this.y}); + + if (this.widget != null) { + this.widget.moveDown(); + } + + }; + + PanelItem.prototype.destroy = function() { + Overlays.deleteOverlay(this.title); + Overlays.deleteOverlay(this.value); + + if (this.widget != null) { + this.widget.destroy(); + } + }; + this.PanelItem = PanelItem; + + var textWidth = 180; + var valueWidth = 100; + var widgetWidth = 300; + var rawHeight = 20; + var rawYDelta = rawHeight * 1.5; + + var Panel = function(x, y) { + + this.x = x; + this.y = y; + + this.nextY = y; print("creating panel at x: " + this.x + " y: " + this.y); + + this.widgetX = x + textWidth + valueWidth; + + this.items = new Array(); + this.activeWidget = null; + this.visible = true; + this.indentation = 30; + + }; + + Panel.prototype.mouseMoveEvent = function(event) { if (this.activeWidget) { this.activeWidget.onMouseMoveEvent(event); } }; - - this.mousePressEvent = function(event) { + + Panel.prototype.mousePressEvent = function(event) { // Make sure we quitted previous widget if (this.activeWidget) { this.activeWidget.onMouseReleaseEvent(event); } this.activeWidget = null; - + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - + this.handleCollapse(clickedOverlay); + // If the user clicked any of the slider background then... for (var i in this.items) { + var item = this.items[i]; var widget = this.items[i].widget; - + if (widget.isClickableOverlayItem(clickedOverlay)) { this.activeWidget = widget; this.activeWidget.onMousePressEvent(event, clickedOverlay); - break; - } + + } } }; - - // Reset panel item upon double-clicking - this.mouseDoublePressEvent = function(event) { - + + // Reset panel item upon double-clicking + Panel.prototype.mouseDoublePressEvent = function(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + this.handleReset(clickedOverlay); + } + + Panel.prototype.handleReset = function (clickedOverlay) { for (var i in this.items) { - + var item = this.items[i]; var widget = item.widget; + + if (item.isSubPanel && widget) { + widget.handleReset(clickedOverlay); + } if (clickedOverlay == item.title) { item.activeWidget = widget; - + item.activeWidget.reset(item.resetValue); break; } - } - } + } + }; - this.mouseReleaseEvent = function(event) { + Panel.prototype.handleCollapse = function (clickedOverlay) { + + for (var i in this.items) { + + var item = this.items[i]; + var widget = item.widget; + + if (item.isSubPanel && widget) { + widget.handleCollapse(clickedOverlay); + } + + if (!item.isCollapsed && item.isCollapsable && clickedOverlay == item.thumb) { + this.collapse(clickedOverlay); + item.isCollapsed = true; + break; + } else if (item.isCollapsed && item.isCollapsable && clickedOverlay == item.thumb) { + this.expand(clickedOverlay); + item.isCollapsed = false; + } + } + }; + + Panel.prototype.collapse = function (clickedOverlay) { + var keys = Object.keys(this.items); + + for (var i = 0; i < keys.length; ++i) { + var item = this.items[keys[i]]; + + if(item.isCollapsable && clickedOverlay == item.thumb) { + var panel = item.widget; + panel.hide(); + break; + } + + } + + // Now recalculate new heights of subsequent widgets + for(var j = i + 1; j < keys.length; ++j) { + + this.items[keys[j]].moveUp(this.getCurrentY(keys[j])); + + } + + }; + + + Panel.prototype.expand = function (clickedOverlay) { + var keys = Object.keys(this.items); + + for (var i = 0; i < keys.length; ++i) { + var item = this.items[keys[i]]; + + if(item.isCollapsable && clickedOverlay == item.thumb) { + var panel = item.widget; + panel.show(); + break; + } + + } + + // Now recalculate new heights of subsequent widgets + for(var j = i + 1; j < keys.length; ++j) { + this.items[keys[j]].moveDown(); + } + + }; + + + Panel.prototype.mouseReleaseEvent = function(event) { if (this.activeWidget) { this.activeWidget.onMouseReleaseEvent(event); } this.activeWidget = null; }; - - this.onMousePressEvent = function(event, clickedOverlay) { + + Panel.prototype.onMousePressEvent = function(event, clickedOverlay) { for (var i in this.items) { var item = this.items[i]; if(item.widget.isClickableOverlayItem(clickedOverlay)) { @@ -674,27 +936,19 @@ Panel = function(x, y) { item.activeWidget.onMousePressEvent(event,clickedOverlay); } } - } - - this.reset = function() { - for (var i in this.items) { - var item = this.items[i]; - if (item.activeWidget) { - item.activeWidget.reset(item.resetValue); - } - } - } - - this.onMouseMoveEvent = function(event) { + }; + + + Panel.prototype.onMouseMoveEvent = function(event) { for (var i in this.items) { var item = this.items[i]; if (item.activeWidget) { item.activeWidget.onMouseMoveEvent(event); } } - } - - this.onMouseReleaseEvent = function(event, clickedOverlay) { + }; + + Panel.prototype.onMouseReleaseEvent = function(event, clickedOverlay) { for (var i in this.items) { var item = this.items[i]; if (item.activeWidget) { @@ -702,47 +956,46 @@ Panel = function(x, y) { } item.activeWidget = null; } - } - - this.onMouseDoublePressEvent = function(event, clickedOverlay) { - + }; + + Panel.prototype.onMouseDoublePressEvent = function(event, clickedOverlay) { for (var i in this.items) { var item = this.items[i]; if (item.activeWidget) { item.activeWidget.onMouseDoublePressEvent(event); } } - } - - this.newSlider = function(name, minValue, maxValue, setValue, getValue, displayValue) { + }; + + Panel.prototype.newSlider = function(name, minValue, maxValue, setValue, getValue, displayValue) { this.nextY = this.y + this.getHeight(); - var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); var slider = new Slider(this.widgetX, this.nextY, widgetWidth, rawHeight); slider.minValue = minValue; slider.maxValue = maxValue; - + item.widget = slider; item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; item.setter(getValue()); this.items[name] = item; - this.nextY += rawYDelta; - }; - this.newCheckbox = function(name, setValue, getValue, displayValue) { + }; + + Panel.prototype.newCheckbox = function(name, setValue, getValue, displayValue) { var display; if (displayValue == true) { display = function() {return "On";}; } else if (displayValue == false) { display = function() {return "Off";}; } - + this.nextY = this.y + this.getHeight(); - + var item = new PanelItem(name, setValue, getValue, display, this.x, this.nextY, textWidth, valueWidth, rawHeight); - + var checkbox = new Checkbox(this.widgetX, this.nextY, widgetWidth, rawHeight); - + item.widget = checkbox; item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; item.setter(getValue()); @@ -750,136 +1003,180 @@ Panel = function(x, y) { //print("created Item... checkbox=" + name); }; - - this.newColorBox = function(name, setValue, getValue, displayValue) { + + Panel.prototype.newColorBox = function(name, setValue, getValue, displayValue) { this.nextY = this.y + this.getHeight(); - + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); - + var colorBox = new ColorBox(this.widgetX, this.nextY, widgetWidth, rawHeight); - + item.widget = colorBox; item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; item.setter(getValue()); this.items[name] = item; - this.nextY += rawYDelta; + // print("created Item... colorBox=" + name); }; - -<<<<<<< Updated upstream - this.newDirectionBox = function(name, setValue, getValue, displayValue) { -======= - this.newDirectionBox= function(name, setValue, getValue, displayValue) { + + Panel.prototype.newDirectionBox = function(name, setValue, getValue, displayValue) { this.nextY = this.y + this.getHeight(); ->>>>>>> Stashed changes - + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); var directionBox = new DirectionBox(this.widgetX, this.nextY, widgetWidth, rawHeight); - + item.widget = directionBox; item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; item.setter(getValue()); this.items[name] = item; - this.nextY += rawYDelta; + // print("created Item... directionBox=" + name); }; - -<<<<<<< Updated upstream - this.newSubPanel = function(name) { - var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); - - var panel = new Panel(this.widgetX, this.nextY); - - item.widget = panel; - - item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; + - this.nextY += rawYDelta; - - }; - -======= - var indentation = 30; - - this.newSubPanel = function(name) { + + Panel.prototype.newSubPanel = function(name) { //TODO: make collapsable, fix double-press event this.nextY = this.y + this.getHeight(); - + var item = new CollapsablePanelItem(name, this.x, this.nextY, textWidth, rawHeight, panel); item.isSubPanel = true; + + this.nextY += 1.5 * item.height; + + var subPanel = new Panel(this.x + this.indentation, this.nextY); - this.nextY += 1.5 * item.height; - - var subPanel = new Panel(this.x + indentation, this.nextY); - item.widget = subPanel; this.items[name] = item; return subPanel; // print("created Item... subPanel=" + name); }; - - this.onValueChanged = function(value) { + + Panel.prototype.onValueChanged = function(value) { for (var i in this.items) { this.items[i].widget.onValueChanged(value); } - } ->>>>>>> Stashed changes - - this.destroy = function() { - for (var i in this.items) { - this.items[i].destroy(); - } - } - - - this.set = function(name, value) { + }; + + + Panel.prototype.set = function(name, value) { var item = this.items[name]; if (item != null) { return item.setter(value); } return null; - } - - this.get = function(name) { + }; + + Panel.prototype.get = function(name) { var item = this.items[name]; if (item != null) { return item.getter(); } return null; - } - - this.update = function(name) { + }; + + Panel.prototype.update = function(name) { var item = this.items[name]; if (item != null) { return item.setter(item.getter()); } return null; - } - - this.isClickableOverlayItem = function(item) { + }; + + Panel.prototype.isClickableOverlayItem = function(item) { for (var i in this.items) { if (this.items[i].widget.isClickableOverlayItem(item)) { return true; } } return false; - } - - this.getHeight = function() { + }; + + Panel.prototype.getHeight = function(show) { var height = 0; - + for (var i in this.items) { + height += this.items[i].widget.getHeight(); - if(this.items[i].isSubPanel) { + // if(show) { + // print("widget: " + i + " height: " + this.items[i].widget.getHeight()); + + // } + if(this.items[i].isSubPanel && this.items[i].widget.visible) { + height += 1.5 * rawHeight; - } + + } + } - return height; - } + }; -}; + Panel.prototype.moveUp = function() { + for (var i in this.items) { + this.items[i].widget.moveUp(); + } + + }; + + Panel.prototype.moveDown = function() { + for (var i in this.items) { + this.items[i].widget.moveDown(); + } + }; + + Panel.prototype.getCurrentY = function(key) { + var height = 0; + var keys = Object.keys(this.items); + + for (var i = 0; i < keys.indexOf(key); ++i) { + var item = this.items[keys[i]]; + + height += item.widget.getHeight(); + + if(item.isSubPanel) { + height += 1.5 * rawHeight; + + } + } + + return this.y + height; + }; + + + Panel.prototype.hide = function() { + for (var i in this.items) { + if(this.items[i].isSubPanel) { + this.items[i].widget.hide(); + } + this.items[i].hide(); + } + this.visible = false; + }; + + Panel.prototype.show = function() { + for (var i in this.items) { + if(this.items[i].isSubPanel) { + this.items[i].widget.show(); + } + this.items[i].show(); + } + this.visible = true; + }; + Panel.prototype.destroy = function() { + for (var i in this.items) { + + if(this.items[i].isSubPanel) { + this.items[i].widget.destroy(); + } + this.items[i].destroy(); + } + }; + + + this.Panel = Panel; +})(); \ No newline at end of file From b7d195e8173360ebb45fc1d9e7a771fc030a245c Mon Sep 17 00:00:00 2001 From: bwent Date: Mon, 27 Jul 2015 13:56:25 -0700 Subject: [PATCH 083/129] more subpanel fixes --- examples/utilities/tools/cookies.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index 9d064385bf..44017c66da 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -888,10 +888,10 @@ } } + // Now recalculate new heights of subsequent widgets for(var j = i + 1; j < keys.length; ++j) { - this.items[keys[j]].moveUp(this.getCurrentY(keys[j])); } From 774b4851c323f5adec20173a45f9aa3474edb9fe Mon Sep 17 00:00:00 2001 From: bwent Date: Tue, 28 Jul 2015 12:18:26 -0700 Subject: [PATCH 084/129] Add tab to highlight widgets and update using left and right arrow keys --- examples/utilities/tools/cookies.js | 453 +++++++++++++++++----------- 1 file changed, 282 insertions(+), 171 deletions(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index 44017c66da..b2dc8c1da7 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -9,6 +9,26 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + +HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + +var SCALE = 1000; +var THUMB_COLOR = { + red: 150, + green: 150, + blue: 150 +}; +var THUMB_HIGHLIGHT = { + red: 255, + green: 255, + blue: 255 +}; +var CHECK_MARK_COLOR = { + red: 70, + green: 70, + blue: 90 +}; + // The Slider class (function () { var Slider = function(x,y,width,thumbSize) { @@ -24,7 +44,7 @@ visible: true }); this.thumb = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, + backgroundColor: THUMB_COLOR, x: x, y: y, width: thumbSize, @@ -61,6 +81,25 @@ return (item == this.thumb) || (item == this.background); }; + + Slider.prototype.onMousePressEvent = function(event, clickedOverlay) { + if (!this.isClickableOverlayItem(clickedOverlay)) { + this.isMoving = false; + return; + } + this.highlight(); + this.isMoving = true; + var clickOffset = event.x - this.thumbX; + if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { + this.clickOffsetX = clickOffset; + } else { + this.clickOffsetX = 0; + this.thumbX = event.x; + this.updateThumb(); + this.onValueChanged(this.getValue()); + } + }; + Slider.prototype.onMouseMoveEvent = function(event) { if (this.isMoving) { var newThumbX = event.x - this.clickOffsetX; @@ -76,34 +115,43 @@ } }; - Slider.prototype.onMousePressEvent = function(event, clickedOverlay) { - if (!this.isClickableOverlayItem(clickedOverlay)) { - this.isMoving = false; - return; - } - this.isMoving = true; - var clickOffset = event.x - this.thumbX; - if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { - this.clickOffsetX = clickOffset; - } else { - this.clickOffsetX = 0; - this.thumbX = event.x; - this.updateThumb(); - this.onValueChanged(this.getValue()); - } - - }; - Slider.prototype.onMouseReleaseEvent = function(event) { this.isMoving = false; + this.unhighlight(); }; - - // Public members: + + Slider.prototype.updateWithKeys = function(direction) { + this.range = this.maxThumbX - this.minThumbX; + this.thumbX += direction * (this.range / SCALE); + this.updateThumb(); + this.onValueChanged(this.getValue()); + }; + + Slider.prototype.highlight = function() { + if(this.highlighted) { + return; + } + Overlays.editOverlay(this.thumb, { + backgroundColor: {red: 255, green: 255, blue: 255} + }); + this.highlighted = true; + }; + + Slider.prototype.unhighlight = function() { + if(!this.highlighted) { + return; + } + Overlays.editOverlay(this.thumb, { + backgroundColor: THUMB_COLOR + }); + this.highlighted = false; + }; + Slider.prototype.setNormalizedValue = function(value) { if (value < 0.0) { this.thumbX = this.minThumbX; } else if (value > 1.0) { - this.thumbX = this.maxThumbX; + this.thumbX = this.maxThsumbX; } else { this.thumbX = value * (this.maxThumbX - this.minThumbX) + this.minThumbX; } @@ -117,16 +165,17 @@ var normValue = (value - this.minValue) / (this.maxValue - this.minValue); this.setNormalizedValue(normValue); }; + Slider.prototype.getValue = function() { + return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; + }; Slider.prototype.reset = function(resetValue) { this.setValue(resetValue); this.onValueChanged(resetValue); }; - Slider.prototype.getValue = function() { - return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; - }; - + Slider.prototype.onValueChanged = function(value) {}; + Slider.prototype.getHeight = function() { if(!this.visible) { return 0; @@ -143,8 +192,6 @@ Overlays.editOverlay(this.background, {y: this.y}); Overlays.editOverlay(this.thumb, {y: this.y}); }; - - Slider.prototype.onValueChanged = function(value) {}; Slider.prototype.hide = function() { Overlays.editOverlay(this.background, {visible: false}); @@ -157,36 +204,19 @@ Overlays.editOverlay(this.thumb, {visible: true}); this.visible = true; }; - + Slider.prototype.destroy = function() { Overlays.deleteOverlay(this.background); Overlays.deleteOverlay(this.thumb); }; - - Slider.prototype.setThumbColor = function(color) { - Overlays.editOverlay(this.thumb, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); - }; - Slider.prototype.setBackgroundColor = function(color) { - Overlays.editOverlay(this.background, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); - }; + this.Slider = Slider; // The Checkbox class var Checkbox = function(x,y,width,thumbSize) { - this.background = Overlays.addOverlay("text", { - backgroundColor: { red: 125, green: 125, blue: 255 }, - x: x, - y: y, - width: width, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true - }); - this.thumb = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, + backgroundColor: THUMB_COLOR, textFontSize: 10, x: x, y: y, @@ -208,64 +238,72 @@ this.checkMark = Overlays.addOverlay("text", { - backgroundColor: { red: 0, green: 255, blue: 0 }, + backgroundColor: CHECK_MARK_COLOR, x: checkX, y: checkY, width: thumbSize / 2.0, height: thumbSize / 2.0, alpha: 1.0, visible: true - }); - - this.unCheckMark = Overlays.addOverlay("image", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: checkX + 1.0, - y: checkY + 1.0, - width: thumbSize / 2.5, - height: thumbSize / 2.5, - alpha: 1.0, - visible: false - }); + }); }; Checkbox.prototype.updateThumb = function() { - - Overlays.editOverlay(this.unCheckMark, { visible: !this.boxCheckStatus }); - + Overlays.editOverlay(this.checkMark, { visible: this.boxCheckStatus }); }; Checkbox.prototype.isClickableOverlayItem = function(item) { - return (item == this.thumb) || (item == this.checkMark) || (item == this.unCheckMark); + return (item == this.thumb) || (item == this.checkMark); }; Checkbox.prototype.onMousePressEvent = function(event, clickedOverlay) { - if (!this.isClickableOverlayItem(clickedOverlay)) { return; - } - + } this.boxCheckStatus = !this.boxCheckStatus; this.onValueChanged(this.getValue()); this.updateThumb(); }; - - Checkbox.prototype.onMouseReleaseEvent = function(event) { }; - - - // Public members: + Checkbox.prototype.onMouseReleaseEvent = function(event) {}; + + Checkbox.prototype.updateWithKeys = function() { + this.boxCheckStatus = !this.boxCheckStatus; + this.onValueChanged(this.getValue()); + this.updateThumb(); + }; + + Checkbox.prototype.highlight = function() { + Overlays.editOverlay(this.thumb, { + backgroundColor: THUMB_HIGHLIGHT + }); + this.highlighted = true; + }; + + Checkbox.prototype.unhighlight = function() { + Overlays.editOverlay(this.thumb, { + backgroundColor: THUMB_COLOR + }); + this.highlighted = false; + }; Checkbox.prototype.setValue = function(value) { this.boxCheckStatus = value; }; + + Checkbox.prototype.setterFromWidget = function(value) { + this.updateThumb(); + }; + + Checkbox.prototype.getValue = function() { + return this.boxCheckStatus; + }; Checkbox.prototype.reset = function(resetValue) { this.setValue(resetValue); }; - - Checkbox.prototype.getValue = function() { - return this.boxCheckStatus; - }; + + Checkbox.prototype.onValueChanged = function(value) { }; Checkbox.prototype.getHeight = function() { if(!this.visible) { @@ -287,12 +325,6 @@ Overlays.editOverlay(this.checkMark, {y: this.y}); Overlays.editOverlay(this.unCheckMark, {y: this.y}); }; - - Checkbox.prototype.setterFromWidget = function(value) { - this.updateThumb(); - }; - - Checkbox.prototype.onValueChanged = function(value) { }; Checkbox.prototype.hide = function() { Overlays.editOverlay(this.background, {visible: false}); @@ -316,13 +348,7 @@ Overlays.deleteOverlay(this.checkMark); Overlays.deleteOverlay(this.unCheckMark); }; - - Checkbox.prototype.setThumbColor = function(color) { - Overlays.editOverlay(this.thumb, { red: 255, green: 255, blue: 255 } ); - }; - Checkbox.prototype.setBackgroundColor = function(color) { - Overlays.editOverlay(this.background, { red: 125, green: 125, blue: 255 }); - }; + this.Checkbox = Checkbox; // The ColorBox class @@ -351,12 +377,6 @@ || this.blue.isClickableOverlayItem(item); }; - ColorBox.prototype.onMouseMoveEvent = function(event) { - this.red.onMouseMoveEvent(event); - this.green.onMouseMoveEvent(event); - this.blue.onMouseMoveEvent(event); - }; - ColorBox.prototype.onMousePressEvent = function(event, clickedOverlay) { this.red.onMousePressEvent(event, clickedOverlay); if (this.red.isMoving) { @@ -370,19 +390,48 @@ this.blue.onMousePressEvent(event, clickedOverlay); }; - + + ColorBox.prototype.onMouseMoveEvent = function(event) { + this.red.onMouseMoveEvent(event); + this.green.onMouseMoveEvent(event); + this.blue.onMouseMoveEvent(event); + }; ColorBox.prototype.onMouseReleaseEvent = function(event) { this.red.onMouseReleaseEvent(event); this.green.onMouseReleaseEvent(event); this.blue.onMouseReleaseEvent(event); }; - + + ColorBox.prototype.updateWithKeys = function(direction) { + this.red.updateWithKeys(direction); + this.green.updateWithKeys(direction); + this.blue.updateWithKeys(direction); + } + + ColorBox.prototype.highlight = function() { + this.red.highlight(); + this.green.highlight(); + this.blue.highlight(); + + this.highlighted = true; + }; + + ColorBox.prototype.unhighlight = function() { + this.red.unhighlight(); + this.green.unhighlight(); + this.blue.unhighlight(); + + this.highlighted = false; + }; + ColorBox.prototype.setterFromWidget = function(value) { var color = this.getValue(); this.onValueChanged(color); this.updateRGBSliders(color); }; + + ColorBox.prototype.onValueChanged = function(value) {}; ColorBox.prototype.updateRGBSliders = function(color) { this.red.setThumbColor({x: color.x, y: 0, z: 0}); @@ -397,17 +446,18 @@ this.blue.setValue(value.z); this.updateRGBSliders(value); }; - - ColorBox.prototype.reset = function(resetValue) { - this.setValue(resetValue); - this.onValueChanged(resetValue); - }; - + ColorBox.prototype.getValue = function() { var value = {x:this.red.getValue(), y:this.green.getValue(),z:this.blue.getValue()}; return value; }; - + + ColorBox.prototype.reset = function(resetValue) { + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; + + ColorBox.prototype.getHeight = function() { if(!this.visible) { return 0; @@ -446,8 +496,7 @@ this.green.destroy(); this.blue.destroy(); }; - - ColorBox.prototype.onValueChanged = function(value) {}; + this.ColorBox = ColorBox; // The DirectionBox class @@ -479,11 +528,6 @@ || this.pitch.isClickableOverlayItem(item); }; - DirectionBox.prototype.onMouseMoveEvent = function(event) { - this.yaw.onMouseMoveEvent(event); - this.pitch.onMouseMoveEvent(event); - }; - DirectionBox.prototype.onMousePressEvent = function(event, clickedOverlay) { this.yaw.onMousePressEvent(event, clickedOverlay); if (this.yaw.isMoving) { @@ -491,18 +535,43 @@ } this.pitch.onMousePressEvent(event, clickedOverlay); }; + + DirectionBox.prototype.onMouseMoveEvent = function(event) { + this.yaw.onMouseMoveEvent(event); + this.pitch.onMouseMoveEvent(event); + }; DirectionBox.prototype.onMouseReleaseEvent = function(event) { this.yaw.onMouseReleaseEvent(event); this.pitch.onMouseReleaseEvent(event); }; + + DirectionBox.prototype.updateWithKeys = function(direction) { + this.yaw.updateWithKeys(direction); + this.pitch.updateWithKeys(direction); + }; + + DirectionBox.prototype.highlight = function() { + this.pitch.highlight(); + this.yaw.highlight(); + + this.highlighted = true; + }; + + DirectionBox.prototype.unhighlight = function() { + this.pitch.unhighlight(); + this.yaw.unhighlight(); + + this.highlighted = false; + }; DirectionBox.prototype.setterFromWidget = function(value) { var yawPitch = this.getValue(); this.onValueChanged(yawPitch); }; - - // Public members: + + DirectionBox.prototype.onValueChanged = function(value) {}; + DirectionBox.prototype.setValue = function(direction) { var flatXZ = Math.sqrt(direction.x * direction.x + direction.z * direction.z); if (flatXZ > 0.0) { @@ -516,13 +585,8 @@ } this.pitch.setValue(direction.y); }; - - DirectionBox.prototype.reset = function(resetValue) { - this.setValue(resetValue); - this.onValueChanged(resetValue); - }; - - DirectionBox.prototype.getValue = function() { + + DirectionBox.prototype.getValue = function() { var dirZ = this.pitch.getValue(); var yaw = this.yaw.getValue() * Math.PI / 180; var cosY = Math.sqrt(1 - dirZ*dirZ); @@ -530,6 +594,11 @@ return value; }; + DirectionBox.prototype.reset = function(resetValue) { + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; + DirectionBox.prototype.getHeight = function() { if(!this.visible) { return 0; @@ -564,7 +633,6 @@ this.pitch.destroy(); }; - DirectionBox.prototype.onValueChanged = function(value) {}; this.DirectionBox = DirectionBox; var textFontSize = 12; @@ -577,15 +645,14 @@ var topMargin = (height - 1.5 * textFontSize); - this.thumb = Overlays.addOverlay("text", { - backgroundColor: { red: 220, green: 220, blue: 220 }, - textFontSize: 10, + this.thumb = Overlays.addOverlay("image", { + color: {red: 255, green: 255, blue: 255}, + imageURL: HIFI_PUBLIC_BUCKET + 'images/tools/min-max-toggle.svg', x: x, y: y, width: rawHeight, height: rawHeight, alpha: 1.0, - backgroundAlpha: 1.0, visible: true }); @@ -644,13 +711,12 @@ if (this.widget != null) { this.widget.moveDown(); } - } - this.CollapsablePanelItem = CollapsablePanelItem; var PanelItem = function (name, setter, getter, displayer, x, y, textWidth, valueWidth, height) { //print("creating panel item: " + name); + this.isCollapsable = false; this.name = name; this.y = y; @@ -780,14 +846,23 @@ var widgetWidth = 300; var rawHeight = 20; var rawYDelta = rawHeight * 1.5; + var outerPanel = true; + var widgets; + var Panel = function(x, y) { - + + if (outerPanel) { + widgets = []; + } + outerPanel = false; + this.x = x; this.y = y; + this.nextY = y; - this.nextY = y; print("creating panel at x: " + this.x + " y: " + this.y); - + print("creating panel at x: " + this.x + " y: " + this.y); + this.widgetX = x + textWidth + valueWidth; this.items = new Array(); @@ -826,12 +901,20 @@ } } }; + + Panel.prototype.mouseReleaseEvent = function(event) { + if (this.activeWidget) { + this.activeWidget.onMouseReleaseEvent(event); + } + this.activeWidget = null; + }; // Reset panel item upon double-clicking Panel.prototype.mouseDoublePressEvent = function(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); this.handleReset(clickedOverlay); - } + }; + Panel.prototype.handleReset = function (clickedOverlay) { for (var i in this.items) { @@ -845,16 +928,13 @@ if (clickedOverlay == item.title) { item.activeWidget = widget; - item.activeWidget.reset(item.resetValue); - break; } } }; Panel.prototype.handleCollapse = function (clickedOverlay) { - for (var i in this.items) { var item = this.items[i]; @@ -886,19 +966,14 @@ panel.hide(); break; } - } - // Now recalculate new heights of subsequent widgets for(var j = i + 1; j < keys.length; ++j) { this.items[keys[j]].moveUp(this.getCurrentY(keys[j])); - } - }; - Panel.prototype.expand = function (clickedOverlay) { var keys = Object.keys(this.items); @@ -910,23 +985,13 @@ panel.show(); break; } - - } - - // Now recalculate new heights of subsequent widgets + } + // Now recalculate new heights of subsequent widgets for(var j = i + 1; j < keys.length; ++j) { this.items[keys[j]].moveDown(); } + }; - }; - - - Panel.prototype.mouseReleaseEvent = function(event) { - if (this.activeWidget) { - this.activeWidget.onMouseReleaseEvent(event); - } - this.activeWidget = null; - }; Panel.prototype.onMousePressEvent = function(event, clickedOverlay) { for (var i in this.items) { @@ -938,7 +1003,6 @@ } }; - Panel.prototype.onMouseMoveEvent = function(event) { for (var i in this.items) { var item = this.items[i]; @@ -966,7 +1030,63 @@ } } }; - + + var tabView = false; + var tabIndex = 0; + + Panel.prototype.keyPressEvent = function(event) { + if(event.text == "TAB" && !event.isShifted) { + tabView = true; + if(tabIndex < widgets.length) { + if(tabIndex > 0 && widgets[tabIndex - 1].highlighted) { + // Unhighlight previous widget + widgets[tabIndex - 1].unhighlight(); + } + widgets[tabIndex].highlight(); + tabIndex++; + } else { + widgets[tabIndex - 1].unhighlight(); + //Wrap around to front + tabIndex = 0; + widgets[tabIndex].highlight(); + tabIndex++; + } + } else if (tabView && event.isShifted) { + if(tabIndex > 0) { + tabIndex--; + if(tabIndex < widgets.length && widgets[tabIndex + 1].highlighted) { + // Unhighlight previous widget + widgets[tabIndex + 1].unhighlight(); + } + widgets[tabIndex].highlight(); + } else { + widgets[tabIndex].unhighlight(); + //Wrap around to end + tabIndex = widgets.length - 1; + widgets[tabIndex].highlight(); + } + } else if (event.text == "LEFT") { + for(var i = 0; i < widgets.length; i++) { + // Find the highlighted widget, allow control with arrow keys + if(widgets[i].highlighted) { + var k = -1; + widgets[i].updateWithKeys(k); + break; + } + } + } else if (event.text == "RIGHT") { + for(var i = 0; i < widgets.length; i++) { + // Find the highlighted widget, allow control with arrow keys + if(widgets[i].highlighted) { + var k = 1; + widgets[i].updateWithKeys(k); + break; + } + } + } + }; + + // Widget constructors Panel.prototype.newSlider = function(name, minValue, maxValue, setValue, getValue, displayValue) { this.nextY = this.y + this.getHeight(); @@ -974,6 +1094,7 @@ var slider = new Slider(this.widgetX, this.nextY, widgetWidth, rawHeight); slider.minValue = minValue; slider.maxValue = maxValue; + widgets.push(slider); item.widget = slider; item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; @@ -995,6 +1116,7 @@ var item = new PanelItem(name, setValue, getValue, display, this.x, this.nextY, textWidth, valueWidth, rawHeight); var checkbox = new Checkbox(this.widgetX, this.nextY, widgetWidth, rawHeight); + widgets.push(checkbox); item.widget = checkbox; item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; @@ -1010,6 +1132,7 @@ var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); var colorBox = new ColorBox(this.widgetX, this.nextY, widgetWidth, rawHeight); + widgets.push(colorBox); item.widget = colorBox; item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; @@ -1025,6 +1148,7 @@ var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); var directionBox = new DirectionBox(this.widgetX, this.nextY, widgetWidth, rawHeight); + widgets.push(directionBox); item.widget = directionBox; item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; @@ -1034,10 +1158,8 @@ // print("created Item... directionBox=" + name); }; - - Panel.prototype.newSubPanel = function(name) { - //TODO: make collapsable, fix double-press event + this.nextY = this.y + this.getHeight(); var item = new CollapsablePanelItem(name, this.x, this.nextY, textWidth, rawHeight, panel); @@ -1093,22 +1215,14 @@ return false; }; - Panel.prototype.getHeight = function(show) { + Panel.prototype.getHeight = function() { var height = 0; for (var i in this.items) { - height += this.items[i].widget.getHeight(); - // if(show) { - // print("widget: " + i + " height: " + this.items[i].widget.getHeight()); - - // } if(this.items[i].isSubPanel && this.items[i].widget.visible) { - - height += 1.5 * rawHeight; - - } - + height += 1.5 * rawHeight; + } } return height; @@ -1118,7 +1232,6 @@ for (var i in this.items) { this.items[i].widget.moveUp(); } - }; Panel.prototype.moveDown = function() { @@ -1141,7 +1254,6 @@ } } - return this.y + height; }; @@ -1177,6 +1289,5 @@ } }; - this.Panel = Panel; })(); \ No newline at end of file From d9693796bc06a77eb38c1c7fede2eb26d077f3c9 Mon Sep 17 00:00:00 2001 From: bwent Date: Tue, 28 Jul 2015 12:27:37 -0700 Subject: [PATCH 085/129] Capture key events --- examples/utilities/tools/cookies.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index b2dc8c1da7..175d8c2393 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -1288,6 +1288,15 @@ var CHECK_MARK_COLOR = { this.items[i].destroy(); } }; - this.Panel = Panel; -})(); \ No newline at end of file +})(); + + +Script.scriptEnding.connect(function scriptEnding() { + Controller.releaseKeyEvents({text: "left"}); + Controller.releaseKeyEvents({key: "right"}); +}); + + +Controller.captureKeyEvents({text: "left"}); +Controller.captureKeyEvents({text: "right"}); \ No newline at end of file From 2be95997d16ed572aac938af45393f8b8fbcfad1 Mon Sep 17 00:00:00 2001 From: bwent Date: Tue, 28 Jul 2015 12:32:14 -0700 Subject: [PATCH 086/129] clean up formatting --- examples/utilities/tools/cookies.js | 1317 +++++++++++++++------------ 1 file changed, 749 insertions(+), 568 deletions(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index 175d8c2393..24cda69ba2 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -30,204 +30,230 @@ var CHECK_MARK_COLOR = { }; // The Slider class -(function () { - var Slider = function(x,y,width,thumbSize) { - +(function() { + var Slider = function(x, y, width, thumbSize) { + this.background = Overlays.addOverlay("text", { - backgroundColor: { red: 200, green: 200, blue: 255 }, - x: x, - y: y, - width: width, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true - }); + backgroundColor: { + red: 200, + green: 200, + blue: 255 + }, + x: x, + y: y, + width: width, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true + }); this.thumb = Overlays.addOverlay("text", { - backgroundColor: THUMB_COLOR, - x: x, - y: y, - width: thumbSize, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); - + backgroundColor: THUMB_COLOR, + x: x, + y: y, + width: thumbSize, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); + this.thumbSize = thumbSize; - + this.thumbHalfSize = 0.5 * thumbSize; - + this.minThumbX = x + this.thumbHalfSize; this.maxThumbX = x + width - this.thumbHalfSize; this.thumbX = this.minThumbX; - + this.minValue = 0.0; this.maxValue = 1.0; this.y = y; - + this.clickOffsetX = 0; this.isMoving = false; this.visible = true; }; - - Slider.prototype.updateThumb = function() { - var thumbTruePos = this.thumbX - 0.5 * this.thumbSize; - Overlays.editOverlay(this.thumb, { x: thumbTruePos } ); - }; - - Slider.prototype.isClickableOverlayItem = function(item) { - return (item == this.thumb) || (item == this.background); - }; - - - Slider.prototype.onMousePressEvent = function(event, clickedOverlay) { - if (!this.isClickableOverlayItem(clickedOverlay)) { - this.isMoving = false; - return; - } - this.highlight(); - this.isMoving = true; - var clickOffset = event.x - this.thumbX; - if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { - this.clickOffsetX = clickOffset; - } else { - this.clickOffsetX = 0; - this.thumbX = event.x; - this.updateThumb(); - this.onValueChanged(this.getValue()); - } - }; - Slider.prototype.onMouseMoveEvent = function(event) { - if (this.isMoving) { - var newThumbX = event.x - this.clickOffsetX; - if (newThumbX < this.minThumbX) { - newThumbX = this.minThumbX; - } - if (newThumbX > this.maxThumbX) { - newThumbX = this.maxThumbX; - } - this.thumbX = newThumbX; - this.updateThumb(); - this.onValueChanged(this.getValue()); - } - }; - - Slider.prototype.onMouseReleaseEvent = function(event) { + Slider.prototype.updateThumb = function() { + var thumbTruePos = this.thumbX - 0.5 * this.thumbSize; + Overlays.editOverlay(this.thumb, { + x: thumbTruePos + }); + }; + + Slider.prototype.isClickableOverlayItem = function(item) { + return (item == this.thumb) || (item == this.background); + }; + + + Slider.prototype.onMousePressEvent = function(event, clickedOverlay) { + if (!this.isClickableOverlayItem(clickedOverlay)) { this.isMoving = false; - this.unhighlight(); - }; + return; + } + this.highlight(); + this.isMoving = true; + var clickOffset = event.x - this.thumbX; + if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { + this.clickOffsetX = clickOffset; + } else { + this.clickOffsetX = 0; + this.thumbX = event.x; + this.updateThumb(); + this.onValueChanged(this.getValue()); + } + }; + + Slider.prototype.onMouseMoveEvent = function(event) { + if (this.isMoving) { + var newThumbX = event.x - this.clickOffsetX; + if (newThumbX < this.minThumbX) { + newThumbX = this.minThumbX; + } + if (newThumbX > this.maxThumbX) { + newThumbX = this.maxThumbX; + } + this.thumbX = newThumbX; + this.updateThumb(); + this.onValueChanged(this.getValue()); + } + }; + + Slider.prototype.onMouseReleaseEvent = function(event) { + this.isMoving = false; + this.unhighlight(); + }; Slider.prototype.updateWithKeys = function(direction) { this.range = this.maxThumbX - this.minThumbX; this.thumbX += direction * (this.range / SCALE); this.updateThumb(); this.onValueChanged(this.getValue()); - }; + }; Slider.prototype.highlight = function() { - if(this.highlighted) { + if (this.highlighted) { return; } Overlays.editOverlay(this.thumb, { - backgroundColor: {red: 255, green: 255, blue: 255} + backgroundColor: { + red: 255, + green: 255, + blue: 255 + } }); - this.highlighted = true; + this.highlighted = true; }; Slider.prototype.unhighlight = function() { - if(!this.highlighted) { + if (!this.highlighted) { return; } Overlays.editOverlay(this.thumb, { backgroundColor: THUMB_COLOR - }); + }); this.highlighted = false; }; Slider.prototype.setNormalizedValue = function(value) { - if (value < 0.0) { - this.thumbX = this.minThumbX; - } else if (value > 1.0) { - this.thumbX = this.maxThsumbX; - } else { - this.thumbX = value * (this.maxThumbX - this.minThumbX) + this.minThumbX; - } - this.updateThumb(); - }; + if (value < 0.0) { + this.thumbX = this.minThumbX; + } else if (value > 1.0) { + this.thumbX = this.maxThsumbX; + } else { + this.thumbX = value * (this.maxThumbX - this.minThumbX) + this.minThumbX; + } + this.updateThumb(); + }; Slider.prototype.getNormalizedValue = function() { - return (this.thumbX - this.minThumbX) / (this.maxThumbX - this.minThumbX); - }; - + return (this.thumbX - this.minThumbX) / (this.maxThumbX - this.minThumbX); + }; + Slider.prototype.setValue = function(value) { - var normValue = (value - this.minValue) / (this.maxValue - this.minValue); - this.setNormalizedValue(normValue); - }; + var normValue = (value - this.minValue) / (this.maxValue - this.minValue); + this.setNormalizedValue(normValue); + }; Slider.prototype.getValue = function() { - return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; - }; - + return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; + }; + Slider.prototype.reset = function(resetValue) { - this.setValue(resetValue); - this.onValueChanged(resetValue); - }; + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; Slider.prototype.onValueChanged = function(value) {}; Slider.prototype.getHeight = function() { - if(!this.visible) { - return 0; - } - return 1.5 * this.thumbSize; - }; + if (!this.visible) { + return 0; + } + return 1.5 * this.thumbSize; + }; Slider.prototype.moveUp = function(newY) { - Overlays.editOverlay(this.background, {y: newY}); - Overlays.editOverlay(this.thumb, {y: newY}); + Overlays.editOverlay(this.background, { + y: newY + }); + Overlays.editOverlay(this.thumb, { + y: newY + }); }; Slider.prototype.moveDown = function() { - Overlays.editOverlay(this.background, {y: this.y}); - Overlays.editOverlay(this.thumb, {y: this.y}); + Overlays.editOverlay(this.background, { + y: this.y + }); + Overlays.editOverlay(this.thumb, { + y: this.y + }); }; Slider.prototype.hide = function() { - Overlays.editOverlay(this.background, {visible: false}); - Overlays.editOverlay(this.thumb, {visible: false}); - this.visible = false; - }; + Overlays.editOverlay(this.background, { + visible: false + }); + Overlays.editOverlay(this.thumb, { + visible: false + }); + this.visible = false; + }; Slider.prototype.show = function() { - Overlays.editOverlay(this.background, {visible: true}); - Overlays.editOverlay(this.thumb, {visible: true}); - this.visible = true; - }; + Overlays.editOverlay(this.background, { + visible: true + }); + Overlays.editOverlay(this.thumb, { + visible: true + }); + this.visible = true; + }; Slider.prototype.destroy = function() { - Overlays.deleteOverlay(this.background); - Overlays.deleteOverlay(this.thumb); - }; + Overlays.deleteOverlay(this.background); + Overlays.deleteOverlay(this.thumb); + }; this.Slider = Slider; - + // The Checkbox class - var Checkbox = function(x,y,width,thumbSize) { - + var Checkbox = function(x, y, width, thumbSize) { + this.thumb = Overlays.addOverlay("text", { - backgroundColor: THUMB_COLOR, - textFontSize: 10, - x: x, - y: y, - width: thumbSize, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); - - + backgroundColor: THUMB_COLOR, + textFontSize: 10, + x: x, + y: y, + width: thumbSize, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); + + this.thumbSize = thumbSize; var checkX = x + (0.25 * thumbSize); var checkY = y + (0.25 * thumbSize); @@ -235,173 +261,217 @@ var CHECK_MARK_COLOR = { this.boxCheckStatus = true; this.clickedBox = false; this.visible = true; - - + + this.checkMark = Overlays.addOverlay("text", { - backgroundColor: CHECK_MARK_COLOR, - x: checkX, - y: checkY, - width: thumbSize / 2.0, - height: thumbSize / 2.0, - alpha: 1.0, - visible: true - }); + backgroundColor: CHECK_MARK_COLOR, + x: checkX, + y: checkY, + width: thumbSize / 2.0, + height: thumbSize / 2.0, + alpha: 1.0, + visible: true + }); }; - - Checkbox.prototype.updateThumb = function() { - Overlays.editOverlay(this.checkMark, { visible: this.boxCheckStatus }); - }; - + + Checkbox.prototype.updateThumb = function() { + Overlays.editOverlay(this.checkMark, { + visible: this.boxCheckStatus + }); + }; + Checkbox.prototype.isClickableOverlayItem = function(item) { - return (item == this.thumb) || (item == this.checkMark); - }; - + return (item == this.thumb) || (item == this.checkMark); + }; + Checkbox.prototype.onMousePressEvent = function(event, clickedOverlay) { - if (!this.isClickableOverlayItem(clickedOverlay)) { - return; - } - this.boxCheckStatus = !this.boxCheckStatus; - this.onValueChanged(this.getValue()); - this.updateThumb(); - }; - + if (!this.isClickableOverlayItem(clickedOverlay)) { + return; + } + this.boxCheckStatus = !this.boxCheckStatus; + this.onValueChanged(this.getValue()); + this.updateThumb(); + }; + Checkbox.prototype.onMouseReleaseEvent = function(event) {}; Checkbox.prototype.updateWithKeys = function() { this.boxCheckStatus = !this.boxCheckStatus; this.onValueChanged(this.getValue()); this.updateThumb(); - }; + }; Checkbox.prototype.highlight = function() { Overlays.editOverlay(this.thumb, { backgroundColor: THUMB_HIGHLIGHT }); - this.highlighted = true; - }; + this.highlighted = true; + }; Checkbox.prototype.unhighlight = function() { Overlays.editOverlay(this.thumb, { backgroundColor: THUMB_COLOR - }); + }); this.highlighted = false; - }; - + }; + Checkbox.prototype.setValue = function(value) { - this.boxCheckStatus = value; - }; + this.boxCheckStatus = value; + }; Checkbox.prototype.setterFromWidget = function(value) { - this.updateThumb(); - }; + this.updateThumb(); + }; Checkbox.prototype.getValue = function() { - return this.boxCheckStatus; - }; - - Checkbox.prototype.reset = function(resetValue) { - this.setValue(resetValue); - }; + return this.boxCheckStatus; + }; + + Checkbox.prototype.reset = function(resetValue) { + this.setValue(resetValue); + }; + + Checkbox.prototype.onValueChanged = function(value) {}; - Checkbox.prototype.onValueChanged = function(value) { }; - Checkbox.prototype.getHeight = function() { - if(!this.visible) { + if (!this.visible) { return 0; } - return 1.5 * this.thumbSize; - }; + return 1.5 * this.thumbSize; + }; Checkbox.prototype.moveUp = function(newY) { - Overlays.editOverlay(this.background, {y: newY}); - Overlays.editOverlay(this.thumb, {y: newY}); - Overlays.editOverlay(this.checkMark, {y: newY}); - Overlays.editOverlay(this.unCheckMark, {y: newY}); + Overlays.editOverlay(this.background, { + y: newY + }); + Overlays.editOverlay(this.thumb, { + y: newY + }); + Overlays.editOverlay(this.checkMark, { + y: newY + }); + Overlays.editOverlay(this.unCheckMark, { + y: newY + }); }; Checkbox.prototype.moveDown = function() { - Overlays.editOverlay(this.background, {y: this.y}); - Overlays.editOverlay(this.thumb, {y: this.y}); - Overlays.editOverlay(this.checkMark, {y: this.y}); - Overlays.editOverlay(this.unCheckMark, {y: this.y}); + Overlays.editOverlay(this.background, { + y: this.y + }); + Overlays.editOverlay(this.thumb, { + y: this.y + }); + Overlays.editOverlay(this.checkMark, { + y: this.y + }); + Overlays.editOverlay(this.unCheckMark, { + y: this.y + }); }; Checkbox.prototype.hide = function() { - Overlays.editOverlay(this.background, {visible: false}); - Overlays.editOverlay(this.thumb, {visible: false}); - Overlays.editOverlay(this.checkMark, {visible: false}); - Overlays.editOverlay(this.unCheckMark, {visible: false}); + Overlays.editOverlay(this.background, { + visible: false + }); + Overlays.editOverlay(this.thumb, { + visible: false + }); + Overlays.editOverlay(this.checkMark, { + visible: false + }); + Overlays.editOverlay(this.unCheckMark, { + visible: false + }); this.visible = false; } Checkbox.prototype.show = function() { - Overlays.editOverlay(this.background, {visible: true}); - Overlays.editOverlay(this.thumb, {visible: true}); - Overlays.editOverlay(this.checkMark, {visible: true}); - Overlays.editOverlay(this.unCheckMark, {visible: true}); + Overlays.editOverlay(this.background, { + visible: true + }); + Overlays.editOverlay(this.thumb, { + visible: true + }); + Overlays.editOverlay(this.checkMark, { + visible: true + }); + Overlays.editOverlay(this.unCheckMark, { + visible: true + }); this.visible = true; } - + Checkbox.prototype.destroy = function() { - Overlays.deleteOverlay(this.background); - Overlays.deleteOverlay(this.thumb); - Overlays.deleteOverlay(this.checkMark); - Overlays.deleteOverlay(this.unCheckMark); - }; + Overlays.deleteOverlay(this.background); + Overlays.deleteOverlay(this.thumb); + Overlays.deleteOverlay(this.checkMark); + Overlays.deleteOverlay(this.unCheckMark); + }; this.Checkbox = Checkbox; - + // The ColorBox class - var ColorBox = function(x,y,width,thumbSize) { + var ColorBox = function(x, y, width, thumbSize) { var self = this; - + var slideHeight = thumbSize / 3; var sliderWidth = width; this.red = new Slider(x, y, width, slideHeight); this.green = new Slider(x, y + slideHeight, width, slideHeight); this.blue = new Slider(x, y + 2 * slideHeight, width, slideHeight); - this.red.setBackgroundColor({x: 1, y: 0, z: 0}); - this.green.setBackgroundColor({x: 0, y: 1, z: 0}); - this.blue.setBackgroundColor({x: 0, y: 0, z: 1}); - + this.red.setBackgroundColor({ + x: 1, + y: 0, + z: 0 + }); + this.green.setBackgroundColor({ + x: 0, + y: 1, + z: 0 + }); + this.blue.setBackgroundColor({ + x: 0, + y: 0, + z: 1 + }); + this.red.onValueChanged = this.setterFromWidget; this.green.onValueChanged = this.setterFromWidget; this.blue.onValueChanged = this.setterFromWidget; this.visible = true; }; - - ColorBox.prototype.isClickableOverlayItem = function(item) { - return this.red.isClickableOverlayItem(item) - || this.green.isClickableOverlayItem(item) - || this.blue.isClickableOverlayItem(item); - }; - - ColorBox.prototype.onMousePressEvent = function(event, clickedOverlay) { - this.red.onMousePressEvent(event, clickedOverlay); - if (this.red.isMoving) { - return; - } - - this.green.onMousePressEvent(event, clickedOverlay); - if (this.green.isMoving) { - return; - } - - this.blue.onMousePressEvent(event, clickedOverlay); - }; - ColorBox.prototype.onMouseMoveEvent = function(event) { - this.red.onMouseMoveEvent(event); - this.green.onMouseMoveEvent(event); - this.blue.onMouseMoveEvent(event); - }; - + ColorBox.prototype.isClickableOverlayItem = function(item) { + return this.red.isClickableOverlayItem(item) || this.green.isClickableOverlayItem(item) || this.blue.isClickableOverlayItem(item); + }; + + ColorBox.prototype.onMousePressEvent = function(event, clickedOverlay) { + this.red.onMousePressEvent(event, clickedOverlay); + if (this.red.isMoving) { + return; + } + + this.green.onMousePressEvent(event, clickedOverlay); + if (this.green.isMoving) { + return; + } + + this.blue.onMousePressEvent(event, clickedOverlay); + }; + + ColorBox.prototype.onMouseMoveEvent = function(event) { + this.red.onMouseMoveEvent(event); + this.green.onMouseMoveEvent(event); + this.blue.onMouseMoveEvent(event); + }; + ColorBox.prototype.onMouseReleaseEvent = function(event) { - this.red.onMouseReleaseEvent(event); - this.green.onMouseReleaseEvent(event); - this.blue.onMouseReleaseEvent(event); - }; + this.red.onMouseReleaseEvent(event); + this.green.onMouseReleaseEvent(event); + this.blue.onMouseReleaseEvent(event); + }; ColorBox.prototype.updateWithKeys = function(direction) { this.red.updateWithKeys(direction); @@ -412,7 +482,7 @@ var CHECK_MARK_COLOR = { ColorBox.prototype.highlight = function() { this.red.highlight(); this.green.highlight(); - this.blue.highlight(); + this.blue.highlight(); this.highlighted = true; }; @@ -426,44 +496,60 @@ var CHECK_MARK_COLOR = { }; ColorBox.prototype.setterFromWidget = function(value) { - var color = this.getValue(); - this.onValueChanged(color); - this.updateRGBSliders(color); - }; + var color = this.getValue(); + this.onValueChanged(color); + this.updateRGBSliders(color); + }; ColorBox.prototype.onValueChanged = function(value) {}; - + ColorBox.prototype.updateRGBSliders = function(color) { - this.red.setThumbColor({x: color.x, y: 0, z: 0}); - this.green.setThumbColor({x: 0, y: color.y, z: 0}); - this.blue.setThumbColor({x: 0, y: 0, z: color.z}); - }; - - // Public members: + this.red.setThumbColor({ + x: color.x, + y: 0, + z: 0 + }); + this.green.setThumbColor({ + x: 0, + y: color.y, + z: 0 + }); + this.blue.setThumbColor({ + x: 0, + y: 0, + z: color.z + }); + }; + + // Public members: ColorBox.prototype.setValue = function(value) { - this.red.setValue(value.x); - this.green.setValue(value.y); - this.blue.setValue(value.z); - this.updateRGBSliders(value); - }; + this.red.setValue(value.x); + this.green.setValue(value.y); + this.blue.setValue(value.z); + this.updateRGBSliders(value); + }; ColorBox.prototype.getValue = function() { - var value = {x:this.red.getValue(), y:this.green.getValue(),z:this.blue.getValue()}; - return value; + var value = { + x: this.red.getValue(), + y: this.green.getValue(), + z: this.blue.getValue() }; + return value; + }; ColorBox.prototype.reset = function(resetValue) { - this.setValue(resetValue); - this.onValueChanged(resetValue); - }; + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; + - ColorBox.prototype.getHeight = function() { - if(!this.visible) { + if (!this.visible) { return 0; } - return 1.5 * this.thumbSize; - }; + return 1.5 * this.thumbSize; + }; ColorBox.prototype.moveUp = function(newY) { this.red.moveUp(newY); @@ -490,121 +576,132 @@ var CHECK_MARK_COLOR = { this.blue.show(); this.visible = true; } - + ColorBox.prototype.destroy = function() { - this.red.destroy(); - this.green.destroy(); - this.blue.destroy(); - }; + this.red.destroy(); + this.green.destroy(); + this.blue.destroy(); + }; this.ColorBox = ColorBox; - + // The DirectionBox class - var DirectionBox = function(x,y,width,thumbSize) { + var DirectionBox = function(x, y, width, thumbSize) { var self = this; - + var slideHeight = thumbSize / 2; var sliderWidth = width; this.yaw = new Slider(x, y, width, slideHeight); this.pitch = new Slider(x, y + slideHeight, width, slideHeight); - - - this.yaw.setThumbColor({x: 1, y: 0, z: 0}); + + + this.yaw.setThumbColor({ + x: 1, + y: 0, + z: 0 + }); this.yaw.minValue = -180; this.yaw.maxValue = +180; - - this.pitch.setThumbColor({x: 0, y: 0, z: 1}); + + this.pitch.setThumbColor({ + x: 0, + y: 0, + z: 1 + }); this.pitch.minValue = -1; this.pitch.maxValue = +1; - + this.yaw.onValueChanged = this.setterFromWidget; this.pitch.onValueChanged = this.setterFromWidget; this.visible = true; }; - - DirectionBox.prototype.isClickableOverlayItem = function(item) { - return this.yaw.isClickableOverlayItem(item) - || this.pitch.isClickableOverlayItem(item); - }; - - DirectionBox.prototype.onMousePressEvent = function(event, clickedOverlay) { - this.yaw.onMousePressEvent(event, clickedOverlay); - if (this.yaw.isMoving) { - return; - } - this.pitch.onMousePressEvent(event, clickedOverlay); - }; - DirectionBox.prototype.onMouseMoveEvent = function(event) { - this.yaw.onMouseMoveEvent(event); - this.pitch.onMouseMoveEvent(event); - }; - + DirectionBox.prototype.isClickableOverlayItem = function(item) { + return this.yaw.isClickableOverlayItem(item) || this.pitch.isClickableOverlayItem(item); + }; + + DirectionBox.prototype.onMousePressEvent = function(event, clickedOverlay) { + this.yaw.onMousePressEvent(event, clickedOverlay); + if (this.yaw.isMoving) { + return; + } + this.pitch.onMousePressEvent(event, clickedOverlay); + }; + + DirectionBox.prototype.onMouseMoveEvent = function(event) { + this.yaw.onMouseMoveEvent(event); + this.pitch.onMouseMoveEvent(event); + }; + DirectionBox.prototype.onMouseReleaseEvent = function(event) { - this.yaw.onMouseReleaseEvent(event); - this.pitch.onMouseReleaseEvent(event); - }; + this.yaw.onMouseReleaseEvent(event); + this.pitch.onMouseReleaseEvent(event); + }; DirectionBox.prototype.updateWithKeys = function(direction) { this.yaw.updateWithKeys(direction); this.pitch.updateWithKeys(direction); - }; + }; DirectionBox.prototype.highlight = function() { this.pitch.highlight(); this.yaw.highlight(); - + this.highlighted = true; - }; + }; DirectionBox.prototype.unhighlight = function() { this.pitch.unhighlight(); this.yaw.unhighlight(); - + this.highlighted = false; - }; - + }; + DirectionBox.prototype.setterFromWidget = function(value) { - var yawPitch = this.getValue(); - this.onValueChanged(yawPitch); - }; + var yawPitch = this.getValue(); + this.onValueChanged(yawPitch); + }; DirectionBox.prototype.onValueChanged = function(value) {}; DirectionBox.prototype.setValue = function(direction) { - var flatXZ = Math.sqrt(direction.x * direction.x + direction.z * direction.z); - if (flatXZ > 0.0) { - var flatX = direction.x / flatXZ; - var flatZ = direction.z / flatXZ; - var yaw = Math.acos(flatX) * 180 / Math.PI; - if (flatZ < 0) { - yaw = -yaw; - } - this.yaw.setValue(yaw); + var flatXZ = Math.sqrt(direction.x * direction.x + direction.z * direction.z); + if (flatXZ > 0.0) { + var flatX = direction.x / flatXZ; + var flatZ = direction.z / flatXZ; + var yaw = Math.acos(flatX) * 180 / Math.PI; + if (flatZ < 0) { + yaw = -yaw; } - this.pitch.setValue(direction.y); - }; + this.yaw.setValue(yaw); + } + this.pitch.setValue(direction.y); + }; - DirectionBox.prototype.getValue = function() { - var dirZ = this.pitch.getValue(); - var yaw = this.yaw.getValue() * Math.PI / 180; - var cosY = Math.sqrt(1 - dirZ*dirZ); - var value = {x:cosY * Math.cos(yaw), y:dirZ, z: cosY * Math.sin(yaw)}; - return value; + DirectionBox.prototype.getValue = function() { + var dirZ = this.pitch.getValue(); + var yaw = this.yaw.getValue() * Math.PI / 180; + var cosY = Math.sqrt(1 - dirZ * dirZ); + var value = { + x: cosY * Math.cos(yaw), + y: dirZ, + z: cosY * Math.sin(yaw) }; - + return value; + }; + DirectionBox.prototype.reset = function(resetValue) { - this.setValue(resetValue); - this.onValueChanged(resetValue); - }; - + this.setValue(resetValue); + this.onValueChanged(resetValue); + }; + DirectionBox.prototype.getHeight = function() { - if(!this.visible) { + if (!this.visible) { return 0; } - return 1.5 * this.thumbSize; - }; + return 1.5 * this.thumbSize; + }; DirectionBox.prototype.moveUp = function(newY) { this.pitch.moveUp(newY); @@ -627,59 +724,73 @@ var CHECK_MARK_COLOR = { this.yaw.show(); this.visible = true; } - + DirectionBox.prototype.destroy = function() { - this.yaw.destroy(); - this.pitch.destroy(); - }; - + this.yaw.destroy(); + this.pitch.destroy(); + }; + this.DirectionBox = DirectionBox; - + var textFontSize = 12; - - var CollapsablePanelItem = function (name, x, y, textWidth, height) { + + var CollapsablePanelItem = function(name, x, y, textWidth, height) { this.name = name; this.height = height; this.y = y; this.isCollapsable = true; - + var topMargin = (height - 1.5 * textFontSize); - + this.thumb = Overlays.addOverlay("image", { - color: {red: 255, green: 255, blue: 255}, - imageURL: HIFI_PUBLIC_BUCKET + 'images/tools/min-max-toggle.svg', - x: x, - y: y, - width: rawHeight, - height: rawHeight, - alpha: 1.0, - visible: true - }); - + color: { + red: 255, + green: 255, + blue: 255 + }, + imageURL: HIFI_PUBLIC_BUCKET + 'images/tools/min-max-toggle.svg', + x: x, + y: y, + width: rawHeight, + height: rawHeight, + alpha: 1.0, + visible: true + }); + this.title = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x + rawHeight * 1.5, - y: y, - width: textWidth, - height: height, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true, - text: " " + name, - font: {size: textFontSize}, - topMargin: topMargin - }); + backgroundColor: { + red: 255, + green: 255, + blue: 255 + }, + x: x + rawHeight * 1.5, + y: y, + width: textWidth, + height: height, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true, + text: " " + name, + font: { + size: textFontSize + }, + topMargin: topMargin + }); }; CollapsablePanelItem.prototype.destroy = function() { Overlays.deleteOverlay(this.title); Overlays.deleteOverlay(this.thumb); }; - - + + CollapsablePanelItem.prototype.hide = function() { - Overlays.editOverlay(this.title, {visible: false}); - Overlays.editOverlay(this.thumb, {visible: false}); + Overlays.editOverlay(this.title, { + visible: false + }); + Overlays.editOverlay(this.thumb, { + visible: false + }); if (this.widget != null) { this.widget.hide(); @@ -687,8 +798,12 @@ var CHECK_MARK_COLOR = { }; CollapsablePanelItem.prototype.show = function() { - Overlays.editOverlay(this.title, {visible: true}); - Overlays.editOverlay(this.thumb, {visible: true}); + Overlays.editOverlay(this.title, { + visible: true + }); + Overlays.editOverlay(this.thumb, { + visible: true + }); if (this.widget != null) { this.widget.show(); @@ -696,8 +811,12 @@ var CHECK_MARK_COLOR = { }; CollapsablePanelItem.prototype.moveUp = function(newY) { - Overlays.editOverlay(this.title, {y: newY}); - Overlays.editOverlay(this.thumb, {y: newY}); + Overlays.editOverlay(this.title, { + y: newY + }); + Overlays.editOverlay(this.thumb, { + y: newY + }); if (this.widget != null) { this.widget.moveUp(newY); @@ -705,74 +824,92 @@ var CHECK_MARK_COLOR = { } CollapsablePanelItem.prototype.moveDown = function() { - Overlays.editOverlay(this.title, {y: this.y}); - Overlays.editOverlay(this.thumb, {y: this.y}); + Overlays.editOverlay(this.title, { + y: this.y + }); + Overlays.editOverlay(this.thumb, { + y: this.y + }); if (this.widget != null) { this.widget.moveDown(); } } this.CollapsablePanelItem = CollapsablePanelItem; - - var PanelItem = function (name, setter, getter, displayer, x, y, textWidth, valueWidth, height) { + + var PanelItem = function(name, setter, getter, displayer, x, y, textWidth, valueWidth, height) { //print("creating panel item: " + name); this.isCollapsable = false; this.name = name; this.y = y; this.isCollapsed = false; - - this.displayer = typeof displayer !== 'undefined' ? displayer : function(value) { - if(value == true) { + + this.displayer = typeof displayer !== 'undefined' ? displayer : function(value) { + if (value == true) { return "On"; } else if (value == false) { return "Off"; } - return value.toFixed(2); + return value.toFixed(2); }; - + var topMargin = (height - 1.5 * textFontSize); this.title = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x, - y: y, - width: textWidth, - height: height, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true, - text: " " + name, - font: {size: textFontSize}, - topMargin: topMargin - }); - + backgroundColor: { + red: 255, + green: 255, + blue: 255 + }, + x: x, + y: y, + width: textWidth, + height: height, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true, + text: " " + name, + font: { + size: textFontSize + }, + topMargin: topMargin + }); + this.value = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x + textWidth, - y: y, - width: valueWidth, - height: height, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true, - text: this.displayer(getter()), - font: {size: textFontSize}, - topMargin: topMargin - }); - + backgroundColor: { + red: 255, + green: 255, + blue: 255 + }, + x: x + textWidth, + y: y, + width: valueWidth, + height: height, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true, + text: this.displayer(getter()), + font: { + size: textFontSize + }, + topMargin: topMargin + }); + this.getter = getter; this.resetValue = getter(); - + this.setter = function(value) { - + setter(value); - Overlays.editOverlay(this.value, {text: this.displayer(getter())}); + Overlays.editOverlay(this.value, { + text: this.displayer(getter()) + }); if (this.widget) { this.widget.setValue(value); - } - + } + //print("successfully set value of widget to " + value); }; this.setterFromWidget = function(value) { @@ -782,16 +919,22 @@ var CHECK_MARK_COLOR = { if (this.widget) { this.widget.setValue(value); - } - Overlays.editOverlay(this.value, {text: this.displayer(value)}); - }; - + } + Overlays.editOverlay(this.value, { + text: this.displayer(value) + }); + }; + this.widget = null; }; PanelItem.prototype.hide = function() { - Overlays.editOverlay(this.title, {visible: false}); - Overlays.editOverlay(this.value, {visible: false}); + Overlays.editOverlay(this.title, { + visible: false + }); + Overlays.editOverlay(this.value, { + visible: false + }); if (this.widget != null) { this.widget.hide(); @@ -800,8 +943,12 @@ var CHECK_MARK_COLOR = { PanelItem.prototype.show = function() { - Overlays.editOverlay(this.title, {visible: true}); - Overlays.editOverlay(this.value, {visible: true}); + Overlays.editOverlay(this.title, { + visible: true + }); + Overlays.editOverlay(this.value, { + visible: true + }); if (this.widget != null) { this.widget.show(); @@ -811,8 +958,12 @@ var CHECK_MARK_COLOR = { PanelItem.prototype.moveUp = function(newY) { - Overlays.editOverlay(this.title, {y: newY}); - Overlays.editOverlay(this.value, {y: newY}); + Overlays.editOverlay(this.title, { + y: newY + }); + Overlays.editOverlay(this.value, { + y: newY + }); if (this.widget != null) { this.widget.moveUp(newY); @@ -822,8 +973,12 @@ var CHECK_MARK_COLOR = { PanelItem.prototype.moveDown = function() { - Overlays.editOverlay(this.title, {y: this.y}); - Overlays.editOverlay(this.value, {y: this.y}); + Overlays.editOverlay(this.title, { + y: this.y + }); + Overlays.editOverlay(this.value, { + y: this.y + }); if (this.widget != null) { this.widget.moveDown(); @@ -832,15 +987,15 @@ var CHECK_MARK_COLOR = { }; PanelItem.prototype.destroy = function() { - Overlays.deleteOverlay(this.title); - Overlays.deleteOverlay(this.value); + Overlays.deleteOverlay(this.title); + Overlays.deleteOverlay(this.value); - if (this.widget != null) { - this.widget.destroy(); - } - }; + if (this.widget != null) { + this.widget.destroy(); + } + }; this.PanelItem = PanelItem; - + var textWidth = 180; var valueWidth = 100; var widgetWidth = 300; @@ -848,7 +1003,7 @@ var CHECK_MARK_COLOR = { var rawYDelta = rawHeight * 1.5; var outerPanel = true; var widgets; - + var Panel = function(x, y) { @@ -856,50 +1011,53 @@ var CHECK_MARK_COLOR = { widgets = []; } outerPanel = false; - + this.x = x; this.y = y; - this.nextY = y; + this.nextY = y; print("creating panel at x: " + this.x + " y: " + this.y); - - this.widgetX = x + textWidth + valueWidth; - + + this.widgetX = x + textWidth + valueWidth; + this.items = new Array(); this.activeWidget = null; this.visible = true; this.indentation = 30; }; - + Panel.prototype.mouseMoveEvent = function(event) { if (this.activeWidget) { this.activeWidget.onMouseMoveEvent(event); } }; - + Panel.prototype.mousePressEvent = function(event) { // Make sure we quitted previous widget if (this.activeWidget) { this.activeWidget.onMouseReleaseEvent(event); } - this.activeWidget = null; - - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + this.activeWidget = null; + + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); this.handleCollapse(clickedOverlay); - + // If the user clicked any of the slider background then... for (var i in this.items) { var item = this.items[i]; var widget = this.items[i].widget; - + if (widget.isClickableOverlayItem(clickedOverlay)) { this.activeWidget = widget; - this.activeWidget.onMousePressEvent(event, clickedOverlay); + this.activeWidget.onMousePressEvent(event, clickedOverlay); break; - } - } + } + } }; Panel.prototype.mouseReleaseEvent = function(event) { @@ -907,39 +1065,42 @@ var CHECK_MARK_COLOR = { this.activeWidget.onMouseReleaseEvent(event); } this.activeWidget = null; - }; - - // Reset panel item upon double-clicking + }; + + // Reset panel item upon double-clicking Panel.prototype.mouseDoublePressEvent = function(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); this.handleReset(clickedOverlay); }; - - Panel.prototype.handleReset = function (clickedOverlay) { + + Panel.prototype.handleReset = function(clickedOverlay) { for (var i in this.items) { - - var item = this.items[i]; + + var item = this.items[i]; var widget = item.widget; - + if (item.isSubPanel && widget) { widget.handleReset(clickedOverlay); } - + if (clickedOverlay == item.title) { item.activeWidget = widget; item.activeWidget.reset(item.resetValue); break; - } + } } }; - Panel.prototype.handleCollapse = function (clickedOverlay) { + Panel.prototype.handleCollapse = function(clickedOverlay) { for (var i in this.items) { - - var item = this.items[i]; + + var item = this.items[i]; var widget = item.widget; - + if (item.isSubPanel && widget) { widget.handleCollapse(clickedOverlay); } @@ -948,20 +1109,20 @@ var CHECK_MARK_COLOR = { this.collapse(clickedOverlay); item.isCollapsed = true; break; - } else if (item.isCollapsed && item.isCollapsable && clickedOverlay == item.thumb) { + } else if (item.isCollapsed && item.isCollapsable && clickedOverlay == item.thumb) { this.expand(clickedOverlay); item.isCollapsed = false; } } }; - Panel.prototype.collapse = function (clickedOverlay) { + Panel.prototype.collapse = function(clickedOverlay) { var keys = Object.keys(this.items); - + for (var i = 0; i < keys.length; ++i) { var item = this.items[keys[i]]; - if(item.isCollapsable && clickedOverlay == item.thumb) { + if (item.isCollapsable && clickedOverlay == item.thumb) { var panel = item.widget; panel.hide(); break; @@ -969,40 +1130,40 @@ var CHECK_MARK_COLOR = { } // Now recalculate new heights of subsequent widgets - for(var j = i + 1; j < keys.length; ++j) { + for (var j = i + 1; j < keys.length; ++j) { this.items[keys[j]].moveUp(this.getCurrentY(keys[j])); } }; - Panel.prototype.expand = function (clickedOverlay) { + Panel.prototype.expand = function(clickedOverlay) { var keys = Object.keys(this.items); - + for (var i = 0; i < keys.length; ++i) { var item = this.items[keys[i]]; - if(item.isCollapsable && clickedOverlay == item.thumb) { + if (item.isCollapsable && clickedOverlay == item.thumb) { var panel = item.widget; panel.show(); break; } - } - // Now recalculate new heights of subsequent widgets - for(var j = i + 1; j < keys.length; ++j) { + } + // Now recalculate new heights of subsequent widgets + for (var j = i + 1; j < keys.length; ++j) { this.items[keys[j]].moveDown(); } }; - + Panel.prototype.onMousePressEvent = function(event, clickedOverlay) { for (var i in this.items) { var item = this.items[i]; - if(item.widget.isClickableOverlayItem(clickedOverlay)) { + if (item.widget.isClickableOverlayItem(clickedOverlay)) { item.activeWidget = item.widget; - item.activeWidget.onMousePressEvent(event,clickedOverlay); + item.activeWidget.onMousePressEvent(event, clickedOverlay); } } }; - + Panel.prototype.onMouseMoveEvent = function(event) { for (var i in this.items) { var item = this.items[i]; @@ -1011,7 +1172,7 @@ var CHECK_MARK_COLOR = { } } }; - + Panel.prototype.onMouseReleaseEvent = function(event, clickedOverlay) { for (var i in this.items) { var item = this.items[i]; @@ -1021,7 +1182,7 @@ var CHECK_MARK_COLOR = { item.activeWidget = null; } }; - + Panel.prototype.onMouseDoublePressEvent = function(event, clickedOverlay) { for (var i in this.items) { var item = this.items[i]; @@ -1035,13 +1196,13 @@ var CHECK_MARK_COLOR = { var tabIndex = 0; Panel.prototype.keyPressEvent = function(event) { - if(event.text == "TAB" && !event.isShifted) { + if (event.text == "TAB" && !event.isShifted) { tabView = true; - if(tabIndex < widgets.length) { - if(tabIndex > 0 && widgets[tabIndex - 1].highlighted) { + if (tabIndex < widgets.length) { + if (tabIndex > 0 && widgets[tabIndex - 1].highlighted) { // Unhighlight previous widget widgets[tabIndex - 1].unhighlight(); - } + } widgets[tabIndex].highlight(); tabIndex++; } else { @@ -1052,32 +1213,32 @@ var CHECK_MARK_COLOR = { tabIndex++; } } else if (tabView && event.isShifted) { - if(tabIndex > 0) { + if (tabIndex > 0) { tabIndex--; - if(tabIndex < widgets.length && widgets[tabIndex + 1].highlighted) { + if (tabIndex < widgets.length && widgets[tabIndex + 1].highlighted) { // Unhighlight previous widget widgets[tabIndex + 1].unhighlight(); - } + } widgets[tabIndex].highlight(); } else { widgets[tabIndex].unhighlight(); //Wrap around to end tabIndex = widgets.length - 1; - widgets[tabIndex].highlight(); + widgets[tabIndex].highlight(); } } else if (event.text == "LEFT") { - for(var i = 0; i < widgets.length; i++) { + for (var i = 0; i < widgets.length; i++) { // Find the highlighted widget, allow control with arrow keys - if(widgets[i].highlighted) { + if (widgets[i].highlighted) { var k = -1; widgets[i].updateWithKeys(k); break; } } } else if (event.text == "RIGHT") { - for(var i = 0; i < widgets.length; i++) { + for (var i = 0; i < widgets.length; i++) { // Find the highlighted widget, allow control with arrow keys - if(widgets[i].highlighted) { + if (widgets[i].highlighted) { var k = 1; widgets[i].updateWithKeys(k); break; @@ -1095,93 +1256,105 @@ var CHECK_MARK_COLOR = { slider.minValue = minValue; slider.maxValue = maxValue; widgets.push(slider); - + item.widget = slider; - item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; - item.setter(getValue()); + item.widget.onValueChanged = function(value) { + item.setterFromWidget(value); + }; + item.setter(getValue()); this.items[name] = item; }; - + Panel.prototype.newCheckbox = function(name, setValue, getValue, displayValue) { var display; if (displayValue == true) { - display = function() {return "On";}; + display = function() { + return "On"; + }; } else if (displayValue == false) { - display = function() {return "Off";}; + display = function() { + return "Off"; + }; } - + this.nextY = this.y + this.getHeight(); - + var item = new PanelItem(name, setValue, getValue, display, this.x, this.nextY, textWidth, valueWidth, rawHeight); - + var checkbox = new Checkbox(this.widgetX, this.nextY, widgetWidth, rawHeight); widgets.push(checkbox); - + item.widget = checkbox; - item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; - item.setter(getValue()); - this.items[name] = item; - - //print("created Item... checkbox=" + name); - }; - - Panel.prototype.newColorBox = function(name, setValue, getValue, displayValue) { - this.nextY = this.y + this.getHeight(); - - var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); - - var colorBox = new ColorBox(this.widgetX, this.nextY, widgetWidth, rawHeight); - widgets.push(colorBox); - - item.widget = colorBox; - item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; - item.setter(getValue()); + item.widget.onValueChanged = function(value) { + item.setterFromWidget(value); + }; + item.setter(getValue()); this.items[name] = item; - // print("created Item... colorBox=" + name); + //print("created Item... checkbox=" + name); }; - + + Panel.prototype.newColorBox = function(name, setValue, getValue, displayValue) { + this.nextY = this.y + this.getHeight(); + + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); + + var colorBox = new ColorBox(this.widgetX, this.nextY, widgetWidth, rawHeight); + widgets.push(colorBox); + + item.widget = colorBox; + item.widget.onValueChanged = function(value) { + item.setterFromWidget(value); + }; + item.setter(getValue()); + this.items[name] = item; + + // print("created Item... colorBox=" + name); + }; + Panel.prototype.newDirectionBox = function(name, setValue, getValue, displayValue) { this.nextY = this.y + this.getHeight(); - + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); var directionBox = new DirectionBox(this.widgetX, this.nextY, widgetWidth, rawHeight); widgets.push(directionBox); - + item.widget = directionBox; - item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; - item.setter(getValue()); + item.widget.onValueChanged = function(value) { + item.setterFromWidget(value); + }; + item.setter(getValue()); this.items[name] = item; - - // print("created Item... directionBox=" + name); + + // print("created Item... directionBox=" + name); }; - + Panel.prototype.newSubPanel = function(name) { - + this.nextY = this.y + this.getHeight(); - + var item = new CollapsablePanelItem(name, this.x, this.nextY, textWidth, rawHeight, panel); item.isSubPanel = true; - + this.nextY += 1.5 * item.height; - + var subPanel = new Panel(this.x + this.indentation, this.nextY); - + item.widget = subPanel; this.items[name] = item; return subPanel; - // print("created Item... subPanel=" + name); + // print("created Item... subPanel=" + name); }; - + Panel.prototype.onValueChanged = function(value) { for (var i in this.items) { this.items[i].widget.onValueChanged(value); } }; - - + + Panel.prototype.set = function(name, value) { var item = this.items[name]; if (item != null) { @@ -1189,7 +1362,7 @@ var CHECK_MARK_COLOR = { } return null; }; - + Panel.prototype.get = function(name) { var item = this.items[name]; if (item != null) { @@ -1197,7 +1370,7 @@ var CHECK_MARK_COLOR = { } return null; }; - + Panel.prototype.update = function(name) { var item = this.items[name]; if (item != null) { @@ -1205,7 +1378,7 @@ var CHECK_MARK_COLOR = { } return null; }; - + Panel.prototype.isClickableOverlayItem = function(item) { for (var i in this.items) { if (this.items[i].widget.isClickableOverlayItem(item)) { @@ -1214,30 +1387,30 @@ var CHECK_MARK_COLOR = { } return false; }; - + Panel.prototype.getHeight = function() { var height = 0; - + for (var i in this.items) { - height += this.items[i].widget.getHeight(); - if(this.items[i].isSubPanel && this.items[i].widget.visible) { - height += 1.5 * rawHeight; - } + height += this.items[i].widget.getHeight(); + if (this.items[i].isSubPanel && this.items[i].widget.visible) { + height += 1.5 * rawHeight; + } } return height; }; Panel.prototype.moveUp = function() { - for (var i in this.items) { + for (var i in this.items) { this.items[i].widget.moveUp(); - } + } }; Panel.prototype.moveDown = function() { for (var i in this.items) { this.items[i].widget.moveDown(); - } + } }; Panel.prototype.getCurrentY = function(key) { @@ -1247,34 +1420,34 @@ var CHECK_MARK_COLOR = { for (var i = 0; i < keys.indexOf(key); ++i) { var item = this.items[keys[i]]; - height += item.widget.getHeight(); - - if(item.isSubPanel) { + height += item.widget.getHeight(); + + if (item.isSubPanel) { height += 1.5 * rawHeight; - - } + + } } return this.y + height; }; - + Panel.prototype.hide = function() { for (var i in this.items) { - if(this.items[i].isSubPanel) { + if (this.items[i].isSubPanel) { this.items[i].widget.hide(); } this.items[i].hide(); - } + } this.visible = false; }; Panel.prototype.show = function() { for (var i in this.items) { - if(this.items[i].isSubPanel) { + if (this.items[i].isSubPanel) { this.items[i].widget.show(); } this.items[i].show(); - } + } this.visible = true; }; @@ -1282,21 +1455,29 @@ var CHECK_MARK_COLOR = { Panel.prototype.destroy = function() { for (var i in this.items) { - if(this.items[i].isSubPanel) { + if (this.items[i].isSubPanel) { this.items[i].widget.destroy(); } this.items[i].destroy(); - } + } }; this.Panel = Panel; })(); Script.scriptEnding.connect(function scriptEnding() { - Controller.releaseKeyEvents({text: "left"}); - Controller.releaseKeyEvents({key: "right"}); + Controller.releaseKeyEvents({ + text: "left" + }); + Controller.releaseKeyEvents({ + key: "right" + }); }); -Controller.captureKeyEvents({text: "left"}); -Controller.captureKeyEvents({text: "right"}); \ No newline at end of file +Controller.captureKeyEvents({ + text: "left" +}); +Controller.captureKeyEvents({ + text: "right" +}); \ No newline at end of file From ccb3d433afb69e6ce391c7d302092143515a96f1 Mon Sep 17 00:00:00 2001 From: bwent Date: Fri, 24 Jul 2015 09:43:49 -0700 Subject: [PATCH 087/129] Example script solarsystem.js with orbiting satellite game --- examples/example/games/satellite.js | 279 +++++++++++++ examples/example/games/solarsystem.js | 554 ++++++++++++++++++++++++++ examples/utilities/tools/vector.js | 197 +++++++++ 3 files changed, 1030 insertions(+) create mode 100644 examples/example/games/satellite.js create mode 100644 examples/example/games/solarsystem.js create mode 100644 examples/utilities/tools/vector.js diff --git a/examples/example/games/satellite.js b/examples/example/games/satellite.js new file mode 100644 index 0000000000..d2e4dd2a99 --- /dev/null +++ b/examples/example/games/satellite.js @@ -0,0 +1,279 @@ +// +// satellite.js +// games +// +// Created by Bridget Went 7/1/2015. +// Copyright 2015 High Fidelity, Inc. +// +// A game to bring a satellite model into orbit around an animated earth model . +// - Double click to create a new satellite +// - Click on the satellite, drag a vector arrow to specify initial velocity +// - Release mouse to launch the active satellite +// - Orbital movement is calculated using equations of gravitational physics +// +// 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/vector.js'); + +var URL = "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/"; + +SatelliteGame = function() { + var MAX_RANGE = 50.0; + var Y_AXIS = { + x: 0, + y: 1, + z: 0 + } + var LIFETIME = 6000; + + var v0; + var T = 4.0; + var M = 16000.0; + var m = M * 0.000000333; + var ERROR_THRESH = 20.0; + + // Create the spinning earth model + var EARTH_SIZE = 20.0; + var CLOUDS_OFFSET = 0.5; + var SPIN = 0.1; + var ZONE_DIM = 10.0; + var LIGHT_INTENSITY = 1.2; + + Earth = function(position, size) { + this.earth = Entities.addEntity({ + type: "Model", + shapeType: 'sphere', + modelURL: URL + "earth.fbx", + position: position, + dimensions: { + x: size, + y: size, + z: size + }, + rotation: Quat.angleAxis(180, {x: 1, y: 0, z: 0}), + angularVelocity: { x: 0.00, y: 0.5 * SPIN, z: 0.00 }, + angularDamping: 0.0, + damping: 0.0, + ignoreCollisions: false, + lifetime: 6000, + collisionsWillMove: false, + visible: true + }); + + this.clouds = Entities.addEntity({ + type: "Model", + shapeType: 'sphere', + modelURL: URL + "clouds.fbx?", + position: position, + dimensions: { + x: size + CLOUDS_OFFSET, + y: size + CLOUDS_OFFSET, + z: size + CLOUDS_OFFSET + }, + angularVelocity: { x: 0.00, y: SPIN, z: 0.00 }, + angularDamping: 0.0, + damping: 0.0, + ignoreCollisions: false, + lifetime: LIFETIME, + collisionsWillMove: false, + visible: true + }); + + this.zone = Entities.addEntity({ + type: "Zone", + position: position, + dimensions: { + x: ZONE_DIM, + y: ZONE_DIM, + z: ZONE_DIM + }, + keyLightDirection: Vec3.normalize(Vec3.subtract(position, Camera.getPosition())), + keyLightIntensity: LIGHT_INTENSITY + }); + + this.cleanup = function() { + Entities.deleteEntity(this.clouds); + Entities.deleteEntity(this.earth); + Entities.deleteEntity(this.zone); + } + } + + // Create earth model + var center = Vec3.sum(Camera.getPosition(), Vec3.multiply(MAX_RANGE, Quat.getFront(Camera.getOrientation()))); + var distance = Vec3.length(Vec3.subtract(center, Camera.getPosition())); + var earth = new Earth(center, EARTH_SIZE); + + var satellites = []; + var SATELLITE_SIZE = 2.0; + var launched = false; + var activeSatellite; + + Satellite = function(position, planetCenter) { + // The Satellite class + + this.launched = false; + this.startPosition = position; + this.readyToLaunch = false; + this.radius = Vec3.length(Vec3.subtract(position, planetCenter)); + + this.satellite = Entities.addEntity({ + type: "Model", + modelURL: "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/satellite/satellite.fbx", + position: this.startPosition, + dimensions: { + x: SATELLITE_SIZE, + y: SATELLITE_SIZE, + z: SATELLITE_SIZE + }, + angularDamping: 0.0, + damping: 0.0, + ignoreCollisions: false, + lifetime: LIFETIME, + collisionsWillMove: false, + }); + + this.getProperties = function() { + return Entities.getEntityProperties(this.satellite); + } + + this.launch = function() { + var prop = Entities.getEntityProperties(this.satellite); + var between = Vec3.subtract(planetCenter, prop.position); + var radius = Vec3.length(between); + this.G = (4.0 * Math.PI * Math.PI * Math.pow(radius, 3.0)) / (M * T * T); + + var v0 = Vec3.normalize(Vec3.cross(between, Y_AXIS)); + v0 = Vec3.multiply(Math.sqrt((this.G * M) / radius), v0); + v0 = Vec3.multiply(this.arrow.magnitude, v0); + v0 = Vec3.multiply(Vec3.length(v0), this.arrow.direction); + + Entities.editEntity(this.satellite, { velocity: v0 }); + this.launched = true; + }; + + + this.update = function(deltaTime) { + var prop = Entities.getEntityProperties(this.satellite); + var between = Vec3.subtract(prop.position, planetCenter); + var radius = Vec3.length(between); + var a = -(this.G * M) * Math.pow(radius, (-2.0)); + var speed = a * deltaTime; + var vel = Vec3.multiply(speed, Vec3.normalize(between)); + + var newVelocity = Vec3.sum(prop.velocity, vel); + var newPos = Vec3.sum(prop.position, Vec3.multiply(newVelocity, deltaTime)); + + Entities.editEntity(this.satellite, { + velocity: newVelocity, + position: newPos + }); + }; + } + + function mouseDoublePressEvent(event) { + var pickRay = Camera.computePickRay(event.x, event.y); + var addVector = Vec3.multiply(pickRay.direction, distance); + var point = Vec3.sum(Camera.getPosition(), addVector); + + // Create a new satellite + activeSatellite = new Satellite(point, center); + satellites.push(activeSatellite); + } + + function mousePressEvent(event) { + if (!activeSatellite) { + return; + } + // Reset label + if (activeSatellite.arrow) { + activeSatellite.arrow.deleteLabel(); + } + var statsPosition = Vec3.sum(Camera.getPosition(), Vec3.multiply(MAX_RANGE * 0.5, Quat.getFront(Camera.getOrientation()))); + var pickRay = Camera.computePickRay(event.x, event.y) + var rayPickResult = Entities.findRayIntersection(pickRay, true); + if (rayPickResult.entityID === activeSatellite.satellite) { + // Create a draggable vector arrow at satellite position + activeSatellite.arrow = new VectorArrow(distance, true, "INITIAL VELOCITY", statsPosition); + activeSatellite.arrow.onMousePressEvent(event); + activeSatellite.arrow.isDragging = true; + } + } + + function mouseMoveEvent(event) { + if(!activeSatellite || !activeSatellite.arrow || !activeSatellite.arrow.isDragging) { + return; + } + activeSatellite.arrow.onMouseMoveEvent(event); + } + + function mouseReleaseEvent(event) { + if(!activeSatellite || !activeSatellite.arrow || !activeSatellite.arrow.isDragging) { + return; + } + activeSatellite.arrow.onMouseReleaseEvent(event); + activeSatellite.launch(); + activeSatellite.arrow.cleanup(); + } + + var counter = 0.0; + var TIME = 500; + + function update(deltaTime) { + if(!activeSatellite) { + return; + } + // Update all satellites + for (var i = 0; i < satellites.length; i++) { + if (!satellites[i].launched) { + return; + } + satellites[i].update(deltaTime); + } + + counter++; + if (counter % TIME == 0) { + var prop = activeSatellite.getProperties(); + var error = calcEnergyError(prop.position, Vec3.length(prop.velocity)); + if (Math.abs(error) <= ERROR_THRESH) { + activeSatellite.arrow.editLabel("Nice job! The satellite has reached a stable orbit."); + } else { + activeSatellite.arrow.editLabel("Try again! The satellite is in an unstable orbit."); + } + } + } + + this.endGame = function() { + print("ending game"); + for(var i = 0; i < satellites.length; i++) { + Entities.deleteEntitiy(satellites[i].satellite); + satellites[i].arrow.cleanup(); + } + earth.cleanup(); + } + + + function calcEnergyError(pos, vel) { + //Calculate total energy error for active satellite's orbital motion + var radius = activeSatellite.radius; + var G = (4.0 * Math.PI * Math.PI * Math.pow(radius, 3.0)) / (M * T * T); + var v0 = Math.sqrt((G * M) / radius); + + var totalEnergy = 0.5 * M * Math.pow(v0, 2.0) - ((G * M * m) / radius); + var measuredEnergy = 0.5 * M * Math.pow(vel, 2.0) - ((G * M * m) / Vec3.length(Vec3.subtract(pos, center))); + var error = ((measuredEnergy - totalEnergy) / totalEnergy) * 100; + return error; + } + + Controller.mousePressEvent.connect(mousePressEvent); + Controller.mouseDoublePressEvent.connect(mouseDoublePressEvent); + Controller.mouseMoveEvent.connect(mouseMoveEvent); + Controller.mouseReleaseEvent.connect(mouseReleaseEvent); + Script.update.connect(update); + Script.scriptEnding.connect(this.endGame); + +} + + + diff --git a/examples/example/games/solarsystem.js b/examples/example/games/solarsystem.js new file mode 100644 index 0000000000..b651e551f0 --- /dev/null +++ b/examples/example/games/solarsystem.js @@ -0,0 +1,554 @@ +// +// solarsystem.js +// games +// +// Created by Bridget Went, 5/28/15. +// Copyright 2015 High Fidelity, Inc. +// +// The start to a project to build a virtual physics classroom to simulate the solar system, gravity, and orbital physics. +// A sun with oribiting planets is created in front of the user. UI elements allow for adjusting the period, gravity, trails, and energy recalculations. +// +// 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'); +Script.include('satellite.js'); + +var BASE_URL = "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/planets/"; + +var NUM_PLANETS = 8; + +var trailsEnabled = true; +var energyConserved = true; +var planetView = false; +var earthView = false; +var satelliteGame; + +var PANEL_X = 850; +var PANEL_Y = 600; +var BUTTON_SIZE = 20; +var PADDING = 20; + +var DAMPING = 0.0; +var LIFETIME = 6000; +var ERROR_THRESH = 2.0; +var TIME_STEP = 70.0; + +var MAX_POINTS_PER_LINE = 5; +var LINE_DIM = 10; +var LINE_WIDTH = 3.0; +var line; +var planetLines = []; +var trails = []; + +var BOUNDS = 200; + + +// Alert user to move if they are too close to domain bounds +if (MyAvatar.position.x < BOUNDS || MyAvatar.position.x > TREE_SCALE - BOUNDS + || MyAvatar.position.y < BOUNDS || MyAvatar.position.y > TREE_SCALE - BOUNDS + || MyAvatar.position.z < BOUNDS || MyAvatar.position.z > TREE_SCALE - BOUNDS) { + Window.alert("Please move at least 200m away from domain bounds."); + return; +} + +// Save intiial avatar and camera position +var startingPosition = MyAvatar.position; +var startFrame = Window.location.href; + +// Place the sun +var MAX_RANGE = 80.0; +var SUN_SIZE = 8.0; +var center = Vec3.sum(startingPosition, Vec3.multiply(MAX_RANGE, Quat.getFront(Camera.getOrientation()))); + +var theSun = Entities.addEntity({ + type: "Model", + modelURL: BASE_URL + "sun.fbx", + position: center, + dimensions: { + x: SUN_SIZE, + y: SUN_SIZE, + z: SUN_SIZE + }, + angularDamping: DAMPING, + damping: DAMPING, + ignoreCollisions: false, + lifetime: LIFETIME, + collisionsWillMove: false +}); + +var planets = []; +var planet_properties = []; + +// Reference values +var radius = 7.0; +var T_ref = 1.0; +var size = 1.0; +var M = 250.0; +var m = M * 0.000000333; +var G = (Math.pow(radius, 3.0) / Math.pow((T_ref / (2.0 * Math.PI)), 2.0)) / M; +var G_ref = G; + +// Adjust size and distance as number of planets increases +var DELTA_RADIUS = 1.8; +var DELTA_SIZE = 0.2; + +function initPlanets() { + for (var i = 0; i < NUM_PLANETS; ++i) { + var v0 = Math.sqrt((G * M) / radius); + var T = (2.0 * Math.PI) * Math.sqrt(Math.pow(radius, 3.0) / (G * M)); + + if (i == 0) { + var color = {red: 255, green: 255, blue: 255}; + } else if (i == 1) { + var color = {red: 255, green: 160, blue: 110}; + } else if (i == 2) { + var color = {red: 10, green: 150, blue: 160}; + } else if (i == 3) { + var color = {red: 180, green: 70, blue: 10}; + } else if (i == 4) { + var color = {red: 250, green: 140, blue: 0}; + } else if (i == 5) { + var color = {red: 235, green: 215, blue: 0}; + } else if (i == 6) { + var color = {red:135, green: 205, blue: 240}; + } else if (i == 7) { + var color = {red:30, green: 140, blue: 255}; + } + + var prop = { + radius: radius, + position: Vec3.sum(center, {x: radius, y: 0.0, z: 0.0}), + lineColor: color, + period: T, + dimensions: size, + velocity: Vec3.multiply(v0, Vec3.normalize({x: 0, y: -0.2, z: 0.9})) + }; + planet_properties.push(prop); + + planets.push(Entities.addEntity({ + type: "Model", + modelURL: BASE_URL + (i + 1) + ".fbx", + position: prop.position, + dimensions: { + x: prop.dimensions, + y: prop.dimensions, + z: prop.dimensions + }, + velocity: prop.velocity, + angularDamping: DAMPING, + damping: DAMPING, + ignoreCollisions: false, + lifetime: LIFETIME, + collisionsWillMove: true, + })); + + radius *= DELTA_RADIUS; + size += DELTA_SIZE; + } +} + +// Initialize planets +initPlanets(); + + +var labels = []; +var labelLines = []; +var labelsShowing = false; +var LABEL_X = 8.0; +var LABEL_Y = 3.0; +var LABEL_Z = 1.0; +var LABEL_DIST = 8.0; +var TEXT_HEIGHT = 1.0; +var sunLabel; + +function showLabels() { + labelsShowing = true; + for (var i = 0; i < NUM_PLANETS; i++) { + var properties = planet_properties[i]; + var text; + if (i == 0) { + text = "Mercury"; + } else if (i == 1) { + text = "Venus"; + } else if (i == 2) { + text = "Earth"; + } else if (i == 3) { + text = "Mars"; + } else if (i == 4) { + text = "Jupiter"; + } else if (i == 5) { + text = "Saturn"; + } else if (i == 6) { + text = "Uranus"; + } else if (i == 7) { + text = "Neptune"; + } + + text = text + " Speed: " + Vec3.length(properties.velocity).toFixed(2); + + var labelPos = Vec3.sum(planet_properties[i].position, {x: 0.0, y: LABEL_DIST, z: LABEL_DIST}); + var linePos = planet_properties[i].position; + labelLines.push(Entities.addEntity( { + type: "Line", + position: linePos, + dimensions: {x: 20, y: 20, z: 20}, + lineWidth: 3.0, + color: {red: 255, green: 255, blue: 255}, + linePoints: [{x: 0, y: 0, z: 0}, computeLocalPoint(linePos, labelPos)] + })); + + labels.push(Entities.addEntity( { + type: "Text", + text: text, + lineHeight: TEXT_HEIGHT, + dimensions: {x: LABEL_X, y: LABEL_Y, z: LABEL_Z}, + position: labelPos, + backgroundColor: {red: 10, green: 10, blue: 10}, + textColor: {red: 255, green: 255, blue: 255}, + faceCamera: true + })); + } +} + +function hideLabels() { + labelsShowing = false; + Entities.deleteEntity(sunLabel); + + for (var i = 0; i < NUM_PLANETS; ++i) { + Entities.deleteEntity(labelLines[i]); + Entities.deleteEntity(labels[i]); + } + labels = []; + labelLines = []; +} + +var time = 0.0; +var elapsed; +var counter = 0; +var dt = 1.0 / TIME_STEP; + +function update(deltaTime) { + if (paused) { + return; + } + deltaTime = dt; + time++; + + for (var i = 0; i < NUM_PLANETS; ++i) { + var properties = planet_properties[i]; + var between = Vec3.subtract(properties.position, center); + var speed = getAcceleration(properties.radius) * deltaTime; + var vel = Vec3.multiply(speed, Vec3.normalize(between)); + + // Update velocity and position + properties.velocity = Vec3.sum(properties.velocity, vel); + properties.position = Vec3.sum(properties.position, Vec3.multiply(properties.velocity, deltaTime)); + Entities.editEntity(planets[i], { + velocity: properties.velocity, + position: properties.position + }); + + + // Create new or update current trail + if (trailsEnabled) { + var lineStack = planetLines[i]; + var point = properties.position; + var prop = Entities.getEntityProperties(lineStack[lineStack.length - 1]); + var linePos = prop.position; + + trails[i].push(computeLocalPoint(linePos, point)); + + Entities.editEntity(lineStack[lineStack.length - 1], { + linePoints: trails[i] + }); + if (trails[i].length === MAX_POINTS_PER_LINE) { + trails[i] = newLine(lineStack, point, properties.period, properties.lineColor); + } + } + + // Measure total energy every 10 updates, recalibrate velocity if necessary + if (energyConserved) { + if (counter % 10 === 0) { + var error = calcEnergyError(planets[i], properties.radius, properties.v0, properties.velocity, properties.position); + if (Math.abs(error) >= ERROR_THRESH) { + var speed = adjustVelocity(planets[i], properties.position); + properties.velocity = Vec3.multiply(speed, Vec3.normalize(properties.velocity)); + } + } + } + } + + counter++; + if (time % TIME_STEP == 0) { + elapsed++; + } +} + +function computeLocalPoint(linePos, worldPoint) { + var localPoint = Vec3.subtract(worldPoint, linePos); + return localPoint; +} + +function getAcceleration(radius) { + var acc = -(G * M) * Math.pow(radius, (-2.0)); + return acc; +} + +// Create a new trail +function resetTrails(planetIndex) { + elapsed = 0.0; + var properties = planet_properties[planetIndex]; + + var trail = []; + var lineStack = []; + + //add the first line to both the line entity stack and the trail + trails.push(newLine(lineStack, properties.position, properties.period, properties.lineColor)); + planetLines.push(lineStack); +} + +// Create a new line +function newLine(lineStack, point, period, color) { + if (elapsed < period) { + var line = Entities.addEntity({ + position: point, + type: "Line", + color: color, + dimensions: { + x: LINE_DIM, + y: LINE_DIM, + z: LINE_DIM + }, + lifetime: LIFETIME, + lineWidth: LINE_WIDTH + }); + lineStack.push(line); + } else { + // Begin overwriting first lines after one full revolution (one period) + var firstLine = lineStack.shift(); + Entities.editEntity(firstLine, { + position: point, + linePoints: [{x: 0.0, y: 0.0, z: 0.0}] + }); + lineStack.push(firstLine); + + } + var points = []; + points.push(computeLocalPoint(point, point)); + return points; +} + +// Measure energy error, recalculate velocity to return to initial net energy +var totalEnergy; +var measuredEnergy; +var measuredPE; + +function calcEnergyError(planet, radius, v0, v, pos) { + totalEnergy = 0.5 * M * Math.pow(v0, 2.0) - ((G * M * m) / radius); + measuredEnergy = 0.5 * M * Math.pow(v, 2.0) - ((G * M * m) / Vec3.length(Vec3.subtract(center, pos))); + var error = ((measuredEnergy - totalEnergy) / totalEnergy) * 100; + return error; +} +function adjustVelocity(planet, pos) { + var measuredPE = -(G * M * m) / Vec3.length(Vec3.subtract(center, pos)); + return Math.sqrt(2 * (totalEnergy - measuredPE) / M); +} + + +// Allow user to toggle pausing the model, switch to planet view +var pauseButton = Overlays.addOverlay("text", { + backgroundColor: { red: 200, green: 200, blue: 255 }, + text: "Pause", + x: PANEL_X, + y: PANEL_Y - 30, + width: 70, + height: 20, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true +}); + +var paused = false; + +function mousePressEvent(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); + if(clickedOverlay == pauseButton) { + paused = !paused; + for (var i = 0; i < NUM_PLANETS; ++i) { + Entities.editEntity(planets[i], { velocity: {x: 0.0, y: 0.0, z: 0.0} }); + } + if (paused && !labelsShowing) { + Overlays.editOverlay(pauseButton, { text: "Paused", backgroundColor: {red: 255, green: 50, blue: 50} } ); + showLabels(); + } + if (paused == false && labelsShowing) { + Overlays.editOverlay(pauseButton, { text: "Pause", backgroundColor: {red: 200, green: 200, blue: 255}}); + hideLabels(); + } + planetView = false; + } +} + +function keyPressEvent(event) { + // Jump back to solar system view + if (event.text == "TAB" && planetView) { + if (earthView) { + satelliteGame.endGame(); + earthView = false; + } + MyAvatar.position = startingPosition; + } +} + +function mouseDoublePressEvent(event) { + if(earthView) { + return; + } + var pickRay = Camera.computePickRay(event.x, event.y) + var rayPickResult = Entities.findRayIntersection(pickRay, true); + + for (var i = 0; i < NUM_PLANETS; ++i) { + if (rayPickResult.entityID === labels[i]) { + planetView = true; + if (i == 2) { + MyAvatar.position = Vec3.sum(center, {x: 200, y: 200, z: 200}); + Camera.setPosition(Vec3.sum(center, {x: 200, y: 200, z: 200})); + earthView = true; + satelliteGame = new SatelliteGame(); + + } else { + MyAvatar.position = Vec3.sum({x: 0.0, y: 0.0, z: 3.0}, planet_properties[i].position); + Camera.lookAt(planet_properties[i].position); + } + break; + } + } +} + + + + +// Create UI panel +var panel = new Panel(PANEL_X, PANEL_Y); +var panelItems = []; + +var g_multiplier = 1.0; +panelItems.push(panel.newSlider("Adjust Gravitational Force: ", 0.1, 5.0, + function (value) { + g_multiplier = value; + G = G_ref * g_multiplier; + }, + + function () { + return g_multiplier; + }, + function (value) { + return value.toFixed(1) + "x"; + })); + +var period_multiplier = 1.0; +var last_alpha = period_multiplier; +panelItems.push(panel.newSlider("Adjust Orbital Period: ", 0.1, 3.0, + function (value) { + period_multiplier = value; + changePeriod(period_multiplier); + }, + function () { + return period_multiplier; + }, + function (value) { + return (value).toFixed(2) + "x"; + })); + +panelItems.push(panel.newCheckbox("Leave Trails: ", + function (value) { + trailsEnabled = value; + if (trailsEnabled) { + for (var i = 0; i < NUM_PLANETS; ++i) { + resetTrails(i); + } + //if trails are off and we've already created trails, remove existing trails + } else if (planetLines.length != 0) { + for (var i = 0; i < NUM_PLANETS; ++i) { + for (var j = 0; j < planetLines[i].length; ++j) { + Entities.deleteEntity(planetLines[i][j]); + } + planetLines[i] = []; + } + } + }, + function () { + return trailsEnabled; + }, + function (value) { + return value; + })); + +panelItems.push(panel.newCheckbox("Energy Error Calculations: ", + function (value) { + energyConserved = value; + }, + function () { + return energyConserved; + }, + function (value) { + return value; + })); + +// Update global G constant, period, poke velocity to new value +function changePeriod(alpha) { + var ratio = last_alpha / alpha; + G = Math.pow(ratio, 2.0) * G; + for (var i = 0; i < NUM_PLANETS; ++i) { + var properties = planet_properties[i]; + properties.period = ratio * properties.period; + properties.velocity = Vec3.multiply(ratio, properties.velocity); + + } + last_alpha = alpha; +} + + +// Clean up models, UI panels, lines, and button overlays +function scriptEnding() { + + satelliteGame.endGame(); + + Entities.deleteEntity(theSun); + for (var i = 0; i < NUM_PLANETS; ++i) { + Entities.deleteEntity(planets[i]); + } + Menu.removeMenu("Developer > Scene"); + panel.destroy(); + Overlays.deleteOverlay(pauseButton); + + var e = Entities.findEntities(MyAvatar.position, 16000); + for (i = 0; i < e.length; i++) { + var props = Entities.getEntityProperties(e[i]); + if (props.type === "Line" || props.type === "Text") { + Entities.deleteEntity(e[i]); + } + } +}; + + +Controller.mouseMoveEvent.connect(function panelMouseMoveEvent(event) { + return panel.mouseMoveEvent(event); +}); +Controller.mousePressEvent.connect(function panelMousePressEvent(event) { + return panel.mousePressEvent(event); +}); +Controller.mouseDoublePressEvent.connect(function panelMouseDoublePressEvent(event) { + return panel.mouseDoublePressEvent(event); +}); +Controller.mouseReleaseEvent.connect(function (event) { + return panel.mouseReleaseEvent(event); +}); +Controller.mousePressEvent.connect(mousePressEvent); +Controller.mouseDoublePressEvent.connect(mouseDoublePressEvent); +Controller.keyPressEvent.connect(keyPressEvent); + +Script.scriptEnding.connect(scriptEnding); +Script.update.connect(update); \ No newline at end of file diff --git a/examples/utilities/tools/vector.js b/examples/utilities/tools/vector.js new file mode 100644 index 0000000000..ab2e8cf200 --- /dev/null +++ b/examples/utilities/tools/vector.js @@ -0,0 +1,197 @@ +// +// vector.js +// examples +// +// Created by Bridget Went on 7/1/15. +// Copyright 2015 High Fidelity, Inc. +// +// A template for creating vector arrows using line entities. A VectorArrow object creates a +// draggable vector arrow where the user clicked at a specified distance from the viewer. +// The relative magnitude and direction of the vector may be displayed. +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// + +var LINE_DIMENSIONS = 100; +var LIFETIME = 6000; +var RAD_TO_DEG = 180.0 / Math.PI; + +var LINE_WIDTH = 4; +var ARROW_WIDTH = 6; +var line, linePosition; +var arrow1, arrow2; + +var SCALE = 0.15; +var ANGLE = 150.0; + + +VectorArrow = function(distance, showStats, statsTitle, statsPosition) { + this.magnitude = 0; + this.direction = {x: 0, y: 0, z: 0}; + + this.showStats = showStats; + this.isDragging = false; + + this.newLine = function(position) { + linePosition = position; + var points = []; + + line = Entities.addEntity({ + position: linePosition, + type: "Line", + color: {red: 255, green: 255, blue: 255}, + dimensions: { + x: LINE_DIMENSIONS, + y: LINE_DIMENSIONS, + z: LINE_DIMENSIONS + }, + lineWidth: LINE_WIDTH, + lifetime: LIFETIME, + linePoints: [] + }); + + arrow1 = Entities.addEntity({ + position: {x: 0, y: 0, z: 0}, + type: "Line", + dimensions: { + x: LINE_DIMENSIONS, + y: LINE_DIMENSIONS, + z: LINE_DIMENSIONS + }, + color: {red: 255, green: 255, blue: 255}, + lineWidth: ARROW_WIDTH, + linePoints: [], + }); + + arrow2 = Entities.addEntity({ + position: {x: 0, y: 0, z: 0}, + type: "Line", + dimensions: { + x: LINE_DIMENSIONS, + y: LINE_DIMENSIONS, + z: LINE_DIMENSIONS + }, + color: {red: 255, green: 255, blue: 255}, + lineWidth: ARROW_WIDTH, + linePoints: [], + }); + + } + + + this.onMousePressEvent = function(event) { + + this.newLine(computeWorldPoint(event)); + + if (this.showStats) { + this.label = Entities.addEntity({ + type: "Text", + position: statsPosition, + dimensions: { + x: 4.0, + y: 1.5, + z: 0.1 + }, + lineHeight: 0.3, + faceCamera: true + }); + } + + this.isDragging = true; + + } + + + this.onMouseMoveEvent = function(event) { + + if (!this.isDragging) { + return; + } + + var worldPoint = computeWorldPoint(event); + var localPoint = computeLocalPoint(event, linePosition); + points = [{x: 0, y: 0, z: 0}, localPoint]; + Entities.editEntity(line, { linePoints: points }); + + var nextOffset = Vec3.multiply(SCALE, localPoint); + var normOffset = Vec3.normalize(localPoint); + var axis = Vec3.cross(normOffset, Quat.getFront(Camera.getOrientation()) ); + axis = Vec3.cross(axis, normOffset); + var rotate1 = Quat.angleAxis(ANGLE, axis); + var rotate2 = Quat.angleAxis(-ANGLE, axis); + + // Rotate arrow head to follow direction of the line + Entities.editEntity(arrow1, { + visible: true, + position: worldPoint, + linePoints: [{x: 0, y: 0, z: 0}, nextOffset], + rotation: rotate1 + }); + Entities.editEntity(arrow2, { + visible: true, + position: worldPoint, + linePoints: [{x: 0, y: 0, z: 0}, nextOffset], + rotation: rotate2 + }); + + this.magnitude = Vec3.length(localPoint) / 10.0; + this.direction = Vec3.normalize(Vec3.subtract(worldPoint, linePosition)); + + if (this.showStats) { + this.editLabel(statsTitle + " Magnitude " + this.magnitude.toFixed(2) + ", Direction: " + + this.direction.x.toFixed(2) + ", " + this.direction.y.toFixed(2) + ", " + this.direction.z.toFixed(2)); + } + } + + this.onMouseReleaseEvent = function() { + this.isDragging = false; + } + + this.cleanup = function() { + Entities.deleteEntity(line); + Entities.deleteEntity(arrow1); + Entities.deleteEntity(arrow2); + } + + this.deleteLabel = function() { + Entities.deleteEntity(this.label); + } + + this.editLabel = function(str) { + if(!this.showStats) { + return; + } + Entities.editEntity(this.label, { + text: str + }); + } + + function computeWorldPoint(event) { + var pickRay = Camera.computePickRay(event.x, event.y); + var addVector = Vec3.multiply(pickRay.direction, distance); + return Vec3.sum(Camera.getPosition(), addVector); + } + + function computeLocalPoint(event, linePosition) { + var localPoint = Vec3.subtract(computeWorldPoint(event), linePosition); + return localPoint; + } + + + +} + + + + + + + + + + + + From e0d6609a99b198f84a7a54445b2f9abb6465f047 Mon Sep 17 00:00:00 2001 From: bwent Date: Fri, 24 Jul 2015 10:18:33 -0700 Subject: [PATCH 088/129] resolve file path issue --- examples/example/games/satellite.js | 13 ++++++------- examples/example/{games => }/solarsystem.js | 12 +++++++++--- 2 files changed, 15 insertions(+), 10 deletions(-) rename examples/example/{games => }/solarsystem.js (96%) diff --git a/examples/example/games/satellite.js b/examples/example/games/satellite.js index d2e4dd2a99..e82285622b 100644 --- a/examples/example/games/satellite.js +++ b/examples/example/games/satellite.js @@ -15,7 +15,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include('../../utilities/tools/vector.js'); +Script.include('../utilities/tools/vector.js'); var URL = "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/"; @@ -38,8 +38,8 @@ SatelliteGame = function() { var EARTH_SIZE = 20.0; var CLOUDS_OFFSET = 0.5; var SPIN = 0.1; - var ZONE_DIM = 10.0; - var LIGHT_INTENSITY = 1.2; + var ZONE_DIM = 100.0; + var LIGHT_INTENSITY = 1.5; Earth = function(position, size) { this.earth = Entities.addEntity({ @@ -65,7 +65,7 @@ SatelliteGame = function() { this.clouds = Entities.addEntity({ type: "Model", shapeType: 'sphere', - modelURL: URL + "clouds.fbx?", + modelURL: URL + "clouds.fbx?i=2", position: position, dimensions: { x: size + CLOUDS_OFFSET, @@ -190,7 +190,7 @@ SatelliteGame = function() { if (activeSatellite.arrow) { activeSatellite.arrow.deleteLabel(); } - var statsPosition = Vec3.sum(Camera.getPosition(), Vec3.multiply(MAX_RANGE * 0.5, Quat.getFront(Camera.getOrientation()))); + var statsPosition = Vec3.sum(Camera.getPosition(), Vec3.multiply(MAX_RANGE * 0.4, Quat.getFront(Camera.getOrientation()))); var pickRay = Camera.computePickRay(event.x, event.y) var rayPickResult = Entities.findRayIntersection(pickRay, true); if (rayPickResult.entityID === activeSatellite.satellite) { @@ -245,9 +245,8 @@ SatelliteGame = function() { } this.endGame = function() { - print("ending game"); for(var i = 0; i < satellites.length; i++) { - Entities.deleteEntitiy(satellites[i].satellite); + Entities.deleteEntity(satellites[i].satellite); satellites[i].arrow.cleanup(); } earth.cleanup(); diff --git a/examples/example/games/solarsystem.js b/examples/example/solarsystem.js similarity index 96% rename from examples/example/games/solarsystem.js rename to examples/example/solarsystem.js index b651e551f0..09ba2eec8d 100644 --- a/examples/example/games/solarsystem.js +++ b/examples/example/solarsystem.js @@ -6,14 +6,20 @@ // Copyright 2015 High Fidelity, Inc. // // The start to a project to build a virtual physics classroom to simulate the solar system, gravity, and orbital physics. -// A sun with oribiting planets is created in front of the user. UI elements allow for adjusting the period, gravity, trails, and energy recalculations. +// - A sun with oribiting planets is created in front of the user +// - UI elements allow for adjusting the period, gravity, trails, and energy recalculations +// - Click "PAUSE" to pause the animation and show planet labels +// - In this mode, double-click a planet label to zoom in on that planet +// -Double-clicking on earth label initiates satellite orbiter game +// -Press "TAB" to toggle back to solar system view +// // // 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'); -Script.include('satellite.js'); +Script.include('../utilities/tools/cookies.js'); +Script.include('games/satellite.js'); var BASE_URL = "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/planets/"; From 5272a1d6e74a23b310b765ef51242a9ea81e0cc7 Mon Sep 17 00:00:00 2001 From: bwent Date: Mon, 27 Jul 2015 14:28:43 -0700 Subject: [PATCH 089/129] refactoring variables and constants, fix update loop to continue over unlaunched satellites --- examples/example/games/satellite.js | 212 +++++++++++++------------ examples/example/solarsystem.js | 229 ++++++++++++++++++++-------- examples/utilities/tools/vector.js | 31 ++-- 3 files changed, 290 insertions(+), 182 deletions(-) diff --git a/examples/example/games/satellite.js b/examples/example/games/satellite.js index e82285622b..3ddce96aa5 100644 --- a/examples/example/games/satellite.js +++ b/examples/example/games/satellite.js @@ -27,11 +27,6 @@ SatelliteGame = function() { z: 0 } var LIFETIME = 6000; - - var v0; - var T = 4.0; - var M = 16000.0; - var m = M * 0.000000333; var ERROR_THRESH = 20.0; // Create the spinning earth model @@ -43,42 +38,54 @@ SatelliteGame = function() { Earth = function(position, size) { this.earth = Entities.addEntity({ - type: "Model", - shapeType: 'sphere', - modelURL: URL + "earth.fbx", - position: position, - dimensions: { - x: size, - y: size, - z: size - }, - rotation: Quat.angleAxis(180, {x: 1, y: 0, z: 0}), - angularVelocity: { x: 0.00, y: 0.5 * SPIN, z: 0.00 }, - angularDamping: 0.0, - damping: 0.0, - ignoreCollisions: false, - lifetime: 6000, - collisionsWillMove: false, - visible: true + type: "Model", + shapeType: 'sphere', + modelURL: URL + "earth.fbx", + position: position, + dimensions: { + x: size, + y: size, + z: size + }, + rotation: Quat.angleAxis(180, { + x: 1, + y: 0, + z: 0 + }), + angularVelocity: { + x: 0.00, + y: 0.5 * SPIN, + z: 0.00 + }, + angularDamping: 0.0, + damping: 0.0, + ignoreCollisions: false, + lifetime: 6000, + collisionsWillMove: false, + visible: true }); this.clouds = Entities.addEntity({ - type: "Model", - shapeType: 'sphere', - modelURL: URL + "clouds.fbx?i=2", - position: position, - dimensions: { - x: size + CLOUDS_OFFSET, - y: size + CLOUDS_OFFSET, - z: size + CLOUDS_OFFSET - }, - angularVelocity: { x: 0.00, y: SPIN, z: 0.00 }, - angularDamping: 0.0, - damping: 0.0, - ignoreCollisions: false, - lifetime: LIFETIME, - collisionsWillMove: false, - visible: true + type: "Model", + shapeType: 'sphere', + modelURL: URL + "clouds.fbx?i=2", + position: position, + dimensions: { + x: size + CLOUDS_OFFSET, + y: size + CLOUDS_OFFSET, + z: size + CLOUDS_OFFSET + }, + angularVelocity: { + x: 0.00, + y: SPIN, + z: 0.00 + }, + angularDamping: 0.0, + damping: 0.0, + ignoreCollisions: false, + lifetime: LIFETIME, + collisionsWillMove: false, + visible: true }); this.zone = Entities.addEntity({ @@ -93,11 +100,11 @@ SatelliteGame = function() { keyLightIntensity: LIGHT_INTENSITY }); - this.cleanup = function() { - Entities.deleteEntity(this.clouds); + this.cleanup = function() { + Entities.deleteEntity(this.clouds); Entities.deleteEntity(this.earth); Entities.deleteEntity(this.zone); - } + } } // Create earth model @@ -110,6 +117,10 @@ SatelliteGame = function() { var launched = false; var activeSatellite; + var PERIOD = 4.0; + var LARGE_BODY_MASS = 16000.0; + var SMALL_BODY_MASS = LARGE_BODY_MASS * 0.000000333; + Satellite = function(position, planetCenter) { // The Satellite class @@ -118,20 +129,20 @@ SatelliteGame = function() { this.readyToLaunch = false; this.radius = Vec3.length(Vec3.subtract(position, planetCenter)); - this.satellite = Entities.addEntity({ + this.satellite = Entities.addEntity({ type: "Model", - modelURL: "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/satellite/satellite.fbx", - position: this.startPosition, - dimensions: { - x: SATELLITE_SIZE, - y: SATELLITE_SIZE, - z: SATELLITE_SIZE - }, - angularDamping: 0.0, - damping: 0.0, - ignoreCollisions: false, - lifetime: LIFETIME, - collisionsWillMove: false, + modelURL: "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/satellite/satellite.fbx", + position: this.startPosition, + dimensions: { + x: SATELLITE_SIZE, + y: SATELLITE_SIZE, + z: SATELLITE_SIZE + }, + angularDamping: 0.0, + damping: 0.0, + ignoreCollisions: false, + lifetime: LIFETIME, + collisionsWillMove: false, }); this.getProperties = function() { @@ -142,14 +153,16 @@ SatelliteGame = function() { var prop = Entities.getEntityProperties(this.satellite); var between = Vec3.subtract(planetCenter, prop.position); var radius = Vec3.length(between); - this.G = (4.0 * Math.PI * Math.PI * Math.pow(radius, 3.0)) / (M * T * T); + this.gravity = (4.0 * Math.PI * Math.PI * Math.pow(radius, 3.0)) / (LARGE_BODY_MASS * PERIOD * PERIOD); - var v0 = Vec3.normalize(Vec3.cross(between, Y_AXIS)); - v0 = Vec3.multiply(Math.sqrt((this.G * M) / radius), v0); - v0 = Vec3.multiply(this.arrow.magnitude, v0); - v0 = Vec3.multiply(Vec3.length(v0), this.arrow.direction); + var initialVelocity = Vec3.normalize(Vec3.cross(between, Y_AXIS)); + initialVelocity = Vec3.multiply(Math.sqrt((this.gravity * LARGE_BODY_MASS) / radius), initialVelocity); + initialVelocity = Vec3.multiply(this.arrow.magnitude, initialVelocity); + initialVelocity = Vec3.multiply(Vec3.length(initialVelocity), this.arrow.direction); - Entities.editEntity(this.satellite, { velocity: v0 }); + Entities.editEntity(this.satellite, { + velocity: initialVelocity + }); this.launched = true; }; @@ -158,12 +171,12 @@ SatelliteGame = function() { var prop = Entities.getEntityProperties(this.satellite); var between = Vec3.subtract(prop.position, planetCenter); var radius = Vec3.length(between); - var a = -(this.G * M) * Math.pow(radius, (-2.0)); - var speed = a * deltaTime; - var vel = Vec3.multiply(speed, Vec3.normalize(between)); + var acceleration = -(this.gravity * LARGE_BODY_MASS) * Math.pow(radius, (-2.0)); + var speed = acceleration * deltaTime; + var vel = Vec3.multiply(speed, Vec3.normalize(between)); - var newVelocity = Vec3.sum(prop.velocity, vel); - var newPos = Vec3.sum(prop.position, Vec3.multiply(newVelocity, deltaTime)); + var newVelocity = Vec3.sum(prop.velocity, vel); + var newPos = Vec3.sum(prop.position, Vec3.multiply(newVelocity, deltaTime)); Entities.editEntity(this.satellite, { velocity: newVelocity, @@ -173,11 +186,11 @@ SatelliteGame = function() { } function mouseDoublePressEvent(event) { - var pickRay = Camera.computePickRay(event.x, event.y); - var addVector = Vec3.multiply(pickRay.direction, distance); - var point = Vec3.sum(Camera.getPosition(), addVector); + var pickRay = Camera.computePickRay(event.x, event.y); + var addVector = Vec3.multiply(pickRay.direction, distance); + var point = Vec3.sum(Camera.getPosition(), addVector); - // Create a new satellite + // Create a new satellite activeSatellite = new Satellite(point, center); satellites.push(activeSatellite); } @@ -188,11 +201,11 @@ SatelliteGame = function() { } // Reset label if (activeSatellite.arrow) { - activeSatellite.arrow.deleteLabel(); - } + activeSatellite.arrow.deleteLabel(); + } var statsPosition = Vec3.sum(Camera.getPosition(), Vec3.multiply(MAX_RANGE * 0.4, Quat.getFront(Camera.getOrientation()))); var pickRay = Camera.computePickRay(event.x, event.y) - var rayPickResult = Entities.findRayIntersection(pickRay, true); + var rayPickResult = Entities.findRayIntersection(pickRay, true); if (rayPickResult.entityID === activeSatellite.satellite) { // Create a draggable vector arrow at satellite position activeSatellite.arrow = new VectorArrow(distance, true, "INITIAL VELOCITY", statsPosition); @@ -202,50 +215,50 @@ SatelliteGame = function() { } function mouseMoveEvent(event) { - if(!activeSatellite || !activeSatellite.arrow || !activeSatellite.arrow.isDragging) { + if (!activeSatellite || !activeSatellite.arrow || !activeSatellite.arrow.isDragging) { return; } activeSatellite.arrow.onMouseMoveEvent(event); } function mouseReleaseEvent(event) { - if(!activeSatellite || !activeSatellite.arrow || !activeSatellite.arrow.isDragging) { + if (!activeSatellite || !activeSatellite.arrow || !activeSatellite.arrow.isDragging) { return; } activeSatellite.arrow.onMouseReleaseEvent(event); - activeSatellite.launch(); - activeSatellite.arrow.cleanup(); + activeSatellite.launch(); + activeSatellite.arrow.cleanup(); } var counter = 0.0; - var TIME = 500; + var CHECK_ENERGY_PERIOD = 500; function update(deltaTime) { - if(!activeSatellite) { + if (!activeSatellite) { return; } // Update all satellites for (var i = 0; i < satellites.length; i++) { if (!satellites[i].launched) { - return; + continue; } - satellites[i].update(deltaTime); + satellites[i].update(deltaTime); } - + counter++; - if (counter % TIME == 0) { + if (counter % CHECK_ENERGY_PERIOD == 0) { var prop = activeSatellite.getProperties(); - var error = calcEnergyError(prop.position, Vec3.length(prop.velocity)); - if (Math.abs(error) <= ERROR_THRESH) { - activeSatellite.arrow.editLabel("Nice job! The satellite has reached a stable orbit."); - } else { - activeSatellite.arrow.editLabel("Try again! The satellite is in an unstable orbit."); - } - } + var error = calcEnergyError(prop.position, Vec3.length(prop.velocity)); + if (Math.abs(error) <= ERROR_THRESH) { + activeSatellite.arrow.editLabel("Nice job! The satellite has reached a stable orbit."); + } else { + activeSatellite.arrow.editLabel("Try again! The satellite is in an unstable orbit."); + } + } } this.endGame = function() { - for(var i = 0; i < satellites.length; i++) { + for (var i = 0; i < satellites.length; i++) { Entities.deleteEntity(satellites[i].satellite); satellites[i].arrow.cleanup(); } @@ -256,13 +269,13 @@ SatelliteGame = function() { function calcEnergyError(pos, vel) { //Calculate total energy error for active satellite's orbital motion var radius = activeSatellite.radius; - var G = (4.0 * Math.PI * Math.PI * Math.pow(radius, 3.0)) / (M * T * T); - var v0 = Math.sqrt((G * M) / radius); - - var totalEnergy = 0.5 * M * Math.pow(v0, 2.0) - ((G * M * m) / radius); - var measuredEnergy = 0.5 * M * Math.pow(vel, 2.0) - ((G * M * m) / Vec3.length(Vec3.subtract(pos, center))); - var error = ((measuredEnergy - totalEnergy) / totalEnergy) * 100; - return error; + var gravity = (4.0 * Math.PI * Math.PI * Math.pow(radius, 3.0)) / (LARGE_BODY_MASS * PERIOD * PERIOD); + var initialVelocityCalculated = Math.sqrt((gravity * LARGE_BODY_MASS) / radius); + + var totalEnergy = 0.5 * LARGE_BODY_MASS * Math.pow(initialVelocityCalculated, 2.0) - ((gravity * LARGE_BODY_MASS * SMALL_BODY_MASS) / radius); + var measuredEnergy = 0.5 * LARGE_BODY_MASS * Math.pow(vel, 2.0) - ((gravity * LARGE_BODY_MASS * SMALL_BODY_MASS) / Vec3.length(Vec3.subtract(pos, center))); + var error = ((measuredEnergy - totalEnergy) / totalEnergy) * 100; + return error; } Controller.mousePressEvent.connect(mousePressEvent); @@ -272,7 +285,4 @@ SatelliteGame = function() { Script.update.connect(update); Script.scriptEnding.connect(this.endGame); -} - - - +} \ No newline at end of file diff --git a/examples/example/solarsystem.js b/examples/example/solarsystem.js index 09ba2eec8d..8d1f0c81e3 100644 --- a/examples/example/solarsystem.js +++ b/examples/example/solarsystem.js @@ -52,9 +52,7 @@ var BOUNDS = 200; // Alert user to move if they are too close to domain bounds -if (MyAvatar.position.x < BOUNDS || MyAvatar.position.x > TREE_SCALE - BOUNDS - || MyAvatar.position.y < BOUNDS || MyAvatar.position.y > TREE_SCALE - BOUNDS - || MyAvatar.position.z < BOUNDS || MyAvatar.position.z > TREE_SCALE - BOUNDS) { +if (MyAvatar.position.x < BOUNDS || MyAvatar.position.x > TREE_SCALE - BOUNDS || MyAvatar.position.y < BOUNDS || MyAvatar.position.y > TREE_SCALE - BOUNDS || MyAvatar.position.z < BOUNDS || MyAvatar.position.z > TREE_SCALE - BOUNDS) { Window.alert("Please move at least 200m away from domain bounds."); return; } @@ -106,30 +104,70 @@ function initPlanets() { var T = (2.0 * Math.PI) * Math.sqrt(Math.pow(radius, 3.0) / (G * M)); if (i == 0) { - var color = {red: 255, green: 255, blue: 255}; + var color = { + red: 255, + green: 255, + blue: 255 + }; } else if (i == 1) { - var color = {red: 255, green: 160, blue: 110}; + var color = { + red: 255, + green: 160, + blue: 110 + }; } else if (i == 2) { - var color = {red: 10, green: 150, blue: 160}; + var color = { + red: 10, + green: 150, + blue: 160 + }; } else if (i == 3) { - var color = {red: 180, green: 70, blue: 10}; + var color = { + red: 180, + green: 70, + blue: 10 + }; } else if (i == 4) { - var color = {red: 250, green: 140, blue: 0}; + var color = { + red: 250, + green: 140, + blue: 0 + }; } else if (i == 5) { - var color = {red: 235, green: 215, blue: 0}; + var color = { + red: 235, + green: 215, + blue: 0 + }; } else if (i == 6) { - var color = {red:135, green: 205, blue: 240}; + var color = { + red: 135, + green: 205, + blue: 240 + }; } else if (i == 7) { - var color = {red:30, green: 140, blue: 255}; + var color = { + red: 30, + green: 140, + blue: 255 + }; } var prop = { radius: radius, - position: Vec3.sum(center, {x: radius, y: 0.0, z: 0.0}), + position: Vec3.sum(center, { + x: radius, + y: 0.0, + z: 0.0 + }), lineColor: color, period: T, dimensions: size, - velocity: Vec3.multiply(v0, Vec3.normalize({x: 0, y: -0.2, z: 0.9})) + velocity: Vec3.multiply(v0, Vec3.normalize({ + x: 0, + y: -0.2, + z: 0.9 + })) }; planet_properties.push(prop); @@ -194,27 +232,55 @@ function showLabels() { text = text + " Speed: " + Vec3.length(properties.velocity).toFixed(2); - var labelPos = Vec3.sum(planet_properties[i].position, {x: 0.0, y: LABEL_DIST, z: LABEL_DIST}); + var labelPos = Vec3.sum(planet_properties[i].position, { + x: 0.0, + y: LABEL_DIST, + z: LABEL_DIST + }); var linePos = planet_properties[i].position; - labelLines.push(Entities.addEntity( { + labelLines.push(Entities.addEntity({ type: "Line", position: linePos, - dimensions: {x: 20, y: 20, z: 20}, + dimensions: { + x: 20, + y: 20, + z: 20 + }, lineWidth: 3.0, - color: {red: 255, green: 255, blue: 255}, - linePoints: [{x: 0, y: 0, z: 0}, computeLocalPoint(linePos, labelPos)] + color: { + red: 255, + green: 255, + blue: 255 + }, + linePoints: [{ + x: 0, + y: 0, + z: 0 + }, computeLocalPoint(linePos, labelPos)] })); - labels.push(Entities.addEntity( { + labels.push(Entities.addEntity({ type: "Text", text: text, lineHeight: TEXT_HEIGHT, - dimensions: {x: LABEL_X, y: LABEL_Y, z: LABEL_Z}, + dimensions: { + x: LABEL_X, + y: LABEL_Y, + z: LABEL_Z + }, position: labelPos, - backgroundColor: {red: 10, green: 10, blue: 10}, - textColor: {red: 255, green: 255, blue: 255}, + backgroundColor: { + red: 10, + green: 10, + blue: 10 + }, + textColor: { + red: 255, + green: 255, + blue: 255 + }, faceCamera: true - })); + })); } } @@ -255,7 +321,7 @@ function update(deltaTime) { velocity: properties.velocity, position: properties.position }); - + // Create new or update current trail if (trailsEnabled) { @@ -285,11 +351,11 @@ function update(deltaTime) { } } } - + counter++; if (time % TIME_STEP == 0) { elapsed++; - } + } } function computeLocalPoint(linePos, worldPoint) { @@ -306,7 +372,7 @@ function getAcceleration(radius) { function resetTrails(planetIndex) { elapsed = 0.0; var properties = planet_properties[planetIndex]; - + var trail = []; var lineStack = []; @@ -333,10 +399,14 @@ function newLine(lineStack, point, period, color) { lineStack.push(line); } else { // Begin overwriting first lines after one full revolution (one period) - var firstLine = lineStack.shift(); + var firstLine = lineStack.shift(); Entities.editEntity(firstLine, { position: point, - linePoints: [{x: 0.0, y: 0.0, z: 0.0}] + linePoints: [{ + x: 0.0, + y: 0.0, + z: 0.0 + }] }); lineStack.push(firstLine); @@ -357,6 +427,7 @@ function calcEnergyError(planet, radius, v0, v, pos) { var error = ((measuredEnergy - totalEnergy) / totalEnergy) * 100; return error; } + function adjustVelocity(planet, pos) { var measuredPE = -(G * M * m) / Vec3.length(Vec3.subtract(center, pos)); return Math.sqrt(2 * (totalEnergy - measuredPE) / M); @@ -365,7 +436,11 @@ function adjustVelocity(planet, pos) { // Allow user to toggle pausing the model, switch to planet view var pauseButton = Overlays.addOverlay("text", { - backgroundColor: { red: 200, green: 200, blue: 255 }, + backgroundColor: { + red: 200, + green: 200, + blue: 255 + }, text: "Pause", x: PANEL_X, y: PANEL_Y - 30, @@ -379,22 +454,45 @@ var pauseButton = Overlays.addOverlay("text", { var paused = false; function mousePressEvent(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - if(clickedOverlay == pauseButton) { + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + if (clickedOverlay == pauseButton) { paused = !paused; for (var i = 0; i < NUM_PLANETS; ++i) { - Entities.editEntity(planets[i], { velocity: {x: 0.0, y: 0.0, z: 0.0} }); + Entities.editEntity(planets[i], { + velocity: { + x: 0.0, + y: 0.0, + z: 0.0 + } + }); } if (paused && !labelsShowing) { - Overlays.editOverlay(pauseButton, { text: "Paused", backgroundColor: {red: 255, green: 50, blue: 50} } ); + Overlays.editOverlay(pauseButton, { + text: "Paused", + backgroundColor: { + red: 255, + green: 50, + blue: 50 + } + }); showLabels(); } if (paused == false && labelsShowing) { - Overlays.editOverlay(pauseButton, { text: "Pause", backgroundColor: {red: 200, green: 200, blue: 255}}); + Overlays.editOverlay(pauseButton, { + text: "Pause", + backgroundColor: { + red: 200, + green: 200, + blue: 255 + } + }); hideLabels(); } planetView = false; - } + } } function keyPressEvent(event) { @@ -409,7 +507,7 @@ function keyPressEvent(event) { } function mouseDoublePressEvent(event) { - if(earthView) { + if (earthView) { return; } var pickRay = Camera.computePickRay(event.x, event.y) @@ -419,57 +517,68 @@ function mouseDoublePressEvent(event) { if (rayPickResult.entityID === labels[i]) { planetView = true; if (i == 2) { - MyAvatar.position = Vec3.sum(center, {x: 200, y: 200, z: 200}); - Camera.setPosition(Vec3.sum(center, {x: 200, y: 200, z: 200})); + MyAvatar.position = Vec3.sum(center, { + x: 200, + y: 200, + z: 200 + }); + Camera.setPosition(Vec3.sum(center, { + x: 200, + y: 200, + z: 200 + })); earthView = true; satelliteGame = new SatelliteGame(); - + } else { - MyAvatar.position = Vec3.sum({x: 0.0, y: 0.0, z: 3.0}, planet_properties[i].position); + MyAvatar.position = Vec3.sum({ + x: 0.0, + y: 0.0, + z: 3.0 + }, planet_properties[i].position); Camera.lookAt(planet_properties[i].position); } - break; - } - } + break; + } + } } - // Create UI panel var panel = new Panel(PANEL_X, PANEL_Y); var panelItems = []; var g_multiplier = 1.0; panelItems.push(panel.newSlider("Adjust Gravitational Force: ", 0.1, 5.0, - function (value) { + function(value) { g_multiplier = value; G = G_ref * g_multiplier; }, - function () { + function() { return g_multiplier; }, - function (value) { + function(value) { return value.toFixed(1) + "x"; })); var period_multiplier = 1.0; var last_alpha = period_multiplier; panelItems.push(panel.newSlider("Adjust Orbital Period: ", 0.1, 3.0, - function (value) { + function(value) { period_multiplier = value; changePeriod(period_multiplier); }, - function () { + function() { return period_multiplier; }, - function (value) { + function(value) { return (value).toFixed(2) + "x"; })); panelItems.push(panel.newCheckbox("Leave Trails: ", - function (value) { + function(value) { trailsEnabled = value; if (trailsEnabled) { for (var i = 0; i < NUM_PLANETS; ++i) { @@ -485,21 +594,21 @@ panelItems.push(panel.newCheckbox("Leave Trails: ", } } }, - function () { + function() { return trailsEnabled; }, - function (value) { + function(value) { return value; })); panelItems.push(panel.newCheckbox("Energy Error Calculations: ", - function (value) { + function(value) { energyConserved = value; }, - function () { + function() { return energyConserved; }, - function (value) { + function(value) { return value; })); @@ -519,7 +628,7 @@ function changePeriod(alpha) { // Clean up models, UI panels, lines, and button overlays function scriptEnding() { - + satelliteGame.endGame(); Entities.deleteEntity(theSun); @@ -536,7 +645,7 @@ function scriptEnding() { if (props.type === "Line" || props.type === "Text") { Entities.deleteEntity(e[i]); } - } + } }; @@ -549,7 +658,7 @@ Controller.mousePressEvent.connect(function panelMousePressEvent(event) { Controller.mouseDoublePressEvent.connect(function panelMouseDoublePressEvent(event) { return panel.mouseDoublePressEvent(event); }); -Controller.mouseReleaseEvent.connect(function (event) { +Controller.mouseReleaseEvent.connect(function(event) { return panel.mouseReleaseEvent(event); }); Controller.mousePressEvent.connect(mousePressEvent); diff --git a/examples/utilities/tools/vector.js b/examples/utilities/tools/vector.js index ab2e8cf200..0635b6cbc7 100644 --- a/examples/utilities/tools/vector.js +++ b/examples/utilities/tools/vector.js @@ -82,6 +82,13 @@ VectorArrow = function(distance, showStats, statsTitle, statsPosition) { } + var STATS_DIMENSIONS = { + x: 4.0, + y: 1.5, + z: 0.1 + }; + var TEXT_HEIGHT = 0.3; + this.onMousePressEvent = function(event) { this.newLine(computeWorldPoint(event)); @@ -90,12 +97,8 @@ VectorArrow = function(distance, showStats, statsTitle, statsPosition) { this.label = Entities.addEntity({ type: "Text", position: statsPosition, - dimensions: { - x: 4.0, - y: 1.5, - z: 0.1 - }, - lineHeight: 0.3, + dimensions: STATS_DIMENSIONS, + lineHeight: TEXT_HEIGHT, faceCamera: true }); } @@ -137,7 +140,7 @@ VectorArrow = function(distance, showStats, statsTitle, statsPosition) { rotation: rotate2 }); - this.magnitude = Vec3.length(localPoint) / 10.0; + this.magnitude = Vec3.length(localPoint) * 0.1; this.direction = Vec3.normalize(Vec3.subtract(worldPoint, linePosition)); if (this.showStats) { @@ -180,18 +183,4 @@ VectorArrow = function(distance, showStats, statsTitle, statsPosition) { return localPoint; } - - } - - - - - - - - - - - - From 1107742188a8cd878a65c2983f68d458648d0598 Mon Sep 17 00:00:00 2001 From: bwent Date: Tue, 28 Jul 2015 12:39:04 -0700 Subject: [PATCH 090/129] Clean up formatting for satellite.js --- examples/example/games/satellite.js | 468 ++++++++++++++-------------- 1 file changed, 234 insertions(+), 234 deletions(-) diff --git a/examples/example/games/satellite.js b/examples/example/games/satellite.js index 3ddce96aa5..f362c0c1e4 100644 --- a/examples/example/games/satellite.js +++ b/examples/example/games/satellite.js @@ -3,13 +3,13 @@ // games // // Created by Bridget Went 7/1/2015. -// Copyright 2015 High Fidelity, Inc. +// Copyright 2015 High Fidelity, Inc. // // A game to bring a satellite model into orbit around an animated earth model . -// - Double click to create a new satellite -// - Click on the satellite, drag a vector arrow to specify initial velocity -// - Release mouse to launch the active satellite -// - Orbital movement is calculated using equations of gravitational physics +// - Double click to create a new satellite +// - Click on the satellite, drag a vector arrow to specify initial velocity +// - Release mouse to launch the active satellite +// - Orbital movement is calculated using equations of gravitational physics // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -20,269 +20,269 @@ Script.include('../utilities/tools/vector.js'); var URL = "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/"; SatelliteGame = function() { - var MAX_RANGE = 50.0; - var Y_AXIS = { - x: 0, - y: 1, - z: 0 - } - var LIFETIME = 6000; - var ERROR_THRESH = 20.0; + var MAX_RANGE = 50.0; + var Y_AXIS = { + x: 0, + y: 1, + z: 0 + } + var LIFETIME = 6000; + var ERROR_THRESH = 20.0; - // Create the spinning earth model - var EARTH_SIZE = 20.0; - var CLOUDS_OFFSET = 0.5; - var SPIN = 0.1; - var ZONE_DIM = 100.0; - var LIGHT_INTENSITY = 1.5; + // Create the spinning earth model + var EARTH_SIZE = 20.0; + var CLOUDS_OFFSET = 0.5; + var SPIN = 0.1; + var ZONE_DIM = 100.0; + var LIGHT_INTENSITY = 1.5; - Earth = function(position, size) { - this.earth = Entities.addEntity({ - type: "Model", - shapeType: 'sphere', - modelURL: URL + "earth.fbx", - position: position, - dimensions: { - x: size, - y: size, - z: size - }, - rotation: Quat.angleAxis(180, { - x: 1, - y: 0, - z: 0 - }), - angularVelocity: { - x: 0.00, - y: 0.5 * SPIN, - z: 0.00 - }, - angularDamping: 0.0, - damping: 0.0, - ignoreCollisions: false, - lifetime: 6000, - collisionsWillMove: false, - visible: true - }); + Earth = function(position, size) { + this.earth = Entities.addEntity({ + type: "Model", + shapeType: 'sphere', + modelURL: URL + "earth.fbx", + position: position, + dimensions: { + x: size, + y: size, + z: size + }, + rotation: Quat.angleAxis(180, { + x: 1, + y: 0, + z: 0 + }), + angularVelocity: { + x: 0.00, + y: 0.5 * SPIN, + z: 0.00 + }, + angularDamping: 0.0, + damping: 0.0, + ignoreCollisions: false, + lifetime: 6000, + collisionsWillMove: false, + visible: true + }); - this.clouds = Entities.addEntity({ - type: "Model", - shapeType: 'sphere', - modelURL: URL + "clouds.fbx?i=2", - position: position, - dimensions: { - x: size + CLOUDS_OFFSET, - y: size + CLOUDS_OFFSET, - z: size + CLOUDS_OFFSET - }, - angularVelocity: { - x: 0.00, - y: SPIN, - z: 0.00 - }, - angularDamping: 0.0, - damping: 0.0, - ignoreCollisions: false, - lifetime: LIFETIME, - collisionsWillMove: false, - visible: true - }); + this.clouds = Entities.addEntity({ + type: "Model", + shapeType: 'sphere', + modelURL: URL + "clouds.fbx?i=2", + position: position, + dimensions: { + x: size + CLOUDS_OFFSET, + y: size + CLOUDS_OFFSET, + z: size + CLOUDS_OFFSET + }, + angularVelocity: { + x: 0.00, + y: SPIN, + z: 0.00 + }, + angularDamping: 0.0, + damping: 0.0, + ignoreCollisions: false, + lifetime: LIFETIME, + collisionsWillMove: false, + visible: true + }); - this.zone = Entities.addEntity({ - type: "Zone", - position: position, - dimensions: { - x: ZONE_DIM, - y: ZONE_DIM, - z: ZONE_DIM - }, - keyLightDirection: Vec3.normalize(Vec3.subtract(position, Camera.getPosition())), - keyLightIntensity: LIGHT_INTENSITY - }); + this.zone = Entities.addEntity({ + type: "Zone", + position: position, + dimensions: { + x: ZONE_DIM, + y: ZONE_DIM, + z: ZONE_DIM + }, + keyLightDirection: Vec3.normalize(Vec3.subtract(position, Camera.getPosition())), + keyLightIntensity: LIGHT_INTENSITY + }); - this.cleanup = function() { - Entities.deleteEntity(this.clouds); - Entities.deleteEntity(this.earth); - Entities.deleteEntity(this.zone); - } - } + this.cleanup = function() { + Entities.deleteEntity(this.clouds); + Entities.deleteEntity(this.earth); + Entities.deleteEntity(this.zone); + } + } - // Create earth model - var center = Vec3.sum(Camera.getPosition(), Vec3.multiply(MAX_RANGE, Quat.getFront(Camera.getOrientation()))); - var distance = Vec3.length(Vec3.subtract(center, Camera.getPosition())); - var earth = new Earth(center, EARTH_SIZE); + // Create earth model + var center = Vec3.sum(Camera.getPosition(), Vec3.multiply(MAX_RANGE, Quat.getFront(Camera.getOrientation()))); + var distance = Vec3.length(Vec3.subtract(center, Camera.getPosition())); + var earth = new Earth(center, EARTH_SIZE); - var satellites = []; - var SATELLITE_SIZE = 2.0; - var launched = false; - var activeSatellite; + var satellites = []; + var SATELLITE_SIZE = 2.0; + var launched = false; + var activeSatellite; var PERIOD = 4.0; var LARGE_BODY_MASS = 16000.0; var SMALL_BODY_MASS = LARGE_BODY_MASS * 0.000000333; - Satellite = function(position, planetCenter) { - // The Satellite class + Satellite = function(position, planetCenter) { + // The Satellite class - this.launched = false; - this.startPosition = position; - this.readyToLaunch = false; - this.radius = Vec3.length(Vec3.subtract(position, planetCenter)); + this.launched = false; + this.startPosition = position; + this.readyToLaunch = false; + this.radius = Vec3.length(Vec3.subtract(position, planetCenter)); - this.satellite = Entities.addEntity({ - type: "Model", - modelURL: "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/satellite/satellite.fbx", - position: this.startPosition, - dimensions: { - x: SATELLITE_SIZE, - y: SATELLITE_SIZE, - z: SATELLITE_SIZE - }, - angularDamping: 0.0, - damping: 0.0, - ignoreCollisions: false, - lifetime: LIFETIME, - collisionsWillMove: false, - }); + this.satellite = Entities.addEntity({ + type: "Model", + modelURL: "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/satellite/satellite.fbx", + position: this.startPosition, + dimensions: { + x: SATELLITE_SIZE, + y: SATELLITE_SIZE, + z: SATELLITE_SIZE + }, + angularDamping: 0.0, + damping: 0.0, + ignoreCollisions: false, + lifetime: LIFETIME, + collisionsWillMove: false, + }); - this.getProperties = function() { - return Entities.getEntityProperties(this.satellite); - } + this.getProperties = function() { + return Entities.getEntityProperties(this.satellite); + } - this.launch = function() { - var prop = Entities.getEntityProperties(this.satellite); - var between = Vec3.subtract(planetCenter, prop.position); - var radius = Vec3.length(between); - this.gravity = (4.0 * Math.PI * Math.PI * Math.pow(radius, 3.0)) / (LARGE_BODY_MASS * PERIOD * PERIOD); + this.launch = function() { + var prop = Entities.getEntityProperties(this.satellite); + var between = Vec3.subtract(planetCenter, prop.position); + var radius = Vec3.length(between); + this.gravity = (4.0 * Math.PI * Math.PI * Math.pow(radius, 3.0)) / (LARGE_BODY_MASS * PERIOD * PERIOD); - var initialVelocity = Vec3.normalize(Vec3.cross(between, Y_AXIS)); - initialVelocity = Vec3.multiply(Math.sqrt((this.gravity * LARGE_BODY_MASS) / radius), initialVelocity); - initialVelocity = Vec3.multiply(this.arrow.magnitude, initialVelocity); - initialVelocity = Vec3.multiply(Vec3.length(initialVelocity), this.arrow.direction); + var initialVelocity = Vec3.normalize(Vec3.cross(between, Y_AXIS)); + initialVelocity = Vec3.multiply(Math.sqrt((this.gravity * LARGE_BODY_MASS) / radius), initialVelocity); + initialVelocity = Vec3.multiply(this.arrow.magnitude, initialVelocity); + initialVelocity = Vec3.multiply(Vec3.length(initialVelocity), this.arrow.direction); - Entities.editEntity(this.satellite, { - velocity: initialVelocity - }); - this.launched = true; - }; + Entities.editEntity(this.satellite, { + velocity: initialVelocity + }); + this.launched = true; + }; - this.update = function(deltaTime) { - var prop = Entities.getEntityProperties(this.satellite); - var between = Vec3.subtract(prop.position, planetCenter); - var radius = Vec3.length(between); - var acceleration = -(this.gravity * LARGE_BODY_MASS) * Math.pow(radius, (-2.0)); - var speed = acceleration * deltaTime; - var vel = Vec3.multiply(speed, Vec3.normalize(between)); + this.update = function(deltaTime) { + var prop = Entities.getEntityProperties(this.satellite); + var between = Vec3.subtract(prop.position, planetCenter); + var radius = Vec3.length(between); + var acceleration = -(this.gravity * LARGE_BODY_MASS) * Math.pow(radius, (-2.0)); + var speed = acceleration * deltaTime; + var vel = Vec3.multiply(speed, Vec3.normalize(between)); - var newVelocity = Vec3.sum(prop.velocity, vel); - var newPos = Vec3.sum(prop.position, Vec3.multiply(newVelocity, deltaTime)); + var newVelocity = Vec3.sum(prop.velocity, vel); + var newPos = Vec3.sum(prop.position, Vec3.multiply(newVelocity, deltaTime)); - Entities.editEntity(this.satellite, { - velocity: newVelocity, - position: newPos - }); - }; - } + Entities.editEntity(this.satellite, { + velocity: newVelocity, + position: newPos + }); + }; + } - function mouseDoublePressEvent(event) { - var pickRay = Camera.computePickRay(event.x, event.y); - var addVector = Vec3.multiply(pickRay.direction, distance); - var point = Vec3.sum(Camera.getPosition(), addVector); + function mouseDoublePressEvent(event) { + var pickRay = Camera.computePickRay(event.x, event.y); + var addVector = Vec3.multiply(pickRay.direction, distance); + var point = Vec3.sum(Camera.getPosition(), addVector); - // Create a new satellite - activeSatellite = new Satellite(point, center); - satellites.push(activeSatellite); - } + // Create a new satellite + activeSatellite = new Satellite(point, center); + satellites.push(activeSatellite); + } - function mousePressEvent(event) { - if (!activeSatellite) { - return; - } - // Reset label - if (activeSatellite.arrow) { - activeSatellite.arrow.deleteLabel(); - } - var statsPosition = Vec3.sum(Camera.getPosition(), Vec3.multiply(MAX_RANGE * 0.4, Quat.getFront(Camera.getOrientation()))); - var pickRay = Camera.computePickRay(event.x, event.y) - var rayPickResult = Entities.findRayIntersection(pickRay, true); - if (rayPickResult.entityID === activeSatellite.satellite) { - // Create a draggable vector arrow at satellite position - activeSatellite.arrow = new VectorArrow(distance, true, "INITIAL VELOCITY", statsPosition); - activeSatellite.arrow.onMousePressEvent(event); - activeSatellite.arrow.isDragging = true; - } - } + function mousePressEvent(event) { + if (!activeSatellite) { + return; + } + // Reset label + if (activeSatellite.arrow) { + activeSatellite.arrow.deleteLabel(); + } + var statsPosition = Vec3.sum(Camera.getPosition(), Vec3.multiply(MAX_RANGE * 0.4, Quat.getFront(Camera.getOrientation()))); + var pickRay = Camera.computePickRay(event.x, event.y) + var rayPickResult = Entities.findRayIntersection(pickRay, true); + if (rayPickResult.entityID === activeSatellite.satellite) { + // Create a draggable vector arrow at satellite position + activeSatellite.arrow = new VectorArrow(distance, true, "INITIAL VELOCITY", statsPosition); + activeSatellite.arrow.onMousePressEvent(event); + activeSatellite.arrow.isDragging = true; + } + } - function mouseMoveEvent(event) { - if (!activeSatellite || !activeSatellite.arrow || !activeSatellite.arrow.isDragging) { - return; - } - activeSatellite.arrow.onMouseMoveEvent(event); - } + function mouseMoveEvent(event) { + if (!activeSatellite || !activeSatellite.arrow || !activeSatellite.arrow.isDragging) { + return; + } + activeSatellite.arrow.onMouseMoveEvent(event); + } - function mouseReleaseEvent(event) { - if (!activeSatellite || !activeSatellite.arrow || !activeSatellite.arrow.isDragging) { - return; - } - activeSatellite.arrow.onMouseReleaseEvent(event); - activeSatellite.launch(); - activeSatellite.arrow.cleanup(); - } + function mouseReleaseEvent(event) { + if (!activeSatellite || !activeSatellite.arrow || !activeSatellite.arrow.isDragging) { + return; + } + activeSatellite.arrow.onMouseReleaseEvent(event); + activeSatellite.launch(); + activeSatellite.arrow.cleanup(); + } - var counter = 0.0; - var CHECK_ENERGY_PERIOD = 500; + var counter = 0.0; + var CHECK_ENERGY_PERIOD = 500; - function update(deltaTime) { - if (!activeSatellite) { - return; - } - // Update all satellites - for (var i = 0; i < satellites.length; i++) { - if (!satellites[i].launched) { - continue; - } - satellites[i].update(deltaTime); - } + function update(deltaTime) { + if (!activeSatellite) { + return; + } + // Update all satellites + for (var i = 0; i < satellites.length; i++) { + if (!satellites[i].launched) { + continue; + } + satellites[i].update(deltaTime); + } - counter++; - if (counter % CHECK_ENERGY_PERIOD == 0) { - var prop = activeSatellite.getProperties(); - var error = calcEnergyError(prop.position, Vec3.length(prop.velocity)); - if (Math.abs(error) <= ERROR_THRESH) { - activeSatellite.arrow.editLabel("Nice job! The satellite has reached a stable orbit."); - } else { - activeSatellite.arrow.editLabel("Try again! The satellite is in an unstable orbit."); - } - } - } + counter++; + if (counter % CHECK_ENERGY_PERIOD == 0) { + var prop = activeSatellite.getProperties(); + var error = calcEnergyError(prop.position, Vec3.length(prop.velocity)); + if (Math.abs(error) <= ERROR_THRESH) { + activeSatellite.arrow.editLabel("Nice job! The satellite has reached a stable orbit."); + } else { + activeSatellite.arrow.editLabel("Try again! The satellite is in an unstable orbit."); + } + } + } - this.endGame = function() { - for (var i = 0; i < satellites.length; i++) { - Entities.deleteEntity(satellites[i].satellite); - satellites[i].arrow.cleanup(); - } - earth.cleanup(); - } + this.endGame = function() { + for (var i = 0; i < satellites.length; i++) { + Entities.deleteEntity(satellites[i].satellite); + satellites[i].arrow.cleanup(); + } + earth.cleanup(); + } - function calcEnergyError(pos, vel) { - //Calculate total energy error for active satellite's orbital motion - var radius = activeSatellite.radius; - var gravity = (4.0 * Math.PI * Math.PI * Math.pow(radius, 3.0)) / (LARGE_BODY_MASS * PERIOD * PERIOD); - var initialVelocityCalculated = Math.sqrt((gravity * LARGE_BODY_MASS) / radius); + function calcEnergyError(pos, vel) { + //Calculate total energy error for active satellite's orbital motion + var radius = activeSatellite.radius; + var gravity = (4.0 * Math.PI * Math.PI * Math.pow(radius, 3.0)) / (LARGE_BODY_MASS * PERIOD * PERIOD); + var initialVelocityCalculated = Math.sqrt((gravity * LARGE_BODY_MASS) / radius); - var totalEnergy = 0.5 * LARGE_BODY_MASS * Math.pow(initialVelocityCalculated, 2.0) - ((gravity * LARGE_BODY_MASS * SMALL_BODY_MASS) / radius); - var measuredEnergy = 0.5 * LARGE_BODY_MASS * Math.pow(vel, 2.0) - ((gravity * LARGE_BODY_MASS * SMALL_BODY_MASS) / Vec3.length(Vec3.subtract(pos, center))); - var error = ((measuredEnergy - totalEnergy) / totalEnergy) * 100; - return error; - } + var totalEnergy = 0.5 * LARGE_BODY_MASS * Math.pow(initialVelocityCalculated, 2.0) - ((gravity * LARGE_BODY_MASS * SMALL_BODY_MASS) / radius); + var measuredEnergy = 0.5 * LARGE_BODY_MASS * Math.pow(vel, 2.0) - ((gravity * LARGE_BODY_MASS * SMALL_BODY_MASS) / Vec3.length(Vec3.subtract(pos, center))); + var error = ((measuredEnergy - totalEnergy) / totalEnergy) * 100; + return error; + } - Controller.mousePressEvent.connect(mousePressEvent); - Controller.mouseDoublePressEvent.connect(mouseDoublePressEvent); - Controller.mouseMoveEvent.connect(mouseMoveEvent); - Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - Script.update.connect(update); - Script.scriptEnding.connect(this.endGame); + Controller.mousePressEvent.connect(mousePressEvent); + Controller.mouseDoublePressEvent.connect(mouseDoublePressEvent); + Controller.mouseMoveEvent.connect(mouseMoveEvent); + Controller.mouseReleaseEvent.connect(mouseReleaseEvent); + Script.update.connect(update); + Script.scriptEnding.connect(this.endGame); } \ No newline at end of file From 34d63cdb43eceef33bd8ed4b66e06aae698ec2d1 Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Tue, 28 Jul 2015 22:02:36 +0200 Subject: [PATCH 091/129] Removed double "" --- interface/src/Menu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 0edd93c5a6..6487e6cac5 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -161,7 +161,7 @@ namespace MenuOption { const QString CenterPlayerInView = "Center Player In View"; const QString Chat = "Chat..."; const QString Collisions = "Collisions"; - const QString Connexion = "Activate 3D Connexion Devices""; + const QString Connexion = "Activate 3D Connexion Devices"; const QString Console = "Console..."; const QString ControlWithSpeech = "Control With Speech"; const QString CopyAddress = "Copy Address to Clipboard"; From 0b25fc335e84e43b75e9ed61ed6998b46ed0fec8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 28 Jul 2015 13:21:29 -0700 Subject: [PATCH 092/129] Cleanup edit.js entity creation --- examples/edit.js | 228 ++++++++++++++++++++++------------------------- 1 file changed, 106 insertions(+), 122 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index a07779c19d..0f9c9fc4dd 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -291,22 +291,18 @@ var toolBar = (function () { var RESIZE_TIMEOUT = 120000; // 2 minutes var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL; function addModel(url) { - var position; + var entityID = createNewEntity({ + type: "Model", + dimensions: DEFAULT_DIMENSIONS, + modelURL: url + }, false); - position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - var entityId = Entities.addEntity({ - type: "Model", - position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS), - dimensions: DEFAULT_DIMENSIONS, - modelURL: url - }); + if (entityID) { print("Model added: " + url); var checkCount = 0; function resize() { - var entityProperties = Entities.getEntityProperties(entityId); + var entityProperties = Entities.getEntityProperties(entityID); var naturalDimensions = entityProperties.naturalDimensions; checkCount++; @@ -318,21 +314,41 @@ var toolBar = (function () { print("Resize failed: timed out waiting for model (" + url + ") to load"); } } else { - Entities.editEntity(entityId, { dimensions: naturalDimensions }); + Entities.editEntity(entityID, { dimensions: naturalDimensions }); // Reset selection so that the selection overlays will be updated - selectionManager.setSelections([entityId]); + selectionManager.setSelections([entityID]); } } - selectionManager.setSelections([entityId]); + selectionManager.setSelections([entityID]); Script.setTimeout(resize, RESIZE_INTERVAL); - } else { - Window.alert("Can't add model: Model would be out of bounds."); } } + function createNewEntity(properties, dragOnCreate) { + // Default to true if not passed in + dragOnCreate = dragOnCreate == undefined ? true : dragOnCreate; + + var dimensions = properties.dimensions ? properties.dimensions : DEFAULT_DIMENSIONS; + var position = getPositionToCreateEntity(); + var entityID = null; + if (position != null) { + position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions), + properties.position = position; + + entityID = Entities.addEntity(properties); + if (dragOnCreate) { + placingEntityID = entityID; + } + } else { + Window.alert("Can't create " + properties.type + ": " + properties.type + " would be out of bounds."); + } + + return entityID; + } + var newModelButtonDown = false; var browseMarketplaceButtonDown = false; that.mousePressEvent = function (event) { @@ -363,127 +379,82 @@ var toolBar = (function () { } if (newCubeButton === toolBar.clicked(clickedOverlay)) { - var position = getPositionToCreateEntity(); + createNewEntity({ + type: "Box", + dimensions: DEFAULT_DIMENSIONS, + color: { red: 255, green: 0, blue: 0 } + }); - if (position.x > 0 && position.y > 0 && position.z > 0) { - placingEntityID = Entities.addEntity({ - type: "Box", - position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS), - dimensions: DEFAULT_DIMENSIONS, - color: { red: 255, green: 0, blue: 0 } - - }); - } else { - Window.alert("Can't create box: Box would be out of bounds."); - } return true; } if (newSphereButton === toolBar.clicked(clickedOverlay)) { - var position = getPositionToCreateEntity(); + createNewEntity({ + type: "Sphere", + dimensions: DEFAULT_DIMENSIONS, + color: { red: 255, green: 0, blue: 0 } + }); - if (position.x > 0 && position.y > 0 && position.z > 0) { - placingEntityID = Entities.addEntity({ - type: "Sphere", - position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS), - dimensions: DEFAULT_DIMENSIONS, - color: { red: 255, green: 0, blue: 0 } - }); - } else { - Window.alert("Can't create sphere: Sphere would be out of bounds."); - } return true; } if (newLightButton === toolBar.clicked(clickedOverlay)) { - var position = getPositionToCreateEntity(); + createNewEntity({ + type: "Light", + dimensions: DEFAULT_LIGHT_DIMENSIONS, + isSpotlight: false, + color: { red: 150, green: 150, blue: 150 }, - if (position.x > 0 && position.y > 0 && position.z > 0) { - placingEntityID = Entities.addEntity({ - type: "Light", - position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_LIGHT_DIMENSIONS), DEFAULT_LIGHT_DIMENSIONS), - dimensions: DEFAULT_LIGHT_DIMENSIONS, - isSpotlight: false, - color: { red: 150, green: 150, blue: 150 }, + constantAttenuation: 1, + linearAttenuation: 0, + quadraticAttenuation: 0, + exponent: 0, + cutoff: 180, // in degrees + }); - constantAttenuation: 1, - linearAttenuation: 0, - quadraticAttenuation: 0, - exponent: 0, - cutoff: 180, // in degrees - }); - } else { - Window.alert("Can't create Light: Light would be out of bounds."); - } return true; } - if (newTextButton === toolBar.clicked(clickedOverlay)) { - var position = getPositionToCreateEntity(); + createNewEntity({ + type: "Text", + dimensions: { x: 0.65, y: 0.3, z: 0.01 }, + backgroundColor: { red: 64, green: 64, blue: 64 }, + textColor: { red: 255, green: 255, blue: 255 }, + text: "some text", + lineHeight: 0.06 + }); - if (position.x > 0 && position.y > 0 && position.z > 0) { - placingEntityID = Entities.addEntity({ - type: "Text", - position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS), - dimensions: { x: 0.65, y: 0.3, z: 0.01 }, - backgroundColor: { red: 64, green: 64, blue: 64 }, - textColor: { red: 255, green: 255, blue: 255 }, - text: "some text", - lineHeight: 0.06 - }); - } else { - Window.alert("Can't create box: Text would be out of bounds."); - } return true; } if (newWebButton === toolBar.clicked(clickedOverlay)) { - var position = getPositionToCreateEntity(); + createNewEntity({ + type: "Web", + dimensions: { x: 1.6, y: 0.9, z: 0.01 }, + sourceUrl: "https://highfidelity.com/", + }); - if (position.x > 0 && position.y > 0 && position.z > 0) { - placingEntityID = Entities.addEntity({ - type: "Web", - position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS), - dimensions: { x: 1.6, y: 0.9, z: 0.01 }, - sourceUrl: "https://highfidelity.com/", - }); - } else { - Window.alert("Can't create Web Entity: would be out of bounds."); - } return true; } if (newZoneButton === toolBar.clicked(clickedOverlay)) { - var position = getPositionToCreateEntity(); + createNewEntity({ + type: "Zone", + dimensions: { x: 10, y: 10, z: 10 }, + }); - if (position.x > 0 && position.y > 0 && position.z > 0) { - placingEntityID = Entities.addEntity({ - type: "Zone", - position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS), - dimensions: { x: 10, y: 10, z: 10 }, - }); - } else { - Window.alert("Can't create box: Text would be out of bounds."); - } return true; } if (newPolyVoxButton === toolBar.clicked(clickedOverlay)) { - var position = getPositionToCreateEntity(); + createNewEntity({ + type: "PolyVox", + dimensions: { x: 10, y: 10, z: 10 }, + voxelVolumeSize: {x:16, y:16, z:16}, + voxelSurfaceStyle: 1 + }); - if (position.x > 0 && position.y > 0 && position.z > 0) { - placingEntityID = Entities.addEntity({ - type: "PolyVox", - position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), - DEFAULT_DIMENSIONS), - dimensions: { x: 10, y: 10, z: 10 }, - voxelVolumeSize: {x:16, y:16, z:16}, - voxelSurfaceStyle: 1 - }); - } else { - Window.alert("Can't create PolyVox: would be out of bounds."); - } return true; } @@ -666,7 +637,7 @@ function handleIdleMouse() { idleMouseTimerId = null; if (isActive) { highlightEntityUnderCursor(lastMousePosition, true); - } + } } function highlightEntityUnderCursor(position, accurateRay) { @@ -837,15 +808,15 @@ function setupModelMenus() { } Menu.addMenuItem({ menuName: "Edit", menuItemName: "Entity List...", shortcutKey: "CTRL+META+L", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", afterItem: "Entity List...", isCheckable: true, isChecked: true }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", afterItem: "Allow Selecting of Large Models", isCheckable: true, isChecked: true }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L", + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L", afterItem: "Allow Selecting of Small Models", isCheckable: true }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities In Box", shortcutKey: "CTRL+SHIFT+META+A", + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities In Box", shortcutKey: "CTRL+SHIFT+META+A", afterItem: "Allow Selecting of Lights" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities Touching Box", shortcutKey: "CTRL+SHIFT+META+T", + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities Touching Box", shortcutKey: "CTRL+SHIFT+META+T", afterItem: "Select All Entities In Box" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); @@ -962,7 +933,7 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) { entities.splice(i, 1); --i; } - } + } } selectionManager.setSelections(entities); } @@ -1038,17 +1009,29 @@ function handeMenuEvent(menuItem) { tooltip.show(false); } +// This function tries to find a reasonable position to place a new entity based on the camera +// position. If a reasonable position within the world bounds can't be found, `null` will +// be returned. The returned position will also take into account grid snapping settings. function getPositionToCreateEntity() { var distance = cameraManager.enabled ? cameraManager.zoomDistance : DEFAULT_ENTITY_DRAG_DROP_DISTANCE; var direction = Quat.getFront(Camera.orientation); var offset = Vec3.multiply(distance, direction); - var position = Vec3.sum(Camera.position, offset); + var placementPosition = Vec3.sum(Camera.position, offset); - position.x = Math.max(0, position.x); - position.y = Math.max(0, position.y); - position.z = Math.max(0, position.z); + var cameraPosition = Camera.position; - return position; + var cameraOutOfBounds = cameraPosition.x < 0 || cameraPosition.y < 0 || cameraPosition.z < 0; + var placementOutOfBounds = placementPosition.x < 0 || placementPosition.y < 0 || placementPosition.z < 0; + + if (cameraOutOfBounds && placementOutOfBounds) { + return null; + } + + placementPosition.x = Math.max(0, placementPosition.x); + placementPosition.y = Math.max(0, placementPosition.y); + placementPosition.z = Math.max(0, placementPosition.z); + + return placementPosition; } function importSVO(importURL) { @@ -1064,16 +1047,17 @@ function importSVO(importURL) { if (success) { var VERY_LARGE = 10000; - var position = { x: 0.01, y: 0.01, z: 0.01}; + var position = { x: 0, y: 0, z: 0 }; if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) { position = getPositionToCreateEntity(); } - if (position.x > 0 && position.y > 0 && position.z > 0) { + if (position != null) { var pastedEntityIDs = Clipboard.pasteEntities(position); if (isActive) { selectionManager.setSelections(pastedEntityIDs); } + Window.raiseMainWindow(); } else { Window.alert("Can't import objects: objects would be out of bounds."); @@ -1264,7 +1248,7 @@ PropertiesTool = function(opts) { if (data.properties.keyLightDirection !== undefined) { data.properties.keyLightDirection = Vec3.fromPolar( data.properties.keyLightDirection.x * DEGREES_TO_RADIANS, data.properties.keyLightDirection.y * DEGREES_TO_RADIANS); - } + } Entities.editEntity(selectionManager.selections[0], data.properties); if (data.properties.name != undefined) { entityListTool.sendUpdate(); @@ -1360,8 +1344,8 @@ PropertiesTool = function(opts) { var properties = selectionManager.savedProperties[selectionManager.selections[i]]; if (properties.type == "Zone") { var centerOfZone = properties.boundingBox.center; - var atmosphereCenter = { x: centerOfZone.x, - y: centerOfZone.y - properties.atmosphere.innerRadius, + var atmosphereCenter = { x: centerOfZone.x, + y: centerOfZone.y - properties.atmosphere.innerRadius, z: centerOfZone.z }; Entities.editEntity(selectionManager.selections[i], { From df9b66d2679c3740c8d885d5d02c2e37ea098e22 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 28 Jul 2015 15:08:52 -0700 Subject: [PATCH 093/129] Implement the uniform buffer and resource texture cache and their reset --- libraries/gpu/src/gpu/GLBackend.h | 30 +++++-- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 86 +++++++++++++++++++-- 2 files changed, 103 insertions(+), 13 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 843e5d2006..215e01689b 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -197,6 +197,15 @@ public: uint32 getNumInputBuffers() const { return _input._invalidBuffers.size(); } + // this is the maximum per shader stage on the low end apple + // TODO make it platform dependant at init time + static const int MAX_NUM_UNIFORM_BUFFERS = 12; + uint32 getMaxNumUniformBuffers() const { return MAX_NUM_UNIFORM_BUFFERS; } + + // this is the maximum per shader stage on the low end apple + // TODO make it platform dependant at init time + static const int MAX_NUM_RESOURCE_TEXTURES = 16; + uint32 getMaxNumResourceTextures() const { return MAX_NUM_RESOURCE_TEXTURES; } // The State setters called by the GLState::Commands when a new state is assigned void do_setStateFillMode(int32 mode); @@ -332,19 +341,30 @@ protected: // Uniform Stage void do_setUniformBuffer(Batch& batch, uint32 paramOffset); - + + void releaseUniformBuffer(int slot); void resetUniformStage(); struct UniformStageState { - - }; + Buffers _buffers; + + UniformStageState(): + _buffers(MAX_NUM_UNIFORM_BUFFERS, nullptr) + {} + } _uniform; // Resource Stage void do_setResourceTexture(Batch& batch, uint32 paramOffset); + void releaseResourceTexture(int slot); void resetResourceStage(); struct ResourceStageState { - - }; + Textures _textures; + + ResourceStageState(): + _textures(MAX_NUM_RESOURCE_TEXTURES, nullptr) + {} + + } _resource; // Pipeline Stage void do_setPipeline(Batch& batch, uint32 paramOffset); diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 4a54753af8..090dd4ad31 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -178,8 +178,27 @@ void GLBackend::resetPipelineStage() { glUseProgram(0); } + +void GLBackend::releaseUniformBuffer(int slot) { +#if (GPU_FEATURE_PROFILE == GPU_CORE) + auto& buf = _uniform._buffers[slot]; + if (buf) { + auto* object = Backend::getGPUObject(*buf); + if (object) { + GLuint bo = object->_buffer; + glBindBufferBase(GL_UNIFORM_BUFFER, slot, 0); // RELEASE + + (void) CHECK_GL_ERROR(); + } + buf.reset(); + } +#endif +} + void GLBackend::resetUniformStage() { - + for (int i = 0; i < _uniform._buffers.size(); i++) { + releaseUniformBuffer(i); + } } void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { @@ -188,9 +207,31 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { GLintptr rangeStart = batch._params[paramOffset + 1]._uint; GLsizeiptr rangeSize = batch._params[paramOffset + 0]._uint; + + + #if (GPU_FEATURE_PROFILE == GPU_CORE) - GLuint bo = getBufferID(*uniformBuffer); - glBindBufferRange(GL_UNIFORM_BUFFER, slot, bo, rangeStart, rangeSize); + if (!uniformBuffer) { + releaseUniformBuffer(slot); + return; + } + + // check cache before thinking + if (_uniform._buffers[slot] == uniformBuffer) { + return; + } + + // Sync BufferObject + auto* object = GLBackend::syncGPUObject(*uniformBuffer); + if (object) { + glBindBufferRange(GL_UNIFORM_BUFFER, slot, object->_buffer, rangeStart, rangeSize); + + _uniform._buffers[slot] = uniformBuffer; + (void) CHECK_GL_ERROR(); + } else { + releaseResourceTexture(slot); + return; + } #else // because we rely on the program uniform mechanism we need to have // the program bound, thank you MacOSX Legacy profile. @@ -202,23 +243,49 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { // NOT working so we ll stick to the uniform float array until we move to core profile // GLuint bo = getBufferID(*uniformBuffer); //glUniformBufferEXT(_shader._program, slot, bo); -#endif + (void) CHECK_GL_ERROR(); + +#endif +} + +void GLBackend::releaseResourceTexture(int slot) { + auto& tex = _resource._textures[slot]; + if (tex) { + auto* object = Backend::getGPUObject(*tex); + if (object) { + GLuint to = object->_texture; + GLuint target = object->_target; + glActiveTexture(GL_TEXTURE0 + slot); + glBindTexture(target, 0); // RELEASE + + (void) CHECK_GL_ERROR(); + } + tex.reset(); + } } void GLBackend::resetResourceStage() { - + for (int i = 0; i < _resource._textures.size(); i++) { + releaseResourceTexture(i); + } } void GLBackend::do_setResourceTexture(Batch& batch, uint32 paramOffset) { GLuint slot = batch._params[paramOffset + 1]._uint; - TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); + TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); - if (!uniformTexture) { + if (!resourceTexture) { + releaseResourceTexture(slot); + return; + } + // check cache before thinking + if (_resource._textures[slot] == resourceTexture) { return; } - GLTexture* object = GLBackend::syncGPUObject(*uniformTexture); + // Always make sure the GLObject is in sync + GLTexture* object = GLBackend::syncGPUObject(*resourceTexture); if (object) { GLuint to = object->_texture; GLuint target = object->_target; @@ -227,7 +294,10 @@ void GLBackend::do_setResourceTexture(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); + _resource._textures[slot] = resourceTexture; + } else { + releaseResourceTexture(slot); return; } } From 469bace7ca4ec8d00ce2f6453f2d1d61df613e65 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 28 Jul 2015 15:15:34 -0700 Subject: [PATCH 094/129] removed unnessary computations from hit effect fragment shader --- libraries/render-utils/src/hit_effect.slf | 18 ++++++------------ libraries/render-utils/src/hit_effect.slv | 5 ++++- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/libraries/render-utils/src/hit_effect.slf b/libraries/render-utils/src/hit_effect.slf index 2c308f3711..6c0dcd7a70 100644 --- a/libraries/render-utils/src/hit_effect.slf +++ b/libraries/render-utils/src/hit_effect.slf @@ -11,20 +11,14 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> + <@include DeferredBufferWrite.slh@> -void main(void) { +varying vec2 varQuadPosition; - TransformCamera cam = getTransformCamera(); - vec4 myViewport; - <$transformCameraViewport(cam, myViewport)$> - vec2 center = vec2(myViewport.z/2.0, myViewport.w/2.0); - float distFromCenter = distance(center, gl_FragCoord.xy); - //normalize distance from center based on average of screen width and height - float normalizationFactor = (myViewport.z + myViewport.w)/2.0; - distFromCenter = distFromCenter/normalizationFactor; - float alpha = mix(0.0, 1.0, pow(distFromCenter, 1.5)); +void main(void) { + vec2 center = vec2(0.0, 0.0); + float distFromCenter = distance( vec2(0.0, 0.0), varQuadPosition); + float alpha = mix(0.0, 0.5, pow(distFromCenter,5.)); gl_FragColor = vec4(1.0, 0.0, 0.0, alpha); } \ No newline at end of file diff --git a/libraries/render-utils/src/hit_effect.slv b/libraries/render-utils/src/hit_effect.slv index e7c3062667..d1efdebc18 100644 --- a/libraries/render-utils/src/hit_effect.slv +++ b/libraries/render-utils/src/hit_effect.slv @@ -16,6 +16,9 @@ <$declareStandardTransform()$> +varying vec2 varQuadPosition; + void main(void) { - gl_Position = gl_Vertex; + varQuadPosition = gl_Vertex.xy; + gl_Position = gl_Vertex; } \ No newline at end of file From 8b20f9d3a68a31450c95a6dbb90f51aa9fca8837 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 28 Jul 2015 15:48:01 -0700 Subject: [PATCH 095/129] do the minimum include to use glew on linux --- libraries/gpu/src/gpu/GLBackend.cpp | 7 +++++++ libraries/gpu/src/gpu/GPUConfig.h | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 6b1d552be9..3942af4f84 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -115,6 +115,13 @@ GLBackend::GLBackend() : #endif #if defined(Q_OS_LINUX) + GLenum err = glewInit(); + if (GLEW_OK != err) { + /* Problem: glewInit failed, something is seriously wrong. */ + qCDebug(gpulogging, "Error: %s\n", glewGetErrorString(err)); + } + qCDebug(gpulogging, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); + // TODO: Write the correct code for Linux... /* if (wglewGetExtension("WGL_EXT_swap_control")) { int swapInterval = wglGetSwapIntervalEXT(); diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h index 1d092dbc6a..a9657076fa 100644 --- a/libraries/gpu/src/gpu/GPUConfig.h +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -34,8 +34,11 @@ #elif defined(ANDROID) #else -#include -#include + +#include +#include +//#include +//#include #define GPU_FEATURE_PROFILE GPU_LEGACY #define GPU_TRANSFORM_PROFILE GPU_LEGACY From 9cf3dfd3f7ef47469f87773daac5de87fba2b90f Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 28 Jul 2015 15:49:39 -0700 Subject: [PATCH 096/129] test this on windows ? --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b7522633ba..8f0a0e864f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1014,7 +1014,7 @@ void Application::paintGL() { // Back to the default framebuffer; gpu::Batch batch; batch.resetStages(); - renderArgs._context->render(batch); + // renderArgs._context->render(batch); } void Application::runTests() { From 27d3d3f450cc904636cfe55e13a4a1d053923c82 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 28 Jul 2015 15:51:15 -0700 Subject: [PATCH 097/129] fix w to x --- libraries/gpu/src/gpu/GPUConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h index a9657076fa..2e3149919c 100644 --- a/libraries/gpu/src/gpu/GPUConfig.h +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -36,7 +36,7 @@ #else #include -#include +#include //#include //#include From 77a12eb50ea7af97a46060e178c2d6479af0bdc0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 28 Jul 2015 17:53:01 -0700 Subject: [PATCH 098/129] compile on linux with GLEW --- cmake/modules/FindGLEW.cmake | 14 +++++++ interface/CMakeLists.txt | 6 +++ interface/src/Stars.cpp | 10 ++--- interface/src/devices/OculusManager.cpp | 6 +-- interface/src/devices/TV3DManager.cpp | 9 +++-- interface/src/devices/TV3DManager.h | 1 + .../src/RenderablePolyVoxEntityItem.cpp | 2 +- .../src/RenderableWebEntityItem.cpp | 3 +- libraries/gpu/CMakeLists.txt | 7 +++- libraries/gpu/src/gpu/Batch.cpp | 6 +-- libraries/gpu/src/gpu/GLBackend.cpp | 3 +- libraries/gpu/src/gpu/GLBackendQuery.cpp | 1 - libraries/gpu/src/gpu/GLBackendShader.cpp | 1 - libraries/gpu/src/gpu/GLBackendShared.h | 5 ++- libraries/gpu/src/gpu/GPUConfig.h | 2 +- libraries/model/src/model/Material.h | 2 +- .../src/AmbientOcclusionEffect.cpp | 6 +-- .../src/DeferredLightingEffect.cpp | 38 +++++++++--------- libraries/render-utils/src/GeometryCache.cpp | 10 ++--- libraries/render-utils/src/Model.cpp | 8 ++-- .../render-utils/src/RenderDeferredTask.cpp | 4 +- libraries/render-utils/src/TextureCache.cpp | 7 ++-- libraries/render/src/render/DrawStatus.cpp | 7 ++-- libraries/render/src/render/DrawTask.cpp | 6 +-- tests/render-utils/src/main.cpp | 39 ++++++++++--------- 25 files changed, 109 insertions(+), 94 deletions(-) diff --git a/cmake/modules/FindGLEW.cmake b/cmake/modules/FindGLEW.cmake index e86db3fdac..b1789fb614 100644 --- a/cmake/modules/FindGLEW.cmake +++ b/cmake/modules/FindGLEW.cmake @@ -38,5 +38,19 @@ if (WIN32) find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_INCLUDE_DIRS GLEW_LIBRARIES GLEW_DLL_PATH) add_paths_to_fixup_libs(${GLEW_DLL_PATH}) +elseif (APPLE) +else () + find_path(GLEW_INCLUDE_DIR GL/glew.h) + find_library(GLEW_LIBRARY NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64) + + set(GLEW_INCLUDE_DIRS ${GLEW_INCLUDE_DIR}) + set(GLEW_LIBRARIES ${GLEW_LIBRARY}) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(GLEW + REQUIRED_VARS GLEW_INCLUDE_DIR GLEW_LIBRARY) + + mark_as_advanced(GLEW_INCLUDE_DIR GLEW_LIBRARY) + endif () diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0c44ac801f..6af3cfa08b 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -245,6 +245,12 @@ else (APPLE) endif () endif() + else (WIN32) + find_package(GLEW REQUIRED) + target_include_directories(${TARGET_NAME} PRIVATE ${GLEW_INCLUDE_DIRS}) + + target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES}) + message(STATUS ${GLEW_LIBRARY}) endif() endif (APPLE) diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp index ebfddee38c..7b612acb68 100644 --- a/interface/src/Stars.cpp +++ b/interface/src/Stars.cpp @@ -14,8 +14,6 @@ #include #include -#include -#include #include #include #include @@ -207,7 +205,7 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { batch._glUniform1f(_timeSlot, secs); geometryCache->renderUnitCube(batch); - glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + //glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); static const size_t VERTEX_STRIDE = sizeof(StarVertex); size_t offset = offsetof(StarVertex, position); @@ -217,9 +215,9 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { // Render the stars batch.setPipeline(_starsPipeline); - batch._glEnable(GL_PROGRAM_POINT_SIZE_EXT); - batch._glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - batch._glEnable(GL_POINT_SMOOTH); + //batch._glEnable(GL_PROGRAM_POINT_SIZE_EXT); + //batch._glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + //batch._glEnable(GL_POINT_SMOOTH); batch.setInputFormat(streamFormat); batch.setInputBuffer(VERTICES_SLOT, posView); diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index c9c70b4417..16685df96f 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -11,16 +11,16 @@ // #include "OculusManager.h" -#include +#include #include #include +#include #include +#include #include #include -#include -#include #include #include diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index fefaf060bd..5dee5988c1 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -9,13 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "TV3DManager.h" + #include #include -#include "gpu/GLBackend.h" -#include "Application.h" +#include -#include "TV3DManager.h" +#include "Application.h" #include "Menu.h" int TV3DManager::_screenWidth = 1; @@ -63,6 +64,7 @@ void TV3DManager::setFrustum(Camera& whichCamera) { } void TV3DManager::configureCamera(Camera& whichCamera, int screenWidth, int screenHeight) { +#ifdef THIS_CURRENTLY_BROKEN_WAITING_FOR_DISPLAY_PLUGINS if (screenHeight == 0) { screenHeight = 1; // prevent divide by 0 } @@ -72,6 +74,7 @@ void TV3DManager::configureCamera(Camera& whichCamera, int screenWidth, int scre setFrustum(whichCamera); glViewport (0, 0, _screenWidth, _screenHeight); // sets drawing viewport +#endif } void TV3DManager::display(RenderArgs* renderArgs, Camera& whichCamera) { diff --git a/interface/src/devices/TV3DManager.h b/interface/src/devices/TV3DManager.h index 330a4ee0ee..96ee79f7d1 100644 --- a/interface/src/devices/TV3DManager.h +++ b/interface/src/devices/TV3DManager.h @@ -17,6 +17,7 @@ #include class Camera; +class RenderArgs; struct eyeFrustum { double left; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index d3ee312311..681702bb07 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -35,7 +35,7 @@ #include #include "model/Geometry.h" -#include "gpu/GLBackend.h" +#include "gpu/Context.h" #include "EntityTreeRenderer.h" #include "RenderablePolyVoxEntityItem.h" diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 7fa615073b..9e48164647 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -8,7 +8,6 @@ #include "RenderableWebEntityItem.h" -#include #include #include #include @@ -24,7 +23,7 @@ #include #include #include -#include +#include #include "EntityTreeRenderer.h" diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index 30949b83e1..eda168091e 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -31,13 +31,16 @@ elseif (WIN32) elseif (ANDROID) target_link_libraries(${TARGET_NAME} "-lGLESv3" "-lEGL") else () + find_package(GLEW REQUIRED) + target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS}) + find_package(OpenGL REQUIRED) if (${OPENGL_INCLUDE_DIR}) include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") endif () - target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") + target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" "${OPENGL_LIBRARY}") - target_include_directories(${TARGET_NAME} PUBLIC ${OPENGL_INCLUDE_DIR}) + # target_include_directories(${TARGET_NAME} PUBLIC ${OPENGL_INCLUDE_DIR}) endif (APPLE) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 4ac33d8f14..b7f3ef444c 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "Batch.h" -#include "GPUConfig.h" - -#include #include +#include + +#include "GPUConfig.h" #if defined(NSIGHT_FOUND) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 3942af4f84..4bc8abadd0 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -8,9 +8,10 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "GLBackendShared.h" + #include #include "GPULogging.h" -#include "GLBackendShared.h" #include using namespace gpu; diff --git a/libraries/gpu/src/gpu/GLBackendQuery.cpp b/libraries/gpu/src/gpu/GLBackendQuery.cpp index 39db19dafd..297bdf9c40 100644 --- a/libraries/gpu/src/gpu/GLBackendQuery.cpp +++ b/libraries/gpu/src/gpu/GLBackendQuery.cpp @@ -8,7 +8,6 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "GPULogging.h" #include "GLBackendShared.h" diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index fd5bed2e5e..dccd035cb4 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -8,7 +8,6 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "GPULogging.h" #include "GLBackendShared.h" #include "Format.h" diff --git a/libraries/gpu/src/gpu/GLBackendShared.h b/libraries/gpu/src/gpu/GLBackendShared.h index 27f58fcbe3..75bef461f9 100644 --- a/libraries/gpu/src/gpu/GLBackendShared.h +++ b/libraries/gpu/src/gpu/GLBackendShared.h @@ -11,10 +11,11 @@ #ifndef hifi_gpu_GLBackend_Shared_h #define hifi_gpu_GLBackend_Shared_h -#include "GLBackend.h" - #include +#include "GPULogging.h" +#include "GLBackend.h" + #include "Batch.h" static const GLenum _primitiveToGLmode[gpu::NUM_PRIMITIVES] = { diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h index 2e3149919c..5046221ad3 100644 --- a/libraries/gpu/src/gpu/GPUConfig.h +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -36,7 +36,7 @@ #else #include -#include +//#include //#include //#include diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index 392fd918a1..a1a17d29e9 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -13,13 +13,13 @@ #include #include +#include #include #include "gpu/Resource.h" #include "gpu/Texture.h" -#include namespace model { diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index f19fa6e18a..22e5a705e3 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -9,15 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL -#include - -#include #include #include #include +#include #include "gpu/StandardShaderLib.h" #include "AmbientOcclusionEffect.h" @@ -176,7 +173,6 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons assert(renderContext->args); assert(renderContext->args->_viewFrustum); RenderArgs* args = renderContext->args; - auto& scene = sceneContext->_scene; gpu::Batch batch; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index c14bbfcb1d..7563609026 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -12,12 +12,12 @@ #include "DeferredLightingEffect.h" #include -#include +#include +#include + #include #include #include -#include -#include #include "AbstractViewStateInterface.h" #include "GeometryCache.h" @@ -291,7 +291,7 @@ void DeferredLightingEffect::render(RenderArgs* args) { locations = &_directionalAmbientSphereLightCascadedShadowMapLocations; } batch.setPipeline(program); - batch._glUniform3fv(locations->shadowDistances, 1, (const GLfloat*) &_viewState->getShadowDistances()); + batch._glUniform3fv(locations->shadowDistances, 1, (const float*) &_viewState->getShadowDistances()); } else { if (useSkyboxCubemap) { @@ -325,7 +325,7 @@ void DeferredLightingEffect::render(RenderArgs* args) { sh = (*_skybox->getCubemap()->getIrradiance()); } for (int i =0; i ambientSphere + i, 1, (const GLfloat*) (&sh) + i * 4); + batch._glUniform4fv(locations->ambientSphere + i, 1, (const float*) (&sh) + i * 4); } } @@ -340,7 +340,7 @@ void DeferredLightingEffect::render(RenderArgs* args) { if (_atmosphere && (locations->atmosphereBufferUnit >= 0)) { batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer()); } - batch._glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); + batch._glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const float* >(&invViewMat)); } float left, right, bottom, top, nearVal, farVal; @@ -419,9 +419,9 @@ void DeferredLightingEffect::render(RenderArgs* args) { batch._glUniform2f(_pointLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); batch._glUniform2f(_pointLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); - batch._glUniformMatrix4fv(_pointLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); + batch._glUniformMatrix4fv(_pointLightLocations.invViewMat, 1, false, reinterpret_cast< const float* >(&invViewMat)); - batch._glUniformMatrix4fv(_pointLightLocations.texcoordMat, 1, false, reinterpret_cast< const GLfloat* >(&texcoordMat)); + batch._glUniformMatrix4fv(_pointLightLocations.texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat)); for (auto lightID : _pointLights) { auto& light = _allocatedLights[lightID]; @@ -467,9 +467,9 @@ void DeferredLightingEffect::render(RenderArgs* args) { batch._glUniform2f(_spotLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); batch._glUniform2f(_spotLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); - batch._glUniformMatrix4fv(_spotLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); + batch._glUniformMatrix4fv(_spotLightLocations.invViewMat, 1, false, reinterpret_cast< const float* >(&invViewMat)); - batch._glUniformMatrix4fv(_spotLightLocations.texcoordMat, 1, false, reinterpret_cast< const GLfloat* >(&texcoordMat)); + batch._glUniformMatrix4fv(_spotLightLocations.texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat)); for (auto lightID : _spotLights) { auto light = _allocatedLights[lightID]; @@ -489,7 +489,7 @@ void DeferredLightingEffect::render(RenderArgs* args) { if ((eyeHalfPlaneDistance > -nearRadius) && (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius)) { coneParam.w = 0.0f; - batch._glUniform4fv(_spotLightLocations.coneParam, 1, reinterpret_cast< const GLfloat* >(&coneParam)); + batch._glUniform4fv(_spotLightLocations.coneParam, 1, reinterpret_cast< const float* >(&coneParam)); Transform model; model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f)); @@ -509,7 +509,7 @@ void DeferredLightingEffect::render(RenderArgs* args) { batch.setViewTransform(viewMat); } else { coneParam.w = 1.0f; - batch._glUniform4fv(_spotLightLocations.coneParam, 1, reinterpret_cast< const GLfloat* >(&coneParam)); + batch._glUniform4fv(_spotLightLocations.coneParam, 1, reinterpret_cast< const float* >(&coneParam)); Transform model; model.setTranslation(light->getPosition()); @@ -595,9 +595,9 @@ void DeferredLightingEffect::loadLightProgram(const char* vertSource, const char slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), 3)); slotBindings.insert(gpu::Shader::Binding(std::string("shadowMap"), 4)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), 5)); - const GLint LIGHT_GPU_SLOT = 3; + const int LIGHT_GPU_SLOT = 3; slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); - const GLint ATMOSPHERE_GPU_SLOT = 4; + const int ATMOSPHERE_GPU_SLOT = 4; slotBindings.insert(gpu::Shader::Binding(std::string("atmosphereBufferUnit"), ATMOSPHERE_GPU_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); @@ -677,10 +677,10 @@ model::MeshPointer DeferredLightingEffect::getSpotLightMesh() { int ringFloatOffset = slices * 3; - GLfloat* vertexData = new GLfloat[verticesSize]; - GLfloat* vertexRing0 = vertexData; - GLfloat* vertexRing1 = vertexRing0 + ringFloatOffset; - GLfloat* vertexRing2 = vertexRing1 + ringFloatOffset; + float* vertexData = new float[verticesSize]; + float* vertexRing0 = vertexData; + float* vertexRing1 = vertexRing0 + ringFloatOffset; + float* vertexRing2 = vertexRing1 + ringFloatOffset; for (int i = 0; i < slices; i++) { float theta = TWO_PI * i / slices; @@ -746,7 +746,7 @@ model::MeshPointer DeferredLightingEffect::getSpotLightMesh() { *(index++) = capVertex; } - _spotLightMesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(sizeof(GLushort) * indices, (gpu::Byte*) indexData), gpu::Element::INDEX_UINT16)); + _spotLightMesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(sizeof(unsigned short) * indices, (gpu::Byte*) indexData), gpu::Element::INDEX_UINT16)); delete[] indexData; model::Mesh::Part part(0, indices, 0, model::Mesh::TRIANGLES); diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 8550f8d8b6..b873b35b9c 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -9,22 +9,22 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// include this before QOpenGLBuffer, which includes an earlier version of OpenGL +#include "GeometryCache.h" + #include #include #include #include -#include -#include - #include #include +#include +#include + #include "TextureCache.h" #include "RenderUtilsLogging.h" -#include "GeometryCache.h" #include "standardTransformPNTC_vert.h" #include "standardDrawTexture_frag.h" diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 67eb85edfc..1e0e04c776 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -18,20 +18,18 @@ #include #include -#include -#include #include #include -#include "PhysicsEntity.h" #include #include #include +#include +#include #include "AbstractViewStateInterface.h" #include "AnimationHandle.h" #include "DeferredLightingEffect.h" #include "Model.h" -#include "RenderUtilsLogging.h" #include "model_vert.h" #include "model_shadow_vert.h" @@ -96,7 +94,7 @@ Model::~Model() { } Model::RenderPipelineLib Model::_renderPipelineLib; -const GLint MATERIAL_GPU_SLOT = 3; +const int MATERIAL_GPU_SLOT = 3; void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, gpu::ShaderPointer& vertexShader, diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index cf9b455059..b4863a4764 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -10,12 +10,10 @@ // #include "RenderDeferredTask.h" -#include -#include -#include #include #include #include +#include #include "FramebufferCache.h" #include "DeferredLightingEffect.h" diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 1a6ea97b64..d6a9bf5b36 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -16,16 +16,15 @@ #include #include -#include -#include -#include - #include #include #include #include #include +#include + + #include "RenderUtilsLogging.h" diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index f84d212112..f50f517d7d 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -15,15 +15,14 @@ #include #include +#include +#include #include #include #include #include -#include -#include - #include "drawItemBounds_vert.h" #include "drawItemBounds_frag.h" #include "drawItemStatus_vert.h" @@ -171,4 +170,4 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex args->_context->syncCache(); renderContext->args->_context->syncCache(); args->_context->render((batch)); -} \ No newline at end of file +} diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 0e3eba0b53..d29420fdfd 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -14,12 +14,12 @@ #include #include -#include -#include -#include #include #include #include +#include +#include +#include using namespace render; diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index 3b7eb18368..ab01d333ac 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -8,30 +8,31 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include #include + #include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include class RateCounter { std::vector times; From 475d069185ffe68e2979a43856d082adb747b04c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 28 Jul 2015 18:12:10 -0700 Subject: [PATCH 099/129] fix rendering on linux --- libraries/gpu/src/gpu/Config.slh | 7 +++---- libraries/gpu/src/gpu/GPUConfig.h | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/libraries/gpu/src/gpu/Config.slh b/libraries/gpu/src/gpu/Config.slh index 76be161822..f24b54e5d5 100644 --- a/libraries/gpu/src/gpu/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -21,10 +21,9 @@ <@def VERSION_HEADER #version 120 #extension GL_EXT_gpu_shader4 : enable@> <@else@> - <@def GPU_FEATURE_PROFILE GPU_LEGACY@> - <@def GPU_TRANSFORM_PROFILE GPU_LEGACY@> - <@def VERSION_HEADER #version 120 -#extension GL_EXT_gpu_shader4 : enable@> + <@def GPU_FEATURE_PROFILE GPU_CORE@> + <@def GPU_TRANSFORM_PROFILE GPU_CORE@> + <@def VERSION_HEADER #version 430 compatibility@> <@endif@> <@endif@> diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h index 5046221ad3..d9b6d18894 100644 --- a/libraries/gpu/src/gpu/GPUConfig.h +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -40,8 +40,8 @@ //#include //#include -#define GPU_FEATURE_PROFILE GPU_LEGACY -#define GPU_TRANSFORM_PROFILE GPU_LEGACY +#define GPU_FEATURE_PROFILE GPU_CORE +#define GPU_TRANSFORM_PROFILE GPU_CORE #endif From 044ea2ace56303e1a5101dc282db4c1459f561ce Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 28 Jul 2015 19:31:43 -0700 Subject: [PATCH 100/129] Changed mirror position to not be achored to the head. But instead it's anchored to the "default" eye position, which is where the eyes are in the model, before IK or animations occur. --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3f185af5a1..967880ca8d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3381,7 +3381,7 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further // investigated in order to adapt the technique while fixing the head rendering issue, // but the complexity of the hack suggests that a better approach - _mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() + + _mirrorCamera.setPosition(_myAvatar->getDefaultEyePosition() + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); } _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); From 1d29fb9d7f9b2c482a352881cb6595904671e657 Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Wed, 29 Jul 2015 14:56:24 +0200 Subject: [PATCH 101/129] replace tabs with whitespaces. --- interface/src/devices/3Dconnexion.cpp | 38 +++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/interface/src/devices/3Dconnexion.cpp b/interface/src/devices/3Dconnexion.cpp index 111e2d5991..ef66e6660b 100755 --- a/interface/src/devices/3Dconnexion.cpp +++ b/interface/src/devices/3Dconnexion.cpp @@ -165,11 +165,11 @@ static ConnexionClient* gMouseInput = 0; void ConnexionClient::toggleConnexion(bool shouldEnable) { - ConnexionData& connexiondata = ConnexionData::getInstance(); - if (shouldEnable && connexiondata.getDeviceID() == 0) { + ConnexionData& connexiondata = ConnexionData::getInstance(); + if (shouldEnable && connexiondata.getDeviceID() == 0) { ConnexionClient::init(); } - if (!shouldEnable && connexiondata.getDeviceID() != 0) { + if (!shouldEnable && connexiondata.getDeviceID() != 0) { ConnexionClient::destroy(); } @@ -177,24 +177,24 @@ void ConnexionClient::toggleConnexion(bool shouldEnable) void ConnexionClient::init() { if (Menu::getInstance()->isOptionChecked(MenuOption::Connexion)) { - ConnexionClient& cclient = ConnexionClient::getInstance(); - cclient.fLast3dmouseInputTime = 0; + ConnexionClient& cclient = ConnexionClient::getInstance(); + cclient.fLast3dmouseInputTime = 0; - cclient.InitializeRawInput(GetActiveWindow()); + cclient.InitializeRawInput(GetActiveWindow()); - gMouseInput = &cclient; + gMouseInput = &cclient; - QAbstractEventDispatcher::instance()->installNativeEventFilter(&cclient); + QAbstractEventDispatcher::instance()->installNativeEventFilter(&cclient); } } void ConnexionClient::destroy() { - ConnexionClient& cclient = ConnexionClient::getInstance(); - QAbstractEventDispatcher::instance()->removeNativeEventFilter(&cclient); - ConnexionData& connexiondata = ConnexionData::getInstance(); - int deviceid = connexiondata.getDeviceID(); - connexiondata.setDeviceID(0); - Application::getUserInputMapper()->removeDevice(deviceid); + ConnexionClient& cclient = ConnexionClient::getInstance(); + QAbstractEventDispatcher::instance()->removeNativeEventFilter(&cclient); + ConnexionData& connexiondata = ConnexionData::getInstance(); + int deviceid = connexiondata.getDeviceID(); + connexiondata.setDeviceID(0); + Application::getUserInputMapper()->removeDevice(deviceid); } #define LOGITECH_VENDOR_ID 0x46d @@ -305,9 +305,9 @@ bool ConnexionClient::RawInputEventFilter(void* msg, long* result) { connexiondata.assignDefaultInputMapping(*Application::getUserInputMapper()); UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion"); } else if (!ConnexionClient::Is3dmouseAttached() && connexiondata.getDeviceID() != 0) { - int deviceid = connexiondata.getDeviceID(); - connexiondata.setDeviceID(0); - Application::getUserInputMapper()->removeDevice(deviceid); + int deviceid = connexiondata.getDeviceID(); + connexiondata.setDeviceID(0); + Application::getUserInputMapper()->removeDevice(deviceid); } if (!ConnexionClient::Is3dmouseAttached()) { @@ -332,8 +332,8 @@ ConnexionClient::ConnexionClient() { } ConnexionClient::~ConnexionClient() { - ConnexionClient& cclient = ConnexionClient::getInstance(); - QAbstractEventDispatcher::instance()->removeNativeEventFilter(&cclient); + ConnexionClient& cclient = ConnexionClient::getInstance(); + QAbstractEventDispatcher::instance()->removeNativeEventFilter(&cclient); } // Access the mouse parameters structure From 7325e6a7b7fcfa280ab3ed4534f84db804402880 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 29 Jul 2015 14:57:06 +0200 Subject: [PATCH 102/129] Send ping requests to the nodes (AvatarMixer, AudioMixer, EntityServer) that the Assignment agent connected with to keep the connections alive. --- assignment-client/src/Agent.cpp | 27 ++++++++++++++++++++++++++- assignment-client/src/Agent.h | 2 ++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index da588bc316..77b47f4d7c 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -107,6 +107,7 @@ void Agent::handleAudioPacket(QSharedPointer packet) { } const QString AGENT_LOGGING_NAME = "agent"; +const int PING_INTERVAL = 1000; void Agent::run() { ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent); @@ -118,6 +119,10 @@ void Agent::run() { << NodeType::EntityServer ); + _pingTimer = new QTimer(this); + connect(_pingTimer, SIGNAL(timeout()), SLOT(sendPingRequests())); + _pingTimer->start(PING_INTERVAL); + // figure out the URL for the script for this agent assignment QUrl scriptURL; if (_payload.isEmpty()) { @@ -193,7 +198,27 @@ void Agent::run() { void Agent::aboutToFinish() { _scriptEngine.stop(); - + + _pingTimer->stop(); + delete _pingTimer; + // our entity tree is going to go away so tell that to the EntityScriptingInterface DependencyManager::get()->setEntityTree(NULL); } + +void Agent::sendPingRequests() { + auto nodeList = DependencyManager::get(); + + nodeList->eachMatchingNode([](const SharedNodePointer& node)->bool { + switch (node->getType()) { + case NodeType::AvatarMixer: + case NodeType::AudioMixer: + case NodeType::EntityServer: + return true; + default: + return false; + } + }, [nodeList](const SharedNodePointer& node) { + nodeList->sendPacket(nodeList->constructPingPacket(), *node); + }); +} diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 241e14439c..4c207e59aa 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -58,11 +58,13 @@ private slots: void handleAudioPacket(QSharedPointer packet); void handleOctreePacket(QSharedPointer packet, SharedNodePointer senderNode); void handleJurisdictionPacket(QSharedPointer packet, SharedNodePointer senderNode); + void sendPingRequests(); private: ScriptEngine _scriptEngine; EntityEditPacketSender _entityEditSender; EntityTreeHeadlessViewer _entityViewer; + QTimer* _pingTimer; MixedAudioStream _receivedAudioStream; float _lastReceivedAudioLoudness; From 7805cf4e481c07a78298c7774cb1792d55f06713 Mon Sep 17 00:00:00 2001 From: bwent Date: Wed, 29 Jul 2015 09:19:33 -0700 Subject: [PATCH 103/129] Format fixes, UI logos for collapse/expand toggle --- examples/utilities/tools/cookies.js | 35 ++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index 24cda69ba2..751008fd99 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -12,7 +12,7 @@ HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -var SCALE = 1000; +var SLIDER_RANGE_INCREMENT_SCALE = 1 / 1000; var THUMB_COLOR = { red: 150, green: 150, @@ -59,7 +59,6 @@ var CHECK_MARK_COLOR = { }); this.thumbSize = thumbSize; - this.thumbHalfSize = 0.5 * thumbSize; this.minThumbX = x + this.thumbHalfSize; @@ -128,7 +127,7 @@ var CHECK_MARK_COLOR = { Slider.prototype.updateWithKeys = function(direction) { this.range = this.maxThumbX - this.minThumbX; - this.thumbX += direction * (this.range / SCALE); + this.thumbX += direction * (this.range * SCALE); this.updateThumb(); this.onValueChanged(this.getValue()); }; @@ -211,6 +210,25 @@ var CHECK_MARK_COLOR = { }); }; + this.setThumbColor = function(color) { + Overlays.editOverlay(this.thumb, { + backgroundColor: { + red: color.x * 255, + green: color.y * 255, + blue: color.z * 255 + } + }); + }; + this.setBackgroundColor = function(color) { + Overlays.editOverlay(this.background, { + backgroundColor: { + red: color.x * 255, + green: color.y * 255, + blue: color.z * 255 + } + }); + }; + Slider.prototype.hide = function() { Overlays.editOverlay(this.background, { visible: false @@ -748,7 +766,7 @@ var CHECK_MARK_COLOR = { green: 255, blue: 255 }, - imageURL: HIFI_PUBLIC_BUCKET + 'images/tools/min-max-toggle.svg', + imageURL: HIFI_PUBLIC_BUCKET + 'images/tools/expand-ui.svg', x: x, y: y, width: rawHeight, @@ -778,6 +796,7 @@ var CHECK_MARK_COLOR = { }); }; + CollapsablePanelItem.prototype.destroy = function() { Overlays.deleteOverlay(this.title); Overlays.deleteOverlay(this.thumb); @@ -1044,6 +1063,7 @@ var CHECK_MARK_COLOR = { x: event.x, y: event.y }); + this.handleCollapse(clickedOverlay); // If the user clicked any of the slider background then... @@ -1106,10 +1126,15 @@ var CHECK_MARK_COLOR = { } if (!item.isCollapsed && item.isCollapsable && clickedOverlay == item.thumb) { + Overlays.editOverlay(item.thumb, { + imageURL: HIFI_PUBLIC_BUCKET + 'images/tools/expand-right.svg' + }); this.collapse(clickedOverlay); item.isCollapsed = true; - break; } else if (item.isCollapsed && item.isCollapsable && clickedOverlay == item.thumb) { + Overlays.editOverlay(item.thumb, { + imageURL: HIFI_PUBLIC_BUCKET + 'images/tools/expand-ui.svg' + }); this.expand(clickedOverlay); item.isCollapsed = false; } From 76acbde5955c1cd3f33d8e7228e19ae8899b6f34 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Jul 2015 09:54:10 -0700 Subject: [PATCH 104/129] Removing the opengl and glew links from Interface since now coming from gpu lib --- interface/CMakeLists.txt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 6af3cfa08b..4f99b6b34f 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -219,21 +219,22 @@ else (APPLE) $/resources ) - find_package(OpenGL REQUIRED) + # find_package(OpenGL REQUIRED) - if (${OPENGL_INCLUDE_DIR}) - include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") - endif () + # if (${OPENGL_INCLUDE_DIR}) + # include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") +# endif () - target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") + # target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") # link target to external libraries if (WIN32) - add_dependency_external_projects(glew) - find_package(GLEW REQUIRED) - target_include_directories(${TARGET_NAME} PRIVATE ${GLEW_INCLUDE_DIRS}) + # add_dependency_external_projects(glew) + # find_package(GLEW REQUIRED) + # target_include_directories(${TARGET_NAME} PRIVATE ${GLEW_INCLUDE_DIRS}) - target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} wsock32.lib opengl32.lib Winmm.lib) + # target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} wsock32.lib opengl32.lib Winmm.lib) + target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib) if (USE_NSIGHT) # try to find the Nsight package and add it to the build if we find it From d76cda396f84943b48da360b78438fd62916254a Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Wed, 29 Jul 2015 11:05:19 -0700 Subject: [PATCH 105/129] HBAO implementation ported from NVidia HLSL --- .../render-utils/src/ambient_occlusion.slf | 259 +++++++++++++++++- 1 file changed, 258 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index 3a49accf58..96aba989a8 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -17,7 +17,7 @@ <@include gpu/Transform.slh@> <$declareStandardTransform()$> - +/* varying vec2 varTexcoord; uniform sampler2D depthTexture; @@ -105,5 +105,262 @@ void main(void) { occlusion = 1.0 - occlusion / float(SAMPLE_COUNT); occlusion = clamp(pow(occlusion, g_intensity), 0.0, 1.0); gl_FragColor = vec4(vec3(occlusion), 1.0); +}*/ + +// This is a HBAO-Shader for OpenGL, based upon nvidias directX implementation +// supplied in their SampleSDK available from nvidia.com +// The slides describing the implementation is available at +// http://www.nvidia.co.uk/object/siggraph-2008-HBAO.html + +varying vec2 varTexcoord; + +uniform sampler2D depthTexture; +uniform sampler2D normalTexture; + +uniform float g_scale; +uniform float g_bias; +uniform float g_sample_rad; +uniform float g_intensity; +uniform float bufferWidth; +uniform float bufferHeight; + +const float PI = 3.14159265; + +const vec2 FocalLen = vec2(1.0, 1.0); +//const vec2 UVToViewA = vec2(1.0, 1.0); +//const vec2 UVToViewB = vec2(1.0, 1.0); + +const vec2 LinMAD = vec2(0.1-10.0, 0.1+10.0) / (2.0*0.1*10.0); + +const vec2 AORes = vec2(1024.0, 768.0); +const vec2 InvAORes = vec2(1.0/1024.0, 1.0/768.0); +const vec2 NoiseScale = vec2(1024.0, 768.0) / 4.0; + +const float AOStrength = 1.9; +const float R = 0.3; +const float R2 = 0.3*0.3; +const float NegInvR2 = - 1.0 / (0.3*0.3); +const float TanBias = tan(30.0 * PI / 180.0); +const float MaxRadiusPixels = 100.0; + +const int NumDirections = 6; +const int NumSamples = 4; + +float ViewSpaceZFromDepth(float d) +{ + // [0,1] -> [-1,1] clip space + d = d * 2.0 - 1.0; + + // Get view space Z + return -1.0 / (LinMAD.x * d + LinMAD.y); } +vec3 UVToViewSpace(vec2 uv, float z) +{ + //uv = UVToViewA * uv + UVToViewB; + return vec3(uv * z, z); +} + +vec3 GetViewPos(vec2 uv) +{ + float z = ViewSpaceZFromDepth(texture2D(depthTexture, uv).r); + return UVToViewSpace(uv, z); +} + +vec3 GetViewPosPoint(ivec2 uv) +{ + vec2 coord = vec2(gl_FragCoord.xy) + uv; + //float z = texelFetch(texture0, coord, 0).r; + float z = texture2D(depthTexture, uv).r; + return UVToViewSpace(uv, z); +} + +float TanToSin(float x) +{ + return x * inversesqrt(x*x + 1.0); +} + +float InvLength(vec2 V) +{ + return inversesqrt(dot(V,V)); +} + +float Tangent(vec3 V) +{ + return V.z * InvLength(V.xy); +} + +float BiasedTangent(vec3 V) +{ + return V.z * InvLength(V.xy) + TanBias; +} + +float Tangent(vec3 P, vec3 S) +{ + return -(P.z - S.z) * InvLength(S.xy - P.xy); +} + +float Length2(vec3 V) +{ + return dot(V,V); +} + +vec3 MinDiff(vec3 P, vec3 Pr, vec3 Pl) +{ + vec3 V1 = Pr - P; + vec3 V2 = P - Pl; + return (Length2(V1) < Length2(V2)) ? V1 : V2; +} + +vec2 SnapUVOffset(vec2 uv) +{ + return round(uv * AORes) * InvAORes; +} + +float Falloff(float d2) +{ + return d2 * NegInvR2 + 1.0f; +} + +float HorizonOcclusion( vec2 deltaUV, + vec3 P, + vec3 dPdu, + vec3 dPdv, + float randstep, + float numSamples) +{ + float ao = 0; + + // Offset the first coord with some noise + vec2 uv = varTexcoord + SnapUVOffset(randstep*deltaUV); + deltaUV = SnapUVOffset( deltaUV ); + + // Calculate the tangent vector + vec3 T = deltaUV.x * dPdu + deltaUV.y * dPdv; + + // Get the angle of the tangent vector from the viewspace axis + float tanH = BiasedTangent(T); + float sinH = TanToSin(tanH); + + float tanS; + float d2; + vec3 S; + + // Sample to find the maximum angle + for(float s = 1; s <= numSamples; ++s) + { + uv += deltaUV; + S = GetViewPos(uv); + tanS = Tangent(P, S); + d2 = Length2(S - P); + + // Is the sample within the radius and the angle greater? + if(d2 < R2 && tanS > tanH) + { + float sinS = TanToSin(tanS); + // Apply falloff based on the distance + ao += Falloff(d2) * (sinS - sinH); + + tanH = tanS; + sinH = sinS; + } + } + + return ao; +} + +vec2 RotateDirections(vec2 Dir, vec2 CosSin) +{ + return vec2(Dir.x*CosSin.x - Dir.y*CosSin.y, + Dir.x*CosSin.y + Dir.y*CosSin.x); +} + +void ComputeSteps(inout vec2 stepSizeUv, inout float numSteps, float rayRadiusPix, float rand) +{ + // Avoid oversampling if numSteps is greater than the kernel radius in pixels + numSteps = min(NumSamples, rayRadiusPix); + + // Divide by Ns+1 so that the farthest samples are not fully attenuated + float stepSizePix = rayRadiusPix / (numSteps + 1); + + // Clamp numSteps if it is greater than the max kernel footprint + float maxNumSteps = MaxRadiusPixels / stepSizePix; + if (maxNumSteps < numSteps) + { + // Use dithering to avoid AO discontinuities + numSteps = floor(maxNumSteps + rand); + numSteps = max(numSteps, 1); + stepSizePix = MaxRadiusPixels / numSteps; + } + + // Step size in uv space + stepSizeUv = stepSizePix * InvAORes; +} + +float getRandom(vec2 uv) { + return fract(sin(dot(uv.xy ,vec2(12.9898,78.233))) * 43758.5453); +} + +void main(void) +{ + float numDirections = NumDirections; + + vec3 P, Pr, Pl, Pt, Pb; + P = GetViewPos(varTexcoord); + + // Sample neighboring pixels + Pr = GetViewPos(varTexcoord + vec2( InvAORes.x, 0)); + Pl = GetViewPos(varTexcoord + vec2(-InvAORes.x, 0)); + Pt = GetViewPos(varTexcoord + vec2( 0, InvAORes.y)); + Pb = GetViewPos(varTexcoord + vec2( 0,-InvAORes.y)); + + // Calculate tangent basis vectors using the minimu difference + vec3 dPdu = MinDiff(P, Pr, Pl); + vec3 dPdv = MinDiff(P, Pt, Pb) * (AORes.y * InvAORes.x); + + // Get the random samples from the noise texture + vec3 random = vec3(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx), getRandom(varTexcoord.xx)); + + // Calculate the projected size of the hemisphere + vec2 rayRadiusUV = 0.5 * R * FocalLen / -P.z; + float rayRadiusPix = rayRadiusUV.x * AORes.x; + + float ao = 1.0; + + // Make sure the radius of the evaluated hemisphere is more than a pixel + if(rayRadiusPix > 1.0) + { + ao = 0.0; + float numSteps; + vec2 stepSizeUV; + + // Compute the number of steps + ComputeSteps(stepSizeUV, numSteps, rayRadiusPix, random.z); + + float alpha = 2.0 * PI / numDirections; + + // Calculate the horizon occlusion of each direction + for(float d = 0; d < numDirections; ++d) + { + float theta = alpha * d; + + // Apply noise to the direction + vec2 dir = RotateDirections(vec2(cos(theta), sin(theta)), random.xy); + vec2 deltaUV = dir * stepSizeUV; + + // Sample the pixels along the direction + ao += HorizonOcclusion( deltaUV, + P, + dPdu, + dPdv, + random.z, + numSteps); + } + + // Average the results and produce the final AO + ao = 1.0 - ao / numDirections * AOStrength; + } + + //out_frag0 = vec2(ao, 30.0 * P.z); + gl_FragColor = vec4(vec3(ao), 1.0); +} \ No newline at end of file From 65e04337bf7abb58ad15e0f3159d236173a13812 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 29 Jul 2015 11:15:20 -0700 Subject: [PATCH 106/129] removed synccache line --- libraries/render-utils/src/HitEffect.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/render-utils/src/HitEffect.cpp b/libraries/render-utils/src/HitEffect.cpp index 170a6eaf0b..f65bc7666f 100644 --- a/libraries/render-utils/src/HitEffect.cpp +++ b/libraries/render-utils/src/HitEffect.cpp @@ -80,7 +80,6 @@ void HitEffect::run(const render::SceneContextPointer& sceneContext, const rende // Ready to render - // renderContext->args->_context->syncCache(); args->_context->render((batch)); } From 17650dde74598fb1cdff9df8979d7f8db096546c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Jul 2015 11:49:22 -0700 Subject: [PATCH 107/129] Solving the coimpiling issue with Render-utils test --- tests/render-utils/src/main.cpp | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index ab01d333ac..7c02c7e8a7 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -19,6 +19,10 @@ #include #include #include + +#include +#include + #include #include #include @@ -29,7 +33,7 @@ #include #include #include -#include + #include @@ -90,6 +94,7 @@ class QTestWindow : public QWindow { QSize _size; //TextRenderer* _textRenderer[4]; RateCounter fps; + gpu::ContextPointer _gpuContext; protected: void renderText(); @@ -119,6 +124,9 @@ public: show(); makeCurrent(); + _gpuContext.reset(new gpu::Context(new gpu::GLBackend())); + + { QOpenGLDebugLogger* logger = new QOpenGLDebugLogger(this); @@ -131,23 +139,6 @@ public: } qDebug() << (const char*)glGetString(GL_VERSION); -#ifdef WIN32 - glewExperimental = true; - GLenum err = glewInit(); - if (GLEW_OK != err) { - /* Problem: glewInit failed, something is seriously wrong. */ - const GLubyte * errStr = glewGetErrorString(err); - qDebug("Error: %s\n", errStr); - } - qDebug("Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); - - if (wglewGetExtension("WGL_EXT_swap_control")) { - int swapInterval = wglGetSwapIntervalEXT(); - qDebug("V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); - } - glGetError(); -#endif - //_textRenderer[0] = TextRenderer::getInstance(SANS_FONT_FAMILY, 12, false); //_textRenderer[1] = TextRenderer::getInstance(SERIF_FONT_FAMILY, 12, false, // TextRenderer::SHADOW_EFFECT); From 661f29924fd79f6be76468ff5f6376b8153db557 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Jul 2015 13:55:26 -0700 Subject: [PATCH 108/129] Clean up the cmakelist to normally onlly do th eminimal linking and include for gl --- interface/CMakeLists.txt | 29 ++++------------------------- libraries/gpu/CMakeLists.txt | 2 +- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 4f99b6b34f..b6c8e3f3f4 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -218,40 +218,19 @@ else (APPLE) "${PROJECT_SOURCE_DIR}/resources" $/resources ) - - # find_package(OpenGL REQUIRED) - - # if (${OPENGL_INCLUDE_DIR}) - # include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") -# endif () - - # target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") - + # link target to external libraries if (WIN32) - # add_dependency_external_projects(glew) - # find_package(GLEW REQUIRED) - # target_include_directories(${TARGET_NAME} PRIVATE ${GLEW_INCLUDE_DIRS}) - - # target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} wsock32.lib opengl32.lib Winmm.lib) target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib) - + if (USE_NSIGHT) - # try to find the Nsight package and add it to the build if we find it - find_package(NSIGHT) + # If required NSIGHT lib comes from gpu lib but still to add a precroc define if (NSIGHT_FOUND) - include_directories(${NSIGHT_INCLUDE_DIRS}) add_definitions(-DNSIGHT_FOUND) - target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") endif () endif() - else (WIN32) - find_package(GLEW REQUIRED) - target_include_directories(${TARGET_NAME} PRIVATE ${GLEW_INCLUDE_DIRS}) - - target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES}) - message(STATUS ${GLEW_LIBRARY}) + # Nothing else required on linux apparently endif() endif (APPLE) diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index eda168091e..1e8faf1bca 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -23,7 +23,7 @@ elseif (WIN32) # try to find the Nsight package and add it to the build if we find it find_package(NSIGHT) if (NSIGHT_FOUND) - include_directories(${NSIGHT_INCLUDE_DIRS}) + target_include_directories(${TARGET_NAME} PUBLIC ${NSIGHT_INCLUDE_DIRS}) add_definitions(-DNSIGHT_FOUND) target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") endif () From 9601e09ba9301005057a608893e82e23f7734427 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Jul 2015 14:42:24 -0700 Subject: [PATCH 109/129] A simpler way to add the NSIGHT_FOUND define to all the projects depending on GPU --- interface/CMakeLists.txt | 8 +------- libraries/gpu/CMakeLists.txt | 8 ++++---- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index d47395a810..f1ef38ade9 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -221,14 +221,8 @@ else (APPLE) # link target to external libraries if (WIN32) + # target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib) target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib) - - if (USE_NSIGHT) - # If required NSIGHT lib comes from gpu lib but still to add a precroc define - if (NSIGHT_FOUND) - add_definitions(-DNSIGHT_FOUND) - endif () - endif() else (WIN32) # Nothing else required on linux apparently endif() diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index 1e8faf1bca..89939535b0 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -21,10 +21,11 @@ elseif (WIN32) if (USE_NSIGHT) # try to find the Nsight package and add it to the build if we find it + # note that this will also enable NSIGHT profilers in all the projects linking gpu find_package(NSIGHT) if (NSIGHT_FOUND) target_include_directories(${TARGET_NAME} PUBLIC ${NSIGHT_INCLUDE_DIRS}) - add_definitions(-DNSIGHT_FOUND) + target_compile_definitions(${TARGET_NAME} PUBLIC NSIGHT_FOUND) target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") endif () endif() @@ -39,8 +40,7 @@ else () if (${OPENGL_INCLUDE_DIR}) include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") endif () - + target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" "${OPENGL_LIBRARY}") - - # target_include_directories(${TARGET_NAME} PUBLIC ${OPENGL_INCLUDE_DIR}) + endif (APPLE) From 3c934af297617fcceb90b5b70366c673be5dc768 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Jul 2015 14:45:48 -0700 Subject: [PATCH 110/129] clean the gpuCOnfig.h for linux --- libraries/gpu/src/gpu/GPUConfig.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/gpu/src/gpu/GPUConfig.h b/libraries/gpu/src/gpu/GPUConfig.h index d9b6d18894..5590c4cc8d 100644 --- a/libraries/gpu/src/gpu/GPUConfig.h +++ b/libraries/gpu/src/gpu/GPUConfig.h @@ -36,9 +36,6 @@ #else #include -//#include -//#include -//#include #define GPU_FEATURE_PROFILE GPU_CORE #define GPU_TRANSFORM_PROFILE GPU_CORE From 838711e5261e1eccf73936f5c80242dff35e73e3 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 29 Jul 2015 15:27:50 -0700 Subject: [PATCH 111/129] Remove avatar->shift hips for idle animations. See https://app.asana.com/0/32622044445063/43127903156601 --- interface/src/Menu.cpp | 2 - interface/src/Menu.h | 1 - interface/src/avatar/MyAvatar.cpp | 11 +---- interface/src/avatar/MyAvatar.h | 1 - interface/src/avatar/SkeletonModel.cpp | 68 -------------------------- interface/src/avatar/SkeletonModel.h | 7 --- tests/ui/src/main.cpp | 1 - 7 files changed, 1 insertion(+), 90 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d6f64d360a..1cbe127857 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -249,8 +249,6 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::BlueSpeechSphere, 0, true); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::EnableCharacterController, 0, true, avatar, SLOT(updateMotionBehavior())); - addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ShiftHipsForIdleAnimations, 0, false, - avatar, SLOT(updateMotionBehavior())); MenuWrapper* viewMenu = addMenu("View"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7a9fec4e78..62a1ae3b0f 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -273,7 +273,6 @@ namespace MenuOption { const QString SimpleShadows = "Simple"; const QString SixenseEnabled = "Enable Hydra Support"; const QString SixenseMouseInput = "Enable Sixense Mouse Input"; - const QString ShiftHipsForIdleAnimations = "Shift hips for idle animations"; const QString Stars = "Stars"; const QString Stats = "Stats"; const QString StopAllScripts = "Stop All Scripts"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f332173568..3ec6a2b1d6 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -98,7 +98,6 @@ MyAvatar::MyAvatar() : _lookAtTargetAvatar(), _shouldRender(true), _billboardValid(false), - _feetTouchFloor(true), _eyeContactTarget(LEFT_EYE), _realWorldFieldOfView("realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), @@ -166,9 +165,6 @@ void MyAvatar::update(float deltaTime) { head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); simulate(deltaTime); - if (_feetTouchFloor) { - _skeletonModel.updateStandingFoot(); - } } void MyAvatar::simulate(float deltaTime) { @@ -1140,11 +1136,7 @@ glm::vec3 MyAvatar::getSkeletonPosition() const { // The avatar is rotated PI about the yAxis, so we have to correct for it // to get the skeleton offset contribution in the world-frame. const glm::quat FLIP = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); - glm::vec3 skeletonOffset = _skeletonOffset; - if (_feetTouchFloor) { - skeletonOffset += _skeletonModel.getStandingOffset(); - } - return _position + getOrientation() * FLIP * skeletonOffset; + return _position + getOrientation() * FLIP * _skeletonOffset; } return Avatar::getPosition(); } @@ -1622,7 +1614,6 @@ void MyAvatar::updateMotionBehavior() { _motionBehaviors &= ~AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED; } _characterController.setEnabled(menu->isOptionChecked(MenuOption::EnableCharacterController)); - _feetTouchFloor = menu->isOptionChecked(MenuOption::ShiftHipsForIdleAnimations); } //Renders sixense laser pointers for UI selection with controllers diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index b18b8df121..90d9b47e1c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -258,7 +258,6 @@ private: QList _animationHandles; - bool _feetTouchFloor; eyeContactTarget _eyeContactTarget; RecorderPointer _recorder; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index fa7c5f08bb..5deebca638 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -24,12 +24,6 @@ #include "Util.h" #include "InterfaceLogging.h" -enum StandingFootState { - LEFT_FOOT, - RIGHT_FOOT, - NO_FOOT -}; - SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : Model(parent), _triangleFanID(DependencyManager::get()->allocateID()), @@ -37,9 +31,6 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : _boundingShape(), _boundingShapeLocalOffset(0.0f), _defaultEyeModelPosition(glm::vec3(0.0f, 0.0f, 0.0f)), - _standingFoot(NO_FOOT), - _standingOffset(0.0f), - _clampedFootPosition(0.0f), _headClipDistance(DEFAULT_NEAR_CLIP), _isFirstPerson(false) { @@ -573,65 +564,6 @@ glm::vec3 SkeletonModel::getDefaultEyeModelPosition() const { return _owningAvatar->getScale() * _defaultEyeModelPosition; } -/// \return offset of hips after foot animation -void SkeletonModel::updateStandingFoot() { - if (_geometry == NULL) { - return; - } - glm::vec3 offset(0.0f); - int leftFootIndex = _geometry->getFBXGeometry().leftToeJointIndex; - int rightFootIndex = _geometry->getFBXGeometry().rightToeJointIndex; - - if (leftFootIndex != -1 && rightFootIndex != -1) { - glm::vec3 leftPosition, rightPosition; - getJointPosition(leftFootIndex, leftPosition); - getJointPosition(rightFootIndex, rightPosition); - - int lowestFoot = (leftPosition.y < rightPosition.y) ? LEFT_FOOT : RIGHT_FOOT; - const float MIN_STEP_HEIGHT_THRESHOLD = 0.05f; - bool oneFoot = fabsf(leftPosition.y - rightPosition.y) > MIN_STEP_HEIGHT_THRESHOLD; - int currentFoot = oneFoot ? lowestFoot : _standingFoot; - - if (_standingFoot == NO_FOOT) { - currentFoot = lowestFoot; - } - if (currentFoot != _standingFoot) { - if (_standingFoot == NO_FOOT) { - // pick the lowest foot - glm::vec3 lowestPosition = (currentFoot == LEFT_FOOT) ? leftPosition : rightPosition; - // we ignore zero length positions which can happen for a few frames until skeleton is fully loaded - if (glm::length(lowestPosition) > 0.0f) { - _standingFoot = currentFoot; - _clampedFootPosition = lowestPosition; - } - } else { - // swap feet - _standingFoot = currentFoot; - glm::vec3 nextPosition = leftPosition; - glm::vec3 prevPosition = rightPosition; - if (_standingFoot == RIGHT_FOOT) { - nextPosition = rightPosition; - prevPosition = leftPosition; - } - glm::vec3 oldOffset = _clampedFootPosition - prevPosition; - _clampedFootPosition = oldOffset + nextPosition; - offset = _clampedFootPosition - nextPosition; - } - } else { - glm::vec3 nextPosition = (_standingFoot == LEFT_FOOT) ? leftPosition : rightPosition; - offset = _clampedFootPosition - nextPosition; - } - - // clamp the offset to not exceed some max distance - const float MAX_STEP_OFFSET = 1.0f; - float stepDistance = glm::length(offset); - if (stepDistance > MAX_STEP_OFFSET) { - offset *= (MAX_STEP_OFFSET / stepDistance); - } - } - _standingOffset = offset; -} - float DENSITY_OF_WATER = 1000.0f; // kg/m^3 float MIN_JOINT_MASS = 1.0f; float VERY_BIG_MASS = 1.0e6f; diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 1044a16696..6f4dd096ad 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -96,10 +96,6 @@ public: /// \return whether or not the head was found. glm::vec3 getDefaultEyeModelPosition() const; - /// skeleton offset caused by moving feet - void updateStandingFoot(); - const glm::vec3& getStandingOffset() const { return _standingOffset; } - void computeBoundingShape(const FBXGeometry& geometry); void renderBoundingCollisionShapes(gpu::Batch& batch, float alpha); float getBoundingShapeRadius() const { return _boundingShape.getRadius(); } @@ -169,9 +165,6 @@ private: glm::vec3 _boundingShapeLocalOffset; glm::vec3 _defaultEyeModelPosition; - int _standingFoot; - glm::vec3 _standingOffset; - glm::vec3 _clampedFootPosition; float _headClipDistance; // Near clip distance to use if no separate head model diff --git a/tests/ui/src/main.cpp b/tests/ui/src/main.cpp index 614c733322..e8ab7e02df 100644 --- a/tests/ui/src/main.cpp +++ b/tests/ui/src/main.cpp @@ -215,7 +215,6 @@ public: SixenseEnabled, SixenseMouseInput, SixenseLasers, - ShiftHipsForIdleAnimations, Stars, Stats, StereoAudio, From 269db0ff6fc71aeca8179e173ad3e9e042f1da6c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Jul 2015 16:08:16 -0700 Subject: [PATCH 112/129] fixing the stars rendering that was vilently broken durign the hunt for GPUCOnfig.h includes --- interface/src/Stars.cpp | 6 +----- libraries/gpu/src/gpu/GLBackendState.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp index 7b612acb68..68e0001996 100644 --- a/interface/src/Stars.cpp +++ b/interface/src/Stars.cpp @@ -141,6 +141,7 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { auto state = gpu::StatePointer(new gpu::State()); // enable decal blend state->setDepthTest(gpu::State::DepthTest(false)); + state->setAntialiasedLineEnable(true); // line smoothing also smooth points state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); _gridPipeline.reset(gpu::Pipeline::create(program, state)); } @@ -205,8 +206,6 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { batch._glUniform1f(_timeSlot, secs); geometryCache->renderUnitCube(batch); - //glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); - static const size_t VERTEX_STRIDE = sizeof(StarVertex); size_t offset = offsetof(StarVertex, position); gpu::BufferView posView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, positionElement); @@ -215,9 +214,6 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { // Render the stars batch.setPipeline(_starsPipeline); - //batch._glEnable(GL_PROGRAM_POINT_SIZE_EXT); - //batch._glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - //batch._glEnable(GL_POINT_SMOOTH); batch.setInputFormat(streamFormat); batch.setInputBuffer(VERTICES_SLOT, posView); diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 18fc9ddd3c..e9dcd3aad3 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -482,6 +482,12 @@ void GLBackend::syncPipelineStateCache() { State::Data state; glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // Point size is always on + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + glEnable(GL_PROGRAM_POINT_SIZE_EXT); + glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + getCurrentGLState(state); State::Signature signature = State::evalSignature(state); From 5baf993c24a70b26de159259a5a6fbb5d6ffbc0f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Jul 2015 16:27:45 -0700 Subject: [PATCH 113/129] fixing the stars again --- interface/src/Stars.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp index 68e0001996..42b1a3f2e2 100644 --- a/interface/src/Stars.cpp +++ b/interface/src/Stars.cpp @@ -141,7 +141,6 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { auto state = gpu::StatePointer(new gpu::State()); // enable decal blend state->setDepthTest(gpu::State::DepthTest(false)); - state->setAntialiasedLineEnable(true); // line smoothing also smooth points state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); _gridPipeline.reset(gpu::Pipeline::create(program, state)); } @@ -153,6 +152,7 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { auto state = gpu::StatePointer(new gpu::State()); // enable decal blend state->setDepthTest(gpu::State::DepthTest(false)); + state->setAntialiasedLineEnable(true); // line smoothing also smooth points state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); _starsPipeline.reset(gpu::Pipeline::create(program, state)); @@ -219,6 +219,6 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { batch.setInputBuffer(VERTICES_SLOT, posView); batch.setInputBuffer(COLOR_SLOT, colView); batch.draw(gpu::Primitive::POINTS, STARFIELD_NUM_STARS); - + renderArgs->_context->render(batch); } From 4972cb024f34eb5fe2f4cfa34080be52ae06f3b2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Jul 2015 16:48:23 -0700 Subject: [PATCH 114/129] Try to make the inlucde sequence simpler in gpu for GLBackend --- libraries/gpu/src/gpu/Batch.cpp | 18 ------------------ libraries/gpu/src/gpu/GLBackend.cpp | 1 - libraries/gpu/src/gpu/GLBackend.h | 2 -- libraries/gpu/src/gpu/GLBackendShared.h | 2 -- 4 files changed, 23 deletions(-) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index b7f3ef444c..a10f5b3de7 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -10,12 +10,6 @@ // #include "Batch.h" -#include -#include - -#include "GPUConfig.h" - - #if defined(NSIGHT_FOUND) #include "nvToolsExt.h" @@ -288,15 +282,3 @@ void Batch::getQuery(const QueryPointer& query) { _params.push_back(_queries.cache(query)); } -void push_back(Batch::Params& params, const vec3& v) { - params.push_back(v.x); - params.push_back(v.y); - params.push_back(v.z); -} - -void push_back(Batch::Params& params, const vec4& v) { - params.push_back(v.x); - params.push_back(v.y); - params.push_back(v.z); - params.push_back(v.a); -} diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 4bc8abadd0..51a767882c 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -11,7 +11,6 @@ #include "GLBackendShared.h" #include -#include "GPULogging.h" #include using namespace gpu; diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 9d8c9ef805..3b1d4cde5e 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -18,8 +18,6 @@ #include "GPUConfig.h" #include "Context.h" -#include "Batch.h" - namespace gpu { diff --git a/libraries/gpu/src/gpu/GLBackendShared.h b/libraries/gpu/src/gpu/GLBackendShared.h index 75bef461f9..888fd1164d 100644 --- a/libraries/gpu/src/gpu/GLBackendShared.h +++ b/libraries/gpu/src/gpu/GLBackendShared.h @@ -16,8 +16,6 @@ #include "GPULogging.h" #include "GLBackend.h" -#include "Batch.h" - static const GLenum _primitiveToGLmode[gpu::NUM_PRIMITIVES] = { GL_POINTS, GL_LINES, From 8b7ad9cfcbaa68ab360c0a7561e5af5da8ee3c6e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Jul 2015 17:13:48 -0700 Subject: [PATCH 115/129] merge with upstream --- interface/src/Application.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5845267f72..1dc2878008 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1019,7 +1019,9 @@ void Application::paintGL() { // Back to the default framebuffer; gpu::Batch batch; batch.resetStages(); - // renderArgs._context->render(batch); + // TODO: Testing the water here, it is maybe not needed at all, + // i would like to keep it like that until we merge with DisplayPlugin + // renderArgs._context->render(batch); } void Application::runTests() { From ac46b2bd1733ba18fe6e1db99a1ee204c7408bdc Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 29 Jul 2015 17:38:23 -0700 Subject: [PATCH 116/129] Keep the resetstage in --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1dc2878008..8f37174c18 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1021,7 +1021,7 @@ void Application::paintGL() { batch.resetStages(); // TODO: Testing the water here, it is maybe not needed at all, // i would like to keep it like that until we merge with DisplayPlugin - // renderArgs._context->render(batch); + renderArgs._context->render(batch); } void Application::runTests() { From b7ecffa0beba9a47969e97f69063ab761a613781 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 29 Jul 2015 17:55:56 -0700 Subject: [PATCH 117/129] treat a "g" in an obj file the same as a "o" --- libraries/fbx/src/OBJReader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index f16c6ba215..da63b2f47f 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -306,7 +306,8 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi } QByteArray token = tokenizer.getDatum(); //qCDebug(modelformat) << token; - if (token == "g") { + // we don't support separate objects in the same file, so treat "o" the same as "g". + if (token == "g" || token == "o") { if (sawG) { // we've encountered the beginning of the next group. tokenizer.pushBackToken(OBJTokenizer::DATUM_TOKEN); From e32e45ed2b8faefc74c0f884d96eb9e1ee3a8865 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 29 Jul 2015 18:06:46 -0700 Subject: [PATCH 118/129] make sure the writting mask is on for depth buffer --- interface/src/Application.cpp | 2 -- libraries/gpu/src/gpu/GLBackendOutput.cpp | 12 ++++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8f37174c18..1c91f9282c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1019,8 +1019,6 @@ void Application::paintGL() { // Back to the default framebuffer; gpu::Batch batch; batch.resetStages(); - // TODO: Testing the water here, it is maybe not needed at all, - // i would like to keep it like that until we merge with DisplayPlugin renderArgs._context->render(batch); } diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index d57ef57d78..c898b4a843 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -209,10 +209,17 @@ void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { int stencil = batch._params[paramOffset + 1]._int; int useScissor = batch._params[paramOffset + 0]._int; + bool restoreDepthMask = false; GLuint glmask = 0; if (masks & Framebuffer::BUFFER_STENCIL) { glClearStencil(stencil); glmask |= GL_STENCIL_BUFFER_BIT; + + bool cacheDepthMask = _pipeline._stateCache.depthTest.getWriteMask(); + if (!cacheDepthMask) { + restoreDepthMask = true; + glDepthMask(GL_TRUE); + } } if (masks & Framebuffer::BUFFER_DEPTH) { @@ -252,6 +259,11 @@ void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { glDisable(GL_SCISSOR_TEST); } + // REstore write mask + if (restoreDepthMask) { + glDepthMask(GL_FALSE); + } + // Restore the color draw buffers only if a frmaebuffer is bound if (_output._framebuffer && !drawBuffers.empty()) { auto glFramebuffer = syncGPUObject(*_output._framebuffer); From 70d64a7777f90d6ae2afabc20348adfceb00e5e1 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 29 Jul 2015 18:27:10 -0700 Subject: [PATCH 119/129] Really fixing the depth write mask issue on clear... --- libraries/gpu/src/gpu/GLBackendOutput.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index c898b4a843..d75d0cf521 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -209,11 +209,18 @@ void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { int stencil = batch._params[paramOffset + 1]._int; int useScissor = batch._params[paramOffset + 0]._int; - bool restoreDepthMask = false; GLuint glmask = 0; if (masks & Framebuffer::BUFFER_STENCIL) { glClearStencil(stencil); glmask |= GL_STENCIL_BUFFER_BIT; + // TODO: we will probably need to also check the write mask of stencil like we do + // for depth buffer, but as would say a famous Fez owner "We'll cross that bridge when we come to it" + } + + bool restoreDepthMask = false; + if (masks & Framebuffer::BUFFER_DEPTH) { + glClearDepth(depth); + glmask |= GL_DEPTH_BUFFER_BIT; bool cacheDepthMask = _pipeline._stateCache.depthTest.getWriteMask(); if (!cacheDepthMask) { @@ -222,11 +229,6 @@ void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { } } - if (masks & Framebuffer::BUFFER_DEPTH) { - glClearDepth(depth); - glmask |= GL_DEPTH_BUFFER_BIT; - } - std::vector drawBuffers; if (masks & Framebuffer::BUFFER_COLORS) { for (unsigned int i = 0; i < Framebuffer::MAX_NUM_RENDER_BUFFERS; i++) { @@ -259,7 +261,7 @@ void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { glDisable(GL_SCISSOR_TEST); } - // REstore write mask + // Restore write mask meaning turn back off if (restoreDepthMask) { glDepthMask(GL_FALSE); } From 291e0e21ae858d09b53d05cbb1fc2dc19c7e306f Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Wed, 29 Jul 2015 18:47:27 -0700 Subject: [PATCH 120/129] HBAO final implementation --- .../src/AmbientOcclusionEffect.cpp | 2 +- .../render-utils/src/ambient_occlusion.slf | 183 +++--------------- .../render-utils/src/occlusion_blend.slf | 7 +- 3 files changed, 34 insertions(+), 158 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index f19fa6e18a..720f765ae4 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -164,7 +164,7 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { // Blend on transparent state->setBlendFunction(true, - gpu::State::SRC_COLOR, gpu::State::BLEND_OP_ADD, gpu::State::DEST_COLOR); + gpu::State::INV_SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::SRC_ALPHA); // Good to go add the brand new pipeline _blendPipeline.reset(gpu::Pipeline::create(program, state)); diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index 96aba989a8..f45fd9b6a0 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -17,99 +17,8 @@ <@include gpu/Transform.slh@> <$declareStandardTransform()$> -/* -varying vec2 varTexcoord; -uniform sampler2D depthTexture; -uniform sampler2D normalTexture; - -uniform float g_scale; -uniform float g_bias; -uniform float g_sample_rad; -uniform float g_intensity; -uniform float bufferWidth; -uniform float bufferHeight; - -#define SAMPLE_COUNT 4 - -float getRandom(vec2 uv) { - return fract(sin(dot(uv.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - -void main(void) { - vec3 sampleKernel[4] = { vec3(0.2, 0.0, 0.0), - vec3(0.0, 0.2, 0.0), - vec3(0.0, 0.0, 0.2), - vec3(0.2, 0.2, 0.2) }; - - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - - vec3 eyeDir = vec3(0.0, 0.0, -3.0); - vec3 cameraPositionWorldSpace; - <$transformEyeToWorldDir(cam, eyeDir, cameraPositionWorldSpace)$> - - vec4 depthColor = texture2D(depthTexture, varTexcoord); - - // z in non linear range [0,1] - float depthVal = depthColor.r; - // conversion into NDC [-1,1] - float zNDC = depthVal * 2.0 - 1.0; - float n = 1.0; // the near plane - float f = 30.0; // the far plane - float l = -1.0; // left - float r = 1.0; // right - float b = -1.0; // bottom - float t = 1.0; // top - - // conversion into eye space - float zEye = 2*f*n / (zNDC*(f-n)-(f+n)); - // Converting from pixel coordinates to NDC - float xNDC = gl_FragCoord.x/bufferWidth * 2.0 - 1.0; - float yNDC = gl_FragCoord.y/bufferHeight * 2.0 - 1.0; - // Unprojecting X and Y from NDC to eye space - float xEye = -zEye*(xNDC*(r-l)+(r+l))/(2.0*n); - float yEye = -zEye*(yNDC*(t-b)+(t+b))/(2.0*n); - vec3 currentFragEyeSpace = vec3(xEye, yEye, zEye); - vec3 currentFragWorldSpace; - <$transformEyeToWorldDir(cam, currentFragEyeSpace, currentFragWorldSpace)$> - - vec3 cameraToPositionRay = normalize(currentFragWorldSpace - cameraPositionWorldSpace); - vec3 origin = cameraToPositionRay * depthVal + cameraPositionWorldSpace; - - vec3 normal = normalize(texture2D(normalTexture, varTexcoord).xyz); - //normal = normalize(normal * normalMatrix); - - vec3 rvec = vec3(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx), getRandom(varTexcoord.xx)) * 2.0 - 1.0; - vec3 tangent = normalize(rvec - normal * dot(rvec, normal)); - vec3 bitangent = cross(normal, tangent); - mat3 tbn = mat3(tangent, bitangent, normal); - - float occlusion = 0.0; - - for (int i = 0; i < SAMPLE_COUNT; ++i) { - vec3 samplePos = origin + (tbn * sampleKernel[i]) * g_sample_rad; - vec4 offset = cam._projectionViewUntranslated * vec4(samplePos, 1.0); - - offset.xy = (offset.xy / offset.w) * 0.5 + 0.5; - float depth = length(samplePos - cameraPositionWorldSpace); - - float sampleDepthVal = texture2D(depthTexture, offset.xy).r; - - float rangeDelta = abs(depthVal - sampleDepthVal); - float rangeCheck = smoothstep(0.0, 1.0, g_sample_rad / rangeDelta); - - occlusion += rangeCheck * step(sampleDepthVal, depth); - } - - occlusion = 1.0 - occlusion / float(SAMPLE_COUNT); - occlusion = clamp(pow(occlusion, g_intensity), 0.0, 1.0); - gl_FragColor = vec4(vec3(occlusion), 1.0); -}*/ - -// This is a HBAO-Shader for OpenGL, based upon nvidias directX implementation -// supplied in their SampleSDK available from nvidia.com -// The slides describing the implementation is available at +// Based on NVidia HBAO implementation in D3D11 // http://www.nvidia.co.uk/object/siggraph-2008-HBAO.html varying vec2 varTexcoord; @@ -127,8 +36,6 @@ uniform float bufferHeight; const float PI = 3.14159265; const vec2 FocalLen = vec2(1.0, 1.0); -//const vec2 UVToViewA = vec2(1.0, 1.0); -//const vec2 UVToViewB = vec2(1.0, 1.0); const vec2 LinMAD = vec2(0.1-10.0, 0.1+10.0) / (2.0*0.1*10.0); @@ -141,13 +48,12 @@ const float R = 0.3; const float R2 = 0.3*0.3; const float NegInvR2 = - 1.0 / (0.3*0.3); const float TanBias = tan(30.0 * PI / 180.0); -const float MaxRadiusPixels = 100.0; +const float MaxRadiusPixels = 50.0; const int NumDirections = 6; const int NumSamples = 4; -float ViewSpaceZFromDepth(float d) -{ +float ViewSpaceZFromDepth(float d){ // [0,1] -> [-1,1] clip space d = d * 2.0 - 1.0; @@ -155,80 +61,62 @@ float ViewSpaceZFromDepth(float d) return -1.0 / (LinMAD.x * d + LinMAD.y); } -vec3 UVToViewSpace(vec2 uv, float z) -{ +vec3 UVToViewSpace(vec2 uv, float z){ //uv = UVToViewA * uv + UVToViewB; return vec3(uv * z, z); } -vec3 GetViewPos(vec2 uv) -{ +vec3 GetViewPos(vec2 uv){ float z = ViewSpaceZFromDepth(texture2D(depthTexture, uv).r); return UVToViewSpace(uv, z); } -vec3 GetViewPosPoint(ivec2 uv) -{ +vec3 GetViewPosPoint(ivec2 uv){ vec2 coord = vec2(gl_FragCoord.xy) + uv; //float z = texelFetch(texture0, coord, 0).r; float z = texture2D(depthTexture, uv).r; return UVToViewSpace(uv, z); } -float TanToSin(float x) -{ +float TanToSin(float x){ return x * inversesqrt(x*x + 1.0); } -float InvLength(vec2 V) -{ +float InvLength(vec2 V){ return inversesqrt(dot(V,V)); } -float Tangent(vec3 V) -{ +float Tangent(vec3 V){ return V.z * InvLength(V.xy); } -float BiasedTangent(vec3 V) -{ +float BiasedTangent(vec3 V){ return V.z * InvLength(V.xy) + TanBias; } -float Tangent(vec3 P, vec3 S) -{ +float Tangent(vec3 P, vec3 S){ return -(P.z - S.z) * InvLength(S.xy - P.xy); } -float Length2(vec3 V) -{ +float Length2(vec3 V){ return dot(V,V); } -vec3 MinDiff(vec3 P, vec3 Pr, vec3 Pl) -{ +vec3 MinDiff(vec3 P, vec3 Pr, vec3 Pl){ vec3 V1 = Pr - P; vec3 V2 = P - Pl; return (Length2(V1) < Length2(V2)) ? V1 : V2; } -vec2 SnapUVOffset(vec2 uv) -{ +vec2 SnapUVOffset(vec2 uv){ return round(uv * AORes) * InvAORes; } -float Falloff(float d2) -{ +float Falloff(float d2){ return d2 * NegInvR2 + 1.0f; } -float HorizonOcclusion( vec2 deltaUV, - vec3 P, - vec3 dPdu, - vec3 dPdv, - float randstep, - float numSamples) -{ +float HorizonOcclusion( vec2 deltaUV, vec3 P, vec3 dPdu, vec3 dPdv, float randstep, float numSamples){ float ao = 0; // Offset the first coord with some noise @@ -247,8 +135,7 @@ float HorizonOcclusion( vec2 deltaUV, vec3 S; // Sample to find the maximum angle - for(float s = 1; s <= numSamples; ++s) - { + for(float s = 1; s <= numSamples; ++s){ uv += deltaUV; S = GetViewPos(uv); tanS = Tangent(P, S); @@ -265,18 +152,14 @@ float HorizonOcclusion( vec2 deltaUV, sinH = sinS; } } - return ao; } -vec2 RotateDirections(vec2 Dir, vec2 CosSin) -{ - return vec2(Dir.x*CosSin.x - Dir.y*CosSin.y, - Dir.x*CosSin.y + Dir.y*CosSin.x); +vec2 RotateDirections(vec2 Dir, vec2 CosSin){ + return vec2(Dir.x*CosSin.x - Dir.y*CosSin.y, Dir.x*CosSin.y + Dir.y*CosSin.x); } -void ComputeSteps(inout vec2 stepSizeUv, inout float numSteps, float rayRadiusPix, float rand) -{ +void ComputeSteps(inout vec2 stepSizeUv, inout float numSteps, float rayRadiusPix, float rand){ // Avoid oversampling if numSteps is greater than the kernel radius in pixels numSteps = min(NumSamples, rayRadiusPix); @@ -297,28 +180,27 @@ void ComputeSteps(inout vec2 stepSizeUv, inout float numSteps, float rayRadiusPi stepSizeUv = stepSizePix * InvAORes; } -float getRandom(vec2 uv) { +float getRandom(vec2 uv){ return fract(sin(dot(uv.xy ,vec2(12.9898,78.233))) * 43758.5453); } -void main(void) -{ +void main(void){ float numDirections = NumDirections; vec3 P, Pr, Pl, Pt, Pb; - P = GetViewPos(varTexcoord); + P = GetViewPos(varTexcoord); // Sample neighboring pixels - Pr = GetViewPos(varTexcoord + vec2( InvAORes.x, 0)); - Pl = GetViewPos(varTexcoord + vec2(-InvAORes.x, 0)); - Pt = GetViewPos(varTexcoord + vec2( 0, InvAORes.y)); - Pb = GetViewPos(varTexcoord + vec2( 0,-InvAORes.y)); + Pr = GetViewPos(varTexcoord + vec2( InvAORes.x, 0)); + Pl = GetViewPos(varTexcoord + vec2(-InvAORes.x, 0)); + Pt = GetViewPos(varTexcoord + vec2( 0, InvAORes.y)); + Pb = GetViewPos(varTexcoord + vec2( 0,-InvAORes.y)); - // Calculate tangent basis vectors using the minimu difference + // Calculate tangent basis vectors using the minimum difference vec3 dPdu = MinDiff(P, Pr, Pl); vec3 dPdv = MinDiff(P, Pt, Pb) * (AORes.y * InvAORes.x); - // Get the random samples from the noise texture + // Get the random samples from the noise function vec3 random = vec3(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx), getRandom(varTexcoord.xx)); // Calculate the projected size of the hemisphere @@ -328,8 +210,7 @@ void main(void) float ao = 1.0; // Make sure the radius of the evaluated hemisphere is more than a pixel - if(rayRadiusPix > 1.0) - { + if(rayRadiusPix > 1.0){ ao = 0.0; float numSteps; vec2 stepSizeUV; @@ -340,8 +221,7 @@ void main(void) float alpha = 2.0 * PI / numDirections; // Calculate the horizon occlusion of each direction - for(float d = 0; d < numDirections; ++d) - { + for(float d = 0; d < numDirections; ++d){ float theta = alpha * d; // Apply noise to the direction @@ -361,6 +241,5 @@ void main(void) ao = 1.0 - ao / numDirections * AOStrength; } - //out_frag0 = vec2(ao, 30.0 * P.z); gl_FragColor = vec4(vec3(ao), 1.0); } \ No newline at end of file diff --git a/libraries/render-utils/src/occlusion_blend.slf b/libraries/render-utils/src/occlusion_blend.slf index 965d806759..cdab624b95 100644 --- a/libraries/render-utils/src/occlusion_blend.slf +++ b/libraries/render-utils/src/occlusion_blend.slf @@ -21,9 +21,6 @@ uniform sampler2D blurredOcclusionTexture; void main(void) { vec4 occlusionColor = texture2D(blurredOcclusionTexture, varTexcoord); - if(occlusionColor.r > 0.8 && occlusionColor.r <= 1.0) { - gl_FragColor = vec4(vec3(0.0), 0.0); - } else { - gl_FragColor = vec4(vec3(occlusionColor.r), 1.0); - } + gl_FragColor = vec4(vec3(0.0), occlusionColor.r); + } From a9556660c4ee2995eb5f96039c7489a0bf276d8b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 29 Jul 2015 20:53:24 -0700 Subject: [PATCH 121/129] fix linux build --- libraries/entities/src/ParticleEffectEntityItem.cpp | 6 +++--- libraries/gpu/src/gpu/Batch.cpp | 2 ++ libraries/gpu/src/gpu/GLBackendShader.cpp | 3 +-- libraries/gpu/src/gpu/GLBackendState.cpp | 10 +++++----- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 4dfc9dd436..dc5bbb85ed 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -155,9 +155,9 @@ void ParticleEffectEntityItem::computeAndUpdateDimensions() { float yMin = std::min(yApex, yEnd); // times 2 because dimensions are diameters not radii. - glm::vec3 dims(2.0f * std::max(fabs(xMin), fabs(xMax)), - 2.0f * std::max(fabs(yMin), fabs(yMax)), - 2.0f * std::max(fabs(zMin), fabs(zMax))); + glm::vec3 dims(2.0f * std::max(fabsf(xMin), fabsf(xMax)), + 2.0f * std::max(fabsf(yMin), fabsf(yMax)), + 2.0f * std::max(fabsf(zMin), fabsf(zMax))); EntityItem::setDimensions(dims); } diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index a10f5b3de7..0347536808 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -8,6 +8,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "Batch.h" #if defined(NSIGHT_FOUND) diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index dccd035cb4..5fa0e277e5 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -639,14 +639,13 @@ int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindin GLchar name[NAME_LENGTH]; GLint length = 0; GLint size = 0; - GLenum type = 0; GLint binding = -1; glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &length); glGetActiveUniformBlockName(glprogram, i, NAME_LENGTH, &length, name); glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_BINDING, &binding); glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &size); - + GLuint blockIndex = glGetUniformBlockIndex(glprogram, name); // CHeck if there is a requested binding for this block diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index e9dcd3aad3..22c61b2365 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -482,15 +482,15 @@ void GLBackend::syncPipelineStateCache() { State::Data state; glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - - // Point size is always on - glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); - glEnable(GL_PROGRAM_POINT_SIZE_EXT); + + // Point size is always on + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + glEnable(GL_PROGRAM_POINT_SIZE_EXT); glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); getCurrentGLState(state); State::Signature signature = State::evalSignature(state); - + _pipeline._stateCache = state; _pipeline._stateSignatureCache = signature; } From fa6d6a51230de1c91b8d2bf0ff29ddc5fe757603 Mon Sep 17 00:00:00 2001 From: Marcel Verhagen Date: Thu, 30 Jul 2015 15:08:02 +0200 Subject: [PATCH 122/129] Added the & references to the const variables --- libraries/fbx/src/FBXReader.cpp | 8 ++++---- libraries/fbx/src/FBXReader.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 69482a8c81..8b83acdca4 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1455,7 +1455,7 @@ void buildModelMesh(ExtractedMesh& extracted) { } #endif // USE_MODEL_MESH -QByteArray fileOnUrl(const QByteArray filenameString,const QString url) { +QByteArray fileOnUrl(const QByteArray& filenameString, const QString& url) { QString path = QFileInfo(url).path(); QByteArray filename = filenameString; QFileInfo checkFile(path + "/" + filename.replace('\\', '/')); @@ -1469,7 +1469,7 @@ QByteArray fileOnUrl(const QByteArray filenameString,const QString url) { return filename; } -FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QString url, bool loadLightmaps, float lightmapLevel) { +FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { QHash meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; @@ -2722,12 +2722,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, return geometry; } -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString url, bool loadLightmaps, float lightmapLevel) { +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); return readFBX(&buffer, mapping, url, loadLightmaps, lightmapLevel); } -FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString url, bool loadLightmaps, float lightmapLevel) { +FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { return extractFBXGeometry(parseFBX(device), mapping, url, loadLightmaps, lightmapLevel); } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index cf86c304ac..776b78b3bb 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -268,10 +268,10 @@ Q_DECLARE_METATYPE(FBXGeometry) /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); +FBXGeometry readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); #endif // hifi_FBXReader_h From fc80e427b9ceef1f61acf4f6005ef1a688091f94 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 30 Jul 2015 11:08:45 -0700 Subject: [PATCH 123/129] remove names from audio-mixer jitter calc comments --- assignment-client/src/audio/AudioMixer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index b68332210b..04cbb0b325 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -927,9 +927,9 @@ void AudioMixer::parseSettingsObject(const QJsonObject &settingsObject) { const QString USE_STDEV_FOR_DESIRED_CALC_JSON_KEY = "use_stdev_for_desired_calc"; _streamSettings._useStDevForJitterCalc = audioBufferGroupObject[USE_STDEV_FOR_DESIRED_CALC_JSON_KEY].toBool(); if (_streamSettings._useStDevForJitterCalc) { - qDebug() << "Using Philip's stdev method for jitter calc if dynamic jitter buffers enabled"; + qDebug() << "Using stdev method for jitter calc if dynamic jitter buffers enabled"; } else { - qDebug() << "Using Fred's max-gap method for jitter calc if dynamic jitter buffers enabled"; + qDebug() << "Using max-gap method for jitter calc if dynamic jitter buffers enabled"; } const QString WINDOW_STARVE_THRESHOLD_JSON_KEY = "window_starve_threshold"; From 14f4c9c6c04b462f177828717803f52256902887 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 30 Jul 2015 15:07:36 -0700 Subject: [PATCH 124/129] REmove more of the unnecessary GLBacken .h and GPUCOnfig.h include, The gpu::Context is now completely agnostic of the True Backend --- interface/src/Application.cpp | 5 ++-- interface/src/GLCanvas.h | 1 - libraries/gpu/src/gpu/Context.cpp | 17 ++++++----- libraries/gpu/src/gpu/Context.h | 28 +++++++++++++++---- libraries/gpu/src/gpu/GLBackend.cpp | 18 ++++++++---- libraries/gpu/src/gpu/GLBackend.h | 10 +++++-- .../render-utils/src/FramebufferCache.cpp | 1 - libraries/render/src/render/DrawStatus.cpp | 13 ++++----- libraries/render/src/render/DrawTask.cpp | 2 -- tests/render-utils/src/main.cpp | 4 +-- 10 files changed, 63 insertions(+), 36 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1c91f9282c..047596e40a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -772,8 +772,9 @@ void Application::initializeGL() { } #endif - // Where the gpuContext is created and where the TRUE Backend is created and assigned - _gpuContext = std::make_shared(new gpu::GLBackend()); + // Where the gpuContext is initialized and where the TRUE Backend is created and assigned + gpu::Context::init(); + _gpuContext = std::make_shared(); initDisplay(); qCDebug(interfaceapp, "Initialized Display."); diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index 925061edd0..6c53a17e04 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -13,7 +13,6 @@ #define hifi_GLCanvas_h #include -#include #include #include diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 6730be33bb..239c460c77 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -10,13 +10,16 @@ // #include "Context.h" -// this include should disappear! as soon as the gpu::Context is in place -#include "GLBackend.h" - using namespace gpu; -Context::Context(Backend* backend) : - _backend(backend) { +Context::CreateBackend Context::_createBackendCallback = nullptr; +Context::MakeProgram Context::_makeProgramCallback = nullptr; +std::once_flag Context::_initialized; + +Context::Context() { + if (_createBackendCallback) { + _backend.reset(_createBackendCallback()); + } } Context::Context(const Context& context) { @@ -26,8 +29,8 @@ Context::~Context() { } bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) { - if (shader.isProgram()) { - return GLBackend::makeProgram(shader, bindings); + if (shader.isProgram() && _makeProgramCallback) { + return _makeProgramCallback(shader, bindings); } return false; } diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index ab7a1d1c11..7158bd1a6d 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -12,6 +12,7 @@ #define hifi_gpu_Context_h #include +#include #include "Batch.h" @@ -26,13 +27,12 @@ namespace gpu { class Backend { public: - virtual~ Backend() {}; + virtual void render(Batch& batch) = 0; virtual void syncCache() = 0; virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0; - class TransformObject { public: Mat4 _model; @@ -118,7 +118,21 @@ protected: class Context { public: - Context(Backend* backend); + typedef Backend* (*CreateBackend)(); + typedef bool (*MakeProgram)(Shader& shader, const Shader::BindingSet& bindings); + + + // This one call must happen before any context is created or used (Shader::MakeProgram) in order to setup the Backend and any singleton data needed + template + static void init() { + std::call_once(_initialized, [] { + _createBackendCallback = T::createBackend; + _makeProgramCallback = T::makeProgram; + T::init(); + }); + } + + Context(); ~Context(); void render(Batch& batch); @@ -132,13 +146,17 @@ public: protected: Context(const Context& context); + std::unique_ptr _backend; + // This function can only be called by "static Shader::makeProgram()" // makeProgramShader(...) make a program shader ready to be used in a Batch. // It compiles the sub shaders, link them and defines the Slots and their bindings. // If the shader passed is not a program, nothing happens. - static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings); - std::unique_ptr _backend; + static CreateBackend _createBackendCallback; + static MakeProgram _makeProgramCallback; + static std::once_flag _initialized; friend class Shader; }; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 198fe4802a..c74a94e03e 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -63,12 +63,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glLineWidth), }; -GLBackend::GLBackend() : - _input(), - _transform(), - _pipeline(), - _output() -{ +void GLBackend::init() { static std::once_flag once; std::call_once(once, [] { qCDebug(gpulogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); @@ -108,7 +103,18 @@ GLBackend::GLBackend() : }*/ #endif }); +} +Backend* GLBackend::createBackend() { + return new GLBackend(); +} + +GLBackend::GLBackend() : + _input(), + _transform(), + _pipeline(), + _output() +{ initInput(); initTransform(); } diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 3686c5138d..e86424ceb7 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -22,10 +22,17 @@ namespace gpu { class GLBackend : public Backend { -public: + + // Context Backend static interface required + friend class Context; + static void init(); + static Backend* createBackend(); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); explicit GLBackend(bool syncCache); GLBackend(); +public: + virtual ~GLBackend(); virtual void render(Batch& batch); @@ -47,7 +54,6 @@ public: static void checkGLStackStable(std::function f); - static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); class GLBuffer : public GPUObject { diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index 601d99108d..d6ebd001d2 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include "RenderUtilsLogging.h" static QQueue _cachedFramebuffers; diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index f50f517d7d..cf3616a83a 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -18,10 +18,7 @@ #include #include -#include #include -#include -#include #include "drawItemBounds_vert.h" #include "drawItemBounds_frag.h" @@ -151,17 +148,17 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex const unsigned int VEC3_ADRESS_OFFSET = 3; for (int i = 0; i < nbItems; i++) { - batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const GLfloat*) (itemAABox + i)); - batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); + batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*) (itemAABox + i)); + batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); batch.draw(gpu::LINES, 24, 0); } batch.setPipeline(getDrawItemStatusPipeline()); for (int i = 0; i < nbItems; i++) { - batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const GLfloat*) (itemAABox + i)); - batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); - batch._glUniform4iv(_drawItemStatusValueLoc, 1, (const GLint*) (itemStatus + i)); + batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*) (itemAABox + i)); + batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); + batch._glUniform4iv(_drawItemStatusValueLoc, 1, (const int*) (itemStatus + i)); batch.draw(gpu::TRIANGLES, 24, 0); } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 1a3b68af03..36ff302952 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -17,9 +17,7 @@ #include #include #include -#include #include -#include using namespace render; diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index 7c02c7e8a7..9abd533650 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -94,7 +94,6 @@ class QTestWindow : public QWindow { QSize _size; //TextRenderer* _textRenderer[4]; RateCounter fps; - gpu::ContextPointer _gpuContext; protected: void renderText(); @@ -124,7 +123,8 @@ public: show(); makeCurrent(); - _gpuContext.reset(new gpu::Context(new gpu::GLBackend())); + + gpu::Context::init(); From fbf21cb089a4579b507dee31110266f183429243 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 30 Jul 2015 18:27:47 -0700 Subject: [PATCH 125/129] FIxed the problem on Mac, by removing all of the gpuConfig includesgit status q :q wq --- libraries/gpu/src/gpu/GLBackend.h | 8 +++---- libraries/gpu/src/gpu/GLBackendShader.cpp | 22 +++++++++++++++++-- .../src/DeferredLightingEffect.cpp | 5 ----- libraries/render-utils/src/Model.cpp | 6 +---- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index e86424ceb7..c0bae76d78 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -27,7 +27,7 @@ class GLBackend : public Backend { friend class Context; static void init(); static Backend* createBackend(); - static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings); explicit GLBackend(bool syncCache); GLBackend(); @@ -95,9 +95,9 @@ public: #if (GPU_TRANSFORM_PROFILE == GPU_CORE) #else - GLuint _transformObject_model = -1; - GLuint _transformCamera_viewInverse = -1; - GLuint _transformCamera_viewport = -1; + GLint _transformObject_model = -1; + GLint _transformCamera_viewInverse = -1; + GLint _transformCamera_viewport = -1; #endif GLShader(); diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 5fa0e277e5..9c0cf7628d 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -541,7 +541,12 @@ ElementResource getFormatFromGLUniform(GLenum gltype) { }; -int makeUniformSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& samplers) { +int makeUniformSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, + Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& samplers +#if (GPU_FEATURE_PROFILE == GPU_LEGACY) + , Shader::SlotSet& fakeBuffers +#endif +) { GLint uniformsCount = 0; #if (GPU_FEATURE_PROFILE == GPU_LEGACY) @@ -582,6 +587,15 @@ int makeUniformSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, S } if (elementResource._resource == Resource::BUFFER) { +#if (GPU_FEATURE_PROFILE == GPU_LEGACY) + // if in legacy profile, we fake the uniform buffer with an array + // this is where we detect it assuming it's explicitely assinged a binding + auto requestedBinding = slotBindings.find(std::string(sname)); + if (requestedBinding != slotBindings.end()) { + // found one buffer! + fakeBuffers.insert(Shader::Slot(sname, location, elementResource._element, elementResource._resource)); + } +#endif uniforms.insert(Shader::Slot(sname, location, elementResource._element, elementResource._resource)); } else { // For texture/Sampler, the location is the actual binding value @@ -736,8 +750,12 @@ bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindin Shader::SlotSet uniforms; Shader::SlotSet textures; Shader::SlotSet samplers; +#if (GPU_FEATURE_PROFILE == GPU_CORE) makeUniformSlots(object->_program, slotBindings, uniforms, textures, samplers); - +#else + makeUniformSlots(object->_program, slotBindings, uniforms, textures, samplers, buffers); +#endif + Shader::SlotSet inputs; makeInputSlots(object->_program, slotBindings, inputs); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 7563609026..3fc0a4c46a 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -614,13 +614,8 @@ void DeferredLightingEffect::loadLightProgram(const char* vertSource, const char locations.texcoordMat = program->getUniforms().findLocation("texcoordMat"); locations.coneParam = program->getUniforms().findLocation("coneParam"); -#if (GPU_FEATURE_PROFILE == GPU_CORE) locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); locations.atmosphereBufferUnit = program->getBuffers().findLocation("atmosphereBufferUnit"); -#else - locations.lightBufferUnit = program->getUniforms().findLocation("lightBuffer"); - locations.atmosphereBufferUnit = program->getUniforms().findLocation("atmosphereBufferUnit"); -#endif auto state = std::make_shared(); if (lightVolume) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 1e0e04c776..1e4f3f7190 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -187,13 +187,9 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model: locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); -#if (GPU_FEATURE_PROFILE == GPU_CORE) locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); -#else - locations.materialBufferUnit = program->getUniforms().findLocation("materialBuffer"); - locations.lightBufferUnit = program->getUniforms().findLocation("lightBuffer"); -#endif + locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices"); locations.clusterIndices = program->getInputs().findLocation("clusterIndices");; From 67760fad79897fa3151bd3b265a484f9c8b121d8 Mon Sep 17 00:00:00 2001 From: bwent Date: Fri, 31 Jul 2015 09:27:25 -0700 Subject: [PATCH 126/129] Add gettable naturalPosition property for model entities --- libraries/entities/src/EntityItemProperties.cpp | 9 ++++++++- libraries/entities/src/EntityItemProperties.h | 6 +++++- libraries/entities/src/EntityScriptingInterface.cpp | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 61253ba6ba..caae0203ae 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -114,7 +114,8 @@ _glowLevelChanged(false), _localRenderAlphaChanged(false), _defaultSettings(true), -_naturalDimensions(1.0f, 1.0f, 1.0f) +_naturalDimensions(1.0f, 1.0f, 1.0f), +_naturalPosition(0.0f, 0.0f, 0.0f) { } @@ -128,6 +129,11 @@ void EntityItemProperties::setSittingPoints(const QVector& sitting } } +void EntityItemProperties::setNaturalPosition(const glm::vec3& min, const glm::vec3& max) { + glm::vec3 radius = (max - min) / 2.0f; + _naturalPosition = max - radius; +} + bool EntityItemProperties::animationSettingsChanged() const { return _animationSettingsChanged; } @@ -378,6 +384,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(dimensions); if (!skipDefaults) { COPY_PROPERTY_TO_QSCRIPTVALUE(naturalDimensions); // gettable, but not settable + COPY_PROPERTY_TO_QSCRIPTVALUE(naturalPosition); } COPY_PROPERTY_TO_QSCRIPTVALUE(rotation); COPY_PROPERTY_TO_QSCRIPTVALUE(velocity); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 4532ffd67b..94e0f0fac8 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -192,7 +192,10 @@ public: const glm::vec3& getNaturalDimensions() const { return _naturalDimensions; } void setNaturalDimensions(const glm::vec3& value) { _naturalDimensions = value; } - + + const glm::vec3& getNaturalPosition() const { return _naturalPosition; } + void setNaturalPosition(const glm::vec3& min, const glm::vec3& max); + const QStringList& getTextureNames() const { return _textureNames; } void setTextureNames(const QStringList& value) { _textureNames = value; } @@ -232,6 +235,7 @@ private: QVector _sittingPoints; QStringList _textureNames; glm::vec3 _naturalDimensions; + glm::vec3 _naturalPosition; }; Q_DECLARE_METATYPE(EntityItemProperties); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 36fcc17a71..c40f7edd47 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -118,6 +118,7 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit results.setSittingPoints(geometry->sittingPoints); Extents meshExtents = geometry->getUnscaledMeshExtents(); results.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum); + results.setNaturalPosition(meshExtents.minimum, meshExtents.maximum); } } From aab1f708002c5e15d19e7b0371fa05a2faccd6e7 Mon Sep 17 00:00:00 2001 From: bwent Date: Fri, 31 Jul 2015 10:47:05 -0700 Subject: [PATCH 127/129] Renaming vars --- libraries/entities/src/EntityItemProperties.cpp | 6 +++--- libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/EntityScriptingInterface.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index caae0203ae..ebe4ac6014 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -129,9 +129,9 @@ void EntityItemProperties::setSittingPoints(const QVector& sitting } } -void EntityItemProperties::setNaturalPosition(const glm::vec3& min, const glm::vec3& max) { - glm::vec3 radius = (max - min) / 2.0f; - _naturalPosition = max - radius; +void EntityItemProperties::calculateNaturalPosition(const glm::vec3& min, const glm::vec3& max) { + glm::vec3 halfDimension = (max - min) / 2.0f; + _naturalPosition = max - halfDimension; } bool EntityItemProperties::animationSettingsChanged() const { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 94e0f0fac8..3ce6040d19 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -194,7 +194,7 @@ public: void setNaturalDimensions(const glm::vec3& value) { _naturalDimensions = value; } const glm::vec3& getNaturalPosition() const { return _naturalPosition; } - void setNaturalPosition(const glm::vec3& min, const glm::vec3& max); + void calculateNaturalPosition(const glm::vec3& min, const glm::vec3& max); const QStringList& getTextureNames() const { return _textureNames; } void setTextureNames(const QStringList& value) { _textureNames = value; } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index c40f7edd47..12f5ffe190 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -118,7 +118,7 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit results.setSittingPoints(geometry->sittingPoints); Extents meshExtents = geometry->getUnscaledMeshExtents(); results.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum); - results.setNaturalPosition(meshExtents.minimum, meshExtents.maximum); + results.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum); } } From b0afdb21ad3daf1b6ae6b139d39f32ba4c9fe48f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 31 Jul 2015 14:29:05 -0700 Subject: [PATCH 128/129] correct the unique_ptr char allocations --- assignment-client/src/Agent.cpp | 2 +- ice-server/src/IceServer.cpp | 2 +- libraries/networking/src/NLPacket.cpp | 4 ++-- libraries/networking/src/NLPacket.h | 4 ++-- libraries/networking/src/PacketReceiver.cpp | 2 +- libraries/networking/src/udt/Packet.cpp | 6 +++--- libraries/networking/src/udt/Packet.h | 6 +++--- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index da588bc316..43866ce3a6 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -70,7 +70,7 @@ void Agent::handleOctreePacket(QSharedPointer packet, SharedNodePointe // pull out the piggybacked packet and create a new QSharedPointer for it int piggyBackedSizeWithHeader = packet->getPayloadSize() - statsMessageLength; - std::unique_ptr buffer = std::unique_ptr(new char[piggyBackedSizeWithHeader]); + auto buffer = std::unique_ptr(new char[piggyBackedSizeWithHeader]); memcpy(buffer.get(), packet->getPayload() + statsMessageLength, piggyBackedSizeWithHeader); auto newPacket = NLPacket::fromReceivedPacket(std::move(buffer), piggyBackedSizeWithHeader, packet->getSenderSockAddr()); diff --git a/ice-server/src/IceServer.cpp b/ice-server/src/IceServer.cpp index 46c1582e7d..2a4e2b4300 100644 --- a/ice-server/src/IceServer.cpp +++ b/ice-server/src/IceServer.cpp @@ -50,7 +50,7 @@ void IceServer::processDatagrams() { while (_serverSocket.hasPendingDatagrams()) { // setup a buffer to read the packet into int packetSizeWithHeader = _serverSocket.pendingDatagramSize(); - std::unique_ptr buffer = std::unique_ptr(new char[packetSizeWithHeader]); + auto buffer = std::unique_ptr(new char[packetSizeWithHeader]); _serverSocket.readDatagram(buffer.get(), packetSizeWithHeader, sendingSockAddr.getAddressPointer(), sendingSockAddr.getPortPointer()); diff --git a/libraries/networking/src/NLPacket.cpp b/libraries/networking/src/NLPacket.cpp index 7a6503dbc3..7ec10fc4ce 100644 --- a/libraries/networking/src/NLPacket.cpp +++ b/libraries/networking/src/NLPacket.cpp @@ -46,7 +46,7 @@ std::unique_ptr NLPacket::create(PacketType::Value type, qint64 size) return packet; } -std::unique_ptr NLPacket::fromReceivedPacket(std::unique_ptr data, qint64 size, +std::unique_ptr NLPacket::fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) { // Fail with null data Q_ASSERT(data); @@ -85,7 +85,7 @@ NLPacket::NLPacket(const NLPacket& other) : Packet(other) { } -NLPacket::NLPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : +NLPacket::NLPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : Packet(std::move(data), size, senderSockAddr) { adjustPayloadStartAndCapacity(); diff --git a/libraries/networking/src/NLPacket.h b/libraries/networking/src/NLPacket.h index 669278ed65..6ebf15ffec 100644 --- a/libraries/networking/src/NLPacket.h +++ b/libraries/networking/src/NLPacket.h @@ -20,7 +20,7 @@ class NLPacket : public Packet { Q_OBJECT public: static std::unique_ptr create(PacketType::Value type, qint64 size = -1); - static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, + static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); // Provided for convenience, try to limit use static std::unique_ptr createCopy(const NLPacket& other); @@ -45,7 +45,7 @@ protected: NLPacket(PacketType::Value type); NLPacket(PacketType::Value type, qint64 size); - NLPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + NLPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); NLPacket(const NLPacket& other); void readSourceID(); diff --git a/libraries/networking/src/PacketReceiver.cpp b/libraries/networking/src/PacketReceiver.cpp index 5fc327673d..b1a77d4c39 100644 --- a/libraries/networking/src/PacketReceiver.cpp +++ b/libraries/networking/src/PacketReceiver.cpp @@ -243,7 +243,7 @@ void PacketReceiver::processDatagrams() { while (nodeList && nodeList->getNodeSocket().hasPendingDatagrams()) { // setup a buffer to read the packet into int packetSizeWithHeader = nodeList->getNodeSocket().pendingDatagramSize(); - std::unique_ptr buffer = std::unique_ptr(new char[packetSizeWithHeader]); + auto buffer = std::unique_ptr(new char[packetSizeWithHeader]); // if we're supposed to drop this packet then break out here if (_shouldDropPackets) { diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 02a44c4a4f..13f8a39e26 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -31,7 +31,7 @@ std::unique_ptr Packet::create(PacketType::Value type, qint64 size) { return packet; } -std::unique_ptr Packet::fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) { +std::unique_ptr Packet::fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) { // Fail with invalid size Q_ASSERT(size >= 0); @@ -82,7 +82,7 @@ Packet::Packet(PacketType::Value type, qint64 size) : } } -Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : +Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : _packetSize(size), _packet(std::move(data)), _senderSockAddr(senderSockAddr) @@ -110,7 +110,7 @@ Packet& Packet::operator=(const Packet& other) { _type = other._type; _packetSize = other._packetSize; - _packet = std::unique_ptr(new char[_packetSize]); + _packet = std::unique_ptr(new char[_packetSize]); memcpy(_packet.get(), other._packet.get(), _packetSize); _payloadStart = _packet.get() + (other._payloadStart - other._packet.get()); diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index b4c53b8165..91b5974e09 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -27,7 +27,7 @@ public: static const qint64 PACKET_WRITE_ERROR; static std::unique_ptr create(PacketType::Value type, qint64 size = -1); - static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); // Provided for convenience, try to limit use static std::unique_ptr createCopy(const Packet& other); @@ -88,7 +88,7 @@ public: protected: Packet(PacketType::Value type, qint64 size); - Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); Packet(const Packet& other); Packet& operator=(const Packet& other); Packet(Packet&& other); @@ -109,7 +109,7 @@ protected: PacketVersion _version; // Packet version qint64 _packetSize = 0; // Total size of the allocated memory - std::unique_ptr _packet; // Allocated memory + std::unique_ptr _packet; // Allocated memory char* _payloadStart = nullptr; // Start of the payload qint64 _payloadCapacity = 0; // Total capacity of the payload From 12ad60a6b5afa77c73b4d899922afa5e637e04f8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 31 Jul 2015 14:48:54 -0700 Subject: [PATCH 129/129] add a missed char[] in OctreePacketProcessor --- interface/src/octree/OctreePacketProcessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index 7bb94323b7..1abbb21089 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -57,7 +57,7 @@ void OctreePacketProcessor::processPacket(QSharedPointer packet, Share if (piggybackBytes) { // construct a new packet from the piggybacked one - std::unique_ptr buffer = std::unique_ptr(new char[piggybackBytes]); + auto buffer = std::unique_ptr(new char[piggybackBytes]); memcpy(buffer.get(), packet->getPayload() + statsMessageLength, piggybackBytes); auto newPacket = NLPacket::fromReceivedPacket(std::move(buffer), piggybackBytes, packet->getSenderSockAddr());