diff --git a/examples/entityScripts/tribble.js b/examples/entityScripts/tribble.js new file mode 100644 index 0000000000..3f84901344 --- /dev/null +++ b/examples/entityScripts/tribble.js @@ -0,0 +1,66 @@ +(function () { + // See tests/performance/tribbles.js + var dimensions, oldColor, entityID, + editRate = 60, + moveRate = 1, + scale = 2, + accumulated = 0, + increment = {red: 1, green: 1, blue: 1}, + hasUpdate = false, + shutdown = false; + function nextWavelength(color) { + var old = oldColor[color]; + if (old === 255) { + increment[color] = -1; + } else if (old === 0) { + increment[color] = 1; + } + var next = (old + increment[color]) % 256; + return next; + } + function update(delta) { // High frequency stuff is done in update in case we fall behind. + accumulated += delta; + if (accumulated > (1 / editRate)) { + var newColor = {red: nextWavelength('red'), green: nextWavelength('green'), blue: nextWavelength('blue')}; + oldColor = newColor; + Entities.editEntity(entityID, {color: newColor}); + accumulated = 0; + } + } + function randomCentered() { return Math.random() - 0.5; } + function randomVector() { return {x: randomCentered() * dimensions.x, y: randomCentered() * dimensions.y, z: randomCentered() * dimensions.z}; } + function move() { + var newData = {velocity: Vec3.sum({x: 0, y: 1, z: 0}, randomVector()), angularVelocity: Vec3.multiply(Math.PI, randomVector())}; + var nextChange = Math.ceil(Math.random() * 2000 / moveRate); + Entities.editEntity(entityID, newData); + if (!shutdown) { Script.setTimeout(move, nextChange); } + } + this.preload = function (givenEntityID) { + entityID = givenEntityID; + var properties = Entities.getEntityProperties(entityID); + var userData = properties.userData && JSON.parse(properties.userData); + var moveTimeout = userData ? userData.moveTimeout : 0; + var editTimeout = userData ? userData.editTimeout : 0; + editRate = (userData && userData.editRate) || editRate; + moveRate = (moveRate && userData.moveRate) || moveRate; + oldColor = properties.color; + dimensions = Vec3.multiply(scale, properties.dimensions); + if (editTimeout) { + hasUpdate = true; + Script.update.connect(update); + if (editTimeout > 0) { + Script.setTimeout(function () { Script.update.disconnect(update); hasUpdate = false; }, editTimeout * 1000); + } + } + if (moveTimeout) { + Script.setTimeout(move, 1000); + if (moveTimeout > 0) { + Script.setTimeout(function () { shutdown = true; }, moveTimeout * 1000); + } + } + }; + this.unload = function () { + shutdown = true; + if (hasUpdate) { Script.update.disconnect(update); } + }; +}) diff --git a/examples/tests/performance/tribbles.js b/examples/tests/performance/tribbles.js new file mode 100644 index 0000000000..1e7b6ddf39 --- /dev/null +++ b/examples/tests/performance/tribbles.js @@ -0,0 +1,96 @@ +"use strict"; +/*jslint nomen: true, plusplus: true, vars: true*/ +var Vec3, Quat, MyAvatar, Entities, Camera, Script, print; +// +// Created by Howard Stearns +// Copyright 2016 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 +// +// Drops a bunch of physical spheres in front of you, each running a script that will: +// * Edit color at EDIT_RATE for EDIT_TIMEOUT. +// * Randomly move at an average of MOVE_RATE for MOVE_TIMEOUT. +// The _TIMEOUT parameters can be 0 for no activity, and -1 to be active indefinitely. +// + +var NUMBER_TO_CREATE = 120; +var LIFETIME = 60; // seconds +var EDIT_RATE = 60; // hz +var EDIT_TIMEOUT = -1; +var MOVE_RATE = 1; // hz +var MOVE_TIMEOUT = LIFETIME / 2; + +var SIZE = 0.5; +var TYPE = "Sphere"; +// Note that when creating things quickly, the entity server will ignore data if we send updates too quickly. +// like Internet MTU, these rates are set by th domain operator, so in this script there is a RATE_PER_SECOND +// variable letting you set this speed. If entities are missing from the grid after a relog, this number +// being too high may be the reason. +var RATE_PER_SECOND = 600; // The entity server will drop data if we create things too fast. +var SCRIPT_INTERVAL = 100; + +var GRAVITY = { x: 0, y: -9.8, z: 0 }; +var VELOCITY = { x: 0.0, y: 0, z: 0 }; +var ANGULAR_VELOCITY = { x: 1, y: 1, z: 1 }; + +var DAMPING = 0.5; +var ANGULAR_DAMPING = 0.5; + +var RANGE = 3; +var HOW_FAR_IN_FRONT_OF_ME = RANGE * 3; +var HOW_FAR_UP = RANGE / 1.5; // higher (for uneven ground) above range/2 (for distribution) + +var x = 0; +var z = 0; +var totalCreated = 0; +var offset = Vec3.sum(Vec3.multiply(HOW_FAR_UP, Vec3.UNIT_Y), + Vec3.multiply(HOW_FAR_IN_FRONT_OF_ME, Quat.getFront(Camera.orientation))); +var center = Vec3.sum(MyAvatar.position, offset); + +function randomVector(range) { + return { + x: (Math.random() - 0.5) * range.x, + y: (Math.random() - 0.5) * range.y, + z: (Math.random() - 0.5) * range.z + }; +} + +Script.setInterval(function () { + if (!Entities.serversExist() || !Entities.canRez()) { + return; + } + if (totalCreated >= NUMBER_TO_CREATE) { + print("Created " + totalCreated + " tribbles."); + Script.stop(); + } + + var i, numToCreate = RATE_PER_SECOND * (SCRIPT_INTERVAL / 1000.0); + var parameters = JSON.stringify({ + moveTimeout: MOVE_TIMEOUT, + moveRate: MOVE_RATE, + editTimeout: EDIT_TIMEOUT, + editRate: EDIT_RATE + }); + for (i = 0; (i < numToCreate) && (totalCreated < NUMBER_TO_CREATE); i++) { + Entities.addEntity({ + userData: parameters, + type: TYPE, + name: "tribble-" + totalCreated, + position: Vec3.sum(center, randomVector({ x: RANGE, y: RANGE, z: RANGE })), + dimensions: {x: SIZE, y: SIZE, z: SIZE}, + color: {red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255}, + velocity: VELOCITY, + angularVelocity: Vec3.multiply(Math.random(), ANGULAR_VELOCITY), + damping: DAMPING, + angularDamping: ANGULAR_DAMPING, + gravity: GRAVITY, + collisionsWillMove: true, + lifetime: LIFETIME, + script: "https://s3.amazonaws.com/hifi-public/scripts/entityScripts/tribble.js" + }); + + totalCreated++; + } +}, SCRIPT_INTERVAL); +