diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 8f291b509a..04b52ebb50 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -275,6 +275,7 @@ function MyController(hand) { this.rawTriggerValue = 0; this.rawBumperValue = 0; +<<<<<<< HEAD //for visualizations this.overlayLine = null; this.particleBeam = null; @@ -282,6 +283,9 @@ function MyController(hand) { //for lights this.spotlight = null; this.pointlight = null; +======= + this.overlayLine = null; +>>>>>>> master this.ignoreIK = false; this.offsetPosition = Vec3.ZERO; @@ -1154,20 +1158,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/controllers/reticleHandRotationTest.js b/examples/controllers/reticleHandRotationTest.js index 781dbf66ab..ece9283deb 100644 --- a/examples/controllers/reticleHandRotationTest.js +++ b/examples/controllers/reticleHandRotationTest.js @@ -9,8 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var whichHand = Controller.Standard.RightHand; -var whichTrigger = Controller.Standard.RT; var DEBUGGING = false; Math.clamp=function(a,b,c) { @@ -34,14 +32,14 @@ function moveReticleAbsolute(x, y) { // some debugging to see if position is jumping around on us... var distanceSinceLastMove = length(lastPos, globalPos); if (distanceSinceLastMove > EXPECTED_CHANGE) { - print("------------------ distanceSinceLastMove:" + distanceSinceLastMove + "----------------------------"); + debugPrint("------------------ distanceSinceLastMove:" + distanceSinceLastMove + "----------------------------"); } if (Math.abs(dX) > EXPECTED_CHANGE) { - print("surpressing unexpectedly large change dX:" + dX + "----------------------------"); + debugPrint("surpressing unexpectedly large change dX:" + dX + "----------------------------"); } if (Math.abs(dY) > EXPECTED_CHANGE) { - print("surpressing unexpectedly large change dY:" + dY + "----------------------------"); + debugPrint("surpressing unexpectedly large change dY:" + dY + "----------------------------"); } globalPos.x = x; @@ -53,14 +51,165 @@ function moveReticleAbsolute(x, y) { 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) { +mapping.from(Controller.Standard.LT).peek().constrainToInteger().to(Controller.Actions.ReticleClick); +mapping.from(Controller.Standard.RT).peek().constrainToInteger().to(Controller.Actions.ReticleClick); +mapping.enable(); + + +var lastRotatedLeft = Vec3.UNIT_NEG_Y; +var lastRotatedRight = Vec3.UNIT_NEG_Y; + +function debugPrint(message) { + if (DEBUGGING) { + print(message); + } +} + +var MAX_WAKE_UP_DISTANCE = 0.005; +var MIN_WAKE_UP_DISTANCE = 0.001; +var INITIAL_WAKE_UP_DISTANCE = MIN_WAKE_UP_DISTANCE; +var INCREMENTAL_WAKE_UP_DISTANCE = 0.001; + +var MAX_SLEEP_DISTANCE = 0.0004; +var MIN_SLEEP_DISTANCE = 0.00001; //0.00002; +var INITIAL_SLEEP_DISTANCE = MIN_SLEEP_DISTANCE; +var INCREMENTAL_SLEEP_DISTANCE = 0.000002; // 0.00002; + +var leftAsleep = true; +var rightAsleep = true; + +var leftWakeUpDistance = INITIAL_WAKE_UP_DISTANCE; +var rightWakeUpDistance = INITIAL_WAKE_UP_DISTANCE; + +var leftSleepDistance = INITIAL_SLEEP_DISTANCE; +var rightSleepDistance = INITIAL_SLEEP_DISTANCE; + +Script.update.connect(function(deltaTime) { + + var poseRight = Controller.getPoseValue(Controller.Standard.RightHand); + var poseLeft = Controller.getPoseValue(Controller.Standard.LeftHand); // NOTE: hack for now var screenSizeX = 1920; var screenSizeY = 1080; - var rotated = Vec3.multiplyQbyV(pose.rotation, Vec3.UNIT_NEG_Y); // + var rotatedRight = Vec3.multiplyQbyV(poseRight.rotation, Vec3.UNIT_NEG_Y); + var rotatedLeft = Vec3.multiplyQbyV(poseLeft.rotation, Vec3.UNIT_NEG_Y); + + var suppressRight = false; + var suppressLeft = false; + + // What I really want to do is to slowly increase the epsilon you have to move it + // to wake up, the longer you go without moving it + var leftDistance = Vec3.distance(rotatedLeft, lastRotatedLeft); + var rightDistance = Vec3.distance(rotatedRight, lastRotatedRight); + + // check to see if hand should wakeup or sleep + if (leftAsleep) { + if (leftDistance > leftWakeUpDistance) { + leftAsleep = false; + leftSleepDistance = INITIAL_SLEEP_DISTANCE; + leftWakeUpDistance = INITIAL_WAKE_UP_DISTANCE; + } else { + // grow the wake up distance to make it harder to wake up + leftWakeUpDistance = Math.min(leftWakeUpDistance + INCREMENTAL_WAKE_UP_DISTANCE, MAX_WAKE_UP_DISTANCE); + } + } else { + // we are awake, determine if we should fall asleep, if we haven't moved + // at least as much as our sleep distance then we sleep + if (leftDistance < leftSleepDistance) { + leftAsleep = true; + leftSleepDistance = INITIAL_SLEEP_DISTANCE; + leftWakeUpDistance = INITIAL_WAKE_UP_DISTANCE; + } else { + // if we moved more than the sleep amount, but we moved less than the max sleep + // amount, then increase our liklihood of sleep. + if (leftDistance < MAX_SLEEP_DISTANCE) { + print("growing sleep...."); + leftSleepDistance = Math.max(leftSleepDistance + INCREMENTAL_SLEEP_DISTANCE, MAX_SLEEP_DISTANCE); + } else { + // otherwise reset it to initial + leftSleepDistance = INITIAL_SLEEP_DISTANCE; + } + } + } + if (leftAsleep) { + suppressLeft = true; + debugPrint("suppressing left not moving enough"); + } + + // check to see if hand should wakeup or sleep + if (rightAsleep) { + if (rightDistance > rightWakeUpDistance) { + rightAsleep = false; + rightSleepDistance = INITIAL_SLEEP_DISTANCE; + rightWakeUpDistance = INITIAL_WAKE_UP_DISTANCE; + } else { + // grow the wake up distance to make it harder to wake up + rightWakeUpDistance = Math.min(rightWakeUpDistance + INCREMENTAL_WAKE_UP_DISTANCE, MAX_WAKE_UP_DISTANCE); + } + } else { + // we are awake, determine if we should fall asleep, if we haven't moved + // at least as much as our sleep distance then we sleep + if (rightDistance < rightSleepDistance) { + rightAsleep = true; + rightSleepDistance = INITIAL_SLEEP_DISTANCE; + rightWakeUpDistance = INITIAL_WAKE_UP_DISTANCE; + } else { + // if we moved more than the sleep amount, but we moved less than the max sleep + // amount, then increase our liklihood of sleep. + if (rightDistance < MAX_SLEEP_DISTANCE) { + print("growing sleep...."); + rightSleepDistance = Math.max(rightSleepDistance + INCREMENTAL_SLEEP_DISTANCE, MAX_SLEEP_DISTANCE); + } else { + // otherwise reset it to initial + rightSleepDistance = INITIAL_SLEEP_DISTANCE; + } + } + } + if (rightAsleep) { + suppressRight = true; + debugPrint("suppressing right not moving enough"); + } + + // check to see if hand is on base station + if (Vec3.equal(rotatedLeft, Vec3.UNIT_NEG_Y)) { + suppressLeft = true; + debugPrint("suppressing left on base station"); + } + if (Vec3.equal(rotatedRight, Vec3.UNIT_NEG_Y)) { + suppressRight = true; + debugPrint("suppressing right on base station"); + } + + // Keep track of last rotations, to detect resting (but not on base station hands) in the future + lastRotatedLeft = rotatedLeft; + lastRotatedRight = rotatedRight; + + if (suppressLeft && suppressRight) { + debugPrint("both hands suppressed bail out early"); + return; + } + + if (suppressLeft) { + debugPrint("right only"); + rotatedLeft = rotatedRight; + } + if (suppressRight) { + debugPrint("left only"); + rotatedRight = rotatedLeft; + } + + // Average the two hand positions, if either hand is on base station, the + // other hand becomes the only used hand and the average is the hand in use + var rotated = Vec3.multiply(Vec3.sum(rotatedRight,rotatedLeft), 0.5); + + if (DEBUGGING) { + Vec3.print("rotatedRight:", rotatedRight); + Vec3.print("rotatedLeft:", rotatedLeft); + Vec3.print("rotated:", rotated); + } + 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.x; // from -1 left to 1 right @@ -97,7 +246,6 @@ mapping.from(whichHand).peek().to(function(pose) { moveReticleAbsolute(x, y); } }); -mapping.enable(); Script.scriptEnding.connect(function(){ mapping.disable(); diff --git a/examples/flowArts/arcBall/arcBall.js b/examples/flowArts/arcBall/arcBall.js new file mode 100644 index 0000000000..12ef2df48a --- /dev/null +++ b/examples/flowArts/arcBall/arcBall.js @@ -0,0 +1,145 @@ +// +// arcBall.js +// examples/arcBall +// +// Created by Eric Levin on 12/17/15. +// Copyright 2015 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?v1" + Math.random()); +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.5, + // z: 0.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: 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 + }) + + + + 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..987ddc7a31 --- /dev/null +++ b/examples/flowArts/arcBall/arcBallEntityScript.js @@ -0,0 +1,155 @@ +// 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; + this.colorPalette = [{ + red: 25, + green: 20, + blue: 162 + }, { + red: 200, + green: 10, + blue: 10 + }]; + + this.searchRadius = 10; + }; + + ArcBall.prototype = { + isGrabbed: false, + startDistantGrab: function() { + this.searchForNearbyArcBalls(); + }, + + startNearGrab: 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, this.searchRadius); + 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); + + } + }); + }, + + 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: 1, + speedSpread: 0.02, + emitDimensions: { + x: .01, + y: .01, + z: .01 + }, + polarStart: 0, + polarFinish: 0, + azimuthStart: 0.02, + azimuthFinish: .01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: 0, + y: 0, + z: 0 + }, + radiusStart: 0.01, + radiusFinish: 0.005, + radiusSpread: 0.005, + alpha: 0.5, + alphaSpread: 0.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); + }, + + updateBeam: function() { + if(!this.target) { + 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); + Entities.editEntity(this.particleArc, { + emitOrientation: emitOrientation + }); + }, + + continueNearGrab: function() { + this.updateBeam(); + }, + + continueDistantGrab: function() { + this.updateBeam(); + }, + + releaseGrab: function() { + Entities.editEntity(this.particleArc, { + isEmitting: false + }); + this.target = null; + }, + + 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 new file mode 100644 index 0000000000..faa07c186d --- /dev/null +++ b/examples/flowArts/flowArtsHutSpawner.js @@ -0,0 +1,91 @@ +// +// flowArtsHutSpawner.js +// examples/flowArts +// +// Created by Eric Levin on 12/17/15. +// Copyright 2015 High Fidelity, Inc. +// +// 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. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +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"); + + + +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 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})); + + +var modelURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/models/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, + visible: true +}); + +var floor = Entities.addEntity({ + type: "Box", + 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' +}); + + + +var lightZone = Entities.addEntity({ + type: "Zone", + name: "Rave Hut Zone", + shapeType: 'box', + keyLightIntensity: 0.4, + 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(); + arcBall.cleanup(); + arcBall2.cleanup(); + raveStick.cleanup(); + lightSaber.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 new file mode 100644 index 0000000000..b2ed00f326 --- /dev/null +++ b/examples/flowArts/lightBall/lightBall.js @@ -0,0 +1,145 @@ +// +// 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) { + + var colorPalette = [{ + red: 25, + green: 20, + blue: 162 + }]; + + + var containerBall = Entities.addEntity({ + type: "Sphere", + name: "containerBall", + position: Vec3.sum(spawnPosition, { + x: 0, + y: 0.5, + z: 0 + }), + dimensions: { + x: 0.1, + y: 0.1, + z: 0.1 + }, + color: { + red: 15, + green: 10, + blue: 150 + }, + collisionsWillMove: true, + // gravity: { + // x: 0, + // y: -0.5, + // z: 0 + // }, + userData: JSON.stringify({ + grabbableKey: { + spatialKey: { + relativePosition: { + x: 0, + y: 0.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 lightBall = Entities.addEntity({ + type: "ParticleEffect", + parentID: containerBall, + isEmitting: true, + name: "particleBall", + 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.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: 0.00, + y: 0.00, + z: 0.00 + }, + particleRadius: 0.02, + radiusSpread: 0, + radiusStart: 0.03, + radiusFinish: 0.0003, + alpha: 0, + alphaSpread: 0.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; +} diff --git a/examples/flowArts/lightSaber/lightSaber.js b/examples/flowArts/lightSaber/lightSaber.js new file mode 100644 index 0000000000..c4ab49e8e6 --- /dev/null +++ b/examples/flowArts/lightSaber/lightSaber.js @@ -0,0 +1,67 @@ +// +// LightSaber.js +// examples +// +// Created by Eric Levin on 12/17/15. +// Copyright 2015 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 = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/models/lightSaber.fbx"; +var scriptURL = Script.resolvePath("lightSaberEntityScript.js"); +LightSaber = function(spawnPosition) { + + var saberHandle = Entities.addEntity({ + type: "Model", + name: "LightSaber Handle", + modelURL: modelURL, + position: spawnPosition, + shapeType: 'box', + collisionsWillMove: true, + 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(180, 90, 0) + }, + invertSolidWhileHeld: true + } + }) + }); + + 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); + } + + this.cleanup = cleanup; +} diff --git a/examples/flowArts/lightSaber/lightSaberEntityScript.js b/examples/flowArts/lightSaber/lightSaberEntityScript.js new file mode 100644 index 0000000000..a86f471449 --- /dev/null +++ b/examples/flowArts/lightSaber/lightSaberEntityScript.js @@ -0,0 +1,116 @@ +// lightSaberEntityScript.js +// +// Script Type: Entity +// Created by Eric Levin on 12/17/15. +// Copyright 2015 High Fidelity, Inc. +// +// 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 +// + +(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() { + Entities.editEntity(this.beam, { + isEmitting: true, + visible: true + }); + }, + + releaseGrab: function() { + Entities.editEntity(this.beam, { + visible: false, + isEmitting: false + }); + }, + + preload: function(entityID) { + this.entityID = entityID; + this.createBeam(); + }, + + unload: function() { + Entities.deleteEntity(this.beam); + }, + + createBeam: function() { + + this.props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); + var forwardVec = Quat.getFront(Quat.multiply(this.props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0))); + var forwardQuat = Quat.rotationBetween(Vec3.UNIT_Z, forwardVec); + var position = this.props.position; + + 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, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 2, + emitRate: 1000, + emitOrientation: forwardQuat, + emitSpeed: 0.7, + speedSpread: 0.0, + emitDimensions: { + x: 0, + y: 0, + z: 0 + }, + polarStart: 0, + polarFinish: 0, + azimuthStart: 0.1, + azimuthFinish: 0.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: 0.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); + + } + }; + // entity scripts always need to return a newly constructed object of our type + return new LightSaber(); +}); diff --git a/examples/flowArts/lightTrails.js b/examples/flowArts/lightTrails.js new file mode 100644 index 0000000000..bb936d55c2 --- /dev/null +++ b/examples/flowArts/lightTrails.js @@ -0,0 +1,191 @@ +// +// lightTrails.js +// examples +// +// Created by Eric Levin on 5/14/15. +// Copyright 2015 High Fidelity, Inc. +// +// This script creates light trails as you move your hydra hands +// +// +// 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 eraseTrail = true; +var ugLSD = 25; +// var eraseTrail = false; +var LEFT = 0; +var RIGHT = 1; +var MAX_POINTS_PER_LINE = 50; + +var LIFETIME = 6000; +var DRAWING_DEPTH = 0.8; +var LINE_DIMENSIONS = 100; + + +var MIN_POINT_DISTANCE = 0.02; + + +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 STROKE_WIDTH = 0.04; + +function controller(side, triggerAction) { + this.triggerHeld = false; + this.triggerThreshold = 0.9; + this.side = side; + this.triggerAction = triggerAction; + var texture = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/trails.png"; + + this.light = Entities.addEntity({ + type: 'Light', + position: MyAvatar.position, + dimensions: { + x: 30, + y: 30, + z: 30 + }, + color: colorPalette[randInt(0, colorPalette.length)], + intensity: 5 + }); + + 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 = []; + 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.setTrailPosition = function(position) { + this.trailPosition = position; + Entities.editEntity(this.trail, { + position: this.trailPosition + }); + } + + + this.update = function(deltaTime) { + 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) { + this.setTrailPosition(newTrailPos); + this.drawing = true; + } + + 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(newTrailPos, Camera.getPosition()); + + this.normals.push(normal); + this.strokeWidths.push(STROKE_WIDTH + Math.random() * 0.01); + Entities.editEntity(this.trail, { + linePoints: this.points, + normals: this.normals, + strokeWidths: this.strokeWidths, + }); + + } + } + + + this.updateControllerState = function() { + 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.cleanup = function() { + Entities.deleteEntity(this.trail); + Entities.deleteEntity(this.light); + Script.clearInterval(this.trailEraseInterval); + } +} + +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/flowArts/raveStick/raveStick.js b/examples/flowArts/raveStick/raveStick.js new file mode 100644 index 0000000000..c51e8b5d89 --- /dev/null +++ b/examples/flowArts/raveStick/raveStick.js @@ -0,0 +1,90 @@ +// +// RaveStick.js +// examples/flowArats/raveStick +// +// Created by Eric Levin on 12/17/15. +// Copyright 2015 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 = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/models/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', + collisionsWillMove: true, + 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 + } + }) + }); + + 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 + }); + + 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 + }; + + + + + function cleanup() { + Entities.deleteEntity(stick); + Entities.deleteEntity(light); + } + + this.cleanup = cleanup; +} \ No newline at end of file diff --git a/examples/flowArts/raveStick/raveStickEntityScript.js b/examples/flowArts/raveStick/raveStickEntityScript.js new file mode 100644 index 0000000000..3f571817d2 --- /dev/null +++ b/examples/flowArts/raveStick/raveStickEntityScript.js @@ -0,0 +1,141 @@ +// raveStickEntityScript.js +// +// Script Type: Entity +// 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. +// 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 LIFETIME = 6000; + var DRAWING_DEPTH = 0.8; + var LINE_DIMENSIONS = 100; + var MAX_POINTS_PER_LINE = 50; + var MIN_POINT_DISTANCE = 0.02; + var STROKE_WIDTH = 0.05 + var ugLSD = 35; + var RaveStick = function() { + _this = this; + this.colorPalette = [{ + red: 0, + green: 200, + blue: 40 + }, { + red: 200, + 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 = { + isGrabbed: false, + + startNearGrab: function() { + this.trailBasePosition = Entities.getEntityProperties(this.entityID, "position").position; + Entities.editEntity(this.trail, { + position: this.trailBasePosition + }); + this.points = []; + this.normals = []; + this.strokeWidths = []; + this.setupEraseInterval(); + }, + + continueNearGrab: 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.04)); + 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; + } + if (this.points.length === MAX_POINTS_PER_LINE) { + this.points.shift(); + this.normals.shift(); + this.strokeWidths.shift(); + } + + this.points.push(localPoint); + var normal = Quat.getUp(props.rotation); + this.normals.push(normal); + this.strokeWidths.push(STROKE_WIDTH); + Entities.editEntity(this.trail, { + linePoints: this.points, + normals: this.normals, + strokeWidths: this.strokeWidths + }); + + + }, + + 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() { + if(!this.trailEraseInterval) { + return; + } + Script.setTimeout(function() { + Script.clearInterval(_this.trailEraseInterval); + _this.trailEraseInterval = null; + }, 3000); + }, + + preload: function(entityID) { + this.entityID = entityID; + }, + + unload: function() { + Entities.deleteEntity(this.beam); + Entities.deleteEntity(this.trail); + if (this.trailEraseInterval) { + Script.clearInterval(this.trailEraseInterval); + } + } + }; + return new RaveStick(); + + function computeNormal(p1, p2) { + return Vec3.normalize(Vec3.subtract(p2, p1)); + } +}); \ No newline at end of file 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/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 } }) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 379d1cc4a3..567d2bc24a 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -240,8 +240,11 @@ 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-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 256e36ebc3..cfdcc87121 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -23,6 +23,13 @@ #include "paintStroke_frag.h" + +struct PolyLineUniforms { + glm::vec3 color; +}; + + + EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer entity{ new RenderablePolyLineEntityItem(entityID) }; entity->setProperties(properties); @@ -30,9 +37,12 @@ EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& enti } RenderablePolyLineEntityItem::RenderablePolyLineEntityItem(const EntityItemID& entityItemID) : - PolyLineEntityItem(entityItemID) { - _numVertices = 0; +PolyLineEntityItem(entityItemID), +_numVertices(0) +{ _vertices = QVector(0.0f); + PolyLineUniforms uniforms; + _uniformBuffer = std::make_shared(sizeof(PolyLineUniforms), (const gpu::Byte*) &uniforms); } gpu::PipelinePointer RenderablePolyLineEntityItem::_pipeline; @@ -41,13 +51,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::Shader::createVertex(std::string(paintStroke_vert)); @@ -72,47 +80,28 @@ 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); _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++; _numVertices += 2; + uCoord += uCoordInc; } _pointsChanged = false; _normalsChanged = false; @@ -161,6 +150,16 @@ void RenderablePolyLineEntityItem::updateVertices() { } +void RenderablePolyLineEntityItem::update(const quint64& now) { + PolyLineUniforms uniforms; + uniforms.color = toGlm(getXColor()); + memcpy(&_uniformBuffer.edit(), &uniforms, sizeof(PolyLineUniforms)); + if (_pointsChanged || _strokeWidthsChanged || _normalsChanged) { + updateVertices(); + updateGeometry(); + } + +} void RenderablePolyLineEntityItem::render(RenderArgs* args) { QWriteLocker lock(&_quadReadWriteLock); @@ -181,17 +180,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 +195,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 eca7c59fef..d320610d83 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -29,6 +29,8 @@ public: RenderablePolyLineEntityItem(const EntityItemID& entityItemID); virtual void render(RenderArgs* args); + virtual void update(const quint64& now) override; + virtual bool needsToCallUpdate() const { return true; }; SIMPLE_RENDERABLE(); @@ -42,6 +44,7 @@ protected: void updateGeometry(); void updateVertices(); gpu::BufferPointer _verticesBuffer; + gpu::BufferView _uniformBuffer; unsigned int _numVertices; QVector _vertices; diff --git a/libraries/entities-renderer/src/RenderableProceduralItemShader.h b/libraries/entities-renderer/src/RenderableProceduralItemShader.h index 8c9e7c77dd..a01a6b8571 100644 --- a/libraries/entities-renderer/src/RenderableProceduralItemShader.h +++ b/libraries/entities-renderer/src/RenderableProceduralItemShader.h @@ -23,8 +23,6 @@ layout(location = 0) out vec4 _fragColor0; layout(location = 1) out vec4 _fragColor1; layout(location = 2) out vec4 _fragColor2; -// the glow intensity -uniform float glowIntensity; // the alpha threshold uniform float alphaThreshold; uniform sampler2D normalFittingMap; @@ -318,8 +316,8 @@ const QString SHADER_TEMPLATE_V1 = SHADER_COMMON + R"SCRIBE( void main(void) { vec4 emissive = getProceduralColor(); - float alpha = glowIntensity * emissive.a; - if (alpha != glowIntensity) { + float alpha = emissive.a; + if (alpha != 1.0) { discard; } diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 4e2bc8d097..fc659d5928 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -23,23 +23,24 @@ 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); -} - +struct PolyLineUniforms { + vec3 color; +}; +uniform polyLineBuffer { + PolyLineUniforms polyline; +}; void main(void) { vec4 texel = texture(originalTexture, varTexcoord); int frontCondition = 1 -int(gl_FrontFacing) * 2; - vec3 color = varColor.rgb; - //vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess + vec3 color = varColor.rgb; packDeferredFragmentTranslucent( interpolatedNormal * frontCondition, texel.a, - color *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 c7dd112bcc..769b87f2a9 100644 --- a/libraries/entities-renderer/src/paintStroke.slv +++ b/libraries/entities-renderer/src/paintStroke.slv @@ -32,6 +32,7 @@ void main(void) { // pass along the diffuse color varColor = colorToLinearRGBA(inColor); + // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); 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 165afd1536..16196aa129 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 @@ -91,7 +91,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) { @@ -331,7 +331,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; @@ -370,7 +370,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; @@ -463,7 +463,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; @@ -503,7 +503,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; } @@ -546,7 +546,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 { @@ -641,13 +641,17 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { Particle particle; - - particle.seed = randFloatInRange(0.0f, 1.0f); - + + + particle.seed = randFloatInRange(-1.0f, 1.0f); + 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 - 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 { @@ -658,11 +662,12 @@ 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) *randFloat()); float azimuth; if (_azimuthFinish >= _azimuthStart) { - azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat(); + azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat(); } else { azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * randFloat(); } @@ -693,7 +698,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 cae9340b6d..5afcbe2ae1 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -213,10 +213,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; } @@ -286,7 +286,7 @@ protected: float _timeUntilNextEmit { 0.0f }; - bool _additiveBlending { DEFAULT_ADDITIVE_BLENDING }; + bool _emitterShouldTrail { DEFAULT_EMITTER_SHOULD_TRAIL }; }; #endif // hifi_ParticleEffectEntityItem_h diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index e7281d8157..b0b78bc9c5 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -89,6 +89,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!"; @@ -104,6 +105,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 dfe062bbdb..cf7b14dbf1 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; @@ -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. diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 23150a1779..ca678770fb 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -56,7 +56,7 @@ static const std::string DEEFAULT_ROUGHNESS_SHADER { }; static const std::string DEEFAULT_NORMAL_SHADER { "vec4 getFragmentColor() {" - " return vec4(texture(normalMap, uv).xyz, 1.0);" + " return vec4(normalize(texture(normalMap, uv).xyz), 1.0);" " }" }; static const std::string DEEFAULT_DEPTH_SHADER { diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index d3a5ff1e31..1045c4afc7 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -15,12 +15,6 @@ layout(location = 0) out vec4 _fragColor0; layout(location = 1) out vec4 _fragColor1; layout(location = 2) out vec4 _fragColor2; -// the glow intensity -uniform float glowIntensity; - -// the alpha threshold -uniform float alphaThreshold; - uniform sampler2D normalFittingMap; vec3 bestFitNormal(vec3 normal) { @@ -39,15 +33,18 @@ vec3 bestFitNormal(vec3 normal) { return (cN * 0.5 + 0.5); } + +// the alpha threshold +const float alphaThreshold = 0.5; float evalOpaqueFinalAlpha(float alpha, float mapAlpha) { - return mix(alpha * glowIntensity, 1.0 - alpha * glowIntensity, step(mapAlpha, alphaThreshold)); + return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold)); } const vec3 DEFAULT_SPECULAR = vec3(0.1); const float DEFAULT_SHININESS = 10; void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { - if (alpha != glowIntensity) { + if (alpha != 1.0) { discard; } @@ -57,7 +54,7 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, } void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess, vec3 emissive) { - if (alpha != glowIntensity) { + if (alpha != 1.0) { discard; } @@ -67,7 +64,7 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 s } void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { - if (alpha <= alphaThreshold) { + if (alpha <= 0.0) { discard; } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 4e4799612d..db0e47de5e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -40,8 +40,6 @@ #include "point_light_frag.h" #include "spot_light_frag.h" -static const std::string glowIntensityShaderHandle = "glowIntensity"; - struct LightLocations { int radius; int ambientSphere; @@ -134,8 +132,6 @@ gpu::PipelinePointer DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch batch.setPipeline(pipeline); gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader; - int glowIntensity = program->getUniforms().findLocation("glowIntensity"); - batch._glUniform1f(glowIntensity, 1.0f); if (!config.isTextured()) { // If it is not textured, bind white texture and keep using textured pipeline diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 2fae09a158..414ad9cf97 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -199,8 +199,6 @@ void MeshPartPayload::render(RenderArgs* args) const { gpu::Batch& batch = *(args->_batch); auto mode = args->_renderMode; - auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME - model::MaterialKey drawMaterialKey; if (_drawMaterial) { drawMaterialKey = _drawMaterial->getKey(); @@ -217,7 +215,7 @@ void MeshPartPayload::render(RenderArgs* args) const { } ModelRender::Locations* locations = nullptr; - ModelRender::pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, + ModelRender::pickPrograms(batch, mode, translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, args, locations); @@ -395,9 +393,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { gpu::Batch& batch = *(args->_batch); auto mode = args->_renderMode; - - auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME - + const FBXGeometry& geometry = _model->_geometry->getFBXGeometry(); const std::vector>& networkMeshes = _model->_geometry->getMeshes(); @@ -467,7 +463,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { } ModelRender::Locations* locations = nullptr; - ModelRender::pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, + ModelRender::pickPrograms(batch, mode, translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, args, locations); if (!locations) { // the pipeline could not be found diff --git a/libraries/render-utils/src/ModelRender.cpp b/libraries/render-utils/src/ModelRender.cpp index 10c9d738d2..312d34e41b 100644 --- a/libraries/render-utils/src/ModelRender.cpp +++ b/libraries/render-utils/src/ModelRender.cpp @@ -228,10 +228,8 @@ void ModelRender::RenderPipelineLib::addRenderPipeline(ModelRender::RenderKey ke void ModelRender::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, ModelRender::Locations& locations) { - locations.alphaThreshold = program->getUniforms().findLocation("alphaThreshold"); locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); - locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); locations.diffuseTextureUnit = program->getTextures().findLocation("diffuseMap"); locations.normalTextureUnit = program->getTextures().findLocation("normalMap"); @@ -244,14 +242,14 @@ void ModelRender::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, } -void ModelRender::pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, +void ModelRender::pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, Locations*& locations) { PerformanceTimer perfTimer("Model::pickPrograms"); getRenderPipelineLib(); - RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe); + RenderKey key(mode, translucent, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe); auto pipeline = _renderPipelineLib.find(key.getRaw()); if (pipeline == _renderPipelineLib.end()) { qDebug() << "No good, couldn't find a pipeline from the key ?" << key.getRaw(); @@ -266,15 +264,6 @@ void ModelRender::pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, b // Setup the One pipeline batch.setPipeline((*pipeline).second._pipeline); - if ((locations->alphaThreshold > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) { - batch._glUniform1f(locations->alphaThreshold, alphaThreshold); - } - - if ((locations->glowIntensity > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) { - const float DEFAULT_GLOW_INTENSITY = 1.0f; // FIXME - glow is removed - batch._glUniform1f(locations->glowIntensity, DEFAULT_GLOW_INTENSITY); - } - if ((locations->normalFittingMapUnit > -1)) { batch.setResourceTexture(locations->normalFittingMapUnit, DependencyManager::get()->getNormalFittingTexture()); diff --git a/libraries/render-utils/src/ModelRender.h b/libraries/render-utils/src/ModelRender.h index 39fe05378d..8331440fb0 100644 --- a/libraries/render-utils/src/ModelRender.h +++ b/libraries/render-utils/src/ModelRender.h @@ -29,21 +29,19 @@ public: class Locations { public: - int alphaThreshold; int texcoordMatrices; int diffuseTextureUnit; int normalTextureUnit; int specularTextureUnit; int emissiveTextureUnit; int emissiveParams; - int glowIntensity; int normalFittingMapUnit; int skinClusterBufferUnit; int materialBufferUnit; int lightBufferUnit; }; - static void pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, + static void pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, Locations*& locations); @@ -111,9 +109,9 @@ public: ) {} RenderKey(RenderArgs::RenderMode mode, - bool translucent, float alphaThreshold, bool hasLightmap, + bool translucent, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe) : - RenderKey(((translucent && (alphaThreshold == 0.0f) && (mode != RenderArgs::SHADOW_RENDER_MODE)) ? IS_TRANSLUCENT : 0) + RenderKey(((translucent && (mode != RenderArgs::SHADOW_RENDER_MODE)) ? IS_TRANSLUCENT : 0) | (hasLightmap && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_LIGHTMAP : 0) // Lightmap, tangents and specular don't matter for depthOnly | (hasTangents && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_TANGENTS : 0) | (hasSpecular && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_SPECULAR : 0) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 4dcda425a1..cf60fcfe37 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -126,12 +126,6 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new HitEffect::JobModel("HitEffect"))); _jobs.back().setEnabled(false); _drawHitEffectJobIndex = (int)_jobs.size() -1; - - // Give ourselves 3 frmaes of timer queries - _timerQueries.push_back(std::make_shared()); - _timerQueries.push_back(std::make_shared()); - _timerQueries.push_back(std::make_shared()); - _currentTimerQueryIndex = 0; } RenderDeferredTask::~RenderDeferredTask() { @@ -197,10 +191,6 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - { - const float OPAQUE_ALPHA_THRESHOLD = 0.5f; - args->_alphaThreshold = OPAQUE_ALPHA_THRESHOLD; - } renderItems(sceneContext, renderContext, inItems, opaque.maxDrawn); args->_batch = nullptr; }); @@ -226,10 +216,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - - const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; - args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD; - + renderItems(sceneContext, renderContext, inItems, transparent.maxDrawn); args->_batch = nullptr; }); diff --git a/libraries/render-utils/src/SkyFromSpace.slf b/libraries/render-utils/src/SkyFromSpace.slf index e3569a2914..42282fe08b 100755 --- a/libraries/render-utils/src/SkyFromSpace.slf +++ b/libraries/render-utils/src/SkyFromSpace.slf @@ -114,5 +114,6 @@ void main (void) vec3 finalColor = color + fMiePhase * secondaryColor; 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/simple.slf b/libraries/render-utils/src/simple.slf index 8c93ee564e..b24e4f92ff 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -51,9 +51,9 @@ void main(void) { if (emissiveAmount > 0.0) { packDeferredFragmentLightmap( - normal, glowIntensity, diffuse, specular, shininess, specular); + normal, 1.0, diffuse, specular, shininess, specular); } else { packDeferredFragment( - normal, glowIntensity, diffuse, specular, shininess); + normal, 1.0, diffuse, specular, shininess); } } diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index d567b043f4..727c029bbe 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -29,7 +29,7 @@ void main(void) { packDeferredFragment( normalize(_normal.xyz), - glowIntensity * texel.a, + texel.a, _color.rgb * texel.rgb, DEFAULT_SPECULAR, DEFAULT_SHININESS); } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_emisive.slf b/libraries/render-utils/src/simple_textured_emisive.slf index 96119e98f0..1dd3d667a6 100644 --- a/libraries/render-utils/src/simple_textured_emisive.slf +++ b/libraries/render-utils/src/simple_textured_emisive.slf @@ -27,7 +27,7 @@ void main(void) { packDeferredFragmentLightmap( normalize(_normal), - glowIntensity * texel.a, + texel.a, _color.rgb, DEFAULT_SPECULAR, DEFAULT_SHININESS, texel.rgb); diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 061e07c600..399b94bcef 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -115,8 +115,6 @@ public: std::shared_ptr _whiteTexture; RenderDetails _details; - - float _alphaThreshold = 0.5f; }; #endif // hifi_RenderArgs_h diff --git a/tests/gpu-test/src/unlit.slf b/tests/gpu-test/src/unlit.slf index 350190180a..77d28aa7e9 100644 --- a/tests/gpu-test/src/unlit.slf +++ b/tests/gpu-test/src/unlit.slf @@ -22,7 +22,7 @@ in vec3 _color; void main(void) { packDeferredFragment( normalize(_normal.xyz), - glowIntensity, + 1.0, _color.rgb, DEFAULT_SPECULAR, DEFAULT_SHININESS); } diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index ee53e36f9e..94d815796b 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: 0.2, + speedSpread: 0.0, + polarStart: 0, + polarFinish: 0.0, + azimuthStart: 0.1, + azimuthFinish: 0.01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: 0.00, + y: 0.00, + z: 0.00 + }, + radiusStart: 0.03, + radiusFinish: 0.025, + alpha: 0.7, + alphaSpread:0.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"; @@ -1012,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", @@ -1040,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 1837f4d656..9afbd0a68b 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: 0.2, + speedSpread: 0.0, + polarStart: 0, + polarFinish: 0.0, + azimuthStart: 0.1, + azimuthFinish: 0.01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: 0.00, + y: 0.00, + z: 0.00 + }, + radiusStart: 0.03, + radiusFinish: 0.025, + alpha: 0.7, + alphaSpread: 0.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"; @@ -992,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", @@ -1020,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 } @@ -1349,7 +1471,7 @@ MasterReset = function() { resetMe: true }, grabbableKey: { - invertSolidWhileHeld: true + invertSolidWhileHeld: true } }) });