From a9379c41fe1226a44bd25e69618073bd2acfe3d1 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 16 Nov 2015 19:04:07 -0800 Subject: [PATCH 001/174] gnight --- examples/libraries/createAvatarDetector.js | 40 ++++ examples/libraries/ratTest.js | 242 +++++++++++++++++++++ examples/libraries/steer.js | 217 ++++++++++++++++++ 3 files changed, 499 insertions(+) create mode 100644 examples/libraries/createAvatarDetector.js create mode 100644 examples/libraries/ratTest.js create mode 100644 examples/libraries/steer.js diff --git a/examples/libraries/createAvatarDetector.js b/examples/libraries/createAvatarDetector.js new file mode 100644 index 0000000000..82a1806ca8 --- /dev/null +++ b/examples/libraries/createAvatarDetector.js @@ -0,0 +1,40 @@ +var avatarDetector = null; + +function createAvatarDetector() { + + var detectorProperties = { + name: 'Hifi-Avatar-Detector', + type: 'Box', + position: MyAvatar.position, + dimensions: { + x: 1, + y: 2, + z: 1 + }, + collisionsWillMove: false, + ignoreForCollisions: true, + visible: false, + color: { + red: 255, + green: 0, + blue: 0 + } + } + avatarDetector= Entities.addEntity(detectorProperties); +}; +var updateAvatarDetector = function() { + // print('updating detector position' + JSON.stringify(MyAvatar.position)) + + Entities.editEntity(avatarDetector, { + position: MyAvatar.position + }) +}; + +var cleanup = function() { + Script.update.disconnect(updateAvatarDetector); + Entities.deleteEntity(avatarDetector); +} + +createAvatarDetector(); +Script.scriptEnding.connect(cleanup); +Script.update.connect(updateAvatarDetector); \ No newline at end of file diff --git a/examples/libraries/ratTest.js b/examples/libraries/ratTest.js new file mode 100644 index 0000000000..3d06c15037 --- /dev/null +++ b/examples/libraries/ratTest.js @@ -0,0 +1,242 @@ +Script.include('steer.js') +var steer = loadSteer(); +Script.include('tween.js'); +var TWEEN = loadTween(); + +var ratProperties = { + name: 'Hifi-Rat-Nest', + type: 'Box', + color: { + red: 0, + green: 0, + blue: 255 + }, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + position: { + x: 0, + y: 0, + z: 0 + } +}; + +var targetProperties = { + name: 'Hifi-Rat', + type: 'Box', + color: { + red: 0, + green: 255, + blue: 0 + }, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + position: { + x: 5, + y: 0, + z: 0 + } + // script: Script.resolvePath('rat.js') +}; + +var target = Entities.addEntity(targetProperties) + +function addRat() { + var rat = Entities.addEntity(ratProperties); + rats.push(rat); +} + +var rats = []; +addRat(); + +var avoiders = []; + +function addAvoiderBlock() { + + var avoiderProperties = { + name: 'Hifi-Rat-Avoider', + type: 'Box', + color: { + red: 255, + green: 0, + blue: 255 + }, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + position: { + x: 1, + y: 1, + z: 1 + } + } + + var avoider = Entities.addEntity(avoiderProperties); + avoiders.push(avoider) +} +addAvoiderBlock(); +tweenAvoider(avoiders[0]); + +function tweenAvoider(entityID) { + var ANIMATION_DURATION = 500; + + var begin = { + x: 1, + y: 1, + z: 1 + } + var target = { + x: 3, + y: 1, + z: 3 + } + var original = { + x: 1, + y: 1, + z: 1 + } + var tweenHead = new TWEEN.Tween(begin).to(target, ANIMATION_DURATION); + + function updateTo() { + Entities.editEntity(entityID, { + position: { + x: begin.x, + y: begin.y, + z: begin.z + } + }) + } + + function updateBack() { + Entities.editEntity(entityID, { + position: { + x: begin.x, + y: begin.y, + z: begin.z + } + }) + } + var tweenBack = new TWEEN.Tween(begin).to(original, ANIMATION_DURATION).onUpdate(updateBack); + + tweenHead.onUpdate(function() { + updateTo() + }) + tweenHead.chain(tweenBack); + tweenBack.chain(tweenHead); + tweenHead.start(); + +} + +function updateTweens() { + TWEEN.update(); +} + +function moveRats() { + rats.forEach(function(rat) { + // print('debug1') + + var avatarFlightVectors = steer.fleeAllAvatars(rat); + print('avatarFlightVectors'+avatarFlightVectors) + var i; + var averageAvatarFlight; + + for (i = 0; i < avatarFlightVectors.length; i++) { + print('debug2') + + if (i === 0) { + averageAvatarFlight = avatarFlightVectors[0]; + } else { + averageAvatarFlight = Vec3.sum(avatarFlightVectors[i - 1], avatarFlightVectors[i]) + } + } + + averageAvatarFlight = Vec3.multiply(averageAvatarFlight, 1 / avatarFlightVectors.length); + + + // var avoidBlockVectors = steer.fleeAvoiderBlocks(rat); + + // var averageAvoiderFlight; + + // for (i = 0; i < avoidBlockVectors.length; i++) { + // if (i === 0) { + // averageAvoiderFlight = avoidBlockVectors[0]; + // } else { + // averageAvoiderFlight = Vec3.sum(avoidBlockVectors[i - 1], avoidBlockVectors[i]) + // } + // } + + // averageAvoiderFlight = Vec3.multiply(averageAvoiderFlight, 1 / avoidBlockVectors.length); + + + + var averageVector; + var seek = steer.arrive(rat, target); + averageVector = seek; + var divisorCount = 1; + if (avatarFlightVectors.length > 0) { + divisorCount++; + averageVector = Vec3.sum(averageVector, averageAvatarFlight); + } + // if (avoidBlockVectors > 0) { + // divisorCount++ + // averageVector = Vec3.sum(averageVector, averageAvoiderFlight); + // } + + averageVector = Vec3.multiply(averageVector, 1 / divisorCount); + print('AVERAGE VECTOR:::'+JSON.stringify(averageVector)) + // castRay(rat); + Entities.editEntity(rat, { + velocity: averageVector + }) + + }) +} + +Script.update.connect(moveRats) +Script.update.connect(updateTweens); + +function castRay(rat) { + var ratProps = Entities.getEntityProperties(rat, ["position", "rotation"]); + var shotDirection = Quat.getFront(ratProps.rotation); + var pickRay = { + origin: ratProps.position, + direction: shotDirection + }; + + var intersection = Entities.findRayIntersection(pickRay, true); + if (intersection.intersects) { + var distance = Vec3.subtract(intersection.properties.position, ratProps.position); + distance = Vec3.length(distance); + // print('INTERSECTION:::'+distance); + } else { + print('no intersection') + } +} + +function cleanup() { + while (rats.length > 0) { + Entities.deleteEntity(rats.pop()); + } + + while (avoiders.length > 0) { + Entities.deleteEntity(avoiders.pop()); + } + Entities.deleteEntity(target); + Script.update.disconnect(moveRats); + Script.update.disconnect(updateTweens); + + +} + +Script.scriptEnding.connect(cleanup) + +// Script.setInterval(function() { +// addRat(); +// }) \ No newline at end of file diff --git a/examples/libraries/steer.js b/examples/libraries/steer.js new file mode 100644 index 0000000000..d7b1a8e295 --- /dev/null +++ b/examples/libraries/steer.js @@ -0,0 +1,217 @@ +function seek(thisEntity, target) { + var targetPosition = Entities.getEntityProperties(target, "position").position; + var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); + var location = properties.position; + var velocity = properties.velocity; + var MAX_SPEED = 1; + var MAX_FORCE = 1; + + var desired = Vec3.subtract(targetPosition, location); + desired = Vec3.normalize(desired); + desired = Vec3.multiply(MAX_SPEED, desired); + + var steer = Vec3.subtract(desired, velocity); + var steerVector = new V3(desired.x, desired.y, desired.z); + steer = steerVector.limit(MAX_FORCE) + + return steer + +} + +function flee(thisEntity, target) { + var targetPosition = Entities.getEntityProperties(target, "position").position; + var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); + var location = properties.position; + var velocity = properties.velocity; + var MAX_SPEED = 1; + var MAX_FORCE = 1; + + + var desired = Vec3.subtract(location, targetPosition); + var d = Vec3.length(desired); + desired = Vec3.normalize(desired); + desired = Vec3.multiply(MAX_SPEED, desired); + if (d < 2) { + var steer = Vec3.subtract(desired, velocity); + + var steerVector = new V3(desired.x, desired.y, desired.z); + steer = steerVector.limit(MAX_FORCE) + + return steer + } else { + // print('target too far away to flee' + d); + return + } +} + +function fleeAvatar(thisEntity, avatarPosition) { + var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); + var location = properties.position; + var velocity = properties.velocity; + var MAX_SPEED = 2; + var MAX_FORCE = 2; + + var desired = Vec3.subtract(location, avatarPosition); + var d = Vec3.length(desired); + desired = Vec3.normalize(desired); + desired = Vec3.multiply(MAX_SPEED, desired); + if (d < 3) { + var steer = Vec3.subtract(desired, velocity); + + var steerVector = new V3(desired.x, desired.y, desired.z); + steer = steerVector.limit(MAX_FORCE) + return steer + } else { + // print('target too far away to flee' + d); + return + } + +} + +function fleeAllAvatars(thisEntity) { + print('FLEE AVATARS') + var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); + var location = properties.position; + var velocity = properties.velocity; + + var nearbyEntities = Entities.findEntities(location, 3); + var flightVectors = [] + for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { + var entityID = nearbyEntities[entityIndex]; + var entityProps = Entities.getEntityProperties(entityID); + if (entityProps.name === 'Hifi-Avatar-Detector') { + print('found an avatar to flee') + + var MAX_SPEED = 2; + var MAX_FORCE = 2; + + var desired = Vec3.subtract(location, entityProps.position); + var d = Vec3.length(desired); + desired = Vec3.normalize(desired); + desired = Vec3.multiply(MAX_SPEED, desired); + if (d < 3) { + var steer = Vec3.subtract(desired, velocity); + var steerVector = new V3(desired.x, desired.y, desired.z); + steer = steerVector.limit(MAX_FORCE) + flightVectors.push(steer) + } else { + print('target too far away from this avatar to flee' + d); + } + + + } + + } + + return flightVectors +} + +function fleeAvoiderBlocks(thisEntity) { + var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); + var location = properties.position; + var velocity = properties.velocity; + + var nearbyEntities = Entities.findEntities(location, 2); + var flightVectors = [] + for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { + var entityID = nearbyEntities[entityIndex]; + var entityProps = Entities.getEntityProperties(entityID); + if (entityProps.name === 'Hifi-Rat-Avoider') { + print('found an avatar to flee') + + var MAX_SPEED = 2; + var MAX_FORCE = 2; + + var desired = Vec3.subtract(location, entityProps.position); + var d = Vec3.length(desired); + desired = Vec3.normalize(desired); + desired = Vec3.multiply(MAX_SPEED, desired); + if (d < 2) { + var steer = Vec3.subtract(desired, velocity); + var steerVector = new V3(desired.x, desired.y, desired.z); + steer = steerVector.limit(MAX_FORCE) + flightVectors.push(steer) + } else { + print('target too far away from this avoider to flee' + d); + } + + + } + + } + + return flightVectors +} + +function arrive(thisEntity, target) { + + var targetPosition = Entities.getEntityProperties(target, "position").position; + var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); + var location = properties.position; + var velocity = properties.velocity; + var MAX_SPEED = 3; + var MAX_FORCE = 2; + var ARRIVAL_DISTANCE = 3; + + + var desired = Vec3.subtract(targetPosition, location); + var d = Vec3.length(desired); + desired = Vec3.normalize(desired); + if (d < ARRIVAL_DISTANCE) { + var m = scale(d, 0, ARRIVAL_DISTANCE, 0, MAX_SPEED); + } else { + desired = Vec3.multiply(MAX_SPEED, desired); + + } + var steer = Vec3.subtract(desired, velocity); + var steerVector = new V3(desired.x, desired.y, desired.z); + steer = steerVector.limit(MAX_FORCE) + + return steer +} + + +function V3(x, y, z) { + this.x = x; + this.y = y; + this.z = z; + return +} + +V3.prototype.length = function() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); +}; + +V3.prototype.limit = function(s) { + var len = this.length(); + + if (len > s && len > 0) { + this.scale(s / len); + } + + return this; +}; + +V3.prototype.scale = function(f) { + this.x *= f; + this.y *= f; + this.z *= f; + return this; +}; + +var v3 = new V3(); + +var scale = function(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); +} + +loadSteer = function() { + return { + seek: seek, + flee: flee, + fleeAvatar: fleeAvatar, + fleeAllAvatars: fleeAllAvatars, + // fleeAvoiderBlocks:fleeAvoiderBlocks, + arrive: arrive + } +} \ No newline at end of file From 609828273643ef52d71646ab79c1067995390975 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 16 Nov 2015 19:10:41 -0800 Subject: [PATCH 002/174] end --- examples/libraries/ratTest.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/libraries/ratTest.js b/examples/libraries/ratTest.js index 3d06c15037..80c861a1e9 100644 --- a/examples/libraries/ratTest.js +++ b/examples/libraries/ratTest.js @@ -140,15 +140,15 @@ function updateTweens() { function moveRats() { rats.forEach(function(rat) { - // print('debug1') + // print('debug1') var avatarFlightVectors = steer.fleeAllAvatars(rat); - print('avatarFlightVectors'+avatarFlightVectors) + print('avatarFlightVectors' + avatarFlightVectors) var i; var averageAvatarFlight; for (i = 0; i < avatarFlightVectors.length; i++) { - print('debug2') + print('debug2') if (i === 0) { averageAvatarFlight = avatarFlightVectors[0]; @@ -174,7 +174,7 @@ function moveRats() { // averageAvoiderFlight = Vec3.multiply(averageAvoiderFlight, 1 / avoidBlockVectors.length); - + var averageVector; var seek = steer.arrive(rat, target); @@ -190,8 +190,8 @@ function moveRats() { // } averageVector = Vec3.multiply(averageVector, 1 / divisorCount); - print('AVERAGE VECTOR:::'+JSON.stringify(averageVector)) - // castRay(rat); + print('AVERAGE VECTOR:::' + JSON.stringify(averageVector)) + // castRay(rat); Entities.editEntity(rat, { velocity: averageVector }) From f669f8ac79bf8467592b5e7fe1872c2ed5987239 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 17 Nov 2015 00:34:14 -0800 Subject: [PATCH 003/174] prep for adding to drylake --- .../createAvatarDetector.js | 0 examples/drylake/ratCreator.js | 371 ++++++++++++++++++ examples/{libraries => drylake}/steer.js | 30 +- examples/libraries/ratTest.js | 38 +- 4 files changed, 410 insertions(+), 29 deletions(-) rename examples/{libraries => drylake}/createAvatarDetector.js (100%) create mode 100644 examples/drylake/ratCreator.js rename examples/{libraries => drylake}/steer.js (93%) diff --git a/examples/libraries/createAvatarDetector.js b/examples/drylake/createAvatarDetector.js similarity index 100% rename from examples/libraries/createAvatarDetector.js rename to examples/drylake/createAvatarDetector.js diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js new file mode 100644 index 0000000000..c907183de4 --- /dev/null +++ b/examples/drylake/ratCreator.js @@ -0,0 +1,371 @@ +Script.include('steer.js') +var steer = loadSteer(); +Script.include('tween.js'); +var TWEEN = loadTween(); + +var USE_CONSTANT_SPAWNER = false; + +var RAT_SPAWNER_LOCATION = { + x: 0, + y: 0, + z: 0 +}; + +var RAT_NEST_LOCATION = { + x: 0, + y: 0, + z: 0 +}; + +var RAT_MODEL_URL = ''; +var RAT_RUNNING_ANIMATION_URL = ''; +var RAT_DEATH_ANIMATION_URL = ''; + +var RAT_IN_NEST_DISTANCE = 0.25; + +//how many milliseconds between rats +var RAT_SPAWN_RATE = 1000; + + +function playRatRunningAnimation() { + var animationSettings = JSON.stringify({ + running: true + }); + Entities.editEntity(rat, { + animationURL: RAT_RUNNING_ANIMATION_URL, + animationSettings: animationSettings, + // animation: { + // url: RAT_RUNNING_ANIMATION_URL, + // running: true, + // fps: 180 + // }, + }); +} + +function playRatDeathAnimation() { + var animationSettings = JSON.stringify({ + running: true + }); + + Entities.editEntity(rat, { + animationURL: RAT_DEATH_ANIMATION_URL, + animationSettings: animationSettings, + // animation: { + // url: RAT_DEATH_ANIMATION_URL, + // running: true, + // fps: 180 + // }, + }); +} + +var ratProperties = { + name: 'Hifi-Rat', + type: 'Box', + color: { + red: 0, + green: 0, + blue: 255 + }, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + position: RAT_SPAWNER_LOCATION +}; + +var modelRatProperties = { + name: 'Hifi-Rat', + type: 'Model', + dimensions: RAT_DIMENSIONS, + position: RAT_SPAWNER_LOCATION, + shapeType: 'Box', + collisionsWillMove: true, + gravity: { + x: 0, + y: -9.8 + z: 0 + }, + //enable this if for some reason we want grabbable rats + // userData:JSON.stringify({ + // grabbableKey:{ + // grabbable:false + // } + // }) + +}; + +var targetProperties = { + name: 'Hifi-Rat-Nest', + type: 'Box', + color: { + red: 0, + green: 255, + blue: 0 + }, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + position: RAT_NEST_LOCATION + // script: Script.resolvePath('rat.js') +}; + +var target = Entities.addEntity(targetProperties) + +function addRat() { + var rat = Entities.addEntity(ratProperties); + rats.push(rat); +} + +var rats = []; +addRat(); + + +var FIRST_AVOIDER_START_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var FIRST_AVOIDER_FINISH_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var SECOND_AVOIDER_START_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var SECOND_AVOIDER_FINISH_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var THIRD_AVOIDER_START_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var THIRD_AVOIDER_FINISH_POSITION = { + x: 0, + y: 0, + z: 0 +}; + +var avoiders = [ + addAvoiderBlock(FIRST_AVOIDER_START_POSITION), + addAvoiderBlock(SECOND_AVOIDER_START_POSITION), + addAvoiderBlock(THIRD_AVOIDER_START_POSITION) +]; + +function addAvoiderBlock(position) { + + var avoiderProperties = { + name: 'Hifi-Rat-Avoider', + type: 'Box', + color: { + red: 255, + green: 0, + blue: 255 + }, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + position: { + x: 1, + y: 1, + z: 1 + }, + collisionsWillMove: false, + ignoreForCollisions: true + } + + var avoider = Entities.addEntity(avoiderProperties); + avoiders.push(avoider); +}; + +addAvoiderBlock(); +tweenAvoider(avoiders[0]); + +function tweenAvoider(entityID, startPosition, endPosition) { + var ANIMATION_DURATION = 500; + + var begin = { + x: startPosition.x, + y: startPosition.y, + z: startPosition.z + }; + + var target = endPosition; + + var original = startPosition; + + var tweenHead = new TWEEN.Tween(begin).to(target, ANIMATION_DURATION); + + function updateTo() { + Entities.editEntity(entityID, { + position: { + x: begin.x, + y: begin.y, + z: begin.z + } + }) + }; + + function updateBack() { + Entities.editEntity(entityID, { + position: { + x: begin.x, + y: begin.y, + z: begin.z + } + }) + }; + + var tweenBack = new TWEEN.Tween(begin).to(original, ANIMATION_DURATION).onUpdate(updateBack); + + tweenHead.onUpdate(function() { + updateTo() + }); + + tweenHead.chain(tweenBack); + tweenBack.chain(tweenHead); + tweenHead.start(); + +} + +function updateTweens() { + TWEEN.update(); +} + +function moveRats() { + rats.forEach(function(rat) { + // print('debug1') + + var avatarFlightVectors = steer.fleeAllAvatars(rat); + print('avatarFlightVectors' + avatarFlightVectors) + var i, j; + var averageAvatarFlight; + + for (i = 0; i < avatarFlightVectors.length; i++) { + if (i === 0) { + averageAvatarFlight = avatarFlightVectors[0]; + } else { + averageAvatarFlight = Vec3.sum(avatarFlightVectors[i - 1], avatarFlightVectors[i]) + } + } + + averageAvatarFlight = Vec3.normalize(averageAvatarFlight); + + averageAvatarFlight = Vec3.multiply(averageAvatarFlight, 1 / avatarFlightVectors.length); + + + var avoidBlockVectors = steer.fleeAvoiderBlocks(rat); + + var averageAvoiderFlight; + + for (j = 0; j < avoidBlockVectors.length; j++) { + if (j === 0) { + averageAvoiderFlight = avoidBlockVectors[0]; + } else { + averageAvoiderFlight = Vec3.sum(avoidBlockVectors[j - 1], avoidBlockVectors[j]) + } + }; + + avarageAvoiderFlight = Vec3.normalize(averageAvoiderFlight); + + averageAvoiderFlight = Vec3.multiply(averageAvoiderFlight, 1 / avoidBlockVectors.length); + + var averageVector; + var seek = steer.arrive(rat, target); + averageVector = seek; + var divisorCount = 1; + if (avatarFlightVectors.length > 0) { + divisorCount++; + averageVector = Vec3.sum(averageVector, averageAvatarFlight); + } + if (avoidBlockVectors > 0) { + divisorCount++; + averageVector = Vec3.sum(averageVector, averageAvoiderFlight); + } + + averageVector = Vec3.multiply(averageVector, 1 / divisorCount); + + Entities.editEntity(rat, { + velocity: averageVector + }) + + // castRay(rat); + + }) +} + +Script.update.connect(moveRats) +Script.update.connect(updateTweens); + +function checkDistanceFromNest(rat) { + var ratProps = Entitis.getEntityProperties(rat, "position"); + var distance = Vec3.distance(ratProps.position, RAT_NEST_LOCATION); + if (distance < RAT_IN_NEST_DISTANCE) { + removeRatFromScene(); + } +} + +function removeRatFromScene(rat) { + var index = rats.indexOf(rat); + if (index > -1) { + rats.splice(index, 1); + } + Entities.deleteEntity(rat); +} + + + +function cleanup() { + while (rats.length > 0) { + Entities.deleteEntity(rats.pop()); + } + + while (avoiders.length > 0) { + Entities.deleteEntity(avoiders.pop()); + } + + Entities.deleteEntity(target); + Script.update.disconnect(moveRats); + Script.update.disconnect(updateTweens); + Script.clearInterval(ratSpawnerInterval); +} + +Script.scriptEnding.connect(cleanup) + +var ratSpawnerInterval; + +if (USE_CONSTANT_SPAWNER === true) { + ratSpawnerInterval = Script.setInterval(function() { + addRat(); + }, RAT_SPAWN_RATE) +} + +//unused for now, to be used for some collision avoidance on walls and stuff? + +// function castRay(rat) { +// var ratProps = Entities.getEntityProperties(rat, ["position", "rotation"]); +// var shotDirection = Quat.getFront(ratProps.rotation); +// var pickRay = { +// origin: ratProps.position, +// direction: shotDirection +// }; + +// var intersection = Entities.findRayIntersection(pickRay, true); +// if (intersection.intersects) { +// var distance = Vec3.subtract(intersection.properties.position, ratProps.position); +// distance = Vec3.length(distance); +// // print('INTERSECTION:::'+distance); +// } else { +// //print('no intersection') +// } +// } \ No newline at end of file diff --git a/examples/libraries/steer.js b/examples/drylake/steer.js similarity index 93% rename from examples/libraries/steer.js rename to examples/drylake/steer.js index d7b1a8e295..b54d06b3e4 100644 --- a/examples/libraries/steer.js +++ b/examples/drylake/steer.js @@ -14,7 +14,7 @@ function seek(thisEntity, target) { var steerVector = new V3(desired.x, desired.y, desired.z); steer = steerVector.limit(MAX_FORCE) - return steer + return steer; } @@ -35,9 +35,9 @@ function flee(thisEntity, target) { var steer = Vec3.subtract(desired, velocity); var steerVector = new V3(desired.x, desired.y, desired.z); - steer = steerVector.limit(MAX_FORCE) + steer = steerVector.limit(MAX_FORCE); - return steer + return steer; } else { // print('target too far away to flee' + d); return @@ -59,7 +59,7 @@ function fleeAvatar(thisEntity, avatarPosition) { var steer = Vec3.subtract(desired, velocity); var steerVector = new V3(desired.x, desired.y, desired.z); - steer = steerVector.limit(MAX_FORCE) + steer = steerVector.limit(MAX_FORCE); return steer } else { // print('target too far away to flee' + d); @@ -69,13 +69,13 @@ function fleeAvatar(thisEntity, avatarPosition) { } function fleeAllAvatars(thisEntity) { - print('FLEE AVATARS') + print('FLEE AVATARS'); var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; var nearbyEntities = Entities.findEntities(location, 3); - var flightVectors = [] + var flightVectors = []; for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { var entityID = nearbyEntities[entityIndex]; var entityProps = Entities.getEntityProperties(entityID); @@ -97,8 +97,6 @@ function fleeAllAvatars(thisEntity) { } else { print('target too far away from this avatar to flee' + d); } - - } } @@ -107,26 +105,27 @@ function fleeAllAvatars(thisEntity) { } function fleeAvoiderBlocks(thisEntity) { + print('FLEE AVOIDER BLOCKS'); var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; - var nearbyEntities = Entities.findEntities(location, 2); - var flightVectors = [] + var nearbyEntities = Entities.findEntities(location, 3); + var flightVectors = []; for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { var entityID = nearbyEntities[entityIndex]; var entityProps = Entities.getEntityProperties(entityID); if (entityProps.name === 'Hifi-Rat-Avoider') { - print('found an avatar to flee') + print('found an avoiderblock to flee'); var MAX_SPEED = 2; - var MAX_FORCE = 2; + var MAX_FORCE = 0.8; var desired = Vec3.subtract(location, entityProps.position); var d = Vec3.length(desired); desired = Vec3.normalize(desired); desired = Vec3.multiply(MAX_SPEED, desired); - if (d < 2) { + if (d < 3) { var steer = Vec3.subtract(desired, velocity); var steerVector = new V3(desired.x, desired.y, desired.z); steer = steerVector.limit(MAX_FORCE) @@ -134,8 +133,6 @@ function fleeAvoiderBlocks(thisEntity) { } else { print('target too far away from this avoider to flee' + d); } - - } } @@ -153,7 +150,6 @@ function arrive(thisEntity, target) { var MAX_FORCE = 2; var ARRIVAL_DISTANCE = 3; - var desired = Vec3.subtract(targetPosition, location); var d = Vec3.length(desired); desired = Vec3.normalize(desired); @@ -211,7 +207,7 @@ loadSteer = function() { flee: flee, fleeAvatar: fleeAvatar, fleeAllAvatars: fleeAllAvatars, - // fleeAvoiderBlocks:fleeAvoiderBlocks, + fleeAvoiderBlocks:fleeAvoiderBlocks, arrive: arrive } } \ No newline at end of file diff --git a/examples/libraries/ratTest.js b/examples/libraries/ratTest.js index 80c861a1e9..c173de6f2b 100644 --- a/examples/libraries/ratTest.js +++ b/examples/libraries/ratTest.js @@ -1,8 +1,26 @@ -Script.include('steer.js') +Script.include('steer.js'); var steer = loadSteer(); Script.include('tween.js'); var TWEEN = loadTween(); +var RAT_NEST_LOCATION = { + x: 0, + y: 0, + z: 0 +}; + +var RAT_SPAWNER_LOCATION = { + x: 0, + y: 0, + z: 0 +}; + +var AVOIDER_BLOCK_START_LOCATION = { + x: 0, + y: 0, + z: 0 +}; + var ratProperties = { name: 'Hifi-Rat-Nest', type: 'Box', @@ -16,11 +34,7 @@ var ratProperties = { y: 1, z: 1 }, - position: { - x: 0, - y: 0, - z: 0 - } + position: RAT_SPAWNER_LOCATION }; var targetProperties = { @@ -36,11 +50,7 @@ var targetProperties = { y: 1, z: 1 }, - position: { - x: 5, - y: 0, - z: 0 - } + position: RAT_NEST_LOCATION // script: Script.resolvePath('rat.js') }; @@ -75,12 +85,16 @@ function addAvoiderBlock() { x: 1, y: 1, z: 1 - } + }, + collisionsWillMove:false, + ignoreForCollisions:true, + visible: true } var avoider = Entities.addEntity(avoiderProperties); avoiders.push(avoider) } + addAvoiderBlock(); tweenAvoider(avoiders[0]); From 08ca03e0af56c31f9ac16b25cd7adb07a7be6506 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 17 Nov 2015 11:33:48 -0800 Subject: [PATCH 004/174] ratssss --- examples/drylake/ratCreator.js | 196 ++++++++++++++++++--------------- examples/drylake/steer.js | 38 +++---- 2 files changed, 126 insertions(+), 108 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index c907183de4..63e88067d8 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -1,65 +1,70 @@ -Script.include('steer.js') +Script.include('steer.js'); var steer = loadSteer(); -Script.include('tween.js'); +Script.include('../libraries/tween.js'); var TWEEN = loadTween(); -var USE_CONSTANT_SPAWNER = false; +var USE_CONSTANT_SPAWNER = true; var RAT_SPAWNER_LOCATION = { - x: 0, - y: 0, - z: 0 + x: 1001, + y: 98.5, + z: 1039 }; var RAT_NEST_LOCATION = { - x: 0, - y: 0, - z: 0 + x: 1003.5, + y: 99, + z: 964.2 }; -var RAT_MODEL_URL = ''; -var RAT_RUNNING_ANIMATION_URL = ''; -var RAT_DEATH_ANIMATION_URL = ''; +var RAT_DIMENSIONS = { + x: 0.22, + y: 0.32, + z: 1.14 +}; -var RAT_IN_NEST_DISTANCE = 0.25; + +var RAT_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/ratrotated.fbx'; +var RAT_RUNNING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/walk.fbx'; +var RAT_DEATH_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/death.fbx'; + +var RAT_IN_NEST_DISTANCE = 3; //how many milliseconds between rats -var RAT_SPAWN_RATE = 1000; +var RAT_SPAWN_RATE = 2500; - -function playRatRunningAnimation() { +function playRatRunningAnimation(rat) { var animationSettings = JSON.stringify({ running: true }); Entities.editEntity(rat, { animationURL: RAT_RUNNING_ANIMATION_URL, - animationSettings: animationSettings, - // animation: { - // url: RAT_RUNNING_ANIMATION_URL, - // running: true, - // fps: 180 - // }, + animationSettings: animationSettings + // animation: { + // url: RAT_RUNNING_ANIMATION_URL, + // running: true, + // fps: 180 + // }, }); } -function playRatDeathAnimation() { +function playRatDeathAnimation(rat) { var animationSettings = JSON.stringify({ running: true }); Entities.editEntity(rat, { animationURL: RAT_DEATH_ANIMATION_URL, - animationSettings: animationSettings, - // animation: { - // url: RAT_DEATH_ANIMATION_URL, - // running: true, - // fps: 180 - // }, + animationSettings: animationSettings + // animation: { + // url: RAT_DEATH_ANIMATION_URL, + // running: true + // }, }); } var ratProperties = { - name: 'Hifi-Rat', + name: 'Rat', type: 'Box', color: { red: 0, @@ -71,21 +76,28 @@ var ratProperties = { y: 1, z: 1 }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, position: RAT_SPAWNER_LOCATION }; var modelRatProperties = { - name: 'Hifi-Rat', + name: 'rat', type: 'Model', + modelURL: RAT_MODEL_URL, dimensions: RAT_DIMENSIONS, position: RAT_SPAWNER_LOCATION, shapeType: 'Box', collisionsWillMove: true, gravity: { x: 0, - y: -9.8 + y: -9.8, z: 0 - }, + } //enable this if for some reason we want grabbable rats // userData:JSON.stringify({ // grabbableKey:{ @@ -112,56 +124,54 @@ var targetProperties = { // script: Script.resolvePath('rat.js') }; -var target = Entities.addEntity(targetProperties) +var target = Entities.addEntity(targetProperties); function addRat() { - var rat = Entities.addEntity(ratProperties); + var rat = Entities.addEntity(modelRatProperties); rats.push(rat); } var rats = []; addRat(); - +var AVOIDER_Y_HEIGHT = 99; var FIRST_AVOIDER_START_POSITION = { - x: 0, - y: 0, - z: 0 + x: 1004, + y: AVOIDER_Y_HEIGHT, + z: 1019 }; var FIRST_AVOIDER_FINISH_POSITION = { - x: 0, - y: 0, - z: 0 + x: 997, + y: AVOIDER_Y_HEIGHT, + z: 1019 }; var SECOND_AVOIDER_START_POSITION = { - x: 0, - y: 0, - z: 0 + x: 998, + y: AVOIDER_Y_HEIGHT, + z: 998 }; var SECOND_AVOIDER_FINISH_POSITION = { - x: 0, - y: 0, - z: 0 + x: 1005, + y: AVOIDER_Y_HEIGHT, + z: 999 }; var THIRD_AVOIDER_START_POSITION = { - x: 0, - y: 0, - z: 0 + x: 1001.5, + y: 100, + z: 978 }; var THIRD_AVOIDER_FINISH_POSITION = { - x: 0, - y: 0, - z: 0 + x: 1005, + y: 100, + z: 974 }; -var avoiders = [ - addAvoiderBlock(FIRST_AVOIDER_START_POSITION), - addAvoiderBlock(SECOND_AVOIDER_START_POSITION), - addAvoiderBlock(THIRD_AVOIDER_START_POSITION) -]; +var avoiders = []; +addAvoiderBlock(FIRST_AVOIDER_START_POSITION); +addAvoiderBlock(SECOND_AVOIDER_START_POSITION); +addAvoiderBlock(THIRD_AVOIDER_START_POSITION); function addAvoiderBlock(position) { - var avoiderProperties = { name: 'Hifi-Rat-Avoider', type: 'Box', @@ -175,24 +185,23 @@ function addAvoiderBlock(position) { y: 1, z: 1 }, - position: { - x: 1, - y: 1, - z: 1 - }, + position: position, collisionsWillMove: false, - ignoreForCollisions: true - } + ignoreForCollisions: true, + visible:false + }; var avoider = Entities.addEntity(avoiderProperties); avoiders.push(avoider); -}; +} -addAvoiderBlock(); -tweenAvoider(avoiders[0]); + +tweenAvoider(avoiders[0], FIRST_AVOIDER_START_POSITION, FIRST_AVOIDER_FINISH_POSITION); +tweenAvoider(avoiders[1], SECOND_AVOIDER_START_POSITION, SECOND_AVOIDER_FINISH_POSITION); +tweenAvoider(avoiders[2], THIRD_AVOIDER_START_POSITION, THIRD_AVOIDER_FINISH_POSITION); function tweenAvoider(entityID, startPosition, endPosition) { - var ANIMATION_DURATION = 500; + var ANIMATION_DURATION = 4200; var begin = { x: startPosition.x, @@ -200,11 +209,11 @@ function tweenAvoider(entityID, startPosition, endPosition) { z: startPosition.z }; - var target = endPosition; + var end = endPosition; var original = startPosition; - var tweenHead = new TWEEN.Tween(begin).to(target, ANIMATION_DURATION); + var tweenHead = new TWEEN.Tween(begin).to(end, ANIMATION_DURATION); function updateTo() { Entities.editEntity(entityID, { @@ -213,8 +222,8 @@ function tweenAvoider(entityID, startPosition, endPosition) { y: begin.y, z: begin.z } - }) - }; + }); + } function updateBack() { Entities.editEntity(entityID, { @@ -224,7 +233,7 @@ function tweenAvoider(entityID, startPosition, endPosition) { z: begin.z } }) - }; + } var tweenBack = new TWEEN.Tween(begin).to(original, ANIMATION_DURATION).onUpdate(updateBack); @@ -244,10 +253,10 @@ function updateTweens() { function moveRats() { rats.forEach(function(rat) { + checkDistanceFromNest(rat); // print('debug1') - var avatarFlightVectors = steer.fleeAllAvatars(rat); - print('avatarFlightVectors' + avatarFlightVectors) + // print('avatarFlightVectors' + avatarFlightVectors) var i, j; var averageAvatarFlight; @@ -259,7 +268,7 @@ function moveRats() { } } - averageAvatarFlight = Vec3.normalize(averageAvatarFlight); + // averageAvatarFlight = Vec3.normalize(averageAvatarFlight); averageAvatarFlight = Vec3.multiply(averageAvatarFlight, 1 / avatarFlightVectors.length); @@ -276,7 +285,7 @@ function moveRats() { } }; - avarageAvoiderFlight = Vec3.normalize(averageAvoiderFlight); + // avarageAvoiderFlight = Vec3.normalize(averageAvoiderFlight); averageAvoiderFlight = Vec3.multiply(averageAvoiderFlight, 1 / avoidBlockVectors.length); @@ -288,19 +297,24 @@ function moveRats() { divisorCount++; averageVector = Vec3.sum(averageVector, averageAvatarFlight); } - if (avoidBlockVectors > 0) { + if (avoidBlockVectors.length > 0) { divisorCount++; averageVector = Vec3.sum(averageVector, averageAvoiderFlight); } averageVector = Vec3.multiply(averageVector, 1 / divisorCount); + var thisRatProps = Entities.getEntityProperties(rat, ["position", "rotation"]); + var ratPosition = thisRatProps.position; + var ratToNest = Vec3.subtract(RAT_NEST_LOCATION, ratPosition); + var ratRotation = Quat.rotationBetween(Vec3.FRONT, ratToNest); Entities.editEntity(rat, { - velocity: averageVector + velocity: averageVector, + rotation: ratRotation, + //rotation: Quat.fromPitchYawRollDegrees(0,0,0) }) // castRay(rat); - }) } @@ -308,10 +322,14 @@ Script.update.connect(moveRats) Script.update.connect(updateTweens); function checkDistanceFromNest(rat) { - var ratProps = Entitis.getEntityProperties(rat, "position"); + var ratProps = Entities.getEntityProperties(rat, "position"); var distance = Vec3.distance(ratProps.position, RAT_NEST_LOCATION); if (distance < RAT_IN_NEST_DISTANCE) { - removeRatFromScene(); + //print('at nest') + removeRatFromScene(rat); + } else { + // print('not yet at nest:::' + distance) + } } @@ -323,8 +341,6 @@ function removeRatFromScene(rat) { Entities.deleteEntity(rat); } - - function cleanup() { while (rats.length > 0) { Entities.deleteEntity(rats.pop()); @@ -340,14 +356,16 @@ function cleanup() { Script.clearInterval(ratSpawnerInterval); } -Script.scriptEnding.connect(cleanup) +Script.scriptEnding.connect(cleanup); var ratSpawnerInterval; if (USE_CONSTANT_SPAWNER === true) { ratSpawnerInterval = Script.setInterval(function() { addRat(); - }, RAT_SPAWN_RATE) + // playRatRunningAnimation(rat); + rats.push(rat); + }, RAT_SPAWN_RATE); } //unused for now, to be used for some collision avoidance on walls and stuff? diff --git a/examples/drylake/steer.js b/examples/drylake/steer.js index b54d06b3e4..c55aed33ec 100644 --- a/examples/drylake/steer.js +++ b/examples/drylake/steer.js @@ -3,8 +3,8 @@ function seek(thisEntity, target) { var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; - var MAX_SPEED = 1; - var MAX_FORCE = 1; + var MAX_SPEED = 30; + var MAX_FORCE = 20; var desired = Vec3.subtract(targetPosition, location); desired = Vec3.normalize(desired); @@ -48,8 +48,8 @@ function fleeAvatar(thisEntity, avatarPosition) { var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; - var MAX_SPEED = 2; - var MAX_FORCE = 2; + var MAX_SPEED = 3; + var MAX_FORCE = 10; var desired = Vec3.subtract(location, avatarPosition); var d = Vec3.length(desired); @@ -69,7 +69,7 @@ function fleeAvatar(thisEntity, avatarPosition) { } function fleeAllAvatars(thisEntity) { - print('FLEE AVATARS'); + //print('FLEE AVATARS'); var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; @@ -80,10 +80,10 @@ function fleeAllAvatars(thisEntity) { var entityID = nearbyEntities[entityIndex]; var entityProps = Entities.getEntityProperties(entityID); if (entityProps.name === 'Hifi-Avatar-Detector') { - print('found an avatar to flee') + //print('found an avatar to flee') - var MAX_SPEED = 2; - var MAX_FORCE = 2; + var MAX_SPEED = 8; + var MAX_FORCE = 8; var desired = Vec3.subtract(location, entityProps.position); var d = Vec3.length(desired); @@ -95,7 +95,7 @@ function fleeAllAvatars(thisEntity) { steer = steerVector.limit(MAX_FORCE) flightVectors.push(steer) } else { - print('target too far away from this avatar to flee' + d); + // print('target too far away from this avatar to flee' + d); } } @@ -105,33 +105,33 @@ function fleeAllAvatars(thisEntity) { } function fleeAvoiderBlocks(thisEntity) { - print('FLEE AVOIDER BLOCKS'); + // print('FLEE AVOIDER BLOCKS'); var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; - var nearbyEntities = Entities.findEntities(location, 3); + var nearbyEntities = Entities.findEntities(location, 4); var flightVectors = []; for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { var entityID = nearbyEntities[entityIndex]; var entityProps = Entities.getEntityProperties(entityID); if (entityProps.name === 'Hifi-Rat-Avoider') { - print('found an avoiderblock to flee'); + // print('found an avoiderblock to flee'); - var MAX_SPEED = 2; - var MAX_FORCE = 0.8; + var MAX_SPEED = 8; + var MAX_FORCE = 6; var desired = Vec3.subtract(location, entityProps.position); var d = Vec3.length(desired); desired = Vec3.normalize(desired); desired = Vec3.multiply(MAX_SPEED, desired); - if (d < 3) { + if (d < 5) { var steer = Vec3.subtract(desired, velocity); var steerVector = new V3(desired.x, desired.y, desired.z); steer = steerVector.limit(MAX_FORCE) - flightVectors.push(steer) + flightVectors.push(steer); } else { - print('target too far away from this avoider to flee' + d); + //print('target too far away from this avoider to flee' + d); } } @@ -146,8 +146,8 @@ function arrive(thisEntity, target) { var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; - var MAX_SPEED = 3; - var MAX_FORCE = 2; + var MAX_SPEED = 16; + var MAX_FORCE = 12; var ARRIVAL_DISTANCE = 3; var desired = Vec3.subtract(targetPosition, location); From bb7328e47671bda1bad6b519f4af771fcde8c045 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 17 Nov 2015 11:35:16 -0800 Subject: [PATCH 005/174] hide nest --- examples/drylake/ratCreator.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 63e88067d8..0f369d4c0d 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -120,6 +120,7 @@ var targetProperties = { y: 1, z: 1 }, + visible:false, position: RAT_NEST_LOCATION // script: Script.resolvePath('rat.js') }; From 3d2dc5a7a2bcc75ff7ea968eb408bf1e7817e7f9 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 17 Nov 2015 13:24:34 -0800 Subject: [PATCH 006/174] slower rats, pop from stack --- examples/drylake/ratCreator.js | 17 +++++++++++++---- examples/drylake/steer.js | 4 ++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 0f369d4c0d..575653581d 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -23,7 +23,6 @@ var RAT_DIMENSIONS = { z: 1.14 }; - var RAT_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/ratrotated.fbx'; var RAT_RUNNING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/walk.fbx'; var RAT_DEATH_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/death.fbx'; @@ -120,7 +119,7 @@ var targetProperties = { y: 1, z: 1 }, - visible:false, + visible: false, position: RAT_NEST_LOCATION // script: Script.resolvePath('rat.js') }; @@ -189,7 +188,7 @@ function addAvoiderBlock(position) { position: position, collisionsWillMove: false, ignoreForCollisions: true, - visible:false + visible: false }; var avoider = Entities.addEntity(avoiderProperties); @@ -342,6 +341,15 @@ function removeRatFromScene(rat) { Entities.deleteEntity(rat); } +function popRatFromStack(entityID) { + var index = rats.indexOf(entityID); + if (index > -1) { + rats.splice(index, 1); + } +} + +Entities.deletingEntity.connect(popRatFromStack); + function cleanup() { while (rats.length > 0) { Entities.deleteEntity(rats.pop()); @@ -354,6 +362,7 @@ function cleanup() { Entities.deleteEntity(target); Script.update.disconnect(moveRats); Script.update.disconnect(updateTweens); + Entities.deletingEntity.disconnect(popRatFromStack); Script.clearInterval(ratSpawnerInterval); } @@ -364,7 +373,7 @@ var ratSpawnerInterval; if (USE_CONSTANT_SPAWNER === true) { ratSpawnerInterval = Script.setInterval(function() { addRat(); - // playRatRunningAnimation(rat); + playRatRunningAnimation(rat); rats.push(rat); }, RAT_SPAWN_RATE); } diff --git a/examples/drylake/steer.js b/examples/drylake/steer.js index c55aed33ec..40dc9b3ebd 100644 --- a/examples/drylake/steer.js +++ b/examples/drylake/steer.js @@ -146,8 +146,8 @@ function arrive(thisEntity, target) { var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; - var MAX_SPEED = 16; - var MAX_FORCE = 12; + var MAX_SPEED = 12; + var MAX_FORCE = 8; var ARRIVAL_DISTANCE = 3; var desired = Vec3.subtract(targetPosition, location); From e375a959476d5905f6a8866b021c9594da88c46a Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 17 Nov 2015 16:24:14 -0800 Subject: [PATCH 007/174] remove unused methods from steering --- examples/drylake/steer.js | 46 --------------------------------------- 1 file changed, 46 deletions(-) diff --git a/examples/drylake/steer.js b/examples/drylake/steer.js index 40dc9b3ebd..3c4a21091c 100644 --- a/examples/drylake/steer.js +++ b/examples/drylake/steer.js @@ -1,23 +1,3 @@ -function seek(thisEntity, target) { - var targetPosition = Entities.getEntityProperties(target, "position").position; - var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); - var location = properties.position; - var velocity = properties.velocity; - var MAX_SPEED = 30; - var MAX_FORCE = 20; - - var desired = Vec3.subtract(targetPosition, location); - desired = Vec3.normalize(desired); - desired = Vec3.multiply(MAX_SPEED, desired); - - var steer = Vec3.subtract(desired, velocity); - var steerVector = new V3(desired.x, desired.y, desired.z); - steer = steerVector.limit(MAX_FORCE) - - return steer; - -} - function flee(thisEntity, target) { var targetPosition = Entities.getEntityProperties(target, "position").position; var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); @@ -44,30 +24,6 @@ function flee(thisEntity, target) { } } -function fleeAvatar(thisEntity, avatarPosition) { - var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); - var location = properties.position; - var velocity = properties.velocity; - var MAX_SPEED = 3; - var MAX_FORCE = 10; - - var desired = Vec3.subtract(location, avatarPosition); - var d = Vec3.length(desired); - desired = Vec3.normalize(desired); - desired = Vec3.multiply(MAX_SPEED, desired); - if (d < 3) { - var steer = Vec3.subtract(desired, velocity); - - var steerVector = new V3(desired.x, desired.y, desired.z); - steer = steerVector.limit(MAX_FORCE); - return steer - } else { - // print('target too far away to flee' + d); - return - } - -} - function fleeAllAvatars(thisEntity) { //print('FLEE AVATARS'); var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); @@ -203,9 +159,7 @@ var scale = function(value, min1, max1, min2, max2) { loadSteer = function() { return { - seek: seek, flee: flee, - fleeAvatar: fleeAvatar, fleeAllAvatars: fleeAllAvatars, fleeAvoiderBlocks:fleeAvoiderBlocks, arrive: arrive From 7b70562a1b68ca2fb0d858dc282bdd81f6059145 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 15:51:43 -0800 Subject: [PATCH 008/174] update RenderableModelEntityItem::_model during simulate rather than during render --- .../src/RenderableModelEntityItem.cpp | 91 ++++++++++--------- .../src/RenderableModelEntityItem.h | 1 + libraries/entities/src/EntityItem.h | 2 +- 3 files changed, 49 insertions(+), 45 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f1be8611e1..bbc230ec1d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -210,6 +210,53 @@ void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::sha } } +void RenderableModelEntityItem::simulate(const quint64& now) { + EntityItem::simulate(now); + + if (_model) { + // handle animations.. + if (hasAnimation()) { + if (!jointsMapped()) { + QStringList modelJointNames = _model->getJointNames(); + mapJoints(modelJointNames); + } + + if (jointsMapped()) { + bool newFrame; + QVector frameDataRotations; + QVector frameDataTranslations; + getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); + assert(frameDataRotations.size() == frameDataTranslations.size()); + if (newFrame) { + for (int i = 0; i < frameDataRotations.size(); i++) { + _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); + } + } + } + } + + bool movingOrAnimating = isMoving() || isAnimatingSomething(); + if ((movingOrAnimating || + _needsInitialSimulation || + _model->getTranslation() != getPosition() || + _model->getRotation() != getRotation() || + _model->getRegistrationPoint() != getRegistrationPoint()) + && _model->isActive() && _dimensionsInitialized) { + _model->setScaleToFit(true, getDimensions()); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + + // make sure to simulate so everything gets set up correctly for rendering + { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + + _needsInitialSimulation = false; + } + } +} // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items, and it handles // the per frame simulation/update that might be required if the models properties changed. @@ -259,50 +306,6 @@ void RenderableModelEntityItem::render(RenderArgs* args) { EntityTreeRenderer* renderer = static_cast(args->_renderer); getModel(renderer); } - - if (_model) { - // handle animations.. - if (hasAnimation()) { - if (!jointsMapped()) { - QStringList modelJointNames = _model->getJointNames(); - mapJoints(modelJointNames); - } - - if (jointsMapped()) { - bool newFrame; - QVector frameDataRotations; - QVector frameDataTranslations; - getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); - assert(frameDataRotations.size() == frameDataTranslations.size()); - if (newFrame) { - for (int i = 0; i < frameDataRotations.size(); i++) { - _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); - } - } - } - } - - bool movingOrAnimating = isMoving() || isAnimatingSomething(); - if ((movingOrAnimating || - _needsInitialSimulation || - _model->getTranslation() != getPosition() || - _model->getRotation() != getRotation() || - _model->getRegistrationPoint() != getRegistrationPoint()) - && _model->isActive() && _dimensionsInitialized) { - _model->setScaleToFit(true, getDimensions()); - _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); - - // make sure to simulate so everything gets set up correctly for rendering - { - PerformanceTimer perfTimer("_model->simulate"); - _model->simulate(0.0f); - } - - _needsInitialSimulation = false; - } - } } } else { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index c4e36c240a..3d7ca73624 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -47,6 +47,7 @@ public: virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual void simulate(const quint64& now); virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5ceccef4b1..6514c955e8 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -183,7 +183,7 @@ public: quint64 getLastUpdated() const { return _lastUpdated; } // perform linear extrapolation for SimpleEntitySimulation - void simulate(const quint64& now); + virtual void simulate(const quint64& now); void simulateKinematicMotion(float timeElapsed, bool setFlags=true); virtual bool needsToCallUpdate() const { return false; } From 89e5b11f9eea009336b5795d9978a61ec5b7b3bc Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 16:17:22 -0800 Subject: [PATCH 009/174] do this from update rather than simulate --- .../src/RenderableModelEntityItem.cpp | 96 +++++++++---------- .../src/RenderableModelEntityItem.h | 2 - libraries/entities/src/EntityItem.h | 2 +- 3 files changed, 47 insertions(+), 53 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index bbc230ec1d..6985d1a617 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -210,54 +210,6 @@ void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::sha } } -void RenderableModelEntityItem::simulate(const quint64& now) { - EntityItem::simulate(now); - - if (_model) { - // handle animations.. - if (hasAnimation()) { - if (!jointsMapped()) { - QStringList modelJointNames = _model->getJointNames(); - mapJoints(modelJointNames); - } - - if (jointsMapped()) { - bool newFrame; - QVector frameDataRotations; - QVector frameDataTranslations; - getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); - assert(frameDataRotations.size() == frameDataTranslations.size()); - if (newFrame) { - for (int i = 0; i < frameDataRotations.size(); i++) { - _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); - } - } - } - } - - bool movingOrAnimating = isMoving() || isAnimatingSomething(); - if ((movingOrAnimating || - _needsInitialSimulation || - _model->getTranslation() != getPosition() || - _model->getRotation() != getRotation() || - _model->getRegistrationPoint() != getRegistrationPoint()) - && _model->isActive() && _dimensionsInitialized) { - _model->setScaleToFit(true, getDimensions()); - _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); - - // make sure to simulate so everything gets set up correctly for rendering - { - PerformanceTimer perfTimer("_model->simulate"); - _model->simulate(0.0f); - } - - _needsInitialSimulation = false; - } - } -} - // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items, and it handles // the per frame simulation/update that might be required if the models properties changed. void RenderableModelEntityItem::render(RenderArgs* args) { @@ -369,14 +321,58 @@ 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)); } - + + if (_model) { + // handle animations.. + if (hasAnimation()) { + if (!jointsMapped()) { + QStringList modelJointNames = _model->getJointNames(); + mapJoints(modelJointNames); + } + + if (jointsMapped()) { + bool newFrame; + QVector frameDataRotations; + QVector frameDataTranslations; + getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); + assert(frameDataRotations.size() == frameDataTranslations.size()); + if (newFrame) { + for (int i = 0; i < frameDataRotations.size(); i++) { + _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); + } + } + } + } + + bool movingOrAnimating = isMoving() || isAnimatingSomething(); + if ((movingOrAnimating || + _needsInitialSimulation || + _model->getTranslation() != getPosition() || + _model->getRotation() != getRotation() || + _model->getRegistrationPoint() != getRegistrationPoint()) + && _model->isActive() && _dimensionsInitialized) { + _model->setScaleToFit(true, getDimensions()); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + + // make sure to simulate so everything gets set up correctly for rendering + { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + + _needsInitialSimulation = false; + } + } + ModelEntityItem::update(now); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 3d7ca73624..6c5bfc4423 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -47,8 +47,6 @@ public: virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); - virtual void simulate(const quint64& now); - virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 6514c955e8..5ceccef4b1 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -183,7 +183,7 @@ public: quint64 getLastUpdated() const { return _lastUpdated; } // perform linear extrapolation for SimpleEntitySimulation - virtual void simulate(const quint64& now); + void simulate(const quint64& now); void simulateKinematicMotion(float timeElapsed, bool setFlags=true); virtual bool needsToCallUpdate() const { return false; } From 283ad7ffd938a858510f815bb4442e13e89ef0ff Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 16:39:19 -0800 Subject: [PATCH 010/174] try, try again --- .../src/RenderableModelEntityItem.cpp | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 6985d1a617..3d9a336e83 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -313,7 +313,27 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } bool RenderableModelEntityItem::needsToCallUpdate() const { - return !_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate(); + if (EntityItem::needsToCallUpdate()) { + return true; + } + // these if statements match the structure of those in RenderableModelEntityItem::update + if (!_dimensionsInitialized && _model && _model->isActive()) { + return true; + } + if (_model) { + if (hasAnimation()) { + return true; + } + bool movingOrAnimating = isMoving() || isAnimatingSomething(); + if ((movingOrAnimating || + _needsInitialSimulation || + _model->getTranslation() != getPosition() || + _model->getRotation() != getRotation() || + _model->getRegistrationPoint() != getRegistrationPoint()) + && _model->isActive() && _dimensionsInitialized) { + return true; + } + } } void RenderableModelEntityItem::update(const quint64& now) { From cfcff42004cd134224bbd46ff49dcf35c07a7b63 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 16:41:16 -0800 Subject: [PATCH 011/174] missed a line --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3d9a336e83..31d3e3ca78 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -334,6 +334,8 @@ bool RenderableModelEntityItem::needsToCallUpdate() const { return true; } } + + return false; } void RenderableModelEntityItem::update(const quint64& now) { From 5cd047da15cfdc65d4e2a23700a0f3ed99ebd5b0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 16:49:36 -0800 Subject: [PATCH 012/174] move some more code over --- .../src/RenderableModelEntityItem.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 31d3e3ca78..2fedc02a2f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -247,18 +247,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { _model->setVisibleInScene(getVisible(), scene); } - remapTextures(); - { - // float alpha = getLocalRenderAlpha(); - - if (!_model || _needsModelReload) { - // TODO: this getModel() appears to be about 3% of model render time. We should optimize - PerformanceTimer perfTimer("getModel"); - EntityTreeRenderer* renderer = static_cast(args->_renderer); - getModel(renderer); - } - } } else { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); gpu::Batch& batch = *args->_batch; @@ -317,6 +306,11 @@ bool RenderableModelEntityItem::needsToCallUpdate() const { return true; } // these if statements match the structure of those in RenderableModelEntityItem::update + if (hasModel() && _myRenderer) { + if (!_model || _needsModelReload) { + return true; + } + } if (!_dimensionsInitialized && _model && _model->isActive()) { return true; } @@ -351,6 +345,12 @@ void RenderableModelEntityItem::update(const quint64& now) { Q_ARG(EntityItemProperties, properties)); } + if (!_model || _needsModelReload) { + // TODO: this getModel() appears to be about 3% of model render time. We should optimize + PerformanceTimer perfTimer("getModel"); + getModel(_myRenderer); + } + if (_model) { // handle animations.. if (hasAnimation()) { From 09f14bc9a56bc7bb54c2c24a773058b9beed7ab0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 16:51:17 -0800 Subject: [PATCH 013/174] guard against nullptr deferenece --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 2fedc02a2f..ade96901dc 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -345,7 +345,7 @@ void RenderableModelEntityItem::update(const quint64& now) { Q_ARG(EntityItemProperties, properties)); } - if (!_model || _needsModelReload) { + if (_myRenderer && (!_model || _needsModelReload)) { // TODO: this getModel() appears to be about 3% of model render time. We should optimize PerformanceTimer perfTimer("getModel"); getModel(_myRenderer); From 2ff4e87a933e775331f109ebac842495f84eed15 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 23 Nov 2015 18:28:57 -0800 Subject: [PATCH 014/174] add animation urls to rat --- examples/drylake/ratCreator.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 575653581d..bc7b6cf9a2 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -23,9 +23,11 @@ var RAT_DIMENSIONS = { z: 1.14 }; -var RAT_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/ratrotated.fbx'; -var RAT_RUNNING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/walk.fbx'; -var RAT_DEATH_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/death.fbx'; +var RAT_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/models/rat_model.fbx'; +var RAT_IDLE_ANIMATION_URL ='http://hifi-content.s3.amazonaws.com/james/rat/animations/idle.fbx'; +var RAT_WALKING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/walk.fbx'; +var RAT_RUNNING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/run.fbx'; +var RAT_DEATH_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/death.fbx'; var RAT_IN_NEST_DISTANCE = 3; From 9320623ff5f3bfe1d1a61220028bc3762c8fc474 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 12 Nov 2015 18:07:23 -0800 Subject: [PATCH 015/174] Add AABox functionalities --- libraries/shared/src/AABox.cpp | 45 +++++++++++++++++++++++++++++++--- libraries/shared/src/AABox.h | 7 +++++- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index b514e171eb..7c001c570e 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -42,9 +42,48 @@ glm::vec3 AABox::calcCenter() const { return center; } -void AABox::scale(float scale) { - _corner = _corner * scale; - _scale = _scale * scale; +void AABox::rotate(const glm::quat& rotation) { + auto minimum = _corner; + auto maximum = _corner + _scale; + + glm::vec3 bottomLeftNear(minimum.x, minimum.y, minimum.z); + glm::vec3 bottomRightNear(maximum.x, minimum.y, minimum.z); + glm::vec3 bottomLeftFar(minimum.x, minimum.y, maximum.z); + glm::vec3 bottomRightFar(maximum.x, minimum.y, maximum.z); + glm::vec3 topLeftNear(minimum.x, maximum.y, minimum.z); + glm::vec3 topRightNear(maximum.x, maximum.y, minimum.z); + glm::vec3 topLeftFar(minimum.x, maximum.y, maximum.z); + glm::vec3 topRightFar(maximum.x, maximum.y, maximum.z); + + glm::vec3 bottomLeftNearRotated = rotation * bottomLeftNear; + glm::vec3 bottomRightNearRotated = rotation * bottomRightNear; + glm::vec3 bottomLeftFarRotated = rotation * bottomLeftFar; + glm::vec3 bottomRightFarRotated = rotation * bottomRightFar; + glm::vec3 topLeftNearRotated = rotation * topLeftNear; + glm::vec3 topRightNearRotated = rotation * topRightNear; + glm::vec3 topLeftFarRotated = rotation * topLeftFar; + glm::vec3 topRightFarRotated = rotation * topRightFar; + + minimum = glm::min(bottomLeftNearRotated, + glm::min(bottomRightNearRotated, + glm::min(bottomLeftFarRotated, + glm::min(bottomRightFarRotated, + glm::min(topLeftNearRotated, + glm::min(topRightNearRotated, + glm::min(topLeftFarRotated, + topRightFarRotated))))))); + + maximum = glm::max(bottomLeftNearRotated, + glm::max(bottomRightNearRotated, + glm::max(bottomLeftFarRotated, + glm::max(bottomRightFarRotated, + glm::max(topLeftNearRotated, + glm::max(topRightNearRotated, + glm::max(topLeftFarRotated, + topRightFarRotated))))))); + + _corner = minimum; + _scale = maximum - minimum; } glm::vec3 AABox::getVertex(BoxVertex vertex) const { diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index 1f5923dbd8..e5227ade44 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -40,7 +40,12 @@ public: void setBox(const glm::vec3& corner, float scale); glm::vec3 getVertexP(const glm::vec3& normal) const; glm::vec3 getVertexN(const glm::vec3& normal) const; - void scale(float scale); + + void shiftBy(const glm::vec3& delta) { _corner += delta; } + void rotate(const glm::quat& rotation); + void scale(float scale) { _corner *= scale; _scale *= scale; } + void scale(const glm::vec3& scale) { _corner *= scale; _scale *= scale; } + const glm::vec3& getCorner() const { return _corner; } const glm::vec3& getScale() const { return _scale; } const glm::vec3& getDimensions() const { return _scale; } From a71ed7b16657601a8f97bf97a4914b076a7f6fcf Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 12 Nov 2015 18:23:09 -0800 Subject: [PATCH 016/174] Implement particle bounds with Extents --- .../RenderableParticleEffectEntityItem.cpp | 40 +++++-------------- .../entities/src/ParticleEffectEntityItem.cpp | 19 ++------- .../entities/src/ParticleEffectEntityItem.h | 6 +-- 3 files changed, 15 insertions(+), 50 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 05fca343fd..ebe87dec9b 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -272,37 +272,17 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { } // update transform - glm::quat rot = getRotation(); - glm::vec3 pos = getPosition(); - Transform t; - t.setRotation(rot); - payload.setModelTransform(t); + glm::vec3 position = getPosition(); + glm::quat rotation = getRotation(); + Transform transform; + transform.setTranslation(position); + transform.setRotation(rotation); + payload.setModelTransform(transform); - // transform _particleMinBound and _particleMaxBound corners into world coords - glm::vec3 d = _particleMaxBound - _particleMinBound; - const size_t NUM_BOX_CORNERS = 8; - glm::vec3 corners[NUM_BOX_CORNERS] = { - pos + rot * (_particleMinBound + glm::vec3(0.0f, 0.0f, 0.0f)), - pos + rot * (_particleMinBound + glm::vec3(d.x, 0.0f, 0.0f)), - pos + rot * (_particleMinBound + glm::vec3(0.0f, d.y, 0.0f)), - pos + rot * (_particleMinBound + glm::vec3(d.x, d.y, 0.0f)), - pos + rot * (_particleMinBound + glm::vec3(0.0f, 0.0f, d.z)), - pos + rot * (_particleMinBound + glm::vec3(d.x, 0.0f, d.z)), - pos + rot * (_particleMinBound + glm::vec3(0.0f, d.y, d.z)), - pos + rot * (_particleMinBound + glm::vec3(d.x, d.y, d.z)) - }; - glm::vec3 min(FLT_MAX, FLT_MAX, FLT_MAX); - glm::vec3 max = -min; - for (size_t i = 0; i < NUM_BOX_CORNERS; i++) { - min.x = std::min(min.x, corners[i].x); - min.y = std::min(min.y, corners[i].y); - min.z = std::min(min.z, corners[i].z); - max.x = std::max(max.x, corners[i].x); - max.y = std::max(max.y, corners[i].y); - max.z = std::max(max.z, corners[i].z); - } - AABox bound(min, max - min); - payload.setBound(bound); + AABox bounds(_particlesBounds); + bounds.rotate(rotation); + bounds.shiftBy(position); + payload.setBound(bounds); bool textured = _texture && _texture->isLoaded(); if (textured) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 06fcdb495c..f3abeffc20 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -121,8 +121,6 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte _alphaStarts(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), _alphaMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), _alphaFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), - _particleMaxBound(glm::vec3(1.0f, 1.0f, 1.0f)), - _particleMinBound(glm::vec3(-1.0f, -1.0f, -1.0f)) , _additiveBlending(DEFAULT_ADDITIVE_BLENDING) { @@ -631,15 +629,6 @@ void ParticleEffectEntityItem::updateAlpha(quint32 index, float age) { _alphaFinishes[index], age); } -void ParticleEffectEntityItem::extendBounds(const glm::vec3& point) { - _particleMinBound.x = glm::min(_particleMinBound.x, point.x); - _particleMinBound.y = glm::min(_particleMinBound.y, point.y); - _particleMinBound.z = glm::min(_particleMinBound.z, point.z); - _particleMaxBound.x = glm::max(_particleMaxBound.x, point.x); - _particleMaxBound.y = glm::max(_particleMaxBound.y, point.y); - _particleMaxBound.z = glm::max(_particleMaxBound.z, point.z); -} - void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) { glm::vec3 accel = _particleAccelerations[index]; glm::vec3 atSquared = (0.5f * deltaTime * deltaTime) * accel; @@ -649,9 +638,7 @@ void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) } void ParticleEffectEntityItem::stepSimulation(float deltaTime) { - - _particleMinBound = glm::vec3(-1.0f, -1.0f, -1.0f); - _particleMaxBound = glm::vec3(1.0f, 1.0f, 1.0f); + _particlesBounds.reset(); // update particles between head and tail for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) { @@ -667,7 +654,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { updateColor(i, age); updateAlpha(i, age); integrateParticle(i, deltaTime); - extendBounds(_particlePositions[i]); + _particlesBounds.addPoint(_particlePositions[i]); } } @@ -766,7 +753,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particleAccelerations[i] = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } integrateParticle(i, timeLeftInFrame); - extendBounds(_particlePositions[i]); + _particlesBounds.addPoint(_particlePositions[i]); // Color if (_colorSpread == xColor{ 0, 0, 0 }) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index e3c5cd895a..7ac115d8e5 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -224,7 +224,6 @@ protected: void updateRadius(quint32 index, float age); void updateColor(quint32 index, float age); void updateAlpha(quint32 index, float age); - void extendBounds(const glm::vec3& point); void integrateParticle(quint32 index, float deltaTime); quint32 getLivingParticleCount() const; // the properties of this entity @@ -289,9 +288,8 @@ protected: quint32 _particleTailIndex = 0; // bounding volume - glm::vec3 _particleMaxBound; - glm::vec3 _particleMinBound; - + Extents _particlesBounds; + bool _additiveBlending; }; From 395822c6cdeb8bc6c7a2c36a4ce342d6e52ffc96 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Nov 2015 11:47:33 -0800 Subject: [PATCH 017/174] Use make_shared --- .../src/RenderableParticleEffectEntityItem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index ebe87dec9b..f4243db621 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -134,11 +134,11 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) { - auto particlePayload = std::shared_ptr(new ParticlePayload(shared_from_this())); + auto particlePayload = std::make_shared(shared_from_this()); particlePayload->setPipeline(_untexturedPipeline); _renderItemId = scene->allocateID(); auto renderData = ParticlePayload::Pointer(particlePayload); - auto renderPayload = render::PayloadPointer(new ParticlePayload::Payload(renderData)); + auto renderPayload = std::make_shared(renderData); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(shared_from_this(), statusGetters); renderPayload->addStatusGetters(statusGetters); From 40e802bae766b60536b8574f44d8af356679a6c2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Nov 2015 12:05:43 -0800 Subject: [PATCH 018/174] Get rid of global variable for sort Fix rhs/lhs --- .../src/RenderableParticleEffectEntityItem.cpp | 16 +++++++--------- .../entities/src/ParticleEffectEntityItem.cpp | 6 +++--- libraries/shared/src/AABox.h | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f4243db621..5c65f0bee5 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -184,11 +184,6 @@ public: uint32_t rgba; }; -static glm::vec3 zSortAxis; -static bool zSort(const ParticleDetails& rhs, const ParticleDetails& lhs) { - return glm::dot(rhs.position, ::zSortAxis) > glm::dot(lhs.position, ::zSortAxis); -} - void RenderableParticleEffectEntityItem::updateRenderItem() { if (!_scene) { return; @@ -201,7 +196,7 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { auto xcolor = _particleColors[i]; auto alpha = (uint8_t)(glm::clamp(_particleAlphas[i] * getLocalRenderAlpha(), 0.0f, 1.0f) * 255.0f); auto rgba = toRGBA(xcolor.red, xcolor.green, xcolor.blue, alpha); - particleDetails.push_back(ParticleDetails(_particlePositions[i], _particleRadiuses[i], rgba)); + particleDetails.emplace_back(_particlePositions[i], _particleRadiuses[i], rgba); } // sort particles back to front @@ -210,9 +205,12 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { auto frustum = AbstractViewStateInterface::instance()->getCurrentViewFrustum(); // No need to sort if we're doing additive blending - if (_additiveBlending != true) { - ::zSortAxis = frustum->getDirection(); - qSort(particleDetails.begin(), particleDetails.end(), zSort); + if (!_additiveBlending) { + glm::vec3 zSortAxis = frustum->getDirection(); + std::sort(particleDetails.begin(), particleDetails.end(), + [&](const ParticleDetails& lhs, const ParticleDetails& rhs) { + return glm::dot(lhs.position, zSortAxis) > glm::dot(rhs.position, zSortAxis); + }); } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index f3abeffc20..9d802295f8 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -106,9 +106,9 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte EntityItem(entityItemID), _lastSimulated(usecTimestampNow()), _particleLifetimes(DEFAULT_MAX_PARTICLES, 0.0f), - _particlePositions(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)), - _particleVelocities(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)), - _particleAccelerations(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)), + _particlePositions(DEFAULT_MAX_PARTICLES, Vectors::ZERO), + _particleVelocities(DEFAULT_MAX_PARTICLES, Vectors::ZERO), + _particleAccelerations(DEFAULT_MAX_PARTICLES, Vectors::ZERO), _particleRadiuses(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), _radiusStarts(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), _radiusMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index e5227ade44..8de0462138 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -34,7 +34,7 @@ public: AABox(const glm::vec3& corner, const glm::vec3& dimensions); AABox(); ~AABox() {}; - + void setBox(const glm::vec3& corner, const glm::vec3& scale); void setBox(const glm::vec3& corner, float scale); From c33b6205a80ee09d95f1c3be59705898f599bf5d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Nov 2015 14:02:52 -0800 Subject: [PATCH 019/174] Some cleanup --- .../RenderableParticleEffectEntityItem.cpp | 38 ++++++++----------- .../entities/src/ParticleEffectEntityItem.h | 1 + 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 5c65f0bee5..42b2296529 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -37,8 +37,8 @@ public: _vertexBuffer(std::make_shared()), _indexBuffer(std::make_shared()) { - _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC3F_XYZ, 0); - _vertexFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), offsetof(Vertex, uv)); + _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC3F_XYZ, offsetof(Vertex, xyz)); + _vertexFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element::VEC2F_UV, offsetof(Vertex, uv)); _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, offsetof(Vertex, rgba)); } @@ -134,16 +134,15 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) { + _scene = scene; + _renderItemId = _scene->allocateID(); auto particlePayload = std::make_shared(shared_from_this()); particlePayload->setPipeline(_untexturedPipeline); - _renderItemId = scene->allocateID(); - auto renderData = ParticlePayload::Pointer(particlePayload); - auto renderPayload = std::make_shared(renderData); + auto renderPayload = std::make_shared(particlePayload); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(shared_from_this(), statusGetters); renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(_renderItemId, renderPayload); - _scene = scene; return true; } @@ -175,8 +174,7 @@ uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { return ((uint32_t)r | (uint32_t)g << 8 | (uint32_t)b << 16 | (uint32_t)a << 24); } -class ParticleDetails { -public: +struct ParticleDetails { ParticleDetails(glm::vec3 position, float radius, uint32_t rgba) : position(position), radius(radius), rgba(rgba) { } glm::vec3 position; @@ -201,15 +199,13 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // sort particles back to front // NOTE: this is view frustum might be one frame out of date. - - auto frustum = AbstractViewStateInterface::instance()->getCurrentViewFrustum(); + auto direction = AbstractViewStateInterface::instance()->getCurrentViewFrustum()->getDirection(); // No need to sort if we're doing additive blending if (!_additiveBlending) { - glm::vec3 zSortAxis = frustum->getDirection(); std::sort(particleDetails.begin(), particleDetails.end(), [&](const ParticleDetails& lhs, const ParticleDetails& rhs) { - return glm::dot(lhs.position, zSortAxis) > glm::dot(rhs.position, zSortAxis); + return glm::dot(lhs.position, direction) > glm::dot(rhs.position, direction); }); } @@ -219,11 +215,9 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { _vertices.clear(); // build vertices from particle positions and radiuses - glm::vec3 dir = frustum->getDirection(); - for (auto&& particle : particleDetails) { - glm::vec3 right = glm::normalize(glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), dir)); - glm::vec3 up = glm::normalize(glm::cross(right, dir)); - + glm::vec3 right = glm::normalize(glm::cross(direction, Vectors::UNIT_Y)); + glm::vec3 up = glm::normalize(glm::cross(right, direction)); + for (const auto& particle : particleDetails) { glm::vec3 upOffset = up * particle.radius; glm::vec3 rightOffset = right * particle.radius; // generate corners of quad aligned to face the camera. @@ -237,28 +231,26 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { // update vertex buffer auto vertexBuffer = payload.getVertexBuffer(); + auto indexBuffer = payload.getIndexBuffer(); size_t numBytes = sizeof(Vertex) * _vertices.size(); if (numBytes == 0) { vertexBuffer->resize(0); - auto indexBuffer = payload.getIndexBuffer(); indexBuffer->resize(0); return; } - + vertexBuffer->resize(numBytes); - gpu::Byte* data = vertexBuffer->editData(); - memcpy(data, &(_vertices[0]), numBytes); + memcpy(vertexBuffer->editData(), _vertices.data(), numBytes); // FIXME, don't update index buffer if num particles has not changed. // update index buffer - auto indexBuffer = payload.getIndexBuffer(); const size_t NUM_VERTS_PER_PARTICLE = 4; const size_t NUM_INDICES_PER_PARTICLE = 6; auto numQuads = (_vertices.size() / NUM_VERTS_PER_PARTICLE); numBytes = sizeof(uint16_t) * numQuads * NUM_INDICES_PER_PARTICLE; indexBuffer->resize(numBytes); - data = indexBuffer->editData(); + gpu::Byte* data = indexBuffer->editData(); auto indexPtr = reinterpret_cast(data); for (size_t i = 0; i < numQuads; ++i) { indexPtr[i * NUM_INDICES_PER_PARTICLE + 0] = i * NUM_VERTS_PER_PARTICLE + 0; diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 7ac115d8e5..94266402d2 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -226,6 +226,7 @@ protected: void updateAlpha(quint32 index, float age); void integrateParticle(quint32 index, float deltaTime); quint32 getLivingParticleCount() const; + // the properties of this entity rgbColor _color; xColor _colorStart = DEFAULT_COLOR; From 964ac5bad6be4e0ccb57c00cd46a0695f5b47e3d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Nov 2015 17:00:34 -0800 Subject: [PATCH 020/174] More cleanup --- .../RenderableParticleEffectEntityItem.cpp | 8 +- .../entities/src/ParticleEffectEntityItem.cpp | 230 +++++++----------- .../entities/src/ParticleEffectEntityItem.h | 84 +++---- 3 files changed, 135 insertions(+), 187 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 42b2296529..6e86eab135 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -190,11 +190,11 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // make a copy of each particle's details std::vector particleDetails; particleDetails.reserve(getLivingParticleCount()); - for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) { - auto xcolor = _particleColors[i]; - auto alpha = (uint8_t)(glm::clamp(_particleAlphas[i] * getLocalRenderAlpha(), 0.0f, 1.0f) * 255.0f); + for (auto& particle : _particles) { + auto xcolor = particle.color; + auto alpha = (uint8_t)(glm::clamp(particle.alpha * getLocalRenderAlpha(), 0.0f, 1.0f) * 255.0f); auto rgba = toRGBA(xcolor.red, xcolor.green, xcolor.blue, alpha); - particleDetails.emplace_back(_particlePositions[i], _particleRadiuses[i], rgba); + particleDetails.emplace_back(particle.position, particle.radius, rgba); } // sort particles back to front diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 9d802295f8..f82c80a865 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -40,9 +40,6 @@ #include "EntityScriptingInterface.h" #include "ParticleEffectEntityItem.h" -const glm::vec3 X_AXIS = glm::vec3(1.0f, 0.0f, 0.0f); -const glm::vec3 Z_AXIS = glm::vec3(0.0f, 0.0f, 1.0f); - const float SCRIPT_MAXIMUM_PI = 3.1416f; // Round up so that reasonable property values work const xColor ParticleEffectEntityItem::DEFAULT_COLOR = { 255, 255, 255 }; @@ -66,8 +63,8 @@ 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 const float ParticleEffectEntityItem::DEFAULT_SPEED_SPREAD = 1.0f; -const glm::quat ParticleEffectEntityItem::DEFAULT_EMIT_ORIENTATION = glm::angleAxis(-PI_OVER_TWO, X_AXIS); // Vertical -const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIMENSIONS = glm::vec3(0.0f, 0.0f, 0.0f); // Emit from point +const glm::quat ParticleEffectEntityItem::DEFAULT_EMIT_ORIENTATION = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_X); // Vertical +const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIMENSIONS = Vectors::ZERO; // Emit from point const float ParticleEffectEntityItem::MINIMUM_EMIT_DIMENSION = 0.0f; const float ParticleEffectEntityItem::MAXIMUM_EMIT_DIMENSION = (float)TREE_SCALE; const float ParticleEffectEntityItem::DEFAULT_EMIT_RADIUS_START = 1.0f; // Emit from surface (when emitDimensions > 0) @@ -104,35 +101,12 @@ EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID // our non-pure virtual subclass for now... ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : EntityItem(entityItemID), - _lastSimulated(usecTimestampNow()), - _particleLifetimes(DEFAULT_MAX_PARTICLES, 0.0f), - _particlePositions(DEFAULT_MAX_PARTICLES, Vectors::ZERO), - _particleVelocities(DEFAULT_MAX_PARTICLES, Vectors::ZERO), - _particleAccelerations(DEFAULT_MAX_PARTICLES, Vectors::ZERO), - _particleRadiuses(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), - _radiusStarts(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), - _radiusMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), - _radiusFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), - _particleColors(DEFAULT_MAX_PARTICLES, DEFAULT_COLOR), - _colorStarts(DEFAULT_MAX_PARTICLES, DEFAULT_COLOR), - _colorMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_COLOR), - _colorFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_COLOR), - _particleAlphas(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), - _alphaStarts(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), - _alphaMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), - _alphaFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), - _additiveBlending(DEFAULT_ADDITIVE_BLENDING) + _lastSimulated(usecTimestampNow()) { - _type = EntityTypes::ParticleEffect; - setColor(DEFAULT_COLOR); setProperties(properties); } -ParticleEffectEntityItem::~ParticleEffectEntityItem() { -} - - void ParticleEffectEntityItem::setAlpha(float alpha) { if (MINIMUM_ALPHA <= alpha && alpha <= MAXIMUM_ALPHA) { _alpha = alpha; @@ -307,8 +281,8 @@ void ParticleEffectEntityItem::setRadiusSpread(float radiusSpread) { void ParticleEffectEntityItem::computeAndUpdateDimensions() { const float time = _lifespan * 1.1f; // add 10% extra time to account for incremental timer accumulation error - glm::vec3 velocity = _emitSpeed * (_emitOrientation * Z_AXIS); - glm::vec3 velocitySpread = _speedSpread * (_emitOrientation * Z_AXIS); + glm::vec3 velocity = _emitSpeed * (_emitOrientation * Vectors::UNIT_Z); + glm::vec3 velocitySpread = _speedSpread * (_emitOrientation * Vectors::UNIT_Z); glm::vec3 maxVelocity = glm::abs(velocity) + velocitySpread; glm::vec3 maxAccleration = glm::abs(_acceleration) + _accelerationSpread; @@ -610,51 +584,50 @@ void ParticleEffectEntityItem::updateShapeType(ShapeType type) { } } -void ParticleEffectEntityItem::updateRadius(quint32 index, float age) { - _particleRadiuses[index] = Interpolate::interpolate3Points(_radiusStarts[index], _radiusMiddles[index], - _radiusFinishes[index], age); +void ParticleEffectEntityItem::updateRadius(Particle& particle, float age) { + particle.radius = Interpolate::interpolate3Points(particle.radiusStart, particle.radiusMiddle, + particle.radiusFinish, age); } -void ParticleEffectEntityItem::updateColor(quint32 index, float age) { - _particleColors[index].red = (int)Interpolate::interpolate3Points(_colorStarts[index].red, _colorMiddles[index].red, - _colorFinishes[index].red, age); - _particleColors[index].green = (int)Interpolate::interpolate3Points(_colorStarts[index].green, _colorMiddles[index].green, - _colorFinishes[index].green, age); - _particleColors[index].blue = (int)Interpolate::interpolate3Points(_colorStarts[index].blue, _colorMiddles[index].blue, - _colorFinishes[index].blue, age); +void ParticleEffectEntityItem::updateColor(Particle& particle, float age) { + particle.color.red = (int)Interpolate::interpolate3Points(particle.colorStart.red, particle.colorMiddle.red, + particle.colorFinish.red, age); + particle.color.green = (int)Interpolate::interpolate3Points(particle.colorStart.green, particle.colorMiddle.green, + particle.colorFinish.green, age); + particle.color.blue = (int)Interpolate::interpolate3Points(particle.colorStart.blue, particle.colorMiddle.blue, + particle.colorFinish.blue, age); } -void ParticleEffectEntityItem::updateAlpha(quint32 index, float age) { - _particleAlphas[index] = Interpolate::interpolate3Points(_alphaStarts[index], _alphaMiddles[index], - _alphaFinishes[index], age); +void ParticleEffectEntityItem::updateAlpha(Particle& particle, float age) { + particle.alpha = Interpolate::interpolate3Points(particle.alphaStart, particle.alphaMiddle, + particle.alphaFinish, age); } -void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) { - glm::vec3 accel = _particleAccelerations[index]; - glm::vec3 atSquared = (0.5f * deltaTime * deltaTime) * accel; - glm::vec3 at = accel * deltaTime; - _particlePositions[index] += _particleVelocities[index] * deltaTime + atSquared; - _particleVelocities[index] += at; +void ParticleEffectEntityItem::integrateParticle(Particle& particle, float deltaTime) { + glm::vec3 atSquared = (0.5f * deltaTime * deltaTime) * particle.acceleration; + glm::vec3 at = particle.acceleration * deltaTime; + particle.position += particle.velocity * deltaTime + atSquared; + particle.velocity += at; } void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particlesBounds.reset(); // update particles between head and tail - for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) { - _particleLifetimes[i] += deltaTime; + for (Particle& particle : _particles) { + particle.lifetime += deltaTime; // if particle has died. - if (_particleLifetimes[i] >= _lifespan || _lifespan < EPSILON) { + if (particle.lifetime >= _lifespan || _lifespan < EPSILON) { // move head forward - _particleHeadIndex = (_particleHeadIndex + 1) % _maxParticles; + _particles.pop_front(); } else { - float age = _particleLifetimes[i] / _lifespan; // 0.0 .. 1.0 - updateRadius(i, age); - updateColor(i, age); - updateAlpha(i, age); - integrateParticle(i, deltaTime); - _particlesBounds.addPoint(_particlePositions[i]); + float age = particle.lifetime / _lifespan; // 0.0 .. 1.0 + updateRadius(particle, age); + updateColor(particle, age); + updateAlpha(particle, age); + integrateParticle(particle, deltaTime); + _particlesBounds.addPoint(particle.position); } } @@ -667,15 +640,22 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { timeLeftInFrame -= _timeUntilNextEmit; _timeUntilNextEmit = 1.0f / _emitRate; + // overflow! move head forward by one. + // because the case of head == tail indicates an empty array, not a full one. + // This can drop an existing older particle, but this is by design, newer particles are a higher priority. + if (_particles.size() >= _maxParticles) { + _particles.pop_front(); + } + // emit a new particle at tail index. - quint32 i = _particleTailIndex; - _particleLifetimes[i] = 0.0f; + _particles.push_back(Particle()); + auto particle = _particles.back(); // Radius if (_radiusSpread == 0.0f) { - _radiusStarts[i] = getRadiusStart(); - _radiusMiddles[i] =_particleRadius; - _radiusFinishes[i] = getRadiusFinish(); + particle.radiusStart = getRadiusStart(); + particle.radiusMiddle = _particleRadius; + particle.radiusFinish = getRadiusFinish(); } else { float spreadMultiplier; if (_particleRadius > 0.0f) { @@ -683,23 +663,21 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } else { spreadMultiplier = 1.0f; } - _radiusStarts[i] = - glm::clamp(spreadMultiplier * getRadiusStart(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - _radiusMiddles[i] = - glm::clamp(spreadMultiplier * _particleRadius, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - _radiusFinishes[i] = - glm::clamp(spreadMultiplier * getRadiusFinish(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + particle.radiusStart = glm::clamp(spreadMultiplier * getRadiusStart(), + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + particle.radiusMiddle = glm::clamp(spreadMultiplier * _particleRadius, + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + particle.radiusFinish = glm::clamp(spreadMultiplier * getRadiusFinish(), + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); } - updateRadius(i, 0.0f); + updateRadius(particle, 0.0f); // Position, velocity, and acceleration if (_polarStart == 0.0f && _polarFinish == 0.0f && _emitDimensions.z == 0.0f) { // Emit along z-axis from position - _particlePositions[i] = getPosition(); - _particleVelocities[i] = - (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * Z_AXIS); - _particleAccelerations[i] = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; - + particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * Vectors::UNIT_Z); + particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; + } else { // Emit around point or from ellipsoid // - Distribute directions evenly around point @@ -719,11 +697,9 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { glm::vec3 emitDirection; - if (_emitDimensions == glm::vec3()) { + if (_emitDimensions == Vectors::ZERO) { // Point - emitDirection = glm::quat(glm::vec3(PI_OVER_TWO - elevation, 0.0f, azimuth)) * Z_AXIS; - - _particlePositions[i] = getPosition(); + emitDirection = glm::quat(glm::vec3(PI_OVER_TWO - elevation, 0.0f, azimuth)) * Vectors::UNIT_Z; } else { // Ellipsoid float radiusScale = 1.0f; @@ -745,69 +721,59 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { radiuses.z > 0.0f ? z / (radiuses.z * radiuses.z) : 0.0f )); - _particlePositions[i] = getPosition() + _emitOrientation * emitPosition; + particle.position = _emitOrientation * emitPosition; } - _particleVelocities[i] = - (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); - _particleAccelerations[i] = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; + particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); + particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } - integrateParticle(i, timeLeftInFrame); - _particlesBounds.addPoint(_particlePositions[i]); + integrateParticle(particle, timeLeftInFrame); + _particlesBounds.addPoint(particle.position); // Color if (_colorSpread == xColor{ 0, 0, 0 }) { - _colorStarts[i] = getColorStart(); - _colorMiddles[i] = getXColor(); - _colorFinishes[i] = getColorFinish(); + particle.colorStart = getColorStart(); + particle.colorMiddle = getXColor(); + particle.colorFinish = getColorFinish(); } else { xColor startColor = getColorStart(); xColor middleColor = getXColor(); xColor finishColor = getColorFinish(); float spread = randFloatInRange(-1.0f, 1.0f); - float spreadMultiplierRed = + float spreadMultiplierRed = middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; float spreadMultiplierGreen = middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green : 1.0f; float spreadMultiplierBlue = middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; - _colorStarts[i].red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); - _colorStarts[i].green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); - _colorStarts[i].blue = (int)glm::clamp(spreadMultiplierBlue * (float)startColor.blue, 0.0f, 255.0f); + particle.colorStart.red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); + particle.colorStart.green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); + particle.colorStart.blue = (int)glm::clamp(spreadMultiplierBlue * (float)startColor.blue, 0.0f, 255.0f); - _colorMiddles[i].red = (int)glm::clamp(spreadMultiplierRed * (float)middleColor.red, 0.0f, 255.0f); - _colorMiddles[i].green = (int)glm::clamp(spreadMultiplierGreen * (float)middleColor.green, 0.0f, 255.0f); - _colorMiddles[i].blue = (int)glm::clamp(spreadMultiplierBlue * (float)middleColor.blue, 0.0f, 255.0f); + particle.colorMiddle.red = (int)glm::clamp(spreadMultiplierRed * (float)middleColor.red, 0.0f, 255.0f); + particle.colorMiddle.green = (int)glm::clamp(spreadMultiplierGreen * (float)middleColor.green, 0.0f, 255.0f); + particle.colorMiddle.blue = (int)glm::clamp(spreadMultiplierBlue * (float)middleColor.blue, 0.0f, 255.0f); - _colorFinishes[i].red = (int)glm::clamp(spreadMultiplierRed * (float)finishColor.red, 0.0f, 255.0f); - _colorFinishes[i].green = (int)glm::clamp(spreadMultiplierGreen * (float)finishColor.green, 0.0f, 255.0f); - _colorFinishes[i].blue = (int)glm::clamp(spreadMultiplierBlue * (float)finishColor.blue, 0.0f, 255.0f); + particle.colorFinish.red = (int)glm::clamp(spreadMultiplierRed * (float)finishColor.red, 0.0f, 255.0f); + particle.colorFinish.green = (int)glm::clamp(spreadMultiplierGreen * (float)finishColor.green, 0.0f, 255.0f); + particle.colorFinish.blue = (int)glm::clamp(spreadMultiplierBlue * (float)finishColor.blue, 0.0f, 255.0f); } - updateColor(i, 0.0f); + updateColor(particle, 0.0f); // Alpha if (_alphaSpread == 0.0f) { - _alphaStarts[i] = getAlphaStart(); - _alphaMiddles[i] = _alpha; - _alphaFinishes[i] = getAlphaFinish(); + particle.alphaStart = getAlphaStart(); + particle.alphaMiddle = _alpha; + particle.alphaFinish = getAlphaFinish(); } else { float spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _alphaSpread / _alpha; - _alphaStarts[i] = spreadMultiplier * getAlphaStart(); - _alphaMiddles[i] = spreadMultiplier * _alpha; - _alphaFinishes[i] = spreadMultiplier * getAlphaFinish(); - } - updateAlpha(i, 0.0f); - - _particleTailIndex = (_particleTailIndex + 1) % _maxParticles; - - // overflow! move head forward by one. - // because the case of head == tail indicates an empty array, not a full one. - // This can drop an existing older particle, but this is by design, newer particles are a higher priority. - if (_particleTailIndex == _particleHeadIndex) { - _particleHeadIndex = (_particleHeadIndex + 1) % _maxParticles; + particle.alphaStart = spreadMultiplier * getAlphaStart(); + particle.alphaMiddle = spreadMultiplier * _alpha; + particle.alphaFinish = spreadMultiplier * getAlphaFinish(); } + updateAlpha(particle, 0.0f); } _timeUntilNextEmit -= timeLeftInFrame; @@ -818,37 +784,17 @@ void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { if (_maxParticles != maxParticles && MINIMUM_MAX_PARTICLES <= maxParticles && maxParticles <= MAXIMUM_MAX_PARTICLES) { _maxParticles = maxParticles; - // TODO: try to do something smart here and preserve the state of existing particles. - - // resize vectors - _particleLifetimes.resize(_maxParticles); - _particlePositions.resize(_maxParticles); - _particleVelocities.resize(_maxParticles); - _particleRadiuses.resize(_maxParticles); - _radiusStarts.resize(_maxParticles); - _radiusMiddles.resize(_maxParticles); - _radiusFinishes.resize(_maxParticles); - _particleColors.resize(_maxParticles); - _colorStarts.resize(_maxParticles); - _colorMiddles.resize(_maxParticles); - _colorFinishes.resize(_maxParticles); - _particleAlphas.resize(_maxParticles); - _alphaStarts.resize(_maxParticles); - _alphaMiddles.resize(_maxParticles); - _alphaFinishes.resize(_maxParticles); + // Pop all the overflowing oldest particles + while (_particles.size() > _maxParticles) { + _particles.pop_front(); + } // effectively clear all particles and start emitting new ones from scratch. - _particleHeadIndex = 0; - _particleTailIndex = 0; _timeUntilNextEmit = 0.0f; } } // because particles are in a ring buffer, this isn't trivial quint32 ParticleEffectEntityItem::getLivingParticleCount() const { - if (_particleTailIndex >= _particleHeadIndex) { - return _particleTailIndex - _particleHeadIndex; - } else { - return (_maxParticles - _particleHeadIndex) + _particleTailIndex; - } + return _particles.size(); } diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 94266402d2..86b3f4fabc 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -11,19 +11,18 @@ #ifndef hifi_ParticleEffectEntityItem_h #define hifi_ParticleEffectEntityItem_h -#include +#include #include "EntityItem.h" class ParticleEffectEntityItem : public EntityItem { public: + ALLOW_INSTANTIATION // This class can be instantiated static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); - virtual ~ParticleEffectEntityItem(); - ALLOW_INSTANTIATION // This class can be instantiated // methods for getting/setting all properties of this entity virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const; @@ -218,15 +217,43 @@ public: virtual bool supportsDetailedRayIntersection() const { return false; } protected: + struct Particle; + using Particles = std::deque; bool isAnimatingSomething() const; void stepSimulation(float deltaTime); - void updateRadius(quint32 index, float age); - void updateColor(quint32 index, float age); - void updateAlpha(quint32 index, float age); - void integrateParticle(quint32 index, float deltaTime); + void updateRadius(Particle& particle, float age); + void updateColor(Particle& particle, float age); + void updateAlpha(Particle& particle, float age); + void integrateParticle(Particle& particle, float deltaTime); quint32 getLivingParticleCount() const; + struct Particle { + float lifetime { 0.0f }; + glm::vec3 position { Vectors::ZERO}; + glm::vec3 velocity { Vectors::ZERO}; + glm::vec3 acceleration { Vectors::ZERO}; + float radius { DEFAULT_PARTICLE_RADIUS }; + xColor color = DEFAULT_COLOR; + float alpha { DEFAULT_ALPHA }; + + float radiusStart { DEFAULT_PARTICLE_RADIUS }; + float radiusMiddle { DEFAULT_PARTICLE_RADIUS }; + float radiusFinish { DEFAULT_PARTICLE_RADIUS }; + xColor colorStart = DEFAULT_COLOR; + xColor colorMiddle = DEFAULT_COLOR; + xColor colorFinish = DEFAULT_COLOR; + float alphaStart { DEFAULT_ALPHA }; + float alphaMiddle { DEFAULT_ALPHA }; + float alphaFinish { DEFAULT_ALPHA }; + }; + + // Particles container + Particles _particles; + + // bounding volume + Extents _particlesBounds; + // the properties of this entity rgbColor _color; xColor _colorStart = DEFAULT_COLOR; @@ -256,42 +283,17 @@ protected: float _radiusSpread = DEFAULT_RADIUS_SPREAD; - quint64 _lastSimulated; - bool _isEmitting = true; + quint64 _lastSimulated { 0 }; + bool _isEmitting { true }; - QString _textures = DEFAULT_TEXTURES; - bool _texturesChangedFlag = false; - ShapeType _shapeType = SHAPE_TYPE_NONE; - - // all the internals of running the particle sim - QVector _particleLifetimes; - QVector _particlePositions; - QVector _particleVelocities; - QVector _particleAccelerations; - QVector _particleRadiuses; - QVector _radiusStarts; - QVector _radiusMiddles; - QVector _radiusFinishes; - QVector _particleColors; - QVector _colorStarts; - QVector _colorMiddles; - QVector _colorFinishes; - QVector _particleAlphas; - QVector _alphaStarts; - QVector _alphaMiddles; - QVector _alphaFinishes; - - float _timeUntilNextEmit = 0.0f; - - // particle arrays are a ring buffer, use these indices - // to keep track of the living particles. - quint32 _particleHeadIndex = 0; - quint32 _particleTailIndex = 0; - - // bounding volume - Extents _particlesBounds; + QString _textures { DEFAULT_TEXTURES }; + bool _texturesChangedFlag { false }; + ShapeType _shapeType { SHAPE_TYPE_NONE }; - bool _additiveBlending; + float _timeUntilNextEmit { 0.0f }; + + + bool _additiveBlending { DEFAULT_ADDITIVE_BLENDING }; }; #endif // hifi_ParticleEffectEntityItem_h From 7d0a5677faf2ac81d2d1f203c7e979179078c837 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Nov 2015 17:41:39 -0800 Subject: [PATCH 021/174] More code cleanup --- .../entities/src/ParticleEffectEntityItem.cpp | 277 +++++++++--------- .../entities/src/ParticleEffectEntityItem.h | 6 +- 2 files changed, 149 insertions(+), 134 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index f82c80a865..b52cbcd90d 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -610,6 +610,14 @@ void ParticleEffectEntityItem::integrateParticle(Particle& particle, float delta particle.velocity += at; } +void ParticleEffectEntityItem::updateParticle(Particle& particle, float deltaTime) { + float age = particle.lifetime / _lifespan; // 0.0 .. 1.0 + updateRadius(particle, age); + updateColor(particle, age); + updateAlpha(particle, age); + integrateParticle(particle, deltaTime); +} + void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particlesBounds.reset(); @@ -622,11 +630,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { // move head forward _particles.pop_front(); } else { - float age = particle.lifetime / _lifespan; // 0.0 .. 1.0 - updateRadius(particle, age); - updateColor(particle, age); - updateAlpha(particle, age); - integrateParticle(particle, deltaTime); + // Otherwise update it + updateParticle(particle, deltaTime); _particlesBounds.addPoint(particle.position); } } @@ -636,10 +641,6 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { float timeLeftInFrame = deltaTime; while (_timeUntilNextEmit < timeLeftInFrame) { - - timeLeftInFrame -= _timeUntilNextEmit; - _timeUntilNextEmit = 1.0f / _emitRate; - // overflow! move head forward by one. // because the case of head == tail indicates an empty array, not a full one. // This can drop an existing older particle, but this is by design, newer particles are a higher priority. @@ -648,138 +649,148 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } // emit a new particle at tail index. - _particles.push_back(Particle()); + _particles.push_back(createParticle()); auto particle = _particles.back(); - - // Radius - if (_radiusSpread == 0.0f) { - particle.radiusStart = getRadiusStart(); - particle.radiusMiddle = _particleRadius; - particle.radiusFinish = getRadiusFinish(); - } else { - float spreadMultiplier; - if (_particleRadius > 0.0f) { - spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _radiusSpread / _particleRadius; - } else { - spreadMultiplier = 1.0f; - } - particle.radiusStart = glm::clamp(spreadMultiplier * getRadiusStart(), - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - particle.radiusMiddle = glm::clamp(spreadMultiplier * _particleRadius, - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - particle.radiusFinish = glm::clamp(spreadMultiplier * getRadiusFinish(), - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - } - updateRadius(particle, 0.0f); - - // 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.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; - - } else { - // Emit around point or from ellipsoid - // - Distribute directions evenly around point - // - Distribute points relatively evenly over ellipsoid surface - // - Distribute points relatively evenly within ellipsoid volume - - float elevationMinZ = sin(PI_OVER_TWO - _polarFinish); - float elevationMaxZ = sin(PI_OVER_TWO - _polarStart); - float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat()); - - float azimuth; - if (_azimuthFinish >= _azimuthStart) { - azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat(); - } else { - azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * randFloat(); - } - - glm::vec3 emitDirection; - - if (_emitDimensions == Vectors::ZERO) { - // Point - emitDirection = glm::quat(glm::vec3(PI_OVER_TWO - elevation, 0.0f, azimuth)) * Vectors::UNIT_Z; - } else { - // Ellipsoid - float radiusScale = 1.0f; - if (_emitRadiusStart < 1.0f) { - float emitRadiusStart = glm::max(_emitRadiusStart, EPSILON); // Avoid math complications at center - float randRadius = - emitRadiusStart + randFloatInRange(0.0f, MAXIMUM_EMIT_RADIUS_START - emitRadiusStart); - radiusScale = 1.0f - std::pow(1.0f - randRadius, 3.0f); - } - - glm::vec3 radiuses = radiusScale * 0.5f * _emitDimensions; - float x = radiuses.x * glm::cos(elevation) * glm::cos(azimuth); - float y = radiuses.y * glm::cos(elevation) * glm::sin(azimuth); - float z = radiuses.z * glm::sin(elevation); - glm::vec3 emitPosition = glm::vec3(x, y, z); - emitDirection = glm::normalize(glm::vec3( - radiuses.x > 0.0f ? x / (radiuses.x * radiuses.x) : 0.0f, - radiuses.y > 0.0f ? y / (radiuses.y * radiuses.y) : 0.0f, - radiuses.z > 0.0f ? z / (radiuses.z * radiuses.z) : 0.0f - )); - - particle.position = _emitOrientation * emitPosition; - } - - particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); - particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; - } - integrateParticle(particle, timeLeftInFrame); + particle.lifetime += timeLeftInFrame; + + // Initialize it + updateParticle(particle, timeLeftInFrame); _particlesBounds.addPoint(particle.position); - - // Color - if (_colorSpread == xColor{ 0, 0, 0 }) { - particle.colorStart = getColorStart(); - particle.colorMiddle = getXColor(); - particle.colorFinish = getColorFinish(); - } else { - xColor startColor = getColorStart(); - xColor middleColor = getXColor(); - xColor finishColor = getColorFinish(); - - float spread = randFloatInRange(-1.0f, 1.0f); - float spreadMultiplierRed = - middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; - float spreadMultiplierGreen = - middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green : 1.0f; - float spreadMultiplierBlue = - middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; - - particle.colorStart.red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); - particle.colorStart.green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); - particle.colorStart.blue = (int)glm::clamp(spreadMultiplierBlue * (float)startColor.blue, 0.0f, 255.0f); - - particle.colorMiddle.red = (int)glm::clamp(spreadMultiplierRed * (float)middleColor.red, 0.0f, 255.0f); - particle.colorMiddle.green = (int)glm::clamp(spreadMultiplierGreen * (float)middleColor.green, 0.0f, 255.0f); - particle.colorMiddle.blue = (int)glm::clamp(spreadMultiplierBlue * (float)middleColor.blue, 0.0f, 255.0f); - - particle.colorFinish.red = (int)glm::clamp(spreadMultiplierRed * (float)finishColor.red, 0.0f, 255.0f); - particle.colorFinish.green = (int)glm::clamp(spreadMultiplierGreen * (float)finishColor.green, 0.0f, 255.0f); - particle.colorFinish.blue = (int)glm::clamp(spreadMultiplierBlue * (float)finishColor.blue, 0.0f, 255.0f); - } - updateColor(particle, 0.0f); - - // Alpha - if (_alphaSpread == 0.0f) { - particle.alphaStart = getAlphaStart(); - particle.alphaMiddle = _alpha; - particle.alphaFinish = getAlphaFinish(); - } else { - float spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _alphaSpread / _alpha; - particle.alphaStart = spreadMultiplier * getAlphaStart(); - particle.alphaMiddle = spreadMultiplier * _alpha; - particle.alphaFinish = spreadMultiplier * getAlphaFinish(); - } - updateAlpha(particle, 0.0f); + + // Advance in frame + timeLeftInFrame -= _timeUntilNextEmit; + _timeUntilNextEmit = 1.0f / _emitRate; } _timeUntilNextEmit -= timeLeftInFrame; } } +ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { + Particle particle; + + // Radius + if (_radiusSpread == 0.0f) { + particle.radiusStart = getRadiusStart(); + particle.radiusMiddle = _particleRadius; + particle.radiusFinish = getRadiusFinish(); + } else { + float spreadMultiplier; + if (_particleRadius > 0.0f) { + spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _radiusSpread / _particleRadius; + } else { + spreadMultiplier = 1.0f; + } + particle.radiusStart = glm::clamp(spreadMultiplier * getRadiusStart(), + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + particle.radiusMiddle = glm::clamp(spreadMultiplier * _particleRadius, + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + particle.radiusFinish = glm::clamp(spreadMultiplier * getRadiusFinish(), + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + } + + // 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.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; + + } else { + // Emit around point or from ellipsoid + // - Distribute directions evenly around point + // - Distribute points relatively evenly over ellipsoid surface + // - Distribute points relatively evenly within ellipsoid volume + + float elevationMinZ = sin(PI_OVER_TWO - _polarFinish); + float elevationMaxZ = sin(PI_OVER_TWO - _polarStart); + float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat()); + + float azimuth; + if (_azimuthFinish >= _azimuthStart) { + azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat(); + } else { + azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * randFloat(); + } + + glm::vec3 emitDirection; + + if (_emitDimensions == Vectors::ZERO) { + // Point + emitDirection = glm::quat(glm::vec3(PI_OVER_TWO - elevation, 0.0f, azimuth)) * Vectors::UNIT_Z; + } else { + // Ellipsoid + float radiusScale = 1.0f; + if (_emitRadiusStart < 1.0f) { + float emitRadiusStart = glm::max(_emitRadiusStart, EPSILON); // Avoid math complications at center + float randRadius = + emitRadiusStart + randFloatInRange(0.0f, MAXIMUM_EMIT_RADIUS_START - emitRadiusStart); + radiusScale = 1.0f - std::pow(1.0f - randRadius, 3.0f); + } + + glm::vec3 radiuses = radiusScale * 0.5f * _emitDimensions; + float x = radiuses.x * glm::cos(elevation) * glm::cos(azimuth); + float y = radiuses.y * glm::cos(elevation) * glm::sin(azimuth); + float z = radiuses.z * glm::sin(elevation); + glm::vec3 emitPosition = glm::vec3(x, y, z); + emitDirection = glm::normalize(glm::vec3( + radiuses.x > 0.0f ? x / (radiuses.x * radiuses.x) : 0.0f, + radiuses.y > 0.0f ? y / (radiuses.y * radiuses.y) : 0.0f, + radiuses.z > 0.0f ? z / (radiuses.z * radiuses.z) : 0.0f + )); + + particle.position = _emitOrientation * emitPosition; + } + + particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); + particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; + } + + // Color + if (_colorSpread == xColor{ 0, 0, 0 }) { + particle.colorStart = getColorStart(); + particle.colorMiddle = getXColor(); + particle.colorFinish = getColorFinish(); + } else { + xColor startColor = getColorStart(); + xColor middleColor = getXColor(); + xColor finishColor = getColorFinish(); + + float spread = randFloatInRange(-1.0f, 1.0f); + float spreadMultiplierRed = + middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; + float spreadMultiplierGreen = + middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green : 1.0f; + float spreadMultiplierBlue = + middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; + + particle.colorStart.red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); + particle.colorStart.green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); + particle.colorStart.blue = (int)glm::clamp(spreadMultiplierBlue * (float)startColor.blue, 0.0f, 255.0f); + + particle.colorMiddle.red = (int)glm::clamp(spreadMultiplierRed * (float)middleColor.red, 0.0f, 255.0f); + particle.colorMiddle.green = (int)glm::clamp(spreadMultiplierGreen * (float)middleColor.green, 0.0f, 255.0f); + particle.colorMiddle.blue = (int)glm::clamp(spreadMultiplierBlue * (float)middleColor.blue, 0.0f, 255.0f); + + particle.colorFinish.red = (int)glm::clamp(spreadMultiplierRed * (float)finishColor.red, 0.0f, 255.0f); + particle.colorFinish.green = (int)glm::clamp(spreadMultiplierGreen * (float)finishColor.green, 0.0f, 255.0f); + particle.colorFinish.blue = (int)glm::clamp(spreadMultiplierBlue * (float)finishColor.blue, 0.0f, 255.0f); + } + + // Alpha + if (_alphaSpread == 0.0f) { + particle.alphaStart = getAlphaStart(); + particle.alphaMiddle = _alpha; + particle.alphaFinish = getAlphaFinish(); + } else { + float spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _alphaSpread / _alpha; + particle.alphaStart = spreadMultiplier * getAlphaStart(); + particle.alphaMiddle = spreadMultiplier * _alpha; + particle.alphaFinish = spreadMultiplier * getAlphaFinish(); + } + + return particle; +} + void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { if (_maxParticles != maxParticles && MINIMUM_MAX_PARTICLES <= maxParticles && maxParticles <= MAXIMUM_MAX_PARTICLES) { _maxParticles = maxParticles; diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 86b3f4fabc..7a3d515f45 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -221,12 +221,16 @@ protected: using Particles = std::deque; bool isAnimatingSomething() const; + quint32 getLivingParticleCount() const; + + Particle createParticle(); void stepSimulation(float deltaTime); + void updateParticle(Particle& particle, float deltaTime); + void updateRadius(Particle& particle, float age); void updateColor(Particle& particle, float age); void updateAlpha(Particle& particle, float age); void integrateParticle(Particle& particle, float deltaTime); - quint32 getLivingParticleCount() const; struct Particle { float lifetime { 0.0f }; From 230a413ec19e6796b124a73dbc0cea780444a5d0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 12:20:07 -0800 Subject: [PATCH 022/174] First pass at new particle shader --- .../RenderableParticleEffectEntityItem.cpp | 82 ++++++------------- .../src/RenderableParticleEffectEntityItem.h | 7 +- .../src/textured_particle.slf | 15 ++-- .../src/textured_particle.slv | 55 +++++++++++-- .../entities/src/ParticleEffectEntityItem.cpp | 2 +- .../entities/src/ParticleEffectEntityItem.h | 2 +- libraries/gpu/src/gpu/GLBackendShader.cpp | 2 +- libraries/gpu/src/gpu/Stream.cpp | 2 +- libraries/gpu/src/gpu/Stream.h | 6 +- libraries/gpu/src/gpu/Transform.slh | 17 +++- 10 files changed, 104 insertions(+), 86 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 6e86eab135..06f5dde300 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -25,21 +25,23 @@ #include "textured_particle_frag.h" #include "textured_particle_alpha_discard_frag.h" +static const uint32_t VERTEX_PER_QUAD = 6; + class ParticlePayload { public: - typedef render::Payload Payload; - typedef Payload::DataPointer Pointer; - typedef RenderableParticleEffectEntityItem::Vertex Vertex; + using Payload = render::Payload; + using Pointer = Payload::DataPointer; + using Vertex = RenderableParticleEffectEntityItem::Vertex; ParticlePayload(EntityItemPointer entity) : _entity(entity), _vertexFormat(std::make_shared()), - _vertexBuffer(std::make_shared()), - _indexBuffer(std::make_shared()) { + _vertexBuffer(std::make_shared()) { - _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC3F_XYZ, offsetof(Vertex, xyz)); - _vertexFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element::VEC2F_UV, offsetof(Vertex, uv)); - _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, offsetof(Vertex, rgba)); + _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC4F_XYZW, + offsetof(Vertex, xyzw), VERTEX_PER_QUAD); + _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, + offsetof(Vertex, rgba), VERTEX_PER_QUAD); } void setPipeline(gpu::PipelinePointer pipeline) { _pipeline = pipeline; } @@ -54,9 +56,6 @@ public: gpu::BufferPointer getVertexBuffer() { return _vertexBuffer; } const gpu::BufferPointer& getVertexBuffer() const { return _vertexBuffer; } - gpu::BufferPointer getIndexBuffer() { return _indexBuffer; } - const gpu::BufferPointer& getIndexBuffer() const { return _indexBuffer; } - void setTexture(gpu::TexturePointer texture) { _texture = texture; } const gpu::TexturePointer& getTexture() const { return _texture; } @@ -76,10 +75,9 @@ public: batch.setModelTransform(_modelTransform); batch.setInputFormat(_vertexFormat); batch.setInputBuffer(0, _vertexBuffer, 0, sizeof(Vertex)); - batch.setIndexBuffer(gpu::UINT16, _indexBuffer, 0); - auto numIndices = _indexBuffer->getSize() / sizeof(uint16_t); - batch.drawIndexed(gpu::TRIANGLES, numIndices); + auto numVertices = _vertexBuffer->getSize() / sizeof(Vertex); + batch.draw(gpu::TRIANGLES, numVertices * VERTEX_PER_QUAD); } protected: @@ -89,7 +87,6 @@ protected: gpu::PipelinePointer _pipeline; gpu::Stream::FormatPointer _vertexFormat; gpu::BufferPointer _vertexBuffer; - gpu::BufferPointer _indexBuffer; gpu::TexturePointer _texture; bool _visibleFlag = true; }; @@ -197,70 +194,38 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { particleDetails.emplace_back(particle.position, particle.radius, rgba); } - // sort particles back to front - // NOTE: this is view frustum might be one frame out of date. - auto direction = AbstractViewStateInterface::instance()->getCurrentViewFrustum()->getDirection(); - // No need to sort if we're doing additive blending if (!_additiveBlending) { + // sort particles back to front + // NOTE: this is view frustum might be one frame out of date. + auto direction = AbstractViewStateInterface::instance()->getCurrentViewFrustum()->getDirection(); + // Get direction in the entity space + direction = glm::inverse(getRotation()) * direction; + std::sort(particleDetails.begin(), particleDetails.end(), [&](const ParticleDetails& lhs, const ParticleDetails& rhs) { return glm::dot(lhs.position, direction) > glm::dot(rhs.position, direction); }); } - - - // allocate vertices - _vertices.clear(); - // build vertices from particle positions and radiuses - glm::vec3 right = glm::normalize(glm::cross(direction, Vectors::UNIT_Y)); - glm::vec3 up = glm::normalize(glm::cross(right, direction)); + _vertices.clear(); // clear vertices + _vertices.reserve(particleDetails.size()); // Reserve space for (const auto& particle : particleDetails) { - glm::vec3 upOffset = up * particle.radius; - glm::vec3 rightOffset = right * particle.radius; - // generate corners of quad aligned to face the camera. - _vertices.emplace_back(particle.position + rightOffset + upOffset, glm::vec2(1.0f, 1.0f), particle.rgba); - _vertices.emplace_back(particle.position - rightOffset + upOffset, glm::vec2(0.0f, 1.0f), particle.rgba); - _vertices.emplace_back(particle.position - rightOffset - upOffset, glm::vec2(0.0f, 0.0f), particle.rgba); - _vertices.emplace_back(particle.position + rightOffset - upOffset, glm::vec2(1.0f, 0.0f), particle.rgba); + _vertices.emplace_back(glm::vec4(particle.position, particle.radius), particle.rgba); } render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { // update vertex buffer auto vertexBuffer = payload.getVertexBuffer(); - auto indexBuffer = payload.getIndexBuffer(); size_t numBytes = sizeof(Vertex) * _vertices.size(); - + vertexBuffer->resize(numBytes); if (numBytes == 0) { - vertexBuffer->resize(0); - indexBuffer->resize(0); return; } - - vertexBuffer->resize(numBytes); memcpy(vertexBuffer->editData(), _vertices.data(), numBytes); - // FIXME, don't update index buffer if num particles has not changed. - // update index buffer - const size_t NUM_VERTS_PER_PARTICLE = 4; - const size_t NUM_INDICES_PER_PARTICLE = 6; - auto numQuads = (_vertices.size() / NUM_VERTS_PER_PARTICLE); - numBytes = sizeof(uint16_t) * numQuads * NUM_INDICES_PER_PARTICLE; - indexBuffer->resize(numBytes); - gpu::Byte* data = indexBuffer->editData(); - auto indexPtr = reinterpret_cast(data); - for (size_t i = 0; i < numQuads; ++i) { - indexPtr[i * NUM_INDICES_PER_PARTICLE + 0] = i * NUM_VERTS_PER_PARTICLE + 0; - indexPtr[i * NUM_INDICES_PER_PARTICLE + 1] = i * NUM_VERTS_PER_PARTICLE + 1; - indexPtr[i * NUM_INDICES_PER_PARTICLE + 2] = i * NUM_VERTS_PER_PARTICLE + 3; - indexPtr[i * NUM_INDICES_PER_PARTICLE + 3] = i * NUM_VERTS_PER_PARTICLE + 1; - indexPtr[i * NUM_INDICES_PER_PARTICLE + 4] = i * NUM_VERTS_PER_PARTICLE + 2; - indexPtr[i * NUM_INDICES_PER_PARTICLE + 5] = i * NUM_VERTS_PER_PARTICLE + 3; - } - // update transform glm::vec3 position = getPosition(); glm::quat rotation = getRotation(); @@ -323,8 +288,7 @@ void RenderableParticleEffectEntityItem::createPipelines() { gpu::ShaderPointer fragShader; if (_additiveBlending) { fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_frag))); - } - else { + } else { //If we are sorting and have no additive blending, we want to discard pixels with low alpha to avoid inter-particle entity artifacts fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_alpha_discard_frag))); } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 678f7eb904..5270a29dd5 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -32,10 +32,9 @@ protected: render::ItemID _renderItemId; struct Vertex { - Vertex(glm::vec3 xyzIn, glm::vec2 uvIn, uint32_t rgbaIn) : xyz(xyzIn), uv(uvIn), rgba(rgbaIn) {} - glm::vec3 xyz; - glm::vec2 uv; - uint32_t rgba; + Vertex(glm::vec4 xyzwIn, uint32_t rgbaIn) : xyzw(xyzwIn), rgba(rgbaIn) {} + glm::vec4 xyzw; // Position + radius + uint32_t rgba; // Color }; void createPipelines(); diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf index 58a3103323..29e683bc4c 100644 --- a/libraries/entities-renderer/src/textured_particle.slf +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -9,14 +9,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -uniform sampler2D colorMap; - -in vec4 _color; -in vec2 _texCoord0; +in vec4 varColor; +in vec2 varTexcoord; out vec4 outFragColor; +uniform sampler2D tex; + void main(void) { - vec4 color = texture(colorMap, _texCoord0); - outFragColor = color * _color; + outFragColor = varColor;//texture(tex, varTexcoord.xy) * varColor; + + if (varColor == vec4(0,0,0,1)) { + discard; + } } diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index c741af559d..012f1659ec 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -10,21 +10,58 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Inputs.slh@> - <@include gpu/Transform.slh@> <$declareStandardTransform()$> -out vec4 _color; -out vec2 _texCoord0; +in vec4 inPosition; +in vec4 inColor; + +out vec4 varColor; +out vec2 varTexcoord; void main(void) { - // pass along the color & uvs to fragment shader - _color = inColor; - _texCoord0 = inTexCoord0.xy; - + const int NUM_VERTICES_PER_PARTICLE = 6; + const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 1.0) + ); + + // anchor point in eye space + vec4 anchorPoint = vec4(inPosition.xyz, 1.0); + float radius = inPosition.w; + TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyePos(cam, obj, anchorPoint, anchorPoint)$> + + // Which icon are we dealing with ? + int particleID = gl_VertexID / NUM_VERTICES_PER_PARTICLE; + + // Which quad vertex pos? + int twoTriID = gl_VertexID - particleID * NUM_VERTICES_PER_PARTICLE; + vec4 quadPos = radius * UNIT_QUAD[twoTriID]; + + // Pass the texcoord and the z texcoord is representing the texture icon + varTexcoord = vec2((quadPos.xy + 1.0) * 0.5); + varColor = inColor; + + if (particleID == 0) { + varColor = vec4(1,0,0,1); + } else if (particleID == 5) { + varColor = vec4(0,1,0,1); + } else if (particleID == 10) { + varColor = vec4(0,0,1,1); + } else { + varColor = vec4(0,0,0,1); + } + + vec4 clipPos; + vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); + <$transformEyeToClip(cam, eyePos, clipPos)$> + gl_Position = clipPos; } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index b52cbcd90d..e12d7df488 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -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_ADDITIVE_BLENDING = true; EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 7a3d515f45..62c9415749 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -211,7 +211,7 @@ public: static const bool DEFAULT_ADDITIVE_BLENDING; bool getAdditiveBlending() const { return _additiveBlending; } void setAdditiveBlending(bool additiveBlending) { - _additiveBlending = additiveBlending; + _additiveBlending = true; } virtual bool supportsDetailedRayIntersection() const { return false; } diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 5a0ab93ec5..19fa94524e 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -154,7 +154,7 @@ GLBackend::GLShader* compileShader(const Shader& shader) { qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:"; qCWarning(gpulogging) << temp; - + /* filestream.open("debugshader.glsl.info.txt"); if (filestream.is_open()) { diff --git a/libraries/gpu/src/gpu/Stream.cpp b/libraries/gpu/src/gpu/Stream.cpp index 183f2137fb..d43999d3dd 100644 --- a/libraries/gpu/src/gpu/Stream.cpp +++ b/libraries/gpu/src/gpu/Stream.cpp @@ -59,7 +59,7 @@ void Stream::Format::evaluateCache() { } } -bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offset offset, Frequency frequency) { +bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offset offset, uint32 frequency) { _attributes[slot] = Attribute((InputSlot) slot, channel, element, offset, frequency); evaluateCache(); return true; diff --git a/libraries/gpu/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h index 492af5f62a..6adf9a60a0 100644 --- a/libraries/gpu/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -49,8 +49,8 @@ public: // Frequency describer enum Frequency { + PER_INSTANCE = -1, PER_VERTEX = 0, - PER_INSTANCE, }; // The attribute description @@ -59,7 +59,7 @@ public: public: Attribute() {} - Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX) : + Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, uint32 frequency = PER_VERTEX) : _slot(slot), _channel(channel), _element(element), @@ -107,7 +107,7 @@ public: uint32 getElementTotalSize() const { return _elementTotalSize; } - bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX); + bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, uint32 frequency = PER_VERTEX); bool setAttribute(Slot slot, Frequency frequency = PER_VERTEX); bool setAttribute(Slot slot, Slot channel, Frequency frequency = PER_VERTEX); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index e67fbf7f66..de7cdbf7af 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -74,6 +74,16 @@ TransformCamera getTransformCamera() { } <@endfunc@> +<@func $transformModelToEyePos(cameraTransform, objectTransform, modelPos, eyePos)@> + + { // transformModelToEyePos + vec4 _worldpos = (<$objectTransform$>._model * <$modelPos$>); + <$eyePos$> = (<$cameraTransform$>._view * _worldpos); + // <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>); + } +<@endfunc@> + <@func $transformInstancedModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> @@ -86,7 +96,6 @@ TransformCamera getTransformCamera() { } <@endfunc@> - <@func transformModelToWorldPos(objectTransform, modelPos, worldPos)@> { // transformModelToWorldPos <$worldPos$> = (<$objectTransform$>._model * <$modelPos$>); @@ -140,4 +149,10 @@ TransformCamera getTransformCamera() { } <@endfunc@> +<@func transformEyeToClip(cameraTransform, eyePos, clipPos)@> + { // transformEyeToClip + <$clipPos$> = <$cameraTransform$>._projection * <$eyePos$>; + } +<@endfunc@> + <@endif@> From cb14fbf4a1ea8326cf1594ef413bdcf403338645 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 15:52:42 -0800 Subject: [PATCH 023/174] Instance particle draw calls --- .../RenderableParticleEffectEntityItem.cpp | 40 +++++++++---------- .../src/RenderableParticleEffectEntityItem.h | 9 +++-- .../src/textured_particle.slf | 6 +-- .../src/textured_particle.slv | 14 +------ libraries/gpu/src/gpu/Stream.cpp | 12 +----- libraries/gpu/src/gpu/Stream.h | 11 ++--- 6 files changed, 32 insertions(+), 60 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 06f5dde300..f2978a4092 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -25,23 +25,23 @@ #include "textured_particle_frag.h" #include "textured_particle_alpha_discard_frag.h" -static const uint32_t VERTEX_PER_QUAD = 6; +static const size_t VERTEX_PER_PARTICLE = 4; class ParticlePayload { public: using Payload = render::Payload; using Pointer = Payload::DataPointer; - using Vertex = RenderableParticleEffectEntityItem::Vertex; + using ParticlePrimitive = RenderableParticleEffectEntityItem::ParticlePrimitive; ParticlePayload(EntityItemPointer entity) : _entity(entity), _vertexFormat(std::make_shared()), - _vertexBuffer(std::make_shared()) { + _particleBuffer(std::make_shared()) { _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC4F_XYZW, - offsetof(Vertex, xyzw), VERTEX_PER_QUAD); + offsetof(ParticlePrimitive, xyzw), gpu::Stream::PER_INSTANCE); _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, - offsetof(Vertex, rgba), VERTEX_PER_QUAD); + offsetof(ParticlePrimitive, rgba), gpu::Stream::PER_INSTANCE); } void setPipeline(gpu::PipelinePointer pipeline) { _pipeline = pipeline; } @@ -53,8 +53,8 @@ public: const AABox& getBound() const { return _bound; } void setBound(AABox& bound) { _bound = bound; } - gpu::BufferPointer getVertexBuffer() { return _vertexBuffer; } - const gpu::BufferPointer& getVertexBuffer() const { return _vertexBuffer; } + gpu::BufferPointer getParticleBuffer() { return _particleBuffer; } + const gpu::BufferPointer& getParticleBuffer() const { return _particleBuffer; } void setTexture(gpu::TexturePointer texture) { _texture = texture; } const gpu::TexturePointer& getTexture() const { return _texture; } @@ -74,10 +74,10 @@ public: batch.setModelTransform(_modelTransform); batch.setInputFormat(_vertexFormat); - batch.setInputBuffer(0, _vertexBuffer, 0, sizeof(Vertex)); + batch.setInputBuffer(0, _particleBuffer, 0, sizeof(ParticlePrimitive)); - auto numVertices = _vertexBuffer->getSize() / sizeof(Vertex); - batch.draw(gpu::TRIANGLES, numVertices * VERTEX_PER_QUAD); + auto numParticles = _particleBuffer->getSize() / sizeof(ParticlePrimitive); + batch.drawInstanced(numParticles, gpu::TRIANGLE_STRIP, VERTEX_PER_PARTICLE); } protected: @@ -86,7 +86,7 @@ protected: AABox _bound; gpu::PipelinePointer _pipeline; gpu::Stream::FormatPointer _vertexFormat; - gpu::BufferPointer _vertexBuffer; + gpu::BufferPointer _particleBuffer; gpu::TexturePointer _texture; bool _visibleFlag = true; }; @@ -208,23 +208,23 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { }); } - // build vertices from particle positions and radiuses - _vertices.clear(); // clear vertices - _vertices.reserve(particleDetails.size()); // Reserve space + // build primitives from particle positions and radiuses + _particlePrimitives.clear(); // clear primitives + _particlePrimitives.reserve(particleDetails.size()); // Reserve space for (const auto& particle : particleDetails) { - _vertices.emplace_back(glm::vec4(particle.position, particle.radius), particle.rgba); + _particlePrimitives.emplace_back(glm::vec4(particle.position, particle.radius), particle.rgba); } render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { - // update vertex buffer - auto vertexBuffer = payload.getVertexBuffer(); - size_t numBytes = sizeof(Vertex) * _vertices.size(); - vertexBuffer->resize(numBytes); + // update particle buffer + auto particleBuffer = payload.getParticleBuffer(); + size_t numBytes = sizeof(ParticlePrimitive) * _particlePrimitives.size(); + particleBuffer->resize(numBytes); if (numBytes == 0) { return; } - memcpy(vertexBuffer->editData(), _vertices.data(), numBytes); + memcpy(particleBuffer->editData(), _particlePrimitives.data(), numBytes); // update transform glm::vec3 position = getPosition(); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 5270a29dd5..b385b6fe41 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -16,7 +16,7 @@ #include "RenderableEntityItem.h" class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem { -friend class ParticlePayload; + friend class ParticlePayload; public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); @@ -31,15 +31,16 @@ public: protected: render::ItemID _renderItemId; - struct Vertex { - Vertex(glm::vec4 xyzwIn, uint32_t rgbaIn) : xyzw(xyzwIn), rgba(rgbaIn) {} + struct ParticlePrimitive { + ParticlePrimitive(glm::vec4 xyzwIn, uint32_t rgbaIn) : xyzw(xyzwIn), rgba(rgbaIn) {} glm::vec4 xyzw; // Position + radius uint32_t rgba; // Color }; + using Particles = std::vector; void createPipelines(); - std::vector _vertices; + Particles _particlePrimitives; gpu::PipelinePointer _untexturedPipeline; gpu::PipelinePointer _texturedPipeline; diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf index 29e683bc4c..4c718c0b58 100644 --- a/libraries/entities-renderer/src/textured_particle.slf +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -17,9 +17,5 @@ out vec4 outFragColor; uniform sampler2D tex; void main(void) { - outFragColor = varColor;//texture(tex, varTexcoord.xy) * varColor; - - if (varColor == vec4(0,0,0,1)) { - discard; - } + outFragColor = texture(tex, varTexcoord.xy) * varColor; } diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 012f1659ec..615fd1a747 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -21,13 +21,11 @@ out vec4 varColor; out vec2 varTexcoord; void main(void) { - const int NUM_VERTICES_PER_PARTICLE = 6; + const int NUM_VERTICES_PER_PARTICLE = 4; const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( vec4(-1.0, -1.0, 0.0, 1.0), vec4(1.0, -1.0, 0.0, 1.0), vec4(-1.0, 1.0, 0.0, 1.0), - vec4(-1.0, 1.0, 0.0, 1.0), - vec4(1.0, -1.0, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0) ); @@ -50,16 +48,6 @@ void main(void) { varTexcoord = vec2((quadPos.xy + 1.0) * 0.5); varColor = inColor; - if (particleID == 0) { - varColor = vec4(1,0,0,1); - } else if (particleID == 5) { - varColor = vec4(0,1,0,1); - } else if (particleID == 10) { - varColor = vec4(0,0,1,1); - } else { - varColor = vec4(0,0,0,1); - } - vec4 clipPos; vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); <$transformEyeToClip(cam, eyePos, clipPos)$> diff --git a/libraries/gpu/src/gpu/Stream.cpp b/libraries/gpu/src/gpu/Stream.cpp index d43999d3dd..ff765f3250 100644 --- a/libraries/gpu/src/gpu/Stream.cpp +++ b/libraries/gpu/src/gpu/Stream.cpp @@ -59,7 +59,7 @@ void Stream::Format::evaluateCache() { } } -bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offset offset, uint32 frequency) { +bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offset offset, Frequency frequency) { _attributes[slot] = Attribute((InputSlot) slot, channel, element, offset, frequency); evaluateCache(); return true; @@ -77,16 +77,6 @@ bool Stream::Format::setAttribute(Slot slot, Slot channel, Frequency frequency) return true; } - -BufferStream::BufferStream() : - _buffers(), - _offsets(), - _strides() -{} - -BufferStream::~BufferStream() { -} - void BufferStream::addBuffer(const BufferPointer& buffer, Offset offset, Offset stride) { _buffers.push_back(buffer); _offsets.push_back(offset); diff --git a/libraries/gpu/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h index 6adf9a60a0..9966fceca9 100644 --- a/libraries/gpu/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -49,8 +49,8 @@ public: // Frequency describer enum Frequency { - PER_INSTANCE = -1, PER_VERTEX = 0, + PER_INSTANCE = 1, }; // The attribute description @@ -59,7 +59,7 @@ public: public: Attribute() {} - Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, uint32 frequency = PER_VERTEX) : + Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX) : _slot(slot), _channel(channel), _element(element), @@ -107,7 +107,7 @@ public: uint32 getElementTotalSize() const { return _elementTotalSize; } - bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, uint32 frequency = PER_VERTEX); + bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX); bool setAttribute(Slot slot, Frequency frequency = PER_VERTEX); bool setAttribute(Slot slot, Slot channel, Frequency frequency = PER_VERTEX); @@ -129,10 +129,7 @@ typedef std::vector< Offset > Offsets; // A Buffer Stream can be assigned to the Batch to set several stream channels in one call class BufferStream { public: - typedef Offsets Strides; - - BufferStream(); - ~BufferStream(); + using Strides = Offsets; void clear() { _buffers.clear(); _offsets.clear(); _strides.clear(); } void addBuffer(const BufferPointer& buffer, Offset offset, Offset stride); From ca17c756319fb02bed2662d243a7c8c36aa2f330 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 16:07:01 -0800 Subject: [PATCH 024/174] Save one array traversal --- .../RenderableParticleEffectEntityItem.cpp | 34 +++++-------------- .../entities/src/ParticleEffectEntityItem.cpp | 7 +--- .../entities/src/ParticleEffectEntityItem.h | 1 - 3 files changed, 10 insertions(+), 32 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f2978a4092..f4117dd790 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -171,27 +171,18 @@ uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { return ((uint32_t)r | (uint32_t)g << 8 | (uint32_t)b << 16 | (uint32_t)a << 24); } -struct ParticleDetails { - ParticleDetails(glm::vec3 position, float radius, uint32_t rgba) : position(position), radius(radius), rgba(rgba) { } - - glm::vec3 position; - float radius; - uint32_t rgba; -}; - void RenderableParticleEffectEntityItem::updateRenderItem() { if (!_scene) { return; } - // make a copy of each particle's details - std::vector particleDetails; - particleDetails.reserve(getLivingParticleCount()); + // build primitives from particle positions and radiuses + _particlePrimitives.clear(); // clear primitives + _particlePrimitives.reserve(_particles.size()); // Reserve space for (auto& particle : _particles) { - auto xcolor = particle.color; - auto alpha = (uint8_t)(glm::clamp(particle.alpha * getLocalRenderAlpha(), 0.0f, 1.0f) * 255.0f); - auto rgba = toRGBA(xcolor.red, xcolor.green, xcolor.blue, alpha); - particleDetails.emplace_back(particle.position, particle.radius, rgba); + auto alpha = glm::clamp(particle.alpha * getLocalRenderAlpha(), 0.0f, 1.0f) * 255; + auto rgba = toRGBA(particle.color.red, particle.color.green, particle.color.blue, alpha); + _particlePrimitives.emplace_back(glm::vec4(particle.position, particle.radius), rgba); } // No need to sort if we're doing additive blending @@ -202,19 +193,12 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // Get direction in the entity space direction = glm::inverse(getRotation()) * direction; - std::sort(particleDetails.begin(), particleDetails.end(), - [&](const ParticleDetails& lhs, const ParticleDetails& rhs) { - return glm::dot(lhs.position, direction) > glm::dot(rhs.position, direction); + std::sort(_particlePrimitives.begin(), _particlePrimitives.end(), + [&](const ParticlePrimitive& lhs, const ParticlePrimitive& rhs) { + return glm::dot(glm::vec3(lhs.xyzw), direction) > glm::dot(glm::vec3(rhs.xyzw), direction); }); } - // build primitives from particle positions and radiuses - _particlePrimitives.clear(); // clear primitives - _particlePrimitives.reserve(particleDetails.size()); // Reserve space - for (const auto& particle : particleDetails) { - _particlePrimitives.emplace_back(glm::vec4(particle.position, particle.radius), particle.rgba); - } - render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { // update particle buffer diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index e12d7df488..e7475c30b1 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -549,7 +549,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, bool ParticleEffectEntityItem::isEmittingParticles() const { // keep emitting if there are particles still alive. - return (getIsEmitting() || getLivingParticleCount() > 0); + return (getIsEmitting() || !_particles.empty()); } bool ParticleEffectEntityItem::needsToCallUpdate() const { @@ -804,8 +804,3 @@ void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { _timeUntilNextEmit = 0.0f; } } - -// because particles are in a ring buffer, this isn't trivial -quint32 ParticleEffectEntityItem::getLivingParticleCount() const { - return _particles.size(); -} diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 62c9415749..08074f58fe 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -221,7 +221,6 @@ protected: using Particles = std::deque; bool isAnimatingSomething() const; - quint32 getLivingParticleCount() const; Particle createParticle(); void stepSimulation(float deltaTime); From 61511d57bba8c2ca2adc283133253c51404bbd0b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 16:23:31 -0800 Subject: [PATCH 025/174] Rename struct/Add type aliases --- .../RenderableParticleEffectEntityItem.cpp | 32 ++++++++++--------- .../src/RenderableParticleEffectEntityItem.h | 4 +-- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f4117dd790..c971813bd0 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -32,20 +32,22 @@ public: using Payload = render::Payload; using Pointer = Payload::DataPointer; using ParticlePrimitive = RenderableParticleEffectEntityItem::ParticlePrimitive; + using PipelinePointer = gpu::PipelinePointer; + using FormatPointer = gpu::Stream::FormatPointer; + using BufferPointer = gpu::BufferPointer; + using TexturePointer = gpu::TexturePointer; + using Format = gpu::Stream::Format; + using Buffer = gpu::Buffer; - ParticlePayload(EntityItemPointer entity) : - _entity(entity), - _vertexFormat(std::make_shared()), - _particleBuffer(std::make_shared()) { - + ParticlePayload(EntityItemPointer entity) : _entity(entity) { _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC4F_XYZW, offsetof(ParticlePrimitive, xyzw), gpu::Stream::PER_INSTANCE); _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, offsetof(ParticlePrimitive, rgba), gpu::Stream::PER_INSTANCE); } - void setPipeline(gpu::PipelinePointer pipeline) { _pipeline = pipeline; } - const gpu::PipelinePointer& getPipeline() const { return _pipeline; } + void setPipeline(PipelinePointer pipeline) { _pipeline = pipeline; } + const PipelinePointer& getPipeline() const { return _pipeline; } const Transform& getModelTransform() const { return _modelTransform; } void setModelTransform(const Transform& modelTransform) { _modelTransform = modelTransform; } @@ -53,11 +55,11 @@ public: const AABox& getBound() const { return _bound; } void setBound(AABox& bound) { _bound = bound; } - gpu::BufferPointer getParticleBuffer() { return _particleBuffer; } - const gpu::BufferPointer& getParticleBuffer() const { return _particleBuffer; } + BufferPointer getParticleBuffer() { return _particleBuffer; } + const BufferPointer& getParticleBuffer() const { return _particleBuffer; } - void setTexture(gpu::TexturePointer texture) { _texture = texture; } - const gpu::TexturePointer& getTexture() const { return _texture; } + void setTexture(TexturePointer texture) { _texture = texture; } + const TexturePointer& getTexture() const { return _texture; } bool getVisibleFlag() const { return _visibleFlag; } void setVisibleFlag(bool visibleFlag) { _visibleFlag = visibleFlag; } @@ -84,10 +86,10 @@ protected: EntityItemPointer _entity; Transform _modelTransform; AABox _bound; - gpu::PipelinePointer _pipeline; - gpu::Stream::FormatPointer _vertexFormat; - gpu::BufferPointer _particleBuffer; - gpu::TexturePointer _texture; + PipelinePointer _pipeline; + FormatPointer _vertexFormat { std::make_shared() }; + BufferPointer _particleBuffer { std::make_shared() }; + TexturePointer _texture; bool _visibleFlag = true; }; diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index b385b6fe41..4b3fb608ca 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -36,11 +36,11 @@ protected: glm::vec4 xyzw; // Position + radius uint32_t rgba; // Color }; - using Particles = std::vector; + using ParticlePrimitives = std::vector; void createPipelines(); - Particles _particlePrimitives; + ParticlePrimitives _particlePrimitives; gpu::PipelinePointer _untexturedPipeline; gpu::PipelinePointer _texturedPipeline; From e25ea122d85029ac5559f6819fae1230c5ace630 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 23:07:06 -0800 Subject: [PATCH 026/174] Start moving update to shader --- .../RenderableParticleEffectEntityItem.cpp | 53 +++++++--- .../src/RenderableParticleEffectEntityItem.h | 33 +++++-- .../src/textured_particle.slf | 6 +- .../src/textured_particle.slv | 45 ++++++++- .../src/textured_particle_alpha_discard.slf | 8 +- .../entities/src/ParticleEffectEntityItem.cpp | 96 +------------------ .../entities/src/ParticleEffectEntityItem.h | 21 +--- libraries/model/src/model/Light.cpp | 2 +- libraries/model/src/model/Light.h | 2 - 9 files changed, 119 insertions(+), 147 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index c971813bd0..c7a2e4893c 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -32,18 +32,23 @@ public: using Payload = render::Payload; using Pointer = Payload::DataPointer; using ParticlePrimitive = RenderableParticleEffectEntityItem::ParticlePrimitive; + using ParticleUniforms = RenderableParticleEffectEntityItem::ParticleUniforms; using PipelinePointer = gpu::PipelinePointer; using FormatPointer = gpu::Stream::FormatPointer; using BufferPointer = gpu::BufferPointer; using TexturePointer = gpu::TexturePointer; using Format = gpu::Stream::Format; using Buffer = gpu::Buffer; + using BufferView = gpu::BufferView; ParticlePayload(EntityItemPointer entity) : _entity(entity) { - _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC4F_XYZW, - offsetof(ParticlePrimitive, xyzw), gpu::Stream::PER_INSTANCE); - _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, - offsetof(ParticlePrimitive, rgba), gpu::Stream::PER_INSTANCE); + ParticleUniforms uniforms; + _uniformBuffer = std::make_shared(sizeof(ParticleUniforms), (const gpu::Byte*) &uniforms); + + _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC3F_XYZ, + offsetof(ParticlePrimitive, xyz), gpu::Stream::PER_INSTANCE); + _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::VEC2F_UV, + offsetof(ParticlePrimitive, uv), gpu::Stream::PER_INSTANCE); } void setPipeline(PipelinePointer pipeline) { _pipeline = pipeline; } @@ -57,6 +62,9 @@ public: BufferPointer getParticleBuffer() { return _particleBuffer; } const BufferPointer& getParticleBuffer() const { return _particleBuffer; } + + const ParticleUniforms& getParticleUniforms() const { return _uniformBuffer.get(); } + ParticleUniforms& editParticleUniforms() { return _uniformBuffer.edit(); } void setTexture(TexturePointer texture) { _texture = texture; } const TexturePointer& getTexture() const { return _texture; } @@ -75,6 +83,7 @@ public: } batch.setModelTransform(_modelTransform); + batch.setUniformBuffer(0, _uniformBuffer); batch.setInputFormat(_vertexFormat); batch.setInputBuffer(0, _particleBuffer, 0, sizeof(ParticlePrimitive)); @@ -89,6 +98,7 @@ protected: PipelinePointer _pipeline; FormatPointer _vertexFormat { std::make_shared() }; BufferPointer _particleBuffer { std::make_shared() }; + BufferView _uniformBuffer; TexturePointer _texture; bool _visibleFlag = true; }; @@ -169,22 +179,33 @@ void RenderableParticleEffectEntityItem::update(const quint64& now) { updateRenderItem(); } -uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - return ((uint32_t)r | (uint32_t)g << 8 | (uint32_t)b << 16 | (uint32_t)a << 24); +glm::vec3 toGlm(const rgbColor& color) { + return glm::vec3(color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX]); } void RenderableParticleEffectEntityItem::updateRenderItem() { if (!_scene) { return; } - - // build primitives from particle positions and radiuses + + // Fill in Uniforms structure + _particleUniforms.radius.start = getRadiusStart(); + _particleUniforms.radius.middle = getParticleRadius(); + _particleUniforms.radius.finish = getRadiusFinish(); + _particleUniforms.radius.spread = getRadiusSpread(); + + _particleUniforms.color.start = glm::vec4(toGlm(getColorStart()), getAlphaStart()); + _particleUniforms.color.middle = glm::vec4(toGlm(getColor()), getAlpha()); + _particleUniforms.color.finish = glm::vec4(toGlm(getColorFinish()), getAlphaFinish()); + _particleUniforms.color.spread = glm::vec4(toGlm(getColorSpread()), getAlphaSpread()); + + _particleUniforms.lifespan = getLifespan(); + + // Build particle primitives _particlePrimitives.clear(); // clear primitives _particlePrimitives.reserve(_particles.size()); // Reserve space for (auto& particle : _particles) { - auto alpha = glm::clamp(particle.alpha * getLocalRenderAlpha(), 0.0f, 1.0f) * 255; - auto rgba = toRGBA(particle.color.red, particle.color.green, particle.color.blue, alpha); - _particlePrimitives.emplace_back(glm::vec4(particle.position, particle.radius), rgba); + _particlePrimitives.emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed)); } // No need to sort if we're doing additive blending @@ -197,13 +218,16 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { std::sort(_particlePrimitives.begin(), _particlePrimitives.end(), [&](const ParticlePrimitive& lhs, const ParticlePrimitive& rhs) { - return glm::dot(glm::vec3(lhs.xyzw), direction) > glm::dot(glm::vec3(rhs.xyzw), direction); + return glm::dot(lhs.xyz, direction) > glm::dot(rhs.xyz, direction); }); } render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { - // update particle buffer + // Update particle uniforms + memcpy(&payload.editParticleUniforms(), &_particleUniforms, sizeof(ParticleUniforms)); + + // Update particle buffer auto particleBuffer = payload.getParticleBuffer(); size_t numBytes = sizeof(ParticlePrimitive) * _particlePrimitives.size(); particleBuffer->resize(numBytes); @@ -243,8 +267,7 @@ void RenderableParticleEffectEntityItem::createPipelines() { gpu::State::BlendArg destinationColorBlendArg; if (_additiveBlending) { destinationColorBlendArg = gpu::State::ONE; - } - else { + } else { destinationColorBlendArg = gpu::State::INV_SRC_ALPHA; writeToDepthBuffer = true; } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 4b3fb608ca..0e1dabb6a6 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -29,18 +29,37 @@ public: virtual void removeFromScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) override; protected: - render::ItemID _renderItemId; - + struct ParticleUniforms { + struct { + float start; + float middle; + float finish; + float spread; + } radius; + + struct { + glm::vec4 start; + glm::vec4 middle; + glm::vec4 finish; + glm::vec4 spread; + } color; + + float lifespan; + }; + struct ParticlePrimitive { - ParticlePrimitive(glm::vec4 xyzwIn, uint32_t rgbaIn) : xyzw(xyzwIn), rgba(rgbaIn) {} - glm::vec4 xyzw; // Position + radius - uint32_t rgba; // Color + ParticlePrimitive(glm::vec3 xyzIn, glm::vec2 uvIn) : xyz(xyzIn), uv(uvIn) {} + glm::vec3 xyz; // Position + glm::vec2 uv; // Lifetime + seed }; using ParticlePrimitives = std::vector; - + void createPipelines(); - + + render::ItemID _renderItemId; ParticlePrimitives _particlePrimitives; + ParticleUniforms _particleUniforms; + gpu::PipelinePointer _untexturedPipeline; gpu::PipelinePointer _texturedPipeline; diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf index 4c718c0b58..e139c7cc01 100644 --- a/libraries/entities-renderer/src/textured_particle.slf +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +uniform sampler2D colorMap; + in vec4 varColor; in vec2 varTexcoord; out vec4 outFragColor; -uniform sampler2D tex; - void main(void) { - outFragColor = texture(tex, varTexcoord.xy) * varColor; + outFragColor = texture(colorMap, varTexcoord.xy) * varColor; } diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 615fd1a747..0027d70da3 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -14,12 +14,45 @@ <$declareStandardTransform()$> -in vec4 inPosition; -in vec4 inColor; +struct ParticleUniforms { + struct { + float start; + float middle; + float finish; + float spread; + } radius; + + struct { + vec4 start; + vec4 middle; + vec4 finish; + vec4 spread; + } color; + + float lifespan; +}; + +uniform particleBuffer { + ParticleUniforms particle; +}; + +in vec3 inPosition; +in vec2 inExtra; out vec4 varColor; out vec2 varTexcoord; +float mix(float start, float finish, float age) { + return start + (finish - start) * age; +} + +vec4 mixV(vec4 start, vec4 finish, float age) { + return vec4(mix(start.x, finish.x, age), + mix(start.y, finish.y, age), + mix(start.z, finish.z, age), + mix(start.w, finish.w, age)); +} + void main(void) { const int NUM_VERTICES_PER_PARTICLE = 4; const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( @@ -29,9 +62,12 @@ void main(void) { vec4(1.0, 1.0, 0.0, 1.0) ); + float age = inExtra.x / particle.lifespan; + float seed = inExtra.y; + // anchor point in eye space vec4 anchorPoint = vec4(inPosition.xyz, 1.0); - float radius = inPosition.w; + float radius = mix(particle.radius.start, particle.radius.finish , age); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); @@ -46,7 +82,8 @@ void main(void) { // Pass the texcoord and the z texcoord is representing the texture icon varTexcoord = vec2((quadPos.xy + 1.0) * 0.5); - varColor = inColor; + varColor = mixV(particle.color.start, particle.color.finish , age); + varColor.w = particle.color.middle.w; vec4 clipPos; vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); diff --git a/libraries/entities-renderer/src/textured_particle_alpha_discard.slf b/libraries/entities-renderer/src/textured_particle_alpha_discard.slf index 389744449a..4d96da943b 100644 --- a/libraries/entities-renderer/src/textured_particle_alpha_discard.slf +++ b/libraries/entities-renderer/src/textured_particle_alpha_discard.slf @@ -11,15 +11,15 @@ uniform sampler2D colorMap; -in vec4 _color; -in vec2 _texCoord0; +in vec4 varColor; +in vec2 varTexcoord; out vec4 outFragColor; void main(void) { - vec4 color = texture(colorMap, _texCoord0); + vec4 color = texture(colorMap, varTexcoord); if (color.a < 0.1) { discard; } - outFragColor = color * _color; + outFragColor = color * varColor; } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index e7475c30b1..4341dba187 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -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 = true; +const bool ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING = false; EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -584,25 +584,6 @@ void ParticleEffectEntityItem::updateShapeType(ShapeType type) { } } -void ParticleEffectEntityItem::updateRadius(Particle& particle, float age) { - particle.radius = Interpolate::interpolate3Points(particle.radiusStart, particle.radiusMiddle, - particle.radiusFinish, age); -} - -void ParticleEffectEntityItem::updateColor(Particle& particle, float age) { - particle.color.red = (int)Interpolate::interpolate3Points(particle.colorStart.red, particle.colorMiddle.red, - particle.colorFinish.red, age); - particle.color.green = (int)Interpolate::interpolate3Points(particle.colorStart.green, particle.colorMiddle.green, - particle.colorFinish.green, age); - particle.color.blue = (int)Interpolate::interpolate3Points(particle.colorStart.blue, particle.colorMiddle.blue, - particle.colorFinish.blue, age); -} - -void ParticleEffectEntityItem::updateAlpha(Particle& particle, float age) { - particle.alpha = Interpolate::interpolate3Points(particle.alphaStart, particle.alphaMiddle, - particle.alphaFinish, age); -} - void ParticleEffectEntityItem::integrateParticle(Particle& particle, float deltaTime) { glm::vec3 atSquared = (0.5f * deltaTime * deltaTime) * particle.acceleration; glm::vec3 at = particle.acceleration * deltaTime; @@ -610,14 +591,6 @@ void ParticleEffectEntityItem::integrateParticle(Particle& particle, float delta particle.velocity += at; } -void ParticleEffectEntityItem::updateParticle(Particle& particle, float deltaTime) { - float age = particle.lifetime / _lifespan; // 0.0 .. 1.0 - updateRadius(particle, age); - updateColor(particle, age); - updateAlpha(particle, age); - integrateParticle(particle, deltaTime); -} - void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particlesBounds.reset(); @@ -631,7 +604,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particles.pop_front(); } else { // Otherwise update it - updateParticle(particle, deltaTime); + integrateParticle(particle, deltaTime); _particlesBounds.addPoint(particle.position); } } @@ -654,7 +627,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { particle.lifetime += timeLeftInFrame; // Initialize it - updateParticle(particle, timeLeftInFrame); + integrateParticle(particle, deltaTime); _particlesBounds.addPoint(particle.position); // Advance in frame @@ -669,25 +642,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { Particle particle; - // Radius - if (_radiusSpread == 0.0f) { - particle.radiusStart = getRadiusStart(); - particle.radiusMiddle = _particleRadius; - particle.radiusFinish = getRadiusFinish(); - } else { - float spreadMultiplier; - if (_particleRadius > 0.0f) { - spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _radiusSpread / _particleRadius; - } else { - spreadMultiplier = 1.0f; - } - particle.radiusStart = glm::clamp(spreadMultiplier * getRadiusStart(), - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - particle.radiusMiddle = glm::clamp(spreadMultiplier * _particleRadius, - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - particle.radiusFinish = glm::clamp(spreadMultiplier * getRadiusFinish(), - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - } + particle.seed = randFloatInRange(0.0f, 1.0f); // Position, velocity, and acceleration if (_polarStart == 0.0f && _polarFinish == 0.0f && _emitDimensions.z == 0.0f) { @@ -745,49 +700,6 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } - // Color - if (_colorSpread == xColor{ 0, 0, 0 }) { - particle.colorStart = getColorStart(); - particle.colorMiddle = getXColor(); - particle.colorFinish = getColorFinish(); - } else { - xColor startColor = getColorStart(); - xColor middleColor = getXColor(); - xColor finishColor = getColorFinish(); - - float spread = randFloatInRange(-1.0f, 1.0f); - float spreadMultiplierRed = - middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; - float spreadMultiplierGreen = - middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green : 1.0f; - float spreadMultiplierBlue = - middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; - - particle.colorStart.red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); - particle.colorStart.green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); - particle.colorStart.blue = (int)glm::clamp(spreadMultiplierBlue * (float)startColor.blue, 0.0f, 255.0f); - - particle.colorMiddle.red = (int)glm::clamp(spreadMultiplierRed * (float)middleColor.red, 0.0f, 255.0f); - particle.colorMiddle.green = (int)glm::clamp(spreadMultiplierGreen * (float)middleColor.green, 0.0f, 255.0f); - particle.colorMiddle.blue = (int)glm::clamp(spreadMultiplierBlue * (float)middleColor.blue, 0.0f, 255.0f); - - particle.colorFinish.red = (int)glm::clamp(spreadMultiplierRed * (float)finishColor.red, 0.0f, 255.0f); - particle.colorFinish.green = (int)glm::clamp(spreadMultiplierGreen * (float)finishColor.green, 0.0f, 255.0f); - particle.colorFinish.blue = (int)glm::clamp(spreadMultiplierBlue * (float)finishColor.blue, 0.0f, 255.0f); - } - - // Alpha - if (_alphaSpread == 0.0f) { - particle.alphaStart = getAlphaStart(); - particle.alphaMiddle = _alpha; - particle.alphaFinish = getAlphaFinish(); - } else { - float spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _alphaSpread / _alpha; - particle.alphaStart = spreadMultiplier * getAlphaStart(); - particle.alphaMiddle = spreadMultiplier * _alpha; - particle.alphaFinish = spreadMultiplier * getAlphaFinish(); - } - return particle; } diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 08074f58fe..090c5e3a80 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -211,7 +211,7 @@ public: static const bool DEFAULT_ADDITIVE_BLENDING; bool getAdditiveBlending() const { return _additiveBlending; } void setAdditiveBlending(bool additiveBlending) { - _additiveBlending = true; + _additiveBlending = additiveBlending; } virtual bool supportsDetailedRayIntersection() const { return false; } @@ -224,31 +224,14 @@ protected: Particle createParticle(); void stepSimulation(float deltaTime); - void updateParticle(Particle& particle, float deltaTime); - - void updateRadius(Particle& particle, float age); - void updateColor(Particle& particle, float age); - void updateAlpha(Particle& particle, float age); void integrateParticle(Particle& particle, float deltaTime); struct Particle { + float seed { 0.0f }; float lifetime { 0.0f }; glm::vec3 position { Vectors::ZERO}; glm::vec3 velocity { Vectors::ZERO}; glm::vec3 acceleration { Vectors::ZERO}; - float radius { DEFAULT_PARTICLE_RADIUS }; - xColor color = DEFAULT_COLOR; - float alpha { DEFAULT_ALPHA }; - - float radiusStart { DEFAULT_PARTICLE_RADIUS }; - float radiusMiddle { DEFAULT_PARTICLE_RADIUS }; - float radiusFinish { DEFAULT_PARTICLE_RADIUS }; - xColor colorStart = DEFAULT_COLOR; - xColor colorMiddle = DEFAULT_COLOR; - xColor colorFinish = DEFAULT_COLOR; - float alphaStart { DEFAULT_ALPHA }; - float alphaMiddle { DEFAULT_ALPHA }; - float alphaFinish { DEFAULT_ALPHA }; }; // Particles container diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 823be727a4..917e3bed7e 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -18,7 +18,7 @@ Light::Light() : _transform() { // only if created from nothing shall we create the Buffer to store the properties Schema schema; - _schemaBuffer = gpu::BufferView(std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema)); + _schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema); } Light::Light(const Light& light) : diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index efc02e3de4..de7a846a25 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -112,8 +112,6 @@ public: Vec4 _shadow{0.0f}; Vec4 _control{0.0f, 0.0f, 0.0f, 0.0f}; - - Schema() {} }; const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; } From 74278cad40f34c8f632f335ffc99397e9cd1c09c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 23:16:44 -0800 Subject: [PATCH 027/174] Fix particle texturing --- libraries/entities-renderer/src/textured_particle.slv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 0027d70da3..718c65a2dc 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -81,7 +81,7 @@ void main(void) { vec4 quadPos = radius * UNIT_QUAD[twoTriID]; // Pass the texcoord and the z texcoord is representing the texture icon - varTexcoord = vec2((quadPos.xy + 1.0) * 0.5); + varTexcoord = vec2((UNIT_QUAD[twoTriID].xy + 1.0) * 0.5); varColor = mixV(particle.color.start, particle.color.finish , age); varColor.w = particle.color.middle.w; From 2cb2ca29e6159cbb32645fd1291c404f28909ef4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 19 Nov 2015 12:10:54 -0800 Subject: [PATCH 028/174] More particle shader work --- .../RenderableParticleEffectEntityItem.cpp | 12 +-- .../src/textured_particle.slv | 84 +++++++++++++++---- 2 files changed, 74 insertions(+), 22 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index c7a2e4893c..ca543d0210 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -179,8 +179,8 @@ void RenderableParticleEffectEntityItem::update(const quint64& now) { updateRenderItem(); } -glm::vec3 toGlm(const rgbColor& color) { - return glm::vec3(color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX]); +static glm::vec4 toGlm(const xColor& color, float alpha) { + return glm::vec4((float)color.red / 255.0f, (float)color.green / 255.0f, (float)color.blue / 255.0f, alpha); } void RenderableParticleEffectEntityItem::updateRenderItem() { @@ -194,10 +194,10 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { _particleUniforms.radius.finish = getRadiusFinish(); _particleUniforms.radius.spread = getRadiusSpread(); - _particleUniforms.color.start = glm::vec4(toGlm(getColorStart()), getAlphaStart()); - _particleUniforms.color.middle = glm::vec4(toGlm(getColor()), getAlpha()); - _particleUniforms.color.finish = glm::vec4(toGlm(getColorFinish()), getAlphaFinish()); - _particleUniforms.color.spread = glm::vec4(toGlm(getColorSpread()), getAlphaSpread()); + _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.lifespan = getLifespan(); diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 718c65a2dc..7a9c91cb0f 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -37,22 +37,68 @@ uniform particleBuffer { }; in vec3 inPosition; -in vec2 inExtra; +in vec2 inColor; // This is actual Lifetime + Seed out vec4 varColor; out vec2 varTexcoord; -float mix(float start, float finish, float age) { - return start + (finish - start) * age; +float bezierInterpolate(float y1, float y2, float y3, float u) { + // https://en.wikipedia.org/wiki/Bezier_curve + return (1.0 - u) * (1.0 - u) * y1 + 2.0 * (1.0 - u) * u * y2 + u * u * y3; } -vec4 mixV(vec4 start, vec4 finish, float age) { - return vec4(mix(start.x, finish.x, age), - mix(start.y, finish.y, age), - mix(start.z, finish.z, age), - mix(start.w, finish.w, age)); +float interpolate3Floats(float y1, float y2, float y3, float u) { + if ((u <= 0.5 && y1 == y2) || (u >= 0.5 && y2 == y3)) { + // Flat line. + return y2; + } + + if ((y2 >= y1 && y2 >= y3) || (y2 <= y1 && y2 <= y3)) { + // U or inverted-U shape. + // Make the slope at y2 = 0, which means that the control points half way between the value points have the value y2. + if (u <= 0.5) { + return bezierInterpolate(y1, y2, y2, 2.0 * u); + } else { + return bezierInterpolate(y2, y2, y3, 2.0 * u - 1.0); + } + + } else { + // L or inverted and/or mirrored L shape. + // Make the slope at y2 be the slope between y1 and y3, up to a maximum of double the minimum of the slopes between y1 + // and y2, and y2 and y3. Use this slope to calculate the control points half way between the value points. + // Note: The maximum ensures that the control points and therefore the interpolated values stay between y1 and y3. + float slope = y3 - y1; + float slope12 = y2 - y1; + float slope23 = y3 - y2; + if (abs(slope) > abs(2.0 * slope12)) { + slope = 2.0 * slope12; + } else if (abs(slope) > abs(2.0 * slope23)) { + slope = 2.0 * slope23; + } + + if (u <= 0.5) { + return bezierInterpolate(y1, y2 - slope / 2.0, y2, 2.0 * u); + } else { + return bezierInterpolate(y2, y2 + slope / 2.0, y3, 2.0 * u - 1.0); + } + +// float uGreaterHalf = step(0.5, u); +// float uSign = sign(uGreaterHalf - 0.5); +// vec4 y12 = mix(y1, y2, uGreaterHalf) +// vec4 y23 = mix(y2, y3, uGreaterHalf) +// +// return bezierInterpolate(y12, y2 + uSign * slope / 2.0, y23, 2.0 * u - uGreaterHalf); + } } +vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) { + return vec4(interpolate3Floats(y1.x, y2.x, y3.x, u), + interpolate3Floats(y1.y, y2.y, y3.y, u), + interpolate3Floats(y1.z, y2.z, y3.z, u), + interpolate3Floats(y1.w, y2.w, y3.w, u)); +} + + void main(void) { const int NUM_VERTICES_PER_PARTICLE = 4; const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( @@ -62,12 +108,12 @@ void main(void) { vec4(1.0, 1.0, 0.0, 1.0) ); - float age = inExtra.x / particle.lifespan; - float seed = inExtra.y; + float age = inColor.x / particle.lifespan; + float seed = inColor.y; // anchor point in eye space vec4 anchorPoint = vec4(inPosition.xyz, 1.0); - float radius = mix(particle.radius.start, particle.radius.finish , age); + float radius = interpolate3Floats(particle.radius.start, particle.radius.middle, particle.radius.finish , age); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); @@ -80,13 +126,19 @@ void main(void) { int twoTriID = gl_VertexID - particleID * NUM_VERTICES_PER_PARTICLE; vec4 quadPos = radius * UNIT_QUAD[twoTriID]; - // Pass the texcoord and the z texcoord is representing the texture icon - varTexcoord = vec2((UNIT_QUAD[twoTriID].xy + 1.0) * 0.5); - varColor = mixV(particle.color.start, particle.color.finish , age); - varColor.w = particle.color.middle.w; - vec4 clipPos; vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); <$transformEyeToClip(cam, eyePos, clipPos)$> gl_Position = clipPos; + + + // Pass the texcoord and the z texcoord is representing the texture icon + varTexcoord = vec2((UNIT_QUAD[twoTriID].xy + 1.0) * 0.5); + varColor = interpolate3Vec4(particle.color.start, particle.color.middle, particle.color.finish, age); + + // if (inColor.x == 0.0) { + // varColor = vec4(0, 1, 0, 1); + // } else { + // varColor = vec4(1, 0, 0, 1); + // } } From 0f316e6ae107eb174cb4ffa0a61c2f38d0f222ab Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 19 Nov 2015 15:24:36 -0800 Subject: [PATCH 029/174] Remove particles emiter bounds compute --- .../RenderableParticleEffectEntityItem.cpp | 9 ++--- .../entities/src/ParticleEffectEntityItem.cpp | 6 +-- .../entities/src/ParticleEffectEntityItem.h | 40 ++++++++++--------- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index ca543d0210..e3de0f9555 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -58,7 +58,7 @@ public: void setModelTransform(const Transform& modelTransform) { _modelTransform = modelTransform; } const AABox& getBound() const { return _bound; } - void setBound(AABox& bound) { _bound = bound; } + void setBound(const AABox& bound) { _bound = bound; } BufferPointer getParticleBuffer() { return _particleBuffer; } const BufferPointer& getParticleBuffer() const { return _particleBuffer; } @@ -242,12 +242,9 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { Transform transform; transform.setTranslation(position); transform.setRotation(rotation); + payload.setModelTransform(transform); - - AABox bounds(_particlesBounds); - bounds.rotate(rotation); - bounds.shiftBy(position); - payload.setBound(bounds); + payload.setBound(getAABox()); bool textured = _texture && _texture->isLoaded(); if (textured) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 4341dba187..f598426e3c 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -592,20 +592,17 @@ void ParticleEffectEntityItem::integrateParticle(Particle& particle, float delta } void ParticleEffectEntityItem::stepSimulation(float deltaTime) { - _particlesBounds.reset(); - // update particles between head and tail for (Particle& particle : _particles) { particle.lifetime += deltaTime; // if particle has died. - if (particle.lifetime >= _lifespan || _lifespan < EPSILON) { + if (particle.lifetime >= _lifespan) { // move head forward _particles.pop_front(); } else { // Otherwise update it integrateParticle(particle, deltaTime); - _particlesBounds.addPoint(particle.position); } } @@ -628,7 +625,6 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { // Initialize it integrateParticle(particle, deltaTime); - _particlesBounds.addPoint(particle.position); // Advance in frame timeLeftInFrame -= _timeUntilNextEmit; diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 090c5e3a80..0789f5b95e 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -237,10 +237,7 @@ protected: // Particles container Particles _particles; - // bounding volume - Extents _particlesBounds; - - // the properties of this entity + // Particles properties rgbColor _color; xColor _colorStart = DEFAULT_COLOR; xColor _colorFinish = DEFAULT_COLOR; @@ -249,25 +246,30 @@ protected: float _alphaStart = DEFAULT_ALPHA_START; float _alphaFinish = DEFAULT_ALPHA_FINISH; float _alphaSpread = DEFAULT_ALPHA_SPREAD; - quint32 _maxParticles = DEFAULT_MAX_PARTICLES; - float _lifespan = DEFAULT_LIFESPAN; - float _emitRate = DEFAULT_EMIT_RATE; - float _emitSpeed = DEFAULT_EMIT_SPEED; - float _speedSpread = DEFAULT_SPEED_SPREAD; - glm::quat _emitOrientation = DEFAULT_EMIT_ORIENTATION; - glm::vec3 _emitDimensions = DEFAULT_EMIT_DIMENSIONS; - float _emitRadiusStart = DEFAULT_EMIT_RADIUS_START; - float _polarStart = DEFAULT_POLAR_START; - float _polarFinish = DEFAULT_POLAR_FINISH; - float _azimuthStart = DEFAULT_AZIMUTH_START; - float _azimuthFinish = DEFAULT_AZIMUTH_FINISH; - glm::vec3 _emitAcceleration = DEFAULT_EMIT_ACCELERATION; - glm::vec3 _accelerationSpread = DEFAULT_ACCELERATION_SPREAD; float _particleRadius = DEFAULT_PARTICLE_RADIUS; float _radiusStart = DEFAULT_RADIUS_START; float _radiusFinish = DEFAULT_RADIUS_FINISH; float _radiusSpread = DEFAULT_RADIUS_SPREAD; - + float _lifespan = DEFAULT_LIFESPAN; + + // Emiter properties + quint32 _maxParticles = DEFAULT_MAX_PARTICLES; + + float _emitRate = DEFAULT_EMIT_RATE; + float _emitSpeed = DEFAULT_EMIT_SPEED; + float _speedSpread = DEFAULT_SPEED_SPREAD; + + glm::quat _emitOrientation = DEFAULT_EMIT_ORIENTATION; + glm::vec3 _emitDimensions = DEFAULT_EMIT_DIMENSIONS; + float _emitRadiusStart = DEFAULT_EMIT_RADIUS_START; + glm::vec3 _emitAcceleration = DEFAULT_EMIT_ACCELERATION; + glm::vec3 _accelerationSpread = DEFAULT_ACCELERATION_SPREAD; + + float _polarStart = DEFAULT_POLAR_START; + float _polarFinish = DEFAULT_POLAR_FINISH; + float _azimuthStart = DEFAULT_AZIMUTH_START; + float _azimuthFinish = DEFAULT_AZIMUTH_FINISH; + quint64 _lastSimulated { 0 }; bool _isEmitting { true }; From 9adc43755384684007be5a3d685559222ea8a093 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 20 Nov 2015 15:36:34 -0800 Subject: [PATCH 030/174] Make Particle's Payload/PendingChanges *almost* pointer free --- .../RenderableParticleEffectEntityItem.cpp | 99 ++++++++++++------- .../src/RenderableParticleEffectEntityItem.h | 34 +------ 2 files changed, 64 insertions(+), 69 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index e3de0f9555..5c33d2e01e 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -27,12 +27,30 @@ static const size_t VERTEX_PER_PARTICLE = 4; -class ParticlePayload { +template +struct InterpolationData { + T start; + T middle; + T finish; + T spread; +}; + +class ParticlePayloadData { public: - using Payload = render::Payload; + struct ParticleUniforms { + InterpolationData radius; + InterpolationData color; // rgba + float lifespan; + }; + + struct ParticlePrimitive { + ParticlePrimitive(glm::vec3 xyzIn, glm::vec2 uvIn) : xyz(xyzIn), uv(uvIn) {} + glm::vec3 xyz; // Position + glm::vec2 uv; // Lifetime + seed + }; + + using Payload = render::Payload; using Pointer = Payload::DataPointer; - using ParticlePrimitive = RenderableParticleEffectEntityItem::ParticlePrimitive; - using ParticleUniforms = RenderableParticleEffectEntityItem::ParticleUniforms; using PipelinePointer = gpu::PipelinePointer; using FormatPointer = gpu::Stream::FormatPointer; using BufferPointer = gpu::BufferPointer; @@ -40,8 +58,9 @@ public: using Format = gpu::Stream::Format; using Buffer = gpu::Buffer; using BufferView = gpu::BufferView; - - ParticlePayload(EntityItemPointer entity) : _entity(entity) { + using ParticlePrimitives = std::vector; + + ParticlePayloadData() { ParticleUniforms uniforms; _uniformBuffer = std::make_shared(sizeof(ParticleUniforms), (const gpu::Byte*) &uniforms); @@ -92,7 +111,6 @@ public: } protected: - EntityItemPointer _entity; Transform _modelTransform; AABox _bound; PipelinePointer _pipeline; @@ -105,7 +123,7 @@ protected: namespace render { template <> - const ItemKey payloadGetKey(const ParticlePayload::Pointer& payload) { + const ItemKey payloadGetKey(const ParticlePayloadData::Pointer& payload) { if (payload->getVisibleFlag()) { return ItemKey::Builder::transparentShape(); } else { @@ -114,12 +132,12 @@ namespace render { } template <> - const Item::Bound payloadGetBound(const ParticlePayload::Pointer& payload) { + const Item::Bound payloadGetBound(const ParticlePayloadData::Pointer& payload) { return payload->getBound(); } template <> - void payloadRender(const ParticlePayload::Pointer& payload, RenderArgs* args) { + void payloadRender(const ParticlePayloadData::Pointer& payload, RenderArgs* args) { payload->render(args); } } @@ -145,9 +163,9 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, _scene = scene; _renderItemId = _scene->allocateID(); - auto particlePayload = std::make_shared(shared_from_this()); - particlePayload->setPipeline(_untexturedPipeline); - auto renderPayload = std::make_shared(particlePayload); + auto particlePayloadData = std::make_shared(); + particlePayloadData->setPipeline(_untexturedPipeline); + auto renderPayload = std::make_shared(particlePayloadData); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(shared_from_this(), statusGetters); renderPayload->addStatusGetters(statusGetters); @@ -187,25 +205,29 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { if (!_scene) { return; } + using ParticleUniforms = ParticlePayloadData::ParticleUniforms; + using ParticlePrimitive = ParticlePayloadData::ParticlePrimitive; + using ParticlePrimitives = ParticlePayloadData::ParticlePrimitives; + ParticleUniforms particleUniforms; // Fill in Uniforms structure - _particleUniforms.radius.start = getRadiusStart(); - _particleUniforms.radius.middle = getParticleRadius(); - _particleUniforms.radius.finish = getRadiusFinish(); - _particleUniforms.radius.spread = getRadiusSpread(); + particleUniforms.radius.start = getRadiusStart(); + 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 = toGlm(getColorStart(), getAlphaStart()); + particleUniforms.color.middle = toGlm(getXColor(), getAlpha()); + particleUniforms.color.finish = toGlm(getColorFinish(), getAlphaFinish()); + particleUniforms.color.spread = toGlm(getColorSpread(), getAlphaSpread()); - _particleUniforms.lifespan = getLifespan(); + particleUniforms.lifespan = getLifespan(); // Build particle primitives - _particlePrimitives.clear(); // clear primitives - _particlePrimitives.reserve(_particles.size()); // Reserve space + auto particlePrimitives = std::make_shared(); + particlePrimitives->reserve(_particles.size()); // Reserve space for (auto& particle : _particles) { - _particlePrimitives.emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed)); + particlePrimitives->emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed)); } // No need to sort if we're doing additive blending @@ -216,35 +238,36 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // Get direction in the entity space direction = glm::inverse(getRotation()) * direction; - std::sort(_particlePrimitives.begin(), _particlePrimitives.end(), + std::sort(particlePrimitives->begin(), particlePrimitives->end(), [&](const ParticlePrimitive& lhs, const ParticlePrimitive& rhs) { return glm::dot(lhs.xyz, direction) > glm::dot(rhs.xyz, direction); }); } + + auto bounds = getAABox(); + auto position = getPosition(); + auto rotation = getRotation(); + Transform transform; + transform.setTranslation(position); + transform.setRotation(rotation); render::PendingChanges pendingChanges; - pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { + pendingChanges.updateItem(_renderItemId, [=](ParticlePayloadData& payload) { // Update particle uniforms - memcpy(&payload.editParticleUniforms(), &_particleUniforms, sizeof(ParticleUniforms)); + memcpy(&payload.editParticleUniforms(), &particleUniforms, sizeof(ParticleUniforms)); // Update particle buffer auto particleBuffer = payload.getParticleBuffer(); - size_t numBytes = sizeof(ParticlePrimitive) * _particlePrimitives.size(); + size_t numBytes = sizeof(ParticlePrimitive) * particlePrimitives->size(); particleBuffer->resize(numBytes); if (numBytes == 0) { return; } - memcpy(particleBuffer->editData(), _particlePrimitives.data(), numBytes); + memcpy(particleBuffer->editData(), particlePrimitives->data(), numBytes); - // update transform - glm::vec3 position = getPosition(); - glm::quat rotation = getRotation(); - Transform transform; - transform.setTranslation(position); - transform.setRotation(rotation); - + // Update transform and bounds payload.setModelTransform(transform); - payload.setBound(getAABox()); + payload.setBound(bounds); bool textured = _texture && _texture->isLoaded(); if (textured) { diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 0e1dabb6a6..1fb9674682 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -16,7 +16,7 @@ #include "RenderableEntityItem.h" class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem { - friend class ParticlePayload; + friend class ParticlePayloadData; public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); @@ -29,42 +29,14 @@ public: virtual void removeFromScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) override; protected: - struct ParticleUniforms { - struct { - float start; - float middle; - float finish; - float spread; - } radius; - - struct { - glm::vec4 start; - glm::vec4 middle; - glm::vec4 finish; - glm::vec4 spread; - } color; - - float lifespan; - }; - - struct ParticlePrimitive { - ParticlePrimitive(glm::vec3 xyzIn, glm::vec2 uvIn) : xyz(xyzIn), uv(uvIn) {} - glm::vec3 xyz; // Position - glm::vec2 uv; // Lifetime + seed - }; - using ParticlePrimitives = std::vector; - void createPipelines(); + render::ScenePointer _scene; render::ItemID _renderItemId; - ParticlePrimitives _particlePrimitives; - ParticleUniforms _particleUniforms; + NetworkTexturePointer _texture; gpu::PipelinePointer _untexturedPipeline; gpu::PipelinePointer _texturedPipeline; - - render::ScenePointer _scene; - NetworkTexturePointer _texture; }; From 28c8cf26f50d403672e7f60c56d1895c4f27c4b4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 23 Nov 2015 15:19:41 -0800 Subject: [PATCH 031/174] Fix shader transform errors --- .../entities-renderer/src/textured_particle.slv | 2 +- libraries/gpu/src/gpu/Transform.slh | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 7a9c91cb0f..72b06e0228 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -128,7 +128,7 @@ void main(void) { vec4 clipPos; vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); - <$transformEyeToClip(cam, eyePos, clipPos)$> + <$transformEyeToClipPos(cam, eyePos, clipPos)$> gl_Position = clipPos; diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index de7cdbf7af..5d8be1137d 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -76,11 +76,10 @@ TransformCamera getTransformCamera() { <@func $transformModelToEyePos(cameraTransform, objectTransform, modelPos, eyePos)@> + //return camera._view * object._model * pos; !> { // transformModelToEyePos - vec4 _worldpos = (<$objectTransform$>._model * <$modelPos$>); + vec4 _worldpos = (<$objectTransform$>._model * vec4(<$modelPos$>.xyz, 1.0)); <$eyePos$> = (<$cameraTransform$>._view * _worldpos); - // <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>); } <@endfunc@> @@ -145,13 +144,13 @@ TransformCamera getTransformCamera() { <@func transformClipToEyeDir(cameraTransform, clipPos, eyeDir)@> { // transformClipToEyeDir - <$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 1.0)); + <$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 0.0)); } <@endfunc@> -<@func transformEyeToClip(cameraTransform, eyePos, clipPos)@> - { // transformEyeToClip - <$clipPos$> = <$cameraTransform$>._projection * <$eyePos$>; +<@func transformEyeToClipPos(cameraTransform, eyePos, clipPos)@> + { // transformEyeToClipPos + <$clipPos$> = <$cameraTransform$>._projection * vec4(<$eyePos$>.xyz, 1.0); } <@endfunc@> From d08a4d77dc172314e8e25c28f60e54b3c8d0eb9e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 23 Nov 2015 16:11:23 -0800 Subject: [PATCH 032/174] Shader cleanup --- .../src/textured_particle.slv | 52 ++++++++----------- libraries/gpu/src/gpu/Transform.slh | 18 +++---- 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 72b06e0228..9289c8f08d 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -42,6 +42,14 @@ in vec2 inColor; // This is actual Lifetime + Seed out vec4 varColor; out vec2 varTexcoord; +const int NUM_VERTICES_PER_PARTICLE = 4; +const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 1.0) +); + float bezierInterpolate(float y1, float y2, float y3, float u) { // https://en.wikipedia.org/wiki/Bezier_curve return (1.0 - u) * (1.0 - u) * y1 + 2.0 * (1.0 - u) * u * y2 + u * u * y3; @@ -100,45 +108,29 @@ vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) { void main(void) { - const int NUM_VERTICES_PER_PARTICLE = 4; - const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( - vec4(-1.0, -1.0, 0.0, 1.0), - vec4(1.0, -1.0, 0.0, 1.0), - vec4(-1.0, 1.0, 0.0, 1.0), - vec4(1.0, 1.0, 0.0, 1.0) - ); - - float age = inColor.x / particle.lifespan; - float seed = inColor.y; - - // anchor point in eye space - vec4 anchorPoint = vec4(inPosition.xyz, 1.0); - float radius = interpolate3Floats(particle.radius.start, particle.radius.middle, particle.radius.finish , age); - TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyePos(cam, obj, anchorPoint, anchorPoint)$> // Which icon are we dealing with ? int particleID = gl_VertexID / NUM_VERTICES_PER_PARTICLE; - // Which quad vertex pos? int twoTriID = gl_VertexID - particleID * NUM_VERTICES_PER_PARTICLE; - vec4 quadPos = radius * UNIT_QUAD[twoTriID]; - - vec4 clipPos; - vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); - <$transformEyeToClipPos(cam, eyePos, clipPos)$> - gl_Position = clipPos; - - + + // Particle properties + float age = inColor.x / particle.lifespan; + float seed = inColor.y; + // Pass the texcoord and the z texcoord is representing the texture icon varTexcoord = vec2((UNIT_QUAD[twoTriID].xy + 1.0) * 0.5); varColor = interpolate3Vec4(particle.color.start, particle.color.middle, particle.color.finish, age); - // if (inColor.x == 0.0) { - // varColor = vec4(0, 1, 0, 1); - // } else { - // varColor = vec4(1, 0, 0, 1); - // } + // anchor point in eye space + float radius = interpolate3Floats(particle.radius.start, particle.radius.middle, particle.radius.finish , age); + vec4 quadPos = radius * UNIT_QUAD[twoTriID]; + + vec4 anchorPoint; + <$transformModelToEyePos(cam, obj, inPosition, anchorPoint)$> + + vec4 eyePos = anchorPoint + quadPos; + <$transformEyeToClipPos(cam, eyePos, gl_Position)$> } diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 5d8be1137d..9a866ca4d0 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -74,15 +74,6 @@ TransformCamera getTransformCamera() { } <@endfunc@> -<@func $transformModelToEyePos(cameraTransform, objectTransform, modelPos, eyePos)@> - - { // transformModelToEyePos - vec4 _worldpos = (<$objectTransform$>._model * vec4(<$modelPos$>.xyz, 1.0)); - <$eyePos$> = (<$cameraTransform$>._view * _worldpos); - } -<@endfunc@> - <@func $transformInstancedModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> @@ -148,6 +139,15 @@ TransformCamera getTransformCamera() { } <@endfunc@> +<@func $transformModelToEyePos(cameraTransform, objectTransform, modelPos, eyePos)@> + + { // transformModelToEyePos + vec4 _worldpos = (<$objectTransform$>._model * vec4(<$modelPos$>.xyz, 1.0)); + <$eyePos$> = (<$cameraTransform$>._view * _worldpos); + } +<@endfunc@> + <@func transformEyeToClipPos(cameraTransform, eyePos, clipPos)@> { // transformEyeToClipPos <$clipPos$> = <$cameraTransform$>._projection * vec4(<$eyePos$>.xyz, 1.0); From 4827a96bfa3519673e8fa7d9a59e33878f966cc4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 23 Nov 2015 17:53:22 -0800 Subject: [PATCH 033/174] Fix vertex shader (nested struct unsupported) --- .../RenderableParticleEffectEntityItem.cpp | 2 +- .../src/textured_particle.slv | 37 ++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 5c33d2e01e..f6e8298ec3 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -152,7 +152,7 @@ RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const Ent ParticleEffectEntityItem(entityItemID, properties) { // lazy creation of particle system pipeline - if (!_untexturedPipeline && !_texturedPipeline) { + if (!_untexturedPipeline || !_texturedPipeline) { createPipelines(); } } diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 9289c8f08d..cd5dd75101 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -14,21 +14,22 @@ <$declareStandardTransform()$> +struct Radiuses { + float start; + float middle; + float finish; + float spread; +}; +struct Colors { + vec4 start; + vec4 middle; + vec4 finish; + vec4 spread; +}; + struct ParticleUniforms { - struct { - float start; - float middle; - float finish; - float spread; - } radius; - - struct { - vec4 start; - vec4 middle; - vec4 finish; - vec4 spread; - } color; - + Radiuses radius; + Colors color; float lifespan; }; @@ -44,10 +45,10 @@ out vec2 varTexcoord; const int NUM_VERTICES_PER_PARTICLE = 4; const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( - vec4(-1.0, -1.0, 0.0, 1.0), - vec4(1.0, -1.0, 0.0, 1.0), - vec4(-1.0, 1.0, 0.0, 1.0), - vec4(1.0, 1.0, 0.0, 1.0) + vec4(-1.0, -1.0, 0.0, 0.0), + vec4(1.0, -1.0, 0.0, 0.0), + vec4(-1.0, 1.0, 0.0, 0.0), + vec4(1.0, 1.0, 0.0, 0.0) ); float bezierInterpolate(float y1, float y2, float y3, float u) { From 2dd494b5df2a6222a9bf03029f6ee07edfc1bfdc Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 23 Nov 2015 21:00:54 -0800 Subject: [PATCH 034/174] Remove additive blending option (force it) --- .../RenderableParticleEffectEntityItem.cpp | 50 ++++--------------- .../src/textured_particle_alpha_discard.slf | 25 ---------- 2 files changed, 10 insertions(+), 65 deletions(-) delete mode 100644 libraries/entities-renderer/src/textured_particle_alpha_discard.slf diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f6e8298ec3..86a0603569 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,7 +23,6 @@ #include "untextured_particle_frag.h" #include "textured_particle_vert.h" #include "textured_particle_frag.h" -#include "textured_particle_alpha_discard_frag.h" static const size_t VERTEX_PER_PARTICLE = 4; @@ -229,20 +228,6 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { for (auto& particle : _particles) { particlePrimitives->emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed)); } - - // No need to sort if we're doing additive blending - if (!_additiveBlending) { - // sort particles back to front - // NOTE: this is view frustum might be one frame out of date. - auto direction = AbstractViewStateInterface::instance()->getCurrentViewFrustum()->getDirection(); - // Get direction in the entity space - direction = glm::inverse(getRotation()) * direction; - - std::sort(particlePrimitives->begin(), particlePrimitives->end(), - [&](const ParticlePrimitive& lhs, const ParticlePrimitive& rhs) { - return glm::dot(lhs.xyz, direction) > glm::dot(rhs.xyz, direction); - }); - } auto bounds = getAABox(); auto position = getPosition(); @@ -283,44 +268,29 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { } void RenderableParticleEffectEntityItem::createPipelines() { - bool writeToDepthBuffer = false; - gpu::State::BlendArg destinationColorBlendArg; - if (_additiveBlending) { - destinationColorBlendArg = gpu::State::ONE; - } else { - destinationColorBlendArg = gpu::State::INV_SRC_ALPHA; - writeToDepthBuffer = true; - } if (!_untexturedPipeline) { auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, writeToDepthBuffer, gpu::LESS_EQUAL); - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, - destinationColorBlendArg, gpu::State::FACTOR_ALPHA, - gpu::State::BLEND_OP_ADD, gpu::State::ONE); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(untextured_particle_vert))); auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(untextured_particle_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vertShader, fragShader)); _untexturedPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); } if (!_texturedPipeline) { auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); - + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - bool writeToDepthBuffer = !_additiveBlending; - state->setDepthTest(true, writeToDepthBuffer, gpu::LESS_EQUAL); - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, - destinationColorBlendArg, gpu::State::FACTOR_ALPHA, - gpu::State::BLEND_OP_ADD, gpu::State::ONE); auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(textured_particle_vert))); - gpu::ShaderPointer fragShader; - if (_additiveBlending) { - fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_frag))); - } else { - //If we are sorting and have no additive blending, we want to discard pixels with low alpha to avoid inter-particle entity artifacts - fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_alpha_discard_frag))); - } + auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vertShader, fragShader)); _texturedPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); diff --git a/libraries/entities-renderer/src/textured_particle_alpha_discard.slf b/libraries/entities-renderer/src/textured_particle_alpha_discard.slf deleted file mode 100644 index 4d96da943b..0000000000 --- a/libraries/entities-renderer/src/textured_particle_alpha_discard.slf +++ /dev/null @@ -1,25 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// fragment shader -// -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -uniform sampler2D colorMap; - -in vec4 varColor; -in vec2 varTexcoord; - -out vec4 outFragColor; - -void main(void) { - vec4 color = texture(colorMap, varTexcoord); - if (color.a < 0.1) { - discard; - } - outFragColor = color * varColor; -} From b7cdca75b7ed403c212b2f05b3b937718c2738f9 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Tue, 24 Nov 2015 16:12:04 -0600 Subject: [PATCH 035/174] Checkpoint towards integrated delivery --- assignment-client/CMakeLists.txt | 1 + cmake/macros/ConsolidateStackComponents.cmake | 9 +++++++++ ...e.cmake => PackageLibrariesForDeployment.cmake} | 2 +- domain-server/CMakeLists.txt | 1 + stack-manager/CMakeLists.txt | 14 +++++++++----- 5 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 cmake/macros/ConsolidateStackComponents.cmake rename cmake/macros/{CopyDllsBesideWindowsExecutable.cmake => PackageLibrariesForDeployment.cmake} (98%) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 58f200b0fe..3064e97d70 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -11,3 +11,4 @@ link_hifi_libraries( include_application_version() package_libraries_for_deployment() +consolidate_stack_components() \ No newline at end of file diff --git a/cmake/macros/ConsolidateStackComponents.cmake b/cmake/macros/ConsolidateStackComponents.cmake new file mode 100644 index 0000000000..2b2fe9a691 --- /dev/null +++ b/cmake/macros/ConsolidateStackComponents.cmake @@ -0,0 +1,9 @@ +macro(CONSOLIDATE_STACK_COMPONENTS) + + # Copy all the output for this target into the common deployment location + add_custom_command( + TARGET ${TARGET_NAME} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy_directory $ ${CMAKE_BINARY_DIR}/full-stack-deployment + ) + +endmacro() \ No newline at end of file diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/PackageLibrariesForDeployment.cmake similarity index 98% rename from cmake/macros/CopyDllsBesideWindowsExecutable.cmake rename to cmake/macros/PackageLibrariesForDeployment.cmake index 9330515a62..bb0b268dd4 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/PackageLibrariesForDeployment.cmake @@ -1,5 +1,5 @@ # -# CopyDllsBesideWindowsExecutable.cmake +# PackageLibrariesForDeployment.cmake # cmake/macros # # Copyright 2015 High Fidelity, Inc. diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index 1f9280a899..2200916765 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -38,3 +38,4 @@ endif (UNIX) include_application_version() package_libraries_for_deployment() +consolidate_stack_components() \ No newline at end of file diff --git a/stack-manager/CMakeLists.txt b/stack-manager/CMakeLists.txt index e70fefc6e0..35b4f091a7 100644 --- a/stack-manager/CMakeLists.txt +++ b/stack-manager/CMakeLists.txt @@ -1,16 +1,19 @@ set(TARGET_NAME "stack-manager") set(BUILD_BUNDLE YES) setup_hifi_project(Widgets Gui Svg Core Network WebKitWidgets) +add_dependencies(${TARGET_NAME} assignment-client domain-server) if (WIN32) target_zlib() endif () target_quazip() -set_target_properties( - ${TARGET_NAME} PROPERTIES - EXCLUDE_FROM_ALL TRUE -) +if (UNIX) + set_target_properties( + ${TARGET_NAME} PROPERTIES + EXCLUDE_FROM_ALL TRUE + ) +endif (UNIX) if (DEFINED ENV{JOB_ID}) set(PR_BUILD "false") @@ -45,4 +48,5 @@ if (APPLE) set(SM_SRCS ${SM_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/assets/icon.icns") endif () -package_libraries_for_deployment() \ No newline at end of file +package_libraries_for_deployment() +consolidate_stack_components() \ No newline at end of file From 1776b08e1b8fb84052c1ea752b8c327136ae3d85 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 24 Nov 2015 17:35:18 -0800 Subject: [PATCH 036/174] end of day --- examples/drylake/ratCreator.js | 78 ++++++++++++++-------------------- examples/drylake/steer.js | 16 +++---- 2 files changed, 40 insertions(+), 54 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index bc7b6cf9a2..0edd348f1a 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -24,7 +24,7 @@ var RAT_DIMENSIONS = { }; var RAT_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/models/rat_model.fbx'; -var RAT_IDLE_ANIMATION_URL ='http://hifi-content.s3.amazonaws.com/james/rat/animations/idle.fbx'; +var RAT_IDLE_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/idle.fbx'; var RAT_WALKING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/walk.fbx'; var RAT_RUNNING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/run.fbx'; var RAT_DEATH_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/death.fbx'; @@ -35,17 +35,18 @@ var RAT_IN_NEST_DISTANCE = 3; var RAT_SPAWN_RATE = 2500; function playRatRunningAnimation(rat) { + print('RUN RAT') var animationSettings = JSON.stringify({ running: true }); Entities.editEntity(rat, { animationURL: RAT_RUNNING_ANIMATION_URL, - animationSettings: animationSettings - // animation: { - // url: RAT_RUNNING_ANIMATION_URL, - // running: true, - // fps: 180 - // }, + // animationSettings: animationSettings, + animation: { + url: RAT_RUNNING_ANIMATION_URL, + running: true, + fps: 30 + }, }); } @@ -64,28 +65,6 @@ function playRatDeathAnimation(rat) { }); } -var ratProperties = { - name: 'Rat', - type: 'Box', - color: { - red: 0, - green: 0, - blue: 255 - }, - dimensions: { - x: 1, - y: 1, - z: 1 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - position: RAT_SPAWNER_LOCATION -}; - var modelRatProperties = { name: 'rat', type: 'Model', @@ -94,17 +73,20 @@ var modelRatProperties = { position: RAT_SPAWNER_LOCATION, shapeType: 'Box', collisionsWillMove: true, + ignoreForCollisions: false, gravity: { x: 0, - y: -9.8, + y: -19.8, z: 0 - } - //enable this if for some reason we want grabbable rats - // userData:JSON.stringify({ - // grabbableKey:{ - // grabbable:false - // } - // }) + }, + lifetime: 30, + rotation: Quat.fromPitchYawRollDegrees(0, 180, 0), + //disable this if for some reason we want grabbable rats + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) }; @@ -123,18 +105,16 @@ var targetProperties = { }, visible: false, position: RAT_NEST_LOCATION - // script: Script.resolvePath('rat.js') }; var target = Entities.addEntity(targetProperties); function addRat() { var rat = Entities.addEntity(modelRatProperties); - rats.push(rat); + return rat } var rats = []; -addRat(); var AVOIDER_Y_HEIGHT = 99; var FIRST_AVOIDER_START_POSITION = { @@ -190,7 +170,7 @@ function addAvoiderBlock(position) { position: position, collisionsWillMove: false, ignoreForCollisions: true, - visible: false + visible: true }; var avoider = Entities.addEntity(avoiderProperties); @@ -274,7 +254,6 @@ function moveRats() { averageAvatarFlight = Vec3.multiply(averageAvatarFlight, 1 / avatarFlightVectors.length); - var avoidBlockVectors = steer.fleeAvoiderBlocks(rat); var averageAvoiderFlight; @@ -306,14 +285,21 @@ function moveRats() { averageVector = Vec3.multiply(averageVector, 1 / divisorCount); var thisRatProps = Entities.getEntityProperties(rat, ["position", "rotation"]); + + var eulerAngle = Quat.safeEulerAngles(thisRatProps.rotation); + eulerAngle.x = 0; + eulerAngle.z = 0; + var constrainedRotation = Quat.fromVec3Degrees(eulerAngle); + + // print('CR:::'+JSON.stringify(constrainedRotation)) + var ratPosition = thisRatProps.position; var ratToNest = Vec3.subtract(RAT_NEST_LOCATION, ratPosition); - var ratRotation = Quat.rotationBetween(Vec3.FRONT, ratToNest); + var ratRotation = Quat.rotationBetween(Vec3.UNIT_Z, ratToNest); Entities.editEntity(rat, { velocity: averageVector, - rotation: ratRotation, - //rotation: Quat.fromPitchYawRollDegrees(0,0,0) + rotation: constrainedRotation, }) // castRay(rat); @@ -374,7 +360,7 @@ var ratSpawnerInterval; if (USE_CONSTANT_SPAWNER === true) { ratSpawnerInterval = Script.setInterval(function() { - addRat(); + var rat = addRat(); playRatRunningAnimation(rat); rats.push(rat); }, RAT_SPAWN_RATE); diff --git a/examples/drylake/steer.js b/examples/drylake/steer.js index 3c4a21091c..7068273e4d 100644 --- a/examples/drylake/steer.js +++ b/examples/drylake/steer.js @@ -14,7 +14,7 @@ function flee(thisEntity, target) { if (d < 2) { var steer = Vec3.subtract(desired, velocity); - var steerVector = new V3(desired.x, desired.y, desired.z); + var steerVector = new V3(desired.x, 0, desired.z); steer = steerVector.limit(MAX_FORCE); return steer; @@ -47,11 +47,11 @@ function fleeAllAvatars(thisEntity) { desired = Vec3.multiply(MAX_SPEED, desired); if (d < 3) { var steer = Vec3.subtract(desired, velocity); - var steerVector = new V3(desired.x, desired.y, desired.z); + var steerVector = new V3(desired.x, 0, desired.z); steer = steerVector.limit(MAX_FORCE) flightVectors.push(steer) } else { - // print('target too far away from this avatar to flee' + d); + // print('target too far away from this avatar to flee' + d); } } @@ -61,7 +61,7 @@ function fleeAllAvatars(thisEntity) { } function fleeAvoiderBlocks(thisEntity) { - // print('FLEE AVOIDER BLOCKS'); + // print('FLEE AVOIDER BLOCKS'); var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; @@ -72,7 +72,7 @@ function fleeAvoiderBlocks(thisEntity) { var entityID = nearbyEntities[entityIndex]; var entityProps = Entities.getEntityProperties(entityID); if (entityProps.name === 'Hifi-Rat-Avoider') { - // print('found an avoiderblock to flee'); + // print('found an avoiderblock to flee'); var MAX_SPEED = 8; var MAX_FORCE = 6; @@ -87,7 +87,7 @@ function fleeAvoiderBlocks(thisEntity) { steer = steerVector.limit(MAX_FORCE) flightVectors.push(steer); } else { - //print('target too far away from this avoider to flee' + d); + //print('target too far away from this avoider to flee' + d); } } @@ -116,7 +116,7 @@ function arrive(thisEntity, target) { } var steer = Vec3.subtract(desired, velocity); - var steerVector = new V3(desired.x, desired.y, desired.z); + var steerVector = new V3(desired.x, 0, desired.z); steer = steerVector.limit(MAX_FORCE) return steer @@ -161,7 +161,7 @@ loadSteer = function() { return { flee: flee, fleeAllAvatars: fleeAllAvatars, - fleeAvoiderBlocks:fleeAvoiderBlocks, + fleeAvoiderBlocks: fleeAvoiderBlocks, arrive: arrive } } \ No newline at end of file From 4ab2bfa85461d7e1fd7b298dfb08b8b10c1cbd2e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 26 Nov 2015 08:35:28 -0800 Subject: [PATCH 037/174] clean up, minimize diff --- .../src/RenderableModelEntityItem.cpp | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e0923313c7..1221c53f24 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -210,6 +210,7 @@ void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::sha } } + // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items, and it handles // the per frame simulation/update that might be required if the models properties changed. void RenderableModelEntityItem::render(RenderArgs* args) { @@ -249,6 +250,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { _model->setVisibleInScene(getVisible(), scene); } + remapTextures(); } else { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); @@ -304,22 +306,23 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } bool RenderableModelEntityItem::needsToCallUpdate() const { - if (EntityItem::needsToCallUpdate()) { + if (!_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate()) { return true; } - // these if statements match the structure of those in RenderableModelEntityItem::update - if (hasModel() && _myRenderer) { - if (!_model || _needsModelReload) { - return true; - } - } + if (!_dimensionsInitialized && _model && _model->isActive()) { return true; } + + if (_myRenderer && (!_model || _needsModelReload)) { + return true; + } + if (_model) { - if (hasAnimation()) { + if (hasAnimation() || jointsMapped()) { return true; } + bool movingOrAnimating = isMoving() || isAnimatingSomething(); if ((movingOrAnimating || _needsInitialSimulation || @@ -339,14 +342,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)); } - + if (_myRenderer && (!_model || _needsModelReload)) { // TODO: this getModel() appears to be about 3% of model render time. We should optimize PerformanceTimer perfTimer("getModel"); From 4b5fec4b008731a905e87ee669d0827a2af4d5f2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 26 Nov 2015 08:36:41 -0800 Subject: [PATCH 038/174] clean up, minimize diff --- libraries/entities-renderer/src/RenderableModelEntityItem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 6c5bfc4423..c4e36c240a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -47,6 +47,7 @@ public: virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, From 766f0dbd32561a791a2d7a43365d2364e1f8af30 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Fri, 27 Nov 2015 14:04:33 -0600 Subject: [PATCH 039/174] Have stack manager use bundled stack --- CMakeLists.txt | 15 ++ cmake/templates/FixupBundlePostBuild.cmake.in | 2 +- interface/CMakeLists.txt | 2 +- stack-manager/CMakeLists.txt | 1 + stack-manager/src/AppDelegate.cpp | 232 +----------------- stack-manager/src/AppDelegate.h | 7 - stack-manager/src/GlobalData.cpp | 19 +- stack-manager/src/GlobalData.h | 1 + 8 files changed, 25 insertions(+), 254 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e95974383..d5f615949c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,3 +221,18 @@ if (HIFI_MEMORY_DEBUGGING) MESSAGE("-- Memory debugging is enabled") endif (UNIX) endif () + +set(CPACK_PACKAGE_NAME "High Fidelity") +set(CPACK_PACKAGE_VENDOR "High Fidelity, Inc") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "High Fidelity Interface and Stack") +set(CPACK_PACKAGE_VERSION "${BUILD_SEQ}") +set(CPACK_PACKAGE_VERSION_MAJOR "${BUILD_SEQ}") +set(CPACK_PACKAGE_VERSION_MINOR "0") +set(CPACK_PACKAGE_VERSION_PATCH "0") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity") + +if (WIN32) + install(DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment/ DESTINATION "./") +endif (WIN32) + +include(CPack) \ No newline at end of file diff --git a/cmake/templates/FixupBundlePostBuild.cmake.in b/cmake/templates/FixupBundlePostBuild.cmake.in index ee686a6967..6e3ad9723b 100644 --- a/cmake/templates/FixupBundlePostBuild.cmake.in +++ b/cmake/templates/FixupBundlePostBuild.cmake.in @@ -53,4 +53,4 @@ else() endif() file(GLOB RUNTIME_PLUGINS "${BUNDLE_PLUGIN_DIR}/*.${PLUGIN_EXTENSION}") -fixup_bundle("${BUNDLE_EXECUTABLE}" "${RUNTIME_PLUGINS}" "@FIXUP_LIBS@") \ No newline at end of file +fixup_bundle("${BUNDLE_EXECUTABLE}" "${RUNTIME_PLUGINS}" "@FIXUP_LIBS@") diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 3357b57858..091cad56ab 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -194,7 +194,6 @@ else (APPLE) # link target to external libraries if (WIN32) - # target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib) target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib) else (WIN32) # Nothing else required on linux apparently @@ -202,3 +201,4 @@ else (APPLE) endif (APPLE) package_libraries_for_deployment() +consolidate_stack_components() diff --git a/stack-manager/CMakeLists.txt b/stack-manager/CMakeLists.txt index 35b4f091a7..520beb6893 100644 --- a/stack-manager/CMakeLists.txt +++ b/stack-manager/CMakeLists.txt @@ -2,6 +2,7 @@ set(TARGET_NAME "stack-manager") set(BUILD_BUNDLE YES) setup_hifi_project(Widgets Gui Svg Core Network WebKitWidgets) add_dependencies(${TARGET_NAME} assignment-client domain-server) +include_application_version() if (WIN32) target_zlib() diff --git a/stack-manager/src/AppDelegate.cpp b/stack-manager/src/AppDelegate.cpp index ea9310a2d8..6b350af117 100644 --- a/stack-manager/src/AppDelegate.cpp +++ b/stack-manager/src/AppDelegate.cpp @@ -81,10 +81,6 @@ void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const Q AppDelegate::AppDelegate(int argc, char* argv[]) : QApplication(argc, argv), - _qtReady(false), - _dsReady(false), - _dsResourcesReady(false), - _acReady(false), _domainServerProcess(NULL), _acMonitorProcess(NULL), _domainServerName("localhost") @@ -115,14 +111,15 @@ AppDelegate::AppDelegate(int argc, char* argv[]) : _window = new MainWindow(); - createExecutablePath(); - downloadLatestExecutablesAndRequirements(); - _checkVersionTimer.setInterval(0); connect(&_checkVersionTimer, SIGNAL(timeout()), this, SLOT(checkVersion())); _checkVersionTimer.start(); connect(this, &QApplication::aboutToQuit, this, &AppDelegate::stopStack); + + _window->setRequirementsLastChecked(QDateTime::currentDateTime().toString()); + _window->show(); + toggleStack(true); } AppDelegate::~AppDelegate() { @@ -427,227 +424,6 @@ void AppDelegate::handleContentSetDownloadFinished() { emit domainAddressChanged(); } -void AppDelegate::onFileSuccessfullyInstalled(const QUrl& url) { - if (url == GlobalData::getInstance().getRequirementsURL()) { - _qtReady = true; - } else if (url == GlobalData::getInstance().getAssignmentClientURL()) { - _acReady = true; - } else if (url == GlobalData::getInstance().getDomainServerURL()) { - _dsReady = true; - } else if (url == GlobalData::getInstance().getDomainServerResourcesURL()) { - _dsResourcesReady = true; - } - - if (_qtReady && _acReady && _dsReady && _dsResourcesReady) { - _window->setRequirementsLastChecked(QDateTime::currentDateTime().toString()); - _window->show(); - toggleStack(true); - } -} - -void AppDelegate::createExecutablePath() { - QDir launchDir(GlobalData::getInstance().getClientsLaunchPath()); - QDir resourcesDir(GlobalData::getInstance().getClientsResourcesPath()); - QDir logsDir(GlobalData::getInstance().getLogsPath()); - if (!launchDir.exists()) { - if (QDir().mkpath(launchDir.absolutePath())) { - qDebug() << "Successfully created directory: " - << launchDir.absolutePath(); - } else { - qCritical() << "Failed to create directory: " - << launchDir.absolutePath(); - } - } - if (!resourcesDir.exists()) { - if (QDir().mkpath(resourcesDir.absolutePath())) { - qDebug() << "Successfully created directory: " - << resourcesDir.absolutePath(); - } else { - qCritical() << "Failed to create directory: " - << resourcesDir.absolutePath(); - } - } - if (!logsDir.exists()) { - if (QDir().mkpath(logsDir.absolutePath())) { - qDebug() << "Successfully created directory: " - << logsDir.absolutePath(); - } else { - qCritical() << "Failed to create directory: " - << logsDir.absolutePath(); - } - } -} - -void AppDelegate::downloadLatestExecutablesAndRequirements() { - // Check if Qt is already installed - if (GlobalData::getInstance().getPlatform() == "mac") { - if (QDir(GlobalData::getInstance().getClientsLaunchPath() + "QtCore.framework").exists()) { - _qtReady = true; - } - } else if (GlobalData::getInstance().getPlatform() == "win") { - if (QFileInfo(GlobalData::getInstance().getClientsLaunchPath() + "Qt5Core.dll").exists()) { - _qtReady = true; - } - } else { // linux - if (QFileInfo(GlobalData::getInstance().getClientsLaunchPath() + "libQt5Core.so.5").exists()) { - _qtReady = true; - } - } - - - QFile reqZipFile(GlobalData::getInstance().getRequirementsZipPath()); - QByteArray reqZipData; - if (reqZipFile.open(QIODevice::ReadOnly)) { - reqZipData = reqZipFile.readAll(); - reqZipFile.close(); - } - QFile resZipFile(GlobalData::getInstance().getDomainServerResourcesZipPath()); - QByteArray resZipData; - if (resZipFile.open(QIODevice::ReadOnly)) { - resZipData = resZipFile.readAll(); - resZipFile.close(); - } - - QDir resourcesDir(GlobalData::getInstance().getClientsResourcesPath()); - if (!(resourcesDir.entryInfoList(QDir::AllEntries).size() < 3)) { - _dsResourcesReady = true; - } - - // if the user has set hifiBuildDirectory, don't attempt to download the domain-server or assignement-client - if (GlobalData::getInstance().isGetHifiBuildDirectorySet()) { - _dsReady = true; - _acReady = true; - } else { - QByteArray dsData; - QFile dsFile(GlobalData::getInstance().getDomainServerExecutablePath()); - if (dsFile.open(QIODevice::ReadOnly)) { - dsData = dsFile.readAll(); - dsFile.close(); - } - QByteArray acData; - QFile acFile(GlobalData::getInstance().getAssignmentClientExecutablePath()); - if (acFile.open(QIODevice::ReadOnly)) { - acData = acFile.readAll(); - acFile.close(); - } - - QNetworkRequest acReq(QUrl(GlobalData::getInstance().getAssignmentClientMD5URL())); - QNetworkReply* acReply = _manager->get(acReq); - QEventLoop acLoop; - connect(acReply, SIGNAL(finished()), &acLoop, SLOT(quit())); - acLoop.exec(); - QByteArray acMd5Data = acReply->readAll().trimmed(); - if (GlobalData::getInstance().getPlatform() == "win") { - // fix for reading the MD5 hash from Windows-generated - // binary data of the MD5 hash - QTextStream stream(acMd5Data); - stream >> acMd5Data; - } - - // fix for Mac and Linux network accessibility - if (acMd5Data.size() == 0) { - // network is not accessible - qDebug() << "Could not connect to the internet."; - _window->show(); - return; - } - - qDebug() << "AC MD5: " << acMd5Data; - if (acMd5Data.toLower() == QCryptographicHash::hash(acData, QCryptographicHash::Md5).toHex()) { - _acReady = true; - } - - - QNetworkRequest dsReq(QUrl(GlobalData::getInstance().getDomainServerMD5URL())); - QNetworkReply* dsReply = _manager->get(dsReq); - QEventLoop dsLoop; - connect(dsReply, SIGNAL(finished()), &dsLoop, SLOT(quit())); - dsLoop.exec(); - QByteArray dsMd5Data = dsReply->readAll().trimmed(); - if (GlobalData::getInstance().getPlatform() == "win") { - // fix for reading the MD5 hash from Windows generated - // binary data of the MD5 hash - QTextStream stream(dsMd5Data); - stream >> dsMd5Data; - } - qDebug() << "DS MD5: " << dsMd5Data; - if (dsMd5Data.toLower() == QCryptographicHash::hash(dsData, QCryptographicHash::Md5).toHex()) { - _dsReady = true; - } - } - - if (_qtReady) { - // check MD5 of requirements.zip only if Qt is found - QNetworkRequest reqZipReq(QUrl(GlobalData::getInstance().getRequirementsMD5URL())); - QNetworkReply* reqZipReply = _manager->get(reqZipReq); - QEventLoop reqZipLoop; - connect(reqZipReply, SIGNAL(finished()), &reqZipLoop, SLOT(quit())); - reqZipLoop.exec(); - QByteArray reqZipMd5Data = reqZipReply->readAll().trimmed(); - if (GlobalData::getInstance().getPlatform() == "win") { - // fix for reading the MD5 hash from Windows generated - // binary data of the MD5 hash - QTextStream stream(reqZipMd5Data); - stream >> reqZipMd5Data; - } - qDebug() << "Requirements ZIP MD5: " << reqZipMd5Data; - if (reqZipMd5Data.toLower() != QCryptographicHash::hash(reqZipData, QCryptographicHash::Md5).toHex()) { - _qtReady = false; - } - } - - if (_dsResourcesReady) { - // check MD5 of resources.zip only if Domain Server - // resources are installed - QNetworkRequest resZipReq(QUrl(GlobalData::getInstance().getDomainServerResourcesMD5URL())); - QNetworkReply* resZipReply = _manager->get(resZipReq); - QEventLoop resZipLoop; - connect(resZipReply, SIGNAL(finished()), &resZipLoop, SLOT(quit())); - resZipLoop.exec(); - QByteArray resZipMd5Data = resZipReply->readAll().trimmed(); - if (GlobalData::getInstance().getPlatform() == "win") { - // fix for reading the MD5 hash from Windows generated - // binary data of the MD5 hash - QTextStream stream(resZipMd5Data); - stream >> resZipMd5Data; - } - qDebug() << "Domain Server Resources ZIP MD5: " << resZipMd5Data; - if (resZipMd5Data.toLower() != QCryptographicHash::hash(resZipData, QCryptographicHash::Md5).toHex()) { - _dsResourcesReady = false; - } - } - - DownloadManager* downloadManager = 0; - if (!_qtReady || !_acReady || !_dsReady || !_dsResourcesReady) { - // initialise DownloadManager - downloadManager = new DownloadManager(_manager); - downloadManager->setWindowModality(Qt::ApplicationModal); - connect(downloadManager, SIGNAL(fileSuccessfullyInstalled(QUrl)), - SLOT(onFileSuccessfullyInstalled(QUrl))); - downloadManager->show(); - } else { - _window->setRequirementsLastChecked(QDateTime::currentDateTime().toString()); - _window->show(); - toggleStack(true); - } - - if (!_qtReady) { - downloadManager->downloadFile(GlobalData::getInstance().getRequirementsURL()); - } - - if (!_acReady) { - downloadManager->downloadFile(GlobalData::getInstance().getAssignmentClientURL()); - } - - if (!_dsReady) { - downloadManager->downloadFile(GlobalData::getInstance().getDomainServerURL()); - } - - if (!_dsResourcesReady) { - downloadManager->downloadFile(GlobalData::getInstance().getDomainServerResourcesURL()); - } -} - void AppDelegate::checkVersion() { QNetworkRequest latestVersionRequest((QUrl(CHECK_BUILDS_URL))); latestVersionRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); diff --git a/stack-manager/src/AppDelegate.h b/stack-manager/src/AppDelegate.h index 1d4728b7ce..ebcb8ce904 100644 --- a/stack-manager/src/AppDelegate.h +++ b/stack-manager/src/AppDelegate.h @@ -53,7 +53,6 @@ signals: void indexPathChangeResponse(bool wasSuccessful); void stackStateChanged(bool isOn); private slots: - void onFileSuccessfullyInstalled(const QUrl& url); void requestDomainServerID(); void handleDomainIDReply(); void handleDomainGetReply(); @@ -64,16 +63,10 @@ private slots: private: void parseCommandLine(); - void createExecutablePath(); - void downloadLatestExecutablesAndRequirements(); void changeDomainServerIndexPath(const QString& newPath); QNetworkAccessManager* _manager; - bool _qtReady; - bool _dsReady; - bool _dsResourcesReady; - bool _acReady; BackgroundProcess* _domainServerProcess; BackgroundProcess* _acMonitorProcess; QHash _scriptProcesses; diff --git a/stack-manager/src/GlobalData.cpp b/stack-manager/src/GlobalData.cpp index ecc5ed520d..3078b3b24a 100644 --- a/stack-manager/src/GlobalData.cpp +++ b/stack-manager/src/GlobalData.cpp @@ -32,11 +32,8 @@ GlobalData::GlobalData() { _resourcePath = "resources/"; _assignmentClientExecutable = "assignment-client"; _domainServerExecutable = "domain-server"; - QString applicationSupportDirectory = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - if (PR_BUILD) { - applicationSupportDirectory += "/pr-binaries"; - } - + QString applicationSupportDirectory = QCoreApplication::applicationDirPath(); + _clientsLaunchPath = QDir::toNativeSeparators(applicationSupportDirectory + "/"); _clientsResourcePath = QDir::toNativeSeparators(applicationSupportDirectory + "/" + _resourcePath); @@ -49,18 +46,6 @@ GlobalData::GlobalData() { _domainServerExecutablePath.append(".exe"); } - _requirementsURL = urlBase + "/binaries/" + _platform + "/requirements/requirements.zip"; - _requirementsZipPath = _clientsLaunchPath + "requirements.zip"; - _requirementsMD5URL = urlBase + "/binaries/" + _platform + "/requirements/requirements.md5"; - _assignmentClientURL = urlBase + "/binaries/" + _platform + "/assignment-client" + (_platform == "win" ? "/assignment-client.exe" : "/assignment-client"); - _domainServerResourcesURL = urlBase + "/binaries/" + _platform + "/domain-server/resources.zip"; - _domainServerResourcesZipPath = _clientsLaunchPath + "resources.zip"; - _domainServerResourcesMD5URL = urlBase + "/binaries/" + _platform + "/domain-server/resources.md5"; - _domainServerURL = urlBase + "/binaries/" + _platform + "/domain-server" + (_platform == "win" ? "/domain-server.exe" : "/domain-server"); - - _assignmentClientMD5URL = urlBase + "/binaries/" + _platform + "/assignment-client/assignment-client.md5"; - _domainServerMD5URL = urlBase + "/binaries/" + _platform + "/domain-server/domain-server.md5"; - _defaultDomain = "localhost"; _logsPath = QDir::toNativeSeparators(_clientsLaunchPath + "logs/"); _availableAssignmentTypes.insert("audio-mixer", 0); diff --git a/stack-manager/src/GlobalData.h b/stack-manager/src/GlobalData.h index 58c9a93526..a8687f31d2 100644 --- a/stack-manager/src/GlobalData.h +++ b/stack-manager/src/GlobalData.h @@ -9,6 +9,7 @@ #ifndef hifi_GlobalData_h #define hifi_GlobalData_h +#include #include #include From a37262465f60bc932bb63311ff9d26b17db1c157 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Fri, 27 Nov 2015 14:23:38 -0600 Subject: [PATCH 040/174] Creating icons --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d5f615949c..dc11d28a2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,6 +230,8 @@ set(CPACK_PACKAGE_VERSION_MAJOR "${BUILD_SEQ}") set(CPACK_PACKAGE_VERSION_MINOR "0") set(CPACK_PACKAGE_VERSION_PATCH "0") set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity") +set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Interface.lnk' '$INSTDIR\\\\interface.exe'") +set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\StacK Manager.lnk' '$INSTDIR\\\\stack-manager.exe'") if (WIN32) install(DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment/ DESTINATION "./") From fe0a732b5dc46a38099779c7ea1d3b091681bd06 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 27 Nov 2015 13:11:00 -0800 Subject: [PATCH 041/174] remove rattest file --- examples/libraries/ratTest.js | 256 ---------------------------------- 1 file changed, 256 deletions(-) delete mode 100644 examples/libraries/ratTest.js diff --git a/examples/libraries/ratTest.js b/examples/libraries/ratTest.js deleted file mode 100644 index c173de6f2b..0000000000 --- a/examples/libraries/ratTest.js +++ /dev/null @@ -1,256 +0,0 @@ -Script.include('steer.js'); -var steer = loadSteer(); -Script.include('tween.js'); -var TWEEN = loadTween(); - -var RAT_NEST_LOCATION = { - x: 0, - y: 0, - z: 0 -}; - -var RAT_SPAWNER_LOCATION = { - x: 0, - y: 0, - z: 0 -}; - -var AVOIDER_BLOCK_START_LOCATION = { - x: 0, - y: 0, - z: 0 -}; - -var ratProperties = { - name: 'Hifi-Rat-Nest', - type: 'Box', - color: { - red: 0, - green: 0, - blue: 255 - }, - dimensions: { - x: 1, - y: 1, - z: 1 - }, - position: RAT_SPAWNER_LOCATION -}; - -var targetProperties = { - name: 'Hifi-Rat', - type: 'Box', - color: { - red: 0, - green: 255, - blue: 0 - }, - dimensions: { - x: 1, - y: 1, - z: 1 - }, - position: RAT_NEST_LOCATION - // script: Script.resolvePath('rat.js') -}; - -var target = Entities.addEntity(targetProperties) - -function addRat() { - var rat = Entities.addEntity(ratProperties); - rats.push(rat); -} - -var rats = []; -addRat(); - -var avoiders = []; - -function addAvoiderBlock() { - - var avoiderProperties = { - name: 'Hifi-Rat-Avoider', - type: 'Box', - color: { - red: 255, - green: 0, - blue: 255 - }, - dimensions: { - x: 1, - y: 1, - z: 1 - }, - position: { - x: 1, - y: 1, - z: 1 - }, - collisionsWillMove:false, - ignoreForCollisions:true, - visible: true - } - - var avoider = Entities.addEntity(avoiderProperties); - avoiders.push(avoider) -} - -addAvoiderBlock(); -tweenAvoider(avoiders[0]); - -function tweenAvoider(entityID) { - var ANIMATION_DURATION = 500; - - var begin = { - x: 1, - y: 1, - z: 1 - } - var target = { - x: 3, - y: 1, - z: 3 - } - var original = { - x: 1, - y: 1, - z: 1 - } - var tweenHead = new TWEEN.Tween(begin).to(target, ANIMATION_DURATION); - - function updateTo() { - Entities.editEntity(entityID, { - position: { - x: begin.x, - y: begin.y, - z: begin.z - } - }) - } - - function updateBack() { - Entities.editEntity(entityID, { - position: { - x: begin.x, - y: begin.y, - z: begin.z - } - }) - } - var tweenBack = new TWEEN.Tween(begin).to(original, ANIMATION_DURATION).onUpdate(updateBack); - - tweenHead.onUpdate(function() { - updateTo() - }) - tweenHead.chain(tweenBack); - tweenBack.chain(tweenHead); - tweenHead.start(); - -} - -function updateTweens() { - TWEEN.update(); -} - -function moveRats() { - rats.forEach(function(rat) { - // print('debug1') - - var avatarFlightVectors = steer.fleeAllAvatars(rat); - print('avatarFlightVectors' + avatarFlightVectors) - var i; - var averageAvatarFlight; - - for (i = 0; i < avatarFlightVectors.length; i++) { - print('debug2') - - if (i === 0) { - averageAvatarFlight = avatarFlightVectors[0]; - } else { - averageAvatarFlight = Vec3.sum(avatarFlightVectors[i - 1], avatarFlightVectors[i]) - } - } - - averageAvatarFlight = Vec3.multiply(averageAvatarFlight, 1 / avatarFlightVectors.length); - - - // var avoidBlockVectors = steer.fleeAvoiderBlocks(rat); - - // var averageAvoiderFlight; - - // for (i = 0; i < avoidBlockVectors.length; i++) { - // if (i === 0) { - // averageAvoiderFlight = avoidBlockVectors[0]; - // } else { - // averageAvoiderFlight = Vec3.sum(avoidBlockVectors[i - 1], avoidBlockVectors[i]) - // } - // } - - // averageAvoiderFlight = Vec3.multiply(averageAvoiderFlight, 1 / avoidBlockVectors.length); - - - - var averageVector; - var seek = steer.arrive(rat, target); - averageVector = seek; - var divisorCount = 1; - if (avatarFlightVectors.length > 0) { - divisorCount++; - averageVector = Vec3.sum(averageVector, averageAvatarFlight); - } - // if (avoidBlockVectors > 0) { - // divisorCount++ - // averageVector = Vec3.sum(averageVector, averageAvoiderFlight); - // } - - averageVector = Vec3.multiply(averageVector, 1 / divisorCount); - print('AVERAGE VECTOR:::' + JSON.stringify(averageVector)) - // castRay(rat); - Entities.editEntity(rat, { - velocity: averageVector - }) - - }) -} - -Script.update.connect(moveRats) -Script.update.connect(updateTweens); - -function castRay(rat) { - var ratProps = Entities.getEntityProperties(rat, ["position", "rotation"]); - var shotDirection = Quat.getFront(ratProps.rotation); - var pickRay = { - origin: ratProps.position, - direction: shotDirection - }; - - var intersection = Entities.findRayIntersection(pickRay, true); - if (intersection.intersects) { - var distance = Vec3.subtract(intersection.properties.position, ratProps.position); - distance = Vec3.length(distance); - // print('INTERSECTION:::'+distance); - } else { - print('no intersection') - } -} - -function cleanup() { - while (rats.length > 0) { - Entities.deleteEntity(rats.pop()); - } - - while (avoiders.length > 0) { - Entities.deleteEntity(avoiders.pop()); - } - Entities.deleteEntity(target); - Script.update.disconnect(moveRats); - Script.update.disconnect(updateTweens); - - -} - -Script.scriptEnding.connect(cleanup) - -// Script.setInterval(function() { -// addRat(); -// }) \ No newline at end of file From 5822386702d04ee5e048417c91c3e6d95d22af11 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Mon, 30 Nov 2015 08:56:30 -0600 Subject: [PATCH 042/174] Checkpoint --- CMakeLists.txt | 32 +++++++++++-------- cmake/macros/ConsolidateStackComponents.cmake | 2 ++ 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc11d28a2e..500c27791b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,19 +222,23 @@ if (HIFI_MEMORY_DEBUGGING) endif (UNIX) endif () -set(CPACK_PACKAGE_NAME "High Fidelity") -set(CPACK_PACKAGE_VENDOR "High Fidelity, Inc") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "High Fidelity Interface and Stack") -set(CPACK_PACKAGE_VERSION "${BUILD_SEQ}") -set(CPACK_PACKAGE_VERSION_MAJOR "${BUILD_SEQ}") -set(CPACK_PACKAGE_VERSION_MINOR "0") -set(CPACK_PACKAGE_VERSION_PATCH "0") -set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity") -set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Interface.lnk' '$INSTDIR\\\\interface.exe'") -set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\StacK Manager.lnk' '$INSTDIR\\\\stack-manager.exe'") +include_application_version() -if (WIN32) - install(DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment/ DESTINATION "./") -endif (WIN32) +if (DEFINED ENV{ghprbPullId}) + set(CPACK_PACKAGE_NAME "High Fidelity - Test Build") + set(CPACK_PACKAGE_VENDOR "High Fidelity, Inc") + set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "High Fidelity Interface and Stack") + set(CPACK_PACKAGE_VERSION "${BUILD_SEQ}") + set(CPACK_PACKAGE_VERSION_MAJOR "${BUILD_SEQ}") + set(CPACK_PACKAGE_VERSION_MINOR "0") + set(CPACK_PACKAGE_VERSION_PATCH "0") + set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity - Test Build") + set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Interface.lnk' '$INSTDIR\\\\interface.exe'") + set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\StacK Manager.lnk' '$INSTDIR\\\\stack-manager.exe'") -include(CPack) \ No newline at end of file + if (WIN32) + install(DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment/ DESTINATION "./") + endif (WIN32) + + include(CPack) +endif () \ No newline at end of file diff --git a/cmake/macros/ConsolidateStackComponents.cmake b/cmake/macros/ConsolidateStackComponents.cmake index 2b2fe9a691..50a1f5e48a 100644 --- a/cmake/macros/ConsolidateStackComponents.cmake +++ b/cmake/macros/ConsolidateStackComponents.cmake @@ -1,9 +1,11 @@ macro(CONSOLIDATE_STACK_COMPONENTS) + if (DEFINED ENV{ghprbPullId}) # Copy all the output for this target into the common deployment location add_custom_command( TARGET ${TARGET_NAME} POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory $ ${CMAKE_BINARY_DIR}/full-stack-deployment ) + endif () endmacro() \ No newline at end of file From 4e186409221b2adbc9ace33c1b7101796ca63a71 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Mon, 30 Nov 2015 10:07:11 -0600 Subject: [PATCH 043/174] Some fixes --- CMakeLists.txt | 6 +++--- cmake/macros/IncludeApplicationVersion.cmake | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 500c27791b..47368a0f4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,16 +225,16 @@ endif () include_application_version() if (DEFINED ENV{ghprbPullId}) - set(CPACK_PACKAGE_NAME "High Fidelity - Test Build") + set(CPACK_PACKAGE_NAME "High Fidelity") set(CPACK_PACKAGE_VENDOR "High Fidelity, Inc") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "High Fidelity Interface and Stack") set(CPACK_PACKAGE_VERSION "${BUILD_SEQ}") set(CPACK_PACKAGE_VERSION_MAJOR "${BUILD_SEQ}") set(CPACK_PACKAGE_VERSION_MINOR "0") set(CPACK_PACKAGE_VERSION_PATCH "0") - set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity - Test Build") + set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity-${BUILD_SEQ}") set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Interface.lnk' '$INSTDIR\\\\interface.exe'") - set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\StacK Manager.lnk' '$INSTDIR\\\\stack-manager.exe'") + set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Stack Manager.lnk' '$INSTDIR\\\\stack-manager.exe'") if (WIN32) install(DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment/ DESTINATION "./") diff --git a/cmake/macros/IncludeApplicationVersion.cmake b/cmake/macros/IncludeApplicationVersion.cmake index 96137294a7..a2993efbd2 100644 --- a/cmake/macros/IncludeApplicationVersion.cmake +++ b/cmake/macros/IncludeApplicationVersion.cmake @@ -13,7 +13,7 @@ macro(INCLUDE_APPLICATION_VERSION) if (DEFINED ENV{JOB_ID}) set (BUILD_SEQ $ENV{JOB_ID}) elseif (DEFINED ENV{ghprbPullId}) - set (BUILD_SEQ "PR: $ENV{ghprbPullId} - Commit: $ENV{ghprbActualCommit}") + set (BUILD_SEQ "PR.$ENV{ghprbPullId}") else () set(BUILD_SEQ "dev") endif () From cd4ac8ac69880f11626a27dce090f4e2c22b206d Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 30 Nov 2015 12:44:06 -0800 Subject: [PATCH 044/174] good enough --- examples/drylake/ratCreator.js | 25 +++++++++++++++---------- examples/drylake/steer.js | 14 +++++++------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 0edd348f1a..f653d59e9e 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -7,7 +7,7 @@ var USE_CONSTANT_SPAWNER = true; var RAT_SPAWNER_LOCATION = { x: 1001, - y: 98.5, + y: 97.5, z: 1039 }; @@ -35,7 +35,6 @@ var RAT_IN_NEST_DISTANCE = 3; var RAT_SPAWN_RATE = 2500; function playRatRunningAnimation(rat) { - print('RUN RAT') var animationSettings = JSON.stringify({ running: true }); @@ -72,15 +71,19 @@ var modelRatProperties = { dimensions: RAT_DIMENSIONS, position: RAT_SPAWNER_LOCATION, shapeType: 'Box', + damping:0.8, + angularDamping:0.99, + friction:0.75, + // restitution:0.1, collisionsWillMove: true, ignoreForCollisions: false, gravity: { x: 0, - y: -19.8, + y: -9.8, z: 0 }, lifetime: 30, - rotation: Quat.fromPitchYawRollDegrees(0, 180, 0), + // rotation: Quat.fromPitchYawRollDegrees(0, 180, 0), //disable this if for some reason we want grabbable rats userData: JSON.stringify({ grabbableKey: { @@ -286,17 +289,19 @@ function moveRats() { averageVector = Vec3.multiply(averageVector, 1 / divisorCount); var thisRatProps = Entities.getEntityProperties(rat, ["position", "rotation"]); - var eulerAngle = Quat.safeEulerAngles(thisRatProps.rotation); - eulerAngle.x = 0; - eulerAngle.z = 0; - var constrainedRotation = Quat.fromVec3Degrees(eulerAngle); + + // var constrainedRotation = Quat.fromVec3Degrees(eulerAngle); // print('CR:::'+JSON.stringify(constrainedRotation)) var ratPosition = thisRatProps.position; var ratToNest = Vec3.subtract(RAT_NEST_LOCATION, ratPosition); - var ratRotation = Quat.rotationBetween(Vec3.UNIT_Z, ratToNest); - + var ratRotation = Quat.rotationBetween(Vec3.UNIT_Z, ratToNest); + var eulerAngle = Quat.safeEulerAngles(ratRotation); + eulerAngle.x = 0; + eulerAngle.z = 0; + var constrainedRotation = Quat.fromVec3Degrees(eulerAngle) + Entities.editEntity(rat, { velocity: averageVector, rotation: constrainedRotation, diff --git a/examples/drylake/steer.js b/examples/drylake/steer.js index 7068273e4d..0a44da5ab5 100644 --- a/examples/drylake/steer.js +++ b/examples/drylake/steer.js @@ -66,15 +66,15 @@ function fleeAvoiderBlocks(thisEntity) { var location = properties.position; var velocity = properties.velocity; - var nearbyEntities = Entities.findEntities(location, 4); + var nearbyEntities = Entities.findEntities(location, 2); var flightVectors = []; for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { var entityID = nearbyEntities[entityIndex]; var entityProps = Entities.getEntityProperties(entityID); if (entityProps.name === 'Hifi-Rat-Avoider') { - // print('found an avoiderblock to flee'); + // print('found an avoiderblock to flee'); - var MAX_SPEED = 8; + var MAX_SPEED = 11; var MAX_FORCE = 6; var desired = Vec3.subtract(location, entityProps.position); @@ -83,7 +83,7 @@ function fleeAvoiderBlocks(thisEntity) { desired = Vec3.multiply(MAX_SPEED, desired); if (d < 5) { var steer = Vec3.subtract(desired, velocity); - var steerVector = new V3(desired.x, desired.y, desired.z); + var steerVector = new V3(desired.x, 0, desired.z); steer = steerVector.limit(MAX_FORCE) flightVectors.push(steer); } else { @@ -102,9 +102,9 @@ function arrive(thisEntity, target) { var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; - var MAX_SPEED = 12; - var MAX_FORCE = 8; - var ARRIVAL_DISTANCE = 3; + var MAX_SPEED = 10; + var MAX_FORCE = 6; + var ARRIVAL_DISTANCE = 5; var desired = Vec3.subtract(targetPosition, location); var d = Vec3.length(desired); From 8267c70bb18bf6fcc916336028ac512de07182de Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 30 Nov 2015 12:45:10 -0800 Subject: [PATCH 045/174] hide avoiders --- examples/drylake/ratCreator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index f653d59e9e..19374ef5de 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -173,7 +173,7 @@ function addAvoiderBlock(position) { position: position, collisionsWillMove: false, ignoreForCollisions: true, - visible: true + visible: false }; var avoider = Entities.addEntity(avoiderProperties); From ca8cd13c4876775843ee941d2b057e5f4fd9c084 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Tue, 1 Dec 2015 12:32:31 -0600 Subject: [PATCH 046/174] Checkpoint --- cmake/macros/ConsolidateStackComponents.cmake | 2 +- cmake/modules/FindOpenSSL.cmake | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cmake/macros/ConsolidateStackComponents.cmake b/cmake/macros/ConsolidateStackComponents.cmake index 50a1f5e48a..2a991e5d03 100644 --- a/cmake/macros/ConsolidateStackComponents.cmake +++ b/cmake/macros/ConsolidateStackComponents.cmake @@ -1,6 +1,6 @@ macro(CONSOLIDATE_STACK_COMPONENTS) - if (DEFINED ENV{ghprbPullId}) + if (DEFINED ENV{ghprbPullId} AND WIN32) # Copy all the output for this target into the common deployment location add_custom_command( TARGET ${TARGET_NAME} POST_BUILD diff --git a/cmake/modules/FindOpenSSL.cmake b/cmake/modules/FindOpenSSL.cmake index 2142322687..2a15cf7929 100644 --- a/cmake/modules/FindOpenSSL.cmake +++ b/cmake/modules/FindOpenSSL.cmake @@ -107,7 +107,7 @@ if (WIN32 AND NOT CYGWIN) select_library_configurations(SSL_EAY) set(OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY}) - + find_path(OPENSSL_DLL_PATH NAMES ssleay32.dll PATH_SUFFIXES "bin" ${_OPENSSL_ROOT_HINTS_AND_PATHS}) elseif (MINGW) @@ -250,8 +250,18 @@ else () ) endif () + + message(STATUS "++++++++++++++++++++++++++++") + message(STATUS "${OPENSSL_LIBRARIES}") + message(STATUS "${OPENSSL_DLL_PATH}") if (WIN32) add_paths_to_fixup_libs(${OPENSSL_DLL_PATH}) + if (DEFINED ENV{ghprbPullId}) + add_custom_command( + TARGET ${TARGET_NAME} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy ${OPENSSL_DLL_PATH}/ssleay32.dll ${CMAKE_BINARY_DIR}/full-stack-deployment + ) + endif () endif () mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES OPENSSL_SEARCH_DIRS) From c786789c4cd11996b63bd4cea2ead9eabaf05597 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Wed, 2 Dec 2015 12:43:25 -0600 Subject: [PATCH 047/174] Changes for SSL and icons --- CMakeLists.txt | 15 ++++++++-- cmake/macros/ConsolidateStackComponents.cmake | 28 +++++++++++++++---- cmake/macros/IncludeApplicationVersion.cmake | 7 ++++- cmake/modules/FindOpenSSL.cmake | 11 ++++---- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 47368a0f4e..4b44f81d2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,16 @@ endif () include_application_version() -if (DEFINED ENV{ghprbPullId}) +if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE) + message(STATUS "+++++ Package for deployment will be generated on this build +++++") + + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment) + + set (ICONPATH_INTERFACE "$INSTDIR/${PATH_INSTALL_DATA}/interface.ico") + set (ICONPATH_STACK_MANAGER "$INSTDIR/${PATH_INSTALL_DATA}/stack-manager.ico") + string (REPLACE "/" "\\\\" ICONPATH_INTERFACE ${ICONPATH_INTERFACE}) + string (REPLACE "/" "\\\\" ICONPATH_STACK_MANAGER ${ICONPATH_STACK_MANAGER}) + set(CPACK_PACKAGE_NAME "High Fidelity") set(CPACK_PACKAGE_VENDOR "High Fidelity, Inc") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "High Fidelity Interface and Stack") @@ -233,8 +242,8 @@ if (DEFINED ENV{ghprbPullId}) set(CPACK_PACKAGE_VERSION_MINOR "0") set(CPACK_PACKAGE_VERSION_PATCH "0") set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity-${BUILD_SEQ}") - set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Interface.lnk' '$INSTDIR\\\\interface.exe'") - set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Stack Manager.lnk' '$INSTDIR\\\\stack-manager.exe'") + set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Interface.lnk' '$INSTDIR\\\\interface.exe' '${ICONPATH_INTERFACE}'") + set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Stack Manager.lnk' '$INSTDIR\\\\stack-manager.exe' '${ICONPATH_STACK_MANAGER}'") if (WIN32) install(DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment/ DESTINATION "./") diff --git a/cmake/macros/ConsolidateStackComponents.cmake b/cmake/macros/ConsolidateStackComponents.cmake index 2a991e5d03..4bcc777751 100644 --- a/cmake/macros/ConsolidateStackComponents.cmake +++ b/cmake/macros/ConsolidateStackComponents.cmake @@ -1,11 +1,27 @@ macro(CONSOLIDATE_STACK_COMPONENTS) - if (DEFINED ENV{ghprbPullId} AND WIN32) - # Copy all the output for this target into the common deployment location - add_custom_command( - TARGET ${TARGET_NAME} POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy_directory $ ${CMAKE_BINARY_DIR}/full-stack-deployment - ) + if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE AND WIN32) + + # Copy all the output for this target into the common deployment location + add_custom_command( + TARGET ${TARGET_NAME} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy_directory $ ${CMAKE_BINARY_DIR}/full-stack-deployment + ) + + # Copy icon files for interface and stack manager + if (TARGET_NAME STREQUAL "interface" OR TARGET_NAME STREQUAL "stack-manager") + if (TARGET_NAME STREQUAL "interface") + set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/icon/interface.ico") + set (ICON_DESTINATION_NAME "interface.ico") + elseif (TARGET_NAME STREQUAL "stack-manager") + set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/assets/icon.ico") + set (ICON_DESTINATION_NAME "stack-manager.ico") + endif () + add_custom_command( + TARGET ${TARGET_NAME} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy ${ICON_FILE_PATH} ${CMAKE_BINARY_DIR}/full-stack-deployment/${ICON_DESTINATION_NAME} + ) + endif () endif () endmacro() \ No newline at end of file diff --git a/cmake/macros/IncludeApplicationVersion.cmake b/cmake/macros/IncludeApplicationVersion.cmake index a2993efbd2..a91aad6acc 100644 --- a/cmake/macros/IncludeApplicationVersion.cmake +++ b/cmake/macros/IncludeApplicationVersion.cmake @@ -10,10 +10,15 @@ # macro(INCLUDE_APPLICATION_VERSION) + # + # We are relying on Jenkins defined environment variables to determine the origin of this build + # and will only package if this is a PR or Release build if (DEFINED ENV{JOB_ID}) + set (DEPLOY_PACKAGE 1) set (BUILD_SEQ $ENV{JOB_ID}) elseif (DEFINED ENV{ghprbPullId}) - set (BUILD_SEQ "PR.$ENV{ghprbPullId}") + set (DEPLOY_PACKAGE 1) + set (BUILD_SEQ "PR-$ENV{ghprbPullId}") else () set(BUILD_SEQ "dev") endif () diff --git a/cmake/modules/FindOpenSSL.cmake b/cmake/modules/FindOpenSSL.cmake index 2a15cf7929..9d9557ad9e 100644 --- a/cmake/modules/FindOpenSSL.cmake +++ b/cmake/modules/FindOpenSSL.cmake @@ -250,16 +250,15 @@ else () ) endif () - - message(STATUS "++++++++++++++++++++++++++++") - message(STATUS "${OPENSSL_LIBRARIES}") - message(STATUS "${OPENSSL_DLL_PATH}") if (WIN32) add_paths_to_fixup_libs(${OPENSSL_DLL_PATH}) - if (DEFINED ENV{ghprbPullId}) + # + # For some reason fixup misses the following DLL and only copies libeay32. There's gotta be a better way to handle this + # but for now resorting to the following interm solution + if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE) add_custom_command( TARGET ${TARGET_NAME} POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy ${OPENSSL_DLL_PATH}/ssleay32.dll ${CMAKE_BINARY_DIR}/full-stack-deployment + COMMAND "${CMAKE_COMMAND}" -E copy ${OPENSSL_DLL_PATH}/ssleay32.dll ${CMAKE_BINARY_DIR}/full-stack-deployment/ ) endif () endif () From 252086ea483f32f5097170c9fe11ec3abe2e975c Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Wed, 2 Dec 2015 12:48:58 -0600 Subject: [PATCH 048/174] indentation fixes --- stack-manager/src/AppDelegate.cpp | 6 +++--- stack-manager/src/GlobalData.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stack-manager/src/AppDelegate.cpp b/stack-manager/src/AppDelegate.cpp index 6b350af117..3e65406bc5 100644 --- a/stack-manager/src/AppDelegate.cpp +++ b/stack-manager/src/AppDelegate.cpp @@ -117,9 +117,9 @@ AppDelegate::AppDelegate(int argc, char* argv[]) : connect(this, &QApplication::aboutToQuit, this, &AppDelegate::stopStack); - _window->setRequirementsLastChecked(QDateTime::currentDateTime().toString()); - _window->show(); - toggleStack(true); + _window->setRequirementsLastChecked(QDateTime::currentDateTime().toString()); + _window->show(); + toggleStack(true); } AppDelegate::~AppDelegate() { diff --git a/stack-manager/src/GlobalData.cpp b/stack-manager/src/GlobalData.cpp index 3078b3b24a..bc2f3e3482 100644 --- a/stack-manager/src/GlobalData.cpp +++ b/stack-manager/src/GlobalData.cpp @@ -32,7 +32,7 @@ GlobalData::GlobalData() { _resourcePath = "resources/"; _assignmentClientExecutable = "assignment-client"; _domainServerExecutable = "domain-server"; - QString applicationSupportDirectory = QCoreApplication::applicationDirPath(); + QString applicationSupportDirectory = QCoreApplication::applicationDirPath(); _clientsLaunchPath = QDir::toNativeSeparators(applicationSupportDirectory + "/"); _clientsResourcePath = QDir::toNativeSeparators(applicationSupportDirectory + "/" + _resourcePath); From 8ae05d8490f3c00c3b22089e63ade4b0a2213efe Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 2 Dec 2015 16:40:41 -0800 Subject: [PATCH 049/174] Plugins target frame rate and period. --- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 3 ++- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h | 6 ++++++ .../src/display-plugins/openvr/OpenVrDisplayPlugin.h | 5 +++++ libraries/plugins/src/plugins/DisplayPlugin.h | 2 ++ plugins/oculus/src/OculusDisplayPlugin.h | 5 +++++ plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h | 5 +++++ 6 files changed, 25 insertions(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 9366ec4403..b0dffbb7bc 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -139,7 +139,8 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { } else if (FRAMERATE_30 == actionText) { _framerateTarget = 30; } - } + } + _inverseFrameRate = _framerateTarget ? 1.0f / (float) _framerateTarget : 1.0f / TARGET_FRAMERATE_Basic2DWindowOpenGL; // not truncated int newInterval = getDesiredInterval(); qDebug() << newInterval; diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index f4655ab79f..f6052f82ca 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -9,6 +9,8 @@ #include "WindowOpenGLDisplayPlugin.h" +#define TARGET_FRAMERATE_Basic2DWindowOpenGL 60.0f + class QScreen; class Basic2DWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin { Q_OBJECT @@ -16,6 +18,9 @@ class Basic2DWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin { public: virtual const QString & getName() const override; + virtual float getTargetFrameRate() { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } + virtual float getTargetFramePeriod() { return _inverseFrameRate; } + virtual void activate() override; virtual void deactivate() override; @@ -33,4 +38,5 @@ private: QScreen* getFullscreenTarget(); uint32_t _framerateTarget{ 0 }; int _fullscreenTarget{ -1 }; + float _inverseFrameRate{ 1.0f }; //seconds }; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h index 15d37d9de8..6116cd2283 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -14,12 +14,17 @@ #include "../WindowOpenGLDisplayPlugin.h" +#define TARGET_RATE_OpenVr 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only. + class OpenVrDisplayPlugin : public WindowOpenGLDisplayPlugin { public: virtual bool isSupported() const override; virtual const QString & getName() const override; virtual bool isHmd() const override { return true; } + virtual float getTargetFrameRate() { return TARGET_RATE_OpenVr; } + virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_OpenVr; } + virtual void activate() override; virtual void deactivate() override; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 5b00391f09..ea6060010e 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -57,6 +57,8 @@ public: /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } virtual bool isThrottled() const { return false; } + virtual float getTargetFrameRate() { return 0.0f; } + virtual float getTargetFramePeriod() { return 0.0f; } // Rendering support diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index c1224ecf3a..62cdf35fc7 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -12,12 +12,17 @@ struct SwapFramebufferWrapper; using SwapFboPtr = QSharedPointer; +#define TARGET_RATE_Oculus 75.0f; + class OculusDisplayPlugin : public OculusBaseDisplayPlugin { public: virtual void activate() override; virtual void deactivate() override; virtual const QString & getName() const override; + virtual float getTargetFrameRate() { return TARGET_RATE_Oculus; } + virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_Oculus; } + protected: virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; virtual void customizeContext() override; diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index 6e3f864aee..ca45e201f4 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -13,6 +13,8 @@ #include +#define TARGET_RATE_OculusLegacy 75.0f; + class OculusLegacyDisplayPlugin : public WindowOpenGLDisplayPlugin { public: OculusLegacyDisplayPlugin(); @@ -25,6 +27,9 @@ public: virtual bool eventFilter(QObject* receiver, QEvent* event) override; virtual int getHmdScreen() const override; + virtual float getTargetFrameRate() { return TARGET_RATE_OculusLegacy; } + virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_OculusLegacy; } + // Stereo specific methods virtual bool isHmd() const override { return true; } virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; From 53bfcd17e2537c7930faa3221ab1c74de5a2a482 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 2 Dec 2015 16:41:16 -0800 Subject: [PATCH 050/174] Use plugins data for Application frame rate/period. --- interface/src/Application.cpp | 2 ++ interface/src/Application.h | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ef10ad4464..94aa3949cc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3246,6 +3246,8 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node bool Application::isHMDMode() const { return getActiveDisplayPlugin()->isHmd(); } +float Application::getTargetFrameRate() { return getActiveDisplayPlugin()->getTargetFrameRate(); } +float Application::getTargetFramePeriod() { return getActiveDisplayPlugin()->getTargetFramePeriod(); } QRect Application::getDesirableApplicationGeometry() { QRect applicationGeometry = getWindow()->geometry(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 730158c689..adef152ac5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -159,10 +159,8 @@ public: bool isForeground() const { return _isForeground; } float getFps() const { return _fps; } - float const HMD_TARGET_FRAME_RATE = 75.0f; - float const DESKTOP_TARGET_FRAME_RATE = 60.0f; - float getTargetFrameRate() { return isHMDMode() ? HMD_TARGET_FRAME_RATE : DESKTOP_TARGET_FRAME_RATE; } - float getTargetFramePeriod() { return isHMDMode() ? 1.0f / HMD_TARGET_FRAME_RATE : 1.0f / DESKTOP_TARGET_FRAME_RATE; } // same as 1/getTargetFrameRate, but w/compile-time division + float getTargetFrameRate(); // frames/second + float getTargetFramePeriod(); // seconds float getLastInstanteousFps() const { return _lastInstantaneousFps; } float getLastPaintWait() const { return _lastPaintWait; }; float getLastDeducedNonVSyncFps() const { return _lastDeducedNonVSyncFps; } From ed86a880832d988e05b33b2c8e2b7739e309274b Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 2 Dec 2015 21:48:06 -0800 Subject: [PATCH 051/174] Make various forms of throttling more consistent and give it a chance of actually reaching target. --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index b0dffbb7bc..ea8ffe1e2f 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -90,12 +90,8 @@ void Basic2DWindowOpenGLDisplayPlugin::display(GLuint sceneTexture, const glm::u int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const { - static const int THROTTLED_PAINT_TIMER_DELAY_MS = MSECS_PER_SECOND / 15; static const int ULIMIITED_PAINT_TIMER_DELAY_MS = 1; int result = ULIMIITED_PAINT_TIMER_DELAY_MS; - if (_isThrottled) { - result = THROTTLED_PAINT_TIMER_DELAY_MS; - } if (0 != _framerateTarget) { result = MSECS_PER_SECOND / _framerateTarget; } @@ -139,12 +135,18 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { } else if (FRAMERATE_30 == actionText) { _framerateTarget = 30; } + } else if (_isThrottled) { + _framerateTarget = 15; } _inverseFrameRate = _framerateTarget ? 1.0f / (float) _framerateTarget : 1.0f / TARGET_FRAMERATE_Basic2DWindowOpenGL; // not truncated int newInterval = getDesiredInterval(); + if (_framerateTarget) { // For any target other than vsync, we have little hope of achieving it with timer alone: + const int ALLOWANCE_FOR_DISPLAY_FINISHFRAME_AND_TIMER = 3; // ideally a windowed average of qApp->getLastPaintWait and then some, but not worth the complexity + newInterval -= ALLOWANCE_FOR_DISPLAY_FINISHFRAME_AND_TIMER; // Otherwise, any controller expecting us to hit "target" will always be disappointed. + } qDebug() << newInterval; - _timer.start(getDesiredInterval()); + _timer.start(newInterval); } // FIXME target the screen the window is currently on From a989b926b054fce73e694221646c2c8c385a5db0 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 3 Dec 2015 11:28:26 -0800 Subject: [PATCH 052/174] isVSynchronized, and proper override declarations. --- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 9 +++++---- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.h | 5 +++-- .../src/display-plugins/openvr/OpenVrDisplayPlugin.h | 4 ++-- libraries/plugins/src/plugins/DisplayPlugin.h | 1 + plugins/oculus/src/OculusDisplayPlugin.h | 4 ++-- plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h | 4 ++-- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index ea8ffe1e2f..c0af5609ee 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -113,6 +113,9 @@ bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { return shouldThrottle; } +bool Basic2DWindowOpenGLDisplayPlugin::isVSynchronized() const { + return (_framerateTarget == 0) && (!_vsyncAction || _vsyncAction->isChecked()); +} void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { QAction* checkedFramerate{ nullptr }; @@ -141,10 +144,8 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { _inverseFrameRate = _framerateTarget ? 1.0f / (float) _framerateTarget : 1.0f / TARGET_FRAMERATE_Basic2DWindowOpenGL; // not truncated int newInterval = getDesiredInterval(); - if (_framerateTarget) { // For any target other than vsync, we have little hope of achieving it with timer alone: - const int ALLOWANCE_FOR_DISPLAY_FINISHFRAME_AND_TIMER = 3; // ideally a windowed average of qApp->getLastPaintWait and then some, but not worth the complexity - newInterval -= ALLOWANCE_FOR_DISPLAY_FINISHFRAME_AND_TIMER; // Otherwise, any controller expecting us to hit "target" will always be disappointed. - } + // Note: when not isVSynchronized, we are often not likely to hit target with a newInterval timer. + // We could try subtracting an allowance for qApp->getLastPaintWait() and qt timer machinery, but that starts getting complicated. qDebug() << newInterval; _timer.start(newInterval); } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index f6052f82ca..45d2545a94 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -18,8 +18,8 @@ class Basic2DWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin { public: virtual const QString & getName() const override; - virtual float getTargetFrameRate() { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } - virtual float getTargetFramePeriod() { return _inverseFrameRate; } + virtual float getTargetFrameRate() override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } + virtual float getTargetFramePeriod() override { return _inverseFrameRate; } virtual void activate() override; virtual void deactivate() override; @@ -27,6 +27,7 @@ public: virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) override; virtual bool isThrottled() const override; + virtual bool isVSynchronized() const override; protected: int getDesiredInterval() const; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h index 6116cd2283..390ab4b539 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -22,8 +22,8 @@ public: virtual const QString & getName() const override; virtual bool isHmd() const override { return true; } - virtual float getTargetFrameRate() { return TARGET_RATE_OpenVr; } - virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_OpenVr; } + virtual float getTargetFrameRate() override { return TARGET_RATE_OpenVr; } + virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_OpenVr; } virtual void activate() override; virtual void deactivate() override; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index ea6060010e..729b62f124 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -57,6 +57,7 @@ public: /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } virtual bool isThrottled() const { return false; } + virtual bool isVSynchronized() const { return true; } // false when throttled or run by non vsync timer virtual float getTargetFrameRate() { return 0.0f; } virtual float getTargetFramePeriod() { return 0.0f; } diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index 62cdf35fc7..febfd5b08e 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -20,8 +20,8 @@ public: virtual void deactivate() override; virtual const QString & getName() const override; - virtual float getTargetFrameRate() { return TARGET_RATE_Oculus; } - virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_Oculus; } + virtual float getTargetFrameRate() override { return TARGET_RATE_Oculus; } + virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_Oculus; } protected: virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index ca45e201f4..d0840d3a72 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -27,8 +27,8 @@ public: virtual bool eventFilter(QObject* receiver, QEvent* event) override; virtual int getHmdScreen() const override; - virtual float getTargetFrameRate() { return TARGET_RATE_OculusLegacy; } - virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_OculusLegacy; } + virtual float getTargetFrameRate() override { return TARGET_RATE_OculusLegacy; } + virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_OculusLegacy; } // Stereo specific methods virtual bool isHmd() const override { return true; } From 375211e13b454d64fc7b2d8a33c915119cc5b043 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 3 Dec 2015 11:29:13 -0800 Subject: [PATCH 053/174] Use isVSynchronized in controller. --- interface/src/Application.cpp | 1 + interface/src/Application.h | 1 + interface/src/avatar/AvatarManager.cpp | 22 +++++++++++++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 94aa3949cc..921c126ce6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3248,6 +3248,7 @@ bool Application::isHMDMode() const { } float Application::getTargetFrameRate() { return getActiveDisplayPlugin()->getTargetFrameRate(); } float Application::getTargetFramePeriod() { return getActiveDisplayPlugin()->getTargetFramePeriod(); } +bool Application::isVSynchronized() const { return getActiveDisplayPlugin()->isVSynchronized(); } QRect Application::getDesirableApplicationGeometry() { QRect applicationGeometry = getWindow()->geometry(); diff --git a/interface/src/Application.h b/interface/src/Application.h index adef152ac5..5c952f462e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -124,6 +124,7 @@ public: PickRay computePickRay() const; bool isThrottleRendering() const; + bool isVSynchronized() const; Camera* getCamera() { return &_myCamera; } // Represents the current view frustum of the avatar. diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index e094f2e263..0ee07d15ec 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -146,13 +146,21 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { PerformanceTimer perfTimer("otherAvatars"); - _renderDistanceController.setMeasuredValueSetpoint(qApp->getTargetFrameRate()); // No problem updating in flight. - // The PID controller raises the controlled value when the measured value goes up. - // The measured value is frame rate. When the controlled value (1 / render cutoff distance) - // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate - // goes up. - const float deduced = qApp->getLastDeducedNonVSyncFps(); - const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime); + float distance; + if (qApp->isVSynchronized()) { + _renderDistanceController.setMeasuredValueSetpoint(qApp->getTargetFrameRate()); // No problem updating in flight. + // The PID controller raises the controlled value when the measured value goes up. + // The measured value is frame rate. When the controlled value (1 / render cutoff distance) + // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate + // goes up. + const float deduced = qApp->getLastDeducedNonVSyncFps(); + distance = 1.0f / _renderDistanceController.update(deduced, deltaTime); + } else { + // We could keep the controller running when not vsync'd, if getLastDeducedNonVSyncFps is still meaningful. + // But the basic 2d controller doesn't try to adjust the timer for qt load or getLastPaintWait, so running the + // Here we choose to just use the maximum render cutoff distance if: throttled, running without vsync, or 30-60 "fixed" targets. + distance = 1.0f / _renderDistanceController.getControlledValueLowLimit(); + } _renderDistanceAverage.updateAverage(distance); _renderDistance = _renderDistanceAverage.getAverage(); int renderableCount = 0; From 30bbc82c245ddd357bb3f54abd9046f0c9f63a05 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 3 Dec 2015 13:00:07 -0800 Subject: [PATCH 054/174] Restore throttling interval code. --- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index c0af5609ee..8633628fef 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -88,10 +88,15 @@ void Basic2DWindowOpenGLDisplayPlugin::display(GLuint sceneTexture, const glm::u WindowOpenGLDisplayPlugin::display(sceneTexture, sceneSize); } - +#define THROTTLED_FRAMERATE 15 int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const { static const int ULIMIITED_PAINT_TIMER_DELAY_MS = 1; int result = ULIMIITED_PAINT_TIMER_DELAY_MS; + // This test wouldn't be necessary if we could depend on updateFramerate setting _framerateTarget. + // Alas, that gets complicated: isThrottled() is const and other stuff depends on it. + if (_isThrottled) { + result = MSECS_PER_SECOND / THROTTLED_FRAMERATE; + } if (0 != _framerateTarget) { result = MSECS_PER_SECOND / _framerateTarget; } @@ -139,7 +144,7 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { _framerateTarget = 30; } } else if (_isThrottled) { - _framerateTarget = 15; + _framerateTarget = (float) THROTTLED_FRAMERATE; } _inverseFrameRate = _framerateTarget ? 1.0f / (float) _framerateTarget : 1.0f / TARGET_FRAMERATE_Basic2DWindowOpenGL; // not truncated From f5b25791f466402549cdaaa066d1519854ad0532 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 3 Dec 2015 13:39:41 -0800 Subject: [PATCH 055/174] When throttling starts, we won't have noticed, so change test. --- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 8633628fef..b3719265ea 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -119,7 +119,7 @@ bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { } bool Basic2DWindowOpenGLDisplayPlugin::isVSynchronized() const { - return (_framerateTarget == 0) && (!_vsyncAction || _vsyncAction->isChecked()); + return (_framerateTarget == 0) && !_isThrottled; } void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { From 9c5486fb4b407e80a3876422ed04f3c6901f30ad Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Nov 2015 12:58:35 -0800 Subject: [PATCH 056/174] More particle work --- .../RenderableParticleEffectEntityItem.cpp | 24 +++++------ .../src/textured_particle.slv | 40 +------------------ 2 files changed, 12 insertions(+), 52 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 86a0603569..a03d2a9b14 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -26,16 +26,15 @@ static const size_t VERTEX_PER_PARTICLE = 4; -template -struct InterpolationData { - T start; - T middle; - T finish; - T spread; -}; - class ParticlePayloadData { public: + template + struct InterpolationData { + T start; + T middle; + T finish; + T spread; + }; struct ParticleUniforms { InterpolationData radius; InterpolationData color; // rgba @@ -207,19 +206,17 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { using ParticleUniforms = ParticlePayloadData::ParticleUniforms; using ParticlePrimitive = ParticlePayloadData::ParticlePrimitive; using ParticlePrimitives = ParticlePayloadData::ParticlePrimitives; - - ParticleUniforms particleUniforms; + // Fill in Uniforms structure + ParticleUniforms particleUniforms; particleUniforms.radius.start = getRadiusStart(); 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.lifespan = getLifespan(); // Build particle primitives @@ -254,8 +251,7 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { payload.setModelTransform(transform); payload.setBound(bounds); - bool textured = _texture && _texture->isLoaded(); - if (textured) { + if (_texture && _texture->isLoaded()) { payload.setTexture(_texture->getGPUTexture()); payload.setPipeline(_texturedPipeline); } else { diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index cd5dd75101..0d915a3468 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -61,43 +61,7 @@ float interpolate3Floats(float y1, float y2, float y3, float u) { // Flat line. return y2; } - - if ((y2 >= y1 && y2 >= y3) || (y2 <= y1 && y2 <= y3)) { - // U or inverted-U shape. - // Make the slope at y2 = 0, which means that the control points half way between the value points have the value y2. - if (u <= 0.5) { - return bezierInterpolate(y1, y2, y2, 2.0 * u); - } else { - return bezierInterpolate(y2, y2, y3, 2.0 * u - 1.0); - } - - } else { - // L or inverted and/or mirrored L shape. - // Make the slope at y2 be the slope between y1 and y3, up to a maximum of double the minimum of the slopes between y1 - // and y2, and y2 and y3. Use this slope to calculate the control points half way between the value points. - // Note: The maximum ensures that the control points and therefore the interpolated values stay between y1 and y3. - float slope = y3 - y1; - float slope12 = y2 - y1; - float slope23 = y3 - y2; - if (abs(slope) > abs(2.0 * slope12)) { - slope = 2.0 * slope12; - } else if (abs(slope) > abs(2.0 * slope23)) { - slope = 2.0 * slope23; - } - - if (u <= 0.5) { - return bezierInterpolate(y1, y2 - slope / 2.0, y2, 2.0 * u); - } else { - return bezierInterpolate(y2, y2 + slope / 2.0, y3, 2.0 * u - 1.0); - } - -// float uGreaterHalf = step(0.5, u); -// float uSign = sign(uGreaterHalf - 0.5); -// vec4 y12 = mix(y1, y2, uGreaterHalf) -// vec4 y23 = mix(y2, y3, uGreaterHalf) -// -// return bezierInterpolate(y12, y2 + uSign * slope / 2.0, y23, 2.0 * u - uGreaterHalf); - } + return bezierInterpolate(y1, y2, y3, u); } vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) { @@ -116,7 +80,7 @@ void main(void) { int particleID = gl_VertexID / NUM_VERTICES_PER_PARTICLE; // Which quad vertex pos? int twoTriID = gl_VertexID - particleID * NUM_VERTICES_PER_PARTICLE; - + // Particle properties float age = inColor.x / particle.lifespan; float seed = inColor.y; From bd23a4137ef395231eb7e2776dd63179d15d0897 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 25 Nov 2015 11:11:06 -0800 Subject: [PATCH 057/174] Move toGlm to GLMHelpers --- .../src/RenderableParticleEffectEntityItem.cpp | 7 ++----- libraries/shared/src/GLMHelpers.cpp | 4 ++++ libraries/shared/src/GLMHelpers.h | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index a03d2a9b14..cabf616881 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -24,10 +24,11 @@ #include "textured_particle_vert.h" #include "textured_particle_frag.h" -static const size_t VERTEX_PER_PARTICLE = 4; class ParticlePayloadData { public: + static const size_t VERTEX_PER_PARTICLE = 4; + template struct InterpolationData { T start; @@ -195,10 +196,6 @@ void RenderableParticleEffectEntityItem::update(const quint64& now) { updateRenderItem(); } -static glm::vec4 toGlm(const xColor& color, float alpha) { - return glm::vec4((float)color.red / 255.0f, (float)color.green / 255.0f, (float)color.blue / 255.0f, alpha); -} - void RenderableParticleEffectEntityItem::updateRenderItem() { if (!_scene) { return; diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index fa010a85bd..d89457d761 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -345,6 +345,10 @@ QSize fromGlm(const glm::ivec2 & v) { return QSize(v.x, v.y); } +vec4 toGlm(const xColor& color, float alpha) { + return vec4((float)color.red / 255.0f, (float)color.green / 255.0f, (float)color.blue / 255.0f, alpha); +} + QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size) { QRectF result(pos.x, pos.y, size.x, size.y); return result; diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 8d3410aaf2..d518ab8ae4 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -154,6 +154,7 @@ vec2 toGlm(const QPointF& pt); vec3 toGlm(const xColor& color); vec4 toGlm(const QColor& color); ivec4 toGlm(const QRect& rect); +vec4 toGlm(const xColor& color, float alpha); QSize fromGlm(const glm::ivec2 & v); QMatrix4x4 fromGlm(const glm::mat4 & m); From 591025850b91fd1c209b0bac636168c45ae9a508 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 25 Nov 2015 11:38:59 -0800 Subject: [PATCH 058/174] Fix particle shader --- .../src/textured_particle.slv | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 0d915a3468..8572350de6 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -56,19 +56,11 @@ float bezierInterpolate(float y1, float y2, float y3, float u) { return (1.0 - u) * (1.0 - u) * y1 + 2.0 * (1.0 - u) * u * y2 + u * u * y3; } -float interpolate3Floats(float y1, float y2, float y3, float u) { - if ((u <= 0.5 && y1 == y2) || (u >= 0.5 && y2 == y3)) { - // Flat line. - return y2; - } - return bezierInterpolate(y1, y2, y3, u); -} - vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) { - return vec4(interpolate3Floats(y1.x, y2.x, y3.x, u), - interpolate3Floats(y1.y, y2.y, y3.y, u), - interpolate3Floats(y1.z, y2.z, y3.z, u), - interpolate3Floats(y1.w, y2.w, y3.w, u)); + return vec4(bezierInterpolate(y1.x, y2.x, y3.x, u), + bezierInterpolate(y1.y, y2.y, y3.y, u), + bezierInterpolate(y1.z, y2.z, y3.z, u), + bezierInterpolate(y1.w, y2.w, y3.w, u)); } @@ -90,7 +82,7 @@ void main(void) { varColor = interpolate3Vec4(particle.color.start, particle.color.middle, particle.color.finish, age); // anchor point in eye space - float radius = interpolate3Floats(particle.radius.start, particle.radius.middle, particle.radius.finish , age); + float radius = bezierInterpolate(particle.radius.start, particle.radius.middle, particle.radius.finish , age); vec4 quadPos = radius * UNIT_QUAD[twoTriID]; vec4 anchorPoint; From 180ffcc456132efa5a0dab26f1a8206b95549484 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 1 Dec 2015 15:42:29 -0800 Subject: [PATCH 059/174] Typo (English is weird) --- .../entities-renderer/src/textured_particle.slv | 4 ++-- .../entities/src/ParticleEffectEntityItem.cpp | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 8572350de6..1e9275ec72 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -14,7 +14,7 @@ <$declareStandardTransform()$> -struct Radiuses { +struct Radii { float start; float middle; float finish; @@ -28,7 +28,7 @@ struct Colors { }; struct ParticleUniforms { - Radiuses radius; + Radii radius; Colors color; float lifespan; }; diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index f598426e3c..27de4766f4 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -678,16 +678,16 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { radiusScale = 1.0f - std::pow(1.0f - randRadius, 3.0f); } - glm::vec3 radiuses = radiusScale * 0.5f * _emitDimensions; - float x = radiuses.x * glm::cos(elevation) * glm::cos(azimuth); - float y = radiuses.y * glm::cos(elevation) * glm::sin(azimuth); - float z = radiuses.z * glm::sin(elevation); + glm::vec3 radii = radiusScale * 0.5f * _emitDimensions; + float x = radii.x * glm::cos(elevation) * glm::cos(azimuth); + float y = radii.y * glm::cos(elevation) * glm::sin(azimuth); + float z = radii.z * glm::sin(elevation); glm::vec3 emitPosition = glm::vec3(x, y, z); emitDirection = glm::normalize(glm::vec3( - radiuses.x > 0.0f ? x / (radiuses.x * radiuses.x) : 0.0f, - radiuses.y > 0.0f ? y / (radiuses.y * radiuses.y) : 0.0f, - radiuses.z > 0.0f ? z / (radiuses.z * radiuses.z) : 0.0f - )); + radii.x > 0.0f ? x / (radii.x * radii.x) : 0.0f, + radii.y > 0.0f ? y / (radii.y * radii.y) : 0.0f, + radii.z > 0.0f ? z / (radii.z * radii.z) : 0.0f + )); particle.position = _emitOrientation * emitPosition; } From c8ab95bb53f12b7f8e03f8b2e81e97ee7ebc8f48 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 1 Dec 2015 16:25:08 -0800 Subject: [PATCH 060/174] Spacing --- libraries/entities/src/ParticleEffectEntityItem.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 0789f5b95e..ca6bcf8959 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -229,9 +229,9 @@ protected: struct Particle { float seed { 0.0f }; float lifetime { 0.0f }; - glm::vec3 position { Vectors::ZERO}; - glm::vec3 velocity { Vectors::ZERO}; - glm::vec3 acceleration { Vectors::ZERO}; + glm::vec3 position { Vectors::ZERO }; + glm::vec3 velocity { Vectors::ZERO }; + glm::vec3 acceleration { Vectors::ZERO }; }; // Particles container From a9aecb5c494d07fc3633c2849a5f20f3c521af74 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 4 Dec 2015 13:54:59 -0800 Subject: [PATCH 061/174] add rat sounds --- examples/drylake/ratCreator.js | 88 +++++++++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 12 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 19374ef5de..1d79401202 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -6,9 +6,9 @@ var TWEEN = loadTween(); var USE_CONSTANT_SPAWNER = true; var RAT_SPAWNER_LOCATION = { - x: 1001, - y: 97.5, - z: 1039 + x: 1000.5, + y: 98, + z: 1039.5 }; var RAT_NEST_LOCATION = { @@ -34,6 +34,9 @@ var RAT_IN_NEST_DISTANCE = 3; //how many milliseconds between rats var RAT_SPAWN_RATE = 2500; +var RAT_SOUND_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/sounds/rat2.wav'; +var ratRunningSound = SoundCache.getSound(RAT_SOUND_URL); + function playRatRunningAnimation(rat) { var animationSettings = JSON.stringify({ running: true @@ -71,9 +74,9 @@ var modelRatProperties = { dimensions: RAT_DIMENSIONS, position: RAT_SPAWNER_LOCATION, shapeType: 'Box', - damping:0.8, - angularDamping:0.99, - friction:0.75, + damping: 0.8, + angularDamping: 0.99, + friction: 0.75, // restitution:0.1, collisionsWillMove: true, ignoreForCollisions: false, @@ -83,7 +86,7 @@ var modelRatProperties = { z: 0 }, lifetime: 30, - // rotation: Quat.fromPitchYawRollDegrees(0, 180, 0), + // rotation: Quat.fromPitchYawRollDegrees(0, 180, 0), //disable this if for some reason we want grabbable rats userData: JSON.stringify({ grabbableKey: { @@ -118,6 +121,8 @@ function addRat() { } var rats = []; +var metaRats = []; +var ratCount = 0; var AVOIDER_Y_HEIGHT = 99; var FIRST_AVOIDER_START_POSITION = { @@ -236,6 +241,17 @@ function updateTweens() { TWEEN.update(); } +function createRatSoundInjector() { + var audioOptions = { + volume: 0.05, + loop: true + } + + var injector = Audio.playSound(ratRunningSound, audioOptions); + + return injector +} + function moveRats() { rats.forEach(function(rat) { checkDistanceFromNest(rat); @@ -289,24 +305,33 @@ function moveRats() { averageVector = Vec3.multiply(averageVector, 1 / divisorCount); var thisRatProps = Entities.getEntityProperties(rat, ["position", "rotation"]); - - // var constrainedRotation = Quat.fromVec3Degrees(eulerAngle); + + // var constrainedRotation = Quat.fromVec3Degrees(eulerAngle); // print('CR:::'+JSON.stringify(constrainedRotation)) var ratPosition = thisRatProps.position; var ratToNest = Vec3.subtract(RAT_NEST_LOCATION, ratPosition); - var ratRotation = Quat.rotationBetween(Vec3.UNIT_Z, ratToNest); - var eulerAngle = Quat.safeEulerAngles(ratRotation); + var ratRotation = Quat.rotationBetween(Vec3.UNIT_Z, ratToNest); + var eulerAngle = Quat.safeEulerAngles(ratRotation); eulerAngle.x = 0; eulerAngle.z = 0; var constrainedRotation = Quat.fromVec3Degrees(eulerAngle) - + Entities.editEntity(rat, { velocity: averageVector, rotation: constrainedRotation, }) + var metaRat = getMetaRatByRat(rat); + if (metaRat !== undefined) { + metaRat.injector.options = { + loop: true, + position: ratPosition + } + } else { + print('no meta rat for this rat') + } // castRay(rat); }) } @@ -332,6 +357,13 @@ function removeRatFromScene(rat) { rats.splice(index, 1); } Entities.deleteEntity(rat); + + var metaRatIndex = findWithAttr(metaRats, 'rat', rat); + if (metaRatIndex > -1) { + metaRats[index].injector.stop(); + delete metaRats[index].injector + metaRats.splice(index, 1); + } } function popRatFromStack(entityID) { @@ -339,6 +371,29 @@ function popRatFromStack(entityID) { if (index > -1) { rats.splice(index, 1); } + var metaRatIndex = findWithAttr(metaRats, 'rat', entityID); + if (metaRatIndex > -1) { + metaRats[index].injector.stop(); + delete metaRats[index].injector + metaRats.splice(index, 1); + } +} + +function findWithAttr(array, attr, value) { + for (var i = 0; i < array.length; i += 1) { + if (array[i][attr] === value) { + return i; + } + } +} + +function getMetaRatByRat(rat) { + var result = metaRats.filter(function(metaRat) { + print('metarat:::' + metaRat) + return rat === metaRat.rat; + }); + // print('RESULT LENGTH:::' + result.length) + return result[0]; } Entities.deletingEntity.connect(popRatFromStack); @@ -368,6 +423,15 @@ if (USE_CONSTANT_SPAWNER === true) { var rat = addRat(); playRatRunningAnimation(rat); rats.push(rat); + // print('ratCount::'+ratCount) + ratCount++; + if (ratCount % 3 === 0) { + metaRats.push({ + rat: rat, + injector: createRatSoundInjector() + }); + } + }, RAT_SPAWN_RATE); } From 7ed0e3d8aecde226c1e52dd6b4ec3ce17dd5d9a4 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 4 Dec 2015 13:56:38 -0800 Subject: [PATCH 062/174] change clear rat order --- examples/drylake/ratCreator.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 1d79401202..46b2694149 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -330,7 +330,7 @@ function moveRats() { position: ratPosition } } else { - print('no meta rat for this rat') + // print('no meta rat for this rat') } // castRay(rat); }) @@ -352,11 +352,6 @@ function checkDistanceFromNest(rat) { } function removeRatFromScene(rat) { - var index = rats.indexOf(rat); - if (index > -1) { - rats.splice(index, 1); - } - Entities.deleteEntity(rat); var metaRatIndex = findWithAttr(metaRats, 'rat', rat); if (metaRatIndex > -1) { @@ -364,19 +359,29 @@ function removeRatFromScene(rat) { delete metaRats[index].injector metaRats.splice(index, 1); } -} -function popRatFromStack(entityID) { - var index = rats.indexOf(entityID); + var index = rats.indexOf(rat); if (index > -1) { rats.splice(index, 1); } + Entities.deleteEntity(rat); + + +} + +function popRatFromStack(entityID) { var metaRatIndex = findWithAttr(metaRats, 'rat', entityID); if (metaRatIndex > -1) { metaRats[index].injector.stop(); delete metaRats[index].injector metaRats.splice(index, 1); } + + var index = rats.indexOf(entityID); + if (index > -1) { + rats.splice(index, 1); + } + } function findWithAttr(array, attr, value) { @@ -389,10 +394,8 @@ function findWithAttr(array, attr, value) { function getMetaRatByRat(rat) { var result = metaRats.filter(function(metaRat) { - print('metarat:::' + metaRat) return rat === metaRat.rat; }); - // print('RESULT LENGTH:::' + result.length) return result[0]; } From 3211bec7ce2746ce861981ef078c25ae5ac74704 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 4 Dec 2015 13:57:59 -0800 Subject: [PATCH 063/174] increase distance for rat to be in the nest and deleted --- examples/drylake/ratCreator.js | 2 +- examples/drylake/steer.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 46b2694149..e85fdce74b 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -29,7 +29,7 @@ var RAT_WALKING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/ var RAT_RUNNING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/run.fbx'; var RAT_DEATH_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/death.fbx'; -var RAT_IN_NEST_DISTANCE = 3; +var RAT_IN_NEST_DISTANCE = 4; //how many milliseconds between rats var RAT_SPAWN_RATE = 2500; diff --git a/examples/drylake/steer.js b/examples/drylake/steer.js index 0a44da5ab5..1c2502fbcb 100644 --- a/examples/drylake/steer.js +++ b/examples/drylake/steer.js @@ -104,7 +104,7 @@ function arrive(thisEntity, target) { var velocity = properties.velocity; var MAX_SPEED = 10; var MAX_FORCE = 6; - var ARRIVAL_DISTANCE = 5; + var ARRIVAL_DISTANCE = 2; var desired = Vec3.subtract(targetPosition, location); var d = Vec3.length(desired); From 51b0c48866b22c7794d3d1e69c42e6d648a63752 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 4 Dec 2015 14:05:31 -0800 Subject: [PATCH 064/174] splicing and dicing --- examples/drylake/ratCreator.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index e85fdce74b..73ce7c48f0 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -356,7 +356,6 @@ function removeRatFromScene(rat) { var metaRatIndex = findWithAttr(metaRats, 'rat', rat); if (metaRatIndex > -1) { metaRats[index].injector.stop(); - delete metaRats[index].injector metaRats.splice(index, 1); } @@ -373,7 +372,6 @@ function popRatFromStack(entityID) { var metaRatIndex = findWithAttr(metaRats, 'rat', entityID); if (metaRatIndex > -1) { metaRats[index].injector.stop(); - delete metaRats[index].injector metaRats.splice(index, 1); } From b1ec1eb113d81d8df26eb801d979e6b90369ec9e Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 4 Dec 2015 15:17:13 -0800 Subject: [PATCH 065/174] make injectors more stable --- examples/drylake/ratCreator.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 73ce7c48f0..831b29282d 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -178,7 +178,7 @@ function addAvoiderBlock(position) { position: position, collisionsWillMove: false, ignoreForCollisions: true, - visible: false + visible: true }; var avoider = Entities.addEntity(avoiderProperties); @@ -361,9 +361,11 @@ function removeRatFromScene(rat) { var index = rats.indexOf(rat); if (index > -1) { + Entities.deleteEntity(rat); rats.splice(index, 1); + } - Entities.deleteEntity(rat); + } @@ -426,12 +428,18 @@ if (USE_CONSTANT_SPAWNER === true) { rats.push(rat); // print('ratCount::'+ratCount) ratCount++; - if (ratCount % 3 === 0) { - metaRats.push({ - rat: rat, - injector: createRatSoundInjector() - }); + // if (ratCount % 3 === 0) { + var metaRat = { + rat: rat, + injector: createRatSoundInjector() } + metaRats.push(metaRat); + + Script.setTimeout(function() { + //if we have too many injectors hanging around there are problems + metaRat.injector.stop(); + }, RAT_SPAWN_RATE * 3) + // } }, RAT_SPAWN_RATE); } From f867ebf1d102f9a070bc63867b13fa1bb7ddb85c Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 4 Dec 2015 15:18:35 -0800 Subject: [PATCH 066/174] every sixth rat --- examples/drylake/ratCreator.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 831b29282d..4f53430d25 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -428,7 +428,7 @@ if (USE_CONSTANT_SPAWNER === true) { rats.push(rat); // print('ratCount::'+ratCount) ratCount++; - // if (ratCount % 3 === 0) { + if (ratCount % 6 === 0) { var metaRat = { rat: rat, injector: createRatSoundInjector() @@ -439,7 +439,7 @@ if (USE_CONSTANT_SPAWNER === true) { //if we have too many injectors hanging around there are problems metaRat.injector.stop(); }, RAT_SPAWN_RATE * 3) - // } + } }, RAT_SPAWN_RATE); } From b8e731fd229e5eb5cfc1e5db857946bb7522d938 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 4 Dec 2015 15:25:55 -0800 Subject: [PATCH 067/174] adjustments --- examples/drylake/ratCreator.js | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 4f53430d25..8eece5c024 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -8,7 +8,7 @@ var USE_CONSTANT_SPAWNER = true; var RAT_SPAWNER_LOCATION = { x: 1000.5, y: 98, - z: 1039.5 + z: 1040 }; var RAT_NEST_LOCATION = { @@ -156,6 +156,8 @@ var THIRD_AVOIDER_FINISH_POSITION = { z: 974 }; +cleanupLeftoverAvoidersBeforeStart(); + var avoiders = []; addAvoiderBlock(FIRST_AVOIDER_START_POSITION); addAvoiderBlock(SECOND_AVOIDER_START_POSITION); @@ -178,7 +180,7 @@ function addAvoiderBlock(position) { position: position, collisionsWillMove: false, ignoreForCollisions: true, - visible: true + visible: false }; var avoider = Entities.addEntity(avoiderProperties); @@ -401,6 +403,20 @@ function getMetaRatByRat(rat) { Entities.deletingEntity.connect(popRatFromStack); + +function cleanupLeftoverAvoidersBeforeStart() { + print('CLEANING UP LEFTOVER AVOIDERS') + var nearbyEntities = Entities.findEntities(RAT_SPAWNER_LOCATION, 100); + var entityIndex; + for (entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { + var entityID = nearbyEntities[entityIndex]; + var entityProps = Entities.getEntityProperties(entityID); + if (entityProps.name === 'Hifi-Rat-Avoider') { + Entities.deleteEntity(entityID); + } + } +} + function cleanup() { while (rats.length > 0) { Entities.deleteEntity(rats.pop()); @@ -429,17 +445,17 @@ if (USE_CONSTANT_SPAWNER === true) { // print('ratCount::'+ratCount) ratCount++; if (ratCount % 6 === 0) { - var metaRat = { - rat: rat, - injector: createRatSoundInjector() - } - metaRats.push(metaRat); + var metaRat = { + rat: rat, + injector: createRatSoundInjector() + } + metaRats.push(metaRat); - Script.setTimeout(function() { + Script.setTimeout(function() { //if we have too many injectors hanging around there are problems metaRat.injector.stop(); }, RAT_SPAWN_RATE * 3) - } + } }, RAT_SPAWN_RATE); } From bfe12cf8dbb5bf69397fd61984f5ed3abe540751 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 4 Dec 2015 15:49:04 -0800 Subject: [PATCH 068/174] stability improvments --- examples/drylake/ratCreator.js | 42 ++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 8eece5c024..731255527a 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -327,10 +327,17 @@ function moveRats() { var metaRat = getMetaRatByRat(rat); if (metaRat !== undefined) { - metaRat.injector.options = { - loop: true, - position: ratPosition + if (metaRat.injector !== undefined) { + if (metaRat.injector.isPlaying === true) { + // print('update injector position') + metaRat.injector.options = { + loop: true, + position: ratPosition + } + } } + + } else { // print('no meta rat for this rat') } @@ -355,35 +362,39 @@ function checkDistanceFromNest(rat) { function removeRatFromScene(rat) { - var metaRatIndex = findWithAttr(metaRats, 'rat', rat); - if (metaRatIndex > -1) { - metaRats[index].injector.stop(); - metaRats.splice(index, 1); - } var index = rats.indexOf(rat); if (index > -1) { - Entities.deleteEntity(rat); + // print('CLEAR RAT::'+rat) rats.splice(index, 1); + Entities.deleteEntity(rat); } + var metaRatIndex = findWithAttr(metaRats, 'rat', rat); + if (metaRatIndex > -1) { + // print('CLEAR META RAT') + metaRats[index].injector.stop(); + metaRats.splice(index, 1); + } + } function popRatFromStack(entityID) { - var metaRatIndex = findWithAttr(metaRats, 'rat', entityID); - if (metaRatIndex > -1) { - metaRats[index].injector.stop(); - metaRats.splice(index, 1); - } var index = rats.indexOf(entityID); if (index > -1) { rats.splice(index, 1); } + var metaRatIndex = findWithAttr(metaRats, 'rat', entityID); + if (metaRatIndex > -1) { + metaRats[index].injector.stop(); + metaRats.splice(index, 1); + } + } function findWithAttr(array, attr, value) { @@ -405,7 +416,7 @@ Entities.deletingEntity.connect(popRatFromStack); function cleanupLeftoverAvoidersBeforeStart() { - print('CLEANING UP LEFTOVER AVOIDERS') + // print('CLEANING UP LEFTOVER AVOIDERS') var nearbyEntities = Entities.findEntities(RAT_SPAWNER_LOCATION, 100); var entityIndex; for (entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { @@ -454,6 +465,7 @@ if (USE_CONSTANT_SPAWNER === true) { Script.setTimeout(function() { //if we have too many injectors hanging around there are problems metaRat.injector.stop(); + delete metaRat.injector; }, RAT_SPAWN_RATE * 3) } From df413c0b14a1f87b221f021ba83997e470a920a8 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 7 Dec 2015 09:31:06 -0800 Subject: [PATCH 069/174] Temporary debugging aids. --- libraries/shared/src/PIDController.cpp | 10 ++++++---- libraries/shared/src/PIDController.h | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libraries/shared/src/PIDController.cpp b/libraries/shared/src/PIDController.cpp index a853553b89..36c670e66d 100644 --- a/libraries/shared/src/PIDController.cpp +++ b/libraries/shared/src/PIDController.cpp @@ -14,7 +14,7 @@ #include "SharedLogging.h" #include "PIDController.h" -float PIDController::update(float measuredValue, float dt, bool resetAccumulator) { +float PIDController::update(float measuredValue, float dt, bool resetAccumulator, float fixme1, float fixme2) { const float error = getMeasuredValueSetpoint() - measuredValue; // Sign is the direction we want measuredValue to go. Positive means go higher. const float p = getKP() * error; // term is Proportional to error @@ -32,7 +32,7 @@ float PIDController::update(float measuredValue, float dt, bool resetAccumulator getControlledValueHighLimit()); if (getIsLogging()) { // if logging/reporting - updateHistory(measuredValue, dt, error, accumulatedError, changeInError, p, i, d, computedValue); + updateHistory(measuredValue, dt, error, accumulatedError, changeInError, p, i, d, computedValue, fixme1, fixme2); } Q_ASSERT(!isnan(computedValue)); @@ -43,7 +43,7 @@ float PIDController::update(float measuredValue, float dt, bool resetAccumulator } // Just for logging/reporting. Used when picking/verifying the operational parameters. -void PIDController::updateHistory(float measuredValue, float dt, float error, float accumulatedError, float changeInError, float p, float i, float d, float computedValue) { +void PIDController::updateHistory(float measuredValue, float dt, float error, float accumulatedError, float changeInError, float p, float i, float d, float computedValue, float fixme1, float fixme2) { // Don't report each update(), as the I/O messes with the results a lot. // Instead, add to history, and then dump out at once when full. // Typically, the first few values reported in each batch should be ignored. @@ -59,16 +59,18 @@ void PIDController::updateHistory(float measuredValue, float dt, float error, fl next.i = i; next.d = d; next.computed = computedValue; + next.fixme1 = fixme1; next.fixme2 = fixme2; if (_history.size() == _history.capacity()) { // report when buffer is full reportHistory(); _history.resize(0); } } void PIDController::reportHistory() { - qCDebug(shared) << _label << "measured dt FIXME || error accumulated changed || p i d controlled"; + qCDebug(shared) << _label << "measured dt || error accumulated changed || p i d controlled"; for (int i = 0; i < _history.size(); i++) { Row& row = _history[i]; qCDebug(shared) << row.measured << row.dt << + row.fixme1 << row.fixme2 << "||" << row.error << row.accumulated << row.changed << "||" << row.p << row.i << row.d << row.computed << 1.0f/row.computed; } diff --git a/libraries/shared/src/PIDController.h b/libraries/shared/src/PIDController.h index 0b2411530a..24e619b13b 100644 --- a/libraries/shared/src/PIDController.h +++ b/libraries/shared/src/PIDController.h @@ -28,7 +28,7 @@ class PIDController { public: // These are the main interfaces: void setMeasuredValueSetpoint(float newValue) { _measuredValueSetpoint = newValue; } - float update(float measuredValue, float dt, bool resetAccumulator = false); // returns the new computedValue + float update(float measuredValue, float dt, bool resetAccumulator = false, float fixme1=0, float fixme2=0); // returns the new computedValue void setHistorySize(QString label = QString(""), int size = 0) { _history.reserve(size); _history.resize(0); _label = label; } // non-empty does logging bool getIsLogging() { return _history.capacity(); } @@ -64,10 +64,11 @@ public: float i; float d; float computed; + float fixme1; float fixme2; }; protected: void reportHistory(); - void updateHistory(float measured, float dt, float error, float accumulatedError, float changeInErro, float p, float i, float d, float computedValue); + void updateHistory(float measured, float dt, float error, float accumulatedError, float changeInErro, float p, float i, float d, float computedValue, float fixme1, float fixme2); float _measuredValueSetpoint { 0.0f }; float _controlledValueLowLimit { 0.0f }; float _controlledValueHighLimit { std::numeric_limits::max() }; From 34de4d67d80f6e9337d3f28ce6bc3dcf29ffcfba Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 7 Dec 2015 09:32:12 -0800 Subject: [PATCH 070/174] DisplayPlugin::getLastSynchronizedElapsed --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 6 ++++++ .../src/display-plugins/OpenGLDisplayPlugin.h | 4 ++++ libraries/plugins/src/plugins/DisplayPlugin.h | 1 + 3 files changed, 11 insertions(+) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index d306c23dc0..4668f8ba1a 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -156,8 +156,10 @@ OpenGLDisplayPlugin::OpenGLDisplayPlugin() { _container->releaseOverlayTexture(texture); }); + _synchronizedTimer.start(); connect(&_timer, &QTimer::timeout, this, [&] { if (_active && _sceneTextureEscrow.depth() <= 1) { + _synchronizedTimer.start(); emit requestRender(); } }); @@ -279,6 +281,10 @@ void OpenGLDisplayPlugin::submitOverlayTexture(GLuint sceneTexture, const glm::u } void OpenGLDisplayPlugin::updateTextures() { + const qint64 elapsed =_synchronizedTimer.elapsed(); + if (elapsed != 0) { + _lastSynchronizedElapsed = elapsed; + } _currentSceneTexture = _sceneTextureEscrow.fetchAndRelease(_currentSceneTexture); _currentOverlayTexture = _overlayTextureEscrow.fetchAndRelease(_currentOverlayTexture); } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index ef78374994..4577777034 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -10,6 +10,7 @@ #include "DisplayPlugin.h" #include +#include #include #include @@ -30,6 +31,7 @@ public: virtual void submitSceneTexture(uint32_t frameIndex, uint32_t sceneTexture, const glm::uvec2& sceneSize) override; virtual void submitOverlayTexture(uint32_t overlayTexture, const glm::uvec2& overlaySize) override; virtual float presentRate() override; + virtual qint64 getLastSynchronizedElapsed() { return _lastSynchronizedElapsed; } virtual glm::uvec2 getRecommendedRenderSize() const override { return getSurfacePixels(); @@ -68,6 +70,8 @@ protected: virtual void internalPresent(); mutable QTimer _timer; + QElapsedTimer _synchronizedTimer; + qint64 _lastSynchronizedElapsed { 0 }; ProgramPtr _program; ShapeWrapperPtr _plane; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 83afbc9402..6fc6062214 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -58,6 +58,7 @@ public: /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } virtual bool isThrottled() const { return false; } + virtual qint64 getLastSynchronizedElapsed() { return 0; } // Rendering support From 1d4cc7c9847bbf615b40e9647e7a13e564e6f181 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 7 Dec 2015 10:01:46 -0800 Subject: [PATCH 071/174] Checkpoint exploring use of getLastSynchronizedElapsed and fixing paintWait (which may go away). --- interface/src/Application.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9e98b51442..3af0e6d39b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1126,9 +1126,9 @@ void Application::paintGL() { // Time between previous paintGL call and this one, which can vary not only with vSync misses, but also with QT timing. // We're using this as a proxy for the time between vsync and displayEnd, below. (Not exact, but tends to be the same over time.) // This is not the same as update(deltaTime), because the latter attempts to throttle to 60hz and also clamps to 1/4 second. - const float actualPeriod = diff / (float)USECS_PER_SECOND; // same as 1/instantaneousFps but easier for compiler to optimize + //const float actualPeriod = diff / (float)USECS_PER_SECOND; // same as 1/instantaneousFps but easier for compiler to optimize // Note that _lastPaintWait (stored at end of last call) is for the same paint cycle. - float deducedNonVSyncPeriod = actualPeriod - _lastPaintWait + _marginForDeducedFramePeriod; // plus a some non-zero time for machinery we can't measure + float deducedNonVSyncPeriod = (float) getActiveDisplayPlugin()->getLastSynchronizedElapsed() / (float) MSECS_PER_SECOND; /*actualPeriod - _lastPaintWait + _marginForDeducedFramePeriod; // plus a some non-zero time for machinery we can't measure // We don't know how much time to allow for that, but if we went over the target period, we know it's at least the portion // of paintWait up to the next vSync. This gives us enough of a penalty so that when actualPeriod crosses two cycles, // the key part (and not an exagerated part) of _lastPaintWait is accounted for. @@ -1136,7 +1136,7 @@ void Application::paintGL() { if (_lastPaintWait > EPSILON && actualPeriod > targetPeriod) { // Don't use C++ remainder(). It's authors are mathematically insane. deducedNonVSyncPeriod += fmod(actualPeriod, _lastPaintWait); - } + }*/ _lastDeducedNonVSyncFps = 1.0f / deducedNonVSyncPeriod; _lastInstantaneousFps = instantaneousFps; @@ -1375,6 +1375,7 @@ void Application::paintGL() { } // deliver final composited scene to the display plugin + uint64_t displayStart = usecTimestampNow(); { PROFILE_RANGE(__FUNCTION__ "/pluginOutput"); PerformanceTimer perfTimer("pluginOutput"); @@ -1396,7 +1397,6 @@ void Application::paintGL() { Q_ASSERT(!_lockedFramebufferMap.contains(finalTexture)); _lockedFramebufferMap[finalTexture] = scratchFramebuffer; - uint64_t displayStart = usecTimestampNow(); Q_ASSERT(QOpenGLContext::currentContext() == _offscreenContext->getContext()); { PROFILE_RANGE(__FUNCTION__ "/pluginSubmitScene"); @@ -1404,10 +1404,6 @@ void Application::paintGL() { displayPlugin->submitSceneTexture(_frameCount, finalTexture, toGlm(size)); } Q_ASSERT(QOpenGLContext::currentContext() == _offscreenContext->getContext()); - - uint64_t displayEnd = usecTimestampNow(); - const float displayPeriodUsec = (float)(displayEnd - displayStart); // usecs - _lastPaintWait = displayPeriodUsec / (float)USECS_PER_SECOND; } { @@ -1418,6 +1414,9 @@ void Application::paintGL() { batch.resetStages(); }); } + uint64_t displayEnd = usecTimestampNow(); + const float displayPeriodUsec = (float)(displayEnd - displayStart); // usecs + _lastPaintWait = displayPeriodUsec / (float)USECS_PER_SECOND; } void Application::runTests() { From 17ecf9b6b70e027ecd9656bbea59418bfbc029ec Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 7 Dec 2015 11:26:56 -0800 Subject: [PATCH 072/174] debugging --- interface/src/avatar/AvatarManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 7aa5073921..35b5db7946 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -111,7 +111,7 @@ void AvatarManager::init() { _renderDistanceController.setKP(0.0008f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. _renderDistanceController.setKI(0.0006f); // Big enough to bring us to target with the above KP. _renderDistanceController.setKD(0.000001f); // A touch of kd increases the speed by which we get there. - + a_renderDistanceController.setHistorySize("av", 240); //FIXME } void AvatarManager::updateMyAvatar(float deltaTime) { @@ -152,7 +152,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate // goes up. const float deduced = qApp->getLastDeducedNonVSyncFps(); - const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime); + const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime, false, qApp->getLastPaintWait(), qApp->getLastInstanteousFps()); _renderDistanceAverage.updateAverage(distance); _renderDistance = _renderDistanceAverage.getAverage(); int renderableCount = 0; From e9f21b4dba79fa8e81c22b4c2d110449f23735dc Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 7 Dec 2015 11:30:10 -0800 Subject: [PATCH 073/174] make lights parented to flashlight instead of updated in loop --- examples/toybox/flashlight/flashlight.js | 47 ++++++++++-------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/examples/toybox/flashlight/flashlight.js b/examples/toybox/flashlight/flashlight.js index 8911c0ecd8..2640ff0bff 100644 --- a/examples/toybox/flashlight/flashlight.js +++ b/examples/toybox/flashlight/flashlight.js @@ -25,7 +25,7 @@ //we are creating lights that we don't want to get stranded so lets make sure that we can get rid of them var startTime = Date.now(); //if you're going to be using this in a dungeon or something and holding it for a long time, increase this lifetime value. - var LIFETIME = 25; + var LIFETIME = 100; var MSEC_PER_SEC = 1000.0; // this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember @@ -85,9 +85,16 @@ this.hand = 'LEFT'; }, - startNearGrab: function() { + startNearGrab: function(entityID) { + print('id on grab',entityID) if (!this.hasSpotlight) { + print('CREATING LIGHTS', this.entityID) + var modelProperties = Entities.getEntityProperties(this.entityID, ['position', 'rotation']); + var lightTransform = evalLightWorldTransform(modelProperties.position, modelProperties.rotation); + var glowLightTransform = glowLightWorldTransform(modelProperties.position, modelProperties.rotation); + + //this light casts the beam this.spotlight = Entities.addEntity({ type: "Light", @@ -97,6 +104,7 @@ y: 2, z: 20 }, + parentID: this.entityID, color: { red: 255, green: 255, @@ -105,7 +113,9 @@ intensity: 2, exponent: 0.3, cutoff: 20, - lifetime: LIFETIME + lifetime: LIFETIME, + position: lightTransform.p, + rotation: lightTransform.q, }); //this light creates the effect of a bulb at the end of the flashlight @@ -116,6 +126,7 @@ y: 0.25, z: 0.25 }, + parentID: this.entityID, isSpotlight: false, color: { red: 255, @@ -123,8 +134,11 @@ blue: 255 }, exponent: 0, + lifetime: LIFETIME, cutoff: 90, // in degrees - lifetime: LIFETIME + position: glowLightTransform.p, + rotation: glowLightTransform.q, + }); this.hasSpotlight = true; @@ -142,7 +156,6 @@ //only set the active hand once -- if we always read the current hand, our 'holding' hand will get overwritten this.setWhichHand(); } else { - this.updateLightPositions(); this.changeLightWithTriggerPressure(this.whichHand); } }, @@ -159,29 +172,7 @@ this.lightOn = false; } }, - - updateLightPositions: function() { - var modelProperties = Entities.getEntityProperties(this.entityID, ['position', 'rotation']); - - //move the two lights along the vectors we set above - var lightTransform = evalLightWorldTransform(modelProperties.position, modelProperties.rotation); - var glowLightTransform = glowLightWorldTransform(modelProperties.position, modelProperties.rotation); - - //move them with the entity model - Entities.editEntity(this.spotlight, { - position: lightTransform.p, - rotation: lightTransform.q, - lifetime: (Date.now() - startTime) / MSEC_PER_SEC + LIFETIME - }); - - Entities.editEntity(this.glowLight, { - position: glowLightTransform.p, - rotation: glowLightTransform.q, - lifetime: (Date.now() - startTime) / MSEC_PER_SEC + LIFETIME - }); - - }, - + changeLightWithTriggerPressure: function(flashLightHand) { if (flashLightHand === 'LEFT') { From 27ce0a36d3e6f6fcc0c21155443bc73d6ad853fa Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 7 Dec 2015 12:20:06 -0800 Subject: [PATCH 074/174] cleanup logging --- examples/toybox/flashlight/flashlight.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/toybox/flashlight/flashlight.js b/examples/toybox/flashlight/flashlight.js index 2640ff0bff..251ca71b7a 100644 --- a/examples/toybox/flashlight/flashlight.js +++ b/examples/toybox/flashlight/flashlight.js @@ -86,10 +86,8 @@ }, startNearGrab: function(entityID) { - print('id on grab',entityID) if (!this.hasSpotlight) { - print('CREATING LIGHTS', this.entityID) var modelProperties = Entities.getEntityProperties(this.entityID, ['position', 'rotation']); var lightTransform = evalLightWorldTransform(modelProperties.position, modelProperties.rotation); var glowLightTransform = glowLightWorldTransform(modelProperties.position, modelProperties.rotation); From 8683bb5002915c05645b9dacbebe6fc24dd19307 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Mon, 7 Dec 2015 13:05:30 -0800 Subject: [PATCH 075/174] New reverb parameters --- examples/utilities/tools/reverbTest.js | 60 +++++--- libraries/audio-client/src/AudioClient.cpp | 74 ++++++---- libraries/audio/src/AudioEffectOptions.cpp | 149 ++++++++++++-------- libraries/audio/src/AudioEffectOptions.h | 154 +++++++++++++-------- 4 files changed, 277 insertions(+), 160 deletions(-) diff --git a/examples/utilities/tools/reverbTest.js b/examples/utilities/tools/reverbTest.js index 32c28a993f..2b08073ae0 100644 --- a/examples/utilities/tools/reverbTest.js +++ b/examples/utilities/tools/reverbTest.js @@ -12,31 +12,57 @@ Script.include("cookies.js"); var audioOptions = new AudioEffectOptions({ - maxRoomSize: 50, + bandwidth: 10000, + preDelay: 20, + lateDelay: 0, + reverbTime: 2, + earlyDiffusion: 100, + lateDiffusion: 100, roomSize: 50, - reverbTime: 4, - damping: 0.50, - inputBandwidth: 0.8, - earlyLevel: 0, - tailLevel: 0, - dryLevel: -6, - wetLevel: -6 + density: 100, + bassMult: 1.5, + bassFreq: 250, + highGain: -6, + highFreq: 3000, + modRate: 2.3, + modDepth: 50, + earlyGain: 0, + lateGain: 0, + earlyMixLeft: 20, + earlyMixRight: 20, + lateMixLeft: 90, + lateMixRight: 90, + wetDryMix: 50, }); AudioDevice.setReverbOptions(audioOptions); AudioDevice.setReverb(true); print("Reverb is ON."); -var panel = new Panel(10, 200); +var panel = new Panel(10, 150); var parameters = [ - { name: "roomSize", min: 0, max: 100, units: " feet" }, - { name: "reverbTime", min: 0, max: 10, units: " sec" }, - { name: "damping", min: 0, max: 1, units: " " }, - { name: "inputBandwidth", min: 0, max: 1, units: " " }, - { name: "earlyLevel", min: -48, max: 0, units: " dB" }, - { name: "tailLevel", min: -48, max: 0, units: " dB" }, - { name: "wetLevel", min: -48, max: 0, units: " dB" }, + { name: "bandwidth", min: 1000, max: 12000, units: " Hz" }, + { name: "preDelay", min: 0, max: 333, units: " ms" }, + { name: "lateDelay", min: 0, max: 166, units: " ms" }, + { name: "reverbTime", min: 0.1, max: 10, units: " seconds" }, + { name: "earlyDiffusion", min: 0, max: 100, units: " percent" }, + { name: "lateDiffusion", min: 0, max: 100, units: " percent" }, + { name: "roomSize", min: 0, max: 100, units: " percent" }, + { name: "density", min: 0, max: 100, units: " percent" }, + { name: "bassMult", min: 0.1, max: 4, units: " ratio" }, + { name: "bassFreq", min: 10, max: 500, units: " Hz" }, + { name: "highGain", min: -24, max: 0, units: " dB" }, + { name: "highFreq", min: 1000, max: 12000, units: " Hz" }, + { name: "modRate", min: 0.1, max: 10, units: " Hz" }, + { name: "modDepth", min: 0, max: 100, units: " percent" }, + { name: "earlyGain", min: -96, max: 24, units: " dB" }, + { name: "lateGain", min: -96, max: 24, units: " dB" }, + { name: "earlyMixLeft", min: 0, max: 100, units: " percent" }, + { name: "earlyMixRight", min: 0, max: 100, units: " percent" }, + { name: "lateMixLeft", min: 0, max: 100, units: " percent" }, + { name: "lateMixRight", min: 0, max: 100, units: " percent" }, + { name: "wetDryMix", min: 0, max: 100, units: " percent" }, ] function setter(name) { @@ -48,7 +74,7 @@ function getter(name) { } function displayer(units) { - return function(value) { return (value).toFixed(1) + units; }; + return function(value) { return (value).toFixed(1) + units; } } // create a slider for each parameter diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index b141c70272..23e00c85cd 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -541,26 +541,40 @@ bool AudioClient::switchOutputToAudioDevice(const QString& outputDeviceName) { void AudioClient::configureReverb() { ReverbParameters p; - _listenerReverb.getParameters(&p); - - // for now, reuse the gverb parameters p.sampleRate = _outputFormat.sampleRate(); - p.roomSize = _reverbOptions->getRoomSize(); + + p.bandwidth = _reverbOptions->getBandwidth(); + p.preDelay = _reverbOptions->getPreDelay(); + p.lateDelay = _reverbOptions->getLateDelay(); p.reverbTime = _reverbOptions->getReverbTime(); - p.highGain = -24.0f * (1.0f - _reverbOptions->getDamping()); - p.bandwidth = 10000.0f * _reverbOptions->getInputBandwidth(); - p.earlyGain = _reverbOptions->getEarlyLevel(); - p.lateGain = _reverbOptions->getTailLevel(); - p.wetDryMix = 100.0f * powf(10.0f, _reverbOptions->getWetLevel() * (1/20.0f)); + p.earlyDiffusion = _reverbOptions->getEarlyDiffusion(); + p.lateDiffusion = _reverbOptions->getLateDiffusion(); + p.roomSize = _reverbOptions->getRoomSize(); + p.density = _reverbOptions->getDensity(); + p.bassMult = _reverbOptions->getBassMult(); + p.bassFreq = _reverbOptions->getBassFreq(); + p.highGain = _reverbOptions->getHighGain(); + p.highFreq = _reverbOptions->getHighFreq(); + p.modRate = _reverbOptions->getModRate(); + p.modDepth = _reverbOptions->getModDepth(); + p.earlyGain = _reverbOptions->getEarlyGain(); + p.lateGain = _reverbOptions->getLateGain(); + p.earlyMixLeft = _reverbOptions->getEarlyMixLeft(); + p.earlyMixRight = _reverbOptions->getEarlyMixRight(); + p.lateMixLeft = _reverbOptions->getLateMixLeft(); + p.lateMixRight = _reverbOptions->getLateMixRight(); + p.wetDryMix = _reverbOptions->getWetDryMix(); + _listenerReverb.setParameters(&p); - // used for adding self-reverb to loopback audio + // used only for adding self-reverb to loopback audio p.wetDryMix = 100.0f; p.preDelay = 0.0f; p.earlyGain = -96.0f; // disable ER - p.lateGain -= 12.0f; // quieter than listener reverb + p.lateGain -= 12.0f; // quieter than listener reverb p.lateMixLeft = 0.0f; p.lateMixRight = 0.0f; + _sourceReverb.setParameters(&p); } @@ -572,10 +586,10 @@ void AudioClient::updateReverbOptions() { _zoneReverbOptions.setReverbTime(_receivedAudioStream.getRevebTime()); reverbChanged = true; } - if (_zoneReverbOptions.getWetLevel() != _receivedAudioStream.getWetLevel()) { - _zoneReverbOptions.setWetLevel(_receivedAudioStream.getWetLevel()); - reverbChanged = true; - } + //if (_zoneReverbOptions.getWetLevel() != _receivedAudioStream.getWetLevel()) { + // _zoneReverbOptions.setWetLevel(_receivedAudioStream.getWetLevel()); + // reverbChanged = true; + //} if (_reverbOptions != &_zoneReverbOptions) { _reverbOptions = &_zoneReverbOptions; @@ -602,17 +616,27 @@ void AudioClient::setReverb(bool reverb) { void AudioClient::setReverbOptions(const AudioEffectOptions* options) { // Save the new options - _scriptReverbOptions.setMaxRoomSize(options->getMaxRoomSize()); - _scriptReverbOptions.setRoomSize(options->getRoomSize()); + _scriptReverbOptions.setBandwidth(options->getBandwidth()); + _scriptReverbOptions.setPreDelay(options->getPreDelay()); + _scriptReverbOptions.setLateDelay(options->getLateDelay()); _scriptReverbOptions.setReverbTime(options->getReverbTime()); - _scriptReverbOptions.setDamping(options->getDamping()); - _scriptReverbOptions.setSpread(options->getSpread()); - _scriptReverbOptions.setInputBandwidth(options->getInputBandwidth()); - _scriptReverbOptions.setEarlyLevel(options->getEarlyLevel()); - _scriptReverbOptions.setTailLevel(options->getTailLevel()); - - _scriptReverbOptions.setDryLevel(options->getDryLevel()); - _scriptReverbOptions.setWetLevel(options->getWetLevel()); + _scriptReverbOptions.setEarlyDiffusion(options->getEarlyDiffusion()); + _scriptReverbOptions.setLateDiffusion(options->getLateDiffusion()); + _scriptReverbOptions.setRoomSize(options->getRoomSize()); + _scriptReverbOptions.setDensity(options->getDensity()); + _scriptReverbOptions.setBassMult(options->getBassMult()); + _scriptReverbOptions.setBassFreq(options->getBassFreq()); + _scriptReverbOptions.setHighGain(options->getHighGain()); + _scriptReverbOptions.setHighFreq(options->getHighFreq()); + _scriptReverbOptions.setModRate(options->getModRate()); + _scriptReverbOptions.setModDepth(options->getModDepth()); + _scriptReverbOptions.setEarlyGain(options->getEarlyGain()); + _scriptReverbOptions.setLateGain(options->getLateGain()); + _scriptReverbOptions.setEarlyMixLeft(options->getEarlyMixLeft()); + _scriptReverbOptions.setEarlyMixRight(options->getEarlyMixRight()); + _scriptReverbOptions.setLateMixLeft(options->getLateMixLeft()); + _scriptReverbOptions.setLateMixRight(options->getLateMixRight()); + _scriptReverbOptions.setWetDryMix(options->getWetDryMix()); if (_reverbOptions == &_scriptReverbOptions) { // Apply them to the reverb instances diff --git a/libraries/audio/src/AudioEffectOptions.cpp b/libraries/audio/src/AudioEffectOptions.cpp index a61213d9c4..792799b776 100644 --- a/libraries/audio/src/AudioEffectOptions.cpp +++ b/libraries/audio/src/AudioEffectOptions.cpp @@ -10,58 +10,76 @@ #include "AudioEffectOptions.h" -static const QString MAX_ROOM_SIZE_HANDLE = "maxRoomSize"; -static const QString ROOM_SIZE_HANDLE = "roomSize"; +static const QString BANDWIDTH_HANDLE = "bandwidth"; +static const QString PRE_DELAY_HANDLE = "preDelay"; +static const QString LATE_DELAY_HANDLE = "lateDelay"; static const QString REVERB_TIME_HANDLE = "reverbTime"; -static const QString DAMPIMG_HANDLE = "damping"; -static const QString SPREAD_HANDLE = "spread"; -static const QString INPUT_BANDWIDTH_HANDLE = "inputBandwidth"; -static const QString EARLY_LEVEL_HANDLE = "earlyLevel"; -static const QString TAIL_LEVEL_HANDLE = "tailLevel"; -static const QString DRY_LEVEL_HANDLE = "dryLevel"; -static const QString WET_LEVEL_HANDLE = "wetLevel"; +static const QString EARLY_DIFFUSION_HANDLE = "earlyDiffusion"; +static const QString LATE_DIFFUSION_HANDLE = "lateDiffusion"; +static const QString ROOM_SIZE_HANDLE = "roomSize"; +static const QString DENSITY_HANDLE = "density"; +static const QString BASS_MULT_HANDLE = "bassMult"; +static const QString BASS_FREQ_HANDLE = "bassFreq"; +static const QString HIGH_GAIN_HANDLE = "highGain"; +static const QString HIGH_FREQ_HANDLE = "highFreq"; +static const QString MOD_RATE_HANDLE = "modRate"; +static const QString MOD_DEPTH_HANDLE = "modDepth"; +static const QString EARLY_GAIN_HANDLE = "earlyGain"; +static const QString LATE_GAIN_HANDLE = "lateGain"; +static const QString EARLY_MIX_LEFT_HANDLE = "earlyMixLeft"; +static const QString EARLY_MIX_RIGHT_HANDLE = "earlyMixRight"; +static const QString LATE_MIX_LEFT_HANDLE = "lateMixLeft"; +static const QString LATE_MIX_RIGHT_HANDLE = "lateMixRight"; +static const QString WET_DRY_MIX_HANDLE = "wetDryMix"; -AudioEffectOptions::AudioEffectOptions(QScriptValue arguments) : - _maxRoomSize(50.0f), - _roomSize(50.0f), - _reverbTime(4.0f), - _damping(0.5f), - _spread(15.0f), - _inputBandwidth(0.75f), - _earlyLevel(-12.0f), - _tailLevel(-18.0f), - _dryLevel(0.0f), - _wetLevel(0.0f) { - if (arguments.property(MAX_ROOM_SIZE_HANDLE).isNumber()) { - _maxRoomSize = arguments.property(MAX_ROOM_SIZE_HANDLE).toNumber(); - } - if (arguments.property(ROOM_SIZE_HANDLE).isNumber()) { - _roomSize = arguments.property(ROOM_SIZE_HANDLE).toNumber(); - } - if (arguments.property(REVERB_TIME_HANDLE).isNumber()) { - _reverbTime = arguments.property(REVERB_TIME_HANDLE).toNumber(); - } - if (arguments.property(DAMPIMG_HANDLE).isNumber()) { - _damping = arguments.property(DAMPIMG_HANDLE).toNumber(); - } - if (arguments.property(SPREAD_HANDLE).isNumber()) { - _spread = arguments.property(SPREAD_HANDLE).toNumber(); - } - if (arguments.property(INPUT_BANDWIDTH_HANDLE).isNumber()) { - _inputBandwidth = arguments.property(INPUT_BANDWIDTH_HANDLE).toNumber(); - } - if (arguments.property(EARLY_LEVEL_HANDLE).isNumber()) { - _earlyLevel = arguments.property(EARLY_LEVEL_HANDLE).toNumber(); - } - if (arguments.property(TAIL_LEVEL_HANDLE).isNumber()) { - _tailLevel = arguments.property(TAIL_LEVEL_HANDLE).toNumber(); - } - if (arguments.property(DRY_LEVEL_HANDLE).isNumber()) { - _dryLevel = arguments.property(DRY_LEVEL_HANDLE).toNumber(); - } - if (arguments.property(WET_LEVEL_HANDLE).isNumber()) { - _wetLevel = arguments.property(WET_LEVEL_HANDLE).toNumber(); - } +static const float BANDWIDTH_DEFAULT = 10000.0f; +static const float PRE_DELAY_DEFAULT = 20.0f; +static const float LATE_DELAY_DEFAULT = 0.0f; +static const float REVERB_TIME_DEFAULT = 2.0f; +static const float EARLY_DIFFUSION_DEFAULT = 100.0f; +static const float LATE_DIFFUSION_DEFAULT = 100.0f; +static const float ROOM_SIZE_DEFAULT = 50.0f; +static const float DENSITY_DEFAULT = 100.0f; +static const float BASS_MULT_DEFAULT = 1.5f; +static const float BASS_FREQ_DEFAULT = 250.0f; +static const float HIGH_GAIN_DEFAULT = -6.0f; +static const float HIGH_FREQ_DEFAULT = 3000.0f; +static const float MOD_RATE_DEFAULT = 2.3f; +static const float MOD_DEPTH_DEFAULT = 50.0f; +static const float EARLY_GAIN_DEFAULT = 0.0f; +static const float LATE_GAIN_DEFAULT = 0.0f; +static const float EARLY_MIX_LEFT_DEFAULT = 20.0f; +static const float EARLY_MIX_RIGHT_DEFAULT = 20.0f; +static const float LATE_MIX_LEFT_DEFAULT = 90.0f; +static const float LATE_MIX_RIGHT_DEFAULT = 90.0f; +static const float WET_DRY_MIX_DEFAULT = 50.0f; + +static void setOption(QScriptValue arguments, const QString name, float default, float& var) { + var = arguments.property(name).isNumber() ? arguments.property(name).toNumber() : default; +} + +AudioEffectOptions::AudioEffectOptions(QScriptValue arguments) { + setOption(arguments, BANDWIDTH_HANDLE, BANDWIDTH_DEFAULT, _bandwidth); + setOption(arguments, PRE_DELAY_HANDLE, PRE_DELAY_DEFAULT, _preDelay); + setOption(arguments, LATE_DELAY_HANDLE, LATE_DELAY_DEFAULT, _lateDelay); + setOption(arguments, REVERB_TIME_HANDLE, REVERB_TIME_DEFAULT, _reverbTime); + setOption(arguments, EARLY_DIFFUSION_HANDLE, EARLY_DIFFUSION_DEFAULT, _earlyDiffusion); + setOption(arguments, LATE_DIFFUSION_HANDLE, LATE_DIFFUSION_DEFAULT, _lateDiffusion); + setOption(arguments, ROOM_SIZE_HANDLE, ROOM_SIZE_DEFAULT, _roomSize); + setOption(arguments, DENSITY_HANDLE, DENSITY_DEFAULT, _density); + setOption(arguments, BASS_MULT_HANDLE, BASS_MULT_DEFAULT, _bassMult); + setOption(arguments, BASS_FREQ_HANDLE, BASS_FREQ_DEFAULT, _bassFreq); + setOption(arguments, HIGH_GAIN_HANDLE, HIGH_GAIN_DEFAULT, _highGain); + setOption(arguments, HIGH_FREQ_HANDLE, HIGH_FREQ_DEFAULT, _highFreq); + setOption(arguments, MOD_RATE_HANDLE, MOD_RATE_DEFAULT, _modRate); + setOption(arguments, MOD_DEPTH_HANDLE, MOD_DEPTH_DEFAULT, _modDepth); + setOption(arguments, EARLY_GAIN_HANDLE, EARLY_GAIN_DEFAULT, _earlyGain); + setOption(arguments, LATE_GAIN_HANDLE, LATE_GAIN_DEFAULT, _lateGain); + setOption(arguments, EARLY_MIX_LEFT_HANDLE, EARLY_MIX_LEFT_DEFAULT, _earlyMixLeft); + setOption(arguments, EARLY_MIX_RIGHT_HANDLE, EARLY_MIX_RIGHT_DEFAULT, _earlyMixRight); + setOption(arguments, LATE_MIX_LEFT_HANDLE, LATE_MIX_LEFT_DEFAULT, _lateMixLeft); + setOption(arguments, LATE_MIX_RIGHT_HANDLE, LATE_MIX_RIGHT_DEFAULT, _lateMixRight); + setOption(arguments, WET_DRY_MIX_HANDLE, WET_DRY_MIX_DEFAULT, _wetDryMix); } AudioEffectOptions::AudioEffectOptions(const AudioEffectOptions &other) : QObject() { @@ -69,17 +87,28 @@ AudioEffectOptions::AudioEffectOptions(const AudioEffectOptions &other) : QObjec } AudioEffectOptions& AudioEffectOptions::operator=(const AudioEffectOptions &other) { - _maxRoomSize = other._maxRoomSize; - _roomSize = other._roomSize; + _bandwidth = other._bandwidth; + _preDelay = other._preDelay; + _lateDelay = other._lateDelay; _reverbTime = other._reverbTime; - _damping = other._damping; - _spread = other._spread; - _inputBandwidth = other._inputBandwidth; - _earlyLevel = other._earlyLevel; - _tailLevel = other._tailLevel; - _dryLevel = other._dryLevel; - _wetLevel = other._wetLevel; - + _earlyDiffusion = other._earlyDiffusion; + _lateDiffusion = other._lateDiffusion; + _roomSize = other._roomSize; + _density = other._density; + _bassMult = other._bassMult; + _bassFreq = other._bassFreq; + _highGain = other._highGain; + _highFreq = other._highFreq; + _modRate = other._modRate; + _modDepth = other._modDepth; + _earlyGain = other._earlyGain; + _lateGain = other._lateGain; + _earlyMixLeft = other._earlyMixLeft; + _earlyMixRight = other._earlyMixRight; + _lateMixLeft = other._lateMixLeft; + _lateMixRight = other._lateMixRight; + _wetDryMix = other._wetDryMix; + return *this; } diff --git a/libraries/audio/src/AudioEffectOptions.h b/libraries/audio/src/AudioEffectOptions.h index be5e1cca5e..9a65301473 100644 --- a/libraries/audio/src/AudioEffectOptions.h +++ b/libraries/audio/src/AudioEffectOptions.h @@ -15,32 +15,30 @@ #include #include -#include "AudioReverb.h" - class AudioEffectOptions : public QObject { Q_OBJECT - // Meters Square - Q_PROPERTY(float maxRoomSize READ getMaxRoomSize WRITE setMaxRoomSize) - Q_PROPERTY(float roomSize READ getRoomSize WRITE setRoomSize) - - // Seconds + Q_PROPERTY(float bandwidth READ getBandwidth WRITE setBandwidth) + Q_PROPERTY(float preDelay READ getPreDelay WRITE setPreDelay) + Q_PROPERTY(float lateDelay READ getLateDelay WRITE setLateDelay) Q_PROPERTY(float reverbTime READ getReverbTime WRITE setReverbTime) - - // Ratio between 0 and 1 - Q_PROPERTY(float damping READ getDamping WRITE setDamping) - - // (?) Does not appear to be set externally very often - Q_PROPERTY(float spread READ getSpread WRITE setSpread) - - // Ratio between 0 and 1 - Q_PROPERTY(float inputBandwidth READ getInputBandwidth WRITE setInputBandwidth) - - // in dB - Q_PROPERTY(float earlyLevel READ getEarlyLevel WRITE setEarlyLevel) - Q_PROPERTY(float tailLevel READ getTailLevel WRITE setTailLevel) - Q_PROPERTY(float dryLevel READ getDryLevel WRITE setDryLevel) - Q_PROPERTY(float wetLevel READ getWetLevel WRITE setWetLevel) + Q_PROPERTY(float earlyDiffusion READ getEarlyDiffusion WRITE setEarlyDiffusion) + Q_PROPERTY(float lateDiffusion READ getLateDiffusion WRITE setLateDiffusion) + Q_PROPERTY(float roomSize READ getRoomSize WRITE setRoomSize) + Q_PROPERTY(float density READ getDensity WRITE setDensity) + Q_PROPERTY(float bassMult READ getBassMult WRITE setBassMult) + Q_PROPERTY(float bassFreq READ getBassFreq WRITE setBassFreq) + Q_PROPERTY(float highGain READ getHighGain WRITE setHighGain) + Q_PROPERTY(float highFreq READ getHighFreq WRITE setHighFreq) + Q_PROPERTY(float modRate READ getModRate WRITE setModRate) + Q_PROPERTY(float modDepth READ getModDepth WRITE setModDepth) + Q_PROPERTY(float earlyGain READ getEarlyGain WRITE setEarlyGain) + Q_PROPERTY(float lateGain READ getLateGain WRITE setLateGain) + Q_PROPERTY(float earlyMixLeft READ getEarlyMixLeft WRITE setEarlyMixLeft) + Q_PROPERTY(float earlyMixRight READ getEarlyMixRight WRITE setEarlyMixRight) + Q_PROPERTY(float lateMixLeft READ getLateMixLeft WRITE setLateMixLeft) + Q_PROPERTY(float lateMixRight READ getLateMixRight WRITE setLateMixRight) + Q_PROPERTY(float wetDryMix READ getWetDryMix WRITE setWetDryMix) public: AudioEffectOptions(QScriptValue arguments = QScriptValue()); @@ -49,60 +47,100 @@ public: static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine); - float getRoomSize() const { return _roomSize; } - void setRoomSize(float roomSize ) { _roomSize = roomSize; } + float getBandwidth() const { return _bandwidth; } + void setBandwidth(float bandwidth) { _bandwidth = bandwidth; } - float getMaxRoomSize() const { return _maxRoomSize; } - void setMaxRoomSize(float maxRoomSize ) { _maxRoomSize = maxRoomSize; } + float getPreDelay() const { return _preDelay; } + void setPreDelay(float preDelay) { _preDelay = preDelay; } + + float getLateDelay() const { return _lateDelay; } + void setLateDelay(float lateDelay) { _lateDelay = lateDelay; } float getReverbTime() const { return _reverbTime; } - void setReverbTime(float reverbTime ) { _reverbTime = reverbTime; } + void setReverbTime(float reverbTime) { _reverbTime = reverbTime; } - float getDamping() const { return _damping; } - void setDamping(float damping ) { _damping = damping; } + float getEarlyDiffusion() const { return _earlyDiffusion; } + void setEarlyDiffusion(float earlyDiffusion) { _earlyDiffusion = earlyDiffusion; } - float getSpread() const { return _spread; } - void setSpread(float spread ) { _spread = spread; } + float getLateDiffusion() const { return _lateDiffusion; } + void setLateDiffusion(float lateDiffusion) { _lateDiffusion = lateDiffusion; } - float getInputBandwidth() const { return _inputBandwidth; } - void setInputBandwidth(float inputBandwidth ) { _inputBandwidth = inputBandwidth; } + float getRoomSize() const { return _roomSize; } + void setRoomSize(float roomSize) { _roomSize = roomSize; } - float getEarlyLevel() const { return _earlyLevel; } - void setEarlyLevel(float earlyLevel ) { _earlyLevel = earlyLevel; } + float getDensity() const { return _density; } + void setDensity(float density) { _density = density; } - float getTailLevel() const { return _tailLevel; } - void setTailLevel(float tailLevel ) { _tailLevel = tailLevel; } + float getBassMult() const { return _bassMult; } + void setBassMult(float bassMult) { _bassMult = bassMult; } - float getDryLevel() const { return _dryLevel; } - void setDryLevel(float dryLevel) { _dryLevel = dryLevel; } + float getBassFreq() const { return _bassFreq; } + void setBassFreq(float bassFreq) { _bassFreq = bassFreq; } - float getWetLevel() const { return _wetLevel; } - void setWetLevel(float wetLevel) { _wetLevel = wetLevel; } + float getHighGain() const { return _highGain; } + void setHighGain(float highGain) { _highGain = highGain; } + + float getHighFreq() const { return _highFreq; } + void setHighFreq(float highFreq) { _highFreq = highFreq; } + + float getModRate() const { return _modRate; } + void setModRate(float modRate) { _modRate = modRate; } + + float getModDepth() const { return _modDepth; } + void setModDepth(float modDepth) { _modDepth = modDepth; } + + float getEarlyGain() const { return _earlyGain; } + void setEarlyGain(float earlyGain) { _earlyGain = earlyGain; } + + float getLateGain() const { return _lateGain; } + void setLateGain(float lateGain) { _lateGain = lateGain; } + + float getEarlyMixLeft() const { return _earlyMixLeft; } + void setEarlyMixLeft(float earlyMixLeft) { _earlyMixLeft = earlyMixLeft; } + + float getEarlyMixRight() const { return _earlyMixRight; } + void setEarlyMixRight(float earlyMixRight) { _earlyMixRight = earlyMixRight; } + + float getLateMixLeft() const { return _lateMixLeft; } + void setLateMixLeft(float lateMixLeft) { _lateMixLeft = lateMixLeft; } + + float getLateMixRight() const { return _lateMixRight; } + void setLateMixRight(float lateMixRight) { _lateMixRight = lateMixRight; } + + float getWetDryMix() const { return _wetDryMix; } + void setWetDryMix(float wetDryMix) { _wetDryMix = wetDryMix; } private: - // http://wiki.audacityteam.org/wiki/GVerb#Instant_Reverberb_settings + float _bandwidth; // [20, 24000] Hz - // Meters Square - float _maxRoomSize; - float _roomSize; + float _preDelay; // [0, 333] ms + float _lateDelay; // [0, 166] ms - // Seconds - float _reverbTime; + float _reverbTime; // [0.1, 100] seconds - // Ratio between 0 and 1 - float _damping; + float _earlyDiffusion; // [0, 100] percent + float _lateDiffusion; // [0, 100] percent - // ? (Does not appear to be set externally very often) - float _spread; + float _roomSize; // [0, 100] percent + float _density; // [0, 100] percent - // Ratio between 0 and 1 - float _inputBandwidth; + float _bassMult; // [0.1, 10] ratio + float _bassFreq; // [10, 500] Hz + float _highGain; // [-24, 0] dB + float _highFreq; // [1000, 12000] Hz - // dB - float _earlyLevel; - float _tailLevel; - float _dryLevel; - float _wetLevel; + float _modRate; // [0.1, 10] Hz + float _modDepth; // [0, 100] percent + + float _earlyGain; // [-96, +24] dB + float _lateGain; // [-96, +24] dB + + float _earlyMixLeft; // [0, 100] percent + float _earlyMixRight; // [0, 100] percent + float _lateMixLeft; // [0, 100] percent + float _lateMixRight; // [0, 100] percent + + float _wetDryMix; // [0, 100] percent }; #endif // hifi_AudioEffectOptions_h From 90ef92c79b95285db630c10c0edabc15a1f6ae42 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Mon, 7 Dec 2015 13:34:55 -0800 Subject: [PATCH 076/174] Fix slider layout --- examples/utilities/tools/reverbTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/utilities/tools/reverbTest.js b/examples/utilities/tools/reverbTest.js index 2b08073ae0..a7a6bad9d7 100644 --- a/examples/utilities/tools/reverbTest.js +++ b/examples/utilities/tools/reverbTest.js @@ -39,7 +39,7 @@ AudioDevice.setReverbOptions(audioOptions); AudioDevice.setReverb(true); print("Reverb is ON."); -var panel = new Panel(10, 150); +var panel = new Panel(10, 160); var parameters = [ { name: "bandwidth", min: 1000, max: 12000, units: " Hz" }, From 873496e64b68ca57b76744429aa9b9b156cbffd7 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 7 Dec 2015 13:53:40 -0800 Subject: [PATCH 077/174] cleanup --- examples/drylake/createAvatarDetector.js | 21 +++- examples/drylake/ratCreator.js | 110 +++++++++------------ examples/drylake/{steer.js => ratSteer.js} | 28 ++++-- 3 files changed, 86 insertions(+), 73 deletions(-) rename examples/drylake/{steer.js => ratSteer.js} (89%) diff --git a/examples/drylake/createAvatarDetector.js b/examples/drylake/createAvatarDetector.js index 82a1806ca8..51ca55248e 100644 --- a/examples/drylake/createAvatarDetector.js +++ b/examples/drylake/createAvatarDetector.js @@ -1,3 +1,16 @@ +// +// createAvatarDetector.js +// +// Created by James B. Pollack @imgntn on 12/7/2015 +// Copyright 2015 High Fidelity, Inc. +// +// Run this script if you want the rats to run away from you. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + var avatarDetector = null; function createAvatarDetector() { @@ -20,14 +33,16 @@ function createAvatarDetector() { blue: 0 } } - avatarDetector= Entities.addEntity(detectorProperties); + + avatarDetector = Entities.addEntity(detectorProperties); }; + var updateAvatarDetector = function() { // print('updating detector position' + JSON.stringify(MyAvatar.position)) - Entities.editEntity(avatarDetector, { position: MyAvatar.position - }) + }); + }; var cleanup = function() { diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 731255527a..ecf19d66eb 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -1,4 +1,22 @@ -Script.include('steer.js'); +// +// ratCreator.js +// +// Created by James B. Pollack @imgntn on 12/7/2015 +// Copyright 2015 High Fidelity, Inc. +// +// This script spawns some rats that have simple steering behaviors applied to them. +// Run it in the 'drylake' environment, or adjust all object locations to match your scene. +// +// Steering bevhaviors from ratSteer.js: +// The rats will move from a spawning point toward their nest. +// They will avoid avoider blocks moving across the alley +// They will avoid avatars running createAvatarDetector.js +// +// 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('ratSteer.js'); var steer = loadSteer(); Script.include('../libraries/tween.js'); var TWEEN = loadTween(); @@ -60,10 +78,6 @@ function playRatDeathAnimation(rat) { Entities.editEntity(rat, { animationURL: RAT_DEATH_ANIMATION_URL, animationSettings: animationSettings - // animation: { - // url: RAT_DEATH_ANIMATION_URL, - // running: true - // }, }); } @@ -77,7 +91,6 @@ var modelRatProperties = { damping: 0.8, angularDamping: 0.99, friction: 0.75, - // restitution:0.1, collisionsWillMove: true, ignoreForCollisions: false, gravity: { @@ -86,8 +99,6 @@ var modelRatProperties = { z: 0 }, lifetime: 30, - // rotation: Quat.fromPitchYawRollDegrees(0, 180, 0), - //disable this if for some reason we want grabbable rats userData: JSON.stringify({ grabbableKey: { grabbable: false @@ -256,13 +267,16 @@ function createRatSoundInjector() { function moveRats() { rats.forEach(function(rat) { - checkDistanceFromNest(rat); - // print('debug1') - var avatarFlightVectors = steer.fleeAllAvatars(rat); - // print('avatarFlightVectors' + avatarFlightVectors) - var i, j; - var averageAvatarFlight; + //remove the rat if its near the nest + checkDistanceFromNest(rat); + + //otherwise figure out where to send it + + //see if there are avatars to run from + var avatarFlightVectors = steer.fleeAllAvatars(rat); + var averageAvatarFlight; + var i; for (i = 0; i < avatarFlightVectors.length; i++) { if (i === 0) { averageAvatarFlight = avatarFlightVectors[0]; @@ -270,15 +284,12 @@ function moveRats() { averageAvatarFlight = Vec3.sum(avatarFlightVectors[i - 1], avatarFlightVectors[i]) } } - - // averageAvatarFlight = Vec3.normalize(averageAvatarFlight); - averageAvatarFlight = Vec3.multiply(averageAvatarFlight, 1 / avatarFlightVectors.length); + //see if there are avoiders to flee var avoidBlockVectors = steer.fleeAvoiderBlocks(rat); - var averageAvoiderFlight; - + var j; for (j = 0; j < avoidBlockVectors.length; j++) { if (j === 0) { averageAvoiderFlight = avoidBlockVectors[0]; @@ -286,32 +297,29 @@ function moveRats() { averageAvoiderFlight = Vec3.sum(avoidBlockVectors[j - 1], avoidBlockVectors[j]) } }; - - // avarageAvoiderFlight = Vec3.normalize(averageAvoiderFlight); - averageAvoiderFlight = Vec3.multiply(averageAvoiderFlight, 1 / avoidBlockVectors.length); - var averageVector; + //add all of the vectors and divide them by total to get average vector + //start by trying to go toward the nest var seek = steer.arrive(rat, target); - averageVector = seek; + var averageVector = seek; var divisorCount = 1; + + //if there are avatars to run away from if (avatarFlightVectors.length > 0) { divisorCount++; averageVector = Vec3.sum(averageVector, averageAvatarFlight); } + + //or if there are avoider blocks to run away from if (avoidBlockVectors.length > 0) { divisorCount++; averageVector = Vec3.sum(averageVector, averageAvoiderFlight); } averageVector = Vec3.multiply(averageVector, 1 / divisorCount); + var thisRatProps = Entities.getEntityProperties(rat, ["position", "rotation"]); - - - // var constrainedRotation = Quat.fromVec3Degrees(eulerAngle); - - // print('CR:::'+JSON.stringify(constrainedRotation)) - var ratPosition = thisRatProps.position; var ratToNest = Vec3.subtract(RAT_NEST_LOCATION, ratPosition); var ratRotation = Quat.rotationBetween(Vec3.UNIT_Z, ratToNest); @@ -325,11 +333,12 @@ function moveRats() { rotation: constrainedRotation, }) + //have to make a 'meta' rat object to keep track of rats for updating sound injector locations. parenting sounds would make this easy. var metaRat = getMetaRatByRat(rat); if (metaRat !== undefined) { if (metaRat.injector !== undefined) { if (metaRat.injector.isPlaying === true) { - // print('update injector position') + // print('update injector position') metaRat.injector.options = { loop: true, position: ratPosition @@ -337,11 +346,9 @@ function moveRats() { } } - } else { // print('no meta rat for this rat') } - // castRay(rat); }) } @@ -356,16 +363,14 @@ function checkDistanceFromNest(rat) { removeRatFromScene(rat); } else { // print('not yet at nest:::' + distance) - } } function removeRatFromScene(rat) { - var index = rats.indexOf(rat); if (index > -1) { - // print('CLEAR RAT::'+rat) + // print('CLEAR RAT::'+rat) rats.splice(index, 1); Entities.deleteEntity(rat); @@ -373,13 +378,11 @@ function removeRatFromScene(rat) { var metaRatIndex = findWithAttr(metaRats, 'rat', rat); if (metaRatIndex > -1) { - // print('CLEAR META RAT') + // print('CLEAR META RAT') metaRats[index].injector.stop(); metaRats.splice(index, 1); } - - } function popRatFromStack(entityID) { @@ -389,7 +392,7 @@ function popRatFromStack(entityID) { rats.splice(index, 1); } - var metaRatIndex = findWithAttr(metaRats, 'rat', entityID); + var metaRatIndex = findWithAttr(metaRats, 'rat', entityID); if (metaRatIndex > -1) { metaRats[index].injector.stop(); metaRats.splice(index, 1); @@ -416,7 +419,7 @@ Entities.deletingEntity.connect(popRatFromStack); function cleanupLeftoverAvoidersBeforeStart() { - // print('CLEANING UP LEFTOVER AVOIDERS') + //sometimes if we crash or something there could be extra avoider blocks around. clear them out. var nearbyEntities = Entities.findEntities(RAT_SPAWNER_LOCATION, 100); var entityIndex; for (entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { @@ -453,7 +456,6 @@ if (USE_CONSTANT_SPAWNER === true) { var rat = addRat(); playRatRunningAnimation(rat); rats.push(rat); - // print('ratCount::'+ratCount) ratCount++; if (ratCount % 6 === 0) { var metaRat = { @@ -466,28 +468,8 @@ if (USE_CONSTANT_SPAWNER === true) { //if we have too many injectors hanging around there are problems metaRat.injector.stop(); delete metaRat.injector; - }, RAT_SPAWN_RATE * 3) + }, RAT_SPAWN_RATE * 3); } }, RAT_SPAWN_RATE); -} - -//unused for now, to be used for some collision avoidance on walls and stuff? - -// function castRay(rat) { -// var ratProps = Entities.getEntityProperties(rat, ["position", "rotation"]); -// var shotDirection = Quat.getFront(ratProps.rotation); -// var pickRay = { -// origin: ratProps.position, -// direction: shotDirection -// }; - -// var intersection = Entities.findRayIntersection(pickRay, true); -// if (intersection.intersects) { -// var distance = Vec3.subtract(intersection.properties.position, ratProps.position); -// distance = Vec3.length(distance); -// // print('INTERSECTION:::'+distance); -// } else { -// //print('no intersection') -// } -// } \ No newline at end of file +} \ No newline at end of file diff --git a/examples/drylake/steer.js b/examples/drylake/ratSteer.js similarity index 89% rename from examples/drylake/steer.js rename to examples/drylake/ratSteer.js index 1c2502fbcb..577166087e 100644 --- a/examples/drylake/steer.js +++ b/examples/drylake/ratSteer.js @@ -1,3 +1,15 @@ +// +// ratSteer.js +// +// Created by James B. Pollack @imgntn on 12/7/2015 +// Copyright 2015 High Fidelity, Inc. +// +// This is an example of steering behaviors that can be applied entities. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + function flee(thisEntity, target) { var targetPosition = Entities.getEntityProperties(target, "position").position; var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); @@ -48,8 +60,8 @@ function fleeAllAvatars(thisEntity) { if (d < 3) { var steer = Vec3.subtract(desired, velocity); var steerVector = new V3(desired.x, 0, desired.z); - steer = steerVector.limit(MAX_FORCE) - flightVectors.push(steer) + steer = steerVector.limit(MAX_FORCE); + flightVectors.push(steer); } else { // print('target too far away from this avatar to flee' + d); } @@ -57,7 +69,7 @@ function fleeAllAvatars(thisEntity) { } - return flightVectors + return flightVectors; } function fleeAvoiderBlocks(thisEntity) { @@ -81,6 +93,7 @@ function fleeAvoiderBlocks(thisEntity) { var d = Vec3.length(desired); desired = Vec3.normalize(desired); desired = Vec3.multiply(MAX_SPEED, desired); + if (d < 5) { var steer = Vec3.subtract(desired, velocity); var steerVector = new V3(desired.x, 0, desired.z); @@ -89,11 +102,12 @@ function fleeAvoiderBlocks(thisEntity) { } else { //print('target too far away from this avoider to flee' + d); } + } } - return flightVectors + return flightVectors; } function arrive(thisEntity, target) { @@ -109,17 +123,19 @@ function arrive(thisEntity, target) { var desired = Vec3.subtract(targetPosition, location); var d = Vec3.length(desired); desired = Vec3.normalize(desired); + if (d < ARRIVAL_DISTANCE) { var m = scale(d, 0, ARRIVAL_DISTANCE, 0, MAX_SPEED); } else { desired = Vec3.multiply(MAX_SPEED, desired); } + var steer = Vec3.subtract(desired, velocity); var steerVector = new V3(desired.x, 0, desired.z); - steer = steerVector.limit(MAX_FORCE) + steer = steerVector.limit(MAX_FORCE); - return steer + return steer; } From 692527681922ece28980f421ff9fab51ed284c93 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 7 Dec 2015 14:01:53 -0800 Subject: [PATCH 078/174] cleanup --- examples/drylake/ratSteer.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/drylake/ratSteer.js b/examples/drylake/ratSteer.js index 577166087e..f69ab81f6d 100644 --- a/examples/drylake/ratSteer.js +++ b/examples/drylake/ratSteer.js @@ -18,7 +18,6 @@ function flee(thisEntity, target) { var MAX_SPEED = 1; var MAX_FORCE = 1; - var desired = Vec3.subtract(location, targetPosition); var d = Vec3.length(desired); desired = Vec3.normalize(desired); @@ -85,7 +84,6 @@ function fleeAvoiderBlocks(thisEntity) { var entityProps = Entities.getEntityProperties(entityID); if (entityProps.name === 'Hifi-Rat-Avoider') { // print('found an avoiderblock to flee'); - var MAX_SPEED = 11; var MAX_FORCE = 6; From 86db12acae1c8eaf93674dbe1d76c6d75a2becfe Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Mon, 7 Dec 2015 14:03:11 -0800 Subject: [PATCH 079/174] Fix naming clash with reserved word --- libraries/audio/src/AudioEffectOptions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio/src/AudioEffectOptions.cpp b/libraries/audio/src/AudioEffectOptions.cpp index 792799b776..758875e896 100644 --- a/libraries/audio/src/AudioEffectOptions.cpp +++ b/libraries/audio/src/AudioEffectOptions.cpp @@ -54,8 +54,8 @@ static const float LATE_MIX_LEFT_DEFAULT = 90.0f; static const float LATE_MIX_RIGHT_DEFAULT = 90.0f; static const float WET_DRY_MIX_DEFAULT = 50.0f; -static void setOption(QScriptValue arguments, const QString name, float default, float& var) { - var = arguments.property(name).isNumber() ? arguments.property(name).toNumber() : default; +static void setOption(QScriptValue arguments, const QString name, float defaultValue, float& variable) { + variable = arguments.property(name).isNumber() ? arguments.property(name).toNumber() : defaultValue; } AudioEffectOptions::AudioEffectOptions(QScriptValue arguments) { From 2974241796d847e1a5c13fa7ab54d50918d04a93 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 7 Dec 2015 15:49:29 -0800 Subject: [PATCH 080/174] typo --- interface/src/avatar/AvatarManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 35b5db7946..0f96ca9af0 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -111,7 +111,7 @@ void AvatarManager::init() { _renderDistanceController.setKP(0.0008f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. _renderDistanceController.setKI(0.0006f); // Big enough to bring us to target with the above KP. _renderDistanceController.setKD(0.000001f); // A touch of kd increases the speed by which we get there. - a_renderDistanceController.setHistorySize("av", 240); //FIXME + _renderDistanceController.setHistorySize("av", 240); //FIXME } void AvatarManager::updateMyAvatar(float deltaTime) { From b007617c8555dca32206fe1c69f26abfd2fe6b13 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 7 Dec 2015 16:56:59 -0800 Subject: [PATCH 081/174] Remove unneeded DisplayPlugin stuff. --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 6 ------ .../src/display-plugins/OpenGLDisplayPlugin.h | 4 ---- 2 files changed, 10 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index b010414396..8e02077600 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -151,7 +151,6 @@ OpenGLDisplayPlugin::OpenGLDisplayPlugin() { _container->releaseOverlayTexture(texture); }); - _synchronizedTimer.start(); connect(&_timer, &QTimer::timeout, this, [&] { #ifdef Q_OS_MAC // On Mac, QT thread timing is such that we can miss one or even two cycles quite often, giving a render rate (including update/simulate) @@ -161,7 +160,6 @@ OpenGLDisplayPlugin::OpenGLDisplayPlugin() { #else if (_active && _sceneTextureEscrow.depth() < 1) { #endif - _synchronizedTimer.start(); emit requestRender(); } }); @@ -283,10 +281,6 @@ void OpenGLDisplayPlugin::submitOverlayTexture(GLuint sceneTexture, const glm::u } void OpenGLDisplayPlugin::updateTextures() { - const qint64 elapsed =_synchronizedTimer.elapsed(); - if (elapsed != 0) { - _lastSynchronizedElapsed = elapsed; - } _currentSceneTexture = _sceneTextureEscrow.fetchAndRelease(_currentSceneTexture); _currentOverlayTexture = _overlayTextureEscrow.fetchAndRelease(_currentOverlayTexture); } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 4577777034..ef78374994 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -10,7 +10,6 @@ #include "DisplayPlugin.h" #include -#include #include #include @@ -31,7 +30,6 @@ public: virtual void submitSceneTexture(uint32_t frameIndex, uint32_t sceneTexture, const glm::uvec2& sceneSize) override; virtual void submitOverlayTexture(uint32_t overlayTexture, const glm::uvec2& overlaySize) override; virtual float presentRate() override; - virtual qint64 getLastSynchronizedElapsed() { return _lastSynchronizedElapsed; } virtual glm::uvec2 getRecommendedRenderSize() const override { return getSurfacePixels(); @@ -70,8 +68,6 @@ protected: virtual void internalPresent(); mutable QTimer _timer; - QElapsedTimer _synchronizedTimer; - qint64 _lastSynchronizedElapsed { 0 }; ProgramPtr _program; ShapeWrapperPtr _plane; From 9512c3f73da0033a6c094606bd6bb824c60e4b7f Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 7 Dec 2015 16:58:59 -0800 Subject: [PATCH 082/174] Debugging. Please enter the commit message for your changes. Lines starting --- interface/src/Application.cpp | 19 +++++++++---------- interface/src/Application.h | 1 + interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/AvatarManager.cpp | 21 +++++++++++++++++---- libraries/shared/src/PIDController.cpp | 2 +- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6e4f3de649..521921faea 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1117,6 +1117,8 @@ void Application::paintGL() { _inPaint = true; Finally clearFlagLambda([this] { _inPaint = false; }); + _lastPaintWait = (float)(now - _paintWaitStart) / (float)USECS_PER_SECOND; + _lastInstantaneousFps = instantaneousFps; // Some LOD-like controls need to know a smoothly varying "potential" frame rate that doesn't // include time waiting for vsync, and which can report a number above target if we've got the headroom. // For example, if we're shooting for 75fps and paintWait is 3.3333ms (= 75% * 13.33ms), our deducedNonVSyncFps @@ -1126,20 +1128,20 @@ void Application::paintGL() { // Time between previous paintGL call and this one, which can vary not only with vSync misses, but also with QT timing. // We're using this as a proxy for the time between vsync and displayEnd, below. (Not exact, but tends to be the same over time.) // This is not the same as update(deltaTime), because the latter attempts to throttle to 60hz and also clamps to 1/4 second. - //const float actualPeriod = diff / (float)USECS_PER_SECOND; // same as 1/instantaneousFps but easier for compiler to optimize +/* const float actualPeriod = diff / (float)USECS_PER_SECOND; // same as 1/instantaneousFps but easier for compiler to optimize // Note that _lastPaintWait (stored at end of last call) is for the same paint cycle. - float deducedNonVSyncPeriod = (float) getActiveDisplayPlugin()->getLastSynchronizedElapsed() / (float) MSECS_PER_SECOND; /*actualPeriod - _lastPaintWait + _marginForDeducedFramePeriod; // plus a some non-zero time for machinery we can't measure + float deducedNonVSyncPeriod = actualPeriod - _lastPaintWait + _marginForDeducedFramePeriod; // plus a some non-zero time for machinery we can't measure // We don't know how much time to allow for that, but if we went over the target period, we know it's at least the portion // of paintWait up to the next vSync. This gives us enough of a penalty so that when actualPeriod crosses two cycles, // the key part (and not an exagerated part) of _lastPaintWait is accounted for. const float targetPeriod = getTargetFramePeriod(); if (_lastPaintWait > EPSILON && actualPeriod > targetPeriod) { // Don't use C++ remainder(). It's authors are mathematically insane. - deducedNonVSyncPeriod += fmod(actualPeriod, _lastPaintWait); - }*/ + deducedNonVSyncPeriod += fmod(targetPeriod, _lastPaintWait); + } _lastDeducedNonVSyncFps = 1.0f / deducedNonVSyncPeriod; - _lastInstantaneousFps = instantaneousFps; - + */ + auto displayPlugin = getActiveDisplayPlugin(); // FIXME not needed anymore? _offscreenContext->makeCurrent(); @@ -1375,7 +1377,6 @@ void Application::paintGL() { } // deliver final composited scene to the display plugin - uint64_t displayStart = usecTimestampNow(); { PROFILE_RANGE(__FUNCTION__ "/pluginOutput"); PerformanceTimer perfTimer("pluginOutput"); @@ -1415,9 +1416,7 @@ void Application::paintGL() { batch.resetStages(); }); } - uint64_t displayEnd = usecTimestampNow(); - const float displayPeriodUsec = (float)(displayEnd - displayStart); // usecs - _lastPaintWait = displayPeriodUsec / (float)USECS_PER_SECOND; + _paintWaitStart = usecTimestampNow(); } void Application::runTests() { diff --git a/interface/src/Application.h b/interface/src/Application.h index ce33f051ef..197d9a7a60 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -443,6 +443,7 @@ private: QElapsedTimer _lastTimeUpdated; float _lastInstantaneousFps { 0.0f }; float _lastPaintWait { 0.0f }; + uint64_t _paintWaitStart { 0 }; float _lastDeducedNonVSyncFps { 0.0f }; float _marginForDeducedFramePeriod{ 0.002f }; // 2ms, adjustable diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2c8d970336..4558e6046d 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -174,14 +174,14 @@ void Avatar::simulate(float deltaTime) { _shouldSkipRender = false; _skeletonModel.setVisibleInScene(true, qApp->getMain3DScene()); if (!isControllerLogging) { // Test for isMyAvatar is prophylactic. Never occurs in current code. - qCDebug(interfaceapp) << "Rerendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for distance" << renderDistance; + //qCDebug(interfaceapp) << "Rerendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for distance" << renderDistance; } } } else if (distance > renderDistance * (1.0f + SKIP_HYSTERESIS_PROPORTION)) { _shouldSkipRender = true; _skeletonModel.setVisibleInScene(false, qApp->getMain3DScene()); if (!isControllerLogging) { - qCDebug(interfaceapp) << "Unrendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for distance" << renderDistance; + //qCDebug(interfaceapp) << "Unrendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for distance" << renderDistance; } } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index ba483a80ca..0b5551555c 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -111,7 +111,7 @@ void AvatarManager::init() { _renderDistanceController.setKP(0.0008f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. _renderDistanceController.setKI(0.0006f); // Big enough to bring us to target with the above KP. _renderDistanceController.setKD(0.000001f); // A touch of kd increases the speed by which we get there. - _renderDistanceController.setHistorySize("av", 240); //FIXME + //_renderDistanceController.setHistorySize("av", 240); //FIXME } void AvatarManager::updateMyAvatar(float deltaTime) { @@ -130,7 +130,7 @@ void AvatarManager::updateMyAvatar(float deltaTime) { _lastSendAvatarDataTime = now; } } - +#include "InterfaceLogging.h" void AvatarManager::updateOtherAvatars(float deltaTime) { // lock the hash for read to check the size QReadLocker lock(&_hashLock); @@ -151,8 +151,21 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { // The measured value is frame rate. When the controlled value (1 / render cutoff distance) // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate // goes up. - const float deduced = qApp->getLastDeducedNonVSyncFps(); - const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime, false, qApp->getLastPaintWait(), qApp->getLastInstanteousFps()); + const float targetFps = 60.0f; + const float instantaneousFps = qApp->getLastInstanteousFps(); + const float paintWait = qApp->getLastPaintWait(); + const float actual = 1.0f / instantaneousFps; + const float firstAdjusted = actual - paintWait + 0.002f; + const float machinery = (paintWait > 0.0001f) ? fmod(1.0f / targetFps, paintWait) : 0.0f; + const float secondAdjusted = firstAdjusted + machinery; + const float deduced = 1.0f / secondAdjusted; + qCDebug(interfaceapp) << "dump " << instantaneousFps << (1000.0f * paintWait) + << "(" << paintWait << actual + << "(" << firstAdjusted << machinery << secondAdjusted + << ")" << deduced << ")"; + + //const float deduced = qApp->getLastDeducedNonVSyncFps(); + const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime, false, paintWait, instantaneousFps); _renderDistanceAverage.updateAverage(distance); _renderDistance = _renderDistanceAverage.getAverage(); int renderableCount = 0; diff --git a/libraries/shared/src/PIDController.cpp b/libraries/shared/src/PIDController.cpp index 36c670e66d..3607c281ec 100644 --- a/libraries/shared/src/PIDController.cpp +++ b/libraries/shared/src/PIDController.cpp @@ -70,7 +70,7 @@ void PIDController::reportHistory() { for (int i = 0; i < _history.size(); i++) { Row& row = _history[i]; qCDebug(shared) << row.measured << row.dt << - row.fixme1 << row.fixme2 << + (row.fixme1 * 1000.0f) << (row.fixme2) << "||" << row.error << row.accumulated << row.changed << "||" << row.p << row.i << row.d << row.computed << 1.0f/row.computed; } From b24af06589141a194c1c50f64f2752eaee199243 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 7 Dec 2015 18:26:55 -0800 Subject: [PATCH 083/174] Fixing the display of the collision hull mesh --- libraries/render-utils/src/MeshPartPayload.cpp | 4 ++++ libraries/render-utils/src/MeshPartPayload.h | 3 +++ libraries/render-utils/src/Model.cpp | 15 ++++++++++++--- libraries/render-utils/src/ModelRender.cpp | 11 +++++++++++ libraries/render-utils/src/ModelRender.h | 5 +++++ libraries/script-engine/src/ScriptEngine.cpp | 2 +- 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index bb37bb4932..456f6eac51 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -71,6 +71,10 @@ void MeshPartPayload::initCache() { } +void MeshPartPayload::updateDrawMaterial(model::MaterialPointer material) { + _drawMaterial = material; +} + void MeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) { _modelPosition = position; _modelOrientation = orientation; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index b29d9510d1..5d30eddd20 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -36,6 +36,9 @@ public: glm::vec3 _modelPosition; glm::quat _modelOrientation; + // can replace the material used to draw that item + void updateDrawMaterial(model::MaterialPointer material); + void updateModelLocation(glm::vec3 position, glm::quat orientation); // Render Item interface diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f566d0879d..96fd52edcc 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -544,6 +544,7 @@ void Model::removeFromScene(std::shared_ptr scene, render::Pendin pendingChanges.removeItem(item); } _renderItems.clear(); + _renderItemsSet.clear(); _readyWhenAdded = false; } @@ -1118,8 +1119,10 @@ AABox Model::getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition void Model::segregateMeshGroups() { QSharedPointer networkGeometry; + bool showingCollisionHull = false; if (_showCollisionHull && _collisionGeometry && _collisionGeometry->isLoaded()) { networkGeometry = _collisionGeometry; + showingCollisionHull = true; } else { networkGeometry = _geometry; } @@ -1127,8 +1130,10 @@ void Model::segregateMeshGroups() { const std::vector>& networkMeshes = networkGeometry->getMeshes(); // all of our mesh vectors must match in size - if ((int)networkMeshes.size() != geometry.meshes.size() || - geometry.meshes.size() != _meshStates.size()) { + auto geoMeshesSize = geometry.meshes.size(); + if ((int)networkMeshes.size() != geoMeshesSize || + // geometry.meshes.size() != _meshStates.size()) { + geoMeshesSize > _meshStates.size()) { qDebug() << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; return; } @@ -1146,7 +1151,11 @@ void Model::segregateMeshGroups() { // Create the render payloads int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { - _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); + auto renderItem = std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); + if (showingCollisionHull) { + renderItem->updateDrawMaterial(ModelRender::getCollisionHullMaterial()); + } + _renderItemsSet << renderItem; shapeID++; } } diff --git a/libraries/render-utils/src/ModelRender.cpp b/libraries/render-utils/src/ModelRender.cpp index 73f3d715b6..1c4109b185 100644 --- a/libraries/render-utils/src/ModelRender.cpp +++ b/libraries/render-utils/src/ModelRender.cpp @@ -280,3 +280,14 @@ void ModelRender::pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, b DependencyManager::get()->getNormalFittingTexture()); } } + +model::MaterialPointer ModelRender::_collisionHullMaterial; + +model::MaterialPointer ModelRender::getCollisionHullMaterial() { + if (!_collisionHullMaterial) { + _collisionHullMaterial = std::make_shared(); + _collisionHullMaterial->setDiffuse(glm::vec3(1.0f, 0.5f, 0.0f)); + } + return _collisionHullMaterial; +} + diff --git a/libraries/render-utils/src/ModelRender.h b/libraries/render-utils/src/ModelRender.h index 1528dcfc87..39fe05378d 100644 --- a/libraries/render-utils/src/ModelRender.h +++ b/libraries/render-utils/src/ModelRender.h @@ -149,6 +149,11 @@ public: static const RenderPipelineLib& getRenderPipelineLib(); + // Collision hull Material + static model::MaterialPointer _collisionHullMaterial; + + static model::MaterialPointer getCollisionHullMaterial(); + }; #endif // hifi_ModelRender_h \ No newline at end of file diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 3306659c80..a075b0a91d 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 faec4639b1d8b93f090799b80f084f8f7ac0fc25 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 8 Dec 2015 09:14:40 -0800 Subject: [PATCH 084/174] cap --- interface/src/avatar/AvatarManager.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 0b5551555c..b101c106a2 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -111,7 +111,7 @@ void AvatarManager::init() { _renderDistanceController.setKP(0.0008f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. _renderDistanceController.setKI(0.0006f); // Big enough to bring us to target with the above KP. _renderDistanceController.setKD(0.000001f); // A touch of kd increases the speed by which we get there. - //_renderDistanceController.setHistorySize("av", 240); //FIXME + _renderDistanceController.setHistorySize("av", 240); //FIXME } void AvatarManager::updateMyAvatar(float deltaTime) { @@ -155,17 +155,23 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { const float instantaneousFps = qApp->getLastInstanteousFps(); const float paintWait = qApp->getLastPaintWait(); const float actual = 1.0f / instantaneousFps; - const float firstAdjusted = actual - paintWait + 0.002f; - const float machinery = (paintWait > 0.0001f) ? fmod(1.0f / targetFps, paintWait) : 0.0f; + const float target = 1.0f / targetFps; + const float firstAdjusted = actual - paintWait /*+ 0.002f*/; + const float machinery = (paintWait > target) ? fmod(paintWait, target) : 0.0f; const float secondAdjusted = firstAdjusted + machinery; const float deduced = 1.0f / secondAdjusted; - qCDebug(interfaceapp) << "dump " << instantaneousFps << (1000.0f * paintWait) + const float modulus = (instantaneousFps >= targetFps) ? + (1.0f + floor(instantaneousFps / targetFps)) : + (1.0f / floor(targetFps / instantaneousFps)); + const float cap = modulus * targetFps; + const float capped = glm::min(cap, deduced); + /*qCDebug(interfaceapp) << "dump " << instantaneousFps << (1000.0f * paintWait) << "(" << paintWait << actual << "(" << firstAdjusted << machinery << secondAdjusted - << ")" << deduced << ")"; + << ")" << deduced << ")";*/ //const float deduced = qApp->getLastDeducedNonVSyncFps(); - const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime, false, paintWait, instantaneousFps); + const float distance = 1.0f / _renderDistanceController.update(capped, deltaTime, false, paintWait, instantaneousFps); _renderDistanceAverage.updateAverage(distance); _renderDistance = _renderDistanceAverage.getAverage(); int renderableCount = 0; From 44d740ef571148912ce233c63bb1e8d7c76d5f73 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 8 Dec 2015 09:22:02 -0800 Subject: [PATCH 085/174] Remove unused variable 'addr' --- libraries/networking/src/PacketReceiver.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/networking/src/PacketReceiver.cpp b/libraries/networking/src/PacketReceiver.cpp index 7e91a42a64..a162ba72c8 100644 --- a/libraries/networking/src/PacketReceiver.cpp +++ b/libraries/networking/src/PacketReceiver.cpp @@ -297,7 +297,6 @@ void PacketReceiver::handleVerifiedMessage(QSharedPointer recei emit dataReceived(matchingNode->getType(), receivedMessage->getSize()); matchingNode->recordBytesReceived(receivedMessage->getSize()); Node* n = matchingNode.data(); - auto addr = n->getActiveSocket(); QMetaMethod metaMethod = listener.method; From 71c266bc00e6e997eae0eba898efd65d99abc222 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 8 Dec 2015 09:22:17 -0800 Subject: [PATCH 086/174] Fix order of initializion in ReceivedMessage --- libraries/networking/src/ReceivedMessage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/ReceivedMessage.cpp b/libraries/networking/src/ReceivedMessage.cpp index f383257520..651b856923 100644 --- a/libraries/networking/src/ReceivedMessage.cpp +++ b/libraries/networking/src/ReceivedMessage.cpp @@ -22,8 +22,8 @@ static const int HEAD_DATA_SIZE = 512; ReceivedMessage::ReceivedMessage(const NLPacketList& packetList) : _data(packetList.getMessage()), _headData(_data.mid(0, HEAD_DATA_SIZE)), - _sourceID(packetList.getSourceID()), _numPackets(packetList.getNumPackets()), + _sourceID(packetList.getSourceID()), _packetType(packetList.getType()), _packetVersion(packetList.getVersion()), _senderSockAddr(packetList.getSenderSockAddr()), @@ -34,8 +34,8 @@ ReceivedMessage::ReceivedMessage(const NLPacketList& packetList) ReceivedMessage::ReceivedMessage(NLPacket& packet) : _data(packet.readAll()), _headData(_data.mid(0, HEAD_DATA_SIZE)), - _sourceID(packet.getSourceID()), _numPackets(1), + _sourceID(packet.getSourceID()), _packetType(packet.getType()), _packetVersion(packet.getVersion()), _senderSockAddr(packet.getSenderSockAddr()), From 0759462df714c865e897da07a42e99b9c65c008e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 8 Dec 2015 09:38:23 -0800 Subject: [PATCH 087/174] Remove unused variable in PacketReceiver --- libraries/networking/src/PacketReceiver.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/networking/src/PacketReceiver.cpp b/libraries/networking/src/PacketReceiver.cpp index a162ba72c8..530efc5fb3 100644 --- a/libraries/networking/src/PacketReceiver.cpp +++ b/libraries/networking/src/PacketReceiver.cpp @@ -296,7 +296,6 @@ void PacketReceiver::handleVerifiedMessage(QSharedPointer recei if (matchingNode) { emit dataReceived(matchingNode->getType(), receivedMessage->getSize()); matchingNode->recordBytesReceived(receivedMessage->getSize()); - Node* n = matchingNode.data(); QMetaMethod metaMethod = listener.method; From 22a1ee83e6381bd753697d9deb4acfa9ba2c8381 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 8 Dec 2015 10:39:04 -0800 Subject: [PATCH 088/174] ignore parenting properties --- examples/particle_explorer/main.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/particle_explorer/main.js b/examples/particle_explorer/main.js index 32ec12b640..a2a112d8e5 100644 --- a/examples/particle_explorer/main.js +++ b/examples/particle_explorer/main.js @@ -74,7 +74,9 @@ var keysToIgnore = [ 'shapeType', 'isEmitting', 'sittingPoints', - 'originalTextures' + 'originalTextures', + 'parentJointIndex', + 'parentID' ]; var individualKeys = []; From eeebe0622851ee5e6090143e66b728838524527c Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Tue, 8 Dec 2015 10:54:42 -0800 Subject: [PATCH 089/174] Using CPACK_PACKAGE_EXECUTABLES instead of CPACK_NSIS_CREATE_ICONS_EXTRE --- CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b44f81d2f..9e47d38067 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -229,10 +229,10 @@ if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment) - set (ICONPATH_INTERFACE "$INSTDIR/${PATH_INSTALL_DATA}/interface.ico") - set (ICONPATH_STACK_MANAGER "$INSTDIR/${PATH_INSTALL_DATA}/stack-manager.ico") - string (REPLACE "/" "\\\\" ICONPATH_INTERFACE ${ICONPATH_INTERFACE}) - string (REPLACE "/" "\\\\" ICONPATH_STACK_MANAGER ${ICONPATH_STACK_MANAGER}) + set(ICONPATH_INTERFACE "$INSTDIR/${PATH_INSTALL_DATA}/interface.ico") + set(ICONPATH_STACK_MANAGER "$INSTDIR/${PATH_INSTALL_DATA}/stack-manager.ico") + string(REPLACE "/" "\\\\" ICONPATH_INTERFACE ${ICONPATH_INTERFACE}) + string(REPLACE "/" "\\\\" ICONPATH_STACK_MANAGER ${ICONPATH_STACK_MANAGER}) set(CPACK_PACKAGE_NAME "High Fidelity") set(CPACK_PACKAGE_VENDOR "High Fidelity, Inc") @@ -242,8 +242,10 @@ if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE) set(CPACK_PACKAGE_VERSION_MINOR "0") set(CPACK_PACKAGE_VERSION_PATCH "0") set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity-${BUILD_SEQ}") - set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Interface.lnk' '$INSTDIR\\\\interface.exe' '${ICONPATH_INTERFACE}'") - set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Stack Manager.lnk' '$INSTDIR\\\\stack-manager.exe' '${ICONPATH_STACK_MANAGER}'") + set(CPACK_PACKAGE_EXECUTABLES + stack-manager "Stack Manager" + interface "Interface" + ) if (WIN32) install(DIRECTORY ${CMAKE_BINARY_DIR}/full-stack-deployment/ DESTINATION "./") From 011a43d5f214243e00b3feee613d6028299f977e Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 8 Dec 2015 11:08:22 -0800 Subject: [PATCH 090/174] Add sphere and cube triangle counts to displayed stats --- .../src/RenderableBoxEntityItem.cpp | 5 ++++- .../src/RenderableSphereEntityItem.cpp | 4 +++- libraries/render-utils/src/GeometryCache.cpp | 14 ++++++++++++++ libraries/render-utils/src/GeometryCache.h | 3 +++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index 588f17d959..54fe491c46 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -41,6 +41,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { Q_ASSERT(getType() == EntityTypes::Box); Q_ASSERT(args->_batch); + if (!_procedural) { _procedural.reset(new Procedural(this->getUserData())); _procedural->_vertexSource = simple_vert; @@ -64,4 +65,6 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { } else { DependencyManager::get()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor); } -}; + static const auto triCount = DependencyManager::get()->getCubeTriangleCount(); + args->_details._trianglesRendered += triCount; +} diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp index 2bdcfc19ad..8768e41a07 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp @@ -71,4 +71,6 @@ void RenderableSphereEntityItem::render(RenderArgs* args) { batch.setModelTransform(Transform()); DependencyManager::get()->renderSolidSphereInstance(batch, modelTransform, sphereColor); } -}; + static const auto triCount = DependencyManager::get()->getSphereTriangleCount(); + args->_details._trianglesRendered += triCount; +} diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 75b3b91c10..b9fdcd95a4 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -214,6 +214,19 @@ VertexVector tesselate(const VertexVector& startingTriangles, int count) { return triangles; } +size_t GeometryCache::getShapeTriangleCount(Shape shape) { + return _shapes[shape]._indexCount / VERTICES_PER_TRIANGLE; +} + +size_t GeometryCache::getSphereTriangleCount() { + return getShapeTriangleCount(Sphere); +} + +size_t GeometryCache::getCubeTriangleCount() { + return getShapeTriangleCount(Cube); +} + + // FIXME solids need per-face vertices, but smooth shaded // components do not. Find a way to support using draw elements // or draw arrays as appropriate @@ -1727,3 +1740,4 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) { batch.setPipeline(_standardDrawPipeline); } } + diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index aa1593db78..c408115011 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -151,16 +151,19 @@ public: void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer); void renderShape(gpu::Batch& batch, Shape shape); void renderWireShape(gpu::Batch& batch, Shape shape); + size_t getShapeTriangleCount(Shape shape); void renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer); void renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer); void renderCube(gpu::Batch& batch); void renderWireCube(gpu::Batch& batch); + size_t getCubeTriangleCount(); void renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer); void renderWireSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer); void renderSphere(gpu::Batch& batch); void renderWireSphere(gpu::Batch& batch); + size_t getSphereTriangleCount(); void renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color); void renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID); From 4dbfd3bfd936702e58ac90cc102d7df8bd4fe5a8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 8 Dec 2015 10:49:10 -0800 Subject: [PATCH 091/174] Fix concurrency issues for bools in ScriptEngine Several member variables were unsafely being accessed from multiple threads. Making these variables std::atomic makes this safe. --- libraries/script-engine/src/ScriptEngine.cpp | 2 +- libraries/script-engine/src/ScriptEngine.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 3306659c80..daadb0e394 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -183,7 +183,7 @@ void ScriptEngine::runInThread() { QSet ScriptEngine::_allKnownScriptEngines; QMutex ScriptEngine::_allScriptsMutex; -bool ScriptEngine::_stoppingAllScripts = false; +std::atomic ScriptEngine::_stoppingAllScripts = false; void ScriptEngine::stopAllScripts(QObject* application) { _allScriptsMutex.lock(); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 90b99d46fd..82b91aed2e 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -166,8 +166,8 @@ signals: protected: QString _scriptContents; QString _parentURL; - bool _isFinished { false }; - bool _isRunning { false }; + std::atomic _isFinished { false }; + std::atomic _isRunning { false }; int _evaluatesPending { 0 }; bool _isInitialized { false }; QHash _timerFunctionMap; @@ -206,7 +206,7 @@ protected: static QSet _allKnownScriptEngines; static QMutex _allScriptsMutex; - static bool _stoppingAllScripts; + static std::atomic _stoppingAllScripts; }; #endif // hifi_ScriptEngine_h \ No newline at end of file From cc6d30fe6f867080e61901588a023add803fecb7 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Tue, 8 Dec 2015 13:06:10 -0800 Subject: [PATCH 092/174] Fix to path setting in shortcuts --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e47d38067..ab88e9e46a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,6 +242,7 @@ if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE) set(CPACK_PACKAGE_VERSION_MINOR "0") set(CPACK_PACKAGE_VERSION_PATCH "0") set(CPACK_PACKAGE_INSTALL_DIRECTORY "High Fidelity-${BUILD_SEQ}") + set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") set(CPACK_PACKAGE_EXECUTABLES stack-manager "Stack Manager" interface "Interface" @@ -252,4 +253,4 @@ if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE) endif (WIN32) include(CPack) -endif () \ No newline at end of file +endif () From 9062cca8c474d83f33bc6fecfcd0a5c2e7e583ff Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Tue, 8 Dec 2015 13:33:15 -0800 Subject: [PATCH 093/174] Restoring --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 1adb00fe5f..3db23e4d36 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -201,7 +201,7 @@ else (APPLE) # link target to external libraries if (WIN32) - target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib) + #target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib) else (WIN32) # Nothing else required on linux apparently endif() From 164439b3037af5628b381a3526a9ef074030aa17 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 8 Dec 2015 13:53:39 -0800 Subject: [PATCH 094/174] don't enable physics until an entire scene has been received from the entity server and until nearby (to MyAvatar) entities are ready --- interface/src/Application.cpp | 36 +++++++++++++++++++++++++++++++++-- interface/src/Application.h | 2 ++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c0cfbda15b..4a97fd6275 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -195,6 +195,8 @@ static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-commands.html"; static const unsigned int THROTTLED_SIM_FRAMERATE = 15; static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE; +static const float PHYSICS_READY_RANGE = 3.0f; // how far from avatar to check for entities that aren't ready for simulation + #ifndef __APPLE__ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); #else @@ -2905,7 +2907,7 @@ void Application::update(float deltaTime) { _avatarUpdate->synchronousProcess(); - { + if (_physicsEnabled) { PerformanceTimer perfTimer("physics"); static VectorOfMotionStates motionStates; @@ -3893,6 +3895,31 @@ void Application::trackIncomingOctreePacket(ReceivedMessage& message, SharedNode } } +bool Application::nearbyEntitiesAreReadyForPhysics() { + // this is used to avoid the following scenario: + // A table has some items sitting on top of it. The items are at rest, meaning they aren't active in bullet. + // Someone logs in close to the table. They receive information about the items on the table before they + // receive information about the table. The items are very close to the avatar's capsule, so they become + // activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet. + EntityTreePointer entityTree = _entities.getTree(); + if (!entityTree) { + return false; + } + + QVector entities; + entityTree->withReadLock([&] { + AABox box(getMyAvatar()->getPosition() - glm::vec3(PHYSICS_READY_RANGE), glm::vec3(2 * PHYSICS_READY_RANGE)); + entityTree->findEntities(box, entities); + }); + + foreach (EntityItemPointer entity, entities) { + if (!entity->isReadyToComputeShape()) { + return false; + } + } + return true; +} + int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode) { // But, also identify the sender, and keep track of the contained jurisdiction root for this server @@ -3938,7 +3965,12 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer }); }); - + if (!_physicsEnabled && nearbyEntitiesAreReadyForPhysics()) { + // These stats packets are sent in between full sends of a scene. + // We keep physics disabled until we've recieved a full scene and everything near the avatar in that + // scene is ready to compute its collision shape. + _physicsEnabled = true; + } return statsMessageLength; } diff --git a/interface/src/Application.h b/interface/src/Application.h index ce33f051ef..27df7835e6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -395,6 +395,7 @@ private: bool importSVOFromURL(const QString& urlString); + bool nearbyEntitiesAreReadyForPhysics(); int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode); void trackIncomingOctreePacket(ReceivedMessage& message, SharedNodePointer sendingNode, bool wasStatsPacket); @@ -564,6 +565,7 @@ private: bool _isForeground = true; // starts out assumed to be in foreground bool _inPaint = false; bool _isGLInitialized { false }; + bool _physicsEnabled { false }; }; #endif // hifi_Application_h From c462bda86cb221aa7b8e5329f93367a42399d3d7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 8 Dec 2015 14:01:18 -0800 Subject: [PATCH 095/174] disable physics when moving to a new domain --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4a97fd6275..eee1ea7226 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3788,6 +3788,8 @@ void Application::domainChanged(const QString& domainHostname) { updateWindowTitle(); clearDomainOctreeDetails(); _domainConnectionRefusals.clear(); + // disable physics until we have enough information about our new location to not cause craziness. + _physicsEnabled = false; } void Application::handleDomainConnectionDeniedPacket(QSharedPointer message) { From 9ba5670c7611f8c09ff44bf47658778c735018e8 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Tue, 8 Dec 2015 14:20:19 -0800 Subject: [PATCH 096/174] Fix --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 4332ae24be..0baf709082 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -194,7 +194,7 @@ else (APPLE) # link target to external libraries if (WIN32) - #target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib) + target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib) else (WIN32) # Nothing else required on linux apparently endif() From 987b8d3334a1136dbce95122159a98650f4216b7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 8 Dec 2015 14:34:25 -0800 Subject: [PATCH 097/174] fix bad simulation ownership when using edit.js --- libraries/entities/src/EntityItem.cpp | 123 ++++++++++---------------- libraries/entities/src/EntityItem.h | 2 +- 2 files changed, 50 insertions(+), 75 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 51ade5b46e..5235cb6db0 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -628,71 +628,50 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); - if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE) { - // pack SimulationOwner and terse update properties near each other + // pack SimulationOwner and terse update properties near each other - // NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data - // even when we would otherwise ignore the rest of the packet. + // NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data + // even when we would otherwise ignore the rest of the packet. - if (propertyFlags.getHasProperty(PROP_SIMULATION_OWNER)) { + if (propertyFlags.getHasProperty(PROP_SIMULATION_OWNER)) { - QByteArray simOwnerData; - int bytes = OctreePacketData::unpackDataFromBytes(dataAt, simOwnerData); - SimulationOwner newSimOwner; - newSimOwner.fromByteArray(simOwnerData); - dataAt += bytes; - bytesRead += bytes; + QByteArray simOwnerData; + int bytes = OctreePacketData::unpackDataFromBytes(dataAt, simOwnerData); + SimulationOwner newSimOwner; + newSimOwner.fromByteArray(simOwnerData); + dataAt += bytes; + bytesRead += bytes; - if (wantTerseEditLogging() && _simulationOwner != newSimOwner) { - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner; - } - if (_simulationOwner.set(newSimOwner)) { - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; - } + if (wantTerseEditLogging() && _simulationOwner != newSimOwner) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner; } - { // When we own the simulation we don't accept updates to the entity's transform/velocities - // but since we're using macros below we have to temporarily modify overwriteLocalData. - bool oldOverwrite = overwriteLocalData; - overwriteLocalData = overwriteLocalData && !weOwnSimulation; - READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition); - READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotation); - READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity); - READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity); - READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration); - overwriteLocalData = oldOverwrite; + if (_simulationOwner.set(newSimOwner)) { + _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; } - - READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions); - READ_ENTITY_PROPERTY(PROP_DENSITY, float, updateDensity); - READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity); - - READ_ENTITY_PROPERTY(PROP_DAMPING, float, updateDamping); - READ_ENTITY_PROPERTY(PROP_RESTITUTION, float, updateRestitution); - READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction); - READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime); - READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript); - READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp); - READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint); - } else { - // legacy order of packing here - // TODO: purge this logic in a few months from now (2015.07) - READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition); - READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions); - READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotation); - READ_ENTITY_PROPERTY(PROP_DENSITY, float, updateDensity); - READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity); - READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity); - READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration); - - READ_ENTITY_PROPERTY(PROP_DAMPING, float, updateDamping); - READ_ENTITY_PROPERTY(PROP_RESTITUTION, float, updateRestitution); - READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction); - READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime); - READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript); - READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp); - READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint); - READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity); } + { // When we own the simulation we don't accept updates to the entity's transform/velocities + // but since we're using macros below we have to temporarily modify overwriteLocalData. + bool oldOverwrite = overwriteLocalData; + overwriteLocalData = overwriteLocalData && !weOwnSimulation; + READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition); + READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotation); + READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity); + READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity); + READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration); + overwriteLocalData = oldOverwrite; + } + + READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions); + READ_ENTITY_PROPERTY(PROP_DENSITY, float, updateDensity); + READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity); + + READ_ENTITY_PROPERTY(PROP_DAMPING, float, updateDamping); + READ_ENTITY_PROPERTY(PROP_RESTITUTION, float, updateRestitution); + READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction); + READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime); + READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript); + READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp); + READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint); READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping); READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible); @@ -701,17 +680,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData); - if (args.bitstreamVersion < VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE) { - // this code for when there is only simulatorID and no simulation priority - - // we always accept the server's notion of simulatorID, so we fake overwriteLocalData as true - // before we try to READ_ENTITY_PROPERTY it - bool temp = overwriteLocalData; - overwriteLocalData = true; - READ_ENTITY_PROPERTY(PROP_SIMULATION_OWNER, QUuid, updateSimulatorID); - overwriteLocalData = temp; - } - if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_MARKETPLACE_ID) { READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID); } @@ -1104,7 +1072,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; // these affect TerseUpdate properties - SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulationOwner, setSimulationOwner); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulationOwner, updateSimulationOwner); SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, updatePosition); SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, updateRotation); SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, updateVelocity); @@ -1324,6 +1292,13 @@ void EntityItem::updatePosition(const glm::vec3& value) { } if (getLocalPosition() != value) { setLocalPosition(value); + _dirtyFlags |= Simulation::DIRTY_POSITION; + forEachDescendant([&](SpatiallyNestablePointer object) { + if (object->getNestableType() == NestableTypes::Entity) { + EntityItemPointer entity = std::static_pointer_cast(object); + entity->_dirtyFlags |= Simulation::DIRTY_POSITION; + } + }); } } @@ -1496,12 +1471,12 @@ void EntityItem::setSimulationOwner(const SimulationOwner& owner) { _simulationOwner.set(owner); } -void EntityItem::updateSimulatorID(const QUuid& value) { - if (wantTerseEditLogging() && _simulationOwner.getID() != value) { - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << value; +void EntityItem::updateSimulationOwner(const SimulationOwner& owner) { + if (wantTerseEditLogging() && _simulationOwner != owner) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << owner; } - if (_simulationOwner.setID(value)) { + if (_simulationOwner.set(owner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 761208cb06..f94fc6e3c7 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -288,7 +288,7 @@ public: quint8 getSimulationPriority() const { return _simulationOwner.getPriority(); } QUuid getSimulatorID() const { return _simulationOwner.getID(); } - void updateSimulatorID(const QUuid& value); + void updateSimulationOwner(const SimulationOwner& owner); void clearSimulationOwnership(); const QString& getMarketplaceID() const { return _marketplaceID; } From 5b41d4da1caae89d6517c2d6641405994cb7b0c0 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 8 Dec 2015 15:30:23 -0800 Subject: [PATCH 098/174] Snapshot of "working" version. --- interface/src/Application.cpp | 9 +++++++-- interface/src/avatar/AvatarManager.cpp | 17 +++++++---------- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 3 ++- .../src/display-plugins/OpenGLDisplayPlugin.h | 3 +++ libraries/plugins/src/plugins/DisplayPlugin.h | 2 +- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1718389a5f..9de395dc57 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1086,6 +1086,7 @@ void Application::paintGL() { // update fps moving average uint64_t now = usecTimestampNow(); + qint64 sinceSync = getActiveDisplayPlugin()->getTimeSinceSync(); static uint64_t lastPaintBegin{ now }; uint64_t diff = now - lastPaintBegin; float instantaneousFps = 0.0f; @@ -1122,8 +1123,8 @@ void Application::paintGL() { _inPaint = true; Finally clearFlagLambda([this] { _inPaint = false; }); - _lastPaintWait = (float)(now - _paintWaitStart) / (float)USECS_PER_SECOND; - _lastInstantaneousFps = instantaneousFps; + //_lastPaintWait = (float)(now - _paintWaitStart) / (float)USECS_PER_SECOND; + //_lastInstantaneousFps = instantaneousFps; // Some LOD-like controls need to know a smoothly varying "potential" frame rate that doesn't // include time waiting for vsync, and which can report a number above target if we've got the headroom. // For example, if we're shooting for 75fps and paintWait is 3.3333ms (= 75% * 13.33ms), our deducedNonVSyncFps @@ -1422,6 +1423,10 @@ void Application::paintGL() { }); } _paintWaitStart = usecTimestampNow(); + _lastPaintWait = (float)sinceSync / (float)MSECS_PER_SECOND; + _lastInstantaneousFps = instantaneousFps; + _lastDeducedNonVSyncFps = 1.0f / (((_paintWaitStart - now) / (float)USECS_PER_SECOND) + ((float)sinceSync / (float)MSECS_PER_SECOND)); + // qCDebug(interfaceapp) << "pw/now/sync" << _paintWaitStart << now << sinceSync << "period" << (((_paintWaitStart - now) / (float)USECS_PER_SECOND) + ((float)sinceSync / (float)MSECS_PER_SECOND)) << "hz" << _lastDeducedNonVSyncFps; } void Application::runTests() { diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index b101c106a2..c0485bdebb 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -154,24 +154,21 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { const float targetFps = 60.0f; const float instantaneousFps = qApp->getLastInstanteousFps(); const float paintWait = qApp->getLastPaintWait(); - const float actual = 1.0f / instantaneousFps; + const float deduced = qApp->getLastDeducedNonVSyncFps(); + /*const float actual = 1.0f / instantaneousFps; const float target = 1.0f / targetFps; - const float firstAdjusted = actual - paintWait /*+ 0.002f*/; - const float machinery = (paintWait > target) ? fmod(paintWait, target) : 0.0f; - const float secondAdjusted = firstAdjusted + machinery; - const float deduced = 1.0f / secondAdjusted; const float modulus = (instantaneousFps >= targetFps) ? - (1.0f + floor(instantaneousFps / targetFps)) : - (1.0f / floor(targetFps / instantaneousFps)); + (1.0f + floor(instantaneousFps / targetFps)) : + (1.0f / floor(targetFps / instantaneousFps)); const float cap = modulus * targetFps; - const float capped = glm::min(cap, deduced); + const float deduced = instantaneousFps + ((cap - instantaneousFps) * (paintWait / target));*/ /*qCDebug(interfaceapp) << "dump " << instantaneousFps << (1000.0f * paintWait) << "(" << paintWait << actual << "(" << firstAdjusted << machinery << secondAdjusted - << ")" << deduced << ")";*/ + << ")" << deduced << modulus << cap << capped << ")";*/ //const float deduced = qApp->getLastDeducedNonVSyncFps(); - const float distance = 1.0f / _renderDistanceController.update(capped, deltaTime, false, paintWait, instantaneousFps); + const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime, false, paintWait, instantaneousFps); _renderDistanceAverage.updateAverage(distance); _renderDistance = _renderDistanceAverage.getAverage(); int renderableCount = 0; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 9a0db0ad97..b59ac24b52 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -168,8 +168,9 @@ OpenGLDisplayPlugin::OpenGLDisplayPlugin() { // This is likely to be mooted by further planned changes. if (_active && _sceneTextureEscrow.depth() <= 1) { #else - if (_active && _sceneTextureEscrow.depth() < 1) { + if (_active && _sceneTextureEscrow.depth() <= 1) { #endif + _sinceSync.start(); emit requestRender(); } }); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index ef78374994..4231c8ff7f 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -10,6 +10,7 @@ #include "DisplayPlugin.h" #include +#include #include #include @@ -40,6 +41,7 @@ public: } virtual QImage getScreenshot() const override; + virtual quint64 getTimeSinceSync() { return _sinceSync.elapsed(); } protected: friend class PresentThread; @@ -82,6 +84,7 @@ protected: GLTextureEscrow _sceneTextureEscrow; bool _vsyncSupported { false }; + QElapsedTimer _sinceSync; }; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 6fc6062214..c2e10dcc02 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -58,7 +58,7 @@ public: /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } virtual bool isThrottled() const { return false; } - virtual qint64 getLastSynchronizedElapsed() { return 0; } + virtual quint64 getTimeSinceSync() { return 0; } // Rendering support From 2604b4965061075c7aede8163469ad263bae473a Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 8 Dec 2015 15:35:43 -0800 Subject: [PATCH 099/174] Fix occasional crashes switching from the Oculus plugin --- .../display-plugins/OpenGLDisplayPlugin.cpp | 30 ++++++++++++++----- .../src/display-plugins/OpenGLDisplayPlugin.h | 11 ++++++- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 9a0db0ad97..80710e9b96 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -54,6 +54,7 @@ public: } virtual void run() override { + OpenGLDisplayPlugin* currentPlugin{ nullptr }; Q_ASSERT(_context); while (!_shutdown) { if (_pendingMainThreadOperation) { @@ -81,12 +82,13 @@ public: // Check if we have a new plugin to activate if (_newPlugin != nullptr) { // Deactivate the old plugin - if (_activePlugin != nullptr) { - _activePlugin->uncustomizeContext(); + if (currentPlugin != nullptr) { + currentPlugin->uncustomizeContext(); + currentPlugin->enableDeactivate(); } _newPlugin->customizeContext(); - _activePlugin = _newPlugin; + currentPlugin = _newPlugin; _newPlugin = nullptr; } _context->doneCurrent(); @@ -94,20 +96,21 @@ public: } // If there's no active plugin, just sleep - if (_activePlugin == nullptr) { + if (currentPlugin == nullptr) { QThread::usleep(100); continue; } // take the latest texture and present it _context->makeCurrent(); - _activePlugin->present(); + currentPlugin->present(); _context->doneCurrent(); } _context->makeCurrent(); - if (_activePlugin) { - _activePlugin->uncustomizeContext(); + if (currentPlugin) { + currentPlugin->uncustomizeContext(); + currentPlugin->enableDeactivate(); } _context->doneCurrent(); _context->moveToThread(qApp->thread()); @@ -147,7 +150,6 @@ private: bool _finishedMainThreadOperation { false }; QThread* _mainThread { nullptr }; OpenGLDisplayPlugin* _newPlugin { nullptr }; - OpenGLDisplayPlugin* _activePlugin { nullptr }; QGLContext* _context { nullptr }; }; @@ -208,11 +210,16 @@ void OpenGLDisplayPlugin::stop() { } void OpenGLDisplayPlugin::deactivate() { + { + Lock lock(_mutex); + _deactivateWait.wait(lock, [&]{ return _uncustomized; }); + } _timer.stop(); DisplayPlugin::deactivate(); } void OpenGLDisplayPlugin::customizeContext() { + _uncustomized = false; auto presentThread = DependencyManager::get(); Q_ASSERT(thread() == presentThread->thread()); @@ -233,6 +240,7 @@ void OpenGLDisplayPlugin::uncustomizeContext() { _plane.reset(); } + // Pressing Alt (and Meta) key alone activates the menubar because its style inherits the // SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to // receive keyPress events for the Alt (and Meta) key in a reliable manner. @@ -380,3 +388,9 @@ QImage OpenGLDisplayPlugin::getScreenshot() const { }); return result; } + +void OpenGLDisplayPlugin::enableDeactivate() { + Lock lock(_mutex); + _uncustomized = true; + _deactivateWait.notify_one(); +} \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index ef78374994..88ccddc125 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -9,6 +9,8 @@ #include "DisplayPlugin.h" +#include + #include #include @@ -18,8 +20,9 @@ class OpenGLDisplayPlugin : public DisplayPlugin { protected: - using Mutex = std::recursive_mutex; + using Mutex = std::mutex; using Lock = std::unique_lock; + using Condition = std::condition_variable; public: OpenGLDisplayPlugin(); virtual void activate() override; @@ -82,6 +85,12 @@ protected: GLTextureEscrow _sceneTextureEscrow; bool _vsyncSupported { false }; + +private: + void enableDeactivate(); + Condition _deactivateWait; + bool _uncustomized{ false }; + }; From 32e4967ee0a66e8b2f9eba8a06e53b5d553b0d19 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 8 Dec 2015 16:38:05 -0800 Subject: [PATCH 100/174] cleanup --- interface/src/Application.cpp | 37 ++++--------------- interface/src/Application.h | 10 +---- interface/src/avatar/Avatar.cpp | 4 +- interface/src/avatar/AvatarManager.cpp | 23 ++---------- .../display-plugins/OpenGLDisplayPlugin.cpp | 3 +- .../src/display-plugins/OpenGLDisplayPlugin.h | 3 -- libraries/plugins/src/plugins/DisplayPlugin.h | 1 - libraries/shared/src/PIDController.cpp | 8 ++-- libraries/shared/src/PIDController.h | 5 +-- 9 files changed, 20 insertions(+), 74 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f56231ada8..78882342df 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1086,7 +1086,6 @@ void Application::paintGL() { // update fps moving average uint64_t now = usecTimestampNow(); - qint64 sinceSync = getActiveDisplayPlugin()->getTimeSinceSync(); static uint64_t lastPaintBegin{ now }; uint64_t diff = now - lastPaintBegin; float instantaneousFps = 0.0f; @@ -1123,31 +1122,6 @@ void Application::paintGL() { _inPaint = true; Finally clearFlagLambda([this] { _inPaint = false; }); - //_lastPaintWait = (float)(now - _paintWaitStart) / (float)USECS_PER_SECOND; - //_lastInstantaneousFps = instantaneousFps; - // Some LOD-like controls need to know a smoothly varying "potential" frame rate that doesn't - // include time waiting for vsync, and which can report a number above target if we've got the headroom. - // For example, if we're shooting for 75fps and paintWait is 3.3333ms (= 75% * 13.33ms), our deducedNonVSyncFps - // would be 100fps. In principle, a paintWait of zero would have deducedNonVSyncFps=75. - // Here we make a guess for deducedNonVSyncFps = 1 / deducedNonVSyncPeriod. - // - // Time between previous paintGL call and this one, which can vary not only with vSync misses, but also with QT timing. - // We're using this as a proxy for the time between vsync and displayEnd, below. (Not exact, but tends to be the same over time.) - // This is not the same as update(deltaTime), because the latter attempts to throttle to 60hz and also clamps to 1/4 second. -/* const float actualPeriod = diff / (float)USECS_PER_SECOND; // same as 1/instantaneousFps but easier for compiler to optimize - // Note that _lastPaintWait (stored at end of last call) is for the same paint cycle. - float deducedNonVSyncPeriod = actualPeriod - _lastPaintWait + _marginForDeducedFramePeriod; // plus a some non-zero time for machinery we can't measure - // We don't know how much time to allow for that, but if we went over the target period, we know it's at least the portion - // of paintWait up to the next vSync. This gives us enough of a penalty so that when actualPeriod crosses two cycles, - // the key part (and not an exagerated part) of _lastPaintWait is accounted for. - const float targetPeriod = getTargetFramePeriod(); - if (_lastPaintWait > EPSILON && actualPeriod > targetPeriod) { - // Don't use C++ remainder(). It's authors are mathematically insane. - deducedNonVSyncPeriod += fmod(targetPeriod, _lastPaintWait); - } - _lastDeducedNonVSyncFps = 1.0f / deducedNonVSyncPeriod; - */ - auto displayPlugin = getActiveDisplayPlugin(); // FIXME not needed anymore? _offscreenContext->makeCurrent(); @@ -1422,11 +1396,14 @@ void Application::paintGL() { batch.resetStages(); }); } - _paintWaitStart = usecTimestampNow(); - _lastPaintWait = (float)sinceSync / (float)MSECS_PER_SECOND; + + // Some LOD-like controls need to know a smoothly varying "potential" frame rate that doesn't + // include time waiting for sync, and which can report a number above target if we've got the headroom. + // In my tests, the following is mostly less than 0.5ms, and never more than 3ms. I don't think its worth measuring during runtime. + static const float paintWaitAndQTTimerAllowance = 0.001; // seconds + // Store both values now for use by next cycle. _lastInstantaneousFps = instantaneousFps; - _lastDeducedNonVSyncFps = 1.0f / (((_paintWaitStart - now) / (float)USECS_PER_SECOND) + ((float)sinceSync / (float)MSECS_PER_SECOND)); - // qCDebug(interfaceapp) << "pw/now/sync" << _paintWaitStart << now << sinceSync << "period" << (((_paintWaitStart - now) / (float)USECS_PER_SECOND) + ((float)sinceSync / (float)MSECS_PER_SECOND)) << "hz" << _lastDeducedNonVSyncFps; + _lastUnsynchronizedFps = 1.0f / (((usecTimestampNow() - now) / (float)USECS_PER_SECOND) + paintWaitAndQTTimerAllowance); } void Application::runTests() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 197d9a7a60..17d609ee0c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -163,11 +163,8 @@ public: float const HMD_TARGET_FRAME_RATE = 75.0f; float const DESKTOP_TARGET_FRAME_RATE = 60.0f; float getTargetFrameRate() { return isHMDMode() ? HMD_TARGET_FRAME_RATE : DESKTOP_TARGET_FRAME_RATE; } - float getTargetFramePeriod() { return isHMDMode() ? 1.0f / HMD_TARGET_FRAME_RATE : 1.0f / DESKTOP_TARGET_FRAME_RATE; } // same as 1/getTargetFrameRate, but w/compile-time division float getLastInstanteousFps() const { return _lastInstantaneousFps; } - float getLastPaintWait() const { return _lastPaintWait; }; - float getLastDeducedNonVSyncFps() const { return _lastDeducedNonVSyncFps; } - void setMarginForDeducedFramePeriod(float newValue) { _marginForDeducedFramePeriod = newValue; } + float getLastUnsynchronizedFps() const { return _lastUnsynchronizedFps; } float getFieldOfView() { return _fieldOfView.get(); } void setFieldOfView(float fov); @@ -442,10 +439,7 @@ private: QElapsedTimer _timerStart; QElapsedTimer _lastTimeUpdated; float _lastInstantaneousFps { 0.0f }; - float _lastPaintWait { 0.0f }; - uint64_t _paintWaitStart { 0 }; - float _lastDeducedNonVSyncFps { 0.0f }; - float _marginForDeducedFramePeriod{ 0.002f }; // 2ms, adjustable + float _lastUnsynchronizedFps { 0.0f }; ShapeManager _shapeManager; PhysicalEntitySimulation _entitySimulation; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e3b7cd5735..e2b92cc06f 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -174,14 +174,14 @@ void Avatar::simulate(float deltaTime) { _shouldSkipRender = false; _skeletonModel.setVisibleInScene(true, qApp->getMain3DScene()); if (!isControllerLogging) { // Test for isMyAvatar is prophylactic. Never occurs in current code. - //qCDebug(interfaceapp) << "Rerendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for distance" << renderDistance; + qCDebug(interfaceapp) << "Rerendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for distance" << renderDistance; } } } else if (distance > renderDistance * (1.0f + SKIP_HYSTERESIS_PROPORTION)) { _shouldSkipRender = true; _skeletonModel.setVisibleInScene(false, qApp->getMain3DScene()); if (!isControllerLogging) { - //qCDebug(interfaceapp) << "Unrendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for distance" << renderDistance; + qCDebug(interfaceapp) << "Unrendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for distance" << renderDistance; } } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index c0485bdebb..59af6b18df 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -111,7 +111,6 @@ void AvatarManager::init() { _renderDistanceController.setKP(0.0008f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. _renderDistanceController.setKI(0.0006f); // Big enough to bring us to target with the above KP. _renderDistanceController.setKD(0.000001f); // A touch of kd increases the speed by which we get there. - _renderDistanceController.setHistorySize("av", 240); //FIXME } void AvatarManager::updateMyAvatar(float deltaTime) { @@ -130,7 +129,7 @@ void AvatarManager::updateMyAvatar(float deltaTime) { _lastSendAvatarDataTime = now; } } -#include "InterfaceLogging.h" + void AvatarManager::updateOtherAvatars(float deltaTime) { // lock the hash for read to check the size QReadLocker lock(&_hashLock); @@ -151,24 +150,8 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { // The measured value is frame rate. When the controlled value (1 / render cutoff distance) // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate // goes up. - const float targetFps = 60.0f; - const float instantaneousFps = qApp->getLastInstanteousFps(); - const float paintWait = qApp->getLastPaintWait(); - const float deduced = qApp->getLastDeducedNonVSyncFps(); - /*const float actual = 1.0f / instantaneousFps; - const float target = 1.0f / targetFps; - const float modulus = (instantaneousFps >= targetFps) ? - (1.0f + floor(instantaneousFps / targetFps)) : - (1.0f / floor(targetFps / instantaneousFps)); - const float cap = modulus * targetFps; - const float deduced = instantaneousFps + ((cap - instantaneousFps) * (paintWait / target));*/ - /*qCDebug(interfaceapp) << "dump " << instantaneousFps << (1000.0f * paintWait) - << "(" << paintWait << actual - << "(" << firstAdjusted << machinery << secondAdjusted - << ")" << deduced << modulus << cap << capped << ")";*/ - - //const float deduced = qApp->getLastDeducedNonVSyncFps(); - const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime, false, paintWait, instantaneousFps); + const float deduced = qApp->getLastUnsynchronizedFps(); + const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime); _renderDistanceAverage.updateAverage(distance); _renderDistance = _renderDistanceAverage.getAverage(); int renderableCount = 0; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index b59ac24b52..9a0db0ad97 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -168,9 +168,8 @@ OpenGLDisplayPlugin::OpenGLDisplayPlugin() { // This is likely to be mooted by further planned changes. if (_active && _sceneTextureEscrow.depth() <= 1) { #else - if (_active && _sceneTextureEscrow.depth() <= 1) { + if (_active && _sceneTextureEscrow.depth() < 1) { #endif - _sinceSync.start(); emit requestRender(); } }); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 4231c8ff7f..ef78374994 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -10,7 +10,6 @@ #include "DisplayPlugin.h" #include -#include #include #include @@ -41,7 +40,6 @@ public: } virtual QImage getScreenshot() const override; - virtual quint64 getTimeSinceSync() { return _sinceSync.elapsed(); } protected: friend class PresentThread; @@ -84,7 +82,6 @@ protected: GLTextureEscrow _sceneTextureEscrow; bool _vsyncSupported { false }; - QElapsedTimer _sinceSync; }; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index c2e10dcc02..83afbc9402 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -58,7 +58,6 @@ public: /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } virtual bool isThrottled() const { return false; } - virtual quint64 getTimeSinceSync() { return 0; } // Rendering support diff --git a/libraries/shared/src/PIDController.cpp b/libraries/shared/src/PIDController.cpp index 3607c281ec..78aa31e4c7 100644 --- a/libraries/shared/src/PIDController.cpp +++ b/libraries/shared/src/PIDController.cpp @@ -14,7 +14,7 @@ #include "SharedLogging.h" #include "PIDController.h" -float PIDController::update(float measuredValue, float dt, bool resetAccumulator, float fixme1, float fixme2) { +float PIDController::update(float measuredValue, float dt, bool resetAccumulator) { const float error = getMeasuredValueSetpoint() - measuredValue; // Sign is the direction we want measuredValue to go. Positive means go higher. const float p = getKP() * error; // term is Proportional to error @@ -32,7 +32,7 @@ float PIDController::update(float measuredValue, float dt, bool resetAccumulator getControlledValueHighLimit()); if (getIsLogging()) { // if logging/reporting - updateHistory(measuredValue, dt, error, accumulatedError, changeInError, p, i, d, computedValue, fixme1, fixme2); + updateHistory(measuredValue, dt, error, accumulatedError, changeInError, p, i, d, computedValue); } Q_ASSERT(!isnan(computedValue)); @@ -43,7 +43,7 @@ float PIDController::update(float measuredValue, float dt, bool resetAccumulator } // Just for logging/reporting. Used when picking/verifying the operational parameters. -void PIDController::updateHistory(float measuredValue, float dt, float error, float accumulatedError, float changeInError, float p, float i, float d, float computedValue, float fixme1, float fixme2) { +void PIDController::updateHistory(float measuredValue, float dt, float error, float accumulatedError, float changeInError, float p, float i, float d, float computedValue) { // Don't report each update(), as the I/O messes with the results a lot. // Instead, add to history, and then dump out at once when full. // Typically, the first few values reported in each batch should be ignored. @@ -59,7 +59,6 @@ void PIDController::updateHistory(float measuredValue, float dt, float error, fl next.i = i; next.d = d; next.computed = computedValue; - next.fixme1 = fixme1; next.fixme2 = fixme2; if (_history.size() == _history.capacity()) { // report when buffer is full reportHistory(); _history.resize(0); @@ -70,7 +69,6 @@ void PIDController::reportHistory() { for (int i = 0; i < _history.size(); i++) { Row& row = _history[i]; qCDebug(shared) << row.measured << row.dt << - (row.fixme1 * 1000.0f) << (row.fixme2) << "||" << row.error << row.accumulated << row.changed << "||" << row.p << row.i << row.d << row.computed << 1.0f/row.computed; } diff --git a/libraries/shared/src/PIDController.h b/libraries/shared/src/PIDController.h index 24e619b13b..0b2411530a 100644 --- a/libraries/shared/src/PIDController.h +++ b/libraries/shared/src/PIDController.h @@ -28,7 +28,7 @@ class PIDController { public: // These are the main interfaces: void setMeasuredValueSetpoint(float newValue) { _measuredValueSetpoint = newValue; } - float update(float measuredValue, float dt, bool resetAccumulator = false, float fixme1=0, float fixme2=0); // returns the new computedValue + float update(float measuredValue, float dt, bool resetAccumulator = false); // returns the new computedValue void setHistorySize(QString label = QString(""), int size = 0) { _history.reserve(size); _history.resize(0); _label = label; } // non-empty does logging bool getIsLogging() { return _history.capacity(); } @@ -64,11 +64,10 @@ public: float i; float d; float computed; - float fixme1; float fixme2; }; protected: void reportHistory(); - void updateHistory(float measured, float dt, float error, float accumulatedError, float changeInErro, float p, float i, float d, float computedValue, float fixme1, float fixme2); + void updateHistory(float measured, float dt, float error, float accumulatedError, float changeInErro, float p, float i, float d, float computedValue); float _measuredValueSetpoint { 0.0f }; float _controlledValueLowLimit { 0.0f }; float _controlledValueHighLimit { std::numeric_limits::max() }; From 1adf2cc8ba7b20c9c0e9ab9e30f93622a49a9167 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 8 Dec 2015 16:45:12 -0800 Subject: [PATCH 101/174] Repesenting the collision meshes of a Model correctly --- libraries/gpu/src/gpu/Stream.h | 1 + .../render-utils/src/MeshPartPayload.cpp | 72 ++++++++++--------- libraries/render-utils/src/MeshPartPayload.h | 4 +- libraries/render-utils/src/Model.cpp | 5 +- 4 files changed, 45 insertions(+), 37 deletions(-) diff --git a/libraries/gpu/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h index 4fff3b651d..d2fb8a37e9 100644 --- a/libraries/gpu/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -106,6 +106,7 @@ public: bool setAttribute(Slot slot, Frequency frequency = PER_VERTEX); bool setAttribute(Slot slot, Slot channel, Frequency frequency = PER_VERTEX); + bool hasAttribute(Slot slot) const { return (_attributes.find(slot) != _attributes.end()); } protected: AttributeMap _attributes; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 456f6eac51..3aee6cb62c 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -39,30 +39,31 @@ namespace render { using namespace render; -MeshPartPayload::MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, - glm::vec3 position, glm::quat orientation) : +MeshPartPayload::MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, + glm::vec3 position, glm::quat orientation, bool applyMeshJoints) : model(model), + _drawMesh(drawMesh), meshIndex(meshIndex), partIndex(partIndex), _shapeID(shapeIndex), _modelPosition(position), - _modelOrientation(orientation) { + _modelOrientation(orientation), + _applyMeshJoints(applyMeshJoints) { initCache(); } void MeshPartPayload::initCache() { - const std::vector>& networkMeshes = model->_geometry->getMeshes(); - const NetworkMesh& networkMesh = *(networkMeshes.at(meshIndex).get()); - _drawMesh = networkMesh._mesh; + if (_drawMesh) { + auto vertexFormat = _drawMesh->getVertexFormat(); + _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); + _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); - const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); - const FBXMesh& mesh = geometry.meshes.at(meshIndex); - _hasColorAttrib = !mesh.colors.isEmpty(); - _isBlendShaped = !mesh.blendshapes.isEmpty(); - _isSkinned = !mesh.clusterIndices.isEmpty(); + const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); + const FBXMesh& mesh = geometry.meshes.at(meshIndex); + _isBlendShaped = !mesh.blendshapes.isEmpty(); - - _drawPart = _drawMesh->getPartBuffer().get(partIndex); + _drawPart = _drawMesh->getPartBuffer().get(partIndex); + } auto networkMaterial = model->_geometry->getShapeMaterial(_shapeID); if (networkMaterial) { @@ -219,25 +220,34 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio } void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const { - // Still relying on the raw data from the model - const Model::MeshState& state = model->_meshStates.at(meshIndex); + if (_applyMeshJoints) { + // Still relying on the raw data from the model + const Model::MeshState& state = model->_meshStates.at(meshIndex); - Transform transform; - if (state.clusterBuffer) { - if (model->_cauterizeBones) { - batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer); + Transform transform; + if (state.clusterBuffer) { + if (model->_cauterizeBones) { + batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer); + } else { + batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer); + } } else { - batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer); + if (model->_cauterizeBones) { + transform = Transform(state.cauterizedClusterMatrices[0]); + } else { + transform = Transform(state.clusterMatrices[0]); + } } + transform.preTranslate(_modelPosition); + batch.setModelTransform(transform); } else { - if (model->_cauterizeBones) { - transform = Transform(state.cauterizedClusterMatrices[0]); - } else { - transform = Transform(state.clusterMatrices[0]); - } + Transform transform; + transform.setTranslation(_modelPosition); + transform.setRotation(_modelOrientation); + transform.postScale(model->getScale()); + transform.postTranslate(model->getOffset()); + batch.setModelTransform(transform); } - transform.preTranslate(_modelPosition); - batch.setModelTransform(transform); } @@ -280,13 +290,7 @@ void MeshPartPayload::render(RenderArgs* args) const { // sanity check return; // FIXME! } - - - // guard against partially loaded meshes - if (partIndex >= mesh.parts.size()) { - return; - } - + model::MaterialKey drawMaterialKey; if (_drawMaterial) { drawMaterialKey = _drawMaterial->getKey(); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 5d30eddd20..867dd2d264 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -24,7 +24,7 @@ class Model; class MeshPartPayload { public: - MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation); + MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation, bool applyMeshJoints = true); typedef render::Payload Payload; typedef Payload::DataPointer Pointer; @@ -36,6 +36,7 @@ public: glm::vec3 _modelPosition; glm::quat _modelOrientation; + // can replace the material used to draw that item void updateDrawMaterial(model::MaterialPointer material); @@ -62,6 +63,7 @@ public: bool _hasColorAttrib = false; bool _isSkinned = false; bool _isBlendShaped = false; + bool _applyMeshJoints = true; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 96fd52edcc..56c1f642b8 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -90,7 +90,7 @@ void Model::setScale(const glm::vec3& scale) { _scaledToFit = false; } -const float METERS_PER_MILLIMETER = 0.01f; +const float METERS_PER_MILLIMETER = 0.01f; void Model::setScaleInternal(const glm::vec3& scale) { if (glm::distance(_scale, scale) > METERS_PER_MILLIMETER) { @@ -1147,11 +1147,12 @@ void Model::segregateMeshGroups() { int shapeID = 0; for (int i = 0; i < (int)networkMeshes.size(); i++) { const FBXMesh& mesh = geometry.meshes.at(i); + const NetworkMesh& networkMesh = *(networkMeshes.at(i).get()); // Create the render payloads int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { - auto renderItem = std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); + auto renderItem = std::make_shared(this, networkMesh._mesh, i, partIndex, shapeID, _translation, _rotation, !showingCollisionHull); if (showingCollisionHull) { renderItem->updateDrawMaterial(ModelRender::getCollisionHullMaterial()); } From e77f2e8ac47defd8aad70a3e385eabd45e2f2c2d Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 8 Dec 2015 16:49:50 -0800 Subject: [PATCH 102/174] Pass correct frame index into Oculus SDK --- plugins/oculus/src/OculusDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index 8846b8a6a6..e6eae2cf02 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -230,7 +230,7 @@ void OculusDisplayPlugin::internalPresent() { viewScaleDesc.HmdToEyeViewOffset[1] = _eyeOffsets[1]; ovrLayerHeader* layers = &_sceneLayer.Header; - ovrResult result = ovr_SubmitFrame(_hmd, 0, &viewScaleDesc, &layers, 1); + ovrResult result = ovr_SubmitFrame(_hmd, frameIndex, &viewScaleDesc, &layers, 1); if (!OVR_SUCCESS(result)) { qDebug() << result; } From 8c109fd6238cf60e99fbe5e101786013e8bac356 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 8 Dec 2015 17:21:43 -0800 Subject: [PATCH 103/174] move raw bullet code from interface to physics lib --- interface/src/avatar/MyAvatar.cpp | 4 +- .../src/avatar/MyCharacterController.cpp | 329 +----------------- interface/src/avatar/MyCharacterController.h | 75 +--- libraries/physics/src/CharacterController.cpp | 329 +++++++++++++++++- libraries/physics/src/CharacterController.h | 85 ++++- 5 files changed, 405 insertions(+), 417 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6637331b64..34821e6737 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1058,7 +1058,7 @@ void MyAvatar::rebuildSkeletonBody() { void MyAvatar::prepareForPhysicsSimulation() { relayDriveKeysToCharacterController(); _characterController.setTargetVelocity(getTargetVelocity()); - _characterController.setAvatarPositionAndOrientation(getPosition(), getOrientation()); + _characterController.setPositionAndOrientation(getPosition(), getOrientation()); if (qApp->isHMDMode()) { updateHMDFollowVelocity(); } else if (_followSpeed > 0.0f) { @@ -1071,7 +1071,7 @@ void MyAvatar::prepareForPhysicsSimulation() { void MyAvatar::harvestResultsFromPhysicsSimulation() { glm::vec3 position = getPosition(); glm::quat orientation = getOrientation(); - _characterController.getAvatarPositionAndOrientation(position, orientation); + _characterController.getPositionAndOrientation(position, orientation); nextAttitude(position, orientation); if (_followSpeed > 0.0f) { adjustSensorTransform(); diff --git a/interface/src/avatar/MyCharacterController.cpp b/interface/src/avatar/MyCharacterController.cpp index e8f686da6f..23d601e58e 100644 --- a/interface/src/avatar/MyCharacterController.cpp +++ b/interface/src/avatar/MyCharacterController.cpp @@ -11,255 +11,25 @@ #include "MyCharacterController.h" -#include -#include -#include -#include - -#include -#include -#include +#include #include "MyAvatar.h" -const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); -const float DEFAULT_GRAVITY = -5.0f; -const float JUMP_SPEED = 3.5f; - -const float MAX_FALL_HEIGHT = 20.0f; - // TODO: improve walking up steps // TODO: make avatars able to walk up and down steps/slopes // TODO: make avatars stand on steep slope // TODO: make avatars not snag on low ceilings -// helper class for simple ray-traces from character -class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback { -public: - ClosestNotMe(btRigidBody* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0f, 0.0f, 0.0f), btVector3(0.0f, 0.0f, 0.0f)) { - _me = me; - } - virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) { - if (rayResult.m_collisionObject == _me) { - return 1.0f; - } - return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); - } -protected: - btRigidBody* _me; -}; - MyCharacterController::MyCharacterController(MyAvatar* avatar) { - _halfHeight = 1.0f; assert(avatar); _avatar = avatar; - - _enabled = false; - - _floorDistance = MAX_FALL_HEIGHT; - - _walkVelocity.setValue(0.0f, 0.0f, 0.0f); - _followVelocity.setValue(0.0f, 0.0f, 0.0f); - _jumpSpeed = JUMP_SPEED; - _isOnGround = false; - _isJumping = false; - _isFalling = false; - _isHovering = true; - _isPushingUp = false; - _jumpToHoverStart = 0; - _followTime = 0.0f; - - _pendingFlags = PENDING_FLAG_UPDATE_SHAPE; updateShapeIfNecessary(); } MyCharacterController::~MyCharacterController() { } -void MyCharacterController::preStep(btCollisionWorld* collisionWorld) { - // trace a ray straight down to see if we're standing on the ground - const btTransform& xform = _rigidBody->getWorldTransform(); - - // rayStart is at center of bottom sphere - btVector3 rayStart = xform.getOrigin() - _halfHeight * _currentUp; - - // rayEnd is some short distance outside bottom sphere - const btScalar FLOOR_PROXIMITY_THRESHOLD = 0.3f * _radius; - btScalar rayLength = _radius + FLOOR_PROXIMITY_THRESHOLD; - btVector3 rayEnd = rayStart - rayLength * _currentUp; - - // scan down for nearby floor - ClosestNotMe rayCallback(_rigidBody); - rayCallback.m_closestHitFraction = 1.0f; - collisionWorld->rayTest(rayStart, rayEnd, rayCallback); - if (rayCallback.hasHit()) { - _floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius; - } -} - -void MyCharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) { - btVector3 actualVelocity = _rigidBody->getLinearVelocity(); - btScalar actualSpeed = actualVelocity.length(); - - btVector3 desiredVelocity = _walkVelocity; - btScalar desiredSpeed = desiredVelocity.length(); - - const btScalar MIN_UP_PUSH = 0.1f; - if (desiredVelocity.dot(_currentUp) < MIN_UP_PUSH) { - _isPushingUp = false; - } - - const btScalar MIN_SPEED = 0.001f; - if (_isHovering) { - if (desiredSpeed < MIN_SPEED) { - if (actualSpeed < MIN_SPEED) { - _rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f)); - } else { - const btScalar HOVER_BRAKING_TIMESCALE = 0.1f; - btScalar tau = glm::max(dt / HOVER_BRAKING_TIMESCALE, 1.0f); - _rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity); - } - } else { - const btScalar HOVER_ACCELERATION_TIMESCALE = 0.1f; - btScalar tau = dt / HOVER_ACCELERATION_TIMESCALE; - _rigidBody->setLinearVelocity(actualVelocity - tau * (actualVelocity - desiredVelocity)); - } - } else { - if (onGround()) { - // walking on ground - if (desiredSpeed < MIN_SPEED) { - if (actualSpeed < MIN_SPEED) { - _rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f)); - } else { - const btScalar HOVER_BRAKING_TIMESCALE = 0.1f; - btScalar tau = dt / HOVER_BRAKING_TIMESCALE; - _rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity); - } - } else { - // TODO: modify desiredVelocity using floor normal - const btScalar WALK_ACCELERATION_TIMESCALE = 0.1f; - btScalar tau = dt / WALK_ACCELERATION_TIMESCALE; - btVector3 velocityCorrection = tau * (desiredVelocity - actualVelocity); - // subtract vertical component - velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp; - _rigidBody->setLinearVelocity(actualVelocity + velocityCorrection); - } - } else { - // transitioning to flying - btVector3 velocityCorrection = desiredVelocity - actualVelocity; - const btScalar FLY_ACCELERATION_TIMESCALE = 0.2f; - btScalar tau = dt / FLY_ACCELERATION_TIMESCALE; - if (!_isPushingUp) { - // actually falling --> compute a different velocity attenuation factor - const btScalar FALL_ACCELERATION_TIMESCALE = 2.0f; - tau = dt / FALL_ACCELERATION_TIMESCALE; - // zero vertical component - velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp; - } - _rigidBody->setLinearVelocity(actualVelocity + tau * velocityCorrection); - } - } - - // Rather than add _followVelocity to the velocity of the RigidBody, we explicitly teleport - // the RigidBody forward according to the formula: distance = rate * time - if (_followVelocity.length2() > 0.0f) { - btTransform bodyTransform = _rigidBody->getWorldTransform(); - bodyTransform.setOrigin(bodyTransform.getOrigin() + dt * _followVelocity); - _rigidBody->setWorldTransform(bodyTransform); - } - _followTime += dt; -} - -void MyCharacterController::jump() { - // check for case where user is holding down "jump" key... - // we'll eventually tansition to "hover" - if (!_isJumping) { - if (!_isHovering) { - _jumpToHoverStart = usecTimestampNow(); - _pendingFlags |= PENDING_FLAG_JUMP; - } - } else { - quint64 now = usecTimestampNow(); - const quint64 JUMP_TO_HOVER_PERIOD = 75 * (USECS_PER_SECOND / 100); - if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) { - _isPushingUp = true; - setHovering(true); - } - } -} - -bool MyCharacterController::onGround() const { - const btScalar FLOOR_PROXIMITY_THRESHOLD = 0.3f * _radius; - return _floorDistance < FLOOR_PROXIMITY_THRESHOLD; -} - -void MyCharacterController::setHovering(bool hover) { - if (hover != _isHovering) { - _isHovering = hover; - _isJumping = false; - - if (_rigidBody) { - if (hover) { - _rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f)); - } else { - _rigidBody->setGravity(DEFAULT_GRAVITY * _currentUp); - } - } - } -} - -void MyCharacterController::setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale) { - _boxScale = scale; - - float x = _boxScale.x; - float z = _boxScale.z; - float radius = 0.5f * sqrtf(0.5f * (x * x + z * z)); - float halfHeight = 0.5f * _boxScale.y - radius; - float MIN_HALF_HEIGHT = 0.1f; - if (halfHeight < MIN_HALF_HEIGHT) { - halfHeight = MIN_HALF_HEIGHT; - } - - // compare dimensions - float radiusDelta = glm::abs(radius - _radius); - float heightDelta = glm::abs(halfHeight - _halfHeight); - if (radiusDelta < FLT_EPSILON && heightDelta < FLT_EPSILON) { - // shape hasn't changed --> nothing to do - } else { - if (_dynamicsWorld) { - // must REMOVE from world prior to shape update - _pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION; - } - _pendingFlags |= PENDING_FLAG_UPDATE_SHAPE; - // only need to ADD back when we happen to be enabled - if (_enabled) { - _pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION; - } - } - - // it's ok to change offset immediately -- there are no thread safety issues here - _shapeLocalOffset = corner + 0.5f * _boxScale; -} - -void MyCharacterController::setEnabled(bool enabled) { - if (enabled != _enabled) { - if (enabled) { - // Don't bother clearing REMOVE bit since it might be paired with an UPDATE_SHAPE bit. - // Setting the ADD bit here works for all cases so we don't even bother checking other bits. - _pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION; - } else { - if (_dynamicsWorld) { - _pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION; - } - _pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION; - _isOnGround = false; - } - setHovering(true); - _enabled = enabled; - } -} - void MyCharacterController::updateShapeIfNecessary() { if (_pendingFlags & PENDING_FLAG_UPDATE_SHAPE) { _pendingFlags &= ~ PENDING_FLAG_UPDATE_SHAPE; @@ -300,7 +70,7 @@ void MyCharacterController::updateShapeIfNecessary() { if (_isHovering) { _rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f)); } else { - _rigidBody->setGravity(DEFAULT_GRAVITY * _currentUp); + _rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp); } //_rigidBody->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT); } else { @@ -309,98 +79,3 @@ void MyCharacterController::updateShapeIfNecessary() { } } -void MyCharacterController::updateUpAxis(const glm::quat& rotation) { - btVector3 oldUp = _currentUp; - _currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS); - if (!_isHovering) { - const btScalar MIN_UP_ERROR = 0.01f; - if (oldUp.distance(_currentUp) > MIN_UP_ERROR) { - _rigidBody->setGravity(DEFAULT_GRAVITY * _currentUp); - } - } -} - -void MyCharacterController::setAvatarPositionAndOrientation( - const glm::vec3& position, - const glm::quat& orientation) { - // TODO: update gravity if up has changed - updateUpAxis(orientation); - - btQuaternion bodyOrientation = glmToBullet(orientation); - btVector3 bodyPosition = glmToBullet(position + orientation * _shapeLocalOffset); - _avatarBodyTransform = btTransform(bodyOrientation, bodyPosition); -} - -void MyCharacterController::getAvatarPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const { - if (_enabled && _rigidBody) { - const btTransform& avatarTransform = _rigidBody->getWorldTransform(); - rotation = bulletToGLM(avatarTransform.getRotation()); - position = bulletToGLM(avatarTransform.getOrigin()) - rotation * _shapeLocalOffset; - } -} - -void MyCharacterController::setTargetVelocity(const glm::vec3& velocity) { - //_walkVelocity = glmToBullet(_avatarData->getTargetVelocity()); - _walkVelocity = glmToBullet(velocity); -} - -void MyCharacterController::setFollowVelocity(const glm::vec3& velocity) { - _followVelocity = glmToBullet(velocity); -} - -glm::vec3 MyCharacterController::getLinearVelocity() const { - glm::vec3 velocity(0.0f); - if (_rigidBody) { - velocity = bulletToGLM(_rigidBody->getLinearVelocity()); - } - return velocity; -} - -void MyCharacterController::preSimulation() { - if (_enabled && _dynamicsWorld) { - // slam body to where it is supposed to be - _rigidBody->setWorldTransform(_avatarBodyTransform); - - // scan for distant floor - // rayStart is at center of bottom sphere - btVector3 rayStart = _avatarBodyTransform.getOrigin() - _halfHeight * _currentUp; - - // rayEnd is straight down MAX_FALL_HEIGHT - btScalar rayLength = _radius + MAX_FALL_HEIGHT; - btVector3 rayEnd = rayStart - rayLength * _currentUp; - - ClosestNotMe rayCallback(_rigidBody); - rayCallback.m_closestHitFraction = 1.0f; - _dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback); - if (rayCallback.hasHit()) { - _floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius; - const btScalar MIN_HOVER_HEIGHT = 3.0f; - if (_isHovering && _floorDistance < MIN_HOVER_HEIGHT && !_isPushingUp) { - setHovering(false); - } - // TODO: use collision events rather than ray-trace test to disable jumping - const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius; - if (_floorDistance < JUMP_PROXIMITY_THRESHOLD) { - _isJumping = false; - } - } else { - _floorDistance = FLT_MAX; - setHovering(true); - } - - if (_pendingFlags & PENDING_FLAG_JUMP) { - _pendingFlags &= ~ PENDING_FLAG_JUMP; - if (onGround()) { - _isJumping = true; - btVector3 velocity = _rigidBody->getLinearVelocity(); - velocity += _jumpSpeed * _currentUp; - _rigidBody->setLinearVelocity(velocity); - } - } - } - _followTime = 0.0f; -} - -void MyCharacterController::postSimulation() { - // postSimulation() exists for symmetry and just in case we need to do something here later -} diff --git a/interface/src/avatar/MyCharacterController.h b/interface/src/avatar/MyCharacterController.h index 82aa958309..39f0f99917 100644 --- a/interface/src/avatar/MyCharacterController.h +++ b/interface/src/avatar/MyCharacterController.h @@ -13,12 +13,8 @@ #ifndef hifi_MyCharacterController_h #define hifi_MyCharacterController_h -#include -#include - -#include #include -#include +//#include class btCollisionShape; class MyAvatar; @@ -28,79 +24,10 @@ public: MyCharacterController(MyAvatar* avatar); ~MyCharacterController (); - // TODO: implement these when needed - virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) override { assert(false); } - virtual void reset(btCollisionWorld* collisionWorld) override { } - virtual void warp(const btVector3& origin) override { } - virtual void debugDraw(btIDebugDraw* debugDrawer) override { } - virtual void setUpInterpolate(bool value) override { } - - // overrides from btCharacterControllerInterface - virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime) override { - preStep(collisionWorld); - playerStep(collisionWorld, deltaTime); - } - virtual void preStep(btCollisionWorld* collisionWorld) override; - virtual void playerStep(btCollisionWorld* collisionWorld, btScalar dt) override; - virtual bool canJump() const override { assert(false); return false; } // never call this - virtual void jump() override; // call this every frame the jump button is pressed - virtual bool onGround() const override; - - // overrides from CharacterController - virtual void preSimulation() override; - virtual void postSimulation() override; - - bool isHovering() const { return _isHovering; } - void setHovering(bool enabled); - - void setEnabled(bool enabled); - bool isEnabled() const { return _enabled && _dynamicsWorld; } - - void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale); - virtual void updateShapeIfNecessary() override; - void setAvatarPositionAndOrientation( const glm::vec3& position, const glm::quat& orientation); - void getAvatarPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const; - - void setTargetVelocity(const glm::vec3& velocity); - void setFollowVelocity(const glm::vec3& velocity); - float getFollowTime() const { return _followTime; } - - glm::vec3 getLinearVelocity() const; - protected: - void updateUpAxis(const glm::quat& rotation); - -protected: - btVector3 _currentUp; - btVector3 _walkVelocity; - btVector3 _followVelocity; - btTransform _avatarBodyTransform; - - glm::vec3 _shapeLocalOffset; - glm::vec3 _boxScale; // used to compute capsule shape - - quint64 _jumpToHoverStart; - MyAvatar* _avatar { nullptr }; - - btScalar _halfHeight; - btScalar _radius; - - btScalar _floorDistance; - - btScalar _gravity; - - btScalar _jumpSpeed; - btScalar _followTime; - - bool _enabled; - bool _isOnGround; - bool _isJumping; - bool _isFalling; - bool _isHovering; - bool _isPushingUp; }; #endif // hifi_MyCharacterController_h diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 8da9541387..ba3a59f69d 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -11,8 +11,55 @@ #include "CharacterController.h" +#include + +#include "BulletUtil.h" #include "PhysicsCollisionGroups.h" +const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); +const float JUMP_SPEED = 3.5f; +const float MAX_FALL_HEIGHT = 20.0f; + + +// helper class for simple ray-traces from character +class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback { +public: + ClosestNotMe(btRigidBody* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0f, 0.0f, 0.0f), btVector3(0.0f, 0.0f, 0.0f)) { + _me = me; + } + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) { + if (rayResult.m_collisionObject == _me) { + return 1.0f; + } + return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); + } +protected: + btRigidBody* _me; +}; + + +CharacterController::CharacterController() { + _halfHeight = 1.0f; + + _enabled = false; + + _floorDistance = MAX_FALL_HEIGHT; + + _walkVelocity.setValue(0.0f, 0.0f, 0.0f); + _followVelocity.setValue(0.0f, 0.0f, 0.0f); + _jumpSpeed = JUMP_SPEED; + _isOnGround = false; + _isJumping = false; + _isFalling = false; + _isHovering = true; + _isPushingUp = false; + _jumpToHoverStart = 0; + _followTime = 0.0f; + + _pendingFlags = PENDING_FLAG_UPDATE_SHAPE; + +} + bool CharacterController::needsRemoval() const { return ((_pendingFlags & PENDING_FLAG_REMOVE_FROM_SIMULATION) == PENDING_FLAG_REMOVE_FROM_SIMULATION); } @@ -23,7 +70,7 @@ bool CharacterController::needsAddition() const { void CharacterController::setDynamicsWorld(btDynamicsWorld* world) { if (_dynamicsWorld != world) { - if (_dynamicsWorld) { + if (_dynamicsWorld) { if (_rigidBody) { _dynamicsWorld->removeRigidBody(_rigidBody); _dynamicsWorld->removeAction(this); @@ -48,5 +95,283 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) { } else { _pendingFlags &= ~PENDING_FLAG_REMOVE_FROM_SIMULATION; } -} +} +void CharacterController::preStep(btCollisionWorld* collisionWorld) { + // trace a ray straight down to see if we're standing on the ground + const btTransform& xform = _rigidBody->getWorldTransform(); + + // rayStart is at center of bottom sphere + btVector3 rayStart = xform.getOrigin() - _halfHeight * _currentUp; + + // rayEnd is some short distance outside bottom sphere + const btScalar FLOOR_PROXIMITY_THRESHOLD = 0.3f * _radius; + btScalar rayLength = _radius + FLOOR_PROXIMITY_THRESHOLD; + btVector3 rayEnd = rayStart - rayLength * _currentUp; + + // scan down for nearby floor + ClosestNotMe rayCallback(_rigidBody); + rayCallback.m_closestHitFraction = 1.0f; + collisionWorld->rayTest(rayStart, rayEnd, rayCallback); + if (rayCallback.hasHit()) { + _floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius; + } +} + +void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) { + btVector3 actualVelocity = _rigidBody->getLinearVelocity(); + btScalar actualSpeed = actualVelocity.length(); + + btVector3 desiredVelocity = _walkVelocity; + btScalar desiredSpeed = desiredVelocity.length(); + + const btScalar MIN_UP_PUSH = 0.1f; + if (desiredVelocity.dot(_currentUp) < MIN_UP_PUSH) { + _isPushingUp = false; + } + + const btScalar MIN_SPEED = 0.001f; + if (_isHovering) { + if (desiredSpeed < MIN_SPEED) { + if (actualSpeed < MIN_SPEED) { + _rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f)); + } else { + const btScalar HOVER_BRAKING_TIMESCALE = 0.1f; + btScalar tau = glm::max(dt / HOVER_BRAKING_TIMESCALE, 1.0f); + _rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity); + } + } else { + const btScalar HOVER_ACCELERATION_TIMESCALE = 0.1f; + btScalar tau = dt / HOVER_ACCELERATION_TIMESCALE; + _rigidBody->setLinearVelocity(actualVelocity - tau * (actualVelocity - desiredVelocity)); + } + } else { + if (onGround()) { + // walking on ground + if (desiredSpeed < MIN_SPEED) { + if (actualSpeed < MIN_SPEED) { + _rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f)); + } else { + const btScalar HOVER_BRAKING_TIMESCALE = 0.1f; + btScalar tau = dt / HOVER_BRAKING_TIMESCALE; + _rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity); + } + } else { + // TODO: modify desiredVelocity using floor normal + const btScalar WALK_ACCELERATION_TIMESCALE = 0.1f; + btScalar tau = dt / WALK_ACCELERATION_TIMESCALE; + btVector3 velocityCorrection = tau * (desiredVelocity - actualVelocity); + // subtract vertical component + velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp; + _rigidBody->setLinearVelocity(actualVelocity + velocityCorrection); + } + } else { + // transitioning to flying + btVector3 velocityCorrection = desiredVelocity - actualVelocity; + const btScalar FLY_ACCELERATION_TIMESCALE = 0.2f; + btScalar tau = dt / FLY_ACCELERATION_TIMESCALE; + if (!_isPushingUp) { + // actually falling --> compute a different velocity attenuation factor + const btScalar FALL_ACCELERATION_TIMESCALE = 2.0f; + tau = dt / FALL_ACCELERATION_TIMESCALE; + // zero vertical component + velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp; + } + _rigidBody->setLinearVelocity(actualVelocity + tau * velocityCorrection); + } + } + + // Rather than add _followVelocity to the velocity of the RigidBody, we explicitly teleport + // the RigidBody forward according to the formula: distance = rate * time + if (_followVelocity.length2() > 0.0f) { + btTransform bodyTransform = _rigidBody->getWorldTransform(); + bodyTransform.setOrigin(bodyTransform.getOrigin() + dt * _followVelocity); + _rigidBody->setWorldTransform(bodyTransform); + } + _followTime += dt; +} + +void CharacterController::jump() { + // check for case where user is holding down "jump" key... + // we'll eventually tansition to "hover" + if (!_isJumping) { + if (!_isHovering) { + _jumpToHoverStart = usecTimestampNow(); + _pendingFlags |= PENDING_FLAG_JUMP; + } + } else { + quint64 now = usecTimestampNow(); + const quint64 JUMP_TO_HOVER_PERIOD = 75 * (USECS_PER_SECOND / 100); + if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) { + _isPushingUp = true; + setHovering(true); + } + } +} + +bool CharacterController::onGround() const { + const btScalar FLOOR_PROXIMITY_THRESHOLD = 0.3f * _radius; + return _floorDistance < FLOOR_PROXIMITY_THRESHOLD; +} + +void CharacterController::setHovering(bool hover) { + if (hover != _isHovering) { + _isHovering = hover; + _isJumping = false; + + if (_rigidBody) { + if (hover) { + _rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f)); + } else { + _rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp); + } + } + } +} + +void CharacterController::setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale) { + _boxScale = scale; + + float x = _boxScale.x; + float z = _boxScale.z; + float radius = 0.5f * sqrtf(0.5f * (x * x + z * z)); + float halfHeight = 0.5f * _boxScale.y - radius; + float MIN_HALF_HEIGHT = 0.1f; + if (halfHeight < MIN_HALF_HEIGHT) { + halfHeight = MIN_HALF_HEIGHT; + } + + // compare dimensions + float radiusDelta = glm::abs(radius - _radius); + float heightDelta = glm::abs(halfHeight - _halfHeight); + if (radiusDelta < FLT_EPSILON && heightDelta < FLT_EPSILON) { + // shape hasn't changed --> nothing to do + } else { + if (_dynamicsWorld) { + // must REMOVE from world prior to shape update + _pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION; + } + _pendingFlags |= PENDING_FLAG_UPDATE_SHAPE; + // only need to ADD back when we happen to be enabled + if (_enabled) { + _pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION; + } + } + + // it's ok to change offset immediately -- there are no thread safety issues here + _shapeLocalOffset = corner + 0.5f * _boxScale; +} + +void CharacterController::setEnabled(bool enabled) { + if (enabled != _enabled) { + if (enabled) { + // Don't bother clearing REMOVE bit since it might be paired with an UPDATE_SHAPE bit. + // Setting the ADD bit here works for all cases so we don't even bother checking other bits. + _pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION; + } else { + if (_dynamicsWorld) { + _pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION; + } + _pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION; + _isOnGround = false; + } + setHovering(true); + _enabled = enabled; + } +} + +void CharacterController::updateUpAxis(const glm::quat& rotation) { + btVector3 oldUp = _currentUp; + _currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS); + if (!_isHovering) { + const btScalar MIN_UP_ERROR = 0.01f; + if (oldUp.distance(_currentUp) > MIN_UP_ERROR) { + _rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp); + } + } +} + +void CharacterController::setPositionAndOrientation( + const glm::vec3& position, + const glm::quat& orientation) { + // TODO: update gravity if up has changed + updateUpAxis(orientation); + + btQuaternion bodyOrientation = glmToBullet(orientation); + btVector3 bodyPosition = glmToBullet(position + orientation * _shapeLocalOffset); + _characterBodyTransform = btTransform(bodyOrientation, bodyPosition); +} + +void CharacterController::getPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const { + if (_enabled && _rigidBody) { + const btTransform& avatarTransform = _rigidBody->getWorldTransform(); + rotation = bulletToGLM(avatarTransform.getRotation()); + position = bulletToGLM(avatarTransform.getOrigin()) - rotation * _shapeLocalOffset; + } +} + +void CharacterController::setTargetVelocity(const glm::vec3& velocity) { + //_walkVelocity = glmToBullet(_avatarData->getTargetVelocity()); + _walkVelocity = glmToBullet(velocity); +} + +void CharacterController::setFollowVelocity(const glm::vec3& velocity) { + _followVelocity = glmToBullet(velocity); +} + +glm::vec3 CharacterController::getLinearVelocity() const { + glm::vec3 velocity(0.0f); + if (_rigidBody) { + velocity = bulletToGLM(_rigidBody->getLinearVelocity()); + } + return velocity; +} + +void CharacterController::preSimulation() { + if (_enabled && _dynamicsWorld) { + // slam body to where it is supposed to be + _rigidBody->setWorldTransform(_characterBodyTransform); + + // scan for distant floor + // rayStart is at center of bottom sphere + btVector3 rayStart = _characterBodyTransform.getOrigin() - _halfHeight * _currentUp; + + // rayEnd is straight down MAX_FALL_HEIGHT + btScalar rayLength = _radius + MAX_FALL_HEIGHT; + btVector3 rayEnd = rayStart - rayLength * _currentUp; + + ClosestNotMe rayCallback(_rigidBody); + rayCallback.m_closestHitFraction = 1.0f; + _dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback); + if (rayCallback.hasHit()) { + _floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius; + const btScalar MIN_HOVER_HEIGHT = 3.0f; + if (_isHovering && _floorDistance < MIN_HOVER_HEIGHT && !_isPushingUp) { + setHovering(false); + } + // TODO: use collision events rather than ray-trace test to disable jumping + const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius; + if (_floorDistance < JUMP_PROXIMITY_THRESHOLD) { + _isJumping = false; + } + } else { + _floorDistance = FLT_MAX; + setHovering(true); + } + + if (_pendingFlags & PENDING_FLAG_JUMP) { + _pendingFlags &= ~ PENDING_FLAG_JUMP; + if (onGround()) { + _isJumping = true; + btVector3 velocity = _rigidBody->getLinearVelocity(); + velocity += _jumpSpeed * _currentUp; + _rigidBody->setLinearVelocity(velocity); + } + } + } + _followTime = 0.0f; +} + +void CharacterController::postSimulation() { + // postSimulation() exists for symmetry and just in case we need to do something here later +} diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index e9e6f1328e..6edbabdab8 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -17,11 +17,14 @@ #include #include +#include + const uint32_t PENDING_FLAG_ADD_TO_SIMULATION = 1U << 0; const uint32_t PENDING_FLAG_REMOVE_FROM_SIMULATION = 1U << 1; const uint32_t PENDING_FLAG_UPDATE_SHAPE = 1U << 2; const uint32_t PENDING_FLAG_JUMP = 1U << 3; +const float DEFAULT_CHARACTER_GRAVITY = -5.0f; class btRigidBody; class btCollisionWorld; @@ -29,31 +32,89 @@ class btDynamicsWorld; class CharacterController : public btCharacterControllerInterface { public: + CharacterController(); + virtual ~CharacterController() {} + bool needsRemoval() const; bool needsAddition() const; void setDynamicsWorld(btDynamicsWorld* world); btCollisionObject* getCollisionObject() { return _rigidBody; } virtual void updateShapeIfNecessary() = 0; - virtual void preSimulation() = 0; - virtual void postSimulation() = 0; + // overrides from btCharacterControllerInterface virtual void setWalkDirection(const btVector3 &walkDirection) { assert(false); } + virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) override { assert(false); } + virtual void reset(btCollisionWorld* collisionWorld) override { } + virtual void warp(const btVector3& origin) override { } + virtual void debugDraw(btIDebugDraw* debugDrawer) override { } + virtual void setUpInterpolate(bool value) override { } + virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime) override { + preStep(collisionWorld); + playerStep(collisionWorld, deltaTime); + } + virtual void preStep(btCollisionWorld *collisionWorld) override; + virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) override; + virtual bool canJump() const override { assert(false); return false; } // never call this + virtual void jump() override; + virtual bool onGround() const; + + void preSimulation(); + void postSimulation(); + + void setPositionAndOrientation( const glm::vec3& position, const glm::quat& orientation); + void getPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const; + + void setTargetVelocity(const glm::vec3& velocity); + void setFollowVelocity(const glm::vec3& velocity); + float getFollowTime() const { return _followTime; } + + glm::vec3 getLinearVelocity() const; + + bool isHovering() const { return _isHovering; } + void setHovering(bool enabled); + + void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale); + + void setEnabled(bool enabled); + bool isEnabled() const { return _enabled && _dynamicsWorld; } - /* these from btCharacterControllerInterface remain to be overridden - virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) = 0; - virtual void reset() = 0; - virtual void warp(const btVector3 &origin) = 0; - virtual void preStep(btCollisionWorld *collisionWorld) = 0; - virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) = 0; - virtual bool canJump() const = 0; - virtual void jump() = 0; - virtual bool onGround() const = 0; - */ protected: + void updateUpAxis(const glm::quat& rotation); + +protected: + btVector3 _currentUp; + btVector3 _walkVelocity; + btVector3 _followVelocity; + btTransform _characterBodyTransform; + + glm::vec3 _shapeLocalOffset; + + glm::vec3 _boxScale; // used to compute capsule shape + + quint64 _jumpToHoverStart; + + btScalar _halfHeight; + btScalar _radius; + + btScalar _floorDistance; + + btScalar _gravity; + + btScalar _jumpSpeed; + btScalar _followTime; + + bool _enabled; + bool _isOnGround; + bool _isJumping; + bool _isFalling; + bool _isHovering; + bool _isPushingUp; + btDynamicsWorld* _dynamicsWorld { nullptr }; btRigidBody* _rigidBody { nullptr }; uint32_t _pendingFlags { 0 }; + }; #endif // hifi_CharacterControllerInterface_h From 1d65cbce882525243d5be7f54e70484058493e93 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 8 Dec 2015 18:08:57 -0800 Subject: [PATCH 104/174] Remove unneeded getTargetFramePeriod and isVSynchronized. --- interface/src/Application.cpp | 2 -- interface/src/Application.h | 1 - interface/src/avatar/AvatarManager.cpp | 6 ++---- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 7 ------- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h | 3 --- .../src/display-plugins/openvr/OpenVrDisplayPlugin.h | 1 - libraries/plugins/src/plugins/DisplayPlugin.h | 2 -- plugins/oculus/src/OculusDisplayPlugin.h | 1 - plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h | 1 - 9 files changed, 2 insertions(+), 22 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 24fd1d1ac9..e01899726a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3235,8 +3235,6 @@ bool Application::isHMDMode() const { return getActiveDisplayPlugin()->isHmd(); } float Application::getTargetFrameRate() { return getActiveDisplayPlugin()->getTargetFrameRate(); } -float Application::getTargetFramePeriod() { return getActiveDisplayPlugin()->getTargetFramePeriod(); } -bool Application::isVSynchronized() const { return getActiveDisplayPlugin()->isVSynchronized(); } QRect Application::getDesirableApplicationGeometry() { QRect applicationGeometry = getWindow()->geometry(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0678477aaa..122b6ea3ae 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -124,7 +124,6 @@ public: PickRay computePickRay() const; bool isThrottleRendering() const; - bool isVSynchronized() const; Camera* getCamera() { return &_myCamera; } // Represents the current view frustum of the avatar. diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index dff6893bef..7c1a52f1b3 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -146,7 +146,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { PerformanceTimer perfTimer("otherAvatars"); float distance; - if (qApp->isVSynchronized()) { + if (!qApp->isThrottleRendering()) { _renderDistanceController.setMeasuredValueSetpoint(qApp->getTargetFrameRate()); // No problem updating in flight. // The PID controller raises the controlled value when the measured value goes up. // The measured value is frame rate. When the controlled value (1 / render cutoff distance) @@ -155,9 +155,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { const float deduced = qApp->getLastUnsynchronizedFps(); distance = 1.0f / _renderDistanceController.update(deduced, deltaTime); } else { - // We could keep the controller running when not vsync'd, if getLastDeducedNonVSyncFps is still meaningful. - // But the basic 2d controller doesn't try to adjust the timer for qt load or getLastPaintWait, so running the - // Here we choose to just use the maximum render cutoff distance if: throttled, running without vsync, or 30-60 "fixed" targets. + // Here we choose to just use the maximum render cutoff distance if throttled. distance = 1.0f / _renderDistanceController.getControlledValueLowLimit(); } _renderDistanceAverage.updateAverage(distance); diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 97e12643a9..9139a9dcc9 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -113,10 +113,6 @@ bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { return shouldThrottle; } -bool Basic2DWindowOpenGLDisplayPlugin::isVSynchronized() const { - return (_framerateTarget == 0) && !_isThrottled; -} - void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { QAction* checkedFramerate{ nullptr }; foreach(auto action, _framerateActions) { @@ -141,11 +137,8 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { } else if (_isThrottled) { _framerateTarget = (float) THROTTLED_FRAMERATE; } - _inverseFrameRate = _framerateTarget ? 1.0f / (float) _framerateTarget : 1.0f / TARGET_FRAMERATE_Basic2DWindowOpenGL; // not truncated int newInterval = getDesiredInterval(); - // Note: when not isVSynchronized, we are often not likely to hit target with a newInterval timer. - // We could try subtracting an allowance for qApp->getLastPaintWait() and qt timer machinery, but that starts getting complicated. qDebug() << newInterval; _timer.start(newInterval); } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index bd5359e141..59c0e4e759 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -21,7 +21,6 @@ public: virtual const QString & getName() const override; virtual float getTargetFrameRate() override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } - virtual float getTargetFramePeriod() override { return _inverseFrameRate; } virtual void activate() override; @@ -30,7 +29,6 @@ public: virtual void internalPresent() override; virtual bool isThrottled() const override; - virtual bool isVSynchronized() const override; protected: int getDesiredInterval() const; @@ -44,6 +42,5 @@ private: QAction* _vsyncAction { nullptr }; uint32_t _framerateTarget { 0 }; int _fullscreenTarget{ -1 }; - float _inverseFrameRate{ 1.0f }; //seconds bool _wantVsync { true }; }; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h index feb5c0716c..2b51c53d58 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -23,7 +23,6 @@ public: virtual bool isHmd() const override { return true; } virtual float getTargetFrameRate() override { return TARGET_RATE_OpenVr; } - virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_OpenVr; } virtual void activate() override; virtual void deactivate() override; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 5352cf9a87..7f3b38e4a2 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -58,9 +58,7 @@ public: /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } virtual bool isThrottled() const { return false; } - virtual bool isVSynchronized() const { return true; } // false when throttled or run by non vsync timer virtual float getTargetFrameRate() { return 0.0f; } - virtual float getTargetFramePeriod() { return 0.0f; } // Rendering support diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index 47b41b08b6..071dca0258 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -21,7 +21,6 @@ public: virtual void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) override final; virtual float getTargetFrameRate() override { return TARGET_RATE_Oculus; } - virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_Oculus; } protected: virtual void internalPresent() override; diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index 67efcc6575..7fe721fc45 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -28,7 +28,6 @@ public: virtual int getHmdScreen() const override; virtual float getTargetFrameRate() override { return TARGET_RATE_OculusLegacy; } - virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_OculusLegacy; } // Stereo specific methods virtual bool isHmd() const override { return true; } From 4d60c7bbc035afe9dbaef3bc69e7140bb2893ec7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 9 Dec 2015 10:42:32 -0800 Subject: [PATCH 105/174] update model location with SpatiallyNestable's locationChanged call --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 8 ++++++++ .../entities-renderer/src/RenderableModelEntityItem.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5b4704cabb..81c0554111 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -584,3 +584,11 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in } return glm::vec3(0.0f); } + +void RenderableModelEntityItem::locationChanged() { + EntityItem::locationChanged(); + if (_model && _model->isActive()) { + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + } +} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 5c05dc5b44..3f3fe11633 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -71,6 +71,8 @@ public: virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; + void locationChanged(); + private: void remapTextures(); From 446ca8236f58dadd1c7cbbb208a665075c9dee28 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 9 Dec 2015 11:25:44 -0800 Subject: [PATCH 106/174] disable physics disabler --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eee1ea7226..1a03cad62a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2907,7 +2907,7 @@ void Application::update(float deltaTime) { _avatarUpdate->synchronousProcess(); - if (_physicsEnabled) { + if (true || _physicsEnabled) { PerformanceTimer perfTimer("physics"); static VectorOfMotionStates motionStates; From 65bc6aa37114fc3fcd9a6a9437ee3df2a702283e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 8 Dec 2015 10:48:11 -0800 Subject: [PATCH 107/174] Fix left hand grab --- examples/controllers/handControllerGrab.js | 43 ++++++++++++++++------ interface/src/avatar/AvatarActionHold.cpp | 4 +- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 138240f5d6..07894b46d1 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -202,31 +202,41 @@ function entityIsGrabbedByOther(entityID) { } function getSpatialOffsetPosition(hand, spatialKey) { + var position = Vec3.ZERO; + if (hand !== RIGHT_HAND && spatialKey.leftRelativePosition) { - return spatialKey.leftRelativePosition; + position = spatialKey.leftRelativePosition; } if (hand === RIGHT_HAND && spatialKey.rightRelativePosition) { - return spatialKey.rightRelativePosition; + position = spatialKey.rightRelativePosition; } if (spatialKey.relativePosition) { - return spatialKey.relativePosition; + position = spatialKey.relativePosition; } - return Vec3.ZERO; + return position; } +var yFlip = Quat.angleAxis(180, Vec3.UNIT_Y); function getSpatialOffsetRotation(hand, spatialKey) { + var rotation = Quat.IDENTITY; + if (hand !== RIGHT_HAND && spatialKey.leftRelativeRotation) { - return spatialKey.leftRelativeRotation; + rotation = spatialKey.leftRelativeRotation; } if (hand === RIGHT_HAND && spatialKey.rightRelativeRotation) { - return spatialKey.rightRelativeRotation; + rotation = spatialKey.rightRelativeRotation; } if (spatialKey.relativeRotation) { - return spatialKey.relativeRotation; + rotation = spatialKey.relativeRotation; } - return Quat.IDENTITY; + // Flip left hand + if (hand !== RIGHT_HAND) { + rotation = Quat.multiply(yFlip, rotation); + } + + return rotation; } function MyController(hand) { @@ -254,6 +264,7 @@ function MyController(hand) { this.overlayLine = null; + this.ignoreIK = false; this.offsetPosition = Vec3.ZERO; this.offsetRotation = Quat.IDENTITY; @@ -853,9 +864,12 @@ function MyController(hand) { 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); @@ -872,7 +886,8 @@ function MyController(hand) { relativeRotation: this.offsetRotation, ttl: ACTION_TTL, kinematic: NEAR_GRABBING_KINEMATIC, - kinematicSetVelocity: true + kinematicSetVelocity: true, + ignoreIK: this.ignoreIK }); if (this.actionID === NULL_ACTION_ID) { this.actionID = null; @@ -956,7 +971,8 @@ function MyController(hand) { relativeRotation: this.offsetRotation, ttl: ACTION_TTL, kinematic: NEAR_GRABBING_KINEMATIC, - kinematicSetVelocity: true + kinematicSetVelocity: true, + ignoreIK: this.ignoreIK }); this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); } @@ -982,6 +998,7 @@ function MyController(hand) { // 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); @@ -996,7 +1013,8 @@ function MyController(hand) { linearTimeScale: EQUIP_SPRING_TIMEFRAME, targetRotation: targetRotation, angularTimeScale: EQUIP_SPRING_TIMEFRAME, - ttl: ACTION_TTL + ttl: ACTION_TTL, + ignoreIK: ignoreIK }); if (this.equipSpringID === NULL_ACTION_ID) { this.equipSpringID = null; @@ -1009,7 +1027,8 @@ function MyController(hand) { linearTimeScale: EQUIP_SPRING_TIMEFRAME, targetRotation: targetRotation, angularTimeScale: EQUIP_SPRING_TIMEFRAME, - ttl: ACTION_TTL + ttl: ACTION_TTL, + ignoreIK: ignoreIK }); } diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index fab838aa68..c2eea69a17 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -85,8 +85,8 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) { QList holdActions = ownerEntity->getActionsOfType(ACTION_TYPE_HOLD); foreach (EntityActionPointer action, holdActions) { std::shared_ptr holdAction = std::static_pointer_cast(action); - glm::quat rotationForAction; - glm::vec3 positionForAction; + glm::quat rotationForAction { Quaternions::IDENTITY }; + glm::vec3 positionForAction { Vectors::ZERO }; std::shared_ptr holdingAvatar = holdAction->getTarget(rotationForAction, positionForAction); if (holdingAvatar) { holdCount ++; From 4ee5bf316a98f982db5993a77b881dd9fc9bf21d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 8 Dec 2015 10:48:30 -0800 Subject: [PATCH 108/174] Fix bow offsets --- examples/toybox/bow/bow.js | 14 +++++++------- examples/toybox/bow/createBow.js | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/toybox/bow/bow.js b/examples/toybox/bow/bow.js index 90199fb70f..a5bada779f 100644 --- a/examples/toybox/bow/bow.js +++ b/examples/toybox/bow/bow.js @@ -67,15 +67,15 @@ } var BOW_SPATIAL_KEY = { - leftRelativePosition: { - x: 0.05, - y: 0.06, - z: -0.05 + leftRelativePosition: { + x: -0.02, + y: 0.08, + z: 0.09 }, rightRelativePosition: { - x: -0.05, - y: 0.06, - z: -0.05 + x: 0.02, + y: 0.08, + z: 0.09 }, relativeRotation: Quat.fromPitchYawRollDegrees(0, 90, -90) } diff --git a/examples/toybox/bow/createBow.js b/examples/toybox/bow/createBow.js index 9a9ed98c20..4f0cddfc0d 100644 --- a/examples/toybox/bow/createBow.js +++ b/examples/toybox/bow/createBow.js @@ -49,14 +49,14 @@ var bow = Entities.addEntity({ invertSolidWhileHeld: true, spatialKey: { leftRelativePosition: { - x: 0.05, - y: 0.06, - z: -0.05 + x: -0.02, + y: 0.08, + z: 0.09 }, - rightRelativePosition: { - x: -0.05, - y: 0.06, - z: -0.05 + relativePosition: { + x: 0.02, + y: 0.08, + z: 0.09 }, relativeRotation: Quat.fromPitchYawRollDegrees(0, 90, -90) } From 17daff920c959422c1753092d7c18aec7373439d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 8 Dec 2015 11:21:04 -0800 Subject: [PATCH 109/174] Fix all entities using relative grab pos/rot --- examples/toybox/bow/bow.js | 32 ++++++------------------ examples/toybox/bubblewand/createWand.js | 9 +++++-- examples/toybox/pistol/createPistol.js | 6 ++--- 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/examples/toybox/bow/bow.js b/examples/toybox/bow/bow.js index a5bada779f..f0128acc77 100644 --- a/examples/toybox/bow/bow.js +++ b/examples/toybox/bow/bow.js @@ -66,21 +66,6 @@ max2: 15 } - var BOW_SPATIAL_KEY = { - leftRelativePosition: { - x: -0.02, - y: 0.08, - z: 0.09 - }, - rightRelativePosition: { - x: 0.02, - y: 0.08, - z: 0.09 - }, - relativeRotation: Quat.fromPitchYawRollDegrees(0, 90, -90) - } - - var USE_DEBOUNCE = false; var TRIGGER_CONTROLS = [ @@ -168,11 +153,9 @@ var handToDisable = this.initialHand === 'right' ? 'left' : 'right'; Messages.sendMessage('Hifi-Hand-Disabler', handToDisable); - setEntityCustomData('grabbableKey', this.entityID, { - grabbable: false, - invertSolidWhileHeld: true, - spatialKey: BOW_SPATIAL_KEY - }); + var data = getEntityCustomData('grabbableKey', this.entityID, {}); + data.grabbable = false; + setEntityCustomData('grabbableKey', this.entityID, data); }, continueNearGrab: function() { @@ -226,11 +209,10 @@ this.isGrabbed = false; this.stringDrawn = false; this.deleteStrings(); - setEntityCustomData('grabbableKey', this.entityID, { - grabbable: true, - invertSolidWhileHeld: true, - spatialKey: BOW_SPATIAL_KEY - }); + + var data = getEntityCustomData('grabbableKey', this.entityID, {}); + data.grabbable = true; + setEntityCustomData('grabbableKey', this.entityID, data); Entities.deleteEntity(this.preNotchString); Entities.deleteEntity(this.arrow); this.aiming = false; diff --git a/examples/toybox/bubblewand/createWand.js b/examples/toybox/bubblewand/createWand.js index 6b4f9717ec..efd86b046f 100644 --- a/examples/toybox/bubblewand/createWand.js +++ b/examples/toybox/bubblewand/createWand.js @@ -53,8 +53,13 @@ var wand = Entities.addEntity({ y: 0.1, z: 0 }, - relativeRotation: Quat.fromPitchYawRollDegrees(0, 0, 90) + relativeRotation: Quat.fromPitchYawRollDegrees(0, 0, -90) } } }) -}); \ No newline at end of file +}); + +function scriptEnding() { + Entities.deleteEntity(wand); +} +Script.scriptEnding.connect(scriptEnding); diff --git a/examples/toybox/pistol/createPistol.js b/examples/toybox/pistol/createPistol.js index d804150cbe..693c53b9b4 100644 --- a/examples/toybox/pistol/createPistol.js +++ b/examples/toybox/pistol/createPistol.js @@ -28,10 +28,10 @@ var pistol = Entities.addEntity({ spatialKey: { relativePosition: { x: 0, - y: 0, - z: 0 + y: 0.05, + z: -0.08 }, - relativeRotation: Quat.fromPitchYawRollDegrees(45, 90, 0) + relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0) }, invertSolidWhileHeld: true } From 5574f4736b368af38542b35c3cc370b72f39364a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 9 Dec 2015 14:26:49 -0800 Subject: [PATCH 110/174] CR --- interface/src/avatar/AvatarActionHold.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index c2eea69a17..fab838aa68 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -85,8 +85,8 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) { QList holdActions = ownerEntity->getActionsOfType(ACTION_TYPE_HOLD); foreach (EntityActionPointer action, holdActions) { std::shared_ptr holdAction = std::static_pointer_cast(action); - glm::quat rotationForAction { Quaternions::IDENTITY }; - glm::vec3 positionForAction { Vectors::ZERO }; + glm::quat rotationForAction; + glm::vec3 positionForAction; std::shared_ptr holdingAvatar = holdAction->getTarget(rotationForAction, positionForAction); if (holdingAvatar) { holdCount ++; From 4bfce768ca68951d44d2f973d1bd408f46b5133c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 14:48:33 -0800 Subject: [PATCH 111/174] Add locks around read/writes of _scriptEnginesHash --- interface/src/Application.cpp | 113 +++++++++++++++++++++++----------- interface/src/Application.h | 1 + 2 files changed, 77 insertions(+), 37 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0b29cdc892..8655d6b77e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4259,10 +4259,13 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser QUrl scriptUrl(scriptFilename); const QString& scriptURLString = scriptUrl.toString(); - if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor - && !_scriptEnginesHash[scriptURLString]->isFinished()) { + { + QReadLocker lock(&_scriptEnginesHashLock); + if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor + && !_scriptEnginesHash[scriptURLString]->isFinished()) { - return _scriptEnginesHash[scriptURLString]; + return _scriptEnginesHash[scriptURLString]; + } } ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); @@ -4302,7 +4305,11 @@ void Application::reloadScript(const QString& scriptName, bool isUserLoaded) { void Application::handleScriptEngineLoaded(const QString& scriptFilename) { ScriptEngine* scriptEngine = qobject_cast(sender()); - _scriptEnginesHash.insertMulti(scriptFilename, scriptEngine); + { + QWriteLocker lock(&_scriptEnginesHashLock); + _scriptEnginesHash.insertMulti(scriptFilename, scriptEngine); + } + _runningScriptsWidget->setRunningScripts(getRunningScripts()); UserActivityLogger::getInstance().loadedScript(scriptFilename); @@ -4317,55 +4324,86 @@ void Application::handleScriptLoadError(const QString& scriptFilename) { QMessageBox::warning(getWindow(), "Error Loading Script", scriptFilename + " failed to load."); } -void Application::scriptFinished(const QString& scriptName) { - const QString& scriptURLString = QUrl(scriptName).toString(); - QHash::iterator it = _scriptEnginesHash.find(scriptURLString); - if (it != _scriptEnginesHash.end()) { - _scriptEnginesHash.erase(it); - _runningScriptsWidget->scriptStopped(scriptName); - _runningScriptsWidget->setRunningScripts(getRunningScripts()); - } +QStringList Application::getRunningScripts() { + QReadLocker lock(&_scriptEnginesHashLock); + return _scriptEnginesHash.keys(); } -void Application::stopAllScripts(bool restart) { - if (restart) { - // Delete all running scripts from cache so that they are re-downloaded when they are restarted - auto scriptCache = DependencyManager::get(); - for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); - it != _scriptEnginesHash.constEnd(); it++) { - if (!it.value()->isFinished()) { - scriptCache->deleteScript(it.key()); +ScriptEngine* Application::getScriptEngine(const QString& scriptHash) { + QReadLocker lock(&_scriptEnginesHashLock); + return _scriptEnginesHash.value(scriptHash, nullptr); +} + +void Application::scriptFinished(const QString& scriptName, ScriptEngine* engine) { + bool removed = false; + { + QWriteLocker lock(&_scriptEnginesHashLock); + const QString& scriptURLString = QUrl(scriptName).toString(); + for (auto it = _scriptEnginesHash.find(scriptURLString); it != _scriptEnginesHash.end(); ++it) { + if (it.value() == engine) { + _scriptEnginesHash.erase(it); + removed = true; + break; } } } + postLambdaEvent([this, scriptName]() { + _runningScriptsWidget->scriptStopped(scriptName); + _runningScriptsWidget->setRunningScripts(getRunningScripts()); + }); +} - // Stop and possibly restart all currently running scripts - for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); +void Application::stopAllScripts(bool restart) { + { + QReadLocker lock(&_scriptEnginesHashLock); + + if (restart) { + // Delete all running scripts from cache so that they are re-downloaded when they are restarted + auto scriptCache = DependencyManager::get(); + for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); it != _scriptEnginesHash.constEnd(); it++) { - if (it.value()->isFinished()) { - continue; + if (!it.value()->isFinished()) { + scriptCache->deleteScript(it.key()); + } + } } - if (restart && it.value()->isUserLoaded()) { - connect(it.value(), SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&))); + + // Stop and possibly restart all currently running scripts + for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); + it != _scriptEnginesHash.constEnd(); it++) { + if (it.value()->isFinished()) { + continue; + } + if (restart && it.value()->isUserLoaded()) { + connect(it.value(), &ScriptEngine::finished, this, [this](QString scriptName, ScriptEngine* engine) { + reloadScript(scriptName); + }); + } + QMetaObject::invokeMethod(it.value(), "stop"); + //it.value()->stop(); + qCDebug(interfaceapp) << "stopping script..." << it.key(); } - it.value()->stop(); - qCDebug(interfaceapp) << "stopping script..." << it.key(); } getMyAvatar()->clearScriptableSettings(); } bool Application::stopScript(const QString& scriptHash, bool restart) { bool stoppedScript = false; - if (_scriptEnginesHash.contains(scriptHash)) { - ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash]; - if (restart) { - auto scriptCache = DependencyManager::get(); - scriptCache->deleteScript(QUrl(scriptHash)); - connect(scriptEngine, SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&))); + { + QReadLocker lock(&_scriptEnginesHashLock); + if (_scriptEnginesHash.contains(scriptHash)) { + ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash]; + if (restart) { + auto scriptCache = DependencyManager::get(); + scriptCache->deleteScript(QUrl(scriptHash)); + connect(scriptEngine, &ScriptEngine::finished, this, [this](QString scriptName, ScriptEngine* engine) { + reloadScript(scriptName); + }); + } + scriptEngine->stop(); + stoppedScript = true; + qCDebug(interfaceapp) << "stopping script..." << scriptHash; } - scriptEngine->stop(); - stoppedScript = true; - qCDebug(interfaceapp) << "stopping script..." << scriptHash; } if (_scriptEnginesHash.empty()) { getMyAvatar()->clearScriptableSettings(); @@ -4384,6 +4422,7 @@ void Application::reloadOneScript(const QString& scriptName) { } void Application::loadDefaultScripts() { + QReadLocker lock(&_scriptEnginesHashLock); if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) { loadScript(DEFAULT_SCRIPTS_JS_URL); } diff --git a/interface/src/Application.h b/interface/src/Application.h index ce33f051ef..2f4e33e52d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -505,6 +505,7 @@ private: TouchEvent _lastTouchEvent; + QReadWriteLock _scriptEnginesHashLock; RunningScriptsWidget* _runningScriptsWidget; QHash _scriptEnginesHash; bool _runningScriptsWidgetWasVisible; From fc6a78d9ef74483a861aea122fee0885c674628f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 14:49:05 -0800 Subject: [PATCH 112/174] Update scriptFinished signal to be a DirectConnection --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8655d6b77e..740b0062f0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4013,7 +4013,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Clipboard", clipboardScriptable); connect(scriptEngine, SIGNAL(finished(const QString&)), clipboardScriptable, SLOT(deleteLater())); - connect(scriptEngine, SIGNAL(finished(const QString&)), this, SLOT(scriptFinished(const QString&))); + connect(scriptEngine, &ScriptEngine::finished, this, &Application::scriptFinished, Qt::DirectConnection); connect(scriptEngine, SIGNAL(loadScript(const QString&, bool)), this, SLOT(loadScript(const QString&, bool))); connect(scriptEngine, SIGNAL(reloadScript(const QString&, bool)), this, SLOT(reloadScript(const QString&, bool))); diff --git a/interface/src/Application.h b/interface/src/Application.h index 2f4e33e52d..0d5b920c10 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -202,8 +202,8 @@ public: NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } - QStringList getRunningScripts() { return _scriptEnginesHash.keys(); } - ScriptEngine* getScriptEngine(const QString& scriptHash) { return _scriptEnginesHash.value(scriptHash, NULL); } + QStringList getRunningScripts(); + ScriptEngine* getScriptEngine(const QString& scriptHash); float getRenderResolutionScale() const; @@ -336,7 +336,7 @@ private slots: void loadSettings(); void saveSettings(); - void scriptFinished(const QString& scriptName); + void scriptFinished(const QString& scriptName, ScriptEngine* engine); void saveScripts(); void reloadScript(const QString& scriptName, bool isUserLoaded = true); From e7a1550b64e831a9b0eb820d277c72e324c8b189 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 14:50:09 -0800 Subject: [PATCH 113/174] Update ScriptEngine::finished to include --- libraries/script-engine/src/ScriptEngine.cpp | 4 ++-- libraries/script-engine/src/ScriptEngine.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index daadb0e394..42287bbea7 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -183,7 +183,7 @@ void ScriptEngine::runInThread() { QSet ScriptEngine::_allKnownScriptEngines; QMutex ScriptEngine::_allScriptsMutex; -std::atomic ScriptEngine::_stoppingAllScripts = false; +std::atomic ScriptEngine::_stoppingAllScripts { false }; void ScriptEngine::stopAllScripts(QObject* application) { _allScriptsMutex.lock(); @@ -752,7 +752,7 @@ void ScriptEngine::run() { } if (_wantSignals) { - emit finished(_fileNameString); + emit finished(_fileNameString, this); } _isRunning = false; diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 82b91aed2e..f8da05135a 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -153,7 +153,7 @@ signals: void errorLoadingScript(const QString& scriptFilename); void update(float deltaTime); void scriptEnding(); - void finished(const QString& fileNameString); + void finished(const QString& fileNameString, ScriptEngine* engine); void cleanupMenuItem(const QString& menuItemString); void printedMessage(const QString& message); void errorMessage(const QString& message); From a21e07327d4da97256411cb6be691f13cedb8af2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 14:50:30 -0800 Subject: [PATCH 114/174] Update ScriptEngine::stop() to always run on its thread --- libraries/script-engine/src/ScriptEngine.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 42287bbea7..e06fe2b209 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -775,6 +775,10 @@ void ScriptEngine::stopAllTimers() { void ScriptEngine::stop() { if (!_isFinished) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "stop"); + return; + } _isFinished = true; if (_wantSignals) { emit runningStateChanged(); From 5f60aeef2217e5fc1e3be0da0754a80982f933a4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 14:50:48 -0800 Subject: [PATCH 115/174] Update ScriptEngine::_isUserLoaded to be atomic --- libraries/script-engine/src/ScriptEngine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index f8da05135a..67a206d673 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -193,7 +193,7 @@ protected: Quat _quatLibrary; Vec3 _vec3Library; ScriptUUID _uuidLibrary; - bool _isUserLoaded { false }; + std::atomic _isUserLoaded { false }; bool _isReloading { false }; ArrayBufferClass* _arrayBufferClass; From a57a2792a4b7bfc49e1a3eb74e3718be70d6466b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 9 Dec 2015 15:17:06 -0800 Subject: [PATCH 116/174] SixenseManager: Added debug draw options These debug draw options were added to help debug rare intermittent issues with configuration the hydra and the Avatar arm IK. --- .../src/input-plugins/SixenseManager.cpp | 61 ++++++++++++++++++- .../src/input-plugins/SixenseManager.h | 4 ++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 5dd0248224..3b08c218a2 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -48,6 +49,8 @@ const QString MENU_PARENT = "Avatar"; const QString MENU_NAME = "Sixense"; const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME; const QString TOGGLE_SMOOTH = "Smooth Sixense Movement"; +const QString SHOW_DEBUG_RAW = "Debug Draw Raw Data"; +const QString SHOW_DEBUG_CALIBRATED = "Debug Draw Calibrated Data"; bool SixenseManager::isSupported() const { #ifdef HAVE_SIXENSE @@ -72,6 +75,14 @@ void SixenseManager::activate() { [this] (bool clicked) { setSixenseFilter(clicked); }, true, true); + _container->addMenuItem(PluginType::INPUT_PLUGIN, MENU_PATH, SHOW_DEBUG_RAW, + [this] (bool clicked) { _inputDevice->setDebugDrawRaw(clicked); }, + true, false); + + _container->addMenuItem(PluginType::INPUT_PLUGIN, MENU_PATH, SHOW_DEBUG_CALIBRATED, + [this] (bool clicked) { _inputDevice->setDebugDrawCalibrated(clicked); }, + true, false); + auto userInputMapper = DependencyManager::get(); userInputMapper->registerDevice(_inputDevice); @@ -149,6 +160,9 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) { // we only support two controllers SixenseControllerData controllers[2]; + // store the raw controller data for debug rendering + controller::Pose rawPoses[2]; + int numActiveControllers = 0; for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) { if (!sixenseIsControllerEnabled(i)) { @@ -175,7 +189,7 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) { // Rotation of Palm glm::quat rotation(data->rot_quat[3], data->rot_quat[0], data->rot_quat[1], data->rot_quat[2]); handlePoseEvent(deltaTime, position, rotation, left); - + rawPoses[i] = controller::Pose(position, rotation, glm::vec3(0), glm::quat()); } else { _poseStateMap.clear(); _collectedSamples.clear(); @@ -197,9 +211,54 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) { _axisStateMap[axisState.first] = 0.0f; } } + + if (_debugDrawCalibrated) { + auto poseIter = _poseStateMap.find(controller::StandardPoseChannel::LEFT_HAND); + if (poseIter != _poseStateMap.end() && poseIter->second.isValid()) { + DebugDraw::getInstance().addMyAvatarMarker("SIXENSE_CALIBRATED_LEFT", poseIter->second.rotation, poseIter->second.translation, glm::vec4(1)); + } else { + DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_CALIBRATED_LEFT"); + } + poseIter = _poseStateMap.find(controller::StandardPoseChannel::RIGHT_HAND); + if (poseIter != _poseStateMap.end() && poseIter->second.isValid()) { + DebugDraw::getInstance().addMyAvatarMarker("SIXENSE_CALIBRATED_RIGHT", poseIter->second.rotation, poseIter->second.translation, glm::vec4(1)); + } else { + DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_CALIBRATED_RIGHT"); + } + } + + if (_debugDrawRaw) { + if (rawPoses[0].isValid()) { + DebugDraw::getInstance().addMyAvatarMarker("SIXENSE_RAW_LEFT", rawPoses[0].rotation, rawPoses[0].translation, glm::vec4(1)); + } else { + DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_RAW_LEFT"); + } + if (rawPoses[1].isValid()) { + DebugDraw::getInstance().addMyAvatarMarker("SIXENSE_RAW_RIGHT", rawPoses[1].rotation, rawPoses[1].translation, glm::vec4(1)); + } else { + DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_RAW_RIGHT"); + } + } + #endif // HAVE_SIXENSE } +void SixenseManager::InputDevice::setDebugDrawRaw(bool flag) { + _debugDrawRaw = flag; + if (!flag) { + DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_RAW_LEFT"); + DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_RAW_RIGHT"); + } +} + +void SixenseManager::InputDevice::setDebugDrawCalibrated(bool flag) { + _debugDrawCalibrated = flag; + if (!flag) { + DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_CALIBRATED_LEFT"); + DebugDraw::getInstance().removeMyAvatarMarker("SIXENSE_CALIBRATED_RIGHT"); + } +} + #ifdef HAVE_SIXENSE // the calibration sequence is: diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index 348a7a4590..b6bf4b24c0 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -60,6 +60,8 @@ private: class InputDevice : public controller::InputDevice { public: InputDevice() : controller::InputDevice("Hydra") {} + void setDebugDrawRaw(bool flag); + void setDebugDrawCalibrated(bool flag); private: // Device functions virtual controller::Input::NamedVector getAvailableInputs() const override; @@ -82,6 +84,8 @@ private: float _lastDistance; bool _requestReset { false }; + bool _debugDrawRaw { false }; + bool _debugDrawCalibrated { false }; // these are measured values used to compute the calibration results quint64 _lockExpiry; glm::vec3 _averageLeft; From 270cfe8af7a63efebf603e908da887bb7fd32def Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 9 Dec 2015 15:22:44 -0800 Subject: [PATCH 117/174] coding standards --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 78882342df..a0842ca678 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1400,7 +1400,7 @@ void Application::paintGL() { // Some LOD-like controls need to know a smoothly varying "potential" frame rate that doesn't // include time waiting for sync, and which can report a number above target if we've got the headroom. // In my tests, the following is mostly less than 0.5ms, and never more than 3ms. I don't think its worth measuring during runtime. - static const float paintWaitAndQTTimerAllowance = 0.001; // seconds + const float paintWaitAndQTTimerAllowance = 0.001f; // seconds // Store both values now for use by next cycle. _lastInstantaneousFps = instantaneousFps; _lastUnsynchronizedFps = 1.0f / (((usecTimestampNow() - now) / (float)USECS_PER_SECOND) + paintWaitAndQTTimerAllowance); From ad0865171b53ca9030cf6875ae8afced602a2b39 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 15:52:30 -0800 Subject: [PATCH 118/174] Fix unused variable in scriptFinished --- interface/src/Application.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 740b0062f0..d648537155 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4347,10 +4347,12 @@ void Application::scriptFinished(const QString& scriptName, ScriptEngine* engine } } } - postLambdaEvent([this, scriptName]() { - _runningScriptsWidget->scriptStopped(scriptName); - _runningScriptsWidget->setRunningScripts(getRunningScripts()); - }); + if (removed) { + postLambdaEvent([this, scriptName]() { + _runningScriptsWidget->scriptStopped(scriptName); + _runningScriptsWidget->setRunningScripts(getRunningScripts()); + }); + } } void Application::stopAllScripts(bool restart) { From acb43e18d0a2c6b18b71c2081dd331a10fcfb68e Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 9 Dec 2015 15:54:49 -0800 Subject: [PATCH 119/174] coding standards --- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h | 2 +- .../src/display-plugins/openvr/OpenVrDisplayPlugin.h | 2 +- plugins/oculus/src/OculusDisplayPlugin.h | 2 +- plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 59c0e4e759..e3633b5fe8 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -9,7 +9,7 @@ #include "WindowOpenGLDisplayPlugin.h" -#define TARGET_FRAMERATE_Basic2DWindowOpenGL 60.0f +const float TARGET_FRAMERATE_Basic2DWindowOpenGL = 60.0f; class QScreen; class QAction; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h index 2b51c53d58..d07add7ea5 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -14,7 +14,7 @@ #include "../WindowOpenGLDisplayPlugin.h" -#define TARGET_RATE_OpenVr 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only. +const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only. class OpenVrDisplayPlugin : public WindowOpenGLDisplayPlugin { public: diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index 071dca0258..03c9ba7511 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -12,7 +12,7 @@ struct SwapFramebufferWrapper; using SwapFboPtr = QSharedPointer; -#define TARGET_RATE_Oculus 75.0f; +const float TARGET_RATE_Oculus = 75.0f; class OculusDisplayPlugin : public OculusBaseDisplayPlugin { public: diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index 7fe721fc45..d3e68585df 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -13,7 +13,7 @@ #include -#define TARGET_RATE_OculusLegacy 75.0f; +const float TARGET_RATE_OculusLegacy = 75.0f; class OculusLegacyDisplayPlugin : public WindowOpenGLDisplayPlugin { public: From 3b372fd897aa9b4c011216037201c6c35ff92491 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 9 Dec 2015 16:12:34 -0800 Subject: [PATCH 120/174] coding standards --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 9139a9dcc9..5beadffb1e 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -83,17 +83,16 @@ void Basic2DWindowOpenGLDisplayPlugin::internalPresent() { } WindowOpenGLDisplayPlugin::internalPresent(); } -#define THROTTLED_FRAMERATE 15 +const uint32_t THROTTLED_FRAMERATE = 15; int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const { static const int ULIMIITED_PAINT_TIMER_DELAY_MS = 1; int result = ULIMIITED_PAINT_TIMER_DELAY_MS; - // This test wouldn't be necessary if we could depend on updateFramerate setting _framerateTarget. - // Alas, that gets complicated: isThrottled() is const and other stuff depends on it. - if (_isThrottled) { - result = MSECS_PER_SECOND / THROTTLED_FRAMERATE; - } if (0 != _framerateTarget) { result = MSECS_PER_SECOND / _framerateTarget; + } else if (_isThrottled) { + // This test wouldn't be necessary if we could depend on updateFramerate setting _framerateTarget. + // Alas, that gets complicated: isThrottled() is const and other stuff depends on it. + result = MSECS_PER_SECOND / THROTTLED_FRAMERATE; } qDebug() << "New interval " << result; @@ -135,7 +134,7 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { _framerateTarget = 30; } } else if (_isThrottled) { - _framerateTarget = (float) THROTTLED_FRAMERATE; + _framerateTarget = THROTTLED_FRAMERATE; } int newInterval = getDesiredInterval(); From 978d39b7f4f29a8db11c6fff19021d12da0b8e3f Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 18 Nov 2015 15:20:29 -0800 Subject: [PATCH 121/174] Moving OpenVR to external plugin and updating to latest version --- cmake/externals/openvr/CMakeLists.txt | 5 +- .../src/display-plugins/DisplayPlugin.cpp | 12 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 9 +- .../src/display-plugins/OpenGLDisplayPlugin.h | 2 +- libraries/input-plugins/CMakeLists.txt | 12 +- .../src/input-plugins/InputPlugin.cpp | 2 - libraries/script-engine/src/ScriptEngine.cpp | 2 +- plugins/openvr/CMakeLists.txt | 25 +++++ .../openvr/src}/OpenVrDisplayPlugin.cpp | 103 +++++++++--------- .../openvr/src}/OpenVrDisplayPlugin.h | 11 +- .../openvr/src}/OpenVrHelpers.cpp | 25 ++--- .../openvr/src}/OpenVrHelpers.h | 5 - plugins/openvr/src/OpenVrProvider.cpp | 60 ++++++++++ .../openvr/src}/ViveControllerManager.cpp | 27 ++--- .../openvr/src}/ViveControllerManager.h | 2 +- plugins/openvr/src/plugin.json | 1 + 16 files changed, 175 insertions(+), 128 deletions(-) create mode 100644 plugins/openvr/CMakeLists.txt rename {libraries/display-plugins/src/display-plugins/openvr => plugins/openvr/src}/OpenVrDisplayPlugin.cpp (65%) rename {libraries/display-plugins/src/display-plugins/openvr => plugins/openvr/src}/OpenVrDisplayPlugin.h (84%) rename {libraries/display-plugins/src/display-plugins/openvr => plugins/openvr/src}/OpenVrHelpers.cpp (80%) rename {libraries/display-plugins/src/display-plugins/openvr => plugins/openvr/src}/OpenVrHelpers.h (89%) create mode 100644 plugins/openvr/src/OpenVrProvider.cpp rename {libraries/input-plugins/src/input-plugins => plugins/openvr/src}/ViveControllerManager.cpp (97%) rename {libraries/input-plugins/src/input-plugins => plugins/openvr/src}/ViveControllerManager.h (98%) create mode 100644 plugins/openvr/src/plugin.json diff --git a/cmake/externals/openvr/CMakeLists.txt b/cmake/externals/openvr/CMakeLists.txt index f9d0ef5a71..9ef95b17da 100644 --- a/cmake/externals/openvr/CMakeLists.txt +++ b/cmake/externals/openvr/CMakeLists.txt @@ -7,9 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) ExternalProject_Add( ${EXTERNAL_NAME} - #URL https://github.com/ValveSoftware/openvr/archive/0.9.1.zip - URL http://hifi-public.s3.amazonaws.com/dependencies/openvr-0.9.1.zip - URL_MD5 f986f5a6815e9454c53c5bf58ce02fdc + URL https://github.com/ValveSoftware/openvr/archive/v0.9.12.zip + URL_MD5 c08dced68ce4e341e1467e6814ae419d CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp index 6c34612e8c..08368597d0 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp @@ -14,8 +14,6 @@ #include "stereo/InterleavedStereoDisplayPlugin.h" #include "Basic2DWindowOpenGLDisplayPlugin.h" -#include "openvr/OpenVrDisplayPlugin.h" - const QString& DisplayPlugin::MENU_PATH() { static const QString value = "Display"; return value; @@ -25,22 +23,14 @@ const QString& DisplayPlugin::MENU_PATH() { DisplayPluginList getDisplayPlugins() { DisplayPlugin* PLUGIN_POOL[] = { new Basic2DWindowOpenGLDisplayPlugin(), - new NullDisplayPlugin(), #ifdef DEBUG + new NullDisplayPlugin(), #endif - // Stereo modes - // SBS left/right new SideBySideStereoDisplayPlugin(), // Interleaved left/right new InterleavedStereoDisplayPlugin(), - - // HMDs -//#ifdef Q_OS_WIN -// // SteamVR SDK -// new OpenVrDisplayPlugin(), -//#endif nullptr }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 80710e9b96..db7acf8bf1 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -103,8 +104,12 @@ public: // take the latest texture and present it _context->makeCurrent(); - currentPlugin->present(); - _context->doneCurrent(); + if (QOpenGLContext::currentContext() == _context->contextHandle()) { + _activePlugin->present(); + _context->doneCurrent(); + } else { + qWarning() << "Makecurrent failed"; + } } _context->makeCurrent(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 88ccddc125..72211056d9 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -74,7 +74,7 @@ protected: ProgramPtr _program; ShapeWrapperPtr _plane; - Mutex _mutex; + mutable Mutex _mutex; SimpleMovingAverage _usecsPerFrame { 10 }; QMap _sceneTextureToFrameIndexMap; diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 0e21d4a40c..b81554511d 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,15 +1,5 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins controllers script-engine render-utils) +link_hifi_libraries(shared plugins controllers) GroupSources("src/input-plugins") - -if (WIN32) - add_dependency_external_projects(OpenVR) - find_package(OpenVR REQUIRED) - target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS}) - target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES}) -endif() - -target_sdl2() -target_sixense() diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index 6db35572b5..4b79572a07 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -15,7 +15,6 @@ #include "KeyboardMouseDevice.h" #include "SDL2Manager.h" #include "SixenseManager.h" -#include "ViveControllerManager.h" // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class InputPluginList getInputPlugins() { @@ -23,7 +22,6 @@ InputPluginList getInputPlugins() { new KeyboardMouseDevice(), new SDL2Manager(), new SixenseManager(), - new ViveControllerManager(), nullptr }; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 3306659c80..a075b0a91d 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); diff --git a/plugins/openvr/CMakeLists.txt b/plugins/openvr/CMakeLists.txt new file mode 100644 index 0000000000..e7fab5903d --- /dev/null +++ b/plugins/openvr/CMakeLists.txt @@ -0,0 +1,25 @@ +# +# Created by Bradley Austin Davis on 2015/11/18 +# 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 +# + +if (WIN32) + # we're using static GLEW, so define GLEW_STATIC + add_definitions(-DGLEW_STATIC) + set(TARGET_NAME openvr) + setup_hifi_plugin(OpenGL Script Qml Widgets) + link_hifi_libraries(shared gl networking controllers + plugins display-plugins input-plugins script-engine + render-utils model gpu render model-networking fbx) + + include_hifi_library_headers(octree) + + add_dependency_external_projects(OpenVR) + find_package(OpenVR REQUIRED) + target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS}) + target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES}) + +endif() \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp similarity index 65% rename from libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp rename to plugins/openvr/src/OpenVrDisplayPlugin.cpp index 68a711a847..58f7536856 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -7,24 +7,23 @@ // #include "OpenVrDisplayPlugin.h" -#if defined(Q_OS_WIN) - #include #include +#include #include -#include #include #include +#include +#include + #include #include #include #include "OpenVrHelpers.h" -#include "GLMHelpers.h" -#include Q_DECLARE_LOGGING_CATEGORY(displayplugins) Q_LOGGING_CATEGORY(displayplugins, "hifi.displayplugins") @@ -41,12 +40,11 @@ vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; static mat4 _sensorResetMat; static uvec2 _windowSize; -static ivec2 _windowPosition; static uvec2 _renderTargetSize; struct PerEyeData { - uvec2 _viewportOrigin; - uvec2 _viewportSize; + //uvec2 _viewportOrigin; + //uvec2 _viewportSize; mat4 _projectionMatrix; mat4 _eyeOffset; mat4 _pose; @@ -89,36 +87,17 @@ void OpenVrDisplayPlugin::activate() { } Q_ASSERT(_hmd); - _hmd->GetWindowBounds(&_windowPosition.x, &_windowPosition.y, &_windowSize.x, &_windowSize.y); _hmd->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y); // Recommended render target size is per-eye, so double the X size for // left + right eyes _renderTargetSize.x *= 2; openvr_for_each_eye([&](vr::Hmd_Eye eye) { PerEyeData& eyeData = _eyesData[eye]; - _hmd->GetEyeOutputViewport(eye, - &eyeData._viewportOrigin.x, &eyeData._viewportOrigin.y, - &eyeData._viewportSize.x, &eyeData._viewportSize.y); eyeData._projectionMatrix = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL)); eyeData._eyeOffset = toGlm(_hmd->GetEyeToHeadTransform(eye)); }); - - - vr::HmdError eError = vr::HmdError_None; - _compositor = (vr::IVRCompositor*)vr::VR_GetGenericInterface(vr::IVRCompositor_Version, &eError); - Q_ASSERT(eError == vr::HmdError_None); + _compositor = vr::VRCompositor(); Q_ASSERT(_compositor); - - _compositor->SetGraphicsDevice(vr::Compositor_DeviceType_OpenGL, NULL); - - uint32_t unSize = _compositor->GetLastError(NULL, 0); - if (unSize > 1) { - char* buffer = new char[unSize]; - _compositor->GetLastError(buffer, unSize); - printf("Compositor - %s\n", buffer); - delete[] buffer; - } - Q_ASSERT(unSize <= 1); WindowOpenGLDisplayPlugin::activate(); } @@ -132,6 +111,16 @@ void OpenVrDisplayPlugin::deactivate() { WindowOpenGLDisplayPlugin::deactivate(); } +void OpenVrDisplayPlugin::customizeContext() { + static std::once_flag once; + std::call_once(once, []{ + glewExperimental = true; + GLenum err = glewInit(); + glGetError(); + }); + WindowOpenGLDisplayPlugin::customizeContext(); +} + uvec2 OpenVrDisplayPlugin::getRecommendedRenderSize() const { return _renderTargetSize; } @@ -153,33 +142,41 @@ glm::mat4 OpenVrDisplayPlugin::getEyeToHeadTransform(Eye eye) const { } glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const { - return _trackedDevicePoseMat4[0]; + glm::mat4 result; + { + Lock lock(_mutex); + result = _trackedDevicePoseMat4[0]; + + } + return result; } -void OpenVrDisplayPlugin::customizeContext() { - WindowOpenGLDisplayPlugin::customizeContext(); + +void OpenVrDisplayPlugin::submitSceneTexture(uint32_t frameIndex, uint32_t sceneTexture, const glm::uvec2& sceneSize) { + WindowOpenGLDisplayPlugin::submitSceneTexture(frameIndex, sceneTexture, sceneSize); } -//void OpenVrDisplayPlugin::display(uint32_t frameIndex, uint32_t finalTexture, const glm::uvec2& sceneSize) { -// // Flip y-axis since GL UV coords are backwards. -// static vr::Compositor_TextureBounds leftBounds{ 0, 1, 0.5f, 0 }; -// static vr::Compositor_TextureBounds rightBounds{ 0.5f, 1, 1, 0 }; -// _compositor->Submit(vr::Eye_Left, (void*)finalTexture, &leftBounds); -// _compositor->Submit(vr::Eye_Right, (void*)finalTexture, &rightBounds); -// glFinish(); -//} - -//void OpenVrDisplayPlugin::finishFrame() { -//// swapBuffers(); -// doneCurrent(); -// _compositor->WaitGetPoses(_trackedDevicePose, vr::k_unMaxTrackedDeviceCount); -// for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { -// _trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking); -// } -// openvr_for_each_eye([&](vr::Hmd_Eye eye) { -// _eyesData[eye]._pose = _trackedDevicePoseMat4[0]; -// }); -//}; - -#endif +void OpenVrDisplayPlugin::internalPresent() { + // Flip y-axis since GL UV coords are backwards. + static vr::VRTextureBounds_t leftBounds{ 0, 0, 0.5f, 1 }; + static vr::VRTextureBounds_t rightBounds{ 0.5f, 0, 1, 1 }; + vr::Texture_t texture{ (void*)_currentSceneTexture, vr::API_OpenGL, vr::ColorSpace_Auto }; + { + Lock lock(_mutex); + _compositor->Submit(vr::Eye_Left, &texture, &leftBounds); + _compositor->Submit(vr::Eye_Right, &texture, &rightBounds); + } + glFinish(); + { + Lock lock(_mutex); + _compositor->WaitGetPoses(_trackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0); + for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { + _trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking); + } + openvr_for_each_eye([&](vr::Hmd_Eye eye) { + _eyesData[eye]._pose = _trackedDevicePoseMat4[0]; + }); + } + //WindowOpenGLDisplayPlugin::internalPresent(); +} diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h similarity index 84% rename from libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h rename to plugins/openvr/src/OpenVrDisplayPlugin.h index c8887276b7..4b5639d52b 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -9,10 +9,9 @@ #include -#if defined(Q_OS_WIN) #include -#include "../WindowOpenGLDisplayPlugin.h" +#include class OpenVrDisplayPlugin : public WindowOpenGLDisplayPlugin { public: @@ -23,6 +22,8 @@ public: virtual void activate() override; virtual void deactivate() override; + virtual void customizeContext() override; + virtual glm::uvec2 getRecommendedRenderSize() const override; virtual glm::uvec2 getRecommendedUiSize() const override { return uvec2(1920, 1080); } @@ -32,15 +33,13 @@ public: virtual glm::mat4 getEyeToHeadTransform(Eye eye) const override; virtual glm::mat4 getHeadPose(uint32_t frameIndex) const override; + virtual void submitSceneTexture(uint32_t frameIndex, uint32_t sceneTexture, const glm::uvec2& sceneSize) override; protected: -// virtual void display(uint32_t frameIndex, uint32_t finalTexture, const glm::uvec2& sceneSize) override; - virtual void customizeContext() override; + virtual void internalPresent() override; private: vr::IVRSystem* _hmd { nullptr }; static const QString NAME; }; -#endif - diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp similarity index 80% rename from libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.cpp rename to plugins/openvr/src/OpenVrHelpers.cpp index f8e810beaf..7020fcb40d 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -7,14 +7,15 @@ // #include "OpenVrHelpers.h" -#if defined(Q_OS_WIN) - -#include - #include #include -#include "../Logging.h" +#include +#include +#include + + +Q_DECLARE_LOGGING_CATEGORY(displayplugins) using Mutex = std::mutex; using Lock = std::unique_lock; @@ -30,13 +31,13 @@ vr::IVRSystem* acquireOpenVrSystem() { if (hmdPresent) { Lock lock(mutex); if (!activeHmd) { - qCDebug(displayPlugins) << "openvr: No vr::IVRSystem instance active, building"; - vr::HmdError eError = vr::HmdError_None; + qCDebug(displayplugins) << "openvr: No vr::IVRSystem instance active, building"; + vr::EVRInitError eError = vr::VRInitError_None; activeHmd = vr::VR_Init(&eError); - qCDebug(displayPlugins) << "openvr display: HMD is " << activeHmd << " error is " << eError; + qCDebug(displayplugins) << "openvr display: HMD is " << activeHmd << " error is " << eError; } if (activeHmd) { - qCDebug(displayPlugins) << "openvr: incrementing refcount"; + qCDebug(displayplugins) << "openvr: incrementing refcount"; ++refCount; } } @@ -46,10 +47,10 @@ vr::IVRSystem* acquireOpenVrSystem() { void releaseOpenVrSystem() { if (activeHmd) { Lock lock(mutex); - qDebug() << "openvr: decrementing refcount"; + qCDebug(displayplugins) << "openvr: decrementing refcount"; --refCount; if (0 == refCount) { - qDebug() << "openvr: zero refcount, deallocate VR system"; + qCDebug(displayplugins) << "openvr: zero refcount, deallocate VR system"; // Avoid spamming the VR system with activate/deactivate calls at system startup by // putting in a delay before we destory the shutdown the VR subsystem @@ -71,5 +72,3 @@ void releaseOpenVrSystem() { } } } - -#endif diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h b/plugins/openvr/src/OpenVrHelpers.h similarity index 89% rename from libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h rename to plugins/openvr/src/OpenVrHelpers.h index 3e445d90ba..513e1702d2 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h +++ b/plugins/openvr/src/OpenVrHelpers.h @@ -7,9 +7,6 @@ // #pragma once -#include - -#if defined(Q_OS_WIN) #include #include #include @@ -18,5 +15,3 @@ vr::IVRSystem* acquireOpenVrSystem(); void releaseOpenVrSystem(); -#endif - diff --git a/plugins/openvr/src/OpenVrProvider.cpp b/plugins/openvr/src/OpenVrProvider.cpp new file mode 100644 index 0000000000..66227a9543 --- /dev/null +++ b/plugins/openvr/src/OpenVrProvider.cpp @@ -0,0 +1,60 @@ +// +// Created by Bradley Austin Davis on 2015/10/25 +// 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 + +#include +#include +#include + +#include + +#include "OpenVrDisplayPlugin.h" +#include "ViveControllerManager.h" + +class OpenVrProvider : public QObject, public DisplayProvider, InputProvider +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID DisplayProvider_iid FILE "plugin.json") + Q_INTERFACES(DisplayProvider) + Q_PLUGIN_METADATA(IID InputProvider_iid FILE "plugin.json") + Q_INTERFACES(InputProvider) + +public: + OpenVrProvider(QObject* parent = nullptr) : QObject(parent) {} + virtual ~OpenVrProvider() {} + + virtual DisplayPluginList getDisplayPlugins() override { + static std::once_flag once; + std::call_once(once, [&] { + DisplayPluginPointer plugin(new OpenVrDisplayPlugin()); + if (plugin->isSupported()) { + _displayPlugins.push_back(plugin); + } + }); + return _displayPlugins; + } + + virtual InputPluginList getInputPlugins() override { + static std::once_flag once; + std::call_once(once, [&] { + InputPluginPointer plugin(new ViveControllerManager()); + if (plugin->isSupported()) { + _inputPlugins.push_back(plugin); + } + }); + return _inputPlugins; + } + + +private: + DisplayPluginList _displayPlugins; + InputPluginList _inputPlugins; +}; + +#include "OpenVrProvider.moc" diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp similarity index 97% rename from libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp rename to plugins/openvr/src/ViveControllerManager.cpp index 5315152cea..39056cd46f 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -26,10 +25,10 @@ #include -#ifdef Q_OS_WIN +#include "OpenVrHelpers.h" + extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; extern mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; -#endif vr::IVRSystem* acquireOpenVrSystem(); void releaseOpenVrSystem(); @@ -39,7 +38,7 @@ static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, CONTROLLER_LENGTH_OFFSET / 2.0f, CONTROLLER_LENGTH_OFFSET * 2.0f); -static const QString CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b"; +static const char* CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b"; static const QString MENU_PARENT = "Avatar"; static const QString MENU_NAME = "Vive Controllers"; @@ -49,19 +48,14 @@ static const QString RENDER_CONTROLLERS = "Render Hand Controllers"; const QString ViveControllerManager::NAME = "OpenVR"; bool ViveControllerManager::isSupported() const { -#ifdef Q_OS_WIN auto hmd = acquireOpenVrSystem(); bool success = hmd != nullptr; releaseOpenVrSystem(); return success; -#else - return false; -#endif } void ViveControllerManager::activate() { InputPlugin::activate(); -#ifdef Q_OS_WIN _container->addMenu(MENU_PATH); _container->addMenuItem(PluginType::INPUT_PLUGIN, MENU_PATH, RENDER_CONTROLLERS, [this] (bool clicked) { this->setRenderControllers(clicked); }, @@ -72,8 +66,11 @@ void ViveControllerManager::activate() { } Q_ASSERT(_hmd); + auto renderModels = vr::VRRenderModels(); + vr::RenderModel_t model; - if (!_hmd->LoadRenderModel(CONTROLLER_MODEL_STRING.toStdString().c_str(), &model)) { + /* + if (!_hmd->LoadRenderModel(CONTROLLER_MODEL_STRING, &model)) { qDebug() << QString("Unable to load render model %1\n").arg(CONTROLLER_MODEL_STRING); } else { model::Mesh* mesh = new model::Mesh(); @@ -118,7 +115,7 @@ void ViveControllerManager::activate() { _modelLoaded = true; _renderControllers = true; } -#endif + */ // unregister with UserInputMapper auto userInputMapper = DependencyManager::get(); @@ -129,7 +126,6 @@ void ViveControllerManager::activate() { void ViveControllerManager::deactivate() { InputPlugin::deactivate(); -#ifdef Q_OS_WIN _container->removeMenuItem(MENU_NAME, RENDER_CONTROLLERS); _container->removeMenu(MENU_PATH); @@ -139,7 +135,6 @@ void ViveControllerManager::deactivate() { } _inputDevice->_poseStateMap.clear(); -#endif // unregister with UserInputMapper auto userInputMapper = DependencyManager::get(); @@ -225,7 +220,6 @@ void ViveControllerManager::pluginUpdate(float deltaTime, bool jointsCaptured) { } void ViveControllerManager::InputDevice::update(float deltaTime, bool jointsCaptured) { -#ifdef Q_OS_WIN _poseStateMap.clear(); _buttonPressedMap.clear(); @@ -276,7 +270,6 @@ void ViveControllerManager::InputDevice::update(float deltaTime, bool jointsCapt } _trackedControllers = numTrackedControllers; -#endif } void ViveControllerManager::InputDevice::focusOutEvent() { @@ -286,7 +279,6 @@ void ViveControllerManager::InputDevice::focusOutEvent() { // These functions do translation from the Steam IDs to the standard controller IDs void ViveControllerManager::InputDevice::handleAxisEvent(uint32_t axis, float x, float y, bool left) { -#ifdef Q_OS_WIN //FIX ME? It enters here every frame: probably we want to enter only if an event occurs axis += vr::k_EButton_Axis0; using namespace controller; @@ -296,12 +288,10 @@ void ViveControllerManager::InputDevice::handleAxisEvent(uint32_t axis, float x, } else if (axis == vr::k_EButton_SteamVR_Trigger) { _axisStateMap[left ? LT : RT] = x; } -#endif } // These functions do translation from the Steam IDs to the standard controller IDs void ViveControllerManager::InputDevice::handleButtonEvent(uint32_t button, bool pressed, bool left) { -#ifdef Q_OS_WIN if (!pressed) { return; } @@ -319,7 +309,6 @@ void ViveControllerManager::InputDevice::handleButtonEvent(uint32_t button, bool //FIX ME: not able to ovrewrite the behaviour of this button _buttonPressedMap.insert(left ? controller::LEFT_SECONDARY_THUMB : controller::RIGHT_SECONDARY_THUMB); } -#endif } void ViveControllerManager::InputDevice::handlePoseEvent(const mat4& mat, bool left) { diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h similarity index 98% rename from libraries/input-plugins/src/input-plugins/ViveControllerManager.h rename to plugins/openvr/src/ViveControllerManager.h index 02bdecb10a..077aec7fc3 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -20,7 +20,7 @@ #include #include #include -#include "InputPlugin.h" +#include #include #include diff --git a/plugins/openvr/src/plugin.json b/plugins/openvr/src/plugin.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/plugins/openvr/src/plugin.json @@ -0,0 +1 @@ +{} From 9eb40bcd651bcc21a505905aa860827a4689e4bf Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 9 Dec 2015 16:58:14 -0800 Subject: [PATCH 122/174] Trying to redner the collision geometry correctly but still an issue with the bounding box i get --- libraries/model/src/model/Geometry.cpp | 4 +-- libraries/model/src/model/Geometry.h | 4 +-- .../render-utils/src/MeshPartPayload.cpp | 30 ++++++++++++++----- libraries/render-utils/src/MeshPartPayload.h | 5 ++-- libraries/render-utils/src/Model.cpp | 12 +++++--- libraries/render-utils/src/ModelRender.cpp | 2 ++ 6 files changed, 40 insertions(+), 17 deletions(-) diff --git a/libraries/model/src/model/Geometry.cpp b/libraries/model/src/model/Geometry.cpp index 63adeec0f1..df86ba2a8f 100755 --- a/libraries/model/src/model/Geometry.cpp +++ b/libraries/model/src/model/Geometry.cpp @@ -92,7 +92,7 @@ void Mesh::setPartBuffer(const BufferView& buffer) { _partBuffer = buffer; } -const Box Mesh::evalPartBound(int partNum) const { +Box Mesh::evalPartBound(int partNum) const { Box box; if (partNum < _partBuffer.getNum()) { const Part& part = _partBuffer.get(partNum); @@ -111,7 +111,7 @@ const Box Mesh::evalPartBound(int partNum) const { return box; } -const Box Mesh::evalPartBounds(int partStart, int partEnd, Boxes& bounds) const { +Box Mesh::evalPartBounds(int partStart, int partEnd, Boxes& bounds) const { Box totalBound; auto part = _partBuffer.cbegin() + partStart; auto partItEnd = _partBuffer.cbegin() + partEnd; diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h index 8b5f448a64..a35d55d938 100755 --- a/libraries/model/src/model/Geometry.h +++ b/libraries/model/src/model/Geometry.h @@ -107,10 +107,10 @@ public: uint getNumParts() const { return _partBuffer.getNumElements(); } // evaluate the bounding box of A part - const Box evalPartBound(int partNum) const; + Box evalPartBound(int partNum) const; // evaluate the bounding boxes of the parts in the range [start, end[ and fill the bounds parameter // the returned box is the bounding box of ALL the evaluated part bounds. - const Box evalPartBounds(int partStart, int partEnd, Boxes& bounds) const; + Box evalPartBounds(int partStart, int partEnd, Boxes& bounds) const; static gpu::Primitive topologyToPrimitive(Topology topo) { return static_cast(topo); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 3aee6cb62c..b3e27ff558 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -40,7 +40,7 @@ namespace render { using namespace render; MeshPartPayload::MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, - glm::vec3 position, glm::quat orientation, bool applyMeshJoints) : + glm::vec3 position, glm::quat orientation, bool isCollisionGeometry) : model(model), _drawMesh(drawMesh), meshIndex(meshIndex), @@ -48,7 +48,7 @@ MeshPartPayload::MeshPartPayload(Model* model, model::MeshPointer drawMesh, int _shapeID(shapeIndex), _modelPosition(position), _modelOrientation(orientation), - _applyMeshJoints(applyMeshJoints) { + _isCollisionGeometry(isCollisionGeometry) { initCache(); } @@ -58,9 +58,13 @@ void MeshPartPayload::initCache() { _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); - const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); - const FBXMesh& mesh = geometry.meshes.at(meshIndex); - _isBlendShaped = !mesh.blendshapes.isEmpty(); + if (!_isCollisionGeometry) { + const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); + const FBXMesh& mesh = geometry.meshes.at(meshIndex); + _isBlendShaped = !mesh.blendshapes.isEmpty(); + } else { + _isBlendShaped = false; + } _drawPart = _drawMesh->getPartBuffer().get(partIndex); } @@ -106,7 +110,19 @@ render::ItemKey MeshPartPayload::getKey() const { render::Item::Bound MeshPartPayload::getBound() const { // NOTE: we can't cache this bounds because we need to handle the case of a moving // entity or mesh part. - return model->getPartBounds(meshIndex, partIndex, _modelPosition, _modelOrientation); + if (_isCollisionGeometry) { + if (_drawMesh && _drawBound.isNull()) { + _drawBound = _drawMesh->evalPartBound(partIndex); + } + // If we not skinned use the bounds of the subMesh for all it's parts + const FBXMesh& mesh = model->_collisionGeometry->getFBXGeometry().meshes.at(meshIndex); + auto otherBound = model->calculateScaledOffsetExtents(mesh.meshExtents, _modelPosition, _modelOrientation); + + return model->getPartBounds(0, 0, _modelPosition, _modelOrientation); + + } else { + return model->getPartBounds(meshIndex, partIndex, _modelPosition, _modelOrientation); + } } void MeshPartPayload::drawCall(gpu::Batch& batch) const { @@ -220,7 +236,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio } void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const { - if (_applyMeshJoints) { + if (!_isCollisionGeometry) { // Still relying on the raw data from the model const Model::MeshState& state = model->_meshStates.at(meshIndex); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 867dd2d264..b810ad8acf 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -24,7 +24,7 @@ class Model; class MeshPartPayload { public: - MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation, bool applyMeshJoints = true); + MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation, bool isCollisionGeometry = false); typedef render::Payload Payload; typedef Payload::DataPointer Pointer; @@ -60,10 +60,11 @@ public: model::MeshPointer _drawMesh; model::Mesh::Part _drawPart; model::MaterialPointer _drawMaterial; + mutable model::Box _drawBound; bool _hasColorAttrib = false; bool _isSkinned = false; bool _isBlendShaped = false; - bool _applyMeshJoints = true; + bool _isCollisionGeometry = false; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 56c1f642b8..35d2702cc2 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1120,9 +1120,13 @@ AABox Model::getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition void Model::segregateMeshGroups() { QSharedPointer networkGeometry; bool showingCollisionHull = false; - if (_showCollisionHull && _collisionGeometry && _collisionGeometry->isLoaded()) { - networkGeometry = _collisionGeometry; - showingCollisionHull = true; + if (_showCollisionHull && _collisionGeometry) { + if (_collisionGeometry->isLoaded()) { + networkGeometry = _collisionGeometry; + showingCollisionHull = true; + } else { + return; + } } else { networkGeometry = _geometry; } @@ -1152,7 +1156,7 @@ void Model::segregateMeshGroups() { // Create the render payloads int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { - auto renderItem = std::make_shared(this, networkMesh._mesh, i, partIndex, shapeID, _translation, _rotation, !showingCollisionHull); + auto renderItem = std::make_shared(this, networkMesh._mesh, i, partIndex, shapeID, _translation, _rotation, showingCollisionHull); if (showingCollisionHull) { renderItem->updateDrawMaterial(ModelRender::getCollisionHullMaterial()); } diff --git a/libraries/render-utils/src/ModelRender.cpp b/libraries/render-utils/src/ModelRender.cpp index 1c4109b185..10c9d738d2 100644 --- a/libraries/render-utils/src/ModelRender.cpp +++ b/libraries/render-utils/src/ModelRender.cpp @@ -287,6 +287,8 @@ model::MaterialPointer ModelRender::getCollisionHullMaterial() { if (!_collisionHullMaterial) { _collisionHullMaterial = std::make_shared(); _collisionHullMaterial->setDiffuse(glm::vec3(1.0f, 0.5f, 0.0f)); + _collisionHullMaterial->setMetallic(0.02f); + _collisionHullMaterial->setGloss(1.0f); } return _collisionHullMaterial; } From b4c272aaa13c1f44beb2b6a9592e59171063aea3 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 9 Dec 2015 17:28:45 -0800 Subject: [PATCH 123/174] sam just left --- .../src/RenderableParticleEffectEntityItem.cpp | 11 +++++++---- libraries/script-engine/src/ScriptEngine.cpp | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 43c6373147..74c26c91d4 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -60,8 +60,7 @@ public: void setTexture(gpu::TexturePointer texture) { _texture = texture; } const gpu::TexturePointer& getTexture() const { return _texture; } - bool getVisibleFlag() const { return _visibleFlag; } - void setVisibleFlag(bool visibleFlag) { _visibleFlag = visibleFlag; } + bool getVisibleFlag() const { return _entity->isVisible(); } void render(RenderArgs* args) const { assert(_pipeline); @@ -91,7 +90,7 @@ protected: gpu::BufferPointer _vertexBuffer; gpu::BufferPointer _indexBuffer; gpu::TexturePointer _texture; - bool _visibleFlag = true; + }; namespace render { @@ -111,7 +110,11 @@ namespace render { template <> void payloadRender(const ParticlePayload::Pointer& payload, RenderArgs* args) { - payload->render(args); + if (args) { + if (payload && payload->getVisibleFlag()) { + payload->render(args); + } + } } } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 3306659c80..a075b0a91d 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 fd5fb3096f2eacaeddf98977be9caa06ab258c7b Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 8 Dec 2015 17:55:46 -0800 Subject: [PATCH 124/174] Disabling OpenVR plugin --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 2 +- plugins/openvr/CMakeLists.txt | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index db7acf8bf1..880e4a16b3 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -105,7 +105,7 @@ public: // take the latest texture and present it _context->makeCurrent(); if (QOpenGLContext::currentContext() == _context->contextHandle()) { - _activePlugin->present(); + currentPlugin->present(); _context->doneCurrent(); } else { qWarning() << "Makecurrent failed"; diff --git a/plugins/openvr/CMakeLists.txt b/plugins/openvr/CMakeLists.txt index e7fab5903d..c3c4771276 100644 --- a/plugins/openvr/CMakeLists.txt +++ b/plugins/openvr/CMakeLists.txt @@ -6,7 +6,10 @@ # See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html # -if (WIN32) +# OpenVR is disabled until a) it works with threaded present and +# b) it doesn't interfere with Oculus SDK 0.8 +if (FALSE) +#if (WIN32) # we're using static GLEW, so define GLEW_STATIC add_definitions(-DGLEW_STATIC) set(TARGET_NAME openvr) @@ -21,5 +24,4 @@ if (WIN32) find_package(OpenVR REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES}) - -endif() \ No newline at end of file +endif() From 1644bda9080983237524dea8d5db6636976af1aa Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 8 Dec 2015 14:21:14 -0800 Subject: [PATCH 125/174] Migrate to latest Oculus SDK (0.8) --- cmake/externals/LibOVR/CMakeLists.txt | 11 ++- .../oculus/src/OculusBaseDisplayPlugin.cpp | 71 ++++++++++--------- plugins/oculus/src/OculusBaseDisplayPlugin.h | 8 +-- plugins/oculus/src/OculusDisplayPlugin.cpp | 51 ++++++------- 4 files changed, 70 insertions(+), 71 deletions(-) diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt index 8d13882d48..a98745b404 100644 --- a/cmake/externals/LibOVR/CMakeLists.txt +++ b/cmake/externals/LibOVR/CMakeLists.txt @@ -15,17 +15,16 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) # 0.6 public # URL http://static.oculus.com/sdk-downloads/0.6.0.1/Public/1435190862/ovr_sdk_win_0.6.0.1.zip # URL_MD5 4b3ef825f9a1d6d3035c9f6820687da9 -# 0.7 alpha -# URL https://s3.amazonaws.com/static.oculus.com/sdk-downloads/0.7.0.0/Public/Alpha/ovr_sdk_win_0.7.0.0_RC1.zip -# URL_MD5 a562bb9d117087b2cf9d86653ea70fd8 - +# 0.8 public +# URL http://static.oculus.com/sdk-downloads/0.8.0.0/Public/1445451746/ovr_sdk_win_0.8.0.0.zip +# URL_MD5 54944b03b95149d6010f84eb701b9647 if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://static.oculus.com/sdk-downloads/0.6.0.1/Public/1435190862/ovr_sdk_win_0.6.0.1.zip - URL_MD5 4b3ef825f9a1d6d3035c9f6820687da9 + URL http://static.oculus.com/sdk-downloads/0.8.0.0/Public/1445451746/ovr_sdk_win_0.8.0.0.zip + URL_MD5 54944b03b95149d6010f84eb701b9647 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index 7c057c7152..d6811c3529 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -20,9 +20,7 @@ glm::mat4 OculusBaseDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseP } void OculusBaseDisplayPlugin::resetSensors() { -#if (OVR_MAJOR_VERSION >= 6) - ovr_RecenterPose(_hmd); -#endif + ovr_RecenterPose(_session); } glm::mat4 OculusBaseDisplayPlugin::getEyeToHeadTransform(Eye eye) const { @@ -30,27 +28,39 @@ glm::mat4 OculusBaseDisplayPlugin::getEyeToHeadTransform(Eye eye) const { } glm::mat4 OculusBaseDisplayPlugin::getHeadPose(uint32_t frameIndex) const { -#if (OVR_MAJOR_VERSION >= 6) - auto frameTiming = ovr_GetFrameTiming(_hmd, frameIndex); - auto trackingState = ovr_GetTrackingState(_hmd, frameTiming.DisplayMidpointSeconds); + static uint32_t lastFrameSeen = 0; + auto displayTime = ovr_GetPredictedDisplayTime(_session, frameIndex); + auto trackingState = ovr_GetTrackingState(_session, displayTime, frameIndex > lastFrameSeen); + if (frameIndex > lastFrameSeen) { + lastFrameSeen = frameIndex; + } return toGlm(trackingState.HeadPose.ThePose); -#endif } bool OculusBaseDisplayPlugin::isSupported() const { -#if (OVR_MAJOR_VERSION >= 6) if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { return false; } - bool result = false; - if (ovrHmd_Detect() > 0) { - result = true; + + ovrSession session { nullptr }; + ovrGraphicsLuid luid; + auto result = ovr_Create(&session, &luid); + if (!OVR_SUCCESS(result)) { + ovrErrorInfo error; + ovr_GetLastErrorInfo(&error); + ovr_Shutdown(); + return false; } + + auto hmdDesc = ovr_GetHmdDesc(session); + if (hmdDesc.Type == ovrHmd_None) { + ovr_Destroy(session); + ovr_Shutdown(); + return false; + } + ovr_Shutdown(); - return result; -#else - return false; -#endif + return true; } // DLL based display plugins MUST initialize GLEW inside the DLL code. @@ -69,28 +79,22 @@ void OculusBaseDisplayPlugin::deinit() { void OculusBaseDisplayPlugin::activate() { WindowOpenGLDisplayPlugin::activate(); -#if (OVR_MAJOR_VERSION >= 6) if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { qFatal("Could not init OVR"); } -#if (OVR_MAJOR_VERSION == 6) - if (!OVR_SUCCESS(ovr_Create(0, &_hmd))) { -#elif (OVR_MAJOR_VERSION == 7) - if (!OVR_SUCCESS(ovr_Create(&_hmd, &_luid))) { -#endif - Q_ASSERT(false); + if (!OVR_SUCCESS(ovr_Create(&_session, &_luid))) { qFatal("Failed to acquire HMD"); } - _hmdDesc = ovr_GetHmdDesc(_hmd); + _hmdDesc = ovr_GetHmdDesc(_session); - _ipd = ovr_GetFloat(_hmd, OVR_KEY_IPD, _ipd); + _ipd = ovr_GetFloat(_session, OVR_KEY_IPD, _ipd); glm::uvec2 eyeSizes[2]; ovr_for_each_eye([&](ovrEyeType eye) { _eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye]; - ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_hmd, eye, _eyeFovs[eye]); + ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_session, eye, _eyeFovs[eye]); ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); _eyeProjections[eye] = toGlm(ovrPerspectiveProjection); @@ -100,7 +104,7 @@ void OculusBaseDisplayPlugin::activate() { _compositeEyeProjections[eye] = toGlm(ovrPerspectiveProjection); _eyeOffsets[eye] = erd.HmdToEyeViewOffset; - eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f)); + eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f)); }); ovrFovPort combined = _eyeFovs[Left]; combined.LeftTan = std::max(_eyeFovs[Left].LeftTan, _eyeFovs[Right].LeftTan); @@ -115,34 +119,33 @@ void OculusBaseDisplayPlugin::activate() { eyeSizes[0].x + eyeSizes[1].x, std::max(eyeSizes[0].y, eyeSizes[1].y)); - if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd, + if (!OVR_SUCCESS(ovr_ConfigureTracking(_session, ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { qFatal("Could not attach to sensor device"); } - // Parent class relies on our _hmd intialization, so it must come after that. + // Parent class relies on our _session intialization, so it must come after that. memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov)); _sceneLayer.Header.Type = ovrLayerType_EyeFov; _sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; ovr_for_each_eye([&](ovrEyeType eye) { ovrFovPort & fov = _sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov; - ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_hmd, eye, fov, 1.0f); + ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_session, eye, fov, 1.0f); _sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 }; }); - if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd, + if (!OVR_SUCCESS(ovr_ConfigureTracking(_session, ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { qFatal("Could not attach to sensor device"); } -#endif } void OculusBaseDisplayPlugin::deactivate() { WindowOpenGLDisplayPlugin::deactivate(); #if (OVR_MAJOR_VERSION >= 6) - ovr_Destroy(_hmd); - _hmd = nullptr; + ovr_Destroy(_session); + _session = nullptr; ovr_Shutdown(); #endif } @@ -151,7 +154,7 @@ void OculusBaseDisplayPlugin::deactivate() { float OculusBaseDisplayPlugin::getIPD() const { float result = OVR_DEFAULT_IPD; #if (OVR_MAJOR_VERSION >= 6) - result = ovr_GetFloat(_hmd, OVR_KEY_IPD, result); + result = ovr_GetFloat(_session, OVR_KEY_IPD, result); #endif return result; } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 711be6aa5e..1a26c6958b 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -43,17 +43,13 @@ protected: mat4 _compositeEyeProjections[2]; uvec2 _desiredFramebufferSize; -#if (OVR_MAJOR_VERSION >= 6) - ovrHmd _hmd; + ovrSession _session; + ovrGraphicsLuid _luid; float _ipd{ OVR_DEFAULT_IPD }; ovrEyeRenderDesc _eyeRenderDescs[2]; ovrFovPort _eyeFovs[2]; ovrHmdDesc _hmdDesc; ovrLayerEyeFov _sceneLayer; -#endif -#if (OVR_MAJOR_VERSION == 7) - ovrGraphicsLuid _luid; -#endif }; #if (OVR_MAJOR_VERSION == 6) diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index e6eae2cf02..c8fb0ba080 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -23,12 +23,16 @@ // ovr_CreateMirrorTextureGL, etc template struct RiftFramebufferWrapper : public FramebufferWrapper { - ovrHmd hmd; - RiftFramebufferWrapper(const ovrHmd & hmd) : hmd(hmd) { + ovrSession session; + RiftFramebufferWrapper(const ovrSession& session) : session(session) { color = 0; depth = 0; }; + ~RiftFramebufferWrapper() { + destroyColor(); + } + void Resize(const uvec2 & size) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo)); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); @@ -39,6 +43,9 @@ struct RiftFramebufferWrapper : public FramebufferWrapper { } protected: + virtual void destroyColor() { + } + virtual void initDepth() override final { } }; @@ -53,12 +60,6 @@ struct SwapFramebufferWrapper : public RiftFramebufferWrapperCurrentIndex; @@ -66,13 +67,17 @@ struct SwapFramebufferWrapper : public RiftFramebufferWrapper { MirrorFramebufferWrapper(const ovrHmd & hmd) : RiftFramebufferWrapper(hmd) { } - virtual ~MirrorFramebufferWrapper() { +private: + virtual void destroyColor() override { if (color) { - ovr_DestroyMirrorTexture(hmd, (ovrTexture*)color); + ovr_DestroyMirrorTexture(session, (ovrTexture*)color); color = nullptr; } } -private: void initColor() override { - if (color) { - ovr_DestroyMirrorTexture(hmd, (ovrTexture*)color); - color = nullptr; - } - ovrResult result = ovr_CreateMirrorTextureGL(hmd, GL_RGBA, size.x, size.y, (ovrTexture**)&color); + destroyColor(); + ovrResult result = ovr_CreateMirrorTextureGL(session, GL_SRGB8_ALPHA8, size.x, size.y, (ovrTexture**)&color); Q_ASSERT(OVR_SUCCESS(result)); } @@ -154,8 +156,7 @@ void OculusDisplayPlugin::activate() { void OculusDisplayPlugin::customizeContext() { OculusBaseDisplayPlugin::customizeContext(); -#if (OVR_MAJOR_VERSION >= 6) - _sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd)); + _sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_session)); _sceneFbo->Init(getRecommendedRenderSize()); // We're rendering both eyes to the same texture, so only one of the @@ -163,7 +164,7 @@ void OculusDisplayPlugin::customizeContext() { _sceneLayer.ColorTexture[0] = _sceneFbo->color; // not needed since the structure was zeroed on init, but explicit _sceneLayer.ColorTexture[1] = nullptr; -#endif + enableVsync(false); // Only enable mirroring if we know vsync is disabled _enablePreview = !isVsyncEnabled(); @@ -177,7 +178,6 @@ void OculusDisplayPlugin::uncustomizeContext() { } void OculusDisplayPlugin::internalPresent() { -#if (OVR_MAJOR_VERSION >= 6) if (!_currentSceneTexture) { return; } @@ -206,8 +206,10 @@ void OculusDisplayPlugin::internalPresent() { auto size = _sceneFbo->size; Context::Viewport(size.x, size.y); glBindTexture(GL_TEXTURE_2D, _currentSceneTexture); + //glEnable(GL_FRAMEBUFFER_SRGB); GLenum err = glGetError(); drawUnitQuad(); + //glDisable(GL_FRAMEBUFFER_SRGB); }); uint32_t frameIndex { 0 }; @@ -230,13 +232,12 @@ void OculusDisplayPlugin::internalPresent() { viewScaleDesc.HmdToEyeViewOffset[1] = _eyeOffsets[1]; ovrLayerHeader* layers = &_sceneLayer.Header; - ovrResult result = ovr_SubmitFrame(_hmd, frameIndex, &viewScaleDesc, &layers, 1); + ovrResult result = ovr_SubmitFrame(_session, frameIndex, &viewScaleDesc, &layers, 1); if (!OVR_SUCCESS(result)) { qDebug() << result; } } _sceneFbo->Increment(); -#endif /* The swapbuffer call here is only required if we want to mirror the content to the screen. From e9f529bf12d300050892eae9f16b5de81ca14d9c Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 9 Dec 2015 17:59:56 -0800 Subject: [PATCH 126/174] Entities: Removed Start Automatically property from Animation Group There is an issue when startAutomatically was set to true and animationPlaying was set to false. This would cause clients to play the animation when they connected to the entity server, even though the server was not. --- examples/html/entityProperties.html | 9 ------- .../entities/src/AnimationPropertyGroup.cpp | 26 ------------------- .../entities/src/AnimationPropertyGroup.h | 1 - .../entities/src/EntityItemProperties.cpp | 1 - libraries/entities/src/ModelEntityItem.cpp | 5 ---- libraries/entities/src/ModelEntityItem.h | 3 --- .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 1 + 8 files changed, 2 insertions(+), 46 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 186b2ee828..ff72e95313 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -298,7 +298,6 @@ var elModelAnimationLastFrame = document.getElementById("property-model-animation-last-frame"); var elModelAnimationLoop = document.getElementById("property-model-animation-loop"); var elModelAnimationHold = document.getElementById("property-model-animation-hold"); - var elModelAnimationStartAutomatically = document.getElementById("property-model-animation-start-automatically"); var elModelTextures = document.getElementById("property-model-textures"); var elModelOriginalTextures = document.getElementById("property-model-original-textures"); @@ -532,7 +531,6 @@ elModelAnimationLastFrame.value = properties.animation.lastFrame; elModelAnimationLoop.checked = properties.animation.loop; elModelAnimationHold.checked = properties.animation.hold; - elModelAnimationStartAutomatically.checked = properties.animation.startAutomatically; elModelTextures.value = properties.textures; elModelOriginalTextures.value = properties.originalTextures; } else if (properties.type == "Web") { @@ -785,7 +783,6 @@ elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame')); elModelAnimationLoop.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'loop')); elModelAnimationHold.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'hold')); - elModelAnimationStartAutomatically.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'startAutomatically')); elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); @@ -1348,12 +1345,6 @@ -
- Animation Start Automatically - - - -
Textures
diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index f9d8c07443..ef89128e30 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -29,7 +29,6 @@ void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desire COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame, _animationLoop->getFirstFrame); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame, _animationLoop->getLastFrame); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold, _animationLoop->getHold); - COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_START_AUTOMATICALLY, Animation, animation, StartAutomatically, startAutomatically, _animationLoop->getStartAutomatically); } else { COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FPS, Animation, animation, FPS, fps); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame); @@ -38,7 +37,6 @@ void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desire COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); - COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_START_AUTOMATICALLY, Animation, animation, StartAutomatically, startAutomatically); } } @@ -58,7 +56,6 @@ void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, boo COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, firstFrame, float, _animationLoop->setFirstFrame); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, lastFrame, float, _animationLoop->setLastFrame); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, hold, bool, _animationLoop->setHold); - COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, startAutomatically, bool, _animationLoop->setStartAutomatically); // legacy property support COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFPS, float, _animationLoop->setFPS, _animationLoop->getFPS); @@ -73,7 +70,6 @@ void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, boo COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, firstFrame, float, setFirstFrame); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, lastFrame, float, setLastFrame); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, hold, bool, setHold); - COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, startAutomatically, bool, setStartAutomatically); // legacy property support COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFPS, float, setFPS, getFPS); @@ -95,7 +91,6 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { float lastFrame = _animationLoop ? _animationLoop->getLastFrame() : getLastFrame(); bool loop = _animationLoop ? _animationLoop->getLoop() : getLoop(); bool hold = _animationLoop ? _animationLoop->getHold() : getHold(); - bool startAutomatically = _animationLoop ? _animationLoop->getStartAutomatically() : getStartAutomatically(); QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); QJsonObject settingsAsJsonObject = settingsAsJson.object(); @@ -130,10 +125,6 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { running = settingsMap["hold"].toBool(); } - if (settingsMap.contains("startAutomatically")) { - running = settingsMap["startAutomatically"].toBool(); - } - if (_animationLoop) { _animationLoop->setFPS(fps); _animationLoop->setCurrentFrame(currentFrame); @@ -142,7 +133,6 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { _animationLoop->setLastFrame(lastFrame); _animationLoop->setLoop(loop); _animationLoop->setHold(hold); - _animationLoop->setStartAutomatically(startAutomatically); } else { setFPS(fps); setCurrentFrame(currentFrame); @@ -151,7 +141,6 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { setLastFrame(lastFrame); setLoop(loop); setHold(hold); - setStartAutomatically(startAutomatically); } } @@ -194,7 +183,6 @@ bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, _animationLoop->getFirstFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, _animationLoop->getLastFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, _animationLoop->getHold()); - APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, _animationLoop->getStartAutomatically()); } else { APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame()); @@ -203,7 +191,6 @@ bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, getFirstFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, getLastFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, getHold()); - APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, getStartAutomatically()); } return true; @@ -226,7 +213,6 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, _animationLoop->setFirstFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, _animationLoop->setLastFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, _animationLoop->setHold); - READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, _animationLoop->setStartAutomatically); } else { READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS); READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame); @@ -235,7 +221,6 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold); - READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, setStartAutomatically); } DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_URL, URL); @@ -246,7 +231,6 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FIRST_FRAME, FirstFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_LAST_FRAME, LastFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_HOLD, Hold); - DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_START_AUTOMATICALLY, StartAutomatically); processedBytes += bytesRead; @@ -273,7 +257,6 @@ EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FIRST_FRAME, firstFrame); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_LAST_FRAME, lastFrame); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_HOLD, hold); - CHECK_PROPERTY_CHANGE(PROP_ANIMATION_START_AUTOMATICALLY, startAutomatically); return changedProperties; } @@ -288,7 +271,6 @@ void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) con COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FirstFrame, _animationLoop->getFirstFrame); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, LastFrame, _animationLoop->getLastFrame); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Hold, _animationLoop->getHold); - COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, StartAutomatically, _animationLoop->getStartAutomatically); } else { COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FPS, getFPS); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, CurrentFrame, getCurrentFrame); @@ -297,7 +279,6 @@ void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) con COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FirstFrame, getFirstFrame); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, LastFrame, getLastFrame); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Hold, getHold); - COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, StartAutomatically, getStartAutomatically); } } @@ -313,7 +294,6 @@ bool AnimationPropertyGroup::setProperties(const EntityItemProperties& propertie SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FirstFrame, firstFrame, _animationLoop->setFirstFrame); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, LastFrame, lastFrame, _animationLoop->setLastFrame); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Hold, hold, _animationLoop->setHold); - SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, StartAutomatically, startAutomatically, _animationLoop->setStartAutomatically); } else { SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FPS, fps, setFPS); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, CurrentFrame, currentFrame, setCurrentFrame); @@ -322,7 +302,6 @@ bool AnimationPropertyGroup::setProperties(const EntityItemProperties& propertie SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FirstFrame, firstFrame, setFirstFrame); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, LastFrame, lastFrame, setLastFrame); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Hold, hold, setHold); - SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, StartAutomatically, startAutomatically, setStartAutomatically); } return somethingChanged; @@ -339,7 +318,6 @@ EntityPropertyFlags AnimationPropertyGroup::getEntityProperties(EncodeBitstreamP requestedProperties += PROP_ANIMATION_FIRST_FRAME; requestedProperties += PROP_ANIMATION_LAST_FRAME; requestedProperties += PROP_ANIMATION_HOLD; - requestedProperties += PROP_ANIMATION_START_AUTOMATICALLY; return requestedProperties; } @@ -363,7 +341,6 @@ void AnimationPropertyGroup::appendSubclassData(OctreePacketData* packetData, En APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, _animationLoop->getFirstFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, _animationLoop->getLastFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, _animationLoop->getHold()); - APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, _animationLoop->getStartAutomatically()); } else { APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame()); @@ -372,7 +349,6 @@ void AnimationPropertyGroup::appendSubclassData(OctreePacketData* packetData, En APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, getFirstFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, getLastFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, getHold()); - APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, getStartAutomatically()); } } @@ -395,7 +371,6 @@ int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, _animationLoop->setFirstFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, _animationLoop->setLastFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, _animationLoop->setHold); - READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, _animationLoop->setStartAutomatically); } else { READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS); READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame); @@ -404,7 +379,6 @@ int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold); - READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, setStartAutomatically); } return bytesRead; diff --git a/libraries/entities/src/AnimationPropertyGroup.h b/libraries/entities/src/AnimationPropertyGroup.h index 8c40b0c036..8e85d8bc99 100644 --- a/libraries/entities/src/AnimationPropertyGroup.h +++ b/libraries/entities/src/AnimationPropertyGroup.h @@ -80,7 +80,6 @@ public: DEFINE_PROPERTY(PROP_ANIMATION_FIRST_FRAME, FirstFrame, firstFrame, float, 0.0f); // was animationSettings.firstFrame DEFINE_PROPERTY(PROP_ANIMATION_LAST_FRAME, LastFrame, lastFrame, float, AnimationLoop::MAXIMUM_POSSIBLE_FRAME); // was animationSettings.lastFrame DEFINE_PROPERTY(PROP_ANIMATION_HOLD, Hold, hold, bool, false); // was animationSettings.hold - DEFINE_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, StartAutomatically, startAutomatically, bool, false); // was animationSettings.startAutomatically protected: void setFromOldAnimationSettings(const QString& value); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index d040f785da..2e785519da 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -747,7 +747,6 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); - ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_START_AUTOMATICALLY, Animation, animation, StartAutomatically, startAutomatically); ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_CENTER, Atmosphere, atmosphere, Center, center); ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_INNER_RADIUS, Atmosphere, atmosphere, InnerRadius, innerRadius); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index b0b0e7c76a..d96814ff04 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -384,11 +384,6 @@ void ModelEntityItem::setAnimationSettings(const QString& value) { setAnimationHold(hold); } - if (settingsMap.contains("startAutomatically")) { - bool startAutomatically = settingsMap["startAutomatically"].toBool(); - setAnimationStartAutomatically(startAutomatically); - } - _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; } diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index cbd54f7168..2b8121c2f6 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -97,9 +97,6 @@ public: void setAnimationHold(bool hold) { _animationLoop.setHold(hold); } bool getAnimationHold() const { return _animationLoop.getHold(); } - void setAnimationStartAutomatically(bool startAutomatically) { _animationLoop.setStartAutomatically(startAutomatically); } - bool getAnimationStartAutomatically() const { return _animationLoop.getStartAutomatically(); } - void setAnimationFirstFrame(float firstFrame) { _animationLoop.setFirstFrame(firstFrame); } float getAnimationFirstFrame() const { return _animationLoop.getFirstFrame(); } diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 93fbe7acdc..81aae796c1 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -41,7 +41,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityAdd: case PacketType::EntityEdit: case PacketType::EntityData: - return VERSION_ENTITIES_HAVE_PARENTS; + return VERSION_ENTITITES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP; case PacketType::AvatarData: case PacketType::BulkAvatarData: return 17; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index cd7b9a113c..ba48c4ccf1 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -161,5 +161,6 @@ const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS = 48; const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49; const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50; const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51; +const PacketVersion VERSION_ENTITITES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52; #endif // hifi_PacketHeaders_h From 9e99bff25016f0c2739d9ed2599b4ac701be845a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 9 Dec 2015 18:09:55 -0800 Subject: [PATCH 127/174] fix avatar upward drift after shape change --- libraries/physics/src/CharacterController.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index ba3a59f69d..44d4269e0e 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -80,9 +80,13 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) { if (world && _rigidBody) { _dynamicsWorld = world; _pendingFlags &= ~PENDING_FLAG_JUMP; + // Before adding the RigidBody to the world we must save its oldGravity to the side + // because adding an object to the world will overwrite it with the default gravity. + btVector3 oldGravity = _rigidBody->getGravity(); _dynamicsWorld->addRigidBody(_rigidBody, COLLISION_GROUP_MY_AVATAR, COLLISION_MASK_MY_AVATAR); _dynamicsWorld->addAction(this); - //reset(_dynamicsWorld); + // restore gravity settings + _rigidBody->setGravity(oldGravity); } } if (_dynamicsWorld) { From 4e93f3ae81d1320b00e702a11ea69569d2ccbae1 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 9 Dec 2015 18:26:13 -0800 Subject: [PATCH 128/174] respect visibility yay --- .../src/RenderableParticleEffectEntityItem.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 74c26c91d4..edbfb6158c 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -60,8 +60,6 @@ public: void setTexture(gpu::TexturePointer texture) { _texture = texture; } const gpu::TexturePointer& getTexture() const { return _texture; } - bool getVisibleFlag() const { return _entity->isVisible(); } - void render(RenderArgs* args) const { assert(_pipeline); @@ -80,23 +78,23 @@ public: auto numIndices = _indexBuffer->getSize() / sizeof(uint16_t); batch.drawIndexed(gpu::TRIANGLES, numIndices); } + + EntityItemPointer _entity; protected: - EntityItemPointer _entity; Transform _modelTransform; AABox _bound; gpu::PipelinePointer _pipeline; gpu::Stream::FormatPointer _vertexFormat; gpu::BufferPointer _vertexBuffer; gpu::BufferPointer _indexBuffer; - gpu::TexturePointer _texture; - + gpu::TexturePointer _texture; }; namespace render { template <> const ItemKey payloadGetKey(const ParticlePayload::Pointer& payload) { - if (payload->getVisibleFlag()) { + if (payload->_entity->getVisible()) { return ItemKey::Builder::transparentShape(); } else { return ItemKey::Builder().withInvisible().build(); @@ -110,11 +108,10 @@ namespace render { template <> void payloadRender(const ParticlePayload::Pointer& payload, RenderArgs* args) { - if (args) { - if (payload && payload->getVisibleFlag()) { - payload->render(args); - } + if (payload->_entity->getVisible()) { + payload->render(args); } + } } From 9ecb2b22770c25e421c80302b4b112c951ec9569 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 9 Dec 2015 18:27:45 -0800 Subject: [PATCH 129/174] uncomment sams change to scriptengine --- libraries/script-engine/src/ScriptEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index a075b0a91d..3306659c80 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 b16822ed8a8cfc303c3223188080013139e68610 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 9 Dec 2015 18:41:06 -0800 Subject: [PATCH 130/174] swap sound file --- examples/drylake/ratCreator.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index ecf19d66eb..f51052aea3 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -52,7 +52,7 @@ var RAT_IN_NEST_DISTANCE = 4; //how many milliseconds between rats var RAT_SPAWN_RATE = 2500; -var RAT_SOUND_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/sounds/rat2.wav'; +var RAT_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/Rats_Squeaks_Active.wav'; var ratRunningSound = SoundCache.getSound(RAT_SOUND_URL); function playRatRunningAnimation(rat) { @@ -61,7 +61,6 @@ function playRatRunningAnimation(rat) { }); Entities.editEntity(rat, { animationURL: RAT_RUNNING_ANIMATION_URL, - // animationSettings: animationSettings, animation: { url: RAT_RUNNING_ANIMATION_URL, running: true, @@ -257,7 +256,7 @@ function updateTweens() { function createRatSoundInjector() { var audioOptions = { volume: 0.05, - loop: true + loop: false } var injector = Audio.playSound(ratRunningSound, audioOptions); From 3499b452f81225bc5961abebebe52773107fa445 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 10 Dec 2015 09:02:13 -0800 Subject: [PATCH 131/174] add back SDL and Sixense --- libraries/input-plugins/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index b81554511d..af7cc3daa0 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -3,3 +3,6 @@ setup_hifi_library() link_hifi_libraries(shared plugins controllers) GroupSources("src/input-plugins") + +target_sdl2() +target_sixense() From d09f70239c435fba20eafd61f84b160d856d7afe Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 09:03:53 -0800 Subject: [PATCH 132/174] make entity-tree a global. change how network-requests to load model geometry are triggered --- interface/src/Application.cpp | 73 ++++--- interface/src/Application.h | 3 +- .../src/EntityTreeRenderer.h | 2 +- .../src/RenderableModelEntityItem.cpp | 187 ++++++++++-------- .../src/RenderableModelEntityItem.h | 4 +- libraries/entities/src/EntityItem.h | 2 + libraries/entities/src/EntityTree.cpp | 9 + libraries/entities/src/EntityTree.h | 3 + libraries/entities/src/ModelEntityItem.h | 7 +- libraries/entities/src/ZoneEntityItem.h | 2 +- 10 files changed, 170 insertions(+), 122 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a03cad62a..1b94c913db 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -352,6 +352,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(true, qApp, qApp); return true; } @@ -371,7 +372,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _frameCount(0), _fps(60.0f), _physicsEngine(new PhysicsEngine(Vectors::ZERO)), - _entities(true, this, this), _entityClipboardRenderer(false, this, this), _entityClipboard(new EntityTree()), _lastQueriedTime(usecTimestampNow()), @@ -864,7 +864,7 @@ void Application::cleanupBeforeQuit() { } _keyboardFocusHighlight = nullptr; - _entities.clear(); // this will allow entity scripts to properly shutdown + getEntities()->clear(); // this will allow entity scripts to properly shutdown auto nodeList = DependencyManager::get(); @@ -875,7 +875,7 @@ void Application::cleanupBeforeQuit() { // tell the packet receiver we're shutting down, so it can drop packets nodeList->getPacketReceiver().setShouldDropPackets(true); - _entities.shutdown(); // tell the entities system we're shutting down, so it will stop running scripts + getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts ScriptEngine::stopAllScripts(this); // stop all currently running global scripts // first stop all timers directly or by invokeMethod @@ -921,7 +921,7 @@ void Application::emptyLocalCache() { } Application::~Application() { - EntityTreePointer tree = _entities.getTree(); + EntityTreePointer tree = getEntities()->getTree(); tree->setSimulation(NULL); _octreeProcessor.terminate(); @@ -1995,7 +1995,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { event->buttons(), event->modifiers()); - _entities.mouseMoveEvent(&mappedEvent, deviceID); + getEntities()->mouseMoveEvent(&mappedEvent, deviceID); _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it @@ -2021,7 +2021,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { event->buttons(), event->modifiers()); if (!_aboutToQuit) { - _entities.mousePressEvent(&mappedEvent, deviceID); + getEntities()->mousePressEvent(&mappedEvent, deviceID); } _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts @@ -2066,7 +2066,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { event->buttons(), event->modifiers()); if (!_aboutToQuit) { - _entities.mouseReleaseEvent(&mappedEvent, deviceID); + getEntities()->mouseReleaseEvent(&mappedEvent, deviceID); } _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts @@ -2389,7 +2389,7 @@ void Application::calibrateEyeTracker5Points() { bool Application::exportEntities(const QString& filename, const QVector& entityIDs) { QVector entities; - auto entityTree = _entities.getTree(); + auto entityTree = getEntities()->getTree(); auto exportTree = std::make_shared(); exportTree->createRootElement(); @@ -2433,7 +2433,7 @@ bool Application::exportEntities(const QString& filename, const QVector entities; - _entities.getTree()->findEntities(AACube(glm::vec3(x, y, z), scale), entities); + getEntities()->getTree()->findEntities(AACube(glm::vec3(x, y, z), scale), entities); if (entities.size() > 0) { glm::vec3 root(x, y, z); @@ -2501,7 +2501,7 @@ bool Application::importEntities(const QString& urlOrFilename) { } QVector Application::pasteEntities(float x, float y, float z) { - return _entityClipboard->sendEntities(&_entityEditSender, _entities.getTree(), x, y, z); + return _entityClipboard->sendEntities(&_entityEditSender, getEntities()->getTree(), x, y, z); } void Application::initDisplay() { @@ -2540,13 +2540,13 @@ void Application::init() { // fire off an immediate domain-server check in now that settings are loaded DependencyManager::get()->sendDomainServerCheckIn(); - _entities.init(); - _entities.setViewFrustum(getViewFrustum()); + getEntities()->init(); + getEntities()->setViewFrustum(getViewFrustum()); ObjectMotionState::setShapeManager(&_shapeManager); _physicsEngine->init(); - EntityTreePointer tree = _entities.getTree(); + EntityTreePointer tree = getEntities()->getTree(); _entitySimulation.init(tree, _physicsEngine, &_entityEditSender); tree->setSimulation(&_entitySimulation); @@ -2554,11 +2554,11 @@ void Application::init() { // connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts connect(&_entitySimulation, &EntitySimulation::entityCollisionWithEntity, - &_entities, &EntityTreeRenderer::entityCollisionWithEntity); + getEntities(), &EntityTreeRenderer::entityCollisionWithEntity); // connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing // of events related clicking, hovering over, and entering entities - _entities.connectSignalsToSlots(entityScriptingInterface.data()); + getEntities()->connectSignalsToSlots(entityScriptingInterface.data()); _entityClipboardRenderer.init(); _entityClipboardRenderer.setViewFrustum(getViewFrustum()); @@ -2907,19 +2907,19 @@ void Application::update(float deltaTime) { _avatarUpdate->synchronousProcess(); - if (true || _physicsEnabled) { + if (_physicsEnabled) { PerformanceTimer perfTimer("physics"); static VectorOfMotionStates motionStates; _entitySimulation.getObjectsToDelete(motionStates); _physicsEngine->deleteObjects(motionStates); - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _entitySimulation.getObjectsToAdd(motionStates); _physicsEngine->addObjects(motionStates); }); - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _entitySimulation.getObjectsToChange(motionStates); VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates); _entitySimulation.setObjectsToChange(stillNeedChange); @@ -2937,12 +2937,12 @@ void Application::update(float deltaTime) { myAvatar->prepareForPhysicsSimulation(); - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _physicsEngine->stepSimulation(); }); if (_physicsEngine->hasOutgoingChanges()) { - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), _physicsEngine->getSessionID()); avatarManager->handleOutgoingChanges(_physicsEngine->getOutgoingChanges()); }); @@ -2957,9 +2957,9 @@ void Application::update(float deltaTime) { // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk // deadlock.) _entitySimulation.handleCollisionEvents(collisionEvents); - // NOTE: the _entities.update() call below will wait for lock + // NOTE: the getEntities()->update() call below will wait for lock // and will simulate entity motion (the EntityTree has been given an EntitySimulation). - _entities.update(); // update the models... + getEntities()->update(); // update the models... } myAvatar->harvestResultsFromPhysicsSimulation(); @@ -3781,7 +3781,7 @@ void Application::clearDomainOctreeDetails() { }); // reset the model renderer - _entities.clear(); + getEntities()->clear(); } void Application::domainChanged(const QString& domainHostname) { @@ -3903,7 +3903,7 @@ bool Application::nearbyEntitiesAreReadyForPhysics() { // Someone logs in close to the table. They receive information about the items on the table before they // receive information about the table. The items are very close to the avatar's capsule, so they become // activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet. - EntityTreePointer entityTree = _entities.getTree(); + EntityTreePointer entityTree = getEntities()->getTree(); if (!entityTree) { return false; } @@ -3916,6 +3916,9 @@ bool Application::nearbyEntitiesAreReadyForPhysics() { foreach (EntityItemPointer entity, entities) { if (!entity->isReadyToComputeShape()) { + static QString repeatedMessage = + LogHandler::getInstance().addRepeatedMessageRegex("Physics disabled until entity loads: .*"); + qCDebug(interfaceapp) << "Physics disabled until entity loads: " << entity->getID() << entity->getName(); return false; } } @@ -3967,11 +3970,21 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer }); }); - if (!_physicsEnabled && nearbyEntitiesAreReadyForPhysics()) { - // These stats packets are sent in between full sends of a scene. - // We keep physics disabled until we've recieved a full scene and everything near the avatar in that - // scene is ready to compute its collision shape. - _physicsEnabled = true; + if (!_physicsEnabled) { + if (nearbyEntitiesAreReadyForPhysics()) { + // These stats packets are sent in between full sends of a scene. + // We keep physics disabled until we've recieved a full scene and everything near the avatar in that + // scene is ready to compute its collision shape. + _physicsEnabled = true; + getMyAvatar()->updateMotionBehaviorFromMenu(); + } else { + auto characterController = getMyAvatar()->getCharacterController(); + if (characterController) { + // if we have a character controller, disable it here so the avatar doesn't get stuck due to + // a non-loading collision hull. + characterController->setEnabled(false); + } + } } return statsMessageLength; @@ -4034,7 +4047,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri // we can use the same ones from the application. auto entityScriptingInterface = DependencyManager::get(); entityScriptingInterface->setPacketSender(&_entityEditSender); - entityScriptingInterface->setEntityTree(_entities.getTree()); + entityScriptingInterface->setEntityTree(getEntities()->getTree()); // AvatarManager has some custom types AvatarManager::registerMetaTypes(scriptEngine); diff --git a/interface/src/Application.h b/interface/src/Application.h index 27df7835e6..3d033e3b02 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -136,7 +136,7 @@ public: const ViewFrustum* getDisplayViewFrustum() const; ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } - EntityTreeRenderer* getEntities() { return &_entities; } + EntityTreeRenderer* getEntities() { return DependencyManager::get().data(); } QUndoStack* getUndoStack() { return &_undoStack; } MainWindow* getWindow() { return _window; } EntityTreePointer getEntityClipboard() { return _entityClipboard; } @@ -451,7 +451,6 @@ private: PhysicalEntitySimulation _entitySimulation; PhysicsEnginePointer _physicsEngine; - EntityTreeRenderer _entities; EntityTreeRenderer _entityClipboardRenderer; EntityTreePointer _entityClipboard; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 9980b9d8b6..076fe26d6f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -30,7 +30,7 @@ class ZoneEntityItem; // Generic client side Octree renderer class. -class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService { +class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public Dependency { Q_OBJECT public: EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b0f155decf..8b6f5ab967 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -12,12 +12,14 @@ #include #include +#include #include #include #include #include #include +#include #include "EntityTreeRenderer.h" #include "EntitiesRendererLogging.h" @@ -44,6 +46,32 @@ RenderableModelEntityItem::~RenderableModelEntityItem() { } } +void RenderableModelEntityItem::setModelURL(const QString& url) { + auto& currentURL = getParsedModelURL(); + ModelEntityItem::setModelURL(url); + + if (currentURL != getParsedModelURL() || !_model) { + EntityTreePointer tree = getTree(); + if (tree) { + QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); + } + } +} + +void RenderableModelEntityItem::loader() { + _needsModelReload = true; + EntityTreeRenderer* renderer = DependencyManager::get().data(); + assert(renderer); + if (!_model || _needsModelReload) { + PerformanceTimer perfTimer("getModel"); + getModel(renderer); + } + if (_model) { + _model->setURL(getParsedModelURL()); + _model->setCollisionModelURL(QUrl(getCompoundShapeURL())); + } +} + void RenderableModelEntityItem::setDimensions(const glm::vec3& value) { _dimensionsInitialized = true; ModelEntityItem::setDimensions(value); @@ -253,6 +281,60 @@ void RenderableModelEntityItem::render(RenderArgs* args) { remapTextures(); + { + // float alpha = getLocalRenderAlpha(); + + if (!_model || _needsModelReload) { + // TODO: this getModel() appears to be about 3% of model render time. We should optimize + PerformanceTimer perfTimer("getModel"); + EntityTreeRenderer* renderer = static_cast(args->_renderer); + getModel(renderer); + } + + if (_model) { + // handle animations.. + if (hasAnimation()) { + if (!jointsMapped()) { + QStringList modelJointNames = _model->getJointNames(); + mapJoints(modelJointNames); + } + + if (jointsMapped()) { + bool newFrame; + QVector frameDataRotations; + QVector frameDataTranslations; + getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); + assert(frameDataRotations.size() == frameDataTranslations.size()); + if (newFrame) { + for (int i = 0; i < frameDataRotations.size(); i++) { + _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); + } + } + } + } + + bool movingOrAnimating = isMoving() || isAnimatingSomething(); + if ((movingOrAnimating || + _needsInitialSimulation || + _model->getTranslation() != getPosition() || + _model->getRotation() != getRotation() || + _model->getRegistrationPoint() != getRegistrationPoint()) + && _model->isActive() && _dimensionsInitialized) { + _model->setScaleToFit(true, getDimensions()); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + + // make sure to simulate so everything gets set up correctly for rendering + { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + + _needsInitialSimulation = false; + } + } + } } else { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); gpu::Batch& batch = *args->_batch; @@ -264,7 +346,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { Model* result = NULL; - + if (!renderer) { return result; } @@ -286,7 +368,8 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { // if we have a previously allocated model, but its URL doesn't match // then we need to let our renderer update our model for us. - if (_model && QUrl(getModelURL()) != _model->getURL()) { + if (_model && (QUrl(getModelURL()) != _model->getURL() || + QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) { result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL()); _needsInitialSimulation = true; } else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one @@ -295,6 +378,12 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } else { // we already have the model we want... result = _model; } + + if (_model && _needsInitialSimulation) { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + _needsInitialSimulation = false; } else { // if our desired URL is empty, we may need to delete our existing model if (_model) { _myRenderer->releaseModel(_model); @@ -307,35 +396,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } bool RenderableModelEntityItem::needsToCallUpdate() const { - if (!_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate()) { - return true; - } - - if (!_dimensionsInitialized && _model && _model->isActive()) { - return true; - } - - if (_myRenderer && (!_model || _needsModelReload)) { - return true; - } - - if (_model) { - if (hasAnimation() || jointsMapped()) { - return true; - } - - bool movingOrAnimating = isMoving() || isAnimatingSomething(); - if ((movingOrAnimating || - _needsInitialSimulation || - _model->getTranslation() != getPosition() || - _model->getRotation() != getRotation() || - _model->getRegistrationPoint() != getRegistrationPoint()) - && _model->isActive() && _dimensionsInitialized) { - return true; - } - } - - return false; + return !_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate(); } void RenderableModelEntityItem::update(const quint64& now) { @@ -351,56 +412,6 @@ void RenderableModelEntityItem::update(const quint64& now) { Q_ARG(EntityItemProperties, properties)); } - if (_myRenderer && (!_model || _needsModelReload)) { - // TODO: this getModel() appears to be about 3% of model render time. We should optimize - PerformanceTimer perfTimer("getModel"); - getModel(_myRenderer); - } - - if (_model) { - // handle animations.. - if (hasAnimation()) { - if (!jointsMapped()) { - QStringList modelJointNames = _model->getJointNames(); - mapJoints(modelJointNames); - } - - if (jointsMapped()) { - bool newFrame; - QVector frameDataRotations; - QVector frameDataTranslations; - getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); - assert(frameDataRotations.size() == frameDataTranslations.size()); - if (newFrame) { - for (int i = 0; i < frameDataRotations.size(); i++) { - _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); - } - } - } - } - - bool movingOrAnimating = isMoving() || isAnimatingSomething(); - if ((movingOrAnimating || - _needsInitialSimulation || - _model->getTranslation() != getPosition() || - _model->getRotation() != getRotation() || - _model->getRegistrationPoint() != getRegistrationPoint()) - && _model->isActive() && _dimensionsInitialized) { - _model->setScaleToFit(true, getDimensions()); - _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); - - // make sure to simulate so everything gets set up correctly for rendering - { - PerformanceTimer perfTimer("_model->simulate"); - _model->simulate(0.0f); - } - - _needsInitialSimulation = false; - } - } - ModelEntityItem::update(now); } @@ -427,17 +438,27 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori } void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) { + auto currentCompoundShapeURL = getCompoundShapeURL(); ModelEntityItem::setCompoundShapeURL(url); - if (_model) { - _model->setCollisionModelURL(QUrl(url)); + + if (getCompoundShapeURL() != currentCompoundShapeURL || !_model) { + EntityTreePointer tree = getTree(); + if (tree) { + QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); + } } } bool RenderableModelEntityItem::isReadyToComputeShape() { ShapeType type = getShapeType(); + if (type == SHAPE_TYPE_COMPOUND) { if (!_model) { + EntityTreePointer tree = getTree(); + if (tree) { + QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); + } return false; // hmm... } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 3f3fe11633..45d5f43683 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -29,7 +29,8 @@ public: virtual ~RenderableModelEntityItem(); virtual void setDimensions(const glm::vec3& value) override; - + virtual void setModelURL(const QString& url); + virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -72,6 +73,7 @@ public: virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; void locationChanged(); + virtual void loader() override; private: void remapTextures(); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 69d642fad1..a1fc89c5e0 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -382,6 +382,8 @@ public: virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); } + virtual void loader() {} // called indirectly when urls for geometry are updated + protected: const QByteArray getActionDataInternal() const; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index abad1e5cd1..7688d034d0 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1266,3 +1266,12 @@ void EntityTree::trackIncomingEntityLastEdited(quint64 lastEditedTime, int bytes } } } + + +void EntityTree::callLoader(EntityItemID entityID) { + // this is used to bounce from the networking thread to the main thread + EntityItemPointer entity = findEntityByEntityItemID(entityID); + if (entity) { + entity->loader(); + } +} diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 064c106b91..e893c69259 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -235,6 +235,9 @@ public: return _deletedEntityItemIDs.contains(id); } +public slots: + void callLoader(EntityItemID entityID); + signals: void deletingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index cbd54f7168..310e741fda 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -74,11 +74,10 @@ public: _color[GREEN_INDEX] = value.green; _color[BLUE_INDEX] = value.blue; } - - // model related properties - void setModelURL(const QString& url) { _modelURL = url; _parsedModelURL = QUrl(url); } - virtual void setCompoundShapeURL(const QString& url); + // model related properties + virtual void setModelURL(const QString& url) { _modelURL = url; _parsedModelURL = QUrl(url); } + virtual void setCompoundShapeURL(const QString& url); // Animation related items... const AnimationPropertyGroup& getAnimationProperties() const { return _animationProperties; } diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index bf323248c0..19206f8acc 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -57,7 +57,7 @@ public: static bool getDrawZoneBoundaries() { return _drawZoneBoundaries; } static void setDrawZoneBoundaries(bool value) { _drawZoneBoundaries = value; } - virtual bool isReadyToComputeShape() { return false; } + virtual bool isReadyToComputeShape() { return true; } void updateShapeType(ShapeType type) { _shapeType = type; } virtual ShapeType getShapeType() const; From d731875c5b8ac454115255bb266e6cb3ab4e36e2 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 10 Dec 2015 09:58:53 -0800 Subject: [PATCH 133/174] Fix dependencies for Linux builds. --- libraries/input-plugins/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index af7cc3daa0..101a6c8016 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins controllers) +link_hifi_libraries(shared plugins controllers script-engine) GroupSources("src/input-plugins") From dd011e8bc4c72ecb9578666f7d369bba0793cb00 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 10 Dec 2015 10:05:01 -0800 Subject: [PATCH 134/174] Freakin' xcode ^S. --- libraries/input-plugins/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 101a6c8016..d2cf96c7f8 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins controllers script-engine) +link_hifi_libraries(shared plugins controllers script-engine) GroupSources("src/input-plugins") From 5053fcd11320530ce893bc581c96f74ebde90aee Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 10 Dec 2015 10:19:13 -0800 Subject: [PATCH 135/174] Fix unix builds --- libraries/input-plugins/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index af7cc3daa0..d2cf96c7f8 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins controllers) +link_hifi_libraries(shared plugins controllers script-engine) GroupSources("src/input-plugins") From b4ef2b4a088ea6e19cd4d3b1e3d8c20b9c00da5f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 10:27:31 -0800 Subject: [PATCH 136/174] quiet some logging --- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 6c450e0735..8fcc50931d 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -95,7 +95,6 @@ int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const { result = MSECS_PER_SECOND / _framerateTarget; } - qDebug() << "New interval " << result; return result; } @@ -136,8 +135,6 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { } } - int newInterval = getDesiredInterval(); - qDebug() << newInterval; _timer.start(getDesiredInterval()); } From d243132b5c9049b196539952ded60bf4a8dd9f4f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 10:28:24 -0800 Subject: [PATCH 137/174] quiet some logging --- libraries/networking/src/ResourceCache.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 84af87f217..e5771401b9 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -319,10 +319,10 @@ void Resource::attemptRequest() { void Resource::finishedLoading(bool success) { if (success) { - qDebug().noquote() << "Finished loading:" << _url.toDisplayString(); + qCDebug(networking).noquote() << "Finished loading:" << _url.toDisplayString(); _loaded = true; } else { - qDebug().noquote() << "Failed to load:" << _url.toDisplayString(); + qCDebug(networking).noquote() << "Failed to load:" << _url.toDisplayString(); _failedToLoad = true; } _loadPriorities.clear(); @@ -339,13 +339,13 @@ void Resource::makeRequest() { _request = ResourceManager::createResourceRequest(this, _activeUrl); if (!_request) { - qDebug().noquote() << "Failed to get request for" << _url.toDisplayString(); + qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString(); ResourceCache::requestCompleted(this); finishedLoading(false); return; } - qDebug().noquote() << "Starting request for:" << _url.toDisplayString(); + qCDebug(networking).noquote() << "Starting request for:" << _url.toDisplayString(); connect(_request, &ResourceRequest::progress, this, &Resource::handleDownloadProgress); connect(_request, &ResourceRequest::finished, this, &Resource::handleReplyFinished); @@ -369,7 +369,7 @@ void Resource::handleReplyFinished() { if (result == ResourceRequest::Success) { _data = _request->getData(); auto extraInfo = _url == _activeUrl ? "" : QString(", %1").arg(_activeUrl.toDisplayString()); - qDebug().noquote() << QString("Request finished for %1%2").arg(_url.toDisplayString(), extraInfo); + qCDebug(networking).noquote() << QString("Request finished for %1%2").arg(_url.toDisplayString(), extraInfo); finishedLoading(true); emit loaded(_data); @@ -377,7 +377,7 @@ void Resource::handleReplyFinished() { } else { switch (result) { case ResourceRequest::Result::Timeout: { - qDebug() << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal; + qCDebug(networking) << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal; // Fall through to other cases } case ResourceRequest::Result::ServerUnavailable: { @@ -386,7 +386,7 @@ void Resource::handleReplyFinished() { const int BASE_DELAY_MS = 1000; if (_attempts++ < MAX_ATTEMPTS) { auto waitTime = BASE_DELAY_MS * (int)pow(2.0, _attempts); - qDebug().nospace() << "Retrying to load the asset in " << waitTime + qCDebug(networking).nospace() << "Retrying to load the asset in " << waitTime << "ms, attempt " << _attempts << " of " << MAX_ATTEMPTS; QTimer::singleShot(waitTime, this, &Resource::attemptRequest); break; @@ -394,7 +394,7 @@ void Resource::handleReplyFinished() { // fall through to final failure } default: { - qDebug() << "Error loading " << _url; + qCDebug(networking) << "Error loading " << _url; auto error = (result == ResourceRequest::Timeout) ? QNetworkReply::TimeoutError : QNetworkReply::UnknownNetworkError; emit failed(error); From 2dd40beed5817358421163cd34c8f50d911299f5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 10:42:25 -0800 Subject: [PATCH 138/174] formatting --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 8b6f5ab967..3709c0b9ad 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -453,7 +453,6 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { ShapeType type = getShapeType(); if (type == SHAPE_TYPE_COMPOUND) { - if (!_model) { EntityTreePointer tree = getTree(); if (tree) { From 645695d5d546676d8963a9e3aa685c984923afcf Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 18 Nov 2015 15:20:29 -0800 Subject: [PATCH 139/174] Moving sixense to external plugin --- .../ControllerScriptingInterface.cpp | 3 -- interface/src/ui/ApplicationCompositor.cpp | 1 - interface/src/ui/PreferencesDialog.cpp | 1 - libraries/input-plugins/CMakeLists.txt | 1 - .../src/input-plugins/InputPlugin.cpp | 2 - plugins/hifiSixense/CMakeLists.txt | 12 +++++ .../hifiSixense/src}/SixenseManager.cpp | 6 ++- .../hifiSixense/src}/SixenseManager.h | 2 +- plugins/hifiSixense/src/SixenseProvider.cpp | 45 +++++++++++++++++++ .../hifiSixense/src}/SixenseSupportOSX.cpp | 3 +- plugins/hifiSixense/src/plugin.json | 1 + 11 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 plugins/hifiSixense/CMakeLists.txt rename {libraries/input-plugins/src/input-plugins => plugins/hifiSixense/src}/SixenseManager.cpp (99%) rename {libraries/input-plugins/src/input-plugins => plugins/hifiSixense/src}/SixenseManager.h (99%) create mode 100644 plugins/hifiSixense/src/SixenseProvider.cpp rename {libraries/input-plugins/src/input-plugins => plugins/hifiSixense/src}/SixenseSupportOSX.cpp (99%) create mode 100644 plugins/hifiSixense/src/plugin.json diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 11053154b6..3bcf8bb311 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -20,9 +20,6 @@ #include "Application.h" #include "devices/MotionTracker.h" -// TODO: this needs to be removed, as well as any related controller-specific information -#include - void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) { if (event->type() == HFActionEvent::startType()) { emit actionStartEvent(static_cast(*event)); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 4cee190a47..f4dbdd3bc0 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -26,7 +26,6 @@ #include "Tooltip.h" #include "Application.h" -#include // TODO: any references to sixense should be removed here #include diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a25f868172..9a995263cd 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -16,7 +16,6 @@ #include #include #include -#include // TODO: This should be replaced with InputDevice/InputPlugin, or something similar #include #include "Application.h" diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index d2cf96c7f8..592f1fcc84 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -5,4 +5,3 @@ link_hifi_libraries(shared plugins controllers script-engine) GroupSources("src/input-plugins") target_sdl2() -target_sixense() diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index 4b79572a07..d226797e95 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -14,14 +14,12 @@ #include "KeyboardMouseDevice.h" #include "SDL2Manager.h" -#include "SixenseManager.h" // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class InputPluginList getInputPlugins() { InputPlugin* PLUGIN_POOL[] = { new KeyboardMouseDevice(), new SDL2Manager(), - new SixenseManager(), nullptr }; diff --git a/plugins/hifiSixense/CMakeLists.txt b/plugins/hifiSixense/CMakeLists.txt new file mode 100644 index 0000000000..c790f6f14d --- /dev/null +++ b/plugins/hifiSixense/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Created by Bradley Austin Davis on 2015/11/18 +# 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 +# + +set(TARGET_NAME hifiSixense) +setup_hifi_plugin(Script Qml Widgets) +link_hifi_libraries(shared controllers plugins input-plugins) +target_sixense() diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/plugins/hifiSixense/src/SixenseManager.cpp similarity index 99% rename from libraries/input-plugins/src/input-plugins/SixenseManager.cpp rename to plugins/hifiSixense/src/SixenseManager.cpp index 3b08c218a2..93329d768e 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/plugins/hifiSixense/src/SixenseManager.cpp @@ -27,9 +27,11 @@ #include #include #include -#include -#include "InputPluginsLogging.h" +#include + +Q_DECLARE_LOGGING_CATEGORY(inputplugins) +Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") static const unsigned int BUTTON_0 = 1U << 0; // the skinny button between 1 and 2 static const unsigned int BUTTON_1 = 1U << 5; diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/plugins/hifiSixense/src/SixenseManager.h similarity index 99% rename from libraries/input-plugins/src/input-plugins/SixenseManager.h rename to plugins/hifiSixense/src/SixenseManager.h index b6bf4b24c0..5cd4dc2451 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/plugins/hifiSixense/src/SixenseManager.h @@ -17,7 +17,7 @@ #include #include -#include "InputPlugin.h" +#include struct _sixenseControllerData; using SixenseControllerData = _sixenseControllerData; diff --git a/plugins/hifiSixense/src/SixenseProvider.cpp b/plugins/hifiSixense/src/SixenseProvider.cpp new file mode 100644 index 0000000000..2958e47848 --- /dev/null +++ b/plugins/hifiSixense/src/SixenseProvider.cpp @@ -0,0 +1,45 @@ +// +// Created by Bradley Austin Davis on 2015/10/25 +// 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 + +#include +#include +#include + +#include +#include + +#include "SixenseManager.h" + +class SixenseProvider : public QObject, public InputProvider +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID InputProvider_iid FILE "plugin.json") + Q_INTERFACES(InputProvider) + +public: + SixenseProvider(QObject* parent = nullptr) : QObject(parent) {} + virtual ~SixenseProvider() {} + + virtual InputPluginList getInputPlugins() override { + static std::once_flag once; + std::call_once(once, [&] { + InputPluginPointer plugin(new SixenseManager()); + if (plugin->isSupported()) { + _inputPlugins.push_back(plugin); + } + }); + return _inputPlugins; + } + +private: + InputPluginList _inputPlugins; +}; + +#include "SixenseProvider.moc" diff --git a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp b/plugins/hifiSixense/src/SixenseSupportOSX.cpp similarity index 99% rename from libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp rename to plugins/hifiSixense/src/SixenseSupportOSX.cpp index f6cec5d67f..85e0f3fe48 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp +++ b/plugins/hifiSixense/src/SixenseSupportOSX.cpp @@ -17,8 +17,7 @@ #include #include - -#include "InputPluginsLogging.h" +#include #ifndef SIXENSE_LIB_FILENAME #define SIXENSE_LIB_FILENAME QCoreApplication::applicationDirPath() + "/../Frameworks/libsixense_x64" diff --git a/plugins/hifiSixense/src/plugin.json b/plugins/hifiSixense/src/plugin.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/plugins/hifiSixense/src/plugin.json @@ -0,0 +1 @@ +{} From 6f29d9e7b8ac889fbd47aaba9aa4225a75366a12 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 8 Dec 2015 17:30:26 -0800 Subject: [PATCH 140/174] Use strongly typed enum instead of nested alias --- libraries/avatars/src/AvatarData.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 6 +++--- libraries/entities/src/EntityTree.cpp | 4 ++-- libraries/shared/src/SpatiallyNestable.cpp | 2 +- libraries/shared/src/SpatiallyNestable.h | 17 +++++++---------- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 3f2cd92dbc..d241df7e0e 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -47,7 +47,7 @@ const QString AvatarData::FRAME_NAME = "com.highfidelity.recording.AvatarData"; static std::once_flag frameTypeRegistration; AvatarData::AvatarData() : - SpatiallyNestable(NestableTypes::Avatar, QUuid()), + SpatiallyNestable(NestableType::Avatar, QUuid()), _handPosition(0.0f), _targetScale(1.0f), _handState(0), diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d089427abb..f74cdedb9d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -36,7 +36,7 @@ int EntityItem::_maxActionsDataSize = 800; quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND; EntityItem::EntityItem(const EntityItemID& entityItemID) : - SpatiallyNestable(NestableTypes::Entity, entityItemID), + SpatiallyNestable(NestableType::Entity, entityItemID), _type(EntityTypes::Unknown), _lastSimulated(0), _lastUpdated(0), @@ -1294,7 +1294,7 @@ void EntityItem::updatePosition(const glm::vec3& value) { setLocalPosition(value); _dirtyFlags |= Simulation::DIRTY_POSITION; forEachDescendant([&](SpatiallyNestablePointer object) { - if (object->getNestableType() == NestableTypes::Entity) { + if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); entity->_dirtyFlags |= Simulation::DIRTY_POSITION; } @@ -1317,7 +1317,7 @@ void EntityItem::updateRotation(const glm::quat& rotation) { setLocalOrientation(rotation); _dirtyFlags |= Simulation::DIRTY_ROTATION; forEachDescendant([&](SpatiallyNestablePointer object) { - if (object->getNestableType() == NestableTypes::Entity) { + if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); entity->_dirtyFlags |= Simulation::DIRTY_ROTATION; entity->_dirtyFlags |= Simulation::DIRTY_POSITION; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index abad1e5cd1..8d0962f662 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -219,7 +219,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI // if the entity has children, run UpdateEntityOperator on them. If the children have children, recurse QQueue toProcess; foreach (SpatiallyNestablePointer child, entity->getChildren()) { - if (child && child->getNestableType() == NestableTypes::Entity) { + if (child && child->getNestableType() == NestableType::Entity) { toProcess.enqueue(child); } } @@ -232,7 +232,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI childEntity, newChildBBRelProperties); recurseTreeWithOperator(&theChildOperator); foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) { - if (childChild && childChild->getNestableType() == NestableTypes::Entity) { + if (childChild && childChild->getNestableType() == NestableType::Entity) { toProcess.enqueue(childChild); } } diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index bde788f6ff..98d127cc1e 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -15,7 +15,7 @@ #include "SpatiallyNestable.h" -SpatiallyNestable::SpatiallyNestable(NestableTypes::NestableType nestableType, QUuid id) : +SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) : _nestableType(nestableType), _id(id), _transform() { diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index e656957912..7a43e2a563 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -25,17 +25,14 @@ using SpatiallyNestableWeakConstPointer = std::weak_ptr using SpatiallyNestablePointer = std::shared_ptr; using SpatiallyNestableConstPointer = std::shared_ptr; -class NestableTypes { -public: - using NestableType = enum NestableType_t { - Entity, - Avatar - }; +enum class NestableType { + Entity, + Avatar }; class SpatiallyNestable : public std::enable_shared_from_this { public: - SpatiallyNestable(NestableTypes::NestableType nestableType, QUuid id); + SpatiallyNestable(NestableType nestableType, QUuid id); virtual ~SpatiallyNestable() { } virtual const QUuid& getID() const { return _id; } @@ -88,17 +85,17 @@ public: virtual void setLocalScale(const glm::vec3& scale); QList getChildren() const; - NestableTypes::NestableType getNestableType() const { return _nestableType; } + NestableType getNestableType() const { return _nestableType; } // this object's frame virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const; virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { assert(false); return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { assert(false); return glm::vec3(); } - + SpatiallyNestablePointer getThisPointer() const; protected: - NestableTypes::NestableType _nestableType; // EntityItem or an AvatarData + const NestableType _nestableType; // EntityItem or an AvatarData QUuid _id; QUuid _parentID; // what is this thing's transform relative to? quint16 _parentJointIndex { 0 }; // which joint of the parent is this relative to? From 1467a9d2ebb82485911333c130f9fe94802ef00f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 11:17:40 -0800 Subject: [PATCH 141/174] handle initial simulation of _model --- .../src/RenderableModelEntityItem.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3709c0b9ad..3dcb86fc50 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -251,7 +251,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { // check if the URL has changed auto& currentURL = getParsedModelURL(); if (currentURL != _model->getURL()) { - qDebug().noquote() << "Updating model URL: " << currentURL.toDisplayString(); + qCDebug(entitiesrenderer).noquote() << "Updating model URL: " << currentURL.toDisplayString(); _model->setURL(currentURL); } @@ -378,12 +378,6 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } else { // we already have the model we want... result = _model; } - - if (_model && _needsInitialSimulation) { - PerformanceTimer perfTimer("_model->simulate"); - _model->simulate(0.0f); - } - _needsInitialSimulation = false; } else { // if our desired URL is empty, we may need to delete our existing model if (_model) { _myRenderer->releaseModel(_model); @@ -463,7 +457,9 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { if (_needsInitialSimulation) { // the _model's offset will be wrong until _needsInitialSimulation is false - return false; + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + _needsInitialSimulation = false; } assert(!_model->getCollisionURL().isEmpty()); From 739e184b526f9a16a25ea07d243701e8bc4f3399 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 10 Dec 2015 11:19:11 -0800 Subject: [PATCH 142/174] Fix attachments jitter --- interface/src/Application.cpp | 1 + interface/src/avatar/Avatar.cpp | 1 - interface/src/avatar/Avatar.h | 4 +--- interface/src/avatar/MyAvatar.cpp | 5 ----- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a03cad62a..b3385a3744 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2963,6 +2963,7 @@ void Application::update(float deltaTime) { } myAvatar->harvestResultsFromPhysicsSimulation(); + myAvatar->simulateAttachments(deltaTime); } } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e2b92cc06f..218d679898 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -200,7 +200,6 @@ void Avatar::simulate(float deltaTime) { PerformanceTimer perfTimer("skeleton"); _skeletonModel.getRig()->copyJointsFromJointData(_jointData); _skeletonModel.simulate(deltaTime, _hasNewJointRotations || _hasNewJointTranslations); - simulateAttachments(deltaTime); locationChanged(); // joints changed, so if there are any children, update them. _hasNewJointRotations = false; _hasNewJointTranslations = false; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 99a4fc52a9..09685c318e 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -69,6 +69,7 @@ public: void init(); void simulate(float deltaTime); + void simulateAttachments(float deltaTime); virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition); @@ -87,7 +88,6 @@ public: bool isInitialized() const { return _initialized; } SkeletonModel& getSkeletonModel() { return _skeletonModel; } const SkeletonModel& getSkeletonModel() const { return _skeletonModel; } - const QVector& getAttachmentModels() const { return _attachmentModels; } glm::vec3 getChestPosition() const; float getAvatarScale() const { return getScale().y; } const Head* getHead() const { return static_cast(_headData); } @@ -217,8 +217,6 @@ protected: virtual bool shouldRenderHead(const RenderArgs* renderArgs) const; virtual void fixupModelsInScene(); - void simulateAttachments(float deltaTime); - virtual void updateJointMappings(); render::ItemID _renderItemID; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6637331b64..29f81ae47e 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -323,11 +323,6 @@ void MyAvatar::simulate(float deltaTime) { return; } - { - PerformanceTimer perfTimer("attachments"); - simulateAttachments(deltaTime); - } - { PerformanceTimer perfTimer("joints"); // copy out the skeleton joints from the model From 3a35df191a56576c45d23c43efaf1126aa8d3c70 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 11:19:26 -0800 Subject: [PATCH 143/174] remove an off-brand change --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 8 -------- .../entities-renderer/src/RenderableModelEntityItem.h | 1 - 2 files changed, 9 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3dcb86fc50..f2826db43f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -624,11 +624,3 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in } return glm::vec3(0.0f); } - -void RenderableModelEntityItem::locationChanged() { - EntityItem::locationChanged(); - if (_model && _model->isActive()) { - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); - } -} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 45d5f43683..0aaa7a0977 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -72,7 +72,6 @@ public: virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; - void locationChanged(); virtual void loader() override; private: From c5f5e8de60d84f5f8930ac5fc032b88d1e8b8de8 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 10 Dec 2015 11:43:18 -0800 Subject: [PATCH 144/174] Trying to fix build problem --- interface/CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0baf709082..87cf1a384c 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -100,6 +100,15 @@ else() add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM}) endif() +# These are external plugins, but we need to do the 'add dependency' here so that their +# binary directories get added to the fixup path +add_dependency_external_projects(sixense) +add_dependency_external_projects(sdl2) +if (WIN32) + add_dependency_external_projects(OpenVR) +endif() + + # disable /OPT:REF and /OPT:ICF for the Debug builds # This will prevent the following linker warnings # LINK : warning LNK4075: ignoring '/INCREMENTAL' due to '/OPT:ICF' specification From c463e36ce6978900932b3248a1f264316647c046 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 14:02:52 -0800 Subject: [PATCH 145/174] make particle explorer visible --- examples/particle_explorer/particleExplorer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/particle_explorer/particleExplorer.js b/examples/particle_explorer/particleExplorer.js index 16c75e18c6..0cc51c1a39 100644 --- a/examples/particle_explorer/particleExplorer.js +++ b/examples/particle_explorer/particleExplorer.js @@ -128,7 +128,6 @@ function setUp() { blue: 255 }, lifespan: 5.0, - visible: false, locked: false, isEmitting: true, lifetime: 3600 // 1 hour; just in case From 2fbabf20db0879a404f8dafbbdb79c92706bdcab Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 10 Dec 2015 13:56:37 -0800 Subject: [PATCH 146/174] properly handle repack attempts --- .../src/octree/OctreeSendThread.cpp | 42 +++---------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 9b664572c1..b4eb75ede9 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -416,27 +416,6 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus return; } - /* TODO: Looking for a way to prevent locking and encoding a tree that is not - // going to result in any packets being sent... - // - // If our node is root, and the root hasn't changed, and our view hasn't changed, - // and we've already seen at least one duplicate packet, then we probably don't need - // to lock the tree and encode, because the result should be that no bytes will be - // encoded, and this will be a duplicate packet from the last one we sent... - OctreeElementPointer root = _myServer->getOctree()->getRoot(); - bool skipEncode = false; - if ( - (subTree == root) - && (nodeData->getLastRootTimestamp() == root->getLastChanged()) - && !viewFrustumChanged - && (nodeData->getDuplicatePacketCount() > 0) - ) { - qDebug() << "is root, root not changed, view not changed, already seen a duplicate!" - << "Can we skip it?"; - skipEncode = true; - } - */ - float octreeSizeScale = nodeData->getOctreeSizeScale(); int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust(); @@ -471,20 +450,9 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // the packet and send it completedScene = nodeData->elementBag.isEmpty(); - // if we're trying to fill a full size packet, then we use this logic to determine if we have a DIDNT_FIT case. - if (_packetData.getTargetSize() == MAX_OCTREE_PACKET_DATA_SIZE) { - if (_packetData.hasContent() && bytesWritten == 0 && - params.stopReason == EncodeBitstreamParams::DIDNT_FIT) { - lastNodeDidntFit = true; - } - } else { - // in compressed mode and we are trying to pack more... and we don't care if the _packetData has - // content or not... because in this case even if we were unable to pack any data, we want to drop - // below to our sendNow logic, but we do want to track that we attempted to pack extra + if (params.stopReason == EncodeBitstreamParams::DIDNT_FIT) { + lastNodeDidntFit = true; extraPackingAttempts++; - if (bytesWritten == 0 && params.stopReason == EncodeBitstreamParams::DIDNT_FIT) { - lastNodeDidntFit = true; - } } nodeData->stats.encodeStopped(); @@ -517,7 +485,6 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus } nodeData->writeToPacket(_packetData.getFinalizedData(), _packetData.getFinalizedSize()); - extraPackingAttempts = 0; quint64 compressAndWriteEnd = usecTimestampNow(); compressAndWriteElapsedUsec = (float)(compressAndWriteEnd - compressAndWriteStart); } @@ -526,8 +493,8 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // the packet doesn't have enough space to bother attempting to pack more... bool sendNow = true; - if (nodeData->getAvailable() >= MINIMUM_ATTEMPT_MORE_PACKING && - extraPackingAttempts <= REASONABLE_NUMBER_OF_PACKING_ATTEMPTS) { + if (!completedScene && (nodeData->getAvailable() >= MINIMUM_ATTEMPT_MORE_PACKING && + extraPackingAttempts <= REASONABLE_NUMBER_OF_PACKING_ATTEMPTS)) { sendNow = false; // try to pack more } @@ -539,6 +506,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus packetSendingElapsedUsec = (float)(packetSendingEnd - packetSendingStart); targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE); + extraPackingAttempts = 0; } else { // If we're in compressed mode, then we want to see if we have room for more in this wire packet. // but we've finalized the _packetData, so we want to start a new section, we will do that by From b5e3dce3763986758ca8ed729bae46134357c3cf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 10 Dec 2015 14:34:28 -0800 Subject: [PATCH 147/174] Add keyhole radius to OctreeQuery --- assignment-client/src/octree/OctreeQueryNode.cpp | 2 ++ interface/src/Application.cpp | 1 + libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 1 + libraries/octree/src/OctreeHeadlessViewer.cpp | 1 + libraries/octree/src/OctreeQuery.cpp | 4 ++++ libraries/octree/src/OctreeQuery.h | 3 +++ 7 files changed, 13 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index ba47a15ef3..ffe2e24ca0 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -225,6 +225,8 @@ bool OctreeQueryNode::updateCurrentViewFrustum() { newestViewFrustum.setPosition(getCameraPosition()); newestViewFrustum.setOrientation(getCameraOrientation()); + newestViewFrustum.setKeyholeRadius(getKeyholeRadius()); + // Also make sure it's got the correct lens details from the camera float originalFOV = getCameraFov(); float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 32500a9996..7e863ddcb5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3076,6 +3076,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip()); _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip()); _octreeQuery.setCameraEyeOffsetPosition(glm::vec3()); + _octreeQuery.setKeyholeRadius(_viewFrustum.getKeyholeRadius()); auto lodManager = DependencyManager::get(); _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale()); _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust()); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 93fbe7acdc..0713f0a902 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -41,7 +41,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityAdd: case PacketType::EntityEdit: case PacketType::EntityData: - return VERSION_ENTITIES_HAVE_PARENTS; + return VERSION_ENTITIES_QUERY_KEYHOLE_RADIUS; case PacketType::AvatarData: case PacketType::BulkAvatarData: return 17; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index cd7b9a113c..197e619652 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -161,5 +161,6 @@ const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS = 48; const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49; const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50; const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51; +const PacketVersion VERSION_ENTITIES_QUERY_KEYHOLE_RADIUS = 52; #endif // hifi_PacketHeaders_h diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index 32da638f96..3f761a0748 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -56,6 +56,7 @@ void OctreeHeadlessViewer::queryOctree() { _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip()); _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip()); _octreeQuery.setCameraEyeOffsetPosition(glm::vec3()); + _octreeQuery.setKeyholeRadius(_viewFrustum.getKeyholeRadius()); _octreeQuery.setOctreeSizeScale(getVoxelSizeScale()); _octreeQuery.setBoundaryLevelAdjust(getBoundaryLevelAdjust()); diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 07bca14844..b79d3775ea 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -37,6 +37,8 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip); memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition)); destinationBuffer += sizeof(_cameraEyeOffsetPosition); + memcpy(destinationBuffer, &_keyholeRadius, sizeof(_keyholeRadius)); + destinationBuffer += sizeof(_keyholeRadius); // bitMask of less than byte wide items unsigned char bitItems = 0; @@ -83,6 +85,8 @@ int OctreeQuery::parseData(ReceivedMessage& message) { sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip); memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition)); sourceBuffer += sizeof(_cameraEyeOffsetPosition); + memcpy(&_keyholeRadius, sourceBuffer, sizeof(_keyholeRadius)); + sourceBuffer += sizeof(_keyholeRadius); // optional feature flags unsigned char bitItems = 0; diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index fec1ac0c2a..7e157c4252 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -58,6 +58,7 @@ public: float getCameraNearClip() const { return _cameraNearClip; } float getCameraFarClip() const { return _cameraFarClip; } const glm::vec3& getCameraEyeOffsetPosition() const { return _cameraEyeOffsetPosition; } + float getKeyholeRadius() const { return _keyholeRadius; } glm::vec3 calculateCameraDirection() const; @@ -69,6 +70,7 @@ public: void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; } void setCameraFarClip(float farClip) { _cameraFarClip = farClip; } void setCameraEyeOffsetPosition(const glm::vec3& eyeOffsetPosition) { _cameraEyeOffsetPosition = eyeOffsetPosition; } + void setKeyholeRadius(float keyholeRadius) { _keyholeRadius = keyholeRadius; } // related to Octree Sending strategies int getMaxQueryPacketsPerSecond() const { return _maxQueryPPS; } @@ -88,6 +90,7 @@ protected: float _cameraAspectRatio = 1.0f; float _cameraNearClip = 0.0f; float _cameraFarClip = 0.0f; + float _keyholeRadius { 0.0f }; glm::vec3 _cameraEyeOffsetPosition = glm::vec3(0.0f); // octree server sending items From 46d645376b7f31dff11493382a59e43c24953aa2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 10 Dec 2015 14:38:44 -0800 Subject: [PATCH 148/174] Fix misspelling of entities --- libraries/networking/src/udt/PacketHeaders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 96b3cba3c9..84323588b8 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -161,7 +161,7 @@ const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS = 48; const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49; const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50; const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51; -const PacketVersion VERSION_ENTITITES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52; +const PacketVersion VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52; const PacketVersion VERSION_ENTITIES_QUERY_KEYHOLE_RADIUS = 53; #endif // hifi_PacketHeaders_h From cfcc07da2e83e2d93ab111f6d017eacb42ee336c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 10 Dec 2015 14:49:28 -0800 Subject: [PATCH 149/174] Fix current version for EntityQuery --- libraries/networking/src/udt/PacketHeaders.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 0713f0a902..c6969428a4 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -41,6 +41,8 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityAdd: case PacketType::EntityEdit: case PacketType::EntityData: + return VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP; + case PacketType::EntityQuery: return VERSION_ENTITIES_QUERY_KEYHOLE_RADIUS; case PacketType::AvatarData: case PacketType::BulkAvatarData: From 98263f0c0d270c35b4d0cf90afecc7099e985ef2 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 18 Nov 2015 15:20:29 -0800 Subject: [PATCH 150/174] Moving sdl2 to external plugin --- cmake/externals/sdl2/CMakeLists.txt | 8 ++++ interface/src/Application.cpp | 10 ----- libraries/input-plugins/CMakeLists.txt | 4 +- .../src/input-plugins/InputPlugin.cpp | 2 - plugins/hifiSdl2/CMakeLists.txt | 12 +++++ .../hifiSdl2/src}/Joystick.cpp | 0 .../hifiSdl2/src}/Joystick.h | 0 .../hifiSdl2/src}/SDL2Manager.cpp | 4 +- .../hifiSdl2/src}/SDL2Manager.h | 3 +- plugins/hifiSdl2/src/SDL2Provider.cpp | 44 +++++++++++++++++++ plugins/hifiSdl2/src/plugin.json | 1 + 11 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 plugins/hifiSdl2/CMakeLists.txt rename {libraries/input-plugins/src/input-plugins => plugins/hifiSdl2/src}/Joystick.cpp (100%) rename {libraries/input-plugins/src/input-plugins => plugins/hifiSdl2/src}/Joystick.h (100%) rename {libraries/input-plugins/src/input-plugins => plugins/hifiSdl2/src}/SDL2Manager.cpp (99%) rename {libraries/input-plugins/src/input-plugins => plugins/hifiSdl2/src}/SDL2Manager.h (98%) create mode 100644 plugins/hifiSdl2/src/SDL2Provider.cpp create mode 100644 plugins/hifiSdl2/src/plugin.json diff --git a/cmake/externals/sdl2/CMakeLists.txt b/cmake/externals/sdl2/CMakeLists.txt index ee1d57d2e9..4222cd41f0 100644 --- a/cmake/externals/sdl2/CMakeLists.txt +++ b/cmake/externals/sdl2/CMakeLists.txt @@ -63,7 +63,11 @@ set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") if (APPLE) + +# NOOP + elseif (WIN32) + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/include CACHE PATH "Location of SDL2 include directory") @@ -75,8 +79,12 @@ elseif (WIN32) set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/lib/x86 CACHE PATH "Location of SDL2 DLL") endif() + add_paths_to_fixup_libs(${${EXTERNAL_NAME_UPPER}_DLL_PATH}) + else () + ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/SDL2 CACHE PATH "Location of SDL2 include directory") set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${INSTALL_DIR}/lib/libSDL2.so CACHE FILEPATH "Path to SDL2 library") + endif () diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a79c23712e..a55c4d3617 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -68,7 +68,6 @@ #include #include #include -#include // this should probably be removed #include #include #include @@ -4004,13 +4003,6 @@ void Application::saveScripts() { settings.endArray(); } -QScriptValue joystickToScriptValue(QScriptEngine *engine, Joystick* const &in) { - return engine->newQObject(in); -} - -void joystickFromScriptValue(const QScriptValue &object, Joystick* &out) { - out = qobject_cast(object.toQObject()); -} void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) { // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so @@ -4075,8 +4067,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AvatarManager", DependencyManager::get().data()); - qScriptRegisterMetaType(scriptEngine, joystickToScriptValue, joystickFromScriptValue); - scriptEngine->registerGlobalObject("UndoStack", &_undoStackScriptingInterface); scriptEngine->registerGlobalObject("LODManager", DependencyManager::get().data()); diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 592f1fcc84..b81554511d 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins controllers script-engine) +link_hifi_libraries(shared plugins controllers) GroupSources("src/input-plugins") - -target_sdl2() diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index d226797e95..4d59adb602 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -13,13 +13,11 @@ #include #include "KeyboardMouseDevice.h" -#include "SDL2Manager.h" // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class InputPluginList getInputPlugins() { InputPlugin* PLUGIN_POOL[] = { new KeyboardMouseDevice(), - new SDL2Manager(), nullptr }; diff --git a/plugins/hifiSdl2/CMakeLists.txt b/plugins/hifiSdl2/CMakeLists.txt new file mode 100644 index 0000000000..2f106aedce --- /dev/null +++ b/plugins/hifiSdl2/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Created by Bradley Austin Davis on 2015/11/18 +# 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 +# + +set(TARGET_NAME hifiSdl2) +setup_hifi_plugin(Script Qml Widgets) +link_hifi_libraries(shared controllers plugins input-plugins script-engine) +target_sdl2() diff --git a/libraries/input-plugins/src/input-plugins/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp similarity index 100% rename from libraries/input-plugins/src/input-plugins/Joystick.cpp rename to plugins/hifiSdl2/src/Joystick.cpp diff --git a/libraries/input-plugins/src/input-plugins/Joystick.h b/plugins/hifiSdl2/src/Joystick.h similarity index 100% rename from libraries/input-plugins/src/input-plugins/Joystick.h rename to plugins/hifiSdl2/src/Joystick.h diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp b/plugins/hifiSdl2/src/SDL2Manager.cpp similarity index 99% rename from libraries/input-plugins/src/input-plugins/SDL2Manager.cpp rename to plugins/hifiSdl2/src/SDL2Manager.cpp index c6f5491a5a..7ca49bbd75 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp +++ b/plugins/hifiSdl2/src/SDL2Manager.cpp @@ -11,8 +11,6 @@ #include -#include -#include #include #include @@ -163,6 +161,7 @@ void SDL2Manager::pluginUpdate(float deltaTime, bool jointsCaptured) { joystick->handleButtonEvent(event.cbutton); } +#if 0 if (event.cbutton.button == SDL_CONTROLLER_BUTTON_BACK) { // this will either start or stop a global back event QEvent::Type backType = (event.type == SDL_CONTROLLERBUTTONDOWN) @@ -172,6 +171,7 @@ void SDL2Manager::pluginUpdate(float deltaTime, bool jointsCaptured) { qApp->sendEvent(qApp, &backEvent); } +#endif } else if (event.type == SDL_CONTROLLERDEVICEADDED) { SDL_GameController* controller = SDL_GameControllerOpen(event.cdevice.which); diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.h b/plugins/hifiSdl2/src/SDL2Manager.h similarity index 98% rename from libraries/input-plugins/src/input-plugins/SDL2Manager.h rename to plugins/hifiSdl2/src/SDL2Manager.h index d6b6de24b3..61e2d37fd5 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.h +++ b/plugins/hifiSdl2/src/SDL2Manager.h @@ -17,8 +17,7 @@ #endif #include - -#include "InputPlugin.h" +#include #include "Joystick.h" class SDL2Manager : public InputPlugin { diff --git a/plugins/hifiSdl2/src/SDL2Provider.cpp b/plugins/hifiSdl2/src/SDL2Provider.cpp new file mode 100644 index 0000000000..1c387a9886 --- /dev/null +++ b/plugins/hifiSdl2/src/SDL2Provider.cpp @@ -0,0 +1,44 @@ +// +// Created by Bradley Austin Davis on 2015/10/25 +// 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 + +#include +#include +#include + +#include +#include + +#include "SDL2Manager.h" + +class SDL2Provider : public QObject, public InputProvider { + Q_OBJECT + Q_PLUGIN_METADATA(IID InputProvider_iid FILE "plugin.json") + Q_INTERFACES(InputProvider) + +public: + SDL2Provider(QObject* parent = nullptr) : QObject(parent) {} + virtual ~SDL2Provider() {} + + virtual InputPluginList getInputPlugins() override { + static std::once_flag once; + std::call_once(once, [&] { + InputPluginPointer plugin(new SDL2Manager()); + if (plugin->isSupported()) { + _inputPlugins.push_back(plugin); + } + }); + return _inputPlugins; + } + +private: + InputPluginList _inputPlugins; +}; + +#include "SDL2Provider.moc" diff --git a/plugins/hifiSdl2/src/plugin.json b/plugins/hifiSdl2/src/plugin.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/plugins/hifiSdl2/src/plugin.json @@ -0,0 +1 @@ +{} From 6acf3603d047faafe3de31ff8404fad4c697a7f6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 10 Dec 2015 14:58:08 -0800 Subject: [PATCH 151/174] Update naming and number of entity query version --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index c6969428a4..b02e94e9e8 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -43,7 +43,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityData: return VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP; case PacketType::EntityQuery: - return VERSION_ENTITIES_QUERY_KEYHOLE_RADIUS; + return VERSION_ENTITY_QUERY_KEYHOLE_RADIUS; case PacketType::AvatarData: case PacketType::BulkAvatarData: return 17; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 84323588b8..2d321233a8 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -162,6 +162,8 @@ const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49; const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50; const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51; const PacketVersion VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52; -const PacketVersion VERSION_ENTITIES_QUERY_KEYHOLE_RADIUS = 53; + +// EntityQuery versions +const PacketVersion VERSION_ENTITY_QUERY_KEYHOLE_RADIUS = 18; #endif // hifi_PacketHeaders_h From 5805cc8f2b67a723bcf99f17a9abedd28547416b Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Dec 2015 14:59:04 -0800 Subject: [PATCH 152/174] Adding the AABox transform features (from Extents) adn introducing a simple MeshPartPayload to render simple geometry --- .../render-utils/src/MeshPartPayload.cpp | 347 ++++++++++++------ libraries/render-utils/src/MeshPartPayload.h | 82 +++-- libraries/render-utils/src/Model.cpp | 35 +- libraries/render-utils/src/Model.h | 2 +- libraries/shared/src/AABox.cpp | 16 + libraries/shared/src/AABox.h | 16 +- 6 files changed, 347 insertions(+), 151 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index b3e27ff558..42924b4a1b 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -25,7 +25,7 @@ namespace render { // Return opaque for lack of a better idea return ItemKey::Builder::opaqueShape(); } - + template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { if (payload) { return payload->getBound(); @@ -39,64 +39,38 @@ namespace render { using namespace render; -MeshPartPayload::MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, - glm::vec3 position, glm::quat orientation, bool isCollisionGeometry) : - model(model), - _drawMesh(drawMesh), - meshIndex(meshIndex), - partIndex(partIndex), - _shapeID(shapeIndex), - _modelPosition(position), - _modelOrientation(orientation), - _isCollisionGeometry(isCollisionGeometry) { - initCache(); +MeshPartPayload::MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform) { + + updateMeshPart(mesh, partIndex); + updateMaterial(material); + updateTransform(transform); } -void MeshPartPayload::initCache() { +void MeshPartPayload::updateMeshPart(model::MeshPointer drawMesh, int partIndex) { + _drawMesh = drawMesh; if (_drawMesh) { auto vertexFormat = _drawMesh->getVertexFormat(); _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); - _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); - - if (!_isCollisionGeometry) { - const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); - const FBXMesh& mesh = geometry.meshes.at(meshIndex); - _isBlendShaped = !mesh.blendshapes.isEmpty(); - } else { - _isBlendShaped = false; - } - _drawPart = _drawMesh->getPartBuffer().get(partIndex); + + _localBound = _drawMesh->evalPartBound(partIndex); } - - auto networkMaterial = model->_geometry->getShapeMaterial(_shapeID); - if (networkMaterial) { - _drawMaterial = networkMaterial->_material; - }; - } -void MeshPartPayload::updateDrawMaterial(model::MaterialPointer material) { - _drawMaterial = material; +void MeshPartPayload::updateTransform(const Transform& transform) { + _drawTransform = transform; + _worldBound = _localBound; + _worldBound.transform(_drawTransform); } -void MeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) { - _modelPosition = position; - _modelOrientation = orientation; +void MeshPartPayload::updateMaterial(model::MaterialPointer drawMaterial) { + _drawMaterial = drawMaterial; } render::ItemKey MeshPartPayload::getKey() const { ItemKey::Builder builder; builder.withTypeShape(); - if (!model->isVisible()) { - builder.withInvisible(); - } - - if (_isBlendShaped || _isSkinned) { - builder.withDeformed(); - } - if (_drawMaterial) { auto matKey = _drawMaterial->getKey(); if (matKey.isTransparent() || matKey.isTransparentMap()) { @@ -108,21 +82,7 @@ render::ItemKey MeshPartPayload::getKey() const { } render::Item::Bound MeshPartPayload::getBound() const { - // NOTE: we can't cache this bounds because we need to handle the case of a moving - // entity or mesh part. - if (_isCollisionGeometry) { - if (_drawMesh && _drawBound.isNull()) { - _drawBound = _drawMesh->evalPartBound(partIndex); - } - // If we not skinned use the bounds of the subMesh for all it's parts - const FBXMesh& mesh = model->_collisionGeometry->getFBXGeometry().meshes.at(meshIndex); - auto otherBound = model->calculateScaledOffsetExtents(mesh.meshExtents, _modelPosition, _modelOrientation); - - return model->getPartBounds(0, 0, _modelPosition, _modelOrientation); - - } else { - return model->getPartBounds(meshIndex, partIndex, _modelPosition, _modelOrientation); - } + return _worldBound; } void MeshPartPayload::drawCall(gpu::Batch& batch) const { @@ -130,22 +90,12 @@ void MeshPartPayload::drawCall(gpu::Batch& batch) const { } void MeshPartPayload::bindMesh(gpu::Batch& batch) const { - if (!_isBlendShaped) { - batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); - - batch.setInputFormat((_drawMesh->getVertexFormat())); - - batch.setInputStream(0, _drawMesh->getVertexStream()); - } else { - batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); + batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); - batch.setInputFormat((_drawMesh->getVertexFormat())); + batch.setInputFormat((_drawMesh->getVertexFormat())); + + batch.setInputStream(0, _drawMesh->getVertexStream()); - batch.setInputBuffer(0, model->_blendedVertexBuffers[meshIndex], 0, sizeof(glm::vec3)); - batch.setInputBuffer(1, model->_blendedVertexBuffers[meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3)); - batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); - } - // TODO: Get rid of that extra call if (!_hasColorAttrib) { batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); @@ -236,40 +186,215 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio } void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const { - if (!_isCollisionGeometry) { - // Still relying on the raw data from the model - const Model::MeshState& state = model->_meshStates.at(meshIndex); - - Transform transform; - if (state.clusterBuffer) { - if (model->_cauterizeBones) { - batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer); - } else { - batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer); - } - } else { - if (model->_cauterizeBones) { - transform = Transform(state.cauterizedClusterMatrices[0]); - } else { - transform = Transform(state.clusterMatrices[0]); - } - } - transform.preTranslate(_modelPosition); - batch.setModelTransform(transform); - } else { - Transform transform; - transform.setTranslation(_modelPosition); - transform.setRotation(_modelOrientation); - transform.postScale(model->getScale()); - transform.postTranslate(model->getOffset()); - batch.setModelTransform(transform); - } + batch.setModelTransform(_drawTransform); } void MeshPartPayload::render(RenderArgs* args) const { PerformanceTimer perfTimer("MeshPartPayload::render"); - if (!model->_readyWhenAdded || !model->_isVisible) { + + + 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(); + } + bool translucentMesh = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); + + bool hasTangents = drawMaterialKey.isNormalMap(); + bool hasSpecular = drawMaterialKey.isGlossMap(); + bool hasLightmap = drawMaterialKey.isLightmapMap(); + bool isSkinned = false; + bool wireframe = false; + if (wireframe) { + translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; + } + + ModelRender::Locations* locations = nullptr; + ModelRender::pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, + args, locations); + + + // Bind the model transform and the skinCLusterMatrices if needed + bindTransform(batch, locations); + + //Bind the index buffer and vertex buffer and Blend shapes if needed + bindMesh(batch); + + // apply material properties + bindMaterial(batch, locations); + + + // TODO: We should be able to do that just in the renderTransparentJob + if (translucentMesh && locations->lightBufferUnit >= 0) { + PerformanceTimer perfTimer("DLE->setupTransparent()"); + + DependencyManager::get()->setupTransparent(args, locations->lightBufferUnit); + } + if (args) { + args->_details._materialSwitches++; + } + + // Draw! + { + PerformanceTimer perfTimer("batch.drawIndexed()"); + drawCall(batch); + } + + if (args) { + const int INDICES_PER_TRIANGLE = 3; + args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; + } +} + + + +namespace render { + template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getKey(); + } + // Return opaque for lack of a better idea + return ItemKey::Builder::opaqueShape(); + } + + template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getBound(); + } + return render::Item::Bound(); + } + template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { + return payload->render(args); + } +} + +using namespace render; + +ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, + glm::vec3 position, glm::quat orientation) : + _model(model), + _meshIndex(_meshIndex), + _shapeID(shapeIndex), + _modelPosition(position), + _modelOrientation(orientation) { + auto& modelMesh = _model->_geometry->getMeshes().at(_meshIndex)->_mesh; + updateMeshPart(modelMesh, partIndex); + + initCache(); +} + +void ModelMeshPartPayload::initCache() { + if (_drawMesh) { + auto vertexFormat = _drawMesh->getVertexFormat(); + _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); + _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); + + + const FBXGeometry& geometry = _model->_geometry->getFBXGeometry(); + const FBXMesh& mesh = geometry.meshes.at(_meshIndex); + _isBlendShaped = !mesh.blendshapes.isEmpty(); + } + + auto networkMaterial = _model->_geometry->getShapeMaterial(_shapeID); + if (networkMaterial) { + _drawMaterial = networkMaterial->_material; + }; + +} + + +void ModelMeshPartPayload::notifyLocationChanged() { + _model->_needsUpdateClusterMatrices = true; +} + +void ModelMeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) { + _modelPosition = position; + _modelOrientation = orientation; +} + +render::ItemKey ModelMeshPartPayload::getKey() const { + ItemKey::Builder builder; + builder.withTypeShape(); + + if (!_model->isVisible()) { + builder.withInvisible(); + } + + if (_isBlendShaped || _isSkinned) { + builder.withDeformed(); + } + + if (_drawMaterial) { + auto matKey = _drawMaterial->getKey(); + if (matKey.isTransparent() || matKey.isTransparentMap()) { + builder.withTransparent(); + } + } + + return builder.build(); +} + +render::Item::Bound ModelMeshPartPayload::getBound() const { + // NOTE: we can't cache this bounds because we need to handle the case of a moving + // entity or mesh part. + return _model->getPartBounds(_meshIndex, _partIndex, _modelPosition, _modelOrientation); +} + +void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { + if (!_isBlendShaped) { + batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); + + batch.setInputFormat((_drawMesh->getVertexFormat())); + + batch.setInputStream(0, _drawMesh->getVertexStream()); + } else { + batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); + + batch.setInputFormat((_drawMesh->getVertexFormat())); + + batch.setInputBuffer(0, _model->_blendedVertexBuffers[_meshIndex], 0, sizeof(glm::vec3)); + batch.setInputBuffer(1, _model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3)); + batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); + } + + // TODO: Get rid of that extra call + if (!_hasColorAttrib) { + batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + } +} + +void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const { + // Still relying on the raw data from the model + const Model::MeshState& state = _model->_meshStates.at(_meshIndex); + + Transform transform; + if (state.clusterBuffer) { + if (_model->_cauterizeBones) { + batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer); + } else { + batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer); + } + } else { + if (_model->_cauterizeBones) { + transform = Transform(state.cauterizedClusterMatrices[0]); + } else { + transform = Transform(state.clusterMatrices[0]); + } + } + // transform.preTranslate(_modelPosition); + transform.preTranslate(_drawTransform.getTranslation()); + batch.setModelTransform(transform); +} + + +void ModelMeshPartPayload::render(RenderArgs* args) const { + PerformanceTimer perfTimer("ModelMeshPartPayload::render"); + if (!_model->_readyWhenAdded || !_model->_isVisible) { return; // bail asap } @@ -278,25 +403,25 @@ void MeshPartPayload::render(RenderArgs* args) const { 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(); + const FBXGeometry& geometry = _model->_geometry->getFBXGeometry(); + const std::vector>& networkMeshes = _model->_geometry->getMeshes(); // guard against partially loaded meshes - if (meshIndex >= (int)networkMeshes.size() || meshIndex >= (int)geometry.meshes.size() || meshIndex >= (int)model->_meshStates.size() ) { + if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)_model->_meshStates.size() ) { return; } // Back to model to update the cluster matrices right now - model->updateClusterMatrices(_modelPosition, _modelOrientation); + _model->updateClusterMatrices(_modelPosition, _modelOrientation); - const FBXMesh& mesh = geometry.meshes.at(meshIndex); + const FBXMesh& mesh = geometry.meshes.at(_meshIndex); // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown // to false to rebuild out mesh groups. - if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex > geometry.meshes.size()) { - model->_meshGroupsKnown = false; // regenerate these lists next time around. - model->_readyWhenAdded = false; // in case any of our users are using scenes - model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid + if (_meshIndex < 0 || _meshIndex >= (int)networkMeshes.size() || _meshIndex > geometry.meshes.size()) { + _model->_meshGroupsKnown = false; // regenerate these lists next time around. + _model->_readyWhenAdded = false; // in case any of our users are using scenes + _model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid return; // FIXME! } @@ -317,12 +442,12 @@ void MeshPartPayload::render(RenderArgs* args) const { bool hasSpecular = drawMaterialKey.isGlossMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); bool isSkinned = _isSkinned; - bool wireframe = model->isWireframe(); + bool wireframe = _model->isWireframe(); // render the part bounding box #ifdef DEBUG_BOUNDING_PARTS { - AABox partBounds = getPartBounds(meshIndex, partIndex); + AABox partBounds = getPartBounds(_meshIndex, partIndex); bool inView = args->_viewFrustum->boxInFrustum(partBounds) != ViewFrustum::OUTSIDE; glm::vec4 cubeColor; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index b810ad8acf..9cfda4927f 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -1,5 +1,5 @@ // -// MeshPartPayload.h +// ModelMeshPartPayload.h // interface/src/renderer // // Created by Sam Gateau on 10/3/15. @@ -24,47 +24,42 @@ class Model; class MeshPartPayload { public: - MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation, bool isCollisionGeometry = false); - + MeshPartPayload() {} + MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform); + typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - Model* model; - int meshIndex; - int partIndex; - int _shapeID; - glm::vec3 _modelPosition; - glm::quat _modelOrientation; + virtual void updateMeshPart(model::MeshPointer drawMesh, int partIndex); + virtual void notifyLocationChanged() {} + virtual void updateTransform(const Transform& transform); - // can replace the material used to draw that item - void updateDrawMaterial(model::MaterialPointer material); - - void updateModelLocation(glm::vec3 position, glm::quat orientation); + virtual void updateMaterial(model::MaterialPointer drawMaterial); // Render Item interface - render::ItemKey getKey() const; - render::Item::Bound getBound() const; - void render(RenderArgs* args) const; - - // MeshPartPayload functions to perform render + virtual render::ItemKey getKey() const; + virtual render::Item::Bound getBound() const; + virtual void render(RenderArgs* args) const; + + // ModelMeshPartPayload functions to perform render void drawCall(gpu::Batch& batch) const; - void bindMesh(gpu::Batch& batch) const; - void bindMaterial(gpu::Batch& batch, const ModelRender::Locations* locations) const; - void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const; - - - void initCache(); + virtual void bindMesh(gpu::Batch& batch) const; + virtual void bindMaterial(gpu::Batch& batch, const ModelRender::Locations* locations) const; + virtual void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const; // Payload resource cached values model::MeshPointer _drawMesh; + int _partIndex = 0; model::Mesh::Part _drawPart; + model::MaterialPointer _drawMaterial; - mutable model::Box _drawBound; + + model::Box _localBound; + Transform _drawTransform; + mutable model::Box _worldBound; + bool _hasColorAttrib = false; - bool _isSkinned = false; - bool _isBlendShaped = false; - bool _isCollisionGeometry = false; }; namespace render { @@ -73,4 +68,35 @@ namespace render { template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args); } + +class ModelMeshPartPayload : public MeshPartPayload { +public: + ModelMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation); + + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + + virtual void notifyLocationChanged(); + virtual void updateModelLocation(glm::vec3 position, glm::quat orientation); + + // Render Item interface + render::ItemKey getKey() const; + render::Item::Bound getBound() const; + void render(RenderArgs* args) const; + + // ModelMeshPartPayload functions to perform render + void bindMesh(gpu::Batch& batch) const; + void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const; + + + void initCache(); + Model* _model; + int _meshIndex; + int _shapeID; + glm::vec3 _modelPosition; + glm::quat _modelOrientation; + bool _isSkinned = false; + bool _isBlendShaped = false; +}; + #endif // hifi_MeshPartPayload_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3f88443ade..ce30e99047 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -110,11 +110,15 @@ void Model::setOffset(const glm::vec3& offset) { void Model::enqueueLocationChange() { render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); + Transform transform; + transform.setTranslation(_translation); + transform.setRotation(_rotation); + render::PendingChanges pendingChanges; foreach (auto itemID, _renderItems.keys()) { pendingChanges.updateItem(itemID, [=](MeshPartPayload& data) { - data.updateModelLocation(_translation, _rotation); - data.model->_needsUpdateClusterMatrices = true; + data.updateTransform(transform); + data.notifyLocationChanged(); }); } @@ -495,11 +499,12 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); - auto renderData = MeshPartPayload::Pointer(renderItem); + // auto renderData = MeshPartPayload::Pointer(renderItem); + auto renderData = renderItem; auto renderPayload = std::make_shared(renderData); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { - data.model->_needsUpdateClusterMatrices = true; + data.notifyLocationChanged(); }); _renderItems.insert(item, renderPayload); somethingAdded = true; @@ -528,7 +533,7 @@ bool Model::addToScene(std::shared_ptr scene, renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { - data.model->_needsUpdateClusterMatrices = true; + data.notifyLocationChanged(); }); _renderItems.insert(item, renderPayload); somethingAdded = true; @@ -1155,6 +1160,10 @@ void Model::segregateMeshGroups() { _renderItemsSet.clear(); + Transform transform; + transform.setTranslation(_translation); + transform.setRotation(_rotation); + // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; for (int i = 0; i < (int)networkMeshes.size(); i++) { @@ -1164,11 +1173,13 @@ void Model::segregateMeshGroups() { // Create the render payloads int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { - auto renderItem = std::make_shared(this, networkMesh._mesh, i, partIndex, shapeID, _translation, _rotation, showingCollisionHull); if (showingCollisionHull) { - renderItem->updateDrawMaterial(ModelRender::getCollisionHullMaterial()); + _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ModelRender::getCollisionHullMaterial(), transform); + + } else { + _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); } - _renderItemsSet << renderItem; + shapeID++; } } @@ -1181,6 +1192,10 @@ bool Model::initWhenReady(render::ScenePointer scene) { render::PendingChanges pendingChanges; + Transform transform; + transform.setTranslation(_translation); + transform.setRotation(_rotation); + foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); auto renderData = MeshPartPayload::Pointer(renderItem); @@ -1188,8 +1203,8 @@ bool Model::initWhenReady(render::ScenePointer scene) { _renderItems.insert(item, renderPayload); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { - data.updateModelLocation(_translation, _rotation); - data.model->_needsUpdateClusterMatrices = true; + data.updateTransform(transform); + data.notifyLocationChanged(); }); } scene->enqueuePendingChanges(pendingChanges); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index d77cf830bd..08abb74316 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -366,7 +366,7 @@ private: bool _needsUpdateClusterMatrices = true; bool _showCollisionHull = false; - friend class MeshPartPayload; + friend class ModelMeshPartPayload; protected: RigPointer _rig; }; diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index b514e171eb..2e2b69843a 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -12,6 +12,7 @@ #include "AABox.h" #include "AACube.h" +#include "Transform.h" #include "Extents.h" #include "GeometryUtil.h" #include "NumericalConstants.h" @@ -486,3 +487,18 @@ AABox& AABox::operator += (const AABox& box) { } return (*this); } + +void AABox::scale(const glm::vec3& scale) { + _corner *= scale; + _scale *= scale; +} + +void AABox::rotate(const glm::quat& rotation) { + +} + +void AABox::transform(const Transform& transform) { + scale(transform.getScale()); + rotate(transform.getRotation()); + translate(transform.getTranslation()); +} \ No newline at end of file diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index 1f5923dbd8..57587d4e71 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -24,6 +24,7 @@ class AACube; class Extents; +class Transform; class AABox { @@ -40,7 +41,6 @@ public: void setBox(const glm::vec3& corner, float scale); glm::vec3 getVertexP(const glm::vec3& normal) const; glm::vec3 getVertexN(const glm::vec3& normal) const; - void scale(float scale); const glm::vec3& getCorner() const { return _corner; } const glm::vec3& getScale() const { return _scale; } const glm::vec3& getDimensions() const { return _scale; } @@ -80,6 +80,20 @@ public: AABox& operator += (const glm::vec3& point); AABox& operator += (const AABox& box); + // Translate the AABox just moving the corner + void translate(const glm::vec3& translation) { _corner += translation; } + + // Rotate the AABox around its frame origin + // meaning rotating the corners of the AABox around the point {0,0,0} and reevaluating the min max + void rotate(const glm::quat& rotation); + + /// Scale the AABox + void scale(float scale); + void scale(const glm::vec3& scale); + + // Transform the extents with transform + void transform(const Transform& transform); + bool isInvalid() const { return _corner == glm::vec3(std::numeric_limits::infinity()); } private: From 1af780a6645c82bfbb9dda23392a87a96fecb4df Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 10 Dec 2015 15:05:27 -0800 Subject: [PATCH 153/174] Fix for sixense debug draw after move to plugin. static variables used to hold a Singleton cannot be shared across dll boundaries by default. This uses the globalInstance template to store the instance as a property on the QApplication. --- libraries/shared/src/DebugDraw.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/DebugDraw.cpp b/libraries/shared/src/DebugDraw.cpp index 3060e151c8..557889cab0 100644 --- a/libraries/shared/src/DebugDraw.cpp +++ b/libraries/shared/src/DebugDraw.cpp @@ -8,10 +8,11 @@ // #include "DebugDraw.h" +#include "SharedUtil.h" DebugDraw& DebugDraw::getInstance() { - static DebugDraw instance; - return instance; + static DebugDraw* instance = globalInstance("com.highfidelity.DebugDraw"); + return *instance; } DebugDraw::DebugDraw() { From 4c8b7aa800772d7f1716cf3d3653ebc1b30d2c17 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 10 Dec 2015 16:26:16 -0800 Subject: [PATCH 154/174] Fix EntityErase packets not being handled on agents --- assignment-client/src/Agent.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index d744acc42b..46fa8c8181 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -102,8 +102,10 @@ void Agent::handleOctreePacket(QSharedPointer message, SharedNo packetType = message->getType(); } // fall through to piggyback message - if (packetType == PacketType::EntityData || packetType == PacketType::EntityErase) { + if (packetType == PacketType::EntityData) { _entityViewer.processDatagram(*message, senderNode); + } else if (packetType == PacketType::EntityErase) { + _entityViewer.processEraseMessage(*message, senderNode); } } From dffb83a488560235e6ced4ee9a770f4c70cc3230 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Dec 2015 16:31:00 -0800 Subject: [PATCH 155/174] Potentially working correctly --- libraries/render-utils/src/MeshPartPayload.cpp | 16 +++++++++------- libraries/render-utils/src/MeshPartPayload.h | 6 ++++-- libraries/render-utils/src/Model.cpp | 18 +++++++++++++++--- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 42924b4a1b..4c9adb405b 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -39,11 +39,11 @@ namespace render { using namespace render; -MeshPartPayload::MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform) { +MeshPartPayload::MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform, const Transform& offsetTransform) { updateMeshPart(mesh, partIndex); updateMaterial(material); - updateTransform(transform); + updateTransform(transform, offsetTransform); } void MeshPartPayload::updateMeshPart(model::MeshPointer drawMesh, int partIndex) { @@ -57,8 +57,10 @@ void MeshPartPayload::updateMeshPart(model::MeshPointer drawMesh, int partIndex) } } -void MeshPartPayload::updateTransform(const Transform& transform) { - _drawTransform = transform; +void MeshPartPayload::updateTransform(const Transform& transform, const Transform& offsetTransform) { + _transform = transform; + _offsetTransform = offsetTransform; + Transform::mult(_drawTransform, _transform, _offsetTransform); _worldBound = _localBound; _worldBound.transform(_drawTransform); } @@ -342,7 +344,7 @@ render::ItemKey ModelMeshPartPayload::getKey() const { render::Item::Bound ModelMeshPartPayload::getBound() const { // NOTE: we can't cache this bounds because we need to handle the case of a moving // entity or mesh part. - return _model->getPartBounds(_meshIndex, _partIndex, _modelPosition, _modelOrientation); + return _model->getPartBounds(_meshIndex, _partIndex, _transform.getTranslation(), _transform.getRotation()); } void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { @@ -387,7 +389,7 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::L } } // transform.preTranslate(_modelPosition); - transform.preTranslate(_drawTransform.getTranslation()); + transform.preTranslate(_transform.getTranslation()); batch.setModelTransform(transform); } @@ -412,7 +414,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { } // Back to model to update the cluster matrices right now - _model->updateClusterMatrices(_modelPosition, _modelOrientation); + _model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation()); const FBXMesh& mesh = geometry.meshes.at(_meshIndex); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 9cfda4927f..c5b1e492d8 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -25,7 +25,7 @@ class Model; class MeshPartPayload { public: MeshPartPayload() {} - MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform); + MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform, const Transform& offsetTransform); typedef render::Payload Payload; typedef Payload::DataPointer Pointer; @@ -33,7 +33,7 @@ public: virtual void updateMeshPart(model::MeshPointer drawMesh, int partIndex); virtual void notifyLocationChanged() {} - virtual void updateTransform(const Transform& transform); + virtual void updateTransform(const Transform& transform, const Transform& offsetTransform); virtual void updateMaterial(model::MaterialPointer drawMaterial); @@ -57,6 +57,8 @@ public: model::Box _localBound; Transform _drawTransform; + Transform _transform; + Transform _offsetTransform; mutable model::Box _worldBound; bool _hasColorAttrib = false; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index ce30e99047..545afea681 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -114,10 +114,14 @@ void Model::enqueueLocationChange() { transform.setTranslation(_translation); transform.setRotation(_rotation); + Transform offset; + offset.setScale(_scale); + offset.postTranslate(_offset); + render::PendingChanges pendingChanges; foreach (auto itemID, _renderItems.keys()) { pendingChanges.updateItem(itemID, [=](MeshPartPayload& data) { - data.updateTransform(transform); + data.updateTransform(transform, offset); data.notifyLocationChanged(); }); } @@ -1164,6 +1168,10 @@ void Model::segregateMeshGroups() { transform.setTranslation(_translation); transform.setRotation(_rotation); + Transform offset; + offset.setScale(_scale); + offset.postTranslate(_offset); + // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; for (int i = 0; i < (int)networkMeshes.size(); i++) { @@ -1174,7 +1182,7 @@ void Model::segregateMeshGroups() { int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { if (showingCollisionHull) { - _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ModelRender::getCollisionHullMaterial(), transform); + _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ModelRender::getCollisionHullMaterial(), transform, offset); } else { _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); @@ -1196,6 +1204,10 @@ bool Model::initWhenReady(render::ScenePointer scene) { transform.setTranslation(_translation); transform.setRotation(_rotation); + Transform offset; + offset.setScale(_scale); + offset.postTranslate(_offset); + foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); auto renderData = MeshPartPayload::Pointer(renderItem); @@ -1203,7 +1215,7 @@ bool Model::initWhenReady(render::ScenePointer scene) { _renderItems.insert(item, renderPayload); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { - data.updateTransform(transform); + data.updateTransform(transform, offset); data.notifyLocationChanged(); }); } From 20f3d6abe1bc83eae6971a3622aba18439d1ba60 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Dec 2015 16:52:03 -0800 Subject: [PATCH 156/174] REmoving comments --- libraries/render-utils/src/MeshPartPayload.cpp | 13 +++---------- libraries/render-utils/src/MeshPartPayload.h | 17 +++++++---------- libraries/render-utils/src/Model.cpp | 12 ++++-------- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 4c9adb405b..2d8d7b598b 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -277,16 +277,14 @@ namespace render { using namespace render; -ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, - glm::vec3 position, glm::quat orientation) : +ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : _model(model), _meshIndex(_meshIndex), - _shapeID(shapeIndex), - _modelPosition(position), - _modelOrientation(orientation) { + _shapeID(shapeIndex) { auto& modelMesh = _model->_geometry->getMeshes().at(_meshIndex)->_mesh; updateMeshPart(modelMesh, partIndex); + updateTransform(transform, offsetTransform); initCache(); } @@ -314,11 +312,6 @@ void ModelMeshPartPayload::notifyLocationChanged() { _model->_needsUpdateClusterMatrices = true; } -void ModelMeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) { - _modelPosition = position; - _modelOrientation = orientation; -} - render::ItemKey ModelMeshPartPayload::getKey() const { ItemKey::Builder builder; builder.withTypeShape(); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index c5b1e492d8..e03d1c8a68 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -73,30 +73,27 @@ namespace render { class ModelMeshPartPayload : public MeshPartPayload { public: - ModelMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation); + ModelMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - virtual void notifyLocationChanged(); - virtual void updateModelLocation(glm::vec3 position, glm::quat orientation); + void notifyLocationChanged() override; // Render Item interface - render::ItemKey getKey() const; - render::Item::Bound getBound() const; - void render(RenderArgs* args) const; + render::ItemKey getKey() const override; + render::Item::Bound getBound() const override; + void render(RenderArgs* args) const override; // ModelMeshPartPayload functions to perform render - void bindMesh(gpu::Batch& batch) const; - void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const; + void bindMesh(gpu::Batch& batch) const override; + void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const override; void initCache(); Model* _model; int _meshIndex; int _shapeID; - glm::vec3 _modelPosition; - glm::quat _modelOrientation; bool _isSkinned = false; bool _isBlendShaped = false; }; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 545afea681..e7c4442755 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -503,9 +503,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); - // auto renderData = MeshPartPayload::Pointer(renderItem); - auto renderData = renderItem; - auto renderPayload = std::make_shared(renderData); + auto renderPayload = std::make_shared(renderItem); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { data.notifyLocationChanged(); @@ -532,8 +530,7 @@ bool Model::addToScene(std::shared_ptr scene, foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); - auto renderData = MeshPartPayload::Pointer(renderItem); - auto renderPayload = std::make_shared(renderData); + auto renderPayload = std::make_shared(renderItem); renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { @@ -1185,7 +1182,7 @@ void Model::segregateMeshGroups() { _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ModelRender::getCollisionHullMaterial(), transform, offset); } else { - _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); + _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, transform, offset); } shapeID++; @@ -1210,8 +1207,7 @@ bool Model::initWhenReady(render::ScenePointer scene) { foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); - auto renderData = MeshPartPayload::Pointer(renderItem); - auto renderPayload = std::make_shared(renderData); + auto renderPayload = std::make_shared(renderItem); _renderItems.insert(item, renderPayload); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { From 40bf721ac54ab0b6d6acd459d6e9687bd4cdd081 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Dec 2015 17:16:06 -0800 Subject: [PATCH 157/174] Fixing merging problem --- libraries/shared/src/AABox.cpp | 87 ++++++++++++++++------------------ 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index 3dd020fd90..d16bdafcec 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -43,50 +43,6 @@ glm::vec3 AABox::calcCenter() const { return center; } -void AABox::rotate(const glm::quat& rotation) { - auto minimum = _corner; - auto maximum = _corner + _scale; - - glm::vec3 bottomLeftNear(minimum.x, minimum.y, minimum.z); - glm::vec3 bottomRightNear(maximum.x, minimum.y, minimum.z); - glm::vec3 bottomLeftFar(minimum.x, minimum.y, maximum.z); - glm::vec3 bottomRightFar(maximum.x, minimum.y, maximum.z); - glm::vec3 topLeftNear(minimum.x, maximum.y, minimum.z); - glm::vec3 topRightNear(maximum.x, maximum.y, minimum.z); - glm::vec3 topLeftFar(minimum.x, maximum.y, maximum.z); - glm::vec3 topRightFar(maximum.x, maximum.y, maximum.z); - - glm::vec3 bottomLeftNearRotated = rotation * bottomLeftNear; - glm::vec3 bottomRightNearRotated = rotation * bottomRightNear; - glm::vec3 bottomLeftFarRotated = rotation * bottomLeftFar; - glm::vec3 bottomRightFarRotated = rotation * bottomRightFar; - glm::vec3 topLeftNearRotated = rotation * topLeftNear; - glm::vec3 topRightNearRotated = rotation * topRightNear; - glm::vec3 topLeftFarRotated = rotation * topLeftFar; - glm::vec3 topRightFarRotated = rotation * topRightFar; - - minimum = glm::min(bottomLeftNearRotated, - glm::min(bottomRightNearRotated, - glm::min(bottomLeftFarRotated, - glm::min(bottomRightFarRotated, - glm::min(topLeftNearRotated, - glm::min(topRightNearRotated, - glm::min(topLeftFarRotated, - topRightFarRotated))))))); - - maximum = glm::max(bottomLeftNearRotated, - glm::max(bottomRightNearRotated, - glm::max(bottomLeftFarRotated, - glm::max(bottomRightFarRotated, - glm::max(topLeftNearRotated, - glm::max(topRightNearRotated, - glm::max(topLeftFarRotated, - topRightFarRotated))))))); - - _corner = minimum; - _scale = maximum - minimum; -} - glm::vec3 AABox::getVertex(BoxVertex vertex) const { switch (vertex) { case BOTTOM_LEFT_NEAR: @@ -532,8 +488,49 @@ void AABox::scale(const glm::vec3& scale) { _scale *= scale; } -void AABox::rotate(const glm::quat& rotation) { +void AABox::rotate(const glm::quat& rotation) { + auto minimum = _corner; + auto maximum = _corner + _scale; + + glm::vec3 bottomLeftNear(minimum.x, minimum.y, minimum.z); + glm::vec3 bottomRightNear(maximum.x, minimum.y, minimum.z); + glm::vec3 bottomLeftFar(minimum.x, minimum.y, maximum.z); + glm::vec3 bottomRightFar(maximum.x, minimum.y, maximum.z); + glm::vec3 topLeftNear(minimum.x, maximum.y, minimum.z); + glm::vec3 topRightNear(maximum.x, maximum.y, minimum.z); + glm::vec3 topLeftFar(minimum.x, maximum.y, maximum.z); + glm::vec3 topRightFar(maximum.x, maximum.y, maximum.z); + + glm::vec3 bottomLeftNearRotated = rotation * bottomLeftNear; + glm::vec3 bottomRightNearRotated = rotation * bottomRightNear; + glm::vec3 bottomLeftFarRotated = rotation * bottomLeftFar; + glm::vec3 bottomRightFarRotated = rotation * bottomRightFar; + glm::vec3 topLeftNearRotated = rotation * topLeftNear; + glm::vec3 topRightNearRotated = rotation * topRightNear; + glm::vec3 topLeftFarRotated = rotation * topLeftFar; + glm::vec3 topRightFarRotated = rotation * topRightFar; + + minimum = glm::min(bottomLeftNearRotated, + glm::min(bottomRightNearRotated, + glm::min(bottomLeftFarRotated, + glm::min(bottomRightFarRotated, + glm::min(topLeftNearRotated, + glm::min(topRightNearRotated, + glm::min(topLeftFarRotated, + topRightFarRotated))))))); + + maximum = glm::max(bottomLeftNearRotated, + glm::max(bottomRightNearRotated, + glm::max(bottomLeftFarRotated, + glm::max(bottomRightFarRotated, + glm::max(topLeftNearRotated, + glm::max(topRightNearRotated, + glm::max(topLeftFarRotated, + topRightFarRotated))))))); + + _corner = minimum; + _scale = maximum - minimum; } void AABox::transform(const Transform& transform) { From e5a5c05e84d049ad72f2dc01e1b48b85f93c6c3a Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 10 Dec 2015 17:56:31 -0800 Subject: [PATCH 158/174] switch to july sixense SDK --- cmake/externals/sixense/CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmake/externals/sixense/CMakeLists.txt b/cmake/externals/sixense/CMakeLists.txt index c41694344e..16f2850449 100644 --- a/cmake/externals/sixense/CMakeLists.txt +++ b/cmake/externals/sixense/CMakeLists.txt @@ -8,14 +8,14 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) #set(SIXENSE_URL_MD5 "10cc8dc470d2ac1244a88cf04bc549cc") #set(SIXENSE_NEW_LAYOUT 0) -#set(SIXENSE_URL "http://public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip") -#set(SIXENSE_URL_MD5 "752a3901f334124e9cffc2ba4136ef7d") -#set(SIXENSE_NEW_LAYOUT 1) - -set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_102215.zip") -set(SIXENSE_URL_MD5 "93c3a6795cce777a0f472b09532935f1") +set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip") +set(SIXENSE_URL_MD5 "752a3901f334124e9cffc2ba4136ef7d") set(SIXENSE_NEW_LAYOUT 1) +#set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_102215.zip") +#set(SIXENSE_URL_MD5 "93c3a6795cce777a0f472b09532935f1") +#set(SIXENSE_NEW_LAYOUT 1) + ExternalProject_Add( ${EXTERNAL_NAME} URL ${SIXENSE_URL} From 99bc47867ac769b1d27c7028096c5bac2c9058f3 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 18:16:01 -0800 Subject: [PATCH 159/174] cleanup --- examples/drylake/ratCreator.js | 56 ++++---- examples/drylake/ratSteer.js | 233 +++++++++++++++++---------------- 2 files changed, 147 insertions(+), 142 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index f51052aea3..c20ce9e2ad 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -127,9 +127,15 @@ var target = Entities.addEntity(targetProperties); function addRat() { var rat = Entities.addEntity(modelRatProperties); - return rat + return rat; } +//every sixth rat will play a sound +var RAT_SOUND_RATE = 6; + +//spawn rate will be multiplied by this to clear any sounds hanging around +var RAT_SOUND_CLEAR_RATE = 3; + var rats = []; var metaRats = []; var ratCount = 0; @@ -257,11 +263,11 @@ function createRatSoundInjector() { var audioOptions = { volume: 0.05, loop: false - } + }; var injector = Audio.playSound(ratRunningSound, audioOptions); - return injector + return injector; } function moveRats() { @@ -270,8 +276,6 @@ function moveRats() { //remove the rat if its near the nest checkDistanceFromNest(rat); - //otherwise figure out where to send it - //see if there are avatars to run from var avatarFlightVectors = steer.fleeAllAvatars(rat); var averageAvatarFlight; @@ -280,7 +284,7 @@ function moveRats() { if (i === 0) { averageAvatarFlight = avatarFlightVectors[0]; } else { - averageAvatarFlight = Vec3.sum(avatarFlightVectors[i - 1], avatarFlightVectors[i]) + averageAvatarFlight = Vec3.sum(avatarFlightVectors[i - 1], avatarFlightVectors[i]); } } averageAvatarFlight = Vec3.multiply(averageAvatarFlight, 1 / avatarFlightVectors.length); @@ -325,12 +329,12 @@ function moveRats() { var eulerAngle = Quat.safeEulerAngles(ratRotation); eulerAngle.x = 0; eulerAngle.z = 0; - var constrainedRotation = Quat.fromVec3Degrees(eulerAngle) + var constrainedRotation = Quat.fromVec3Degrees(eulerAngle); Entities.editEntity(rat, { velocity: averageVector, rotation: constrainedRotation, - }) + }); //have to make a 'meta' rat object to keep track of rats for updating sound injector locations. parenting sounds would make this easy. var metaRat = getMetaRatByRat(rat); @@ -452,23 +456,23 @@ var ratSpawnerInterval; if (USE_CONSTANT_SPAWNER === true) { ratSpawnerInterval = Script.setInterval(function() { - var rat = addRat(); - playRatRunningAnimation(rat); - rats.push(rat); - ratCount++; - if (ratCount % 6 === 0) { - var metaRat = { - rat: rat, - injector: createRatSoundInjector() - } - metaRats.push(metaRat); + var rat = addRat(); + playRatRunningAnimation(rat); + rats.push(rat); + ratCount++; + if (ratCount % RAT_SOUND_RATE === 0) { + var metaRat = { + rat: rat, + injector: createRatSoundInjector() + } + metaRats.push(metaRat); - Script.setTimeout(function() { - //if we have too many injectors hanging around there are problems - metaRat.injector.stop(); - delete metaRat.injector; - }, RAT_SPAWN_RATE * 3); - } + Script.setTimeout(function() { + //if we have too many injectors hanging around there are problems + metaRat.injector.stop(); + delete metaRat.injector; + }, RAT_SPAWN_RATE * RAT_SOUND_CLEAR_RATE; + } - }, RAT_SPAWN_RATE); -} \ No newline at end of file + }, RAT_SPAWN_RATE); + } \ No newline at end of file diff --git a/examples/drylake/ratSteer.js b/examples/drylake/ratSteer.js index f69ab81f6d..a4addf4e52 100644 --- a/examples/drylake/ratSteer.js +++ b/examples/drylake/ratSteer.js @@ -11,171 +11,172 @@ // function flee(thisEntity, target) { - var targetPosition = Entities.getEntityProperties(target, "position").position; - var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); - var location = properties.position; - var velocity = properties.velocity; - var MAX_SPEED = 1; - var MAX_FORCE = 1; + var targetPosition = Entities.getEntityProperties(target, "position").position; + var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); + var location = properties.position; + var velocity = properties.velocity; + var MAX_SPEED = 1; + var MAX_FORCE = 1; + var FLEE_RANGE = 2; + var desired = Vec3.subtract(location, targetPosition); + var d = Vec3.length(desired); + desired = Vec3.normalize(desired); + desired = Vec3.multiply(MAX_SPEED, desired); + if (d < FLEE_RANGE) { + var steer = Vec3.subtract(desired, velocity); - var desired = Vec3.subtract(location, targetPosition); - var d = Vec3.length(desired); - desired = Vec3.normalize(desired); - desired = Vec3.multiply(MAX_SPEED, desired); - if (d < 2) { - var steer = Vec3.subtract(desired, velocity); + var steerVector = new V3(desired.x, 0, desired.z); + steer = steerVector.limit(MAX_FORCE); - var steerVector = new V3(desired.x, 0, desired.z); - steer = steerVector.limit(MAX_FORCE); - - return steer; - } else { - // print('target too far away to flee' + d); - return - } + return steer; + } else { + // print('target too far away to flee' + d); + return + } } function fleeAllAvatars(thisEntity) { - //print('FLEE AVATARS'); - var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); - var location = properties.position; - var velocity = properties.velocity; + //print('FLEE AVATARS'); + var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); + var location = properties.position; + var velocity = properties.velocity; - var nearbyEntities = Entities.findEntities(location, 3); - var flightVectors = []; - for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { - var entityID = nearbyEntities[entityIndex]; - var entityProps = Entities.getEntityProperties(entityID); - if (entityProps.name === 'Hifi-Avatar-Detector') { - //print('found an avatar to flee') + var nearbyEntities = Entities.findEntities(location, 3); + var flightVectors = []; + for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { + var entityID = nearbyEntities[entityIndex]; + var entityProps = Entities.getEntityProperties(entityID); + if (entityProps.name === 'Hifi-Avatar-Detector') { + //print('found an avatar to flee') - var MAX_SPEED = 8; - var MAX_FORCE = 8; + var MAX_SPEED = 8; + var MAX_FORCE = 8; + var FLEE_AVATAR_RANGE = 3; + var desired = Vec3.subtract(location, entityProps.position); + var d = Vec3.length(desired); + desired = Vec3.normalize(desired); + desired = Vec3.multiply(MAX_SPEED, desired); + if (d < FLEE_AVATAR_RANGE) { + var steer = Vec3.subtract(desired, velocity); + var steerVector = new V3(desired.x, 0, desired.z); + steer = steerVector.limit(MAX_FORCE); + flightVectors.push(steer); + } else { + // print('target too far away from this avatar to flee' + d); + } + } - var desired = Vec3.subtract(location, entityProps.position); - var d = Vec3.length(desired); - desired = Vec3.normalize(desired); - desired = Vec3.multiply(MAX_SPEED, desired); - if (d < 3) { - var steer = Vec3.subtract(desired, velocity); - var steerVector = new V3(desired.x, 0, desired.z); - steer = steerVector.limit(MAX_FORCE); - flightVectors.push(steer); - } else { - // print('target too far away from this avatar to flee' + d); - } } - } - - return flightVectors; + return flightVectors; } function fleeAvoiderBlocks(thisEntity) { - // print('FLEE AVOIDER BLOCKS'); - var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); - var location = properties.position; - var velocity = properties.velocity; + // print('FLEE AVOIDER BLOCKS'); + var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); + var location = properties.position; + var velocity = properties.velocity; - var nearbyEntities = Entities.findEntities(location, 2); - var flightVectors = []; - for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { - var entityID = nearbyEntities[entityIndex]; - var entityProps = Entities.getEntityProperties(entityID); - if (entityProps.name === 'Hifi-Rat-Avoider') { - // print('found an avoiderblock to flee'); - var MAX_SPEED = 11; - var MAX_FORCE = 6; + var nearbyEntities = Entities.findEntities(location, 2); + var flightVectors = []; + for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { + var entityID = nearbyEntities[entityIndex]; + var entityProps = Entities.getEntityProperties(entityID); + if (entityProps.name === 'Hifi-Rat-Avoider') { + // print('found an avoiderblock to flee'); + var MAX_SPEED = 11; + var MAX_FORCE = 6; + var FLEE_AVOIDER_RANGE = 5; - var desired = Vec3.subtract(location, entityProps.position); - var d = Vec3.length(desired); - desired = Vec3.normalize(desired); - desired = Vec3.multiply(MAX_SPEED, desired); + var desired = Vec3.subtract(location, entityProps.position); + var d = Vec3.length(desired); + desired = Vec3.normalize(desired); + desired = Vec3.multiply(MAX_SPEED, desired); - if (d < 5) { - var steer = Vec3.subtract(desired, velocity); - var steerVector = new V3(desired.x, 0, desired.z); - steer = steerVector.limit(MAX_FORCE) - flightVectors.push(steer); - } else { - //print('target too far away from this avoider to flee' + d); - } + if (d < FLEE_AVOIDER_RANGE) { + var steer = Vec3.subtract(desired, velocity); + var steerVector = new V3(desired.x, 0, desired.z); + steer = steerVector.limit(MAX_FORCE); + flightVectors.push(steer); + } else { + //print('target too far away from this avoider to flee' + d); + } + + } } - } - - return flightVectors; + return flightVectors; } function arrive(thisEntity, target) { - var targetPosition = Entities.getEntityProperties(target, "position").position; - var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); - var location = properties.position; - var velocity = properties.velocity; - var MAX_SPEED = 10; - var MAX_FORCE = 6; - var ARRIVAL_DISTANCE = 2; + var targetPosition = Entities.getEntityProperties(target, "position").position; + var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); + var location = properties.position; + var velocity = properties.velocity; + var MAX_SPEED = 10; + var MAX_FORCE = 6; + var ARRIVAL_DISTANCE = 2; - var desired = Vec3.subtract(targetPosition, location); - var d = Vec3.length(desired); - desired = Vec3.normalize(desired); + var desired = Vec3.subtract(targetPosition, location); + var d = Vec3.length(desired); + desired = Vec3.normalize(desired); - if (d < ARRIVAL_DISTANCE) { - var m = scale(d, 0, ARRIVAL_DISTANCE, 0, MAX_SPEED); - } else { - desired = Vec3.multiply(MAX_SPEED, desired); + if (d < ARRIVAL_DISTANCE) { + var m = scale(d, 0, ARRIVAL_DISTANCE, 0, MAX_SPEED); + } else { + desired = Vec3.multiply(MAX_SPEED, desired); - } + } - var steer = Vec3.subtract(desired, velocity); - var steerVector = new V3(desired.x, 0, desired.z); - steer = steerVector.limit(MAX_FORCE); + var steer = Vec3.subtract(desired, velocity); + var steerVector = new V3(desired.x, 0, desired.z); + steer = steerVector.limit(MAX_FORCE); - return steer; + return steer; } function V3(x, y, z) { - this.x = x; - this.y = y; - this.z = z; - return + this.x = x; + this.y = y; + this.z = z; + return } V3.prototype.length = function() { - return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); }; V3.prototype.limit = function(s) { - var len = this.length(); + var len = this.length(); - if (len > s && len > 0) { - this.scale(s / len); - } + if (len > s && len > 0) { + this.scale(s / len); + } - return this; + return this; }; V3.prototype.scale = function(f) { - this.x *= f; - this.y *= f; - this.z *= f; - return this; + this.x *= f; + this.y *= f; + this.z *= f; + return this; }; var v3 = new V3(); var scale = function(value, min1, max1, min2, max2) { - return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); } loadSteer = function() { - return { - flee: flee, - fleeAllAvatars: fleeAllAvatars, - fleeAvoiderBlocks: fleeAvoiderBlocks, - arrive: arrive - } + return { + flee: flee, + fleeAllAvatars: fleeAllAvatars, + fleeAvoiderBlocks: fleeAvoiderBlocks, + arrive: arrive + }; } \ No newline at end of file From dfec222c817c7f345a8e472a654fe21e2f15de7d Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 10 Dec 2015 20:39:01 -0800 Subject: [PATCH 160/174] Report animation triggers to normal javascript animationStateHandlers, and update away.js as an example. --- examples/away.js | 17 +++++++---------- libraries/animation/src/AnimVariant.cpp | 6 ++++-- libraries/animation/src/Rig.cpp | 3 ++- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/away.js b/examples/away.js index 8cc3790200..0a86815d68 100644 --- a/examples/away.js +++ b/examples/away.js @@ -14,7 +14,6 @@ // Goes into "paused" when the '.' key (and automatically when started in HMD), and normal when pressing any key. // See MAIN CONTROL, below, for what "paused" actually does. -var IK_WINDOW_AFTER_GOING_ACTIVE = 3000; // milliseconds var OVERLAY_DATA = { text: "Paused:\npress any key to continue", font: {size: 75}, @@ -31,7 +30,6 @@ function playAwayAnimation() { return {isAway: true, isNotAway: false, isNotMoving: false, ikOverlayAlpha: 0.0}; } if (stopper) { - Script.clearTimeout(stopper); stopper = false; MyAvatar.removeAnimationStateHandler(activeAnimationHandlerId); // do it now, before making new assignment } @@ -47,15 +45,14 @@ function stopAwayAnimation() { // It cannot be as soon as we want to stop the away animation, because then things will look goofy as we come out of that animation. // (Imagine an away animation that sits or kneels, and then stands back up when coming out of it. If head is at the HMD, then it won't // want to track the standing up animation.) - // Our standard anim graph flips 'awayOutroOnDone' for one frame, but it's a trigger (not an animVar) and other folks might use different graphs. - // So... Just give us a fixed amount of time to be done with animation, before we turn ik back on. + // The anim graph will trigger awayOutroOnDone when awayOutro is finished. var backToNormal = false; - stopper = Script.setTimeout(function () { - backToNormal = true; - stopper = false; - }, IK_WINDOW_AFTER_GOING_ACTIVE); + stopper = true; function animateActive(state) { - if (state.ikOverlayAlpha) { + if (state.awayOutroOnDone) { + backToNormal = true; + stopper = false; + } else if (state.ikOverlayAlpha) { // Once the right state gets reflected back to us, we don't need the hander any more. // But we are locked against handler changes during the execution of a handler, so remove asynchronously. Script.setTimeout(function () { MyAvatar.removeAnimationStateHandler(activeAnimationHandlerId); }, 0); @@ -63,7 +60,7 @@ function stopAwayAnimation() { // It might be cool to "come back to life" by fading the ik overlay back in over a short time. But let's see how this goes. return {isAway: false, isNotAway: true, ikOverlayAlpha: backToNormal ? 1.0 : 0.0}; // IWBNI we had a way of deleting an anim var. } - activeAnimationHandlerId = MyAvatar.addAnimationStateHandler(animateActive, ['isAway', 'isNotAway', 'isNotMoving', 'ikOverlayAlpha']); + activeAnimationHandlerId = MyAvatar.addAnimationStateHandler(animateActive, ['ikOverlayAlpha', 'awayOutroOnDone']); } // OVERLAY diff --git a/libraries/animation/src/AnimVariant.cpp b/libraries/animation/src/AnimVariant.cpp index 118d2e8ce9..d57d1b3c34 100644 --- a/libraries/animation/src/AnimVariant.cpp +++ b/libraries/animation/src/AnimVariant.cpp @@ -50,9 +50,11 @@ QScriptValue AnimVariantMap::animVariantMapToScriptValue(QScriptEngine* engine, if (useNames) { // copy only the requested names for (const QString& name : names) { auto search = _map.find(name); - if (search != _map.end()) { // scripts are allowed to request names that do not exist + if (search != _map.end()) { setOne(name, search->second); - } + } else if (_triggers.count(name) == 1) { + target.setProperty(name, true); + } // scripts are allowed to request names that do not exist } } else { // copy all of them diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index a80ef5d2eb..464ff28980 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -717,7 +717,8 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh // This works (I tried it), but the result would be that we would still have same runtime type checks as the invokeMethod above // (occuring within the ScriptEngine::callAnimationStateHandler invokeMethod trampoline), _plus_ another runtime check for the dynamic_cast. - // gather results in (likely from an earlier update): + // Gather results in (likely from an earlier update). + // Note: the behavior is undefined if a handler (re-)sets a trigger. Scripts should not be doing that. _animVars.copyVariantsFrom(value.results); // If multiple handlers write the same anim var, the last registgered wins. (_map preserves order). } } From 87e30a2157973550cffd47c845136199be4d401d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 11 Dec 2015 09:03:39 -0800 Subject: [PATCH 161/174] Remove EntityQuery version and just append new data to end --- libraries/networking/src/udt/PacketHeaders.cpp | 2 -- libraries/networking/src/udt/PacketHeaders.h | 3 --- libraries/octree/src/OctreeQuery.cpp | 13 +++++++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index b02e94e9e8..4daf7f83b6 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -42,8 +42,6 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: return VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP; - case PacketType::EntityQuery: - return VERSION_ENTITY_QUERY_KEYHOLE_RADIUS; case PacketType::AvatarData: case PacketType::BulkAvatarData: return 17; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 2d321233a8..5daa185af4 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -163,7 +163,4 @@ const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50; const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51; const PacketVersion VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52; -// EntityQuery versions -const PacketVersion VERSION_ENTITY_QUERY_KEYHOLE_RADIUS = 18; - #endif // hifi_PacketHeaders_h diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index b79d3775ea..5a30e178f8 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -37,8 +37,6 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip); memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition)); destinationBuffer += sizeof(_cameraEyeOffsetPosition); - memcpy(destinationBuffer, &_keyholeRadius, sizeof(_keyholeRadius)); - destinationBuffer += sizeof(_keyholeRadius); // bitMask of less than byte wide items unsigned char bitItems = 0; @@ -65,6 +63,9 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { // desired boundaryLevelAdjust memcpy(destinationBuffer, &_boundaryLevelAdjust, sizeof(_boundaryLevelAdjust)); destinationBuffer += sizeof(_boundaryLevelAdjust); + + memcpy(destinationBuffer, &_keyholeRadius, sizeof(_keyholeRadius)); + destinationBuffer += sizeof(_keyholeRadius); return destinationBuffer - bufferStart; } @@ -85,8 +86,6 @@ int OctreeQuery::parseData(ReceivedMessage& message) { sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip); memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition)); sourceBuffer += sizeof(_cameraEyeOffsetPosition); - memcpy(&_keyholeRadius, sourceBuffer, sizeof(_keyholeRadius)); - sourceBuffer += sizeof(_keyholeRadius); // optional feature flags unsigned char bitItems = 0; @@ -108,6 +107,12 @@ int OctreeQuery::parseData(ReceivedMessage& message) { memcpy(&_boundaryLevelAdjust, sourceBuffer, sizeof(_boundaryLevelAdjust)); sourceBuffer += sizeof(_boundaryLevelAdjust); + auto bytesRead = sourceBuffer - startPosition; + auto bytesLeft = message.getSize() - bytesRead; + if (bytesLeft >= sizeof(_keyholeRadius)) { + memcpy(&_keyholeRadius, sourceBuffer, sizeof(_keyholeRadius)); + sourceBuffer += sizeof(_keyholeRadius); + } return sourceBuffer - startPosition; } From 265bd8ee670db8f7aa74428c58a38b296daf34eb Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 9 Dec 2015 17:59:38 -0800 Subject: [PATCH 162/174] Moving QML rendering off the main thread --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 110 +++++++------------- 1 file changed, 39 insertions(+), 71 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 482eb1b36f..d42ae5889c 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -8,15 +8,16 @@ #include "OffscreenQmlSurface.h" #include "OglplusHelpers.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -25,9 +26,6 @@ #include "GLEscrow.h" #include "OffscreenGLCanvas.h" -// FIXME move to threaded rendering with Qt 5.5 -//#define QML_THREADED - // Time between receiving a request to render the offscreen UI actually triggering // the render. Could possibly be increased depending on the framerate we expect to // achieve. @@ -56,13 +54,11 @@ private: Q_DECLARE_LOGGING_CATEGORY(offscreenFocus) Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus") -#ifdef QML_THREADED static const QEvent::Type INIT = QEvent::Type(QEvent::User + 1); static const QEvent::Type RENDER = QEvent::Type(QEvent::User + 2); static const QEvent::Type RESIZE = QEvent::Type(QEvent::User + 3); static const QEvent::Type STOP = QEvent::Type(QEvent::User + 4); static const QEvent::Type UPDATE = QEvent::Type(QEvent::User + 5); -#endif class OffscreenQmlRenderer : public OffscreenGLCanvas { friend class OffscreenQmlSurface; @@ -70,22 +66,30 @@ public: OffscreenQmlRenderer(OffscreenQmlSurface* surface, QOpenGLContext* shareContext) : _surface(surface) { OffscreenGLCanvas::create(shareContext); -#ifdef QML_THREADED + + _renderControl = new QMyQuickRenderControl(); + + // Create a QQuickWindow that is associated with out render control. Note that this + // window never gets created or shown, meaning that it will never get an underlying + // native (platform) window. + QQuickWindow::setDefaultAlphaBuffer(true); + // Weirdness... QQuickWindow NEEDS to be created on the rendering thread, or it will refuse to render + // because it retains an internal 'context' object that retains the thread it was created on, + // regardless of whether you later move it to another thread. + _quickWindow = new QQuickWindow(_renderControl); + _quickWindow->setColor(QColor(255, 255, 255, 0)); + _quickWindow->setFlags(_quickWindow->flags() | static_cast(Qt::WA_TranslucentBackground)); + // Qt 5.5 - _renderControl->prepareThread(_renderThread); + _renderControl->prepareThread(&_thread); _context->moveToThread(&_thread); moveToThread(&_thread); _thread.setObjectName("QML Thread"); _thread.start(); post(INIT); -#else - init(); -#endif } -#ifdef QML_THREADED - bool event(QEvent *e) - { + bool event(QEvent *e) { switch (int(e->type())) { case INIT: { @@ -120,7 +124,6 @@ public: QCoreApplication::postEvent(this, new QEvent(type)); } -#endif private: @@ -143,27 +146,9 @@ private: void init() { - _renderControl = new QMyQuickRenderControl(); connect(_renderControl, &QQuickRenderControl::renderRequested, _surface, &OffscreenQmlSurface::requestRender); connect(_renderControl, &QQuickRenderControl::sceneChanged, _surface, &OffscreenQmlSurface::requestUpdate); - // Create a QQuickWindow that is associated with out render control. Note that this - // window never gets created or shown, meaning that it will never get an underlying - // native (platform) window. - QQuickWindow::setDefaultAlphaBuffer(true); - // Weirdness... QQuickWindow NEEDS to be created on the rendering thread, or it will refuse to render - // because it retains an internal 'context' object that retains the thread it was created on, - // regardless of whether you later move it to another thread. - _quickWindow = new QQuickWindow(_renderControl); - _quickWindow->setColor(QColor(255, 255, 255, 0)); - _quickWindow->setFlags(_quickWindow->flags() | static_cast(Qt::WA_TranslucentBackground)); - -#ifdef QML_THREADED - // However, because we want to use synchronous events with the quickwindow, we need to move it back to the main - // thread after it's created. - _quickWindow->moveToThread(qApp->thread()); -#endif - if (!makeCurrent()) { qWarning("Failed to make context current on render thread"); return; @@ -189,17 +174,15 @@ private: doneCurrent(); -#ifdef QML_THREADED _context->moveToThread(QCoreApplication::instance()->thread()); _cond.wakeOne(); -#endif } - void resize(const QSize& newSize) { + void resize() { // Update our members if (_quickWindow) { - _quickWindow->setGeometry(QRect(QPoint(), newSize)); - _quickWindow->contentItem()->setSize(newSize); + _quickWindow->setGeometry(QRect(QPoint(), _newSize)); + _quickWindow->contentItem()->setSize(_newSize); } // Qt bug in 5.4 forces this check of pixel ratio, @@ -209,7 +192,7 @@ private: pixelRatio = _renderControl->_renderWindow->devicePixelRatio(); } - uvec2 newOffscreenSize = toGlm(newSize * pixelRatio); + uvec2 newOffscreenSize = toGlm(_newSize * pixelRatio); _textures.setSize(newOffscreenSize); if (newOffscreenSize == _size) { return; @@ -222,7 +205,7 @@ private: return; } - qDebug() << "Offscreen UI resizing to " << newSize.width() << "x" << newSize.height() << " with pixel ratio " << pixelRatio; + qDebug() << "Offscreen UI resizing to " << _newSize.width() << "x" << _newSize.height() << " with pixel ratio " << pixelRatio; setupFbo(); doneCurrent(); } @@ -241,11 +224,8 @@ private: //Q_ASSERT(toGlm(_quickWindow->geometry().size()) == _textures._size); _renderControl->sync(); -#ifdef QML_THREADED _cond.wakeOne(); lock->unlock(); -#endif - using namespace oglplus; @@ -271,20 +251,14 @@ private: } void aboutToQuit() { -#ifdef QML_THREADED QMutexLocker lock(&_quitMutex); _quit = true; -#endif } void stop() { -#ifdef QML_THREADED - QMutexLocker lock(&_quitMutex); + QMutexLocker lock(&_mutex); post(STOP); _cond.wait(&_mutex); -#else - cleanup(); -#endif } bool allowNewFrame(uint8_t fps) { @@ -297,13 +271,12 @@ private: QQuickWindow* _quickWindow{ nullptr }; QMyQuickRenderControl* _renderControl{ nullptr }; -#ifdef QML_THREADED QThread _thread; QMutex _mutex; QWaitCondition _cond; QMutex _quitMutex; -#endif + QSize _newSize; bool _quit; FramebufferPtr _fbo; RenderbufferPtr _depthStencil; @@ -346,9 +319,7 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { } void OffscreenQmlSurface::resize(const QSize& newSize) { -#ifdef QML_THREADED - QMutexLocker _locker(&(_renderer->_mutex)); -#endif + if (!_renderer || !_renderer->_quickWindow) { QSize currentSize = _renderer->_quickWindow->geometry().size(); if (newSize == currentSize) { @@ -362,11 +333,12 @@ void OffscreenQmlSurface::resize(const QSize& newSize) { _rootItem->setSize(newSize); } -#ifdef QML_THREADED + { + QMutexLocker _locker(&(_renderer->_mutex)); + _renderer->_newSize = newSize; + } + _renderer->post(RESIZE); -#else - _renderer->resize(newSize); -#endif } QQuickItem* OffscreenQmlSurface::getRootItem() { @@ -466,11 +438,7 @@ void OffscreenQmlSurface::updateQuick() { } if (_render) { -#ifdef QML_THREADED _renderer->post(RENDER); -#else - _renderer->render(nullptr); -#endif _render = false; } From 8497931cb4b43eac49f1ab7b840235eff5d51a5d Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 11 Dec 2015 10:29:14 -0800 Subject: [PATCH 163/174] Changing the path to the win sdk to x64 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab88e9e46a..e0123880df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ if (WIN32) if (MSVC10) set(WINDOW_SDK_PATH "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1 ") elseif (MSVC12) - set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x86 ") + set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x64 ") endif () message (WINDOW_SDK_PATH= ${WINDOW_SDK_PATH}) set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${WINDOW_SDK_PATH}) From 94b6ca4450179b5b360b7765c96fc112799f0616 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 11 Dec 2015 10:48:58 -0800 Subject: [PATCH 164/174] FIxing the bad lambda capture for local variables --- libraries/render-utils/src/Model.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index e7c4442755..99261a02b4 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -120,7 +120,7 @@ void Model::enqueueLocationChange() { render::PendingChanges pendingChanges; foreach (auto itemID, _renderItems.keys()) { - pendingChanges.updateItem(itemID, [=](MeshPartPayload& data) { + pendingChanges.updateItem(itemID, [transform, offset](MeshPartPayload& data) { data.updateTransform(transform, offset); data.notifyLocationChanged(); }); @@ -505,7 +505,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan auto item = scene->allocateID(); auto renderPayload = std::make_shared(renderItem); pendingChanges.resetItem(item, renderPayload); - pendingChanges.updateItem(item, [&](MeshPartPayload& data) { + pendingChanges.updateItem(item, [](MeshPartPayload& data) { data.notifyLocationChanged(); }); _renderItems.insert(item, renderPayload); @@ -533,7 +533,7 @@ bool Model::addToScene(std::shared_ptr scene, auto renderPayload = std::make_shared(renderItem); renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(item, renderPayload); - pendingChanges.updateItem(item, [&](MeshPartPayload& data) { + pendingChanges.updateItem(item, [](MeshPartPayload& data) { data.notifyLocationChanged(); }); _renderItems.insert(item, renderPayload); @@ -1210,7 +1210,7 @@ bool Model::initWhenReady(render::ScenePointer scene) { auto renderPayload = std::make_shared(renderItem); _renderItems.insert(item, renderPayload); pendingChanges.resetItem(item, renderPayload); - pendingChanges.updateItem(item, [&](MeshPartPayload& data) { + pendingChanges.updateItem(item, [transform,offset](MeshPartPayload& data) { data.updateTransform(transform, offset); data.notifyLocationChanged(); }); From 93dbc92c613efd80a392355333c8f454d95b31d8 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 11 Dec 2015 10:59:36 -0800 Subject: [PATCH 165/174] Adding the correct selection of the winSDK based on the generator used --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e0123880df..a8271abd8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,12 @@ if (WIN32) if (MSVC10) set(WINDOW_SDK_PATH "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1 ") elseif (MSVC12) - set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x64 ") + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(WINDOW_SDK_FOLDER "x64") + else() + set(WINDOW_SDK_FOLDER "x86") + endif() + set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\${WINDOW_SDK_FOLDER}") endif () message (WINDOW_SDK_PATH= ${WINDOW_SDK_PATH}) set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${WINDOW_SDK_PATH}) From ae1345bb13275e4e7cb2f0bd84ff08c09b0c5696 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 10 Dec 2015 14:04:34 -0800 Subject: [PATCH 166/174] Adding nsight instrumenting to the QML render thread --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 35 ++++++++++--------- libraries/gpu/src/gpu/Batch.cpp | 7 ---- libraries/gpu/src/gpu/Batch.h | 14 ++------ libraries/shared/CMakeLists.txt | 1 + libraries/shared/src/shared/NsightHelpers.cpp | 22 ++++++++++++ libraries/shared/src/shared/NsightHelpers.h | 24 +++++++++++++ 6 files changed, 67 insertions(+), 36 deletions(-) create mode 100644 libraries/shared/src/shared/NsightHelpers.cpp create mode 100644 libraries/shared/src/shared/NsightHelpers.h diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index d42ae5889c..d30294ae7c 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include "GLEscrow.h" #include "OffscreenGLCanvas.h" + // Time between receiving a request to render the offscreen UI actually triggering // the render. Could possibly be increased depending on the framerate we expect to // achieve. @@ -220,9 +222,6 @@ private: return; } - //Q_ASSERT(toGlm(_quickWindow->geometry().size()) == _size); - //Q_ASSERT(toGlm(_quickWindow->geometry().size()) == _textures._size); - _renderControl->sync(); _cond.wakeOne(); lock->unlock(); @@ -231,22 +230,24 @@ private: _quickWindow->setRenderTarget(GetName(*_fbo), QSize(_size.x, _size.y)); - TexturePtr texture = _textures.getNextTexture(); - _fbo->Bind(Framebuffer::Target::Draw); - _fbo->AttachTexture(Framebuffer::Target::Draw, FramebufferAttachment::Color, *texture, 0); - _fbo->Complete(Framebuffer::Target::Draw); - //Context::Clear().ColorBuffer(); { - _renderControl->render(); - // FIXME The web browsers seem to be leaving GL in an error state. - // Need a debug context with sync logging to figure out why. - // for now just clear the errors - glGetError(); + PROFILE_RANGE("qml_render") + TexturePtr texture = _textures.getNextTexture(); + _fbo->Bind(Framebuffer::Target::Draw); + _fbo->AttachTexture(Framebuffer::Target::Draw, FramebufferAttachment::Color, *texture, 0); + _fbo->Complete(Framebuffer::Target::Draw); + { + _renderControl->render(); + // FIXME The web browsers seem to be leaving GL in an error state. + // Need a debug context with sync logging to figure out why. + // for now just clear the errors + glGetError(); + } + // FIXME probably unecessary + DefaultFramebuffer().Bind(Framebuffer::Target::Draw); + _quickWindow->resetOpenGLState(); + _escrow.submit(GetName(*texture)); } - // FIXME probably unecessary - DefaultFramebuffer().Bind(Framebuffer::Target::Draw); - _quickWindow->resetOpenGLState(); - _escrow.submit(GetName(*texture)); _lastRenderTime = usecTimestampNow(); } diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 80b3a4f158..14871aafd1 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -16,13 +16,6 @@ #if defined(NSIGHT_FOUND) #include "nvToolsExt.h" -ProfileRange::ProfileRange(const char *name) { - nvtxRangePush(name); -} -ProfileRange::~ProfileRange() { - nvtxRangePop(); -} - ProfileRangeBatch::ProfileRangeBatch(gpu::Batch& batch, const char *name) : _batch(batch) { _batch.pushProfileRange(name); } diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index da1f13151e..2afcc7caa9 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -15,6 +15,8 @@ #include #include +#include + #include "Framebuffer.h" #include "Pipeline.h" #include "Query.h" @@ -22,18 +24,6 @@ #include "Texture.h" #include "Transform.h" - -#if defined(NSIGHT_FOUND) - class ProfileRange { - public: - ProfileRange(const char *name); - ~ProfileRange(); - }; -#define PROFILE_RANGE(name) ProfileRange profileRangeThis(name); -#else -#define PROFILE_RANGE(name) -#endif - class QDebug; namespace gpu { diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index 2691c51128..489819747f 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -4,3 +4,4 @@ set(TARGET_NAME shared) setup_hifi_library(Gui Network Script Widgets) target_zlib() +target_nsight() diff --git a/libraries/shared/src/shared/NsightHelpers.cpp b/libraries/shared/src/shared/NsightHelpers.cpp new file mode 100644 index 0000000000..e48e228588 --- /dev/null +++ b/libraries/shared/src/shared/NsightHelpers.cpp @@ -0,0 +1,22 @@ +// +// Created by Bradley Austin Davis on 2015/12/10 +// 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 "NsightHelpers.h" + +#if defined(NSIGHT_FOUND) +#include "nvToolsExt.h" + +ProfileRange::ProfileRange(const char *name) { + nvtxRangePush(name); +} + +ProfileRange::~ProfileRange() { + nvtxRangePop(); +} + +#endif diff --git a/libraries/shared/src/shared/NsightHelpers.h b/libraries/shared/src/shared/NsightHelpers.h new file mode 100644 index 0000000000..3acdf14411 --- /dev/null +++ b/libraries/shared/src/shared/NsightHelpers.h @@ -0,0 +1,24 @@ +// +// Created by Bradley Austin Davis on 2015/12/10 +// 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 +// +#pragma once +#ifndef hifi_gl_NsightHelpers_h +#define hifi_gl_NsightHelpers_h + +#if defined(NSIGHT_FOUND) + class ProfileRange { + public: + ProfileRange(const char *name); + ~ProfileRange(); + }; +#define PROFILE_RANGE(name) ProfileRange profileRangeThis(name); +#else +#define PROFILE_RANGE(name) +#endif + + +#endif \ No newline at end of file From a1a3c4470cd3aca98b7ec4c4bfcb5c48ef0a1704 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 11 Dec 2015 11:02:16 -0800 Subject: [PATCH 167/174] reload own avatar on Content Reload --- interface/src/Application.cpp | 2 ++ interface/src/avatar/MyAvatar.cpp | 8 ++++++++ interface/src/avatar/MyAvatar.h | 2 ++ 3 files changed, 12 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 82663d39a8..24175c0cac 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2763,6 +2763,8 @@ void Application::reloadResourceCaches() { DependencyManager::get()->refreshAll(); DependencyManager::get()->reset(); // Force redownload of .fst models + + getMyAvatar()->resetFullAvatarURL(); } void Application::rotationModeChanged() { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4537ab8bb9..b3f6b4c238 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -986,6 +986,14 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _headBoneSet.clear(); } + +void MyAvatar::resetFullAvatarURL() { + auto lastAvatarURL = getFullAvatarURLFromPreferences(); + auto lastAvatarName = getFullAvatarModelName(); + useFullAvatarURL(QUrl()); + useFullAvatarURL(lastAvatarURL, lastAvatarName); +} + void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) { if (QThread::currentThread() != thread()) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 309e600978..514261bf16 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -196,6 +196,8 @@ public: Q_INVOKABLE void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString()); Q_INVOKABLE const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; } Q_INVOKABLE const QString& getFullAvatarModelName() const { return _fullAvatarModelName; } + void resetFullAvatarURL(); + virtual void setAttachmentData(const QVector& attachmentData) override; From d918eca03005bdfdca746acb7541c5c44bb4b2b5 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 11 Dec 2015 11:36:02 -0800 Subject: [PATCH 168/174] reset skybox on changing domains --- interface/src/Application.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 82663d39a8..4c694e0294 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3429,10 +3429,10 @@ namespace render { // Background rendering decision auto skyStage = DependencyManager::get()->getSkyStage(); - auto skybox = model::SkyboxPointer(); if (skyStage->getBackgroundMode() == model::SunSkyStage::NO_BACKGROUND) { + // this line intentionally left blank } else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_DOME) { - if (/*!selfAvatarOnly &&*/ Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { PerformanceTimer perfTimer("stars"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::payloadRender() ... stars..."); @@ -3498,8 +3498,7 @@ namespace render { } } else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) { PerformanceTimer perfTimer("skybox"); - - skybox = skyStage->getSkybox(); + auto skybox = skyStage->getSkybox(); if (skybox) { skybox->render(batch, *(qApp->getDisplayViewFrustum())); } @@ -3765,6 +3764,10 @@ void Application::clearDomainOctreeDetails() { // reset the model renderer getEntities()->clear(); + + auto skyStage = DependencyManager::get()->getSkyStage(); + skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME); + } void Application::domainChanged(const QString& domainHostname) { From a31ba089c1623e897f74e18126614ce4009f8a4e Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 11 Dec 2015 11:49:00 -0800 Subject: [PATCH 169/174] semicolons and print statements --- examples/drylake/ratCreator.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index c20ce9e2ad..6dc2531cb1 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -297,7 +297,7 @@ function moveRats() { if (j === 0) { averageAvoiderFlight = avoidBlockVectors[0]; } else { - averageAvoiderFlight = Vec3.sum(avoidBlockVectors[j - 1], avoidBlockVectors[j]) + averageAvoiderFlight = Vec3.sum(avoidBlockVectors[j - 1], avoidBlockVectors[j]); } }; averageAvoiderFlight = Vec3.multiply(averageAvoiderFlight, 1 / avoidBlockVectors.length); @@ -341,16 +341,15 @@ function moveRats() { if (metaRat !== undefined) { if (metaRat.injector !== undefined) { if (metaRat.injector.isPlaying === true) { - // print('update injector position') metaRat.injector.options = { loop: true, position: ratPosition - } + }; } } } else { - // print('no meta rat for this rat') + // no meta rat for this rat } }) } @@ -362,10 +361,10 @@ function checkDistanceFromNest(rat) { var ratProps = Entities.getEntityProperties(rat, "position"); var distance = Vec3.distance(ratProps.position, RAT_NEST_LOCATION); if (distance < RAT_IN_NEST_DISTANCE) { - //print('at nest') + //at nest removeRatFromScene(rat); } else { - // print('not yet at nest:::' + distance) + //not yet at nest } } @@ -373,7 +372,6 @@ function removeRatFromScene(rat) { var index = rats.indexOf(rat); if (index > -1) { - // print('CLEAR RAT::'+rat) rats.splice(index, 1); Entities.deleteEntity(rat); @@ -381,7 +379,6 @@ function removeRatFromScene(rat) { var metaRatIndex = findWithAttr(metaRats, 'rat', rat); if (metaRatIndex > -1) { - // print('CLEAR META RAT') metaRats[index].injector.stop(); metaRats.splice(index, 1); } From 35da54fc6c910964f48a406922db2d0d4a7ae51d Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 11 Dec 2015 11:51:32 -0800 Subject: [PATCH 170/174] dead code and print statements --- examples/drylake/ratCreator.js | 4 ---- examples/drylake/ratSteer.js | 11 ++++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js index 6dc2531cb1..237b8ec32f 100644 --- a/examples/drylake/ratCreator.js +++ b/examples/drylake/ratCreator.js @@ -348,8 +348,6 @@ function moveRats() { } } - } else { - // no meta rat for this rat } }) } @@ -363,8 +361,6 @@ function checkDistanceFromNest(rat) { if (distance < RAT_IN_NEST_DISTANCE) { //at nest removeRatFromScene(rat); - } else { - //not yet at nest } } diff --git a/examples/drylake/ratSteer.js b/examples/drylake/ratSteer.js index a4addf4e52..e9a2647ff5 100644 --- a/examples/drylake/ratSteer.js +++ b/examples/drylake/ratSteer.js @@ -30,7 +30,7 @@ function flee(thisEntity, target) { return steer; } else { - // print('target too far away to flee' + d); + //target too far away to flee return } } @@ -47,7 +47,7 @@ function fleeAllAvatars(thisEntity) { var entityID = nearbyEntities[entityIndex]; var entityProps = Entities.getEntityProperties(entityID); if (entityProps.name === 'Hifi-Avatar-Detector') { - //print('found an avatar to flee') + //found an avatar to flee var MAX_SPEED = 8; var MAX_FORCE = 8; @@ -62,7 +62,7 @@ function fleeAllAvatars(thisEntity) { steer = steerVector.limit(MAX_FORCE); flightVectors.push(steer); } else { - // print('target too far away from this avatar to flee' + d); + // target too far away from this avatar to flee } } @@ -83,7 +83,8 @@ function fleeAvoiderBlocks(thisEntity) { var entityID = nearbyEntities[entityIndex]; var entityProps = Entities.getEntityProperties(entityID); if (entityProps.name === 'Hifi-Rat-Avoider') { - // print('found an avoiderblock to flee'); + //found an avoiderblock to flee + var MAX_SPEED = 11; var MAX_FORCE = 6; var FLEE_AVOIDER_RANGE = 5; @@ -99,7 +100,7 @@ function fleeAvoiderBlocks(thisEntity) { steer = steerVector.limit(MAX_FORCE); flightVectors.push(steer); } else { - //print('target too far away from this avoider to flee' + d); + //target too far away from this avoider to flee } } From 04b8251a832c9aa0fd3844c47c2a4f2e46857b5c Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 10 Dec 2015 14:05:19 -0800 Subject: [PATCH 171/174] Refactoring escrow due to long unsignaled syncs reported by Philip --- libraries/gl/src/gl/GLEscrow.h | 96 ++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 39 deletions(-) diff --git a/libraries/gl/src/gl/GLEscrow.h b/libraries/gl/src/gl/GLEscrow.h index d860f1239c..9da3ce0b0b 100644 --- a/libraries/gl/src/gl/GLEscrow.h +++ b/libraries/gl/src/gl/GLEscrow.h @@ -49,35 +49,32 @@ template < > class GLEscrow { public: + static const uint64_t MAX_UNSIGNALED_TIME = USECS_PER_SECOND / 2; struct Item { - T _value; + const T _value; GLsync _sync; - uint64_t _created; + const uint64_t _created; Item(T value, GLsync sync) : _value(value), _sync(sync), _created(usecTimestampNow()) { } - uint64_t age() { + uint64_t age() const { return usecTimestampNow() - _created; } - bool signaled() { + bool signaled() const { auto result = glClientWaitSync(_sync, 0, 0); if (GL_TIMEOUT_EXPIRED != result && GL_WAIT_FAILED != result) { return true; } - if (age() > (USECS_PER_SECOND / 2)) { - qWarning() << "Long unsignaled sync"; - } return false; } }; - using Mutex = std::recursive_mutex; - using Lock = std::unique_lock; + using Mutex = std::mutex; using Recycler = std::function; // deque gives us random access, double ended push & pop and size, all in constant time using Deque = std::deque; @@ -87,9 +84,32 @@ public: _recycler = recycler; } - size_t depth() { + template + void withLock(F f) { + using Lock = std::unique_lock; Lock lock(_mutex); - return _submits.size(); + f(); + } + + template + bool tryLock(F f) { + using Lock = std::unique_lock; + bool result = false; + Lock lock(_mutex, std::try_to_lock_t()); + if (lock.owns_lock()) { + f(); + result = true; + } + return result; + } + + + size_t depth() { + size_t result{ 0 }; + withLock([&]{ + result = _submits.size(); + }); + return result; } // Submit a new resource from the producer context @@ -104,11 +124,9 @@ public: glFlush(); } - { - Lock lock(_mutex); + withLock([&]{ _submits.push_back(Item(t, writeSync)); - } - + }); return cleanTrash(); } @@ -120,13 +138,13 @@ public: // On the one hand using try_lock() reduces the chance of blocking the consumer thread, // but if the produce thread is going fast enough, it could effectively // starve the consumer out of ever actually getting resources. - if (_mutex.try_lock()) { + tryLock([&]{ + // May be called on any thread, but must be inside a locked section if (signaled(_submits, 0)) { result = _submits.at(0)._value; _submits.pop_front(); } - _mutex.unlock(); - } + }); return result; } @@ -154,37 +172,45 @@ public: glFlush(); } - Lock lock(_mutex); - _releases.push_back(Item(t, readSync)); + withLock([&]{ + _releases.push_back(Item(t, readSync)); + }); } private: size_t cleanTrash() { size_t wastedWork{ 0 }; List trash; - { + tryLock([&]{ + while (!_submits.empty()) { + const auto& item = _submits.front(); + if (!item._sync || item.age() < MAX_UNSIGNALED_TIME) { + break; + } + qWarning() << "Long unsignaled sync " << item._sync << " unsignaled for " << item.age(); + _trash.push_front(item); + _submits.pop_front(); + } + // We only ever need one ready item available in the list, so if the // second item is signaled (implying the first is as well, remove the first // item. Iterate until the SECOND item in the list is not in the ready state // The signaled function takes care of checking against the deque size while (signaled(_submits, 1)) { - pop(_submits); + _trash.push_front(_submits.front()); + _submits.pop_front(); ++wastedWork; } // Stuff in the release queue can be cleared out as soon as it's signaled while (signaled(_releases, 0)) { - pop(_releases); + _trash.push_front(_releases.front()); + _releases.pop_front(); } - { - // FIXME I don't think this lock should be necessary, only the submitting thread - // touches the trash - Lock lock(_mutex); - trash.swap(_trash); - } - } - + trash.swap(_trash); + }); + // FIXME maybe doing a timing on the deleters and warn if it's taking excessive time? // although we are out of the lock, so it shouldn't be blocking anything std::for_each(trash.begin(), trash.end(), [&](typename List::const_reference item) { @@ -198,14 +224,6 @@ private: return wastedWork; } - // May be called on any thread, but must be inside a locked section - void pop(Deque& deque) { - Lock lock(_mutex); - auto& item = deque.front(); - _trash.push_front(item); - deque.pop_front(); - } - // May be called on any thread, but must be inside a locked section bool signaled(Deque& deque, size_t i) { if (i >= deque.size()) { From 920e2941b98ccbb44f725f3613483e65a773921c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 11 Dec 2015 15:31:56 -0800 Subject: [PATCH 172/174] don't crash when a child no longer has a containing element --- libraries/entities/src/EntityTree.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 5090ebb7e0..fb2acf3fe7 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -226,9 +226,16 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI while (!toProcess.empty()) { EntityItemPointer childEntity = std::static_pointer_cast(toProcess.dequeue()); + if (!childEntity) { + continue; + } BoundingBoxRelatedProperties newChildBBRelProperties(childEntity); + EntityTreeElementPointer containingElement = childEntity->getElement(); + if (!containingElement) { + continue; + } UpdateEntityOperator theChildOperator(getThisPointer(), - childEntity->getElement(), + containingElement, childEntity, newChildBBRelProperties); recurseTreeWithOperator(&theChildOperator); foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) { From 68134aafe5d22fe1efe19bbdc65fac32f9dfa4bc Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 11 Dec 2015 16:14:55 -0800 Subject: [PATCH 173/174] Fix the broken skybox and simplify a bit the vertex shader used --- interface/src/Application.cpp | 2 +- libraries/gpu/src/gpu/Transform.slh | 2 +- libraries/model/src/model/Skybox.cpp | 12 ------------ libraries/model/src/model/Skybox.slv | 15 ++++++++++----- .../src/procedural/ProceduralSkybox.cpp | 10 ---------- 5 files changed, 12 insertions(+), 29 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 24175c0cac..3f8b14a38d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3503,7 +3503,7 @@ namespace render { skybox = skyStage->getSkybox(); if (skybox) { - skybox->render(batch, *(qApp->getDisplayViewFrustum())); + skybox->render(batch, *(args->_viewFrustum)); } } } diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 9a866ca4d0..26ea9784be 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -135,7 +135,7 @@ TransformCamera getTransformCamera() { <@func transformClipToEyeDir(cameraTransform, clipPos, eyeDir)@> { // transformClipToEyeDir - <$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 0.0)); + <$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 1.0)); // Must be 1.0 here } <@endfunc@> diff --git a/libraries/model/src/model/Skybox.cpp b/libraries/model/src/model/Skybox.cpp index 3e445933fa..8c37359638 100755 --- a/libraries/model/src/model/Skybox.cpp +++ b/libraries/model/src/model/Skybox.cpp @@ -71,22 +71,12 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) { // Create the static shared elements used to render the skybox - static gpu::BufferPointer theBuffer; - static gpu::Stream::FormatPointer theFormat; static gpu::BufferPointer theConstants; static gpu::PipelinePointer thePipeline; const int SKYBOX_SKYMAP_SLOT = 0; const int SKYBOX_CONSTANTS_SLOT = 0; static std::once_flag once; std::call_once(once, [&] { - { - const float CLIP = 1.0f; - const glm::vec2 vertices[4] = { { -CLIP, -CLIP }, { CLIP, -CLIP }, { -CLIP, CLIP }, { CLIP, CLIP } }; - theBuffer = std::make_shared(sizeof(vertices), (const gpu::Byte*) vertices); - theFormat = std::make_shared(); - theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); - } - { auto skyVS = gpu::Shader::createVertex(std::string(Skybox_vert)); auto skyFS = gpu::Shader::createPixel(std::string(Skybox_frag)); @@ -115,8 +105,6 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky batch.setProjectionTransform(projMat); batch.setViewTransform(viewTransform); batch.setModelTransform(Transform()); // only for Mac - batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8); - batch.setInputFormat(theFormat); gpu::TexturePointer skymap; if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) { diff --git a/libraries/model/src/model/Skybox.slv b/libraries/model/src/model/Skybox.slv index d1b9a20a66..810afb1033 100755 --- a/libraries/model/src/model/Skybox.slv +++ b/libraries/model/src/model/Skybox.slv @@ -11,21 +11,26 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - -<@include gpu/Inputs.slh@> - <@include gpu/Transform.slh@> <$declareStandardTransform()$> out vec3 _normal; -void main(void) { +void main(void) { + const float depth = 0.0; + const vec4 UNIT_QUAD[4] = vec4[4]( + vec4(-1.0, -1.0, depth, 1.0), + vec4(1.0, -1.0, depth, 1.0), + vec4(-1.0, 1.0, depth, 1.0), + vec4(1.0, 1.0, depth, 1.0) + ); + vec4 inPosition = UNIT_QUAD[gl_VertexID]; + // standard transform TransformCamera cam = getTransformCamera(); vec3 clipDir = vec3(inPosition.xy, 0.0); vec3 eyeDir; - <$transformClipToEyeDir(cam, clipDir, eyeDir)$> <$transformEyeToWorldDir(cam, eyeDir, _normal)$> diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index bd61de7338..68645045b4 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -51,14 +51,6 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, static gpu::Stream::FormatPointer theFormat; if (skybox._procedural && skybox._procedural->_enabled && skybox._procedural->ready()) { - if (!theBuffer) { - const float CLIP = 1.0f; - const glm::vec2 vertices[4] = { { -CLIP, -CLIP }, { CLIP, -CLIP }, { -CLIP, CLIP }, { CLIP, CLIP } }; - theBuffer = std::make_shared(sizeof(vertices), (const gpu::Byte*) vertices); - theFormat = std::make_shared(); - theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); - } - glm::mat4 projMat; viewFrustum.evalProjectionMatrix(projMat); @@ -67,8 +59,6 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, batch.setProjectionTransform(projMat); batch.setViewTransform(viewTransform); batch.setModelTransform(Transform()); // only for Mac - batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8); - batch.setInputFormat(theFormat); if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) { batch.setResourceTexture(0, skybox.getCubemap()); From 8ec84bdde826edecdc5260abf6bde4239f4d892e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 11 Dec 2015 17:35:18 -0800 Subject: [PATCH 174/174] don't simulate model until it has geometry --- .../src/RenderableModelEntityItem.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f2826db43f..b5203ea460 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -455,13 +455,6 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { return false; // hmm... } - if (_needsInitialSimulation) { - // the _model's offset will be wrong until _needsInitialSimulation is false - PerformanceTimer perfTimer("_model->simulate"); - _model->simulate(0.0f); - _needsInitialSimulation = false; - } - assert(!_model->getCollisionURL().isEmpty()); if (_model->getURL().isEmpty()) { @@ -475,6 +468,14 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { if ((collisionNetworkGeometry && collisionNetworkGeometry->isLoaded()) && (renderNetworkGeometry && renderNetworkGeometry->isLoaded())) { // we have both URLs AND both geometries AND they are both fully loaded. + + if (_needsInitialSimulation) { + // the _model's offset will be wrong until _needsInitialSimulation is false + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + _needsInitialSimulation = false; + } + return true; }