diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 6d37f66563..1b41636874 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -36,11 +36,8 @@ public: public slots: void run(); - void readPendingDatagrams(); -signals: - void willSendAudioDataCallback(); - void willSendVisualDataCallback(); + private: ScriptEngine _scriptEngine; VoxelEditPacketSender _voxelEditSender; diff --git a/domain-server/resources/web/assignment/placeholder.js b/domain-server/resources/web/assignment/placeholder.js index 7c84767f31..46a706999f 100644 --- a/domain-server/resources/web/assignment/placeholder.js +++ b/domain-server/resources/web/assignment/placeholder.js @@ -114,7 +114,7 @@ function sendNextCells() { var sentFirstBoard = false; -function step() { +function step(deltaTime) { if (sentFirstBoard) { // we've already sent the first full board, perform a step in time updateCells(); @@ -127,5 +127,5 @@ function step() { } -Script.willSendVisualDataCallback.connect(step); +Script.update.connect(step); Voxels.setPacketsPerSecond(200); \ No newline at end of file diff --git a/examples/audioBall.js b/examples/audioBall.js index 676b9118b3..0889d9eb31 100644 --- a/examples/audioBall.js +++ b/examples/audioBall.js @@ -18,7 +18,7 @@ var FACTOR = 0.75; var countParticles = 0; // the first time around we want to create the particle and thereafter to modify it. var particleID; -function updateParticle() { +function updateParticle(deltaTime) { // the particle should be placed in front of the user's avatar var avatarFront = Quat.getFront(MyAvatar.orientation); @@ -62,7 +62,7 @@ function updateParticle() { } // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(updateParticle); +Script.update.connect(updateParticle); // register our scriptEnding callback Script.scriptEnding.connect(function scriptEnding() {}); diff --git a/examples/bot.js b/examples/bot.js index 162dde9dae..5fd4785b76 100644 --- a/examples/bot.js +++ b/examples/bot.js @@ -109,7 +109,7 @@ Agent.isAvatar = true; Avatar.position = firstPosition; printVector("New bot, position = ", Avatar.position); -function updateBehavior() { +function updateBehavior(deltaTime) { if (Math.random() < CHANCE_OF_SOUND) { playRandomSound(Avatar.position); } @@ -149,7 +149,7 @@ function updateBehavior() { } } } -Script.willSendVisualDataCallback.connect(updateBehavior); +Script.update.connect(updateBehavior); function loadSounds() { sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/AB1.raw")); diff --git a/examples/cameraExample.js b/examples/cameraExample.js index d55f376b76..ddfff15935 100644 --- a/examples/cameraExample.js +++ b/examples/cameraExample.js @@ -20,9 +20,8 @@ var joysticksCaptured = false; var THRUST_CONTROLLER = 0; var VIEW_CONTROLLER = 1; -function checkCamera() { +function checkCamera(deltaTime) { if (Camera.getMode() == "independent") { - var deltaTime = 1/60; // approximately our FPS - maybe better to be elapsed time since last call var THRUST_MAG_UP = 800.0; var THRUST_MAG_DOWN = 300.0; var THRUST_MAG_FWD = 500.0; @@ -80,7 +79,7 @@ function checkCamera() { } } -Script.willSendVisualDataCallback.connect(checkCamera); +Script.update.connect(checkCamera); function mouseMoveEvent(event) { print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y); diff --git a/examples/clap.js b/examples/clap.js index 81ccda64b7..ef8b61f05a 100644 --- a/examples/clap.js +++ b/examples/clap.js @@ -28,7 +28,7 @@ var clapping = new Array(); clapping[0] = false; clapping[1] = false; -function maybePlaySound() { +function maybePlaySound(deltaTime) { // Set the location and other info for the sound to play var palm1Position = Controller.getSpatialControlPosition(0); var palm2Position = Controller.getSpatialControlPosition(2); @@ -62,4 +62,4 @@ function maybePlaySound() { } // Connect a call back that happens every frame -Script.willSendVisualDataCallback.connect(maybePlaySound); \ No newline at end of file +Script.update.connect(maybePlaySound); \ No newline at end of file diff --git a/examples/collidingParticles.js b/examples/collidingParticles.js index 81ccfe108b..5a1d09b024 100644 --- a/examples/collidingParticles.js +++ b/examples/collidingParticles.js @@ -58,7 +58,7 @@ var color = { green: 255, blue: 0 }; -function draw() { +function draw(deltaTime) { print("hello... draw()... currentIteration=" + currentIteration + "\n"); // on the first iteration, setup a single particle that's slowly moving @@ -150,5 +150,5 @@ function draw() { // register the call back so it fires before each data send print("here...\n"); Particles.setPacketsPerSecond(40000); -Script.willSendVisualDataCallback.connect(draw); +Script.update.connect(draw); print("and here...\n"); diff --git a/examples/controllerExample.js b/examples/controllerExample.js index 43a7b12231..ebb013913e 100644 --- a/examples/controllerExample.js +++ b/examples/controllerExample.js @@ -16,7 +16,7 @@ for (t = 0; t < numberOfTriggers; t++) { triggerPulled[t] = false; } -function checkController() { +function checkController(deltaTime) { var numberOfTriggers = Controller.getNumberOfTriggers(); var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; @@ -48,7 +48,7 @@ function checkController() { } // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(checkController); +Script.update.connect(checkController); function printKeyEvent(eventName, event) { print(eventName); diff --git a/examples/count.js b/examples/count.js index 29799a8271..e04bc2c94b 100644 --- a/examples/count.js +++ b/examples/count.js @@ -10,8 +10,8 @@ var count = 0; -function displayCount() { - print("count =" + count); +function displayCount(deltaTime) { + print("count =" + count + " deltaTime=" + deltaTime); count++; } @@ -20,7 +20,7 @@ function scriptEnding() { } // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(displayCount); +Script.update.connect(displayCount); // register our scriptEnding callback Script.scriptEnding.connect(scriptEnding); diff --git a/examples/drumStick.js b/examples/drumStick.js index 78de8351db..9b0a8ccbca 100644 --- a/examples/drumStick.js +++ b/examples/drumStick.js @@ -31,7 +31,7 @@ var strokeSpeed = new Array(); strokeSpeed[0] = 0.0; strokeSpeed[1] = 0.0; -function checkSticks() { +function checkSticks(deltaTime) { for (var palm = 0; palm < 2; palm++) { var palmVelocity = Controller.getSpatialControlVelocity(palm * 2 + 1); var speed = length(palmVelocity); @@ -69,4 +69,4 @@ function checkSticks() { } // Connect a call back that happens every frame -Script.willSendVisualDataCallback.connect(checkSticks); \ No newline at end of file +Script.update.connect(checkSticks); \ No newline at end of file diff --git a/examples/editParticleExample.js b/examples/editParticleExample.js index 152bb18fca..b632e0229b 100644 --- a/examples/editParticleExample.js +++ b/examples/editParticleExample.js @@ -42,7 +42,7 @@ var positionDelta = { x: 0.05, y: 0, z: 0 }; var particleID = Particles.addParticle(originalProperties); -function moveParticle() { +function moveParticle(deltaTime) { if (count >= moveUntil) { // delete it... @@ -85,5 +85,5 @@ function moveParticle() { // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(moveParticle); +Script.update.connect(moveParticle); diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 9a014639f0..4a194c0f5d 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -1329,7 +1329,7 @@ function checkControllers() { } } -function update() { +function update(deltaTime) { var newWindowDimensions = Controller.getViewportDimensions(); if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) { windowDimensions = newWindowDimensions; @@ -1399,6 +1399,6 @@ function scriptEnding() { } Script.scriptEnding.connect(scriptEnding); -Script.willSendVisualDataCallback.connect(update); +Script.update.connect(update); setupMenus(); diff --git a/examples/findParticleExample.js b/examples/findParticleExample.js index 5eb257d502..4a0e9b832a 100644 --- a/examples/findParticleExample.js +++ b/examples/findParticleExample.js @@ -60,7 +60,7 @@ function printProperties(properties) { } } -function findParticles() { +function findParticles(deltaTime) { // run for a while, then clean up // stop it... @@ -122,7 +122,7 @@ function findParticles() { // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(findParticles); +Script.update.connect(findParticles); // register our scriptEnding callback Script.scriptEnding.connect(scriptEnding); diff --git a/examples/flockingBirds.js b/examples/flockingBirds.js new file mode 100644 index 0000000000..12b402ab40 --- /dev/null +++ b/examples/flockingBirds.js @@ -0,0 +1,464 @@ +// +// flockingBirds.js +// hifi +// +// Created by Brad Hefta-Gaub on 3/4/14. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// +// This is an example script that generates particles that act like flocking birds +// +// All birds, even flying solo... +// birds don't like to fall too fast +// if they fall to fast, they will go into a state of thrusting up, until they reach some max upward velocity, then +// go back to gliding +// birds don't like to be below a certain altitude +// if they are below that altitude they will keep thrusting up, until they get ove + +// flocking +// try to align your velocity with velocity of other birds +// try to fly toward center of flock +// but dont get too close +// + +var birdsInFlock = 40; + +var birdLifetime = 60; // 2 minutes +var count=0; // iterations + +var enableFlyTowardPoints = true; // some birds have a point they want to fly to +var enabledClustedFlyTowardPoints = true; // the flyToward points will be generally near each other +var flyToFrames = 10; // number of frames the bird would like to attempt to fly to it's flyTo point +var PROBABILITY_OF_FLY_TOWARD_CHANGE = 0.01; // chance the bird will decide to change its flyTo point +var PROBABILITY_EACH_BIRD_WILL_FLY_TOWARD = 0.2; // chance the bird will decide to flyTo, otherwise it follows +var flyingToCount = 0; // count of birds currently flying to someplace +var flyToCluster = { }; // the point that the cluster of flyTo points is based on when in enabledClustedFlyTowardPoints + +// Bird behaviors +var enableAvoidDropping = true; // birds will resist falling too fast, and will thrust up if falling +var enableAvoidMinHeight = true; // birds will resist being below a certain height and thrust up to get above it +var enableAvoidMaxHeight = true; // birds will resist being above a certain height and will glide to get below it +var enableMatchFlockVelocity = true; // birds will thrust to match the flocks average velocity +var enableThrustTowardCenter = true; // birds will thrust to try to move toward the center of the flock +var enableAvoidOtherBirds = true; // birds will thrust away from all other birds +var startWithVelocity = true; +var flockGravity = { x: 0, y: -1, z: 0}; + +// NOTE: these two features don't seem to be very interesting, they cause odd behaviors +var enableRandomXZThrust = false; // leading birds randomly decide to thrust in some random direction. +var enableSomeBirdsLead = false; // birds randomly decide not fly toward flock, causing other birds to follow +var leaders = 0; // number of birds leading +var PROBABILITY_TO_LEAD = 0.1; // probabolity a bird will choose to lead + +var birds = new Array(); // array of bird state data + + +var flockStartPosition = { x: 100, y: 10, z: 100}; +var flockStartVelocity = { x: 0, y: 0, z: 0}; +var flockStartThrust = { x: 0, y: 0, z: 0}; // slightly upward against gravity +var INITIAL_XY_VELOCITY_SCALE = 2; +var birdRadius = 0.0625; +var baseBirdColor = { red: 0, green: 255, blue: 255 }; +var glidingColor = { red: 255, green: 0, blue: 0 }; +var thrustUpwardColor = { red: 0, green: 255, blue: 0 }; +var thrustXYColor = { red: 128, green: 0, blue: 128 }; // will be added to any other color +var leadingOrflyToColor = { red: 200, green: 200, blue: 255 }; + +var tooClose = birdRadius * 3; // how close birds are willing to be to each other +var droppingTooFast = -1; // birds don't like to fall too fast +var risingTooFast = 1; // birds don't like to climb too fast +var upwardThrustAgainstGravity = -10; // how hard a bird will attempt to thrust up to avoid downward motion +var droppingAdjustFrames = 5; // birds try to correct their min height in only a couple frames +var minHeight = 10; // meters off the ground +var maxHeight = 50; // meters off the ground +var adjustFrames = 10; // typical number of frames a bird will assume for it's adjustments +var PROBABILITY_OF_RANDOM_XZ_THRUST = 0.25; +var RANDOM_XZ_THRUST_SCALE = 5; // random -SCALE...to...+SCALE in X or Z direction +var MAX_XY_VELOCITY = 10; + +// These are multiplied by every frame since a change. so after 50 frames, there's a 50% probability of change +var PROBABILITY_OF_STARTING_XZ_THRUST = 0.0025; +var PROBABILITY_OF_STOPPING_XZ_THRUST = 0.01; + +var FLY_TOWARD_XZ_DISTANCE = 100; +var FLY_TOWARD_Y_DISTANCE = 0; +var FLY_TOWARD_XZ_CLUSTER_DELTA = 5; +var FLY_TOWARD_Y_CLUSTER_DELTA = 0; + +function createBirds() { + if (enabledClustedFlyTowardPoints) { + flyToCluster = { x: flockStartPosition.x + Math.random() * FLY_TOWARD_XZ_DISTANCE, + y: flockStartPosition.y + Math.random() * FLY_TOWARD_Y_DISTANCE, + z: flockStartPosition.z + Math.random() * FLY_TOWARD_XZ_DISTANCE}; + } + + for(var i =0; i < birdsInFlock; i++) { + var velocity; + + position = Vec3.sum(flockStartPosition, { x: Math.random(), y: Math.random(), z: Math.random() }); // add random + + var flyingToward = position; + var isFlyingToward = false; + if (enableFlyTowardPoints) { + if (Math.random() < PROBABILITY_EACH_BIRD_WILL_FLY_TOWARD) { + flyingToCount++; + isFlyingToward = true; + if (enabledClustedFlyTowardPoints) { + flyingToward = { x: flyToCluster.x + Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA, + y: flyToCluster.y + Math.random() * FLY_TOWARD_Y_CLUSTER_DELTA, + z: flyToCluster.z + Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA}; + } else { + flyingToward = { x: flockStartPosition.x + Math.random() * FLY_TOWARD_XZ_DISTANCE, + y: flockStartPosition.y + Math.random() * FLY_TOWARD_Y_DISTANCE, + z: flockStartPosition.z + Math.random() * FLY_TOWARD_XZ_DISTANCE}; + } + } + + Vec3.print("birds["+i+"].flyingToward=",flyingToward); + } + + birds[i] = { + particle: {}, + properties: {}, + thrust: Vec3.sum(flockStartThrust, { x:0, y: 0, z: 0 }), + gliding: true, + xzThrust: { x:0, y: 0, z: 0}, + xzthrustCount: 0, + isLeading: false, + flyingToward: flyingToward, + isFlyingToward: isFlyingToward, + }; + + if (enableSomeBirdsLead) { + if (Math.random() < PROBABILITY_TO_LEAD) { + birds[i].isLeading = true; + } + if (leaders == 0 && i == (birdsInFlock-1)) { + birds[i].isLeading = true; + } + if (birds[i].isLeading) { + leaders++; + velocity = { x: 2, y: 0, z: 2}; + print(">>>>>>THIS BIRD LEADS!!!! i="+i); + } + } + + if (startWithVelocity) { + velocity = Vec3.sum(flockStartVelocity, { x: (Math.random() * INITIAL_XY_VELOCITY_SCALE), + y: 0, + z: (Math.random() * INITIAL_XY_VELOCITY_SCALE) }); // add random + } else { + velocity = { x: 0, y: 0, z: 0}; + } + birds[i].particle = Particles.addParticle({ + position: position, + velocity: velocity, + gravity: flockGravity, + damping: 0, + radius: birdRadius, + color: baseBirdColor, + lifetime: birdLifetime + }); + + } + print("flyingToCount=" + flyingToCount); +} + +var wantDebug = false; +function updateBirds(deltaTime) { + count++; + + // get all our bird properties, and calculate the current flock velocity + var averageVelocity = { x: 0, y: 0, z: 0}; + var averagePosition = { x: 0, y: 0, z: 0}; + var knownBirds = 0; + for(var i =0; i < birdsInFlock; i++) { + // identifyParticle() will check to see that the particle handle we have is in sync with the domain/server + // context. If the handle is for a created particle that now has a known ID it will be updated to be a + // handle with a known ID. + birds[i].particle = Particles.identifyParticle(birds[i].particle); + + if (birds[i].particle.isKnownID) { + birds[i].properties = Particles.getParticleProperties(birds[i].particle); + if (birds[i].properties.isKnownID) { + knownBirds++; + averageVelocity = Vec3.sum(averageVelocity, birds[i].properties.velocity); + averagePosition = Vec3.sum(averagePosition, birds[i].properties.position); + } + } + } + + if (knownBirds == 0 && count > 100) { + Script.stop(); + return; + } + averageVelocity = Vec3.multiply(averageVelocity, (1 / Math.max(1, knownBirds))); + averagePosition = Vec3.multiply(averagePosition, (1 / Math.max(1, knownBirds))); + + if (wantDebug) { + Vec3.print("averagePosition=",averagePosition); + Vec3.print("averageVelocity=",averageVelocity); + print("knownBirds="+knownBirds); + } + + var flyToClusterChanged = false; + if (enabledClustedFlyTowardPoints) { + if (Math.random() < PROBABILITY_OF_FLY_TOWARD_CHANGE) { + flyToClusterChanged = true; + flyToCluster = { x: averagePosition.x + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2, + y: averagePosition.y + (Math.random() * FLY_TOWARD_Y_DISTANCE) - FLY_TOWARD_Y_DISTANCE/2, + z: averagePosition.z + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2}; + } + } + + // iterate all birds again, adjust their thrust for various goals + for(var i =0; i < birdsInFlock; i++) { + + birds[i].thrust = { x: 0, y: 0, z: 0 }; // assume no thrust... + + if (birds[i].particle.isKnownID) { + + if (enableFlyTowardPoints) { + // if we're flying toward clusters, and the cluster changed, and this bird is flyingToward + // then we need to update it's flyingToward + if (enabledClustedFlyTowardPoints && flyToClusterChanged && birds[i].isFlyingToward) { + flyingToward = { x: flyToCluster.x + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2, + y: flyToCluster.y + (Math.random() * FLY_TOWARD_Y_CLUSTER_DELTA) - FLY_TOWARD_Y_CLUSTER_DELTA/2, + z: flyToCluster.z + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2}; + birds[i].flyingToward = flyingToward; + } + + // there a random chance this bird will decide to change it's flying toward state + if (Math.random() < PROBABILITY_OF_FLY_TOWARD_CHANGE) { + var wasFlyingTo = birds[i].isFlyingToward; + + // there's some chance it will decide it should be flying toward + if (Math.random() < PROBABILITY_EACH_BIRD_WILL_FLY_TOWARD) { + + // if we're flying toward clustered points, then we randomize from the cluster, otherwise we pick + // completely random places based on flocks current averagePosition + if (enabledClustedFlyTowardPoints) { + flyingToward = { x: flyToCluster.x + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2, + y: flyToCluster.y + (Math.random() * FLY_TOWARD_Y_CLUSTER_DELTA) - FLY_TOWARD_Y_CLUSTER_DELTA/2, + z: flyToCluster.z + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2}; + } else { + flyingToward = { x: averagePosition.x + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2, + y: averagePosition.y + (Math.random() * FLY_TOWARD_Y_DISTANCE) - FLY_TOWARD_Y_DISTANCE/2, + z: averagePosition.z + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2}; + } + birds[i].flyingToward = flyingToward; + birds[i].isFlyingToward = true; + } else { + birds[i].flyingToward = {}; + birds[i].isFlyingToward = false; + } + + // keep track of our bookkeeping + if (!wasFlyingTo && birds[i].isFlyingToward) { + flyingToCount++; + } + if (wasFlyingTo && !birds[i].isFlyingToward) { + flyingToCount--; + } + print(">>>> CHANGING flyingToCount="+flyingToCount); + if (birds[i].isFlyingToward) { + Vec3.print("... now birds["+i+"].flyingToward=", birds[i].flyingToward); + } + } + + // actually apply the thrust after all that + if (birds[i].isFlyingToward) { + var flyTowardDelta = Vec3.subtract(birds[i].flyingToward, birds[i].properties.position); + var thrustTowardFlyTo = Vec3.multiply(flyTowardDelta, 1/flyToFrames); + birds[i].thrust = Vec3.sum(birds[i].thrust, thrustTowardFlyTo); + } + } + + + // adjust thrust to avoid dropping to fast + if (enableAvoidDropping) { + if (birds[i].gliding) { + if (birds[i].properties.velocity.y < droppingTooFast) { + birds[i].gliding = false; // leave thrusting against gravity till it gets too high + //print("birdGliding["+i+"]=false <<<< try to conteract gravity <<<<<<<<<<<<<<<<<<<<"); + } + } + } + + // if the bird is currently not gliding, check to see if it's rising too fast + if (!birds[i].gliding && birds[i].properties.velocity.y > risingTooFast) { + //Vec3.print("bird rising too fast will glide bird["+i+"]=",birds[i].properties.velocity.y); + birds[i].gliding = true; + } + + // adjust thrust to avoid minHeight, we don't care about rising too fast in this case, so we do it + // after the rising too fast check + if (enableAvoidMinHeight) { + if (birds[i].properties.position.y < minHeight) { + //Vec3.print("**** enableAvoidMinHeight... enable thrust against gravity... bird["+i+"].position=",birds[i].properties.position); + birds[i].gliding = false; + } + } + + // adjust thrust to avoid maxHeight + if (enableAvoidMaxHeight) { + if (birds[i].properties.position.y > maxHeight) { + //Vec3.print("********************* bird above max height will glide bird["+i+"].position=",birds[i].properties.position); + birds[i].gliding = true; + } + } + + // if the bird is currently not gliding, then it is applying a thrust upward against gravity + if (!birds[i].gliding) { + // as long as we're not rising too fast, keep thrusting... + if (birds[i].properties.velocity.y < risingTooFast) { + var thrustAdjust = {x: 0, y: (flockGravity.y * upwardThrustAgainstGravity), z: 0}; + //Vec3.print("bird fighting gravity thrustAdjust for bird["+i+"]=",thrustAdjust); + birds[i].thrust = Vec3.sum(birds[i].thrust, thrustAdjust); + } else { + //print("%%% non-gliding bird, thrusting too much..."); + } + } + + if (enableRandomXZThrust && birds[i].isLeading) { + birds[i].xzThrustCount++; + + // we will randomly decide to enable XY thrust, in which case we will set the thrust and leave it + // that way till we randomly shut it off. + + // if we don't have a thrust, check against probability of starting it, and create a random thrust if + // probability occurs + if (Vec3.length(birds[i].xzThrust) == 0) { + var probabilityToStart = (PROBABILITY_OF_STARTING_XZ_THRUST * birds[i].xzThrustCount); + //print("probabilityToStart=" + probabilityToStart); + if (Math.random() < probabilityToStart) { + var xThrust = (Math.random() * (RANDOM_XZ_THRUST_SCALE * 2)) - RANDOM_XZ_THRUST_SCALE; + var zThrust = (Math.random() * (RANDOM_XZ_THRUST_SCALE * 2)) - RANDOM_XZ_THRUST_SCALE; + + birds[i].xzThrust = { x: zThrust, y: 0, z: zThrust }; + birds[i].xzThrustCount = 0; + //Vec3.print(">>>>>>>>>> STARTING XY THRUST birdXYthrust["+i+"]=", birds[i].xzThrust); + } + } + + // if we're thrusting... then check for probability of stopping + if (Vec3.length(birds[i].xzThrust)) { + var probabilityToStop = (PROBABILITY_OF_STOPPING_XZ_THRUST * birds[i].xzThrustCount); + //print("probabilityToStop=" + probabilityToStop); + if (Math.random() < probabilityToStop) { + birds[i].xzThrust = { x: 0, y: 0, z: 0}; + //Vec3.print(">>>>>>>>>> STOPPING XY THRUST birdXYthrust["+i+"]=", birds[i].xzThrust); + birds[i].xzThrustCount = 0; + } + + if (birds[i].properties.velocity.x > MAX_XY_VELOCITY) { + birds[i].xzThrust.x = 0; + //Vec3.print(">>>>>>>>>> CLEARING X THRUST birdXYthrust["+i+"]=", birds[i].xzThrust); + } + if (birds[i].properties.velocity.z > MAX_XY_VELOCITY) { + birds[i].xzThrust.z = 0; + //Vec3.print(">>>>>>>>>> CLEARING Y THRUST birdXYthrust["+i+"]=", birds[i].xzThrust); + } + + if (Vec3.length(birds[i].xzThrust)) { + birds[i].thrust = Vec3.sum(birds[i].thrust, birds[i].xzThrust); + } + } + } + + // adjust thrust to move their velocity toward average flock velocity + if (enableMatchFlockVelocity) { + if (birds[i].isLeading) { + print("this bird is leading... i="+i); + } else { + var velocityDelta = Vec3.subtract(averageVelocity, birds[i].properties.velocity); + var thrustAdjust = velocityDelta; + birds[i].thrust = Vec3.sum(birds[i].thrust, thrustAdjust); + } + } + + // adjust thrust to move their velocity toward average flock position + if (enableThrustTowardCenter) { + if (birds[i].isLeading) { + print("this bird is leading... i="+i); + } else { + var positionDelta = Vec3.subtract(averagePosition, birds[i].properties.position); + var thrustTowardCenter = Vec3.multiply(positionDelta, 1/adjustFrames); + birds[i].thrust = Vec3.sum(birds[i].thrust, thrustTowardCenter); + } + } + + + // adjust thrust to avoid other birds + if (enableAvoidOtherBirds) { + var sumThrustThisBird = { x: 0, y: 0, z: 0 }; + + for(var j =0; j < birdsInFlock; j++) { + + // if this is not me, and a known bird, then check our position + if (birds[i].properties.isKnownID && j != i) { + var positionMe = birds[i].properties.position; + var positionYou = birds[j].properties.position; + var awayFromYou = Vec3.subtract(positionMe, positionYou); // vector pointing away from "you" + var distance = Vec3.length(awayFromYou); + if (distance < tooClose) { + // NOTE: this was Philip's recommendation for "avoiding" other birds... + // Vme -= Vec3.multiply(Vme, normalize(PositionMe - PositionYou)) + // + // But it doesn't seem to work... Here's my JS implementation... + // + // var velocityMe = birds[i].properties.velocity; + // var thrustAdjust = Vec3.cross(velocityMe, Vec3.normalize(awayFromYou)); + // sumThrustThisBird = Vec3.sum(sumThrustThisBird, thrustAdjust); + // + // Instead I just apply a thrust equal to the vector away from all the birds + sumThrustThisBird = Vec3.sum(sumThrustThisBird, awayFromYou); + } + } + } + birds[i].thrust = Vec3.sum(birds[i].thrust, sumThrustThisBird); + } + } + } + + + // iterate all birds again, apply their thrust + for(var i =0; i < birdsInFlock; i++) { + if (birds[i].particle.isKnownID) { + + var color; + if (birds[i].gliding) { + color = glidingColor; + } else { + color = thrustUpwardColor; + } + if (Vec3.length(birds[i].xzThrust)) { + color = Vec3.sum(color, thrustXYColor); + } + + var velocityMe = birds[i].properties.velocity; + // add thrust to velocity + var newVelocity = Vec3.sum(velocityMe, Vec3.multiply(birds[i].thrust, deltaTime)); + + if (birds[i].isLeading || birds[i].isFlyingToward) { + Vec3.print("this bird is leading/flying toward... i="+i+" velocity=",newVelocity); + color = leadingOrflyToColor; + } + + if (wantDebug) { + Vec3.print("birds["+i+"].position=", birds[i].properties.position); + Vec3.print("birds["+i+"].oldVelocity=", velocityMe); + Vec3.print("birdThrusts["+i+"]=", birds[i].thrust); + Vec3.print("birds["+i+"].newVelocity=", newVelocity); + } + + birds[i].particle = Particles.editParticle(birds[i].particle,{ velocity: newVelocity, color: color }); + + } + } +} + + +createBirds(); +// register the call back for simulation loop +Script.update.connect(updateBirds); + diff --git a/examples/fountain.js b/examples/fountain.js index 3c943d72a0..8816dab09a 100644 --- a/examples/fountain.js +++ b/examples/fountain.js @@ -41,7 +41,7 @@ var position = { x: 5.0, y: 0.6, z: 5.0 }; Voxels.setVoxel(position.x, 0, position.z, 0.5, 0, 0, 255); var totalParticles = 0; -function makeFountain() { +function makeFountain(deltaTime) { if (Math.random() < 0.10) { //print("Made particle!\n"); var properties = { @@ -64,4 +64,4 @@ function makeFountain() { } } // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(makeFountain); \ No newline at end of file +Script.update.connect(makeFountain); \ No newline at end of file diff --git a/examples/gameoflife.js b/examples/gameoflife.js index d72a72c2de..c0122c604a 100644 --- a/examples/gameoflife.js +++ b/examples/gameoflife.js @@ -114,7 +114,7 @@ function sendNextCells() { var sentFirstBoard = false; -function step() { +function step(deltaTime) { if (sentFirstBoard) { // we've already sent the first full board, perform a step in time updateCells(); @@ -127,6 +127,6 @@ function step() { } print("here"); -Script.willSendVisualDataCallback.connect(step); +Script.update.connect(step); Voxels.setPacketsPerSecond(200); print("now here"); diff --git a/examples/gun.js b/examples/gun.js index b50a8f64d8..617ec1bbc4 100644 --- a/examples/gun.js +++ b/examples/gun.js @@ -73,7 +73,7 @@ function particleCollisionWithVoxel(particle, voxel) { Audio.playSound(impactSound, audioOptions); } -function update() { +function update(deltaTime) { // Check for mouseLook movement, update rotation // rotate body yaw for yaw received from mouse @@ -178,7 +178,7 @@ function scriptEnding() { Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel); Script.scriptEnding.connect(scriptEnding); -Script.willSendVisualDataCallback.connect(update); +Script.update.connect(update); Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.mouseMoveEvent.connect(mouseMoveEvent); diff --git a/examples/hydraMove.js b/examples/hydraMove.js index 6ce0ad884e..1f9634a8e6 100644 --- a/examples/hydraMove.js +++ b/examples/hydraMove.js @@ -29,7 +29,6 @@ var grabbingWithLeftHand = false; var wasGrabbingWithLeftHand = false; var EPSILON = 0.000001; var velocity = { x: 0, y: 0, z: 0}; -var deltaTime = 1/60; // approximately our FPS - maybe better to be elapsed time since last call var THRUST_MAG_UP = 800.0; var THRUST_MAG_DOWN = 300.0; var THRUST_MAG_FWD = 500.0; @@ -77,7 +76,7 @@ function getAndResetGrabRotation() { } // handles all the grab related behavior: position (crawl), velocity (flick), and rotate (twist) -function handleGrabBehavior() { +function handleGrabBehavior(deltaTime) { // check for and handle grab behaviors grabbingWithRightHand = Controller.isButtonPressed(RIGHT_BUTTON_4); grabbingWithLeftHand = Controller.isButtonPressed(LEFT_BUTTON_4); @@ -156,7 +155,7 @@ function handleGrabBehavior() { } // Main update function that handles flying and grabbing behaviort -function flyWithHydra() { +function flyWithHydra(deltaTime) { var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER); if (thrustJoystickPosition.x != 0 || thrustJoystickPosition.y != 0) { @@ -193,10 +192,10 @@ function flyWithHydra() { var newPitch = MyAvatar.headPitch + (viewJoystickPosition.y * JOYSTICK_PITCH_MAG * deltaTime); MyAvatar.headPitch = newPitch; } - handleGrabBehavior(); + handleGrabBehavior(deltaTime); } -Script.willSendVisualDataCallback.connect(flyWithHydra); +Script.update.connect(flyWithHydra); Controller.captureJoystick(THRUST_CONTROLLER); Controller.captureJoystick(VIEW_CONTROLLER); diff --git a/examples/lookAtExample.js b/examples/lookAtExample.js index 6340feda00..46e0863231 100644 --- a/examples/lookAtExample.js +++ b/examples/lookAtExample.js @@ -45,13 +45,13 @@ function releaseMovementKeys() { } var cameraPosition = Camera.getPosition(); -function moveCamera() { +function moveCamera(update) { if (lookingAtSomething) { Camera.setPosition(cameraPosition); } } -Script.willSendVisualDataCallback.connect(moveCamera); +Script.update.connect(moveCamera); function mousePressEvent(event) { diff --git a/examples/lookWithMouse.js b/examples/lookWithMouse.js index 460663c054..878813a94a 100644 --- a/examples/lookWithMouse.js +++ b/examples/lookWithMouse.js @@ -49,7 +49,7 @@ function mouseMoveEvent(event) { } } -function update() { +function update(deltaTime) { if (wantDebugging) { print("update()..."); } @@ -91,5 +91,5 @@ MyAvatar.bodyPitch = 0; MyAvatar.bodyRoll = 0; // would be nice to change to update -Script.willSendVisualDataCallback.connect(update); +Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); diff --git a/examples/lookWithTouch.js b/examples/lookWithTouch.js index bb54a055c4..ddc42c04c0 100644 --- a/examples/lookWithTouch.js +++ b/examples/lookWithTouch.js @@ -43,7 +43,7 @@ function touchUpdateEvent(event) { lastY = event.y; } -function update() { +function update(deltaTime) { // rotate body yaw for yaw received from mouse var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3( { x: 0, y: yawFromMouse, z: 0 } )); if (wantDebugging) { @@ -82,5 +82,5 @@ MyAvatar.bodyPitch = 0; MyAvatar.bodyRoll = 0; // would be nice to change to update -Script.willSendVisualDataCallback.connect(update); +Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); diff --git a/examples/movingVoxel.js b/examples/movingVoxel.js index 14a7e671c6..0ddce48334 100644 --- a/examples/movingVoxel.js +++ b/examples/movingVoxel.js @@ -12,7 +12,7 @@ var colorEdge = { r:255, g:250, b:175 }; var frame = 0; var thisColor = color; -function moveVoxel() { +function moveVoxel(deltaTime) { frame++; if (frame % 3 == 0) { // Get a new position @@ -41,4 +41,4 @@ function moveVoxel() { Voxels.setPacketsPerSecond(300); // Connect a call back that happens every frame -Script.willSendVisualDataCallback.connect(moveVoxel); \ No newline at end of file +Script.update.connect(moveVoxel); \ No newline at end of file diff --git a/examples/multitouchExample.js b/examples/multitouchExample.js index 448d7c3f80..1041651c7b 100644 --- a/examples/multitouchExample.js +++ b/examples/multitouchExample.js @@ -90,7 +90,7 @@ Controller.touchEndEvent.connect(touchEndEvent); -function update() { +function update(deltaTime) { // rotate body yaw for yaw received from multitouch rotate var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3( { x: 0, y: yawFromMultiTouch, z: 0 } )); if (wantDebugging) { @@ -110,7 +110,7 @@ function update() { MyAvatar.headPitch = newPitch; pitchFromMultiTouch = 0; } -Script.willSendVisualDataCallback.connect(update); +Script.update.connect(update); function scriptEnding() { diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index d97ec9e8fd..60f924338f 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -186,7 +186,7 @@ var toolAVisible = false; var count = 0; // Our update() function is called at approximately 60fps, and we will use it to animate our various overlays -function update() { +function update(deltaTime) { count++; // every second or so, toggle the visibility our our blinking tool @@ -226,7 +226,7 @@ function update() { // update our 3D line to go from origin to our avatar's position Overlays.editOverlay(line3d, { end: MyAvatar.position } ); } -Script.willSendVisualDataCallback.connect(update); +Script.update.connect(update); // The slider is handled in the mouse event callbacks. diff --git a/examples/paintGun.js b/examples/paintGun.js index 56e916a183..38c99ddfcb 100644 --- a/examples/paintGun.js +++ b/examples/paintGun.js @@ -13,7 +13,7 @@ for (t = 0; t < numberOfTriggers; t++) { triggerPulled[t] = false; } -function checkController() { +function checkController(deltaTime) { var numberOfTriggers = Controller.getNumberOfTriggers(); var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; @@ -93,4 +93,4 @@ function checkController() { // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(checkController); +Script.update.connect(checkController); diff --git a/examples/particleBird.js b/examples/particleBird.js index 440a91166c..5cd068bd60 100644 --- a/examples/particleBird.js +++ b/examples/particleBird.js @@ -99,7 +99,7 @@ var properties = { var range = 1.0; // Distance around avatar where I can move // Create the actual bird var particleID = Particles.addParticle(properties); -function moveBird() { +function moveBird(deltaTime) { // check to see if we've been running long enough that our bird is dead var nowTimeInSeconds = new Date().getTime() / 1000; @@ -194,4 +194,4 @@ function moveBird() { } // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(moveBird); +Script.update.connect(moveBird); diff --git a/examples/particleModelExample.js b/examples/particleModelExample.js index 2f36445d1a..c43956cd3e 100644 --- a/examples/particleModelExample.js +++ b/examples/particleModelExample.js @@ -47,7 +47,7 @@ var modelAParticleID = Particles.addParticle(modelPropertiesA); var modelBParticleID = Particles.addParticle(modelPropertiesB); var ballParticleID = Particles.addParticle(ballProperties); -function endAfterAWhile() { +function endAfterAWhile(deltaTime) { // stop it... if (count >= stopAfter) { print("calling Script.stop()"); @@ -60,5 +60,5 @@ function endAfterAWhile() { // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(endAfterAWhile); +Script.update.connect(endAfterAWhile); diff --git a/examples/playSound.js b/examples/playSound.js index 657f052aa5..18857826ea 100644 --- a/examples/playSound.js +++ b/examples/playSound.js @@ -5,7 +5,7 @@ // First, load the clap sound from a URL var clap = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/bushtit_1.raw"); -function maybePlaySound() { +function maybePlaySound(deltaTime) { if (Math.random() < 0.01) { // Set the location and other info for the sound to play var options = new AudioInjectionOptions();
 @@ -17,4 +17,4 @@ function maybePlaySound() { } // Connect a call back that happens every frame -Script.willSendVisualDataCallback.connect(maybePlaySound); \ No newline at end of file +Script.update.connect(maybePlaySound); \ No newline at end of file diff --git a/examples/ribbon.js b/examples/ribbon.js index 7858c744fe..a6e1edfa4a 100644 --- a/examples/ribbon.js +++ b/examples/ribbon.js @@ -122,7 +122,7 @@ var velocity; var hueAngle = 0; var smoothedOffset; -function step() { +function step(deltaTime) { if (stateHistory.length === 0) { // start at a random position within the bounds, with a random velocity position = randomVector(BOUNDS_MIN, BOUNDS_MAX); @@ -170,4 +170,4 @@ function step() { hueAngle = (hueAngle + 1) % MAX_HUE_ANGLE; } -Script.willSendVisualDataCallback.connect(step); +Script.update.connect(step); diff --git a/examples/rideAlongWithAParticleExample.js b/examples/rideAlongWithAParticleExample.js index b2b6627063..1148b96b4d 100644 --- a/examples/rideAlongWithAParticleExample.js +++ b/examples/rideAlongWithAParticleExample.js @@ -22,7 +22,7 @@ var particleA = Particles.addParticle( lifetime: (lengthOfRide * 60) + 1 }); -function rideWithParticle() { +function rideWithParticle(deltaTime) { if (iteration <= lengthOfRide) { @@ -46,5 +46,5 @@ function rideWithParticle() { // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(rideWithParticle); +Script.update.connect(rideWithParticle); diff --git a/examples/seeingVoxelsExample.js b/examples/seeingVoxelsExample.js index 93f605755f..62ebd599ee 100644 --- a/examples/seeingVoxelsExample.js +++ b/examples/seeingVoxelsExample.js @@ -31,7 +31,7 @@ function init() { } } -function keepLooking() { +function keepLooking(deltaTime) { //print("count =" + count); if (count == 0) { @@ -63,7 +63,7 @@ function scriptEnding() { } // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(keepLooking); +Script.update.connect(keepLooking); // register our scriptEnding callback Script.scriptEnding.connect(scriptEnding); diff --git a/examples/spaceInvadersExample.js b/examples/spaceInvadersExample.js index c817afcdd4..1d7b127904 100644 --- a/examples/spaceInvadersExample.js +++ b/examples/spaceInvadersExample.js @@ -207,7 +207,7 @@ function displayGameOver() { print("Game over..."); } -function update() { +function update(deltaTime) { if (!gameOver) { //print("updating space invaders... iteration="+iteration); iteration++; @@ -257,7 +257,7 @@ function update() { } // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(update); +Script.update.connect(update); function cleanupGame() { print("cleaning up game..."); diff --git a/examples/toyball.js b/examples/toyball.js index c5672877f7..36f1aa11e5 100644 --- a/examples/toyball.js +++ b/examples/toyball.js @@ -208,7 +208,7 @@ function checkControllerSide(whichSide) { } -function checkController() { +function checkController(deltaTime) { var numberOfButtons = Controller.getNumberOfButtons(); var numberOfTriggers = Controller.getNumberOfTriggers(); var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); @@ -226,4 +226,4 @@ function checkController() { // register the call back so it fires before each data send -Script.willSendVisualDataCallback.connect(checkController); +Script.update.connect(checkController); diff --git a/examples/voxelBird.js b/examples/voxelBird.js index 254f93c21e..1e33851ff6 100644 --- a/examples/voxelBird.js +++ b/examples/voxelBird.js @@ -73,7 +73,7 @@ var moved = true; var CHANCE_OF_MOVING = 0.05; var CHANCE_OF_TWEETING = 0.05; -function moveBird() { +function moveBird(deltaTime) { frame++; if (frame % 3 == 0) { // Tweeting behavior @@ -130,4 +130,4 @@ function moveBird() { Voxels.setPacketsPerSecond(10000); // Connect a call back that happens every frame -Script.willSendVisualDataCallback.connect(moveBird); \ No newline at end of file +Script.update.connect(moveBird); \ No newline at end of file diff --git a/examples/voxelDrumming.js b/examples/voxelDrumming.js index a2acb05958..178c6734d8 100644 --- a/examples/voxelDrumming.js +++ b/examples/voxelDrumming.js @@ -70,14 +70,13 @@ function clamp(valueToClamp, minValue, maxValue) { return Math.max(minValue, Math.min(maxValue, valueToClamp)); } -function produceCollisionSound(palm, voxelDetail) { +function produceCollisionSound(deltaTime, palm, voxelDetail) { // Collision between finger and a voxel plays sound var palmVelocity = Controller.getSpatialControlVelocity(palm * 2); var speed = Vec3.length(palmVelocity); var fingerTipPosition = Controller.getSpatialControlPosition(palm * 2 + 1); - var deltaTime = 1/60; //close enough var LOWEST_FREQUENCY = 100.0; var HERTZ_PER_RGB = 3.0; var DECAY_PER_SAMPLE = 0.0005; @@ -97,9 +96,7 @@ function produceCollisionSound(palm, voxelDetail) { Audio.startDrumSound(volume, frequency, DURATION_MAX, DECAY_PER_SAMPLE, audioOptions); } -function update() { - var deltaTime = 1/60; //close enough - +function update(deltaTime) { // Voxel Drumming with fingertips if enabled if (Menu.isOptionChecked("Voxel Drumming")) { @@ -111,7 +108,7 @@ function update() { if (!isColliding[palm]) { // Collision has just started isColliding[palm] = true; - produceCollisionSound(palm, voxel); + produceCollisionSound(deltaTime, palm, voxel); // Set highlight voxel Overlays.editOverlay(highlightVoxel, @@ -156,7 +153,7 @@ function update() { } // palm loop } // menu item check } -Script.willSendVisualDataCallback.connect(update); +Script.update.connect(update); function scriptEnding() { Overlays.deleteOverlay(highlightVoxel); diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 4515deb6b5..3e7e5dd3c1 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -17,9 +17,7 @@ #include -#include -#include -#include +#include #include "CoverageMap.h" #include diff --git a/libraries/script-engine/src/Quat.cpp b/libraries/script-engine/src/Quat.cpp index 7271f06af6..78ea73987b 100644 --- a/libraries/script-engine/src/Quat.cpp +++ b/libraries/script-engine/src/Quat.cpp @@ -11,6 +11,8 @@ #include +#include + #include #include #include "Quat.h" @@ -56,3 +58,7 @@ glm::quat Quat::mix(const glm::quat& q1, const glm::quat& q2, float alpha) { return safeMix(q1, q2, alpha); } +void Quat::print(const QString& lable, const glm::quat& q) { + qDebug() << qPrintable(lable) << q.x << "," << q.y << "," << q.z << "," << q.w; +} + diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index ac12aaa351..f006374347 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -13,7 +13,9 @@ #define __hifi__Quat__ #include -#include + +#include +#include /// Scriptable interface a Quaternion helper class object. Used exclusively in the JavaScript API class Quat : public QObject { @@ -30,6 +32,7 @@ public slots: glm::vec3 safeEulerAngles(const glm::quat& orientation); glm::quat angleAxis(float angle, const glm::vec3& v); glm::quat mix(const glm::quat& q1, const glm::quat& q2, float alpha); + void print(const QString& lable, const glm::quat& q); }; #endif /* defined(__hifi__Quat__) */ diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 718e5331dd..59ce841969 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -220,6 +220,8 @@ void ScriptEngine::run() { int thisFrame = 0; NodeList* nodeList = NodeList::getInstance(); + + qint64 lastUpdate = usecTimestampNow(); while (!_isFinished) { int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * VISUAL_DATA_CALLBACK_USECS) - usecTimestampNow(); @@ -264,7 +266,10 @@ void ScriptEngine::run() { nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer); } - emit willSendVisualDataCallback(); + qint64 now = usecTimestampNow(); + float deltaTime = (float)(now - lastUpdate)/(float)USECS_PER_SECOND; + emit update(deltaTime); + lastUpdate = now; if (_engine.hasUncaughtException()) { int line = _engine.uncaughtExceptionLineNumber(); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 00906de7b3..6b9ec9c9eb 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -71,8 +71,7 @@ public slots: void clearTimeout(QObject* timer) { stopTimer(reinterpret_cast(timer)); } signals: - void willSendAudioDataCallback(); - void willSendVisualDataCallback(); + void update(float deltaTime); void scriptEnding(); void finished(const QString& fileNameString); void cleanupMenuItem(const QString& menuItemString); diff --git a/libraries/script-engine/src/Vec3.cpp b/libraries/script-engine/src/Vec3.cpp index 2c5bf172fd..dc5dcd9773 100644 --- a/libraries/script-engine/src/Vec3.cpp +++ b/libraries/script-engine/src/Vec3.cpp @@ -9,10 +9,12 @@ // // +#include + #include "Vec3.h" -glm::vec3 Vec3::multiply(const glm::vec3& v1, const glm::vec3& v2) { - return v1 * v2; +glm::vec3 Vec3::cross(const glm::vec3& v1, const glm::vec3& v2) { + return glm::cross(v1,v2); } glm::vec3 Vec3::multiply(const glm::vec3& v1, float f) { @@ -29,6 +31,15 @@ glm::vec3 Vec3::sum(const glm::vec3& v1, const glm::vec3& v2) { glm::vec3 Vec3::subtract(const glm::vec3& v1, const glm::vec3& v2) { return v1 - v2; } + float Vec3::length(const glm::vec3& v) { return glm::length(v); } + +glm::vec3 Vec3::normalize(const glm::vec3& v) { + return glm::normalize(v); +} + +void Vec3::print(const QString& lable, const glm::vec3& v) { + qDebug() << qPrintable(lable) << v.x << "," << v.y << "," << v.z; +} diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h index 20ad3f7eaa..cbec55b992 100644 --- a/libraries/script-engine/src/Vec3.h +++ b/libraries/script-engine/src/Vec3.h @@ -14,19 +14,23 @@ #include #include -#include + +#include +#include /// Scriptable interface a Vec3ernion helper class object. Used exclusively in the JavaScript API class Vec3 : public QObject { Q_OBJECT public slots: - glm::vec3 multiply(const glm::vec3& v1, const glm::vec3& v2); + glm::vec3 cross(const glm::vec3& v1, const glm::vec3& v2); glm::vec3 multiply(const glm::vec3& v1, float f); glm::vec3 multiplyQbyV(const glm::quat& q, const glm::vec3& v); glm::vec3 sum(const glm::vec3& v1, const glm::vec3& v2); glm::vec3 subtract(const glm::vec3& v1, const glm::vec3& v2); float length(const glm::vec3& v); + glm::vec3 normalize(const glm::vec3& v); + void print(const QString& lable, const glm::vec3& v); };