From 71d361ed3bc7f31cec1d2d09d2cf674a90432877 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 30 Nov 2015 17:06:35 -0800 Subject: [PATCH 001/195] fixed hydra paint, adding more interactive brushes --- examples/example/painting/hydraPaint.js | 12 +++---- .../src/RenderablePolyLineEntityItem.cpp | 32 ++++++++++++++----- .../src/RenderablePolyLineEntityItem.h | 4 +++ .../entities-renderer/src/paintStroke.slf | 14 +++++--- .../entities-renderer/src/paintStroke.slv | 2 ++ libraries/entities/src/PolyLineEntityItem.cpp | 2 ++ libraries/entities/src/PolyLineEntityItem.h | 4 ++- 7 files changed, 51 insertions(+), 19 deletions(-) diff --git a/examples/example/painting/hydraPaint.js b/examples/example/painting/hydraPaint.js index 36137945cc..14ea256369 100644 --- a/examples/example/painting/hydraPaint.js +++ b/examples/example/painting/hydraPaint.js @@ -67,12 +67,12 @@ var colorPalette = [{ var MIN_STROKE_WIDTH = 0.002; var MAX_STROKE_WIDTH = 0.05; -function controller(side, cycleColorButton) { +function controller(side, triggerAction) { this.triggerHeld = false; this.triggerThreshold = 0.9; this.side = side; - this.trigger = side == LEFT ? Controller.Stantard.LT : Controller.Standard.RT; - this.cycleColorButton = side == LEFT ? Controller.Stantard.LeftPrimaryThumb : Controller.Standard.RightPrimaryThumb; + this.triggerAction = triggerAction; + this.cycleColorButton = side == LEFT ? Controller.Standard.LeftPrimaryThumb : Controller.Standard.RightPrimaryThumb; this.points = []; this.normals = []; @@ -174,7 +174,7 @@ function controller(side, cycleColorButton) { this.cycleColorButtonPressed = Controller.getValue(this.cycleColorButton); this.palmPosition = this.side == RIGHT ? MyAvatar.rightHandPose.translation : MyAvatar.leftHandPose.translation; this.tipPosition = this.side == RIGHT ? MyAvatar.rightHandTipPose.translation : MyAvatar.leftHandTipPose.translation; - this.triggerValue = Controller.getValue(this.trigger); + this.triggerValue = Controller.getActionValue(this.triggerAction); if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) { @@ -212,8 +212,8 @@ function vectorIsZero(v) { } -var rightController = new controller(RIGHT); -var leftController = new controller(LEFT); +var rightController = new controller(RIGHT, Controller.findAction("RIGHT_HAND_CLICK")); +var leftController = new controller(LEFT, Controller.findAction("LEFT_HAND_CLICK")); Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 036d37a95b..63a03bb8e7 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -24,14 +24,22 @@ +struct PolyLineUniforms { + float time; +}; + EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return EntityItemPointer(new RenderablePolyLineEntityItem(entityID, properties)); } RenderablePolyLineEntityItem::RenderablePolyLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : -PolyLineEntityItem(entityItemID, properties) { - _numVertices = 0; +PolyLineEntityItem(entityItemID, properties), +_counter(0.0f), +_numVertices(0) +{ _vertices = QVector(0.0f); + PolyLineUniforms uniforms; + _uniformBuffer = std::make_shared(sizeof(PolyLineUniforms), (const gpu::Byte*) &uniforms); } @@ -161,6 +169,18 @@ void RenderablePolyLineEntityItem::updateVertices() { } +void RenderablePolyLineEntityItem::update(const quint64& now) { + PolyLineUniforms uniforms; + _counter += 0.01; + uniforms.time = _counter; + memcpy(&_uniformBuffer.edit(), &uniforms, sizeof(PolyLineUniforms)); + + if (_pointsChanged || _strokeWidthsChanged || _normalsChanged) { + updateVertices(); + updateGeometry(); + } + +} void RenderablePolyLineEntityItem::render(RenderArgs* args) { QWriteLocker lock(&_quadReadWriteLock); @@ -181,17 +201,13 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderablePolyLineEntityItem::render"); Q_ASSERT(getType() == EntityTypes::PolyLine); - Q_ASSERT(args->_batch); - if (_pointsChanged || _strokeWidthsChanged || _normalsChanged) { - updateVertices(); - updateGeometry(); - } gpu::Batch& batch = *args->_batch; Transform transform = Transform(); transform.setTranslation(getPosition()); transform.setRotation(getRotation()); + batch.setUniformBuffer(0, _uniformBuffer); batch.setModelTransform(transform); batch.setPipeline(_pipeline); @@ -200,7 +216,7 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) { } else { batch.setResourceTexture(PAINTSTROKE_GPU_SLOT, args->_whiteTexture); } - + batch.setInputFormat(_format); batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index c49777cfa3..658614e72e 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -29,6 +29,8 @@ public: RenderablePolyLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); virtual void render(RenderArgs* args); + virtual void update(const quint64& now) override; + virtual bool needsToCallUpdate() const { return true; }; SIMPLE_RENDERABLE(); @@ -42,8 +44,10 @@ protected: void updateGeometry(); void updateVertices(); gpu::BufferPointer _verticesBuffer; + gpu::BufferView _uniformBuffer; unsigned int _numVertices; QVector _vertices; + float _counter; }; diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 4e2bc8d097..48de1274f4 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -23,11 +23,15 @@ in vec3 interpolatedNormal; in vec2 varTexcoord; in vec4 varColor; -float rand(vec2 point){ - return fract(sin(dot(point.xy ,vec2(12.9898,78.233))) * 43758.5453); -} +flat in int varVertexId; +struct PolyLineUniforms { + float time; +}; +uniform polyLineBuffer { + PolyLineUniforms polyline; +}; void main(void) { @@ -35,11 +39,13 @@ void main(void) { vec4 texel = texture(originalTexture, varTexcoord); int frontCondition = 1 -int(gl_FrontFacing) * 2; vec3 color = varColor.rgb; + color.g = 1.0 + sin(polyline.time) * 0.5; + //texel.a = varVertexId / 20.0; //vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess packDeferredFragmentTranslucent( interpolatedNormal * frontCondition, texel.a, - color *texel.rgb, + color * texel.rgb, vec3(0.01, 0.01, 0.01), 10.0); } diff --git a/libraries/entities-renderer/src/paintStroke.slv b/libraries/entities-renderer/src/paintStroke.slv index 7d7523deb9..25f046456a 100644 --- a/libraries/entities-renderer/src/paintStroke.slv +++ b/libraries/entities-renderer/src/paintStroke.slv @@ -24,6 +24,7 @@ out vec3 interpolatedNormal; out vec2 varTexcoord; out vec4 varColor; +flat out int varVertexId; void main(void) { @@ -31,6 +32,7 @@ void main(void) { // pass along the diffuse color varColor = inColor; + varVertexId = gl_VertexID; // standard transform TransformCamera cam = getTransformCamera(); diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 012ec3ca4a..f2cdd6c1c1 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -90,6 +90,7 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) { return somethingChanged; } + bool PolyLineEntityItem::appendPoint(const glm::vec3& point) { if (_points.size() > MAX_POINTS_PER_LINE - 1) { qDebug() << "MAX POINTS REACHED!"; @@ -105,6 +106,7 @@ bool PolyLineEntityItem::appendPoint(const glm::vec3& point) { return true; } + bool PolyLineEntityItem::setStrokeWidths(const QVector& strokeWidths) { _strokeWidths = strokeWidths; _strokeWidthsChanged = true; diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 4da52f3f21..1610bf87b5 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -75,7 +75,9 @@ class PolyLineEntityItem : public EntityItem { _texturesChangedFlag = true; } } - + + virtual bool needsToCallUpdate() const { return true; } + virtual ShapeType getShapeType() const { return SHAPE_TYPE_LINE; } // never have a ray intersection pick a PolyLineEntityItem. From 191cab2e5f5fd60f40c5310cb8c35d564b1a4157 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 1 Dec 2015 10:15:47 -0800 Subject: [PATCH 002/195] adding light trail app --- examples/flowArts/lightTrails.js | 223 ++++++++++++++++++++++++++++++ examples/lightTrails.js | 224 +++++++++++++++++++++++++++++++ 2 files changed, 447 insertions(+) create mode 100644 examples/flowArts/lightTrails.js create mode 100644 examples/lightTrails.js diff --git a/examples/flowArts/lightTrails.js b/examples/flowArts/lightTrails.js new file mode 100644 index 0000000000..60754f42a8 --- /dev/null +++ b/examples/flowArts/lightTrails.js @@ -0,0 +1,223 @@ +// +// hydraPaint.js +// examples +// +// Created by Eric Levin on 5/14/15. +// Copyright 2014 High Fidelity, Inc. +// +// This script allows you to paint with the hydra! +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +var LEFT = 0; +var RIGHT = 1; +var LASER_WIDTH = 3; +var LASER_COLOR = { + red: 50, + green: 150, + blue: 200 +}; +var TRIGGER_THRESHOLD = .1; + +var MAX_POINTS_PER_LINE = 40; + +var LIFETIME = 6000; +var DRAWING_DEPTH = 1; +var LINE_DIMENSIONS = 20; + + +var MIN_POINT_DISTANCE = 0.01; + +var MIN_BRUSH_RADIUS = 0.08; +var MAX_BRUSH_RADIUS = 0.1; + +var RIGHT_BUTTON_1 = 7 +var RIGHT_BUTTON_2 = 8 +var RIGHT_BUTTON_3 = 9; +var RIGHT_BUTTON_4 = 10 +var LEFT_BUTTON_1 = 1; +var LEFT_BUTTON_2 = 2; +var LEFT_BUTTON_3 = 3; +var LEFT_BUTTON_4 = 4; + +var colorPalette = [{ + red: 250, + green: 0, + blue: 0 +}, { + red: 214, + green: 91, + blue: 67 +}, { + red: 192, + green: 41, + blue: 66 +}, { + red: 84, + green: 36, + blue: 55 +}, { + red: 83, + green: 119, + blue: 122 +}]; + +var MIN_STROKE_WIDTH = 0.002; +var MAX_STROKE_WIDTH = 0.05; + +function controller(side, triggerAction) { + this.triggerHeld = false; + this.triggerThreshold = 0.9; + this.side = side; + this.triggerAction = triggerAction; + this.cycleColorButton = side == LEFT ? Controller.Standard.LeftPrimaryThumb : Controller.Standard.RightPrimaryThumb; + + this.points = []; + this.normals = []; + this.strokeWidths = []; + + this.currentColorIndex = 0; + this.currentColor = colorPalette[this.currentColorIndex]; + + var self = this; + + + this.brush = Entities.addEntity({ + type: 'Sphere', + position: { + x: 0, + y: 0, + z: 0 + }, + color: this.currentColor, + dimensions: { + x: MIN_BRUSH_RADIUS, + y: MIN_BRUSH_RADIUS, + z: MIN_BRUSH_RADIUS + } + }); + + this.cycleColor = function() { + this.currentColor = colorPalette[++this.currentColorIndex]; + if (this.currentColorIndex === colorPalette.length - 1) { + this.currentColorIndex = -1; + } + } + this.newLine = function(position) { + this.linePosition = position; + this.line = Entities.addEntity({ + position: position, + type: "PolyLine", + color: this.currentColor, + dimensions: { + x: LINE_DIMENSIONS, + y: LINE_DIMENSIONS, + z: LINE_DIMENSIONS + }, + textures: "http://localhost:8080/trails.png", + lifetime: LIFETIME + }); + this.points = []; + this.normals = [] + this.strokeWidths = []; + } + + this.update = function(deltaTime) { + this.updateControllerState(); + var newBrushPosOffset = Vec3.multiply(Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)), DRAWING_DEPTH); + var newBrushPos = Vec3.sum(this.palmPosition, newBrushPosOffset); + var brushRadius = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_BRUSH_RADIUS, MAX_BRUSH_RADIUS) + Entities.editEntity(this.brush, { + position: newBrushPos, + color: this.currentColor, + dimensions: { + x: brushRadius, + y: brushRadius, + z: brushRadius + } + }); + + + if (this.triggerValue > TRIGGER_THRESHOLD && !this.drawing) { + this.newLine(newBrushPos); + this.drawing = true; + } else if (this.drawing && this.triggerValue < TRIGGER_THRESHOLD) { + this.drawing = false; + } + + if (this.drawing && this.points.length < MAX_POINTS_PER_LINE) { + var localPoint = Vec3.subtract(newBrushPos, this.linePosition); + if (Vec3.distance(localPoint, this.points[this.points.length - 1]) < MIN_POINT_DISTANCE) { + //Need a minimum distance to avoid binormal NANs + return; + } + + this.points.push(localPoint); + var normal = computeNormal(newBrushPos, Camera.getPosition()); + + this.normals.push(normal); + var strokeWidth = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH); + this.strokeWidths.push(strokeWidth); + Entities.editEntity(this.line, { + linePoints: this.points, + normals: this.normals, + strokeWidths: this.strokeWidths, + color: this.currentColor + }); + + } + } + + + this.updateControllerState = function() { + this.cycleColorButtonPressed = Controller.getValue(this.cycleColorButton); + this.palmPosition = this.side == RIGHT ? MyAvatar.rightHandPose.translation : MyAvatar.leftHandPose.translation; + this.tipPosition = this.side == RIGHT ? MyAvatar.rightHandTipPose.translation : MyAvatar.leftHandTipPose.translation; + this.triggerValue = Controller.getActionValue(this.triggerAction); + + + if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) { + this.cycleColor(); + Entities.editEntity(this.brush, { + // color: this.currentColor + }); + } + + this.prevCycleColorButtonPressed = this.cycleColorButtonPressed; + + } + + this.cleanup = function() { + Entities.deleteEntity(self.brush); + } +} + +function computeNormal(p1, p2) { + return Vec3.normalize(Vec3.subtract(p2, p1)); +} + +function update(deltaTime) { + leftController.update(deltaTime); + rightController.update(deltaTime); +} + +function scriptEnding() { + leftController.cleanup(); + rightController.cleanup(); +} + +function vectorIsZero(v) { + return v.x === 0 && v.y === 0 && v.z === 0; +} + + +var rightController = new controller(RIGHT, Controller.findAction("RIGHT_HAND_CLICK")); +var leftController = new controller(LEFT, Controller.findAction("LEFT_HAND_CLICK")); +Script.update.connect(update); +Script.scriptEnding.connect(scriptEnding); + +function map(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); +} \ No newline at end of file diff --git a/examples/lightTrails.js b/examples/lightTrails.js new file mode 100644 index 0000000000..fc8d7082e4 --- /dev/null +++ b/examples/lightTrails.js @@ -0,0 +1,224 @@ +// +// hydraPaint.js +// examples +// +// Created by Eric Levin on 5/14/15. +// Copyright 2014 High Fidelity, Inc. +// +// This script allows you to paint with the hydra! +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +var LEFT = 0; +var RIGHT = 1; +var LASER_WIDTH = 3; +var LASER_COLOR = { + red: 50, + green: 150, + blue: 200 +}; +var TRIGGER_THRESHOLD = .1; + +var MAX_POINTS_PER_LINE = 40; + +var LIFETIME = 6000; +var DRAWING_DEPTH = 1; +var LINE_DIMENSIONS = 20; + + +var MIN_POINT_DISTANCE = 0.01; + +var MIN_BRUSH_RADIUS = 0.08; +var MAX_BRUSH_RADIUS = 0.1; + +var RIGHT_BUTTON_1 = 7 +var RIGHT_BUTTON_2 = 8 +var RIGHT_BUTTON_3 = 9; +var RIGHT_BUTTON_4 = 10 +var LEFT_BUTTON_1 = 1; +var LEFT_BUTTON_2 = 2; +var LEFT_BUTTON_3 = 3; +var LEFT_BUTTON_4 = 4; + +var colorPalette = [{ + red: 250, + green: 0, + blue: 0 +}, { + red: 214, + green: 91, + blue: 67 +}, { + red: 192, + green: 41, + blue: 66 +}, { + red: 84, + green: 36, + blue: 55 +}, { + red: 83, + green: 119, + blue: 122 +}]; + +var MIN_STROKE_WIDTH = 0.002; +var MAX_STROKE_WIDTH = 0.05; + +function controller(side, triggerAction) { + this.triggerHeld = false; + this.triggerThreshold = 0.9; + this.side = side; + this.triggerAction = triggerAction; + this.cycleColorButton = side == LEFT ? Controller.Standard.LeftPrimaryThumb : Controller.Standard.RightPrimaryThumb; + + this.points = []; + this.normals = []; + this.strokeWidths = []; + + this.currentColorIndex = 0; + this.currentColor = colorPalette[this.currentColorIndex]; + + var self = this; + + + this.brush = Entities.addEntity({ + type: 'Sphere', + position: { + x: 0, + y: 0, + z: 0 + }, + color: this.currentColor, + dimensions: { + x: MIN_BRUSH_RADIUS, + y: MIN_BRUSH_RADIUS, + z: MIN_BRUSH_RADIUS + } + }); + + this.cycleColor = function() { + this.currentColor = colorPalette[++this.currentColorIndex]; + if (this.currentColorIndex === colorPalette.length - 1) { + this.currentColorIndex = -1; + } + } + this.newLine = function(position) { + this.linePosition = position; + this.line = Entities.addEntity({ + position: position, + type: "PolyLine", + color: this.currentColor, + dimensions: { + x: LINE_DIMENSIONS, + y: LINE_DIMENSIONS, + z: LINE_DIMENSIONS + }, + textures: "http://localhost:8080/trails.png", + lifetime: LIFETIME + }); + this.points = []; + this.normals = [] + this.strokeWidths = []; + } + + this.update = function(deltaTime) { + this.updateControllerState(); + var newBrushPosOffset = Vec3.multiply(Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)), DRAWING_DEPTH); + var newBrushPos = Vec3.sum(this.palmPosition, newBrushPosOffset); + var brushRadius = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_BRUSH_RADIUS, MAX_BRUSH_RADIUS) + Entities.editEntity(this.brush, { + position: newBrushPos, + color: this.currentColor, + dimensions: { + x: brushRadius, + y: brushRadius, + z: brushRadius + } + }); + + + if (this.triggerValue > TRIGGER_THRESHOLD && !this.drawing) { + this.newLine(newBrushPos); + this.drawing = true; + } else if (this.drawing && this.triggerValue < TRIGGER_THRESHOLD) { + this.drawing = false; + } + + if (this.drawing && this.points.length < MAX_POINTS_PER_LINE) { + var localPoint = Vec3.subtract(newBrushPos, this.linePosition); + if (Vec3.distance(localPoint, this.points[this.points.length - 1]) < MIN_POINT_DISTANCE) { + //Need a minimum distance to avoid binormal NANs + return; + } + + this.points.push(localPoint); + var normal = computeNormal(newBrushPos, Camera.getPosition()); + + this.normals.push(normal); + var strokeWidth = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH); + this.strokeWidths.push(strokeWidth); + Entities.editEntity(this.line, { + linePoints: this.points, + normals: this.normals, + strokeWidths: this.strokeWidths, + color: this.currentColor + }); + } + + // Once we get to max points + } + + + this.updateControllerState = function() { + this.cycleColorButtonPressed = Controller.getValue(this.cycleColorButton); + this.palmPosition = this.side == RIGHT ? MyAvatar.rightHandPose.translation : MyAvatar.leftHandPose.translation; + this.tipPosition = this.side == RIGHT ? MyAvatar.rightHandTipPose.translation : MyAvatar.leftHandTipPose.translation; + this.triggerValue = Controller.getActionValue(this.triggerAction); + + + if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) { + this.cycleColor(); + Entities.editEntity(this.brush, { + // color: this.currentColor + }); + } + + this.prevCycleColorButtonPressed = this.cycleColorButtonPressed; + + } + + this.cleanup = function() { + Entities.deleteEntity(self.brush); + } +} + +function computeNormal(p1, p2) { + return Vec3.normalize(Vec3.subtract(p2, p1)); +} + +function update(deltaTime) { + leftController.update(deltaTime); + rightController.update(deltaTime); +} + +function scriptEnding() { + leftController.cleanup(); + rightController.cleanup(); +} + +function vectorIsZero(v) { + return v.x === 0 && v.y === 0 && v.z === 0; +} + + +var rightController = new controller(RIGHT, Controller.findAction("RIGHT_HAND_CLICK")); +var leftController = new controller(LEFT, Controller.findAction("LEFT_HAND_CLICK")); +Script.update.connect(update); +Script.scriptEnding.connect(scriptEnding); + +function map(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); +} \ No newline at end of file From a83f374036727eab11afe3616f5f8299814c1e97 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 1 Dec 2015 10:50:25 -0800 Subject: [PATCH 003/195] tweaking light trail --- examples/flowArts/lightTrails.js | 103 +++++++++++-------------------- 1 file changed, 36 insertions(+), 67 deletions(-) diff --git a/examples/flowArts/lightTrails.js b/examples/flowArts/lightTrails.js index 60754f42a8..c01fc1c4d3 100644 --- a/examples/flowArts/lightTrails.js +++ b/examples/flowArts/lightTrails.js @@ -33,14 +33,6 @@ var MIN_POINT_DISTANCE = 0.01; var MIN_BRUSH_RADIUS = 0.08; var MAX_BRUSH_RADIUS = 0.1; -var RIGHT_BUTTON_1 = 7 -var RIGHT_BUTTON_2 = 8 -var RIGHT_BUTTON_3 = 9; -var RIGHT_BUTTON_4 = 10 -var LEFT_BUTTON_1 = 1; -var LEFT_BUTTON_2 = 2; -var LEFT_BUTTON_3 = 3; -var LEFT_BUTTON_4 = 4; var colorPalette = [{ red: 250, @@ -73,94 +65,73 @@ function controller(side, triggerAction) { this.side = side; this.triggerAction = triggerAction; this.cycleColorButton = side == LEFT ? Controller.Standard.LeftPrimaryThumb : Controller.Standard.RightPrimaryThumb; - + this.currentColorIndex = 0; + this.currentColor = colorPalette[this.currentColorIndex]; + this.trail = Entities.addEntity({ + type: "PolyLine", + color: this.currentColor, + dimensions: { + x: LINE_DIMENSIONS, + y: LINE_DIMENSIONS, + z: LINE_DIMENSIONS + }, + textures: "http://localhost:8080/trails.png", + lifetime: LIFETIME + }); this.points = []; this.normals = []; this.strokeWidths = []; - - this.currentColorIndex = 0; - this.currentColor = colorPalette[this.currentColorIndex]; - var self = this; - this.brush = Entities.addEntity({ - type: 'Sphere', - position: { - x: 0, - y: 0, - z: 0 - }, - color: this.currentColor, - dimensions: { - x: MIN_BRUSH_RADIUS, - y: MIN_BRUSH_RADIUS, - z: MIN_BRUSH_RADIUS - } - }); - this.cycleColor = function() { this.currentColor = colorPalette[++this.currentColorIndex]; if (this.currentColorIndex === colorPalette.length - 1) { this.currentColorIndex = -1; } } - this.newLine = function(position) { - this.linePosition = position; - this.line = Entities.addEntity({ - position: position, - type: "PolyLine", - color: this.currentColor, - dimensions: { - x: LINE_DIMENSIONS, - y: LINE_DIMENSIONS, - z: LINE_DIMENSIONS - }, - textures: "http://localhost:8080/trails.png", - lifetime: LIFETIME + + this.setTrailPosition = function(position) { + this.trailPosition = position; + Entities.editEntity(this.trail, { + position: this.trailPosition }); - this.points = []; - this.normals = [] - this.strokeWidths = []; } + this.update = function(deltaTime) { this.updateControllerState(); - var newBrushPosOffset = Vec3.multiply(Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)), DRAWING_DEPTH); - var newBrushPos = Vec3.sum(this.palmPosition, newBrushPosOffset); - var brushRadius = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_BRUSH_RADIUS, MAX_BRUSH_RADIUS) - Entities.editEntity(this.brush, { - position: newBrushPos, - color: this.currentColor, - dimensions: { - x: brushRadius, - y: brushRadius, - z: brushRadius - } - }); + var newTrailPosOffset = Vec3.multiply(Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)), DRAWING_DEPTH); + var newTrailPos = Vec3.sum(this.palmPosition, newTrailPosOffset); if (this.triggerValue > TRIGGER_THRESHOLD && !this.drawing) { - this.newLine(newBrushPos); + this.setTrailPosition(newTrailPos); this.drawing = true; } else if (this.drawing && this.triggerValue < TRIGGER_THRESHOLD) { this.drawing = false; } - if (this.drawing && this.points.length < MAX_POINTS_PER_LINE) { - var localPoint = Vec3.subtract(newBrushPos, this.linePosition); + if (this.drawing) { + var localPoint = Vec3.subtract(newTrailPos, this.trailPosition); if (Vec3.distance(localPoint, this.points[this.points.length - 1]) < MIN_POINT_DISTANCE) { //Need a minimum distance to avoid binormal NANs return; } + if (this.points.length === MAX_POINTS_PER_LINE) { + this.points.shift(); + this.normals.shift(); + this.strokeWidths.shift(); + } + this.points.push(localPoint); - var normal = computeNormal(newBrushPos, Camera.getPosition()); + var normal = computeNormal(newTrailPos, Camera.getPosition()); this.normals.push(normal); var strokeWidth = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH); this.strokeWidths.push(strokeWidth); - Entities.editEntity(this.line, { + Entities.editEntity(this.trail, { linePoints: this.points, normals: this.normals, strokeWidths: this.strokeWidths, @@ -175,9 +146,9 @@ function controller(side, triggerAction) { this.cycleColorButtonPressed = Controller.getValue(this.cycleColorButton); this.palmPosition = this.side == RIGHT ? MyAvatar.rightHandPose.translation : MyAvatar.leftHandPose.translation; this.tipPosition = this.side == RIGHT ? MyAvatar.rightHandTipPose.translation : MyAvatar.leftHandTipPose.translation; - this.triggerValue = Controller.getActionValue(this.triggerAction); + this.triggerValue = Controller.getActionValue(this.triggerAction); + - if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) { this.cycleColor(); Entities.editEntity(this.brush, { @@ -189,9 +160,7 @@ function controller(side, triggerAction) { } - this.cleanup = function() { - Entities.deleteEntity(self.brush); - } + this.cleanup = function() {} } function computeNormal(p1, p2) { @@ -204,7 +173,7 @@ function update(deltaTime) { } function scriptEnding() { - leftController.cleanup(); + leftController.cleanup(); rightController.cleanup(); } From 191f7f2c228771d55c544d2fb497ae34e2d0527e Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 1 Dec 2015 16:22:11 -0800 Subject: [PATCH 004/195] no audio for now --- examples/flowArts/lightTrails.js | 22 ++++++++-------- .../src/RenderablePolyLineEntityItem.cpp | 25 +++---------------- .../entities-renderer/src/paintStroke.slf | 7 ++---- 3 files changed, 16 insertions(+), 38 deletions(-) diff --git a/examples/flowArts/lightTrails.js b/examples/flowArts/lightTrails.js index c01fc1c4d3..8251803a5f 100644 --- a/examples/flowArts/lightTrails.js +++ b/examples/flowArts/lightTrails.js @@ -19,19 +19,17 @@ var LASER_COLOR = { green: 150, blue: 200 }; -var TRIGGER_THRESHOLD = .1; -var MAX_POINTS_PER_LINE = 40; +var MAX_POINTS_PER_LINE = 50; var LIFETIME = 6000; -var DRAWING_DEPTH = 1; +var DRAWING_DEPTH = 0.3; var LINE_DIMENSIONS = 20; -var MIN_POINT_DISTANCE = 0.01; +var MIN_POINT_DISTANCE = 0.03; + -var MIN_BRUSH_RADIUS = 0.08; -var MAX_BRUSH_RADIUS = 0.1; var colorPalette = [{ @@ -75,7 +73,7 @@ function controller(side, triggerAction) { y: LINE_DIMENSIONS, z: LINE_DIMENSIONS }, - textures: "http://localhost:8080/trails.png", + textures: "http://localhost:8080/trails.png?v1" + Math.random(), lifetime: LIFETIME }); this.points = []; @@ -105,11 +103,9 @@ function controller(side, triggerAction) { var newTrailPos = Vec3.sum(this.palmPosition, newTrailPosOffset); - if (this.triggerValue > TRIGGER_THRESHOLD && !this.drawing) { + if (!this.drawing) { this.setTrailPosition(newTrailPos); this.drawing = true; - } else if (this.drawing && this.triggerValue < TRIGGER_THRESHOLD) { - this.drawing = false; } if (this.drawing) { @@ -129,7 +125,7 @@ function controller(side, triggerAction) { var normal = computeNormal(newTrailPos, Camera.getPosition()); this.normals.push(normal); - var strokeWidth = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH); + var strokeWidth = MAX_STROKE_WIDTH; this.strokeWidths.push(strokeWidth); Entities.editEntity(this.trail, { linePoints: this.points, @@ -160,7 +156,9 @@ function controller(side, triggerAction) { } - this.cleanup = function() {} + this.cleanup = function() { + Entities.deleteEntity(this.trail); + } } function computeNormal(p1, p2) { diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 63a03bb8e7..bfb27a93b9 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -80,30 +80,12 @@ void RenderablePolyLineEntityItem::updateGeometry() { _verticesBuffer.reset(new gpu::Buffer()); int vertexIndex = 0; vec2 uv; - float tailStart = 0.0f; - float tailEnd = 0.25f; - float tailLength = tailEnd - tailStart; - - float headStart = 0.76f; - float headEnd = 1.0f; - float headLength = headEnd - headStart; float uCoord, vCoord; - - int numTailStrips = 5; - int numHeadStrips = 10; - int startHeadIndex = _vertices.size() / 2 - numHeadStrips; + uCoord = 0.0f; + float uCoordInc = 1.0 / (_vertices.size() / 2); for (int i = 0; i < _vertices.size() / 2; i++) { - uCoord = 0.26f; vCoord = 0.0f; - //tail - if (i < numTailStrips) { - uCoord = float(i) / numTailStrips * tailLength + tailStart; - } - - //head - if (i > startHeadIndex) { - uCoord = float((i + 1) - startHeadIndex) / numHeadStrips * headLength + headStart; - } + uv = vec2(uCoord, vCoord); @@ -121,6 +103,7 @@ void RenderablePolyLineEntityItem::updateGeometry() { vertexIndex++; _numVertices += 2; + uCoord += uCoordInc; } _pointsChanged = false; _normalsChanged = false; diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 48de1274f4..6c51b4c979 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -38,14 +38,11 @@ void main(void) { vec4 texel = texture(originalTexture, varTexcoord); int frontCondition = 1 -int(gl_FrontFacing) * 2; - vec3 color = varColor.rgb; - color.g = 1.0 + sin(polyline.time) * 0.5; - //texel.a = varVertexId / 20.0; - //vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess + vec3 color = varColor.rgb; packDeferredFragmentTranslucent( interpolatedNormal * frontCondition, texel.a, - color * texel.rgb, + texel.rgb, vec3(0.01, 0.01, 0.01), 10.0); } From 8aeb5598488905b7b47bca4db686874ec1ad51fa Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 2 Dec 2015 15:58:30 -0800 Subject: [PATCH 005/195] flowy --- examples/flowArts/lightTrails.js | 45 +++++-- examples/lightTrails.js | 224 ------------------------------- 2 files changed, 36 insertions(+), 233 deletions(-) delete mode 100644 examples/lightTrails.js diff --git a/examples/flowArts/lightTrails.js b/examples/flowArts/lightTrails.js index 8251803a5f..8d88957f03 100644 --- a/examples/flowArts/lightTrails.js +++ b/examples/flowArts/lightTrails.js @@ -11,6 +11,10 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + +var eraseTrail = true; +var ugLSD = 25; +// var eraseTrail = false; var LEFT = 0; var RIGHT = 1; var LASER_WIDTH = 3; @@ -23,13 +27,11 @@ var LASER_COLOR = { var MAX_POINTS_PER_LINE = 50; var LIFETIME = 6000; -var DRAWING_DEPTH = 0.3; +var DRAWING_DEPTH = 0.2; var LINE_DIMENSIONS = 20; -var MIN_POINT_DISTANCE = 0.03; - - +var MIN_POINT_DISTANCE = 0.02; var colorPalette = [{ @@ -54,8 +56,7 @@ var colorPalette = [{ blue: 122 }]; -var MIN_STROKE_WIDTH = 0.002; -var MAX_STROKE_WIDTH = 0.05; +var STROKE_WIDTH = 0.05; function controller(side, triggerAction) { this.triggerHeld = false; @@ -65,6 +66,16 @@ function controller(side, triggerAction) { this.cycleColorButton = side == LEFT ? Controller.Standard.LeftPrimaryThumb : Controller.Standard.RightPrimaryThumb; this.currentColorIndex = 0; this.currentColor = colorPalette[this.currentColorIndex]; + var textures = "http://localhost:8080/trails.png?v2" + Math.random(); + + // this.light = Entities.addEntity({ + // type: 'Light', + // position: MyAvatar.position, + // dimensions: {x: 20, y: 20, z: 20}, + // color: {red: 60, green: 10, blue: 100}, + // intensity: 10 + // }); + this.trail = Entities.addEntity({ type: "PolyLine", color: this.currentColor, @@ -73,7 +84,7 @@ function controller(side, triggerAction) { y: LINE_DIMENSIONS, z: LINE_DIMENSIONS }, - textures: "http://localhost:8080/trails.png?v1" + Math.random(), + textures: textures, lifetime: LIFETIME }); this.points = []; @@ -81,6 +92,18 @@ function controller(side, triggerAction) { this.strokeWidths = []; var self = this; + this.trailEraseInterval = Script.setInterval(function() { + if (self.points.length > 0 && eraseTrail) { + self.points.shift(); + self.normals.shift(); + self.strokeWidths.shift(); + Entities.editEntity(self.trail, { + linePoints: self.points, + strokeWidths: self.strokeWidths, + normals: self.normals + }); + } + }, ugLSD); this.cycleColor = function() { this.currentColor = colorPalette[++this.currentColorIndex]; @@ -101,6 +124,9 @@ function controller(side, triggerAction) { this.updateControllerState(); var newTrailPosOffset = Vec3.multiply(Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)), DRAWING_DEPTH); var newTrailPos = Vec3.sum(this.palmPosition, newTrailPosOffset); + // Entities.editEntity(this.light, { + // position: newTrailPos + // }); if (!this.drawing) { @@ -125,8 +151,7 @@ function controller(side, triggerAction) { var normal = computeNormal(newTrailPos, Camera.getPosition()); this.normals.push(normal); - var strokeWidth = MAX_STROKE_WIDTH; - this.strokeWidths.push(strokeWidth); + this.strokeWidths.push(STROKE_WIDTH); Entities.editEntity(this.trail, { linePoints: this.points, normals: this.normals, @@ -158,6 +183,8 @@ function controller(side, triggerAction) { this.cleanup = function() { Entities.deleteEntity(this.trail); + // Entities.deleteEntity(this.light); + Script.clearInterval(this.trailEraseInterval); } } diff --git a/examples/lightTrails.js b/examples/lightTrails.js deleted file mode 100644 index fc8d7082e4..0000000000 --- a/examples/lightTrails.js +++ /dev/null @@ -1,224 +0,0 @@ -// -// hydraPaint.js -// examples -// -// Created by Eric Levin on 5/14/15. -// Copyright 2014 High Fidelity, Inc. -// -// This script allows you to paint with the hydra! -// -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -var LEFT = 0; -var RIGHT = 1; -var LASER_WIDTH = 3; -var LASER_COLOR = { - red: 50, - green: 150, - blue: 200 -}; -var TRIGGER_THRESHOLD = .1; - -var MAX_POINTS_PER_LINE = 40; - -var LIFETIME = 6000; -var DRAWING_DEPTH = 1; -var LINE_DIMENSIONS = 20; - - -var MIN_POINT_DISTANCE = 0.01; - -var MIN_BRUSH_RADIUS = 0.08; -var MAX_BRUSH_RADIUS = 0.1; - -var RIGHT_BUTTON_1 = 7 -var RIGHT_BUTTON_2 = 8 -var RIGHT_BUTTON_3 = 9; -var RIGHT_BUTTON_4 = 10 -var LEFT_BUTTON_1 = 1; -var LEFT_BUTTON_2 = 2; -var LEFT_BUTTON_3 = 3; -var LEFT_BUTTON_4 = 4; - -var colorPalette = [{ - red: 250, - green: 0, - blue: 0 -}, { - red: 214, - green: 91, - blue: 67 -}, { - red: 192, - green: 41, - blue: 66 -}, { - red: 84, - green: 36, - blue: 55 -}, { - red: 83, - green: 119, - blue: 122 -}]; - -var MIN_STROKE_WIDTH = 0.002; -var MAX_STROKE_WIDTH = 0.05; - -function controller(side, triggerAction) { - this.triggerHeld = false; - this.triggerThreshold = 0.9; - this.side = side; - this.triggerAction = triggerAction; - this.cycleColorButton = side == LEFT ? Controller.Standard.LeftPrimaryThumb : Controller.Standard.RightPrimaryThumb; - - this.points = []; - this.normals = []; - this.strokeWidths = []; - - this.currentColorIndex = 0; - this.currentColor = colorPalette[this.currentColorIndex]; - - var self = this; - - - this.brush = Entities.addEntity({ - type: 'Sphere', - position: { - x: 0, - y: 0, - z: 0 - }, - color: this.currentColor, - dimensions: { - x: MIN_BRUSH_RADIUS, - y: MIN_BRUSH_RADIUS, - z: MIN_BRUSH_RADIUS - } - }); - - this.cycleColor = function() { - this.currentColor = colorPalette[++this.currentColorIndex]; - if (this.currentColorIndex === colorPalette.length - 1) { - this.currentColorIndex = -1; - } - } - this.newLine = function(position) { - this.linePosition = position; - this.line = Entities.addEntity({ - position: position, - type: "PolyLine", - color: this.currentColor, - dimensions: { - x: LINE_DIMENSIONS, - y: LINE_DIMENSIONS, - z: LINE_DIMENSIONS - }, - textures: "http://localhost:8080/trails.png", - lifetime: LIFETIME - }); - this.points = []; - this.normals = [] - this.strokeWidths = []; - } - - this.update = function(deltaTime) { - this.updateControllerState(); - var newBrushPosOffset = Vec3.multiply(Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)), DRAWING_DEPTH); - var newBrushPos = Vec3.sum(this.palmPosition, newBrushPosOffset); - var brushRadius = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_BRUSH_RADIUS, MAX_BRUSH_RADIUS) - Entities.editEntity(this.brush, { - position: newBrushPos, - color: this.currentColor, - dimensions: { - x: brushRadius, - y: brushRadius, - z: brushRadius - } - }); - - - if (this.triggerValue > TRIGGER_THRESHOLD && !this.drawing) { - this.newLine(newBrushPos); - this.drawing = true; - } else if (this.drawing && this.triggerValue < TRIGGER_THRESHOLD) { - this.drawing = false; - } - - if (this.drawing && this.points.length < MAX_POINTS_PER_LINE) { - var localPoint = Vec3.subtract(newBrushPos, this.linePosition); - if (Vec3.distance(localPoint, this.points[this.points.length - 1]) < MIN_POINT_DISTANCE) { - //Need a minimum distance to avoid binormal NANs - return; - } - - this.points.push(localPoint); - var normal = computeNormal(newBrushPos, Camera.getPosition()); - - this.normals.push(normal); - var strokeWidth = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH); - this.strokeWidths.push(strokeWidth); - Entities.editEntity(this.line, { - linePoints: this.points, - normals: this.normals, - strokeWidths: this.strokeWidths, - color: this.currentColor - }); - } - - // Once we get to max points - } - - - this.updateControllerState = function() { - this.cycleColorButtonPressed = Controller.getValue(this.cycleColorButton); - this.palmPosition = this.side == RIGHT ? MyAvatar.rightHandPose.translation : MyAvatar.leftHandPose.translation; - this.tipPosition = this.side == RIGHT ? MyAvatar.rightHandTipPose.translation : MyAvatar.leftHandTipPose.translation; - this.triggerValue = Controller.getActionValue(this.triggerAction); - - - if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) { - this.cycleColor(); - Entities.editEntity(this.brush, { - // color: this.currentColor - }); - } - - this.prevCycleColorButtonPressed = this.cycleColorButtonPressed; - - } - - this.cleanup = function() { - Entities.deleteEntity(self.brush); - } -} - -function computeNormal(p1, p2) { - return Vec3.normalize(Vec3.subtract(p2, p1)); -} - -function update(deltaTime) { - leftController.update(deltaTime); - rightController.update(deltaTime); -} - -function scriptEnding() { - leftController.cleanup(); - rightController.cleanup(); -} - -function vectorIsZero(v) { - return v.x === 0 && v.y === 0 && v.z === 0; -} - - -var rightController = new controller(RIGHT, Controller.findAction("RIGHT_HAND_CLICK")); -var leftController = new controller(LEFT, Controller.findAction("LEFT_HAND_CLICK")); -Script.update.connect(update); -Script.scriptEnding.connect(scriptEnding); - -function map(value, min1, max1, min2, max2) { - return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); -} \ No newline at end of file From d2d0326c02268b4cf8cd496de12d5e23888910b9 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 2 Dec 2015 16:44:47 -0800 Subject: [PATCH 006/195] using deployed texture --- examples/flowArts/lightTrails.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/flowArts/lightTrails.js b/examples/flowArts/lightTrails.js index 8d88957f03..a494f9a810 100644 --- a/examples/flowArts/lightTrails.js +++ b/examples/flowArts/lightTrails.js @@ -66,7 +66,7 @@ function controller(side, triggerAction) { this.cycleColorButton = side == LEFT ? Controller.Standard.LeftPrimaryThumb : Controller.Standard.RightPrimaryThumb; this.currentColorIndex = 0; this.currentColor = colorPalette[this.currentColorIndex]; - var textures = "http://localhost:8080/trails.png?v2" + Math.random(); + var texture = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/trails.png"; // this.light = Entities.addEntity({ // type: 'Light', @@ -84,7 +84,7 @@ function controller(side, triggerAction) { y: LINE_DIMENSIONS, z: LINE_DIMENSIONS }, - textures: textures, + textures: texture, lifetime: LIFETIME }); this.points = []; From 762a241fa6b66540d2c196f64d6331cf471888ba Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 2 Dec 2015 18:03:58 -0800 Subject: [PATCH 007/195] Adding specific path for loading lightmaps --- .../src/model-networking/ModelCache.cpp | 3 +- .../src/model-networking/TextureCache.h | 2 +- libraries/model/src/model/TextureMap.cpp | 88 ++++++++++++++++++- libraries/model/src/model/TextureMap.h | 2 + 4 files changed, 91 insertions(+), 4 deletions(-) diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index c7d3523496..ddb6449dc7 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -308,10 +308,9 @@ static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const material._material->setTextureMap(model::MaterialKey::GLOSS_MAP, glossMap); } if (!material.emissiveTexture.filename.isEmpty()) { - networkMaterial->emissiveTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.emissiveTexture.filename)), EMISSIVE_TEXTURE, material.emissiveTexture.content); + networkMaterial->emissiveTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.emissiveTexture.filename)), LIGHTMAP_TEXTURE, material.emissiveTexture.content); networkMaterial->emissiveTextureName = material.emissiveTexture.name; - //checkForTexcoordLightmap = true; auto lightmapMap = model::TextureMapPointer(new model::TextureMap()); lightmapMap->setTextureSource(networkMaterial->emissiveTexture->_textureSource); diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index cc22509631..4171b6c1cb 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -29,7 +29,7 @@ class NetworkTexture; typedef QSharedPointer NetworkTexturePointer; -enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, BUMP_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, CUBE_TEXTURE, CUSTOM_TEXTURE }; +enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, BUMP_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, CUBE_TEXTURE, LIGHTMAP_TEXTURE, CUSTOM_TEXTURE }; /// Stores cached textures, including render-to-texture targets. class TextureCache : public ResourceCache, public Dependency { diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index d443522a6f..453bb17a4b 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -119,7 +119,7 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con if ((image.width() > 0) && (image.height() > 0)) { // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); + bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); @@ -520,3 +520,89 @@ gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, c return theTexture; } + + +gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + QImage image = srcImage; + + int imageArea = image.width() * image.height(); + + int opaquePixels = 0; + int translucentPixels = 0; + //bool isTransparent = false; + int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0; + const int EIGHT_BIT_MAXIMUM = 255; + QColor averageColor(EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM); + + if (!image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGB888) { + image = image.convertToFormat(QImage::Format_RGB888); + } + // int redTotal = 0, greenTotal = 0, blueTotal = 0; + for (int y = 0; y < image.height(); y++) { + for (int x = 0; x < image.width(); x++) { + QRgb rgb = image.pixel(x, y); + redTotal += qRed(rgb); + greenTotal += qGreen(rgb); + blueTotal += qBlue(rgb); + } + } + if (imageArea > 0) { + averageColor.setRgb(redTotal / imageArea, greenTotal / imageArea, blueTotal / imageArea); + } + } else { + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + + // check for translucency/false transparency + // int opaquePixels = 0; + // int translucentPixels = 0; + // int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0; + for (int y = 0; y < image.height(); y++) { + for (int x = 0; x < image.width(); x++) { + QRgb rgb = image.pixel(x, y); + redTotal += qRed(rgb); + greenTotal += qGreen(rgb); + blueTotal += qBlue(rgb); + int alpha = qAlpha(rgb); + alphaTotal += alpha; + if (alpha == EIGHT_BIT_MAXIMUM) { + opaquePixels++; + } else if (alpha != 0) { + translucentPixels++; + } + } + } + if (opaquePixels == imageArea) { + qCDebug(modelLog) << "Image with alpha channel is completely opaque:" << QString(srcImageName.c_str()); + image = image.convertToFormat(QImage::Format_RGB888); + } + + averageColor = QColor(redTotal / imageArea, + greenTotal / imageArea, blueTotal / imageArea, alphaTotal / imageArea); + + //isTransparent = (translucentPixels >= imageArea / 2); + } + + gpu::Texture* theTexture = nullptr; + if ((image.width() > 0) && (image.height() > 0)) { + + // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); + bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); + + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + if (image.hasAlphaChannel()) { + formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); + } + + + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); + theTexture->autoGenerateMips(-1); + } + + return theTexture; +} diff --git a/libraries/model/src/model/TextureMap.h b/libraries/model/src/model/TextureMap.h index 107ca2e879..6bc5b8228c 100755 --- a/libraries/model/src/model/TextureMap.h +++ b/libraries/model/src/model/TextureMap.h @@ -35,6 +35,8 @@ public: static gpu::Texture* createNormalTextureFromNormalImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName); + static gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); + }; From 2336dd96dd934f5efc1832db5815bf2dc87f3c21 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 2 Dec 2015 18:10:45 -0800 Subject: [PATCH 008/195] lights --- examples/flowArts/lightTrails.js | 108 ++++++++++++++----------------- 1 file changed, 50 insertions(+), 58 deletions(-) diff --git a/examples/flowArts/lightTrails.js b/examples/flowArts/lightTrails.js index a494f9a810..4a7f9de277 100644 --- a/examples/flowArts/lightTrails.js +++ b/examples/flowArts/lightTrails.js @@ -12,73 +12,82 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +Script.include("../libraries/utils.js"); + var eraseTrail = true; var ugLSD = 25; // var eraseTrail = false; var LEFT = 0; var RIGHT = 1; -var LASER_WIDTH = 3; -var LASER_COLOR = { - red: 50, - green: 150, - blue: 200 -}; - var MAX_POINTS_PER_LINE = 50; var LIFETIME = 6000; -var DRAWING_DEPTH = 0.2; +var DRAWING_DEPTH = 0.6; var LINE_DIMENSIONS = 20; +var lightZone = Entities.addEntity({ + type: "Zone", + shapeType: 'box', + keyLightIntensity: 0.02, + keyLightColor: { + red: 5, + green: 0, + blue: 5 + }, + keyLightAmbientIntensity: .05, + position: MyAvatar.position, + dimensions: { + x: 100, + y: 100, + z: 100 + } +}); + var MIN_POINT_DISTANCE = 0.02; var colorPalette = [{ red: 250, - green: 0, - blue: 0 + green: 137, + blue: 162 }, { - red: 214, - green: 91, - blue: 67 + red: 204, + green: 244, + blue: 249 }, { - red: 192, - green: 41, - blue: 66 + red: 146, + green: 206, + blue: 116 }, { - red: 84, - green: 36, - blue: 55 -}, { - red: 83, - green: 119, - blue: 122 + red: 240, + green: 87, + blue: 129 }]; -var STROKE_WIDTH = 0.05; +var STROKE_WIDTH = 0.03; function controller(side, triggerAction) { this.triggerHeld = false; this.triggerThreshold = 0.9; this.side = side; this.triggerAction = triggerAction; - this.cycleColorButton = side == LEFT ? Controller.Standard.LeftPrimaryThumb : Controller.Standard.RightPrimaryThumb; - this.currentColorIndex = 0; - this.currentColor = colorPalette[this.currentColorIndex]; var texture = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/trails.png"; - // this.light = Entities.addEntity({ - // type: 'Light', - // position: MyAvatar.position, - // dimensions: {x: 20, y: 20, z: 20}, - // color: {red: 60, green: 10, blue: 100}, - // intensity: 10 - // }); + this.light = Entities.addEntity({ + type: 'Light', + position: MyAvatar.position, + dimensions: { + x: 20, + y: 20, + z: 20 + }, + color: colorPalette[randInt(0, colorPalette.length)], + intensity: 20 + }); this.trail = Entities.addEntity({ type: "PolyLine", - color: this.currentColor, dimensions: { x: LINE_DIMENSIONS, y: LINE_DIMENSIONS, @@ -105,12 +114,6 @@ function controller(side, triggerAction) { } }, ugLSD); - this.cycleColor = function() { - this.currentColor = colorPalette[++this.currentColorIndex]; - if (this.currentColorIndex === colorPalette.length - 1) { - this.currentColorIndex = -1; - } - } this.setTrailPosition = function(position) { this.trailPosition = position; @@ -124,9 +127,9 @@ function controller(side, triggerAction) { this.updateControllerState(); var newTrailPosOffset = Vec3.multiply(Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)), DRAWING_DEPTH); var newTrailPos = Vec3.sum(this.palmPosition, newTrailPosOffset); - // Entities.editEntity(this.light, { - // position: newTrailPos - // }); + Entities.editEntity(this.light, { + position: newTrailPos + }); if (!this.drawing) { @@ -151,12 +154,11 @@ function controller(side, triggerAction) { var normal = computeNormal(newTrailPos, Camera.getPosition()); this.normals.push(normal); - this.strokeWidths.push(STROKE_WIDTH); + this.strokeWidths.push(STROKE_WIDTH + Math.random() * 0.01); Entities.editEntity(this.trail, { linePoints: this.points, normals: this.normals, strokeWidths: this.strokeWidths, - color: this.currentColor }); } @@ -164,26 +166,15 @@ function controller(side, triggerAction) { this.updateControllerState = function() { - this.cycleColorButtonPressed = Controller.getValue(this.cycleColorButton); this.palmPosition = this.side == RIGHT ? MyAvatar.rightHandPose.translation : MyAvatar.leftHandPose.translation; this.tipPosition = this.side == RIGHT ? MyAvatar.rightHandTipPose.translation : MyAvatar.leftHandTipPose.translation; this.triggerValue = Controller.getActionValue(this.triggerAction); - - if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) { - this.cycleColor(); - Entities.editEntity(this.brush, { - // color: this.currentColor - }); - } - - this.prevCycleColorButtonPressed = this.cycleColorButtonPressed; - } this.cleanup = function() { Entities.deleteEntity(this.trail); - // Entities.deleteEntity(this.light); + Entities.deleteEntity(this.light); Script.clearInterval(this.trailEraseInterval); } } @@ -200,6 +191,7 @@ function update(deltaTime) { function scriptEnding() { leftController.cleanup(); rightController.cleanup(); + Entities.deleteEntity(lightZone); } function vectorIsZero(v) { From a5475ed14d2089e7e63d5fb294b71da87b6f2658 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 Dec 2015 10:41:32 -0800 Subject: [PATCH 009/195] Early try fixing the lighting --- .../render-utils/src/DeferredLighting.slh | 2 +- .../src/DeferredLightingEffect.cpp | 34 ++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/DeferredLighting.slh b/libraries/render-utils/src/DeferredLighting.slh index 888742bb18..53ffdee0ca 100755 --- a/libraries/render-utils/src/DeferredLighting.slh +++ b/libraries/render-utils/src/DeferredLighting.slh @@ -33,7 +33,7 @@ vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 sp vec3 schlick = specular * (1.0 - shlickPower5) + vec3(shlickPower5); vec3 reflect = specularPower * schlick; - return vec4(reflect, diffuse); + return vec4(reflect, diffuse * (1 - length(schlick))); } <@endfunc@> diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 57e3129ef8..4370f8279e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -143,7 +143,39 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { { //auto VSFS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); //auto PSBlit = gpu::StandardShaderLib::getDrawTexturePS(); - auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); + const char BlitTextureGamma_frag[] = R"SCRIBE(#version 410 core + // Generated on Sat Oct 24 09:34:37 2015 + // + // Draw texture 0 fetched at texcoord.xy + // + // Created by Sam Gateau on 6/22/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 + // + + + uniform sampler2D colorMap; + + in vec2 varTexCoord0; + out vec4 outFragColor; + + void main(void) { + outFragColor = texture(colorMap, varTexCoord0); + if (gl_FragCoord.x > 1000) { + outFragColor.xyz = pow( outFragColor.xyz , vec3(1.0/2.2) ); + } + } + + )SCRIBE"; + auto blitPS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(BlitTextureGamma_frag))); + + //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); + auto blitVS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + auto blitProgram = gpu::ShaderPointer(gpu::Shader::createProgram(blitVS, blitPS)); + + //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); gpu::Shader::makeProgram(*blitProgram); auto blitState = std::make_shared(); blitState->setBlendFunction(true, From 5f881e765093d62d9ecc0031b3883ff31acb5505 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 3 Dec 2015 13:46:29 -0800 Subject: [PATCH 010/195] polylines now take color as a uniform --- examples/flowArts/lightTrails.js | 7 ++++--- examples/painting/closePaint.js | 5 ++++- .../painting/whiteboard/whiteboardEntityScript.js | 3 +++ .../src/RenderablePolyLineEntityItem.cpp | 13 +++---------- .../src/RenderablePolyLineEntityItem.h | 1 - libraries/entities-renderer/src/paintStroke.slf | 6 ++---- libraries/entities-renderer/src/paintStroke.slv | 3 --- libraries/entities/src/PolyLineEntityItem.h | 2 +- 8 files changed, 17 insertions(+), 23 deletions(-) diff --git a/examples/flowArts/lightTrails.js b/examples/flowArts/lightTrails.js index 4a7f9de277..e063897eb8 100644 --- a/examples/flowArts/lightTrails.js +++ b/examples/flowArts/lightTrails.js @@ -22,7 +22,7 @@ var RIGHT = 1; var MAX_POINTS_PER_LINE = 50; var LIFETIME = 6000; -var DRAWING_DEPTH = 0.6; +var DRAWING_DEPTH = 0.8; var LINE_DIMENSIONS = 20; var lightZone = Entities.addEntity({ @@ -65,7 +65,7 @@ var colorPalette = [{ blue: 129 }]; -var STROKE_WIDTH = 0.03; +var STROKE_WIDTH = 0.04; function controller(side, triggerAction) { this.triggerHeld = false; @@ -83,7 +83,7 @@ function controller(side, triggerAction) { z: 20 }, color: colorPalette[randInt(0, colorPalette.length)], - intensity: 20 + intensity: 5 }); this.trail = Entities.addEntity({ @@ -93,6 +93,7 @@ function controller(side, triggerAction) { y: LINE_DIMENSIONS, z: LINE_DIMENSIONS }, + color: {red: 255, green: 255, blue: 255}, textures: texture, lifetime: LIFETIME }); diff --git a/examples/painting/closePaint.js b/examples/painting/closePaint.js index 60b4ac2e25..bea4d9c9aa 100644 --- a/examples/painting/closePaint.js +++ b/examples/painting/closePaint.js @@ -43,6 +43,8 @@ var MAX_STROKE_WIDTH = 0.04; var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(Camera.getOrientation()))); +var textureURL = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/paintStroke.png"; + function MyController(hand, triggerAction) { @@ -148,7 +150,8 @@ function MyController(hand, triggerAction) { y: 50, z: 50 }, - lifetime: 200 + lifetime: 200, + textures: textureURL }); this.strokePoints = []; this.strokeNormals = []; diff --git a/examples/painting/whiteboard/whiteboardEntityScript.js b/examples/painting/whiteboard/whiteboardEntityScript.js index 61d7291e11..374ec8b873 100644 --- a/examples/painting/whiteboard/whiteboardEntityScript.js +++ b/examples/painting/whiteboard/whiteboardEntityScript.js @@ -29,6 +29,8 @@ var MIN_STROKE_WIDTH = 0.0005; var MAX_STROKE_WIDTH = 0.03; + var textureURL = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/paintStroke.png"; + var TRIGGER_CONTROLS = [ Controller.Standard.LT, Controller.Standard.RT, @@ -168,6 +170,7 @@ type: "PolyLine", name: "paintStroke", color: this.strokeColor, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/paintStroke.png", dimensions: { x: 50, y: 50, diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index bfb27a93b9..d38da0d3f7 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -25,7 +25,7 @@ struct PolyLineUniforms { - float time; + glm::vec3 color; }; EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -34,7 +34,6 @@ EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& enti RenderablePolyLineEntityItem::RenderablePolyLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : PolyLineEntityItem(entityItemID, properties), -_counter(0.0f), _numVertices(0) { _vertices = QVector(0.0f); @@ -49,13 +48,11 @@ int32_t RenderablePolyLineEntityItem::PAINTSTROKE_GPU_SLOT; void RenderablePolyLineEntityItem::createPipeline() { static const int NORMAL_OFFSET = 12; - static const int COLOR_OFFSET = 24; - static const int TEXTURE_OFFSET = 28; + static const int TEXTURE_OFFSET = 24; _format.reset(new gpu::Stream::Format()); _format->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); _format->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), NORMAL_OFFSET); - _format->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, COLOR_OFFSET); _format->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), TEXTURE_OFFSET); auto VS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(paintStroke_vert))); @@ -91,14 +88,12 @@ void RenderablePolyLineEntityItem::updateGeometry() { _verticesBuffer->append(sizeof(glm::vec3), (const gpu::Byte*)&_vertices.at(vertexIndex)); _verticesBuffer->append(sizeof(glm::vec3), (const gpu::Byte*)&_normals.at(i)); - _verticesBuffer->append(sizeof(int), (gpu::Byte*)&_color); _verticesBuffer->append(sizeof(glm::vec2), (gpu::Byte*)&uv); vertexIndex++; uv.y = 1.0f; _verticesBuffer->append(sizeof(glm::vec3), (const gpu::Byte*)&_vertices.at(vertexIndex)); _verticesBuffer->append(sizeof(glm::vec3), (const gpu::Byte*)&_normals.at(i)); - _verticesBuffer->append(sizeof(int), (gpu::Byte*)_color); _verticesBuffer->append(sizeof(glm::vec2), (const gpu::Byte*)&uv); vertexIndex++; @@ -154,10 +149,8 @@ void RenderablePolyLineEntityItem::updateVertices() { void RenderablePolyLineEntityItem::update(const quint64& now) { PolyLineUniforms uniforms; - _counter += 0.01; - uniforms.time = _counter; + uniforms.color = toGlm(getXColor()); memcpy(&_uniformBuffer.edit(), &uniforms, sizeof(PolyLineUniforms)); - if (_pointsChanged || _strokeWidthsChanged || _normalsChanged) { updateVertices(); updateGeometry(); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index 658614e72e..411b856d91 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -47,7 +47,6 @@ protected: gpu::BufferView _uniformBuffer; unsigned int _numVertices; QVector _vertices; - float _counter; }; diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 6c51b4c979..1a87f84bfd 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -21,12 +21,11 @@ uniform sampler2D originalTexture; // the interpolated normal in vec3 interpolatedNormal; in vec2 varTexcoord; -in vec4 varColor; flat in int varVertexId; struct PolyLineUniforms { - float time; + vec3 color; }; uniform polyLineBuffer { @@ -38,11 +37,10 @@ void main(void) { vec4 texel = texture(originalTexture, varTexcoord); int frontCondition = 1 -int(gl_FrontFacing) * 2; - vec3 color = varColor.rgb; packDeferredFragmentTranslucent( interpolatedNormal * frontCondition, texel.a, - texel.rgb, + polyline.color * texel.rgb, vec3(0.01, 0.01, 0.01), 10.0); } diff --git a/libraries/entities-renderer/src/paintStroke.slv b/libraries/entities-renderer/src/paintStroke.slv index 25f046456a..5c368f9c0f 100644 --- a/libraries/entities-renderer/src/paintStroke.slv +++ b/libraries/entities-renderer/src/paintStroke.slv @@ -23,15 +23,12 @@ out vec3 interpolatedNormal; //the diffuse texture out vec2 varTexcoord; -out vec4 varColor; flat out int varVertexId; void main(void) { varTexcoord = inTexCoord0.st; - // pass along the diffuse color - varColor = inColor; varVertexId = gl_VertexID; // standard transform diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 1610bf87b5..20549d1bbd 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -49,7 +49,7 @@ class PolyLineEntityItem : public EntityItem { memcpy(_color, value, sizeof(_color)); } void setColor(const xColor& value) { - + _color[RED_INDEX] = value.red; _color[GREEN_INDEX] = value.green; _color[BLUE_INDEX] = value.blue; From 72d393905b36cbf65c7686ee67210c3beaaa1fab Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 Dec 2015 16:03:32 -0800 Subject: [PATCH 011/195] Introducing the Lighting Buffer where all the lighting is beeing accumulated, apply a manual gamma correction when copying back into the main color buffer --- .../src/DeferredLightingEffect.cpp | 26 +++++++------------ .../render-utils/src/FramebufferCache.cpp | 22 ++++++++++++++++ libraries/render-utils/src/FramebufferCache.h | 9 ++++++- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 4370f8279e..371a3d705e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -163,9 +163,10 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { void main(void) { outFragColor = texture(colorMap, varTexCoord0); - if (gl_FragCoord.x > 1000) { - outFragColor.xyz = pow( outFragColor.xyz , vec3(1.0/2.2) ); - } + // if (gl_FragCoord.x > 1000) { + // Manually gamma correct from Ligthing BUffer to color buffer + outFragColor.xyz = pow( outFragColor.xyz , vec3(1.0 / 2.2) ); + // } } )SCRIBE"; @@ -178,9 +179,6 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); gpu::Shader::makeProgram(*blitProgram); auto blitState = std::make_shared(); - blitState->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); blitState->setColorWriteMask(true, true, true, false); _blitLightBuffer = gpu::PipelinePointer(gpu::Pipeline::create(blitProgram, blitState)); } @@ -386,8 +384,6 @@ void DeferredLightingEffect::prepare(RenderArgs* args) { }); } -gpu::FramebufferPointer _copyFBO; - void DeferredLightingEffect::render(RenderArgs* args) { gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { @@ -407,13 +403,13 @@ void DeferredLightingEffect::render(RenderArgs* args) { QSize framebufferSize = framebufferCache->getFrameBufferSize(); // binding the first framebuffer - _copyFBO = framebufferCache->getFramebuffer(); - batch.setFramebuffer(_copyFBO); + auto lightingFBO = framebufferCache->getLightingFramebuffer(); + batch.setFramebuffer(lightingFBO); // Clearing it batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - batch.clearColorFramebuffer(_copyFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); + batch.clearColorFramebuffer(lightingFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); // BInd the G-Buffer surfaces batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture()); @@ -718,11 +714,8 @@ void DeferredLightingEffect::copyBack(RenderArgs* args) { batch.enableStereo(false); QSize framebufferSize = framebufferCache->getFrameBufferSize(); - // TODO why doesn't this blit work? It only seems to affect a small area below the rear view mirror. - // auto destFbo = framebufferCache->getPrimaryFramebuffer(); + auto lightingBuffer = framebufferCache->getLightingTexture(); auto destFbo = framebufferCache->getPrimaryFramebufferDepthColor(); - // gpu::Vec4i vp = args->_viewport; - // batch.blit(_copyFBO, vp, framebufferCache->getPrimaryFramebuffer(), vp); batch.setFramebuffer(destFbo); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); @@ -739,12 +732,11 @@ void DeferredLightingEffect::copyBack(RenderArgs* args) { batch.setModelTransform(model); } - batch.setResourceTexture(0, _copyFBO->getRenderBuffer(0)); + batch.setResourceTexture(0, lightingBuffer); batch.draw(gpu::TRIANGLE_STRIP, 4); args->_context->render(batch); }); - framebufferCache->releaseFramebuffer(_copyFBO); } void DeferredLightingEffect::setupTransparent(RenderArgs* args, int lightBufferUnit) { diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index 5907d3fa27..2a8033be0d 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -41,6 +41,8 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) { _primarySpecularTexture.reset(); _selfieFramebuffer.reset(); _cachedFramebuffers.clear(); + _lightingTexture.reset(); + _lightingFramebuffer.reset(); } } @@ -74,6 +76,12 @@ void FramebufferCache::createPrimaryFramebuffer() { _selfieFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); auto tex = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width * 0.5, height * 0.5, defaultSampler)); _selfieFramebuffer->setRenderBuffer(0, tex); + + _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), width, height, defaultSampler)); + //_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::SRGBA), width, height, defaultSampler)); + // _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler)); + _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + _lightingFramebuffer->setRenderBuffer(0, _lightingTexture); } gpu::FramebufferPointer FramebufferCache::getPrimaryFramebuffer() { @@ -118,6 +126,20 @@ gpu::TexturePointer FramebufferCache::getPrimarySpecularTexture() { return _primarySpecularTexture; } +gpu::FramebufferPointer FramebufferCache::getLightingFramebuffer() { + if (!_lightingFramebuffer) { + createPrimaryFramebuffer(); + } + return _lightingFramebuffer; +} + +gpu::TexturePointer FramebufferCache::getLightingTexture() { + if (!_lightingTexture) { + createPrimaryFramebuffer(); + } + return _lightingTexture; +} + gpu::FramebufferPointer FramebufferCache::getFramebuffer() { if (_cachedFramebuffers.isEmpty()) { _cachedFramebuffers.push_back(gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height()))); diff --git a/libraries/render-utils/src/FramebufferCache.h b/libraries/render-utils/src/FramebufferCache.h index e9a1bbf8e8..610609e7c9 100644 --- a/libraries/render-utils/src/FramebufferCache.h +++ b/libraries/render-utils/src/FramebufferCache.h @@ -37,6 +37,10 @@ public: gpu::TexturePointer getPrimaryNormalTexture(); gpu::TexturePointer getPrimarySpecularTexture(); + + gpu::TexturePointer getLightingTexture(); + gpu::FramebufferPointer getLightingFramebuffer(); + /// Returns the framebuffer object used to render shadow maps; gpu::FramebufferPointer getShadowFramebuffer(); @@ -63,7 +67,10 @@ private: gpu::TexturePointer _primaryColorTexture; gpu::TexturePointer _primaryNormalTexture; gpu::TexturePointer _primarySpecularTexture; - + + gpu::TexturePointer _lightingTexture; + gpu::FramebufferPointer _lightingFramebuffer; + gpu::FramebufferPointer _shadowFramebuffer; gpu::FramebufferPointer _selfieFramebuffer; From d593b824e94cd384614c275b0cefae9f7939db9b Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 Dec 2015 17:26:54 -0800 Subject: [PATCH 012/195] Introducing a true Primary Framebuffer and a different Deferred Framebuffer --- interface/src/Application.cpp | 10 +-- .../src/AmbientOcclusionEffect.cpp | 4 +- .../render-utils/src/AntialiasingEffect.cpp | 4 +- .../src/DeferredLightingEffect.cpp | 10 +-- .../render-utils/src/FramebufferCache.cpp | 76 ++++++++++++------- libraries/render-utils/src/FramebufferCache.h | 20 +++-- .../render-utils/src/RenderDeferredTask.cpp | 16 ++-- 7 files changed, 86 insertions(+), 54 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ef10ad4464..6648a131c4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -676,9 +676,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _applicationStateDevice->addInputVariant(QString("ComfortMode"), controller::StateController::ReadLambda([]() -> float { return (float)Menu::getInstance()->isOptionChecked(MenuOption::ComfortMode); })); - _applicationStateDevice->addInputVariant(QString("Grounded"), controller::StateController::ReadLambda([]() -> float { - return (float)qApp->getMyAvatar()->getCharacterController()->onGround(); - })); + _applicationStateDevice->addInputVariant(QString("Grounded"), controller::StateController::ReadLambda([]() -> float { + return (float)qApp->getMyAvatar()->getCharacterController()->onGround(); + })); userInputMapper->registerDevice(_applicationStateDevice); @@ -1347,7 +1347,7 @@ void Application::paintGL() { { PROFILE_RANGE(__FUNCTION__ "/compositor"); PerformanceTimer perfTimer("compositor"); - auto primaryFbo = framebufferCache->getPrimaryFramebuffer(); + auto primaryFbo = framebufferCache->getPrimaryFramebufferDepthColor(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFbo)); if (displayPlugin->isStereo()) { QRect currentViewport(QPoint(0, 0), QSize(size.width() / 2, size.height())); @@ -1372,7 +1372,7 @@ void Application::paintGL() { { PROFILE_RANGE(__FUNCTION__ "/pluginOutput"); PerformanceTimer perfTimer("pluginOutput"); - auto primaryFbo = framebufferCache->getPrimaryFramebuffer(); + auto primaryFbo = framebufferCache->getPrimaryFramebufferDepthColor(); GLuint finalTexture = gpu::GLBackend::getTextureID(primaryFbo->getRenderBuffer(0)); // Ensure the rendering context commands are completed when rendering GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 456a6430a7..3d2a5ef43b 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -201,7 +201,7 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons // Occlusion step getOcclusionPipeline(); batch.setResourceTexture(0, framebufferCache->getPrimaryDepthTexture()); - batch.setResourceTexture(1, framebufferCache->getPrimaryNormalTexture()); + batch.setResourceTexture(1, framebufferCache->getDeferredNormalTexture()); _occlusionBuffer->setRenderBuffer(0, _occlusionTexture); batch.setFramebuffer(_occlusionBuffer); @@ -276,7 +276,7 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons // Blend step getBlendPipeline(); batch.setResourceTexture(0, _hBlurTexture); - batch.setFramebuffer(framebufferCache->getPrimaryFramebuffer()); + batch.setFramebuffer(framebufferCache->getDeferredFramebuffer()); // Bind the fourth gpu::Pipeline we need - for blending the primary color buffer with blurred occlusion texture batch.setPipeline(getBlendPipeline()); diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index aaef67542f..2abb9f085e 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -123,7 +123,7 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re // FXAA step getAntialiasingPipeline(); - batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture()); + batch.setResourceTexture(0, framebufferCache->getDeferredColorTexture()); _antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture); batch.setFramebuffer(_antialiasingBuffer); batch.setPipeline(getAntialiasingPipeline()); @@ -153,7 +153,7 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re // Blend step getBlendPipeline(); batch.setResourceTexture(0, _antialiasingTexture); - batch.setFramebuffer(framebufferCache->getPrimaryFramebuffer()); + batch.setFramebuffer(framebufferCache->getDeferredFramebuffer()); batch.setPipeline(getBlendPipeline()); DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 371a3d705e..9ade2f5cea 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -374,9 +374,9 @@ void DeferredLightingEffect::prepare(RenderArgs* args) { batch.enableStereo(false); batch.setStateScissorRect(args->_viewport); - auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); + auto deferredFbo = DependencyManager::get()->getDeferredFramebuffer(); - batch.setFramebuffer(primaryFbo); + batch.setFramebuffer(deferredFbo); // clear the normal and specular buffers batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR1, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); const float MAX_SPECULAR_EXPONENT = 128.0f; @@ -412,9 +412,9 @@ void DeferredLightingEffect::render(RenderArgs* args) { batch.clearColorFramebuffer(lightingFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); // BInd the G-Buffer surfaces - batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture()); - batch.setResourceTexture(1, framebufferCache->getPrimaryNormalTexture()); - batch.setResourceTexture(2, framebufferCache->getPrimarySpecularTexture()); + batch.setResourceTexture(0, framebufferCache->getDeferredColorTexture()); + batch.setResourceTexture(1, framebufferCache->getDeferredNormalTexture()); + batch.setResourceTexture(2, framebufferCache->getDeferredSpecularTexture()); batch.setResourceTexture(3, framebufferCache->getPrimaryDepthTexture()); // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport) diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index 2a8033be0d..b39b8cc7e5 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -33,12 +33,14 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) { //If the size changed, we need to delete our FBOs if (_frameBufferSize != frameBufferSize) { _frameBufferSize = frameBufferSize; - _primaryFramebufferFull.reset(); _primaryFramebufferDepthColor.reset(); _primaryDepthTexture.reset(); _primaryColorTexture.reset(); - _primaryNormalTexture.reset(); - _primarySpecularTexture.reset(); + _deferredFramebuffer.reset(); + _deferredFramebufferDepthColor.reset(); + _deferredColorTexture.reset(); + _deferredNormalTexture.reset(); + _deferredSpecularTexture.reset(); _selfieFramebuffer.reset(); _cachedFramebuffers.clear(); _lightingTexture.reset(); @@ -47,8 +49,9 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) { } void FramebufferCache::createPrimaryFramebuffer() { - _primaryFramebufferFull = gpu::FramebufferPointer(gpu::Framebuffer::create()); _primaryFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create()); + _deferredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + _deferredFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create()); auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); auto width = _frameBufferSize.width(); @@ -56,23 +59,30 @@ void FramebufferCache::createPrimaryFramebuffer() { auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); _primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - _primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - _primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - - _primaryFramebufferFull->setRenderBuffer(0, _primaryColorTexture); - _primaryFramebufferFull->setRenderBuffer(1, _primaryNormalTexture); - _primaryFramebufferFull->setRenderBuffer(2, _primarySpecularTexture); _primaryFramebufferDepthColor->setRenderBuffer(0, _primaryColorTexture); + _deferredColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + _deferredNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + + _deferredFramebuffer->setRenderBuffer(0, _deferredColorTexture); + _deferredFramebuffer->setRenderBuffer(1, _deferredNormalTexture); + _deferredFramebuffer->setRenderBuffer(2, _deferredSpecularTexture); + + _deferredFramebufferDepthColor->setRenderBuffer(0, _deferredColorTexture); + // auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format _primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); - - _primaryFramebufferFull->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); _primaryFramebufferDepthColor->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); - + + _deferredFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); + + _deferredFramebufferDepthColor->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); + + _selfieFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); auto tex = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width * 0.5, height * 0.5, defaultSampler)); _selfieFramebuffer->setRenderBuffer(0, tex); @@ -84,13 +94,6 @@ void FramebufferCache::createPrimaryFramebuffer() { _lightingFramebuffer->setRenderBuffer(0, _lightingTexture); } -gpu::FramebufferPointer FramebufferCache::getPrimaryFramebuffer() { - if (!_primaryFramebufferFull) { - createPrimaryFramebuffer(); - } - return _primaryFramebufferFull; -} - gpu::FramebufferPointer FramebufferCache::getPrimaryFramebufferDepthColor() { if (!_primaryFramebufferDepthColor) { createPrimaryFramebuffer(); @@ -112,18 +115,39 @@ gpu::TexturePointer FramebufferCache::getPrimaryColorTexture() { return _primaryColorTexture; } -gpu::TexturePointer FramebufferCache::getPrimaryNormalTexture() { - if (!_primaryNormalTexture) { +gpu::FramebufferPointer FramebufferCache::getDeferredFramebuffer() { + if (!_deferredFramebuffer) { createPrimaryFramebuffer(); } - return _primaryNormalTexture; + return _deferredFramebuffer; } -gpu::TexturePointer FramebufferCache::getPrimarySpecularTexture() { - if (!_primarySpecularTexture) { +gpu::FramebufferPointer FramebufferCache::getDeferredFramebufferDepthColor() { + if (!_deferredFramebufferDepthColor) { createPrimaryFramebuffer(); } - return _primarySpecularTexture; + return _deferredFramebufferDepthColor; +} + +gpu::TexturePointer FramebufferCache::getDeferredColorTexture() { + if (!_deferredColorTexture) { + createPrimaryFramebuffer(); + } + return _deferredColorTexture; +} + +gpu::TexturePointer FramebufferCache::getDeferredNormalTexture() { + if (!_deferredNormalTexture) { + createPrimaryFramebuffer(); + } + return _deferredNormalTexture; +} + +gpu::TexturePointer FramebufferCache::getDeferredSpecularTexture() { + if (!_deferredSpecularTexture) { + createPrimaryFramebuffer(); + } + return _deferredSpecularTexture; } gpu::FramebufferPointer FramebufferCache::getLightingFramebuffer() { diff --git a/libraries/render-utils/src/FramebufferCache.h b/libraries/render-utils/src/FramebufferCache.h index 610609e7c9..6633301d0c 100644 --- a/libraries/render-utils/src/FramebufferCache.h +++ b/libraries/render-utils/src/FramebufferCache.h @@ -29,13 +29,17 @@ public: /// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is /// used for scene rendering. - gpu::FramebufferPointer getPrimaryFramebuffer(); gpu::FramebufferPointer getPrimaryFramebufferDepthColor(); gpu::TexturePointer getPrimaryDepthTexture(); gpu::TexturePointer getPrimaryColorTexture(); - gpu::TexturePointer getPrimaryNormalTexture(); - gpu::TexturePointer getPrimarySpecularTexture(); + + gpu::FramebufferPointer getDeferredFramebuffer(); + gpu::FramebufferPointer getDeferredFramebufferDepthColor(); + + gpu::TexturePointer getDeferredColorTexture(); + gpu::TexturePointer getDeferredNormalTexture(); + gpu::TexturePointer getDeferredSpecularTexture(); gpu::TexturePointer getLightingTexture(); @@ -60,13 +64,17 @@ private: void createPrimaryFramebuffer(); - gpu::FramebufferPointer _primaryFramebufferFull; gpu::FramebufferPointer _primaryFramebufferDepthColor; gpu::TexturePointer _primaryDepthTexture; gpu::TexturePointer _primaryColorTexture; - gpu::TexturePointer _primaryNormalTexture; - gpu::TexturePointer _primarySpecularTexture; + + gpu::FramebufferPointer _deferredFramebuffer; + gpu::FramebufferPointer _deferredFramebufferDepthColor; + + gpu::TexturePointer _deferredColorTexture; + gpu::TexturePointer _deferredNormalTexture; + gpu::TexturePointer _deferredSpecularTexture; gpu::TexturePointer _lightingTexture; gpu::FramebufferPointer _lightingFramebuffer; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index e65018ad3d..bf5f621726 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -38,13 +38,13 @@ void SetupDeferred::run(const SceneContextPointer& sceneContext, const RenderCon RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { - auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferDepthColor(); + auto deferredFbo = DependencyManager::get()->getDeferredFramebufferDepthColor(); batch.enableStereo(false); batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - batch.setFramebuffer(primaryFbo); + batch.setFramebuffer(deferredFbo); batch.clearFramebuffer( gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH | @@ -332,11 +332,11 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren doInBatch(args->_context, [=](gpu::Batch& batch) { args->_batch = &batch; - auto primaryFboColorDepthStencil = DependencyManager::get()->getPrimaryFramebufferDepthColor(); + auto deferredFboColorDepthStencil = DependencyManager::get()->getDeferredFramebufferDepthColor(); batch.enableStereo(false); - batch.setFramebuffer(primaryFboColorDepthStencil); + batch.setFramebuffer(deferredFboColorDepthStencil); batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); @@ -367,12 +367,12 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const doInBatch(args->_context, [=](gpu::Batch& batch) { args->_batch = &batch; - auto primaryFboColorDepthStencil = DependencyManager::get()->getPrimaryFramebufferDepthColor(); - auto primaryFboFull = DependencyManager::get()->getPrimaryFramebuffer(); + auto deferredFboColorDepthStencil = DependencyManager::get()->getDeferredFramebufferDepthColor(); + auto deferredFboFull = DependencyManager::get()->getDeferredFramebuffer(); batch.enableSkybox(true); - batch.setFramebuffer(primaryFboColorDepthStencil); + batch.setFramebuffer(deferredFboColorDepthStencil); batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); @@ -387,7 +387,7 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const renderItems(sceneContext, renderContext, inItems); - batch.setFramebuffer(primaryFboFull); + batch.setFramebuffer(deferredFboFull); }); args->_batch = nullptr; From baf93e8a084f03a5a8c2facfb5b803e14da299be Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 3 Dec 2015 15:54:53 -0800 Subject: [PATCH 013/195] Add basic DebugDeferredBuffer job --- .../render-utils/src/DebugDeferredBuffer.cpp | 72 +++++++++++++++++++ .../render-utils/src/DebugDeferredBuffer.h | 29 ++++++++ libraries/render-utils/src/HitEffect.cpp | 1 + libraries/render-utils/src/HitEffect.h | 8 +-- .../render-utils/src/RenderDeferredTask.cpp | 7 +- .../render-utils/src/RenderDeferredTask.h | 4 +- .../src/debug_deferred_buffer.slf | 21 ++++++ .../src/debug_deferred_buffer.slv | 19 +++++ libraries/render-utils/src/hit_effect.slf | 8 +-- 9 files changed, 155 insertions(+), 14 deletions(-) create mode 100644 libraries/render-utils/src/DebugDeferredBuffer.cpp create mode 100644 libraries/render-utils/src/DebugDeferredBuffer.h create mode 100644 libraries/render-utils/src/debug_deferred_buffer.slf create mode 100644 libraries/render-utils/src/debug_deferred_buffer.slv diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp new file mode 100644 index 0000000000..e1c31f943e --- /dev/null +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -0,0 +1,72 @@ +// +// DebugDeferredBuffer.cpp +// libraries/render-utils/src +// +// Created by Clement on 12/3/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 "DebugDeferredBuffer.h" + +#include +#include +#include +#include + +#include "GeometryCache.h" + +#include "debug_deferred_buffer_vert.h" +#include "debug_deferred_buffer_frag.h" + +using namespace render; + +const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline() { + if (!_pipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex({ debug_deferred_buffer_vert })); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel({ debug_deferred_buffer_frag })); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + auto state = std::make_shared(); + + 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 + _pipeline.reset(gpu::Pipeline::create(program, state)); + } + return _pipeline; +} + + +void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + RenderArgs* args = renderContext->args; + gpu::doInBatch(args->_context, [&](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()); + + batch.setPipeline(getPipeline()); + + glm::vec4 color(0.0f, 0.0f, 1.0f, 1.0f); + glm::vec2 bottomLeft(0.0f, -1.0f); + glm::vec2 topRight(1.0f, 1.0f); + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, color); + }); +} \ No newline at end of file diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h new file mode 100644 index 0000000000..827a3271f0 --- /dev/null +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -0,0 +1,29 @@ +// +// DebugDeferredBuffer.h +// libraries/render-utils/src +// +// Created by Clement on 12/3/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_DebugDeferredBuffer_h +#define hifi_DebugDeferredBuffer_h + +#include + +class DebugDeferredBuffer { +public: + using JobModel = render::Job::Model; + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + +private: + const gpu::PipelinePointer& getPipeline(); + + gpu::PipelinePointer _pipeline; +}; + +#endif // hifi_DebugDeferredBuffer_h \ No newline at end of file diff --git a/libraries/render-utils/src/HitEffect.cpp b/libraries/render-utils/src/HitEffect.cpp index 06bd07b456..f33dc5b3b9 100644 --- a/libraries/render-utils/src/HitEffect.cpp +++ b/libraries/render-utils/src/HitEffect.cpp @@ -14,6 +14,7 @@ #include +#include #include #include diff --git a/libraries/render-utils/src/HitEffect.h b/libraries/render-utils/src/HitEffect.h index b560cf5550..0a96a5300d 100644 --- a/libraries/render-utils/src/HitEffect.h +++ b/libraries/render-utils/src/HitEffect.h @@ -9,11 +9,7 @@ #ifndef hifi_hitEffect_h #define hifi_hitEffect_h -#include -#include "render/DrawTask.h" - -class AbstractViewStateInterface; -class ProgramObject; +#include class HitEffect { public: @@ -23,7 +19,7 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); typedef render::Job::Model JobModel; - const gpu::PipelinePointer& getHitEffectPipeline(); + const gpu::PipelinePointer& getHitEffectPipeline(); private: gpu::PipelinePointer _hitEffectPipeline; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index bf5f621726..43ddd5b7ae 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -18,10 +18,11 @@ #include #include -#include "FramebufferCache.h" +#include "DebugDeferredBuffer.h" #include "DeferredLightingEffect.h" -#include "TextureCache.h" +#include "FramebufferCache.h" #include "HitEffect.h" +#include "TextureCache.h" #include "render/DrawStatus.h" #include "AmbientOcclusionEffect.h" @@ -112,6 +113,8 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)))); _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput()))); + _jobs.push_back(Job(new DebugDeferredBuffer::JobModel("DebugDeferredBuffer"))); + // Grab a texture map representing the different status icons and assign that to the drawStatsuJob auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 6daa90b1ed..e75edd20da 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -80,9 +80,9 @@ class DrawOverlay3D { static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable public: static const gpu::PipelinePointer& getOpaquePipeline(); - + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - + typedef render::Job::Model JobModel; }; diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf new file mode 100644 index 0000000000..c33773aa40 --- /dev/null +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -0,0 +1,21 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// debug_deferred_buffer.slf +// fragment shader +// +// Created by Clement on 12/3 +// 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@> + +out vec4 outFragColor; + +void main(void) { + outFragColor = vec4(0.0, 0.0, 1.0, 1.0); +} \ No newline at end of file diff --git a/libraries/render-utils/src/debug_deferred_buffer.slv b/libraries/render-utils/src/debug_deferred_buffer.slv new file mode 100644 index 0000000000..b1b7b18f86 --- /dev/null +++ b/libraries/render-utils/src/debug_deferred_buffer.slv @@ -0,0 +1,19 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// debug_deferred_buffer.slv +// vertex shader +// +// Created by Clement on 12/3 +// 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/Inputs.slh@> + +void main(void) { + gl_Position = inPosition; +} \ No newline at end of file diff --git a/libraries/render-utils/src/hit_effect.slf b/libraries/render-utils/src/hit_effect.slf index c059488ba1..cc4484442f 100644 --- a/libraries/render-utils/src/hit_effect.slf +++ b/libraries/render-utils/src/hit_effect.slf @@ -20,8 +20,8 @@ in vec2 varQuadPosition; out vec4 outFragColor; 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.)); - outFragColor = vec4(1.0, 0.0, 0.0, alpha); + 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.)); + outFragColor = vec4(1.0, 0.0, 0.0, alpha); } \ No newline at end of file From c27944ae28532fc14ec6f8886b6966e50314c8bc Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 3 Dec 2015 17:13:41 -0800 Subject: [PATCH 014/195] Simple normal map debug --- examples/utilities/tools/renderEngineDebug.js | 6 ++++++ interface/src/Application.cpp | 4 +++- .../render-utils/src/DebugDeferredBuffer.cpp | 18 ++++++++---------- .../render-utils/src/RenderDeferredTask.cpp | 7 ++++++- .../render-utils/src/RenderDeferredTask.h | 13 ++++++++++--- .../render-utils/src/debug_deferred_buffer.slf | 5 +++-- .../render-utils/src/debug_deferred_buffer.slv | 3 +++ libraries/render/src/render/Engine.h | 1 + .../src/SceneScriptingInterface.h | 8 ++++++-- 9 files changed, 46 insertions(+), 19 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index cca97b7184..940eeda02d 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -66,6 +66,12 @@ var overlaysCounter = new CounterWidget(panel, "Overlays", var showDisplayStatusFlag = 1; var showNetworkStatusFlag = 2; +panel.newCheckbox("Debug deferred buffer", + function(value) { Scene.setEngineDisplayDebugDeferredBuffer(value > 0); }, + function() { return Scene.doEngineDisplayDebugDeferredBuffer() > 0; }, + function(value) { return value > 0; } +); + panel.newCheckbox("Display status", function(value) { Scene.setEngineDisplayItemStatus(value ? Scene.doEngineDisplayItemStatus() | showDisplayStatusFlag : diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cc9a47f793..8fa772e316 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3621,7 +3621,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._maxDrawnOpaqueItems = sceneInterface->getEngineMaxDrawnOpaqueItems(); renderContext._maxDrawnTransparentItems = sceneInterface->getEngineMaxDrawnTransparentItems(); renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems(); - + + renderContext._drawDebugDeferredBuffer = sceneInterface->doEngineDisplayDebugDeferredBuffer(); + renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus(); if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned)) { renderContext._drawItemStatus |= render::showNetworkStatusFlag; diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index e1c31f943e..efb78c888c 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -17,6 +17,7 @@ #include #include "GeometryCache.h" +#include "FramebufferCache.h" #include "debug_deferred_buffer_vert.h" #include "debug_deferred_buffer_frag.h" @@ -33,16 +34,8 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline() { gpu::Shader::BindingSet slotBindings; gpu::Shader::makeProgram(*program, slotBindings); - auto state = std::make_shared(); - - 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 - _pipeline.reset(gpu::Pipeline::create(program, state)); + _pipeline.reset(gpu::Pipeline::create(program, std::make_shared())); } return _pipeline; } @@ -53,6 +46,9 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren assert(renderContext->args->_viewFrustum); RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + auto geometryBuffer = DependencyManager::get(); + auto framebufferCache = DependencyManager::get(); + glm::mat4 projMat; Transform viewMat; @@ -64,9 +60,11 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setPipeline(getPipeline()); + batch.setResourceTexture(0, framebufferCache->getPrimaryNormalTexture()); + glm::vec4 color(0.0f, 0.0f, 1.0f, 1.0f); glm::vec2 bottomLeft(0.0f, -1.0f); glm::vec2 topRight(1.0f, 1.0f); - DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, color); + geometryBuffer->renderQuad(batch, bottomLeft, topRight, color); }); } \ No newline at end of file diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 43ddd5b7ae..0f939682c8 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -114,6 +114,8 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput()))); _jobs.push_back(Job(new DebugDeferredBuffer::JobModel("DebugDeferredBuffer"))); + _jobs.back().setEnabled(false); + _drawDebugDeferredBufferIndex = _jobs.size() - 1; // Grab a texture map representing the different status icons and assign that to the drawStatsuJob auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; @@ -154,10 +156,13 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend return; } + // Make sure we turn the deferred buffer debug on/off + setDrawDebugDeferredBuffer(renderContext->_drawDebugDeferredBuffer); + // Make sure we turn the displayItemStatus on/off setDrawItemStatus(renderContext->_drawItemStatus); - //Make sure we display hit effect on screen, as desired from a script + // Make sure we display hit effect on screen, as desired from a script setDrawHitEffect(renderContext->_drawHitEffect); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index e75edd20da..09a2761926 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -93,16 +93,23 @@ public: ~RenderDeferredTask(); render::Jobs _jobs; - + + int _drawDebugDeferredBufferIndex = -1; int _drawStatusJobIndex = -1; int _drawHitEffectJobIndex = -1; - + + void setDrawDebugDeferredBuffer(int draw) { + if (_drawDebugDeferredBufferIndex >= 0) { + _jobs[_drawDebugDeferredBufferIndex].setEnabled(draw > 0); + } + } + bool doDrawDebugDeferredBuffer() const { if (_drawDebugDeferredBufferIndex >= 0) { return _jobs[_drawDebugDeferredBufferIndex].isEnabled(); } else { return false; } } + void setDrawItemStatus(int draw) { if (_drawStatusJobIndex >= 0) { _jobs[_drawStatusJobIndex].setEnabled(draw > 0); } } - bool doDrawItemStatus() const { if (_drawStatusJobIndex >= 0) { return _jobs[_drawStatusJobIndex].isEnabled(); } else { return false; } } void setDrawHitEffect(bool draw) { if (_drawHitEffectJobIndex >= 0) { _jobs[_drawHitEffectJobIndex].setEnabled(draw); } } diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index c33773aa40..212a51c1ed 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -12,10 +12,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> +<@include DeferredBuffer.slh@> +in vec2 uv; out vec4 outFragColor; void main(void) { - outFragColor = vec4(0.0, 0.0, 1.0, 1.0); + outFragColor = texture(normalMap, uv); } \ No newline at end of file diff --git a/libraries/render-utils/src/debug_deferred_buffer.slv b/libraries/render-utils/src/debug_deferred_buffer.slv index b1b7b18f86..85ff2b651d 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slv +++ b/libraries/render-utils/src/debug_deferred_buffer.slv @@ -14,6 +14,9 @@ <@include gpu/Inputs.slh@> +out vec2 uv; + void main(void) { + uv = (inPosition.xy + 1.0) * 0.5; gl_Position = inPosition; } \ No newline at end of file diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 7c11246cff..ab56d68291 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -53,6 +53,7 @@ public: int _numDrawnOverlay3DItems = 0; int _maxDrawnOverlay3DItems = -1; + int _drawDebugDeferredBuffer = 0; int _drawItemStatus = 0; bool _drawHitEffect = false; diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 6be0ce44a8..eac35ad5bb 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -106,7 +106,10 @@ public: Q_INVOKABLE int getEngineMaxDrawnTransparentItems() { return _maxDrawnTransparentItems; } Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _maxDrawnOverlay3DItems = count; } Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _maxDrawnOverlay3DItems; } - + + Q_INVOKABLE void setEngineDisplayDebugDeferredBuffer(int display) { _drawDebugDeferredBuffer = display; } + Q_INVOKABLE int doEngineDisplayDebugDeferredBuffer() { return _drawDebugDeferredBuffer; } + Q_INVOKABLE void setEngineDisplayItemStatus(int display) { _drawItemStatus = display; } Q_INVOKABLE int doEngineDisplayItemStatus() { return _drawItemStatus; } @@ -142,7 +145,8 @@ protected: int _maxDrawnOpaqueItems = -1; int _maxDrawnTransparentItems = -1; int _maxDrawnOverlay3DItems = -1; - + + int _drawDebugDeferredBuffer = 0; int _drawItemStatus = 0; bool _drawHitEffect = false; From ba2e7e1f29df15dd6e8e0551dde243cb01488283 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 4 Dec 2015 11:15:06 -0800 Subject: [PATCH 015/195] Debug diffuse buffer --- libraries/render-utils/src/DebugDeferredBuffer.cpp | 2 +- libraries/render-utils/src/debug_deferred_buffer.slf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index efb78c888c..c71c6ba1a9 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -60,7 +60,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setPipeline(getPipeline()); - batch.setResourceTexture(0, framebufferCache->getPrimaryNormalTexture()); + batch.setResourceTexture(0, framebufferCache->getDeferredColorTexture()); glm::vec4 color(0.0f, 0.0f, 1.0f, 1.0f); glm::vec2 bottomLeft(0.0f, -1.0f); diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index 212a51c1ed..efb1c25628 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -18,5 +18,5 @@ in vec2 uv; out vec4 outFragColor; void main(void) { - outFragColor = texture(normalMap, uv); + outFragColor = texture(diffuseMap, uv); } \ No newline at end of file From 3c18664c57ce86647e3aa40c825b7fa7cbcd5e2f Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 4 Dec 2015 11:47:57 -0800 Subject: [PATCH 016/195] Cleaning all the deferred buffers in the Prepare call --- libraries/render-utils/src/DeferredLightingEffect.cpp | 10 ++++++++++ libraries/render-utils/src/RenderDeferredTask.cpp | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 9ade2f5cea..7ecef1155c 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -372,11 +372,21 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu void DeferredLightingEffect::prepare(RenderArgs* args) { gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.enableStereo(false); + // batch.setStateScissorRect(args->_viewport); + batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); auto deferredFbo = DependencyManager::get()->getDeferredFramebuffer(); batch.setFramebuffer(deferredFbo); + + // Clear Color, Depth and Stencil + batch.clearFramebuffer( + gpu::Framebuffer::BUFFER_COLOR0 | + gpu::Framebuffer::BUFFER_DEPTH | + gpu::Framebuffer::BUFFER_STENCIL, + vec4(vec3(0), 1), 1.0, 0.0, true); + // clear the normal and specular buffers batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR1, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); const float MAX_SPECULAR_EXPONENT = 128.0f; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index bf5f621726..6237534fee 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -35,7 +35,7 @@ using namespace render; void SetupDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - RenderArgs* args = renderContext->args; +/* RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { auto deferredFbo = DependencyManager::get()->getDeferredFramebufferDepthColor(); @@ -51,6 +51,7 @@ void SetupDeferred::run(const SceneContextPointer& sceneContext, const RenderCon gpu::Framebuffer::BUFFER_STENCIL, vec4(vec3(0), 1), 1.0, 0.0, true); }); + */ } void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { From ef7ddce2b64d6d33593d5b55f134f10d26f8ab4e Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 4 Dec 2015 16:52:14 -0800 Subject: [PATCH 017/195] Trying to fix the problem of the background not showing correctly --- libraries/model/src/model/Skybox.slf | 3 ++- .../render-utils/src/DeferredBufferWrite.slh | 7 +++---- .../render-utils/src/DeferredLighting.slh | 4 +++- .../src/DeferredLightingEffect.cpp | 5 ++++- .../render-utils/src/RenderDeferredTask.cpp | 21 ------------------- 5 files changed, 12 insertions(+), 28 deletions(-) diff --git a/libraries/model/src/model/Skybox.slf b/libraries/model/src/model/Skybox.slf index 6246bbd9d3..9b642f138e 100755 --- a/libraries/model/src/model/Skybox.slf +++ b/libraries/model/src/model/Skybox.slf @@ -52,7 +52,8 @@ void main(void) { } } - vec3 pixel = pow(color, vec3(1.0/2.2)); // manual Gamma correction + // vec3 pixel = pow(color, vec3(1.0/2.2)); // manual Gamma correction + vec3 pixel = color; _fragColor = vec4(pixel, 0.0); #endif diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 1c1330f0c0..573146a0af 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -51,7 +51,7 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, discard; } - _fragColor0 = vec4(diffuse.rgb, alpha); + _fragColor0 = vec4(diffuse.rgb, 1.0); // Opaque _fragColor1 = vec4(bestFitNormal(normal), 1.0); _fragColor2 = vec4(specular, shininess / 128.0); } @@ -61,9 +61,8 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 s discard; } - _fragColor0 = vec4(diffuse.rgb, alpha); - //_fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - _fragColor1 = vec4(bestFitNormal(normal), 0.5); + _fragColor0 = vec4(diffuse.rgb, 0.5); + _fragColor1 = vec4(bestFitNormal(normal), 1.0); _fragColor2 = vec4(emissive, shininess / 128.0); } diff --git a/libraries/render-utils/src/DeferredLighting.slh b/libraries/render-utils/src/DeferredLighting.slh index 53ffdee0ca..d01b36f553 100755 --- a/libraries/render-utils/src/DeferredLighting.slh +++ b/libraries/render-utils/src/DeferredLighting.slh @@ -33,7 +33,9 @@ vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 sp vec3 schlick = specular * (1.0 - shlickPower5) + vec3(shlickPower5); vec3 reflect = specularPower * schlick; - return vec4(reflect, diffuse * (1 - length(schlick))); + // FIXME: + //return vec4(reflect, diffuse * (1 - length(schlick))); + return vec4(reflect, diffuse); } <@endfunc@> diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 7ecef1155c..7eace8d302 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -179,7 +179,10 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); gpu::Shader::makeProgram(*blitProgram); auto blitState = std::make_shared(); - blitState->setColorWriteMask(true, true, true, false); + /* blitState->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);*/ + blitState->setColorWriteMask(true, true, true, true); _blitLightBuffer = gpu::PipelinePointer(gpu::Pipeline::create(blitProgram, blitState)); } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 572a3fd842..a55dcbac89 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -35,25 +35,6 @@ using namespace render; -void SetupDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { -/* RenderArgs* args = renderContext->args; - gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { - - auto deferredFbo = DependencyManager::get()->getDeferredFramebufferDepthColor(); - - batch.enableStereo(false); - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - - batch.setFramebuffer(deferredFbo); - batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_COLOR0 | - gpu::Framebuffer::BUFFER_DEPTH | - gpu::Framebuffer::BUFFER_STENCIL, - vec4(vec3(0), 1), 1.0, 0.0, true); - }); - */ -} void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { DependencyManager::get()->prepare(renderContext->args); @@ -69,8 +50,6 @@ void ResolveDeferred::run(const SceneContextPointer& sceneContext, const RenderC } RenderDeferredTask::RenderDeferredTask() : Task() { - _jobs.push_back(Job(new SetupDeferred::JobModel("SetupFramebuffer"))); - _jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred"))); _jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque", FetchItems( From 5bfcd4ed91e5b135a0df219b7e86390f290a6809 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 4 Dec 2015 15:51:37 -0800 Subject: [PATCH 018/195] Fix scripted checkbox --- examples/utilities/tools/cookies.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index d9fa999a13..edb0fb4330 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -384,10 +384,10 @@ var CHECK_MARK_COLOR = { y: newY }); Overlays.editOverlay(this.checkMark, { - y: newY + y: newY + (0.25 * this.thumbSize) }); Overlays.editOverlay(this.unCheckMark, { - y: newY + y: newY + (0.25 * this.thumbSize) }); }; @@ -399,10 +399,10 @@ var CHECK_MARK_COLOR = { y: this.y }); Overlays.editOverlay(this.checkMark, { - y: this.y + y: this.y + (0.25 * this.thumbSize) }); Overlays.editOverlay(this.unCheckMark, { - y: this.y + y: this.y+ (0.25 * this.thumbSize) }); }; From b45b1cc513ca9ed43a07de1bcfbe4b48d7e0f29c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 4 Dec 2015 17:43:00 -0800 Subject: [PATCH 019/195] More work on live g-buffer debug --- examples/utilities/tools/renderEngineDebug.js | 20 +++++++--- interface/src/Menu.cpp | 20 ++++++++++ interface/src/Menu.h | 2 + .../src/scripting/MenuScriptingInterface.cpp | 13 +++++++ .../src/scripting/MenuScriptingInterface.h | 4 ++ .../render-utils/src/DebugDeferredBuffer.cpp | 38 +++++++++++++++---- .../render-utils/src/DebugDeferredBuffer.h | 14 ++++++- libraries/render-utils/src/DeferredBuffer.slh | 3 ++ .../src/debug_deferred_buffer.slf | 6 ++- 9 files changed, 103 insertions(+), 17 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index 940eeda02d..b300ff2ea8 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -10,6 +10,9 @@ Script.include("cookies.js"); +var MENU = "Developer>Render>Debug Deferred Buffer"; +var ACTIONS = ["Off", "Diffuse", "Normal", "Specular", "Depth", "Lighting"]; + var panel = new Panel(10, 100); function CounterWidget(parentPanel, name, feedGetter, drawGetter, capSetter, capGetter) { @@ -61,17 +64,18 @@ var overlaysCounter = new CounterWidget(panel, "Overlays", function () { return Scene.getEngineMaxDrawnOverlay3DItems(); } ); +function menuItemEvent(menuItem) { + var index = ACTIONS.indexOf(menuItem); + if (index >= 0) { + Scene.setEngineDisplayDebugDeferredBuffer(index); + print(menuItem); + } +} // see libraries/render/src/render/Engine.h var showDisplayStatusFlag = 1; var showNetworkStatusFlag = 2; -panel.newCheckbox("Debug deferred buffer", - function(value) { Scene.setEngineDisplayDebugDeferredBuffer(value > 0); }, - function() { return Scene.doEngineDisplayDebugDeferredBuffer() > 0; }, - function(value) { return value > 0; } -); - panel.newCheckbox("Display status", function(value) { Scene.setEngineDisplayItemStatus(value ? Scene.doEngineDisplayItemStatus() | showDisplayStatusFlag : @@ -101,7 +105,11 @@ Controller.mouseMoveEvent.connect(function panelMouseMoveEvent(event) { return p Controller.mousePressEvent.connect( function panelMousePressEvent(event) { return panel.mousePressEvent(event); }); Controller.mouseReleaseEvent.connect(function(event) { return panel.mouseReleaseEvent(event); }); +Menu.menuItemEvent.connect(menuItemEvent); +Menu.addActionGroup(MENU, ACTIONS, ACTIONS[0]); + function scriptEnding() { panel.destroy(); + Menu.removeActionGroup(MENU); } Script.scriptEnding.connect(scriptEnding); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 86b3987af1..66c1824176 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -985,6 +985,26 @@ bool Menu::menuItemExists(const QString& menu, const QString& menuitem) { return false; }; +void Menu::addActionGroup(const QString& groupName, const QStringList& actionList, const QString& selected) { + auto menu = addMenu(groupName); + + QActionGroup* actionGroup = new QActionGroup(menu); + actionGroup->setExclusive(true); + + auto menuScriptingInterface = MenuScriptingInterface::getInstance(); + for (auto action : actionList) { + auto item = addCheckableActionToQMenuAndActionHash(menu, action, 0, action == selected, + menuScriptingInterface, + SLOT(menuItemTriggered())); + actionGroup->addAction(item); + } + + QMenuBar::repaint(); +} + +void Menu::removeActionGroup(const QString& groupName) { + removeMenu(groupName); +} MenuWrapper::MenuWrapper(QMenu* menu) : _realMenu(menu) { VrMenu::executeOrQueue([=](VrMenu* vrMenu) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3ff0b149f4..49759c8beb 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -100,6 +100,8 @@ public slots: void addMenuItem(const MenuItemProperties& properties); void removeMenuItem(const QString& menuName, const QString& menuitem); bool menuItemExists(const QString& menuName, const QString& menuitem); + void addActionGroup(const QString& groupName, const QStringList& actionList, const QString& selected = QString()); + void removeActionGroup(const QString& groupName); bool isOptionChecked(const QString& menuOption) const; void setIsOptionChecked(const QString& menuOption, bool isChecked); diff --git a/interface/src/scripting/MenuScriptingInterface.cpp b/interface/src/scripting/MenuScriptingInterface.cpp index ff7784b9ae..087d391daa 100644 --- a/interface/src/scripting/MenuScriptingInterface.cpp +++ b/interface/src/scripting/MenuScriptingInterface.cpp @@ -84,6 +84,19 @@ bool MenuScriptingInterface::menuItemExists(const QString& menu, const QString& return result; } +void MenuScriptingInterface::addActionGroup(const QString& groupName, const QStringList& actionList, + const QString& selected) { + QMetaObject::invokeMethod(Menu::getInstance(), "addActionGroup", + Q_ARG(const QString&, groupName), + Q_ARG(const QStringList&, actionList), + Q_ARG(const QString&, selected)); +} + +void MenuScriptingInterface::removeActionGroup(const QString& groupName) { + QMetaObject::invokeMethod(Menu::getInstance(), "removeActionGroup", + Q_ARG(const QString&, groupName)); +} + bool MenuScriptingInterface::isOptionChecked(const QString& menuOption) { bool result; QMetaObject::invokeMethod(Menu::getInstance(), "isOptionChecked", Qt::BlockingQueuedConnection, diff --git a/interface/src/scripting/MenuScriptingInterface.h b/interface/src/scripting/MenuScriptingInterface.h index 5c01318a38..51399c2fa5 100644 --- a/interface/src/scripting/MenuScriptingInterface.h +++ b/interface/src/scripting/MenuScriptingInterface.h @@ -42,6 +42,10 @@ public slots: void removeMenuItem(const QString& menuName, const QString& menuitem); bool menuItemExists(const QString& menuName, const QString& menuitem); + void addActionGroup(const QString& groupName, const QStringList& actionList, + const QString& selected = QString()); + void removeActionGroup(const QString& groupName); + bool isOptionChecked(const QString& menuOption); void setIsOptionChecked(const QString& menuOption, bool isChecked); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 5510d9c3fc..3b4e3d2bd5 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -24,20 +24,38 @@ using namespace render; -const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline() { - if (!_pipeline) { +static const std::string PLACEHOLDER { "DEBUG_PLACEHOLDER" }; +static const std::array SLOT_NAMES {{ + "diffuseMap", + "normalMap", + "specularMap", + "depthMap", + "lightingMap" +}}; + +std::string getCode(int slot) { + return std::string("return texture(").append(SLOT_NAMES[slot]).append(", uv);"); +} + +const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(int slot) { + if (!_pipelines[slot]) { + std::string fragmentShader = debug_deferred_buffer_frag; + fragmentShader.replace(fragmentShader.find(PLACEHOLDER), PLACEHOLDER.size(), getCode(slot)); + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex({ debug_deferred_buffer_vert })); - auto ps = gpu::ShaderPointer(gpu::Shader::createPixel({ debug_deferred_buffer_frag })); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(fragmentShader)); auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); - gpu::Shader::BindingSet slotBindings; + for (int slot = 0; slot < NUM_SLOTS; ++slot) { + slotBindings.insert(gpu::Shader::Binding(SLOT_NAMES[slot], slot)); + } gpu::Shader::makeProgram(*program, slotBindings); // Good to go add the brand new pipeline - _pipeline = gpu::Pipeline::create(program, std::make_shared()); + _pipelines[slot] = gpu::Pipeline::create(program, std::make_shared()); } - return _pipeline; + return _pipelines[slot]; } @@ -58,9 +76,13 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); - batch.setPipeline(getPipeline()); + batch.setPipeline(getPipeline((DebugDeferredBufferSlot)(renderContext->_drawDebugDeferredBuffer - 1))); - batch.setResourceTexture(0, framebufferCache->getDeferredColorTexture()); + batch.setResourceTexture(Diffuse, framebufferCache->getDeferredColorTexture()); + batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture()); + batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture()); + batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture()); + batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture()); glm::vec4 color(0.0f, 0.0f, 1.0f, 1.0f); glm::vec2 bottomLeft(0.0f, -1.0f); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 827a3271f0..95865cc12a 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -18,12 +18,22 @@ class DebugDeferredBuffer { public: using JobModel = render::Job::Model; + enum DebugDeferredBufferSlot : int { + Diffuse = 0, + Normal, + Specular, + Depth, + Lighting, + + NUM_SLOTS + }; + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); private: - const gpu::PipelinePointer& getPipeline(); + const gpu::PipelinePointer& getPipeline(int slot); - gpu::PipelinePointer _pipeline; + std::array _pipelines; }; #endif // hifi_DebugDeferredBuffer_h \ No newline at end of file diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index 275966534a..18606f2525 100755 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -24,6 +24,9 @@ uniform sampler2D specularMap; // the depth texture uniform sampler2D depthMap; +// the lighting texture +uniform sampler2D lightingMap; + struct DeferredTransform { mat4 projection; diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index efb1c25628..55632eb337 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -17,6 +17,10 @@ in vec2 uv; out vec4 outFragColor; +vec4 getFragmentColor() { + DEBUG_PLACEHOLDER +} + void main(void) { - outFragColor = texture(diffuseMap, uv); + outFragColor = getFragmentColor(); } \ No newline at end of file From 41af3778784b537b27f23d8be3090c756d6c2d2a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 4 Dec 2015 18:33:11 -0800 Subject: [PATCH 020/195] More g-buffer debugging options --- examples/utilities/tools/renderEngineDebug.js | 2 +- .../render-utils/src/DebugDeferredBuffer.cpp | 66 ++++++++++++++++--- .../render-utils/src/DebugDeferredBuffer.h | 28 ++++---- 3 files changed, 73 insertions(+), 23 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index b300ff2ea8..ab266620ab 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -11,7 +11,7 @@ Script.include("cookies.js"); var MENU = "Developer>Render>Debug Deferred Buffer"; -var ACTIONS = ["Off", "Diffuse", "Normal", "Specular", "Depth", "Lighting"]; +var ACTIONS = ["Off", "Diffuse", "Alpha", "Specular", "Roughness", "Normal", "Depth", "Lighting", "Custom"]; var panel = new Panel(10, 100); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 3b4e3d2bd5..d3879dacf3 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -11,6 +11,8 @@ #include "DebugDeferredBuffer.h" +#include + #include #include #include @@ -24,8 +26,16 @@ using namespace render; -static const std::string PLACEHOLDER { "DEBUG_PLACEHOLDER" }; -static const std::array SLOT_NAMES {{ +enum Slots { + Diffuse = 0, + Normal, + Specular, + Depth, + Lighting, + + NUM_SLOTS +}; +static const std::array SLOT_NAMES {{ "diffuseMap", "normalMap", "specularMap", @@ -33,14 +43,50 @@ static const std::array SLOT_NAMES "lightingMap" }}; -std::string getCode(int slot) { - return std::string("return texture(").append(SLOT_NAMES[slot]).append(", uv);"); +static const std::string PLACEHOLDER { "DEBUG_PLACEHOLDER" }; + +std::string DebugDeferredBuffer::getCode(Modes mode) { + switch (mode) { + case DiffuseMode: { + QString code = "return vec4(texture(%1, uv).xyz, 1.0);"; + return code.arg(SLOT_NAMES[Diffuse].c_str()).toStdString(); + } + case AlphaMode: { + QString code = "return vec4(vec3(texture(%1, uv).a), 1.0);"; + return code.arg(SLOT_NAMES[Diffuse].c_str()).toStdString(); + } + case SpecularMode: { + QString code = "return vec4(texture(%1, uv).xyz, 1.0);"; + return code.arg(SLOT_NAMES[Specular].c_str()).toStdString(); + } + case RoughnessMode: { + QString code = "return vec4(vec3(texture(%1, uv).a), 1.0);"; + return code.arg(SLOT_NAMES[Specular].c_str()).toStdString(); + } + case NormalMode: { + QString code = "return vec4(texture(%1, uv).xyz, 1.0);"; + return code.arg(SLOT_NAMES[Normal].c_str()).toStdString(); + } + case DepthMode: { + QString code = "return vec4(vec3(texture(%1, uv).x), 1.0);"; + return code.arg(SLOT_NAMES[Depth].c_str()).toStdString(); + } + case LightingMode: { + QString code = "return vec4(texture(%1, uv).xyz, 1.0);"; + return code.arg(SLOT_NAMES[Lighting].c_str()).toStdString(); + } + case CustomMode: + return std::string("return vec4(1.0);"); + case NUM_MODES: + Q_UNIMPLEMENTED(); + return std::string("return vec4(1.0);"); + } } -const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(int slot) { - if (!_pipelines[slot]) { +const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode) { + if (!_pipelines[mode]) { std::string fragmentShader = debug_deferred_buffer_frag; - fragmentShader.replace(fragmentShader.find(PLACEHOLDER), PLACEHOLDER.size(), getCode(slot)); + fragmentShader.replace(fragmentShader.find(PLACEHOLDER), PLACEHOLDER.size(), getCode(mode)); auto vs = gpu::ShaderPointer(gpu::Shader::createVertex({ debug_deferred_buffer_vert })); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(fragmentShader)); @@ -53,9 +99,9 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(int slot) { gpu::Shader::makeProgram(*program, slotBindings); // Good to go add the brand new pipeline - _pipelines[slot] = gpu::Pipeline::create(program, std::make_shared()); + _pipelines[mode] = gpu::Pipeline::create(program, std::make_shared()); } - return _pipelines[slot]; + return _pipelines[mode]; } @@ -76,7 +122,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); - batch.setPipeline(getPipeline((DebugDeferredBufferSlot)(renderContext->_drawDebugDeferredBuffer - 1))); + batch.setPipeline(getPipeline(Modes(renderContext->_drawDebugDeferredBuffer - 1))); batch.setResourceTexture(Diffuse, framebufferCache->getDeferredColorTexture()); batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture()); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 95865cc12a..8628d9e21e 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -18,22 +18,26 @@ class DebugDeferredBuffer { public: using JobModel = render::Job::Model; - enum DebugDeferredBufferSlot : int { - Diffuse = 0, - Normal, - Specular, - Depth, - Lighting, - - NUM_SLOTS - }; - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); private: - const gpu::PipelinePointer& getPipeline(int slot); + enum Modes : int { + DiffuseMode = 0, + AlphaMode, + SpecularMode, + RoughnessMode, + NormalMode, + DepthMode, + LightingMode, + CustomMode, + + NUM_MODES + }; - std::array _pipelines; + const gpu::PipelinePointer& getPipeline(Modes mode); + std::string getCode(Modes mode); + + std::array _pipelines; }; #endif // hifi_DebugDeferredBuffer_h \ No newline at end of file From acb9e2774e65494d151ddd1dd91a84722a150d14 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 4 Dec 2015 20:28:38 -0800 Subject: [PATCH 021/195] Basic implementation of debug zone resizing --- examples/utilities/tools/renderEngineDebug.js | 51 +++++++++++++++++-- interface/src/Application.cpp | 3 +- .../render-utils/src/DebugDeferredBuffer.cpp | 14 ++--- .../render-utils/src/RenderDeferredTask.cpp | 2 +- .../render-utils/src/RenderDeferredTask.h | 2 +- .../src/debug_deferred_buffer.slf | 4 +- libraries/render/src/render/Engine.h | 3 +- .../src/SceneScriptingInterface.h | 9 ++-- 8 files changed, 70 insertions(+), 18 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index ab266620ab..c37c104498 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -13,6 +13,10 @@ Script.include("cookies.js"); var MENU = "Developer>Render>Debug Deferred Buffer"; var ACTIONS = ["Off", "Diffuse", "Alpha", "Specular", "Roughness", "Normal", "Depth", "Lighting", "Custom"]; +Number.prototype.clamp = function(min, max) { + return Math.min(Math.max(this, min), max); +}; + var panel = new Panel(10, 100); function CounterWidget(parentPanel, name, feedGetter, drawGetter, capSetter, capGetter) { @@ -64,10 +68,23 @@ var overlaysCounter = new CounterWidget(panel, "Overlays", function () { return Scene.getEngineMaxDrawnOverlay3DItems(); } ); +var resizing = false; +Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size + +function setEngineDeferredDebugSize(eventX) { + var scaledX = (2.0 * (eventX / Window.innerWidth) - 1.0).clamp(-1.0, 1.0); + Scene.setEngineDeferredDebugSize({ x: scaledX, y: -1.0, z: 1.0, w: 1.0 }); +} +function shouldStartResizing(eventX) { + var x = Math.abs(eventX - Window.innerWidth * (1.0 + Scene.getEngineDeferredDebugSize().x) / 2.0); + var mode = Scene.getEngineDeferredDebugMode(); + return mode !== -1 && x < 20; +} + function menuItemEvent(menuItem) { var index = ACTIONS.indexOf(menuItem); if (index >= 0) { - Scene.setEngineDisplayDebugDeferredBuffer(index); + Scene.setEngineDeferredDebugMode(index - 1); print(menuItem); } } @@ -101,9 +118,33 @@ function updateCounters() { } Script.setInterval(updateCounters, tickTackPeriod); -Controller.mouseMoveEvent.connect(function panelMouseMoveEvent(event) { return panel.mouseMoveEvent(event); }); -Controller.mousePressEvent.connect( function panelMousePressEvent(event) { return panel.mousePressEvent(event); }); -Controller.mouseReleaseEvent.connect(function(event) { return panel.mouseReleaseEvent(event); }); +function mouseMoveEvent(event) { + if (resizing) { + setEngineDeferredDebugSize(event.x); + } else { + panel.mouseMoveEvent(event); + } +} + +function mousePressEvent(event) { + if (shouldStartResizing(event.x)) { + resizing = true; + } else { + panel.mousePressEvent(event); + } +} + +function mouseReleaseEvent(event) { + if (resizing) { + resizing = false; + } else { + panel.mouseReleaseEvent(event); + } +} + +Controller.mouseMoveEvent.connect(mouseMoveEvent); +Controller.mousePressEvent.connect(mousePressEvent); +Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Menu.menuItemEvent.connect(menuItemEvent); Menu.addActionGroup(MENU, ACTIONS, ACTIONS[0]); @@ -111,5 +152,7 @@ Menu.addActionGroup(MENU, ACTIONS, ACTIONS[0]); function scriptEnding() { panel.destroy(); Menu.removeActionGroup(MENU); + Scene.setEngineDeferredDebugMode(-1); + Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size } Script.scriptEnding.connect(scriptEnding); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d9fea20ad5..78724862de 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3622,7 +3622,8 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._maxDrawnTransparentItems = sceneInterface->getEngineMaxDrawnTransparentItems(); renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems(); - renderContext._drawDebugDeferredBuffer = sceneInterface->doEngineDisplayDebugDeferredBuffer(); + renderContext._deferredDebugMode = sceneInterface->getEngineDeferredDebugMode(); + renderContext._deferredDebugSize = sceneInterface->getEngineDeferredDebugSize(); renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus(); if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned)) { diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index d3879dacf3..842729144d 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -43,7 +43,8 @@ static const std::array SLOT_NAMES {{ "lightingMap" }}; -static const std::string PLACEHOLDER { "DEBUG_PLACEHOLDER" }; +static const std::string COMPUTE_PLACEHOLDER { "/*COMPUTE_PLACEHOLDER*/" }; // required +static const std::string FUNCTIONS_PLACEHOLDER { "/*FUNCTIONS_PLACEHOLDER*/" }; // optional std::string DebugDeferredBuffer::getCode(Modes mode) { switch (mode) { @@ -86,7 +87,8 @@ std::string DebugDeferredBuffer::getCode(Modes mode) { const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode) { if (!_pipelines[mode]) { std::string fragmentShader = debug_deferred_buffer_frag; - fragmentShader.replace(fragmentShader.find(PLACEHOLDER), PLACEHOLDER.size(), getCode(mode)); + fragmentShader.replace(fragmentShader.find(COMPUTE_PLACEHOLDER), COMPUTE_PLACEHOLDER.size(), + getCode(mode)); auto vs = gpu::ShaderPointer(gpu::Shader::createVertex({ debug_deferred_buffer_vert })); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(fragmentShader)); @@ -122,7 +124,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); - batch.setPipeline(getPipeline(Modes(renderContext->_drawDebugDeferredBuffer - 1))); + batch.setPipeline(getPipeline(Modes(renderContext->_deferredDebugMode))); batch.setResourceTexture(Diffuse, framebufferCache->getDeferredColorTexture()); batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture()); @@ -130,9 +132,9 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture()); batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture()); - glm::vec4 color(0.0f, 0.0f, 1.0f, 1.0f); - glm::vec2 bottomLeft(0.0f, -1.0f); - glm::vec2 topRight(1.0f, 1.0f); + glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); + glm::vec2 bottomLeft(renderContext->_deferredDebugSize.x, renderContext->_deferredDebugSize.y); + glm::vec2 topRight(renderContext->_deferredDebugSize.z, renderContext->_deferredDebugSize.w); geometryBuffer->renderQuad(batch, bottomLeft, topRight, color); }); } \ No newline at end of file diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 1272e1a131..f04394750b 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -157,7 +157,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend } // Make sure we turn the deferred buffer debug on/off - setDrawDebugDeferredBuffer(renderContext->_drawDebugDeferredBuffer); + setDrawDebugDeferredBuffer(renderContext->_deferredDebugMode); // Make sure we turn the displayItemStatus on/off setDrawItemStatus(renderContext->_drawItemStatus); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 09a2761926..f128d186cc 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -100,7 +100,7 @@ public: void setDrawDebugDeferredBuffer(int draw) { if (_drawDebugDeferredBufferIndex >= 0) { - _jobs[_drawDebugDeferredBufferIndex].setEnabled(draw > 0); + _jobs[_drawDebugDeferredBufferIndex].setEnabled(draw >= 0); } } bool doDrawDebugDeferredBuffer() const { if (_drawDebugDeferredBufferIndex >= 0) { return _jobs[_drawDebugDeferredBufferIndex].isEnabled(); } else { return false; } } diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index 55632eb337..d8ff6e71a9 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -17,8 +17,10 @@ in vec2 uv; out vec4 outFragColor; +/*FUNCTIONS_PLACEHOLDER*/ + vec4 getFragmentColor() { - DEBUG_PLACEHOLDER + /*COMPUTE_PLACEHOLDER*/ } void main(void) { diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index ab56d68291..26bd6f2154 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -53,7 +53,8 @@ public: int _numDrawnOverlay3DItems = 0; int _maxDrawnOverlay3DItems = -1; - int _drawDebugDeferredBuffer = 0; + int _deferredDebugMode = -1; + glm::vec4 _deferredDebugSize { 0.0f, -1.0f, 1.0f, 1.0f }; int _drawItemStatus = 0; bool _drawHitEffect = false; diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 583f416576..78261dfdc7 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -107,8 +107,10 @@ public: Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _maxDrawnOverlay3DItems = count; } Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _maxDrawnOverlay3DItems; } - Q_INVOKABLE void setEngineDisplayDebugDeferredBuffer(int display) { _drawDebugDeferredBuffer = display; } - Q_INVOKABLE int doEngineDisplayDebugDeferredBuffer() { return _drawDebugDeferredBuffer; } + Q_INVOKABLE void setEngineDeferredDebugMode(int mode) { _deferredDebugMode = mode; } + Q_INVOKABLE int getEngineDeferredDebugMode() { return _deferredDebugMode; } + Q_INVOKABLE void setEngineDeferredDebugSize(glm::vec4 size) { _deferredDebugSize = size; } + Q_INVOKABLE glm::vec4 getEngineDeferredDebugSize() { return _deferredDebugSize; } Q_INVOKABLE void setEngineDisplayItemStatus(int display) { _drawItemStatus = display; } Q_INVOKABLE int doEngineDisplayItemStatus() { return _drawItemStatus; } @@ -146,7 +148,8 @@ protected: int _maxDrawnTransparentItems = -1; int _maxDrawnOverlay3DItems = -1; - int _drawDebugDeferredBuffer = 0; + int _deferredDebugMode = -1; + glm::vec4 _deferredDebugSize { 0.0f, -1.0f, 1.0f, 1.0f }; int _drawItemStatus = 0; bool _drawHitEffect = false; From 0603ead972cf4823d8a45bc32b1f0a39ac77bca1 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 4 Dec 2015 20:59:21 -0800 Subject: [PATCH 022/195] Have panels collapsed by default --- examples/utilities/tools/renderEngineDebug.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index c37c104498..60686912e8 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -156,3 +156,9 @@ function scriptEnding() { Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size } Script.scriptEnding.connect(scriptEnding); + + +// Collapse items +panel.mousePressEvent({ x: panel.x, y: panel.items["Overlays"].y}); +panel.mousePressEvent({ x: panel.x, y: panel.items["Transparents"].y}); +panel.mousePressEvent({ x: panel.x, y: panel.items["Opaques"].y}); From a018c51945dc527aa0a1a6ade4bf696a3d7336e9 Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Sun, 6 Dec 2015 23:51:29 -0800 Subject: [PATCH 023/195] Drawing background first in the Lighting buffer then lighting passes with stencil test --- .../src/DeferredLightingEffect.cpp | 46 +++++---------- .../render-utils/src/DeferredLightingEffect.h | 12 ---- .../render-utils/src/FramebufferCache.cpp | 1 + .../render-utils/src/RenderDeferredTask.cpp | 5 +- .../src/directional_ambient_light.slf | 1 - ...onal_ambient_light_cascaded_shadow_map.slf | 57 ------------------ .../directional_ambient_light_shadow_map.slf | 56 ------------------ .../directional_light_cascaded_shadow_map.slf | 59 ------------------- .../src/directional_light_shadow_map.slf | 58 ------------------ ...ional_skybox_light_cascaded_shadow_map.slf | 59 ------------------- .../directional_skybox_light_shadow_map.slf | 58 ------------------ 11 files changed, 18 insertions(+), 394 deletions(-) delete mode 100755 libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf delete mode 100755 libraries/render-utils/src/directional_ambient_light_shadow_map.slf delete mode 100644 libraries/render-utils/src/directional_light_cascaded_shadow_map.slf delete mode 100644 libraries/render-utils/src/directional_light_shadow_map.slf delete mode 100755 libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf delete mode 100755 libraries/render-utils/src/directional_skybox_light_shadow_map.slf diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 82cd0dc00f..af67f6b870 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -34,16 +34,8 @@ #include "deferred_light_spot_vert.h" #include "directional_light_frag.h" -#include "directional_light_shadow_map_frag.h" -#include "directional_light_cascaded_shadow_map_frag.h" - #include "directional_ambient_light_frag.h" -#include "directional_ambient_light_shadow_map_frag.h" -#include "directional_ambient_light_cascaded_shadow_map_frag.h" - #include "directional_skybox_light_frag.h" -#include "directional_skybox_light_shadow_map_frag.h" -#include "directional_skybox_light_cascaded_shadow_map_frag.h" #include "point_light_frag.h" #include "spot_light_frag.h" @@ -51,8 +43,6 @@ static const std::string glowIntensityShaderHandle = "glowIntensity"; struct LightLocations { - int shadowDistances; - int shadowScale; int radius; int ambientSphere; int lightBufferUnit; @@ -107,34 +97,16 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { _viewState = viewState; _directionalLightLocations = std::make_shared(); - _directionalLightShadowMapLocations = std::make_shared(); - _directionalLightCascadedShadowMapLocations = std::make_shared(); _directionalAmbientSphereLightLocations = std::make_shared(); - _directionalAmbientSphereLightShadowMapLocations = std::make_shared(); - _directionalAmbientSphereLightCascadedShadowMapLocations = std::make_shared(); _directionalSkyboxLightLocations = std::make_shared(); - _directionalSkyboxLightShadowMapLocations = std::make_shared(); - _directionalSkyboxLightCascadedShadowMapLocations = std::make_shared(); _pointLightLocations = std::make_shared(); _spotLightLocations = std::make_shared(); loadLightProgram(deferred_light_vert, directional_light_frag, false, _directionalLight, _directionalLightLocations); - loadLightProgram(deferred_light_vert, directional_light_shadow_map_frag, false, _directionalLightShadowMap, - _directionalLightShadowMapLocations); - loadLightProgram(deferred_light_vert, directional_light_cascaded_shadow_map_frag, false, _directionalLightCascadedShadowMap, - _directionalLightCascadedShadowMapLocations); loadLightProgram(deferred_light_vert, directional_ambient_light_frag, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations); - loadLightProgram(deferred_light_vert, directional_ambient_light_shadow_map_frag, false, _directionalAmbientSphereLightShadowMap, - _directionalAmbientSphereLightShadowMapLocations); - loadLightProgram(deferred_light_vert, directional_ambient_light_cascaded_shadow_map_frag, false, _directionalAmbientSphereLightCascadedShadowMap, - _directionalAmbientSphereLightCascadedShadowMapLocations); loadLightProgram(deferred_light_vert, directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations); - loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_map_frag, false, _directionalSkyboxLightShadowMap, - _directionalSkyboxLightShadowMapLocations); - loadLightProgram(deferred_light_vert, directional_skybox_light_cascaded_shadow_map_frag, false, _directionalSkyboxLightCascadedShadowMap, - _directionalSkyboxLightCascadedShadowMapLocations); loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations); @@ -379,6 +351,15 @@ void DeferredLightingEffect::prepare(RenderArgs* args) { batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); + // Clear Lighting buffer + auto lightingFbo = DependencyManager::get()->getLightingFramebuffer(); + + batch.setFramebuffer(lightingFbo); + batch.clearFramebuffer( + gpu::Framebuffer::BUFFER_COLOR0, + vec4(vec3(0), 0), 1.0, 0.0, true); + + // Clear deferred auto deferredFbo = DependencyManager::get()->getDeferredFramebuffer(); batch.setFramebuffer(deferredFbo); @@ -422,7 +403,7 @@ void DeferredLightingEffect::render(RenderArgs* args) { // Clearing it batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - batch.clearColorFramebuffer(lightingFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); + // batch.clearColorFramebuffer(lightingFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); // BInd the G-Buffer surfaces batch.setResourceTexture(0, framebufferCache->getDeferredColorTexture()); @@ -768,7 +749,6 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2)); 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 int LIGHT_GPU_SLOT = 3; slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); @@ -779,8 +759,6 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo gpu::Shader::makeProgram(*program, slotBindings); - locations->shadowDistances = program->getUniforms().findLocation("shadowDistances"); - locations->shadowScale = program->getUniforms().findLocation("shadowScale"); locations->radius = program->getUniforms().findLocation("radius"); locations->ambientSphere = program->getUniforms().findLocation("ambientSphere.L00"); @@ -793,6 +771,10 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo locations->deferredTransformBuffer = program->getBuffers().findLocation("deferredTransformBuffer"); auto state = std::make_shared(); + + // Stencil test all the light passes for objects pixels only, not the background + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); + if (lightVolume) { state->setCullMode(gpu::State::CULL_BACK); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 9c4809a82e..bf5db30310 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -106,24 +106,12 @@ private: gpu::PipelinePointer _directionalSkyboxLight; LightLocationsPtr _directionalSkyboxLightLocations; - gpu::PipelinePointer _directionalSkyboxLightShadowMap; - LightLocationsPtr _directionalSkyboxLightShadowMapLocations; - gpu::PipelinePointer _directionalSkyboxLightCascadedShadowMap; - LightLocationsPtr _directionalSkyboxLightCascadedShadowMapLocations; gpu::PipelinePointer _directionalAmbientSphereLight; LightLocationsPtr _directionalAmbientSphereLightLocations; - gpu::PipelinePointer _directionalAmbientSphereLightShadowMap; - LightLocationsPtr _directionalAmbientSphereLightShadowMapLocations; - gpu::PipelinePointer _directionalAmbientSphereLightCascadedShadowMap; - LightLocationsPtr _directionalAmbientSphereLightCascadedShadowMapLocations; gpu::PipelinePointer _directionalLight; LightLocationsPtr _directionalLightLocations; - gpu::PipelinePointer _directionalLightShadowMap; - LightLocationsPtr _directionalLightShadowMapLocations; - gpu::PipelinePointer _directionalLightCascadedShadowMap; - LightLocationsPtr _directionalLightCascadedShadowMapLocations; gpu::PipelinePointer _pointLight; LightLocationsPtr _pointLightLocations; diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index b39b8cc7e5..2d3884d81d 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -92,6 +92,7 @@ void FramebufferCache::createPrimaryFramebuffer() { // _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler)); _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _lightingFramebuffer->setRenderBuffer(0, _lightingTexture); + _lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); } gpu::FramebufferPointer FramebufferCache::getPrimaryFramebufferDepthColor() { diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 90805ca2f8..72ade5315a 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -355,7 +355,8 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const doInBatch(args->_context, [=](gpu::Batch& batch) { args->_batch = &batch; - auto deferredFboColorDepthStencil = DependencyManager::get()->getDeferredFramebufferDepthColor(); + // auto deferredFboColorDepthStencil = DependencyManager::get()->getDeferredFramebufferDepthColor(); + auto deferredFboColorDepthStencil = DependencyManager::get()->getLightingFramebuffer(); auto deferredFboFull = DependencyManager::get()->getDeferredFramebuffer(); batch.enableSkybox(true); @@ -375,7 +376,7 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const renderItems(sceneContext, renderContext, inItems); - batch.setFramebuffer(deferredFboFull); + // batch.setFramebuffer(deferredFboFull); }); args->_batch = nullptr; diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index 52ecc71a14..ae3b05862e 100755 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -27,7 +27,6 @@ void main(void) { DeferredTransform deferredTransform = getDeferredTransform(); DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); - // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, diff --git a/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf deleted file mode 100755 index 8b0212636e..0000000000 --- a/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf +++ /dev/null @@ -1,57 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// directional_light.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/3/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 -// - -// Everything about deferred buffer -<@include DeferredBuffer.slh@> - -<@include DeferredGlobalLight.slh@> - -<$declareEvalLightmappedColor()$> -<$declareEvalAmbientSphereGlobalColor()$> - -// Everything about shadow -<@include Shadow.slh@> - -in vec2 _texCoord0; -out vec4 _fragColor; - -void main(void) { - DeferredTransform deferredTransform = getDeferredTransform(); - DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); - - // Eval shadow Texcoord and then Attenuation - vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); - float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); - - // Light mapped or not ? - if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - vec3 color = evalLightmappedColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.normal, - frag.diffuse, - frag.specularVal.xyz); - _fragColor = vec4(color, 1.0); - } else { - vec3 color = evalAmbienSphereGlobalColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); - _fragColor = vec4(color, frag.normalVal.a); - } -} diff --git a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf deleted file mode 100755 index 97d69f2e63..0000000000 --- a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf +++ /dev/null @@ -1,56 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// directional_light.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/3/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 -// - -// Everything about deferred buffer -<@include DeferredBuffer.slh@> - -<@include DeferredGlobalLight.slh@> -<$declareEvalLightmappedColor()$> -<$declareEvalAmbientSphereGlobalColor()$> - -// Everything about shadow -<@include Shadow.slh@> - -in vec2 _texCoord0; -out vec4 _fragColor; - -void main(void) { - DeferredTransform deferredTransform = getDeferredTransform(); - DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); - - // Eval shadow Texcoord and then Attenuation - vec4 shadowTexcoord = evalShadowTexcoord(frag.position); - float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); - - // Light mapped or not ? - if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - vec3 color = evalLightmappedColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.normal, - frag.diffuse, - frag.specularVal.xyz); - _fragColor = vec4(color, 1.0); - } else { - vec3 color = evalAmbienSphereGlobalColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); - _fragColor = vec4(color, frag.normalVal.a); - } -} diff --git a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf deleted file mode 100644 index 4abe8e2e9d..0000000000 --- a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf +++ /dev/null @@ -1,59 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// directional_light.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/3/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 -// - -// Everything about deferred buffer -<@include DeferredBuffer.slh@> - -<@include DeferredGlobalLight.slh@> - -<$declareEvalLightmappedColor()$> -<$declareEvalAmbientGlobalColor()$> - -// Everything about shadow -<@include Shadow.slh@> - -in vec2 _texCoord0; -out vec4 _fragColor; - -void main(void) { - DeferredTransform deferredTransform = getDeferredTransform(); - DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); - - - // Eval shadow Texcoord and then Attenuation - vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); - float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); - - // Light mapped or not ? - if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - vec3 color = evalLightmappedColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.normal, - frag.diffuse, - frag.specularVal.xyz); - _fragColor = vec4(color, 1.0); - } else { - vec3 color = evalAmbienGlobalColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); - - _fragColor = vec4(color, frag.normalVal.a); - } -} diff --git a/libraries/render-utils/src/directional_light_shadow_map.slf b/libraries/render-utils/src/directional_light_shadow_map.slf deleted file mode 100644 index 4249b2787c..0000000000 --- a/libraries/render-utils/src/directional_light_shadow_map.slf +++ /dev/null @@ -1,58 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// directional_light.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/3/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 -// - -// Everything about deferred buffer -<@include DeferredBuffer.slh@> - -<@include DeferredGlobalLight.slh@> - -<$declareEvalLightmappedColor()$> -<$declareEvalAmbientGlobalColor()$> - -// Everything about shadow -<@include Shadow.slh@> - -in vec2 _texCoord0; -out vec4 _fragColor; - -void main(void) { - DeferredTransform deferredTransform = getDeferredTransform(); - DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); - - // Eval shadow Texcoord and then Attenuation - vec4 shadowTexcoord = evalShadowTexcoord(frag.position); - float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); - - // Light mapped or not ? - if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - vec3 color = evalLightmappedColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.normal, - frag.diffuse, - frag.specularVal.xyz); - _fragColor = vec4(color, 1.0); - } else { - vec3 color = evalAmbienGlobalColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); - - _fragColor = vec4(color, frag.normalVal.a); - } -} diff --git a/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf deleted file mode 100755 index 3c09bf62b6..0000000000 --- a/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf +++ /dev/null @@ -1,59 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// directional_light.frag -// fragment shader -// -// Created by Sam Gateau on 5/8/2015. -// 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 -// - -// Everything about deferred buffer -<@include DeferredBuffer.slh@> - -<@include DeferredGlobalLight.slh@> - -<$declareEvalLightmappedColor()$> -<$declareEvalSkyboxGlobalColor()$> - -// Everything about shadow -<@include Shadow.slh@> - -in vec2 _texCoord0; -out vec4 _fragColor; - -void main(void) { - DeferredTransform deferredTransform = getDeferredTransform(); - DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); - - // Eval shadow Texcoord and then Attenuation - vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); - float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); - - // Light mapped or not ? - if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - vec3 color = evalLightmappedColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.normal, - frag.diffuse, - frag.specularVal.xyz); - - _fragColor = vec4(color, 1.0); - } else { - vec3 color = evalSkyboxGlobalColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); - - _fragColor = vec4(color, frag.normalVal.a); - } -} diff --git a/libraries/render-utils/src/directional_skybox_light_shadow_map.slf b/libraries/render-utils/src/directional_skybox_light_shadow_map.slf deleted file mode 100755 index 6f709f31fa..0000000000 --- a/libraries/render-utils/src/directional_skybox_light_shadow_map.slf +++ /dev/null @@ -1,58 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// directional_light.frag -// fragment shader -// -// Created by Sam Gateau on 5/8/2015. -// 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 -// - -// Everything about deferred buffer -<@include DeferredBuffer.slh@> - -<@include DeferredGlobalLight.slh@> - -<$declareEvalLightmappedColor()$> -<$declareEvalSkyboxGlobalColor()$> - -// Everything about shadow -<@include Shadow.slh@> - -in vec2 _texCoord0; -out vec4 _fragColor; - -void main(void) { - DeferredTransform deferredTransform = getDeferredTransform(); - DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); - - // Eval shadow Texcoord and then Attenuation - vec4 shadowTexcoord = evalShadowTexcoord(frag.position); - float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); - - // Light mapped or not ? - if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - vec3 color = evalLightmappedColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.normal, - frag.diffuse, - frag.specularVal.xyz); - _fragColor = vec4(color, 1.0); - } else { - vec3 color = evalSkyboxGlobalColor( - deferredTransform.viewInverse, - shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); - - _fragColor = vec4(color, frag.normalVal.a); - } -} From 01d48b29aaf8ce8ab6558d7c5e8bf4b22ad0e631 Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Mon, 7 Dec 2015 01:03:14 -0800 Subject: [PATCH 024/195] cleaning code and removing cruft --- libraries/render-utils/src/DeferredLightingEffect.cpp | 6 +----- libraries/render-utils/src/RenderDeferredTask.cpp | 8 ++------ 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index af67f6b870..40f6d4c5eb 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -355,9 +355,7 @@ void DeferredLightingEffect::prepare(RenderArgs* args) { auto lightingFbo = DependencyManager::get()->getLightingFramebuffer(); batch.setFramebuffer(lightingFbo); - batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_COLOR0, - vec4(vec3(0), 0), 1.0, 0.0, true); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(vec3(0), 0), true); // Clear deferred auto deferredFbo = DependencyManager::get()->getDeferredFramebuffer(); @@ -400,10 +398,8 @@ void DeferredLightingEffect::render(RenderArgs* args) { auto lightingFBO = framebufferCache->getLightingFramebuffer(); batch.setFramebuffer(lightingFBO); - // Clearing it batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - // batch.clearColorFramebuffer(lightingFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); // BInd the G-Buffer surfaces batch.setResourceTexture(0, framebufferCache->getDeferredColorTexture()); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 72ade5315a..aeacc95f96 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -355,13 +355,11 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const doInBatch(args->_context, [=](gpu::Batch& batch) { args->_batch = &batch; - // auto deferredFboColorDepthStencil = DependencyManager::get()->getDeferredFramebufferDepthColor(); - auto deferredFboColorDepthStencil = DependencyManager::get()->getLightingFramebuffer(); - auto deferredFboFull = DependencyManager::get()->getDeferredFramebuffer(); + auto lightingFBO = DependencyManager::get()->getLightingFramebuffer(); batch.enableSkybox(true); - batch.setFramebuffer(deferredFboColorDepthStencil); + batch.setFramebuffer(lightingFBO); batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); @@ -376,8 +374,6 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const renderItems(sceneContext, renderContext, inItems); - // batch.setFramebuffer(deferredFboFull); - }); args->_batch = nullptr; } From 3595d0d719d22819b4361e8e1a5b75052d6c5ca4 Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Mon, 7 Dec 2015 01:15:10 -0800 Subject: [PATCH 025/195] less commented stuff --- libraries/model/src/model/Skybox.slf | 4 +--- libraries/render-utils/src/DeferredLightingEffect.cpp | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/libraries/model/src/model/Skybox.slf b/libraries/model/src/model/Skybox.slf index 9b642f138e..f8a568bcf9 100755 --- a/libraries/model/src/model/Skybox.slf +++ b/libraries/model/src/model/Skybox.slf @@ -52,9 +52,7 @@ void main(void) { } } - // vec3 pixel = pow(color, vec3(1.0/2.2)); // manual Gamma correction - vec3 pixel = color; - _fragColor = vec4(pixel, 0.0); + _fragColor = vec4(color, 0.0); #endif diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 40f6d4c5eb..92009ebf07 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -151,9 +151,6 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); gpu::Shader::makeProgram(*blitProgram); auto blitState = std::make_shared(); - /* blitState->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);*/ blitState->setColorWriteMask(true, true, true, true); _blitLightBuffer = gpu::PipelinePointer(gpu::Pipeline::create(blitProgram, blitState)); } @@ -347,7 +344,6 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu void DeferredLightingEffect::prepare(RenderArgs* args) { gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.enableStereo(false); - // batch.setStateScissorRect(args->_viewport); batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); From 7e59d5cc04af8e3f770f9c8fcd41c370015e1f50 Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Mon, 7 Dec 2015 01:27:50 -0800 Subject: [PATCH 026/195] Fixing the failing test for shader compilations (because we removed the shadowing shaders) --- tests/shaders/src/main.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/shaders/src/main.cpp b/tests/shaders/src/main.cpp index 52e43e2faa..40686f5639 100644 --- a/tests/shaders/src/main.cpp +++ b/tests/shaders/src/main.cpp @@ -35,16 +35,10 @@ #include "deferred_light_limited_vert.h" #include "directional_light_frag.h" -#include "directional_light_shadow_map_frag.h" -#include "directional_light_cascaded_shadow_map_frag.h" #include "directional_ambient_light_frag.h" -#include "directional_ambient_light_shadow_map_frag.h" -#include "directional_ambient_light_cascaded_shadow_map_frag.h" #include "directional_skybox_light_frag.h" -#include "directional_skybox_light_shadow_map_frag.h" -#include "directional_skybox_light_cascaded_shadow_map_frag.h" #include "point_light_frag.h" #include "spot_light_frag.h" @@ -185,14 +179,8 @@ void QTestWindow::draw() { testShaderBuild(simple_vert, simple_textured_frag); testShaderBuild(simple_vert, simple_textured_emisive_frag); testShaderBuild(deferred_light_vert, directional_light_frag); - testShaderBuild(deferred_light_vert, directional_light_shadow_map_frag); - testShaderBuild(deferred_light_vert, directional_light_cascaded_shadow_map_frag); testShaderBuild(deferred_light_vert, directional_ambient_light_frag); - testShaderBuild(deferred_light_vert, directional_ambient_light_shadow_map_frag); - testShaderBuild(deferred_light_vert, directional_ambient_light_cascaded_shadow_map_frag); testShaderBuild(deferred_light_vert, directional_skybox_light_frag); - testShaderBuild(deferred_light_vert, directional_skybox_light_shadow_map_frag); - testShaderBuild(deferred_light_vert, directional_skybox_light_cascaded_shadow_map_frag); testShaderBuild(deferred_light_limited_vert, point_light_frag); testShaderBuild(deferred_light_limited_vert, spot_light_frag); testShaderBuild(standardTransformPNTC_vert, standardDrawTexture_frag); From 5d207d0c9c82433995f3850327238978a7c26f29 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 7 Dec 2015 13:19:43 -0800 Subject: [PATCH 027/195] INtroducing the tonemapping job in its separate file and clean DeferredLightingEffect --- .../src/DeferredLightingEffect.cpp | 78 +------------- .../render-utils/src/DeferredLightingEffect.h | 8 +- .../render-utils/src/RenderDeferredTask.cpp | 87 +++++++++------ .../render-utils/src/RenderDeferredTask.h | 8 +- .../render-utils/src/ToneMappingEffect.cpp | 102 ++++++++++++++++++ .../render-utils/src/ToneMappingEffect.h | 46 ++++++++ 6 files changed, 209 insertions(+), 120 deletions(-) create mode 100644 libraries/render-utils/src/ToneMappingEffect.cpp create mode 100644 libraries/render-utils/src/ToneMappingEffect.h diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 92009ebf07..c8996801f1 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -82,7 +82,7 @@ gpu::PipelinePointer DeferredLightingEffect::getPipeline(SimpleProgramKey config return pipeline; } -void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { +void DeferredLightingEffect::init() { auto VS = gpu::Shader::createVertex(std::string(simple_vert)); auto PS = gpu::Shader::createPixel(std::string(simple_textured_frag)); auto PSEmissive = gpu::Shader::createPixel(std::string(simple_textured_emisive_frag)); @@ -95,7 +95,7 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { gpu::Shader::makeProgram(*_simpleShader, slotBindings); gpu::Shader::makeProgram(*_emissiveShader, slotBindings); - _viewState = viewState; + _directionalLightLocations = std::make_shared(); _directionalAmbientSphereLightLocations = std::make_shared(); _directionalSkyboxLightLocations = std::make_shared(); @@ -112,49 +112,6 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations); loadLightProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLight, _spotLightLocations); - { - //auto VSFS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); - //auto PSBlit = gpu::StandardShaderLib::getDrawTexturePS(); - const char BlitTextureGamma_frag[] = R"SCRIBE(#version 410 core - // Generated on Sat Oct 24 09:34:37 2015 - // - // Draw texture 0 fetched at texcoord.xy - // - // Created by Sam Gateau on 6/22/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 - // - - - uniform sampler2D colorMap; - - in vec2 varTexCoord0; - out vec4 outFragColor; - - void main(void) { - outFragColor = texture(colorMap, varTexCoord0); - // if (gl_FragCoord.x > 1000) { - // Manually gamma correct from Ligthing BUffer to color buffer - outFragColor.xyz = pow( outFragColor.xyz , vec3(1.0 / 2.2) ); - // } - } - - )SCRIBE"; - auto blitPS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(BlitTextureGamma_frag))); - - //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); - auto blitVS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); - auto blitProgram = gpu::ShaderPointer(gpu::Shader::createProgram(blitVS, blitPS)); - - //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); - gpu::Shader::makeProgram(*blitProgram); - auto blitState = std::make_shared(); - blitState->setColorWriteMask(true, true, true, true); - _blitLightBuffer = gpu::PipelinePointer(gpu::Pipeline::create(blitProgram, blitState)); - } - // Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light _globalLights.push_back(0); _allocatedLights.push_back(std::make_shared()); @@ -694,37 +651,6 @@ void DeferredLightingEffect::render(RenderArgs* args) { } -void DeferredLightingEffect::copyBack(RenderArgs* args) { - auto framebufferCache = DependencyManager::get(); - gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { - batch.enableStereo(false); - QSize framebufferSize = framebufferCache->getFrameBufferSize(); - - auto lightingBuffer = framebufferCache->getLightingTexture(); - auto destFbo = framebufferCache->getPrimaryFramebufferDepthColor(); - batch.setFramebuffer(destFbo); - batch.setViewportTransform(args->_viewport); - batch.setProjectionTransform(glm::mat4()); - batch.setViewTransform(Transform()); - { - float sMin = args->_viewport.x / (float)framebufferSize.width(); - float sWidth = args->_viewport.z / (float)framebufferSize.width(); - float tMin = args->_viewport.y / (float)framebufferSize.height(); - float tHeight = args->_viewport.w / (float)framebufferSize.height(); - Transform model; - batch.setPipeline(_blitLightBuffer); - model.setTranslation(glm::vec3(sMin, tMin, 0.0)); - model.setScale(glm::vec3(sWidth, tHeight, 1.0)); - batch.setModelTransform(model); - } - - batch.setResourceTexture(0, lightingBuffer); - batch.draw(gpu::TRIANGLE_STRIP, 4); - - args->_context->render(batch); - }); -} - void DeferredLightingEffect::setupTransparent(RenderArgs* args, int lightBufferUnit) { auto globalLight = _allocatedLights[_globalLights.front()]; args->_batch->setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer()); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index bf5db30310..efb84f2101 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -21,7 +21,6 @@ #include "model/Stage.h" #include "model/Geometry.h" -class AbstractViewStateInterface; class RenderArgs; class SimpleProgramKey; struct LightLocations; @@ -78,7 +77,6 @@ public: void prepare(RenderArgs* args); void render(RenderArgs* args); - void copyBack(RenderArgs* args); void setupTransparent(RenderArgs* args, int lightBufferUnit); @@ -101,9 +99,7 @@ private: gpu::ShaderPointer _simpleShader; gpu::ShaderPointer _emissiveShader; QHash _simplePrograms; - - gpu::PipelinePointer _blitLightBuffer; - + gpu::PipelinePointer _directionalSkyboxLight; LightLocationsPtr _directionalSkyboxLightLocations; @@ -143,8 +139,6 @@ private: std::vector _globalLights; std::vector _pointLights; std::vector _spotLights; - - AbstractViewStateInterface* _viewState; int _ambientLightMode = 0; model::AtmospherePointer _atmosphere; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index aeacc95f96..c8eefe65ac 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -44,67 +44,85 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo DependencyManager::get()->render(renderContext->args); } -void ResolveDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - PerformanceTimer perfTimer("ResolveDeferred"); - DependencyManager::get()->copyBack(renderContext->args); +void ToneMappingDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer("ToneMappingDeferred"); + _toneMappingEffect.render(renderContext->args); } RenderDeferredTask::RenderDeferredTask() : Task() { - _jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred"))); + // CPU only, create the list of renderedOpaques items _jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque", FetchItems( - [] (const RenderContextPointer& context, int count) { - context->_numFeedOpaqueItems = count; - } + [](const RenderContextPointer& context, int count) { + context->_numFeedOpaqueItems = count; + } ) - ))); + ))); _jobs.push_back(Job(new CullItemsOpaque::JobModel("CullOpaque", _jobs.back().getOutput()))); _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()))); + // CPU only, create the list of renderedTransparents items + _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", + FetchItems( + ItemFilter::Builder::transparentShape().withoutLayered(), + [](const RenderContextPointer& context, int count) { + context->_numFeedTransparentItems = count; + } + ) + ))); + _jobs.push_back(Job(new CullItemsTransparent::JobModel("CullTransparent", _jobs.back().getOutput()))); + _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)))); + auto& renderedTransparents = _jobs.back().getOutput(); + + // GPU Jobs: Start preparing the deferred and lighting buffer + _jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred"))); + + // Render opaque objects in DeferredBuffer + _jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", renderedOpaques))); + + // Once opaque is all rendered create stencil background _jobs.push_back(Job(new DrawStencilDeferred::JobModel("DrawOpaqueStencil"))); + + // Use Stencil and start drawing background in Lighting buffer _jobs.push_back(Job(new DrawBackgroundDeferred::JobModel("DrawBackgroundDeferred"))); + // Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now. _jobs.push_back(Job(new DrawLight::JobModel("DrawLight"))); - _jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred"))); - _jobs.push_back(Job(new ResolveDeferred::JobModel("ResolveDeferred"))); - _jobs.push_back(Job(new AmbientOcclusion::JobModel("AmbientOcclusion"))); + // DeferredBuffer is complete, now let's shade it into the LightingBuffer + _jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred"))); + + // AO job, to be revisited + _jobs.push_back(Job(new AmbientOcclusion::JobModel("AmbientOcclusion"))); _jobs.back().setEnabled(false); _occlusionJobIndex = _jobs.size() - 1; + // AA job to be revisited _jobs.push_back(Job(new Antialiasing::JobModel("Antialiasing"))); - _jobs.back().setEnabled(false); _antialiasingJobIndex = _jobs.size() - 1; - _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", - FetchItems( - ItemFilter::Builder::transparentShape().withoutLayered(), - [] (const RenderContextPointer& context, int count) { - context->_numFeedTransparentItems = count; - } - ) - ))); - _jobs.push_back(Job(new CullItemsTransparent::JobModel("CullTransparent", _jobs.back().getOutput()))); - - - _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)))); - _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput()))); + // Render transparent objects forward in LigthingBuffer + _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", renderedTransparents))); + // Lighting Buffer ready for tone mapping + _jobs.push_back(Job(new ToneMappingDeferred::JobModel("ToneMapping"))); + + // Debugging Deferred buffer job _jobs.push_back(Job(new DebugDeferredBuffer::JobModel("DebugDeferredBuffer"))); _jobs.back().setEnabled(false); _drawDebugDeferredBufferIndex = _jobs.size() - 1; - - // Grab a texture map representing the different status icons and assign that to the drawStatsuJob - auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; - auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath); - _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques, DrawStatus(statusIconMap)))); - - _jobs.back().setEnabled(false); - _drawStatusJobIndex = _jobs.size() - 1; + // Status icon rendering job + { + // Grab a texture map representing the different status icons and assign that to the drawStatsuJob + auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; + auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath); + _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques, DrawStatus(statusIconMap)))); + _jobs.back().setEnabled(false); + _drawStatusJobIndex = _jobs.size() - 1; + } _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); @@ -112,7 +130,6 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.back().setEnabled(false); _drawHitEffectJobIndex = _jobs.size() -1; - // Give ourselves 3 frmaes of timer queries _timerQueries.push_back(std::make_shared()); _timerQueries.push_back(std::make_shared()); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index f128d186cc..009e6f23b2 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -16,6 +16,8 @@ #include "gpu/Pipeline.h" +#include "ToneMappingEffect.h" + class SetupDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); @@ -38,11 +40,13 @@ public: typedef render::Job::Model JobModel; }; -class ResolveDeferred { +class ToneMappingDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; + ToneMappingEffect _toneMappingEffect; + + typedef render::Job::Model JobModel; }; class DrawOpaqueDeferred { diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp new file mode 100644 index 0000000000..ac5bbc69e5 --- /dev/null +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -0,0 +1,102 @@ +// +// ToneMappingEffect.cpp +// libraries/render-utils/src +// +// Created by Sam Gateau on 12/7/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 +// + +#include "ToneMappingEffect.h" + +#include +#include + +#include + +#include "FramebufferCache.h" + + +ToneMappingEffect::ToneMappingEffect() { + +} + +void ToneMappingEffect::init() { + //auto VSFS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + //auto PSBlit = gpu::StandardShaderLib::getDrawTexturePS(); + const char BlitTextureGamma_frag[] = R"SCRIBE(#version 410 core + // Generated on Sat Oct 24 09:34:37 2015 + // + // Draw texture 0 fetched at texcoord.xy + // + // Created by Sam Gateau on 6/22/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 + // + + + uniform sampler2D colorMap; + + in vec2 varTexCoord0; + out vec4 outFragColor; + + void main(void) { + outFragColor = texture(colorMap, varTexCoord0); + // if (gl_FragCoord.x > 1000) { + // Manually gamma correct from Ligthing BUffer to color buffer + outFragColor.xyz = pow( outFragColor.xyz , vec3(1.0 / 2.2) ); + // } + } + + )SCRIBE"; + auto blitPS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(BlitTextureGamma_frag))); + + //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); + auto blitVS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + auto blitProgram = gpu::ShaderPointer(gpu::Shader::createProgram(blitVS, blitPS)); + + //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); + gpu::Shader::makeProgram(*blitProgram); + auto blitState = std::make_shared(); + blitState->setColorWriteMask(true, true, true, true); + _blitLightBuffer = gpu::PipelinePointer(gpu::Pipeline::create(blitProgram, blitState)); +} + + +void ToneMappingEffect::render(RenderArgs* args) { + if (!_blitLightBuffer) { + init(); + } + auto framebufferCache = DependencyManager::get(); + gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { + batch.enableStereo(false); + QSize framebufferSize = framebufferCache->getFrameBufferSize(); + + auto lightingBuffer = framebufferCache->getLightingTexture(); + auto destFbo = framebufferCache->getPrimaryFramebufferDepthColor(); + batch.setFramebuffer(destFbo); + batch.setViewportTransform(args->_viewport); + batch.setProjectionTransform(glm::mat4()); + batch.setViewTransform(Transform()); + { + float sMin = args->_viewport.x / (float)framebufferSize.width(); + float sWidth = args->_viewport.z / (float)framebufferSize.width(); + float tMin = args->_viewport.y / (float)framebufferSize.height(); + float tHeight = args->_viewport.w / (float)framebufferSize.height(); + Transform model; + batch.setPipeline(_blitLightBuffer); + model.setTranslation(glm::vec3(sMin, tMin, 0.0)); + model.setScale(glm::vec3(sWidth, tHeight, 1.0)); + batch.setModelTransform(model); + } + + batch.setResourceTexture(0, lightingBuffer); + batch.draw(gpu::TRIANGLE_STRIP, 4); + + args->_context->render(batch); + }); +} \ No newline at end of file diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h new file mode 100644 index 0000000000..9b07c0f7df --- /dev/null +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -0,0 +1,46 @@ +// +// ToneMappingEffect.h +// libraries/render-utils/src +// +// Created by Sam Gateau on 12/7/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 +// + +#ifndef hifi_ToneMappingEffect_h +#define hifi_ToneMappingEffect_h + +#include +#include + +#include +#include + +class RenderArgs; + +class ToneMappingEffect { +public: + ToneMappingEffect(); + virtual ~ToneMappingEffect() {} + + void render(RenderArgs* args); + +private: + + gpu::PipelinePointer _blitLightBuffer; + + // Class describing the uniform buffer with all the parameters common to the tone mapping shaders + class Parameters { + public: + + Parameters() {} + }; + typedef gpu::BufferView UniformBufferView; + gpu::BufferView _parametersBuffer; + + void init(); +}; + +#endif // hifi_ToneMappingEffect_h From 9ddc3c27bf7e35ad4f963f949741415ce682bacd Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 7 Dec 2015 13:25:55 -0800 Subject: [PATCH 028/195] compilation errors fixed --- interface/src/Application.cpp | 2 +- libraries/render-utils/src/DeferredLightingEffect.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 78724862de..99519256bf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2499,7 +2499,7 @@ void Application::init() { _environment.init(); - DependencyManager::get()->init(this); + DependencyManager::get()->init(); DependencyManager::get()->init(); _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index efb84f2101..78b8e924ae 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -33,7 +33,7 @@ public: static const int NORMAL_FITTING_MAP_SLOT = 10; static const int DEFERRED_TRANSFORM_BUFFER_SLOT = 2; - void init(AbstractViewStateInterface* viewState); + void init(); /// Sets up the state necessary to render static untextured geometry with the simple program. gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true, From 9faec326da023116577a45ef0a3792bb2894c875 Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Tue, 8 Dec 2015 08:34:42 -0800 Subject: [PATCH 029/195] CHanging the lighting BUffer format and adding tone mapping --- libraries/gpu/src/gpu/Format.h | 3 + libraries/gpu/src/gpu/GLBackendTexture.cpp | 58 +++++++++++++++++++ libraries/gpu/src/gpu/Texture.h | 2 +- .../input-plugins/ViveControllerManager.cpp | 4 +- .../src/model-networking/TextureCache.cpp | 18 +++--- libraries/model/src/model/TextureMap.cpp | 42 +++++++------- .../src/procedural/ProceduralSkybox.slf | 4 +- .../render-utils/src/DeferredBufferWrite.slh | 2 +- .../src/DeferredLightingEffect.cpp | 1 + .../render-utils/src/FramebufferCache.cpp | 6 +- .../render-utils/src/SkyFromAtmosphere.slf | 3 +- .../render-utils/src/ToneMappingEffect.cpp | 14 ++++- libraries/render-utils/src/text/Font.cpp | 8 +-- libraries/script-engine/src/ScriptEngine.cpp | 2 +- 14 files changed, 120 insertions(+), 47 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 3022f47b51..41a95e2578 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -160,6 +160,7 @@ enum Semantic { RGB, RGBA, BGRA, + XY, XYZ, XYZW, @@ -176,6 +177,8 @@ enum Semantic { SRGBA, SBGRA, + R11G11B10, + UNIFORM, UNIFORM_BUFFER, SAMPLER, diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 71c5a83331..dbf29d6ab3 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -224,6 +224,11 @@ public: case gpu::SRGBA: texel.internalFormat = GL_SRGB; // standard 2.2 gamma correction color break; + case gpu::R11G11B10: { + // the type should be float + texel.internalFormat = GL_R11F_G11F_B10F; + break; + } default: qCDebug(gpulogging) << "Unknown combination of texel format"; } @@ -240,6 +245,59 @@ public: break; case gpu::RGBA: texel.internalFormat = GL_RGBA; + switch (dstFormat.getType()) { + case gpu::UINT32: + texel.format = GL_RGBA_INTEGER; + texel.internalFormat = GL_RGBA32UI; + break; + case gpu::INT32: + texel.format = GL_RGBA_INTEGER; + texel.internalFormat = GL_RGBA32I; + break; + case gpu::FLOAT: + texel.internalFormat = GL_RGBA32F; + break; + case gpu::UINT16: + texel.format = GL_RGBA_INTEGER; + texel.internalFormat = GL_RGBA16UI; + break; + case gpu::INT16: + texel.format = GL_RGBA_INTEGER; + texel.internalFormat = GL_RGBA16I; + break; + case gpu::NUINT16: + texel.format = GL_RGBA; + texel.internalFormat = GL_RGBA16; + break; + case gpu::NINT16: + texel.format = GL_RGBA; + texel.internalFormat = GL_RGBA16_SNORM; + break; + case gpu::HALF: + texel.format = GL_RGBA; + texel.internalFormat = GL_RGBA16F; + break; + case gpu::UINT8: + texel.format = GL_RGBA_INTEGER; + texel.internalFormat = GL_RGBA8UI; + break; + case gpu::INT8: + texel.format = GL_RGBA_INTEGER; + texel.internalFormat = GL_RGBA8I; + break; + case gpu::NUINT8: + texel.format = GL_RGBA; + texel.internalFormat = GL_RGBA8; + break; + case gpu::NINT8: + texel.format = GL_RGBA; + texel.internalFormat = GL_RGBA8_SNORM; + break; + case gpu::NUINT32: + case gpu::NINT32: + case gpu::NUM_TYPES: // quiet compiler + Q_UNREACHABLE(); + } break; case gpu::SRGB: texel.internalFormat = GL_SRGB; diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index c3e2809c4b..6e8eb10380 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -407,7 +407,7 @@ public: TexturePointer _texture = TexturePointer(NULL); uint16 _subresource = 0; - Element _element = Element(gpu::VEC4, gpu::UINT8, gpu::RGBA); + Element _element = Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); TextureView() {}; diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp index b315a7a3d9..c26e6e6bf9 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp @@ -104,8 +104,8 @@ void ViveControllerManager::activate() { // sizeof(vr::RenderModel_Vertex_t), // gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::RAW))); - gpu::Element formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA); - gpu::Element formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA); + gpu::Element formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + gpu::Element formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); _texture = gpu::TexturePointer( gpu::Texture::create2D(formatGPU, model.diffuseTexture.unWidth, model.diffuseTexture.unHeight, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 3e80b6c7aa..ae705faf86 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -85,7 +85,7 @@ const gpu::TexturePointer& TextureCache::getPermutationNormalTexture() { data[i + 2] = ((randvec.z + 1.0f) / 2.0f) * 255.0f; } - _permutationNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB), 256, 2)); + _permutationNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB), 256, 2)); _permutationNormalTexture->assignStoredMip(0, _blueTexture->getTexelFormat(), sizeof(data), data); } return _permutationNormalTexture; @@ -98,7 +98,7 @@ const unsigned char OPAQUE_BLACK[] = { 0x00, 0x00, 0x00, 0xFF }; const gpu::TexturePointer& TextureCache::getWhiteTexture() { if (!_whiteTexture) { - _whiteTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA), 1, 1)); + _whiteTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, 1, 1)); _whiteTexture->assignStoredMip(0, _whiteTexture->getTexelFormat(), sizeof(OPAQUE_WHITE), OPAQUE_WHITE); } return _whiteTexture; @@ -106,7 +106,7 @@ const gpu::TexturePointer& TextureCache::getWhiteTexture() { const gpu::TexturePointer& TextureCache::getGrayTexture() { if (!_grayTexture) { - _grayTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA), 1, 1)); + _grayTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, 1, 1)); _grayTexture->assignStoredMip(0, _whiteTexture->getTexelFormat(), sizeof(OPAQUE_WHITE), OPAQUE_GRAY); } return _grayTexture; @@ -114,7 +114,7 @@ const gpu::TexturePointer& TextureCache::getGrayTexture() { const gpu::TexturePointer& TextureCache::getBlueTexture() { if (!_blueTexture) { - _blueTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA), 1, 1)); + _blueTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, 1, 1)); _blueTexture->assignStoredMip(0, _blueTexture->getTexelFormat(), sizeof(OPAQUE_BLUE), OPAQUE_BLUE); } return _blueTexture; @@ -122,7 +122,7 @@ const gpu::TexturePointer& TextureCache::getBlueTexture() { const gpu::TexturePointer& TextureCache::getBlackTexture() { if (!_blackTexture) { - _blackTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA), 1, 1)); + _blackTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, 1, 1)); _blackTexture->assignStoredMip(0, _whiteTexture->getTexelFormat(), sizeof(OPAQUE_BLACK), OPAQUE_BLACK); } return _blackTexture; @@ -151,11 +151,11 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type /// Returns a texture version of an image file gpu::TexturePointer TextureCache::getImageTexture(const QString& path) { QImage image = QImage(path).mirrored(false, true); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA); - formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, gpu::BGRA); + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::BGRA); } gpu::TexturePointer texture = gpu::TexturePointer( gpu::Texture::create2D(formatGPU, image.width(), image.height(), diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 453bb17a4b..a86c7cdbec 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -121,11 +121,11 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); } @@ -156,11 +156,11 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src bool isLinearRGB = true; - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); } theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -246,11 +246,11 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); } @@ -368,11 +368,11 @@ gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, c // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); } @@ -589,13 +589,13 @@ gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImag if ((image.width() > 0) && (image.height() > 0)) { // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); + bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); } diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.slf b/libraries/procedural/src/procedural/ProceduralSkybox.slf index 382801f52d..8705278bee 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.slf +++ b/libraries/procedural/src/procedural/ProceduralSkybox.slf @@ -42,8 +42,8 @@ void main(void) { vec3 coord = normalize(_normal); vec3 texel = texture(cubeMap, coord).rgb; vec3 color = texel * _skybox._color.rgb; - vec3 pixel = pow(color, vec3(1.0/2.2)); // manual Gamma correction - _fragColor = vec4(pixel, 0.0); + // vec3 pixel = pow(color, vec3(1.0/2.2)); // manual Gamma correction + _fragColor = vec4(color, 0.0); #endif diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 573146a0af..d3a5ff1e31 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -62,7 +62,7 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 s } _fragColor0 = vec4(diffuse.rgb, 0.5); - _fragColor1 = vec4(bestFitNormal(normal), 1.0); + _fragColor1 = vec4(bestFitNormal(normal), 0.5); _fragColor2 = vec4(emissive, shininess / 128.0); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index c8996801f1..f1469a2a03 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -689,6 +689,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo locations->deferredTransformBuffer = program->getBuffers().findLocation("deferredTransformBuffer"); auto state = std::make_shared(); + state->setColorWriteMask(true, true, true, false); // Stencil test all the light passes for objects pixels only, not the background state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index 2d3884d81d..83ba8b6950 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -53,7 +53,7 @@ void FramebufferCache::createPrimaryFramebuffer() { _deferredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _deferredFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create()); - auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto colorFormat = gpu::Element::COLOR_RGBA_32; auto width = _frameBufferSize.width(); auto height = _frameBufferSize.height(); @@ -87,8 +87,8 @@ void FramebufferCache::createPrimaryFramebuffer() { auto tex = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width * 0.5, height * 0.5, defaultSampler)); _selfieFramebuffer->setRenderBuffer(0, tex); - _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), width, height, defaultSampler)); - //_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::SRGBA), width, height, defaultSampler)); + //_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, defaultSampler)); + _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::R11G11B10), width, height, defaultSampler)); // _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler)); _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _lightingFramebuffer->setRenderBuffer(0, _lightingTexture); diff --git a/libraries/render-utils/src/SkyFromAtmosphere.slf b/libraries/render-utils/src/SkyFromAtmosphere.slf index c2a3635f07..10b39dc210 100755 --- a/libraries/render-utils/src/SkyFromAtmosphere.slf +++ b/libraries/render-utils/src/SkyFromAtmosphere.slf @@ -108,5 +108,6 @@ void main (void) vec3 finalColor = frontColor.rgb + fMiePhase * secondaryFrontColor.rgb; outFragColor.a = finalColor.b; - outFragColor.rgb = pow(finalColor.rgb, vec3(1.0/2.2)); + // outFragColor.rgb = pow(finalColor.rgb, vec3(1.0/2.2)); + outFragColor.rgb = finalColor.rgb; } diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index ac5bbc69e5..ea38884fac 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -45,10 +45,20 @@ void ToneMappingEffect::init() { out vec4 outFragColor; void main(void) { - outFragColor = texture(colorMap, varTexCoord0); + vec4 fragColor = texture(colorMap, varTexCoord0); // if (gl_FragCoord.x > 1000) { // Manually gamma correct from Ligthing BUffer to color buffer - outFragColor.xyz = pow( outFragColor.xyz , vec3(1.0 / 2.2) ); + // outFragColor.xyz = pow( fragColor.xyz , vec3(1.0 / 2.2) ); + + fragColor *= 4.0; // Hardcoded Exposure Adjustment + vec3 x = max(vec3(0.0),fragColor.xyz-0.004); + vec3 retColor = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06); + + // fragColor *= 8; // Hardcoded Exposure Adjustment + // fragColor = fragColor/(1.0+fragColor); + // vec3 retColor = pow(fragColor.xyz,vec3(1/2.2)); + + outFragColor = vec4(retColor, 1.0); // } } diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index 5587185ead..43202c29c2 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -198,11 +198,11 @@ void Font::read(QIODevice& in) { image = image.convertToFormat(QImage::Format_RGBA8888); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA); - formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, gpu::BGRA); + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::BGRA); } _texture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_POINT_MAG_LINEAR))); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 73c4b7e22b..d0cdbc48bf 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -82,7 +82,7 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) { } Q_DECLARE_METATYPE(controller::InputController*) -static int inputControllerPointerId = qRegisterMetaType(); +//static int inputControllerPointerId = qRegisterMetaType(); QScriptValue inputControllerToScriptValue(QScriptEngine *engine, controller::InputController* const &in) { return engine->newQObject(in); From 4a18b5ffe4f31d0a7671651f1ab620ed210cc406 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 8 Dec 2015 20:29:18 +0100 Subject: [PATCH 030/195] small update to have the bow shoot arrows with the creatorSessionUUID in the userData --- examples/toybox/bow/bow.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/toybox/bow/bow.js b/examples/toybox/bow/bow.js index 90199fb70f..1ea3e39b02 100644 --- a/examples/toybox/bow/bow.js +++ b/examples/toybox/bow/bow.js @@ -259,9 +259,9 @@ userData: JSON.stringify({ grabbableKey: { grabbable: false - } + }, + creatorSessionUUID: MyAvatar.sessionUUID }) - }); var makeArrowStick = function(entityA, entityB, collision) { From 2fb318cc5366afe54e8794f33094e5bca6d84969 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 8 Dec 2015 17:52:23 -0800 Subject: [PATCH 031/195] work with clements branch --- examples/controllers/handControllerGrab.js | 161 +++++++++++++++++++-- 1 file changed, 149 insertions(+), 12 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 138240f5d6..20ca3811c0 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -251,9 +251,10 @@ function MyController(hand) { this.triggerValue = 0; // rolling average of trigger value this.rawTriggerValue = 0; this.rawBumperValue = 0; - + this.overlayLine = null; - + this.particleBeam = null; + this.offsetPosition = Vec3.ZERO; this.offsetRotation = Quat.IDENTITY; @@ -398,6 +399,119 @@ function MyController(hand) { } }; + + //test particles instead of overlays + + + this.handleParticleBeam = function(position, orientation) { + + var rotation = Quat.angleAxis(0, { + x: 1, + y: 0, + z: 0 + }); + + var finalRotation = Quat.multiply(orientation, rotation); + + + if (this.particleBeam === null) { + print('create beam') + this.createParticleBeam(position, finalRotation) + } else { + print('update beam') + this.updateParticleBeam(position, finalRotation) + } + } + + this.createParticleBeam = function(position, orientation) { + var particleBeamProperties = { + type: "ParticleEffect", + isEmitting: true, + position: position, + //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), + "name": "Particle Beam", + "color": { + "red": 110, + "green": 118.52941176470593, + "blue": 255 + }, + "maxParticles": 1000, + "lifespan": 3, + "emitRate": 20, + "emitSpeed": 10, + "speedSpread": 0, + "emitOrientation": { + "x": -0.7000000000000001, + "y": 0, + "z": 0, + "w": 0.7071068286895752 + }, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "emitRadiusStart": 0.5, + "polarStart": 0, + "polarFinish": 0, + "azimuthStart": -3.1415927410125732, + "azimuthFinish": 3.1415927410125732, + "emitAcceleration": { + x: 0, + y: 0, + z: 0 + }, + "accelerationSpread": { + "x": 0, + "y": 0, + "z": 0 + }, + "particleRadius": 0.02, + "radiusSpread": 0, + "radiusStart": 0.01, + "radiusFinish": 0.01, + "colorSpread": { + "red": 0, + "green": 0, + "blue": 0 + }, + "colorStart": { + "red": 110, + "green": 118.52941176470593, + "blue": 255 + }, + "colorFinish": { + "red": 110, + "green": 118.52941176470593, + "blue": 255 + }, + "alpha": 1, + "alphaSpread": 0, + "alphaStart": 1, + "alphaFinish": 1, + "additiveBlending": 0, + "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png" + } + + this.particleBeam = Entities.addEntity(particleBeamProperties); + } + + this.updateParticleBeam = function(position, orientation, acceleration) { + print('O IN UPDATE:::' + JSON.stringify(orientation)) + + // var beamProps = Entities.getEntityProperties(this.particleBeam); + + Entities.editEntity(this.particleBeam, { + //rotation:rotation, + rotation: orientation, + position: position, + + }) + + // var emitO = Entities.getEntityProperties(this.particleBeam, "emitOrientation").emitOrientation; + // print('EMIT o :::' + JSON.stringify(emitO)); + } + this.lineOff = function() { if (this.pointer !== null) { Entities.deleteEntity(this.pointer); @@ -412,6 +526,14 @@ function MyController(hand) { this.overlayLine = null; }; + this.particleBeamOff = function() { + if (this.particleBeam !== null) { + Entities.deleteEntity(this.particleBeam) + } + + this.particleBeam = null; + } + this.triggerPress = function(value) { _this.rawTriggerValue = value; }; @@ -662,6 +784,9 @@ function MyController(hand) { //this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR); + this.handleParticleBeam(distantPickRay.origin, this.getHandRotation()); + + }; this.distanceHolding = function() { @@ -715,6 +840,7 @@ function MyController(hand) { this.currentAvatarOrientation = MyAvatar.orientation; this.overlayLineOff(); + this.particleBeamOff(); }; this.continueDistanceHolding = function() { @@ -808,8 +934,16 @@ function MyController(hand) { // mix in head motion if (MOVE_WITH_HEAD) { var objDistance = Vec3.length(objectToAvatar); - var before = Vec3.multiplyQbyV(this.currentCameraOrientation, { x: 0.0, y: 0.0, z: objDistance }); - var after = Vec3.multiplyQbyV(Camera.orientation, { x: 0.0, y: 0.0, z: objDistance }); + var before = Vec3.multiplyQbyV(this.currentCameraOrientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); + var after = Vec3.multiplyQbyV(Camera.orientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); var change = Vec3.subtract(before, after); this.currentCameraOrientation = Camera.orientation; this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change); @@ -837,6 +971,7 @@ function MyController(hand) { this.lineOff(); this.overlayLineOff(); + this.particleBeamOff(); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); this.activateEntity(this.grabbedEntity, grabbedProperties); @@ -975,6 +1110,7 @@ function MyController(hand) { this.pullTowardEquipPosition = function() { this.lineOff(); this.overlayLineOff(); + this.particleBeamOff(); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); @@ -1164,6 +1300,7 @@ function MyController(hand) { this.lineOff(); this.overlayLineOff(); + this.particleBeamOff(); if (this.grabbedEntity !== null) { if (this.actionID !== null) { Entities.deleteAction(this.grabbedEntity, this.actionID); @@ -1285,10 +1422,10 @@ Controller.enableMapping(MAPPING_NAME); var handToDisable = 'none'; function update() { - if (handToDisable !== LEFT_HAND && handToDisable!=='both') { + if (handToDisable !== LEFT_HAND && handToDisable !== 'both') { leftController.update(); } - if (handToDisable !== RIGHT_HAND && handToDisable!=='both') { + if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') { rightController.update(); } } @@ -1296,7 +1433,7 @@ function update() { Messages.subscribe('Hifi-Hand-Disabler'); handleHandDisablerMessages = function(channel, message, sender) { - + if (sender === MyAvatar.sessionUUID) { if (message === 'left') { handToDisable = LEFT_HAND; @@ -1304,11 +1441,11 @@ handleHandDisablerMessages = function(channel, message, sender) { if (message === 'right') { handToDisable = RIGHT_HAND; } - if(message==='both'){ - handToDisable='both'; + if (message === 'both') { + handToDisable = 'both'; } - if(message==='none'){ - handToDisable='none'; + if (message === 'none') { + handToDisable = 'none'; } } @@ -1323,4 +1460,4 @@ function cleanup() { } Script.scriptEnding.connect(cleanup); -Script.update.connect(update); +Script.update.connect(update); \ No newline at end of file From 1134d12ea0e9f92de38646e6d45c45e91f86bac3 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 9 Dec 2015 16:08:32 -0800 Subject: [PATCH 032/195] particles --- examples/controllers/handControllerGrab.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 20ca3811c0..b2af86c479 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -399,10 +399,7 @@ function MyController(hand) { } }; - //test particles instead of overlays - - this.handleParticleBeam = function(position, orientation) { var rotation = Quat.angleAxis(0, { @@ -435,11 +432,11 @@ function MyController(hand) { "green": 118.52941176470593, "blue": 255 }, - "maxParticles": 1000, + "maxParticles": 2000, "lifespan": 3, - "emitRate": 20, - "emitSpeed": 10, - "speedSpread": 0, + "emitRate": 50, + "emitSpeed": 2, + "speedSpread": 0.1, "emitOrientation": { "x": -0.7000000000000001, "y": 0, From 31526091d323a5ed8ad5038fa533697a6ac257bf Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 11:13:35 -0800 Subject: [PATCH 033/195] create beams at start --- examples/controllers/handControllerGrab.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index b2af86c479..4348722df0 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -425,6 +425,7 @@ function MyController(hand) { type: "ParticleEffect", isEmitting: true, position: position, + visible: false, //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), "name": "Particle Beam", "color": { @@ -436,12 +437,12 @@ function MyController(hand) { "lifespan": 3, "emitRate": 50, "emitSpeed": 2, - "speedSpread": 0.1, + "speedSpread": 0, "emitOrientation": { - "x": -0.7000000000000001, + "x": -1, "y": 0, "z": 0, - "w": 0.7071068286895752 + "w": 1 }, "emitDimensions": { "x": 0, @@ -486,7 +487,7 @@ function MyController(hand) { "alphaSpread": 0, "alphaStart": 1, "alphaFinish": 1, - "additiveBlending": 0, + "additiveBlending": 1, "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png" } @@ -502,6 +503,7 @@ function MyController(hand) { //rotation:rotation, rotation: orientation, position: position, + visible: true }) @@ -525,10 +527,12 @@ function MyController(hand) { this.particleBeamOff = function() { if (this.particleBeam !== null) { - Entities.deleteEntity(this.particleBeam) + Entities.editEntity(this.particleBeam, { + visible: false + }) } - this.particleBeam = null; + //this.particleBeam = null; } this.triggerPress = function(value) { @@ -1314,6 +1318,7 @@ function MyController(hand) { this.cleanup = function() { this.release(); this.endHandGrasp(); + Entities.deleteEntity(this.particleBeam); }; this.activateEntity = function(entityID, grabbedProperties) { @@ -1404,6 +1409,8 @@ function MyController(hand) { var rightController = new MyController(RIGHT_HAND); var leftController = new MyController(LEFT_HAND); +rightController.createParticleBeam(); +leftController.createParticleBeam(); var MAPPING_NAME = "com.highfidelity.handControllerGrab"; From 1000b602808f4a487012be55df9ec685824a8f29 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 12:21:50 -0800 Subject: [PATCH 034/195] far beams --- examples/controllers/handControllerGrab.js | 65 ++++++++++++---------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 4348722df0..812eef07f8 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -400,7 +400,7 @@ function MyController(hand) { }; //test particles instead of overlays - this.handleParticleBeam = function(position, orientation) { + this.handleParticleBeam = function(position, orientation, color) { var rotation = Quat.angleAxis(0, { x: 1, @@ -409,18 +409,36 @@ function MyController(hand) { }); var finalRotation = Quat.multiply(orientation, rotation); + // var finalRotation = orientation + + if (this.particleBeam === null) { + print('create beam') + this.createParticleBeam(position, finalRotation, color) + } else { + print('update beam') + this.updateParticleBeam(position, finalRotation, color) + } + } + + this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { + + + var handToObject = Vec3.subtract(objectPosition, handPosition); + var finalRotation = Quat.rotationBetween(Vec3.multiply(-1,Vec3.UP), handToObject); + + if (this.particleBeam === null) { print('create beam') - this.createParticleBeam(position, finalRotation) + this.createParticleBeam(objectPosition, finalRotation, color) } else { print('update beam') - this.updateParticleBeam(position, finalRotation) + this.updateParticleBeam(objectPosition, finalRotation, color) } } - this.createParticleBeam = function(position, orientation) { + this.createParticleBeam = function(position, orientation, color) { var particleBeamProperties = { type: "ParticleEffect", isEmitting: true, @@ -428,15 +446,11 @@ function MyController(hand) { visible: false, //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), "name": "Particle Beam", - "color": { - "red": 110, - "green": 118.52941176470593, - "blue": 255 - }, + "color": color, "maxParticles": 2000, "lifespan": 3, "emitRate": 50, - "emitSpeed": 2, + "emitSpeed": 20, "speedSpread": 0, "emitOrientation": { "x": -1, @@ -473,16 +487,8 @@ function MyController(hand) { "green": 0, "blue": 0 }, - "colorStart": { - "red": 110, - "green": 118.52941176470593, - "blue": 255 - }, - "colorFinish": { - "red": 110, - "green": 118.52941176470593, - "blue": 255 - }, + "colorStart": color, + "colorFinish": color, "alpha": 1, "alphaSpread": 0, "alphaStart": 1, @@ -494,21 +500,19 @@ function MyController(hand) { this.particleBeam = Entities.addEntity(particleBeamProperties); } - this.updateParticleBeam = function(position, orientation, acceleration) { + this.updateParticleBeam = function(position, orientation, color) { print('O IN UPDATE:::' + JSON.stringify(orientation)) // var beamProps = Entities.getEntityProperties(this.particleBeam); Entities.editEntity(this.particleBeam, { - //rotation:rotation, rotation: orientation, position: position, - visible: true + visible: true, + color: color }) - // var emitO = Entities.getEntityProperties(this.particleBeam, "emitOrientation").emitOrientation; - // print('EMIT o :::' + JSON.stringify(emitO)); } this.lineOff = function() { @@ -784,8 +788,8 @@ function MyController(hand) { } //this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); - this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR); - this.handleParticleBeam(distantPickRay.origin, this.getHandRotation()); + //this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR); + this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR); }; @@ -867,9 +871,8 @@ function MyController(hand) { return; } - this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); - - // the action was set up on a previous call. update the targets. + // this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); + // the action was set up on a previous call. update the targets. var radius = Vec3.distance(this.currentObjectPosition, handControllerPosition) * this.radiusScalar * DISTANCE_HOLDING_RADIUS_FACTOR; if (radius < 1.0) { @@ -950,6 +953,8 @@ function MyController(hand) { this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change); } + this.handleDistantParticleBeam(handPosition, grabbedProperties.position,this.currentObjectRotation, INTERSECT_COLOR) + Entities.updateAction(this.grabbedEntity, this.actionID, { targetPosition: this.currentObjectPosition, linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, From c3e9cde7fbc59ce8dafb0f8c7c443212bd08662c Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 13:44:53 -0800 Subject: [PATCH 035/195] beamz --- examples/controllers/handControllerGrab.js | 31 +++++++++++++--------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 812eef07f8..1106295cde 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -423,22 +423,25 @@ function MyController(hand) { this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { - var handToObject = Vec3.subtract(objectPosition, handPosition); - var finalRotation = Quat.rotationBetween(Vec3.multiply(-1,Vec3.UP), handToObject); - + var handToObject = Vec3.subtract(objectPosition, handPosition); + var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); + var distance = Vec3.distance(handPosition, objectPosition); + var speed = distance * 1; + var lifepsan = distance / speed; + var lifespan = 1; if (this.particleBeam === null) { print('create beam') - this.createParticleBeam(objectPosition, finalRotation, color) + this.createParticleBeam(objectPosition, finalRotation, color, speed) } else { print('update beam') - this.updateParticleBeam(objectPosition, finalRotation, color) + this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan) } } - this.createParticleBeam = function(position, orientation, color) { + this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { var particleBeamProperties = { type: "ParticleEffect", isEmitting: true, @@ -448,9 +451,9 @@ function MyController(hand) { "name": "Particle Beam", "color": color, "maxParticles": 2000, - "lifespan": 3, + "lifespan": 1, "emitRate": 50, - "emitSpeed": 20, + "emitSpeed": 1, "speedSpread": 0, "emitOrientation": { "x": -1, @@ -500,7 +503,7 @@ function MyController(hand) { this.particleBeam = Entities.addEntity(particleBeamProperties); } - this.updateParticleBeam = function(position, orientation, color) { + this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { print('O IN UPDATE:::' + JSON.stringify(orientation)) // var beamProps = Entities.getEntityProperties(this.particleBeam); @@ -509,7 +512,9 @@ function MyController(hand) { rotation: orientation, position: position, visible: true, - color: color + color: color, + emitSpeed: speed, + lifepsan: lifepsan }) @@ -871,8 +876,8 @@ function MyController(hand) { return; } - // this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); - // the action was set up on a previous call. update the targets. + // this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); + // the action was set up on a previous call. update the targets. var radius = Vec3.distance(this.currentObjectPosition, handControllerPosition) * this.radiusScalar * DISTANCE_HOLDING_RADIUS_FACTOR; if (radius < 1.0) { @@ -953,7 +958,7 @@ function MyController(hand) { this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change); } - this.handleDistantParticleBeam(handPosition, grabbedProperties.position,this.currentObjectRotation, INTERSECT_COLOR) + this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) Entities.updateAction(this.grabbedEntity, this.actionID, { targetPosition: this.currentObjectPosition, From efaa30a509148a6f0da8921d88c0c4c732aa04ca Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 16:18:40 -0800 Subject: [PATCH 036/195] rotatable light --- examples/controllers/handControllerGrab.js | 91 ++++++++++++++++++---- 1 file changed, 77 insertions(+), 14 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index d92cb35b43..4e612799f7 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -116,6 +116,17 @@ var DEFAULT_GRABBABLE_DATA = { invertSolidWhileHeld: false }; +var MODEL_LIGHT_POSITION = { + x: 0, + y: -0.3, + z: 0 +}; +var MODEL_LIGHT_ROTATION = Quat.angleAxis(-90, { + x: 1, + y: 0, + z: 0 +}); + // states for the state machine var STATE_OFF = 0; @@ -137,6 +148,7 @@ var STATE_WAITING_FOR_BUMPER_RELEASE = 15; var STATE_EQUIP_SPRING = 16; + function stateToName(state) { switch (state) { case STATE_OFF: @@ -218,6 +230,7 @@ function getSpatialOffsetPosition(hand, spatialKey) { } var yFlip = Quat.angleAxis(180, Vec3.UNIT_Y); + function getSpatialOffsetRotation(hand, spatialKey) { var rotation = Quat.IDENTITY; @@ -264,7 +277,8 @@ function MyController(hand) { this.overlayLine = null; this.particleBeam = null; - + this.spotlight = null; + this.ignoreIK = false; this.offsetPosition = Vec3.ZERO; this.offsetRotation = Quat.IDENTITY; @@ -420,7 +434,6 @@ function MyController(hand) { }); var finalRotation = Quat.multiply(orientation, rotation); - // var finalRotation = orientation if (this.particleBeam === null) { print('create beam') @@ -433,7 +446,6 @@ function MyController(hand) { this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { - var handToObject = Vec3.subtract(objectPosition, handPosition); var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); @@ -453,6 +465,7 @@ function MyController(hand) { } this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { + var particleBeamProperties = { type: "ParticleEffect", isEmitting: true, @@ -463,7 +476,7 @@ function MyController(hand) { "color": color, "maxParticles": 2000, "lifespan": 1, - "emitRate": 50, + "emitRate": 15, "emitSpeed": 1, "speedSpread": 0, "emitOrientation": { @@ -494,21 +507,21 @@ function MyController(hand) { }, "particleRadius": 0.02, "radiusSpread": 0, - "radiusStart": 0.01, - "radiusFinish": 0.01, - "colorSpread": { - "red": 0, - "green": 0, - "blue": 0 - }, - "colorStart": color, - "colorFinish": color, + // "radiusStart": 0.01, + // "radiusFinish": 0.01, + // "colorSpread": { + // "red": 0, + // "green": 0, + // "blue": 0 + // }, + // "colorStart": color, + // "colorFinish": color, "alpha": 1, "alphaSpread": 0, "alphaStart": 1, "alphaFinish": 1, "additiveBlending": 1, - "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png" + "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" } this.particleBeam = Entities.addEntity(particleBeamProperties); @@ -531,6 +544,49 @@ function MyController(hand) { } + + this.evalLightWorldTransform = function(modelPos, modelRot) { + return { + p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), + q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) + }; + } + + this.createSpotlight = function(parentID, position) { + var LIFETIME = 100; + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); + var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + //this light casts the beam + var lightProperties = { + type: "Light", + isSpotlight: true, + dimensions: { + x: 2, + y: 2, + z: 20 + }, + parentID: parentID, + color: { + red: 255, + green: 255, + blue: 255 + }, + intensity: 2, + exponent: 0.3, + cutoff: 20, + lifetime: LIFETIME, + position: lightTransform.p, + rotation: lightTransform.q, + }; + + + if (this.spotlight === null) { + this.spotlight = Entities.addEntity(lightProperties); + } else { + + } + } + this.lineOff = function() { if (this.pointer !== null) { Entities.deleteEntity(this.pointer); @@ -555,6 +611,11 @@ function MyController(hand) { //this.particleBeam = null; } + this.spotlightOff = function() { + // Entities.deleteEntity(this.spotlight); + // this.spotlight = null; + } + this.triggerPress = function(value) { _this.rawTriggerValue = value; }; @@ -970,6 +1031,7 @@ function MyController(hand) { } this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + this.createSpotlight(this.grabbedEntity); Entities.updateAction(this.grabbedEntity, this.actionID, { targetPosition: this.currentObjectPosition, @@ -1331,6 +1393,7 @@ function MyController(hand) { this.lineOff(); this.overlayLineOff(); this.particleBeamOff(); + this.spotlightOff(); if (this.grabbedEntity !== null) { if (this.actionID !== null) { Entities.deleteAction(this.grabbedEntity, this.actionID); From 16ab7e74de0c12813694e4f006c21f8c89e6f739 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 16:53:13 -0800 Subject: [PATCH 037/195] cleanup spotlights --- examples/controllers/handControllerGrab.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 4e612799f7..b787d8f0df 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -476,7 +476,7 @@ function MyController(hand) { "color": color, "maxParticles": 2000, "lifespan": 1, - "emitRate": 15, + "emitRate": 300, "emitSpeed": 1, "speedSpread": 0, "emitOrientation": { @@ -505,7 +505,7 @@ function MyController(hand) { "y": 0, "z": 0 }, - "particleRadius": 0.02, + "particleRadius": 0.01, "radiusSpread": 0, // "radiusStart": 0.01, // "radiusFinish": 0.01, @@ -583,7 +583,10 @@ function MyController(hand) { if (this.spotlight === null) { this.spotlight = Entities.addEntity(lightProperties); } else { - + // var rotationBetween = Quat.rotationBetween(Vec3.UP, ) + // Entities.editEntity(this.spotlight, { + // rotation: lightTransform.q + // }) } } @@ -612,8 +615,10 @@ function MyController(hand) { } this.spotlightOff = function() { - // Entities.deleteEntity(this.spotlight); - // this.spotlight = null; + if (this.spotlight !== null) { + Overlays.deleteOverlay(this.spotlight); + } + this.spotlight = null; } this.triggerPress = function(value) { From 2acc0df1f0bf29315d146b63d4e0f46342f63f37 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 17:39:29 -0800 Subject: [PATCH 038/195] beams with spotlights --- examples/controllers/handControllerGrab.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index b787d8f0df..58eeb83b0e 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -559,7 +559,7 @@ function MyController(hand) { //this light casts the beam var lightProperties = { type: "Light", - isSpotlight: true, + isSpotlight: false, dimensions: { x: 2, y: 2, @@ -576,17 +576,18 @@ function MyController(hand) { cutoff: 20, lifetime: LIFETIME, position: lightTransform.p, - rotation: lightTransform.q, + // rotation: lightTransform.q, }; if (this.spotlight === null) { this.spotlight = Entities.addEntity(lightProperties); } else { - // var rotationBetween = Quat.rotationBetween(Vec3.UP, ) - // Entities.editEntity(this.spotlight, { - // rotation: lightTransform.q - // }) + Entities.editEntity(this.spotlight, { + parentID:parentID, + position:lightTransform.p, + visible:true + }) } } @@ -616,9 +617,13 @@ function MyController(hand) { this.spotlightOff = function() { if (this.spotlight !== null) { - Overlays.deleteOverlay(this.spotlight); + print('SHOULD DELETE SPOTLIGHT' + this.spotlight) + Entities.editEntity(this.spotlight,{ + visible:false + }) + //Entities.deleteEntity(this.spotlight); } - this.spotlight = null; + //this.spotlight = null; } this.triggerPress = function(value) { @@ -1416,6 +1421,7 @@ function MyController(hand) { this.release(); this.endHandGrasp(); Entities.deleteEntity(this.particleBeam); + Entities.deleteEntity(this.spotLight); }; this.activateEntity = function(entityID, grabbedProperties) { From c74bbda663028c8ec621c899396899891931e5f4 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Dec 2015 18:02:02 -0800 Subject: [PATCH 039/195] Nothing fancy --- libraries/render-utils/src/FramebufferCache.cpp | 6 +++--- libraries/render-utils/src/ToneMappingEffect.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index 83ba8b6950..e0ad3dedd2 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -88,9 +88,9 @@ void FramebufferCache::createPrimaryFramebuffer() { _selfieFramebuffer->setRenderBuffer(0, tex); //_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, defaultSampler)); - _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::R11G11B10), width, height, defaultSampler)); - // _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler)); - _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + //lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::R11G11B10), width, height, defaultSampler)); + _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler)); + _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _lightingFramebuffer->setRenderBuffer(0, _lightingTexture); _lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); } diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index ea38884fac..1857d76cbf 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -50,7 +50,7 @@ void ToneMappingEffect::init() { // Manually gamma correct from Ligthing BUffer to color buffer // outFragColor.xyz = pow( fragColor.xyz , vec3(1.0 / 2.2) ); - fragColor *= 4.0; // Hardcoded Exposure Adjustment + fragColor *= 2.0; // Hardcoded Exposure Adjustment vec3 x = max(vec3(0.0),fragColor.xyz-0.004); vec3 retColor = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06); From 4e9d81f18737203e4bbdd60343aab98d65a210a1 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 11 Dec 2015 11:38:16 -0800 Subject: [PATCH 040/195] add support for various beam visualizations --- examples/controllers/handControllerGrab.js | 269 ++++++++++++++------- 1 file changed, 178 insertions(+), 91 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 58eeb83b0e..9e2f55b238 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -116,17 +116,14 @@ var DEFAULT_GRABBABLE_DATA = { invertSolidWhileHeld: false }; -var MODEL_LIGHT_POSITION = { - x: 0, - y: -0.3, - z: 0 -}; -var MODEL_LIGHT_ROTATION = Quat.angleAxis(-90, { - x: 1, - y: 0, - z: 0 -}); - +//we've created various ways of visualizing looking for and moving distant objects +var USE_ENTITY_LASERS_FOR_SEARCHING = false; +var USE_ENTITY_LASERS_FOR_MOVING = true; +var USE_OVERLAY_LINES_FOR_SEARCHING = true; +var USE_PARTICLE_BEAM_FOR_SEARCHING = false; +var USE_PARTICLE_BEAM_FOR_MOVING = false; +var USE_SPOTLIGHT = false; +var USE_POINTLIGHT = false; // states for the state machine var STATE_OFF = 0; @@ -275,9 +272,13 @@ function MyController(hand) { this.rawTriggerValue = 0; this.rawBumperValue = 0; + //for visualizations this.overlayLine = null; this.particleBeam = null; + + //for lights this.spotlight = null; + this.pointlight = null; this.ignoreIK = false; this.offsetPosition = Vec3.ZERO; @@ -366,33 +367,6 @@ function MyController(hand) { }); } - this.overlayLineOn = function(closePoint, farPoint, color) { - if (this.overlayLine === null) { - var lineProperties = { - lineWidth: 5, - start: closePoint, - end: farPoint, - color: color, - ignoreRayIntersection: true, // always ignore this - visible: true, - alpha: 1 - }; - - this.overlayLine = Overlays.addOverlay("line3d", lineProperties); - - } else { - var success = Overlays.editOverlay(this.overlayLine, { - lineWidth: 5, - start: closePoint, - end: farPoint, - color: color, - visible: true, - ignoreRayIntersection: true, // always ignore this - alpha: 1 - }); - } - } - this.lineOn = function(closePoint, farPoint, color) { // draw a line if (this.pointer === null) { @@ -424,7 +398,33 @@ function MyController(hand) { } }; - //test particles instead of overlays + this.overlayLineOn = function(closePoint, farPoint, color) { + if (this.overlayLine === null) { + var lineProperties = { + lineWidth: 5, + start: closePoint, + end: farPoint, + color: color, + ignoreRayIntersection: true, // always ignore this + visible: true, + alpha: 1 + }; + + this.overlayLine = Overlays.addOverlay("line3d", lineProperties); + + } else { + var success = Overlays.editOverlay(this.overlayLine, { + lineWidth: 5, + start: closePoint, + end: farPoint, + color: color, + visible: true, + ignoreRayIntersection: true, // always ignore this + alpha: 1 + }); + } + } + this.handleParticleBeam = function(position, orientation, color) { var rotation = Quat.angleAxis(0, { @@ -437,10 +437,10 @@ function MyController(hand) { if (this.particleBeam === null) { print('create beam') - this.createParticleBeam(position, finalRotation, color) + this.createParticleBeam(position, finalRotation, color); } else { print('update beam') - this.updateParticleBeam(position, finalRotation, color) + this.updateParticleBeam(position, finalRotation, color); } } @@ -456,11 +456,9 @@ function MyController(hand) { var lifespan = 1; if (this.particleBeam === null) { - print('create beam') - this.createParticleBeam(objectPosition, finalRotation, color, speed) + this.createParticleBeam(objectPosition, finalRotation, color, speed); } else { - print('update beam') - this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan) + this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); } } @@ -475,10 +473,10 @@ function MyController(hand) { "name": "Particle Beam", "color": color, "maxParticles": 2000, - "lifespan": 1, - "emitRate": 300, - "emitSpeed": 1, - "speedSpread": 0, + "lifespan": LINE_LENGTH / 10, + "emitRate": 50, + "emitSpeed": 5, + "speedSpread": 2, "emitOrientation": { "x": -1, "y": 0, @@ -528,9 +526,6 @@ function MyController(hand) { } this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { - print('O IN UPDATE:::' + JSON.stringify(orientation)) - - // var beamProps = Entities.getEntityProperties(this.particleBeam); Entities.editEntity(this.particleBeam, { rotation: orientation, @@ -544,19 +539,72 @@ function MyController(hand) { } - this.evalLightWorldTransform = function(modelPos, modelRot) { + + var MODEL_LIGHT_POSITION = { + x: 0, + y: -0.3, + z: 0 + }; + + var MODEL_LIGHT_ROTATION = Quat.angleAxis(-90, { + x: 1, + y: 0, + z: 0 + }); + return { p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) }; } - this.createSpotlight = function(parentID, position) { + this.handleSpotlight = function(parentID, position) { var LIFETIME = 100; + + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); + + var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + var lightProperties = { + type: "Light", + isSpotlight: true, + dimensions: { + x: 2, + y: 2, + z: 20 + }, + parentID: parentID, + color: { + red: 255, + green: 255, + blue: 255 + }, + intensity: 2, + exponent: 0.3, + cutoff: 20, + lifetime: LIFETIME, + position: lightTransform.p, + }; + + if (this.spotlight === null) { + this.spotlight = Entities.addEntity(lightProperties); + } else { + Entities.editEntity(this.spotlight, { + parentID: parentID, + position: lightTransform.p, + //without this, this light would maintain rotation with its parent + rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0), + visible: true + }) + } + } + + this.handlePointLight = function(parentID, position) { + var LIFETIME = 100; + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); - //this light casts the beam + var lightProperties = { type: "Light", isSpotlight: false, @@ -576,17 +624,18 @@ function MyController(hand) { cutoff: 20, lifetime: LIFETIME, position: lightTransform.p, - // rotation: lightTransform.q, }; + if (this.pointlight === null) { - if (this.spotlight === null) { - this.spotlight = Entities.addEntity(lightProperties); + print('create pointlight') + this.pointlight = Entities.addEntity(lightProperties); } else { - Entities.editEntity(this.spotlight, { - parentID:parentID, - position:lightTransform.p, - visible:true + print('update pointlight') + Entities.editEntity(this.pointlight, { + parentID: parentID, + position: lightTransform.p, + visible: true }) } } @@ -611,19 +660,25 @@ function MyController(hand) { visible: false }) } - - //this.particleBeam = null; } - this.spotlightOff = function() { + this.turnLightsOff = function() { + //use visibility for now instead of creating and deleting since deleting seems to crash if (this.spotlight !== null) { - print('SHOULD DELETE SPOTLIGHT' + this.spotlight) - Entities.editEntity(this.spotlight,{ - visible:false - }) - //Entities.deleteEntity(this.spotlight); + Entities.editEntity(this.spotlight, { + visible: false + }) + //Entities.deleteEntity(this.spotlight); + //this.spotLight=null; + } + + if (this.pointlight !== null) { + Entities.editEntity(this.pointlight, { + visible: false + }) + //Entities.deleteEntity(this.pointlight); + //this.pointlight = null; } - //this.spotlight = null; } this.triggerPress = function(value) { @@ -634,7 +689,6 @@ function MyController(hand) { _this.rawBumperValue = value; }; - this.updateSmoothedTrigger = function() { var triggerValue = this.rawTriggerValue; // smooth out trigger value @@ -663,7 +717,6 @@ function MyController(hand) { return _this.rawBumperValue < BUMPER_ON_VALUE; } - this.off = function() { if (this.triggerSmoothedSqueezed()) { this.lastPickTime = 0; @@ -874,10 +927,18 @@ function MyController(hand) { } } - //this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); - //this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR); - this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR); + //search line visualizations + if (USE_ENTITY_LASERS_FOR_SEARCHING === true) { + this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + } + if (USE_OVERLAY_LINES_FOR_SEARCHING === true) { + this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true) { + this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR); + } }; @@ -931,10 +992,22 @@ function MyController(hand) { this.currentAvatarPosition = MyAvatar.position; this.currentAvatarOrientation = MyAvatar.orientation; - this.overlayLineOff(); - this.particleBeamOff(); + this.turnOffVisualizations(); }; + this.turnOffVisualizations = function() { + if (USE_ENTITY_LASERS_FOR_SEARCHING === true || USE_ENTITY_LASERS_FOR_MOVING === true) { + this.lineOff(); + } + if (USE_OVERLAY_LINES_FOR_SEARCHING === true) { + this.overlayLineOff(); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.particleBeamOff(); + } + } + this.continueDistanceHolding = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); @@ -958,7 +1031,7 @@ function MyController(hand) { return; } - // this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); + // the action was set up on a previous call. update the targets. var radius = Vec3.distance(this.currentObjectPosition, handControllerPosition) * this.radiusScalar * DISTANCE_HOLDING_RADIUS_FACTOR; @@ -1040,8 +1113,22 @@ function MyController(hand) { this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change); } - this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) - this.createSpotlight(this.grabbedEntity); + + //visualizations + if (USE_ENTITY_LASERS_FOR_MOVING === true) { + this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); + } + if (USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + } + + if (USE_POINTLIGHT === true) { + this.handlePointLight(this.grabbedEntity); + } + + if (USE_SPOTLIGHT === true) { + this.handleSpotlight(this.grabbedEntity); + } Entities.updateAction(this.grabbedEntity, this.actionID, { targetPosition: this.currentObjectPosition, @@ -1050,6 +1137,7 @@ function MyController(hand) { angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, ttl: ACTION_TTL }); + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); }; @@ -1063,9 +1151,7 @@ function MyController(hand) { return; } - this.lineOff(); - this.overlayLineOff(); - this.particleBeamOff(); + this.turnOffVisualizations(); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); this.activateEntity(this.grabbedEntity, grabbedProperties); @@ -1207,9 +1293,8 @@ function MyController(hand) { }; this.pullTowardEquipPosition = function() { - this.lineOff(); - this.overlayLineOff(); - this.particleBeamOff(); + + this.turnOffVisualizations(); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); @@ -1400,10 +1485,9 @@ function MyController(hand) { this.release = function() { - this.lineOff(); - this.overlayLineOff(); - this.particleBeamOff(); - this.spotlightOff(); + this.turnLightsOff(); + this.turnOffVisualizations(); + if (this.grabbedEntity !== null) { if (this.actionID !== null) { Entities.deleteAction(this.grabbedEntity, this.actionID); @@ -1422,6 +1506,7 @@ function MyController(hand) { this.endHandGrasp(); Entities.deleteEntity(this.particleBeam); Entities.deleteEntity(this.spotLight); + Entities.deleteEntity(this.pointLight); }; this.activateEntity = function(entityID, grabbedProperties) { @@ -1512,6 +1597,8 @@ function MyController(hand) { var rightController = new MyController(RIGHT_HAND); var leftController = new MyController(LEFT_HAND); + +//reload the particle beams rightController.createParticleBeam(); leftController.createParticleBeam(); From 11aaeb1ec00a76273f639648d47a00e4f691e0aa Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 11 Dec 2015 14:48:07 -0800 Subject: [PATCH 041/195] only create particle beams if set --- examples/controllers/handControllerGrab.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 9e2f55b238..217b5b6632 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -1599,8 +1599,10 @@ var rightController = new MyController(RIGHT_HAND); var leftController = new MyController(LEFT_HAND); //reload the particle beams -rightController.createParticleBeam(); -leftController.createParticleBeam(); +if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + rightController.createParticleBeam(); + leftController.createParticleBeam(); +} var MAPPING_NAME = "com.highfidelity.handControllerGrab"; From 1b1edf6f7ab8a8e94e7d78df9eaf2b42d81c703b Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 11 Dec 2015 17:23:35 -0800 Subject: [PATCH 042/195] actually delete lights now that it doesnt crash --- examples/controllers/handControllerGrab.js | 30 +++++----------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 217b5b6632..ae95ab47fd 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -122,7 +122,7 @@ var USE_ENTITY_LASERS_FOR_MOVING = true; var USE_OVERLAY_LINES_FOR_SEARCHING = true; var USE_PARTICLE_BEAM_FOR_SEARCHING = false; var USE_PARTICLE_BEAM_FOR_MOVING = false; -var USE_SPOTLIGHT = false; +var USE_SPOTLIGHT = true; var USE_POINTLIGHT = false; // states for the state machine @@ -436,10 +436,8 @@ function MyController(hand) { var finalRotation = Quat.multiply(orientation, rotation); if (this.particleBeam === null) { - print('create beam') this.createParticleBeam(position, finalRotation, color); } else { - print('update beam') this.updateParticleBeam(position, finalRotation, color); } } @@ -590,11 +588,8 @@ function MyController(hand) { this.spotlight = Entities.addEntity(lightProperties); } else { Entities.editEntity(this.spotlight, { - parentID: parentID, - position: lightTransform.p, //without this, this light would maintain rotation with its parent rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0), - visible: true }) } } @@ -627,16 +622,9 @@ function MyController(hand) { }; if (this.pointlight === null) { - - print('create pointlight') this.pointlight = Entities.addEntity(lightProperties); } else { - print('update pointlight') - Entities.editEntity(this.pointlight, { - parentID: parentID, - position: lightTransform.p, - visible: true - }) + } } @@ -665,19 +653,13 @@ function MyController(hand) { this.turnLightsOff = function() { //use visibility for now instead of creating and deleting since deleting seems to crash if (this.spotlight !== null) { - Entities.editEntity(this.spotlight, { - visible: false - }) - //Entities.deleteEntity(this.spotlight); - //this.spotLight=null; + Entities.deleteEntity(this.spotlight); + this.spotlight = null; } if (this.pointlight !== null) { - Entities.editEntity(this.pointlight, { - visible: false - }) - //Entities.deleteEntity(this.pointlight); - //this.pointlight = null; + Entities.deleteEntity(this.pointlight); + this.pointlight = null; } } From 70a0e51cc9b5898dc49b1134f84a6f96d50b7aff Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 11 Dec 2015 17:59:03 -0800 Subject: [PATCH 043/195] back to default state --- examples/controllers/handControllerGrab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index ae95ab47fd..fc217de03a 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -122,7 +122,7 @@ var USE_ENTITY_LASERS_FOR_MOVING = true; var USE_OVERLAY_LINES_FOR_SEARCHING = true; var USE_PARTICLE_BEAM_FOR_SEARCHING = false; var USE_PARTICLE_BEAM_FOR_MOVING = false; -var USE_SPOTLIGHT = true; +var USE_SPOTLIGHT = false; var USE_POINTLIGHT = false; // states for the state machine From cb948e0608502d38cafac927b682d9759818ee23 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 12 Dec 2015 21:15:06 +0100 Subject: [PATCH 044/195] allow entity scripts to attach entities to a hand with handControllerGrab.js --- examples/controllers/handControllerGrab.js | 40 +++++++++++++--------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 138240f5d6..7976e5286f 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -968,7 +968,6 @@ function MyController(hand) { Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); Entities.callEntityMethod(this.grabbedEntity, "unequip"); this.endHandGrasp(); - } }; @@ -1288,33 +1287,40 @@ function update() { if (handToDisable !== LEFT_HAND && handToDisable!=='both') { leftController.update(); } - if (handToDisable !== RIGHT_HAND && handToDisable!=='both') { + if (handToDisable !== RIGHT_HAND && handToDisable!=='both') { rightController.update(); } } Messages.subscribe('Hifi-Hand-Disabler'); +Messages.subscribe('Hifi-Hand-Grab'); -handleHandDisablerMessages = function(channel, message, sender) { - +handleHandMessages = function(channel, message, sender) { if (sender === MyAvatar.sessionUUID) { - if (message === 'left') { - handToDisable = LEFT_HAND; - } - if (message === 'right') { - handToDisable = RIGHT_HAND; - } - if(message==='both'){ - handToDisable='both'; - } - if(message==='none'){ - handToDisable='none'; + if (channel === 'Hifi-Hand-Disabler') { + if (message === 'left') { + handToDisable = LEFT_HAND; + } + if (message === 'right') { + handToDisable = RIGHT_HAND; + } + if (message === 'both' || message === 'none') { + handToDisable = handToDisable; + } + } else if (channel === 'Hifi-Hand-Grab') { + try { + var data = JSON.parse(message); + var selectedController = (data.hand === 'left') ? leftController : rightController; + selectedController.release(); + selectedController.setState(STATE_EQUIP); + selectedController.grabbedEntity = data.entityID; + + } catch (e) { } } } - } -Messages.messageReceived.connect(handleHandDisablerMessages); +Messages.messageReceived.connect(handleHandMessages); function cleanup() { rightController.cleanup(); From fe05542440f2c74668cbec2859c2c8227eb91e42 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Sat, 12 Dec 2015 14:30:34 -0800 Subject: [PATCH 045/195] more vis --- examples/controllers/handControllerGrab.js | 80 ++++++++++++---------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index fc217de03a..afad62412e 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -1,5 +1,4 @@ // handControllerGrab.js -// examples // // Created by Eric Levin on 9/2/15 // Additions by James B. Pollack @imgntn on 9/24/2015 @@ -7,6 +6,7 @@ // Copyright 2015 High Fidelity, Inc. // // Grabs physically moveable entities with hydra-like controllers; it works for either near or far objects. +// Also supports touch and equipping objects. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -14,7 +14,6 @@ Script.include("../libraries/utils.js"); - // // add lines where the hand ray picking is happening // @@ -54,6 +53,7 @@ var LINE_ENTITY_DIMENSIONS = { y: 1000, z: 1000 }; + var LINE_LENGTH = 500; var PICK_MAX_DISTANCE = 500; // max length of pick-ray @@ -120,6 +120,7 @@ var DEFAULT_GRABBABLE_DATA = { var USE_ENTITY_LASERS_FOR_SEARCHING = false; var USE_ENTITY_LASERS_FOR_MOVING = true; var USE_OVERLAY_LINES_FOR_SEARCHING = true; +var USE_OVERLAY_LINES_FOR_MOVING = false; var USE_PARTICLE_BEAM_FOR_SEARCHING = false; var USE_PARTICLE_BEAM_FOR_MOVING = false; var USE_SPOTLIGHT = false; @@ -345,7 +346,7 @@ function MyController(hand) { print("STATE: " + stateToName(this.state) + " --> " + stateToName(newState) + ", hand: " + this.hand); } this.state = newState; - } + }; this.debugLine = function(closePoint, farPoint, color) { Entities.addEntity({ @@ -365,7 +366,7 @@ function MyController(hand) { } }) }); - } + }; this.lineOn = function(closePoint, farPoint, color) { // draw a line @@ -423,7 +424,7 @@ function MyController(hand) { alpha: 1 }); } - } + }; this.handleParticleBeam = function(position, orientation, color) { @@ -440,7 +441,7 @@ function MyController(hand) { } else { this.updateParticleBeam(position, finalRotation, color); } - } + }; this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { @@ -458,7 +459,7 @@ function MyController(hand) { } else { this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); } - } + }; this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { @@ -521,7 +522,7 @@ function MyController(hand) { } this.particleBeam = Entities.addEntity(particleBeamProperties); - } + }; this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { @@ -535,7 +536,7 @@ function MyController(hand) { }) - } + }; this.evalLightWorldTransform = function(modelPos, modelRot) { @@ -555,7 +556,7 @@ function MyController(hand) { p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) }; - } + }; this.handleSpotlight = function(parentID, position) { var LIFETIME = 100; @@ -592,7 +593,7 @@ function MyController(hand) { rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0), }) } - } + }; this.handlePointLight = function(parentID, position) { var LIFETIME = 100; @@ -626,7 +627,7 @@ function MyController(hand) { } else { } - } + }; this.lineOff = function() { if (this.pointer !== null) { @@ -651,7 +652,6 @@ function MyController(hand) { } this.turnLightsOff = function() { - //use visibility for now instead of creating and deleting since deleting seems to crash if (this.spotlight !== null) { Entities.deleteEntity(this.spotlight); this.spotlight = null; @@ -661,7 +661,22 @@ function MyController(hand) { Entities.deleteEntity(this.pointlight); this.pointlight = null; } - } + }; + + + this.turnOffVisualizations = function() { + if (USE_ENTITY_LASERS_FOR_SEARCHING === true || USE_ENTITY_LASERS_FOR_MOVING === true) { + this.lineOff(); + } + + if (USE_OVERLAY_LINES_FOR_SEARCHING === true || USE_OVERLAY_LINES_FOR_MOVING === true) { + this.overlayLineOff(); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.particleBeamOff(); + } + }; this.triggerPress = function(value) { _this.rawTriggerValue = value; @@ -693,11 +708,11 @@ function MyController(hand) { this.bumperSqueezed = function() { return _this.rawBumperValue > BUMPER_ON_VALUE; - } + }; this.bumperReleased = function() { return _this.rawBumperValue < BUMPER_ON_VALUE; - } + }; this.off = function() { if (this.triggerSmoothedSqueezed()) { @@ -710,7 +725,7 @@ function MyController(hand) { this.setState(STATE_EQUIP_SEARCHING); return; } - } + }; this.search = function() { this.grabbedEntity = null; @@ -977,19 +992,6 @@ function MyController(hand) { this.turnOffVisualizations(); }; - this.turnOffVisualizations = function() { - if (USE_ENTITY_LASERS_FOR_SEARCHING === true || USE_ENTITY_LASERS_FOR_MOVING === true) { - this.lineOff(); - } - if (USE_OVERLAY_LINES_FOR_SEARCHING === true) { - this.overlayLineOff(); - } - - if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { - this.particleBeamOff(); - } - } - this.continueDistanceHolding = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); @@ -1100,14 +1102,15 @@ function MyController(hand) { if (USE_ENTITY_LASERS_FOR_MOVING === true) { this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); } + if (USE_OVERLAY_LINES_FOR_MOVING === true) { + this.overlayLineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); + } if (USE_PARTICLE_BEAM_FOR_MOVING === true) { this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) } - if (USE_POINTLIGHT === true) { this.handlePointLight(this.grabbedEntity); } - if (USE_SPOTLIGHT === true) { this.handleSpotlight(this.grabbedEntity); } @@ -1399,6 +1402,7 @@ function MyController(hand) { }; _this.allTouchedIDs = {}; + this.touchTest = function() { var maxDistance = 0.05; var leftHandPosition = MyAvatar.getLeftPalmPosition(); @@ -1559,28 +1563,29 @@ function MyController(hand) { } //return an object with our updated settings return result; - } + }; this.graspHandler = null + this.startHandGrasp = function() { if (this.hand === RIGHT_HAND) { this.graspHandler = MyAvatar.addAnimationStateHandler(this.graspHand, ['isRightHandGrab']); } else if (this.hand === LEFT_HAND) { this.graspHandler = MyAvatar.addAnimationStateHandler(this.graspHand, ['isLeftHandGrab']); } - } + }; this.endHandGrasp = function() { // Tell the animation system we don't need any more callbacks. MyAvatar.removeAnimationStateHandler(this.graspHandler); - } + }; -} +}; var rightController = new MyController(RIGHT_HAND); var leftController = new MyController(LEFT_HAND); -//reload the particle beams +//preload the particle beams so that they are full length when you start searching if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { rightController.createParticleBeam(); leftController.createParticleBeam(); @@ -1597,6 +1602,7 @@ mapping.from([Controller.Standard.LB]).peek().to(leftController.bumperPress); Controller.enableMapping(MAPPING_NAME); +//the section below allows the grab script to listen for messages that disable either one or both hands. useful for two handed items var handToDisable = 'none'; function update() { From 0ddc2ba76e22359f202cb2205efbf6da24ec08a1 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Sat, 12 Dec 2015 16:18:15 -0800 Subject: [PATCH 046/195] rename lasers to lines --- examples/controllers/handControllerGrab.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index afad62412e..f8fe1b821c 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -117,8 +117,8 @@ var DEFAULT_GRABBABLE_DATA = { }; //we've created various ways of visualizing looking for and moving distant objects -var USE_ENTITY_LASERS_FOR_SEARCHING = false; -var USE_ENTITY_LASERS_FOR_MOVING = true; +var USE_ENTITY_LINES_FOR_SEARCHING = false; +var USE_ENTITY_LINES_FOR_MOVING = true; var USE_OVERLAY_LINES_FOR_SEARCHING = true; var USE_OVERLAY_LINES_FOR_MOVING = false; var USE_PARTICLE_BEAM_FOR_SEARCHING = false; @@ -665,7 +665,7 @@ function MyController(hand) { this.turnOffVisualizations = function() { - if (USE_ENTITY_LASERS_FOR_SEARCHING === true || USE_ENTITY_LASERS_FOR_MOVING === true) { + if (USE_ENTITY_LINES_FOR_SEARCHING === true || USE_ENTITY_LINES_FOR_MOVING === true) { this.lineOff(); } @@ -925,7 +925,7 @@ function MyController(hand) { } //search line visualizations - if (USE_ENTITY_LASERS_FOR_SEARCHING === true) { + if (USE_ENTITY_LINES_FOR_SEARCHING === true) { this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); } @@ -1099,7 +1099,7 @@ function MyController(hand) { //visualizations - if (USE_ENTITY_LASERS_FOR_MOVING === true) { + if (USE_ENTITY_LINES_FOR_MOVING === true) { this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); } if (USE_OVERLAY_LINES_FOR_MOVING === true) { From a0b698c0283ce162720ad13465d04ccb8105439d Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Sat, 12 Dec 2015 17:33:54 -0800 Subject: [PATCH 047/195] reorg props --- examples/controllers/handControllerGrab.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index f8fe1b821c..382d5cac7a 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -118,11 +118,13 @@ var DEFAULT_GRABBABLE_DATA = { //we've created various ways of visualizing looking for and moving distant objects var USE_ENTITY_LINES_FOR_SEARCHING = false; -var USE_ENTITY_LINES_FOR_MOVING = true; var USE_OVERLAY_LINES_FOR_SEARCHING = true; -var USE_OVERLAY_LINES_FOR_MOVING = false; var USE_PARTICLE_BEAM_FOR_SEARCHING = false; + +var USE_ENTITY_LINES_FOR_MOVING = true; +var USE_OVERLAY_LINES_FOR_MOVING = false; var USE_PARTICLE_BEAM_FOR_MOVING = false; + var USE_SPOTLIGHT = false; var USE_POINTLIGHT = false; From ab5b783cb7dbb3bf6f1878bf2f2e134ef331406e Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 14 Dec 2015 09:01:45 -0800 Subject: [PATCH 048/195] zone tweal --- examples/flowArts/lightTrails.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/flowArts/lightTrails.js b/examples/flowArts/lightTrails.js index e063897eb8..8e0dc98bbb 100644 --- a/examples/flowArts/lightTrails.js +++ b/examples/flowArts/lightTrails.js @@ -23,7 +23,7 @@ var MAX_POINTS_PER_LINE = 50; var LIFETIME = 6000; var DRAWING_DEPTH = 0.8; -var LINE_DIMENSIONS = 20; +var LINE_DIMENSIONS = 100; var lightZone = Entities.addEntity({ type: "Zone", @@ -78,9 +78,9 @@ function controller(side, triggerAction) { type: 'Light', position: MyAvatar.position, dimensions: { - x: 20, - y: 20, - z: 20 + x: 30, + y: 30, + z: 30 }, color: colorPalette[randInt(0, colorPalette.length)], intensity: 5 From e43b60f9f54c27b72e2377f32defe489647a415f Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 14 Dec 2015 11:40:47 -0800 Subject: [PATCH 049/195] other variations --- examples/controllers/handControllerGrab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 382d5cac7a..cd82db22b9 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -1105,7 +1105,7 @@ function MyController(hand) { this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); } if (USE_OVERLAY_LINES_FOR_MOVING === true) { - this.overlayLineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); + this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); } if (USE_PARTICLE_BEAM_FOR_MOVING === true) { this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) From 4d9cb6a6df3f3c07866ca4d6fa2170b939f7196b Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 14 Dec 2015 11:41:34 -0800 Subject: [PATCH 050/195] other variations --- .../handControllerGrab-all-overlays.js | 1649 +++++++++++++++++ .../handControllerGrab-particles.js | 1649 +++++++++++++++++ .../handControllerGrab-pointlight.js | 1649 +++++++++++++++++ .../handControllerGrab-spotlight.js | 1649 +++++++++++++++++ 4 files changed, 6596 insertions(+) create mode 100644 examples/controllers/handControllerGrab-all-overlays.js create mode 100644 examples/controllers/handControllerGrab-particles.js create mode 100644 examples/controllers/handControllerGrab-pointlight.js create mode 100644 examples/controllers/handControllerGrab-spotlight.js diff --git a/examples/controllers/handControllerGrab-all-overlays.js b/examples/controllers/handControllerGrab-all-overlays.js new file mode 100644 index 0000000000..acb47b2260 --- /dev/null +++ b/examples/controllers/handControllerGrab-all-overlays.js @@ -0,0 +1,1649 @@ +// handControllerGrab.js +// +// Created by Eric Levin on 9/2/15 +// Additions by James B. Pollack @imgntn on 9/24/2015 +// Additions By Seth Alves on 10/20/2015 +// Copyright 2015 High Fidelity, Inc. +// +// Grabs physically moveable entities with hydra-like controllers; it works for either near or far objects. +// Also supports touch and equipping objects. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ + +Script.include("../libraries/utils.js"); + +// +// add lines where the hand ray picking is happening +// +var WANT_DEBUG = false; + +// +// these tune time-averaging and "on" value for analog trigger +// + +var TRIGGER_SMOOTH_RATIO = 0.1; // 0.0 disables smoothing of trigger value +var TRIGGER_ON_VALUE = 0.4; +var TRIGGER_OFF_VALUE = 0.15; + +var BUMPER_ON_VALUE = 0.5; + +// +// distant manipulation +// + +var DISTANCE_HOLDING_RADIUS_FACTOR = 3.5; // multiplied by distance between hand and object +var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position +var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did +var MOVE_WITH_HEAD = true; // experimental head-controll of distantly held objects + +var NO_INTERSECT_COLOR = { + red: 10, + green: 10, + blue: 255 +}; // line color when pick misses +var INTERSECT_COLOR = { + red: 250, + green: 10, + blue: 10 +}; // line color when pick hits +var LINE_ENTITY_DIMENSIONS = { + x: 1000, + y: 1000, + z: 1000 +}; + +var LINE_LENGTH = 500; +var PICK_MAX_DISTANCE = 500; // max length of pick-ray + +// +// near grabbing +// + +var GRAB_RADIUS = 0.03; // if the ray misses but an object is this close, it will still be selected +var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position +var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held object's velocity. 1.0 to disable. +var NEAR_PICK_MAX_DISTANCE = 0.3; // max length of pick-ray for close grabbing to be selected +var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things +var PICK_BACKOFF_DISTANCE = 0.2; // helps when hand is intersecting the grabble object +var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed + +// +// equip +// + +var EQUIP_SPRING_SHUTOFF_DISTANCE = 0.05; +var EQUIP_SPRING_TIMEFRAME = 0.4; // how quickly objects move to their new position + +// +// other constants +// + +var RIGHT_HAND = 1; +var LEFT_HAND = 0; + +var ZERO_VEC = { + x: 0, + y: 0, + z: 0 +}; + +var NULL_ACTION_ID = "{00000000-0000-0000-000000000000}"; +var MSEC_PER_SEC = 1000.0; + +// these control how long an abandoned pointer line or action will hang around +var LIFETIME = 10; +var ACTION_TTL = 15; // seconds +var ACTION_TTL_REFRESH = 5; +var PICKS_PER_SECOND_PER_HAND = 5; +var MSECS_PER_SEC = 1000.0; +var GRABBABLE_PROPERTIES = [ + "position", + "rotation", + "gravity", + "ignoreForCollisions", + "collisionsWillMove", + "locked", + "name" +]; + +var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js +var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js + +var DEFAULT_GRABBABLE_DATA = { + grabbable: true, + invertSolidWhileHeld: false +}; + +//we've created various ways of visualizing looking for and moving distant objects +var USE_ENTITY_LINES_FOR_SEARCHING = false; +var USE_OVERLAY_LINES_FOR_SEARCHING = true; +var USE_PARTICLE_BEAM_FOR_SEARCHING = false; + +var USE_ENTITY_LINES_FOR_MOVING = false; +var USE_OVERLAY_LINES_FOR_MOVING = true; +var USE_PARTICLE_BEAM_FOR_MOVING = false; + +var USE_SPOTLIGHT = false; +var USE_POINTLIGHT = false; + +// states for the state machine +var STATE_OFF = 0; +var STATE_SEARCHING = 1; +var STATE_DISTANCE_HOLDING = 2; +var STATE_CONTINUE_DISTANCE_HOLDING = 3; +var STATE_NEAR_GRABBING = 4; +var STATE_CONTINUE_NEAR_GRABBING = 5; +var STATE_NEAR_TRIGGER = 6; +var STATE_CONTINUE_NEAR_TRIGGER = 7; +var STATE_FAR_TRIGGER = 8; +var STATE_CONTINUE_FAR_TRIGGER = 9; +var STATE_RELEASE = 10; +var STATE_EQUIP_SEARCHING = 11; +var STATE_EQUIP = 12 +var STATE_CONTINUE_EQUIP_BD = 13; // equip while bumper is still held down +var STATE_CONTINUE_EQUIP = 14; +var STATE_WAITING_FOR_BUMPER_RELEASE = 15; +var STATE_EQUIP_SPRING = 16; + + + +function stateToName(state) { + switch (state) { + case STATE_OFF: + return "off"; + case STATE_SEARCHING: + return "searching"; + case STATE_DISTANCE_HOLDING: + return "distance_holding"; + case STATE_CONTINUE_DISTANCE_HOLDING: + return "continue_distance_holding"; + case STATE_NEAR_GRABBING: + return "near_grabbing"; + case STATE_CONTINUE_NEAR_GRABBING: + return "continue_near_grabbing"; + case STATE_NEAR_TRIGGER: + return "near_trigger"; + case STATE_CONTINUE_NEAR_TRIGGER: + return "continue_near_trigger"; + case STATE_FAR_TRIGGER: + return "far_trigger"; + case STATE_CONTINUE_FAR_TRIGGER: + return "continue_far_trigger"; + case STATE_RELEASE: + return "release"; + case STATE_EQUIP_SEARCHING: + return "equip_searching"; + case STATE_EQUIP: + return "equip"; + case STATE_CONTINUE_EQUIP_BD: + return "continue_equip_bd"; + case STATE_CONTINUE_EQUIP: + return "continue_equip"; + case STATE_WAITING_FOR_BUMPER_RELEASE: + return "waiting_for_bumper_release"; + case STATE_EQUIP_SPRING: + return "state_equip_spring"; + } + + return "unknown"; +} + +function getTag() { + return "grab-" + MyAvatar.sessionUUID; +} + +function entityIsGrabbedByOther(entityID) { + // by convention, a distance grab sets the tag of its action to be grab-*owner-session-id*. + var actionIDs = Entities.getActionIDs(entityID); + for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { + var actionID = actionIDs[actionIndex]; + var actionArguments = Entities.getActionArguments(entityID, actionID); + var tag = actionArguments["tag"]; + if (tag == getTag()) { + // we see a grab-*uuid* shaped tag, but it's our tag, so that's okay. + continue; + } + if (tag.slice(0, 5) == "grab-") { + // we see a grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it. + return true; + } + } + return false; +} + +function getSpatialOffsetPosition(hand, spatialKey) { + var position = Vec3.ZERO; + + if (hand !== RIGHT_HAND && spatialKey.leftRelativePosition) { + position = spatialKey.leftRelativePosition; + } + if (hand === RIGHT_HAND && spatialKey.rightRelativePosition) { + position = spatialKey.rightRelativePosition; + } + if (spatialKey.relativePosition) { + position = spatialKey.relativePosition; + } + + return position; +} + +var yFlip = Quat.angleAxis(180, Vec3.UNIT_Y); + +function getSpatialOffsetRotation(hand, spatialKey) { + var rotation = Quat.IDENTITY; + + if (hand !== RIGHT_HAND && spatialKey.leftRelativeRotation) { + rotation = spatialKey.leftRelativeRotation; + } + if (hand === RIGHT_HAND && spatialKey.rightRelativeRotation) { + rotation = spatialKey.rightRelativeRotation; + } + if (spatialKey.relativeRotation) { + rotation = spatialKey.relativeRotation; + } + + // Flip left hand + if (hand !== RIGHT_HAND) { + rotation = Quat.multiply(yFlip, rotation); + } + + return rotation; +} + +function MyController(hand) { + this.hand = hand; + if (this.hand === RIGHT_HAND) { + this.getHandPosition = MyAvatar.getRightPalmPosition; + this.getHandRotation = MyAvatar.getRightPalmRotation; + } else { + this.getHandPosition = MyAvatar.getLeftPalmPosition; + this.getHandRotation = MyAvatar.getLeftPalmRotation; + } + + var SPATIAL_CONTROLLERS_PER_PALM = 2; + var TIP_CONTROLLER_OFFSET = 1; + this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand; + this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; + + this.actionID = null; // action this script created... + this.grabbedEntity = null; // on this entity. + this.state = STATE_OFF; + this.pointer = null; // entity-id of line object + this.triggerValue = 0; // rolling average of trigger value + this.rawTriggerValue = 0; + this.rawBumperValue = 0; + + //for visualizations + this.overlayLine = null; + this.particleBeam = null; + + //for lights + this.spotlight = null; + this.pointlight = null; + + this.ignoreIK = false; + this.offsetPosition = Vec3.ZERO; + this.offsetRotation = Quat.IDENTITY; + + var _this = this; + + this.update = function() { + + this.updateSmoothedTrigger(); + + switch (this.state) { + case STATE_OFF: + this.off(); + this.touchTest(); + break; + case STATE_SEARCHING: + this.search(); + break; + case STATE_EQUIP_SEARCHING: + this.search(); + break; + case STATE_DISTANCE_HOLDING: + this.distanceHolding(); + break; + case STATE_CONTINUE_DISTANCE_HOLDING: + this.continueDistanceHolding(); + break; + case STATE_NEAR_GRABBING: + case STATE_EQUIP: + this.nearGrabbing(); + break; + case STATE_WAITING_FOR_BUMPER_RELEASE: + this.waitingForBumperRelease(); + break; + case STATE_EQUIP_SPRING: + this.pullTowardEquipPosition() + break; + case STATE_CONTINUE_NEAR_GRABBING: + case STATE_CONTINUE_EQUIP_BD: + case STATE_CONTINUE_EQUIP: + this.continueNearGrabbing(); + break; + case STATE_NEAR_TRIGGER: + this.nearTrigger(); + break; + case STATE_CONTINUE_NEAR_TRIGGER: + this.continueNearTrigger(); + break; + case STATE_FAR_TRIGGER: + this.farTrigger(); + break; + case STATE_CONTINUE_FAR_TRIGGER: + this.continueFarTrigger(); + break; + case STATE_RELEASE: + this.release(); + break; + } + }; + + this.setState = function(newState) { + if (WANT_DEBUG) { + print("STATE: " + stateToName(this.state) + " --> " + stateToName(newState) + ", hand: " + this.hand); + } + this.state = newState; + }; + + this.debugLine = function(closePoint, farPoint, color) { + Entities.addEntity({ + type: "Line", + name: "Grab Debug Entity", + dimensions: LINE_ENTITY_DIMENSIONS, + visible: true, + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: 0.1, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + }; + + this.lineOn = function(closePoint, farPoint, color) { + // draw a line + if (this.pointer === null) { + this.pointer = Entities.addEntity({ + type: "Line", + name: "grab pointer", + dimensions: LINE_ENTITY_DIMENSIONS, + visible: true, + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: LIFETIME, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + } else { + var age = Entities.getEntityProperties(this.pointer, "age").age; + this.pointer = Entities.editEntity(this.pointer, { + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: age + LIFETIME + }); + } + }; + + this.overlayLineOn = function(closePoint, farPoint, color) { + if (this.overlayLine === null) { + var lineProperties = { + lineWidth: 5, + start: closePoint, + end: farPoint, + color: color, + ignoreRayIntersection: true, // always ignore this + visible: true, + alpha: 1 + }; + + this.overlayLine = Overlays.addOverlay("line3d", lineProperties); + + } else { + var success = Overlays.editOverlay(this.overlayLine, { + lineWidth: 5, + start: closePoint, + end: farPoint, + color: color, + visible: true, + ignoreRayIntersection: true, // always ignore this + alpha: 1 + }); + } + }; + + this.handleParticleBeam = function(position, orientation, color) { + + var rotation = Quat.angleAxis(0, { + x: 1, + y: 0, + z: 0 + }); + + var finalRotation = Quat.multiply(orientation, rotation); + + if (this.particleBeam === null) { + this.createParticleBeam(position, finalRotation, color); + } else { + this.updateParticleBeam(position, finalRotation, color); + } + }; + + this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { + + var handToObject = Vec3.subtract(objectPosition, handPosition); + var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); + + var distance = Vec3.distance(handPosition, objectPosition); + var speed = distance * 1; + + var lifepsan = distance / speed; + var lifespan = 1; + + if (this.particleBeam === null) { + this.createParticleBeam(objectPosition, finalRotation, color, speed); + } else { + this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); + } + }; + + this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { + + var particleBeamProperties = { + type: "ParticleEffect", + isEmitting: true, + position: position, + visible: false, + //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), + "name": "Particle Beam", + "color": color, + "maxParticles": 2000, + "lifespan": LINE_LENGTH / 10, + "emitRate": 50, + "emitSpeed": 5, + "speedSpread": 2, + "emitOrientation": { + "x": -1, + "y": 0, + "z": 0, + "w": 1 + }, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "emitRadiusStart": 0.5, + "polarStart": 0, + "polarFinish": 0, + "azimuthStart": -3.1415927410125732, + "azimuthFinish": 3.1415927410125732, + "emitAcceleration": { + x: 0, + y: 0, + z: 0 + }, + "accelerationSpread": { + "x": 0, + "y": 0, + "z": 0 + }, + "particleRadius": 0.01, + "radiusSpread": 0, + // "radiusStart": 0.01, + // "radiusFinish": 0.01, + // "colorSpread": { + // "red": 0, + // "green": 0, + // "blue": 0 + // }, + // "colorStart": color, + // "colorFinish": color, + "alpha": 1, + "alphaSpread": 0, + "alphaStart": 1, + "alphaFinish": 1, + "additiveBlending": 1, + "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" + } + + this.particleBeam = Entities.addEntity(particleBeamProperties); + }; + + this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { + + Entities.editEntity(this.particleBeam, { + rotation: orientation, + position: position, + visible: true, + color: color, + emitSpeed: speed, + lifepsan: lifepsan + + }) + + }; + + this.evalLightWorldTransform = function(modelPos, modelRot) { + + var MODEL_LIGHT_POSITION = { + x: 0, + y: -0.3, + z: 0 + }; + + var MODEL_LIGHT_ROTATION = Quat.angleAxis(-90, { + x: 1, + y: 0, + z: 0 + }); + + return { + p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), + q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) + }; + }; + + this.handleSpotlight = function(parentID, position) { + var LIFETIME = 100; + + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); + + var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + var lightProperties = { + type: "Light", + isSpotlight: true, + dimensions: { + x: 2, + y: 2, + z: 20 + }, + parentID: parentID, + color: { + red: 255, + green: 255, + blue: 255 + }, + intensity: 2, + exponent: 0.3, + cutoff: 20, + lifetime: LIFETIME, + position: lightTransform.p, + }; + + if (this.spotlight === null) { + this.spotlight = Entities.addEntity(lightProperties); + } else { + Entities.editEntity(this.spotlight, { + //without this, this light would maintain rotation with its parent + rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0), + }) + } + }; + + this.handlePointLight = function(parentID, position) { + var LIFETIME = 100; + + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); + var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + + var lightProperties = { + type: "Light", + isSpotlight: false, + dimensions: { + x: 2, + y: 2, + z: 20 + }, + parentID: parentID, + color: { + red: 255, + green: 255, + blue: 255 + }, + intensity: 2, + exponent: 0.3, + cutoff: 20, + lifetime: LIFETIME, + position: lightTransform.p, + }; + + if (this.pointlight === null) { + this.pointlight = Entities.addEntity(lightProperties); + } else { + + } + }; + + this.lineOff = function() { + if (this.pointer !== null) { + Entities.deleteEntity(this.pointer); + } + this.pointer = null; + }; + + this.overlayLineOff = function() { + if (this.overlayLine !== null) { + Overlays.deleteOverlay(this.overlayLine); + } + this.overlayLine = null; + }; + + this.particleBeamOff = function() { + if (this.particleBeam !== null) { + Entities.editEntity(this.particleBeam, { + visible: false + }) + } + } + + this.turnLightsOff = function() { + if (this.spotlight !== null) { + Entities.deleteEntity(this.spotlight); + this.spotlight = null; + } + + if (this.pointlight !== null) { + Entities.deleteEntity(this.pointlight); + this.pointlight = null; + } + }; + + + this.turnOffVisualizations = function() { + if (USE_ENTITY_LINES_FOR_SEARCHING === true || USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOff(); + } + + if (USE_OVERLAY_LINES_FOR_SEARCHING === true || USE_OVERLAY_LINES_FOR_MOVING === true) { + this.overlayLineOff(); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.particleBeamOff(); + } + }; + + this.triggerPress = function(value) { + _this.rawTriggerValue = value; + }; + + this.bumperPress = function(value) { + _this.rawBumperValue = value; + }; + + this.updateSmoothedTrigger = function() { + var triggerValue = this.rawTriggerValue; + // smooth out trigger value + this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + + (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); + }; + + this.triggerSmoothedSqueezed = function() { + return this.triggerValue > TRIGGER_ON_VALUE; + }; + + this.triggerSmoothedReleased = function() { + return this.triggerValue < TRIGGER_OFF_VALUE; + }; + + this.triggerSqueezed = function() { + var triggerValue = this.rawTriggerValue; + return triggerValue > TRIGGER_ON_VALUE; + }; + + this.bumperSqueezed = function() { + return _this.rawBumperValue > BUMPER_ON_VALUE; + }; + + this.bumperReleased = function() { + return _this.rawBumperValue < BUMPER_ON_VALUE; + }; + + this.off = function() { + if (this.triggerSmoothedSqueezed()) { + this.lastPickTime = 0; + this.setState(STATE_SEARCHING); + return; + } + if (this.bumperSqueezed()) { + this.lastPickTime = 0; + this.setState(STATE_EQUIP_SEARCHING); + return; + } + }; + + this.search = function() { + this.grabbedEntity = null; + + if (this.state == STATE_SEARCHING ? this.triggerSmoothedReleased() : this.bumperReleased()) { + this.setState(STATE_RELEASE); + return; + } + + // the trigger is being pressed, do a ray test + var handPosition = this.getHandPosition(); + var distantPickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()), + length: PICK_MAX_DISTANCE + }; + + // don't pick 60x per second. + var pickRays = []; + var now = Date.now(); + if (now - this.lastPickTime > MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) { + pickRays = [distantPickRay]; + this.lastPickTime = now; + } + + for (var index = 0; index < pickRays.length; ++index) { + var pickRay = pickRays[index]; + var directionNormalized = Vec3.normalize(pickRay.direction); + var directionBacked = Vec3.multiply(directionNormalized, PICK_BACKOFF_DISTANCE); + var pickRayBacked = { + origin: Vec3.subtract(pickRay.origin, directionBacked), + direction: pickRay.direction + }; + + if (WANT_DEBUG) { + this.debugLine(pickRayBacked.origin, Vec3.multiply(pickRayBacked.direction, NEAR_PICK_MAX_DISTANCE), { + red: 0, + green: 255, + blue: 0 + }) + } + + var intersection = Entities.findRayIntersection(pickRayBacked, true); + + if (intersection.intersects) { + // the ray is intersecting something we can move. + var intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection); + + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, intersection.entityID, DEFAULT_GRABBABLE_DATA); + + if (intersection.properties.name == "Grab Debug Entity") { + continue; + } + + if (typeof grabbableData.grabbable !== 'undefined' && !grabbableData.grabbable) { + continue; + } + if (intersectionDistance > pickRay.length) { + // too far away for this ray. + continue; + } + if (intersectionDistance <= NEAR_PICK_MAX_DISTANCE) { + // the hand is very close to the intersected object. go into close-grabbing mode. + if (grabbableData.wantsTrigger) { + this.grabbedEntity = intersection.entityID; + this.setState(STATE_NEAR_TRIGGER); + return; + } else if (!intersection.properties.locked) { + this.grabbedEntity = intersection.entityID; + if (this.state == STATE_SEARCHING) { + this.setState(STATE_NEAR_GRABBING); + } else { // equipping + if (typeof grabbableData.spatialKey !== 'undefined') { + // TODO + // if we go to STATE_EQUIP_SPRING the item will be pulled to the hand and will then switch + // to STATE_EQUIP. This needs some debugging, so just jump straight to STATE_EQUIP here. + // this.setState(STATE_EQUIP_SPRING); + this.setState(STATE_EQUIP); + } else { + this.setState(STATE_EQUIP); + } + } + return; + } + } else if (!entityIsGrabbedByOther(intersection.entityID)) { + // don't allow two people to distance grab the same object + if (intersection.properties.collisionsWillMove && !intersection.properties.locked) { + // the hand is far from the intersected object. go into distance-holding mode + this.grabbedEntity = intersection.entityID; + if (typeof grabbableData.spatialKey !== 'undefined' && this.state == STATE_EQUIP_SEARCHING) { + // if a distance pick in equip mode hits something with a spatialKey, equip it + // TODO use STATE_EQUIP_SPRING here once it works right. + // this.setState(STATE_EQUIP_SPRING); + this.setState(STATE_EQUIP); + return; + } else if (this.state == STATE_SEARCHING) { + this.setState(STATE_DISTANCE_HOLDING); + return; + } + } else if (grabbableData.wantsTrigger) { + this.grabbedEntity = intersection.entityID; + this.setState(STATE_FAR_TRIGGER); + return; + } + } + } + } + + // forward ray test failed, try sphere test. + if (WANT_DEBUG) { + Entities.addEntity({ + type: "Sphere", + name: "Grab Debug Entity", + dimensions: { + x: GRAB_RADIUS, + y: GRAB_RADIUS, + z: GRAB_RADIUS + }, + visible: true, + position: handPosition, + color: { + red: 0, + green: 255, + blue: 0 + }, + lifetime: 0.1, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + } + + var nearbyEntities = Entities.findEntities(handPosition, GRAB_RADIUS); + var minDistance = PICK_MAX_DISTANCE; + var i, props, distance, grabbableData; + this.grabbedEntity = null; + for (i = 0; i < nearbyEntities.length; i++) { + var grabbableDataForCandidate = + getEntityCustomData(GRABBABLE_DATA_KEY, nearbyEntities[i], DEFAULT_GRABBABLE_DATA); + if (typeof grabbableDataForCandidate.grabbable !== 'undefined' && !grabbableDataForCandidate.grabbable) { + continue; + } + var propsForCandidate = Entities.getEntityProperties(nearbyEntities[i], GRABBABLE_PROPERTIES); + + if (propsForCandidate.type == 'Unknown') { + continue; + } + + if (propsForCandidate.type == 'Light') { + continue; + } + + if (propsForCandidate.type == 'ParticleEffect') { + continue; + } + + if (propsForCandidate.type == 'PolyLine') { + continue; + } + + if (propsForCandidate.type == 'Zone') { + continue; + } + + if (propsForCandidate.locked && !grabbableDataForCandidate.wantsTrigger) { + continue; + } + + if (propsForCandidate.name == "Grab Debug Entity") { + continue; + } + + if (propsForCandidate.name == "grab pointer") { + continue; + } + + distance = Vec3.distance(propsForCandidate.position, handPosition); + if (distance < minDistance) { + this.grabbedEntity = nearbyEntities[i]; + minDistance = distance; + props = propsForCandidate; + grabbableData = grabbableDataForCandidate; + } + } + if (this.grabbedEntity !== null) { + if (grabbableData.wantsTrigger) { + this.setState(STATE_NEAR_TRIGGER); + return; + } else if (!props.locked && props.collisionsWillMove) { + this.setState(this.state == STATE_SEARCHING ? STATE_NEAR_GRABBING : STATE_EQUIP) + return; + } + } + + //search line visualizations + if (USE_ENTITY_LINES_FOR_SEARCHING === true) { + this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + } + + if (USE_OVERLAY_LINES_FOR_SEARCHING === true) { + this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true) { + this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR); + } + + }; + + this.distanceHolding = function() { + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var now = Date.now(); + + // add the action and initialize some variables + this.currentObjectPosition = grabbedProperties.position; + this.currentObjectRotation = grabbedProperties.rotation; + this.currentObjectTime = now; + this.handRelativePreviousPosition = Vec3.subtract(handControllerPosition, MyAvatar.position); + this.handPreviousRotation = handRotation; + this.currentCameraOrientation = Camera.orientation; + + // compute a constant based on the initial conditions which we use below to exagerate hand motion onto the held object + this.radiusScalar = Math.log(Vec3.distance(this.currentObjectPosition, handControllerPosition) + 1.0); + if (this.radiusScalar < 1.0) { + this.radiusScalar = 1.0; + } + + this.actionID = NULL_ACTION_ID; + this.actionID = Entities.addAction("spring", this.grabbedEntity, { + targetPosition: this.currentObjectPosition, + linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + targetRotation: this.currentObjectRotation, + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + tag: getTag(), + ttl: ACTION_TTL + }); + if (this.actionID === NULL_ACTION_ID) { + this.actionID = null; + } + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + + if (this.actionID !== null) { + this.setState(STATE_CONTINUE_DISTANCE_HOLDING); + this.activateEntity(this.grabbedEntity, grabbedProperties); + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab"); + } + + this.currentAvatarPosition = MyAvatar.position; + this.currentAvatarOrientation = MyAvatar.orientation; + + this.turnOffVisualizations(); + }; + + this.continueDistanceHolding = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + + var handPosition = this.getHandPosition(); + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state == STATE_CONTINUE_DISTANCE_HOLDING && this.bumperSqueezed() && + typeof grabbableData.spatialKey !== 'undefined') { + var saveGrabbedID = this.grabbedEntity; + this.release(); + this.setState(STATE_EQUIP); + this.grabbedEntity = saveGrabbedID; + return; + } + + + // the action was set up on a previous call. update the targets. + var radius = Vec3.distance(this.currentObjectPosition, handControllerPosition) * + this.radiusScalar * DISTANCE_HOLDING_RADIUS_FACTOR; + if (radius < 1.0) { + radius = 1.0; + } + + // how far did avatar move this timestep? + var currentPosition = MyAvatar.position; + var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition); + this.currentAvatarPosition = currentPosition; + + // How far did the avatar turn this timestep? + // Note: The following code is too long because we need a Quat.quatBetween() function + // that returns the minimum quaternion between two quaternions. + var currentOrientation = MyAvatar.orientation; + if (Quat.dot(currentOrientation, this.currentAvatarOrientation) < 0.0) { + var negativeCurrentOrientation = { + x: -currentOrientation.x, + y: -currentOrientation.y, + z: -currentOrientation.z, + w: -currentOrientation.w + }; + var avatarDeltaOrientation = Quat.multiply(negativeCurrentOrientation, Quat.inverse(this.currentAvatarOrientation)); + } else { + var avatarDeltaOrientation = Quat.multiply(currentOrientation, Quat.inverse(this.currentAvatarOrientation)); + } + var handToAvatar = Vec3.subtract(handControllerPosition, this.currentAvatarPosition); + var objectToAvatar = Vec3.subtract(this.currentObjectPosition, this.currentAvatarPosition); + var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar); + var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar); + this.currentAvatarOrientation = currentOrientation; + + // how far did hand move this timestep? + var handMoved = Vec3.subtract(handToAvatar, this.handRelativePreviousPosition); + this.handRelativePreviousPosition = handToAvatar; + + // magnify the hand movement but not the change from avatar movement & rotation + handMoved = Vec3.subtract(handMoved, handMovementFromTurning); + var superHandMoved = Vec3.multiply(handMoved, radius); + + // Move the object by the magnified amount and then by amount from avatar movement & rotation + var newObjectPosition = Vec3.sum(this.currentObjectPosition, superHandMoved); + newObjectPosition = Vec3.sum(newObjectPosition, avatarDeltaPosition); + newObjectPosition = Vec3.sum(newObjectPosition, objectMovementFromTurning); + + var deltaPosition = Vec3.subtract(newObjectPosition, this.currentObjectPosition); // meters + var now = Date.now(); + var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds + + this.currentObjectPosition = newObjectPosition; + this.currentObjectTime = now; + + // this doubles hand rotation + var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, + handRotation, + DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR), + Quat.inverse(this.handPreviousRotation)); + this.handPreviousRotation = handRotation; + this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation); + + Entities.callEntityMethod(this.grabbedEntity, "continueDistantGrab"); + + // mix in head motion + if (MOVE_WITH_HEAD) { + var objDistance = Vec3.length(objectToAvatar); + var before = Vec3.multiplyQbyV(this.currentCameraOrientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); + var after = Vec3.multiplyQbyV(Camera.orientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); + var change = Vec3.subtract(before, after); + this.currentCameraOrientation = Camera.orientation; + this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change); + } + + + //visualizations + if (USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); + } + if (USE_OVERLAY_LINES_FOR_MOVING === true) { + this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); + } + if (USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + } + if (USE_POINTLIGHT === true) { + this.handlePointLight(this.grabbedEntity); + } + if (USE_SPOTLIGHT === true) { + this.handleSpotlight(this.grabbedEntity); + } + + Entities.updateAction(this.grabbedEntity, this.actionID, { + targetPosition: this.currentObjectPosition, + linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + targetRotation: this.currentObjectRotation, + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + ttl: ACTION_TTL + }); + + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + }; + + this.nearGrabbing = function() { + var now = Date.now(); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + + this.turnOffVisualizations(); + + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + this.activateEntity(this.grabbedEntity, grabbedProperties); + if (grabbedProperties.collisionsWillMove && NEAR_GRABBING_KINEMATIC) { + Entities.editEntity(this.grabbedEntity, { + collisionsWillMove: false + }); + } + + var handRotation = this.getHandRotation(); + var handPosition = this.getHandPosition(); + + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) { + // if an object is "equipped" and has a spatialKey, use it. + this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; + this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); + this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + } else { + this.ignoreIK = false; + + var objectRotation = grabbedProperties.rotation; + this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); + + var currentObjectPosition = grabbedProperties.position; + var offset = Vec3.subtract(currentObjectPosition, handPosition); + this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset); + } + + this.actionID = NULL_ACTION_ID; + this.actionID = Entities.addAction("hold", this.grabbedEntity, { + hand: this.hand === RIGHT_HAND ? "right" : "left", + timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, + relativePosition: this.offsetPosition, + relativeRotation: this.offsetRotation, + ttl: ACTION_TTL, + kinematic: NEAR_GRABBING_KINEMATIC, + kinematicSetVelocity: true, + ignoreIK: this.ignoreIK + }); + if (this.actionID === NULL_ACTION_ID) { + this.actionID = null; + } else { + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + if (this.state == STATE_NEAR_GRABBING) { + this.setState(STATE_CONTINUE_NEAR_GRABBING); + } else { + // equipping + Entities.callEntityMethod(this.grabbedEntity, "startEquip", [JSON.stringify(this.hand)]); + this.startHandGrasp(); + + this.setState(STATE_CONTINUE_EQUIP_BD); + } + + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + + Entities.callEntityMethod(this.grabbedEntity, "startNearGrab"); + + } + + this.currentHandControllerTipPosition = + (this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition; + + this.currentObjectTime = Date.now(); + }; + + this.continueNearGrabbing = function() { + if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + if (this.state == STATE_CONTINUE_EQUIP_BD && this.bumperReleased()) { + this.setState(STATE_CONTINUE_EQUIP); + return; + } + if (this.state == STATE_CONTINUE_EQUIP && this.bumperSqueezed()) { + this.setState(STATE_WAITING_FOR_BUMPER_RELEASE); + return; + } + if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.bumperSqueezed()) { + this.setState(STATE_CONTINUE_EQUIP_BD); + Entities.callEntityMethod(this.grabbedEntity, "startEquip", [JSON.stringify(this.hand)]); + return; + } + + // Keep track of the fingertip velocity to impart when we release the object. + // Note that the idea of using a constant 'tip' velocity regardless of the + // object's actual held offset is an idea intended to make it easier to throw things: + // Because we might catch something or transfer it between hands without a good idea + // of it's actual offset, let's try imparting a velocity which is at a fixed radius + // from the palm. + + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var now = Date.now(); + + var deltaPosition = Vec3.subtract(handControllerPosition, this.currentHandControllerTipPosition); // meters + var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds + + this.currentHandControllerTipPosition = handControllerPosition; + this.currentObjectTime = now; + Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); + + if (this.state === STATE_CONTINUE_EQUIP_BD) { + Entities.callEntityMethod(this.grabbedEntity, "continueEquip"); + } + + if (this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) { + // if less than a 5 seconds left, refresh the actions ttl + Entities.updateAction(this.grabbedEntity, this.actionID, { + hand: this.hand === RIGHT_HAND ? "right" : "left", + timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, + relativePosition: this.offsetPosition, + relativeRotation: this.offsetRotation, + ttl: ACTION_TTL, + kinematic: NEAR_GRABBING_KINEMATIC, + kinematicSetVelocity: true, + ignoreIK: this.ignoreIK + }); + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + } + }; + + this.waitingForBumperRelease = function() { + if (this.bumperReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + Entities.callEntityMethod(this.grabbedEntity, "unequip"); + this.endHandGrasp(); + + } + }; + + this.pullTowardEquipPosition = function() { + + this.turnOffVisualizations(); + + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + // use a spring to pull the object to where it will be when equipped + var relativeRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + var relativePosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); + var ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; + var handRotation = this.getHandRotation(); + var handPosition = this.getHandPosition(); + var targetRotation = Quat.multiply(handRotation, relativeRotation); + var offset = Vec3.multiplyQbyV(targetRotation, relativePosition); + var targetPosition = Vec3.sum(handPosition, offset); + + if (typeof this.equipSpringID === 'undefined' || + this.equipSpringID === null || + this.equipSpringID === NULL_ACTION_ID) { + this.equipSpringID = Entities.addAction("spring", this.grabbedEntity, { + targetPosition: targetPosition, + linearTimeScale: EQUIP_SPRING_TIMEFRAME, + targetRotation: targetRotation, + angularTimeScale: EQUIP_SPRING_TIMEFRAME, + ttl: ACTION_TTL, + ignoreIK: ignoreIK + }); + if (this.equipSpringID === NULL_ACTION_ID) { + this.equipSpringID = null; + this.setState(STATE_OFF); + return; + } + } else { + Entities.updateAction(this.grabbedEntity, this.equipSpringID, { + targetPosition: targetPosition, + linearTimeScale: EQUIP_SPRING_TIMEFRAME, + targetRotation: targetRotation, + angularTimeScale: EQUIP_SPRING_TIMEFRAME, + ttl: ACTION_TTL, + ignoreIK: ignoreIK + }); + } + + if (Vec3.distance(grabbedProperties.position, targetPosition) < EQUIP_SPRING_SHUTOFF_DISTANCE) { + Entities.deleteAction(this.grabbedEntity, this.equipSpringID); + this.equipSpringID = null; + this.setState(STATE_EQUIP); + } + }; + + this.nearTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + + Entities.callEntityMethod(this.grabbedEntity, "startNearTrigger"); + this.setState(STATE_CONTINUE_NEAR_TRIGGER); + }; + + this.farTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopFarTrigger"); + return; + } + + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + Entities.callEntityMethod(this.grabbedEntity, "startFarTrigger"); + this.setState(STATE_CONTINUE_FAR_TRIGGER); + }; + + this.continueNearTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + + Entities.callEntityMethod(this.grabbedEntity, "continueNearTrigger"); + }; + + this.continueFarTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + + var handPosition = this.getHandPosition(); + var pickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()) + }; + + var now = Date.now(); + if (now - this.lastPickTime > MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) { + var intersection = Entities.findRayIntersection(pickRay, true); + this.lastPickTime = now; + if (intersection.entityID != this.grabbedEntity) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopFarTrigger"); + return; + } + } + + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger"); + }; + + _this.allTouchedIDs = {}; + + this.touchTest = function() { + var maxDistance = 0.05; + var leftHandPosition = MyAvatar.getLeftPalmPosition(); + var rightHandPosition = MyAvatar.getRightPalmPosition(); + var leftEntities = Entities.findEntities(leftHandPosition, maxDistance); + var rightEntities = Entities.findEntities(rightHandPosition, maxDistance); + var ids = []; + + if (leftEntities.length !== 0) { + leftEntities.forEach(function(entity) { + ids.push(entity); + }); + + } + + if (rightEntities.length !== 0) { + rightEntities.forEach(function(entity) { + ids.push(entity); + }); + } + + ids.forEach(function(id) { + + var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); + if (props.name === 'pointer') { + return; + } else { + var entityMinPoint = props.boundingBox.brn; + var entityMaxPoint = props.boundingBox.tfl; + var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); + var rightIsTouching = pointInExtents(rightHandPosition, entityMinPoint, entityMaxPoint); + + if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id] === undefined) { + // we haven't been touched before, but either right or left is touching us now + _this.allTouchedIDs[id] = true; + _this.startTouch(id); + } else if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id]) { + // we have been touched before and are still being touched + // continue touch + _this.continueTouch(id); + } else if (_this.allTouchedIDs[id]) { + delete _this.allTouchedIDs[id]; + _this.stopTouch(id); + + } else { + //we are in another state + return; + } + } + + }); + + }; + + this.startTouch = function(entityID) { + Entities.callEntityMethod(entityID, "startTouch"); + }; + + this.continueTouch = function(entityID) { + Entities.callEntityMethod(entityID, "continueTouch"); + }; + + this.stopTouch = function(entityID) { + Entities.callEntityMethod(entityID, "stopTouch"); + }; + + this.release = function() { + + this.turnLightsOff(); + this.turnOffVisualizations(); + + if (this.grabbedEntity !== null) { + if (this.actionID !== null) { + Entities.deleteAction(this.grabbedEntity, this.actionID); + } + } + + this.deactivateEntity(this.grabbedEntity); + + this.grabbedEntity = null; + this.actionID = null; + this.setState(STATE_OFF); + }; + + this.cleanup = function() { + this.release(); + this.endHandGrasp(); + Entities.deleteEntity(this.particleBeam); + Entities.deleteEntity(this.spotLight); + Entities.deleteEntity(this.pointLight); + }; + + this.activateEntity = function(entityID, grabbedProperties) { + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, entityID, DEFAULT_GRABBABLE_DATA); + var invertSolidWhileHeld = grabbableData["invertSolidWhileHeld"]; + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + data["activated"] = true; + data["avatarId"] = MyAvatar.sessionUUID; + data["refCount"] = data["refCount"] ? data["refCount"] + 1 : 1; + // zero gravity and set ignoreForCollisions in a way that lets us put them back, after all grabs are done + if (data["refCount"] == 1) { + data["gravity"] = grabbedProperties.gravity; + data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions; + data["collisionsWillMove"] = grabbedProperties.collisionsWillMove; + var whileHeldProperties = { + gravity: { + x: 0, + y: 0, + z: 0 + } + }; + if (invertSolidWhileHeld) { + whileHeldProperties["ignoreForCollisions"] = !grabbedProperties.ignoreForCollisions; + } + Entities.editEntity(entityID, whileHeldProperties); + } + + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + return data; + }; + + this.deactivateEntity = function(entityID) { + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + if (data && data["refCount"]) { + data["refCount"] = data["refCount"] - 1; + if (data["refCount"] < 1) { + Entities.editEntity(entityID, { + gravity: data["gravity"], + ignoreForCollisions: data["ignoreForCollisions"], + collisionsWillMove: data["collisionsWillMove"] + }); + data = null; + } + } else { + data = null; + } + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + }; + + + //this is our handler, where we do the actual work of changing animation settings + this.graspHand = function(animationProperties) { + var result = {}; + //full alpha on overlay for this hand + //set grab to true + //set idle to false + //full alpha on the blend btw open and grab + if (_this.hand === RIGHT_HAND) { + result['rightHandOverlayAlpha'] = 1.0; + result['isRightHandGrab'] = true; + result['isRightHandIdle'] = false; + result['rightHandGrabBlend'] = 1.0; + } else if (_this.hand === LEFT_HAND) { + result['leftHandOverlayAlpha'] = 1.0; + result['isLeftHandGrab'] = true; + result['isLeftHandIdle'] = false; + result['leftHandGrabBlend'] = 1.0; + } + //return an object with our updated settings + return result; + }; + + this.graspHandler = null + + this.startHandGrasp = function() { + if (this.hand === RIGHT_HAND) { + this.graspHandler = MyAvatar.addAnimationStateHandler(this.graspHand, ['isRightHandGrab']); + } else if (this.hand === LEFT_HAND) { + this.graspHandler = MyAvatar.addAnimationStateHandler(this.graspHand, ['isLeftHandGrab']); + } + }; + + this.endHandGrasp = function() { + // Tell the animation system we don't need any more callbacks. + MyAvatar.removeAnimationStateHandler(this.graspHandler); + }; + +}; + +var rightController = new MyController(RIGHT_HAND); +var leftController = new MyController(LEFT_HAND); + +//preload the particle beams so that they are full length when you start searching +if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + rightController.createParticleBeam(); + leftController.createParticleBeam(); +} + +var MAPPING_NAME = "com.highfidelity.handControllerGrab"; + +var mapping = Controller.newMapping(MAPPING_NAME); +mapping.from([Controller.Standard.RT]).peek().to(rightController.triggerPress); +mapping.from([Controller.Standard.LT]).peek().to(leftController.triggerPress); + +mapping.from([Controller.Standard.RB]).peek().to(rightController.bumperPress); +mapping.from([Controller.Standard.LB]).peek().to(leftController.bumperPress); + +Controller.enableMapping(MAPPING_NAME); + +//the section below allows the grab script to listen for messages that disable either one or both hands. useful for two handed items +var handToDisable = 'none'; + +function update() { + if (handToDisable !== LEFT_HAND && handToDisable !== 'both') { + leftController.update(); + } + if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') { + rightController.update(); + } +} + +Messages.subscribe('Hifi-Hand-Disabler'); + +handleHandDisablerMessages = function(channel, message, sender) { + + if (sender === MyAvatar.sessionUUID) { + if (message === 'left') { + handToDisable = LEFT_HAND; + } + if (message === 'right') { + handToDisable = RIGHT_HAND; + } + if (message === 'both') { + handToDisable = 'both'; + } + if (message === 'none') { + handToDisable = 'none'; + } + } + +} + +Messages.messageReceived.connect(handleHandDisablerMessages); + +function cleanup() { + rightController.cleanup(); + leftController.cleanup(); + Controller.disableMapping(MAPPING_NAME); +} + +Script.scriptEnding.connect(cleanup); +Script.update.connect(update); \ No newline at end of file diff --git a/examples/controllers/handControllerGrab-particles.js b/examples/controllers/handControllerGrab-particles.js new file mode 100644 index 0000000000..d9ecb18b01 --- /dev/null +++ b/examples/controllers/handControllerGrab-particles.js @@ -0,0 +1,1649 @@ +// handControllerGrab.js +// +// Created by Eric Levin on 9/2/15 +// Additions by James B. Pollack @imgntn on 9/24/2015 +// Additions By Seth Alves on 10/20/2015 +// Copyright 2015 High Fidelity, Inc. +// +// Grabs physically moveable entities with hydra-like controllers; it works for either near or far objects. +// Also supports touch and equipping objects. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ + +Script.include("../libraries/utils.js"); + +// +// add lines where the hand ray picking is happening +// +var WANT_DEBUG = false; + +// +// these tune time-averaging and "on" value for analog trigger +// + +var TRIGGER_SMOOTH_RATIO = 0.1; // 0.0 disables smoothing of trigger value +var TRIGGER_ON_VALUE = 0.4; +var TRIGGER_OFF_VALUE = 0.15; + +var BUMPER_ON_VALUE = 0.5; + +// +// distant manipulation +// + +var DISTANCE_HOLDING_RADIUS_FACTOR = 3.5; // multiplied by distance between hand and object +var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position +var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did +var MOVE_WITH_HEAD = true; // experimental head-controll of distantly held objects + +var NO_INTERSECT_COLOR = { + red: 10, + green: 10, + blue: 255 +}; // line color when pick misses +var INTERSECT_COLOR = { + red: 250, + green: 10, + blue: 10 +}; // line color when pick hits +var LINE_ENTITY_DIMENSIONS = { + x: 1000, + y: 1000, + z: 1000 +}; + +var LINE_LENGTH = 500; +var PICK_MAX_DISTANCE = 500; // max length of pick-ray + +// +// near grabbing +// + +var GRAB_RADIUS = 0.03; // if the ray misses but an object is this close, it will still be selected +var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position +var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held object's velocity. 1.0 to disable. +var NEAR_PICK_MAX_DISTANCE = 0.3; // max length of pick-ray for close grabbing to be selected +var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things +var PICK_BACKOFF_DISTANCE = 0.2; // helps when hand is intersecting the grabble object +var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed + +// +// equip +// + +var EQUIP_SPRING_SHUTOFF_DISTANCE = 0.05; +var EQUIP_SPRING_TIMEFRAME = 0.4; // how quickly objects move to their new position + +// +// other constants +// + +var RIGHT_HAND = 1; +var LEFT_HAND = 0; + +var ZERO_VEC = { + x: 0, + y: 0, + z: 0 +}; + +var NULL_ACTION_ID = "{00000000-0000-0000-000000000000}"; +var MSEC_PER_SEC = 1000.0; + +// these control how long an abandoned pointer line or action will hang around +var LIFETIME = 10; +var ACTION_TTL = 15; // seconds +var ACTION_TTL_REFRESH = 5; +var PICKS_PER_SECOND_PER_HAND = 5; +var MSECS_PER_SEC = 1000.0; +var GRABBABLE_PROPERTIES = [ + "position", + "rotation", + "gravity", + "ignoreForCollisions", + "collisionsWillMove", + "locked", + "name" +]; + +var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js +var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js + +var DEFAULT_GRABBABLE_DATA = { + grabbable: true, + invertSolidWhileHeld: false +}; + +//we've created various ways of visualizing looking for and moving distant objects +var USE_ENTITY_LINES_FOR_SEARCHING = false; +var USE_OVERLAY_LINES_FOR_SEARCHING = false; +var USE_PARTICLE_BEAM_FOR_SEARCHING = true; + +var USE_ENTITY_LINES_FOR_MOVING = false; +var USE_OVERLAY_LINES_FOR_MOVING = false; +var USE_PARTICLE_BEAM_FOR_MOVING = true; + +var USE_SPOTLIGHT = false; +var USE_POINTLIGHT = false; + +// states for the state machine +var STATE_OFF = 0; +var STATE_SEARCHING = 1; +var STATE_DISTANCE_HOLDING = 2; +var STATE_CONTINUE_DISTANCE_HOLDING = 3; +var STATE_NEAR_GRABBING = 4; +var STATE_CONTINUE_NEAR_GRABBING = 5; +var STATE_NEAR_TRIGGER = 6; +var STATE_CONTINUE_NEAR_TRIGGER = 7; +var STATE_FAR_TRIGGER = 8; +var STATE_CONTINUE_FAR_TRIGGER = 9; +var STATE_RELEASE = 10; +var STATE_EQUIP_SEARCHING = 11; +var STATE_EQUIP = 12 +var STATE_CONTINUE_EQUIP_BD = 13; // equip while bumper is still held down +var STATE_CONTINUE_EQUIP = 14; +var STATE_WAITING_FOR_BUMPER_RELEASE = 15; +var STATE_EQUIP_SPRING = 16; + + + +function stateToName(state) { + switch (state) { + case STATE_OFF: + return "off"; + case STATE_SEARCHING: + return "searching"; + case STATE_DISTANCE_HOLDING: + return "distance_holding"; + case STATE_CONTINUE_DISTANCE_HOLDING: + return "continue_distance_holding"; + case STATE_NEAR_GRABBING: + return "near_grabbing"; + case STATE_CONTINUE_NEAR_GRABBING: + return "continue_near_grabbing"; + case STATE_NEAR_TRIGGER: + return "near_trigger"; + case STATE_CONTINUE_NEAR_TRIGGER: + return "continue_near_trigger"; + case STATE_FAR_TRIGGER: + return "far_trigger"; + case STATE_CONTINUE_FAR_TRIGGER: + return "continue_far_trigger"; + case STATE_RELEASE: + return "release"; + case STATE_EQUIP_SEARCHING: + return "equip_searching"; + case STATE_EQUIP: + return "equip"; + case STATE_CONTINUE_EQUIP_BD: + return "continue_equip_bd"; + case STATE_CONTINUE_EQUIP: + return "continue_equip"; + case STATE_WAITING_FOR_BUMPER_RELEASE: + return "waiting_for_bumper_release"; + case STATE_EQUIP_SPRING: + return "state_equip_spring"; + } + + return "unknown"; +} + +function getTag() { + return "grab-" + MyAvatar.sessionUUID; +} + +function entityIsGrabbedByOther(entityID) { + // by convention, a distance grab sets the tag of its action to be grab-*owner-session-id*. + var actionIDs = Entities.getActionIDs(entityID); + for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { + var actionID = actionIDs[actionIndex]; + var actionArguments = Entities.getActionArguments(entityID, actionID); + var tag = actionArguments["tag"]; + if (tag == getTag()) { + // we see a grab-*uuid* shaped tag, but it's our tag, so that's okay. + continue; + } + if (tag.slice(0, 5) == "grab-") { + // we see a grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it. + return true; + } + } + return false; +} + +function getSpatialOffsetPosition(hand, spatialKey) { + var position = Vec3.ZERO; + + if (hand !== RIGHT_HAND && spatialKey.leftRelativePosition) { + position = spatialKey.leftRelativePosition; + } + if (hand === RIGHT_HAND && spatialKey.rightRelativePosition) { + position = spatialKey.rightRelativePosition; + } + if (spatialKey.relativePosition) { + position = spatialKey.relativePosition; + } + + return position; +} + +var yFlip = Quat.angleAxis(180, Vec3.UNIT_Y); + +function getSpatialOffsetRotation(hand, spatialKey) { + var rotation = Quat.IDENTITY; + + if (hand !== RIGHT_HAND && spatialKey.leftRelativeRotation) { + rotation = spatialKey.leftRelativeRotation; + } + if (hand === RIGHT_HAND && spatialKey.rightRelativeRotation) { + rotation = spatialKey.rightRelativeRotation; + } + if (spatialKey.relativeRotation) { + rotation = spatialKey.relativeRotation; + } + + // Flip left hand + if (hand !== RIGHT_HAND) { + rotation = Quat.multiply(yFlip, rotation); + } + + return rotation; +} + +function MyController(hand) { + this.hand = hand; + if (this.hand === RIGHT_HAND) { + this.getHandPosition = MyAvatar.getRightPalmPosition; + this.getHandRotation = MyAvatar.getRightPalmRotation; + } else { + this.getHandPosition = MyAvatar.getLeftPalmPosition; + this.getHandRotation = MyAvatar.getLeftPalmRotation; + } + + var SPATIAL_CONTROLLERS_PER_PALM = 2; + var TIP_CONTROLLER_OFFSET = 1; + this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand; + this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; + + this.actionID = null; // action this script created... + this.grabbedEntity = null; // on this entity. + this.state = STATE_OFF; + this.pointer = null; // entity-id of line object + this.triggerValue = 0; // rolling average of trigger value + this.rawTriggerValue = 0; + this.rawBumperValue = 0; + + //for visualizations + this.overlayLine = null; + this.particleBeam = null; + + //for lights + this.spotlight = null; + this.pointlight = null; + + this.ignoreIK = false; + this.offsetPosition = Vec3.ZERO; + this.offsetRotation = Quat.IDENTITY; + + var _this = this; + + this.update = function() { + + this.updateSmoothedTrigger(); + + switch (this.state) { + case STATE_OFF: + this.off(); + this.touchTest(); + break; + case STATE_SEARCHING: + this.search(); + break; + case STATE_EQUIP_SEARCHING: + this.search(); + break; + case STATE_DISTANCE_HOLDING: + this.distanceHolding(); + break; + case STATE_CONTINUE_DISTANCE_HOLDING: + this.continueDistanceHolding(); + break; + case STATE_NEAR_GRABBING: + case STATE_EQUIP: + this.nearGrabbing(); + break; + case STATE_WAITING_FOR_BUMPER_RELEASE: + this.waitingForBumperRelease(); + break; + case STATE_EQUIP_SPRING: + this.pullTowardEquipPosition() + break; + case STATE_CONTINUE_NEAR_GRABBING: + case STATE_CONTINUE_EQUIP_BD: + case STATE_CONTINUE_EQUIP: + this.continueNearGrabbing(); + break; + case STATE_NEAR_TRIGGER: + this.nearTrigger(); + break; + case STATE_CONTINUE_NEAR_TRIGGER: + this.continueNearTrigger(); + break; + case STATE_FAR_TRIGGER: + this.farTrigger(); + break; + case STATE_CONTINUE_FAR_TRIGGER: + this.continueFarTrigger(); + break; + case STATE_RELEASE: + this.release(); + break; + } + }; + + this.setState = function(newState) { + if (WANT_DEBUG) { + print("STATE: " + stateToName(this.state) + " --> " + stateToName(newState) + ", hand: " + this.hand); + } + this.state = newState; + }; + + this.debugLine = function(closePoint, farPoint, color) { + Entities.addEntity({ + type: "Line", + name: "Grab Debug Entity", + dimensions: LINE_ENTITY_DIMENSIONS, + visible: true, + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: 0.1, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + }; + + this.lineOn = function(closePoint, farPoint, color) { + // draw a line + if (this.pointer === null) { + this.pointer = Entities.addEntity({ + type: "Line", + name: "grab pointer", + dimensions: LINE_ENTITY_DIMENSIONS, + visible: true, + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: LIFETIME, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + } else { + var age = Entities.getEntityProperties(this.pointer, "age").age; + this.pointer = Entities.editEntity(this.pointer, { + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: age + LIFETIME + }); + } + }; + + this.overlayLineOn = function(closePoint, farPoint, color) { + if (this.overlayLine === null) { + var lineProperties = { + lineWidth: 5, + start: closePoint, + end: farPoint, + color: color, + ignoreRayIntersection: true, // always ignore this + visible: true, + alpha: 1 + }; + + this.overlayLine = Overlays.addOverlay("line3d", lineProperties); + + } else { + var success = Overlays.editOverlay(this.overlayLine, { + lineWidth: 5, + start: closePoint, + end: farPoint, + color: color, + visible: true, + ignoreRayIntersection: true, // always ignore this + alpha: 1 + }); + } + }; + + this.handleParticleBeam = function(position, orientation, color) { + + var rotation = Quat.angleAxis(0, { + x: 1, + y: 0, + z: 0 + }); + + var finalRotation = Quat.multiply(orientation, rotation); + + if (this.particleBeam === null) { + this.createParticleBeam(position, finalRotation, color); + } else { + this.updateParticleBeam(position, finalRotation, color); + } + }; + + this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { + + var handToObject = Vec3.subtract(objectPosition, handPosition); + var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); + + var distance = Vec3.distance(handPosition, objectPosition); + var speed = distance * 1; + + var lifepsan = distance / speed; + var lifespan = 1; + + if (this.particleBeam === null) { + this.createParticleBeam(objectPosition, finalRotation, color, speed); + } else { + this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); + } + }; + + this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { + + var particleBeamProperties = { + type: "ParticleEffect", + isEmitting: true, + position: position, + visible: false, + //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), + "name": "Particle Beam", + "color": color, + "maxParticles": 2000, + "lifespan": LINE_LENGTH / 10, + "emitRate": 50, + "emitSpeed": 5, + "speedSpread": 2, + "emitOrientation": { + "x": -1, + "y": 0, + "z": 0, + "w": 1 + }, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "emitRadiusStart": 0.5, + "polarStart": 0, + "polarFinish": 0, + "azimuthStart": -3.1415927410125732, + "azimuthFinish": 3.1415927410125732, + "emitAcceleration": { + x: 0, + y: 0, + z: 0 + }, + "accelerationSpread": { + "x": 0, + "y": 0, + "z": 0 + }, + "particleRadius": 0.01, + "radiusSpread": 0, + // "radiusStart": 0.01, + // "radiusFinish": 0.01, + // "colorSpread": { + // "red": 0, + // "green": 0, + // "blue": 0 + // }, + // "colorStart": color, + // "colorFinish": color, + "alpha": 1, + "alphaSpread": 0, + "alphaStart": 1, + "alphaFinish": 1, + "additiveBlending": 1, + "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" + } + + this.particleBeam = Entities.addEntity(particleBeamProperties); + }; + + this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { + + Entities.editEntity(this.particleBeam, { + rotation: orientation, + position: position, + visible: true, + color: color, + emitSpeed: speed, + lifepsan: lifepsan + + }) + + }; + + this.evalLightWorldTransform = function(modelPos, modelRot) { + + var MODEL_LIGHT_POSITION = { + x: 0, + y: -0.3, + z: 0 + }; + + var MODEL_LIGHT_ROTATION = Quat.angleAxis(-90, { + x: 1, + y: 0, + z: 0 + }); + + return { + p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), + q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) + }; + }; + + this.handleSpotlight = function(parentID, position) { + var LIFETIME = 100; + + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); + + var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + var lightProperties = { + type: "Light", + isSpotlight: true, + dimensions: { + x: 2, + y: 2, + z: 20 + }, + parentID: parentID, + color: { + red: 255, + green: 255, + blue: 255 + }, + intensity: 2, + exponent: 0.3, + cutoff: 20, + lifetime: LIFETIME, + position: lightTransform.p, + }; + + if (this.spotlight === null) { + this.spotlight = Entities.addEntity(lightProperties); + } else { + Entities.editEntity(this.spotlight, { + //without this, this light would maintain rotation with its parent + rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0), + }) + } + }; + + this.handlePointLight = function(parentID, position) { + var LIFETIME = 100; + + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); + var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + + var lightProperties = { + type: "Light", + isSpotlight: false, + dimensions: { + x: 2, + y: 2, + z: 20 + }, + parentID: parentID, + color: { + red: 255, + green: 255, + blue: 255 + }, + intensity: 2, + exponent: 0.3, + cutoff: 20, + lifetime: LIFETIME, + position: lightTransform.p, + }; + + if (this.pointlight === null) { + this.pointlight = Entities.addEntity(lightProperties); + } else { + + } + }; + + this.lineOff = function() { + if (this.pointer !== null) { + Entities.deleteEntity(this.pointer); + } + this.pointer = null; + }; + + this.overlayLineOff = function() { + if (this.overlayLine !== null) { + Overlays.deleteOverlay(this.overlayLine); + } + this.overlayLine = null; + }; + + this.particleBeamOff = function() { + if (this.particleBeam !== null) { + Entities.editEntity(this.particleBeam, { + visible: false + }) + } + } + + this.turnLightsOff = function() { + if (this.spotlight !== null) { + Entities.deleteEntity(this.spotlight); + this.spotlight = null; + } + + if (this.pointlight !== null) { + Entities.deleteEntity(this.pointlight); + this.pointlight = null; + } + }; + + + this.turnOffVisualizations = function() { + if (USE_ENTITY_LINES_FOR_SEARCHING === true || USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOff(); + } + + if (USE_OVERLAY_LINES_FOR_SEARCHING === true || USE_OVERLAY_LINES_FOR_MOVING === true) { + this.overlayLineOff(); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.particleBeamOff(); + } + }; + + this.triggerPress = function(value) { + _this.rawTriggerValue = value; + }; + + this.bumperPress = function(value) { + _this.rawBumperValue = value; + }; + + this.updateSmoothedTrigger = function() { + var triggerValue = this.rawTriggerValue; + // smooth out trigger value + this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + + (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); + }; + + this.triggerSmoothedSqueezed = function() { + return this.triggerValue > TRIGGER_ON_VALUE; + }; + + this.triggerSmoothedReleased = function() { + return this.triggerValue < TRIGGER_OFF_VALUE; + }; + + this.triggerSqueezed = function() { + var triggerValue = this.rawTriggerValue; + return triggerValue > TRIGGER_ON_VALUE; + }; + + this.bumperSqueezed = function() { + return _this.rawBumperValue > BUMPER_ON_VALUE; + }; + + this.bumperReleased = function() { + return _this.rawBumperValue < BUMPER_ON_VALUE; + }; + + this.off = function() { + if (this.triggerSmoothedSqueezed()) { + this.lastPickTime = 0; + this.setState(STATE_SEARCHING); + return; + } + if (this.bumperSqueezed()) { + this.lastPickTime = 0; + this.setState(STATE_EQUIP_SEARCHING); + return; + } + }; + + this.search = function() { + this.grabbedEntity = null; + + if (this.state == STATE_SEARCHING ? this.triggerSmoothedReleased() : this.bumperReleased()) { + this.setState(STATE_RELEASE); + return; + } + + // the trigger is being pressed, do a ray test + var handPosition = this.getHandPosition(); + var distantPickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()), + length: PICK_MAX_DISTANCE + }; + + // don't pick 60x per second. + var pickRays = []; + var now = Date.now(); + if (now - this.lastPickTime > MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) { + pickRays = [distantPickRay]; + this.lastPickTime = now; + } + + for (var index = 0; index < pickRays.length; ++index) { + var pickRay = pickRays[index]; + var directionNormalized = Vec3.normalize(pickRay.direction); + var directionBacked = Vec3.multiply(directionNormalized, PICK_BACKOFF_DISTANCE); + var pickRayBacked = { + origin: Vec3.subtract(pickRay.origin, directionBacked), + direction: pickRay.direction + }; + + if (WANT_DEBUG) { + this.debugLine(pickRayBacked.origin, Vec3.multiply(pickRayBacked.direction, NEAR_PICK_MAX_DISTANCE), { + red: 0, + green: 255, + blue: 0 + }) + } + + var intersection = Entities.findRayIntersection(pickRayBacked, true); + + if (intersection.intersects) { + // the ray is intersecting something we can move. + var intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection); + + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, intersection.entityID, DEFAULT_GRABBABLE_DATA); + + if (intersection.properties.name == "Grab Debug Entity") { + continue; + } + + if (typeof grabbableData.grabbable !== 'undefined' && !grabbableData.grabbable) { + continue; + } + if (intersectionDistance > pickRay.length) { + // too far away for this ray. + continue; + } + if (intersectionDistance <= NEAR_PICK_MAX_DISTANCE) { + // the hand is very close to the intersected object. go into close-grabbing mode. + if (grabbableData.wantsTrigger) { + this.grabbedEntity = intersection.entityID; + this.setState(STATE_NEAR_TRIGGER); + return; + } else if (!intersection.properties.locked) { + this.grabbedEntity = intersection.entityID; + if (this.state == STATE_SEARCHING) { + this.setState(STATE_NEAR_GRABBING); + } else { // equipping + if (typeof grabbableData.spatialKey !== 'undefined') { + // TODO + // if we go to STATE_EQUIP_SPRING the item will be pulled to the hand and will then switch + // to STATE_EQUIP. This needs some debugging, so just jump straight to STATE_EQUIP here. + // this.setState(STATE_EQUIP_SPRING); + this.setState(STATE_EQUIP); + } else { + this.setState(STATE_EQUIP); + } + } + return; + } + } else if (!entityIsGrabbedByOther(intersection.entityID)) { + // don't allow two people to distance grab the same object + if (intersection.properties.collisionsWillMove && !intersection.properties.locked) { + // the hand is far from the intersected object. go into distance-holding mode + this.grabbedEntity = intersection.entityID; + if (typeof grabbableData.spatialKey !== 'undefined' && this.state == STATE_EQUIP_SEARCHING) { + // if a distance pick in equip mode hits something with a spatialKey, equip it + // TODO use STATE_EQUIP_SPRING here once it works right. + // this.setState(STATE_EQUIP_SPRING); + this.setState(STATE_EQUIP); + return; + } else if (this.state == STATE_SEARCHING) { + this.setState(STATE_DISTANCE_HOLDING); + return; + } + } else if (grabbableData.wantsTrigger) { + this.grabbedEntity = intersection.entityID; + this.setState(STATE_FAR_TRIGGER); + return; + } + } + } + } + + // forward ray test failed, try sphere test. + if (WANT_DEBUG) { + Entities.addEntity({ + type: "Sphere", + name: "Grab Debug Entity", + dimensions: { + x: GRAB_RADIUS, + y: GRAB_RADIUS, + z: GRAB_RADIUS + }, + visible: true, + position: handPosition, + color: { + red: 0, + green: 255, + blue: 0 + }, + lifetime: 0.1, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + } + + var nearbyEntities = Entities.findEntities(handPosition, GRAB_RADIUS); + var minDistance = PICK_MAX_DISTANCE; + var i, props, distance, grabbableData; + this.grabbedEntity = null; + for (i = 0; i < nearbyEntities.length; i++) { + var grabbableDataForCandidate = + getEntityCustomData(GRABBABLE_DATA_KEY, nearbyEntities[i], DEFAULT_GRABBABLE_DATA); + if (typeof grabbableDataForCandidate.grabbable !== 'undefined' && !grabbableDataForCandidate.grabbable) { + continue; + } + var propsForCandidate = Entities.getEntityProperties(nearbyEntities[i], GRABBABLE_PROPERTIES); + + if (propsForCandidate.type == 'Unknown') { + continue; + } + + if (propsForCandidate.type == 'Light') { + continue; + } + + if (propsForCandidate.type == 'ParticleEffect') { + continue; + } + + if (propsForCandidate.type == 'PolyLine') { + continue; + } + + if (propsForCandidate.type == 'Zone') { + continue; + } + + if (propsForCandidate.locked && !grabbableDataForCandidate.wantsTrigger) { + continue; + } + + if (propsForCandidate.name == "Grab Debug Entity") { + continue; + } + + if (propsForCandidate.name == "grab pointer") { + continue; + } + + distance = Vec3.distance(propsForCandidate.position, handPosition); + if (distance < minDistance) { + this.grabbedEntity = nearbyEntities[i]; + minDistance = distance; + props = propsForCandidate; + grabbableData = grabbableDataForCandidate; + } + } + if (this.grabbedEntity !== null) { + if (grabbableData.wantsTrigger) { + this.setState(STATE_NEAR_TRIGGER); + return; + } else if (!props.locked && props.collisionsWillMove) { + this.setState(this.state == STATE_SEARCHING ? STATE_NEAR_GRABBING : STATE_EQUIP) + return; + } + } + + //search line visualizations + if (USE_ENTITY_LINES_FOR_SEARCHING === true) { + this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + } + + if (USE_OVERLAY_LINES_FOR_SEARCHING === true) { + this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true) { + this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR); + } + + }; + + this.distanceHolding = function() { + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var now = Date.now(); + + // add the action and initialize some variables + this.currentObjectPosition = grabbedProperties.position; + this.currentObjectRotation = grabbedProperties.rotation; + this.currentObjectTime = now; + this.handRelativePreviousPosition = Vec3.subtract(handControllerPosition, MyAvatar.position); + this.handPreviousRotation = handRotation; + this.currentCameraOrientation = Camera.orientation; + + // compute a constant based on the initial conditions which we use below to exagerate hand motion onto the held object + this.radiusScalar = Math.log(Vec3.distance(this.currentObjectPosition, handControllerPosition) + 1.0); + if (this.radiusScalar < 1.0) { + this.radiusScalar = 1.0; + } + + this.actionID = NULL_ACTION_ID; + this.actionID = Entities.addAction("spring", this.grabbedEntity, { + targetPosition: this.currentObjectPosition, + linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + targetRotation: this.currentObjectRotation, + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + tag: getTag(), + ttl: ACTION_TTL + }); + if (this.actionID === NULL_ACTION_ID) { + this.actionID = null; + } + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + + if (this.actionID !== null) { + this.setState(STATE_CONTINUE_DISTANCE_HOLDING); + this.activateEntity(this.grabbedEntity, grabbedProperties); + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab"); + } + + this.currentAvatarPosition = MyAvatar.position; + this.currentAvatarOrientation = MyAvatar.orientation; + + this.turnOffVisualizations(); + }; + + this.continueDistanceHolding = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + + var handPosition = this.getHandPosition(); + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state == STATE_CONTINUE_DISTANCE_HOLDING && this.bumperSqueezed() && + typeof grabbableData.spatialKey !== 'undefined') { + var saveGrabbedID = this.grabbedEntity; + this.release(); + this.setState(STATE_EQUIP); + this.grabbedEntity = saveGrabbedID; + return; + } + + + // the action was set up on a previous call. update the targets. + var radius = Vec3.distance(this.currentObjectPosition, handControllerPosition) * + this.radiusScalar * DISTANCE_HOLDING_RADIUS_FACTOR; + if (radius < 1.0) { + radius = 1.0; + } + + // how far did avatar move this timestep? + var currentPosition = MyAvatar.position; + var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition); + this.currentAvatarPosition = currentPosition; + + // How far did the avatar turn this timestep? + // Note: The following code is too long because we need a Quat.quatBetween() function + // that returns the minimum quaternion between two quaternions. + var currentOrientation = MyAvatar.orientation; + if (Quat.dot(currentOrientation, this.currentAvatarOrientation) < 0.0) { + var negativeCurrentOrientation = { + x: -currentOrientation.x, + y: -currentOrientation.y, + z: -currentOrientation.z, + w: -currentOrientation.w + }; + var avatarDeltaOrientation = Quat.multiply(negativeCurrentOrientation, Quat.inverse(this.currentAvatarOrientation)); + } else { + var avatarDeltaOrientation = Quat.multiply(currentOrientation, Quat.inverse(this.currentAvatarOrientation)); + } + var handToAvatar = Vec3.subtract(handControllerPosition, this.currentAvatarPosition); + var objectToAvatar = Vec3.subtract(this.currentObjectPosition, this.currentAvatarPosition); + var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar); + var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar); + this.currentAvatarOrientation = currentOrientation; + + // how far did hand move this timestep? + var handMoved = Vec3.subtract(handToAvatar, this.handRelativePreviousPosition); + this.handRelativePreviousPosition = handToAvatar; + + // magnify the hand movement but not the change from avatar movement & rotation + handMoved = Vec3.subtract(handMoved, handMovementFromTurning); + var superHandMoved = Vec3.multiply(handMoved, radius); + + // Move the object by the magnified amount and then by amount from avatar movement & rotation + var newObjectPosition = Vec3.sum(this.currentObjectPosition, superHandMoved); + newObjectPosition = Vec3.sum(newObjectPosition, avatarDeltaPosition); + newObjectPosition = Vec3.sum(newObjectPosition, objectMovementFromTurning); + + var deltaPosition = Vec3.subtract(newObjectPosition, this.currentObjectPosition); // meters + var now = Date.now(); + var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds + + this.currentObjectPosition = newObjectPosition; + this.currentObjectTime = now; + + // this doubles hand rotation + var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, + handRotation, + DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR), + Quat.inverse(this.handPreviousRotation)); + this.handPreviousRotation = handRotation; + this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation); + + Entities.callEntityMethod(this.grabbedEntity, "continueDistantGrab"); + + // mix in head motion + if (MOVE_WITH_HEAD) { + var objDistance = Vec3.length(objectToAvatar); + var before = Vec3.multiplyQbyV(this.currentCameraOrientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); + var after = Vec3.multiplyQbyV(Camera.orientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); + var change = Vec3.subtract(before, after); + this.currentCameraOrientation = Camera.orientation; + this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change); + } + + + //visualizations + if (USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); + } + if (USE_OVERLAY_LINES_FOR_MOVING === true) { + this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); + } + if (USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + } + if (USE_POINTLIGHT === true) { + this.handlePointLight(this.grabbedEntity); + } + if (USE_SPOTLIGHT === true) { + this.handleSpotlight(this.grabbedEntity); + } + + Entities.updateAction(this.grabbedEntity, this.actionID, { + targetPosition: this.currentObjectPosition, + linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + targetRotation: this.currentObjectRotation, + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + ttl: ACTION_TTL + }); + + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + }; + + this.nearGrabbing = function() { + var now = Date.now(); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + + this.turnOffVisualizations(); + + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + this.activateEntity(this.grabbedEntity, grabbedProperties); + if (grabbedProperties.collisionsWillMove && NEAR_GRABBING_KINEMATIC) { + Entities.editEntity(this.grabbedEntity, { + collisionsWillMove: false + }); + } + + var handRotation = this.getHandRotation(); + var handPosition = this.getHandPosition(); + + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) { + // if an object is "equipped" and has a spatialKey, use it. + this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; + this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); + this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + } else { + this.ignoreIK = false; + + var objectRotation = grabbedProperties.rotation; + this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); + + var currentObjectPosition = grabbedProperties.position; + var offset = Vec3.subtract(currentObjectPosition, handPosition); + this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset); + } + + this.actionID = NULL_ACTION_ID; + this.actionID = Entities.addAction("hold", this.grabbedEntity, { + hand: this.hand === RIGHT_HAND ? "right" : "left", + timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, + relativePosition: this.offsetPosition, + relativeRotation: this.offsetRotation, + ttl: ACTION_TTL, + kinematic: NEAR_GRABBING_KINEMATIC, + kinematicSetVelocity: true, + ignoreIK: this.ignoreIK + }); + if (this.actionID === NULL_ACTION_ID) { + this.actionID = null; + } else { + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + if (this.state == STATE_NEAR_GRABBING) { + this.setState(STATE_CONTINUE_NEAR_GRABBING); + } else { + // equipping + Entities.callEntityMethod(this.grabbedEntity, "startEquip", [JSON.stringify(this.hand)]); + this.startHandGrasp(); + + this.setState(STATE_CONTINUE_EQUIP_BD); + } + + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + + Entities.callEntityMethod(this.grabbedEntity, "startNearGrab"); + + } + + this.currentHandControllerTipPosition = + (this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition; + + this.currentObjectTime = Date.now(); + }; + + this.continueNearGrabbing = function() { + if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + if (this.state == STATE_CONTINUE_EQUIP_BD && this.bumperReleased()) { + this.setState(STATE_CONTINUE_EQUIP); + return; + } + if (this.state == STATE_CONTINUE_EQUIP && this.bumperSqueezed()) { + this.setState(STATE_WAITING_FOR_BUMPER_RELEASE); + return; + } + if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.bumperSqueezed()) { + this.setState(STATE_CONTINUE_EQUIP_BD); + Entities.callEntityMethod(this.grabbedEntity, "startEquip", [JSON.stringify(this.hand)]); + return; + } + + // Keep track of the fingertip velocity to impart when we release the object. + // Note that the idea of using a constant 'tip' velocity regardless of the + // object's actual held offset is an idea intended to make it easier to throw things: + // Because we might catch something or transfer it between hands without a good idea + // of it's actual offset, let's try imparting a velocity which is at a fixed radius + // from the palm. + + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var now = Date.now(); + + var deltaPosition = Vec3.subtract(handControllerPosition, this.currentHandControllerTipPosition); // meters + var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds + + this.currentHandControllerTipPosition = handControllerPosition; + this.currentObjectTime = now; + Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); + + if (this.state === STATE_CONTINUE_EQUIP_BD) { + Entities.callEntityMethod(this.grabbedEntity, "continueEquip"); + } + + if (this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) { + // if less than a 5 seconds left, refresh the actions ttl + Entities.updateAction(this.grabbedEntity, this.actionID, { + hand: this.hand === RIGHT_HAND ? "right" : "left", + timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, + relativePosition: this.offsetPosition, + relativeRotation: this.offsetRotation, + ttl: ACTION_TTL, + kinematic: NEAR_GRABBING_KINEMATIC, + kinematicSetVelocity: true, + ignoreIK: this.ignoreIK + }); + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + } + }; + + this.waitingForBumperRelease = function() { + if (this.bumperReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + Entities.callEntityMethod(this.grabbedEntity, "unequip"); + this.endHandGrasp(); + + } + }; + + this.pullTowardEquipPosition = function() { + + this.turnOffVisualizations(); + + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + // use a spring to pull the object to where it will be when equipped + var relativeRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + var relativePosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); + var ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; + var handRotation = this.getHandRotation(); + var handPosition = this.getHandPosition(); + var targetRotation = Quat.multiply(handRotation, relativeRotation); + var offset = Vec3.multiplyQbyV(targetRotation, relativePosition); + var targetPosition = Vec3.sum(handPosition, offset); + + if (typeof this.equipSpringID === 'undefined' || + this.equipSpringID === null || + this.equipSpringID === NULL_ACTION_ID) { + this.equipSpringID = Entities.addAction("spring", this.grabbedEntity, { + targetPosition: targetPosition, + linearTimeScale: EQUIP_SPRING_TIMEFRAME, + targetRotation: targetRotation, + angularTimeScale: EQUIP_SPRING_TIMEFRAME, + ttl: ACTION_TTL, + ignoreIK: ignoreIK + }); + if (this.equipSpringID === NULL_ACTION_ID) { + this.equipSpringID = null; + this.setState(STATE_OFF); + return; + } + } else { + Entities.updateAction(this.grabbedEntity, this.equipSpringID, { + targetPosition: targetPosition, + linearTimeScale: EQUIP_SPRING_TIMEFRAME, + targetRotation: targetRotation, + angularTimeScale: EQUIP_SPRING_TIMEFRAME, + ttl: ACTION_TTL, + ignoreIK: ignoreIK + }); + } + + if (Vec3.distance(grabbedProperties.position, targetPosition) < EQUIP_SPRING_SHUTOFF_DISTANCE) { + Entities.deleteAction(this.grabbedEntity, this.equipSpringID); + this.equipSpringID = null; + this.setState(STATE_EQUIP); + } + }; + + this.nearTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + + Entities.callEntityMethod(this.grabbedEntity, "startNearTrigger"); + this.setState(STATE_CONTINUE_NEAR_TRIGGER); + }; + + this.farTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopFarTrigger"); + return; + } + + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + Entities.callEntityMethod(this.grabbedEntity, "startFarTrigger"); + this.setState(STATE_CONTINUE_FAR_TRIGGER); + }; + + this.continueNearTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + + Entities.callEntityMethod(this.grabbedEntity, "continueNearTrigger"); + }; + + this.continueFarTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + + var handPosition = this.getHandPosition(); + var pickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()) + }; + + var now = Date.now(); + if (now - this.lastPickTime > MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) { + var intersection = Entities.findRayIntersection(pickRay, true); + this.lastPickTime = now; + if (intersection.entityID != this.grabbedEntity) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopFarTrigger"); + return; + } + } + + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger"); + }; + + _this.allTouchedIDs = {}; + + this.touchTest = function() { + var maxDistance = 0.05; + var leftHandPosition = MyAvatar.getLeftPalmPosition(); + var rightHandPosition = MyAvatar.getRightPalmPosition(); + var leftEntities = Entities.findEntities(leftHandPosition, maxDistance); + var rightEntities = Entities.findEntities(rightHandPosition, maxDistance); + var ids = []; + + if (leftEntities.length !== 0) { + leftEntities.forEach(function(entity) { + ids.push(entity); + }); + + } + + if (rightEntities.length !== 0) { + rightEntities.forEach(function(entity) { + ids.push(entity); + }); + } + + ids.forEach(function(id) { + + var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); + if (props.name === 'pointer') { + return; + } else { + var entityMinPoint = props.boundingBox.brn; + var entityMaxPoint = props.boundingBox.tfl; + var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); + var rightIsTouching = pointInExtents(rightHandPosition, entityMinPoint, entityMaxPoint); + + if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id] === undefined) { + // we haven't been touched before, but either right or left is touching us now + _this.allTouchedIDs[id] = true; + _this.startTouch(id); + } else if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id]) { + // we have been touched before and are still being touched + // continue touch + _this.continueTouch(id); + } else if (_this.allTouchedIDs[id]) { + delete _this.allTouchedIDs[id]; + _this.stopTouch(id); + + } else { + //we are in another state + return; + } + } + + }); + + }; + + this.startTouch = function(entityID) { + Entities.callEntityMethod(entityID, "startTouch"); + }; + + this.continueTouch = function(entityID) { + Entities.callEntityMethod(entityID, "continueTouch"); + }; + + this.stopTouch = function(entityID) { + Entities.callEntityMethod(entityID, "stopTouch"); + }; + + this.release = function() { + + this.turnLightsOff(); + this.turnOffVisualizations(); + + if (this.grabbedEntity !== null) { + if (this.actionID !== null) { + Entities.deleteAction(this.grabbedEntity, this.actionID); + } + } + + this.deactivateEntity(this.grabbedEntity); + + this.grabbedEntity = null; + this.actionID = null; + this.setState(STATE_OFF); + }; + + this.cleanup = function() { + this.release(); + this.endHandGrasp(); + Entities.deleteEntity(this.particleBeam); + Entities.deleteEntity(this.spotLight); + Entities.deleteEntity(this.pointLight); + }; + + this.activateEntity = function(entityID, grabbedProperties) { + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, entityID, DEFAULT_GRABBABLE_DATA); + var invertSolidWhileHeld = grabbableData["invertSolidWhileHeld"]; + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + data["activated"] = true; + data["avatarId"] = MyAvatar.sessionUUID; + data["refCount"] = data["refCount"] ? data["refCount"] + 1 : 1; + // zero gravity and set ignoreForCollisions in a way that lets us put them back, after all grabs are done + if (data["refCount"] == 1) { + data["gravity"] = grabbedProperties.gravity; + data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions; + data["collisionsWillMove"] = grabbedProperties.collisionsWillMove; + var whileHeldProperties = { + gravity: { + x: 0, + y: 0, + z: 0 + } + }; + if (invertSolidWhileHeld) { + whileHeldProperties["ignoreForCollisions"] = !grabbedProperties.ignoreForCollisions; + } + Entities.editEntity(entityID, whileHeldProperties); + } + + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + return data; + }; + + this.deactivateEntity = function(entityID) { + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + if (data && data["refCount"]) { + data["refCount"] = data["refCount"] - 1; + if (data["refCount"] < 1) { + Entities.editEntity(entityID, { + gravity: data["gravity"], + ignoreForCollisions: data["ignoreForCollisions"], + collisionsWillMove: data["collisionsWillMove"] + }); + data = null; + } + } else { + data = null; + } + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + }; + + + //this is our handler, where we do the actual work of changing animation settings + this.graspHand = function(animationProperties) { + var result = {}; + //full alpha on overlay for this hand + //set grab to true + //set idle to false + //full alpha on the blend btw open and grab + if (_this.hand === RIGHT_HAND) { + result['rightHandOverlayAlpha'] = 1.0; + result['isRightHandGrab'] = true; + result['isRightHandIdle'] = false; + result['rightHandGrabBlend'] = 1.0; + } else if (_this.hand === LEFT_HAND) { + result['leftHandOverlayAlpha'] = 1.0; + result['isLeftHandGrab'] = true; + result['isLeftHandIdle'] = false; + result['leftHandGrabBlend'] = 1.0; + } + //return an object with our updated settings + return result; + }; + + this.graspHandler = null + + this.startHandGrasp = function() { + if (this.hand === RIGHT_HAND) { + this.graspHandler = MyAvatar.addAnimationStateHandler(this.graspHand, ['isRightHandGrab']); + } else if (this.hand === LEFT_HAND) { + this.graspHandler = MyAvatar.addAnimationStateHandler(this.graspHand, ['isLeftHandGrab']); + } + }; + + this.endHandGrasp = function() { + // Tell the animation system we don't need any more callbacks. + MyAvatar.removeAnimationStateHandler(this.graspHandler); + }; + +}; + +var rightController = new MyController(RIGHT_HAND); +var leftController = new MyController(LEFT_HAND); + +//preload the particle beams so that they are full length when you start searching +if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + rightController.createParticleBeam(); + leftController.createParticleBeam(); +} + +var MAPPING_NAME = "com.highfidelity.handControllerGrab"; + +var mapping = Controller.newMapping(MAPPING_NAME); +mapping.from([Controller.Standard.RT]).peek().to(rightController.triggerPress); +mapping.from([Controller.Standard.LT]).peek().to(leftController.triggerPress); + +mapping.from([Controller.Standard.RB]).peek().to(rightController.bumperPress); +mapping.from([Controller.Standard.LB]).peek().to(leftController.bumperPress); + +Controller.enableMapping(MAPPING_NAME); + +//the section below allows the grab script to listen for messages that disable either one or both hands. useful for two handed items +var handToDisable = 'none'; + +function update() { + if (handToDisable !== LEFT_HAND && handToDisable !== 'both') { + leftController.update(); + } + if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') { + rightController.update(); + } +} + +Messages.subscribe('Hifi-Hand-Disabler'); + +handleHandDisablerMessages = function(channel, message, sender) { + + if (sender === MyAvatar.sessionUUID) { + if (message === 'left') { + handToDisable = LEFT_HAND; + } + if (message === 'right') { + handToDisable = RIGHT_HAND; + } + if (message === 'both') { + handToDisable = 'both'; + } + if (message === 'none') { + handToDisable = 'none'; + } + } + +} + +Messages.messageReceived.connect(handleHandDisablerMessages); + +function cleanup() { + rightController.cleanup(); + leftController.cleanup(); + Controller.disableMapping(MAPPING_NAME); +} + +Script.scriptEnding.connect(cleanup); +Script.update.connect(update); \ No newline at end of file diff --git a/examples/controllers/handControllerGrab-pointlight.js b/examples/controllers/handControllerGrab-pointlight.js new file mode 100644 index 0000000000..fc14e6026e --- /dev/null +++ b/examples/controllers/handControllerGrab-pointlight.js @@ -0,0 +1,1649 @@ +// handControllerGrab.js +// +// Created by Eric Levin on 9/2/15 +// Additions by James B. Pollack @imgntn on 9/24/2015 +// Additions By Seth Alves on 10/20/2015 +// Copyright 2015 High Fidelity, Inc. +// +// Grabs physically moveable entities with hydra-like controllers; it works for either near or far objects. +// Also supports touch and equipping objects. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ + +Script.include("../libraries/utils.js"); + +// +// add lines where the hand ray picking is happening +// +var WANT_DEBUG = false; + +// +// these tune time-averaging and "on" value for analog trigger +// + +var TRIGGER_SMOOTH_RATIO = 0.1; // 0.0 disables smoothing of trigger value +var TRIGGER_ON_VALUE = 0.4; +var TRIGGER_OFF_VALUE = 0.15; + +var BUMPER_ON_VALUE = 0.5; + +// +// distant manipulation +// + +var DISTANCE_HOLDING_RADIUS_FACTOR = 3.5; // multiplied by distance between hand and object +var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position +var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did +var MOVE_WITH_HEAD = true; // experimental head-controll of distantly held objects + +var NO_INTERSECT_COLOR = { + red: 10, + green: 10, + blue: 255 +}; // line color when pick misses +var INTERSECT_COLOR = { + red: 250, + green: 10, + blue: 10 +}; // line color when pick hits +var LINE_ENTITY_DIMENSIONS = { + x: 1000, + y: 1000, + z: 1000 +}; + +var LINE_LENGTH = 500; +var PICK_MAX_DISTANCE = 500; // max length of pick-ray + +// +// near grabbing +// + +var GRAB_RADIUS = 0.03; // if the ray misses but an object is this close, it will still be selected +var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position +var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held object's velocity. 1.0 to disable. +var NEAR_PICK_MAX_DISTANCE = 0.3; // max length of pick-ray for close grabbing to be selected +var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things +var PICK_BACKOFF_DISTANCE = 0.2; // helps when hand is intersecting the grabble object +var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed + +// +// equip +// + +var EQUIP_SPRING_SHUTOFF_DISTANCE = 0.05; +var EQUIP_SPRING_TIMEFRAME = 0.4; // how quickly objects move to their new position + +// +// other constants +// + +var RIGHT_HAND = 1; +var LEFT_HAND = 0; + +var ZERO_VEC = { + x: 0, + y: 0, + z: 0 +}; + +var NULL_ACTION_ID = "{00000000-0000-0000-000000000000}"; +var MSEC_PER_SEC = 1000.0; + +// these control how long an abandoned pointer line or action will hang around +var LIFETIME = 10; +var ACTION_TTL = 15; // seconds +var ACTION_TTL_REFRESH = 5; +var PICKS_PER_SECOND_PER_HAND = 5; +var MSECS_PER_SEC = 1000.0; +var GRABBABLE_PROPERTIES = [ + "position", + "rotation", + "gravity", + "ignoreForCollisions", + "collisionsWillMove", + "locked", + "name" +]; + +var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js +var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js + +var DEFAULT_GRABBABLE_DATA = { + grabbable: true, + invertSolidWhileHeld: false +}; + +//we've created various ways of visualizing looking for and moving distant objects +var USE_ENTITY_LINES_FOR_SEARCHING = false; +var USE_OVERLAY_LINES_FOR_SEARCHING = true; +var USE_PARTICLE_BEAM_FOR_SEARCHING = false; + +var USE_ENTITY_LINES_FOR_MOVING = true; +var USE_OVERLAY_LINES_FOR_MOVING = false; +var USE_PARTICLE_BEAM_FOR_MOVING = false; + +var USE_SPOTLIGHT = false; +var USE_POINTLIGHT = true; + +// states for the state machine +var STATE_OFF = 0; +var STATE_SEARCHING = 1; +var STATE_DISTANCE_HOLDING = 2; +var STATE_CONTINUE_DISTANCE_HOLDING = 3; +var STATE_NEAR_GRABBING = 4; +var STATE_CONTINUE_NEAR_GRABBING = 5; +var STATE_NEAR_TRIGGER = 6; +var STATE_CONTINUE_NEAR_TRIGGER = 7; +var STATE_FAR_TRIGGER = 8; +var STATE_CONTINUE_FAR_TRIGGER = 9; +var STATE_RELEASE = 10; +var STATE_EQUIP_SEARCHING = 11; +var STATE_EQUIP = 12 +var STATE_CONTINUE_EQUIP_BD = 13; // equip while bumper is still held down +var STATE_CONTINUE_EQUIP = 14; +var STATE_WAITING_FOR_BUMPER_RELEASE = 15; +var STATE_EQUIP_SPRING = 16; + + + +function stateToName(state) { + switch (state) { + case STATE_OFF: + return "off"; + case STATE_SEARCHING: + return "searching"; + case STATE_DISTANCE_HOLDING: + return "distance_holding"; + case STATE_CONTINUE_DISTANCE_HOLDING: + return "continue_distance_holding"; + case STATE_NEAR_GRABBING: + return "near_grabbing"; + case STATE_CONTINUE_NEAR_GRABBING: + return "continue_near_grabbing"; + case STATE_NEAR_TRIGGER: + return "near_trigger"; + case STATE_CONTINUE_NEAR_TRIGGER: + return "continue_near_trigger"; + case STATE_FAR_TRIGGER: + return "far_trigger"; + case STATE_CONTINUE_FAR_TRIGGER: + return "continue_far_trigger"; + case STATE_RELEASE: + return "release"; + case STATE_EQUIP_SEARCHING: + return "equip_searching"; + case STATE_EQUIP: + return "equip"; + case STATE_CONTINUE_EQUIP_BD: + return "continue_equip_bd"; + case STATE_CONTINUE_EQUIP: + return "continue_equip"; + case STATE_WAITING_FOR_BUMPER_RELEASE: + return "waiting_for_bumper_release"; + case STATE_EQUIP_SPRING: + return "state_equip_spring"; + } + + return "unknown"; +} + +function getTag() { + return "grab-" + MyAvatar.sessionUUID; +} + +function entityIsGrabbedByOther(entityID) { + // by convention, a distance grab sets the tag of its action to be grab-*owner-session-id*. + var actionIDs = Entities.getActionIDs(entityID); + for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { + var actionID = actionIDs[actionIndex]; + var actionArguments = Entities.getActionArguments(entityID, actionID); + var tag = actionArguments["tag"]; + if (tag == getTag()) { + // we see a grab-*uuid* shaped tag, but it's our tag, so that's okay. + continue; + } + if (tag.slice(0, 5) == "grab-") { + // we see a grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it. + return true; + } + } + return false; +} + +function getSpatialOffsetPosition(hand, spatialKey) { + var position = Vec3.ZERO; + + if (hand !== RIGHT_HAND && spatialKey.leftRelativePosition) { + position = spatialKey.leftRelativePosition; + } + if (hand === RIGHT_HAND && spatialKey.rightRelativePosition) { + position = spatialKey.rightRelativePosition; + } + if (spatialKey.relativePosition) { + position = spatialKey.relativePosition; + } + + return position; +} + +var yFlip = Quat.angleAxis(180, Vec3.UNIT_Y); + +function getSpatialOffsetRotation(hand, spatialKey) { + var rotation = Quat.IDENTITY; + + if (hand !== RIGHT_HAND && spatialKey.leftRelativeRotation) { + rotation = spatialKey.leftRelativeRotation; + } + if (hand === RIGHT_HAND && spatialKey.rightRelativeRotation) { + rotation = spatialKey.rightRelativeRotation; + } + if (spatialKey.relativeRotation) { + rotation = spatialKey.relativeRotation; + } + + // Flip left hand + if (hand !== RIGHT_HAND) { + rotation = Quat.multiply(yFlip, rotation); + } + + return rotation; +} + +function MyController(hand) { + this.hand = hand; + if (this.hand === RIGHT_HAND) { + this.getHandPosition = MyAvatar.getRightPalmPosition; + this.getHandRotation = MyAvatar.getRightPalmRotation; + } else { + this.getHandPosition = MyAvatar.getLeftPalmPosition; + this.getHandRotation = MyAvatar.getLeftPalmRotation; + } + + var SPATIAL_CONTROLLERS_PER_PALM = 2; + var TIP_CONTROLLER_OFFSET = 1; + this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand; + this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; + + this.actionID = null; // action this script created... + this.grabbedEntity = null; // on this entity. + this.state = STATE_OFF; + this.pointer = null; // entity-id of line object + this.triggerValue = 0; // rolling average of trigger value + this.rawTriggerValue = 0; + this.rawBumperValue = 0; + + //for visualizations + this.overlayLine = null; + this.particleBeam = null; + + //for lights + this.spotlight = null; + this.pointlight = null; + + this.ignoreIK = false; + this.offsetPosition = Vec3.ZERO; + this.offsetRotation = Quat.IDENTITY; + + var _this = this; + + this.update = function() { + + this.updateSmoothedTrigger(); + + switch (this.state) { + case STATE_OFF: + this.off(); + this.touchTest(); + break; + case STATE_SEARCHING: + this.search(); + break; + case STATE_EQUIP_SEARCHING: + this.search(); + break; + case STATE_DISTANCE_HOLDING: + this.distanceHolding(); + break; + case STATE_CONTINUE_DISTANCE_HOLDING: + this.continueDistanceHolding(); + break; + case STATE_NEAR_GRABBING: + case STATE_EQUIP: + this.nearGrabbing(); + break; + case STATE_WAITING_FOR_BUMPER_RELEASE: + this.waitingForBumperRelease(); + break; + case STATE_EQUIP_SPRING: + this.pullTowardEquipPosition() + break; + case STATE_CONTINUE_NEAR_GRABBING: + case STATE_CONTINUE_EQUIP_BD: + case STATE_CONTINUE_EQUIP: + this.continueNearGrabbing(); + break; + case STATE_NEAR_TRIGGER: + this.nearTrigger(); + break; + case STATE_CONTINUE_NEAR_TRIGGER: + this.continueNearTrigger(); + break; + case STATE_FAR_TRIGGER: + this.farTrigger(); + break; + case STATE_CONTINUE_FAR_TRIGGER: + this.continueFarTrigger(); + break; + case STATE_RELEASE: + this.release(); + break; + } + }; + + this.setState = function(newState) { + if (WANT_DEBUG) { + print("STATE: " + stateToName(this.state) + " --> " + stateToName(newState) + ", hand: " + this.hand); + } + this.state = newState; + }; + + this.debugLine = function(closePoint, farPoint, color) { + Entities.addEntity({ + type: "Line", + name: "Grab Debug Entity", + dimensions: LINE_ENTITY_DIMENSIONS, + visible: true, + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: 0.1, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + }; + + this.lineOn = function(closePoint, farPoint, color) { + // draw a line + if (this.pointer === null) { + this.pointer = Entities.addEntity({ + type: "Line", + name: "grab pointer", + dimensions: LINE_ENTITY_DIMENSIONS, + visible: true, + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: LIFETIME, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + } else { + var age = Entities.getEntityProperties(this.pointer, "age").age; + this.pointer = Entities.editEntity(this.pointer, { + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: age + LIFETIME + }); + } + }; + + this.overlayLineOn = function(closePoint, farPoint, color) { + if (this.overlayLine === null) { + var lineProperties = { + lineWidth: 5, + start: closePoint, + end: farPoint, + color: color, + ignoreRayIntersection: true, // always ignore this + visible: true, + alpha: 1 + }; + + this.overlayLine = Overlays.addOverlay("line3d", lineProperties); + + } else { + var success = Overlays.editOverlay(this.overlayLine, { + lineWidth: 5, + start: closePoint, + end: farPoint, + color: color, + visible: true, + ignoreRayIntersection: true, // always ignore this + alpha: 1 + }); + } + }; + + this.handleParticleBeam = function(position, orientation, color) { + + var rotation = Quat.angleAxis(0, { + x: 1, + y: 0, + z: 0 + }); + + var finalRotation = Quat.multiply(orientation, rotation); + + if (this.particleBeam === null) { + this.createParticleBeam(position, finalRotation, color); + } else { + this.updateParticleBeam(position, finalRotation, color); + } + }; + + this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { + + var handToObject = Vec3.subtract(objectPosition, handPosition); + var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); + + var distance = Vec3.distance(handPosition, objectPosition); + var speed = distance * 1; + + var lifepsan = distance / speed; + var lifespan = 1; + + if (this.particleBeam === null) { + this.createParticleBeam(objectPosition, finalRotation, color, speed); + } else { + this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); + } + }; + + this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { + + var particleBeamProperties = { + type: "ParticleEffect", + isEmitting: true, + position: position, + visible: false, + //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), + "name": "Particle Beam", + "color": color, + "maxParticles": 2000, + "lifespan": LINE_LENGTH / 10, + "emitRate": 50, + "emitSpeed": 5, + "speedSpread": 2, + "emitOrientation": { + "x": -1, + "y": 0, + "z": 0, + "w": 1 + }, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "emitRadiusStart": 0.5, + "polarStart": 0, + "polarFinish": 0, + "azimuthStart": -3.1415927410125732, + "azimuthFinish": 3.1415927410125732, + "emitAcceleration": { + x: 0, + y: 0, + z: 0 + }, + "accelerationSpread": { + "x": 0, + "y": 0, + "z": 0 + }, + "particleRadius": 0.01, + "radiusSpread": 0, + // "radiusStart": 0.01, + // "radiusFinish": 0.01, + // "colorSpread": { + // "red": 0, + // "green": 0, + // "blue": 0 + // }, + // "colorStart": color, + // "colorFinish": color, + "alpha": 1, + "alphaSpread": 0, + "alphaStart": 1, + "alphaFinish": 1, + "additiveBlending": 1, + "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" + } + + this.particleBeam = Entities.addEntity(particleBeamProperties); + }; + + this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { + + Entities.editEntity(this.particleBeam, { + rotation: orientation, + position: position, + visible: true, + color: color, + emitSpeed: speed, + lifepsan: lifepsan + + }) + + }; + + this.evalLightWorldTransform = function(modelPos, modelRot) { + + var MODEL_LIGHT_POSITION = { + x: 0, + y: -0.3, + z: 0 + }; + + var MODEL_LIGHT_ROTATION = Quat.angleAxis(-90, { + x: 1, + y: 0, + z: 0 + }); + + return { + p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), + q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) + }; + }; + + this.handleSpotlight = function(parentID, position) { + var LIFETIME = 100; + + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); + + var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + var lightProperties = { + type: "Light", + isSpotlight: true, + dimensions: { + x: 2, + y: 2, + z: 20 + }, + parentID: parentID, + color: { + red: 255, + green: 255, + blue: 255 + }, + intensity: 2, + exponent: 0.3, + cutoff: 20, + lifetime: LIFETIME, + position: lightTransform.p, + }; + + if (this.spotlight === null) { + this.spotlight = Entities.addEntity(lightProperties); + } else { + Entities.editEntity(this.spotlight, { + //without this, this light would maintain rotation with its parent + rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0), + }) + } + }; + + this.handlePointLight = function(parentID, position) { + var LIFETIME = 100; + + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); + var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + + var lightProperties = { + type: "Light", + isSpotlight: false, + dimensions: { + x: 2, + y: 2, + z: 20 + }, + parentID: parentID, + color: { + red: 255, + green: 255, + blue: 255 + }, + intensity: 2, + exponent: 0.3, + cutoff: 20, + lifetime: LIFETIME, + position: lightTransform.p, + }; + + if (this.pointlight === null) { + this.pointlight = Entities.addEntity(lightProperties); + } else { + + } + }; + + this.lineOff = function() { + if (this.pointer !== null) { + Entities.deleteEntity(this.pointer); + } + this.pointer = null; + }; + + this.overlayLineOff = function() { + if (this.overlayLine !== null) { + Overlays.deleteOverlay(this.overlayLine); + } + this.overlayLine = null; + }; + + this.particleBeamOff = function() { + if (this.particleBeam !== null) { + Entities.editEntity(this.particleBeam, { + visible: false + }) + } + } + + this.turnLightsOff = function() { + if (this.spotlight !== null) { + Entities.deleteEntity(this.spotlight); + this.spotlight = null; + } + + if (this.pointlight !== null) { + Entities.deleteEntity(this.pointlight); + this.pointlight = null; + } + }; + + + this.turnOffVisualizations = function() { + if (USE_ENTITY_LINES_FOR_SEARCHING === true || USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOff(); + } + + if (USE_OVERLAY_LINES_FOR_SEARCHING === true || USE_OVERLAY_LINES_FOR_MOVING === true) { + this.overlayLineOff(); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.particleBeamOff(); + } + }; + + this.triggerPress = function(value) { + _this.rawTriggerValue = value; + }; + + this.bumperPress = function(value) { + _this.rawBumperValue = value; + }; + + this.updateSmoothedTrigger = function() { + var triggerValue = this.rawTriggerValue; + // smooth out trigger value + this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + + (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); + }; + + this.triggerSmoothedSqueezed = function() { + return this.triggerValue > TRIGGER_ON_VALUE; + }; + + this.triggerSmoothedReleased = function() { + return this.triggerValue < TRIGGER_OFF_VALUE; + }; + + this.triggerSqueezed = function() { + var triggerValue = this.rawTriggerValue; + return triggerValue > TRIGGER_ON_VALUE; + }; + + this.bumperSqueezed = function() { + return _this.rawBumperValue > BUMPER_ON_VALUE; + }; + + this.bumperReleased = function() { + return _this.rawBumperValue < BUMPER_ON_VALUE; + }; + + this.off = function() { + if (this.triggerSmoothedSqueezed()) { + this.lastPickTime = 0; + this.setState(STATE_SEARCHING); + return; + } + if (this.bumperSqueezed()) { + this.lastPickTime = 0; + this.setState(STATE_EQUIP_SEARCHING); + return; + } + }; + + this.search = function() { + this.grabbedEntity = null; + + if (this.state == STATE_SEARCHING ? this.triggerSmoothedReleased() : this.bumperReleased()) { + this.setState(STATE_RELEASE); + return; + } + + // the trigger is being pressed, do a ray test + var handPosition = this.getHandPosition(); + var distantPickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()), + length: PICK_MAX_DISTANCE + }; + + // don't pick 60x per second. + var pickRays = []; + var now = Date.now(); + if (now - this.lastPickTime > MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) { + pickRays = [distantPickRay]; + this.lastPickTime = now; + } + + for (var index = 0; index < pickRays.length; ++index) { + var pickRay = pickRays[index]; + var directionNormalized = Vec3.normalize(pickRay.direction); + var directionBacked = Vec3.multiply(directionNormalized, PICK_BACKOFF_DISTANCE); + var pickRayBacked = { + origin: Vec3.subtract(pickRay.origin, directionBacked), + direction: pickRay.direction + }; + + if (WANT_DEBUG) { + this.debugLine(pickRayBacked.origin, Vec3.multiply(pickRayBacked.direction, NEAR_PICK_MAX_DISTANCE), { + red: 0, + green: 255, + blue: 0 + }) + } + + var intersection = Entities.findRayIntersection(pickRayBacked, true); + + if (intersection.intersects) { + // the ray is intersecting something we can move. + var intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection); + + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, intersection.entityID, DEFAULT_GRABBABLE_DATA); + + if (intersection.properties.name == "Grab Debug Entity") { + continue; + } + + if (typeof grabbableData.grabbable !== 'undefined' && !grabbableData.grabbable) { + continue; + } + if (intersectionDistance > pickRay.length) { + // too far away for this ray. + continue; + } + if (intersectionDistance <= NEAR_PICK_MAX_DISTANCE) { + // the hand is very close to the intersected object. go into close-grabbing mode. + if (grabbableData.wantsTrigger) { + this.grabbedEntity = intersection.entityID; + this.setState(STATE_NEAR_TRIGGER); + return; + } else if (!intersection.properties.locked) { + this.grabbedEntity = intersection.entityID; + if (this.state == STATE_SEARCHING) { + this.setState(STATE_NEAR_GRABBING); + } else { // equipping + if (typeof grabbableData.spatialKey !== 'undefined') { + // TODO + // if we go to STATE_EQUIP_SPRING the item will be pulled to the hand and will then switch + // to STATE_EQUIP. This needs some debugging, so just jump straight to STATE_EQUIP here. + // this.setState(STATE_EQUIP_SPRING); + this.setState(STATE_EQUIP); + } else { + this.setState(STATE_EQUIP); + } + } + return; + } + } else if (!entityIsGrabbedByOther(intersection.entityID)) { + // don't allow two people to distance grab the same object + if (intersection.properties.collisionsWillMove && !intersection.properties.locked) { + // the hand is far from the intersected object. go into distance-holding mode + this.grabbedEntity = intersection.entityID; + if (typeof grabbableData.spatialKey !== 'undefined' && this.state == STATE_EQUIP_SEARCHING) { + // if a distance pick in equip mode hits something with a spatialKey, equip it + // TODO use STATE_EQUIP_SPRING here once it works right. + // this.setState(STATE_EQUIP_SPRING); + this.setState(STATE_EQUIP); + return; + } else if (this.state == STATE_SEARCHING) { + this.setState(STATE_DISTANCE_HOLDING); + return; + } + } else if (grabbableData.wantsTrigger) { + this.grabbedEntity = intersection.entityID; + this.setState(STATE_FAR_TRIGGER); + return; + } + } + } + } + + // forward ray test failed, try sphere test. + if (WANT_DEBUG) { + Entities.addEntity({ + type: "Sphere", + name: "Grab Debug Entity", + dimensions: { + x: GRAB_RADIUS, + y: GRAB_RADIUS, + z: GRAB_RADIUS + }, + visible: true, + position: handPosition, + color: { + red: 0, + green: 255, + blue: 0 + }, + lifetime: 0.1, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + } + + var nearbyEntities = Entities.findEntities(handPosition, GRAB_RADIUS); + var minDistance = PICK_MAX_DISTANCE; + var i, props, distance, grabbableData; + this.grabbedEntity = null; + for (i = 0; i < nearbyEntities.length; i++) { + var grabbableDataForCandidate = + getEntityCustomData(GRABBABLE_DATA_KEY, nearbyEntities[i], DEFAULT_GRABBABLE_DATA); + if (typeof grabbableDataForCandidate.grabbable !== 'undefined' && !grabbableDataForCandidate.grabbable) { + continue; + } + var propsForCandidate = Entities.getEntityProperties(nearbyEntities[i], GRABBABLE_PROPERTIES); + + if (propsForCandidate.type == 'Unknown') { + continue; + } + + if (propsForCandidate.type == 'Light') { + continue; + } + + if (propsForCandidate.type == 'ParticleEffect') { + continue; + } + + if (propsForCandidate.type == 'PolyLine') { + continue; + } + + if (propsForCandidate.type == 'Zone') { + continue; + } + + if (propsForCandidate.locked && !grabbableDataForCandidate.wantsTrigger) { + continue; + } + + if (propsForCandidate.name == "Grab Debug Entity") { + continue; + } + + if (propsForCandidate.name == "grab pointer") { + continue; + } + + distance = Vec3.distance(propsForCandidate.position, handPosition); + if (distance < minDistance) { + this.grabbedEntity = nearbyEntities[i]; + minDistance = distance; + props = propsForCandidate; + grabbableData = grabbableDataForCandidate; + } + } + if (this.grabbedEntity !== null) { + if (grabbableData.wantsTrigger) { + this.setState(STATE_NEAR_TRIGGER); + return; + } else if (!props.locked && props.collisionsWillMove) { + this.setState(this.state == STATE_SEARCHING ? STATE_NEAR_GRABBING : STATE_EQUIP) + return; + } + } + + //search line visualizations + if (USE_ENTITY_LINES_FOR_SEARCHING === true) { + this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + } + + if (USE_OVERLAY_LINES_FOR_SEARCHING === true) { + this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true) { + this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR); + } + + }; + + this.distanceHolding = function() { + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var now = Date.now(); + + // add the action and initialize some variables + this.currentObjectPosition = grabbedProperties.position; + this.currentObjectRotation = grabbedProperties.rotation; + this.currentObjectTime = now; + this.handRelativePreviousPosition = Vec3.subtract(handControllerPosition, MyAvatar.position); + this.handPreviousRotation = handRotation; + this.currentCameraOrientation = Camera.orientation; + + // compute a constant based on the initial conditions which we use below to exagerate hand motion onto the held object + this.radiusScalar = Math.log(Vec3.distance(this.currentObjectPosition, handControllerPosition) + 1.0); + if (this.radiusScalar < 1.0) { + this.radiusScalar = 1.0; + } + + this.actionID = NULL_ACTION_ID; + this.actionID = Entities.addAction("spring", this.grabbedEntity, { + targetPosition: this.currentObjectPosition, + linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + targetRotation: this.currentObjectRotation, + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + tag: getTag(), + ttl: ACTION_TTL + }); + if (this.actionID === NULL_ACTION_ID) { + this.actionID = null; + } + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + + if (this.actionID !== null) { + this.setState(STATE_CONTINUE_DISTANCE_HOLDING); + this.activateEntity(this.grabbedEntity, grabbedProperties); + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab"); + } + + this.currentAvatarPosition = MyAvatar.position; + this.currentAvatarOrientation = MyAvatar.orientation; + + this.turnOffVisualizations(); + }; + + this.continueDistanceHolding = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + + var handPosition = this.getHandPosition(); + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state == STATE_CONTINUE_DISTANCE_HOLDING && this.bumperSqueezed() && + typeof grabbableData.spatialKey !== 'undefined') { + var saveGrabbedID = this.grabbedEntity; + this.release(); + this.setState(STATE_EQUIP); + this.grabbedEntity = saveGrabbedID; + return; + } + + + // the action was set up on a previous call. update the targets. + var radius = Vec3.distance(this.currentObjectPosition, handControllerPosition) * + this.radiusScalar * DISTANCE_HOLDING_RADIUS_FACTOR; + if (radius < 1.0) { + radius = 1.0; + } + + // how far did avatar move this timestep? + var currentPosition = MyAvatar.position; + var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition); + this.currentAvatarPosition = currentPosition; + + // How far did the avatar turn this timestep? + // Note: The following code is too long because we need a Quat.quatBetween() function + // that returns the minimum quaternion between two quaternions. + var currentOrientation = MyAvatar.orientation; + if (Quat.dot(currentOrientation, this.currentAvatarOrientation) < 0.0) { + var negativeCurrentOrientation = { + x: -currentOrientation.x, + y: -currentOrientation.y, + z: -currentOrientation.z, + w: -currentOrientation.w + }; + var avatarDeltaOrientation = Quat.multiply(negativeCurrentOrientation, Quat.inverse(this.currentAvatarOrientation)); + } else { + var avatarDeltaOrientation = Quat.multiply(currentOrientation, Quat.inverse(this.currentAvatarOrientation)); + } + var handToAvatar = Vec3.subtract(handControllerPosition, this.currentAvatarPosition); + var objectToAvatar = Vec3.subtract(this.currentObjectPosition, this.currentAvatarPosition); + var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar); + var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar); + this.currentAvatarOrientation = currentOrientation; + + // how far did hand move this timestep? + var handMoved = Vec3.subtract(handToAvatar, this.handRelativePreviousPosition); + this.handRelativePreviousPosition = handToAvatar; + + // magnify the hand movement but not the change from avatar movement & rotation + handMoved = Vec3.subtract(handMoved, handMovementFromTurning); + var superHandMoved = Vec3.multiply(handMoved, radius); + + // Move the object by the magnified amount and then by amount from avatar movement & rotation + var newObjectPosition = Vec3.sum(this.currentObjectPosition, superHandMoved); + newObjectPosition = Vec3.sum(newObjectPosition, avatarDeltaPosition); + newObjectPosition = Vec3.sum(newObjectPosition, objectMovementFromTurning); + + var deltaPosition = Vec3.subtract(newObjectPosition, this.currentObjectPosition); // meters + var now = Date.now(); + var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds + + this.currentObjectPosition = newObjectPosition; + this.currentObjectTime = now; + + // this doubles hand rotation + var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, + handRotation, + DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR), + Quat.inverse(this.handPreviousRotation)); + this.handPreviousRotation = handRotation; + this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation); + + Entities.callEntityMethod(this.grabbedEntity, "continueDistantGrab"); + + // mix in head motion + if (MOVE_WITH_HEAD) { + var objDistance = Vec3.length(objectToAvatar); + var before = Vec3.multiplyQbyV(this.currentCameraOrientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); + var after = Vec3.multiplyQbyV(Camera.orientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); + var change = Vec3.subtract(before, after); + this.currentCameraOrientation = Camera.orientation; + this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change); + } + + + //visualizations + if (USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); + } + if (USE_OVERLAY_LINES_FOR_MOVING === true) { + this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); + } + if (USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + } + if (USE_POINTLIGHT === true) { + this.handlePointLight(this.grabbedEntity); + } + if (USE_SPOTLIGHT === true) { + this.handleSpotlight(this.grabbedEntity); + } + + Entities.updateAction(this.grabbedEntity, this.actionID, { + targetPosition: this.currentObjectPosition, + linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + targetRotation: this.currentObjectRotation, + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + ttl: ACTION_TTL + }); + + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + }; + + this.nearGrabbing = function() { + var now = Date.now(); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + + this.turnOffVisualizations(); + + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + this.activateEntity(this.grabbedEntity, grabbedProperties); + if (grabbedProperties.collisionsWillMove && NEAR_GRABBING_KINEMATIC) { + Entities.editEntity(this.grabbedEntity, { + collisionsWillMove: false + }); + } + + var handRotation = this.getHandRotation(); + var handPosition = this.getHandPosition(); + + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) { + // if an object is "equipped" and has a spatialKey, use it. + this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; + this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); + this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + } else { + this.ignoreIK = false; + + var objectRotation = grabbedProperties.rotation; + this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); + + var currentObjectPosition = grabbedProperties.position; + var offset = Vec3.subtract(currentObjectPosition, handPosition); + this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset); + } + + this.actionID = NULL_ACTION_ID; + this.actionID = Entities.addAction("hold", this.grabbedEntity, { + hand: this.hand === RIGHT_HAND ? "right" : "left", + timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, + relativePosition: this.offsetPosition, + relativeRotation: this.offsetRotation, + ttl: ACTION_TTL, + kinematic: NEAR_GRABBING_KINEMATIC, + kinematicSetVelocity: true, + ignoreIK: this.ignoreIK + }); + if (this.actionID === NULL_ACTION_ID) { + this.actionID = null; + } else { + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + if (this.state == STATE_NEAR_GRABBING) { + this.setState(STATE_CONTINUE_NEAR_GRABBING); + } else { + // equipping + Entities.callEntityMethod(this.grabbedEntity, "startEquip", [JSON.stringify(this.hand)]); + this.startHandGrasp(); + + this.setState(STATE_CONTINUE_EQUIP_BD); + } + + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + + Entities.callEntityMethod(this.grabbedEntity, "startNearGrab"); + + } + + this.currentHandControllerTipPosition = + (this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition; + + this.currentObjectTime = Date.now(); + }; + + this.continueNearGrabbing = function() { + if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + if (this.state == STATE_CONTINUE_EQUIP_BD && this.bumperReleased()) { + this.setState(STATE_CONTINUE_EQUIP); + return; + } + if (this.state == STATE_CONTINUE_EQUIP && this.bumperSqueezed()) { + this.setState(STATE_WAITING_FOR_BUMPER_RELEASE); + return; + } + if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.bumperSqueezed()) { + this.setState(STATE_CONTINUE_EQUIP_BD); + Entities.callEntityMethod(this.grabbedEntity, "startEquip", [JSON.stringify(this.hand)]); + return; + } + + // Keep track of the fingertip velocity to impart when we release the object. + // Note that the idea of using a constant 'tip' velocity regardless of the + // object's actual held offset is an idea intended to make it easier to throw things: + // Because we might catch something or transfer it between hands without a good idea + // of it's actual offset, let's try imparting a velocity which is at a fixed radius + // from the palm. + + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var now = Date.now(); + + var deltaPosition = Vec3.subtract(handControllerPosition, this.currentHandControllerTipPosition); // meters + var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds + + this.currentHandControllerTipPosition = handControllerPosition; + this.currentObjectTime = now; + Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); + + if (this.state === STATE_CONTINUE_EQUIP_BD) { + Entities.callEntityMethod(this.grabbedEntity, "continueEquip"); + } + + if (this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) { + // if less than a 5 seconds left, refresh the actions ttl + Entities.updateAction(this.grabbedEntity, this.actionID, { + hand: this.hand === RIGHT_HAND ? "right" : "left", + timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, + relativePosition: this.offsetPosition, + relativeRotation: this.offsetRotation, + ttl: ACTION_TTL, + kinematic: NEAR_GRABBING_KINEMATIC, + kinematicSetVelocity: true, + ignoreIK: this.ignoreIK + }); + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + } + }; + + this.waitingForBumperRelease = function() { + if (this.bumperReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + Entities.callEntityMethod(this.grabbedEntity, "unequip"); + this.endHandGrasp(); + + } + }; + + this.pullTowardEquipPosition = function() { + + this.turnOffVisualizations(); + + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + // use a spring to pull the object to where it will be when equipped + var relativeRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + var relativePosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); + var ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; + var handRotation = this.getHandRotation(); + var handPosition = this.getHandPosition(); + var targetRotation = Quat.multiply(handRotation, relativeRotation); + var offset = Vec3.multiplyQbyV(targetRotation, relativePosition); + var targetPosition = Vec3.sum(handPosition, offset); + + if (typeof this.equipSpringID === 'undefined' || + this.equipSpringID === null || + this.equipSpringID === NULL_ACTION_ID) { + this.equipSpringID = Entities.addAction("spring", this.grabbedEntity, { + targetPosition: targetPosition, + linearTimeScale: EQUIP_SPRING_TIMEFRAME, + targetRotation: targetRotation, + angularTimeScale: EQUIP_SPRING_TIMEFRAME, + ttl: ACTION_TTL, + ignoreIK: ignoreIK + }); + if (this.equipSpringID === NULL_ACTION_ID) { + this.equipSpringID = null; + this.setState(STATE_OFF); + return; + } + } else { + Entities.updateAction(this.grabbedEntity, this.equipSpringID, { + targetPosition: targetPosition, + linearTimeScale: EQUIP_SPRING_TIMEFRAME, + targetRotation: targetRotation, + angularTimeScale: EQUIP_SPRING_TIMEFRAME, + ttl: ACTION_TTL, + ignoreIK: ignoreIK + }); + } + + if (Vec3.distance(grabbedProperties.position, targetPosition) < EQUIP_SPRING_SHUTOFF_DISTANCE) { + Entities.deleteAction(this.grabbedEntity, this.equipSpringID); + this.equipSpringID = null; + this.setState(STATE_EQUIP); + } + }; + + this.nearTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + + Entities.callEntityMethod(this.grabbedEntity, "startNearTrigger"); + this.setState(STATE_CONTINUE_NEAR_TRIGGER); + }; + + this.farTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopFarTrigger"); + return; + } + + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + Entities.callEntityMethod(this.grabbedEntity, "startFarTrigger"); + this.setState(STATE_CONTINUE_FAR_TRIGGER); + }; + + this.continueNearTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + + Entities.callEntityMethod(this.grabbedEntity, "continueNearTrigger"); + }; + + this.continueFarTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + + var handPosition = this.getHandPosition(); + var pickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()) + }; + + var now = Date.now(); + if (now - this.lastPickTime > MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) { + var intersection = Entities.findRayIntersection(pickRay, true); + this.lastPickTime = now; + if (intersection.entityID != this.grabbedEntity) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopFarTrigger"); + return; + } + } + + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger"); + }; + + _this.allTouchedIDs = {}; + + this.touchTest = function() { + var maxDistance = 0.05; + var leftHandPosition = MyAvatar.getLeftPalmPosition(); + var rightHandPosition = MyAvatar.getRightPalmPosition(); + var leftEntities = Entities.findEntities(leftHandPosition, maxDistance); + var rightEntities = Entities.findEntities(rightHandPosition, maxDistance); + var ids = []; + + if (leftEntities.length !== 0) { + leftEntities.forEach(function(entity) { + ids.push(entity); + }); + + } + + if (rightEntities.length !== 0) { + rightEntities.forEach(function(entity) { + ids.push(entity); + }); + } + + ids.forEach(function(id) { + + var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); + if (props.name === 'pointer') { + return; + } else { + var entityMinPoint = props.boundingBox.brn; + var entityMaxPoint = props.boundingBox.tfl; + var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); + var rightIsTouching = pointInExtents(rightHandPosition, entityMinPoint, entityMaxPoint); + + if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id] === undefined) { + // we haven't been touched before, but either right or left is touching us now + _this.allTouchedIDs[id] = true; + _this.startTouch(id); + } else if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id]) { + // we have been touched before and are still being touched + // continue touch + _this.continueTouch(id); + } else if (_this.allTouchedIDs[id]) { + delete _this.allTouchedIDs[id]; + _this.stopTouch(id); + + } else { + //we are in another state + return; + } + } + + }); + + }; + + this.startTouch = function(entityID) { + Entities.callEntityMethod(entityID, "startTouch"); + }; + + this.continueTouch = function(entityID) { + Entities.callEntityMethod(entityID, "continueTouch"); + }; + + this.stopTouch = function(entityID) { + Entities.callEntityMethod(entityID, "stopTouch"); + }; + + this.release = function() { + + this.turnLightsOff(); + this.turnOffVisualizations(); + + if (this.grabbedEntity !== null) { + if (this.actionID !== null) { + Entities.deleteAction(this.grabbedEntity, this.actionID); + } + } + + this.deactivateEntity(this.grabbedEntity); + + this.grabbedEntity = null; + this.actionID = null; + this.setState(STATE_OFF); + }; + + this.cleanup = function() { + this.release(); + this.endHandGrasp(); + Entities.deleteEntity(this.particleBeam); + Entities.deleteEntity(this.spotLight); + Entities.deleteEntity(this.pointLight); + }; + + this.activateEntity = function(entityID, grabbedProperties) { + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, entityID, DEFAULT_GRABBABLE_DATA); + var invertSolidWhileHeld = grabbableData["invertSolidWhileHeld"]; + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + data["activated"] = true; + data["avatarId"] = MyAvatar.sessionUUID; + data["refCount"] = data["refCount"] ? data["refCount"] + 1 : 1; + // zero gravity and set ignoreForCollisions in a way that lets us put them back, after all grabs are done + if (data["refCount"] == 1) { + data["gravity"] = grabbedProperties.gravity; + data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions; + data["collisionsWillMove"] = grabbedProperties.collisionsWillMove; + var whileHeldProperties = { + gravity: { + x: 0, + y: 0, + z: 0 + } + }; + if (invertSolidWhileHeld) { + whileHeldProperties["ignoreForCollisions"] = !grabbedProperties.ignoreForCollisions; + } + Entities.editEntity(entityID, whileHeldProperties); + } + + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + return data; + }; + + this.deactivateEntity = function(entityID) { + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + if (data && data["refCount"]) { + data["refCount"] = data["refCount"] - 1; + if (data["refCount"] < 1) { + Entities.editEntity(entityID, { + gravity: data["gravity"], + ignoreForCollisions: data["ignoreForCollisions"], + collisionsWillMove: data["collisionsWillMove"] + }); + data = null; + } + } else { + data = null; + } + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + }; + + + //this is our handler, where we do the actual work of changing animation settings + this.graspHand = function(animationProperties) { + var result = {}; + //full alpha on overlay for this hand + //set grab to true + //set idle to false + //full alpha on the blend btw open and grab + if (_this.hand === RIGHT_HAND) { + result['rightHandOverlayAlpha'] = 1.0; + result['isRightHandGrab'] = true; + result['isRightHandIdle'] = false; + result['rightHandGrabBlend'] = 1.0; + } else if (_this.hand === LEFT_HAND) { + result['leftHandOverlayAlpha'] = 1.0; + result['isLeftHandGrab'] = true; + result['isLeftHandIdle'] = false; + result['leftHandGrabBlend'] = 1.0; + } + //return an object with our updated settings + return result; + }; + + this.graspHandler = null + + this.startHandGrasp = function() { + if (this.hand === RIGHT_HAND) { + this.graspHandler = MyAvatar.addAnimationStateHandler(this.graspHand, ['isRightHandGrab']); + } else if (this.hand === LEFT_HAND) { + this.graspHandler = MyAvatar.addAnimationStateHandler(this.graspHand, ['isLeftHandGrab']); + } + }; + + this.endHandGrasp = function() { + // Tell the animation system we don't need any more callbacks. + MyAvatar.removeAnimationStateHandler(this.graspHandler); + }; + +}; + +var rightController = new MyController(RIGHT_HAND); +var leftController = new MyController(LEFT_HAND); + +//preload the particle beams so that they are full length when you start searching +if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + rightController.createParticleBeam(); + leftController.createParticleBeam(); +} + +var MAPPING_NAME = "com.highfidelity.handControllerGrab"; + +var mapping = Controller.newMapping(MAPPING_NAME); +mapping.from([Controller.Standard.RT]).peek().to(rightController.triggerPress); +mapping.from([Controller.Standard.LT]).peek().to(leftController.triggerPress); + +mapping.from([Controller.Standard.RB]).peek().to(rightController.bumperPress); +mapping.from([Controller.Standard.LB]).peek().to(leftController.bumperPress); + +Controller.enableMapping(MAPPING_NAME); + +//the section below allows the grab script to listen for messages that disable either one or both hands. useful for two handed items +var handToDisable = 'none'; + +function update() { + if (handToDisable !== LEFT_HAND && handToDisable !== 'both') { + leftController.update(); + } + if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') { + rightController.update(); + } +} + +Messages.subscribe('Hifi-Hand-Disabler'); + +handleHandDisablerMessages = function(channel, message, sender) { + + if (sender === MyAvatar.sessionUUID) { + if (message === 'left') { + handToDisable = LEFT_HAND; + } + if (message === 'right') { + handToDisable = RIGHT_HAND; + } + if (message === 'both') { + handToDisable = 'both'; + } + if (message === 'none') { + handToDisable = 'none'; + } + } + +} + +Messages.messageReceived.connect(handleHandDisablerMessages); + +function cleanup() { + rightController.cleanup(); + leftController.cleanup(); + Controller.disableMapping(MAPPING_NAME); +} + +Script.scriptEnding.connect(cleanup); +Script.update.connect(update); \ No newline at end of file diff --git a/examples/controllers/handControllerGrab-spotlight.js b/examples/controllers/handControllerGrab-spotlight.js new file mode 100644 index 0000000000..ea05a44f78 --- /dev/null +++ b/examples/controllers/handControllerGrab-spotlight.js @@ -0,0 +1,1649 @@ +// handControllerGrab.js +// +// Created by Eric Levin on 9/2/15 +// Additions by James B. Pollack @imgntn on 9/24/2015 +// Additions By Seth Alves on 10/20/2015 +// Copyright 2015 High Fidelity, Inc. +// +// Grabs physically moveable entities with hydra-like controllers; it works for either near or far objects. +// Also supports touch and equipping objects. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ + +Script.include("../libraries/utils.js"); + +// +// add lines where the hand ray picking is happening +// +var WANT_DEBUG = false; + +// +// these tune time-averaging and "on" value for analog trigger +// + +var TRIGGER_SMOOTH_RATIO = 0.1; // 0.0 disables smoothing of trigger value +var TRIGGER_ON_VALUE = 0.4; +var TRIGGER_OFF_VALUE = 0.15; + +var BUMPER_ON_VALUE = 0.5; + +// +// distant manipulation +// + +var DISTANCE_HOLDING_RADIUS_FACTOR = 3.5; // multiplied by distance between hand and object +var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position +var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did +var MOVE_WITH_HEAD = true; // experimental head-controll of distantly held objects + +var NO_INTERSECT_COLOR = { + red: 10, + green: 10, + blue: 255 +}; // line color when pick misses +var INTERSECT_COLOR = { + red: 250, + green: 10, + blue: 10 +}; // line color when pick hits +var LINE_ENTITY_DIMENSIONS = { + x: 1000, + y: 1000, + z: 1000 +}; + +var LINE_LENGTH = 500; +var PICK_MAX_DISTANCE = 500; // max length of pick-ray + +// +// near grabbing +// + +var GRAB_RADIUS = 0.03; // if the ray misses but an object is this close, it will still be selected +var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position +var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held object's velocity. 1.0 to disable. +var NEAR_PICK_MAX_DISTANCE = 0.3; // max length of pick-ray for close grabbing to be selected +var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things +var PICK_BACKOFF_DISTANCE = 0.2; // helps when hand is intersecting the grabble object +var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed + +// +// equip +// + +var EQUIP_SPRING_SHUTOFF_DISTANCE = 0.05; +var EQUIP_SPRING_TIMEFRAME = 0.4; // how quickly objects move to their new position + +// +// other constants +// + +var RIGHT_HAND = 1; +var LEFT_HAND = 0; + +var ZERO_VEC = { + x: 0, + y: 0, + z: 0 +}; + +var NULL_ACTION_ID = "{00000000-0000-0000-000000000000}"; +var MSEC_PER_SEC = 1000.0; + +// these control how long an abandoned pointer line or action will hang around +var LIFETIME = 10; +var ACTION_TTL = 15; // seconds +var ACTION_TTL_REFRESH = 5; +var PICKS_PER_SECOND_PER_HAND = 5; +var MSECS_PER_SEC = 1000.0; +var GRABBABLE_PROPERTIES = [ + "position", + "rotation", + "gravity", + "ignoreForCollisions", + "collisionsWillMove", + "locked", + "name" +]; + +var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js +var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js + +var DEFAULT_GRABBABLE_DATA = { + grabbable: true, + invertSolidWhileHeld: false +}; + +//we've created various ways of visualizing looking for and moving distant objects +var USE_ENTITY_LINES_FOR_SEARCHING = false; +var USE_OVERLAY_LINES_FOR_SEARCHING = true; +var USE_PARTICLE_BEAM_FOR_SEARCHING = false; + +var USE_ENTITY_LINES_FOR_MOVING = true; +var USE_OVERLAY_LINES_FOR_MOVING = false; +var USE_PARTICLE_BEAM_FOR_MOVING = false; + +var USE_SPOTLIGHT = true; +var USE_POINTLIGHT = false; + +// states for the state machine +var STATE_OFF = 0; +var STATE_SEARCHING = 1; +var STATE_DISTANCE_HOLDING = 2; +var STATE_CONTINUE_DISTANCE_HOLDING = 3; +var STATE_NEAR_GRABBING = 4; +var STATE_CONTINUE_NEAR_GRABBING = 5; +var STATE_NEAR_TRIGGER = 6; +var STATE_CONTINUE_NEAR_TRIGGER = 7; +var STATE_FAR_TRIGGER = 8; +var STATE_CONTINUE_FAR_TRIGGER = 9; +var STATE_RELEASE = 10; +var STATE_EQUIP_SEARCHING = 11; +var STATE_EQUIP = 12 +var STATE_CONTINUE_EQUIP_BD = 13; // equip while bumper is still held down +var STATE_CONTINUE_EQUIP = 14; +var STATE_WAITING_FOR_BUMPER_RELEASE = 15; +var STATE_EQUIP_SPRING = 16; + + + +function stateToName(state) { + switch (state) { + case STATE_OFF: + return "off"; + case STATE_SEARCHING: + return "searching"; + case STATE_DISTANCE_HOLDING: + return "distance_holding"; + case STATE_CONTINUE_DISTANCE_HOLDING: + return "continue_distance_holding"; + case STATE_NEAR_GRABBING: + return "near_grabbing"; + case STATE_CONTINUE_NEAR_GRABBING: + return "continue_near_grabbing"; + case STATE_NEAR_TRIGGER: + return "near_trigger"; + case STATE_CONTINUE_NEAR_TRIGGER: + return "continue_near_trigger"; + case STATE_FAR_TRIGGER: + return "far_trigger"; + case STATE_CONTINUE_FAR_TRIGGER: + return "continue_far_trigger"; + case STATE_RELEASE: + return "release"; + case STATE_EQUIP_SEARCHING: + return "equip_searching"; + case STATE_EQUIP: + return "equip"; + case STATE_CONTINUE_EQUIP_BD: + return "continue_equip_bd"; + case STATE_CONTINUE_EQUIP: + return "continue_equip"; + case STATE_WAITING_FOR_BUMPER_RELEASE: + return "waiting_for_bumper_release"; + case STATE_EQUIP_SPRING: + return "state_equip_spring"; + } + + return "unknown"; +} + +function getTag() { + return "grab-" + MyAvatar.sessionUUID; +} + +function entityIsGrabbedByOther(entityID) { + // by convention, a distance grab sets the tag of its action to be grab-*owner-session-id*. + var actionIDs = Entities.getActionIDs(entityID); + for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { + var actionID = actionIDs[actionIndex]; + var actionArguments = Entities.getActionArguments(entityID, actionID); + var tag = actionArguments["tag"]; + if (tag == getTag()) { + // we see a grab-*uuid* shaped tag, but it's our tag, so that's okay. + continue; + } + if (tag.slice(0, 5) == "grab-") { + // we see a grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it. + return true; + } + } + return false; +} + +function getSpatialOffsetPosition(hand, spatialKey) { + var position = Vec3.ZERO; + + if (hand !== RIGHT_HAND && spatialKey.leftRelativePosition) { + position = spatialKey.leftRelativePosition; + } + if (hand === RIGHT_HAND && spatialKey.rightRelativePosition) { + position = spatialKey.rightRelativePosition; + } + if (spatialKey.relativePosition) { + position = spatialKey.relativePosition; + } + + return position; +} + +var yFlip = Quat.angleAxis(180, Vec3.UNIT_Y); + +function getSpatialOffsetRotation(hand, spatialKey) { + var rotation = Quat.IDENTITY; + + if (hand !== RIGHT_HAND && spatialKey.leftRelativeRotation) { + rotation = spatialKey.leftRelativeRotation; + } + if (hand === RIGHT_HAND && spatialKey.rightRelativeRotation) { + rotation = spatialKey.rightRelativeRotation; + } + if (spatialKey.relativeRotation) { + rotation = spatialKey.relativeRotation; + } + + // Flip left hand + if (hand !== RIGHT_HAND) { + rotation = Quat.multiply(yFlip, rotation); + } + + return rotation; +} + +function MyController(hand) { + this.hand = hand; + if (this.hand === RIGHT_HAND) { + this.getHandPosition = MyAvatar.getRightPalmPosition; + this.getHandRotation = MyAvatar.getRightPalmRotation; + } else { + this.getHandPosition = MyAvatar.getLeftPalmPosition; + this.getHandRotation = MyAvatar.getLeftPalmRotation; + } + + var SPATIAL_CONTROLLERS_PER_PALM = 2; + var TIP_CONTROLLER_OFFSET = 1; + this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand; + this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; + + this.actionID = null; // action this script created... + this.grabbedEntity = null; // on this entity. + this.state = STATE_OFF; + this.pointer = null; // entity-id of line object + this.triggerValue = 0; // rolling average of trigger value + this.rawTriggerValue = 0; + this.rawBumperValue = 0; + + //for visualizations + this.overlayLine = null; + this.particleBeam = null; + + //for lights + this.spotlight = null; + this.pointlight = null; + + this.ignoreIK = false; + this.offsetPosition = Vec3.ZERO; + this.offsetRotation = Quat.IDENTITY; + + var _this = this; + + this.update = function() { + + this.updateSmoothedTrigger(); + + switch (this.state) { + case STATE_OFF: + this.off(); + this.touchTest(); + break; + case STATE_SEARCHING: + this.search(); + break; + case STATE_EQUIP_SEARCHING: + this.search(); + break; + case STATE_DISTANCE_HOLDING: + this.distanceHolding(); + break; + case STATE_CONTINUE_DISTANCE_HOLDING: + this.continueDistanceHolding(); + break; + case STATE_NEAR_GRABBING: + case STATE_EQUIP: + this.nearGrabbing(); + break; + case STATE_WAITING_FOR_BUMPER_RELEASE: + this.waitingForBumperRelease(); + break; + case STATE_EQUIP_SPRING: + this.pullTowardEquipPosition() + break; + case STATE_CONTINUE_NEAR_GRABBING: + case STATE_CONTINUE_EQUIP_BD: + case STATE_CONTINUE_EQUIP: + this.continueNearGrabbing(); + break; + case STATE_NEAR_TRIGGER: + this.nearTrigger(); + break; + case STATE_CONTINUE_NEAR_TRIGGER: + this.continueNearTrigger(); + break; + case STATE_FAR_TRIGGER: + this.farTrigger(); + break; + case STATE_CONTINUE_FAR_TRIGGER: + this.continueFarTrigger(); + break; + case STATE_RELEASE: + this.release(); + break; + } + }; + + this.setState = function(newState) { + if (WANT_DEBUG) { + print("STATE: " + stateToName(this.state) + " --> " + stateToName(newState) + ", hand: " + this.hand); + } + this.state = newState; + }; + + this.debugLine = function(closePoint, farPoint, color) { + Entities.addEntity({ + type: "Line", + name: "Grab Debug Entity", + dimensions: LINE_ENTITY_DIMENSIONS, + visible: true, + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: 0.1, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + }; + + this.lineOn = function(closePoint, farPoint, color) { + // draw a line + if (this.pointer === null) { + this.pointer = Entities.addEntity({ + type: "Line", + name: "grab pointer", + dimensions: LINE_ENTITY_DIMENSIONS, + visible: true, + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: LIFETIME, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + } else { + var age = Entities.getEntityProperties(this.pointer, "age").age; + this.pointer = Entities.editEntity(this.pointer, { + position: closePoint, + linePoints: [ZERO_VEC, farPoint], + color: color, + lifetime: age + LIFETIME + }); + } + }; + + this.overlayLineOn = function(closePoint, farPoint, color) { + if (this.overlayLine === null) { + var lineProperties = { + lineWidth: 5, + start: closePoint, + end: farPoint, + color: color, + ignoreRayIntersection: true, // always ignore this + visible: true, + alpha: 1 + }; + + this.overlayLine = Overlays.addOverlay("line3d", lineProperties); + + } else { + var success = Overlays.editOverlay(this.overlayLine, { + lineWidth: 5, + start: closePoint, + end: farPoint, + color: color, + visible: true, + ignoreRayIntersection: true, // always ignore this + alpha: 1 + }); + } + }; + + this.handleParticleBeam = function(position, orientation, color) { + + var rotation = Quat.angleAxis(0, { + x: 1, + y: 0, + z: 0 + }); + + var finalRotation = Quat.multiply(orientation, rotation); + + if (this.particleBeam === null) { + this.createParticleBeam(position, finalRotation, color); + } else { + this.updateParticleBeam(position, finalRotation, color); + } + }; + + this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { + + var handToObject = Vec3.subtract(objectPosition, handPosition); + var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); + + var distance = Vec3.distance(handPosition, objectPosition); + var speed = distance * 1; + + var lifepsan = distance / speed; + var lifespan = 1; + + if (this.particleBeam === null) { + this.createParticleBeam(objectPosition, finalRotation, color, speed); + } else { + this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); + } + }; + + this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { + + var particleBeamProperties = { + type: "ParticleEffect", + isEmitting: true, + position: position, + visible: false, + //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), + "name": "Particle Beam", + "color": color, + "maxParticles": 2000, + "lifespan": LINE_LENGTH / 10, + "emitRate": 50, + "emitSpeed": 5, + "speedSpread": 2, + "emitOrientation": { + "x": -1, + "y": 0, + "z": 0, + "w": 1 + }, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "emitRadiusStart": 0.5, + "polarStart": 0, + "polarFinish": 0, + "azimuthStart": -3.1415927410125732, + "azimuthFinish": 3.1415927410125732, + "emitAcceleration": { + x: 0, + y: 0, + z: 0 + }, + "accelerationSpread": { + "x": 0, + "y": 0, + "z": 0 + }, + "particleRadius": 0.01, + "radiusSpread": 0, + // "radiusStart": 0.01, + // "radiusFinish": 0.01, + // "colorSpread": { + // "red": 0, + // "green": 0, + // "blue": 0 + // }, + // "colorStart": color, + // "colorFinish": color, + "alpha": 1, + "alphaSpread": 0, + "alphaStart": 1, + "alphaFinish": 1, + "additiveBlending": 1, + "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" + } + + this.particleBeam = Entities.addEntity(particleBeamProperties); + }; + + this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { + + Entities.editEntity(this.particleBeam, { + rotation: orientation, + position: position, + visible: true, + color: color, + emitSpeed: speed, + lifepsan: lifepsan + + }) + + }; + + this.evalLightWorldTransform = function(modelPos, modelRot) { + + var MODEL_LIGHT_POSITION = { + x: 0, + y: -0.3, + z: 0 + }; + + var MODEL_LIGHT_ROTATION = Quat.angleAxis(-90, { + x: 1, + y: 0, + z: 0 + }); + + return { + p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), + q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) + }; + }; + + this.handleSpotlight = function(parentID, position) { + var LIFETIME = 100; + + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); + + var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + var lightProperties = { + type: "Light", + isSpotlight: true, + dimensions: { + x: 2, + y: 2, + z: 20 + }, + parentID: parentID, + color: { + red: 255, + green: 255, + blue: 255 + }, + intensity: 2, + exponent: 0.3, + cutoff: 20, + lifetime: LIFETIME, + position: lightTransform.p, + }; + + if (this.spotlight === null) { + this.spotlight = Entities.addEntity(lightProperties); + } else { + Entities.editEntity(this.spotlight, { + //without this, this light would maintain rotation with its parent + rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0), + }) + } + }; + + this.handlePointLight = function(parentID, position) { + var LIFETIME = 100; + + var modelProperties = Entities.getEntityProperties(parentID, ['position', 'rotation']); + var lightTransform = this.evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + + var lightProperties = { + type: "Light", + isSpotlight: false, + dimensions: { + x: 2, + y: 2, + z: 20 + }, + parentID: parentID, + color: { + red: 255, + green: 255, + blue: 255 + }, + intensity: 2, + exponent: 0.3, + cutoff: 20, + lifetime: LIFETIME, + position: lightTransform.p, + }; + + if (this.pointlight === null) { + this.pointlight = Entities.addEntity(lightProperties); + } else { + + } + }; + + this.lineOff = function() { + if (this.pointer !== null) { + Entities.deleteEntity(this.pointer); + } + this.pointer = null; + }; + + this.overlayLineOff = function() { + if (this.overlayLine !== null) { + Overlays.deleteOverlay(this.overlayLine); + } + this.overlayLine = null; + }; + + this.particleBeamOff = function() { + if (this.particleBeam !== null) { + Entities.editEntity(this.particleBeam, { + visible: false + }) + } + } + + this.turnLightsOff = function() { + if (this.spotlight !== null) { + Entities.deleteEntity(this.spotlight); + this.spotlight = null; + } + + if (this.pointlight !== null) { + Entities.deleteEntity(this.pointlight); + this.pointlight = null; + } + }; + + + this.turnOffVisualizations = function() { + if (USE_ENTITY_LINES_FOR_SEARCHING === true || USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOff(); + } + + if (USE_OVERLAY_LINES_FOR_SEARCHING === true || USE_OVERLAY_LINES_FOR_MOVING === true) { + this.overlayLineOff(); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.particleBeamOff(); + } + }; + + this.triggerPress = function(value) { + _this.rawTriggerValue = value; + }; + + this.bumperPress = function(value) { + _this.rawBumperValue = value; + }; + + this.updateSmoothedTrigger = function() { + var triggerValue = this.rawTriggerValue; + // smooth out trigger value + this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + + (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); + }; + + this.triggerSmoothedSqueezed = function() { + return this.triggerValue > TRIGGER_ON_VALUE; + }; + + this.triggerSmoothedReleased = function() { + return this.triggerValue < TRIGGER_OFF_VALUE; + }; + + this.triggerSqueezed = function() { + var triggerValue = this.rawTriggerValue; + return triggerValue > TRIGGER_ON_VALUE; + }; + + this.bumperSqueezed = function() { + return _this.rawBumperValue > BUMPER_ON_VALUE; + }; + + this.bumperReleased = function() { + return _this.rawBumperValue < BUMPER_ON_VALUE; + }; + + this.off = function() { + if (this.triggerSmoothedSqueezed()) { + this.lastPickTime = 0; + this.setState(STATE_SEARCHING); + return; + } + if (this.bumperSqueezed()) { + this.lastPickTime = 0; + this.setState(STATE_EQUIP_SEARCHING); + return; + } + }; + + this.search = function() { + this.grabbedEntity = null; + + if (this.state == STATE_SEARCHING ? this.triggerSmoothedReleased() : this.bumperReleased()) { + this.setState(STATE_RELEASE); + return; + } + + // the trigger is being pressed, do a ray test + var handPosition = this.getHandPosition(); + var distantPickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()), + length: PICK_MAX_DISTANCE + }; + + // don't pick 60x per second. + var pickRays = []; + var now = Date.now(); + if (now - this.lastPickTime > MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) { + pickRays = [distantPickRay]; + this.lastPickTime = now; + } + + for (var index = 0; index < pickRays.length; ++index) { + var pickRay = pickRays[index]; + var directionNormalized = Vec3.normalize(pickRay.direction); + var directionBacked = Vec3.multiply(directionNormalized, PICK_BACKOFF_DISTANCE); + var pickRayBacked = { + origin: Vec3.subtract(pickRay.origin, directionBacked), + direction: pickRay.direction + }; + + if (WANT_DEBUG) { + this.debugLine(pickRayBacked.origin, Vec3.multiply(pickRayBacked.direction, NEAR_PICK_MAX_DISTANCE), { + red: 0, + green: 255, + blue: 0 + }) + } + + var intersection = Entities.findRayIntersection(pickRayBacked, true); + + if (intersection.intersects) { + // the ray is intersecting something we can move. + var intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection); + + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, intersection.entityID, DEFAULT_GRABBABLE_DATA); + + if (intersection.properties.name == "Grab Debug Entity") { + continue; + } + + if (typeof grabbableData.grabbable !== 'undefined' && !grabbableData.grabbable) { + continue; + } + if (intersectionDistance > pickRay.length) { + // too far away for this ray. + continue; + } + if (intersectionDistance <= NEAR_PICK_MAX_DISTANCE) { + // the hand is very close to the intersected object. go into close-grabbing mode. + if (grabbableData.wantsTrigger) { + this.grabbedEntity = intersection.entityID; + this.setState(STATE_NEAR_TRIGGER); + return; + } else if (!intersection.properties.locked) { + this.grabbedEntity = intersection.entityID; + if (this.state == STATE_SEARCHING) { + this.setState(STATE_NEAR_GRABBING); + } else { // equipping + if (typeof grabbableData.spatialKey !== 'undefined') { + // TODO + // if we go to STATE_EQUIP_SPRING the item will be pulled to the hand and will then switch + // to STATE_EQUIP. This needs some debugging, so just jump straight to STATE_EQUIP here. + // this.setState(STATE_EQUIP_SPRING); + this.setState(STATE_EQUIP); + } else { + this.setState(STATE_EQUIP); + } + } + return; + } + } else if (!entityIsGrabbedByOther(intersection.entityID)) { + // don't allow two people to distance grab the same object + if (intersection.properties.collisionsWillMove && !intersection.properties.locked) { + // the hand is far from the intersected object. go into distance-holding mode + this.grabbedEntity = intersection.entityID; + if (typeof grabbableData.spatialKey !== 'undefined' && this.state == STATE_EQUIP_SEARCHING) { + // if a distance pick in equip mode hits something with a spatialKey, equip it + // TODO use STATE_EQUIP_SPRING here once it works right. + // this.setState(STATE_EQUIP_SPRING); + this.setState(STATE_EQUIP); + return; + } else if (this.state == STATE_SEARCHING) { + this.setState(STATE_DISTANCE_HOLDING); + return; + } + } else if (grabbableData.wantsTrigger) { + this.grabbedEntity = intersection.entityID; + this.setState(STATE_FAR_TRIGGER); + return; + } + } + } + } + + // forward ray test failed, try sphere test. + if (WANT_DEBUG) { + Entities.addEntity({ + type: "Sphere", + name: "Grab Debug Entity", + dimensions: { + x: GRAB_RADIUS, + y: GRAB_RADIUS, + z: GRAB_RADIUS + }, + visible: true, + position: handPosition, + color: { + red: 0, + green: 255, + blue: 0 + }, + lifetime: 0.1, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) + }); + } + + var nearbyEntities = Entities.findEntities(handPosition, GRAB_RADIUS); + var minDistance = PICK_MAX_DISTANCE; + var i, props, distance, grabbableData; + this.grabbedEntity = null; + for (i = 0; i < nearbyEntities.length; i++) { + var grabbableDataForCandidate = + getEntityCustomData(GRABBABLE_DATA_KEY, nearbyEntities[i], DEFAULT_GRABBABLE_DATA); + if (typeof grabbableDataForCandidate.grabbable !== 'undefined' && !grabbableDataForCandidate.grabbable) { + continue; + } + var propsForCandidate = Entities.getEntityProperties(nearbyEntities[i], GRABBABLE_PROPERTIES); + + if (propsForCandidate.type == 'Unknown') { + continue; + } + + if (propsForCandidate.type == 'Light') { + continue; + } + + if (propsForCandidate.type == 'ParticleEffect') { + continue; + } + + if (propsForCandidate.type == 'PolyLine') { + continue; + } + + if (propsForCandidate.type == 'Zone') { + continue; + } + + if (propsForCandidate.locked && !grabbableDataForCandidate.wantsTrigger) { + continue; + } + + if (propsForCandidate.name == "Grab Debug Entity") { + continue; + } + + if (propsForCandidate.name == "grab pointer") { + continue; + } + + distance = Vec3.distance(propsForCandidate.position, handPosition); + if (distance < minDistance) { + this.grabbedEntity = nearbyEntities[i]; + minDistance = distance; + props = propsForCandidate; + grabbableData = grabbableDataForCandidate; + } + } + if (this.grabbedEntity !== null) { + if (grabbableData.wantsTrigger) { + this.setState(STATE_NEAR_TRIGGER); + return; + } else if (!props.locked && props.collisionsWillMove) { + this.setState(this.state == STATE_SEARCHING ? STATE_NEAR_GRABBING : STATE_EQUIP) + return; + } + } + + //search line visualizations + if (USE_ENTITY_LINES_FOR_SEARCHING === true) { + this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + } + + if (USE_OVERLAY_LINES_FOR_SEARCHING === true) { + this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR); + } + + if (USE_PARTICLE_BEAM_FOR_SEARCHING === true) { + this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR); + } + + }; + + this.distanceHolding = function() { + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var now = Date.now(); + + // add the action and initialize some variables + this.currentObjectPosition = grabbedProperties.position; + this.currentObjectRotation = grabbedProperties.rotation; + this.currentObjectTime = now; + this.handRelativePreviousPosition = Vec3.subtract(handControllerPosition, MyAvatar.position); + this.handPreviousRotation = handRotation; + this.currentCameraOrientation = Camera.orientation; + + // compute a constant based on the initial conditions which we use below to exagerate hand motion onto the held object + this.radiusScalar = Math.log(Vec3.distance(this.currentObjectPosition, handControllerPosition) + 1.0); + if (this.radiusScalar < 1.0) { + this.radiusScalar = 1.0; + } + + this.actionID = NULL_ACTION_ID; + this.actionID = Entities.addAction("spring", this.grabbedEntity, { + targetPosition: this.currentObjectPosition, + linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + targetRotation: this.currentObjectRotation, + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + tag: getTag(), + ttl: ACTION_TTL + }); + if (this.actionID === NULL_ACTION_ID) { + this.actionID = null; + } + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + + if (this.actionID !== null) { + this.setState(STATE_CONTINUE_DISTANCE_HOLDING); + this.activateEntity(this.grabbedEntity, grabbedProperties); + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab"); + } + + this.currentAvatarPosition = MyAvatar.position; + this.currentAvatarOrientation = MyAvatar.orientation; + + this.turnOffVisualizations(); + }; + + this.continueDistanceHolding = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + + var handPosition = this.getHandPosition(); + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state == STATE_CONTINUE_DISTANCE_HOLDING && this.bumperSqueezed() && + typeof grabbableData.spatialKey !== 'undefined') { + var saveGrabbedID = this.grabbedEntity; + this.release(); + this.setState(STATE_EQUIP); + this.grabbedEntity = saveGrabbedID; + return; + } + + + // the action was set up on a previous call. update the targets. + var radius = Vec3.distance(this.currentObjectPosition, handControllerPosition) * + this.radiusScalar * DISTANCE_HOLDING_RADIUS_FACTOR; + if (radius < 1.0) { + radius = 1.0; + } + + // how far did avatar move this timestep? + var currentPosition = MyAvatar.position; + var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition); + this.currentAvatarPosition = currentPosition; + + // How far did the avatar turn this timestep? + // Note: The following code is too long because we need a Quat.quatBetween() function + // that returns the minimum quaternion between two quaternions. + var currentOrientation = MyAvatar.orientation; + if (Quat.dot(currentOrientation, this.currentAvatarOrientation) < 0.0) { + var negativeCurrentOrientation = { + x: -currentOrientation.x, + y: -currentOrientation.y, + z: -currentOrientation.z, + w: -currentOrientation.w + }; + var avatarDeltaOrientation = Quat.multiply(negativeCurrentOrientation, Quat.inverse(this.currentAvatarOrientation)); + } else { + var avatarDeltaOrientation = Quat.multiply(currentOrientation, Quat.inverse(this.currentAvatarOrientation)); + } + var handToAvatar = Vec3.subtract(handControllerPosition, this.currentAvatarPosition); + var objectToAvatar = Vec3.subtract(this.currentObjectPosition, this.currentAvatarPosition); + var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar); + var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar); + this.currentAvatarOrientation = currentOrientation; + + // how far did hand move this timestep? + var handMoved = Vec3.subtract(handToAvatar, this.handRelativePreviousPosition); + this.handRelativePreviousPosition = handToAvatar; + + // magnify the hand movement but not the change from avatar movement & rotation + handMoved = Vec3.subtract(handMoved, handMovementFromTurning); + var superHandMoved = Vec3.multiply(handMoved, radius); + + // Move the object by the magnified amount and then by amount from avatar movement & rotation + var newObjectPosition = Vec3.sum(this.currentObjectPosition, superHandMoved); + newObjectPosition = Vec3.sum(newObjectPosition, avatarDeltaPosition); + newObjectPosition = Vec3.sum(newObjectPosition, objectMovementFromTurning); + + var deltaPosition = Vec3.subtract(newObjectPosition, this.currentObjectPosition); // meters + var now = Date.now(); + var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds + + this.currentObjectPosition = newObjectPosition; + this.currentObjectTime = now; + + // this doubles hand rotation + var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, + handRotation, + DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR), + Quat.inverse(this.handPreviousRotation)); + this.handPreviousRotation = handRotation; + this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation); + + Entities.callEntityMethod(this.grabbedEntity, "continueDistantGrab"); + + // mix in head motion + if (MOVE_WITH_HEAD) { + var objDistance = Vec3.length(objectToAvatar); + var before = Vec3.multiplyQbyV(this.currentCameraOrientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); + var after = Vec3.multiplyQbyV(Camera.orientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); + var change = Vec3.subtract(before, after); + this.currentCameraOrientation = Camera.orientation; + this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change); + } + + + //visualizations + if (USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); + } + if (USE_OVERLAY_LINES_FOR_MOVING === true) { + this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); + } + if (USE_PARTICLE_BEAM_FOR_MOVING === true) { + this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + } + if (USE_POINTLIGHT === true) { + this.handlePointLight(this.grabbedEntity); + } + if (USE_SPOTLIGHT === true) { + this.handleSpotlight(this.grabbedEntity); + } + + Entities.updateAction(this.grabbedEntity, this.actionID, { + targetPosition: this.currentObjectPosition, + linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + targetRotation: this.currentObjectRotation, + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + ttl: ACTION_TTL + }); + + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + }; + + this.nearGrabbing = function() { + var now = Date.now(); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + + this.turnOffVisualizations(); + + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + this.activateEntity(this.grabbedEntity, grabbedProperties); + if (grabbedProperties.collisionsWillMove && NEAR_GRABBING_KINEMATIC) { + Entities.editEntity(this.grabbedEntity, { + collisionsWillMove: false + }); + } + + var handRotation = this.getHandRotation(); + var handPosition = this.getHandPosition(); + + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) { + // if an object is "equipped" and has a spatialKey, use it. + this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; + this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); + this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + } else { + this.ignoreIK = false; + + var objectRotation = grabbedProperties.rotation; + this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); + + var currentObjectPosition = grabbedProperties.position; + var offset = Vec3.subtract(currentObjectPosition, handPosition); + this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset); + } + + this.actionID = NULL_ACTION_ID; + this.actionID = Entities.addAction("hold", this.grabbedEntity, { + hand: this.hand === RIGHT_HAND ? "right" : "left", + timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, + relativePosition: this.offsetPosition, + relativeRotation: this.offsetRotation, + ttl: ACTION_TTL, + kinematic: NEAR_GRABBING_KINEMATIC, + kinematicSetVelocity: true, + ignoreIK: this.ignoreIK + }); + if (this.actionID === NULL_ACTION_ID) { + this.actionID = null; + } else { + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + if (this.state == STATE_NEAR_GRABBING) { + this.setState(STATE_CONTINUE_NEAR_GRABBING); + } else { + // equipping + Entities.callEntityMethod(this.grabbedEntity, "startEquip", [JSON.stringify(this.hand)]); + this.startHandGrasp(); + + this.setState(STATE_CONTINUE_EQUIP_BD); + } + + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + + Entities.callEntityMethod(this.grabbedEntity, "startNearGrab"); + + } + + this.currentHandControllerTipPosition = + (this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition; + + this.currentObjectTime = Date.now(); + }; + + this.continueNearGrabbing = function() { + if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + return; + } + if (this.state == STATE_CONTINUE_EQUIP_BD && this.bumperReleased()) { + this.setState(STATE_CONTINUE_EQUIP); + return; + } + if (this.state == STATE_CONTINUE_EQUIP && this.bumperSqueezed()) { + this.setState(STATE_WAITING_FOR_BUMPER_RELEASE); + return; + } + if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.bumperSqueezed()) { + this.setState(STATE_CONTINUE_EQUIP_BD); + Entities.callEntityMethod(this.grabbedEntity, "startEquip", [JSON.stringify(this.hand)]); + return; + } + + // Keep track of the fingertip velocity to impart when we release the object. + // Note that the idea of using a constant 'tip' velocity regardless of the + // object's actual held offset is an idea intended to make it easier to throw things: + // Because we might catch something or transfer it between hands without a good idea + // of it's actual offset, let's try imparting a velocity which is at a fixed radius + // from the palm. + + var handControllerPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandPosition : MyAvatar.leftHandPosition; + var now = Date.now(); + + var deltaPosition = Vec3.subtract(handControllerPosition, this.currentHandControllerTipPosition); // meters + var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds + + this.currentHandControllerTipPosition = handControllerPosition; + this.currentObjectTime = now; + Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); + + if (this.state === STATE_CONTINUE_EQUIP_BD) { + Entities.callEntityMethod(this.grabbedEntity, "continueEquip"); + } + + if (this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) { + // if less than a 5 seconds left, refresh the actions ttl + Entities.updateAction(this.grabbedEntity, this.actionID, { + hand: this.hand === RIGHT_HAND ? "right" : "left", + timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, + relativePosition: this.offsetPosition, + relativeRotation: this.offsetRotation, + ttl: ACTION_TTL, + kinematic: NEAR_GRABBING_KINEMATIC, + kinematicSetVelocity: true, + ignoreIK: this.ignoreIK + }); + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); + } + }; + + this.waitingForBumperRelease = function() { + if (this.bumperReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + Entities.callEntityMethod(this.grabbedEntity, "unequip"); + this.endHandGrasp(); + + } + }; + + this.pullTowardEquipPosition = function() { + + this.turnOffVisualizations(); + + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + + // use a spring to pull the object to where it will be when equipped + var relativeRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + var relativePosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); + var ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; + var handRotation = this.getHandRotation(); + var handPosition = this.getHandPosition(); + var targetRotation = Quat.multiply(handRotation, relativeRotation); + var offset = Vec3.multiplyQbyV(targetRotation, relativePosition); + var targetPosition = Vec3.sum(handPosition, offset); + + if (typeof this.equipSpringID === 'undefined' || + this.equipSpringID === null || + this.equipSpringID === NULL_ACTION_ID) { + this.equipSpringID = Entities.addAction("spring", this.grabbedEntity, { + targetPosition: targetPosition, + linearTimeScale: EQUIP_SPRING_TIMEFRAME, + targetRotation: targetRotation, + angularTimeScale: EQUIP_SPRING_TIMEFRAME, + ttl: ACTION_TTL, + ignoreIK: ignoreIK + }); + if (this.equipSpringID === NULL_ACTION_ID) { + this.equipSpringID = null; + this.setState(STATE_OFF); + return; + } + } else { + Entities.updateAction(this.grabbedEntity, this.equipSpringID, { + targetPosition: targetPosition, + linearTimeScale: EQUIP_SPRING_TIMEFRAME, + targetRotation: targetRotation, + angularTimeScale: EQUIP_SPRING_TIMEFRAME, + ttl: ACTION_TTL, + ignoreIK: ignoreIK + }); + } + + if (Vec3.distance(grabbedProperties.position, targetPosition) < EQUIP_SPRING_SHUTOFF_DISTANCE) { + Entities.deleteAction(this.grabbedEntity, this.equipSpringID); + this.equipSpringID = null; + this.setState(STATE_EQUIP); + } + }; + + this.nearTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + + Entities.callEntityMethod(this.grabbedEntity, "startNearTrigger"); + this.setState(STATE_CONTINUE_NEAR_TRIGGER); + }; + + this.farTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopFarTrigger"); + return; + } + + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]); + Entities.callEntityMethod(this.grabbedEntity, "startFarTrigger"); + this.setState(STATE_CONTINUE_FAR_TRIGGER); + }; + + this.continueNearTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + + Entities.callEntityMethod(this.grabbedEntity, "continueNearTrigger"); + }; + + this.continueFarTrigger = function() { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopNearTrigger"); + return; + } + + var handPosition = this.getHandPosition(); + var pickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()) + }; + + var now = Date.now(); + if (now - this.lastPickTime > MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) { + var intersection = Entities.findRayIntersection(pickRay, true); + this.lastPickTime = now; + if (intersection.entityID != this.grabbedEntity) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "stopFarTrigger"); + return; + } + } + + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger"); + }; + + _this.allTouchedIDs = {}; + + this.touchTest = function() { + var maxDistance = 0.05; + var leftHandPosition = MyAvatar.getLeftPalmPosition(); + var rightHandPosition = MyAvatar.getRightPalmPosition(); + var leftEntities = Entities.findEntities(leftHandPosition, maxDistance); + var rightEntities = Entities.findEntities(rightHandPosition, maxDistance); + var ids = []; + + if (leftEntities.length !== 0) { + leftEntities.forEach(function(entity) { + ids.push(entity); + }); + + } + + if (rightEntities.length !== 0) { + rightEntities.forEach(function(entity) { + ids.push(entity); + }); + } + + ids.forEach(function(id) { + + var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); + if (props.name === 'pointer') { + return; + } else { + var entityMinPoint = props.boundingBox.brn; + var entityMaxPoint = props.boundingBox.tfl; + var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); + var rightIsTouching = pointInExtents(rightHandPosition, entityMinPoint, entityMaxPoint); + + if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id] === undefined) { + // we haven't been touched before, but either right or left is touching us now + _this.allTouchedIDs[id] = true; + _this.startTouch(id); + } else if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id]) { + // we have been touched before and are still being touched + // continue touch + _this.continueTouch(id); + } else if (_this.allTouchedIDs[id]) { + delete _this.allTouchedIDs[id]; + _this.stopTouch(id); + + } else { + //we are in another state + return; + } + } + + }); + + }; + + this.startTouch = function(entityID) { + Entities.callEntityMethod(entityID, "startTouch"); + }; + + this.continueTouch = function(entityID) { + Entities.callEntityMethod(entityID, "continueTouch"); + }; + + this.stopTouch = function(entityID) { + Entities.callEntityMethod(entityID, "stopTouch"); + }; + + this.release = function() { + + this.turnLightsOff(); + this.turnOffVisualizations(); + + if (this.grabbedEntity !== null) { + if (this.actionID !== null) { + Entities.deleteAction(this.grabbedEntity, this.actionID); + } + } + + this.deactivateEntity(this.grabbedEntity); + + this.grabbedEntity = null; + this.actionID = null; + this.setState(STATE_OFF); + }; + + this.cleanup = function() { + this.release(); + this.endHandGrasp(); + Entities.deleteEntity(this.particleBeam); + Entities.deleteEntity(this.spotLight); + Entities.deleteEntity(this.pointLight); + }; + + this.activateEntity = function(entityID, grabbedProperties) { + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, entityID, DEFAULT_GRABBABLE_DATA); + var invertSolidWhileHeld = grabbableData["invertSolidWhileHeld"]; + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + data["activated"] = true; + data["avatarId"] = MyAvatar.sessionUUID; + data["refCount"] = data["refCount"] ? data["refCount"] + 1 : 1; + // zero gravity and set ignoreForCollisions in a way that lets us put them back, after all grabs are done + if (data["refCount"] == 1) { + data["gravity"] = grabbedProperties.gravity; + data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions; + data["collisionsWillMove"] = grabbedProperties.collisionsWillMove; + var whileHeldProperties = { + gravity: { + x: 0, + y: 0, + z: 0 + } + }; + if (invertSolidWhileHeld) { + whileHeldProperties["ignoreForCollisions"] = !grabbedProperties.ignoreForCollisions; + } + Entities.editEntity(entityID, whileHeldProperties); + } + + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + return data; + }; + + this.deactivateEntity = function(entityID) { + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + if (data && data["refCount"]) { + data["refCount"] = data["refCount"] - 1; + if (data["refCount"] < 1) { + Entities.editEntity(entityID, { + gravity: data["gravity"], + ignoreForCollisions: data["ignoreForCollisions"], + collisionsWillMove: data["collisionsWillMove"] + }); + data = null; + } + } else { + data = null; + } + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + }; + + + //this is our handler, where we do the actual work of changing animation settings + this.graspHand = function(animationProperties) { + var result = {}; + //full alpha on overlay for this hand + //set grab to true + //set idle to false + //full alpha on the blend btw open and grab + if (_this.hand === RIGHT_HAND) { + result['rightHandOverlayAlpha'] = 1.0; + result['isRightHandGrab'] = true; + result['isRightHandIdle'] = false; + result['rightHandGrabBlend'] = 1.0; + } else if (_this.hand === LEFT_HAND) { + result['leftHandOverlayAlpha'] = 1.0; + result['isLeftHandGrab'] = true; + result['isLeftHandIdle'] = false; + result['leftHandGrabBlend'] = 1.0; + } + //return an object with our updated settings + return result; + }; + + this.graspHandler = null + + this.startHandGrasp = function() { + if (this.hand === RIGHT_HAND) { + this.graspHandler = MyAvatar.addAnimationStateHandler(this.graspHand, ['isRightHandGrab']); + } else if (this.hand === LEFT_HAND) { + this.graspHandler = MyAvatar.addAnimationStateHandler(this.graspHand, ['isLeftHandGrab']); + } + }; + + this.endHandGrasp = function() { + // Tell the animation system we don't need any more callbacks. + MyAvatar.removeAnimationStateHandler(this.graspHandler); + }; + +}; + +var rightController = new MyController(RIGHT_HAND); +var leftController = new MyController(LEFT_HAND); + +//preload the particle beams so that they are full length when you start searching +if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) { + rightController.createParticleBeam(); + leftController.createParticleBeam(); +} + +var MAPPING_NAME = "com.highfidelity.handControllerGrab"; + +var mapping = Controller.newMapping(MAPPING_NAME); +mapping.from([Controller.Standard.RT]).peek().to(rightController.triggerPress); +mapping.from([Controller.Standard.LT]).peek().to(leftController.triggerPress); + +mapping.from([Controller.Standard.RB]).peek().to(rightController.bumperPress); +mapping.from([Controller.Standard.LB]).peek().to(leftController.bumperPress); + +Controller.enableMapping(MAPPING_NAME); + +//the section below allows the grab script to listen for messages that disable either one or both hands. useful for two handed items +var handToDisable = 'none'; + +function update() { + if (handToDisable !== LEFT_HAND && handToDisable !== 'both') { + leftController.update(); + } + if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') { + rightController.update(); + } +} + +Messages.subscribe('Hifi-Hand-Disabler'); + +handleHandDisablerMessages = function(channel, message, sender) { + + if (sender === MyAvatar.sessionUUID) { + if (message === 'left') { + handToDisable = LEFT_HAND; + } + if (message === 'right') { + handToDisable = RIGHT_HAND; + } + if (message === 'both') { + handToDisable = 'both'; + } + if (message === 'none') { + handToDisable = 'none'; + } + } + +} + +Messages.messageReceived.connect(handleHandDisablerMessages); + +function cleanup() { + rightController.cleanup(); + leftController.cleanup(); + Controller.disableMapping(MAPPING_NAME); +} + +Script.scriptEnding.connect(cleanup); +Script.update.connect(update); \ No newline at end of file From 8d691f2132f4acdeb7f98692d1ec97236b77b086 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 14 Dec 2015 11:44:42 -0800 Subject: [PATCH 051/195] light ball --- examples/flowArts/lightBall/lightBall.js | 0 .../flowArts/lightBall/lightBallSpawner.js | 51 +++++++++++++++++++ .../entities/src/ParticleEffectEntityItem.cpp | 4 +- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 examples/flowArts/lightBall/lightBall.js create mode 100644 examples/flowArts/lightBall/lightBallSpawner.js diff --git a/examples/flowArts/lightBall/lightBall.js b/examples/flowArts/lightBall/lightBall.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/flowArts/lightBall/lightBallSpawner.js b/examples/flowArts/lightBall/lightBallSpawner.js new file mode 100644 index 0000000000..f758c26bbe --- /dev/null +++ b/examples/flowArts/lightBall/lightBallSpawner.js @@ -0,0 +1,51 @@ +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation()))); + +var lightBall = Entities.addEntity({ + position: center, + type: "ParticleEffect", + isEmitting: true, + "name": "ParticlesTest Emitter", + "colorStart": {red: 20, green: 20, blue: 255}, + color: {red: 10, green: 0, blue: 255}, + "colorFinish": {red: 250, green: 200, blue:255}, + // "maxParticles": 100000, + "lifespan": 1, + "emitRate": 1000, + "emitSpeed": .1, + "speedSpread": .01, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "polarStart": 0, + "polarFinish": 3, + "azimuthStart": -3.1415927410125732, + "azimuthFinish": 3.1415927410125732, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": .01, + "y": .01, + "z": .01 + }, + "particleRadius": 0.04, + "radiusSpread": 0, + "radiusStart": 0.05, + "radiusFinish": 0.0003, + "alpha": 0, + "alphaSpread": .5, + "alphaStart": 0, + "alphaFinish": 0.5, + "additiveBlending": 0, + "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png" +}) + +function cleanup() { + Entities.deleteEntity(lightBall); +} + +Script.scriptEnding.connect(cleanup); \ No newline at end of file diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 5600c85650..f4210f4486 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -52,13 +52,13 @@ const float ParticleEffectEntityItem::MINIMUM_ALPHA = 0.0f; const float ParticleEffectEntityItem::MAXIMUM_ALPHA = 1.0f; const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; const quint32 ParticleEffectEntityItem::MINIMUM_MAX_PARTICLES = 1; -const quint32 ParticleEffectEntityItem::MAXIMUM_MAX_PARTICLES = 10000; +const quint32 ParticleEffectEntityItem::MAXIMUM_MAX_PARTICLES = 100000; const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; const float ParticleEffectEntityItem::MINIMUM_LIFESPAN = 0.0f; const float ParticleEffectEntityItem::MAXIMUM_LIFESPAN = 86400.0f; // 1 day const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; const float ParticleEffectEntityItem::MINIMUM_EMIT_RATE = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_EMIT_RATE = 1000.0f; +const float ParticleEffectEntityItem::MAXIMUM_EMIT_RATE = 100000.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_SPEED = 5.0f; const float ParticleEffectEntityItem::MINIMUM_EMIT_SPEED = 0.0f; const float ParticleEffectEntityItem::MAXIMUM_EMIT_SPEED = 1000.0f; // Approx mach 3 From 76487bca7ac69c8fdaa2ec9e8eaaa281871b378e Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 14 Dec 2015 13:01:03 -0800 Subject: [PATCH 052/195] updates --- .../handControllerGrab-particles.js | 47 +++++++++++-------- .../handControllerGrab-pointlight.js | 47 +++++++++++-------- .../handControllerGrab-spotlight.js | 47 +++++++++++-------- examples/controllers/handControllerGrab.js | 47 +++++++++++-------- 4 files changed, 108 insertions(+), 80 deletions(-) diff --git a/examples/controllers/handControllerGrab-particles.js b/examples/controllers/handControllerGrab-particles.js index d9ecb18b01..bfe51927d0 100644 --- a/examples/controllers/handControllerGrab-particles.js +++ b/examples/controllers/handControllerGrab-particles.js @@ -437,47 +437,49 @@ function MyController(hand) { }); var finalRotation = Quat.multiply(orientation, rotation); - + var lifespan = LINE_LENGTH / 10; + var speed = 5; + var spread = 2; if (this.particleBeam === null) { - this.createParticleBeam(position, finalRotation, color); + this.createParticleBeam(position, finalRotation, color, speed, spread, lifespan); } else { - this.updateParticleBeam(position, finalRotation, color); + this.updateParticleBeam(position, finalRotation, color, speed, spread, lifespan); } }; - this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { + this.handleDistantParticleBeam = function(handPosition, objectPosition, color) { var handToObject = Vec3.subtract(objectPosition, handPosition); var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); var distance = Vec3.distance(handPosition, objectPosition); - var speed = distance * 1; + var speed = 5; + var spread = 0; + + var lifespan = distance / speed; - var lifepsan = distance / speed; - var lifespan = 1; if (this.particleBeam === null) { - this.createParticleBeam(objectPosition, finalRotation, color, speed); + this.createParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan); } else { - this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); + this.updateParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan); } }; - this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { + this.createParticleBeam = function(position, orientation, color, speed, spread, lifespan) { var particleBeamProperties = { type: "ParticleEffect", isEmitting: true, position: position, visible: false, - //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), "name": "Particle Beam", "color": color, "maxParticles": 2000, - "lifespan": LINE_LENGTH / 10, + "lifespan": lifespan, "emitRate": 50, - "emitSpeed": 5, - "speedSpread": 2, + "emitSpeed": speed, + "speedSpread": spread, "emitOrientation": { "x": -1, "y": 0, @@ -519,22 +521,23 @@ function MyController(hand) { "alphaSpread": 0, "alphaStart": 1, "alphaFinish": 1, - "additiveBlending": 1, + "additiveBlending": 0, "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" } this.particleBeam = Entities.addEntity(particleBeamProperties); }; - this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { - + this.updateParticleBeam = function(position, orientation, color, speed, spread, lifespan) { + print('lifespan::' + lifespan); Entities.editEntity(this.particleBeam, { rotation: orientation, position: position, visible: true, color: color, emitSpeed: speed, - lifepsan: lifepsan + speedSpread:spread, + lifespan: lifespan }) @@ -1108,7 +1111,8 @@ function MyController(hand) { this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); } if (USE_PARTICLE_BEAM_FOR_MOVING === true) { - this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + this.handleDistantParticleBeam(handPosition,grabbedProperties.position, INTERSECT_COLOR) + // this.handleDistantParticleBeam(handPosition, this.currentObjectPosition, INTERSECT_COLOR) } if (USE_POINTLIGHT === true) { this.handlePointLight(this.grabbedEntity); @@ -1399,7 +1403,10 @@ function MyController(hand) { } } - this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + if (USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + } + Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger"); }; diff --git a/examples/controllers/handControllerGrab-pointlight.js b/examples/controllers/handControllerGrab-pointlight.js index fc14e6026e..e7bb4e3e9f 100644 --- a/examples/controllers/handControllerGrab-pointlight.js +++ b/examples/controllers/handControllerGrab-pointlight.js @@ -437,47 +437,49 @@ function MyController(hand) { }); var finalRotation = Quat.multiply(orientation, rotation); - + var lifespan = LINE_LENGTH / 10; + var speed = 5; + var spread = 2; if (this.particleBeam === null) { - this.createParticleBeam(position, finalRotation, color); + this.createParticleBeam(position, finalRotation, color, speed, spread, lifespan); } else { - this.updateParticleBeam(position, finalRotation, color); + this.updateParticleBeam(position, finalRotation, color, speed, spread, lifespan); } }; - this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { + this.handleDistantParticleBeam = function(handPosition, objectPosition, color) { var handToObject = Vec3.subtract(objectPosition, handPosition); var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); var distance = Vec3.distance(handPosition, objectPosition); - var speed = distance * 1; + var speed = 5; + var spread = 0; + + var lifespan = distance / speed; - var lifepsan = distance / speed; - var lifespan = 1; if (this.particleBeam === null) { - this.createParticleBeam(objectPosition, finalRotation, color, speed); + this.createParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan); } else { - this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); + this.updateParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan); } }; - this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { + this.createParticleBeam = function(position, orientation, color, speed, spread, lifespan) { var particleBeamProperties = { type: "ParticleEffect", isEmitting: true, position: position, visible: false, - //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), "name": "Particle Beam", "color": color, "maxParticles": 2000, - "lifespan": LINE_LENGTH / 10, + "lifespan": lifespan, "emitRate": 50, - "emitSpeed": 5, - "speedSpread": 2, + "emitSpeed": speed, + "speedSpread": spread, "emitOrientation": { "x": -1, "y": 0, @@ -519,22 +521,23 @@ function MyController(hand) { "alphaSpread": 0, "alphaStart": 1, "alphaFinish": 1, - "additiveBlending": 1, + "additiveBlending": 0, "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" } this.particleBeam = Entities.addEntity(particleBeamProperties); }; - this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { - + this.updateParticleBeam = function(position, orientation, color, speed, spread, lifespan) { + print('lifespan::' + lifespan); Entities.editEntity(this.particleBeam, { rotation: orientation, position: position, visible: true, color: color, emitSpeed: speed, - lifepsan: lifepsan + speedSpread:spread, + lifespan: lifespan }) @@ -1108,7 +1111,8 @@ function MyController(hand) { this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); } if (USE_PARTICLE_BEAM_FOR_MOVING === true) { - this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + this.handleDistantParticleBeam(handPosition,grabbedProperties.position, INTERSECT_COLOR) + // this.handleDistantParticleBeam(handPosition, this.currentObjectPosition, INTERSECT_COLOR) } if (USE_POINTLIGHT === true) { this.handlePointLight(this.grabbedEntity); @@ -1399,7 +1403,10 @@ function MyController(hand) { } } - this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + if (USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + } + Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger"); }; diff --git a/examples/controllers/handControllerGrab-spotlight.js b/examples/controllers/handControllerGrab-spotlight.js index ea05a44f78..ee6dcfa681 100644 --- a/examples/controllers/handControllerGrab-spotlight.js +++ b/examples/controllers/handControllerGrab-spotlight.js @@ -437,47 +437,49 @@ function MyController(hand) { }); var finalRotation = Quat.multiply(orientation, rotation); - + var lifespan = LINE_LENGTH / 10; + var speed = 5; + var spread = 2; if (this.particleBeam === null) { - this.createParticleBeam(position, finalRotation, color); + this.createParticleBeam(position, finalRotation, color, speed, spread, lifespan); } else { - this.updateParticleBeam(position, finalRotation, color); + this.updateParticleBeam(position, finalRotation, color, speed, spread, lifespan); } }; - this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { + this.handleDistantParticleBeam = function(handPosition, objectPosition, color) { var handToObject = Vec3.subtract(objectPosition, handPosition); var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); var distance = Vec3.distance(handPosition, objectPosition); - var speed = distance * 1; + var speed = 5; + var spread = 0; + + var lifespan = distance / speed; - var lifepsan = distance / speed; - var lifespan = 1; if (this.particleBeam === null) { - this.createParticleBeam(objectPosition, finalRotation, color, speed); + this.createParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan); } else { - this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); + this.updateParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan); } }; - this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { + this.createParticleBeam = function(position, orientation, color, speed, spread, lifespan) { var particleBeamProperties = { type: "ParticleEffect", isEmitting: true, position: position, visible: false, - //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), "name": "Particle Beam", "color": color, "maxParticles": 2000, - "lifespan": LINE_LENGTH / 10, + "lifespan": lifespan, "emitRate": 50, - "emitSpeed": 5, - "speedSpread": 2, + "emitSpeed": speed, + "speedSpread": spread, "emitOrientation": { "x": -1, "y": 0, @@ -519,22 +521,23 @@ function MyController(hand) { "alphaSpread": 0, "alphaStart": 1, "alphaFinish": 1, - "additiveBlending": 1, + "additiveBlending": 0, "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" } this.particleBeam = Entities.addEntity(particleBeamProperties); }; - this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { - + this.updateParticleBeam = function(position, orientation, color, speed, spread, lifespan) { + print('lifespan::' + lifespan); Entities.editEntity(this.particleBeam, { rotation: orientation, position: position, visible: true, color: color, emitSpeed: speed, - lifepsan: lifepsan + speedSpread:spread, + lifespan: lifespan }) @@ -1108,7 +1111,8 @@ function MyController(hand) { this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); } if (USE_PARTICLE_BEAM_FOR_MOVING === true) { - this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + this.handleDistantParticleBeam(handPosition,grabbedProperties.position, INTERSECT_COLOR) + // this.handleDistantParticleBeam(handPosition, this.currentObjectPosition, INTERSECT_COLOR) } if (USE_POINTLIGHT === true) { this.handlePointLight(this.grabbedEntity); @@ -1399,7 +1403,10 @@ function MyController(hand) { } } - this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + if (USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + } + Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger"); }; diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index cd82db22b9..b6f1a82c3f 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -437,47 +437,49 @@ function MyController(hand) { }); var finalRotation = Quat.multiply(orientation, rotation); - + var lifespan = LINE_LENGTH / 10; + var speed = 5; + var spread = 2; if (this.particleBeam === null) { - this.createParticleBeam(position, finalRotation, color); + this.createParticleBeam(position, finalRotation, color, speed, spread, lifespan); } else { - this.updateParticleBeam(position, finalRotation, color); + this.updateParticleBeam(position, finalRotation, color, speed, spread, lifespan); } }; - this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { + this.handleDistantParticleBeam = function(handPosition, objectPosition, color) { var handToObject = Vec3.subtract(objectPosition, handPosition); var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); var distance = Vec3.distance(handPosition, objectPosition); - var speed = distance * 1; + var speed = 5; + var spread = 0; + + var lifespan = distance / speed; - var lifepsan = distance / speed; - var lifespan = 1; if (this.particleBeam === null) { - this.createParticleBeam(objectPosition, finalRotation, color, speed); + this.createParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan); } else { - this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); + this.updateParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan); } }; - this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { + this.createParticleBeam = function(position, orientation, color, speed, spread, lifespan) { var particleBeamProperties = { type: "ParticleEffect", isEmitting: true, position: position, visible: false, - //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), "name": "Particle Beam", "color": color, "maxParticles": 2000, - "lifespan": LINE_LENGTH / 10, + "lifespan": lifespan, "emitRate": 50, - "emitSpeed": 5, - "speedSpread": 2, + "emitSpeed": speed, + "speedSpread": spread, "emitOrientation": { "x": -1, "y": 0, @@ -519,22 +521,23 @@ function MyController(hand) { "alphaSpread": 0, "alphaStart": 1, "alphaFinish": 1, - "additiveBlending": 1, + "additiveBlending": 0, "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" } this.particleBeam = Entities.addEntity(particleBeamProperties); }; - this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { - + this.updateParticleBeam = function(position, orientation, color, speed, spread, lifespan) { + print('lifespan::' + lifespan); Entities.editEntity(this.particleBeam, { rotation: orientation, position: position, visible: true, color: color, emitSpeed: speed, - lifepsan: lifepsan + speedSpread:spread, + lifespan: lifespan }) @@ -1108,7 +1111,8 @@ function MyController(hand) { this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); } if (USE_PARTICLE_BEAM_FOR_MOVING === true) { - this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + this.handleDistantParticleBeam(handPosition,grabbedProperties.position, INTERSECT_COLOR) + // this.handleDistantParticleBeam(handPosition, this.currentObjectPosition, INTERSECT_COLOR) } if (USE_POINTLIGHT === true) { this.handlePointLight(this.grabbedEntity); @@ -1399,7 +1403,10 @@ function MyController(hand) { } } - this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + if (USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + } + Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger"); }; From e3e1bc1dc611b0bbb00860807a04018aa04c7105 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 14 Dec 2015 13:01:44 -0800 Subject: [PATCH 053/195] updates --- .../handControllerGrab-all-overlays.js | 47 +++++++++++-------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/examples/controllers/handControllerGrab-all-overlays.js b/examples/controllers/handControllerGrab-all-overlays.js index acb47b2260..67e2b1f0a7 100644 --- a/examples/controllers/handControllerGrab-all-overlays.js +++ b/examples/controllers/handControllerGrab-all-overlays.js @@ -437,47 +437,49 @@ function MyController(hand) { }); var finalRotation = Quat.multiply(orientation, rotation); - + var lifespan = LINE_LENGTH / 10; + var speed = 5; + var spread = 2; if (this.particleBeam === null) { - this.createParticleBeam(position, finalRotation, color); + this.createParticleBeam(position, finalRotation, color, speed, spread, lifespan); } else { - this.updateParticleBeam(position, finalRotation, color); + this.updateParticleBeam(position, finalRotation, color, speed, spread, lifespan); } }; - this.handleDistantParticleBeam = function(handPosition, objectPosition, objectRotation, color) { + this.handleDistantParticleBeam = function(handPosition, objectPosition, color) { var handToObject = Vec3.subtract(objectPosition, handPosition); var finalRotation = Quat.rotationBetween(Vec3.multiply(-1, Vec3.UP), handToObject); var distance = Vec3.distance(handPosition, objectPosition); - var speed = distance * 1; + var speed = 5; + var spread = 0; + + var lifespan = distance / speed; - var lifepsan = distance / speed; - var lifespan = 1; if (this.particleBeam === null) { - this.createParticleBeam(objectPosition, finalRotation, color, speed); + this.createParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan); } else { - this.updateParticleBeam(objectPosition, finalRotation, color, speed, lifepsan); + this.updateParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan); } }; - this.createParticleBeam = function(position, orientation, color, speed, lifepsan) { + this.createParticleBeam = function(position, orientation, color, speed, spread, lifespan) { var particleBeamProperties = { type: "ParticleEffect", isEmitting: true, position: position, visible: false, - //rotation:Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), "name": "Particle Beam", "color": color, "maxParticles": 2000, - "lifespan": LINE_LENGTH / 10, + "lifespan": lifespan, "emitRate": 50, - "emitSpeed": 5, - "speedSpread": 2, + "emitSpeed": speed, + "speedSpread": spread, "emitOrientation": { "x": -1, "y": 0, @@ -519,22 +521,23 @@ function MyController(hand) { "alphaSpread": 0, "alphaStart": 1, "alphaFinish": 1, - "additiveBlending": 1, + "additiveBlending": 0, "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" } this.particleBeam = Entities.addEntity(particleBeamProperties); }; - this.updateParticleBeam = function(position, orientation, color, speed, lifepsan) { - + this.updateParticleBeam = function(position, orientation, color, speed, spread, lifespan) { + print('lifespan::' + lifespan); Entities.editEntity(this.particleBeam, { rotation: orientation, position: position, visible: true, color: color, emitSpeed: speed, - lifepsan: lifepsan + speedSpread:spread, + lifespan: lifespan }) @@ -1108,7 +1111,8 @@ function MyController(hand) { this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); } if (USE_PARTICLE_BEAM_FOR_MOVING === true) { - this.handleDistantParticleBeam(handPosition, grabbedProperties.position, this.currentObjectRotation, INTERSECT_COLOR) + this.handleDistantParticleBeam(handPosition,grabbedProperties.position, INTERSECT_COLOR) + // this.handleDistantParticleBeam(handPosition, this.currentObjectPosition, INTERSECT_COLOR) } if (USE_POINTLIGHT === true) { this.handlePointLight(this.grabbedEntity); @@ -1399,7 +1403,10 @@ function MyController(hand) { } } - this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + if (USE_ENTITY_LINES_FOR_MOVING === true) { + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + } + Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger"); }; From 761dfeaccd72edbd4cd79ce66bb9d9f517b229d1 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 14 Dec 2015 14:53:08 -0800 Subject: [PATCH 054/195] 2 balls --- .../flowArts/lightBall/lightBallSpawner.js | 73 ++++++++++++++++++- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/examples/flowArts/lightBall/lightBallSpawner.js b/examples/flowArts/lightBall/lightBallSpawner.js index f758c26bbe..da09829257 100644 --- a/examples/flowArts/lightBall/lightBallSpawner.js +++ b/examples/flowArts/lightBall/lightBallSpawner.js @@ -1,16 +1,80 @@ -var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation()))); +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); + +var containerBall = Entities.addEntity({ + type: "Sphere", + position: center, + dimensions: {x: .1, y: .1, z: .1}, + color: {red: 50, green: 10, blue: 50}, + collisionsWillMove: true, + gravity: {x: 0, y: -.1, z: 0} +}); var lightBall = Entities.addEntity({ position: center, type: "ParticleEffect", + parentID: containerBall, isEmitting: true, "name": "ParticlesTest Emitter", "colorStart": {red: 20, green: 20, blue: 255}, color: {red: 10, green: 0, blue: 255}, "colorFinish": {red: 250, green: 200, blue:255}, - // "maxParticles": 100000, + "maxParticles": 20000, "lifespan": 1, - "emitRate": 1000, + "emitRate": 10000, + "emitSpeed": .1, + "speedSpread": .01, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "polarStart": 0, + "polarFinish": 3, + "azimuthStart": -3.1415927410125732, + "azimuthFinish": 3.1415927410125732, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": .01, + "y": .01, + "z": .01 + }, + "particleRadius": 0.04, + "radiusSpread": 0, + "radiusStart": 0.05, + "radiusFinish": 0.0003, + "alpha": 0, + "alphaSpread": .5, + "alphaStart": 0, + "alphaFinish": 0.5, + "additiveBlending": 0, + "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png" +}) + +var containerBall2 = Entities.addEntity({ + type: "Sphere", + position: Vec3.sum(center, {x: 0.5, y: 0, z: 0}), + dimensions: {x: .1, y: .1, z: .1}, + color: {red: 200, green: 10, blue: 50}, + collisionsWillMove: true, + gravity: {x: 0, y: -.1, z: 0} +}); + +var lightBall2 = Entities.addEntity({ + position: Vec3.sum(center, {x: 0.5, y: 0, z: 0}), + type: "ParticleEffect", + parentID: containerBall2, + isEmitting: true, + "name": "ParticlesTest Emitter", + "colorStart": {red: 200, green: 20, blue: 0}, + color: {red: 255, green: 0, blue: 10}, + "colorFinish": {red: 250, green: 200, blue:255}, + "maxParticles": 100000, + "lifespan": 1, + "emitRate": 10000, "emitSpeed": .1, "speedSpread": .01, "emitDimensions": { @@ -46,6 +110,9 @@ var lightBall = Entities.addEntity({ function cleanup() { Entities.deleteEntity(lightBall); + Entities.deleteEntity(lightBall2); + Entities.deleteEntity(containerBall); + Entities.deleteEntity(containerBall2); } Script.scriptEnding.connect(cleanup); \ No newline at end of file From 2bbd5d86b8f72e092c68aed2a0c7fa8bd88ecb2d Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 15 Dec 2015 09:46:18 -0800 Subject: [PATCH 055/195] cleaning indentation --- .../render-utils/src/RenderDeferredTask.cpp | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index d9b5c1caf6..5f9cb7b575 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -52,25 +52,21 @@ void ToneMappingDeferred::run(const SceneContextPointer& sceneContext, const Ren RenderDeferredTask::RenderDeferredTask() : Task() { // CPU only, create the list of renderedOpaques items _jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque", - FetchItems( - [](const RenderContextPointer& context, int count) { - context->_numFeedOpaqueItems = count; - } - ) - ))); + FetchItems([](const RenderContextPointer& context, int count) { + context->_numFeedOpaqueItems = count; + }) + ))); _jobs.push_back(Job(new CullItemsOpaque::JobModel("CullOpaque", _jobs.back().getOutput()))); _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortOpaque", _jobs.back().getOutput()))); auto& renderedOpaques = _jobs.back().getOutput(); // CPU only, create the list of renderedTransparents items _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", - FetchItems( - ItemFilter::Builder::transparentShape().withoutLayered(), - [](const RenderContextPointer& context, int count) { - context->_numFeedTransparentItems = count; - } - ) - ))); + FetchItems(ItemFilter::Builder::transparentShape().withoutLayered(), + [](const RenderContextPointer& context, int count) { + context->_numFeedTransparentItems = count; + }) + ))); _jobs.push_back(Job(new CullItemsTransparent::JobModel("CullTransparent", _jobs.back().getOutput()))); _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)))); auto& renderedTransparents = _jobs.back().getOutput(); From c561a53f7c283a7c80e7aa7d921409f73a4971d7 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 15 Dec 2015 09:56:28 -0800 Subject: [PATCH 056/195] Going to change additive blending to world position prop --- .../flowArts/lightBall/lightBallSpawner.js | 151 ++++++++++-------- .../RenderableParticleEffectEntityItem.cpp | 4 +- .../entities/src/ParticleEffectEntityItem.cpp | 17 +- 3 files changed, 102 insertions(+), 70 deletions(-) diff --git a/examples/flowArts/lightBall/lightBallSpawner.js b/examples/flowArts/lightBall/lightBallSpawner.js index da09829257..8f220129b2 100644 --- a/examples/flowArts/lightBall/lightBallSpawner.js +++ b/examples/flowArts/lightBall/lightBallSpawner.js @@ -1,81 +1,101 @@ + +Script.include("../../libraries/utils.js"); + var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); +var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); + +var raveRoom = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: center, + visible:false +}); + +var colorPalette = [{ + red: 250, + green: 137, + blue: 162 +}, { + red: 204, + green: 244, + blue: 249 +}, { + red: 146, + green: 206, + blue: 116 +}, { + red: 240, + green: 87, + blue: 129 +}]; + var containerBall = Entities.addEntity({ type: "Sphere", position: center, dimensions: {x: .1, y: .1, z: .1}, - color: {red: 50, green: 10, blue: 50}, + color: {red: 1500, green: 10, blue: 50}, collisionsWillMove: true, - gravity: {x: 0, y: -.1, z: 0} + userData: JSON.stringify({ + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 2, + z: 0 + } + }, + invertSolidWhileHeld: true + } + }) + // gravity: {x: 0, y: -.1, z: 0} }); +var lightZone = Entities.addEntity({ + type: "Zone", + shapeType: 'box', + keyLightIntensity: 0.2, + keyLightColor: { + red: 50, + green: 0, + blue: 50 + }, + keyLightAmbientIntensity: .2, + position: MyAvatar.position, + dimensions: { + x: 100, + y: 100, + z: 100 + } +}); + +var light = Entities.addEntity({ + type: 'Light', + position: center, + parentID: containerBall, + dimensions: { + x: 30, + y: 30, + z: 30 + }, + color: colorPalette[randInt(0, colorPalette.length)], + intensity: 5 + }); + + var lightBall = Entities.addEntity({ position: center, type: "ParticleEffect", parentID: containerBall, isEmitting: true, "name": "ParticlesTest Emitter", - "colorStart": {red: 20, green: 20, blue: 255}, + "colorStart": {red: 200, green: 20, blue: 40}, color: {red: 10, green: 0, blue: 255}, "colorFinish": {red: 250, green: 200, blue:255}, - "maxParticles": 20000, - "lifespan": 1, - "emitRate": 10000, - "emitSpeed": .1, - "speedSpread": .01, - "emitDimensions": { - "x": 0, - "y": 0, - "z": 0 - }, - "polarStart": 0, - "polarFinish": 3, - "azimuthStart": -3.1415927410125732, - "azimuthFinish": 3.1415927410125732, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 - }, - "accelerationSpread": { - "x": .01, - "y": .01, - "z": .01 - }, - "particleRadius": 0.04, - "radiusSpread": 0, - "radiusStart": 0.05, - "radiusFinish": 0.0003, - "alpha": 0, - "alphaSpread": .5, - "alphaStart": 0, - "alphaFinish": 0.5, - "additiveBlending": 0, - "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png" -}) - -var containerBall2 = Entities.addEntity({ - type: "Sphere", - position: Vec3.sum(center, {x: 0.5, y: 0, z: 0}), - dimensions: {x: .1, y: .1, z: .1}, - color: {red: 200, green: 10, blue: 50}, - collisionsWillMove: true, - gravity: {x: 0, y: -.1, z: 0} -}); - -var lightBall2 = Entities.addEntity({ - position: Vec3.sum(center, {x: 0.5, y: 0, z: 0}), - type: "ParticleEffect", - parentID: containerBall2, - isEmitting: true, - "name": "ParticlesTest Emitter", - "colorStart": {red: 200, green: 20, blue: 0}, - color: {red: 255, green: 0, blue: 10}, - "colorFinish": {red: 250, green: 200, blue:255}, "maxParticles": 100000, - "lifespan": 1, + "lifespan": 7, "emitRate": 10000, - "emitSpeed": .1, + "emitSpeed": .02, "speedSpread": .01, "emitDimensions": { "x": 0, @@ -83,9 +103,9 @@ var lightBall2 = Entities.addEntity({ "z": 0 }, "polarStart": 0, - "polarFinish": 3, - "azimuthStart": -3.1415927410125732, - "azimuthFinish": 3.1415927410125732, + "polarFinish": Math.PI, + "azimuthStart": -Math.PI, + "azimuthFinish": Math.PI, "emitAcceleration": { "x": 0, "y": 0, @@ -108,11 +128,14 @@ var lightBall2 = Entities.addEntity({ "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png" }) + + function cleanup() { Entities.deleteEntity(lightBall); - Entities.deleteEntity(lightBall2); Entities.deleteEntity(containerBall); - Entities.deleteEntity(containerBall2); + Entities.deleteEntity(raveRoom); + Entities.deleteEntity(lightZone) + Entities.deleteEntity(light); } Script.scriptEnding.connect(cleanup); \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 4abd8dbafd..42e9fa446c 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -240,8 +240,8 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { auto position = getPosition(); auto rotation = getRotation(); Transform transform; - transform.setTranslation(position); - transform.setRotation(rotation); + //transform.setTranslation(position); + // transform.setRotation(rotation); render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [=](ParticlePayloadData& payload) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index f4210f4486..8f6f60fa26 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include "EntityTree.h" #include "EntityTreeElement.h" @@ -640,12 +642,18 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { Particle particle; - particle.seed = randFloatInRange(0.0f, 1.0f); - + std::random_device rd; + + std::mt19937_64 el(rd()); + std::uniform_real_distribution uniform_dist(-1.0, 1.0); + + particle.seed = randFloatInRange(-1.0f, 1.0f); + particle.position = getPosition(); // Position, velocity, and acceleration if (_polarStart == 0.0f && _polarFinish == 0.0f && _emitDimensions.z == 0.0f) { // Emit along z-axis from position - particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * Vectors::UNIT_Z); + + particle.velocity = (_emitSpeed + 0.2f * _speedSpread) * (_emitOrientation * Vectors::UNIT_Z); particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } else { @@ -691,10 +699,11 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { radii.z > 0.0f ? z / (radii.z * radii.z) : 0.0f )); - particle.position = _emitOrientation * emitPosition; + particle.position += _emitOrientation * emitPosition; } particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); + // particle.velocity = (_emitSpeed + uniform_dist(el) * _speedSpread) * (_emitOrientation * emitDirection); particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } From dca83a054ea3b278e1ca2a8f1c1cb23e1740ff19 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 15 Dec 2015 10:30:57 -0800 Subject: [PATCH 057/195] Changed additiveBlending to emitterShouldTrail --- .../flowArts/lightBall/lightBallSpawner.js | 9 ++++---- .../RenderableParticleEffectEntityItem.cpp | 6 +++-- .../entities/src/EntityItemProperties.cpp | 16 ++++++------- libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/EntityPropertyFlags.h | 2 +- .../entities/src/ParticleEffectEntityItem.cpp | 23 ++++++++++++------- .../entities/src/ParticleEffectEntityItem.h | 10 ++++---- 7 files changed, 39 insertions(+), 29 deletions(-) diff --git a/examples/flowArts/lightBall/lightBallSpawner.js b/examples/flowArts/lightBall/lightBallSpawner.js index 8f220129b2..7744c1210e 100644 --- a/examples/flowArts/lightBall/lightBallSpawner.js +++ b/examples/flowArts/lightBall/lightBallSpawner.js @@ -41,7 +41,7 @@ var containerBall = Entities.addEntity({ spatialKey: { relativePosition: { x: 0, - y: 2, + y: 1, z: 0 } }, @@ -93,9 +93,9 @@ var lightBall = Entities.addEntity({ color: {red: 10, green: 0, blue: 255}, "colorFinish": {red: 250, green: 200, blue:255}, "maxParticles": 100000, - "lifespan": 7, + "lifespan": 2, "emitRate": 10000, - "emitSpeed": .02, + "emitSpeed": .2, "speedSpread": .01, "emitDimensions": { "x": 0, @@ -125,7 +125,8 @@ var lightBall = Entities.addEntity({ "alphaStart": 0, "alphaFinish": 0.5, "additiveBlending": 0, - "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png" + "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + emitterShouldTrail: false }) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 42e9fa446c..91a4811011 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -240,8 +240,10 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { auto position = getPosition(); auto rotation = getRotation(); Transform transform; - //transform.setTranslation(position); - // transform.setRotation(rotation); + if (!getEmitterShouldTrail()) { + transform.setTranslation(position); + transform.setRotation(rotation); + } render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [=](ParticlePayloadData& payload) { diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 98a099fcaa..3a2fdf55d4 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -195,7 +195,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ALPHA_SPREAD, alphaSpread); CHECK_PROPERTY_CHANGE(PROP_ALPHA_START, alphaStart); CHECK_PROPERTY_CHANGE(PROP_ALPHA_FINISH, alphaFinish); - CHECK_PROPERTY_CHANGE(PROP_ADDITIVE_BLENDING, additiveBlending); + CHECK_PROPERTY_CHANGE(PROP_EMITTER_SHOULD_TRAIL, emitterShouldTrail); CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL); CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL); CHECK_PROPERTY_CHANGE(PROP_VISIBLE, visible); @@ -354,7 +354,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_SPREAD, alphaSpread); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ADDITIVE_BLENDING, additiveBlending); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMITTER_SHOULD_TRAIL, emitterShouldTrail); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_POSITION, localPosition); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ROTATION, localRotation); } @@ -515,7 +515,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaSpread, float, setAlphaSpread); COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaStart, float, setAlphaStart); COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaFinish, float, setAlphaFinish); - COPY_PROPERTY_FROM_QSCRIPTVALUE(additiveBlending, bool, setAdditiveBlending); + COPY_PROPERTY_FROM_QSCRIPTVALUE(emitterShouldTrail , bool, setEmitterShouldTrail); COPY_PROPERTY_FROM_QSCRIPTVALUE(modelURL, QString, setModelURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(compoundShapeURL, QString, setCompoundShapeURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(glowLevel, float, setGlowLevel); @@ -670,7 +670,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float); ADD_PROPERTY_TO_MAP(PROP_ALPHA_START, AlphaStart, alphaStart, float); ADD_PROPERTY_TO_MAP(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float); - ADD_PROPERTY_TO_MAP(PROP_ADDITIVE_BLENDING, AdditiveBlending, additiveBlending, bool); + ADD_PROPERTY_TO_MAP(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool); ADD_PROPERTY_TO_MAP(PROP_MODEL_URL, ModelURL, modelURL, QString); ADD_PROPERTY_TO_MAP(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString); ADD_PROPERTY_TO_MAP(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3); @@ -980,7 +980,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, properties.getAlphaSpread()); APPEND_ENTITY_PROPERTY(PROP_ALPHA_START, properties.getAlphaStart()); APPEND_ENTITY_PROPERTY(PROP_ALPHA_FINISH, properties.getAlphaFinish()); - APPEND_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, properties.getAdditiveBlending()); + APPEND_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, properties.getEmitterShouldTrail()); } if (properties.getType() == EntityTypes::Zone) { @@ -1265,7 +1265,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_SPREAD, float, setAlphaSpread); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_START, float, setAlphaStart); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_FINISH, float, setAlphaFinish); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ADDITIVE_BLENDING, bool, setAdditiveBlending); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail); } if (properties.getType() == EntityTypes::Zone) { @@ -1608,8 +1608,8 @@ QList EntityItemProperties::listChangedProperties() { if (alphaFinishChanged()) { out += "alphaFinish"; } - if (additiveBlendingChanged()) { - out += "additiveBlending"; + if (emitterShouldTrailChanged()) { + out += "emitterShouldTrail"; } if (modelURLChanged()) { out += "modelURL"; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index c13519996a..5420e75aed 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -161,7 +161,7 @@ public: DEFINE_PROPERTY(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float, ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD); DEFINE_PROPERTY(PROP_RADIUS_START, RadiusStart, radiusStart, float, ParticleEffectEntityItem::DEFAULT_RADIUS_START); DEFINE_PROPERTY(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float, ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH); - DEFINE_PROPERTY(PROP_ADDITIVE_BLENDING, AdditiveBlending, additiveBlending, bool, ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING); + DEFINE_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool, ParticleEffectEntityItem::DEFAULT_EMITTER_SHOULD_TRAIL); DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID); DEFINE_PROPERTY_GROUP(KeyLight, keyLight, KeyLightPropertyGroup); DEFINE_PROPERTY_REF(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3, PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 3bca911a56..2ba86a491e 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -149,7 +149,7 @@ enum EntityPropertyList { PROP_ANIMATION_HOLD, PROP_ANIMATION_START_AUTOMATICALLY, - PROP_ADDITIVE_BLENDING, + PROP_EMITTER_SHOULD_TRAIL, PROP_PARENT_ID, PROP_PARENT_JOINT_INDEX, diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 8f6f60fa26..7d9af11862 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -93,7 +93,7 @@ const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f; const float ParticleEffectEntityItem::DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS; const float ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS; const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = ""; -const bool ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING = false; +const bool ParticleEffectEntityItem::DEFAULT_EMITTER_SHOULD_TRAIL = false; EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -333,7 +333,7 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaStart, getAlphaStart); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaFinish, getAlphaFinish); COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(additiveBlending, getAdditiveBlending); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitterShouldTrail, getEmitterShouldTrail); return properties; @@ -372,7 +372,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaStart, setAlphaStart); SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaFinish, setAlphaFinish); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(additiveBlending, setAdditiveBlending); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitterShouldTrail, setEmitterShouldTrail); if (somethingChanged) { bool wantDebug = false; @@ -465,7 +465,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch } if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING) { - READ_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, bool, setAdditiveBlending); + READ_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail); } return bytesRead; @@ -505,7 +505,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_POLAR_FINISH; requestedProperties += PROP_AZIMUTH_START; requestedProperties += PROP_AZIMUTH_FINISH; - requestedProperties += PROP_ADDITIVE_BLENDING; + requestedProperties += PROP_EMITTER_SHOULD_TRAIL; return requestedProperties; } @@ -548,7 +548,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_POLAR_FINISH, getPolarFinish()); APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_START, getAzimuthStart()); APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, getAzimuthFinish()); - APPEND_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, getAdditiveBlending()); + APPEND_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, getEmitterShouldTrail()); } bool ParticleEffectEntityItem::isEmittingParticles() const { @@ -648,7 +648,9 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { std::uniform_real_distribution uniform_dist(-1.0, 1.0); particle.seed = randFloatInRange(-1.0f, 1.0f); - particle.position = getPosition(); + if (getEmitterShouldTrail()) { + particle.position = getPosition(); + } // Position, velocity, and acceleration if (_polarStart == 0.0f && _polarFinish == 0.0f && _emitDimensions.z == 0.0f) { // Emit along z-axis from position @@ -699,7 +701,12 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { radii.z > 0.0f ? z / (radii.z * radii.z) : 0.0f )); - particle.position += _emitOrientation * emitPosition; + if (getEmitterShouldTrail()) { + particle.position += _emitOrientation * emitPosition; + } + else { + particle.position = _emitOrientation * emitPosition; + } } particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index c35a45baeb..7bedbde6d8 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -207,10 +207,10 @@ public: } } - static const bool DEFAULT_ADDITIVE_BLENDING; - bool getAdditiveBlending() const { return _additiveBlending; } - void setAdditiveBlending(bool additiveBlending) { - _additiveBlending = additiveBlending; + static const bool DEFAULT_EMITTER_SHOULD_TRAIL; + bool getEmitterShouldTrail() const { return _emitterShouldTrail; } + void setEmitterShouldTrail(bool emitterShouldTrail) { + _emitterShouldTrail = emitterShouldTrail; } virtual bool supportsDetailedRayIntersection() const { return false; } @@ -280,7 +280,7 @@ protected: float _timeUntilNextEmit { 0.0f }; - bool _additiveBlending { DEFAULT_ADDITIVE_BLENDING }; + bool _emitterShouldTrail { DEFAULT_EMITTER_SHOULD_TRAIL }; }; #endif // hifi_ParticleEffectEntityItem_h From d9c93130e5a148a2758e9c7016a16467cbd7b5b3 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 15 Dec 2015 18:02:11 -0800 Subject: [PATCH 058/195] In a state where non uniform random vals are clear --- .../flowArts/lightBall/lightBallSpawner.js | 39 +++++++------------ .../entities/src/ParticleEffectEntityItem.cpp | 2 +- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/examples/flowArts/lightBall/lightBallSpawner.js b/examples/flowArts/lightBall/lightBallSpawner.js index 7744c1210e..dd521b4fd4 100644 --- a/examples/flowArts/lightBall/lightBallSpawner.js +++ b/examples/flowArts/lightBall/lightBallSpawner.js @@ -12,21 +12,9 @@ var raveRoom = Entities.addEntity({ }); var colorPalette = [{ - red: 250, - green: 137, + red: 25, + green: 20, blue: 162 -}, { - red: 204, - green: 244, - blue: 249 -}, { - red: 146, - green: 206, - blue: 116 -}, { - red: 240, - green: 87, - blue: 129 }]; @@ -34,7 +22,7 @@ var containerBall = Entities.addEntity({ type: "Sphere", position: center, dimensions: {x: .1, y: .1, z: .1}, - color: {red: 1500, green: 10, blue: 50}, + color: {red: 15, green: 10, blue: 150}, collisionsWillMove: true, userData: JSON.stringify({ grabbableKey: { @@ -90,13 +78,13 @@ var lightBall = Entities.addEntity({ isEmitting: true, "name": "ParticlesTest Emitter", "colorStart": {red: 200, green: 20, blue: 40}, - color: {red: 10, green: 0, blue: 255}, - "colorFinish": {red: 250, green: 200, blue:255}, + color: {red: 200, green: 200, blue: 255}, + "colorFinish": {red: 25, green: 20, blue:255}, "maxParticles": 100000, - "lifespan": 2, - "emitRate": 10000, - "emitSpeed": .2, - "speedSpread": .01, + "lifespan": 5, + "emitRate": 500, + "emitSpeed": .02, + "speedSpread": .0, "emitDimensions": { "x": 0, "y": 0, @@ -112,9 +100,9 @@ var lightBall = Entities.addEntity({ "z": 0 }, "accelerationSpread": { - "x": .01, - "y": .01, - "z": .01 + "x": .00, + "y": .00, + "z": .00 }, "particleRadius": 0.04, "radiusSpread": 0, @@ -124,9 +112,8 @@ var lightBall = Entities.addEntity({ "alphaSpread": .5, "alphaStart": 0, "alphaFinish": 0.5, - "additiveBlending": 0, "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - emitterShouldTrail: false + emitterShouldTrail: true }) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 7d9af11862..954074ec17 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -645,7 +645,7 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { std::random_device rd; std::mt19937_64 el(rd()); - std::uniform_real_distribution uniform_dist(-1.0, 1.0); + std::uniform_real_distribution uniform_dist(0.0, 1.0); particle.seed = randFloatInRange(-1.0f, 1.0f); if (getEmitterShouldTrail()) { From d2ebaef69e9c057bcd6cf4c0ba5e60dd688b141b Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 15 Dec 2015 18:18:42 -0800 Subject: [PATCH 059/195] Adding a simple manual exposure control to configure the tonemapping and expose it to js. Add a convenient way to access the Job._concept._data with template --- examples/utilities/tools/renderEngineDebug.js | 5 +++ interface/src/Application.cpp | 2 + libraries/gpu/src/gpu/Batch.cpp | 6 +++ libraries/gpu/src/gpu/Batch.h | 4 ++ libraries/gpu/src/gpu/GLBackend.cpp | 1 + libraries/gpu/src/gpu/GLBackend.h | 7 +++- libraries/gpu/src/gpu/GLBackendOutput.cpp | 2 +- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 11 +++++ libraries/gpu/src/gpu/GLBackendTexture.cpp | 37 ++++++++++++++++- .../render-utils/src/DebugDeferredBuffer.cpp | 4 +- .../render-utils/src/FramebufferCache.cpp | 4 +- .../render-utils/src/RenderDeferredTask.cpp | 18 +++++++++ .../render-utils/src/RenderDeferredTask.h | 5 +++ .../render-utils/src/ToneMappingEffect.cpp | 40 ++++++++++++++++--- .../render-utils/src/ToneMappingEffect.h | 8 +++- libraries/render/src/render/DrawTask.h | 17 ++++++++ libraries/render/src/render/Engine.h | 2 + .../src/SceneScriptingInterface.h | 4 ++ 18 files changed, 165 insertions(+), 12 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index 60686912e8..2c0dc352b4 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -109,6 +109,11 @@ panel.newCheckbox("Network/Physics status", function(value) { return (value & showNetworkStatusFlag) > 0; } ); +panel.newSlider("Tone Mapping Exposure", -10, 10, + function (value) { Scene.setEngineToneMappingExposure(value); }, + function() { return Scene.getEngineToneMappingExposure(); }, + function (value) { return (value); }); + var tickTackPeriod = 500; function updateCounters() { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c26c8330f8..c6fa997eae 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3691,6 +3691,8 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion); renderContext._fxaaStatus = Menu::getInstance()->isOptionChecked(MenuOption::Antialiasing); + renderContext._toneMappingExposure = sceneInterface->getEngineToneMappingExposure(); + renderArgs->_shouldRender = LODManager::shouldRender; renderContext.args = renderArgs; diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 14871aafd1..843eb3d3a5 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -311,6 +311,12 @@ void Batch::blit(const FramebufferPointer& src, const Vec4i& srcViewport, _params.push_back(dstViewport.w); } +void Batch::generateTextureMipmap(const TexturePointer& texture) { + ADD_COMMAND(generateTextureMipmap); + + _params.push_back(_textures.cache(texture)); +} + void Batch::beginQuery(const QueryPointer& query) { ADD_COMMAND(beginQuery); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 2afcc7caa9..122285f5ea 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -211,6 +211,9 @@ public: // with xy and zw the bounding corners of the rect region. void blit(const FramebufferPointer& src, const Vec4i& srcRect, const FramebufferPointer& dst, const Vec4i& dstRect); + // Generate the mipmap for a texture + void generateTextureMipmap(const TexturePointer& texture); + // Query Section void beginQuery(const QueryPointer& query); void endQuery(const QueryPointer& query); @@ -292,6 +295,7 @@ public: COMMAND_setFramebuffer, COMMAND_clearFramebuffer, COMMAND_blit, + COMMAND_generateTextureMipmap, COMMAND_beginQuery, COMMAND_endQuery, diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index d4f3c5c4b3..ff1b207f7c 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -52,6 +52,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setFramebuffer), (&::gpu::GLBackend::do_clearFramebuffer), (&::gpu::GLBackend::do_blit), + (&::gpu::GLBackend::do_generateTextureMipmap), (&::gpu::GLBackend::do_beginQuery), (&::gpu::GLBackend::do_endQuery), diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index f44fbe6c0d..4733d81cbf 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -376,12 +376,16 @@ protected: // Resource Stage void do_setResourceTexture(Batch& batch, size_t paramOffset); - + + // update resource cache and do the gl unbind call with the current gpu::Texture cached at slot s void releaseResourceTexture(uint32_t slot); + void resetResourceStage(); struct ResourceStageState { Textures _textures; + int findEmptyTextureSlot() const; + ResourceStageState(): _textures(MAX_NUM_RESOURCE_TEXTURES, nullptr) {} @@ -432,6 +436,7 @@ protected: void do_setFramebuffer(Batch& batch, size_t paramOffset); void do_clearFramebuffer(Batch& batch, size_t paramOffset); void do_blit(Batch& batch, size_t paramOffset); + void do_generateTextureMipmap(Batch& batch, size_t paramOffset); // Synchronize the state cache of this Backend with the actual real state of the GL Context void syncOutputStateCache(); diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 6d8ce7b2c6..5f226141a8 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -361,4 +361,4 @@ void GLBackend::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, co glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); (void) CHECK_GL_ERROR(); -} \ No newline at end of file +} diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 8601c7512b..8c9647e0f2 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -231,6 +231,7 @@ void GLBackend::releaseResourceTexture(uint32_t slot) { } } + void GLBackend::resetResourceStage() { for (uint32_t i = 0; i < _resource._textures.size(); i++) { releaseResourceTexture(i); @@ -268,3 +269,13 @@ void GLBackend::do_setResourceTexture(Batch& batch, size_t paramOffset) { } } +int GLBackend::ResourceStageState::findEmptyTextureSlot() const { + // start from the end of the slots, try to find an empty one that can be used + for (auto i = MAX_NUM_RESOURCE_TEXTURES - 1; i > 0; i--) { + if (!_textures[i]) { + return i; + } + } + return -1; +} + diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 73bf02e8c7..eaed50b850 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -404,8 +404,9 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { if (bytes && texture.isAutogenerateMips()) { glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else if (texture.isAutogenerateMips()) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } - object->_target = GL_TEXTURE_2D; syncSampler(texture.getSampler(), texture.getType(), object); @@ -588,3 +589,37 @@ void GLBackend::syncSampler(const Sampler& sampler, Texture::Type type, GLTextur glTexParameterf(object->_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy()); } + + + +void GLBackend::do_generateTextureMipmap(Batch& batch, size_t paramOffset) { + TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); + if (!resourceTexture) { + return; + } + + GLTexture* object = GLBackend::syncGPUObject(*resourceTexture); + if (!object) { + return; + } + + // IN 4.1 we still need to find an available slot + auto freeSlot = _resource.findEmptyTextureSlot(); + auto bindingSlot = (freeSlot < 0 ? 0 : freeSlot); + glActiveTexture(GL_TEXTURE0 + bindingSlot); + glBindTexture(object->_target, object->_texture); + + glGenerateMipmap(object->_target); + + if (freeSlot < 0) { + // If had to use slot 0 then restore state + GLTexture* boundObject = GLBackend::syncGPUObject(*_resource._textures[0]); + if (boundObject) { + glBindTexture(boundObject->_target, boundObject->_texture); + } + } else { + // clean up + glBindTexture(object->_target, 0); + } + (void)CHECK_GL_ERROR(); +} diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 842729144d..169ae0b58e 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -49,7 +49,7 @@ static const std::string FUNCTIONS_PLACEHOLDER { "/*FUNCTIONS_PLACEHOLDER*/" }; std::string DebugDeferredBuffer::getCode(Modes mode) { switch (mode) { case DiffuseMode: { - QString code = "return vec4(texture(%1, uv).xyz, 1.0);"; + QString code = "return vec4(pow(texture(%1, uv).xyz, vec3(1.0 / 2.2)), 1.0);"; return code.arg(SLOT_NAMES[Diffuse].c_str()).toStdString(); } case AlphaMode: { @@ -73,7 +73,7 @@ std::string DebugDeferredBuffer::getCode(Modes mode) { return code.arg(SLOT_NAMES[Depth].c_str()).toStdString(); } case LightingMode: { - QString code = "return vec4(texture(%1, uv).xyz, 1.0);"; + QString code = "return vec4(pow(texture(%1, uv).xyz, vec3(1.0 / 2.2)), 1.0);"; return code.arg(SLOT_NAMES[Lighting].c_str()).toStdString(); } case CustomMode: diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index 7b8c0f7f35..e64e245806 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -87,9 +87,11 @@ void FramebufferCache::createPrimaryFramebuffer() { auto tex = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width * 0.5, height * 0.5, defaultSampler)); _selfieFramebuffer->setRenderBuffer(0, tex); + auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR); + //_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, defaultSampler)); //lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::R11G11B10), width, height, defaultSampler)); - _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler)); + _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, smoothSampler)); _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _lightingFramebuffer->setRenderBuffer(0, _lightingTexture); _lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 5f9cb7b575..ef95876f11 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -104,6 +104,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { // Lighting Buffer ready for tone mapping _jobs.push_back(Job(new ToneMappingDeferred::JobModel("ToneMapping"))); + _toneMappingJobIndex = _jobs.size() - 1; // Debugging Deferred buffer job _jobs.push_back(Job(new DebugDeferredBuffer::JobModel("DebugDeferredBuffer"))); @@ -164,6 +165,8 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend setAntialiasingStatus(renderContext->_fxaaStatus); + setToneMappingExposure(renderContext->_toneMappingExposure); + renderContext->args->_context->syncCache(); for (auto job : _jobs) { @@ -390,3 +393,18 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const }); args->_batch = nullptr; } + + +void RenderDeferredTask::setToneMappingExposure(float exposure) { + if (_toneMappingJobIndex >= 0) { + _jobs[_toneMappingJobIndex].edit()._toneMappingEffect.setExposure(exposure); + } +} + +float RenderDeferredTask::getToneMappingExposure() const { + if (_toneMappingJobIndex >= 0) { + _jobs[_toneMappingJobIndex].get()._toneMappingEffect.getExposure(); + } else { + return 0.0f; + } +} diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 009e6f23b2..ea99c9f12e 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -129,6 +129,11 @@ public: void setAntialiasingStatus(bool draw) { if (_antialiasingJobIndex >= 0) { _jobs[_antialiasingJobIndex].setEnabled(draw); } } bool doAntialiasingStatus() const { if (_antialiasingJobIndex >= 0) { return _jobs[_antialiasingJobIndex].isEnabled(); } else { return false; } } + int _toneMappingJobIndex = -1; + + void setToneMappingExposure(float exposure); + float getToneMappingExposure() const; + virtual void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index 97248a62d0..54794aa4a0 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -20,7 +20,8 @@ ToneMappingEffect::ToneMappingEffect() { - + Parameters parameters; + _parametersBuffer = gpu::BufferView(std::make_shared(sizeof(Parameters), (const gpu::Byte*) ¶meters)); } void ToneMappingEffect::init() { @@ -38,6 +39,16 @@ void ToneMappingEffect::init() { // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + struct ToneMappingParams { + vec4 _exp_2powExp_s0_s1; + }; + + uniform toneMappingParamsBuffer { + ToneMappingParams params; + }; + float getTwoPowExposure() { + return params._exp_2powExp_s0_s1.y; + } uniform sampler2D colorMap; @@ -45,16 +56,24 @@ void ToneMappingEffect::init() { out vec4 outFragColor; void main(void) { - vec4 fragColor = texture(colorMap, varTexCoord0); + vec4 fragColorRaw = textureLod(colorMap, varTexCoord0, 0); + vec3 fragColor = fragColorRaw.xyz; + +/* vec4 fragColorAverage = textureLod(colorMap, varTexCoord0, 10); + float averageIntensity = length(fragColorAverage.xyz); + + vec3 fragColor = fragColorRaw.xyz / averageIntensity; +*/ + fragColor *= getTwoPowExposure(); + + // if (gl_FragCoord.x > 1000) { // Manually gamma correct from Ligthing BUffer to color buffer // outFragColor.xyz = pow( fragColor.xyz , vec3(1.0 / 2.2) ); - fragColor *= 2.0; // Hardcoded Exposure Adjustment vec3 x = max(vec3(0.0),fragColor.xyz-0.004); vec3 retColor = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06); - // fragColor *= 8; // Hardcoded Exposure Adjustment // fragColor = fragColor/(1.0+fragColor); // vec3 retColor = pow(fragColor.xyz,vec3(1/2.2)); @@ -70,12 +89,19 @@ void ToneMappingEffect::init() { auto blitProgram = gpu::ShaderPointer(gpu::Shader::createProgram(blitVS, blitPS)); //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); - gpu::Shader::makeProgram(*blitProgram); + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("toneMappingParamsBuffer"), 3)); + gpu::Shader::makeProgram(*blitProgram, slotBindings); auto blitState = std::make_shared(); blitState->setColorWriteMask(true, true, true, true); _blitLightBuffer = gpu::PipelinePointer(gpu::Pipeline::create(blitProgram, blitState)); } +void ToneMappingEffect::setExposure(float exposure) { + _parametersBuffer.edit()._exposure = exposure; + _parametersBuffer.edit()._twoPowExposure = pow(2.0, exposure); +} + void ToneMappingEffect::render(RenderArgs* args) { if (!_blitLightBuffer) { @@ -89,6 +115,9 @@ void ToneMappingEffect::render(RenderArgs* args) { auto lightingBuffer = framebufferCache->getLightingTexture(); auto destFbo = framebufferCache->getPrimaryFramebuffer(); batch.setFramebuffer(destFbo); + + batch.generateTextureMipmap(lightingBuffer); + batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.setViewTransform(Transform()); @@ -104,6 +133,7 @@ void ToneMappingEffect::render(RenderArgs* args) { batch.setModelTransform(model); } + batch.setUniformBuffer(3, _parametersBuffer); batch.setResourceTexture(0, lightingBuffer); batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index 9b07c0f7df..be9664ddd9 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -27,6 +27,9 @@ public: void render(RenderArgs* args); + void setExposure(float exposure); + float getExposure() const { return _parametersBuffer.get()._exposure; } + private: gpu::PipelinePointer _blitLightBuffer; @@ -34,7 +37,10 @@ private: // Class describing the uniform buffer with all the parameters common to the tone mapping shaders class Parameters { public: - + float _exposure = 0.0f; + float _twoPowExposure = 1.0f; + glm::vec2 spare; + Parameters() {} }; typedef gpu::BufferView UniformBufferView; diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 3f628c3a02..52dc427251 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -84,6 +84,23 @@ public: const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } + template T& edit() { + auto theConcept = std::dynamic_pointer_cast(_concept); + if (theConcept) { + return theConcept->_data; + } + assert(false); + return T(); + } + template const T& get() const { + auto theConcept = std::dynamic_pointer_cast(_concept); + if (theConcept) { + return theConcept->_data; + } + assert(false); + return T(); + } + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { PerformanceTimer perfTimer(getName().c_str()); PROFILE_RANGE(getName().c_str()); diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 26bd6f2154..c219b87f40 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -61,6 +61,8 @@ public: bool _occlusionStatus = false; bool _fxaaStatus = false; + float _toneMappingExposure = 0.0; + RenderContext() {} }; typedef std::shared_ptr RenderContextPointer; diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 78261dfdc7..875a2a1b8f 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -118,6 +118,9 @@ public: Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; } Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; } + Q_INVOKABLE void setEngineToneMappingExposure(float exposure) { _engineToneMappingExposure = exposure; } + Q_INVOKABLE float getEngineToneMappingExposure() { return _engineToneMappingExposure; } + signals: void shouldRenderAvatarsChanged(bool shouldRenderAvatars); void shouldRenderEntitiesChanged(bool shouldRenderEntities); @@ -154,6 +157,7 @@ protected: bool _drawHitEffect = false; + float _engineToneMappingExposure = 0.0f; }; #endif // hifi_SceneScriptingInterface_h From c2feec16de17b7f91cdb08d70e0759a43d3624e8 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 15 Dec 2015 18:24:16 -0800 Subject: [PATCH 060/195] Cleaning the code --- libraries/gpu/src/gpu/GLBackendTexture.cpp | 2 -- libraries/render-utils/src/ToneMappingEffect.cpp | 12 +++--------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index eaed50b850..18b4065b77 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -404,8 +404,6 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { if (bytes && texture.isAutogenerateMips()) { glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } else if (texture.isAutogenerateMips()) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } object->_target = GL_TEXTURE_2D; diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index 54794aa4a0..23d0b3c800 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -25,8 +25,6 @@ ToneMappingEffect::ToneMappingEffect() { } void ToneMappingEffect::init() { - //auto VSFS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); - //auto PSBlit = gpu::StandardShaderLib::getDrawTexturePS(); const char BlitTextureGamma_frag[] = R"SCRIBE(#version 410 core // Generated on Sat Oct 24 09:34:37 2015 // @@ -67,28 +65,24 @@ void ToneMappingEffect::init() { fragColor *= getTwoPowExposure(); - // if (gl_FragCoord.x > 1000) { // Manually gamma correct from Ligthing BUffer to color buffer - // outFragColor.xyz = pow( fragColor.xyz , vec3(1.0 / 2.2) ); + // outFragColor.xyz = pow( fragColor.xyz , vec3(1.0 / 2.2) ); vec3 x = max(vec3(0.0),fragColor.xyz-0.004); vec3 retColor = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06); - // fragColor = fragColor/(1.0+fragColor); - // vec3 retColor = pow(fragColor.xyz,vec3(1/2.2)); + // fragColor = fragColor/(1.0+fragColor); + // vec3 retColor = pow(fragColor.xyz,vec3(1/2.2)); outFragColor = vec4(retColor, 1.0); - // } } )SCRIBE"; auto blitPS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(BlitTextureGamma_frag))); - //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); auto blitVS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); auto blitProgram = gpu::ShaderPointer(gpu::Shader::createProgram(blitVS, blitPS)); - //auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("toneMappingParamsBuffer"), 3)); gpu::Shader::makeProgram(*blitProgram, slotBindings); From a60ef4fb5ad8dc90f14f041c237b799c89690970 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 15 Dec 2015 18:32:30 -0800 Subject: [PATCH 061/195] Finalize the names --- libraries/gpu/src/gpu/Batch.cpp | 4 ++-- libraries/gpu/src/gpu/Batch.h | 6 +++--- libraries/gpu/src/gpu/GLBackend.cpp | 2 +- libraries/gpu/src/gpu/GLBackend.h | 2 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 2 +- libraries/render-utils/src/ToneMappingEffect.cpp | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 843eb3d3a5..f9c4131a1b 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -311,8 +311,8 @@ void Batch::blit(const FramebufferPointer& src, const Vec4i& srcViewport, _params.push_back(dstViewport.w); } -void Batch::generateTextureMipmap(const TexturePointer& texture) { - ADD_COMMAND(generateTextureMipmap); +void Batch::generateTextureMips(const TexturePointer& texture) { + ADD_COMMAND(generateTextureMips); _params.push_back(_textures.cache(texture)); } diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 122285f5ea..88d28f9d10 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -211,8 +211,8 @@ public: // with xy and zw the bounding corners of the rect region. void blit(const FramebufferPointer& src, const Vec4i& srcRect, const FramebufferPointer& dst, const Vec4i& dstRect); - // Generate the mipmap for a texture - void generateTextureMipmap(const TexturePointer& texture); + // Generate the mips for a texture + void generateTextureMips(const TexturePointer& texture); // Query Section void beginQuery(const QueryPointer& query); @@ -295,7 +295,7 @@ public: COMMAND_setFramebuffer, COMMAND_clearFramebuffer, COMMAND_blit, - COMMAND_generateTextureMipmap, + COMMAND_generateTextureMips, COMMAND_beginQuery, COMMAND_endQuery, diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index ff1b207f7c..a730c06bd9 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -52,7 +52,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setFramebuffer), (&::gpu::GLBackend::do_clearFramebuffer), (&::gpu::GLBackend::do_blit), - (&::gpu::GLBackend::do_generateTextureMipmap), + (&::gpu::GLBackend::do_generateTextureMips), (&::gpu::GLBackend::do_beginQuery), (&::gpu::GLBackend::do_endQuery), diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 4733d81cbf..400c9f08f8 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -436,7 +436,7 @@ protected: void do_setFramebuffer(Batch& batch, size_t paramOffset); void do_clearFramebuffer(Batch& batch, size_t paramOffset); void do_blit(Batch& batch, size_t paramOffset); - void do_generateTextureMipmap(Batch& batch, size_t paramOffset); + void do_generateTextureMips(Batch& batch, size_t paramOffset); // Synchronize the state cache of this Backend with the actual real state of the GL Context void syncOutputStateCache(); diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 18b4065b77..17802ae6ed 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -590,7 +590,7 @@ void GLBackend::syncSampler(const Sampler& sampler, Texture::Type type, GLTextur -void GLBackend::do_generateTextureMipmap(Batch& batch, size_t paramOffset) { +void GLBackend::do_generateTextureMips(Batch& batch, size_t paramOffset) { TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); if (!resourceTexture) { return; diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index 23d0b3c800..22c31a2459 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -110,7 +110,7 @@ void ToneMappingEffect::render(RenderArgs* args) { auto destFbo = framebufferCache->getPrimaryFramebuffer(); batch.setFramebuffer(destFbo); - batch.generateTextureMipmap(lightingBuffer); + batch.generateTextureMips(lightingBuffer); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); From 61bad36d5c1b0a0ad40747724372c121040e60d5 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 15 Dec 2015 18:49:04 -0800 Subject: [PATCH 062/195] tweaks --- examples/flowArts/lightBall/lightBallSpawner.js | 5 +++-- libraries/entities/src/ParticleEffectEntityItem.cpp | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/examples/flowArts/lightBall/lightBallSpawner.js b/examples/flowArts/lightBall/lightBallSpawner.js index dd521b4fd4..505df7d83b 100644 --- a/examples/flowArts/lightBall/lightBallSpawner.js +++ b/examples/flowArts/lightBall/lightBallSpawner.js @@ -24,6 +24,7 @@ var containerBall = Entities.addEntity({ dimensions: {x: .1, y: .1, z: .1}, color: {red: 15, green: 10, blue: 150}, collisionsWillMove: true, + visible: false, userData: JSON.stringify({ grabbableKey: { spatialKey: { @@ -82,8 +83,8 @@ var lightBall = Entities.addEntity({ "colorFinish": {red: 25, green: 20, blue:255}, "maxParticles": 100000, "lifespan": 5, - "emitRate": 500, - "emitSpeed": .02, + "emitRate": 5000, + "emitSpeed": .1, "speedSpread": .0, "emitDimensions": { "x": 0, diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 954074ec17..4d46439554 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -666,13 +666,14 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { float elevationMinZ = sin(PI_OVER_TWO - _polarFinish); float elevationMaxZ = sin(PI_OVER_TWO - _polarStart); - float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat()); + // float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat()); + float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * uniform_dist(el)); float azimuth; if (_azimuthFinish >= _azimuthStart) { - azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat(); + azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * uniform_dist(el); } else { - azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * randFloat(); + azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * uniform_dist(el); } glm::vec3 emitDirection; From 1364329886c27afb05d713c7571b652670dcee8a Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 15 Dec 2015 22:07:06 -0800 Subject: [PATCH 063/195] FIxing the compil bug by checking security of the call with assert and avoiding the compilation error --- libraries/render/src/render/DrawTask.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 52dc427251..ab102e32a7 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -86,19 +86,13 @@ public: template T& edit() { auto theConcept = std::dynamic_pointer_cast(_concept); - if (theConcept) { - return theConcept->_data; - } - assert(false); - return T(); + assert(theConcept); + return theConcept->_data; } template const T& get() const { auto theConcept = std::dynamic_pointer_cast(_concept); - if (theConcept) { - return theConcept->_data; - } - assert(false); - return T(); + assert(theConcept); + return theConcept->_data; } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { From fcfa3969125e956b983401983a5964a86721968a Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 16 Dec 2015 13:58:55 -0800 Subject: [PATCH 064/195] syntax tweak --- examples/flowArts/lightBall/lightBallSpawner.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/flowArts/lightBall/lightBallSpawner.js b/examples/flowArts/lightBall/lightBallSpawner.js index 505df7d83b..20a9c312fc 100644 --- a/examples/flowArts/lightBall/lightBallSpawner.js +++ b/examples/flowArts/lightBall/lightBallSpawner.js @@ -24,7 +24,6 @@ var containerBall = Entities.addEntity({ dimensions: {x: .1, y: .1, z: .1}, color: {red: 15, green: 10, blue: 150}, collisionsWillMove: true, - visible: false, userData: JSON.stringify({ grabbableKey: { spatialKey: { @@ -85,7 +84,7 @@ var lightBall = Entities.addEntity({ "lifespan": 5, "emitRate": 5000, "emitSpeed": .1, - "speedSpread": .0, + "speedSpread": 0.0, "emitDimensions": { "x": 0, "y": 0, From b29a6b16a954f4e5427fdbe96517c65153d355ed Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 16 Dec 2015 14:40:56 -0800 Subject: [PATCH 065/195] modularizing flow art tools --- examples/flowArts/flowArtsHutSpawner.js | 77 ++++++ .../flowArts/lightBall/lightBallSpawner.js | 239 +++++++++--------- 2 files changed, 194 insertions(+), 122 deletions(-) create mode 100644 examples/flowArts/flowArtsHutSpawner.js diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js new file mode 100644 index 0000000000..d3c60548ea --- /dev/null +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -0,0 +1,77 @@ +// +// flowArtsHutSpawner.js +// examples +// +// Created by Eric Levin on 5/14/15. +// Copyright 2014 High Fidelity, Inc. +// +// This script creates a special flow arts hut with a numch of flow art toys people can go in and play with +// +// +// 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("../../libraries/utils.js"); +Script.include("lightBall/lightBallSpawner.js"); + +var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); +basePosition.y = MyAvatar.position.y + 1 +var lightBall = LightBallSpawner(basePosition); +var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); + +var roomDimensions = {x: 30.58, y: 15.29, z: 30.58}; + +var raveRoom = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: basePosition, + dimensions:roomDimensions, + visible: true +}); + +var floor = Entities.addEntity({ + type: "Box", + position: Vec3.sum(basePosition, {x: 0, y: -1.5, z: 0}), + dimensions: {x: roomDimensions.x, y: 0.6, z: roomDimensions.z}, + color: {red: 50, green: 10, blue: 100}, + shapeType: 'box' +}); + + + + + +var lightZone = Entities.addEntity({ + type: "Zone", + shapeType: 'box', + keyLightIntensity: 0.2, + keyLightColor: { + red: 50, + green: 0, + blue: 50 + }, + keyLightAmbientIntensity: .2, + position: MyAvatar.position, + dimensions: { + x: 100, + y: 100, + z: 100 + } +}); + + + + + + +function cleanup() { + + Entities.deleteEntity(raveRoom); + Entities.deleteEntity(lightZone) + Entities.deleteEntity(floor); + lightBall.cleanup(); +} + +Script.scriptEnding.connect(cleanup); \ No newline at end of file diff --git a/examples/flowArts/lightBall/lightBallSpawner.js b/examples/flowArts/lightBall/lightBallSpawner.js index 20a9c312fc..7325f16a64 100644 --- a/examples/flowArts/lightBall/lightBallSpawner.js +++ b/examples/flowArts/lightBall/lightBallSpawner.js @@ -1,129 +1,124 @@ + Script.include("../../libraries/utils.js"); -Script.include("../../libraries/utils.js"); + LightBallSpawner = function(basePosition) { -var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); -var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); - -var raveRoom = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - position: center, - visible:false -}); - -var colorPalette = [{ - red: 25, - green: 20, - blue: 162 -}]; + var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); + var colorPalette = [{ + red: 25, + green: 20, + blue: 162 + }]; -var containerBall = Entities.addEntity({ - type: "Sphere", - position: center, - dimensions: {x: .1, y: .1, z: .1}, - color: {red: 15, green: 10, blue: 150}, - collisionsWillMove: true, - userData: JSON.stringify({ - grabbableKey: { - spatialKey: { - relativePosition: { - x: 0, - y: 1, - z: 0 - } + var containerBall = Entities.addEntity({ + type: "Sphere", + position: Vec3.sum(basePosition, { + x: 0, + y: .5, + z: 0 + }), + dimensions: { + x: .1, + y: .1, + z: .1 }, - invertSolidWhileHeld: true + color: { + red: 15, + green: 10, + blue: 150 + }, + collisionsWillMove: true, + userData: JSON.stringify({ + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 1, + z: 0 + } + }, + invertSolidWhileHeld: true + } + }) + }); + + + var light = Entities.addEntity({ + type: 'Light', + parentID: containerBall, + dimensions: { + x: 30, + y: 30, + z: 30 + }, + color: colorPalette[randInt(0, colorPalette.length)], + intensity: 5 + }); + + + var lightBall = Entities.addEntity({ + type: "ParticleEffect", + parentID: containerBall, + isEmitting: true, + "name": "ParticlesTest Emitter", + "colorStart": { + red: 200, + green: 20, + blue: 40 + }, + color: { + red: 200, + green: 200, + blue: 255 + }, + "colorFinish": { + red: 25, + green: 20, + blue: 255 + }, + "maxParticles": 100000, + "lifespan": 5, + "emitRate": 5000, + "emitSpeed": .1, + "speedSpread": 0.0, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "polarStart": 0, + "polarFinish": Math.PI, + "azimuthStart": -Math.PI, + "azimuthFinish": Math.PI, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": .00, + "y": .00, + "z": .00 + }, + "particleRadius": 0.04, + "radiusSpread": 0, + "radiusStart": 0.05, + "radiusFinish": 0.0003, + "alpha": 0, + "alphaSpread": .5, + "alphaStart": 0, + "alphaFinish": 0.5, + "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + emitterShouldTrail: true + }) + + + + function cleanup() { + Entities.deleteEntity(lightBall); + Entities.deleteEntity(containerBall); + Entities.deleteEntity(light); } - }) - // gravity: {x: 0, y: -.1, z: 0} -}); -var lightZone = Entities.addEntity({ - type: "Zone", - shapeType: 'box', - keyLightIntensity: 0.2, - keyLightColor: { - red: 50, - green: 0, - blue: 50 - }, - keyLightAmbientIntensity: .2, - position: MyAvatar.position, - dimensions: { - x: 100, - y: 100, - z: 100 - } -}); - -var light = Entities.addEntity({ - type: 'Light', - position: center, - parentID: containerBall, - dimensions: { - x: 30, - y: 30, - z: 30 - }, - color: colorPalette[randInt(0, colorPalette.length)], - intensity: 5 - }); - - -var lightBall = Entities.addEntity({ - position: center, - type: "ParticleEffect", - parentID: containerBall, - isEmitting: true, - "name": "ParticlesTest Emitter", - "colorStart": {red: 200, green: 20, blue: 40}, - color: {red: 200, green: 200, blue: 255}, - "colorFinish": {red: 25, green: 20, blue:255}, - "maxParticles": 100000, - "lifespan": 5, - "emitRate": 5000, - "emitSpeed": .1, - "speedSpread": 0.0, - "emitDimensions": { - "x": 0, - "y": 0, - "z": 0 - }, - "polarStart": 0, - "polarFinish": Math.PI, - "azimuthStart": -Math.PI, - "azimuthFinish": Math.PI, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 - }, - "accelerationSpread": { - "x": .00, - "y": .00, - "z": .00 - }, - "particleRadius": 0.04, - "radiusSpread": 0, - "radiusStart": 0.05, - "radiusFinish": 0.0003, - "alpha": 0, - "alphaSpread": .5, - "alphaStart": 0, - "alphaFinish": 0.5, - "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - emitterShouldTrail: true -}) - - - -function cleanup() { - Entities.deleteEntity(lightBall); - Entities.deleteEntity(containerBall); - Entities.deleteEntity(raveRoom); - Entities.deleteEntity(lightZone) - Entities.deleteEntity(light); -} - -Script.scriptEnding.connect(cleanup); \ No newline at end of file + this.cleanup = cleanup; + } \ No newline at end of file From c14433979b1911a51afbbf6cdcfddf30be4379ed Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 16 Dec 2015 15:09:37 -0800 Subject: [PATCH 066/195] fix crash mode when model late to get collision URL --- .../src/RenderableModelEntityItem.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b5203ea460..83bfbf7f05 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -385,7 +385,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { _needsInitialSimulation = true; } } - + return result; } @@ -398,14 +398,14 @@ void RenderableModelEntityItem::update(const quint64& now) { EntityItemProperties properties; auto extents = _model->getMeshExtents(); properties.setDimensions(extents.maximum - extents.minimum); - + qCDebug(entitiesrenderer) << "Autoresizing:" << (!getName().isEmpty() ? getName() : getModelURL()); QMetaObject::invokeMethod(DependencyManager::get().data(), "editEntity", Qt::QueuedConnection, Q_ARG(QUuid, getEntityItemID()), Q_ARG(EntityItemProperties, properties)); } - + ModelEntityItem::update(now); } @@ -427,7 +427,7 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori // << precisionPicking; QString extraInfo; - return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, + return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, extraInfo, precisionPicking); } @@ -447,24 +447,22 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { ShapeType type = getShapeType(); if (type == SHAPE_TYPE_COMPOUND) { - if (!_model) { + if (!_model || _model->getCollisionURL().isEmpty()) { EntityTreePointer tree = getTree(); if (tree) { QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); } - return false; // hmm... + return false; } - assert(!_model->getCollisionURL().isEmpty()); - if (_model->getURL().isEmpty()) { // we need a render geometry with a scale to proceed, so give up. return false; } - + const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); const QSharedPointer renderNetworkGeometry = _model->getGeometry(); - + if ((collisionNetworkGeometry && collisionNetworkGeometry->isLoaded()) && (renderNetworkGeometry && renderNetworkGeometry->isLoaded())) { // we have both URLs AND both geometries AND they are both fully loaded. From ff83f8fc37081bfb115cb8878ff224235eed4563 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 16 Dec 2015 15:10:30 -0800 Subject: [PATCH 067/195] fix crash mode when leaving domain with handgun --- libraries/physics/src/PhysicalEntitySimulation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 40366257df..5a12627abd 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -44,7 +44,7 @@ void PhysicalEntitySimulation::updateEntitiesInternal(const quint64& now) { void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { assert(entity); - if (entity->shouldBePhysical()) { + if (entity->shouldBePhysical()) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (!motionState) { _pendingAdds.insert(entity); @@ -117,6 +117,7 @@ void PhysicalEntitySimulation::clearEntitiesInternal() { _pendingRemoves.clear(); _pendingAdds.clear(); _pendingChanges.clear(); + _outgoingChanges.clear(); } // end EntitySimulation overrides From c0faf978f84f4e8b5957234ac35fcd28bf89a735 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 16 Dec 2015 15:21:09 -0800 Subject: [PATCH 068/195] Introducing a setting for the tone curve --- .../render-utils/src/ToneMappingEffect.cpp | 48 ++++++++++++------- .../render-utils/src/ToneMappingEffect.h | 14 +++++- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index 22c31a2459..29e5da6e2a 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -36,18 +36,28 @@ void ToneMappingEffect::init() { // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - + struct ToneMappingParams { vec4 _exp_2powExp_s0_s1; + ivec4 _toneCurve_s0_s1_s2; }; + const float INV_GAMMA_22 = 1.0 / 2.2; + const int ToneCurveNone = 0; + const int ToneCurveGamma22 = 1; + const int ToneCurveReinhard = 2; + const int ToneCurveFilmic = 3; + uniform toneMappingParamsBuffer { ToneMappingParams params; }; float getTwoPowExposure() { return params._exp_2powExp_s0_s1.y; } - + int getToneCurve() { + return params._toneCurve_s0_s1_s2.x; + } + uniform sampler2D colorMap; in vec2 varTexCoord0; @@ -56,25 +66,26 @@ void ToneMappingEffect::init() { void main(void) { vec4 fragColorRaw = textureLod(colorMap, varTexCoord0, 0); vec3 fragColor = fragColorRaw.xyz; - -/* vec4 fragColorAverage = textureLod(colorMap, varTexCoord0, 10); +/* + vec4 fragColorAverage = textureLod(colorMap, varTexCoord0, 10); float averageIntensity = length(fragColorAverage.xyz); - - vec3 fragColor = fragColorRaw.xyz / averageIntensity; + fragColor /= averageIntensity; */ - fragColor *= getTwoPowExposure(); + vec3 srcColor = fragColor * getTwoPowExposure(); + int toneCurve = getToneCurve(); + vec3 tonedColor = srcColor; + if (toneCurve == ToneCurveFilmic) { + vec3 x = max(vec3(0.0), srcColor-0.004); + tonedColor = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); + } else if (toneCurve == ToneCurveReinhard) { + tonedColor = srcColor/(1.0 + srcColor); + tonedColor = pow(tonedColor, vec3(INV_GAMMA_22)); + } else if (toneCurve == ToneCurveGamma22) { + tonedColor = pow(srcColor, vec3(INV_GAMMA_22)); + } // else None toned = src - // Manually gamma correct from Ligthing BUffer to color buffer - // outFragColor.xyz = pow( fragColor.xyz , vec3(1.0 / 2.2) ); - - vec3 x = max(vec3(0.0),fragColor.xyz-0.004); - vec3 retColor = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06); - - // fragColor = fragColor/(1.0+fragColor); - // vec3 retColor = pow(fragColor.xyz,vec3(1/2.2)); - - outFragColor = vec4(retColor, 1.0); + outFragColor = vec4(tonedColor, 1.0); } )SCRIBE"; @@ -96,6 +107,9 @@ void ToneMappingEffect::setExposure(float exposure) { _parametersBuffer.edit()._twoPowExposure = pow(2.0, exposure); } +void ToneMappingEffect::setToneCurve(ToneCurve curve) { + _parametersBuffer.edit()._toneCurve = curve; +} void ToneMappingEffect::render(RenderArgs* args) { if (!_blitLightBuffer) { diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index be9664ddd9..20ee9024cf 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -30,6 +30,16 @@ public: void setExposure(float exposure); float getExposure() const { return _parametersBuffer.get()._exposure; } + // Different tone curve available + enum ToneCurve { + None = 0, + Gamma22, + Reinhard, + Filmic, + }; + void setToneCurve(ToneCurve curve); + ToneCurve getToneCurve() const { return (ToneCurve)_parametersBuffer.get()._toneCurve; } + private: gpu::PipelinePointer _blitLightBuffer; @@ -39,7 +49,9 @@ private: public: float _exposure = 0.0f; float _twoPowExposure = 1.0f; - glm::vec2 spare; + glm::vec2 spareA; + int _toneCurve = Filmic; + glm::vec3 spareB; Parameters() {} }; From 4155e3af71a9efc3bc79772364e475864d2187d6 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 16 Dec 2015 15:22:56 -0800 Subject: [PATCH 069/195] refactoring --- examples/flowArts/flowArtsHutSpawner.js | 8 +- examples/flowArts/lightBall/lightBall.js | 124 ++++++++++++++++++ .../flowArts/lightBall/lightBallSpawner.js | 124 ------------------ .../flowArts/raveStick/createRaveStick.js | 0 4 files changed, 126 insertions(+), 130 deletions(-) delete mode 100644 examples/flowArts/lightBall/lightBallSpawner.js create mode 100644 examples/flowArts/raveStick/createRaveStick.js diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index d3c60548ea..c8f7dbed78 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -14,11 +14,11 @@ Script.include("../../libraries/utils.js"); -Script.include("lightBall/lightBallSpawner.js"); +Script.include("lightBall/LightBall.js"); var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); basePosition.y = MyAvatar.position.y + 1 -var lightBall = LightBallSpawner(basePosition); +var lightBall = LightBall(basePosition); var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); var roomDimensions = {x: 30.58, y: 15.29, z: 30.58}; @@ -62,10 +62,6 @@ var lightZone = Entities.addEntity({ }); - - - - function cleanup() { Entities.deleteEntity(raveRoom); diff --git a/examples/flowArts/lightBall/lightBall.js b/examples/flowArts/lightBall/lightBall.js index e69de29bb2..6f44ed6d74 100644 --- a/examples/flowArts/lightBall/lightBall.js +++ b/examples/flowArts/lightBall/lightBall.js @@ -0,0 +1,124 @@ + Script.include("../../libraries/utils.js"); + + LightBall = function(basePosition) { + + var colorPalette = [{ + red: 25, + green: 20, + blue: 162 + }]; + + + var containerBall = Entities.addEntity({ + type: "Sphere", + position: Vec3.sum(basePosition, { + x: 0, + y: .5, + z: 0 + }), + dimensions: { + x: .1, + y: .1, + z: .1 + }, + color: { + red: 15, + green: 10, + blue: 150 + }, + collisionsWillMove: true, + userData: JSON.stringify({ + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 1, + z: 0 + } + }, + invertSolidWhileHeld: true + } + }) + }); + + + var light = Entities.addEntity({ + type: 'Light', + parentID: containerBall, + dimensions: { + x: 30, + y: 30, + z: 30 + }, + color: colorPalette[randInt(0, colorPalette.length)], + intensity: 5 + }); + + + var lightBall = Entities.addEntity({ + type: "ParticleEffect", + parentID: containerBall, + isEmitting: true, + "name": "ParticlesTest Emitter", + "colorStart": { + red: 200, + green: 20, + blue: 40 + }, + color: { + red: 200, + green: 200, + blue: 255 + }, + "colorFinish": { + red: 25, + green: 20, + blue: 255 + }, + "maxParticles": 100000, + "lifespan": 5, + "emitRate": 5000, + "emitSpeed": .1, + "speedSpread": 0.0, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "polarStart": 0, + "polarFinish": Math.PI, + "azimuthStart": -Math.PI, + "azimuthFinish": Math.PI, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": .00, + "y": .00, + "z": .00 + }, + "particleRadius": 0.04, + "radiusSpread": 0, + "radiusStart": 0.05, + "radiusFinish": 0.0003, + "alpha": 0, + "alphaSpread": .5, + "alphaStart": 0, + "alphaFinish": 0.5, + // "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + "textures": "file:///C:/Users/Eric/Desktop/Particle-Sprite-Smoke-1.png?v1" + Math.random(), + emitterShouldTrail: true + }) + + + + function cleanup() { + Entities.deleteEntity(lightBall); + Entities.deleteEntity(containerBall); + Entities.deleteEntity(light); + } + + this.cleanup = cleanup; + } \ No newline at end of file diff --git a/examples/flowArts/lightBall/lightBallSpawner.js b/examples/flowArts/lightBall/lightBallSpawner.js deleted file mode 100644 index 7325f16a64..0000000000 --- a/examples/flowArts/lightBall/lightBallSpawner.js +++ /dev/null @@ -1,124 +0,0 @@ - Script.include("../../libraries/utils.js"); - - LightBallSpawner = function(basePosition) { - - var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); - var colorPalette = [{ - red: 25, - green: 20, - blue: 162 - }]; - - - var containerBall = Entities.addEntity({ - type: "Sphere", - position: Vec3.sum(basePosition, { - x: 0, - y: .5, - z: 0 - }), - dimensions: { - x: .1, - y: .1, - z: .1 - }, - color: { - red: 15, - green: 10, - blue: 150 - }, - collisionsWillMove: true, - userData: JSON.stringify({ - grabbableKey: { - spatialKey: { - relativePosition: { - x: 0, - y: 1, - z: 0 - } - }, - invertSolidWhileHeld: true - } - }) - }); - - - var light = Entities.addEntity({ - type: 'Light', - parentID: containerBall, - dimensions: { - x: 30, - y: 30, - z: 30 - }, - color: colorPalette[randInt(0, colorPalette.length)], - intensity: 5 - }); - - - var lightBall = Entities.addEntity({ - type: "ParticleEffect", - parentID: containerBall, - isEmitting: true, - "name": "ParticlesTest Emitter", - "colorStart": { - red: 200, - green: 20, - blue: 40 - }, - color: { - red: 200, - green: 200, - blue: 255 - }, - "colorFinish": { - red: 25, - green: 20, - blue: 255 - }, - "maxParticles": 100000, - "lifespan": 5, - "emitRate": 5000, - "emitSpeed": .1, - "speedSpread": 0.0, - "emitDimensions": { - "x": 0, - "y": 0, - "z": 0 - }, - "polarStart": 0, - "polarFinish": Math.PI, - "azimuthStart": -Math.PI, - "azimuthFinish": Math.PI, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 - }, - "accelerationSpread": { - "x": .00, - "y": .00, - "z": .00 - }, - "particleRadius": 0.04, - "radiusSpread": 0, - "radiusStart": 0.05, - "radiusFinish": 0.0003, - "alpha": 0, - "alphaSpread": .5, - "alphaStart": 0, - "alphaFinish": 0.5, - "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - emitterShouldTrail: true - }) - - - - function cleanup() { - Entities.deleteEntity(lightBall); - Entities.deleteEntity(containerBall); - Entities.deleteEntity(light); - } - - this.cleanup = cleanup; - } \ No newline at end of file diff --git a/examples/flowArts/raveStick/createRaveStick.js b/examples/flowArts/raveStick/createRaveStick.js new file mode 100644 index 0000000000..e69de29bb2 From 45e31ca4422359e6af92ba257fdb20bbaa1469b6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 16 Dec 2015 15:35:23 -0800 Subject: [PATCH 070/195] fix warning about unused variable --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f8040754d7..6094a0b9fe 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -157,7 +157,7 @@ void Avatar::animateScaleChanges(float deltaTime) { // snap to the end when we get close enough const float MIN_RELATIVE_SCALE_ERROR = 0.03f; - if (fabsf(_targetScale - currentScale) / _targetScale < 0.03f) { + if (fabsf(_targetScale - currentScale) / _targetScale < MIN_RELATIVE_SCALE_ERROR) { animatedScale = _targetScale; } From 6a77ae5db2cbead0c901ca40e788a73929ad8bc5 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 16 Dec 2015 15:47:34 -0800 Subject: [PATCH 071/195] adding rave stick --- examples/flowArts/flowArtsHutSpawner.js | 9 +- examples/flowArts/lightBall/lightBall.js | 232 +++++++++--------- examples/flowArts/raveStick/RaveStick.js | 24 ++ .../flowArts/raveStick/createRaveStick.js | 0 4 files changed, 145 insertions(+), 120 deletions(-) create mode 100644 examples/flowArts/raveStick/RaveStick.js delete mode 100644 examples/flowArts/raveStick/createRaveStick.js diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index c8f7dbed78..ffd73dbdca 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -15,10 +15,12 @@ Script.include("../../libraries/utils.js"); Script.include("lightBall/LightBall.js"); +Script.include("raveStick/RaveStick.js"); var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); -basePosition.y = MyAvatar.position.y + 1 -var lightBall = LightBall(basePosition); +basePosition.y = MyAvatar.position.y + 1; +var lightBall = new LightBall(basePosition); +var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 1, z: 1})); var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); var roomDimensions = {x: 30.58, y: 15.29, z: 30.58}; @@ -41,8 +43,6 @@ var floor = Entities.addEntity({ - - var lightZone = Entities.addEntity({ type: "Zone", shapeType: 'box', @@ -68,6 +68,7 @@ function cleanup() { Entities.deleteEntity(lightZone) Entities.deleteEntity(floor); lightBall.cleanup(); + raveStick.cleanup(); } Script.scriptEnding.connect(cleanup); \ No newline at end of file diff --git a/examples/flowArts/lightBall/lightBall.js b/examples/flowArts/lightBall/lightBall.js index 6f44ed6d74..e2d65874fa 100644 --- a/examples/flowArts/lightBall/lightBall.js +++ b/examples/flowArts/lightBall/lightBall.js @@ -1,124 +1,124 @@ - Script.include("../../libraries/utils.js"); +Script.include("../../libraries/utils.js"); - LightBall = function(basePosition) { +LightBall = function(spawnPosition) { - var colorPalette = [{ + var colorPalette = [{ + red: 25, + green: 20, + blue: 162 + }]; + + + var containerBall = Entities.addEntity({ + type: "Sphere", + position: Vec3.sum(spawnPosition, { + x: 0, + y: .5, + z: 0 + }), + dimensions: { + x: .1, + y: .1, + z: .1 + }, + color: { + red: 15, + green: 10, + blue: 150 + }, + collisionsWillMove: true, + userData: JSON.stringify({ + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: .7, + z: 0 + } + }, + invertSolidWhileHeld: true + } + }) + }); + + + var light = Entities.addEntity({ + type: 'Light', + parentID: containerBall, + dimensions: { + x: 30, + y: 30, + z: 30 + }, + color: colorPalette[randInt(0, colorPalette.length)], + intensity: 5 + }); + + + var lightBall = Entities.addEntity({ + type: "ParticleEffect", + parentID: containerBall, + isEmitting: true, + "name": "ParticlesTest Emitter", + "colorStart": { + red: 200, + green: 20, + blue: 40 + }, + color: { + red: 200, + green: 200, + blue: 255 + }, + "colorFinish": { red: 25, green: 20, - blue: 162 - }]; - - - var containerBall = Entities.addEntity({ - type: "Sphere", - position: Vec3.sum(basePosition, { - x: 0, - y: .5, - z: 0 - }), - dimensions: { - x: .1, - y: .1, - z: .1 - }, - color: { - red: 15, - green: 10, - blue: 150 - }, - collisionsWillMove: true, - userData: JSON.stringify({ - grabbableKey: { - spatialKey: { - relativePosition: { - x: 0, - y: 1, - z: 0 - } - }, - invertSolidWhileHeld: true - } - }) - }); - - - var light = Entities.addEntity({ - type: 'Light', - parentID: containerBall, - dimensions: { - x: 30, - y: 30, - z: 30 - }, - color: colorPalette[randInt(0, colorPalette.length)], - intensity: 5 - }); - - - var lightBall = Entities.addEntity({ - type: "ParticleEffect", - parentID: containerBall, - isEmitting: true, - "name": "ParticlesTest Emitter", - "colorStart": { - red: 200, - green: 20, - blue: 40 - }, - color: { - red: 200, - green: 200, - blue: 255 - }, - "colorFinish": { - red: 25, - green: 20, - blue: 255 - }, - "maxParticles": 100000, - "lifespan": 5, - "emitRate": 5000, - "emitSpeed": .1, - "speedSpread": 0.0, - "emitDimensions": { - "x": 0, - "y": 0, - "z": 0 - }, - "polarStart": 0, - "polarFinish": Math.PI, - "azimuthStart": -Math.PI, - "azimuthFinish": Math.PI, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 - }, - "accelerationSpread": { - "x": .00, - "y": .00, - "z": .00 - }, - "particleRadius": 0.04, - "radiusSpread": 0, - "radiusStart": 0.05, - "radiusFinish": 0.0003, - "alpha": 0, - "alphaSpread": .5, - "alphaStart": 0, - "alphaFinish": 0.5, - // "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - "textures": "file:///C:/Users/Eric/Desktop/Particle-Sprite-Smoke-1.png?v1" + Math.random(), - emitterShouldTrail: true - }) + blue: 255 + }, + "maxParticles": 100000, + "lifespan": 2, + "emitRate": 10000, + "emitSpeed": .1, + "speedSpread": 0.0, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "polarStart": 0, + "polarFinish": Math.PI, + "azimuthStart": -Math.PI, + "azimuthFinish": Math.PI, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": .00, + "y": .00, + "z": .00 + }, + "particleRadius": 0.02, + "radiusSpread": 0, + "radiusStart": 0.03, + "radiusFinish": 0.0003, + "alpha": 0, + "alphaSpread": .5, + "alphaStart": 0, + "alphaFinish": 0.5, + // "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + "textures": "file:///C:/Users/Eric/Desktop/Particle-Sprite-Smoke-1.png?v1" + Math.random(), + emitterShouldTrail: true + }) - function cleanup() { - Entities.deleteEntity(lightBall); - Entities.deleteEntity(containerBall); - Entities.deleteEntity(light); - } + function cleanup() { + Entities.deleteEntity(lightBall); + Entities.deleteEntity(containerBall); + Entities.deleteEntity(light); + } - this.cleanup = cleanup; - } \ No newline at end of file + this.cleanup = cleanup; +} \ No newline at end of file diff --git a/examples/flowArts/raveStick/RaveStick.js b/examples/flowArts/raveStick/RaveStick.js new file mode 100644 index 0000000000..2703436bec --- /dev/null +++ b/examples/flowArts/raveStick/RaveStick.js @@ -0,0 +1,24 @@ +Script.include("../../libraries/utils.js"); +var modelURL = "file:///C:/Users/Eric/Desktop/raveStick.fbx?v1" + Math.random(); + +RaveStick = function(spawnPosition) { + + var stick = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: spawnPosition, + shapeType: 'box', + userData: JSON.stringify({ + grabbableKey: { + invertSolidWhileHeld: true + } + }) + }); + + + function cleanup() { + Entities.deleteEntity(stick); + } + + this.cleanup = cleanup; +} \ No newline at end of file diff --git a/examples/flowArts/raveStick/createRaveStick.js b/examples/flowArts/raveStick/createRaveStick.js deleted file mode 100644 index e69de29bb2..0000000000 From 263557cc1ac008e5ae98ed1c5ea977cc20aae6fa Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 16 Dec 2015 16:18:57 -0800 Subject: [PATCH 072/195] setting dimensions for rave stick --- examples/flowArts/lightBall/lightBall.js | 3 ++- examples/flowArts/raveStick/RaveStick.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/flowArts/lightBall/lightBall.js b/examples/flowArts/lightBall/lightBall.js index e2d65874fa..698c62a71d 100644 --- a/examples/flowArts/lightBall/lightBall.js +++ b/examples/flowArts/lightBall/lightBall.js @@ -27,12 +27,13 @@ LightBall = function(spawnPosition) { blue: 150 }, collisionsWillMove: true, + gravity: {x: 0, y: -.5, z: 0}, userData: JSON.stringify({ grabbableKey: { spatialKey: { relativePosition: { x: 0, - y: .7, + y: .1, z: 0 } }, diff --git a/examples/flowArts/raveStick/RaveStick.js b/examples/flowArts/raveStick/RaveStick.js index 2703436bec..bee5c995f9 100644 --- a/examples/flowArts/raveStick/RaveStick.js +++ b/examples/flowArts/raveStick/RaveStick.js @@ -8,6 +8,7 @@ RaveStick = function(spawnPosition) { modelURL: modelURL, position: spawnPosition, shapeType: 'box', + dimensions: {x: 0.17, y: 0.48, z: 0.17}, userData: JSON.stringify({ grabbableKey: { invertSolidWhileHeld: true From 1b1365fd403bb661e39606df0d2d5930611b7127 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 16 Dec 2015 16:32:53 -0800 Subject: [PATCH 073/195] Exposing the tone curve in the js api --- interface/src/Application.cpp | 1 + .../render-utils/src/RenderDeferredTask.cpp | 18 ++++++++++++- .../render-utils/src/RenderDeferredTask.h | 3 +++ libraries/render/src/render/Engine.h | 1 + .../src/SceneScriptingInterface.cpp | 27 +++++++++++++++++++ .../src/SceneScriptingInterface.h | 7 ++++- 6 files changed, 55 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9a8373282b..aa0c0fa8c6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3703,6 +3703,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._fxaaStatus = Menu::getInstance()->isOptionChecked(MenuOption::Antialiasing); renderContext._toneMappingExposure = sceneInterface->getEngineToneMappingExposure(); + renderContext._toneMappingToneCurve = sceneInterface->getEngineToneMappingToneCurveValue(); renderArgs->_shouldRender = LODManager::shouldRender; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ef95876f11..5423d928a7 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -166,6 +166,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend setAntialiasingStatus(renderContext->_fxaaStatus); setToneMappingExposure(renderContext->_toneMappingExposure); + setToneMappingToneCurve(renderContext->_toneMappingToneCurve); renderContext->args->_context->syncCache(); @@ -403,8 +404,23 @@ void RenderDeferredTask::setToneMappingExposure(float exposure) { float RenderDeferredTask::getToneMappingExposure() const { if (_toneMappingJobIndex >= 0) { - _jobs[_toneMappingJobIndex].get()._toneMappingEffect.getExposure(); + return _jobs[_toneMappingJobIndex].get()._toneMappingEffect.getExposure(); } else { return 0.0f; } } + +void RenderDeferredTask::setToneMappingToneCurve(int toneCurve) { + if (_toneMappingJobIndex >= 0) { + _jobs[_toneMappingJobIndex].edit()._toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)toneCurve); + } +} + +int RenderDeferredTask::getToneMappingToneCurve() const { + if (_toneMappingJobIndex >= 0) { + return _jobs[_toneMappingJobIndex].get()._toneMappingEffect.getToneCurve(); + } else { + return 0.0f; + } +} + diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index ea99c9f12e..b84db31a26 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -134,6 +134,9 @@ public: void setToneMappingExposure(float exposure); float getToneMappingExposure() const; + void setToneMappingToneCurve(int toneCurve); + int getToneMappingToneCurve() const; + virtual void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index c219b87f40..abfef03039 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -62,6 +62,7 @@ public: bool _fxaaStatus = false; float _toneMappingExposure = 0.0; + int _toneMappingToneCurve = 3; RenderContext() {} }; diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp index 59d2765659..3e22a9e929 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.cpp +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -167,3 +167,30 @@ void SceneScriptingInterface::clearEngineCounters() { _numFeedOverlay3DItems = 0; _numDrawnOverlay3DItems = 0; } + + +void SceneScriptingInterface::setEngineToneMappingToneCurve(const QString& toneCurve) { + if (toneCurve == QString("None")) { + _engineToneMappingToneCurve = 0; + } else if (toneCurve == QString("Gamma22")) { + _engineToneMappingToneCurve = 1; + } else if (toneCurve == QString("Reinhard")) { + _engineToneMappingToneCurve = 2; + } else if (toneCurve == QString("Filmic")) { + _engineToneMappingToneCurve = 3; + } +} +QString SceneScriptingInterface::getEngineToneMappingToneCurve() const { + switch (_engineToneMappingToneCurve) { + case 0: + return QString("None"); + case 1: + return QString("Gamma22"); + case 2: + return QString("Reinhard"); + case 3: + return QString("Filmic"); + default: + return QString("Filmic"); + }; +} \ No newline at end of file diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 875a2a1b8f..246f624b08 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -119,7 +119,11 @@ public: Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; } Q_INVOKABLE void setEngineToneMappingExposure(float exposure) { _engineToneMappingExposure = exposure; } - Q_INVOKABLE float getEngineToneMappingExposure() { return _engineToneMappingExposure; } + Q_INVOKABLE float getEngineToneMappingExposure() const { return _engineToneMappingExposure; } + + Q_INVOKABLE void setEngineToneMappingToneCurve(const QString& curve); + Q_INVOKABLE QString getEngineToneMappingToneCurve() const; + int getEngineToneMappingToneCurveValue() const { return _engineToneMappingToneCurve; } signals: void shouldRenderAvatarsChanged(bool shouldRenderAvatars); @@ -158,6 +162,7 @@ protected: bool _drawHitEffect = false; float _engineToneMappingExposure = 0.0f; + int _engineToneMappingToneCurve = 3; }; #endif // hifi_SceneScriptingInterface_h From d8c877831664a37949932217b75be6937236c468 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 16 Dec 2015 16:50:27 -0800 Subject: [PATCH 074/195] rave stick in right orientation --- examples/flowArts/flowArtsHutSpawner.js | 6 +- examples/flowArts/raveStick/RaveStick.js | 16 +++- .../raveStick/raveStickEntityScript.js | 81 +++++++++++++++++++ 3 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 examples/flowArts/raveStick/raveStickEntityScript.js diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index ffd73dbdca..8e39a4b1d8 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -19,8 +19,12 @@ Script.include("raveStick/RaveStick.js"); var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); basePosition.y = MyAvatar.position.y + 1; + +// RAVE ITEMS var lightBall = new LightBall(basePosition); -var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 1, z: 1})); +var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 0.5, z: 1})); + + var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); var roomDimensions = {x: 30.58, y: 15.29, z: 30.58}; diff --git a/examples/flowArts/raveStick/RaveStick.js b/examples/flowArts/raveStick/RaveStick.js index bee5c995f9..046932c473 100644 --- a/examples/flowArts/raveStick/RaveStick.js +++ b/examples/flowArts/raveStick/RaveStick.js @@ -1,6 +1,6 @@ Script.include("../../libraries/utils.js"); var modelURL = "file:///C:/Users/Eric/Desktop/raveStick.fbx?v1" + Math.random(); - +var scriptURL = Script.resolvePath("raveStickEntityScript.js"); RaveStick = function(spawnPosition) { var stick = Entities.addEntity({ @@ -8,9 +8,21 @@ RaveStick = function(spawnPosition) { modelURL: modelURL, position: spawnPosition, shapeType: 'box', - dimensions: {x: 0.17, y: 0.48, z: 0.17}, + dimensions: { + x: 0.06, + y: 0.06, + z: 0.8 + }, userData: JSON.stringify({ grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 0, + z: -0.4 + }, + relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0) + }, invertSolidWhileHeld: true } }) diff --git a/examples/flowArts/raveStick/raveStickEntityScript.js b/examples/flowArts/raveStick/raveStickEntityScript.js new file mode 100644 index 0000000000..cfe1e3a2fd --- /dev/null +++ b/examples/flowArts/raveStick/raveStickEntityScript.js @@ -0,0 +1,81 @@ +// raveStickEntityScript.js +// +// Script Type: Entity +// Created by Eric Levin on 9/21/15. +// Additions by James B. Pollack @imgntn on 9/24/15 +// Copyright 2015 High Fidelity, Inc. +// +// This entity script create light trails on a given object as it moves. +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + Script.include("../../libraries/utils.js"); + var _this; + // this is the "constructor" for the entity as a JS object we don't do much here + var Doll = function() { + _this = this; + this.screamSounds = [SoundCache.getSound("https://hifi-public.s3.amazonaws.com/sounds/KenDoll_1%2303.wav")]; + }; + + Doll.prototype = { + audioInjector: null, + isGrabbed: false, + setLeftHand: function() { + this.hand = 'left'; + }, + + setRightHand: function() { + this.hand = 'right'; + }, + + startNearGrab: function() { + Entities.editEntity(this.entityID, { + animation: { + url: "https://hifi-public.s3.amazonaws.com/models/Bboys/zombie_scream.fbx", + running: true + } + }); + + var position = Entities.getEntityProperties(this.entityID, "position").position; + this.audioInjector = Audio.playSound(this.screamSounds[randInt(0, this.screamSounds.length)], { + position: position, + volume: 0.1 + }); + + this.isGrabbed = true; + this.initialHand = this.hand; + }, + + continueNearGrab: function() { + var props = Entities.getEntityProperties(this.entityID, ["position"]); + var audioOptions = { + position: props.position + }; + this.audioInjector.options = audioOptions; + }, + + releaseGrab: function() { + if (this.isGrabbed === true && this.hand === this.initialHand) { + this.audioInjector.stop(); + Entities.editEntity(this.entityID, { + animation: { + // Providing actual model fbx for animation used to work, now contorts doll into a weird ball + // See bug: https://app.asana.com/0/26225263936266/70097355490098 + // url: "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx", + running: false, + } + }); + + this.isGrabbed = false; + } + }, + + preload: function(entityID) { + this.entityID = entityID; + }, + }; + // entity scripts always need to return a newly constructed object of our type + return new Doll(); +}); From f9f496ef5ab2d0e65e9d20500fb6f6fe521492d2 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 16 Dec 2015 17:32:30 -0800 Subject: [PATCH 075/195] adding beam effect --- examples/flowArts/flowArtsHutSpawner.js | 2 +- examples/flowArts/raveStick/RaveStick.js | 5 +- .../raveStick/raveStickEntityScript.js | 128 +++++++++++------- 3 files changed, 85 insertions(+), 50 deletions(-) diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index 8e39a4b1d8..aa87ddbd10 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -50,7 +50,7 @@ var floor = Entities.addEntity({ var lightZone = Entities.addEntity({ type: "Zone", shapeType: 'box', - keyLightIntensity: 0.2, + keyLightIntensity: 0.4, keyLightColor: { red: 50, green: 0, diff --git a/examples/flowArts/raveStick/RaveStick.js b/examples/flowArts/raveStick/RaveStick.js index 046932c473..5151b528cc 100644 --- a/examples/flowArts/raveStick/RaveStick.js +++ b/examples/flowArts/raveStick/RaveStick.js @@ -8,10 +8,11 @@ RaveStick = function(spawnPosition) { modelURL: modelURL, position: spawnPosition, shapeType: 'box', + script: scriptURL, dimensions: { x: 0.06, y: 0.06, - z: 0.8 + z: 0.31 }, userData: JSON.stringify({ grabbableKey: { @@ -19,7 +20,7 @@ RaveStick = function(spawnPosition) { relativePosition: { x: 0, y: 0, - z: -0.4 + z: -0.1 }, relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0) }, diff --git a/examples/flowArts/raveStick/raveStickEntityScript.js b/examples/flowArts/raveStick/raveStickEntityScript.js index cfe1e3a2fd..67571e49fa 100644 --- a/examples/flowArts/raveStick/raveStickEntityScript.js +++ b/examples/flowArts/raveStick/raveStickEntityScript.js @@ -1,8 +1,7 @@ // raveStickEntityScript.js // // Script Type: Entity -// Created by Eric Levin on 9/21/15. -// Additions by James B. Pollack @imgntn on 9/24/15 +// Created by Eric Levin on 12/16/15. // Copyright 2015 High Fidelity, Inc. // // This entity script create light trails on a given object as it moves. @@ -14,68 +13,103 @@ Script.include("../../libraries/utils.js"); var _this; // this is the "constructor" for the entity as a JS object we don't do much here - var Doll = function() { + var RaveStick = function() { _this = this; - this.screamSounds = [SoundCache.getSound("https://hifi-public.s3.amazonaws.com/sounds/KenDoll_1%2303.wav")]; }; - Doll.prototype = { - audioInjector: null, + RaveStick.prototype = { isGrabbed: false, - setLeftHand: function() { - this.hand = 'left'; - }, - - setRightHand: function() { - this.hand = 'right'; - }, startNearGrab: function() { - Entities.editEntity(this.entityID, { - animation: { - url: "https://hifi-public.s3.amazonaws.com/models/Bboys/zombie_scream.fbx", - running: true - } - }); - - var position = Entities.getEntityProperties(this.entityID, "position").position; - this.audioInjector = Audio.playSound(this.screamSounds[randInt(0, this.screamSounds.length)], { - position: position, - volume: 0.1 - }); - - this.isGrabbed = true; - this.initialHand = this.hand; + // this.createBeam(); }, continueNearGrab: function() { - var props = Entities.getEntityProperties(this.entityID, ["position"]); - var audioOptions = { - position: props.position - }; - this.audioInjector.options = audioOptions; + }, releaseGrab: function() { - if (this.isGrabbed === true && this.hand === this.initialHand) { - this.audioInjector.stop(); - Entities.editEntity(this.entityID, { - animation: { - // Providing actual model fbx for animation used to work, now contorts doll into a weird ball - // See bug: https://app.asana.com/0/26225263936266/70097355490098 - // url: "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx", - running: false, - } - }); - this.isGrabbed = false; - } }, preload: function(entityID) { this.entityID = entityID; + this.createBeam(); }, + + unload: function() { + Entities.deleteEntity(this.beam); + }, + + createBeam: function() { + + var props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); + var forwardVec = Quat.getFront(Quat.multiply(props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); + forwardVec = Vec3.normalize(forwardVec); + var forwardQuat = orientationOf(forwardVec); + var position = Vec3.sum(props.position, Vec3.multiply(Quat.getFront(props.rotation), 0.1)); + position.z += 0.1; + position.x += -0.035; + var props = { + type: "ParticleEffect", + position: position, + parentID: this.entityID, + isEmitting: true, + "name": "ParticlesTest Emitter", + "colorStart": { + red: 0, + green: 200, + blue: 40 + }, + color: { + red: 200, + green: 200, + blue: 255 + }, + "colorFinish": { + red: 25, + green: 200, + blue: 5 + }, + "maxParticles": 100000, + "lifespan": 2, + "emitRate": 1000, + emitOrientation: forwardQuat, + "emitSpeed": .4, + "speedSpread": 0.0, + // "emitDimensions": { + // "x": .1, + // "y": .1, + // "z": .1 + // }, + "polarStart": 0, + "polarFinish": .0, + "azimuthStart": .1, + "azimuthFinish": .01, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": .00, + "y": .00, + "z": .00 + }, + "radiusStart": 0.03, + radiusFinish: 0.025, + "alpha": 0.7, + "alphaSpread": .1, + "alphaStart": 0.5, + "alphaFinish": 0.5, + // "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + "textures": "file:///C:/Users/Eric/Desktop/beamParticle.png?v1" + Math.random(), + emitterShouldTrail: false + } + this.beam = Entities.addEntity(props); + + } }; // entity scripts always need to return a newly constructed object of our type - return new Doll(); -}); + return new RaveStick(); +}); \ No newline at end of file From bb67ca87e238a4db2b613e15c3de787d93544955 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 16 Dec 2015 17:52:39 -0800 Subject: [PATCH 076/195] lightsabers --- examples/flowArts/flowArtsHutSpawner.js | 2 ++ .../raveStick/raveStickEntityScript.js | 26 ++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index aa87ddbd10..b9d89859df 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -23,6 +23,7 @@ basePosition.y = MyAvatar.position.y + 1; // RAVE ITEMS var lightBall = new LightBall(basePosition); var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 0.5, z: 1})); +var raveStick2 = new RaveStick(Vec3.sum(basePosition, {x: 2, y: 0.5, z: 1})); var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); @@ -73,6 +74,7 @@ function cleanup() { Entities.deleteEntity(floor); lightBall.cleanup(); raveStick.cleanup(); + raveStick2.cleanup(); } Script.scriptEnding.connect(cleanup); \ No newline at end of file diff --git a/examples/flowArts/raveStick/raveStickEntityScript.js b/examples/flowArts/raveStick/raveStickEntityScript.js index 67571e49fa..0372fd388f 100644 --- a/examples/flowArts/raveStick/raveStickEntityScript.js +++ b/examples/flowArts/raveStick/raveStickEntityScript.js @@ -15,6 +15,15 @@ // this is the "constructor" for the entity as a JS object we don't do much here var RaveStick = function() { _this = this; + this.colorPalette = [{ + red: 0, + green: 200, + blue: 40 + }, { + red: 200, + green: 10, + blue: 40 + }]; }; RaveStick.prototype = { @@ -39,6 +48,7 @@ unload: function() { Entities.deleteEntity(this.beam); + // Entities.deleteEntity(this.beamTrail); }, createBeam: function() { @@ -50,27 +60,20 @@ var position = Vec3.sum(props.position, Vec3.multiply(Quat.getFront(props.rotation), 0.1)); position.z += 0.1; position.x += -0.035; + var color = this.colorPalette[randInt(0, this.colorPalette.length)]; var props = { type: "ParticleEffect", position: position, parentID: this.entityID, isEmitting: true, "name": "ParticlesTest Emitter", - "colorStart": { - red: 0, - green: 200, - blue: 40 - }, + "colorStart": color, color: { red: 200, green: 200, blue: 255 }, - "colorFinish": { - red: 25, - green: 200, - blue: 5 - }, + "colorFinish": color, "maxParticles": 100000, "lifespan": 2, "emitRate": 1000, @@ -108,6 +111,9 @@ } this.beam = Entities.addEntity(props); + // props.emitterShouldTrail = true; + // this.beamTrail = Entities.addEntity(props); + } }; // entity scripts always need to return a newly constructed object of our type From 7bc815448e025d677c94a750fb6c184ca9fe94c6 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 16 Dec 2015 18:14:43 -0800 Subject: [PATCH 077/195] The material colors for diffuse and emissive are now gamma corrected by default --- libraries/model/src/model/Material.cpp | 8 ++++---- libraries/model/src/model/Material.h | 27 ++++++++++++++------------ libraries/shared/src/ColorUtils.h | 16 +++++++++++++++ 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index c2ff828af3..1d0f6ee5d9 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -44,9 +44,9 @@ Material& Material::operator= (const Material& material) { Material::~Material() { } -void Material::setDiffuse(const Color& diffuse) { +void Material::setDiffuse(const Color& diffuse, bool isSRGB) { _key.setDiffuse(glm::any(glm::greaterThan(diffuse, Color(0.0f)))); - _schemaBuffer.edit()._diffuse = diffuse; + _schemaBuffer.edit()._diffuse = (isSRGB ? ColorUtils::toLinearVec3(diffuse) : diffuse); } void Material::setMetallic(float metallic) { @@ -54,9 +54,9 @@ void Material::setMetallic(float metallic) { _schemaBuffer.edit()._metallic = glm::vec3(metallic); } -void Material::setEmissive(const Color& emissive) { +void Material::setEmissive(const Color& emissive, bool isSRGB) { _key.setEmissive(glm::any(glm::greaterThan(emissive, Color(0.0f)))); - _schemaBuffer.edit()._emissive = emissive; + _schemaBuffer.edit()._emissive = (isSRGB ? ColorUtils::toLinearVec3(emissive) : emissive); } void Material::setGloss(float gloss) { diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index b0725d9908..bd1d45c7ed 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -14,7 +14,7 @@ #include #include -#include +#include #include @@ -219,28 +219,31 @@ public: virtual ~Material(); const MaterialKey& getKey() const { return _key; } - - const Color& getEmissive() const { return _schemaBuffer.get()._emissive; } - const Color& getDiffuse() const { return _schemaBuffer.get()._diffuse; } - float getMetallic() const { return _schemaBuffer.get()._metallic.x; } - float getGloss() const { return _schemaBuffer.get()._gloss; } - float getOpacity() const { return _schemaBuffer.get()._opacity; } - void setEmissive(const Color& emissive); - void setDiffuse(const Color& diffuse); + void setEmissive(const Color& emissive, bool isSRGB = true); + const Color& getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._emissive) : _schemaBuffer.get()._emissive); } + + void setDiffuse(const Color& diffuse, bool isSRGB = true); + const Color& getDiffuse(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._diffuse) : _schemaBuffer.get()._diffuse); } + void setMetallic(float metallic); + float getMetallic() const { return _schemaBuffer.get()._metallic.x; } + void setGloss(float gloss); + float getGloss() const { return _schemaBuffer.get()._gloss; } + void setOpacity(float opacity); + float getOpacity() const { return _schemaBuffer.get()._opacity; } // Schema to access the attribute values of the material class Schema { public: - Color _diffuse{0.5f}; + glm::vec3 _diffuse{ 0.5f }; float _opacity{1.f}; - Color _metallic{0.03f}; + glm::vec3 _metallic{ 0.03f }; float _gloss{0.1f}; - Color _emissive{0.0f}; + glm::vec3 _emissive{ 0.0f }; float _spare0{0.0f}; glm::vec4 _spareVec4{0.0f}; // for alignment beauty, Material size == Mat4x4 diff --git a/libraries/shared/src/ColorUtils.h b/libraries/shared/src/ColorUtils.h index 1ef8420cd7..b47e7c3a98 100644 --- a/libraries/shared/src/ColorUtils.h +++ b/libraries/shared/src/ColorUtils.h @@ -20,6 +20,10 @@ class ColorUtils { public: inline static glm::vec3 toVec3(const xColor& color); + + // Convert from gamma 2.2 space to linear + inline static glm::vec3 toLinearVec3(const glm::vec3& srgb); + inline static glm::vec3 toGamma22Vec3(const glm::vec3& linear); }; inline glm::vec3 ColorUtils::toVec3(const xColor& color) { @@ -27,4 +31,16 @@ inline glm::vec3 ColorUtils::toVec3(const xColor& color) { return glm::vec3(color.red * ONE_OVER_255, color.green * ONE_OVER_255, color.blue * ONE_OVER_255); } +inline glm::vec3 ColorUtils::toLinearVec3(const glm::vec3& srgb) { + const float GAMMA_22 = 2.2f; + // Couldn't find glm::pow(vec3, vec3) ? so did it myself... + return glm::vec3(glm::pow(srgb.x, GAMMA_22), glm::pow(srgb.y, GAMMA_22), glm::pow(srgb.z, GAMMA_22)); +} + +inline glm::vec3 ColorUtils::toGamma22Vec3(const glm::vec3& linear) { + const float INV_GAMMA_22 = 1.0f / 2.2f; + // Couldn't find glm::pow(vec3, vec3) ? so did it myself... + return glm::vec3(glm::pow(linear.x, INV_GAMMA_22), glm::pow(linear.y, INV_GAMMA_22), glm::pow(linear.z, INV_GAMMA_22)); +} + #endif // hifi_ColorUtils_h \ No newline at end of file From 0b9bd858a7c1fedecca7b32190155b5038ba6491 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 16 Dec 2015 21:28:27 -0800 Subject: [PATCH 078/195] implement support for pose ScriptEndpoints --- examples/controllers/reticleTests.js | 42 +++++++++++++++++ .../controllers/src/controllers/Pose.cpp | 18 +++++++- .../impl/endpoints/ScriptEndpoint.cpp | 46 ++++++++++++++++++- .../impl/endpoints/ScriptEndpoint.h | 13 ++++++ 4 files changed, 117 insertions(+), 2 deletions(-) diff --git a/examples/controllers/reticleTests.js b/examples/controllers/reticleTests.js index 4c805c8b1c..3392d1b7d9 100644 --- a/examples/controllers/reticleTests.js +++ b/examples/controllers/reticleTests.js @@ -34,6 +34,48 @@ var mappingJSON = { mapping = Controller.parseMapping(JSON.stringify(mappingJSON)); mapping.enable(); + +var MAPPING_NAME = "com.highfidelity.testing.reticleWithHand"; +var mapping2 = Controller.newMapping(MAPPING_NAME); +//mapping2.from(Controller.Standard.RightHand).debug(true).to(Controller.Actions.LeftHand); + +/* +mapping2.from(Controller.Standard.RightHand).peek().to(function(pose) { + print("Controller.Standard.RightHand value:" + JSON.stringify(pose)); + }); +*/ + +var translation = { x: 0, y: 0.1, z: 0 }; +var translationDx = 0.01; +var translationDy = 0.01; +var translationDz = 0.01; +var TRANSLATION_LIMIT = 0.5; +var rotation = Quat.fromPitchYawRollDegrees(45, 0, 45); +mapping2.from(function() { + translation.x = translation.x + translationDx; + translation.y = translation.y + translationDy; + translation.z = translation.z + translationDz; + if ((translation.x > TRANSLATION_LIMIT) || (translation.x < (-1 *TRANSLATION_LIMIT))) { + translationDx = translationDx * -1; + } + if ((translation.y > TRANSLATION_LIMIT) || (translation.y < (-1 *TRANSLATION_LIMIT))) { + translationDy = translationDy * -1; + } + if ((translation.z > TRANSLATION_LIMIT) || (translation.z < (-1 *TRANSLATION_LIMIT))) { + translationDz = translationDz * -1; + } + var pose = { + translation: translation, + rotation: rotation, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0, w: 1 } + }; + return pose; +}).debug(true).to(Controller.Standard.LeftHand); + +Controller.enableMapping(MAPPING_NAME); + + Script.scriptEnding.connect(function(){ mapping.disable(); }); diff --git a/libraries/controllers/src/controllers/Pose.cpp b/libraries/controllers/src/controllers/Pose.cpp index 2281fc98ff..2e1d30cff2 100644 --- a/libraries/controllers/src/controllers/Pose.cpp +++ b/libraries/controllers/src/controllers/Pose.cpp @@ -42,7 +42,23 @@ namespace controller { } void Pose::fromScriptValue(const QScriptValue& object, Pose& pose) { - // nothing for now... + bool isValid = true; + auto translation = object.property("translation"); + auto rotation = object.property("rotation"); + auto velocity = object.property("velocity"); + auto angularVelocity = object.property("angularVelocity"); + if (translation.isValid() && + rotation.isValid() && + velocity.isValid() && + angularVelocity.isValid()) { + vec3FromScriptValue(translation, pose.translation); + quatFromScriptValue(rotation, pose.rotation); + vec3FromScriptValue(velocity, pose.velocity); + quatFromScriptValue(angularVelocity, pose.angularVelocity); + pose.valid = true; + } else { + pose.valid = false; + } } } diff --git a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp index bb9517b136..3e7fde347e 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp @@ -10,6 +10,8 @@ #include +#include + using namespace controller; float ScriptEndpoint::peek() const { @@ -23,7 +25,16 @@ void ScriptEndpoint::updateValue() { return; } - _lastValueRead = (float)_callable.call().toNumber(); + QScriptValue result = _callable.call(); + + // If the callable ever returns a non-number, we assume it's a pose + // and start reporting ourselves as a pose. + if (result.isNumber()) { + _lastValueRead = (float)_callable.call().toNumber(); + } else { + Pose::fromScriptValue(result, _lastPoseRead); + _returnPose = true; + } } void ScriptEndpoint::apply(float value, const Pointer& source) { @@ -44,3 +55,36 @@ void ScriptEndpoint::internalApply(float value, int sourceID) { _callable.call(QScriptValue(), QScriptValueList({ QScriptValue(value), QScriptValue(sourceID) })); } + +Pose ScriptEndpoint::peekPose() const { + const_cast(this)->updatePose(); + return _lastPoseRead; +} + +void ScriptEndpoint::updatePose() { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "updatePose", Qt::QueuedConnection); + return; + } + QScriptValue result = _callable.call(); + Pose::fromScriptValue(result, _lastPoseRead); +} + +void ScriptEndpoint::apply(const Pose& newPose, const Pointer& source) { + if (newPose == _lastPoseWritten) { + return; + } + internalApply(newPose, source->getInput().getID()); +} + +void ScriptEndpoint::internalApply(const Pose& newPose, int sourceID) { + _lastPoseWritten = newPose; + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "internalApply", Qt::QueuedConnection, + Q_ARG(const Pose&, newPose), + Q_ARG(int, sourceID)); + return; + } + _callable.call(QScriptValue(), + QScriptValueList({ Pose::toScriptValue(_callable.engine(), newPose), QScriptValue(sourceID) })); +} diff --git a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h index 836af721f6..00439f5560 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h @@ -27,13 +27,26 @@ public: virtual float peek() const override; virtual void apply(float newValue, const Pointer& source) override; + + virtual Pose peekPose() const override; + virtual void apply(const Pose& newValue, const Pointer& source) override; + + virtual bool isPose() const override { return _returnPose; } + protected: Q_INVOKABLE void updateValue(); Q_INVOKABLE virtual void internalApply(float newValue, int sourceID); + + Q_INVOKABLE void updatePose(); + Q_INVOKABLE virtual void internalApply(const Pose& newValue, int sourceID); private: QScriptValue _callable; float _lastValueRead { 0.0f }; float _lastValueWritten { 0.0f }; + + bool _returnPose { false }; + Pose _lastPoseRead; + Pose _lastPoseWritten; }; } From b127b6a9e887874b0cfa253c9dcb447a2e91f7d4 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 08:55:57 -0800 Subject: [PATCH 079/195] separating out rave stick --- examples/flowArts/flowArtsHutSpawner.js | 5 + examples/flowArts/lightSaber/LightSaber.js | 38 ++++++ .../lightSaber/lightSaberEntityScript.js | 121 ++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 examples/flowArts/lightSaber/LightSaber.js create mode 100644 examples/flowArts/lightSaber/lightSaberEntityScript.js diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index b9d89859df..920fcc90ea 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -16,6 +16,9 @@ Script.include("../../libraries/utils.js"); Script.include("lightBall/LightBall.js"); Script.include("raveStick/RaveStick.js"); +Script.include("lightSaber/LightSaber.js"); + + var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); basePosition.y = MyAvatar.position.y + 1; @@ -24,6 +27,7 @@ basePosition.y = MyAvatar.position.y + 1; var lightBall = new LightBall(basePosition); var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 0.5, z: 1})); var raveStick2 = new RaveStick(Vec3.sum(basePosition, {x: 2, y: 0.5, z: 1})); +var lightSaber = new LightSaber(Vec3.sum(basePosition, {x: 3, y: 0.5, z: 1})); var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); @@ -75,6 +79,7 @@ function cleanup() { lightBall.cleanup(); raveStick.cleanup(); raveStick2.cleanup(); + lightSaber.cleanup(); } Script.scriptEnding.connect(cleanup); \ No newline at end of file diff --git a/examples/flowArts/lightSaber/LightSaber.js b/examples/flowArts/lightSaber/LightSaber.js new file mode 100644 index 0000000000..12ac3f3b60 --- /dev/null +++ b/examples/flowArts/lightSaber/LightSaber.js @@ -0,0 +1,38 @@ +Script.include("../../libraries/utils.js"); +var modelURL = "file:///C:/Users/Eric/Desktop/lightSaber.fbx?v1" + Math.random(); +var scriptURL = Script.resolvePath("lightSaberEntityScript.js"); +LightSaber = function(spawnPosition) { + + var stick = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: spawnPosition, + shapeType: 'box', + script: scriptURL, + dimensions: { + x: 0.06, + y: 0.06, + z: 0.31 + }, + userData: JSON.stringify({ + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 0, + z: -0.1 + }, + relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0) + }, + invertSolidWhileHeld: true + } + }) + }); + + + function cleanup() { + Entities.deleteEntity(stick); + } + + this.cleanup = cleanup; +} \ No newline at end of file diff --git a/examples/flowArts/lightSaber/lightSaberEntityScript.js b/examples/flowArts/lightSaber/lightSaberEntityScript.js new file mode 100644 index 0000000000..5ff3c65afd --- /dev/null +++ b/examples/flowArts/lightSaber/lightSaberEntityScript.js @@ -0,0 +1,121 @@ +// lightSaberEntityScript.js +// +// Script Type: Entity +// Created by Eric Levin on 12/16/15. +// Copyright 2015 High Fidelity, Inc. +// +// This entity script creates a lightsaber. +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + Script.include("../../libraries/utils.js"); + var _this; + // this is the "constructor" for the entity as a JS object we don't do much here + var LightSaber = function() { + _this = this; + this.colorPalette = [{ + red: 0, + green: 200, + blue: 40 + }, { + red: 200, + green: 10, + blue: 40 + }]; + }; + + LightSaber.prototype = { + isGrabbed: false, + + startNearGrab: function() { + // this.createBeam(); + this.createBeam(); + }, + + continueNearGrab: function() { + + }, + + releaseGrab: function() { + + }, + + preload: function(entityID) { + this.entityID = entityID; + }, + + unload: function() { + Entities.deleteEntity(this.beam); + // Entities.deleteEntity(this.beamTrail); + }, + + createBeam: function() { + + var props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); + var forwardVec = Quat.getFront(Quat.multiply(props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); + forwardVec = Vec3.normalize(forwardVec); + var forwardQuat = orientationOf(forwardVec); + var position = Vec3.sum(props.position, Vec3.multiply(Quat.getFront(props.rotation), 0.1)); + position.z += 0.1; + position.x += -0.035; + var color = this.colorPalette[randInt(0, this.colorPalette.length)]; + var props = { + type: "ParticleEffect", + position: position, + parentID: this.entityID, + isEmitting: true, + "name": "ParticlesTest Emitter", + "colorStart": color, + color: { + red: 200, + green: 200, + blue: 255 + }, + "colorFinish": color, + "maxParticles": 100000, + "lifespan": 2, + "emitRate": 1000, + emitOrientation: forwardQuat, + "emitSpeed": .4, + "speedSpread": 0.0, + // "emitDimensions": { + // "x": .1, + // "y": .1, + // "z": .1 + // }, + "polarStart": 0, + "polarFinish": .0, + "azimuthStart": .1, + "azimuthFinish": .01, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": .00, + "y": .00, + "z": .00 + }, + "radiusStart": 0.03, + radiusFinish: 0.025, + "alpha": 0.7, + "alphaSpread": .1, + "alphaStart": 0.5, + "alphaFinish": 0.5, + // "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + "textures": "file:///C:/Users/Eric/Desktop/beamParticle.png?v1" + Math.random(), + emitterShouldTrail: false + } + this.beam = Entities.addEntity(props); + + // props.emitterShouldTrail = true; + // this.beamTrail = Entities.addEntity(props); + + } + }; + // entity scripts always need to return a newly constructed object of our type + return new LightSaber(); +}); \ No newline at end of file From 064c05e98cb3f421e36ed3c827af4b643d86996a Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 10:04:51 -0800 Subject: [PATCH 080/195] light trails --- examples/flowArts/flowArtsHutSpawner.js | 2 +- examples/flowArts/lightBall/particles.js | 129 ++++++++++++++++++ .../lightSaber/lightSaberEntityScript.js | 21 +-- .../raveStick/raveStickEntityScript.js | 49 ++++++- 4 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 examples/flowArts/lightBall/particles.js diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index 920fcc90ea..1ed3325b9c 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -27,7 +27,7 @@ basePosition.y = MyAvatar.position.y + 1; var lightBall = new LightBall(basePosition); var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 0.5, z: 1})); var raveStick2 = new RaveStick(Vec3.sum(basePosition, {x: 2, y: 0.5, z: 1})); -var lightSaber = new LightSaber(Vec3.sum(basePosition, {x: 3, y: 0.5, z: 1})); +// var lightSaber = new LightSaber(Vec3.sum(basePosition, {x: 3, y: 0.5, z: 1})); var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); diff --git a/examples/flowArts/lightBall/particles.js b/examples/flowArts/lightBall/particles.js new file mode 100644 index 0000000000..86616d5099 --- /dev/null +++ b/examples/flowArts/lightBall/particles.js @@ -0,0 +1,129 @@ +Script.include("../../libraries/utils.js"); + +LightBall = function(spawnPosition) { + + var colorPalette = [{ + red: 25, + green: 20, + blue: 162 + }]; + + + var containerBall = Entities.addEntity({ + type: "Sphere", + position: Vec3.sum(spawnPosition, { + x: 0, + y: .5, + z: 0 + }), + dimensions: { + x: .1, + y: .1, + z: .1 + }, + color: { + red: 15, + green: 10, + blue: 150 + }, + collisionsWillMove: true, + gravity: {x: 0, y: -.5, z: 0}, + visible: false, + userData: JSON.stringify({ + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: .1, + z: 0 + } + }, + invertSolidWhileHeld: true + } + }) + }); + + + var light = Entities.addEntity({ + type: 'Light', + parentID: containerBall, + dimensions: { + x: 30, + y: 30, + z: 30 + }, + color: colorPalette[randInt(0, colorPalette.length)], + intensity: 5 + }); + + + var lightBall = Entities.addEntity({ + type: "ParticleEffect", + position: spawnPosition, + // parentID: containerBall, + isEmitting: true, + "name": "ParticlesTest Emitter", + "colorStart": { + red: 200, + green: 20, + blue: 40 + }, + color: { + red: 200, + green: 200, + blue: 255 + }, + "colorFinish": { + red: 25, + green: 20, + blue: 255 + }, + "maxParticles": 100000, + "lifespan": 2, + "emitRate": 10000, + "emitSpeed": .0, + "speedSpread": 0.0, + "emitDimensions": { + "x": 5, + "y":0 , + "z": 0 + }, + // "polarStart": 0, + // "polarFinish": Math.PI, + // "azimuthStart": -Math.PI, + // "azimuthFinish": Math.PI, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": .00, + "y": .0, + "z": .00 + }, + "particleRadius": 0.02, + "radiusSpread": 0, + "radiusStart": 0.03, + "radiusFinish": 0.0003, + "alpha": 0, + "alphaSpread": .5, + "alphaStart": 0, + "alphaFinish": 0.5, + // "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + "textures": "file:///C:/Users/Eric/Desktop/Particle-Sprite-Smoke-1.png?v1" + Math.random(), + emitterShouldTrail: true + }) + + + + function cleanup() { + Entities.deleteEntity(lightBall); + Entities.deleteEntity(containerBall); + Entities.deleteEntity(light); + } + + this.cleanup = cleanup; +} + +LightBall(); \ No newline at end of file diff --git a/examples/flowArts/lightSaber/lightSaberEntityScript.js b/examples/flowArts/lightSaber/lightSaberEntityScript.js index 5ff3c65afd..ea1f408abd 100644 --- a/examples/flowArts/lightSaber/lightSaberEntityScript.js +++ b/examples/flowArts/lightSaber/lightSaberEntityScript.js @@ -31,7 +31,7 @@ startNearGrab: function() { // this.createBeam(); - this.createBeam(); + }, continueNearGrab: function() { @@ -44,6 +44,7 @@ preload: function(entityID) { this.entityID = entityID; + this.createBeam(); }, unload: function() { @@ -53,11 +54,12 @@ createBeam: function() { - var props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); - var forwardVec = Quat.getFront(Quat.multiply(props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); + + this.props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); + var forwardVec = Quat.getFront(Quat.multiply(this.props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); forwardVec = Vec3.normalize(forwardVec); var forwardQuat = orientationOf(forwardVec); - var position = Vec3.sum(props.position, Vec3.multiply(Quat.getFront(props.rotation), 0.1)); + var position = Vec3.sum(this.props.position, Vec3.multiply(Quat.getFront(this.props.rotation), 0.1)); position.z += 0.1; position.x += -0.035; var color = this.colorPalette[randInt(0, this.colorPalette.length)]; @@ -66,7 +68,6 @@ position: position, parentID: this.entityID, isEmitting: true, - "name": "ParticlesTest Emitter", "colorStart": color, color: { red: 200, @@ -80,11 +81,11 @@ emitOrientation: forwardQuat, "emitSpeed": .4, "speedSpread": 0.0, - // "emitDimensions": { - // "x": .1, - // "y": .1, - // "z": .1 - // }, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, "polarStart": 0, "polarFinish": .0, "azimuthStart": .1, diff --git a/examples/flowArts/raveStick/raveStickEntityScript.js b/examples/flowArts/raveStick/raveStickEntityScript.js index 0372fd388f..95e37ee79b 100644 --- a/examples/flowArts/raveStick/raveStickEntityScript.js +++ b/examples/flowArts/raveStick/raveStickEntityScript.js @@ -13,6 +13,11 @@ Script.include("../../libraries/utils.js"); var _this; // this is the "constructor" for the entity as a JS object we don't do much here + var LIFETIME = 6000; + var DRAWING_DEPTH = 0.8; + var LINE_DIMENSIONS = 100; + var MAX_POINTS_PER_LINE = 50; + var MIN_POINT_DISTANCE = 0.02; var RaveStick = function() { _this = this; this.colorPalette = [{ @@ -24,6 +29,21 @@ green: 10, blue: 40 }]; + var texture = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/trails.png"; + this.trail = Entities.addEntity({ + type: "PolyLine", + dimensions: {x: LINE_DIMENSIONS, y: LINE_DIMENSIONS, z: LINE_DIMENSIONS}, + color: { + red: 255, + green: 255, + blue: 255 + }, + textures: texture, + lifetime: LIFETIME + }) + this.points = []; + this.normals = []; + this.strokeWidths = []; }; RaveStick.prototype = { @@ -31,9 +51,31 @@ startNearGrab: function() { // this.createBeam(); + this.trailBasePosition = Entities.getEntityProperties(this.entityID, "position").position; + Entities.editEntity(this.trail, { + position: this.trailBasePosition + }); + this.points = []; + this.normals = []; + this.strokeWidths = []; }, continueNearGrab: function() { + var position = Entities.getEntityProperties(this.entityID, "position").position; + var localPoint = Vec3.subtract(position, this.trailBasePosition); + if (this.points.length >=1 && Vec3.distance(localPoint, this.points[this.points.length - 1]) < MIN_POINT_DISTANCE) { + //Need a minimum distance to avoid binormal NANs + return; + } + this.points.push(localPoint); + var normal = computeNormal(position, Camera.getPosition()); + this.normals.push(normal); + this.strokeWidths.push(0.04); + Entities.editEntity(this.trail, { + linePoints: this.points, + normals: this.normals, + strokeWidths: this.strokeWidths + }) }, @@ -48,6 +90,7 @@ unload: function() { Entities.deleteEntity(this.beam); + Entities.deleteEntity(this.trail); // Entities.deleteEntity(this.beamTrail); }, @@ -60,7 +103,7 @@ var position = Vec3.sum(props.position, Vec3.multiply(Quat.getFront(props.rotation), 0.1)); position.z += 0.1; position.x += -0.035; - var color = this.colorPalette[randInt(0, this.colorPalette.length)]; + var color = this.colorPalette[randInt(0, this.colorPalette.length)]; var props = { type: "ParticleEffect", position: position, @@ -118,4 +161,8 @@ }; // entity scripts always need to return a newly constructed object of our type return new RaveStick(); + + function computeNormal(p1, p2) { + return Vec3.normalize(Vec3.subtract(p2, p1)); + } }); \ No newline at end of file From 8d4d0d4e9a849f50109d8cb670bed3d2195994c4 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 17 Dec 2015 10:08:40 -0800 Subject: [PATCH 081/195] FIxing the bad returned value per reference --- libraries/model/src/model/Material.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index bd1d45c7ed..cb5a285dba 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -221,10 +221,10 @@ public: const MaterialKey& getKey() const { return _key; } void setEmissive(const Color& emissive, bool isSRGB = true); - const Color& getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._emissive) : _schemaBuffer.get()._emissive); } + Color getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._emissive) : _schemaBuffer.get()._emissive); } void setDiffuse(const Color& diffuse, bool isSRGB = true); - const Color& getDiffuse(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._diffuse) : _schemaBuffer.get()._diffuse); } + Color getDiffuse(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._diffuse) : _schemaBuffer.get()._diffuse); } void setMetallic(float metallic); float getMetallic() const { return _schemaBuffer.get()._metallic.x; } From f7811cf5dc5bc33af18788a21b8c46d9ad8d8fe7 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 10:25:51 -0800 Subject: [PATCH 082/195] light trails from rave stick --- .../raveStick/raveStickEntityScript.js | 61 ++++++++++++++----- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/examples/flowArts/raveStick/raveStickEntityScript.js b/examples/flowArts/raveStick/raveStickEntityScript.js index 95e37ee79b..7b84f473ea 100644 --- a/examples/flowArts/raveStick/raveStickEntityScript.js +++ b/examples/flowArts/raveStick/raveStickEntityScript.js @@ -18,6 +18,8 @@ var LINE_DIMENSIONS = 100; var MAX_POINTS_PER_LINE = 50; var MIN_POINT_DISTANCE = 0.02; + var STROKE_WIDTH = 0.05 + var ugLSD = 25; var RaveStick = function() { _this = this; this.colorPalette = [{ @@ -32,7 +34,11 @@ var texture = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/trails.png"; this.trail = Entities.addEntity({ type: "PolyLine", - dimensions: {x: LINE_DIMENSIONS, y: LINE_DIMENSIONS, z: LINE_DIMENSIONS}, + dimensions: { + x: LINE_DIMENSIONS, + y: LINE_DIMENSIONS, + z: LINE_DIMENSIONS + }, color: { red: 255, green: 255, @@ -58,29 +64,58 @@ this.points = []; this.normals = []; this.strokeWidths = []; + this.setupEraseInterval(); }, continueNearGrab: function() { - var position = Entities.getEntityProperties(this.entityID, "position").position; + var props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); + var forwardVec = Quat.getFront(Quat.multiply(props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); + forwardVec = Vec3.normalize(forwardVec); + var forwardQuat = orientationOf(forwardVec); + var position = Vec3.sum(props.position, Vec3.multiply(Quat.getFront(props.rotation), 0.2)); + // position.z += 0.1; + // position.x += -0.035; var localPoint = Vec3.subtract(position, this.trailBasePosition); - if (this.points.length >=1 && Vec3.distance(localPoint, this.points[this.points.length - 1]) < MIN_POINT_DISTANCE) { + if (this.points.length >= 1 && Vec3.distance(localPoint, this.points[this.points.length - 1]) < MIN_POINT_DISTANCE) { //Need a minimum distance to avoid binormal NANs return; } + if (this.points.length === MAX_POINTS_PER_LINE) { + this.points.shift(); + this.normals.shift(); + this.strokeWidths.shift(); + } + this.points.push(localPoint); - var normal = computeNormal(position, Camera.getPosition()); + var normal = Quat.getUp(props.rotation); this.normals.push(normal); - this.strokeWidths.push(0.04); + this.strokeWidths.push(STROKE_WIDTH); Entities.editEntity(this.trail, { linePoints: this.points, normals: this.normals, strokeWidths: this.strokeWidths - }) + }); + }, - releaseGrab: function() { + setupEraseInterval: function() { + this.trailEraseInterval = Script.setInterval(function() { + if (_this.points.length > 0) { + _this.points.shift(); + _this.normals.shift(); + _this.strokeWidths.shift(); + Entities.editEntity(_this.trail, { + linePoints: _this.points, + strokeWidths: _this.strokeWidths, + normals: _this.normals + }); + } + }, ugLSD); + }, + releaseGrab: function() { + Script.clearInterval(this.trailEraseInterval); }, preload: function(entityID) { @@ -91,7 +126,7 @@ unload: function() { Entities.deleteEntity(this.beam); Entities.deleteEntity(this.trail); - // Entities.deleteEntity(this.beamTrail); + Script.clearInterval(this.trailEraseInterval); }, createBeam: function() { @@ -111,6 +146,7 @@ isEmitting: true, "name": "ParticlesTest Emitter", "colorStart": color, + colorSpread: {red: 200, green : 10, blue: 10}, color: { red: 200, green: 200, @@ -118,16 +154,11 @@ }, "colorFinish": color, "maxParticles": 100000, - "lifespan": 2, + "lifespan": 1, "emitRate": 1000, emitOrientation: forwardQuat, - "emitSpeed": .4, + "emitSpeed": .2, "speedSpread": 0.0, - // "emitDimensions": { - // "x": .1, - // "y": .1, - // "z": .1 - // }, "polarStart": 0, "polarFinish": .0, "azimuthStart": .1, From 57e51afd46c661db3545cef4345327137abc2338 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 10:35:20 -0800 Subject: [PATCH 083/195] light stick --- examples/flowArts/flowArtsHutSpawner.js | 4 +--- examples/flowArts/lightSaber/lightSaberEntityScript.js | 6 +++--- examples/flowArts/raveStick/raveStickEntityScript.js | 5 ++++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index 1ed3325b9c..2f9b2052d1 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -26,8 +26,7 @@ basePosition.y = MyAvatar.position.y + 1; // RAVE ITEMS var lightBall = new LightBall(basePosition); var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 0.5, z: 1})); -var raveStick2 = new RaveStick(Vec3.sum(basePosition, {x: 2, y: 0.5, z: 1})); -// var lightSaber = new LightSaber(Vec3.sum(basePosition, {x: 3, y: 0.5, z: 1})); +var lightSaber = new LightSaber(Vec3.sum(basePosition, {x: 3, y: 0.5, z: 1})); var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); @@ -78,7 +77,6 @@ function cleanup() { Entities.deleteEntity(floor); lightBall.cleanup(); raveStick.cleanup(); - raveStick2.cleanup(); lightSaber.cleanup(); } diff --git a/examples/flowArts/lightSaber/lightSaberEntityScript.js b/examples/flowArts/lightSaber/lightSaberEntityScript.js index ea1f408abd..5175de25bb 100644 --- a/examples/flowArts/lightSaber/lightSaberEntityScript.js +++ b/examples/flowArts/lightSaber/lightSaberEntityScript.js @@ -31,7 +31,7 @@ startNearGrab: function() { // this.createBeam(); - + }, continueNearGrab: function() { @@ -44,7 +44,7 @@ preload: function(entityID) { this.entityID = entityID; - this.createBeam(); + this.createBeam(); }, unload: function() { @@ -62,7 +62,7 @@ var position = Vec3.sum(this.props.position, Vec3.multiply(Quat.getFront(this.props.rotation), 0.1)); position.z += 0.1; position.x += -0.035; - var color = this.colorPalette[randInt(0, this.colorPalette.length)]; + var color = this.colorPalette[randInt(0, this.colorPalette.length)]; var props = { type: "ParticleEffect", position: position, diff --git a/examples/flowArts/raveStick/raveStickEntityScript.js b/examples/flowArts/raveStick/raveStickEntityScript.js index 7b84f473ea..20c21d3a79 100644 --- a/examples/flowArts/raveStick/raveStickEntityScript.js +++ b/examples/flowArts/raveStick/raveStickEntityScript.js @@ -116,6 +116,7 @@ releaseGrab: function() { Script.clearInterval(this.trailEraseInterval); + this.trailEraseInterval = null; }, preload: function(entityID) { @@ -126,7 +127,9 @@ unload: function() { Entities.deleteEntity(this.beam); Entities.deleteEntity(this.trail); - Script.clearInterval(this.trailEraseInterval); + if(this.trailEraseInterval) { + Script.clearInterval(this.trailEraseInterval); + } }, createBeam: function() { From d4481818b2e991512afb6e8819ed5c910d7cf801 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 10:50:58 -0800 Subject: [PATCH 084/195] lightsaber oriented right --- .../flowArts/lightSaber/lightSaberEntityScript.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/flowArts/lightSaber/lightSaberEntityScript.js b/examples/flowArts/lightSaber/lightSaberEntityScript.js index 5175de25bb..2faf0abff9 100644 --- a/examples/flowArts/lightSaber/lightSaberEntityScript.js +++ b/examples/flowArts/lightSaber/lightSaberEntityScript.js @@ -30,8 +30,9 @@ isGrabbed: false, startNearGrab: function() { - // this.createBeam(); - + Entities.editEntity(this.beam, { + isEmitting: true + }); }, continueNearGrab: function() { @@ -39,7 +40,9 @@ }, releaseGrab: function() { - + Entities.editEntity(this.beam, { + isEmitting: false + }); }, preload: function(entityID) { @@ -57,7 +60,7 @@ this.props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); var forwardVec = Quat.getFront(Quat.multiply(this.props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); - forwardVec = Vec3.normalize(forwardVec); + // forwardVec = Vec3.normalize(forwardVec); var forwardQuat = orientationOf(forwardVec); var position = Vec3.sum(this.props.position, Vec3.multiply(Quat.getFront(this.props.rotation), 0.1)); position.z += 0.1; @@ -67,7 +70,7 @@ type: "ParticleEffect", position: position, parentID: this.entityID, - isEmitting: true, + isEmitting: false, "colorStart": color, color: { red: 200, From 63a63152a48afe98be231bfd653b3c17c3f7cc02 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 17 Dec 2015 11:10:49 -0800 Subject: [PATCH 085/195] add procedural hand pose example --- .../controllers/proceduralHandPoseExample.js | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 examples/controllers/proceduralHandPoseExample.js diff --git a/examples/controllers/proceduralHandPoseExample.js b/examples/controllers/proceduralHandPoseExample.js new file mode 100644 index 0000000000..5d0b10c46a --- /dev/null +++ b/examples/controllers/proceduralHandPoseExample.js @@ -0,0 +1,76 @@ +// +// proceduralHandPoseExample.js +// examples/controllers +// +// Created by Brad Hefta-Gaub on 2015/12/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 +// + + +var MAPPING_NAME = "com.highfidelity.examples.proceduralHandPose"; +var mapping = Controller.newMapping(MAPPING_NAME); +var translation = { x: 0, y: 0.1, z: 0 }; +var translationDx = 0.01; +var translationDy = 0.01; +var translationDz = -0.01; +var TRANSLATION_LIMIT = 0.5; + +var pitch = 45; +var yaw = 0; +var roll = 45; +var pitchDelta = 1; +var yawDelta = -1; +var rollDelta = 1; +var ROTATION_MIN = -90; +var ROTATION_MAX = 90; + +mapping.from(function() { + + // adjust the hand translation in a periodic back and forth motion for each of the 3 axes + translation.x = translation.x + translationDx; + translation.y = translation.y + translationDy; + translation.z = translation.z + translationDz; + if ((translation.x > TRANSLATION_LIMIT) || (translation.x < (-1 * TRANSLATION_LIMIT))) { + translationDx = translationDx * -1; + } + if ((translation.y > TRANSLATION_LIMIT) || (translation.y < (-1 * TRANSLATION_LIMIT))) { + translationDy = translationDy * -1; + } + if ((translation.z > TRANSLATION_LIMIT) || (translation.z < (-1 * TRANSLATION_LIMIT))) { + translationDz = translationDz * -1; + } + + // adjust the hand rotation in a periodic back and forth motion for each of pitch/yaw/roll + pitch = pitch + pitchDelta; + yaw = yaw + yawDelta; + roll = roll + rollDelta; + if ((pitch > ROTATION_MAX) || (pitch < ROTATION_MIN)) { + pitchDelta = pitchDelta * -1; + } + if ((yaw > ROTATION_MAX) || (yaw < ROTATION_MIN)) { + yawDelta = yawDelta * -1; + } + if ((roll > ROTATION_MAX) || (roll < ROTATION_MIN)) { + rollDelta = rollDelta * -1; + } + + var rotation = Quat.fromPitchYawRollDegrees(pitch, yaw, roll); + + var pose = { + translation: translation, + rotation: rotation, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0, w: 1 } + }; + return pose; +}).debug(true).to(Controller.Standard.LeftHand); + +Controller.enableMapping(MAPPING_NAME); + + +Script.scriptEnding.connect(function(){ + mapping.disable(); +}); From 2aaefbcfcbbcc0d6e3ed7d4cfbb932467131d4a4 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 11:32:48 -0800 Subject: [PATCH 086/195] refactoring, adding headers --- examples/flowArts/flowArtsHutSpawner.js | 13 +-- examples/flowArts/lightBall/lightBall.js | 90 +++++++++++-------- examples/flowArts/lightSaber/LightSaber.js | 21 ++++- .../lightSaber/lightSaberEntityScript.js | 74 +++++++-------- examples/flowArts/lightTrails.js | 23 +---- examples/flowArts/raveStick/RaveStick.js | 41 ++++++++- .../raveStick/raveStickEntityScript.js | 67 +++++++------- .../RenderableParticleEffectEntityItem.cpp | 1 + .../entities/src/ParticleEffectEntityItem.cpp | 11 +-- 9 files changed, 195 insertions(+), 146 deletions(-) diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index 2f9b2052d1..03c0ca112f 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -1,11 +1,11 @@ // // flowArtsHutSpawner.js -// examples +// examples/flowArts // -// Created by Eric Levin on 5/14/15. +// Created by Eric Levin on 12/17/15. // Copyright 2014 High Fidelity, Inc. // -// This script creates a special flow arts hut with a numch of flow art toys people can go in and play with +// This script creates a special flow arts hut with a bunch of flow art toys people can go in and play with // // // Distributed under the Apache License, Version 2.0. @@ -29,12 +29,13 @@ var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 0.5, z: 1})); var lightSaber = new LightSaber(Vec3.sum(basePosition, {x: 3, y: 0.5, z: 1})); -var modelURL = "file:///C:/Users/Eric/Desktop/RaveRoom.fbx?v1" + Math.random(); +var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/rave/RaveRoom.fbx"; var roomDimensions = {x: 30.58, y: 15.29, z: 30.58}; var raveRoom = Entities.addEntity({ type: "Model", + name: "Rave Hut Room", modelURL: modelURL, position: basePosition, dimensions:roomDimensions, @@ -43,7 +44,8 @@ var raveRoom = Entities.addEntity({ var floor = Entities.addEntity({ type: "Box", - position: Vec3.sum(basePosition, {x: 0, y: -1.5, z: 0}), + name: "Rave Floor", + position: Vec3.sum(basePosition, {x: 0, y: -1.2, z: 0}), dimensions: {x: roomDimensions.x, y: 0.6, z: roomDimensions.z}, color: {red: 50, green: 10, blue: 100}, shapeType: 'box' @@ -53,6 +55,7 @@ var floor = Entities.addEntity({ var lightZone = Entities.addEntity({ type: "Zone", + name: "Rave Hut Zone", shapeType: 'box', keyLightIntensity: 0.4, keyLightColor: { diff --git a/examples/flowArts/lightBall/lightBall.js b/examples/flowArts/lightBall/lightBall.js index 698c62a71d..a8cdf894d1 100644 --- a/examples/flowArts/lightBall/lightBall.js +++ b/examples/flowArts/lightBall/lightBall.js @@ -1,3 +1,17 @@ +// +// LightBall.js +// examples/lightBall +// +// Created by Eric Levin on 12/17/15. +// Copyright 2014 High Fidelity, Inc. +// +// This script creats a particle light ball which makes particle trails as you move it. +// +// +// 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("../../libraries/utils.js"); LightBall = function(spawnPosition) { @@ -11,6 +25,7 @@ LightBall = function(spawnPosition) { var containerBall = Entities.addEntity({ type: "Sphere", + name: "containerBall", position: Vec3.sum(spawnPosition, { x: 0, y: .5, @@ -27,7 +42,11 @@ LightBall = function(spawnPosition) { blue: 150 }, collisionsWillMove: true, - gravity: {x: 0, y: -.5, z: 0}, + gravity: { + x: 0, + y: -.5, + z: 0 + }, userData: JSON.stringify({ grabbableKey: { spatialKey: { @@ -45,6 +64,7 @@ LightBall = function(spawnPosition) { var light = Entities.addEntity({ type: 'Light', + name: "ballLight", parentID: containerBall, dimensions: { x: 30, @@ -60,8 +80,8 @@ LightBall = function(spawnPosition) { type: "ParticleEffect", parentID: containerBall, isEmitting: true, - "name": "ParticlesTest Emitter", - "colorStart": { + name: "particleBall", + colorStart: { red: 200, green: 20, blue: 40 @@ -71,45 +91,45 @@ LightBall = function(spawnPosition) { green: 200, blue: 255 }, - "colorFinish": { + colorFinish: { red: 25, green: 20, blue: 255 }, - "maxParticles": 100000, - "lifespan": 2, - "emitRate": 10000, - "emitSpeed": .1, - "speedSpread": 0.0, - "emitDimensions": { - "x": 0, - "y": 0, - "z": 0 + maxParticles: 100000, + lifespan: 2, + emitRate: 10000, + emitSpeed: .1, + lifetime: -1, + speedSpread: 0.0, + emitDimensions: { + x: 0, + y: 0, + z: 0 }, - "polarStart": 0, - "polarFinish": Math.PI, - "azimuthStart": -Math.PI, - "azimuthFinish": Math.PI, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 + polarStart: 0, + polarFinish: Math.PI, + azimuthStart: -Math.PI, + azimuthFinish: Math.PI, + emitAcceleration: { + x: 0, + y: 0, + z: 0 }, - "accelerationSpread": { - "x": .00, - "y": .00, - "z": .00 + accelerationSpread: { + x: .00, + y: .00, + z: .00 }, - "particleRadius": 0.02, - "radiusSpread": 0, - "radiusStart": 0.03, - "radiusFinish": 0.0003, - "alpha": 0, - "alphaSpread": .5, - "alphaStart": 0, - "alphaFinish": 0.5, - // "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - "textures": "file:///C:/Users/Eric/Desktop/Particle-Sprite-Smoke-1.png?v1" + Math.random(), + particleRadius: 0.02, + radiusSpread: 0, + radiusStart: 0.03, + radiusFinish: 0.0003, + alpha: 0, + alphaSpread: .5, + alphaStart: 0, + alphaFinish: 0.5, + textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", emitterShouldTrail: true }) diff --git a/examples/flowArts/lightSaber/LightSaber.js b/examples/flowArts/lightSaber/LightSaber.js index 12ac3f3b60..8a4f3f2902 100644 --- a/examples/flowArts/lightSaber/LightSaber.js +++ b/examples/flowArts/lightSaber/LightSaber.js @@ -1,10 +1,25 @@ +// +// LightSaber.js +// examples +// +// Created by Eric Levin on 12/17/15. +// Copyright 2014 High Fidelity, Inc. +// +// This script creates a lightsaber which activates on grab +// +// +// 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("../../libraries/utils.js"); -var modelURL = "file:///C:/Users/Eric/Desktop/lightSaber.fbx?v1" + Math.random(); +var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/rave/lightSaber.fbx"; var scriptURL = Script.resolvePath("lightSaberEntityScript.js"); LightSaber = function(spawnPosition) { - var stick = Entities.addEntity({ + var saberHandle = Entities.addEntity({ type: "Model", + name: "LightSaber Handle", modelURL: modelURL, position: spawnPosition, shapeType: 'box', @@ -31,7 +46,7 @@ LightSaber = function(spawnPosition) { function cleanup() { - Entities.deleteEntity(stick); + Entities.deleteEntity(saberHandle); } this.cleanup = cleanup; diff --git a/examples/flowArts/lightSaber/lightSaberEntityScript.js b/examples/flowArts/lightSaber/lightSaberEntityScript.js index 2faf0abff9..6f396bf6e3 100644 --- a/examples/flowArts/lightSaber/lightSaberEntityScript.js +++ b/examples/flowArts/lightSaber/lightSaberEntityScript.js @@ -1,10 +1,10 @@ // lightSaberEntityScript.js // // Script Type: Entity -// Created by Eric Levin on 12/16/15. +// Created by Eric Levin on 12/17/15. // Copyright 2015 High Fidelity, Inc. // -// This entity script creates a lightsaber. +// This entity script creates the logic for displaying the lightsaber beam. // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // @@ -35,10 +35,6 @@ }); }, - continueNearGrab: function() { - - }, - releaseGrab: function() { Entities.editEntity(this.beam, { isEmitting: false @@ -52,7 +48,6 @@ unload: function() { Entities.deleteEntity(this.beam); - // Entities.deleteEntity(this.beamTrail); }, createBeam: function() { @@ -68,56 +63,53 @@ var color = this.colorPalette[randInt(0, this.colorPalette.length)]; var props = { type: "ParticleEffect", + name: "LightSaber Beam", position: position, parentID: this.entityID, isEmitting: false, - "colorStart": color, + colorStart: color, color: { red: 200, green: 200, blue: 255 }, - "colorFinish": color, - "maxParticles": 100000, - "lifespan": 2, - "emitRate": 1000, + colorFinish: color, + maxParticles: 100000, + lifespan: 2, + emitRate: 1000, emitOrientation: forwardQuat, - "emitSpeed": .4, - "speedSpread": 0.0, - "emitDimensions": { - "x": 0, - "y": 0, - "z": 0 + emitSpeed: .4, + speedSpread: 0.0, + emitDimensions: { + x: 0, + y: 0, + z: 0 }, - "polarStart": 0, - "polarFinish": .0, - "azimuthStart": .1, - "azimuthFinish": .01, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 + polarStart: 0, + polarFinish: .0, + azimuthStart: .1, + azimuthFinish: .01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 }, - "accelerationSpread": { - "x": .00, - "y": .00, - "z": .00 + accelerationSpread: { + x: .00, + y: .00, + z: .00 }, - "radiusStart": 0.03, - radiusFinish: 0.025, - "alpha": 0.7, - "alphaSpread": .1, - "alphaStart": 0.5, - "alphaFinish": 0.5, - // "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - "textures": "file:///C:/Users/Eric/Desktop/beamParticle.png?v1" + Math.random(), + radiusStart: 0.03, + adiusFinish: 0.025, + alpha: 0.7, + alphaSpread: .1, + alphaStart: 0.5, + alphaFinish: 0.5, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", emitterShouldTrail: false } this.beam = Entities.addEntity(props); - // props.emitterShouldTrail = true; - // this.beamTrail = Entities.addEntity(props); - } }; // entity scripts always need to return a newly constructed object of our type diff --git a/examples/flowArts/lightTrails.js b/examples/flowArts/lightTrails.js index 8e0dc98bbb..522ecce851 100644 --- a/examples/flowArts/lightTrails.js +++ b/examples/flowArts/lightTrails.js @@ -1,11 +1,11 @@ // -// hydraPaint.js +// lightTrails.js // examples // // Created by Eric Levin on 5/14/15. // Copyright 2014 High Fidelity, Inc. // -// This script allows you to paint with the hydra! +// This script creates light trails as you move your hydra hands // // // Distributed under the Apache License, Version 2.0. @@ -25,24 +25,6 @@ var LIFETIME = 6000; var DRAWING_DEPTH = 0.8; var LINE_DIMENSIONS = 100; -var lightZone = Entities.addEntity({ - type: "Zone", - shapeType: 'box', - keyLightIntensity: 0.02, - keyLightColor: { - red: 5, - green: 0, - blue: 5 - }, - keyLightAmbientIntensity: .05, - position: MyAvatar.position, - dimensions: { - x: 100, - y: 100, - z: 100 - } -}); - var MIN_POINT_DISTANCE = 0.02; @@ -192,7 +174,6 @@ function update(deltaTime) { function scriptEnding() { leftController.cleanup(); rightController.cleanup(); - Entities.deleteEntity(lightZone); } function vectorIsZero(v) { diff --git a/examples/flowArts/raveStick/RaveStick.js b/examples/flowArts/raveStick/RaveStick.js index 5151b528cc..fd3c98b6e5 100644 --- a/examples/flowArts/raveStick/RaveStick.js +++ b/examples/flowArts/raveStick/RaveStick.js @@ -1,10 +1,32 @@ +// +// RaveStick.js +// examples/flowArats/raveStick +// +// Created by Eric Levin on 12/17/15. +// Copyright 2014 High Fidelity, Inc. +// +// This script creates a rave stick which makes pretty light trails as you paint +// +// 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("../../libraries/utils.js"); -var modelURL = "file:///C:/Users/Eric/Desktop/raveStick.fbx?v1" + Math.random(); +var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/rave/raveStick.fbx"; var scriptURL = Script.resolvePath("raveStickEntityScript.js"); RaveStick = function(spawnPosition) { - + var colorPalette = [{ + red: 0, + green: 200, + blue: 40 + }, { + red: 200, + green: 10, + blue: 40 + }]; var stick = Entities.addEntity({ type: "Model", + name: "raveStick", modelURL: modelURL, position: spawnPosition, shapeType: 'box', @@ -29,9 +51,24 @@ RaveStick = function(spawnPosition) { }) }); + var light = Entities.addEntity({ + type: 'Light', + name: "raveLight", + parentID: stick, + dimensions: { + x: 30, + y: 30, + z: 30 + }, + color: colorPalette[randInt(0, colorPalette.length)], + intensity: 5 + }); + + function cleanup() { Entities.deleteEntity(stick); + Entities.deleteEntity(light); } this.cleanup = cleanup; diff --git a/examples/flowArts/raveStick/raveStickEntityScript.js b/examples/flowArts/raveStick/raveStickEntityScript.js index 20c21d3a79..2c484e601d 100644 --- a/examples/flowArts/raveStick/raveStickEntityScript.js +++ b/examples/flowArts/raveStick/raveStickEntityScript.js @@ -46,7 +46,9 @@ }, textures: texture, lifetime: LIFETIME - }) + }); + + this.points = []; this.normals = []; this.strokeWidths = []; @@ -127,8 +129,8 @@ unload: function() { Entities.deleteEntity(this.beam); Entities.deleteEntity(this.trail); - if(this.trailEraseInterval) { - Script.clearInterval(this.trailEraseInterval); + if (this.trailEraseInterval) { + Script.clearInterval(this.trailEraseInterval); } }, @@ -147,43 +149,46 @@ position: position, parentID: this.entityID, isEmitting: true, - "name": "ParticlesTest Emitter", - "colorStart": color, - colorSpread: {red: 200, green : 10, blue: 10}, + name: "raveBeam", + colorStart: color, + colorSpread: { + red: 200, + green: 10, + blue: 10 + }, color: { red: 200, green: 200, blue: 255 }, - "colorFinish": color, - "maxParticles": 100000, - "lifespan": 1, - "emitRate": 1000, + colorFinish: color, + maxParticles: 100000, + lifespan: 1, + emitRate: 1000, emitOrientation: forwardQuat, - "emitSpeed": .2, - "speedSpread": 0.0, - "polarStart": 0, - "polarFinish": .0, - "azimuthStart": .1, - "azimuthFinish": .01, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 + emitSpeed: .2, + speedSpread: 0.0, + polarStart: 0, + polarFinish: .0, + azimuthStart: .1, + azimuthFinish: .01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 }, - "accelerationSpread": { - "x": .00, - "y": .00, - "z": .00 + accelerationSpread: { + x: .00, + y: .00, + z: .00 }, - "radiusStart": 0.03, + radiusStart: 0.03, radiusFinish: 0.025, - "alpha": 0.7, - "alphaSpread": .1, - "alphaStart": 0.5, - "alphaFinish": 0.5, - // "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - "textures": "file:///C:/Users/Eric/Desktop/beamParticle.png?v1" + Math.random(), + alpha: 0.7, + alphaSpread: .1, + alphaStart: 0.5, + alphaFinish: 0.5, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", emitterShouldTrail: false } this.beam = Entities.addEntity(props); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 91a4811011..43b9ae7870 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -245,6 +245,7 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { transform.setRotation(rotation); } + render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [=](ParticlePayloadData& payload) { payload.setVisibleFlag(true); diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 4d46439554..413604dbdf 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -641,11 +641,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { Particle particle; - - std::random_device rd; - std::mt19937_64 el(rd()); - std::uniform_real_distribution uniform_dist(0.0, 1.0); particle.seed = randFloatInRange(-1.0f, 1.0f); if (getEmitterShouldTrail()) { @@ -667,13 +663,13 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { float elevationMinZ = sin(PI_OVER_TWO - _polarFinish); float elevationMaxZ = sin(PI_OVER_TWO - _polarStart); // float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat()); - float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * uniform_dist(el)); + float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) *randFloat()); float azimuth; if (_azimuthFinish >= _azimuthStart) { - azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * uniform_dist(el); + azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat(); } else { - azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * uniform_dist(el); + azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * randFloat(); } glm::vec3 emitDirection; @@ -711,7 +707,6 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { } particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); - // particle.velocity = (_emitSpeed + uniform_dist(el) * _speedSpread) * (_emitOrientation * emitDirection); particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } From 8d25a666d11dd6e3498e55fcae021f9c886edc4c Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 11:40:06 -0800 Subject: [PATCH 087/195] fixed bug where trail would remain after user released rave stick --- examples/flowArts/flowArtsHutSpawner.js | 1 - examples/flowArts/lightBall/lightBall.js | 2 +- .../flowArts/raveStick/raveStickEntityScript.js | 13 +++++-------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index 03c0ca112f..3762c67fe4 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -72,7 +72,6 @@ var lightZone = Entities.addEntity({ } }); - function cleanup() { Entities.deleteEntity(raveRoom); diff --git a/examples/flowArts/lightBall/lightBall.js b/examples/flowArts/lightBall/lightBall.js index a8cdf894d1..1898f86eef 100644 --- a/examples/flowArts/lightBall/lightBall.js +++ b/examples/flowArts/lightBall/lightBall.js @@ -44,7 +44,7 @@ LightBall = function(spawnPosition) { collisionsWillMove: true, gravity: { x: 0, - y: -.5, + y: -0.5, z: 0 }, userData: JSON.stringify({ diff --git a/examples/flowArts/raveStick/raveStickEntityScript.js b/examples/flowArts/raveStick/raveStickEntityScript.js index 2c484e601d..171b53e0cf 100644 --- a/examples/flowArts/raveStick/raveStickEntityScript.js +++ b/examples/flowArts/raveStick/raveStickEntityScript.js @@ -19,7 +19,7 @@ var MAX_POINTS_PER_LINE = 50; var MIN_POINT_DISTANCE = 0.02; var STROKE_WIDTH = 0.05 - var ugLSD = 25; + var ugLSD = 35; var RaveStick = function() { _this = this; this.colorPalette = [{ @@ -117,8 +117,10 @@ }, releaseGrab: function() { - Script.clearInterval(this.trailEraseInterval); - this.trailEraseInterval = null; + Script.setTimeout(function() { + Script.clearInterval(_this.trailEraseInterval); + _this.trailEraseInterval = null; + }, 3000); }, preload: function(entityID) { @@ -192,13 +194,8 @@ emitterShouldTrail: false } this.beam = Entities.addEntity(props); - - // props.emitterShouldTrail = true; - // this.beamTrail = Entities.addEntity(props); - } }; - // entity scripts always need to return a newly constructed object of our type return new RaveStick(); function computeNormal(p1, p2) { From 6f82d680b9cb7873f091614fde07c6fd055a0ccd Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 12:38:25 -0800 Subject: [PATCH 088/195] removed unwanted file --- examples/flowArts/lightBall/particles.js | 129 ----------------------- 1 file changed, 129 deletions(-) delete mode 100644 examples/flowArts/lightBall/particles.js diff --git a/examples/flowArts/lightBall/particles.js b/examples/flowArts/lightBall/particles.js deleted file mode 100644 index 86616d5099..0000000000 --- a/examples/flowArts/lightBall/particles.js +++ /dev/null @@ -1,129 +0,0 @@ -Script.include("../../libraries/utils.js"); - -LightBall = function(spawnPosition) { - - var colorPalette = [{ - red: 25, - green: 20, - blue: 162 - }]; - - - var containerBall = Entities.addEntity({ - type: "Sphere", - position: Vec3.sum(spawnPosition, { - x: 0, - y: .5, - z: 0 - }), - dimensions: { - x: .1, - y: .1, - z: .1 - }, - color: { - red: 15, - green: 10, - blue: 150 - }, - collisionsWillMove: true, - gravity: {x: 0, y: -.5, z: 0}, - visible: false, - userData: JSON.stringify({ - grabbableKey: { - spatialKey: { - relativePosition: { - x: 0, - y: .1, - z: 0 - } - }, - invertSolidWhileHeld: true - } - }) - }); - - - var light = Entities.addEntity({ - type: 'Light', - parentID: containerBall, - dimensions: { - x: 30, - y: 30, - z: 30 - }, - color: colorPalette[randInt(0, colorPalette.length)], - intensity: 5 - }); - - - var lightBall = Entities.addEntity({ - type: "ParticleEffect", - position: spawnPosition, - // parentID: containerBall, - isEmitting: true, - "name": "ParticlesTest Emitter", - "colorStart": { - red: 200, - green: 20, - blue: 40 - }, - color: { - red: 200, - green: 200, - blue: 255 - }, - "colorFinish": { - red: 25, - green: 20, - blue: 255 - }, - "maxParticles": 100000, - "lifespan": 2, - "emitRate": 10000, - "emitSpeed": .0, - "speedSpread": 0.0, - "emitDimensions": { - "x": 5, - "y":0 , - "z": 0 - }, - // "polarStart": 0, - // "polarFinish": Math.PI, - // "azimuthStart": -Math.PI, - // "azimuthFinish": Math.PI, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 - }, - "accelerationSpread": { - "x": .00, - "y": .0, - "z": .00 - }, - "particleRadius": 0.02, - "radiusSpread": 0, - "radiusStart": 0.03, - "radiusFinish": 0.0003, - "alpha": 0, - "alphaSpread": .5, - "alphaStart": 0, - "alphaFinish": 0.5, - // "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - "textures": "file:///C:/Users/Eric/Desktop/Particle-Sprite-Smoke-1.png?v1" + Math.random(), - emitterShouldTrail: true - }) - - - - function cleanup() { - Entities.deleteEntity(lightBall); - Entities.deleteEntity(containerBall); - Entities.deleteEntity(light); - } - - this.cleanup = cleanup; -} - -LightBall(); \ No newline at end of file From 92f96cbb2f403a556a62bae17326def1e90c4c8f Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 12:49:30 -0800 Subject: [PATCH 089/195] Removed un-needed libraries from particle effect entity --- libraries/entities/src/ParticleEffectEntityItem.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index da8e369841..16196aa129 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -33,8 +33,6 @@ #include #include #include -#include -#include #include "EntityTree.h" #include "EntityTreeElement.h" From 035ca25b485d6d712abeac8975bd9eecda455fe1 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 13:31:27 -0800 Subject: [PATCH 090/195] arc ball finds other balls --- examples/flowArts/arcBall/arcBall.js | 149 ++++++++++++++++++ .../flowArts/arcBall/arcBallEntityScript.js | 45 ++++++ examples/flowArts/flowArtsHutSpawner.js | 9 +- examples/flowArts/lightBall/lightBall.js | 10 +- 4 files changed, 206 insertions(+), 7 deletions(-) create mode 100644 examples/flowArts/arcBall/arcBall.js create mode 100644 examples/flowArts/arcBall/arcBallEntityScript.js diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js new file mode 100644 index 0000000000..3853830863 --- /dev/null +++ b/examples/flowArts/arcBall/arcBall.js @@ -0,0 +1,149 @@ +// +// arcBall.js +// examples/arcBall +// +// Created by Eric Levin on 12/17/15. +// Copyright 2014 High Fidelity, Inc. +// +// This script creats a particle light ball which makes particle trails as you move it. +// +// +// 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("../../libraries/utils.js"); + + +var scriptURL = Script.resolvePath("arcBallEntityScript.js"); +ArcBall = function(spawnPosition) { + + var colorPalette = [{ + red: 25, + green: 20, + blue: 162 + }]; + + + var containerBall = Entities.addEntity({ + type: "Sphere", + name: "Arc Ball", + script: scriptURL, + position: Vec3.sum(spawnPosition, { + x: 0, + y: .5, + z: 0 + }), + dimensions: { + x: .1, + y: .1, + z: .1 + }, + color: { + red: 15, + green: 10, + blue: 150 + }, + mass: 10, + collisionsWillMove: true, + // gravity: { + // x: 0, + // y: -0.5, + // z: 0 + // }, + userData: JSON.stringify({ + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: .1, + z: 0 + } + }, + invertSolidWhileHeld: true + } + }) + }); + + + var light = Entities.addEntity({ + type: 'Light', + name: "ballLight", + parentID: containerBall, + dimensions: { + x: 30, + y: 30, + z: 30 + }, + color: colorPalette[randInt(0, colorPalette.length)], + intensity: 5 + }); + + + var arcBall = Entities.addEntity({ + type: "ParticleEffect", + parentID: containerBall, + isEmitting: true, + name: "Arc Ball Particle Effect", + colorStart: { + red: 200, + green: 20, + blue: 40 + }, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: { + red: 25, + green: 20, + blue: 255 + }, + maxParticles: 100000, + lifespan: 2, + emitRate: 10000, + emitSpeed: .1, + lifetime: -1, + speedSpread: 0.0, + emitDimensions: { + x: 0, + y: 0, + z: 0 + }, + polarStart: 0, + polarFinish: Math.PI, + azimuthStart: -Math.PI, + azimuthFinish: Math.PI, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + particleRadius: 0.02, + radiusSpread: 0, + radiusStart: 0.03, + radiusFinish: 0.0003, + alpha: 0, + alphaSpread: .5, + alphaStart: 0, + alphaFinish: 0.5, + textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + emitterShouldTrail: true + }) + + + + function cleanup() { + Entities.deleteEntity(arcBall); + Entities.deleteEntity(containerBall); + Entities.deleteEntity(light); + } + + this.cleanup = cleanup; +} \ No newline at end of file diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js new file mode 100644 index 0000000000..bcdb2bc5a9 --- /dev/null +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -0,0 +1,45 @@ +// arcBallEntityScript.js +// +// Script Type: Entity +// Created by Eric Levin on 12/17/15. +// Copyright 2015 High Fidelity, Inc. +// +// This entity script handles the logic for the arcBall rave toy +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + Script.include("../../libraries/utils.js"); + var _this; + var ArcBall = function() { + _this = this; + }; + + ArcBall.prototype = { + isGrabbed: false, + startNearGrab: function() { + //Search for nearby balls and create an arc to it if one is found + var position = Entities.getEntityProperties(this.entityID, "position").position + var entities = Entities.findEntities(position, 10); + entities.forEach(function(entity) { + var props = Entities.getEntityProperties(entity, ["position", "name"]); + if (props.name === "Arc Ball" && JSON.stringify(_this.entityID) !== JSON.stringify(entity)) { + print ("WE FOUND ANOTHER ARC BALL"); + } + }) + + }, + + continueNearGrab: function() { + }, + + releaseGrab: function() { + }, + + preload: function(entityID) { + this.entityID = entityID; + }, + }; + return new ArcBall(); +}); diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index 3762c67fe4..742b239981 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -17,6 +17,7 @@ Script.include("../../libraries/utils.js"); Script.include("lightBall/LightBall.js"); Script.include("raveStick/RaveStick.js"); Script.include("lightSaber/LightSaber.js"); +Script.include("arcBall/ArcBall.js"); @@ -24,7 +25,10 @@ var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Ca basePosition.y = MyAvatar.position.y + 1; // RAVE ITEMS -var lightBall = new LightBall(basePosition); +//var lightBall = new LightBall(basePosition); + +var arcBall = new ArcBall(basePosition); +var arcBall2 = new ArcBall(Vec3.sum(basePosition, {x: -1, y: 0, z: 0})); var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 0.5, z: 1})); var lightSaber = new LightSaber(Vec3.sum(basePosition, {x: 3, y: 0.5, z: 1})); @@ -77,7 +81,8 @@ function cleanup() { Entities.deleteEntity(raveRoom); Entities.deleteEntity(lightZone) Entities.deleteEntity(floor); - lightBall.cleanup(); + arcBall.cleanup(); + arcBall2.cleanup(); raveStick.cleanup(); lightSaber.cleanup(); } diff --git a/examples/flowArts/lightBall/lightBall.js b/examples/flowArts/lightBall/lightBall.js index 1898f86eef..df62b1b786 100644 --- a/examples/flowArts/lightBall/lightBall.js +++ b/examples/flowArts/lightBall/lightBall.js @@ -42,11 +42,11 @@ LightBall = function(spawnPosition) { blue: 150 }, collisionsWillMove: true, - gravity: { - x: 0, - y: -0.5, - z: 0 - }, + // gravity: { + // x: 0, + // y: -0.5, + // z: 0 + // }, userData: JSON.stringify({ grabbableKey: { spatialKey: { From 3e6ae7c5710e99f2508022bb80082b4fcc73911b Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 15:02:25 -0800 Subject: [PATCH 091/195] added lightball back --- examples/flowArts/arcBall/arcBall.js | 8 +- .../flowArts/arcBall/arcBallEntityScript.js | 80 +++++++++++++++++-- examples/flowArts/flowArtsHutSpawner.js | 13 +-- .../lightSaber/lightSaberEntityScript.js | 3 +- 4 files changed, 88 insertions(+), 16 deletions(-) diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js index 3853830863..34578cce76 100644 --- a/examples/flowArts/arcBall/arcBall.js +++ b/examples/flowArts/arcBall/arcBall.js @@ -35,9 +35,9 @@ ArcBall = function(spawnPosition) { z: 0 }), dimensions: { - x: .1, - y: .1, - z: .1 + x: .2, + y: .2, + z: .2 }, color: { red: 15, @@ -102,7 +102,7 @@ ArcBall = function(spawnPosition) { }, maxParticles: 100000, lifespan: 2, - emitRate: 10000, + emitRate: 1000, emitSpeed: .1, lifetime: -1, speedSpread: 0.0, diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index bcdb2bc5a9..f1ba9aeb95 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -25,16 +25,86 @@ entities.forEach(function(entity) { var props = Entities.getEntityProperties(entity, ["position", "name"]); if (props.name === "Arc Ball" && JSON.stringify(_this.entityID) !== JSON.stringify(entity)) { - print ("WE FOUND ANOTHER ARC BALL"); + _this.createBeam(position, props.position); } - }) + }); }, - continueNearGrab: function() { + createBeam: function(startPosition, endPosition) { + print("CREATE BEAM") + // Creates particle arc from start position to end position + var sourceToTargetVec = Vec3.subtract(endPosition, startPosition); + var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); + + testBox = Entities.addEntity({ + type: "Box", + dimensions: {x: .1, y: .1, z: 1}, + color: {red: 200, green: 10, blue: 10}, + position: startPosition, + rotation: emitOrientation + }); + var color = { + red: 200, + green: 10, + blue: 10 + }; + var props = { + type: "ParticleEffect", + name: "Particle Arc", + parentID: this.entityID, + isEmitting: true, + colorStart: color, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 2, + emitRate: 1000, + emitOrientation: emitOrientation, + emitSpeed: .4, + speedSpread: 0.0, + emitDimensions: { + x: 0, + y: 0, + z: 0 + }, + polarStart: 0, + polarFinish: .0, + azimuthStart: .1, + azimuthFinish: .01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + radiusStart: 0.03, + adiusFinish: 0.025, + alpha: 0.7, + alphaSpread: .1, + alphaStart: 0.5, + alphaFinish: 0.5, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", + emitterShouldTrail: false + } + this.particleArc = Entities.addEntity(props); }, - releaseGrab: function() { + continueNearGrab: function() {}, + + releaseGrab: function() {}, + + unload: function() { + Entities.deleteEntity(this.particleArc); + Entities.deleteEntity(testBox); }, preload: function(entityID) { @@ -42,4 +112,4 @@ }, }; return new ArcBall(); -}); +}); \ No newline at end of file diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index 742b239981..e03d2bf0e8 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -25,10 +25,10 @@ var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Ca basePosition.y = MyAvatar.position.y + 1; // RAVE ITEMS -//var lightBall = new LightBall(basePosition); +var lightBall = new LightBall(basePosition); -var arcBall = new ArcBall(basePosition); -var arcBall2 = new ArcBall(Vec3.sum(basePosition, {x: -1, y: 0, z: 0})); +// var arcBall = new ArcBall(basePosition); +// var arcBall2 = new ArcBall(Vec3.sum(basePosition, {x: -1, y: 0, z: 0})); var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 0.5, z: 1})); var lightSaber = new LightSaber(Vec3.sum(basePosition, {x: 3, y: 0.5, z: 1})); @@ -79,10 +79,11 @@ var lightZone = Entities.addEntity({ function cleanup() { Entities.deleteEntity(raveRoom); - Entities.deleteEntity(lightZone) + Entities.deleteEntity(lightZone); Entities.deleteEntity(floor); - arcBall.cleanup(); - arcBall2.cleanup(); + lightBall.cleanup(); + // arcBall.cleanup(); + // arcBall2.cleanup(); raveStick.cleanup(); lightSaber.cleanup(); } diff --git a/examples/flowArts/lightSaber/lightSaberEntityScript.js b/examples/flowArts/lightSaber/lightSaberEntityScript.js index 6f396bf6e3..794e241924 100644 --- a/examples/flowArts/lightSaber/lightSaberEntityScript.js +++ b/examples/flowArts/lightSaber/lightSaberEntityScript.js @@ -56,7 +56,8 @@ this.props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); var forwardVec = Quat.getFront(Quat.multiply(this.props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); // forwardVec = Vec3.normalize(forwardVec); - var forwardQuat = orientationOf(forwardVec); + // var forwardQuat = orientationOf(forwardVec); + var forwardQuat = Quat.rotationBetween(Vec3.UNIT_Z, forwardVec); var position = Vec3.sum(this.props.position, Vec3.multiply(Quat.getFront(this.props.rotation), 0.1)); position.z += 0.1; position.x += -0.035; From b271542b73b0446e656e016e829adfd2d13c50af Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Dec 2015 12:06:49 -0800 Subject: [PATCH 092/195] Save DebugMode to setting, restore on script start --- examples/utilities/tools/renderEngineDebug.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index 2c0dc352b4..5e4eded640 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -1,6 +1,7 @@ // -// SunLightExample.js -// examples +// renderEngineDebug.js +// examples/utilities/tools +// // Sam Gateau // Copyright 2015 High Fidelity, Inc. // @@ -12,6 +13,7 @@ Script.include("cookies.js"); var MENU = "Developer>Render>Debug Deferred Buffer"; var ACTIONS = ["Off", "Diffuse", "Alpha", "Specular", "Roughness", "Normal", "Depth", "Lighting", "Custom"]; +var SETTINGS_KEY = "EngineDebugScript.DebugMode"; Number.prototype.clamp = function(min, max) { return Math.min(Math.max(this, min), max); @@ -69,6 +71,9 @@ var overlaysCounter = new CounterWidget(panel, "Overlays", ); var resizing = false; +var previousMode = Settings.getValue(SETTINGS_KEY, -1); +Menu.addActionGroup(MENU, ACTIONS, ACTIONS[previousMode + 1]); +Scene.setEngineDeferredDebugMode(previousMode); Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size function setEngineDeferredDebugSize(eventX) { @@ -152,11 +157,11 @@ Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Menu.menuItemEvent.connect(menuItemEvent); -Menu.addActionGroup(MENU, ACTIONS, ACTIONS[0]); function scriptEnding() { panel.destroy(); Menu.removeActionGroup(MENU); + Settings.setValue(SETTINGS_KEY, Scene.getEngineDeferredDebugMode()); Scene.setEngineDeferredDebugMode(-1); Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size } From 06d7de7106c4b87e0f5fd83d840a58135acdf3a4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Dec 2015 15:16:37 -0800 Subject: [PATCH 093/195] Make Shader interface take more consts --- libraries/gpu/src/gpu/Shader.cpp | 4 ++-- libraries/gpu/src/gpu/Shader.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index ddb3a0d755..74b7734618 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -23,7 +23,7 @@ Shader::Shader(Type type, const Source& source): { } -Shader::Shader(Type type, Pointer& vertex, Pointer& pixel): +Shader::Shader(Type type, const Pointer& vertex, const Pointer& pixel): _type(type) { _shaders.resize(2); @@ -44,7 +44,7 @@ Shader::Pointer Shader::createPixel(const Source& source) { return Pointer(new Shader(PIXEL, source)); } -Shader::Pointer Shader::createProgram(Pointer& vertexShader, Pointer& pixelShader) { +Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& pixelShader) { if (vertexShader && vertexShader->getType() == VERTEX && pixelShader && pixelShader->getType() == PIXEL) { return Pointer(new Shader(PROGRAM, vertexShader, pixelShader)); diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index bceb00c71e..b737a42e12 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -111,7 +111,7 @@ public: static Pointer createVertex(const Source& source); static Pointer createPixel(const Source& source); - static Pointer createProgram(Pointer& vertexShader, Pointer& pixelShader); + static Pointer createProgram(const Pointer& vertexShader, const Pointer& pixelShader); ~Shader(); @@ -157,7 +157,7 @@ public: protected: Shader(Type type, const Source& source); - Shader(Type type, Pointer& vertex, Pointer& pixel); + Shader(Type type, const Pointer& vertex, const Pointer& pixel); Shader(const Shader& shader); // deep copy of the sysmem shader Shader& operator=(const Shader& shader); // deep copy of the sysmem texture From 9d6618c341236d81d12a4153baa09a82fc4beca8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Dec 2015 15:17:03 -0800 Subject: [PATCH 094/195] Cleanup DebugDeferredBuffer code --- examples/utilities/tools/renderEngineDebug.js | 1 - .../render-utils/src/DebugDeferredBuffer.cpp | 115 ++++++++---------- .../render-utils/src/DebugDeferredBuffer.h | 10 +- .../src/debug_deferred_buffer.slf | 6 +- 4 files changed, 57 insertions(+), 75 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index 5e4eded640..5e89bff53b 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -90,7 +90,6 @@ function menuItemEvent(menuItem) { var index = ACTIONS.indexOf(menuItem); if (index >= 0) { Scene.setEngineDeferredDebugMode(index - 1); - print(menuItem); } } diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 169ae0b58e..2046a48d4a 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -11,8 +11,6 @@ #include "DebugDeferredBuffer.h" -#include - #include #include #include @@ -31,73 +29,62 @@ enum Slots { Normal, Specular, Depth, - Lighting, - - NUM_SLOTS + Lighting }; -static const std::array SLOT_NAMES {{ - "diffuseMap", - "normalMap", - "specularMap", - "depthMap", - "lightingMap" -}}; -static const std::string COMPUTE_PLACEHOLDER { "/*COMPUTE_PLACEHOLDER*/" }; // required -static const std::string FUNCTIONS_PLACEHOLDER { "/*FUNCTIONS_PLACEHOLDER*/" }; // optional - -std::string DebugDeferredBuffer::getCode(Modes mode) { +std::string DebugDeferredBuffer::getShaderSourceCode(Modes mode) { switch (mode) { - case DiffuseMode: { - QString code = "return vec4(pow(texture(%1, uv).xyz, vec3(1.0 / 2.2)), 1.0);"; - return code.arg(SLOT_NAMES[Diffuse].c_str()).toStdString(); - } - case AlphaMode: { - QString code = "return vec4(vec3(texture(%1, uv).a), 1.0);"; - return code.arg(SLOT_NAMES[Diffuse].c_str()).toStdString(); - } - case SpecularMode: { - QString code = "return vec4(texture(%1, uv).xyz, 1.0);"; - return code.arg(SLOT_NAMES[Specular].c_str()).toStdString(); - } - case RoughnessMode: { - QString code = "return vec4(vec3(texture(%1, uv).a), 1.0);"; - return code.arg(SLOT_NAMES[Specular].c_str()).toStdString(); - } - case NormalMode: { - QString code = "return vec4(texture(%1, uv).xyz, 1.0);"; - return code.arg(SLOT_NAMES[Normal].c_str()).toStdString(); - } - case DepthMode: { - QString code = "return vec4(vec3(texture(%1, uv).x), 1.0);"; - return code.arg(SLOT_NAMES[Depth].c_str()).toStdString(); - } - case LightingMode: { - QString code = "return vec4(pow(texture(%1, uv).xyz, vec3(1.0 / 2.2)), 1.0);"; - return code.arg(SLOT_NAMES[Lighting].c_str()).toStdString(); - } + case DiffuseMode: + return "vec4 getFragmentColor() { return vec4(pow(texture(diffuseMap, uv).xyz, vec3(1.0 / 2.2)), 1.0); }"; + case AlphaMode: + return "vec4 getFragmentColor() { return vec4(vec3(texture(diffuseMap, uv).a), 1.0); }"; + case SpecularMode: + return "vec4 getFragmentColor() { return vec4(texture(specularMap, uv).xyz, 1.0); }"; + case RoughnessMode: + return "vec4 getFragmentColor() { return vec4(vec3(texture(specularMap, uv).a), 1.0); }"; + case NormalMode: + return "vec4 getFragmentColor() { return vec4(texture(normalMap, uv).xyz, 1.0); }"; + case DepthMode: + return "vec4 getFragmentColor() { return vec4(vec3(texture(depthMap, uv).x), 1.0); }"; + case LightingMode: + return "vec4 getFragmentColor() { return vec4(pow(texture(lightingMap, uv).xyz, vec3(1.0 / 2.2)), 1.0); }"; case CustomMode: - return std::string("return vec4(1.0);"); - case NUM_MODES: - Q_UNIMPLEMENTED(); - return std::string("return vec4(1.0);"); + return "vec4 getFragmentColor() { return vec4(1.0); }"; } } +bool DebugDeferredBuffer::pipelineNeedsUpdate(Modes mode) const { + if (mode != CustomMode) { + return !_pipelines[mode]; + } + + + + return true; +} + const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode) { - if (!_pipelines[mode]) { - std::string fragmentShader = debug_deferred_buffer_frag; - fragmentShader.replace(fragmentShader.find(COMPUTE_PLACEHOLDER), COMPUTE_PLACEHOLDER.size(), - getCode(mode)); + if (pipelineNeedsUpdate(mode)) { + static const std::string VERTEX_SHADER { debug_deferred_buffer_vert }; + static const std::string FRAGMENT_SHADER { debug_deferred_buffer_frag }; + static const std::string SOURCE_PLACEHOLDER { "//SOURCE_PLACEHOLDER" }; + static const auto SOURCE_PLACEHOLDER_INDEX = FRAGMENT_SHADER.find(SOURCE_PLACEHOLDER); + Q_ASSERT_X(SOURCE_PLACEHOLDER_INDEX != std::string::npos, Q_FUNC_INFO, "Could not find source placeholder"); - auto vs = gpu::ShaderPointer(gpu::Shader::createVertex({ debug_deferred_buffer_vert })); - auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(fragmentShader)); - auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + auto bakedFragmentShader = FRAGMENT_SHADER; + bakedFragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), + getShaderSourceCode(mode)); + + const auto vs = gpu::Shader::createVertex(VERTEX_SHADER); + const auto ps = gpu::Shader::createPixel(bakedFragmentShader); + const auto program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; - for (int slot = 0; slot < NUM_SLOTS; ++slot) { - slotBindings.insert(gpu::Shader::Binding(SLOT_NAMES[slot], slot)); - } + slotBindings.insert(gpu::Shader::Binding("diffuseMap", Diffuse)); + slotBindings.insert(gpu::Shader::Binding("normalMap", Normal)); + slotBindings.insert(gpu::Shader::Binding("specularMap", Specular)); + slotBindings.insert(gpu::Shader::Binding("depthMap", Depth)); + slotBindings.insert(gpu::Shader::Binding("lightingMap", Lighting)); gpu::Shader::makeProgram(*program, slotBindings); // Good to go add the brand new pipeline @@ -110,10 +97,10 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode) { void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); - RenderArgs* args = renderContext->args; + const RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - auto geometryBuffer = DependencyManager::get(); - auto framebufferCache = DependencyManager::get(); + const auto geometryBuffer = DependencyManager::get(); + const auto framebufferCache = DependencyManager::get(); glm::mat4 projMat; @@ -132,9 +119,9 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture()); batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture()); - glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); - glm::vec2 bottomLeft(renderContext->_deferredDebugSize.x, renderContext->_deferredDebugSize.y); - glm::vec2 topRight(renderContext->_deferredDebugSize.z, renderContext->_deferredDebugSize.w); + const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); + const glm::vec2 bottomLeft(renderContext->_deferredDebugSize.x, renderContext->_deferredDebugSize.y); + const glm::vec2 topRight(renderContext->_deferredDebugSize.z, renderContext->_deferredDebugSize.w); geometryBuffer->renderQuad(batch, bottomLeft, topRight, color); }); } \ No newline at end of file diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 8628d9e21e..144a72571c 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -21,7 +21,7 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); private: - enum Modes : int { + enum Modes : uint8_t { DiffuseMode = 0, AlphaMode, SpecularMode, @@ -29,15 +29,15 @@ private: NormalMode, DepthMode, LightingMode, - CustomMode, - NUM_MODES + CustomMode // Needs to stay last }; + bool pipelineNeedsUpdate(Modes mode) const; const gpu::PipelinePointer& getPipeline(Modes mode); - std::string getCode(Modes mode); + std::string getShaderSourceCode(Modes mode); - std::array _pipelines; + std::array _pipelines; }; #endif // hifi_DebugDeferredBuffer_h \ No newline at end of file diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index d8ff6e71a9..375972cdc3 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -17,11 +17,7 @@ in vec2 uv; out vec4 outFragColor; -/*FUNCTIONS_PLACEHOLDER*/ - -vec4 getFragmentColor() { - /*COMPUTE_PLACEHOLDER*/ -} +//SOURCE_PLACEHOLDER void main(void) { outFragColor = getFragmentColor(); From d8a389ff925f795ad364e7e1f425b0784af65955 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 16 Dec 2015 17:20:51 -0800 Subject: [PATCH 095/195] First cut at custom pipelines --- libraries/render-utils/src/DebugDeferredBuffer.cpp | 14 +++++++++++--- libraries/render-utils/src/DebugDeferredBuffer.h | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 2046a48d4a..7dbeddd07a 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -11,6 +11,8 @@ #include "DebugDeferredBuffer.h" +#include + #include #include #include @@ -32,6 +34,14 @@ enum Slots { Lighting }; +static std::string getFileContent(std::string fileName, std::string defaultContent = std::string()) { + QFile customFile(QString::fromStdString(fileName)); + if (customFile.open(QIODevice::ReadOnly)) { + return customFile.readAll().toStdString(); + } + return defaultContent; +} + std::string DebugDeferredBuffer::getShaderSourceCode(Modes mode) { switch (mode) { case DiffuseMode: @@ -49,7 +59,7 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Modes mode) { case LightingMode: return "vec4 getFragmentColor() { return vec4(pow(texture(lightingMap, uv).xyz, vec3(1.0 / 2.2)), 1.0); }"; case CustomMode: - return "vec4 getFragmentColor() { return vec4(1.0); }"; + return getFileContent(CUSTOM_FILE, "vec4 getFragmentColor() { return vec4(1.0); }"); } } @@ -58,8 +68,6 @@ bool DebugDeferredBuffer::pipelineNeedsUpdate(Modes mode) const { return !_pipelines[mode]; } - - return true; } diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 144a72571c..a0df42c05a 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -33,6 +33,8 @@ private: CustomMode // Needs to stay last }; + const std::string CUSTOM_FILE { "/Users/clement/Desktop/custom.slh" }; + bool pipelineNeedsUpdate(Modes mode) const; const gpu::PipelinePointer& getPipeline(Modes mode); std::string getShaderSourceCode(Modes mode); From f41ca9fc50752913984400514cc15aab32f692d5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 17 Dec 2015 15:13:09 -0800 Subject: [PATCH 096/195] More custom debug work --- .../render-utils/src/DebugDeferredBuffer.cpp | 115 +++++++++++++++--- .../render-utils/src/DebugDeferredBuffer.h | 21 +++- 2 files changed, 111 insertions(+), 25 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 7dbeddd07a..6bdfbb57ff 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -34,56 +34,119 @@ enum Slots { Lighting }; +static const std::string DEEFAULT_DIFFUSE_SHADER { + "vec4 getFragmentColor() {" + " return vec4(pow(texture(diffuseMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);" + " }" +}; +static const std::string DEEFAULT_ALPHA_SHADER { + "vec4 getFragmentColor() {" + " return vec4(vec3(texture(diffuseMap, uv).a), 1.0);" + " }" +}; +static const std::string DEEFAULT_SPECULAR_SHADER { + "vec4 getFragmentColor() {" + " return vec4(texture(specularMap, uv).xyz, 1.0);" + " }" +}; +static const std::string DEEFAULT_ROUGHNESS_SHADER { + "vec4 getFragmentColor() {" + " return vec4(vec3(texture(specularMap, uv).a), 1.0);" + " }" +}; +static const std::string DEEFAULT_NORMAL_SHADER { + "vec4 getFragmentColor() {" + " return vec4(texture(normalMap, uv).xyz, 1.0);" + " }" +}; +static const std::string DEEFAULT_DEPTH_SHADER { + "vec4 getFragmentColor() {" + " return vec4(vec3(texture(depthMap, uv).x), 1.0);" + " }" +}; +static const std::string DEEFAULT_LIGHTING_SHADER { + "vec4 getFragmentColor() {" + " return vec4(pow(texture(lightingMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);" + " }" +}; +static const std::string DEEFAULT_CUSTOM_SHADER { + "vec4 getFragmentColor() {" + " return vec4(1.0, 0.0, 0.0, 1.0);" + " }" +}; + static std::string getFileContent(std::string fileName, std::string defaultContent = std::string()) { - QFile customFile(QString::fromStdString(fileName)); + QFile customFile(QUrl(QString::fromStdString(fileName)).toLocalFile()); if (customFile.open(QIODevice::ReadOnly)) { return customFile.readAll().toStdString(); } + qWarning() << "DebugDeferredBuffer::getFileContent(): Could not open" + << QUrl(QString::fromStdString(fileName)).toLocalFile(); return defaultContent; } -std::string DebugDeferredBuffer::getShaderSourceCode(Modes mode) { +#include // TODO REMOVE: Temporary until UI +DebugDeferredBuffer::DebugDeferredBuffer() { + // TODO REMOVE: Temporary until UI + static const auto DESKTOP_PATH = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); + static const auto CUSTOM_FILE = "file://" + DESKTOP_PATH.toStdString() + "/custom.slh"; + CustomPipeline pipeline; + pipeline.info = QFileInfo(DESKTOP_PATH + "/custom.slh"); + _customPipelines.emplace(CUSTOM_FILE, pipeline); +} + +std::string DebugDeferredBuffer::getShaderSourceCode(Modes mode, std::string customFile) { switch (mode) { case DiffuseMode: - return "vec4 getFragmentColor() { return vec4(pow(texture(diffuseMap, uv).xyz, vec3(1.0 / 2.2)), 1.0); }"; + return DEEFAULT_DIFFUSE_SHADER; case AlphaMode: - return "vec4 getFragmentColor() { return vec4(vec3(texture(diffuseMap, uv).a), 1.0); }"; + return DEEFAULT_ALPHA_SHADER; case SpecularMode: - return "vec4 getFragmentColor() { return vec4(texture(specularMap, uv).xyz, 1.0); }"; + return DEEFAULT_SPECULAR_SHADER; case RoughnessMode: - return "vec4 getFragmentColor() { return vec4(vec3(texture(specularMap, uv).a), 1.0); }"; + return DEEFAULT_ROUGHNESS_SHADER; case NormalMode: - return "vec4 getFragmentColor() { return vec4(texture(normalMap, uv).xyz, 1.0); }"; + return DEEFAULT_NORMAL_SHADER; case DepthMode: - return "vec4 getFragmentColor() { return vec4(vec3(texture(depthMap, uv).x), 1.0); }"; + return DEEFAULT_DEPTH_SHADER; case LightingMode: - return "vec4 getFragmentColor() { return vec4(pow(texture(lightingMap, uv).xyz, vec3(1.0 / 2.2)), 1.0); }"; + return DEEFAULT_LIGHTING_SHADER; case CustomMode: - return getFileContent(CUSTOM_FILE, "vec4 getFragmentColor() { return vec4(1.0); }"); + return getFileContent(customFile, DEEFAULT_CUSTOM_SHADER); } } -bool DebugDeferredBuffer::pipelineNeedsUpdate(Modes mode) const { +bool DebugDeferredBuffer::pipelineNeedsUpdate(Modes mode, std::string customFile) const { if (mode != CustomMode) { return !_pipelines[mode]; } + auto it = _customPipelines.find(customFile); + if (it != _customPipelines.end() && it->second.pipeline) { + auto& info = it->second.info; + + auto lastModified = info.lastModified(); + info.refresh(); + return lastModified != info.lastModified(); + } + return true; } -const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode) { - if (pipelineNeedsUpdate(mode)) { +const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode, std::string customFile) { + if (pipelineNeedsUpdate(mode, customFile)) { static const std::string VERTEX_SHADER { debug_deferred_buffer_vert }; static const std::string FRAGMENT_SHADER { debug_deferred_buffer_frag }; static const std::string SOURCE_PLACEHOLDER { "//SOURCE_PLACEHOLDER" }; static const auto SOURCE_PLACEHOLDER_INDEX = FRAGMENT_SHADER.find(SOURCE_PLACEHOLDER); - Q_ASSERT_X(SOURCE_PLACEHOLDER_INDEX != std::string::npos, Q_FUNC_INFO, "Could not find source placeholder"); + Q_ASSERT_X(SOURCE_PLACEHOLDER_INDEX != std::string::npos, Q_FUNC_INFO, + "Could not find source placeholder"); auto bakedFragmentShader = FRAGMENT_SHADER; bakedFragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), - getShaderSourceCode(mode)); + getShaderSourceCode(mode, customFile)); - const auto vs = gpu::Shader::createVertex(VERTEX_SHADER); + static const auto vs = gpu::Shader::createVertex(VERTEX_SHADER); const auto ps = gpu::Shader::createPixel(bakedFragmentShader); const auto program = gpu::Shader::createProgram(vs, ps); @@ -95,10 +158,21 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode) { slotBindings.insert(gpu::Shader::Binding("lightingMap", Lighting)); gpu::Shader::makeProgram(*program, slotBindings); + auto pipeline = gpu::Pipeline::create(program, std::make_shared()); + // Good to go add the brand new pipeline - _pipelines[mode] = gpu::Pipeline::create(program, std::make_shared()); + if (mode != CustomMode) { + _pipelines[mode] = pipeline; + } else { + _customPipelines[customFile].pipeline = pipeline; + } + } + + if (mode != CustomMode) { + return _pipelines[mode]; + } else { + return _customPipelines[customFile].pipeline; } - return _pipelines[mode]; } @@ -118,8 +192,11 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); + + // TODO REMOVE: Temporary until UI + auto first = _customPipelines.begin()->first; - batch.setPipeline(getPipeline(Modes(renderContext->_deferredDebugMode))); + batch.setPipeline(getPipeline(Modes(renderContext->_deferredDebugMode), first)); batch.setResourceTexture(Diffuse, framebufferCache->getDeferredColorTexture()); batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture()); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index a0df42c05a..682888b2af 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -12,12 +12,16 @@ #ifndef hifi_DebugDeferredBuffer_h #define hifi_DebugDeferredBuffer_h +#include + #include class DebugDeferredBuffer { public: using JobModel = render::Job::Model; + DebugDeferredBuffer(); + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); private: @@ -32,14 +36,19 @@ private: CustomMode // Needs to stay last }; + struct CustomPipeline { + gpu::PipelinePointer pipeline; + mutable QFileInfo info; + }; + using StandardPipelines = std::array; + using CustomPipelines = std::unordered_map; - const std::string CUSTOM_FILE { "/Users/clement/Desktop/custom.slh" }; + bool pipelineNeedsUpdate(Modes mode, std::string customFile = std::string()) const; + const gpu::PipelinePointer& getPipeline(Modes mode, std::string customFile = std::string()); + std::string getShaderSourceCode(Modes mode, std::string customFile = std::string()); - bool pipelineNeedsUpdate(Modes mode) const; - const gpu::PipelinePointer& getPipeline(Modes mode); - std::string getShaderSourceCode(Modes mode); - - std::array _pipelines; + StandardPipelines _pipelines; + CustomPipelines _customPipelines; }; #endif // hifi_DebugDeferredBuffer_h \ No newline at end of file From aa1f77ab1c6e0294983e2f8f4c18bfa7dbef2772 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 15:42:52 -0800 Subject: [PATCH 097/195] adding ravestick to toybox demo room --- examples/flowArts/raveStick/RaveStick.js | 62 +++++++++ .../raveStick/raveStickEntityScript.js | 62 --------- unpublishedScripts/hiddenEntityReset.js | 115 ++++++++++++++++- unpublishedScripts/masterReset.js | 118 +++++++++++++++++- 4 files changed, 292 insertions(+), 65 deletions(-) diff --git a/examples/flowArts/raveStick/RaveStick.js b/examples/flowArts/raveStick/RaveStick.js index fd3c98b6e5..3e4cf16136 100644 --- a/examples/flowArts/raveStick/RaveStick.js +++ b/examples/flowArts/raveStick/RaveStick.js @@ -64,11 +64,73 @@ RaveStick = function(spawnPosition) { intensity: 5 }); + var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0) + var forwardVec = Quat.getFront(Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); + forwardVec = Vec3.normalize(forwardVec); + var forwardQuat = orientationOf(forwardVec); + var position = Vec3.sum(spawnPosition, Vec3.multiply(Quat.getFront(rotation), 0.1)); + position.z += 0.1; + position.x += -0.035; + var color = { + red: 0, + green: 200, + blue: 40 + }; + var props = { + type: "ParticleEffect", + position: position, + parentID: stick, + isEmitting: true, + name: "raveBeam", + colorStart: color, + colorSpread: { + red: 200, + green: 10, + blue: 10 + }, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 1, + emitRate: 1000, + emitOrientation: forwardQuat, + emitSpeed: .2, + speedSpread: 0.0, + polarStart: 0, + polarFinish: .0, + azimuthStart: .1, + azimuthFinish: .01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + radiusStart: 0.03, + radiusFinish: 0.025, + alpha: 0.7, + alphaSpread: .1, + alphaStart: 0.5, + alphaFinish: 0.5, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", + emitterShouldTrail: false, + } + var beam = Entities.addEntity(props); + function cleanup() { Entities.deleteEntity(stick); Entities.deleteEntity(light); + Entities.deleteEntity(beam); } this.cleanup = cleanup; diff --git a/examples/flowArts/raveStick/raveStickEntityScript.js b/examples/flowArts/raveStick/raveStickEntityScript.js index 171b53e0cf..2e174c78f0 100644 --- a/examples/flowArts/raveStick/raveStickEntityScript.js +++ b/examples/flowArts/raveStick/raveStickEntityScript.js @@ -58,7 +58,6 @@ isGrabbed: false, startNearGrab: function() { - // this.createBeam(); this.trailBasePosition = Entities.getEntityProperties(this.entityID, "position").position; Entities.editEntity(this.trail, { position: this.trailBasePosition @@ -125,7 +124,6 @@ preload: function(entityID) { this.entityID = entityID; - this.createBeam(); }, unload: function() { @@ -134,66 +132,6 @@ if (this.trailEraseInterval) { Script.clearInterval(this.trailEraseInterval); } - }, - - createBeam: function() { - - var props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); - var forwardVec = Quat.getFront(Quat.multiply(props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); - forwardVec = Vec3.normalize(forwardVec); - var forwardQuat = orientationOf(forwardVec); - var position = Vec3.sum(props.position, Vec3.multiply(Quat.getFront(props.rotation), 0.1)); - position.z += 0.1; - position.x += -0.035; - var color = this.colorPalette[randInt(0, this.colorPalette.length)]; - var props = { - type: "ParticleEffect", - position: position, - parentID: this.entityID, - isEmitting: true, - name: "raveBeam", - colorStart: color, - colorSpread: { - red: 200, - green: 10, - blue: 10 - }, - color: { - red: 200, - green: 200, - blue: 255 - }, - colorFinish: color, - maxParticles: 100000, - lifespan: 1, - emitRate: 1000, - emitOrientation: forwardQuat, - emitSpeed: .2, - speedSpread: 0.0, - polarStart: 0, - polarFinish: .0, - azimuthStart: .1, - azimuthFinish: .01, - emitAcceleration: { - x: 0, - y: 0, - z: 0 - }, - accelerationSpread: { - x: .00, - y: .00, - z: .00 - }, - radiusStart: 0.03, - radiusFinish: 0.025, - alpha: 0.7, - alphaSpread: .1, - alphaStart: 0.5, - alphaFinish: 0.5, - textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", - emitterShouldTrail: false - } - this.beam = Entities.addEntity(props); } }; return new RaveStick(); diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index ee53e36f9e..e4cf434bf8 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -24,6 +24,7 @@ var lightsScriptURL = Script.resolvePath("../examples/toybox/lights/lightSwitch.js"); var targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js'); var bowScriptURL = Script.resolvePath('../examples/toybox/bow/bow.js'); + var raveStickEntityScriptURL = Script.resolvePath("../examples/flowarts/raveStick/raveStickEntityScript.js"); var basketballResetterScriptURL = Script.resolvePath('basketballsResetter.js'); var targetsResetterScriptURL = Script.resolvePath('targetsResetter.js'); @@ -106,6 +107,13 @@ z: 505.78 }); + createRaveStick({ + x: 547.4, + y: 495.4, + z: 504.5 + }); + + createCombinedArmChair({ x: 549.29, y: 494.9, @@ -160,6 +168,111 @@ }); } + function createRaveStick(position) { + var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/rave/raveStick.fbx"; + var stick = Entities.addEntity({ + type: "Model", + name: "raveStick", + modelURL: modelURL, + position: position, + shapeType: 'box', + collisionsWillMove: true, + script: raveStickEntityScriptURL, + dimensions: { + x: 0.06, + y: 0.06, + z: 0.31 + }, + gravity: { + x: 0, + y: -3, + z: 0 + }, + userData: JSON.stringify({ + resetMe: { + resetMe: true + }, + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 0, + z: -0.1 + }, + relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0) + }, + invertSolidWhileHeld: true + } + }) + }); + var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0) + var forwardVec = Quat.getFront(Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); + forwardVec = Vec3.normalize(forwardVec); + var forwardQuat = orientationOf(forwardVec); + position = Vec3.sum(position, Vec3.multiply(Quat.getFront(rotation), 0.1)); + position.z += 0.1; + position.x += -0.035; + var color = { + red: 0, + green: 200, + blue: 40 + }; + var props = { + type: "ParticleEffect", + position: position, + parentID: stick, + isEmitting: true, + name: "raveBeam", + colorStart: color, + colorSpread: { + red: 200, + green: 10, + blue: 10 + }, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 1, + emitRate: 1000, + emitOrientation: forwardQuat, + emitSpeed: .2, + speedSpread: 0.0, + polarStart: 0, + polarFinish: .0, + azimuthStart: .1, + azimuthFinish: .01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + radiusStart: 0.03, + radiusFinish: 0.025, + alpha: 0.7, + alphaSpread: .1, + alphaStart: 0.5, + alphaFinish: 0.5, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", + emitterShouldTrail: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true + } + }) + } + var beam = Entities.addEntity(props); + + } + function createGun(position) { var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/gun.fbx"; @@ -1391,4 +1504,4 @@ }; // entity scripts always need to return a newly constructed object of our type return new ResetSwitch(); -}); +}); \ No newline at end of file diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 1837f4d656..66c8c74edd 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -23,10 +23,12 @@ var wandScriptURL = Script.resolvePath("../examples/toybox/bubblewand/wand.js"); var dollScriptURL = Script.resolvePath("../examples/toybox/doll/doll.js"); var lightsScriptURL = Script.resolvePath("../examples/toybox/lights/lightSwitch.js"); var bowScriptURL = Script.resolvePath("../examples/toybox/bow/bow.js"); +var raveStickEntityScriptURL = Script.resolvePath("../examples/flowarts/raveStick/raveStickEntityScript.js"); var targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js'); var basketballResetterScriptURL = Script.resolvePath('basketballsResetter.js'); var targetsResetterScriptURL = Script.resolvePath('targetsResetter.js'); + MasterReset = function() { var resetKey = "resetMe"; @@ -80,6 +82,12 @@ MasterReset = function() { z: 505.78 }); + createRaveStick({ + x: 547.4, + y: 495.4, + z: 504.5 + }); + createCombinedArmChair({ @@ -94,6 +102,8 @@ MasterReset = function() { z: 504.53 }); + + createPingPongBallGun(); createTargets(); createTargetResetter(); @@ -137,6 +147,110 @@ MasterReset = function() { }); } + function createRaveStick(position) { + var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/rave/raveStick.fbx"; + var stick = Entities.addEntity({ + type: "Model", + name: "raveStick", + modelURL: modelURL, + position: position, + shapeType: 'box', + collisionsWillMove: true, + script: raveStickEntityScriptURL, + dimensions: { + x: 0.06, + y: 0.06, + z: 0.31 + }, + gravity: { + x: 0, + y: -3, + z: 0 + }, + userData: JSON.stringify({ + resetMe: { + resetMe: true + }, + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 0, + z: -0.1 + }, + relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0) + }, + invertSolidWhileHeld: true + } + }) + }); + var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0) + var forwardVec = Quat.getFront(Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); + forwardVec = Vec3.normalize(forwardVec); + var forwardQuat = orientationOf(forwardVec); + position = Vec3.sum(position, Vec3.multiply(Quat.getFront(rotation), 0.1)); + position.z += 0.1; + position.x += -0.035; + var color = { + red: 0, + green: 200, + blue: 40 + }; + var props = { + type: "ParticleEffect", + position: position, + parentID: stick, + isEmitting: true, + name: "raveBeam", + colorStart: color, + colorSpread: { + red: 200, + green: 10, + blue: 10 + }, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 1, + emitRate: 1000, + emitOrientation: forwardQuat, + emitSpeed: .2, + speedSpread: 0.0, + polarStart: 0, + polarFinish: .0, + azimuthStart: .1, + azimuthFinish: .01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + radiusStart: 0.03, + radiusFinish: 0.025, + alpha: 0.7, + alphaSpread: .1, + alphaStart: 0.5, + alphaFinish: 0.5, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", + emitterShouldTrail: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true + } + }) + } + var beam = Entities.addEntity(props); + + } function createGun(position) { var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/gun.fbx"; @@ -1349,7 +1463,7 @@ MasterReset = function() { resetMe: true }, grabbableKey: { - invertSolidWhileHeld: true + invertSolidWhileHeld: true } }) }); @@ -1366,4 +1480,4 @@ MasterReset = function() { Script.scriptEnding.connect(cleanup); } -}; +}; \ No newline at end of file From 17af34a3be36fdc30ae832f602d5f260358e5cb4 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 17 Dec 2015 15:48:05 -0800 Subject: [PATCH 098/195] fixed spelling error --- unpublishedScripts/hiddenEntityReset.js | 2 +- unpublishedScripts/masterReset.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index e4cf434bf8..cc4037beb4 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -24,7 +24,7 @@ var lightsScriptURL = Script.resolvePath("../examples/toybox/lights/lightSwitch.js"); var targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js'); var bowScriptURL = Script.resolvePath('../examples/toybox/bow/bow.js'); - var raveStickEntityScriptURL = Script.resolvePath("../examples/flowarts/raveStick/raveStickEntityScript.js"); + var raveStickEntityScriptURL = Script.resolvePath("../examples/flowArts/raveStick/raveStickEntityScript.js"); var basketballResetterScriptURL = Script.resolvePath('basketballsResetter.js'); var targetsResetterScriptURL = Script.resolvePath('targetsResetter.js'); diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 66c8c74edd..a1545a3b67 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -23,7 +23,7 @@ var wandScriptURL = Script.resolvePath("../examples/toybox/bubblewand/wand.js"); var dollScriptURL = Script.resolvePath("../examples/toybox/doll/doll.js"); var lightsScriptURL = Script.resolvePath("../examples/toybox/lights/lightSwitch.js"); var bowScriptURL = Script.resolvePath("../examples/toybox/bow/bow.js"); -var raveStickEntityScriptURL = Script.resolvePath("../examples/flowarts/raveStick/raveStickEntityScript.js"); +var raveStickEntityScriptURL = Script.resolvePath("../examples/flowArts/raveStick/raveStickEntityScript.js"); var targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js'); var basketballResetterScriptURL = Script.resolvePath('basketballsResetter.js'); var targetsResetterScriptURL = Script.resolvePath('targetsResetter.js'); From c0a675dd9e49a137669ba189c1ad44441c4ebdc5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 17 Dec 2015 16:02:49 -0800 Subject: [PATCH 099/195] Fix msvc warning --- libraries/render-utils/src/DebugDeferredBuffer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 6bdfbb57ff..3458712106 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -114,6 +114,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Modes mode, std::string cus case CustomMode: return getFileContent(customFile, DEEFAULT_CUSTOM_SHADER); } + Q_UNREACHABLE(); + return std::string(); } bool DebugDeferredBuffer::pipelineNeedsUpdate(Modes mode, std::string customFile) const { From 78b805a19a50a286a446f252dc3bd84db1f8e1ee Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 17 Dec 2015 16:06:55 -0800 Subject: [PATCH 100/195] Fix file shader file lookup on windows --- libraries/render-utils/src/DebugDeferredBuffer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 3458712106..d61b131844 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -76,12 +76,12 @@ static const std::string DEEFAULT_CUSTOM_SHADER { }; static std::string getFileContent(std::string fileName, std::string defaultContent = std::string()) { - QFile customFile(QUrl(QString::fromStdString(fileName)).toLocalFile()); + QFile customFile(QString::fromStdString(fileName)); if (customFile.open(QIODevice::ReadOnly)) { return customFile.readAll().toStdString(); } qWarning() << "DebugDeferredBuffer::getFileContent(): Could not open" - << QUrl(QString::fromStdString(fileName)).toLocalFile(); + << QString::fromStdString(fileName); return defaultContent; } @@ -89,9 +89,9 @@ static std::string getFileContent(std::string fileName, std::string defaultConte DebugDeferredBuffer::DebugDeferredBuffer() { // TODO REMOVE: Temporary until UI static const auto DESKTOP_PATH = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); - static const auto CUSTOM_FILE = "file://" + DESKTOP_PATH.toStdString() + "/custom.slh"; + static const auto CUSTOM_FILE = DESKTOP_PATH.toStdString() + "/custom.slh"; CustomPipeline pipeline; - pipeline.info = QFileInfo(DESKTOP_PATH + "/custom.slh"); + pipeline.info = QFileInfo(QString::fromStdString(CUSTOM_FILE)); _customPipelines.emplace(CUSTOM_FILE, pipeline); } From 762aefbbca611dd51a6c14b7d310738ff50cf8a6 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 17 Dec 2015 17:38:20 -0800 Subject: [PATCH 101/195] add hand driven reticle --- examples/controllers/reticleHandTest.js | 35 +++++++++++++++ examples/controllers/reticleTests.js | 43 ------------------- .../src/controllers/ScriptingInterface.h | 3 ++ 3 files changed, 38 insertions(+), 43 deletions(-) create mode 100644 examples/controllers/reticleHandTest.js diff --git a/examples/controllers/reticleHandTest.js b/examples/controllers/reticleHandTest.js new file mode 100644 index 0000000000..5d0e2f238a --- /dev/null +++ b/examples/controllers/reticleHandTest.js @@ -0,0 +1,35 @@ +// +// reticleTest.js +// examples/controllers +// +// Created by Brad Hefta-Gaub on 2015/12/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 +// + +function moveReticle(pitch, yaw) { + //print("pitch:" + pitch); + //print("yaw:" + yaw); + + var globalPos = Controller.getReticlePosition(); + globalPos.x += yaw; + globalPos.y += pitch; + Controller.setReticlePosition(globalPos); +} + +var MAPPING_NAME = "com.highfidelity.testing.reticleWithHand"; +var mapping = Controller.newMapping(MAPPING_NAME); +mapping.from(Controller.Standard.RightHand).peek().to(function(pose) { + var angularVelocityEADs = Quat.safeEulerAngles(pose.angularVelocity); // degrees + var yaw = isNaN(angularVelocityEADs.y) ? 0 : (-angularVelocityEADs.y / 10); + var pitch = isNaN(angularVelocityEADs.x) ? 0 : (-angularVelocityEADs.x / 10); + moveReticle(pitch, yaw); +}); +mapping.enable(); + + +Script.scriptEnding.connect(function(){ + mapping.disable(); +}); diff --git a/examples/controllers/reticleTests.js b/examples/controllers/reticleTests.js index 3392d1b7d9..56b2ba413a 100644 --- a/examples/controllers/reticleTests.js +++ b/examples/controllers/reticleTests.js @@ -33,49 +33,6 @@ var mappingJSON = { mapping = Controller.parseMapping(JSON.stringify(mappingJSON)); mapping.enable(); - - -var MAPPING_NAME = "com.highfidelity.testing.reticleWithHand"; -var mapping2 = Controller.newMapping(MAPPING_NAME); -//mapping2.from(Controller.Standard.RightHand).debug(true).to(Controller.Actions.LeftHand); - -/* -mapping2.from(Controller.Standard.RightHand).peek().to(function(pose) { - print("Controller.Standard.RightHand value:" + JSON.stringify(pose)); - }); -*/ - -var translation = { x: 0, y: 0.1, z: 0 }; -var translationDx = 0.01; -var translationDy = 0.01; -var translationDz = 0.01; -var TRANSLATION_LIMIT = 0.5; -var rotation = Quat.fromPitchYawRollDegrees(45, 0, 45); -mapping2.from(function() { - translation.x = translation.x + translationDx; - translation.y = translation.y + translationDy; - translation.z = translation.z + translationDz; - if ((translation.x > TRANSLATION_LIMIT) || (translation.x < (-1 *TRANSLATION_LIMIT))) { - translationDx = translationDx * -1; - } - if ((translation.y > TRANSLATION_LIMIT) || (translation.y < (-1 *TRANSLATION_LIMIT))) { - translationDy = translationDy * -1; - } - if ((translation.z > TRANSLATION_LIMIT) || (translation.z < (-1 *TRANSLATION_LIMIT))) { - translationDz = translationDz * -1; - } - var pose = { - translation: translation, - rotation: rotation, - velocity: { x: 0, y: 0, z: 0 }, - angularVelocity: { x: 0, y: 0, z: 0, w: 1 } - }; - return pose; -}).debug(true).to(Controller.Standard.LeftHand); - -Controller.enableMapping(MAPPING_NAME); - - Script.scriptEnding.connect(function(){ mapping.disable(); }); diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index 9af478e709..9d3942cd55 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -87,6 +88,8 @@ namespace controller { Q_INVOKABLE QObject* parseMapping(const QString& json); Q_INVOKABLE QObject* loadMapping(const QString& jsonUrl); + Q_INVOKABLE glm::vec2 getReticlePosition() { return toGlm(QCursor::pos()); } + Q_INVOKABLE void setReticlePosition(glm::vec2 position) { QCursor::setPos(position.x, position.y); } //Q_INVOKABLE bool isPrimaryButtonPressed() const; //Q_INVOKABLE glm::vec2 getPrimaryJoystickPosition() const; From 32bb8f020cc88c606951a77e16e47273c673a227 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 17 Dec 2015 17:40:35 -0800 Subject: [PATCH 102/195] FIxing the diffuse contribution bug maybe --- .../render-utils/src/DeferredGlobalLight.slh | 6 +++--- .../render-utils/src/DeferredLighting.slh | 20 ++++++------------- libraries/render-utils/src/point_light.slf | 2 +- libraries/render-utils/src/spot_light.slf | 2 +- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 983b8002f7..11e157a50c 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -83,7 +83,7 @@ vec3 evalAmbienGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 positi vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); - color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + color += vec3(diffuse * shading.w + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light); return color; } @@ -106,7 +106,7 @@ vec3 evalAmbienSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); - color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + color += vec3(diffuse * shading.w + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light); return color; } @@ -129,7 +129,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 positi vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); - color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + color += vec3(diffuse * shading.w + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light); return color; } diff --git a/libraries/render-utils/src/DeferredLighting.slh b/libraries/render-utils/src/DeferredLighting.slh index d01b36f553..f4863bbadf 100755 --- a/libraries/render-utils/src/DeferredLighting.slh +++ b/libraries/render-utils/src/DeferredLighting.slh @@ -23,19 +23,16 @@ vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 sp // Specular Lighting depends on the half vector and the gloss vec3 halfDir = normalize(fragEyeDir + fragLightDir); - // float specularPower = pow(facingLight * max(0.0, dot(halfDir, fragNormal)), gloss * 128.0); float specularPower = pow(max(0.0, dot(halfDir, fragNormal)), gloss * 128.0); specularPower *= (gloss * 128.0 * 0.125 + 0.25); float shlickPower = (1.0 - dot(fragLightDir,halfDir)); float shlickPower2 = shlickPower * shlickPower; float shlickPower5 = shlickPower2 * shlickPower2 * shlickPower; - vec3 schlick = specular * (1.0 - shlickPower5) + vec3(shlickPower5); - vec3 reflect = specularPower * schlick; + vec3 fresnel = specular * (1.0 - shlickPower5) + vec3(shlickPower5); + vec3 reflect = specularPower * fresnel * diffuse; - // FIXME: - //return vec4(reflect, diffuse * (1 - length(schlick))); - return vec4(reflect, diffuse); + return vec4(reflect, diffuse * (1 - fresnel.x))); } <@endfunc@> @@ -51,7 +48,7 @@ vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 vec3 halfDir = normalize(fragEyeDir + fragLightDir); float specularPower = pow(facingLight * max(0.0, dot(halfDir, fragNormal)), gloss * 128.0); - vec3 reflect = specularPower * specular; + vec3 reflect = specularPower * specular * diffuse; return vec4(reflect, diffuse); } @@ -61,14 +58,9 @@ vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 <$declareEvalPBRShading()$> - +// Return xyz the specular/reflection component and w the diffuse component vec4 evalFragShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) { - - /*if (gl_FragCoord.x > 1000) { - return evalBlinnShading(fragNormal, fragLightDir, fragEyeDir, specular, gloss); - } else {*/ - return evalPBRShading(fragNormal, fragLightDir, fragEyeDir, specular, gloss); - //} + return evalPBRShading(fragNormal, fragLightDir, fragEyeDir, specular, gloss); } <@endif@> diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index e9045e18c5..716a39aee9 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -66,7 +66,7 @@ void main(void) { float radialAttenuation = evalLightAttenuation(light, fragLightDistance); // Final Lighting color - vec3 fragColor = shading.w * (frag.diffuse + shading.xyz); + vec3 fragColor = (shading.w * frag.diffuse + shading.xyz); _fragColor = vec4(fragColor * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0); if (getLightShowContour(light) > 0.0) { diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 73b081260e..d7a20fc5e5 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -73,7 +73,7 @@ void main(void) { float angularAttenuation = evalLightSpotAttenuation(light, cosSpotAngle); // Final Lighting color - vec3 fragColor = shading.w * (frag.diffuse + shading.xyz); + vec3 fragColor = (shading.w * frag.diffuse + shading.xyz); _fragColor = vec4(fragColor * angularAttenuation * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0); if (getLightShowContour(light) > 0.0) { From c891bcb8cdc26a4cc265b13f59b897065b079191 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 17 Dec 2015 17:44:40 -0800 Subject: [PATCH 103/195] FIxing the diffuse contribution bug maybe --- libraries/render-utils/src/DeferredLighting.slh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DeferredLighting.slh b/libraries/render-utils/src/DeferredLighting.slh index f4863bbadf..cf03861c2f 100755 --- a/libraries/render-utils/src/DeferredLighting.slh +++ b/libraries/render-utils/src/DeferredLighting.slh @@ -32,7 +32,7 @@ vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 sp vec3 fresnel = specular * (1.0 - shlickPower5) + vec3(shlickPower5); vec3 reflect = specularPower * fresnel * diffuse; - return vec4(reflect, diffuse * (1 - fresnel.x))); + return vec4(reflect, diffuse * (1 - fresnel.x)); } <@endfunc@> From d344ef6e2a98cc26da192ce81024f805265a683e Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 17 Dec 2015 18:10:41 -0800 Subject: [PATCH 104/195] fix warning in my PR --- libraries/controllers/src/controllers/Pose.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/controllers/src/controllers/Pose.cpp b/libraries/controllers/src/controllers/Pose.cpp index 2e1d30cff2..8f43242431 100644 --- a/libraries/controllers/src/controllers/Pose.cpp +++ b/libraries/controllers/src/controllers/Pose.cpp @@ -42,7 +42,6 @@ namespace controller { } void Pose::fromScriptValue(const QScriptValue& object, Pose& pose) { - bool isValid = true; auto translation = object.property("translation"); auto rotation = object.property("rotation"); auto velocity = object.property("velocity"); From 919a4b6728d950226a0be472bb193efd2aa9d5c6 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 17 Dec 2015 16:03:18 -0800 Subject: [PATCH 105/195] Split global JS Scene into Render --- interface/src/Application.cpp | 58 +++------- .../render-utils/src/RenderDeferredTask.cpp | 74 ++++++------ .../src/RenderScriptingInterface.cpp | 41 +++++++ .../src/RenderScriptingInterface.h | 95 +++++++++++++++ libraries/render/src/render/Engine.cpp | 10 ++ libraries/render/src/render/Engine.h | 87 ++++++++++---- .../src/SceneScriptingInterface.cpp | 95 +++------------ .../src/SceneScriptingInterface.h | 109 ++---------------- libraries/script-engine/src/ScriptEngine.cpp | 1 - 9 files changed, 293 insertions(+), 277 deletions(-) create mode 100644 libraries/render-utils/src/RenderScriptingInterface.cpp create mode 100644 libraries/render-utils/src/RenderScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 21648f9118..fedc64174f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -89,6 +89,7 @@ #include #include #include +#include #include #include #include @@ -341,6 +342,7 @@ bool setupEssentials(int& argc, char** argv) { #endif DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -3674,40 +3676,22 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se // For now every frame pass the renderContext { PerformanceTimer perfTimer("EngineRun"); - render::RenderContext renderContext; - - auto sceneInterface = DependencyManager::get(); - - renderContext._cullOpaque = sceneInterface->doEngineCullOpaque(); - renderContext._sortOpaque = sceneInterface->doEngineSortOpaque(); - renderContext._renderOpaque = sceneInterface->doEngineRenderOpaque(); - renderContext._cullTransparent = sceneInterface->doEngineCullTransparent(); - renderContext._sortTransparent = sceneInterface->doEngineSortTransparent(); - renderContext._renderTransparent = sceneInterface->doEngineRenderTransparent(); - - renderContext._maxDrawnOpaqueItems = sceneInterface->getEngineMaxDrawnOpaqueItems(); - renderContext._maxDrawnTransparentItems = sceneInterface->getEngineMaxDrawnTransparentItems(); - renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems(); - - renderContext._deferredDebugMode = sceneInterface->getEngineDeferredDebugMode(); - renderContext._deferredDebugSize = sceneInterface->getEngineDeferredDebugSize(); - - renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus(); - if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned)) { - renderContext._drawItemStatus |= render::showNetworkStatusFlag; - } - renderContext._drawHitEffect = sceneInterface->doEngineDisplayHitEffect(); - - renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion); - renderContext._fxaaStatus = Menu::getInstance()->isOptionChecked(MenuOption::Antialiasing); - - renderContext._toneMappingExposure = sceneInterface->getEngineToneMappingExposure(); - renderContext._toneMappingToneCurve = sceneInterface->getEngineToneMappingToneCurveValue(); renderArgs->_shouldRender = LODManager::shouldRender; - - renderContext.args = renderArgs; renderArgs->_viewFrustum = getDisplayViewFrustum(); + + auto renderInterface = DependencyManager::get(); + auto renderItemsMeta = renderInterface->getItemsMeta(); + auto renderTone = renderInterface->getTone(); + int drawStatus = renderInterface->getDrawStatus(); + bool drawHitEffect = renderInterface->getDrawHitEffect(); + + bool occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion); + bool antialiasingStatus = Menu::getInstance()->isOptionChecked(MenuOption::Antialiasing); + bool showOwnedStatus = Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned); + + render::RenderContext renderContext{renderArgs, renderItemsMeta, renderTone}; + renderContext.setOptions(drawStatus, drawHitEffect, occlusionStatus, antialiasingStatus, showOwnedStatus); _renderEngine->setRenderContext(renderContext); // Before the deferred pass, let's try to use the render engine @@ -3715,15 +3699,8 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se _renderEngine->run(); myAvatar->endRenderRun(); - auto engineRC = _renderEngine->getRenderContext(); - sceneInterface->setEngineFeedOpaqueItems(engineRC->_numFeedOpaqueItems); - sceneInterface->setEngineDrawnOpaqueItems(engineRC->_numDrawnOpaqueItems); - - sceneInterface->setEngineFeedTransparentItems(engineRC->_numFeedTransparentItems); - sceneInterface->setEngineDrawnTransparentItems(engineRC->_numDrawnTransparentItems); - - sceneInterface->setEngineFeedOverlay3DItems(engineRC->_numFeedOverlay3DItems); - sceneInterface->setEngineDrawnOverlay3DItems(engineRC->_numDrawnOverlay3DItems); + auto engineContext = _renderEngine->getRenderContext(); + renderInterface->setItemCounts(engineContext->getItemsMeta()); } activeRenderingThread = nullptr; @@ -4177,6 +4154,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerFunction("HMD", "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0); scriptEngine->registerGlobalObject("Scene", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("Render", DependencyManager::get().data()); scriptEngine->registerGlobalObject("ScriptDiscoveryService", this->getRunningScriptsWidget()); } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 5423d928a7..820f2b86bb 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -37,23 +37,24 @@ using namespace render; void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - DependencyManager::get()->prepare(renderContext->args); + DependencyManager::get()->prepare(renderContext->getArgs()); } void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - DependencyManager::get()->render(renderContext->args); + DependencyManager::get()->render(renderContext->getArgs()); } void ToneMappingDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { PerformanceTimer perfTimer("ToneMappingDeferred"); - _toneMappingEffect.render(renderContext->args); + _toneMappingEffect.render(renderContext->getArgs()); } RenderDeferredTask::RenderDeferredTask() : Task() { // CPU only, create the list of renderedOpaques items _jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { - context->_numFeedOpaqueItems = count; + context->getItemsMeta()._opaque._numFeed = count; + auto& opaque = context->getItemsMeta()._opaque; }) ))); _jobs.push_back(Job(new CullItemsOpaque::JobModel("CullOpaque", _jobs.back().getOutput()))); @@ -64,7 +65,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", FetchItems(ItemFilter::Builder::transparentShape().withoutLayered(), [](const RenderContextPointer& context, int count) { - context->_numFeedTransparentItems = count; + context->getItemsMeta()._transparent._numFeed = count; }) ))); _jobs.push_back(Job(new CullItemsTransparent::JobModel("CullTransparent", _jobs.back().getOutput()))); @@ -146,7 +147,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend // Is it possible that we render without a viewFrustum ? - if (!(renderContext->args && renderContext->args->_viewFrustum)) { + if (!(renderContext->getArgs() && renderContext->getArgs()->_viewFrustum)) { return; } @@ -154,21 +155,21 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend setDrawDebugDeferredBuffer(renderContext->_deferredDebugMode); // Make sure we turn the displayItemStatus on/off - setDrawItemStatus(renderContext->_drawItemStatus); + setDrawItemStatus(renderContext->getDrawStatus()); // Make sure we display hit effect on screen, as desired from a script - setDrawHitEffect(renderContext->_drawHitEffect); + setDrawHitEffect(renderContext->getDrawHitEffect()); // TODO: turn on/off AO through menu item - setOcclusionStatus(renderContext->_occlusionStatus); + setOcclusionStatus(renderContext->getOcclusionStatus()); - setAntialiasingStatus(renderContext->_fxaaStatus); + setAntialiasingStatus(renderContext->getFxaaStatus()); - setToneMappingExposure(renderContext->_toneMappingExposure); - setToneMappingToneCurve(renderContext->_toneMappingToneCurve); + setToneMappingExposure(renderContext->getTone()._exposure); + setToneMappingToneCurve(renderContext->getTone()._toneCurve); - renderContext->args->_context->syncCache(); + renderContext->getArgs()->_context->syncCache(); for (auto job : _jobs) { job.run(sceneContext, renderContext); @@ -177,16 +178,17 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend }; void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); args->_batch = &batch; - renderContext->_numDrawnOpaqueItems = (int)inItems.size(); + auto& opaque = renderContext->getItemsMeta()._opaque; + opaque._numDrawn = (int)inItems.size(); glm::mat4 projMat; Transform viewMat; @@ -200,22 +202,23 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend const float OPAQUE_ALPHA_THRESHOLD = 0.5f; args->_alphaThreshold = OPAQUE_ALPHA_THRESHOLD; } - renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnOpaqueItems); + renderItems(sceneContext, renderContext, inItems, opaque._maxDrawn); args->_batch = nullptr; }); } void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); args->_batch = &batch; - renderContext->_numDrawnTransparentItems = (int)inItems.size(); + auto& transparent = renderContext->getItemsMeta()._transparent; + transparent._numDrawn = (int)inItems.size(); glm::mat4 projMat; Transform viewMat; @@ -228,7 +231,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD; - renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnTransparentItems); + renderItems(sceneContext, renderContext, inItems, transparent._maxDrawn); args->_batch = nullptr; }); } @@ -251,8 +254,8 @@ const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() { } void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); // render backgrounds auto& scene = sceneContext->_scene; @@ -267,11 +270,12 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon inItems.emplace_back(id); } } - renderContext->_numFeedOverlay3DItems = (int)inItems.size(); - renderContext->_numDrawnOverlay3DItems = (int)inItems.size(); + auto& overlay3D = renderContext->getItemsMeta()._overlay3D; + overlay3D._numFeed = (int)inItems.size(); + overlay3D._numDrawn = (int)inItems.size(); if (!inItems.empty()) { - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); // Clear the framebuffer without stereo // Needs to be distinct from the other batch because using the clear call @@ -300,7 +304,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnOverlay3DItems); + renderItems(sceneContext, renderContext, inItems, renderContext->getItemsMeta()._overlay3D._maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); @@ -329,11 +333,11 @@ const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() { } void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); // from the touched pixel generate the stencil buffer - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); doInBatch(args->_context, [=](gpu::Batch& batch) { args->_batch = &batch; @@ -355,8 +359,8 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren } void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); // render backgrounds auto& scene = sceneContext->_scene; @@ -368,7 +372,7 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const for (auto id : items) { inItems.emplace_back(id); } - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); doInBatch(args->_context, [=](gpu::Batch& batch) { args->_batch = &batch; diff --git a/libraries/render-utils/src/RenderScriptingInterface.cpp b/libraries/render-utils/src/RenderScriptingInterface.cpp new file mode 100644 index 0000000000..3b283e3058 --- /dev/null +++ b/libraries/render-utils/src/RenderScriptingInterface.cpp @@ -0,0 +1,41 @@ +// +// RenderScriptingInterface.cpp +// libraries/render-utils +// +// Created by Zach Pomerantz on 12/16/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 "RenderScriptingInterface.h" + +RenderScriptingInterface::RenderScriptingInterface() {}; + +void RenderScriptingInterface::setEngineToneMappingToneCurve(const QString& toneCurve) { + if (toneCurve == QString("None")) { + _tone._toneCurve = 0; + } else if (toneCurve == QString("Gamma22")) { + _tone._toneCurve = 1; + } else if (toneCurve == QString("Reinhard")) { + _tone._toneCurve = 2; + } else if (toneCurve == QString("Filmic")) { + _tone._toneCurve = 3; + } +} + +QString RenderScriptingInterface::getEngineToneMappingToneCurve() const { + switch (_tone._toneCurve) { + case 0: + return QString("None"); + case 1: + return QString("Gamma22"); + case 2: + return QString("Reinhard"); + case 3: + return QString("Filmic"); + default: + return QString("Filmic"); + }; +} \ No newline at end of file diff --git a/libraries/render-utils/src/RenderScriptingInterface.h b/libraries/render-utils/src/RenderScriptingInterface.h new file mode 100644 index 0000000000..ec3b5be669 --- /dev/null +++ b/libraries/render-utils/src/RenderScriptingInterface.h @@ -0,0 +1,95 @@ +// +// RenderScriptingInterface.h +// libraries/render-utils +// +// Created by Zach Pomerantz on 12/16/15. +// 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_RenderScriptingInterface_h +#define hifi_RenderScriptingInterface_h + +#include // QObject +#include // Dependency + +#include "render/Engine.h" + +class RenderScriptingInterface : public QObject, public Dependency { + Q_OBJECT + SINGLETON_DEPENDENCY + + public: + Q_INVOKABLE void setEngineRenderOpaque(bool renderOpaque) { _items._opaque._render = renderOpaque; }; + Q_INVOKABLE bool doEngineRenderOpaque() const { return _items._opaque._render; } + Q_INVOKABLE void setEngineRenderTransparent(bool renderTransparent) { _items._transparent._render = renderTransparent; }; + Q_INVOKABLE bool doEngineRenderTransparent() const { return _items._transparent._render; } + + Q_INVOKABLE void setEngineCullOpaque(bool cullOpaque) { _items._opaque._cull = cullOpaque; }; + Q_INVOKABLE bool doEngineCullOpaque() const { return _items._opaque._cull; } + Q_INVOKABLE void setEngineCullTransparent(bool cullTransparent) { _items._transparent._cull = cullTransparent; }; + Q_INVOKABLE bool doEngineCullTransparent() const { return _items._transparent._cull; } + + Q_INVOKABLE void setEngineSortOpaque(bool sortOpaque) { _items._opaque._sort = sortOpaque; }; + Q_INVOKABLE bool doEngineSortOpaque() const { return _items._opaque._sort; } + Q_INVOKABLE void setEngineSortTransparent(bool sortTransparent) { _items._transparent._sort = sortTransparent; }; + Q_INVOKABLE bool doEngineSortTransparent() const { return _items._transparent._sort; } + + Q_INVOKABLE int getEngineNumDrawnOpaqueItems() { return _items._opaque._numDrawn; } + Q_INVOKABLE int getEngineNumDrawnTransparentItems() { return _items._transparent._numDrawn; } + Q_INVOKABLE int getEngineNumDrawnOverlay3DItems() { return _items._overlay3D._numDrawn; } + + Q_INVOKABLE int getEngineNumFeedOpaqueItems() { return _items._opaque._numFeed; } + Q_INVOKABLE int getEngineNumFeedTransparentItems() { return _items._transparent._numFeed; } + Q_INVOKABLE int getEngineNumFeedOverlay3DItems() { return _items._overlay3D._numFeed; } + + Q_INVOKABLE void setEngineMaxDrawnOpaqueItems(int count) { _items._opaque._maxDrawn = count; } + Q_INVOKABLE int getEngineMaxDrawnOpaqueItems() { return _items._opaque._maxDrawn; } + Q_INVOKABLE void setEngineMaxDrawnTransparentItems(int count) { _items._transparent._maxDrawn = count; } + Q_INVOKABLE int getEngineMaxDrawnTransparentItems() { return _items._transparent._maxDrawn; } + Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _items._overlay3D._maxDrawn = count; } + Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _items._overlay3D._maxDrawn; } + + Q_INVOKABLE void setEngineDeferredDebugMode(int mode) { _deferredDebugMode = mode; } + Q_INVOKABLE int getEngineDeferredDebugMode() { return _deferredDebugMode; } + Q_INVOKABLE void setEngineDeferredDebugSize(glm::vec4 size) { _deferredDebugSize = size; } + Q_INVOKABLE glm::vec4 getEngineDeferredDebugSize() { return _deferredDebugSize; } + + Q_INVOKABLE void setEngineDisplayItemStatus(int display) { _drawStatus = display; } + Q_INVOKABLE int doEngineDisplayItemStatus() { return _drawStatus; } + + Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; } + Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; } + + Q_INVOKABLE void setEngineToneMappingExposure(float exposure) { _tone._exposure = exposure; } + Q_INVOKABLE float getEngineToneMappingExposure() const { return _tone._exposure; } + + Q_INVOKABLE void setEngineToneMappingToneCurve(const QString& curve); + Q_INVOKABLE QString getEngineToneMappingToneCurve() const; + int getEngineToneMappingToneCurveValue() const { return _tone._toneCurve; } + + inline int getDrawStatus() { return _drawStatus; } + inline bool getDrawHitEffect() { return _drawHitEffect; } + inline const render::RenderContext::ItemsMeta& getItemsMeta() { return _items; } + inline const render::RenderContext::Tone& getTone() { return _tone; } + void setItemCounts(const render::RenderContext::ItemsMeta& items) { _items.setCounts(items); }; + +protected: + RenderScriptingInterface(); + ~RenderScriptingInterface() {}; + + render::RenderContext::ItemsMeta _items; + render::RenderContext::Tone _tone; + + // Options + int _drawStatus = 0; + bool _drawHitEffect = false; + + // Debugging + int _deferredDebugMode = -1; + glm::vec4 _deferredDebugSize { 0.0f, -1.0f, 1.0f, 1.0f }; +}; + +#endif // hifi_RenderScriptingInterface_h diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index 86f35eb831..0cf09e0ca4 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -13,6 +13,16 @@ #include "DrawTask.h" using namespace render; +void RenderContext::setOptions(int drawStatus, bool drawHitEffect, bool occlusion, bool fxaa, bool showOwned) { + _drawStatus = drawStatus; + _occlusionStatus = occlusion; + _fxaaStatus = fxaa; + _drawHitEffect = drawHitEffect; + + if (showOwned) { + _drawStatus |= render::showNetworkStatusFlag; + } +}; Engine::Engine() : _sceneContext(std::make_shared()), diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index abfef03039..dcfe28a444 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -23,7 +23,7 @@ public: SceneContext() {} }; -typedef std::shared_ptr SceneContextPointer; +using SceneContextPointer = std::shared_ptr; // see examples/utilities/tools/renderEngineDebug.js const int showDisplayStatusFlag = 1; @@ -32,43 +32,80 @@ const int showNetworkStatusFlag = 2; class RenderContext { public: - RenderArgs* args; + struct ItemsMeta { + inline void setCounts(const ItemsMeta& items) { + _opaque.setCounts(items._opaque); + _transparent.setCounts(items._transparent); + _overlay3D.setCounts(items._overlay3D); + }; - bool _cullOpaque = true; - bool _sortOpaque = true; - bool _renderOpaque = true; - bool _cullTransparent = true; - bool _sortTransparent = true; - bool _renderTransparent = true; + struct Counter { + Counter() {}; + Counter(const Counter& counter) { + _numFeed = _numDrawn = 0; + _maxDrawn = counter._maxDrawn; + }; - int _numFeedOpaqueItems = 0; - int _numDrawnOpaqueItems = 0; - int _maxDrawnOpaqueItems = -1; + inline void setCounts(const Counter& counter) { + _numFeed = counter._numFeed; + _numDrawn = counter._numDrawn; + }; + + int _numFeed = 0; + int _numDrawn = 0; + int _maxDrawn = -1; + }; + + struct State : public Counter { + bool _render = true; + bool _cull = true; + bool _sort = true; + + Counter _counter{}; + }; + + // TODO: Store state/counter in a map instead of manually enumerated members + State _opaque{}; + State _transparent{}; + Counter _overlay3D{}; + }; + + struct Tone { + int _toneCurve = 3; + float _exposure = 0.0; + }; - int _numFeedTransparentItems = 0; - int _numDrawnTransparentItems = 0; - int _maxDrawnTransparentItems = -1; + RenderContext(RenderArgs* args, ItemsMeta items, Tone tone) : _args{args}, _items{items}, _tone{tone} {}; + RenderContext() : RenderContext(nullptr, {}, {}) {}; - int _numFeedOverlay3DItems = 0; - int _numDrawnOverlay3DItems = 0; - int _maxDrawnOverlay3DItems = -1; + inline RenderArgs* getArgs() { return _args; } + inline int getDrawStatus() { return _drawStatus; } + inline bool getDrawHitEffect() { return _drawHitEffect; } + inline bool getOcclusionStatus() { return _occlusionStatus; } + inline bool getFxaaStatus() { return _fxaaStatus; } + inline ItemsMeta& getItemsMeta() { return _items; } + inline Tone& getTone() { return _tone; } + void setOptions(int drawStatus, bool drawHitEffect, bool occlusion, bool fxaa, bool showOwned); + // Debugging int _deferredDebugMode = -1; glm::vec4 _deferredDebugSize { 0.0f, -1.0f, 1.0f, 1.0f }; - int _drawItemStatus = 0; - bool _drawHitEffect = false; +protected: + RenderArgs* _args; + + // Options + int _drawStatus = 0; // bitflag + bool _drawHitEffect = false; bool _occlusionStatus = false; bool _fxaaStatus = false; - float _toneMappingExposure = 0.0; - int _toneMappingToneCurve = 3; - - RenderContext() {} + ItemsMeta _items; + Tone _tone; }; typedef std::shared_ptr RenderContextPointer; -// THe base class for a task that runs on the SceneContext +// The base class for a task that runs on the SceneContext class Task { public: Task() {} @@ -81,7 +118,7 @@ protected: typedef std::shared_ptr TaskPointer; typedef std::vector Tasks; -// The root of the takss, the Engine, should not be known from the Tasks, +// The root of the tasks, the Engine, should not be known from the Tasks, // The SceneContext is what navigates from the engine down to the Tasks class Engine { public: diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp index 3e22a9e929..39bceba9d9 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.cpp +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -1,6 +1,6 @@ // // SceneScriptingInterface.cpp -// interface/src/scripting +// libraries/script-engine // // Created by Sam Gateau on 2/24/15. // Copyright 2014 High Fidelity, Inc. @@ -11,16 +11,27 @@ #include "SceneScriptingInterface.h" -#include - - #include SceneScriptingInterface::SceneScriptingInterface() { - // Let's make sure the sunSkyStage is using a proceduralSKybox + // Let's make sure the sunSkyStage is using a proceduralSkybox _skyStage->setSkybox(model::SkyboxPointer(new ProceduralSkybox())); } +void SceneScriptingInterface::setShouldRenderAvatars(bool shouldRenderAvatars) { + if (shouldRenderAvatars != _shouldRenderAvatars) { + _shouldRenderAvatars = shouldRenderAvatars; + emit shouldRenderAvatarsChanged(_shouldRenderAvatars); + } +} + +void SceneScriptingInterface::setShouldRenderEntities(bool shouldRenderEntities) { + if (shouldRenderEntities != _shouldRenderEntities) { + _shouldRenderEntities = shouldRenderEntities; + emit shouldRenderEntitiesChanged(_shouldRenderEntities); + } +} + void SceneScriptingInterface::setStageOrientation(const glm::quat& orientation) { _skyStage->setOriginOrientation(orientation); } @@ -120,77 +131,3 @@ QString SceneScriptingInterface::getBackgroundMode() const { model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const { return _skyStage; } - -void SceneScriptingInterface::setShouldRenderAvatars(bool shouldRenderAvatars) { - if (shouldRenderAvatars != _shouldRenderAvatars) { - _shouldRenderAvatars = shouldRenderAvatars; - emit shouldRenderAvatarsChanged(_shouldRenderAvatars); - } -} - -void SceneScriptingInterface::setShouldRenderEntities(bool shouldRenderEntities) { - if (shouldRenderEntities != _shouldRenderEntities) { - _shouldRenderEntities = shouldRenderEntities; - emit shouldRenderEntitiesChanged(_shouldRenderEntities); - } -} - -void SceneScriptingInterface::setEngineRenderOpaque(bool renderOpaque) { - _engineRenderOpaque = renderOpaque; -} - -void SceneScriptingInterface::setEngineRenderTransparent(bool renderTransparent) { - _engineRenderTransparent = renderTransparent; -} - -void SceneScriptingInterface::setEngineCullOpaque(bool cullOpaque) { - _engineCullOpaque = cullOpaque; -} - -void SceneScriptingInterface::setEngineCullTransparent(bool cullTransparent) { - _engineCullTransparent = cullTransparent; -} - -void SceneScriptingInterface::setEngineSortOpaque(bool sortOpaque) { - _engineSortOpaque = sortOpaque; -} - -void SceneScriptingInterface::setEngineSortTransparent(bool sortTransparent) { - _engineSortOpaque = sortTransparent; -} - -void SceneScriptingInterface::clearEngineCounters() { - _numFeedOpaqueItems = 0; - _numDrawnOpaqueItems = 0; - _numFeedTransparentItems = 0; - _numDrawnTransparentItems = 0; - _numFeedOverlay3DItems = 0; - _numDrawnOverlay3DItems = 0; -} - - -void SceneScriptingInterface::setEngineToneMappingToneCurve(const QString& toneCurve) { - if (toneCurve == QString("None")) { - _engineToneMappingToneCurve = 0; - } else if (toneCurve == QString("Gamma22")) { - _engineToneMappingToneCurve = 1; - } else if (toneCurve == QString("Reinhard")) { - _engineToneMappingToneCurve = 2; - } else if (toneCurve == QString("Filmic")) { - _engineToneMappingToneCurve = 3; - } -} -QString SceneScriptingInterface::getEngineToneMappingToneCurve() const { - switch (_engineToneMappingToneCurve) { - case 0: - return QString("None"); - case 1: - return QString("Gamma22"); - case 2: - return QString("Reinhard"); - case 3: - return QString("Filmic"); - default: - return QString("Filmic"); - }; -} \ No newline at end of file diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 246f624b08..abc4ee68a9 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -1,6 +1,6 @@ // // SceneScriptingInterface.h -// interface/src/scripting +// libraries/script-engine // // Created by Sam Gateau on 2/24/15. // Copyright 2014 High Fidelity, Inc. @@ -12,9 +12,8 @@ #ifndef hifi_SceneScriptingInterface_h #define hifi_SceneScriptingInterface_h -#include - -#include +#include // QObject +#include // Dependency #include "model/Stage.h" @@ -22,10 +21,16 @@ class SceneScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY +public: Q_PROPERTY(bool shouldRenderAvatars READ shouldRenderAvatars WRITE setShouldRenderAvatars) Q_PROPERTY(bool shouldRenderEntities READ shouldRenderEntities WRITE setShouldRenderEntities) -public: + Q_INVOKABLE void setShouldRenderAvatars(bool shouldRenderAvatars); + Q_INVOKABLE bool shouldRenderAvatars() const { return _shouldRenderAvatars; } + + Q_INVOKABLE void setShouldRenderEntities(bool shouldRenderEntities); + Q_INVOKABLE bool shouldRenderEntities() const { return _shouldRenderEntities; } + Q_INVOKABLE void setStageOrientation(const glm::quat& orientation); Q_INVOKABLE void setStageLocation(float longitude, float latitude, float altitude); @@ -43,7 +48,6 @@ public: Q_INVOKABLE void setStageSunModelEnable(bool isEnabled); Q_INVOKABLE bool isStageSunModelEnabled() const; - Q_INVOKABLE void setKeyLightColor(const glm::vec3& color); Q_INVOKABLE glm::vec3 getKeyLightColor() const; Q_INVOKABLE void setKeyLightIntensity(float intensity); @@ -61,108 +65,19 @@ public: Q_INVOKABLE QString getBackgroundMode() const; model::SunSkyStagePointer getSkyStage() const; - - Q_INVOKABLE void setShouldRenderAvatars(bool shouldRenderAvatars); - Q_INVOKABLE bool shouldRenderAvatars() const { return _shouldRenderAvatars; } - - Q_INVOKABLE void setShouldRenderEntities(bool shouldRenderEntities); - Q_INVOKABLE bool shouldRenderEntities() const { return _shouldRenderEntities; } - - - // Controlling the rendering engine - Q_INVOKABLE void setEngineRenderOpaque(bool renderOpaque); - Q_INVOKABLE bool doEngineRenderOpaque() const { return _engineRenderOpaque; } - Q_INVOKABLE void setEngineRenderTransparent(bool renderTransparent); - Q_INVOKABLE bool doEngineRenderTransparent() const { return _engineRenderTransparent; } - - Q_INVOKABLE void setEngineCullOpaque(bool cullOpaque); - Q_INVOKABLE bool doEngineCullOpaque() const { return _engineCullOpaque; } - Q_INVOKABLE void setEngineCullTransparent(bool cullTransparent); - Q_INVOKABLE bool doEngineCullTransparent() const { return _engineCullTransparent; } - - Q_INVOKABLE void setEngineSortOpaque(bool sortOpaque); - Q_INVOKABLE bool doEngineSortOpaque() const { return _engineSortOpaque; } - Q_INVOKABLE void setEngineSortTransparent(bool sortTransparent); - Q_INVOKABLE bool doEngineSortTransparent() const { return _engineSortTransparent; } - - void clearEngineCounters(); - void setEngineDrawnOpaqueItems(int count) { _numDrawnOpaqueItems = count; } - Q_INVOKABLE int getEngineNumDrawnOpaqueItems() { return _numDrawnOpaqueItems; } - void setEngineDrawnTransparentItems(int count) { _numDrawnTransparentItems = count; } - Q_INVOKABLE int getEngineNumDrawnTransparentItems() { return _numDrawnTransparentItems; } - void setEngineDrawnOverlay3DItems(int count) { _numDrawnOverlay3DItems = count; } - Q_INVOKABLE int getEngineNumDrawnOverlay3DItems() { return _numDrawnOverlay3DItems; } - - void setEngineFeedOpaqueItems(int count) { _numFeedOpaqueItems = count; } - Q_INVOKABLE int getEngineNumFeedOpaqueItems() { return _numFeedOpaqueItems; } - void setEngineFeedTransparentItems(int count) { _numFeedTransparentItems = count; } - Q_INVOKABLE int getEngineNumFeedTransparentItems() { return _numFeedTransparentItems; } - void setEngineFeedOverlay3DItems(int count) { _numFeedOverlay3DItems = count; } - Q_INVOKABLE int getEngineNumFeedOverlay3DItems() { return _numFeedOverlay3DItems; } - - Q_INVOKABLE void setEngineMaxDrawnOpaqueItems(int count) { _maxDrawnOpaqueItems = count; } - Q_INVOKABLE int getEngineMaxDrawnOpaqueItems() { return _maxDrawnOpaqueItems; } - Q_INVOKABLE void setEngineMaxDrawnTransparentItems(int count) { _maxDrawnTransparentItems = count; } - Q_INVOKABLE int getEngineMaxDrawnTransparentItems() { return _maxDrawnTransparentItems; } - Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _maxDrawnOverlay3DItems = count; } - Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _maxDrawnOverlay3DItems; } - - Q_INVOKABLE void setEngineDeferredDebugMode(int mode) { _deferredDebugMode = mode; } - Q_INVOKABLE int getEngineDeferredDebugMode() { return _deferredDebugMode; } - Q_INVOKABLE void setEngineDeferredDebugSize(glm::vec4 size) { _deferredDebugSize = size; } - Q_INVOKABLE glm::vec4 getEngineDeferredDebugSize() { return _deferredDebugSize; } - - Q_INVOKABLE void setEngineDisplayItemStatus(int display) { _drawItemStatus = display; } - Q_INVOKABLE int doEngineDisplayItemStatus() { return _drawItemStatus; } - - Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; } - Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; } - - Q_INVOKABLE void setEngineToneMappingExposure(float exposure) { _engineToneMappingExposure = exposure; } - Q_INVOKABLE float getEngineToneMappingExposure() const { return _engineToneMappingExposure; } - - Q_INVOKABLE void setEngineToneMappingToneCurve(const QString& curve); - Q_INVOKABLE QString getEngineToneMappingToneCurve() const; - int getEngineToneMappingToneCurveValue() const { return _engineToneMappingToneCurve; } signals: void shouldRenderAvatarsChanged(bool shouldRenderAvatars); void shouldRenderEntitiesChanged(bool shouldRenderEntities); + protected: SceneScriptingInterface(); ~SceneScriptingInterface() {}; model::SunSkyStagePointer _skyStage = std::make_shared(); - + bool _shouldRenderAvatars = true; bool _shouldRenderEntities = true; - - bool _engineRenderOpaque = true; - bool _engineRenderTransparent = true; - bool _engineCullOpaque = true; - bool _engineCullTransparent = true; - bool _engineSortOpaque = true; - bool _engineSortTransparent = true; - - int _numFeedOpaqueItems = 0; - int _numDrawnOpaqueItems = 0; - int _numFeedTransparentItems = 0; - int _numDrawnTransparentItems = 0; - int _numFeedOverlay3DItems = 0; - int _numDrawnOverlay3DItems = 0; - - int _maxDrawnOpaqueItems = -1; - int _maxDrawnTransparentItems = -1; - int _maxDrawnOverlay3DItems = -1; - - int _deferredDebugMode = -1; - glm::vec4 _deferredDebugSize { 0.0f, -1.0f, 1.0f, 1.0f }; - int _drawItemStatus = 0; - - bool _drawHitEffect = false; - - float _engineToneMappingExposure = 0.0f; - int _engineToneMappingToneCurve = 3; }; #endif // hifi_SceneScriptingInterface_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index ded3db11e9..ef448e93f0 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -46,7 +46,6 @@ #include "XMLHttpRequestClass.h" #include "WebSocketClass.h" -#include "SceneScriptingInterface.h" #include "RecordingScriptingInterface.h" #include "MIDIEvent.h" From cdcb2d565d0dc6e6966ba505d0f16db4733c0d3d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 17 Dec 2015 17:51:07 -0800 Subject: [PATCH 106/195] Use new RenderContext accessors for rendering --- .../src/AmbientOcclusionEffect.cpp | 6 ++-- .../render-utils/src/AntialiasingEffect.cpp | 8 ++--- .../render-utils/src/DebugDeferredBuffer.cpp | 8 ++--- libraries/render-utils/src/HitEffect.cpp | 6 ++-- libraries/render/src/render/DrawStatus.cpp | 10 +++--- libraries/render/src/render/DrawTask.cpp | 36 +++++++++---------- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 1b631aed9c..c32bf2654d 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -175,10 +175,10 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() { } void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { auto framebufferCache = DependencyManager::get(); QSize framebufferSize = framebufferCache->getFrameBufferSize(); diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index fb59f37941..3acc88f953 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -93,14 +93,14 @@ const gpu::PipelinePointer& Antialiasing::getBlendPipeline() { } void Antialiasing::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); - if (renderContext->args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + if (renderContext->getArgs()->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { return; } - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.enableStereo(false); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index d61b131844..23150a1779 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -179,9 +179,9 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode, std::st void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); - const RenderArgs* args = renderContext->args; + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); + RenderArgs* args = renderContext->getArgs(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { const auto geometryBuffer = DependencyManager::get(); const auto framebufferCache = DependencyManager::get(); @@ -211,4 +211,4 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren const glm::vec2 topRight(renderContext->_deferredDebugSize.z, renderContext->_deferredDebugSize.w); geometryBuffer->renderQuad(batch, bottomLeft, topRight, color); }); -} \ No newline at end of file +} diff --git a/libraries/render-utils/src/HitEffect.cpp b/libraries/render-utils/src/HitEffect.cpp index 32915aea0e..bf65eaf059 100644 --- a/libraries/render-utils/src/HitEffect.cpp +++ b/libraries/render-utils/src/HitEffect.cpp @@ -61,9 +61,9 @@ const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() { } void HitEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); - RenderArgs* args = renderContext->args; + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); + RenderArgs* args = renderContext->getArgs(); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { glm::mat4 projMat; diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 3f37ce378b..fa177bd0d4 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -97,9 +97,9 @@ const gpu::TexturePointer DrawStatus::getStatusIconMap() const { void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); - RenderArgs* args = renderContext->args; + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); + RenderArgs* args = renderContext->getArgs(); auto& scene = sceneContext->_scene; const int NUM_STATUS_VEC4_PER_ITEM = 2; const int VEC4_LENGTH = 4; @@ -179,7 +179,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const unsigned int VEC3_ADRESS_OFFSET = 3; - if ((renderContext->_drawItemStatus & showDisplayStatusFlag) > 0) { + if ((renderContext->getDrawStatus() & showDisplayStatusFlag) > 0) { for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*) (itemAABox + i)); batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); @@ -192,7 +192,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, batch.setPipeline(getDrawItemStatusPipeline()); - if ((renderContext->_drawItemStatus & showNetworkStatusFlag) > 0) { + if ((renderContext->getDrawStatus() & showNetworkStatusFlag) > 0) { for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*) (itemAABox + i)); batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index c0e50037e0..44ba57143f 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -37,7 +37,7 @@ void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderCon // Is it possible that we render without a viewFrustum ? - if (!(renderContext->args && renderContext->args->_viewFrustum)) { + if (!(renderContext->getArgs() && renderContext->getArgs()->_viewFrustum)) { return; } @@ -54,11 +54,11 @@ Job::~Job() { void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); - RenderArgs* args = renderContext->args; - auto renderDetails = renderContext->args->_details._item; + RenderArgs* args = renderContext->getArgs(); + auto renderDetails = renderContext->getArgs()->_details._item; renderDetails->_considered += inItems.size(); @@ -115,7 +115,7 @@ void CullItems::run(const SceneContextPointer& sceneContext, const RenderContext outItems.clear(); outItems.reserve(inItems.size()); - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); args->_details.pointTo(RenderDetails::OTHER_ITEM); cullItems(sceneContext, renderContext, inItems, outItems); } @@ -124,7 +124,7 @@ void CullItemsOpaque::run(const SceneContextPointer& sceneContext, const RenderC outItems.clear(); outItems.reserve(inItems.size()); - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); args->_details.pointTo(RenderDetails::OPAQUE_ITEM); cullItems(sceneContext, renderContext, inItems, outItems); } @@ -133,7 +133,7 @@ void CullItemsTransparent::run(const SceneContextPointer& sceneContext, const Re outItems.clear(); outItems.reserve(inItems.size()); - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); args->_details.pointTo(RenderDetails::TRANSLUCENT_ITEM); cullItems(sceneContext, renderContext, inItems, outItems); } @@ -163,11 +163,11 @@ struct BackToFrontSort { }; void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); auto& scene = sceneContext->_scene; - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); // Allocate and simply copy @@ -211,7 +211,7 @@ void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderCo void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems) { auto& scene = sceneContext->_scene; - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); // render if ((maxDrawnItems < 0) || (maxDrawnItems > (int) inItems.size())) { for (auto itemDetails : inItems) { @@ -236,8 +236,8 @@ void render::renderItems(const SceneContextPointer& sceneContext, const RenderCo } void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); // render lights auto& scene = sceneContext->_scene; @@ -253,7 +253,7 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext ItemIDsBounds culledItems; culledItems.reserve(inItems.size()); - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); args->_details.pointTo(RenderDetails::OTHER_ITEM); cullItems(sceneContext, renderContext, inItems, culledItems); @@ -265,8 +265,8 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext } void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); // render backgrounds auto& scene = sceneContext->_scene; @@ -278,7 +278,7 @@ void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderCo for (auto id : items) { inItems.emplace_back(id); } - RenderArgs* args = renderContext->args; + RenderArgs* args = renderContext->getArgs(); doInBatch(args->_context, [=](gpu::Batch& batch) { args->_batch = &batch; batch.enableSkybox(true); From de9e03a3794ac7a6567e498b23930440756500e3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 18 Dec 2015 10:54:04 -0800 Subject: [PATCH 107/195] remove qxmpp external --- cmake/externals/qxmpp/CMakeLists.txt | 77 ---------------------------- 1 file changed, 77 deletions(-) delete mode 100644 cmake/externals/qxmpp/CMakeLists.txt diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt deleted file mode 100644 index 600aa7b2ff..0000000000 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ /dev/null @@ -1,77 +0,0 @@ -set(EXTERNAL_NAME qxmpp) - -# we need to find qmake inside QT_DIR -find_program(QMAKE_COMMAND NAME qmake PATHS ${QT_DIR}/bin $ENV{QTTOOLDIR} NO_DEFAULT_PATH) - -if (NOT QMAKE_COMMAND) - message(FATAL_ERROR "Could not find qmake. Qxmpp cannot be compiled without qmake.") -endif () - -if (ANDROID) - set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") -endif () - -if (WIN32) - find_program(PLATFORM_BUILD_COMMAND nmake PATHS "C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin") - - if (NOT PLATFORM_BUILD_COMMAND) - message(FATAL_ERROR "You asked CMake to grap QXmpp and build it, but nmake was not found. Please make sure the folder containing nmake.exe is in your PATH.") - endif () -else () - find_program(PLATFORM_BUILD_COMMAND make) -endif () - -include(ExternalProject) -ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://qxmpp.googlecode.com/files/qxmpp-0.7.6.tar.gz - URL_MD5 ee45a97313306ded2ff0f6618a3ed1e1 - BUILD_IN_SOURCE 1 - PATCH_COMMAND patch -p2 -t -N --verbose < ${CMAKE_CURRENT_SOURCE_DIR}/qxmpp.patch - CONFIGURE_COMMAND ${QMAKE_COMMAND} PREFIX= - BUILD_COMMAND ${PLATFORM_BUILD_COMMAND} - INSTALL_COMMAND ${PLATFORM_BUILD_COMMAND} install - LOG_DOWNLOAD 1 - LOG_CONFIGURE 1 - LOG_BUILD 1 -) - -# Hide this external target (for ide users) -set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") - -ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) - -if (CMAKE_GENERATOR STREQUAL Xcode) - find_program(DITTO_COMMAND ditto) - - ExternalProject_Add_Step( - ${EXTERNAL_NAME} - copy-from-xcode-install - COMMENT "Copying from /tmp/hifi.dst${INSTALL_DIR} to move install to proper location" - COMMAND ${DITTO_COMMAND} /tmp/hifi.dst${INSTALL_DIR} ${INSTALL_DIR} - DEPENDEES install - LOG 1 - ) -endif () - -string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to Qxmpp include directory") - -set(_LIB_DIR ${INSTALL_DIR}/lib) - -if (WIN32) - set(_LIB_EXT "0.lib") - - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${_LIB_DIR} CACHE PATH "Location of QXmpp DLL") -else () - if (APPLE) - set(_LIB_EXT ".dylib") - else () - set(_LIB_EXT ".so") - endif () - - set(_LIB_PREFIX "lib") -endif () - -set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_LIB_DIR}/${_LIB_PREFIX}qxmpp${_LIB_EXT} CACHE FILEPATH "Path to QXmpp release library") -set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to QXmpp debug library") From d057239023dcabd7b734e0268a2c3410ef2c23c4 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 18 Dec 2015 11:48:40 -0800 Subject: [PATCH 108/195] Rename RenderContext::ItemsMeta to ItemsConfig --- interface/src/Application.cpp | 6 +++--- libraries/render-utils/src/RenderDeferredTask.cpp | 14 +++++++------- .../render-utils/src/RenderScriptingInterface.h | 6 +++--- libraries/render/src/render/Engine.h | 10 +++++----- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fedc64174f..3cd185db0a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3681,7 +3681,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderArgs->_viewFrustum = getDisplayViewFrustum(); auto renderInterface = DependencyManager::get(); - auto renderItemsMeta = renderInterface->getItemsMeta(); + auto renderItemsConfig = renderInterface->getItemsConfig(); auto renderTone = renderInterface->getTone(); int drawStatus = renderInterface->getDrawStatus(); bool drawHitEffect = renderInterface->getDrawHitEffect(); @@ -3690,7 +3690,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se bool antialiasingStatus = Menu::getInstance()->isOptionChecked(MenuOption::Antialiasing); bool showOwnedStatus = Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned); - render::RenderContext renderContext{renderArgs, renderItemsMeta, renderTone}; + render::RenderContext renderContext{renderArgs, renderItemsConfig, renderTone}; renderContext.setOptions(drawStatus, drawHitEffect, occlusionStatus, antialiasingStatus, showOwnedStatus); _renderEngine->setRenderContext(renderContext); @@ -3700,7 +3700,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se myAvatar->endRenderRun(); auto engineContext = _renderEngine->getRenderContext(); - renderInterface->setItemCounts(engineContext->getItemsMeta()); + renderInterface->setItemCounts(engineContext->getItemsConfig()); } activeRenderingThread = nullptr; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 820f2b86bb..2594c9503e 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -53,8 +53,8 @@ RenderDeferredTask::RenderDeferredTask() : Task() { // CPU only, create the list of renderedOpaques items _jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { - context->getItemsMeta()._opaque._numFeed = count; - auto& opaque = context->getItemsMeta()._opaque; + context->getItemsConfig()._opaque._numFeed = count; + auto& opaque = context->getItemsConfig()._opaque; }) ))); _jobs.push_back(Job(new CullItemsOpaque::JobModel("CullOpaque", _jobs.back().getOutput()))); @@ -65,7 +65,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", FetchItems(ItemFilter::Builder::transparentShape().withoutLayered(), [](const RenderContextPointer& context, int count) { - context->getItemsMeta()._transparent._numFeed = count; + context->getItemsConfig()._transparent._numFeed = count; }) ))); _jobs.push_back(Job(new CullItemsTransparent::JobModel("CullTransparent", _jobs.back().getOutput()))); @@ -187,7 +187,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setStateScissorRect(args->_viewport); args->_batch = &batch; - auto& opaque = renderContext->getItemsMeta()._opaque; + auto& opaque = renderContext->getItemsConfig()._opaque; opaque._numDrawn = (int)inItems.size(); glm::mat4 projMat; @@ -217,7 +217,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const batch.setStateScissorRect(args->_viewport); args->_batch = &batch; - auto& transparent = renderContext->getItemsMeta()._transparent; + auto& transparent = renderContext->getItemsConfig()._transparent; transparent._numDrawn = (int)inItems.size(); glm::mat4 projMat; @@ -270,7 +270,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon inItems.emplace_back(id); } } - auto& overlay3D = renderContext->getItemsMeta()._overlay3D; + auto& overlay3D = renderContext->getItemsConfig()._overlay3D; overlay3D._numFeed = (int)inItems.size(); overlay3D._numDrawn = (int)inItems.size(); @@ -304,7 +304,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderItems(sceneContext, renderContext, inItems, renderContext->getItemsMeta()._overlay3D._maxDrawn); + renderItems(sceneContext, renderContext, inItems, renderContext->getItemsConfig()._overlay3D._maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); diff --git a/libraries/render-utils/src/RenderScriptingInterface.h b/libraries/render-utils/src/RenderScriptingInterface.h index ec3b5be669..8e33d7b929 100644 --- a/libraries/render-utils/src/RenderScriptingInterface.h +++ b/libraries/render-utils/src/RenderScriptingInterface.h @@ -72,15 +72,15 @@ class RenderScriptingInterface : public QObject, public Dependency { inline int getDrawStatus() { return _drawStatus; } inline bool getDrawHitEffect() { return _drawHitEffect; } - inline const render::RenderContext::ItemsMeta& getItemsMeta() { return _items; } + inline const render::RenderContext::ItemsConfig& getItemsConfig() { return _items; } inline const render::RenderContext::Tone& getTone() { return _tone; } - void setItemCounts(const render::RenderContext::ItemsMeta& items) { _items.setCounts(items); }; + void setItemCounts(const render::RenderContext::ItemsConfig& items) { _items.setCounts(items); }; protected: RenderScriptingInterface(); ~RenderScriptingInterface() {}; - render::RenderContext::ItemsMeta _items; + render::RenderContext::ItemsConfig _items; render::RenderContext::Tone _tone; // Options diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index dcfe28a444..3b1bad45e7 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -32,8 +32,8 @@ const int showNetworkStatusFlag = 2; class RenderContext { public: - struct ItemsMeta { - inline void setCounts(const ItemsMeta& items) { + struct ItemsConfig { + inline void setCounts(const ItemsConfig& items) { _opaque.setCounts(items._opaque); _transparent.setCounts(items._transparent); _overlay3D.setCounts(items._overlay3D); @@ -75,7 +75,7 @@ public: float _exposure = 0.0; }; - RenderContext(RenderArgs* args, ItemsMeta items, Tone tone) : _args{args}, _items{items}, _tone{tone} {}; + RenderContext(RenderArgs* args, ItemsConfig items, Tone tone) : _args{args}, _items{items}, _tone{tone} {}; RenderContext() : RenderContext(nullptr, {}, {}) {}; inline RenderArgs* getArgs() { return _args; } @@ -83,7 +83,7 @@ public: inline bool getDrawHitEffect() { return _drawHitEffect; } inline bool getOcclusionStatus() { return _occlusionStatus; } inline bool getFxaaStatus() { return _fxaaStatus; } - inline ItemsMeta& getItemsMeta() { return _items; } + inline ItemsConfig& getItemsConfig() { return _items; } inline Tone& getTone() { return _tone; } void setOptions(int drawStatus, bool drawHitEffect, bool occlusion, bool fxaa, bool showOwned); @@ -100,7 +100,7 @@ protected: bool _occlusionStatus = false; bool _fxaaStatus = false; - ItemsMeta _items; + ItemsConfig _items; Tone _tone; }; typedef std::shared_ptr RenderContextPointer; From 674bfa4f370780cb892aa5b85c71d8dd8385b7f3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 18 Dec 2015 12:04:21 -0800 Subject: [PATCH 109/195] Replace RenderContext substructs with subclasses --- .../render-utils/src/RenderDeferredTask.cpp | 30 +++++----- .../src/RenderScriptingInterface.cpp | 10 ++-- .../src/RenderScriptingInterface.h | 54 +++++++++--------- libraries/render/src/render/Engine.h | 56 ++++++++++--------- 4 files changed, 77 insertions(+), 73 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 2594c9503e..ddfb6bc7a3 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -53,8 +53,8 @@ RenderDeferredTask::RenderDeferredTask() : Task() { // CPU only, create the list of renderedOpaques items _jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { - context->getItemsConfig()._opaque._numFeed = count; - auto& opaque = context->getItemsConfig()._opaque; + context->getItemsConfig().opaque.numFeed = count; + auto& opaque = context->getItemsConfig().opaque; }) ))); _jobs.push_back(Job(new CullItemsOpaque::JobModel("CullOpaque", _jobs.back().getOutput()))); @@ -65,7 +65,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", FetchItems(ItemFilter::Builder::transparentShape().withoutLayered(), [](const RenderContextPointer& context, int count) { - context->getItemsConfig()._transparent._numFeed = count; + context->getItemsConfig().transparent.numFeed = count; }) ))); _jobs.push_back(Job(new CullItemsTransparent::JobModel("CullTransparent", _jobs.back().getOutput()))); @@ -166,8 +166,8 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend setAntialiasingStatus(renderContext->getFxaaStatus()); - setToneMappingExposure(renderContext->getTone()._exposure); - setToneMappingToneCurve(renderContext->getTone()._toneCurve); + setToneMappingExposure(renderContext->getTone().exposure); + setToneMappingToneCurve(renderContext->getTone().toneCurve); renderContext->getArgs()->_context->syncCache(); @@ -187,8 +187,8 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setStateScissorRect(args->_viewport); args->_batch = &batch; - auto& opaque = renderContext->getItemsConfig()._opaque; - opaque._numDrawn = (int)inItems.size(); + auto& opaque = renderContext->getItemsConfig().opaque; + opaque.numDrawn = (int)inItems.size(); glm::mat4 projMat; Transform viewMat; @@ -202,7 +202,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend const float OPAQUE_ALPHA_THRESHOLD = 0.5f; args->_alphaThreshold = OPAQUE_ALPHA_THRESHOLD; } - renderItems(sceneContext, renderContext, inItems, opaque._maxDrawn); + renderItems(sceneContext, renderContext, inItems, opaque.maxDrawn); args->_batch = nullptr; }); } @@ -217,8 +217,8 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const batch.setStateScissorRect(args->_viewport); args->_batch = &batch; - auto& transparent = renderContext->getItemsConfig()._transparent; - transparent._numDrawn = (int)inItems.size(); + auto& transparent = renderContext->getItemsConfig().transparent; + transparent.numDrawn = (int)inItems.size(); glm::mat4 projMat; Transform viewMat; @@ -231,7 +231,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD; - renderItems(sceneContext, renderContext, inItems, transparent._maxDrawn); + renderItems(sceneContext, renderContext, inItems, transparent.maxDrawn); args->_batch = nullptr; }); } @@ -270,9 +270,9 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon inItems.emplace_back(id); } } - auto& overlay3D = renderContext->getItemsConfig()._overlay3D; - overlay3D._numFeed = (int)inItems.size(); - overlay3D._numDrawn = (int)inItems.size(); + auto& overlay3D = renderContext->getItemsConfig().overlay3D; + overlay3D.numFeed = (int)inItems.size(); + overlay3D.numDrawn = (int)inItems.size(); if (!inItems.empty()) { RenderArgs* args = renderContext->getArgs(); @@ -304,7 +304,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderItems(sceneContext, renderContext, inItems, renderContext->getItemsConfig()._overlay3D._maxDrawn); + renderItems(sceneContext, renderContext, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); diff --git a/libraries/render-utils/src/RenderScriptingInterface.cpp b/libraries/render-utils/src/RenderScriptingInterface.cpp index 3b283e3058..71ca929cfd 100644 --- a/libraries/render-utils/src/RenderScriptingInterface.cpp +++ b/libraries/render-utils/src/RenderScriptingInterface.cpp @@ -15,18 +15,18 @@ RenderScriptingInterface::RenderScriptingInterface() {}; void RenderScriptingInterface::setEngineToneMappingToneCurve(const QString& toneCurve) { if (toneCurve == QString("None")) { - _tone._toneCurve = 0; + _tone.toneCurve = 0; } else if (toneCurve == QString("Gamma22")) { - _tone._toneCurve = 1; + _tone.toneCurve = 1; } else if (toneCurve == QString("Reinhard")) { - _tone._toneCurve = 2; + _tone.toneCurve = 2; } else if (toneCurve == QString("Filmic")) { - _tone._toneCurve = 3; + _tone.toneCurve = 3; } } QString RenderScriptingInterface::getEngineToneMappingToneCurve() const { - switch (_tone._toneCurve) { + switch (_tone.toneCurve) { case 0: return QString("None"); case 1: diff --git a/libraries/render-utils/src/RenderScriptingInterface.h b/libraries/render-utils/src/RenderScriptingInterface.h index 8e33d7b929..49926864df 100644 --- a/libraries/render-utils/src/RenderScriptingInterface.h +++ b/libraries/render-utils/src/RenderScriptingInterface.h @@ -22,35 +22,35 @@ class RenderScriptingInterface : public QObject, public Dependency { SINGLETON_DEPENDENCY public: - Q_INVOKABLE void setEngineRenderOpaque(bool renderOpaque) { _items._opaque._render = renderOpaque; }; - Q_INVOKABLE bool doEngineRenderOpaque() const { return _items._opaque._render; } - Q_INVOKABLE void setEngineRenderTransparent(bool renderTransparent) { _items._transparent._render = renderTransparent; }; - Q_INVOKABLE bool doEngineRenderTransparent() const { return _items._transparent._render; } + Q_INVOKABLE void setEngineRenderOpaque(bool renderOpaque) { _items.opaque.render = renderOpaque; }; + Q_INVOKABLE bool doEngineRenderOpaque() const { return _items.opaque.render; } + Q_INVOKABLE void setEngineRenderTransparent(bool renderTransparent) { _items.transparent.render = renderTransparent; }; + Q_INVOKABLE bool doEngineRenderTransparent() const { return _items.transparent.render; } - Q_INVOKABLE void setEngineCullOpaque(bool cullOpaque) { _items._opaque._cull = cullOpaque; }; - Q_INVOKABLE bool doEngineCullOpaque() const { return _items._opaque._cull; } - Q_INVOKABLE void setEngineCullTransparent(bool cullTransparent) { _items._transparent._cull = cullTransparent; }; - Q_INVOKABLE bool doEngineCullTransparent() const { return _items._transparent._cull; } + Q_INVOKABLE void setEngineCullOpaque(bool cullOpaque) { _items.opaque.cull = cullOpaque; }; + Q_INVOKABLE bool doEngineCullOpaque() const { return _items.opaque.cull; } + Q_INVOKABLE void setEngineCullTransparent(bool cullTransparent) { _items.transparent.cull = cullTransparent; }; + Q_INVOKABLE bool doEngineCullTransparent() const { return _items.transparent.cull; } - Q_INVOKABLE void setEngineSortOpaque(bool sortOpaque) { _items._opaque._sort = sortOpaque; }; - Q_INVOKABLE bool doEngineSortOpaque() const { return _items._opaque._sort; } - Q_INVOKABLE void setEngineSortTransparent(bool sortTransparent) { _items._transparent._sort = sortTransparent; }; - Q_INVOKABLE bool doEngineSortTransparent() const { return _items._transparent._sort; } + Q_INVOKABLE void setEngineSortOpaque(bool sortOpaque) { _items.opaque.sort = sortOpaque; }; + Q_INVOKABLE bool doEngineSortOpaque() const { return _items.opaque.sort; } + Q_INVOKABLE void setEngineSortTransparent(bool sortTransparent) { _items.transparent.sort = sortTransparent; }; + Q_INVOKABLE bool doEngineSortTransparent() const { return _items.transparent.sort; } - Q_INVOKABLE int getEngineNumDrawnOpaqueItems() { return _items._opaque._numDrawn; } - Q_INVOKABLE int getEngineNumDrawnTransparentItems() { return _items._transparent._numDrawn; } - Q_INVOKABLE int getEngineNumDrawnOverlay3DItems() { return _items._overlay3D._numDrawn; } + Q_INVOKABLE int getEngineNumDrawnOpaqueItems() { return _items.opaque.numDrawn; } + Q_INVOKABLE int getEngineNumDrawnTransparentItems() { return _items.transparent.numDrawn; } + Q_INVOKABLE int getEngineNumDrawnOverlay3DItems() { return _items.overlay3D.numDrawn; } - Q_INVOKABLE int getEngineNumFeedOpaqueItems() { return _items._opaque._numFeed; } - Q_INVOKABLE int getEngineNumFeedTransparentItems() { return _items._transparent._numFeed; } - Q_INVOKABLE int getEngineNumFeedOverlay3DItems() { return _items._overlay3D._numFeed; } + Q_INVOKABLE int getEngineNumFeedOpaqueItems() { return _items.opaque.numFeed; } + Q_INVOKABLE int getEngineNumFeedTransparentItems() { return _items.transparent.numFeed; } + Q_INVOKABLE int getEngineNumFeedOverlay3DItems() { return _items.overlay3D.numFeed; } - Q_INVOKABLE void setEngineMaxDrawnOpaqueItems(int count) { _items._opaque._maxDrawn = count; } - Q_INVOKABLE int getEngineMaxDrawnOpaqueItems() { return _items._opaque._maxDrawn; } - Q_INVOKABLE void setEngineMaxDrawnTransparentItems(int count) { _items._transparent._maxDrawn = count; } - Q_INVOKABLE int getEngineMaxDrawnTransparentItems() { return _items._transparent._maxDrawn; } - Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _items._overlay3D._maxDrawn = count; } - Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _items._overlay3D._maxDrawn; } + Q_INVOKABLE void setEngineMaxDrawnOpaqueItems(int count) { _items.opaque.maxDrawn = count; } + Q_INVOKABLE int getEngineMaxDrawnOpaqueItems() { return _items.opaque.maxDrawn; } + Q_INVOKABLE void setEngineMaxDrawnTransparentItems(int count) { _items.transparent.maxDrawn = count; } + Q_INVOKABLE int getEngineMaxDrawnTransparentItems() { return _items.transparent.maxDrawn; } + Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _items.overlay3D.maxDrawn = count; } + Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _items.overlay3D.maxDrawn; } Q_INVOKABLE void setEngineDeferredDebugMode(int mode) { _deferredDebugMode = mode; } Q_INVOKABLE int getEngineDeferredDebugMode() { return _deferredDebugMode; } @@ -63,12 +63,12 @@ class RenderScriptingInterface : public QObject, public Dependency { Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; } Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; } - Q_INVOKABLE void setEngineToneMappingExposure(float exposure) { _tone._exposure = exposure; } - Q_INVOKABLE float getEngineToneMappingExposure() const { return _tone._exposure; } + Q_INVOKABLE void setEngineToneMappingExposure(float exposure) { _tone.exposure = exposure; } + Q_INVOKABLE float getEngineToneMappingExposure() const { return _tone.exposure; } Q_INVOKABLE void setEngineToneMappingToneCurve(const QString& curve); Q_INVOKABLE QString getEngineToneMappingToneCurve() const; - int getEngineToneMappingToneCurveValue() const { return _tone._toneCurve; } + int getEngineToneMappingToneCurveValue() const { return _tone.toneCurve; } inline int getDrawStatus() { return _drawStatus; } inline bool getDrawHitEffect() { return _drawHitEffect; } diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 3b1bad45e7..40196e320e 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -32,59 +32,63 @@ const int showNetworkStatusFlag = 2; class RenderContext { public: - struct ItemsConfig { + class ItemsConfig { + public: inline void setCounts(const ItemsConfig& items) { - _opaque.setCounts(items._opaque); - _transparent.setCounts(items._transparent); - _overlay3D.setCounts(items._overlay3D); + opaque.setCounts(items.opaque); + transparent.setCounts(items.transparent); + overlay3D.setCounts(items.overlay3D); }; - struct Counter { + class Counter { + public: Counter() {}; Counter(const Counter& counter) { - _numFeed = _numDrawn = 0; - _maxDrawn = counter._maxDrawn; + numFeed = numDrawn = 0; + maxDrawn = counter.maxDrawn; }; inline void setCounts(const Counter& counter) { - _numFeed = counter._numFeed; - _numDrawn = counter._numDrawn; + numFeed = counter.numFeed; + numDrawn = counter.numDrawn; }; - int _numFeed = 0; - int _numDrawn = 0; - int _maxDrawn = -1; + int numFeed = 0; + int numDrawn = 0; + int maxDrawn = -1; }; - struct State : public Counter { - bool _render = true; - bool _cull = true; - bool _sort = true; + class State : public Counter { + public: + bool render = true; + bool cull = true; + bool sort = true; - Counter _counter{}; + Counter counter{}; }; - // TODO: Store state/counter in a map instead of manually enumerated members - State _opaque{}; - State _transparent{}; - Counter _overlay3D{}; + // TODO: If member count increases, store counters in a map instead of multiple members + State opaque{}; + State transparent{}; + Counter overlay3D{}; }; - struct Tone { - int _toneCurve = 3; - float _exposure = 0.0; + class Tone { + public: + int toneCurve = 3; + float exposure = 0.0; }; RenderContext(RenderArgs* args, ItemsConfig items, Tone tone) : _args{args}, _items{items}, _tone{tone} {}; RenderContext() : RenderContext(nullptr, {}, {}) {}; inline RenderArgs* getArgs() { return _args; } + inline ItemsConfig& getItemsConfig() { return _items; } + inline Tone& getTone() { return _tone; } inline int getDrawStatus() { return _drawStatus; } inline bool getDrawHitEffect() { return _drawHitEffect; } inline bool getOcclusionStatus() { return _occlusionStatus; } inline bool getFxaaStatus() { return _fxaaStatus; } - inline ItemsConfig& getItemsConfig() { return _items; } - inline Tone& getTone() { return _tone; } void setOptions(int drawStatus, bool drawHitEffect, bool occlusion, bool fxaa, bool showOwned); // Debugging From 5701ad2e8cdf4f700938f033442990888c411569 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 18 Dec 2015 12:38:50 -0800 Subject: [PATCH 110/195] update to new angular velocity --- examples/controllers/proceduralHandPoseExample.js | 2 +- libraries/controllers/src/controllers/Pose.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/controllers/proceduralHandPoseExample.js b/examples/controllers/proceduralHandPoseExample.js index 5d0b10c46a..8b735f579f 100644 --- a/examples/controllers/proceduralHandPoseExample.js +++ b/examples/controllers/proceduralHandPoseExample.js @@ -63,7 +63,7 @@ mapping.from(function() { translation: translation, rotation: rotation, velocity: { x: 0, y: 0, z: 0 }, - angularVelocity: { x: 0, y: 0, z: 0, w: 1 } + angularVelocity: { x: 0, y: 0, z: 0 } }; return pose; }).debug(true).to(Controller.Standard.LeftHand); diff --git a/libraries/controllers/src/controllers/Pose.cpp b/libraries/controllers/src/controllers/Pose.cpp index 6b2d12e5df..d9641618c1 100644 --- a/libraries/controllers/src/controllers/Pose.cpp +++ b/libraries/controllers/src/controllers/Pose.cpp @@ -53,7 +53,7 @@ namespace controller { vec3FromScriptValue(translation, pose.translation); quatFromScriptValue(rotation, pose.rotation); vec3FromScriptValue(velocity, pose.velocity); - quatFromScriptValue(angularVelocity, pose.angularVelocity); + vec3FromScriptValue(angularVelocity, pose.angularVelocity); pose.valid = true; } else { pose.valid = false; From 3014b3bd5ba410659c09bbee1bb3f1c2c5d00f81 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 18 Dec 2015 12:50:21 -0800 Subject: [PATCH 111/195] Adding Gamma correction to all the Color coming for the attribute stream if used as color --- .../entities-renderer/src/paintStroke.slv | 4 +- libraries/gpu/src/gpu/Color.slh | 52 +++++++++++++++++++ libraries/render-utils/src/animdebugdraw.slv | 5 +- libraries/render-utils/src/model.slv | 8 ++- libraries/render-utils/src/model_lightmap.slv | 6 +-- .../src/model_lightmap_normal_map.slv | 6 +-- .../render-utils/src/model_normal_map.slv | 5 +- libraries/render-utils/src/overlay3D.slv | 5 +- libraries/render-utils/src/simple.slv | 5 +- libraries/render-utils/src/skin_model.slv | 5 +- .../src/skin_model_normal_map.slv | 5 +- .../src/standardTransformPNTC.slv | 5 +- libraries/render-utils/src/stars.slv | 5 +- 13 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 libraries/gpu/src/gpu/Color.slh diff --git a/libraries/entities-renderer/src/paintStroke.slv b/libraries/entities-renderer/src/paintStroke.slv index 7d7523deb9..c7dd112bcc 100644 --- a/libraries/entities-renderer/src/paintStroke.slv +++ b/libraries/entities-renderer/src/paintStroke.slv @@ -13,8 +13,8 @@ // <@include gpu/Inputs.slh@> +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> // the interpolated normal @@ -30,7 +30,7 @@ void main(void) { varTexcoord = inTexCoord0.st; // pass along the diffuse color - varColor = inColor; + varColor = colorToLinearRGBA(inColor); // standard transform TransformCamera cam = getTransformCamera(); diff --git a/libraries/gpu/src/gpu/Color.slh b/libraries/gpu/src/gpu/Color.slh new file mode 100644 index 0000000000..f633e6e2d4 --- /dev/null +++ b/libraries/gpu/src/gpu/Color.slh @@ -0,0 +1,52 @@ + +<@if not GPU_COLOR_SLH@> +<@def GPU_COLOR_SLH@> + 0.04045 + // constants: + // T = 0.04045 + // A = 1 / 1.055 = 0.94786729857 + // B = 0.055 * A = 0.05213270142 + // C = 1 / 12.92 = 0.0773993808 + // G = 2.4 + const float T = 0.04045; + const float A = 0.947867; + const float B = 0.052132; + const float C = 0.077399; + const float G = 2.4; + + if (cs > T) { + return pow((cs * A + B), G); + } else { + return cs * C; + } +} + +vec3 colorToLinear(vec3 srgb) { + return vec3(colorComponentToLinear(srgb.x), colorComponentToLinear(srgb.y), colorComponentToLinear(srgb.z)); +} +!> + +vec3 colorToLinearRGB(vec3 srgb) { + const float GAMMA_22 = 2.2; + return pow(srgb, vec3(GAMMA_22)); +} + +vec4 colorToLinearRGBA(vec4 srgba) { + return vec4(colorToLinearRGB(srgba.xyz), srgba.w); +} + +<@endif@> \ No newline at end of file diff --git a/libraries/render-utils/src/animdebugdraw.slv b/libraries/render-utils/src/animdebugdraw.slv index f3117714b0..3cb356c055 100644 --- a/libraries/render-utils/src/animdebugdraw.slv +++ b/libraries/render-utils/src/animdebugdraw.slv @@ -9,16 +9,15 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> out vec4 _color; void main(void) { // pass along the diffuse color - _color = inColor.rgba; + _color = colorToLinearRGBA(inColor.rgba); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 6d56833de1..47de20a5d9 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -12,9 +12,8 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> const int MAX_TEXCOORDS = 2; @@ -27,9 +26,8 @@ out vec3 _color; out vec2 _texCoord0; void main(void) { - - // pass along the diffuse color - _color = inColor.xyz; + // pass along the diffuse color in linear space + _color = colorToLinearRGB(inColor.xyz); // and the texture coordinates _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st; diff --git a/libraries/render-utils/src/model_lightmap.slv b/libraries/render-utils/src/model_lightmap.slv index 7742896228..eacc91245c 100755 --- a/libraries/render-utils/src/model_lightmap.slv +++ b/libraries/render-utils/src/model_lightmap.slv @@ -13,9 +13,8 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> const int MAX_TEXCOORDS = 2; @@ -29,7 +28,8 @@ out vec3 _normal; out vec3 _color; void main(void) { - _color = inColor.xyz; + // pass along the diffuse color in linear space + _color = colorToLinearRGB(inColor.xyz); // and the texture coordinates _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st; diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slv b/libraries/render-utils/src/model_lightmap_normal_map.slv index f63030301f..6046a67e10 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slv +++ b/libraries/render-utils/src/model_lightmap_normal_map.slv @@ -13,9 +13,8 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> const int MAX_TEXCOORDS = 2; @@ -30,7 +29,8 @@ out vec3 _tangent; out vec3 _color; void main(void) { - _color = inColor.xyz; + // pass along the diffuse color in linear space + _color = colorToLinearRGB(inColor.xyz); // and the texture coordinates _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st; diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index e989c1c294..5ed4e37278 100755 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -13,9 +13,8 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> const int MAX_TEXCOORDS = 2; @@ -30,7 +29,7 @@ out vec3 _color; void main(void) { // pass along the diffuse color - _color = inColor.rgb; + _color = colorToLinearRGB(inColor.xyz); // and the texture coordinates _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.xy, 0.0, 1.0)).st; diff --git a/libraries/render-utils/src/overlay3D.slv b/libraries/render-utils/src/overlay3D.slv index a57f02d854..74416f0c1f 100644 --- a/libraries/render-utils/src/overlay3D.slv +++ b/libraries/render-utils/src/overlay3D.slv @@ -11,9 +11,8 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> out vec2 varTexcoord; @@ -30,7 +29,7 @@ void main(void) { varTexcoord = inTexCoord0.xy; // pass along the color - varColor = inColor; + varColor = colorToLinearRGBA(inColor); // standard transform TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index 823654ec27..59b16cf0e5 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -13,9 +13,8 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> uniform bool Instanced = false; @@ -28,7 +27,7 @@ out vec2 _texCoord0; out vec4 _position; void main(void) { - _color = inColor.rgb; + _color = colorToLinearRGB(inColor.rgb); _texCoord0 = inTexCoord0.st; _position = inPosition; _modelNormal = inNormal.xyz; diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index cba419dd4d..8ab475e1fd 100755 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -13,9 +13,8 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> <@include Skinning.slh@> @@ -34,7 +33,7 @@ void main(void) { skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal); // pass along the diffuse color - _color = inColor.rgb; + _color = colorToLinearRGB(inColor.rgb); // and the texture coordinates _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st; diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index 5dfe5ba957..cec93a024e 100755 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -13,9 +13,8 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> <@include Skinning.slh@> @@ -36,7 +35,7 @@ void main(void) { skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz); // pass along the diffuse color - _color = inColor.rgb; + _color = colorToLinearRGB(inColor.rgb); // and the texture coordinates _texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st; diff --git a/libraries/render-utils/src/standardTransformPNTC.slv b/libraries/render-utils/src/standardTransformPNTC.slv index 340dfd9c8e..f7e72b6997 100644 --- a/libraries/render-utils/src/standardTransformPNTC.slv +++ b/libraries/render-utils/src/standardTransformPNTC.slv @@ -13,9 +13,8 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> out vec3 varPosition; @@ -25,7 +24,7 @@ out vec4 varColor; void main(void) { varTexCoord0 = inTexCoord0.st; - varColor = inColor; + varColor = colorToLinearRGBA(inColor); // standard transform TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/stars.slv b/libraries/render-utils/src/stars.slv index b9ad736d5e..d00bb8b7dd 100644 --- a/libraries/render-utils/src/stars.slv +++ b/libraries/render-utils/src/stars.slv @@ -13,9 +13,8 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> // TODO we need to get the viewport resolution and FOV passed to us so we can modify the point size @@ -26,7 +25,7 @@ out vec4 varColor; out float varSize; void main(void) { - varColor = inColor.rgba; + varColor = colorToLinearRGBA(inColor); // standard transform TransformCamera cam = getTransformCamera(); From 2c2b794683104c4c53fef39c26b5877c51465464 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 18 Dec 2015 13:16:05 -0800 Subject: [PATCH 112/195] Stop modelMesh render if pipeline is not found --- libraries/render-utils/src/MeshPartPayload.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 2d8d7b598b..2fae09a158 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -470,6 +470,9 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { ModelRender::pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, args, locations); + if (!locations) { // the pipeline could not be found + return; + } // Bind the model transform and the skinCLusterMatrices if needed bindTransform(batch, locations); From 0492bb1c6dd5473d309121d8467d4159f52ee133 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 18 Dec 2015 13:50:28 -0800 Subject: [PATCH 113/195] Final cleans and tests using R11G11B10 for lighting buffer --- libraries/render-utils/src/FramebufferCache.cpp | 5 +++-- libraries/render-utils/src/ToneMappingEffect.cpp | 11 ++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index e64e245806..9f3d4ba0fe 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -89,9 +89,10 @@ void FramebufferCache::createPrimaryFramebuffer() { auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR); + // FIXME: Decide on the proper one, let s stick to R11G11B10 for now //_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, defaultSampler)); - //lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::R11G11B10), width, height, defaultSampler)); - _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, smoothSampler)); + _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::R11G11B10), width, height, defaultSampler)); + //_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler)); _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _lightingFramebuffer->setRenderBuffer(0, _lightingTexture); _lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index 29e5da6e2a..a00a66fe69 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -64,13 +64,9 @@ void ToneMappingEffect::init() { out vec4 outFragColor; void main(void) { - vec4 fragColorRaw = textureLod(colorMap, varTexCoord0, 0); + vec4 fragColorRaw = texture(colorMap, varTexCoord0); vec3 fragColor = fragColorRaw.xyz; -/* - vec4 fragColorAverage = textureLod(colorMap, varTexCoord0, 10); - float averageIntensity = length(fragColorAverage.xyz); - fragColor /= averageIntensity; -*/ + vec3 srcColor = fragColor * getTwoPowExposure(); int toneCurve = getToneCurve(); @@ -124,7 +120,8 @@ void ToneMappingEffect::render(RenderArgs* args) { auto destFbo = framebufferCache->getPrimaryFramebuffer(); batch.setFramebuffer(destFbo); - batch.generateTextureMips(lightingBuffer); + // FIXME: Generate the Luminosity map + //batch.generateTextureMips(lightingBuffer); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); From 77264b3f99283694ef126d859680760a10e39032 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 18 Dec 2015 14:52:39 -0800 Subject: [PATCH 114/195] Ping pong gun lines up with hand --- examples/flowArts/lightSaber/LightSaber.js | 13 +++++++++++++ unpublishedScripts/hiddenEntityReset.js | 8 ++++++++ unpublishedScripts/masterReset.js | 8 ++++++++ 3 files changed, 29 insertions(+) diff --git a/examples/flowArts/lightSaber/LightSaber.js b/examples/flowArts/lightSaber/LightSaber.js index 8a4f3f2902..50984110bc 100644 --- a/examples/flowArts/lightSaber/LightSaber.js +++ b/examples/flowArts/lightSaber/LightSaber.js @@ -44,6 +44,19 @@ LightSaber = function(spawnPosition) { }) }); + var light = Entities.addEntity({ + type: 'Light', + name: "raveLight", + parentID: saberHandle, + dimensions: { + x: 30, + y: 30, + z: 30 + }, + color: {red: 200, green: 10, blue: 200}, + intensity: 5 + }); + function cleanup() { Entities.deleteEntity(saberHandle); diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index cc4037beb4..c8a2c97b0f 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -1153,6 +1153,14 @@ resetMe: true }, grabbableKey: { + spatialKey: { + relativePosition: { + x: -0.05, + y: 0, + z: 0.0 + }, + relativeRotation: Quat.fromPitchYawRollDegrees(0, -90, -90) + }, invertSolidWhileHeld: true } diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index a1545a3b67..3d985e9a92 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -1134,6 +1134,14 @@ MasterReset = function() { resetMe: true }, grabbableKey: { + spatialKey: { + relativePosition: { + x: -0.05, + y: 0, + z: 0.0 + }, + relativeRotation: Quat.fromPitchYawRollDegrees(0,-90, -90) + }, invertSolidWhileHeld: true } From 2dbb3bd84abf25e2d5d6f0fc0f90ae3d02682012 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 18 Dec 2015 15:12:46 -0800 Subject: [PATCH 115/195] Added grab offsets to createPingPongGun.js --- examples/toybox/ping_pong_gun/createPingPongGun.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/toybox/ping_pong_gun/createPingPongGun.js b/examples/toybox/ping_pong_gun/createPingPongGun.js index 4b93842896..7835dbf7f9 100644 --- a/examples/toybox/ping_pong_gun/createPingPongGun.js +++ b/examples/toybox/ping_pong_gun/createPingPongGun.js @@ -38,6 +38,14 @@ var pingPongGun = Entities.addEntity({ collisionSoundURL: COLLISION_SOUND_URL, userData: JSON.stringify({ grabbableKey: { + spatialKey: { + relativePosition: { + x: -0.05, + y: 0, + z: 0.0 + }, + relativeRotation: Quat.fromPitchYawRollDegrees(0, -90, -90) + }, invertSolidWhileHeld: true } }) From 2c02e7ad631ddec997bbcca99a462b701554d92b Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 18 Dec 2015 15:22:23 -0800 Subject: [PATCH 116/195] grabbing works with left hand for ping pong gun now --- unpublishedScripts/hiddenEntityReset.js | 2 +- unpublishedScripts/masterReset.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index c8a2c97b0f..21971a18ad 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -1125,7 +1125,7 @@ z: 503.39 }; - var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); + var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0); var pingPongGun = Entities.addEntity({ type: "Model", diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 3d985e9a92..3d0773ca10 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -1106,7 +1106,7 @@ MasterReset = function() { z: 503.39 }; - var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); + var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0); var pingPongGun = Entities.addEntity({ type: "Model", From 514cb7a329b835c282cdf448807a221143796eb0 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 18 Dec 2015 15:26:21 -0800 Subject: [PATCH 117/195] Beams arc to each other. BAM --- examples/flowArts/arcBall/arcBall.js | 11 ++--------- examples/flowArts/arcBall/arcBallEntityScript.js | 5 ++++- examples/flowArts/flowArtsHutSpawner.js | 12 ++++++------ 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js index 34578cce76..e39a9af2d6 100644 --- a/examples/flowArts/arcBall/arcBall.js +++ b/examples/flowArts/arcBall/arcBall.js @@ -26,7 +26,7 @@ ArcBall = function(spawnPosition) { var containerBall = Entities.addEntity({ - type: "Sphere", + type: "Box", name: "Arc Ball", script: scriptURL, position: Vec3.sum(spawnPosition, { @@ -37,7 +37,7 @@ ArcBall = function(spawnPosition) { dimensions: { x: .2, y: .2, - z: .2 + z: .5 }, color: { red: 15, @@ -53,13 +53,6 @@ ArcBall = function(spawnPosition) { // }, userData: JSON.stringify({ grabbableKey: { - spatialKey: { - relativePosition: { - x: 0, - y: .1, - z: 0 - } - }, invertSolidWhileHeld: true } }) diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index f1ba9aeb95..8c37f170bb 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -42,7 +42,8 @@ dimensions: {x: .1, y: .1, z: 1}, color: {red: 200, green: 10, blue: 10}, position: startPosition, - rotation: emitOrientation + rotation: emitOrientation, + visible: false }); var color = { red: 200, @@ -53,6 +54,8 @@ type: "ParticleEffect", name: "Particle Arc", parentID: this.entityID, + parentJointIndex: -1, + position: startPosition, isEmitting: true, colorStart: color, color: { diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index e03d2bf0e8..39dcf15698 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -25,10 +25,10 @@ var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Ca basePosition.y = MyAvatar.position.y + 1; // RAVE ITEMS -var lightBall = new LightBall(basePosition); +// var lightBall = new LightBall(basePosition); -// var arcBall = new ArcBall(basePosition); -// var arcBall2 = new ArcBall(Vec3.sum(basePosition, {x: -1, y: 0, z: 0})); +var arcBall = new ArcBall(basePosition); +var arcBall2 = new ArcBall(Vec3.sum(basePosition, {x: -1, y: 0, z: 0})); var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 0.5, z: 1})); var lightSaber = new LightSaber(Vec3.sum(basePosition, {x: 3, y: 0.5, z: 1})); @@ -81,9 +81,9 @@ function cleanup() { Entities.deleteEntity(raveRoom); Entities.deleteEntity(lightZone); Entities.deleteEntity(floor); - lightBall.cleanup(); - // arcBall.cleanup(); - // arcBall2.cleanup(); + // lightBall.cleanup(); + arcBall.cleanup(); + arcBall2.cleanup(); raveStick.cleanup(); lightSaber.cleanup(); } From f24800cf10181b3cb89a21d9df9f982739f8ea37 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 18 Dec 2015 15:35:01 -0800 Subject: [PATCH 118/195] Change the default tone curve to jusimple gamma correct and fix the renaming in the renderENgineDebug script --- examples/utilities/tools/renderEngineDebug.js | 62 +++++++++---------- libraries/render/src/render/Engine.h | 2 +- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index 5e89bff53b..9412f57ca4 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -50,46 +50,46 @@ function CounterWidget(parentPanel, name, feedGetter, drawGetter, capSetter, cap }; var opaquesCounter = new CounterWidget(panel, "Opaques", - function () { return Scene.getEngineNumFeedOpaqueItems(); }, - function () { return Scene.getEngineNumDrawnOpaqueItems(); }, - function(value) { Scene.setEngineMaxDrawnOpaqueItems(value); }, - function () { return Scene.getEngineMaxDrawnOpaqueItems(); } + function () { return Render.getEngineNumFeedOpaqueItems(); }, + function () { return Render.getEngineNumDrawnOpaqueItems(); }, + function(value) { Render.setEngineMaxDrawnOpaqueItems(value); }, + function () { return Render.getEngineMaxDrawnOpaqueItems(); } ); var transparentsCounter = new CounterWidget(panel, "Transparents", - function () { return Scene.getEngineNumFeedTransparentItems(); }, - function () { return Scene.getEngineNumDrawnTransparentItems(); }, - function(value) { Scene.setEngineMaxDrawnTransparentItems(value); }, - function () { return Scene.getEngineMaxDrawnTransparentItems(); } + function () { return Render.getEngineNumFeedTransparentItems(); }, + function () { return Render.getEngineNumDrawnTransparentItems(); }, + function(value) { Render.setEngineMaxDrawnTransparentItems(value); }, + function () { return Render.getEngineMaxDrawnTransparentItems(); } ); var overlaysCounter = new CounterWidget(panel, "Overlays", - function () { return Scene.getEngineNumFeedOverlay3DItems(); }, - function () { return Scene.getEngineNumDrawnOverlay3DItems(); }, - function(value) { Scene.setEngineMaxDrawnOverlay3DItems(value); }, - function () { return Scene.getEngineMaxDrawnOverlay3DItems(); } + function () { return Render.getEngineNumFeedOverlay3DItems(); }, + function () { return Render.getEngineNumDrawnOverlay3DItems(); }, + function(value) { Render.setEngineMaxDrawnOverlay3DItems(value); }, + function () { return Render.getEngineMaxDrawnOverlay3DItems(); } ); var resizing = false; var previousMode = Settings.getValue(SETTINGS_KEY, -1); Menu.addActionGroup(MENU, ACTIONS, ACTIONS[previousMode + 1]); -Scene.setEngineDeferredDebugMode(previousMode); -Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size +Render.setEngineDeferredDebugMode(previousMode); +Render.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size function setEngineDeferredDebugSize(eventX) { var scaledX = (2.0 * (eventX / Window.innerWidth) - 1.0).clamp(-1.0, 1.0); - Scene.setEngineDeferredDebugSize({ x: scaledX, y: -1.0, z: 1.0, w: 1.0 }); + Render.setEngineDeferredDebugSize({ x: scaledX, y: -1.0, z: 1.0, w: 1.0 }); } function shouldStartResizing(eventX) { - var x = Math.abs(eventX - Window.innerWidth * (1.0 + Scene.getEngineDeferredDebugSize().x) / 2.0); - var mode = Scene.getEngineDeferredDebugMode(); + var x = Math.abs(eventX - Window.innerWidth * (1.0 + Render.getEngineDeferredDebugSize().x) / 2.0); + var mode = Render.getEngineDeferredDebugMode(); return mode !== -1 && x < 20; } function menuItemEvent(menuItem) { var index = ACTIONS.indexOf(menuItem); if (index >= 0) { - Scene.setEngineDeferredDebugMode(index - 1); + Render.setEngineDeferredDebugMode(index - 1); } } @@ -98,24 +98,24 @@ var showDisplayStatusFlag = 1; var showNetworkStatusFlag = 2; panel.newCheckbox("Display status", - function(value) { Scene.setEngineDisplayItemStatus(value ? - Scene.doEngineDisplayItemStatus() | showDisplayStatusFlag : - Scene.doEngineDisplayItemStatus() & ~showDisplayStatusFlag); }, - function() { return (Scene.doEngineDisplayItemStatus() & showDisplayStatusFlag) > 0; }, + function(value) { Render.setEngineDisplayItemStatus(value ? + Render.doEngineDisplayItemStatus() | showDisplayStatusFlag : + Render.doEngineDisplayItemStatus() & ~showDisplayStatusFlag); }, + function() { return (Render.doEngineDisplayItemStatus() & showDisplayStatusFlag) > 0; }, function(value) { return (value & showDisplayStatusFlag) > 0; } ); panel.newCheckbox("Network/Physics status", - function(value) { Scene.setEngineDisplayItemStatus(value ? - Scene.doEngineDisplayItemStatus() | showNetworkStatusFlag : - Scene.doEngineDisplayItemStatus() & ~showNetworkStatusFlag); }, - function() { return (Scene.doEngineDisplayItemStatus() & showNetworkStatusFlag) > 0; }, + function(value) { Render.setEngineDisplayItemStatus(value ? + Render.doEngineDisplayItemStatus() | showNetworkStatusFlag : + Render.doEngineDisplayItemStatus() & ~showNetworkStatusFlag); }, + function() { return (Render.doEngineDisplayItemStatus() & showNetworkStatusFlag) > 0; }, function(value) { return (value & showNetworkStatusFlag) > 0; } ); panel.newSlider("Tone Mapping Exposure", -10, 10, - function (value) { Scene.setEngineToneMappingExposure(value); }, - function() { return Scene.getEngineToneMappingExposure(); }, + function (value) { Render.setEngineToneMappingExposure(value); }, + function() { return Render.getEngineToneMappingExposure(); }, function (value) { return (value); }); var tickTackPeriod = 500; @@ -160,9 +160,9 @@ Menu.menuItemEvent.connect(menuItemEvent); function scriptEnding() { panel.destroy(); Menu.removeActionGroup(MENU); - Settings.setValue(SETTINGS_KEY, Scene.getEngineDeferredDebugMode()); - Scene.setEngineDeferredDebugMode(-1); - Scene.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size + Settings.setValue(SETTINGS_KEY, Render.getEngineDeferredDebugMode()); + Render.setEngineDeferredDebugMode(-1); + Render.setEngineDeferredDebugSize({ x: 0.0, y: -1.0, z: 1.0, w: 1.0 }); // Reset to default size } Script.scriptEnding.connect(scriptEnding); diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 40196e320e..542db9b3ae 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -75,7 +75,7 @@ public: class Tone { public: - int toneCurve = 3; + int toneCurve = 1; // Means just Gamma 2.2 correction float exposure = 0.0; }; From fffe6dbb9bd32ec6dcb7ce71a8c787dcbc00df66 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 18 Dec 2015 15:38:01 -0800 Subject: [PATCH 119/195] relative rotation --- examples/flowArts/arcBall/arcBall.js | 13 ++++--------- examples/flowArts/arcBall/arcBallEntityScript.js | 4 +++- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js index e39a9af2d6..736920ddd5 100644 --- a/examples/flowArts/arcBall/arcBall.js +++ b/examples/flowArts/arcBall/arcBall.js @@ -35,22 +35,17 @@ ArcBall = function(spawnPosition) { z: 0 }), dimensions: { - x: .2, - y: .2, - z: .5 + x: .1, + y: .1, + z: .2 }, color: { red: 15, green: 10, blue: 150 }, - mass: 10, + damping: 0.8, collisionsWillMove: true, - // gravity: { - // x: 0, - // y: -0.5, - // z: 0 - // }, userData: JSON.stringify({ grabbableKey: { invertSolidWhileHeld: true diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index 8c37f170bb..4ad0d66257 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -34,8 +34,10 @@ createBeam: function(startPosition, endPosition) { print("CREATE BEAM") // Creates particle arc from start position to end position + var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; var sourceToTargetVec = Vec3.subtract(endPosition, startPosition); var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); + emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation); testBox = Entities.addEntity({ type: "Box", @@ -65,7 +67,7 @@ }, colorFinish: color, maxParticles: 100000, - lifespan: 2, + lifespan: 6, emitRate: 1000, emitOrientation: emitOrientation, emitSpeed: .4, From 4075f355a3dfa9a0e9e5016de4570b9ab68feedc Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 18 Dec 2015 15:44:01 -0800 Subject: [PATCH 120/195] more work on hand movement --- examples/controllers/reticleHandTest.js | 82 ++++++++++++++++--- interface/src/Application.cpp | 36 ++++++-- .../src/controllers/ScriptingInterface.h | 18 +++- 3 files changed, 117 insertions(+), 19 deletions(-) diff --git a/examples/controllers/reticleHandTest.js b/examples/controllers/reticleHandTest.js index 5d0e2f238a..4132c80d85 100644 --- a/examples/controllers/reticleHandTest.js +++ b/examples/controllers/reticleHandTest.js @@ -9,23 +9,83 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -function moveReticle(pitch, yaw) { - //print("pitch:" + pitch); - //print("yaw:" + yaw); - var globalPos = Controller.getReticlePosition(); - globalPos.x += yaw; - globalPos.y += pitch; - Controller.setReticlePosition(globalPos); +function msecTimestampNow() { + var d = new Date(); + return d.getTime(); } +function length(posA, posB) { + var dx = posA.x - posB.x; + var dy = posA.y - posB.y; + var length = Math.sqrt((dx*dx) + (dy*dy)) + return length; +} + +var EXPECTED_CHANGE = 50; +var lastPos = Controller.getReticlePosition(); +function moveReticle(dX, dY) { + var globalPos = Controller.getReticlePosition(); + + // some debugging to see if position is jumping around on us... + var distanceSinceLastMove = length(lastPos, globalPos); + if (distanceSinceLastMove > EXPECTED_CHANGE) { + print("distanceSinceLastMove:" + distanceSinceLastMove + "----------------------------"); + } + + if (Math.abs(dX) > EXPECTED_CHANGE) { + print("surpressing unexpectedly large change dX:" + dX + "----------------------------"); + dX = 0; + } + if (Math.abs(dY) > EXPECTED_CHANGE) { + print("surpressing unexpectedly large change dY:" + dY + "----------------------------"); + dY = 0; + } + + globalPos.x += dX; + globalPos.y += dY; + Controller.setReticlePosition(globalPos); + lastPos = globalPos; +} + +var lastTime = msecTimestampNow(); + var MAPPING_NAME = "com.highfidelity.testing.reticleWithHand"; var mapping = Controller.newMapping(MAPPING_NAME); mapping.from(Controller.Standard.RightHand).peek().to(function(pose) { - var angularVelocityEADs = Quat.safeEulerAngles(pose.angularVelocity); // degrees - var yaw = isNaN(angularVelocityEADs.y) ? 0 : (-angularVelocityEADs.y / 10); - var pitch = isNaN(angularVelocityEADs.x) ? 0 : (-angularVelocityEADs.x / 10); - moveReticle(pitch, yaw); + + + // pose.angularVelocity - is the angularVelocity in a "physics" sense, that + // means the direction of the vector is the axis of symetry of rotation + // and the scale of the vector is the speed in radians/second of rotation + // around that axis. + // + // we want to deconstruct that in the portion of the rotation on the Y axis + // and make that portion move our reticle in the horizontal/X direction + // and the portion of the rotation on the X axis and make that portion + // move our reticle in the veritcle/Y direction + var xPart = -pose.angularVelocity.y; + var yPart = -pose.angularVelocity.x; + + + var MOVE_SCALE = 1; + var MSECS_PER_SECOND = 1000; + var now = msecTimestampNow(); + var secondsSinceLast = (now - lastTime) / MSECS_PER_SECOND; + lastTime = now; + + //print("secondsSinceLast:" + secondsSinceLast); + + //print("x part:" + xPart); + //print("y part:" + yPart); + + var dX = (xPart * MOVE_SCALE) / secondsSinceLast; + var dY = (yPart * MOVE_SCALE) / secondsSinceLast; + + //print("dX:" + dX); + //print("dY:" + dY); + + moveReticle(dX, dY); }); mapping.enable(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fa5565417d..045b8beb40 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -686,13 +686,37 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : } else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) { VrMenu::toggle(); // show context menu even on non-stereo displays } else if (action == controller::toInt(controller::Action::RETICLE_X)) { - auto globalPos = QCursor::pos(); - globalPos.setX(globalPos.x() + state); - QCursor::setPos(globalPos); + auto oldPos = QCursor::pos(); + auto newPos = oldPos; + newPos.setX(oldPos.x() + state); + QCursor::setPos(newPos); + + + // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, + // remove it after we're done + const float REASONABLE_CHANGE = 50.0f; + glm::vec2 oldPosG = { oldPos.x(), oldPos.y() }; + glm::vec2 newPosG = { newPos.x(), newPos.y() }; + auto distance = glm::distance(oldPosG, newPosG); + if (distance > REASONABLE_CHANGE) { + qDebug() << "Action::RETICLE_X... UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPosG << " newPos:" << newPosG; + } + } else if (action == controller::toInt(controller::Action::RETICLE_Y)) { - auto globalPos = QCursor::pos(); - globalPos.setY(globalPos.y() + state); - QCursor::setPos(globalPos); + auto oldPos = QCursor::pos(); + auto newPos = oldPos; + newPos.setY(oldPos.y() + state); + QCursor::setPos(newPos); + + // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, + // remove it after we're done + const float REASONABLE_CHANGE = 50.0f; + glm::vec2 oldPosG = { oldPos.x(), oldPos.y() }; + glm::vec2 newPosG = { newPos.x(), newPos.y() }; + auto distance = glm::distance(oldPosG, newPosG); + if (distance > REASONABLE_CHANGE) { + qDebug() << "Action::RETICLE_Y... UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPosG << " newPos:" << newPosG; + } } } }); diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index 9d3942cd55..52ec52e852 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -30,6 +30,7 @@ #include #include +#include #include "UserInputMapper.h" #include "StandardControls.h" @@ -88,8 +89,21 @@ namespace controller { Q_INVOKABLE QObject* parseMapping(const QString& json); Q_INVOKABLE QObject* loadMapping(const QString& jsonUrl); - Q_INVOKABLE glm::vec2 getReticlePosition() { return toGlm(QCursor::pos()); } - Q_INVOKABLE void setReticlePosition(glm::vec2 position) { QCursor::setPos(position.x, position.y); } + Q_INVOKABLE glm::vec2 getReticlePosition() { + return toGlm(QCursor::pos()); + } + Q_INVOKABLE void setReticlePosition(glm::vec2 position) { + // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, + // remove it after we're done + const float REASONABLE_CHANGE = 50.0f; + glm::vec2 oldPos = toGlm(QCursor::pos()); + auto distance = glm::distance(oldPos, position); + if (distance > REASONABLE_CHANGE) { + qDebug() << "Contrller::ScriptingInterface ---- UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPos << " newPos:" << position; + } + + QCursor::setPos(position.x, position.y); + } //Q_INVOKABLE bool isPrimaryButtonPressed() const; //Q_INVOKABLE glm::vec2 getPrimaryJoystickPosition() const; From a621579f17043ee5db822f183e50a6f1a017ed94 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 18 Dec 2015 15:44:21 -0800 Subject: [PATCH 121/195] add philips version of hand movement --- examples/controllers/philipsVersion.js | 87 ++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 examples/controllers/philipsVersion.js diff --git a/examples/controllers/philipsVersion.js b/examples/controllers/philipsVersion.js new file mode 100644 index 0000000000..4ae617cf0b --- /dev/null +++ b/examples/controllers/philipsVersion.js @@ -0,0 +1,87 @@ +// +// reticleTest.js +// examples/controllers +// +// Created by Brad Hefta-Gaub on 2015/12/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 +// + +function length(posA, posB) { + var dx = posA.x - posB.x; + var dy = posA.y - posB.y; + var length = Math.sqrt((dx*dx) + (dy*dy)) + return length; +} + +var PITCH_DEADZONE = 1.0; +var PITCH_MAX = 20.0; +var YAW_DEADZONE = 1.0; +var YAW_MAX = 20.0; +var PITCH_SCALING = 10.0; +var YAW_SCALING = 10.0; + +var EXPECTED_CHANGE = 50; +var lastPos = Controller.getReticlePosition(); +function moveReticle(dY, dX) { + var globalPos = Controller.getReticlePosition(); + + // some debugging to see if position is jumping around on us... + var distanceSinceLastMove = length(lastPos, globalPos); + if (distanceSinceLastMove > EXPECTED_CHANGE) { + print("distanceSinceLastMove:" + distanceSinceLastMove + "----------------------------"); + } + + if (Math.abs(dX) > EXPECTED_CHANGE) { + print("UNEXPECTED dX:" + dX + "----------------------------"); + dX = 0; + } + if (Math.abs(dY) > EXPECTED_CHANGE) { + print("UNEXPECTED dY:" + dY + "----------------------------"); + dY = 0; + } + + globalPos.x += dX; + globalPos.y += dY; + Controller.setReticlePosition(globalPos); + lastPos = globalPos; +} + + +var MAPPING_NAME = "com.highfidelity.testing.reticleWithHand"; +var mapping = Controller.newMapping(MAPPING_NAME); + +var lastHandPitch = 0; +var lastHandYaw = 0; + +mapping.from(Controller.Standard.LeftHand).peek().to(function(pose) { + var handEulers = Quat.safeEulerAngles(pose.rotation); + //Vec3.print("handEulers:", handEulers); + + var handPitch = handEulers.y; + var handYaw = handEulers.x; + var changePitch = (handPitch - lastHandPitch) * PITCH_SCALING; + var changeYaw = (handYaw - lastHandYaw) * YAW_SCALING; + if (Math.abs(changePitch) > PITCH_MAX) { + print("Pitch: " + changePitch); + changePitch = 0; + } + if (Math.abs(changeYaw) > YAW_MAX) { + print("Yaw: " + changeYaw); + changeYaw = 0; + } + changePitch = Math.abs(changePitch) < PITCH_DEADZONE ? 0 : changePitch; + changeYaw = Math.abs(changeYaw) < YAW_DEADZONE ? 0 : changeYaw; + moveReticle(changePitch, changeYaw); + lastHandPitch = handPitch; + lastHandYaw = handYaw; + +}); +mapping.enable(); + + +Script.scriptEnding.connect(function(){ + mapping.disable(); +}); From 1beec0dbe7c46327bc0553734fa5871bbf3fc90d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 18 Dec 2015 18:15:05 -0800 Subject: [PATCH 122/195] balls --- examples/controllers/handControllerGrab.js | 21 ++++++---- examples/flowArts/arcBall/arcBall.js | 11 ++++- .../flowArts/arcBall/arcBallEntityScript.js | 42 ++++++++++++------- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 07894b46d1..fb7ba8a4f6 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -861,20 +861,25 @@ function MyController(hand) { var handPosition = this.getHandPosition(); var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); - + var objectRotation = grabbedProperties.rotation; + var currentObjectPosition = grabbedProperties.position; + var offset = Vec3.subtract(currentObjectPosition, handPosition); if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) { // if an object is "equipped" and has a spatialKey, use it. this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; - this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); - this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + if (grabbableData.spatialKey.relativePosition) { + this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); + } else { + this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset); + } + if (grabbableData.spatialKey.relativeRotation) { + this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + } else { + this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); + } } else { this.ignoreIK = false; - - var objectRotation = grabbedProperties.rotation; this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); - - var currentObjectPosition = grabbedProperties.position; - var offset = Vec3.subtract(currentObjectPosition, handPosition); this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset); } diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js index 736920ddd5..f779f65643 100644 --- a/examples/flowArts/arcBall/arcBall.js +++ b/examples/flowArts/arcBall/arcBall.js @@ -26,7 +26,7 @@ ArcBall = function(spawnPosition) { var containerBall = Entities.addEntity({ - type: "Box", + type: "Sphere", name: "Arc Ball", script: scriptURL, position: Vec3.sum(spawnPosition, { @@ -37,7 +37,7 @@ ArcBall = function(spawnPosition) { dimensions: { x: .1, y: .1, - z: .2 + z: .1 }, color: { red: 15, @@ -48,6 +48,13 @@ ArcBall = function(spawnPosition) { collisionsWillMove: true, userData: JSON.stringify({ grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 0, + z: -0.5 + }, + }, invertSolidWhileHeld: true } }) diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index 4ad0d66257..7cae0a9cb0 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -25,6 +25,7 @@ entities.forEach(function(entity) { var props = Entities.getEntityProperties(entity, ["position", "name"]); if (props.name === "Arc Ball" && JSON.stringify(_this.entityID) !== JSON.stringify(entity)) { + _this.target = entity; _this.createBeam(position, props.position); } }); @@ -32,21 +33,13 @@ }, createBeam: function(startPosition, endPosition) { - print("CREATE BEAM") // Creates particle arc from start position to end position var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; var sourceToTargetVec = Vec3.subtract(endPosition, startPosition); var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation); - testBox = Entities.addEntity({ - type: "Box", - dimensions: {x: .1, y: .1, z: 1}, - color: {red: 200, green: 10, blue: 10}, - position: startPosition, - rotation: emitOrientation, - visible: false - }); + var color = { red: 200, green: 10, @@ -57,7 +50,7 @@ name: "Particle Arc", parentID: this.entityID, parentJointIndex: -1, - position: startPosition, + // position: startPosition, isEmitting: true, colorStart: color, color: { @@ -67,7 +60,7 @@ }, colorFinish: color, maxParticles: 100000, - lifespan: 6, + lifespan: 5, emitRate: 1000, emitOrientation: emitOrientation, emitSpeed: .4, @@ -103,13 +96,32 @@ this.particleArc = Entities.addEntity(props); }, - continueNearGrab: function() {}, + updateBeam: function(startPosition) { + var targetPosition = Entities.getEntityProperties(this.target, "position").position; + print("TARGET position " + JSON.stringify(this.target)); + var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; + var sourceToTargetVec = Vec3.subtract(targetPosition, startPosition); + var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); + emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation); + Entities.editEntity(this.particleArc, {emitOrientation: emitOrientation}); + Entities.editEntity(this.testBox, {rotation: emitOrientation}); + }, - releaseGrab: function() {}, + continueNearGrab: function() { + var startPosition = Entities.getEntityProperties(this.entityID, "position").position; + this.updateBeam(startPosition); + }, + + releaseGrab: function() { + Entities.editEntity(this.particleArc, { + isEmitting: false + }); + }, unload: function() { - Entities.deleteEntity(this.particleArc); - Entities.deleteEntity(testBox); + if (this.particleArc) { + Entities.deleteEntity(this.particleArc); + } }, preload: function(entityID) { From e929e3f789f94b4305e3801c1a3fb74755b6d3c0 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 18 Dec 2015 19:18:39 -0800 Subject: [PATCH 123/195] more work on angular velocity tests --- ...t.js => reticleHandAngularVelocityTest.js} | 60 +++++++++++++------ libraries/script-engine/src/Quat.cpp | 4 ++ libraries/script-engine/src/Quat.h | 1 + 3 files changed, 48 insertions(+), 17 deletions(-) rename examples/controllers/{reticleHandTest.js => reticleHandAngularVelocityTest.js} (57%) diff --git a/examples/controllers/reticleHandTest.js b/examples/controllers/reticleHandAngularVelocityTest.js similarity index 57% rename from examples/controllers/reticleHandTest.js rename to examples/controllers/reticleHandAngularVelocityTest.js index 4132c80d85..94288b7bfb 100644 --- a/examples/controllers/reticleHandTest.js +++ b/examples/controllers/reticleHandAngularVelocityTest.js @@ -1,5 +1,5 @@ // -// reticleTest.js +// reticleHandAngularVelocityTest.js // examples/controllers // // Created by Brad Hefta-Gaub on 2015/12/15 @@ -9,6 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// If you set this to true, you will get the raw instantaneous angular velocity. +// note: there is a LOT of noise in the hydra rotation, you will probably be very +// frustrated with the level of jitter. +var USE_INSTANTANEOUS_ANGULAR_VELOCITY = false; +var whichHand = Controller.Standard.RightHand; +var whichTrigger = Controller.Standard.RT; + + function msecTimestampNow() { var d = new Date(); @@ -30,7 +38,7 @@ function moveReticle(dX, dY) { // some debugging to see if position is jumping around on us... var distanceSinceLastMove = length(lastPos, globalPos); if (distanceSinceLastMove > EXPECTED_CHANGE) { - print("distanceSinceLastMove:" + distanceSinceLastMove + "----------------------------"); + print("------------------ distanceSinceLastMove:" + distanceSinceLastMove + "----------------------------"); } if (Math.abs(dX) > EXPECTED_CHANGE) { @@ -48,12 +56,25 @@ function moveReticle(dX, dY) { lastPos = globalPos; } +var firstTime = true; var lastTime = msecTimestampNow(); +var previousRotation; var MAPPING_NAME = "com.highfidelity.testing.reticleWithHand"; var mapping = Controller.newMapping(MAPPING_NAME); -mapping.from(Controller.Standard.RightHand).peek().to(function(pose) { +mapping.from(whichTrigger).peek().constrainToInteger().to(Controller.Actions.ReticleClick); +mapping.from(whichHand).peek().to(function(pose) { + var MSECS_PER_SECOND = 1000; + var now = msecTimestampNow(); + var deltaMsecs = (now - lastTime); + var deltaTime = deltaMsecs / MSECS_PER_SECOND; + + if (firstTime) { + previousRotation = pose.rotation; + lastTime = msecTimestampNow(); + firstTime = false; + } // pose.angularVelocity - is the angularVelocity in a "physics" sense, that // means the direction of the vector is the axis of symetry of rotation @@ -67,29 +88,34 @@ mapping.from(Controller.Standard.RightHand).peek().to(function(pose) { var xPart = -pose.angularVelocity.y; var yPart = -pose.angularVelocity.x; + // pose.angularVelocity is "smoothed", we can calculate our own instantaneous + // angular velocity as such: + if (USE_INSTANTANEOUS_ANGULAR_VELOCITY) { + var previousConjugate = Quat.conjugate(previousRotation); + var deltaRotation = Quat.multiply(pose.rotation, previousConjugate); + var normalizedDeltaRotation = Quat.normalize(deltaRotation); + var axis = Quat.axis(normalizedDeltaRotation); + var speed = Quat.angle(normalizedDeltaRotation) / deltaTime; + var instantaneousAngularVelocity = Vec3.multiply(speed, axis); + + xPart = -instantaneousAngularVelocity.y; + yPart = -instantaneousAngularVelocity.x; + + previousRotation = pose.rotation; + } var MOVE_SCALE = 1; - var MSECS_PER_SECOND = 1000; - var now = msecTimestampNow(); - var secondsSinceLast = (now - lastTime) / MSECS_PER_SECOND; lastTime = now; - //print("secondsSinceLast:" + secondsSinceLast); - - //print("x part:" + xPart); - //print("y part:" + yPart); - - var dX = (xPart * MOVE_SCALE) / secondsSinceLast; - var dY = (yPart * MOVE_SCALE) / secondsSinceLast; - - //print("dX:" + dX); - //print("dY:" + dY); + var dX = (xPart * MOVE_SCALE) / deltaTime; + var dY = (yPart * MOVE_SCALE) / deltaTime; moveReticle(dX, dY); }); mapping.enable(); - Script.scriptEnding.connect(function(){ mapping.disable(); }); + + diff --git a/libraries/script-engine/src/Quat.cpp b/libraries/script-engine/src/Quat.cpp index bb74b20be0..f6b1726770 100644 --- a/libraries/script-engine/src/Quat.cpp +++ b/libraries/script-engine/src/Quat.cpp @@ -22,6 +22,10 @@ quat Quat::normalize(const glm::quat& q) { return glm::normalize(q); } +quat Quat::conjugate(const glm::quat& q) { + return glm::conjugate(q); +} + glm::quat Quat::rotationBetween(const glm::vec3& v1, const glm::vec3& v2) { return ::rotationBetween(v1, v2); } diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index 543c93401f..bc7f11ab01 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -26,6 +26,7 @@ class Quat : public QObject { public slots: glm::quat multiply(const glm::quat& q1, const glm::quat& q2); glm::quat normalize(const glm::quat& q); + glm::quat conjugate(const glm::quat& q); glm::quat lookAt(const glm::vec3& eye, const glm::vec3& center, const glm::vec3& up); glm::quat lookAtSimple(const glm::vec3& eye, const glm::vec3& center); glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2); From 8b9de716f137706423b8bd29418aea32f80e6a61 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 19 Dec 2015 08:08:10 -0800 Subject: [PATCH 124/195] fix bad pointer juju --- assignment-client/src/octree/OctreeQueryNode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 044b44a165..edb737ddd5 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -33,7 +33,7 @@ bool OctreeQueryNode::packetIsDuplicate() const { // of the entire packet, we need to compare only the packet content... if (_lastOctreePacketLength == _octreePacket->getPayloadSize()) { - if (memcmp(&_lastOctreePayload + OCTREE_PACKET_EXTRA_HEADERS_SIZE, + if (memcmp(_lastOctreePayload.data() + OCTREE_PACKET_EXTRA_HEADERS_SIZE, _octreePacket->getPayload() + OCTREE_PACKET_EXTRA_HEADERS_SIZE, _octreePacket->getPayloadSize() - OCTREE_PACKET_EXTRA_HEADERS_SIZE) == 0) { return true; From 9271209d8907d01a5365540e46791137efe7dadf Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 19 Dec 2015 08:13:53 -0800 Subject: [PATCH 125/195] another --- assignment-client/src/octree/OctreeQueryNode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index edb737ddd5..78a049edd6 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -101,7 +101,7 @@ void OctreeQueryNode::resetOctreePacket() { // scene information, (e.g. the root node packet of a static scene), we can use this as a strategy for reducing // packet send rate. _lastOctreePacketLength = _octreePacket->getPayloadSize(); - memcpy(&_lastOctreePayload, _octreePacket->getPayload(), _lastOctreePacketLength); + memcpy(_lastOctreePayload.data(), _octreePacket->getPayload(), _lastOctreePacketLength); // If we're moving, and the client asked for low res, then we force monochrome, otherwise, use // the clients requested color state. From aef748b894041d5745dfcf76e20a7a5524bbe5fa Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 21 Dec 2015 10:40:29 -0800 Subject: [PATCH 126/195] Adding linear color in Particule system --- .../src/RenderableParticleEffectEntityItem.cpp | 8 ++++---- libraries/entities-renderer/src/untextured_particle.slv | 5 ++--- libraries/entities/src/ParticleEffectEntityItem.h | 6 ++++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 4abd8dbafd..379d1cc4a3 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -223,10 +223,10 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { particleUniforms.radius.middle = getParticleRadius(); particleUniforms.radius.finish = getRadiusFinish(); particleUniforms.radius.spread = getRadiusSpread(); - particleUniforms.color.start = toGlm(getColorStart(), getAlphaStart()); - particleUniforms.color.middle = toGlm(getXColor(), getAlpha()); - particleUniforms.color.finish = toGlm(getColorFinish(), getAlphaFinish()); - particleUniforms.color.spread = toGlm(getColorSpread(), getAlphaSpread()); + particleUniforms.color.start = glm::vec4(getColorStartRGB(), getAlphaStart()); + particleUniforms.color.middle = glm::vec4(getColorRGB(), getAlpha()); + particleUniforms.color.finish = glm::vec4(getColorFinishRGB(), getAlphaFinish()); + particleUniforms.color.spread = glm::vec4(getColorSpreadRGB(), getAlphaSpread()); particleUniforms.lifespan = getLifespan(); // Build particle primitives diff --git a/libraries/entities-renderer/src/untextured_particle.slv b/libraries/entities-renderer/src/untextured_particle.slv index 3d1d99c0dc..ab0ea15219 100644 --- a/libraries/entities-renderer/src/untextured_particle.slv +++ b/libraries/entities-renderer/src/untextured_particle.slv @@ -9,16 +9,15 @@ // <@include gpu/Inputs.slh@> - +<@include gpu/Color.slh@> <@include gpu/Transform.slh@> - <$declareStandardTransform()$> out vec4 _color; void main(void) { // pass along the diffuse color - _color = inColor; + _color = colorToLinearRGBA(inColor); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index c35a45baeb..cae9340b6d 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -15,6 +15,8 @@ #include "EntityItem.h" +#include "ColorUtils.h" + class ParticleEffectEntityItem : public EntityItem { public: ALLOW_INSTANTIATION // This class can be instantiated @@ -47,6 +49,7 @@ public: const rgbColor& getColor() const { return _color; } xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } + glm::vec3 getColorRGB() const { return ColorUtils::toLinearVec3(toGlm(getXColor())); } static const xColor DEFAULT_COLOR; void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } @@ -59,14 +62,17 @@ public: bool _isColorStartInitialized = false; void setColorStart(const xColor& colorStart) { _colorStart = colorStart; _isColorStartInitialized = true; } xColor getColorStart() const { return _isColorStartInitialized ? _colorStart : getXColor(); } + glm::vec3 getColorStartRGB() const { return _isColorStartInitialized ? ColorUtils::toLinearVec3(toGlm(_colorStart)) : getColorRGB(); } bool _isColorFinishInitialized = false; void setColorFinish(const xColor& colorFinish) { _colorFinish = colorFinish; _isColorFinishInitialized = true; } xColor getColorFinish() const { return _isColorFinishInitialized ? _colorFinish : getXColor(); } + glm::vec3 getColorFinishRGB() const { return _isColorStartInitialized ? ColorUtils::toLinearVec3(toGlm(_colorFinish)) : getColorRGB(); } static const xColor DEFAULT_COLOR_SPREAD; void setColorSpread(const xColor& colorSpread) { _colorSpread = colorSpread; } xColor getColorSpread() const { return _colorSpread; } + glm::vec3 getColorSpreadRGB() const { return ColorUtils::toLinearVec3(toGlm(_colorSpread)); } static const float MAXIMUM_ALPHA; static const float MINIMUM_ALPHA; From 7a7befafb9e4afc78039d4a4f99da1b53763ea5f Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 21 Dec 2015 10:43:59 -0800 Subject: [PATCH 127/195] arc balls working --- examples/controllers/handControllerGrab.js | 54 ++++++++++++------- examples/flowArts/arcBall/arcBall.js | 27 ++++++---- .../flowArts/arcBall/arcBallEntityScript.js | 47 ++++++++++------ 3 files changed, 81 insertions(+), 47 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 07894b46d1..6cacc2e80a 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -218,6 +218,7 @@ function getSpatialOffsetPosition(hand, spatialKey) { } var yFlip = Quat.angleAxis(180, Vec3.UNIT_Y); + function getSpatialOffsetRotation(hand, spatialKey) { var rotation = Quat.IDENTITY; @@ -261,9 +262,9 @@ function MyController(hand) { this.triggerValue = 0; // rolling average of trigger value this.rawTriggerValue = 0; this.rawBumperValue = 0; - + this.overlayLine = null; - + this.ignoreIK = false; this.offsetPosition = Vec3.ZERO; this.offsetRotation = Quat.IDENTITY; @@ -819,8 +820,16 @@ function MyController(hand) { // mix in head motion if (MOVE_WITH_HEAD) { var objDistance = Vec3.length(objectToAvatar); - var before = Vec3.multiplyQbyV(this.currentCameraOrientation, { x: 0.0, y: 0.0, z: objDistance }); - var after = Vec3.multiplyQbyV(Camera.orientation, { x: 0.0, y: 0.0, z: objDistance }); + var before = Vec3.multiplyQbyV(this.currentCameraOrientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); + var after = Vec3.multiplyQbyV(Camera.orientation, { + x: 0.0, + y: 0.0, + z: objDistance + }); var change = Vec3.subtract(before, after); this.currentCameraOrientation = Camera.orientation; this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change); @@ -861,20 +870,25 @@ function MyController(hand) { var handPosition = this.getHandPosition(); var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); - + var objectRotation = grabbedProperties.rotation; + var currentObjectPosition = grabbedProperties.position; + var offset = Vec3.subtract(currentObjectPosition, handPosition); if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) { // if an object is "equipped" and has a spatialKey, use it. this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; - this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); - this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + if (grabbableData.spatialKey.relativePosition) { + this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); + } else { + this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset); + } + if (grabbableData.spatialKey.relativeRotation) { + this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); + } else { + this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); + } } else { this.ignoreIK = false; - - var objectRotation = grabbedProperties.rotation; this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); - - var currentObjectPosition = grabbedProperties.position; - var offset = Vec3.subtract(currentObjectPosition, handPosition); this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset); } @@ -1304,10 +1318,10 @@ Controller.enableMapping(MAPPING_NAME); var handToDisable = 'none'; function update() { - if (handToDisable !== LEFT_HAND && handToDisable!=='both') { + if (handToDisable !== LEFT_HAND && handToDisable !== 'both') { leftController.update(); } - if (handToDisable !== RIGHT_HAND && handToDisable!=='both') { + if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') { rightController.update(); } } @@ -1315,7 +1329,7 @@ function update() { Messages.subscribe('Hifi-Hand-Disabler'); handleHandDisablerMessages = function(channel, message, sender) { - + if (sender === MyAvatar.sessionUUID) { if (message === 'left') { handToDisable = LEFT_HAND; @@ -1323,11 +1337,11 @@ handleHandDisablerMessages = function(channel, message, sender) { if (message === 'right') { handToDisable = RIGHT_HAND; } - if(message==='both'){ - handToDisable='both'; + if (message === 'both') { + handToDisable = 'both'; } - if(message==='none'){ - handToDisable='none'; + if (message === 'none') { + handToDisable = 'none'; } } @@ -1342,4 +1356,4 @@ function cleanup() { } Script.scriptEnding.connect(cleanup); -Script.update.connect(update); +Script.update.connect(update); \ No newline at end of file diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js index 736920ddd5..54cb16fe15 100644 --- a/examples/flowArts/arcBall/arcBall.js +++ b/examples/flowArts/arcBall/arcBall.js @@ -26,7 +26,7 @@ ArcBall = function(spawnPosition) { var containerBall = Entities.addEntity({ - type: "Box", + type: "Sphere", name: "Arc Ball", script: scriptURL, position: Vec3.sum(spawnPosition, { @@ -35,12 +35,12 @@ ArcBall = function(spawnPosition) { z: 0 }), dimensions: { - x: .1, - y: .1, - z: .2 + x: .05, + y: .05, + z: .05 }, color: { - red: 15, + red: 100, green: 10, blue: 150 }, @@ -48,6 +48,13 @@ ArcBall = function(spawnPosition) { collisionsWillMove: true, userData: JSON.stringify({ grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 0, + z: -0.5 + }, + }, invertSolidWhileHeld: true } }) @@ -127,11 +134,11 @@ ArcBall = function(spawnPosition) { - function cleanup() { - Entities.deleteEntity(arcBall); - Entities.deleteEntity(containerBall); - Entities.deleteEntity(light); - } + function cleanup() { + Entities.deleteEntity(arcBall); + Entities.deleteEntity(containerBall); + Entities.deleteEntity(light); + } this.cleanup = cleanup; } \ No newline at end of file diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index 4ad0d66257..7bb8472ce9 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -25,6 +25,7 @@ entities.forEach(function(entity) { var props = Entities.getEntityProperties(entity, ["position", "name"]); if (props.name === "Arc Ball" && JSON.stringify(_this.entityID) !== JSON.stringify(entity)) { + _this.target = entity; _this.createBeam(position, props.position); } }); @@ -32,21 +33,13 @@ }, createBeam: function(startPosition, endPosition) { - print("CREATE BEAM") - // Creates particle arc from start position to end position + // Creates particle arc from start position to end position var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; var sourceToTargetVec = Vec3.subtract(endPosition, startPosition); var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation); - testBox = Entities.addEntity({ - type: "Box", - dimensions: {x: .1, y: .1, z: 1}, - color: {red: 200, green: 10, blue: 10}, - position: startPosition, - rotation: emitOrientation, - visible: false - }); + var color = { red: 200, green: 10, @@ -57,7 +50,7 @@ name: "Particle Arc", parentID: this.entityID, parentJointIndex: -1, - position: startPosition, + // position: startPosition, isEmitting: true, colorStart: color, color: { @@ -67,7 +60,7 @@ }, colorFinish: color, maxParticles: 100000, - lifespan: 6, + lifespan: 5, emitRate: 1000, emitOrientation: emitOrientation, emitSpeed: .4, @@ -98,18 +91,38 @@ alphaStart: 0.5, alphaFinish: 0.5, textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", - emitterShouldTrail: false + emitterShouldTrail: true } this.particleArc = Entities.addEntity(props); }, - continueNearGrab: function() {}, + updateBeam: function(startPosition) { + var targetPosition = Entities.getEntityProperties(this.target, "position").position; + print("TARGET position " + JSON.stringify(this.target)); + var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; + var sourceToTargetVec = Vec3.subtract(targetPosition, startPosition); + var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); + // emitOrientation = Quat.multiply(emitOrientation,Quat.inverse(rotation)); + Entities.editEntity(this.particleArc, { + emitOrientation: emitOrientation + }); + }, - releaseGrab: function() {}, + continueNearGrab: function() { + var startPosition = Entities.getEntityProperties(this.entityID, "position").position; + this.updateBeam(startPosition); + }, + + releaseGrab: function() { + Entities.editEntity(this.particleArc, { + isEmitting: false + }); + }, unload: function() { - Entities.deleteEntity(this.particleArc); - Entities.deleteEntity(testBox); + if (this.particleArc) { + Entities.deleteEntity(this.particleArc); + } }, preload: function(entityID) { From 45ba7a3d35c12e55207acbee615757f022e655e1 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 21 Dec 2015 10:46:54 -0800 Subject: [PATCH 128/195] merged --- examples/controllers/handControllerGrab.js | 10 --------- .../flowArts/arcBall/arcBallEntityScript.js | 21 ------------------- 2 files changed, 31 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 6337079dc5..6cacc2e80a 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -877,24 +877,14 @@ function MyController(hand) { // if an object is "equipped" and has a spatialKey, use it. this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false; if (grabbableData.spatialKey.relativePosition) { -<<<<<<< HEAD this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); -======= - this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey); ->>>>>>> origin/polylineOptimizations } else { this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset); } if (grabbableData.spatialKey.relativeRotation) { -<<<<<<< HEAD this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); } else { this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); -======= - this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey); - } else { - this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); ->>>>>>> origin/polylineOptimizations } } else { this.ignoreIK = false; diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index 539bdd7cf0..7bb8472ce9 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -33,21 +33,13 @@ }, createBeam: function(startPosition, endPosition) { -<<<<<<< HEAD // Creates particle arc from start position to end position -======= - // Creates particle arc from start position to end position ->>>>>>> origin/polylineOptimizations var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; var sourceToTargetVec = Vec3.subtract(endPosition, startPosition); var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation); -<<<<<<< HEAD -======= - ->>>>>>> origin/polylineOptimizations var color = { red: 200, green: 10, @@ -110,7 +102,6 @@ var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; var sourceToTargetVec = Vec3.subtract(targetPosition, startPosition); var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); -<<<<<<< HEAD // emitOrientation = Quat.multiply(emitOrientation,Quat.inverse(rotation)); Entities.editEntity(this.particleArc, { emitOrientation: emitOrientation @@ -122,18 +113,6 @@ this.updateBeam(startPosition); }, -======= - emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation); - Entities.editEntity(this.particleArc, {emitOrientation: emitOrientation}); - Entities.editEntity(this.testBox, {rotation: emitOrientation}); - }, - - continueNearGrab: function() { - var startPosition = Entities.getEntityProperties(this.entityID, "position").position; - this.updateBeam(startPosition); - }, - ->>>>>>> origin/polylineOptimizations releaseGrab: function() { Entities.editEntity(this.particleArc, { isEmitting: false From 248b3d09ace2a887283b255194a429c087e7a981 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Mon, 21 Dec 2015 10:49:49 -0800 Subject: [PATCH 129/195] add absolute rotation based hand reticle movement --- .../controllers/reticleHandRotationTest.js | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 examples/controllers/reticleHandRotationTest.js diff --git a/examples/controllers/reticleHandRotationTest.js b/examples/controllers/reticleHandRotationTest.js new file mode 100644 index 0000000000..d413e531df --- /dev/null +++ b/examples/controllers/reticleHandRotationTest.js @@ -0,0 +1,103 @@ +// +// reticleHandRotationTest.js +// examples/controllers +// +// Created by Brad Hefta-Gaub on 2015/12/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 +// + +Math.clamp=function(a,b,c) { + return Math.max(b,Math.min(c,a)); +} + +var whichHand = Controller.Standard.RightHand; +var whichTrigger = Controller.Standard.RT; + +function length(posA, posB) { + var dx = posA.x - posB.x; + var dy = posA.y - posB.y; + var length = Math.sqrt((dx*dx) + (dy*dy)) + return length; +} + +var EXPECTED_CHANGE = 50; +var lastPos = Controller.getReticlePosition(); +function moveReticleAbsolute(x, y) { + var globalPos = Controller.getReticlePosition(); + var dX = x - globalPos.x; + var dY = y - globalPos.y; + + // some debugging to see if position is jumping around on us... + var distanceSinceLastMove = length(lastPos, globalPos); + if (distanceSinceLastMove > EXPECTED_CHANGE) { + print("------------------ distanceSinceLastMove:" + distanceSinceLastMove + "----------------------------"); + } + + if (Math.abs(dX) > EXPECTED_CHANGE) { + print("surpressing unexpectedly large change dX:" + dX + "----------------------------"); + } + if (Math.abs(dY) > EXPECTED_CHANGE) { + print("surpressing unexpectedly large change dY:" + dY + "----------------------------"); + } + + globalPos.x = x; + globalPos.y = y; + Controller.setReticlePosition(globalPos); + lastPos = globalPos; +} + + +var MAPPING_NAME = "com.highfidelity.testing.reticleWithHandRotation"; +var mapping = Controller.newMapping(MAPPING_NAME); +mapping.from(whichTrigger).peek().constrainToInteger().to(Controller.Actions.ReticleClick); +mapping.from(whichHand).peek().to(function(pose) { + + // NOTE: hack for now + var screenSizeX = 1920; + var screenSizeY = 1080; + + var rotated = Vec3.multiplyQbyV(pose.rotation, Vec3.UNIT_NEG_Y); // + var absolutePitch = rotated.y; // from 1 down to -1 up ... but note: if you rotate down "too far" it starts to go up again... + var absoluteYaw = rotated.z; // from -1 left to 1 right + //print("absolutePitch:" + absolutePitch); + //print("absoluteYaw:" + absoluteYaw); + //Vec3.print("rotated:", rotated); + + var ROTATION_BOUND = 0.6; + var clampYaw = Math.clamp(absoluteYaw, -ROTATION_BOUND, ROTATION_BOUND); + var clampPitch = Math.clamp(absolutePitch, -ROTATION_BOUND, ROTATION_BOUND); + //var clampYaw = absoluteYaw; + //print("clampYaw:" + clampYaw); + //print("clampPitch:" + clampPitch); + + // if using entire span... + //var xRatio = (absoluteYaw + 1) / 2; + //var yRatio = (absolutePitch + 1) / 2; + + // if using only from -0.5 to 0.5 + var xRatio = (clampYaw + ROTATION_BOUND) / (2 * ROTATION_BOUND); + var yRatio = (clampPitch + ROTATION_BOUND) / (2 * ROTATION_BOUND); + + //print("xRatio:" + xRatio); + //print("yRatio:" + yRatio); + + //print("ratio x:" + xRatio + " y:" + yRatio); + + var x = screenSizeX * xRatio; + var y = screenSizeY * yRatio; + + //print("position x:" + x + " y:" + y); + if (!(xRatio == 0.5 && yRatio == 0)) { + moveReticleAbsolute(x, y); + } +}); +mapping.enable(); + +Script.scriptEnding.connect(function(){ + mapping.disable(); +}); + + From 48ab99c34864f5ecd2734900e4d89b29f964288d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 21 Dec 2015 11:00:10 -0800 Subject: [PATCH 130/195] rotation fix --- examples/flowArts/arcBall/arcBall.js | 8 +- .../flowArts/arcBall/arcBallEntityScript.js | 112 +++++++++--------- 2 files changed, 63 insertions(+), 57 deletions(-) diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js index 54cb16fe15..f6860b54c6 100644 --- a/examples/flowArts/arcBall/arcBall.js +++ b/examples/flowArts/arcBall/arcBall.js @@ -31,7 +31,7 @@ ArcBall = function(spawnPosition) { script: scriptURL, position: Vec3.sum(spawnPosition, { x: 0, - y: .5, + y: .7, z: 0 }), dimensions: { @@ -51,8 +51,8 @@ ArcBall = function(spawnPosition) { spatialKey: { relativePosition: { x: 0, - y: 0, - z: -0.5 + y: -0.5, + z: 0.0 }, }, invertSolidWhileHeld: true @@ -97,7 +97,7 @@ ArcBall = function(spawnPosition) { }, maxParticles: 100000, lifespan: 2, - emitRate: 1000, + emitRate: 400, emitSpeed: .1, lifetime: -1, speedSpread: 0.0, diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index 7bb8472ce9..7edf22ecdb 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -14,6 +14,15 @@ var _this; var ArcBall = function() { _this = this; + this.colorPalette = [{ + red: 25, + green: 20, + blue: 162 + }, { + red: 200, + green: 10, + blue: 10 + }]; }; ArcBall.prototype = { @@ -40,59 +49,56 @@ emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation); - var color = { - red: 200, - green: 10, - blue: 10 - }; - var props = { - type: "ParticleEffect", - name: "Particle Arc", - parentID: this.entityID, - parentJointIndex: -1, - // position: startPosition, - isEmitting: true, - colorStart: color, - color: { - red: 200, - green: 200, - blue: 255 - }, - colorFinish: color, - maxParticles: 100000, - lifespan: 5, - emitRate: 1000, - emitOrientation: emitOrientation, - emitSpeed: .4, - speedSpread: 0.0, - emitDimensions: { - x: 0, - y: 0, - z: 0 - }, - polarStart: 0, - polarFinish: .0, - azimuthStart: .1, - azimuthFinish: .01, - emitAcceleration: { - x: 0, - y: 0, - z: 0 - }, - accelerationSpread: { - x: .00, - y: .00, - z: .00 - }, - radiusStart: 0.03, - adiusFinish: 0.025, - alpha: 0.7, - alphaSpread: .1, - alphaStart: 0.5, - alphaFinish: 0.5, - textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", - emitterShouldTrail: true - } + var color = this.colorPalette[randInt(0, this.colorPalette.length)]; + var props = { + type: "ParticleEffect", + name: "Particle Arc", + parentID: this.entityID, + parentJointIndex: -1, + // position: startPosition, + isEmitting: true, + colorStart: color, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 2, + emitRate: 500, + emitOrientation: emitOrientation, + emitSpeed: .4, + speedSpread: 0.1, + emitDimensions: { + x: 0, + y: 0, + z: 0 + }, + polarStart: 0, + polarFinish: .0, + azimuthStart: .1, + azimuthFinish: .01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + radiusStart: 0.03, + radiusFinish: 0.025, + radiusSpread: .01, + alpha: 0.7, + alphaSpread: .1, + alphaStart: 0.5, + alphaFinish: 0.5, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", + emitterShouldTrail: true + } this.particleArc = Entities.addEntity(props); }, From 3c66e3826830a2f9bc84697da5e4d7b61dc77423 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 21 Dec 2015 11:12:59 -0800 Subject: [PATCH 131/195] test --- examples/flowArts/arcBall/arcBall.js | 7 +++--- .../flowArts/arcBall/arcBallEntityScript.js | 22 +++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js index f6860b54c6..e67dffddff 100644 --- a/examples/flowArts/arcBall/arcBall.js +++ b/examples/flowArts/arcBall/arcBall.js @@ -44,6 +44,7 @@ ArcBall = function(spawnPosition) { green: 10, blue: 150 }, + ignoreForCollisions: true, damping: 0.8, collisionsWillMove: true, userData: JSON.stringify({ @@ -51,11 +52,11 @@ ArcBall = function(spawnPosition) { spatialKey: { relativePosition: { x: 0, - y: -0.5, - z: 0.0 + y: 0.0, + z: -0.5 }, }, - invertSolidWhileHeld: true + // invertSolidWhileHeld: true } }) }); diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index 7edf22ecdb..0906b90b53 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -65,15 +65,15 @@ }, colorFinish: color, maxParticles: 100000, - lifespan: 2, - emitRate: 500, + lifespan: 1, + emitRate: 1000, emitOrientation: emitOrientation, - emitSpeed: .4, + emitSpeed: .2, speedSpread: 0.1, emitDimensions: { - x: 0, - y: 0, - z: 0 + x: .1, + y: .1, + z: .1 }, polarStart: 0, polarFinish: .0, @@ -89,13 +89,13 @@ y: .00, z: .00 }, - radiusStart: 0.03, - radiusFinish: 0.025, - radiusSpread: .01, - alpha: 0.7, + radiusStart: 0.01, + radiusFinish: 0.005, + radiusSpread: .005, + alpha: 0.5, alphaSpread: .1, alphaStart: 0.5, - alphaFinish: 0.5, + alphaFinish: 0.0, textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", emitterShouldTrail: true } From 05b7fcc9573dd43a9df57df4d901b618767918b0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 21 Dec 2015 11:19:05 -0800 Subject: [PATCH 132/195] Remove script -> qt::webchannel dependency --- interface/src/Application.cpp | 1 + libraries/script-engine/CMakeLists.txt | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 3 --- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e22b3913d0..f4fe919780 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4183,6 +4183,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri LocationScriptingInterface::locationSetter); scriptEngine->registerFunction("WebWindow", WebWindowClass::constructor, 1); + scriptEngine->registerFunction("OverlayWebWindow", QmlWebWindowClass::constructor); scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Stats", Stats::getInstance()); diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index c1131765f7..3796abd92a 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -1,3 +1,3 @@ set(TARGET_NAME script-engine) setup_hifi_library(Gui Network Script WebSockets Widgets) -link_hifi_libraries(shared networking ui octree gpu procedural model model-networking recording avatars fbx entities controllers animation audio physics) +link_hifi_libraries(shared networking octree gpu procedural model model-networking recording avatars fbx entities controllers animation audio physics) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 5f39bee9fa..ded3db11e9 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -30,7 +30,6 @@ #include #include -#include #include #include @@ -351,8 +350,6 @@ void ScriptEngine::init() { qScriptRegisterSequenceMetaType >(this); qScriptRegisterSequenceMetaType >(this); - - registerFunction("OverlayWebWindow", QmlWebWindowClass::constructor); QScriptValue xmlHttpRequestConstructorValue = newFunction(XMLHttpRequestClass::constructor); globalObject().setProperty("XMLHttpRequest", xmlHttpRequestConstructorValue); From ba3633710a9dfb0663f386a8f532fd5bd83e1c5f Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 21 Dec 2015 11:29:59 -0800 Subject: [PATCH 133/195] name fixes --- examples/flowArts/arcBall/arcBall.js | 258 +++++++++--------- examples/flowArts/flowArtsHutSpawner.js | 8 +- .../{LightSaber.js => lightSaber.js} | 0 .../raveStick/{RaveStick.js => raveStick.js} | 0 4 files changed, 130 insertions(+), 136 deletions(-) rename examples/flowArts/lightSaber/{LightSaber.js => lightSaber.js} (100%) rename examples/flowArts/raveStick/{RaveStick.js => raveStick.js} (100%) diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js index e67dffddff..0906b90b53 100644 --- a/examples/flowArts/arcBall/arcBall.js +++ b/examples/flowArts/arcBall/arcBall.js @@ -1,145 +1,139 @@ -// -// arcBall.js -// examples/arcBall -// +// arcBallEntityScript.js +// +// Script Type: Entity // Created by Eric Levin on 12/17/15. -// Copyright 2014 High Fidelity, Inc. -// -// This script creats a particle light ball which makes particle trails as you move it. -// +// Copyright 2015 High Fidelity, Inc. // +// This entity script handles the logic for the arcBall rave toy // 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("../../libraries/utils.js"); - - -var scriptURL = Script.resolvePath("arcBallEntityScript.js"); -ArcBall = function(spawnPosition) { - - var colorPalette = [{ - red: 25, - green: 20, - blue: 162 - }]; - - - var containerBall = Entities.addEntity({ - type: "Sphere", - name: "Arc Ball", - script: scriptURL, - position: Vec3.sum(spawnPosition, { - x: 0, - y: .7, - z: 0 - }), - dimensions: { - x: .05, - y: .05, - z: .05 - }, - color: { - red: 100, - green: 10, - blue: 150 - }, - ignoreForCollisions: true, - damping: 0.8, - collisionsWillMove: true, - userData: JSON.stringify({ - grabbableKey: { - spatialKey: { - relativePosition: { - x: 0, - y: 0.0, - z: -0.5 - }, - }, - // invertSolidWhileHeld: true - } - }) - }); - - - var light = Entities.addEntity({ - type: 'Light', - name: "ballLight", - parentID: containerBall, - dimensions: { - x: 30, - y: 30, - z: 30 - }, - color: colorPalette[randInt(0, colorPalette.length)], - intensity: 5 - }); - - - var arcBall = Entities.addEntity({ - type: "ParticleEffect", - parentID: containerBall, - isEmitting: true, - name: "Arc Ball Particle Effect", - colorStart: { - red: 200, - green: 20, - blue: 40 - }, - color: { - red: 200, - green: 200, - blue: 255 - }, - colorFinish: { +(function() { + Script.include("../../libraries/utils.js"); + var _this; + var ArcBall = function() { + _this = this; + this.colorPalette = [{ red: 25, green: 20, - blue: 255 + blue: 162 + }, { + red: 200, + green: 10, + blue: 10 + }]; + }; + + ArcBall.prototype = { + isGrabbed: false, + startNearGrab: function() { + //Search for nearby balls and create an arc to it if one is found + var position = Entities.getEntityProperties(this.entityID, "position").position + var entities = Entities.findEntities(position, 10); + entities.forEach(function(entity) { + var props = Entities.getEntityProperties(entity, ["position", "name"]); + if (props.name === "Arc Ball" && JSON.stringify(_this.entityID) !== JSON.stringify(entity)) { + _this.target = entity; + _this.createBeam(position, props.position); + } + }); + }, - maxParticles: 100000, - lifespan: 2, - emitRate: 400, - emitSpeed: .1, - lifetime: -1, - speedSpread: 0.0, - emitDimensions: { - x: 0, - y: 0, - z: 0 - }, - polarStart: 0, - polarFinish: Math.PI, - azimuthStart: -Math.PI, - azimuthFinish: Math.PI, - emitAcceleration: { - x: 0, - y: 0, - z: 0 - }, - accelerationSpread: { - x: .00, - y: .00, - z: .00 - }, - particleRadius: 0.02, - radiusSpread: 0, - radiusStart: 0.03, - radiusFinish: 0.0003, - alpha: 0, - alphaSpread: .5, - alphaStart: 0, - alphaFinish: 0.5, - textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - emitterShouldTrail: true - }) + + createBeam: function(startPosition, endPosition) { + // Creates particle arc from start position to end position + var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; + var sourceToTargetVec = Vec3.subtract(endPosition, startPosition); + var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); + emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation); + var color = this.colorPalette[randInt(0, this.colorPalette.length)]; + var props = { + type: "ParticleEffect", + name: "Particle Arc", + parentID: this.entityID, + parentJointIndex: -1, + // position: startPosition, + isEmitting: true, + colorStart: color, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 1, + emitRate: 1000, + emitOrientation: emitOrientation, + emitSpeed: .2, + speedSpread: 0.1, + emitDimensions: { + x: .1, + y: .1, + z: .1 + }, + polarStart: 0, + polarFinish: .0, + azimuthStart: .1, + azimuthFinish: .01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + radiusStart: 0.01, + radiusFinish: 0.005, + radiusSpread: .005, + alpha: 0.5, + alphaSpread: .1, + alphaStart: 0.5, + alphaFinish: 0.0, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", + emitterShouldTrail: true + } + this.particleArc = Entities.addEntity(props); + }, - function cleanup() { - Entities.deleteEntity(arcBall); - Entities.deleteEntity(containerBall); - Entities.deleteEntity(light); - } + updateBeam: function(startPosition) { + var targetPosition = Entities.getEntityProperties(this.target, "position").position; + print("TARGET position " + JSON.stringify(this.target)); + var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; + var sourceToTargetVec = Vec3.subtract(targetPosition, startPosition); + var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); + // emitOrientation = Quat.multiply(emitOrientation,Quat.inverse(rotation)); + Entities.editEntity(this.particleArc, { + emitOrientation: emitOrientation + }); + }, - this.cleanup = cleanup; -} \ No newline at end of file + continueNearGrab: function() { + var startPosition = Entities.getEntityProperties(this.entityID, "position").position; + this.updateBeam(startPosition); + }, + + releaseGrab: function() { + Entities.editEntity(this.particleArc, { + isEmitting: false + }); + }, + + unload: function() { + if (this.particleArc) { + Entities.deleteEntity(this.particleArc); + } + }, + + preload: function(entityID) { + this.entityID = entityID; + }, + }; + return new ArcBall(); +}); \ No newline at end of file diff --git a/examples/flowArts/flowArtsHutSpawner.js b/examples/flowArts/flowArtsHutSpawner.js index 39dcf15698..2c87a27c15 100644 --- a/examples/flowArts/flowArtsHutSpawner.js +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -14,10 +14,10 @@ Script.include("../../libraries/utils.js"); -Script.include("lightBall/LightBall.js"); -Script.include("raveStick/RaveStick.js"); -Script.include("lightSaber/LightSaber.js"); -Script.include("arcBall/ArcBall.js"); +Script.include("lightBall/lightBall.js"); +Script.include("raveStick/raveStick.js"); +Script.include("lightSaber/lightSaber.js"); +Script.include("arcBall/arcBall.js"); diff --git a/examples/flowArts/lightSaber/LightSaber.js b/examples/flowArts/lightSaber/lightSaber.js similarity index 100% rename from examples/flowArts/lightSaber/LightSaber.js rename to examples/flowArts/lightSaber/lightSaber.js diff --git a/examples/flowArts/raveStick/RaveStick.js b/examples/flowArts/raveStick/raveStick.js similarity index 100% rename from examples/flowArts/raveStick/RaveStick.js rename to examples/flowArts/raveStick/raveStick.js From 6ef77bc46aeab1fb17186855271fd16284da9102 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 17 Dec 2015 15:46:44 -0800 Subject: [PATCH 134/195] Support the marketplace in QML --- examples/edit.js | 47 ++++++++++++------- interface/resources/qml/QmlWebWindow.qml | 16 ++++--- interface/src/Application.cpp | 2 +- interface/src/Application.h | 7 +-- libraries/networking/src/AbstractUriHandler.h | 19 ++++++++ libraries/octree/src/Octree.cpp | 2 +- libraries/ui/src/QmlWebWindowClass.cpp | 43 +++++++++++++++-- 7 files changed, 105 insertions(+), 31 deletions(-) create mode 100644 libraries/networking/src/AbstractUriHandler.h diff --git a/examples/edit.js b/examples/edit.js index 59b6ae3e7d..074b43c8c1 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -140,9 +140,33 @@ var importingSVOTextOverlay = Overlays.addOverlay("text", { }); var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; -var marketplaceWindow = new WebWindow('Marketplace', MARKETPLACE_URL, 900, 700, false); +var marketplaceWindow = new OverlayWebWindow('Marketplace', "about:blank", 900, 700, false); marketplaceWindow.setVisible(false); +function showMarketplace(marketplaceID) { + var url = MARKETPLACE_URL; + if (marketplaceID) { + url = url + "/items/" + marketplaceID; + } + print("setting marketplace URL to " + url); + marketplaceWindow.setURL(url); + marketplaceWindow.setVisible(true); + marketplaceWindow.raise(); +} + +function hideMarketplace() { + marketplaceWindow.setVisible(false); + marketplaceWindow.setURL("about:blank"); +} + +function toggleMarketplace() { + if (marketplaceWindow.visible) { + hideMarketplace(); + } else { + showMarketplace(); + } +} + var toolBar = (function() { var that = {}, toolBar, @@ -413,12 +437,9 @@ var toolBar = (function() { newModelButtonDown = true; return true; } + if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) { - if (marketplaceWindow.url != MARKETPLACE_URL) { - marketplaceWindow.setURL(MARKETPLACE_URL); - } - marketplaceWindow.setVisible(true); - marketplaceWindow.raise(); + toggleMarketplace(); return true; } @@ -1336,6 +1357,7 @@ function getPositionToCreateEntity() { } function importSVO(importURL) { + print("Import URL requested: " + importURL) if (!Entities.canAdjustLocks()) { Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); return; @@ -1574,11 +1596,7 @@ PropertiesTool = function(opts) { pushCommandForSelections(); selectionManager._update(); } else if (data.type == "showMarketplace") { - if (marketplaceWindow.url != data.url) { - marketplaceWindow.setURL(data.url); - } - marketplaceWindow.setVisible(true); - marketplaceWindow.raise(); + showMarketplace(); } else if (data.type == "action") { if (data.action == "moveSelectionToGrid") { if (selectionManager.hasSelection()) { @@ -1859,12 +1877,7 @@ var propertyMenu = PopupMenu(); propertyMenu.onSelectMenuItem = function(name) { if (propertyMenu.marketplaceID) { - var url = MARKETPLACE_URL + "/items/" + propertyMenu.marketplaceID; - if (marketplaceWindow.url != url) { - marketplaceWindow.setURL(url); - } - marketplaceWindow.setVisible(true); - marketplaceWindow.raise(); + showMarketplace(propertyMenu.marketplaceID); } }; diff --git a/interface/resources/qml/QmlWebWindow.qml b/interface/resources/qml/QmlWebWindow.qml index 3eb01aa9ba..029d50519a 100644 --- a/interface/resources/qml/QmlWebWindow.qml +++ b/interface/resources/qml/QmlWebWindow.qml @@ -13,12 +13,18 @@ VrDialog { HifiConstants { id: hifi } title: "WebWindow" resizable: true + // Don't destroy on close... otherwise the JS/C++ will have a dangling pointer + destroyOnCloseButton: false contentImplicitWidth: clientArea.implicitWidth contentImplicitHeight: clientArea.implicitHeight backgroundColor: "#7f000000" property url source: "about:blank" signal navigating(string url) + function stop() { + webview.stop(); + } + Component.onCompleted: { enabled = true @@ -26,18 +32,14 @@ VrDialog { webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { console.log("Web Window JS message: " + sourceID + " " + lineNumber + " " + message); }); - webview.loadingChanged.connect(handleWebviewLoading) } function handleWebviewLoading(loadRequest) { - var HIFI_URL_PATTERN = /^hifi:\/\//; if (WebEngineView.LoadStartedStatus == loadRequest.status) { var newUrl = loadRequest.url.toString(); - if (newUrl.match(HIFI_URL_PATTERN)) { - root.navigating(newUrl); - } + root.navigating(newUrl) } } @@ -55,8 +57,10 @@ VrDialog { url: root.source anchors.fill: parent profile: WebEngineProfile { + id: webviewProfile httpUserAgent: "Mozilla/5.0 (HighFidelityInterface)" - } + storageName: "qmlWebEngine" + } } } // item } // dialog diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e22b3913d0..7f27d97416 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4215,7 +4215,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("ScriptDiscoveryService", this->getRunningScriptsWidget()); } -bool Application::canAcceptURL(const QString& urlString) { +bool Application::canAcceptURL(const QString& urlString) const { QUrl url(urlString); if (urlString.startsWith(HIFI_URL_SCHEME)) { return true; diff --git a/interface/src/Application.h b/interface/src/Application.h index a665e925a9..0953aedd8c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -38,6 +38,7 @@ #include #include #include +#include #include "avatar/AvatarUpdate.h" #include "avatar/MyAvatar.h" @@ -88,7 +89,7 @@ class Application; #endif #define qApp (static_cast(QCoreApplication::instance())) -class Application : public QApplication, public AbstractViewStateInterface, public AbstractScriptingServicesInterface { +class Application : public QApplication, public AbstractViewStateInterface, public AbstractScriptingServicesInterface, public AbstractUriHandler { Q_OBJECT // TODO? Get rid of those @@ -219,8 +220,8 @@ public: QString getScriptsLocation(); void setScriptsLocation(const QString& scriptsLocation); - bool canAcceptURL(const QString& url); - bool acceptURL(const QString& url, bool defaultUpload = false); + virtual bool canAcceptURL(const QString& url) const override; + virtual bool acceptURL(const QString& url, bool defaultUpload = false) override; void setMaxOctreePacketsPerSecond(int maxOctreePPS); int getMaxOctreePacketsPerSecond(); diff --git a/libraries/networking/src/AbstractUriHandler.h b/libraries/networking/src/AbstractUriHandler.h new file mode 100644 index 0000000000..3d6ed472ec --- /dev/null +++ b/libraries/networking/src/AbstractUriHandler.h @@ -0,0 +1,19 @@ +// +// Created by Bradley Austin Davis on 2015/12/17 +// Copyright 2013-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 +// + +#pragma once +#ifndef hifi_network_AbstractUriHandler_h +#define hifi_network_AbstractUriHandler_h + +class AbstractUriHandler { +public: + virtual bool canAcceptURL(const QString& url) const = 0; + virtual bool acceptURL(const QString& url, bool defaultUpload = false) = 0; +}; + +#endif diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 636d1a9a1a..652089ebb1 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1867,7 +1867,7 @@ bool Octree::readJSONFromStream(unsigned long streamLength, QDataStream& inputSt QByteArray jsonBuffer; char* rawData = new char[READ_JSON_BUFFER_SIZE]; - while (true) { + while (!inputStream.atEnd()) { int got = inputStream.readRawData(rawData, READ_JSON_BUFFER_SIZE - 1); if (got < 0) { qCritical() << "error while reading from json stream"; diff --git a/libraries/ui/src/QmlWebWindowClass.cpp b/libraries/ui/src/QmlWebWindowClass.cpp index d5cdc1fde9..68a45a5bff 100644 --- a/libraries/ui/src/QmlWebWindowClass.cpp +++ b/libraries/ui/src/QmlWebWindowClass.cpp @@ -10,7 +10,10 @@ #include +#include #include +#include +#include #include #include @@ -22,6 +25,7 @@ #include #include +#include #include #include @@ -88,7 +92,7 @@ QScriptValue QmlWebWindowClass::constructor(QScriptContext* context, QScriptEngi QmlWebWindowClass* retVal { nullptr }; const QString title = context->argument(0).toString(); QString url = context->argument(1).toString(); - if (!url.startsWith("http") && !url.startsWith("file://")) { + if (!url.startsWith("http") && !url.startsWith("file://") && !url.startsWith("about:")) { url = QUrl::fromLocalFile(url).toString(); } const int width = std::max(100, std::min(1280, context->argument(2).toInt32()));; @@ -119,7 +123,23 @@ QmlWebWindowClass::QmlWebWindowClass(QObject* qmlWindow) } void QmlWebWindowClass::handleNavigation(const QString& url) { - DependencyManager::get()->handleLookupString(url); + bool handled = false; + + if (url.contains(HIFI_URL_PATTERN)) { + DependencyManager::get()->handleLookupString(url); + handled = true; + } else { + static auto handler = dynamic_cast(qApp); + if (handler) { + if (handler->canAcceptURL(url)) { + handled = handler->acceptURL(url); + } + } + } + + if (handled) { + QMetaObject::invokeMethod(_qmlWindow, "stop", Qt::AutoConnection); + } } void QmlWebWindowClass::setVisible(bool visible) { @@ -202,6 +222,7 @@ QString QmlWebWindowClass::getURL() const { QMetaObject::invokeMethod(const_cast(this), "getURL", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, result)); return result; } + return _qmlWindow->property(URL_PROPERTY).toString(); } @@ -209,7 +230,23 @@ void QmlWebWindowClass::setURL(const QString& urlString) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "setURL", Qt::QueuedConnection, Q_ARG(QString, urlString)); } - _qmlWindow->setProperty(URL_PROPERTY, urlString); + + static const QString ACCESS_TOKEN_PARAMETER = "access_token"; + static const QString ALLOWED_HOST = "metaverse.highfidelity.com"; + + QUrl url(urlString); + qDebug() << "Url: " << urlString; + qDebug() << "Host: " << url.host(); + if (url.host() == ALLOWED_HOST) { + QUrlQuery query(url); + if (query.allQueryItemValues(ACCESS_TOKEN_PARAMETER).empty()) { + AccountManager& accountManager = AccountManager::getInstance(); + query.addQueryItem(ACCESS_TOKEN_PARAMETER, accountManager.getAccountInfo().getAccessToken().token); + url.setQuery(query.query()); + qDebug() << "New URL " << url; + } + } + _qmlWindow->setProperty(URL_PROPERTY, url.toString()); } From b89e25f8f7f6fe1138c9521c9b309111f164838d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 21 Dec 2015 11:35:57 -0800 Subject: [PATCH 135/195] correct file --- examples/flowArts/arcBall/arcBall.js | 256 ++++++++++++++------------- 1 file changed, 131 insertions(+), 125 deletions(-) diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js index 0906b90b53..e67dffddff 100644 --- a/examples/flowArts/arcBall/arcBall.js +++ b/examples/flowArts/arcBall/arcBall.js @@ -1,139 +1,145 @@ -// arcBallEntityScript.js -// -// Script Type: Entity -// Created by Eric Levin on 12/17/15. -// Copyright 2015 High Fidelity, Inc. // -// This entity script handles the logic for the arcBall rave toy +// arcBall.js +// examples/arcBall +// +// Created by Eric Levin on 12/17/15. +// Copyright 2014 High Fidelity, Inc. +// +// This script creats a particle light ball which makes particle trails as you move it. +// +// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -(function() { - Script.include("../../libraries/utils.js"); - var _this; - var ArcBall = function() { - _this = this; - this.colorPalette = [{ +Script.include("../../libraries/utils.js"); + + +var scriptURL = Script.resolvePath("arcBallEntityScript.js"); +ArcBall = function(spawnPosition) { + + var colorPalette = [{ + red: 25, + green: 20, + blue: 162 + }]; + + + var containerBall = Entities.addEntity({ + type: "Sphere", + name: "Arc Ball", + script: scriptURL, + position: Vec3.sum(spawnPosition, { + x: 0, + y: .7, + z: 0 + }), + dimensions: { + x: .05, + y: .05, + z: .05 + }, + color: { + red: 100, + green: 10, + blue: 150 + }, + ignoreForCollisions: true, + damping: 0.8, + collisionsWillMove: true, + userData: JSON.stringify({ + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 0.0, + z: -0.5 + }, + }, + // invertSolidWhileHeld: true + } + }) + }); + + + var light = Entities.addEntity({ + type: 'Light', + name: "ballLight", + parentID: containerBall, + dimensions: { + x: 30, + y: 30, + z: 30 + }, + color: colorPalette[randInt(0, colorPalette.length)], + intensity: 5 + }); + + + var arcBall = Entities.addEntity({ + type: "ParticleEffect", + parentID: containerBall, + isEmitting: true, + name: "Arc Ball Particle Effect", + colorStart: { + red: 200, + green: 20, + blue: 40 + }, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: { red: 25, green: 20, - blue: 162 - }, { - red: 200, - green: 10, - blue: 10 - }]; - }; - - ArcBall.prototype = { - isGrabbed: false, - startNearGrab: function() { - //Search for nearby balls and create an arc to it if one is found - var position = Entities.getEntityProperties(this.entityID, "position").position - var entities = Entities.findEntities(position, 10); - entities.forEach(function(entity) { - var props = Entities.getEntityProperties(entity, ["position", "name"]); - if (props.name === "Arc Ball" && JSON.stringify(_this.entityID) !== JSON.stringify(entity)) { - _this.target = entity; - _this.createBeam(position, props.position); - } - }); - + blue: 255 }, - - createBeam: function(startPosition, endPosition) { - // Creates particle arc from start position to end position - var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; - var sourceToTargetVec = Vec3.subtract(endPosition, startPosition); - var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); - emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation); - - - var color = this.colorPalette[randInt(0, this.colorPalette.length)]; - var props = { - type: "ParticleEffect", - name: "Particle Arc", - parentID: this.entityID, - parentJointIndex: -1, - // position: startPosition, - isEmitting: true, - colorStart: color, - color: { - red: 200, - green: 200, - blue: 255 - }, - colorFinish: color, - maxParticles: 100000, - lifespan: 1, - emitRate: 1000, - emitOrientation: emitOrientation, - emitSpeed: .2, - speedSpread: 0.1, - emitDimensions: { - x: .1, - y: .1, - z: .1 - }, - polarStart: 0, - polarFinish: .0, - azimuthStart: .1, - azimuthFinish: .01, - emitAcceleration: { - x: 0, - y: 0, - z: 0 - }, - accelerationSpread: { - x: .00, - y: .00, - z: .00 - }, - radiusStart: 0.01, - radiusFinish: 0.005, - radiusSpread: .005, - alpha: 0.5, - alphaSpread: .1, - alphaStart: 0.5, - alphaFinish: 0.0, - textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", - emitterShouldTrail: true - } - this.particleArc = Entities.addEntity(props); + maxParticles: 100000, + lifespan: 2, + emitRate: 400, + emitSpeed: .1, + lifetime: -1, + speedSpread: 0.0, + emitDimensions: { + x: 0, + y: 0, + z: 0 }, - - updateBeam: function(startPosition) { - var targetPosition = Entities.getEntityProperties(this.target, "position").position; - print("TARGET position " + JSON.stringify(this.target)); - var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; - var sourceToTargetVec = Vec3.subtract(targetPosition, startPosition); - var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); - // emitOrientation = Quat.multiply(emitOrientation,Quat.inverse(rotation)); - Entities.editEntity(this.particleArc, { - emitOrientation: emitOrientation - }); + polarStart: 0, + polarFinish: Math.PI, + azimuthStart: -Math.PI, + azimuthFinish: Math.PI, + emitAcceleration: { + x: 0, + y: 0, + z: 0 }, - - continueNearGrab: function() { - var startPosition = Entities.getEntityProperties(this.entityID, "position").position; - this.updateBeam(startPosition); + accelerationSpread: { + x: .00, + y: .00, + z: .00 }, + particleRadius: 0.02, + radiusSpread: 0, + radiusStart: 0.03, + radiusFinish: 0.0003, + alpha: 0, + alphaSpread: .5, + alphaStart: 0, + alphaFinish: 0.5, + textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + emitterShouldTrail: true + }) - releaseGrab: function() { - Entities.editEntity(this.particleArc, { - isEmitting: false - }); - }, - unload: function() { - if (this.particleArc) { - Entities.deleteEntity(this.particleArc); - } - }, - preload: function(entityID) { - this.entityID = entityID; - }, - }; - return new ArcBall(); -}); \ No newline at end of file + function cleanup() { + Entities.deleteEntity(arcBall); + Entities.deleteEntity(containerBall); + Entities.deleteEntity(light); + } + + this.cleanup = cleanup; +} \ No newline at end of file From ae124ebede205b3caa81905f676af44aae90cc6f Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 21 Dec 2015 12:00:30 -0800 Subject: [PATCH 136/195] Tuning the proedural shader support to work with the current default: gamma corrected emissive --- libraries/procedural/src/procedural/ProceduralSkybox.slf | 3 ++- libraries/render-utils/src/RenderDeferredTask.cpp | 1 - libraries/render-utils/src/ToneMappingEffect.cpp | 2 -- libraries/render-utils/src/simple.slf | 2 ++ 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.slf b/libraries/procedural/src/procedural/ProceduralSkybox.slf index 8705278bee..7ad6f6b5a1 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.slf +++ b/libraries/procedural/src/procedural/ProceduralSkybox.slf @@ -35,6 +35,8 @@ void main(void) { #ifdef PROCEDURAL vec3 color = getSkyboxColor(); + // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline + color = pow(color, vec3(2.2)); _fragColor = vec4(color, 0.0); #else @@ -42,7 +44,6 @@ void main(void) { vec3 coord = normalize(_normal); vec3 texel = texture(cubeMap, coord).rgb; vec3 color = texel * _skybox._color.rgb; - // vec3 pixel = pow(color, vec3(1.0/2.2)); // manual Gamma correction _fragColor = vec4(color, 0.0); #endif diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ddfb6bc7a3..7fced1bdf3 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -54,7 +54,6 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { context->getItemsConfig().opaque.numFeed = count; - auto& opaque = context->getItemsConfig().opaque; }) ))); _jobs.push_back(Job(new CullItemsOpaque::JobModel("CullOpaque", _jobs.back().getOutput()))); diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index a00a66fe69..2583719424 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -141,7 +141,5 @@ void ToneMappingEffect::render(RenderArgs* args) { batch.setUniformBuffer(3, _parametersBuffer); batch.setResourceTexture(0, lightingBuffer); batch.draw(gpu::TRIANGLE_STRIP, 4); - - args->_context->render(batch); }); } \ No newline at end of file diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 576acf9340..8c93ee564e 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -40,6 +40,8 @@ void main(void) { #ifdef PROCEDURAL_V1 specular = getProceduralColor().rgb; + // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline + specular = pow(specular, vec3(2.2)); emissiveAmount = 1.0; #else emissiveAmount = getProceduralColors(diffuse, specular, shininess); From 4f54b85c9208fb2d64c5cf76dcbbd6e1057d39ed Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 21 Dec 2015 12:05:19 -0800 Subject: [PATCH 137/195] Remove warnings --- libraries/render-utils/src/RenderDeferredTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 7fced1bdf3..4dcda425a1 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -104,12 +104,12 @@ RenderDeferredTask::RenderDeferredTask() : Task() { // Lighting Buffer ready for tone mapping _jobs.push_back(Job(new ToneMappingDeferred::JobModel("ToneMapping"))); - _toneMappingJobIndex = _jobs.size() - 1; + _toneMappingJobIndex = (int)_jobs.size() - 1; // Debugging Deferred buffer job _jobs.push_back(Job(new DebugDeferredBuffer::JobModel("DebugDeferredBuffer"))); _jobs.back().setEnabled(false); - _drawDebugDeferredBufferIndex = _jobs.size() - 1; + _drawDebugDeferredBufferIndex = (int)_jobs.size() - 1; // Status icon rendering job { @@ -118,7 +118,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath); _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques, DrawStatus(statusIconMap)))); _jobs.back().setEnabled(false); - _drawStatusJobIndex = _jobs.size() - 1; + _drawStatusJobIndex = (int)_jobs.size() - 1; } _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); From 4b4fe96b64808321652b4ca0e2a8d9ea056d5331 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 21 Dec 2015 12:47:31 -0800 Subject: [PATCH 138/195] tweaks --- examples/flowArts/arcBall/arcBallEntityScript.js | 14 +++++++------- examples/flowArts/lightSaber/lightSaber.js | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index 0906b90b53..84208bf559 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -65,19 +65,19 @@ }, colorFinish: color, maxParticles: 100000, - lifespan: 1, + lifespan: 2, emitRate: 1000, emitOrientation: emitOrientation, - emitSpeed: .2, - speedSpread: 0.1, + emitSpeed: .1, + speedSpread: 0.02, emitDimensions: { - x: .1, - y: .1, - z: .1 + x: .01, + y: .01, + z: .01 }, polarStart: 0, polarFinish: .0, - azimuthStart: .1, + azimuthStart: .02, azimuthFinish: .01, emitAcceleration: { x: 0, diff --git a/examples/flowArts/lightSaber/lightSaber.js b/examples/flowArts/lightSaber/lightSaber.js index 50984110bc..a42f81d196 100644 --- a/examples/flowArts/lightSaber/lightSaber.js +++ b/examples/flowArts/lightSaber/lightSaber.js @@ -23,6 +23,7 @@ LightSaber = function(spawnPosition) { modelURL: modelURL, position: spawnPosition, shapeType: 'box', + collisionsWillMove: true, script: scriptURL, dimensions: { x: 0.06, From 4110630d1f074fdf4c710f804d10d14539424a00 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 21 Dec 2015 13:15:37 -0800 Subject: [PATCH 139/195] fixed ravestick fargrab --- examples/flowArts/raveStick/raveStick.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/flowArts/raveStick/raveStick.js b/examples/flowArts/raveStick/raveStick.js index 3e4cf16136..bcbe44168c 100644 --- a/examples/flowArts/raveStick/raveStick.js +++ b/examples/flowArts/raveStick/raveStick.js @@ -30,7 +30,8 @@ RaveStick = function(spawnPosition) { modelURL: modelURL, position: spawnPosition, shapeType: 'box', - script: scriptURL, + collisionsWillMove: true, + // script: scriptURL, dimensions: { x: 0.06, y: 0.06, From cabc47e7a9914e9e2985e932de6f74310d3bb71f Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 21 Dec 2015 13:30:52 -0800 Subject: [PATCH 140/195] lightsaber immediately turns off on release --- .../flowArts/arcBall/arcBallEntityScript.js | 128 ++++++++++-------- .../lightSaber/lightSaberEntityScript.js | 4 +- 2 files changed, 76 insertions(+), 56 deletions(-) diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index 84208bf559..1952209c95 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -27,7 +27,16 @@ ArcBall.prototype = { isGrabbed: false, - startNearGrab: function() { + startDistanceGrab: function() { + this.searchForNearbyArcBalls(); + + }, + + startFarGrab: function() { + this.searchForNearbyArcBalls(); + }, + + searchForNearbyArcBalls: function() { //Search for nearby balls and create an arc to it if one is found var position = Entities.getEntityProperties(this.entityID, "position").position var entities = Entities.findEntities(position, 10); @@ -36,12 +45,13 @@ if (props.name === "Arc Ball" && JSON.stringify(_this.entityID) !== JSON.stringify(entity)) { _this.target = entity; _this.createBeam(position, props.position); + } }); - }, createBeam: function(startPosition, endPosition) { + // Creates particle arc from start position to end position var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; var sourceToTargetVec = Vec3.subtract(endPosition, startPosition); @@ -50,61 +60,65 @@ var color = this.colorPalette[randInt(0, this.colorPalette.length)]; - var props = { - type: "ParticleEffect", - name: "Particle Arc", - parentID: this.entityID, - parentJointIndex: -1, - // position: startPosition, - isEmitting: true, - colorStart: color, - color: { - red: 200, - green: 200, - blue: 255 - }, - colorFinish: color, - maxParticles: 100000, - lifespan: 2, - emitRate: 1000, - emitOrientation: emitOrientation, - emitSpeed: .1, - speedSpread: 0.02, - emitDimensions: { - x: .01, - y: .01, - z: .01 - }, - polarStart: 0, - polarFinish: .0, - azimuthStart: .02, - azimuthFinish: .01, - emitAcceleration: { - x: 0, - y: 0, - z: 0 - }, - accelerationSpread: { - x: .00, - y: .00, - z: .00 - }, - radiusStart: 0.01, - radiusFinish: 0.005, - radiusSpread: .005, - alpha: 0.5, - alphaSpread: .1, - alphaStart: 0.5, - alphaFinish: 0.0, - textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", - emitterShouldTrail: true - } + var props = { + type: "ParticleEffect", + name: "Particle Arc", + parentID: this.entityID, + parentJointIndex: -1, + // position: startPosition, + isEmitting: true, + colorStart: color, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 2, + emitRate: 1000, + emitOrientation: emitOrientation, + emitSpeed: .1, + speedSpread: 0.02, + emitDimensions: { + x: .01, + y: .01, + z: .01 + }, + polarStart: 0, + polarFinish: .0, + azimuthStart: .02, + azimuthFinish: .01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + radiusStart: 0.01, + radiusFinish: 0.005, + radiusSpread: .005, + alpha: 0.5, + alphaSpread: .1, + alphaStart: 0.5, + alphaFinish: 0.0, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", + emitterShouldTrail: true + } this.particleArc = Entities.addEntity(props); }, - updateBeam: function(startPosition) { + updateBeam: function() { + if(!this.target) { + return; + } + var startPosition = Entities.getEntityProperties(this.entityID, "position").position; + var targetPosition = Entities.getEntityProperties(this.target, "position").position; - print("TARGET position " + JSON.stringify(this.target)); var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; var sourceToTargetVec = Vec3.subtract(targetPosition, startPosition); var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); @@ -115,14 +129,18 @@ }, continueNearGrab: function() { - var startPosition = Entities.getEntityProperties(this.entityID, "position").position; - this.updateBeam(startPosition); + this.updateBeam(); + }, + + continueDistanceGrab: function() { + this.updateBeam(); }, releaseGrab: function() { Entities.editEntity(this.particleArc, { isEmitting: false }); + this.target = null; }, unload: function() { diff --git a/examples/flowArts/lightSaber/lightSaberEntityScript.js b/examples/flowArts/lightSaber/lightSaberEntityScript.js index 794e241924..cbbcd8a0bf 100644 --- a/examples/flowArts/lightSaber/lightSaberEntityScript.js +++ b/examples/flowArts/lightSaber/lightSaberEntityScript.js @@ -31,12 +31,14 @@ startNearGrab: function() { Entities.editEntity(this.beam, { - isEmitting: true + isEmitting: true, + visible: true }); }, releaseGrab: function() { Entities.editEntity(this.beam, { + visible: false, isEmitting: false }); }, From 876d8ab6b25a427ae16acbe459ea3e4f01b05348 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 21 Dec 2015 13:59:00 -0800 Subject: [PATCH 141/195] far grabbing arc balls --- examples/flowArts/arcBall/arcBall.js | 12 ++++++------ examples/flowArts/arcBall/arcBallEntityScript.js | 16 ++++++---------- .../lightSaber/lightSaberEntityScript.js | 1 - 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js index e67dffddff..5a6b1b47f3 100644 --- a/examples/flowArts/arcBall/arcBall.js +++ b/examples/flowArts/arcBall/arcBall.js @@ -15,7 +15,7 @@ Script.include("../../libraries/utils.js"); -var scriptURL = Script.resolvePath("arcBallEntityScript.js"); +var scriptURL = Script.resolvePath("arcBallEntityScript.js?v1" + Math.random()); ArcBall = function(spawnPosition) { var colorPalette = [{ @@ -50,11 +50,11 @@ ArcBall = function(spawnPosition) { userData: JSON.stringify({ grabbableKey: { spatialKey: { - relativePosition: { - x: 0, - y: 0.0, - z: -0.5 - }, + // relativePosition: { + // x: 0, + // y: -0.5, + // z: 0.0 + // }, }, // invertSolidWhileHeld: true } diff --git a/examples/flowArts/arcBall/arcBallEntityScript.js b/examples/flowArts/arcBall/arcBallEntityScript.js index 1952209c95..102ceca40c 100644 --- a/examples/flowArts/arcBall/arcBallEntityScript.js +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -27,12 +27,11 @@ ArcBall.prototype = { isGrabbed: false, - startDistanceGrab: function() { + startDistantGrab: function() { this.searchForNearbyArcBalls(); - }, - startFarGrab: function() { + startNearGrab: function() { this.searchForNearbyArcBalls(); }, @@ -58,7 +57,6 @@ var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation); - var color = this.colorPalette[randInt(0, this.colorPalette.length)]; var props = { type: "ParticleEffect", @@ -75,10 +73,10 @@ }, colorFinish: color, maxParticles: 100000, - lifespan: 2, + lifespan: 1, emitRate: 1000, emitOrientation: emitOrientation, - emitSpeed: .1, + emitSpeed: 1, speedSpread: 0.02, emitDimensions: { x: .01, @@ -105,7 +103,7 @@ alpha: 0.5, alphaSpread: .1, alphaStart: 0.5, - alphaFinish: 0.0, + alphaFinish: 0.5, textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", emitterShouldTrail: true } @@ -117,12 +115,10 @@ return; } var startPosition = Entities.getEntityProperties(this.entityID, "position").position; - var targetPosition = Entities.getEntityProperties(this.target, "position").position; var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation; var sourceToTargetVec = Vec3.subtract(targetPosition, startPosition); var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec); - // emitOrientation = Quat.multiply(emitOrientation,Quat.inverse(rotation)); Entities.editEntity(this.particleArc, { emitOrientation: emitOrientation }); @@ -132,7 +128,7 @@ this.updateBeam(); }, - continueDistanceGrab: function() { + continueDistantGrab: function() { this.updateBeam(); }, diff --git a/examples/flowArts/lightSaber/lightSaberEntityScript.js b/examples/flowArts/lightSaber/lightSaberEntityScript.js index cbbcd8a0bf..fd55916cc6 100644 --- a/examples/flowArts/lightSaber/lightSaberEntityScript.js +++ b/examples/flowArts/lightSaber/lightSaberEntityScript.js @@ -54,7 +54,6 @@ createBeam: function() { - this.props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); var forwardVec = Quat.getFront(Quat.multiply(this.props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); // forwardVec = Vec3.normalize(forwardVec); From 5a86f0c23fbe4f1e3c64cfe3bec987f76ea650dd Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 21 Dec 2015 12:12:13 -0800 Subject: [PATCH 142/195] Nest JS props in SceneScriptingInterface --- .../src/EntityTreeRenderer.cpp | 61 ++--- libraries/model/src/model/Stage.cpp | 15 ++ libraries/model/src/model/Stage.h | 3 + .../src/SceneScriptingInterface.cpp | 211 ++++++++++-------- .../src/SceneScriptingInterface.h | 155 +++++++++---- 5 files changed, 279 insertions(+), 166 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index e3618d0e2a..996a8f3e1d 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -256,33 +256,38 @@ void EntityTreeRenderer::forceRecheckEntities() { void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr zone) { QSharedPointer scene = DependencyManager::get(); + auto sceneStage = scene->getStage(); + auto sceneKeyLight = sceneStage->getKeyLight(); + auto sceneLocation = sceneStage->getLocation(); + auto sceneTime = sceneStage->getTime(); + if (zone) { if (!_hasPreviousZone) { - _previousKeyLightColor = scene->getKeyLightColor(); - _previousKeyLightIntensity = scene->getKeyLightIntensity(); - _previousKeyLightAmbientIntensity = scene->getKeyLightAmbientIntensity(); - _previousKeyLightDirection = scene->getKeyLightDirection(); - _previousStageSunModelEnabled = scene->isStageSunModelEnabled(); - _previousStageLongitude = scene->getStageLocationLongitude(); - _previousStageLatitude = scene->getStageLocationLatitude(); - _previousStageAltitude = scene->getStageLocationAltitude(); - _previousStageHour = scene->getStageDayTime(); - _previousStageDay = scene->getStageYearTime(); + _previousKeyLightColor = sceneKeyLight->getColor(); + _previousKeyLightIntensity = sceneKeyLight->getIntensity(); + _previousKeyLightAmbientIntensity = sceneKeyLight->getAmbientIntensity(); + _previousKeyLightDirection = sceneKeyLight->getDirection(); + _previousStageSunModelEnabled = sceneStage->isSunModelEnabled(); + _previousStageLongitude = sceneLocation->getLongitude(); + _previousStageLatitude = sceneLocation->getLatitude(); + _previousStageAltitude = sceneLocation->getAltitude(); + _previousStageHour = sceneTime->getHour(); + _previousStageDay = sceneTime->getDay(); _hasPreviousZone = true; } - scene->setKeyLightColor(ColorUtils::toVec3(zone->getKeyLightProperties().getColor())); - scene->setKeyLightIntensity(zone->getKeyLightProperties().getIntensity()); - scene->setKeyLightAmbientIntensity(zone->getKeyLightProperties().getAmbientIntensity()); - scene->setKeyLightDirection(zone->getKeyLightProperties().getDirection()); - scene->setStageSunModelEnable(zone->getStageProperties().getSunModelEnabled()); - scene->setStageLocation(zone->getStageProperties().getLongitude(), zone->getStageProperties().getLatitude(), + sceneKeyLight->setColor(ColorUtils::toVec3(zone->getKeyLightProperties().getColor())); + sceneKeyLight->setIntensity(zone->getKeyLightProperties().getIntensity()); + sceneKeyLight->setAmbientIntensity(zone->getKeyLightProperties().getAmbientIntensity()); + sceneKeyLight->setDirection(zone->getKeyLightProperties().getDirection()); + sceneStage->setSunModelEnable(zone->getStageProperties().getSunModelEnabled()); + sceneStage->setLocation(zone->getStageProperties().getLongitude(), zone->getStageProperties().getLatitude(), zone->getStageProperties().getAltitude()); - scene->setStageDayTime(zone->getStageProperties().calculateHour()); - scene->setStageYearTime(zone->getStageProperties().calculateDay()); + sceneTime->setHour(zone->getStageProperties().calculateHour()); + sceneTime->setDay(zone->getStageProperties().calculateDay()); if (zone->getBackgroundMode() == BACKGROUND_MODE_ATMOSPHERE) { EnvironmentData data = zone->getEnvironmentData(); - glm::vec3 keyLightDirection = scene->getKeyLightDirection(); + glm::vec3 keyLightDirection = sceneKeyLight->getDirection(); glm::vec3 inverseKeyLightDirection = keyLightDirection * -1.0f; // NOTE: is this right? It seems like the "sun" should be based on the center of the @@ -293,7 +298,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetKeyLightIntensity() * KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO; + float sunBrightness = sceneKeyLight->getIntensity() * KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO; data.setSunBrightness(sunBrightness); _viewState->overrideEnvironmentData(data); @@ -339,15 +344,15 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrsetKeyLightColor(_previousKeyLightColor); - scene->setKeyLightIntensity(_previousKeyLightIntensity); - scene->setKeyLightAmbientIntensity(_previousKeyLightAmbientIntensity); - scene->setKeyLightDirection(_previousKeyLightDirection); - scene->setStageSunModelEnable(_previousStageSunModelEnabled); - scene->setStageLocation(_previousStageLongitude, _previousStageLatitude, + sceneKeyLight->setColor(_previousKeyLightColor); + sceneKeyLight->setIntensity(_previousKeyLightIntensity); + sceneKeyLight->setAmbientIntensity(_previousKeyLightAmbientIntensity); + sceneKeyLight->setDirection(_previousKeyLightDirection); + sceneStage->setSunModelEnable(_previousStageSunModelEnabled); + sceneStage->setLocation(_previousStageLongitude, _previousStageLatitude, _previousStageAltitude); - scene->setStageDayTime(_previousStageHour); - scene->setStageYearTime(_previousStageDay); + sceneTime->setHour(_previousStageHour); + sceneTime->setDay(_previousStageDay); _hasPreviousZone = false; } _viewState->endOverrideEnvironmentData(); diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 67f0262b61..47d3ba3063 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -225,6 +225,21 @@ void SunSkyStage::setOriginOrientation(const Quat& orientation) { invalidate(); } +void SunSkyStage::setOriginLongitude(float longitude) { + _earthSunModel.setLongitude(longitude); + invalidate(); +} + +void SunSkyStage::setOriginLatitude(float latitude) { + _earthSunModel.setLatitude(latitude); + invalidate(); +} + +void SunSkyStage::setOriginSurfaceAltitude(float altitude) { + _earthSunModel.setAltitude(altitude); + invalidate(); +} + void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { _earthSunModel.setLongitude(longitude); _earthSunModel.setLatitude(latitude); diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index 978c308ac6..bf586b6b55 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -184,6 +184,9 @@ public: const Quat& getOriginOrientation() const { return _earthSunModel.getSurfaceOrientation(); } // Location used to define the sun & sky is a longitude and latitude [rad] and a earth surface altitude [km] + void setOriginLatitude(float latitude); + void setOriginLongitude(float longitude); + void setOriginSurfaceAltitude(float surfaceAltitude); void setOriginLocation(float longitude, float latitude, float surfaceAltitude); float getOriginLatitude() const { return _earthSunModel.getLatitude(); } float getOriginLongitude() const { return _earthSunModel.getLongitude(); } diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp index 39bceba9d9..e3d16912f4 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.cpp +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -13,7 +13,118 @@ #include -SceneScriptingInterface::SceneScriptingInterface() { +float SceneScripting::Location::getLongitude() const { + return _skyStage->getOriginLongitude(); +} + +float SceneScripting::Location::getLatitude() const { + return _skyStage->getOriginLatitude(); +} + +float SceneScripting::Location::getAltitude() const { + return _skyStage->getOriginSurfaceAltitude(); +} + +void SceneScripting::Location::setLongitude(float longitude) { + _skyStage->setOriginLongitude(longitude); +} + +void SceneScripting::Location::setLatitude(float latitude) { + _skyStage->setOriginLatitude(latitude); +} + +void SceneScripting::Location::setAltitude(float altitude) { + _skyStage->setOriginSurfaceAltitude(altitude); +} + +void SceneScripting::Time::setHour(float hour) { + _skyStage->setDayTime(hour); +} + +float SceneScripting::Time::getHour() const { + return _skyStage->getDayTime(); +} + +void SceneScripting::Time::setDay(int day) { + _skyStage->setYearTime(day); +} + +int SceneScripting::Time::getDay() const { + return _skyStage->getYearTime(); +} + +glm::vec3 SceneScripting::KeyLight::getColor() const { + return _skyStage->getSunColor(); +} + +void SceneScripting::KeyLight::setColor(const glm::vec3& color) { + _skyStage->setSunColor(color); +} + +float SceneScripting::KeyLight::getIntensity() const { + return _skyStage->getSunIntensity(); +} + +void SceneScripting::KeyLight::setIntensity(float intensity) { + _skyStage->setSunIntensity(intensity); +} + +float SceneScripting::KeyLight::getAmbientIntensity() const { + return _skyStage->getSunAmbientIntensity(); +} + +void SceneScripting::KeyLight::setAmbientIntensity(float intensity) { + _skyStage->setSunAmbientIntensity(intensity); +} + +glm::vec3 SceneScripting::KeyLight::getDirection() const { + return _skyStage->getSunDirection(); +} + +void SceneScripting::KeyLight::setDirection(const glm::vec3& direction) { + _skyStage->setSunDirection(direction); +} + +void SceneScripting::Stage::setOrientation(const glm::quat& orientation) const { + _skyStage->setOriginOrientation(orientation); +} + +void SceneScripting::Stage::setLocation(float longitude, float latitude, float altitude) { + _skyStage->setOriginLocation(longitude, latitude, altitude); +} + +void SceneScripting::Stage::setSunModelEnable(bool isEnabled) { + _skyStage->setSunModelEnable(isEnabled); +} + +bool SceneScripting::Stage::isSunModelEnabled() const { + return _skyStage->isSunModelEnabled(); +} + +void SceneScripting::Stage::setBackgroundMode(const QString& mode) { + if (mode == QString("inherit")) { + _skyStage->setBackgroundMode(model::SunSkyStage::NO_BACKGROUND); + } else if (mode == QString("atmosphere")) { + _skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME); + } else if (mode == QString("skybox")) { + _skyStage->setBackgroundMode(model::SunSkyStage::SKY_BOX); + } +} + +QString SceneScripting::Stage::getBackgroundMode() const { + switch (_skyStage->getBackgroundMode()) { + case model::SunSkyStage::NO_BACKGROUND: + return QString("inherit"); + case model::SunSkyStage::SKY_DOME: + return QString("atmosphere"); + case model::SunSkyStage::SKY_BOX: + return QString("skybox"); + default: + return QString("inherit"); + }; +} + +SceneScriptingInterface::SceneScriptingInterface() : _stage{ std::make_unique(_skyStage) } { // Let's make sure the sunSkyStage is using a proceduralSkybox _skyStage->setSkybox(model::SkyboxPointer(new ProceduralSkybox())); } @@ -32,102 +143,6 @@ void SceneScriptingInterface::setShouldRenderEntities(bool shouldRenderEntities) } } -void SceneScriptingInterface::setStageOrientation(const glm::quat& orientation) { - _skyStage->setOriginOrientation(orientation); -} -void SceneScriptingInterface::setStageLocation(float longitude, float latitude, float altitude) { - _skyStage->setOriginLocation(longitude, latitude, altitude); -} - -float SceneScriptingInterface::getStageLocationLongitude() const { - return _skyStage->getOriginLongitude(); -} -float SceneScriptingInterface::getStageLocationLatitude() const { - return _skyStage->getOriginLatitude(); -} -float SceneScriptingInterface::getStageLocationAltitude() const { - return _skyStage->getOriginSurfaceAltitude(); -} - -void SceneScriptingInterface::setStageDayTime(float hour) { - _skyStage->setDayTime(hour); -} - -float SceneScriptingInterface::getStageDayTime() const { - return _skyStage->getDayTime(); -} - -void SceneScriptingInterface::setStageYearTime(int day) { - _skyStage->setYearTime(day); -} - -int SceneScriptingInterface::getStageYearTime() const { - return _skyStage->getYearTime(); -} - -void SceneScriptingInterface::setKeyLightColor(const glm::vec3& color) { - _skyStage->setSunColor(color); -} - -glm::vec3 SceneScriptingInterface::getKeyLightColor() const { - return _skyStage->getSunColor(); -} - -void SceneScriptingInterface::setKeyLightIntensity(float intensity) { - _skyStage->setSunIntensity(intensity); -} - -float SceneScriptingInterface::getKeyLightIntensity() const { - return _skyStage->getSunIntensity(); -} - -void SceneScriptingInterface::setKeyLightAmbientIntensity(float intensity) { - _skyStage->setSunAmbientIntensity(intensity); -} - -float SceneScriptingInterface::getKeyLightAmbientIntensity() const { - return _skyStage->getSunAmbientIntensity(); -} - -void SceneScriptingInterface::setKeyLightDirection(const glm::vec3& direction) { - _skyStage->setSunDirection(direction); -} - -glm::vec3 SceneScriptingInterface::getKeyLightDirection() const { - return _skyStage->getSunDirection(); -} - -void SceneScriptingInterface::setStageSunModelEnable(bool isEnabled) { - _skyStage->setSunModelEnable(isEnabled); -} - -bool SceneScriptingInterface::isStageSunModelEnabled() const { - return _skyStage->isSunModelEnabled(); -} - -void SceneScriptingInterface::setBackgroundMode(const QString& mode) { - if (mode == QString("inherit")) { - _skyStage->setBackgroundMode(model::SunSkyStage::NO_BACKGROUND); - } else if (mode == QString("atmosphere")) { - _skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME); - } else if (mode == QString("skybox")) { - _skyStage->setBackgroundMode(model::SunSkyStage::SKY_BOX); - } -} - -QString SceneScriptingInterface::getBackgroundMode() const { - switch (_skyStage->getBackgroundMode()) { - case model::SunSkyStage::NO_BACKGROUND: - return QString("inherit"); - case model::SunSkyStage::SKY_DOME: - return QString("atmosphere"); - case model::SunSkyStage::SKY_BOX: - return QString("skybox"); - default: - return QString("inherit"); - }; -} - model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const { return _skyStage; -} +} \ No newline at end of file diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index abc4ee68a9..da107b3126 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -17,6 +17,112 @@ #include "model/Stage.h" +// TODO: if QT moc ever supports nested classes, subclass these to the interface instead of namespacing +namespace SceneScripting { + class Location : public QObject { + Q_OBJECT + + public: + Location(model::SunSkyStagePointer skyStage) : _skyStage{ skyStage } {} + + Q_PROPERTY(float longitude READ getLongitude WRITE setLongitude) + Q_PROPERTY(float latitude READ getLatitude WRITE setLatitude) + Q_PROPERTY(float altitude READ getAltitude WRITE setAltitude) + + float getLongitude() const; + float getLatitude() const; + float getAltitude() const; + void setLongitude(float longitude); + void setLatitude(float latitude); + void setAltitude(float altitude); + + protected: + model::SunSkyStagePointer _skyStage; + }; + using LocationPointer = std::unique_ptr; + + class Time : public QObject { + Q_OBJECT + + public: + Time(model::SunSkyStagePointer skyStage) : _skyStage{ skyStage } {} + + Q_PROPERTY(float hour READ getHour WRITE setHour) + Q_PROPERTY(int day READ getDay WRITE setDay) + + float getHour() const; + void setHour(float hour); + int getDay() const; + void setDay(int day); + + protected: + model::SunSkyStagePointer _skyStage; + }; + using TimePointer = std::unique_ptr