From a9379c41fe1226a44bd25e69618073bd2acfe3d1 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 16 Nov 2015 19:04:07 -0800 Subject: [PATCH 01/43] 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 02/43] 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 03/43] 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 04/43] 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 05/43] 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 06/43] 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 07/43] 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 2ff4e87a933e775331f109ebac842495f84eed15 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 23 Nov 2015 18:28:57 -0800 Subject: [PATCH 08/43] 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 1776b08e1b8fb84052c1ea752b8c327136ae3d85 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 24 Nov 2015 17:35:18 -0800 Subject: [PATCH 09/43] 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 fe0a732b5dc46a38099779c7ea1d3b091681bd06 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 27 Nov 2015 13:11:00 -0800 Subject: [PATCH 10/43] 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 cd4ac8ac69880f11626a27dce090f4e2c22b206d Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 30 Nov 2015 12:44:06 -0800 Subject: [PATCH 11/43] 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 12/43] 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 a9aecb5c494d07fc3633c2849a5f20f3c521af74 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 4 Dec 2015 13:54:59 -0800 Subject: [PATCH 13/43] 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 14/43] 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 15/43] 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 16/43] 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 17/43] 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 18/43] 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 19/43] 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 20/43] 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 873496e64b68ca57b76744429aa9b9b156cbffd7 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 7 Dec 2015 13:53:40 -0800 Subject: [PATCH 21/43] 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 22/43] 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 b16822ed8a8cfc303c3223188080013139e68610 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 9 Dec 2015 18:41:06 -0800 Subject: [PATCH 23/43] 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 b5e3dce3763986758ca8ed729bae46134357c3cf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 10 Dec 2015 14:34:28 -0800 Subject: [PATCH 24/43] 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 25/43] 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 26/43] 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 6acf3603d047faafe3de31ff8404fad4c697a7f6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 10 Dec 2015 14:58:08 -0800 Subject: [PATCH 27/43] 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 99bc47867ac769b1d27c7028096c5bac2c9058f3 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 18:16:01 -0800 Subject: [PATCH 28/43] 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 29/43] 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 30/43] 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 31/43] 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 32/43] 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 33/43] 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 34/43] 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 35/43] 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 36/43] 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 37/43] 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 38/43] 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 39/43] 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 40/43] 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 41/43] 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 42/43] 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 43/43] 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; }