diff --git a/scripts/tutorials/NBody/gravity.js b/scripts/tutorials/NBody/gravity.js deleted file mode 100644 index b6bdb9d20b..0000000000 --- a/scripts/tutorials/NBody/gravity.js +++ /dev/null @@ -1,181 +0,0 @@ -// gravity.js -// -// Created by Philip Rosedale on March 29, 2016 -// 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 -// -// This entity script causes the object to move with gravitational force and be attracted to other spheres nearby. -// The force is scaled by GRAVITY_STRENGTH, and only entities of type "Sphere" within GRAVITY_RANGE will affect it. -// The person who has most recently grabbed this object will simulate it. -// - -function Timer() { - var time; - var count = 0; - var totalTime = 0; - this.reset = function() { - count = 0; - totalTime = 0; - } - this.start = function() { - time = new Date().getTime(); - } - this.record = function() { - var elapsed = new Date().getTime() - time; - totalTime += elapsed; - count++; - return elapsed; - } - this.count = function() { - return count; - } - this.average = function() { - return (count == 0) ? 0 : totalTime / count; - } - this.elapsed = function() { - return new Date().getTime() - time; - } -} - -(function () { - var entityID, - wantDebug = true, - CHECK_INTERVAL = 10.00, - SEARCH_INTERVAL = 1000, - GRAVITY_RANGE = 20.0, - GRAVITY_STRENGTH = 1.0, - MIN_VELOCITY = 0.01, - timeoutID = null, - timeSinceLastSearch = 0, - timer = new Timer(), - simulate = false, - spheres = []; - - var printDebug = function(message) { - if (wantDebug) { - print(message); - } - } - - var greatestDimension = function(dimensions) { - return Math.max(Math.max(dimensions.x, dimensions.y), dimensions.z); - } - - var mass2 = function(dimensions) { - return dimensions.x * dimensions.y * dimensions.z; - } - - var findSpheres = function(position) { - var entities = Entities.findEntities(position, GRAVITY_RANGE); - spheres = []; - for (var i = 0; i < entities.length; i++) { - if (entityID == spheres[i]) { - // this entity doesn't experience its own gravity. - continue; - } - var props = Entities.getEntityProperties(entities[i]); - if (props && (props.shapeType == "sphere" || props.type == "Sphere")) { - spheres.push(entities[i]); - } - } - // print("FOUND " + spheres.length + " SPHERES"); - } - - var applyGravity = function() { - if (!simulate) { - return; - } - - var properties = Entities.getEntityProperties(entityID); - if (!properties || !properties.position) { - return; - } - - // update the list of nearby spheres - var deltaTime = timer.elapsed() / 1000.0; - if (deltaTime == 0.0) { - return; - } - timeSinceLastSearch += CHECK_INTERVAL; - if (timeSinceLastSearch >= SEARCH_INTERVAL) { - findSpheres(properties.position); - timeSinceLastSearch = 0; - } - - var deltaVelocity = { x: 0, y: 0, z: 0 }; - var otherCount = 0; - var mass = mass2(properties.dimensions); - - for (var i = 0; i < spheres.length; i++) { - otherProperties = Entities.getEntityProperties(spheres[i]); - if (!otherProperties || !otherProperties.position) { - continue; // sphere was deleted - } - otherCount++; - var radius = Vec3.distance(properties.position, otherProperties.position); - var otherMass = mass2(otherProperties.dimensions); - var r = (greatestDimension(properties.dimensions) + greatestDimension(otherProperties.dimensions)) / 2; - if (radius > r) { - var n0 = Vec3.normalize(Vec3.subtract(otherProperties.position, properties.position)); - var n1 = Vec3.multiply(deltaTime * GRAVITY_STRENGTH * otherMass / (radius * radius), n0); - deltaVelocity = Vec3.sum(deltaVelocity, n1); - } - } - Entities.editEntity(entityID, { velocity: Vec3.sum(properties.velocity, deltaVelocity) }); - if (Vec3.length(properties.velocity) < MIN_VELOCITY) { - print("Gravity simulation stopped due to velocity"); - simulate = false; - } else { - timer.start(); - timeoutID = Script.setTimeout(applyGravity, CHECK_INTERVAL); - } - } - this.applyGravity = applyGravity; - - var releaseGrab = function() { - printDebug("Gravity simulation started."); - var properties = Entities.getEntityProperties(entityID); - findSpheres(properties.position); - timer.start(); - timeoutID = Script.setTimeout(applyGravity, CHECK_INTERVAL); - simulate = true; - } - this.releaseGrab = releaseGrab; - - var preload = function (givenEntityID) { - printDebug("load gravity..."); - entityID = givenEntityID; - }; - this.preload = preload; - - var unload = function () { - printDebug("Unload gravity..."); - if (timeoutID !== undefined) { - Script.clearTimeout(timeoutID); - } - if (simulate) { - Entities.editEntity(entityID, { velocity: { x: 0, y: 0, z: 0 } }); - } - }; - this.unload = unload; - - var handleMessages = function(channel, message, sender) { - if (channel === 'Hifi-Object-Manipulation') { - try { - var parsedMessage = JSON.parse(message); - if (parsedMessage.action === 'grab' && parsedMessage.grabbedEntity == entityID) { - print("Gravity simulation stopped due to grab"); - simulate = false; - } - } catch (e) { - print('error parsing Hifi-Object-Manipulation message: ' + message); - } - } - } - this.handleMessages = handleMessages; - - Messages.messageReceived.connect(this.handleMessages); - Messages.subscribe('Hifi-Object-Manipulation'); -}); diff --git a/scripts/tutorials/NBody/gravity.svg b/scripts/tutorials/NBody/gravity.svg deleted file mode 100644 index 9bac2d65e1..0000000000 --- a/scripts/tutorials/NBody/gravity.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/scripts/tutorials/NBody/makePlanets.js b/scripts/tutorials/NBody/makePlanets.js deleted file mode 100644 index 21415ccdc2..0000000000 --- a/scripts/tutorials/NBody/makePlanets.js +++ /dev/null @@ -1,166 +0,0 @@ -// makePlanets.js -// -// Created by Philip Rosedale on March 29, 2016 -// 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 -// -// Make an earth and moon, where you can grab and throw moon into orbit. Entity -// script attached to moon gives it gravitation behavior and will also make it attracted to -// other spheres placed nearby. -// - -var SCALE = 3.0; -var EARTH_SIZE = 3.959 / SCALE; -var MOON_SIZE = 1.079 / SCALE; - -var BUTTON_SIZE = 32; -var PADDING = 3; - -var earth = null; -var moon = null; - -var SCRIPT_URL = Script.resolvePath("gravity.js"); - -HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -Script.include(["/~/system/libraries/toolBars.js"]); -var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.makePlanets.js"); - -var makePlanetsIconURL = Script.resolvePath("gravity.svg"); -var button = toolBar.addOverlay("image", { - width: BUTTON_SIZE, - height: BUTTON_SIZE, - imageURL: makePlanetsIconURL, - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1 -}); - -var deleteButton = toolBar.addOverlay("image", { - width: BUTTON_SIZE, - height: BUTTON_SIZE, - imageURL: HIFI_PUBLIC_BUCKET + "images/delete.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1 -}); - -function inFrontOfMe(distance) { - return Vec3.sum(Camera.getPosition(), Vec3.multiply(distance, Quat.getForward(Camera.getOrientation()))); -} - -function onButtonClick() { - earth = Entities.addEntity({ - type: "Model", - name: "Earth", - modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/NBody/earth.fbx", - position: inFrontOfMe(2 * EARTH_SIZE), - dimensions: { x: EARTH_SIZE, y: EARTH_SIZE, z: EARTH_SIZE }, - shapeType: "sphere", - lifetime: 86400, // 1 day - angularDamping: 0, - angularVelocity: { x: 0, y: 0.1, z: 0 }, - }); - moon = Entities.addEntity({ - type: "Model", - name: "Moon", - modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/NBody/moon.fbx", - position: inFrontOfMe(EARTH_SIZE - MOON_SIZE), - dimensions: { x: MOON_SIZE, y: MOON_SIZE, z: MOON_SIZE }, - dynamic: true, - damping: 0, // 0.01, - angularDamping: 0, // 0.01, - script: SCRIPT_URL, - shapeType: "sphere" - }); - Entities.addEntity({ - "accelerationSpread": { - "x": 0, - "y": 0, - "z": 0 - }, - "alpha": 1, - "alphaFinish": 0, - "alphaStart": 1, - "azimuthFinish": 0, - "azimuthStart": 0, - "color": { - "blue": 255, - "green": 255, - "red": 255 - }, - "colorFinish": { - "blue": 255, - "green": 255, - "red": 255 - }, - "colorStart": { - "blue": 255, - "green": 255, - "red": 255 - }, - "dimensions": { - "x": 0.10890001058578491, - "y": 0.10890001058578491, - "z": 0.10890001058578491 - }, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 - }, - "emitOrientation": { - "w": 0.99999994039535522, - "x": 0, - "y": 0, - "z": 0 - }, - "emitRate": 300, - "emitSpeed": 0, - "emitterShouldTrail": 1, - "maxParticles": 10000, - "name": "moon trail", - "parentID": moon, - "particleRadius": 0.005, - "radiusFinish": 0.005, - "radiusSpread": 0.005, - "radiusStart": 0.005, - "speedSpread": 0, - "lifespan": 20, - "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - "type": "ParticleEffect", - "userData": "{\"grabbableKey\":{\"grabbable\":false}}" - }); -} - -function onDeleteButton() { - Entities.deleteEntity(earth); - Entities.deleteEntity(moon); -} - -function mousePressEvent(event) { - var clickedText = false; - var clickedOverlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (clickedOverlay == button) { - onButtonClick(); - } else if (clickedOverlay == deleteButton) { - onDeleteButton(); - } -} - -function scriptEnding() { - toolBar.cleanup(); -} - -Controller.mousePressEvent.connect(mousePressEvent); -Script.scriptEnding.connect(scriptEnding); diff --git a/scripts/tutorials/createSwords.js b/scripts/tutorials/createSwords.js new file mode 100644 index 0000000000..749df3c5ed --- /dev/null +++ b/scripts/tutorials/createSwords.js @@ -0,0 +1,59 @@ +// createSwords.js +// +// Created by Philip Rosedale on April 9, 2017 +// 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 +// +// Makes two grabbable 'swords' in front of the user, that can be held and used +// to hit the other. Demonstration of an action that would allow two people to hold +// entities that are also colliding. +// + +var COLOR = { red: 255, green: 0, blue: 0 }; +var SIZE = { x: 0.10, y: 1.5, z: 0.10 }; + +var SCRIPT_URL = Script.resolvePath("entity_scripts/springHold.js"); + +function inFrontOfMe(distance) { + return Vec3.sum(Camera.getPosition(), Vec3.multiply(distance, Quat.getForward(Camera.getOrientation()))); +} + +var sword1 = Entities.addEntity({ + type: "Box", + name: "Sword1", + position: inFrontOfMe(2 * SIZE.y), + dimensions: SIZE, + color: COLOR, + angularDamping: 0, + damping: 0, + script: SCRIPT_URL, + userData:JSON.stringify({ + grabbableKey:{ + grabbable:true + } + }) + }); + +var sword2 = Entities.addEntity({ + type: "Box", + name: "Sword2", + position: inFrontOfMe(3 * SIZE.y), + dimensions: SIZE, + color: COLOR, + angularDamping: 0, + damping: 0, + script: SCRIPT_URL, + userData:JSON.stringify({ + grabbableKey:{ + grabbable:true + } + }) + }); + +Script.scriptEnding.connect(function scriptEnding() { + Entities.deleteEntity(sword1); + Entities.deleteEntity(sword2); +}); + diff --git a/scripts/tutorials/entity_scripts/springHold.js b/scripts/tutorials/entity_scripts/springHold.js new file mode 100644 index 0000000000..12b34381a6 --- /dev/null +++ b/scripts/tutorials/entity_scripts/springHold.js @@ -0,0 +1,116 @@ +// +// springHold.js +// +// Created by Philip Rosedale on March 18, 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Attach this entity script to a model or basic shape and grab it. The object will +// follow your hand like a spring, allowing you, for example, to swordfight with others. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + + var TIMESCALE = 0.03; + var ACTION_TTL = 10; + var _this; + + function SpringHold() { + _this = this; + } + + function updateSpringAction(timescale) { + + var targetProps = Entities.getEntityProperties(_this.entityID); + var props = { + targetPosition: targetProps.position, + targetRotation: targetProps.rotation, + linearTimeScale: timescale, + angularTimeScale: timescale, + ttl: ACTION_TTL + }; + Entities.updateAction(_this.copy, _this.actionID, props); + } + + function createSpringAction(timescale) { + + var targetProps = Entities.getEntityProperties(_this.entityID); + var props = { + targetPosition: targetProps.position, + targetRotation: targetProps.rotation, + linearTimeScale: timescale, + angularTimeScale: timescale, + ttl: ACTION_TTL + }; + _this.actionID = Entities.addAction("spring", _this.copy, props); + } + + function createCopy() { + var originalProps = Entities.getEntityProperties(_this.entityID); + var props = { + type: originalProps.type, + color: originalProps.color, + modelURL: originalProps.modelURL, + dimensions: originalProps.dimensions, + dynamic: true, + damping: 0.0, + angularDamping: 0.0, + collidesWith: 'dynamic,static,kinematic', + rotation: originalProps.rotation, + position: originalProps.position, + shapeType: originalProps.shapeType, + visible: true, + userData:JSON.stringify({ + grabbableKey:{ + grabbable:false + } + }) + }; + _this.copy = Entities.addEntity(props); + } + + function deleteCopy() { + Entities.deleteEntity(_this.copy); + } + + function makeOriginalInvisible() { + Entities.editEntity(_this.entityID, { + visible: false, + collisionless: true + }); + } + + function makeOriginalVisible() { + Entities.editEntity(_this.entityID, { + visible: true, + collisionless: false + }); + } + + function deleteSpringAction() { + Entities.deleteAction(_this.copy, _this.actionID); + } + + SpringHold.prototype = { + preload: function(entityID) { + _this.entityID = entityID; + }, + startNearGrab: function(entityID, data) { + createCopy(); + createSpringAction(TIMESCALE); + makeOriginalInvisible(); + }, + continueNearGrab: function() { + updateSpringAction(TIMESCALE); + }, + releaseGrab: function() { + deleteSpringAction(); + deleteCopy(); + makeOriginalVisible(); + } + }; + + return new SpringHold(); +}); \ No newline at end of file diff --git a/scripts/tutorials/entity_scripts/touch.js b/scripts/tutorials/entity_scripts/touch.js new file mode 100644 index 0000000000..d6a59aa167 --- /dev/null +++ b/scripts/tutorials/entity_scripts/touch.js @@ -0,0 +1,206 @@ +(function() { + + // touch.js + // + // Sample file using spring action, haptic vibration, and color change to demonstrate two spheres + // That can give a sense of touch to the holders. + // Create two standard spheres, make them grabbable, and attach this entity script. Grab them and touch them together. + // + // Created by Philip Rosedale on March 18, 2017 + // Copyright 2017 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 + // + + var TIMESCALE = 0.03; + var ACTION_TTL = 10; + var _this; + + var RIGHT_HAND = 1; + var LEFT_HAND = 0; + var HAPTIC_PULSE_FIRST_STRENGTH = 0.5; + var HAPTIC_PULSE_MIN_STRENGTH = 0.20; + var HAPTIC_PULSE_MAX_STRENGTH = 0.5; + var HAPTIC_PULSE_FIRST_DURATION = 1.0; + var HAPTIC_PULSE_DURATION = 16.0; + var HAPTIC_PULSE_DISTANCE = 0.0; + var MAX_PENETRATION = 0.02; + var HAPTIC_MIN_VELOCITY = 0.002; + var HAPTIC_MAX_VELOCITY = 0.5; + var PENETRATION_PULLBACK_FACTOR = 0.65; + var FRAME_TIME = 0.016; + + var isColliding = false; + + var hand = LEFT_HAND; + var lastHapticPulseLocation = { x:0, y:0, z:0 }; + + + var GRAY = { red: 128, green: 128, blue: 128 }; + var RED = { red: 255, green: 0, blue: 0 }; + + var targetColor = { x: GRAY.red, y: GRAY.green, z: GRAY.blue }; + + var lastPosition = { x: 0, y: 0, z: 0 }; + var velocity = { x: 0, y: 0, z: 0 }; + + var lastOtherPosition = { x: 0, y: 0, z: 0 }; + var otherVelocity = { x: 0, y: 0, z: 0 }; + + + function TouchExample() { + _this = this; + } + + function updateSpringAction(timescale) { + var targetProps = Entities.getEntityProperties(_this.entityID); + // + // Look for nearby entities to touch + // + var copyProps = Entities.getEntityProperties(_this.copy); + var nearbyEntities = Entities.findEntities(copyProps.position, copyProps.dimensions.x * 2); + var wasColliding = isColliding; + var targetAdjust = { x: 0, y: 0, z: 0 }; + + isColliding = false; + for (var i = 0; i < nearbyEntities.length; i++) { + if (_this.copy != nearbyEntities[i] && _this.entityID != nearbyEntities[i]) { + var otherProps = Entities.getEntityProperties(nearbyEntities[i]); + var penetration = Vec3.distance(copyProps.position, otherProps.position) - (copyProps.dimensions.x / 2 + otherProps.dimensions.x / 2); + if (otherProps.type === 'Sphere' && penetration < 0 && penetration > -copyProps.dimensions.x * 3) { + isColliding = true; + targetAdjust = Vec3.sum(targetAdjust, Vec3.multiply(Vec3.normalize(Vec3.subtract(targetProps.position, otherProps.position)), -penetration * PENETRATION_PULLBACK_FACTOR)); + if (!wasColliding && false) { + targetColor = { x: RED.red, y: RED.green, z: RED.blue }; + } else { + targetColor = { x: 200 + Math.min(-penetration / MAX_PENETRATION, 1.0) * 55, y: GRAY.green, z: GRAY.blue }; + } + if (Vec3.distance(targetProps.position, lastHapticPulseLocation) > HAPTIC_PULSE_DISTANCE || !wasColliding) { + if (!wasColliding) { + velocity = { x: 0, y: 0, z: 0}; + otherVelocity = { x: 0, y: 0, z: 0 }; + Controller.triggerHapticPulse(HAPTIC_PULSE_FIRST_STRENGTH, HAPTIC_PULSE_FIRST_DURATION, hand); + } else { + velocity = Vec3.distance(targetProps.position, lastPosition) / FRAME_TIME; + otherVelocity = Vec3.distance(otherProps.position, lastOtherPosition) / FRAME_TIME; + var velocityStrength = Math.min(velocity + otherVelocity / HAPTIC_MAX_VELOCITY, 1.0); + var strength = HAPTIC_PULSE_MIN_STRENGTH + Math.min(-penetration / MAX_PENETRATION, 1.0) * (HAPTIC_PULSE_MAX_STRENGTH - HAPTIC_PULSE_MIN_STRENGTH); + Controller.triggerHapticPulse(velocityStrength * strength, HAPTIC_PULSE_DURATION, hand); + } + lastPosition = targetProps.position; + lastOtherPosition = otherProps.position; + lastHapticPulseLocation = targetProps.position; + } + } + } + } + if ((wasColliding != isColliding) && !isColliding) { + targetColor = { x: GRAY.red, y: GRAY.green, z: GRAY.blue }; + } + // Interpolate color toward target color + var currentColor = { x: copyProps.color.red, y: copyProps.color.green, z: copyProps.color.blue }; + var newColor = Vec3.sum(currentColor, Vec3.multiply(Vec3.subtract(targetColor, currentColor), 0.1)); + Entities.editEntity(_this.copy, { color: { red: newColor.x, green: newColor.y, blue: newColor.z } }); + + var props = { + targetPosition: Vec3.sum(targetProps.position, targetAdjust), + targetRotation: targetProps.rotation, + linearTimeScale: timescale, + angularTimeScale: timescale, + ttl: ACTION_TTL + }; + var success = Entities.updateAction(_this.copy, _this.actionID, props); + } + + function createSpringAction(timescale) { + + var targetProps = Entities.getEntityProperties(_this.entityID); + var props = { + targetPosition: targetProps.position, + targetRotation: targetProps.rotation, + linearTimeScale: timescale, + angularTimeScale: timescale, + ttl: ACTION_TTL + }; + _this.actionID = Entities.addAction("spring", _this.copy, props); + return; + } + + function createCopy() { + var originalProps = Entities.getEntityProperties(_this.entityID); + var props = { + type: originalProps.type, + modelURL: originalProps.modelURL, + dimensions: originalProps.dimensions, + color: GRAY, + dynamic: true, + damping: 0.0, + angularDamping: 0.0, + collidesWith: 'static', + rotation: originalProps.rotation, + position: originalProps.position, + shapeType: originalProps.shapeType, + visible: true, + userData:JSON.stringify({ + grabbableKey:{ + grabbable:false + } + }) + }; + _this.copy = Entities.addEntity(props); + } + + function deleteCopy() { + print("Delete copy"); + Entities.deleteEntity(_this.copy); + } + + function makeOriginalInvisible() { + Entities.editEntity(_this.entityID, { + visible: false, + collisionless: true + }); + } + + function makeOriginalVisible() { + Entities.editEntity(_this.entityID, { + visible: true, + collisionless: false + }); + } + + function deleteSpringAction() { + Entities.deleteAction(_this.copy, _this.actionID); + } + + function setHand(position) { + if (Vec3.distance(MyAvatar.getLeftPalmPosition(), position) < Vec3.distance(MyAvatar.getRightPalmPosition(), position)) { + hand = LEFT_HAND; + } else { + hand = RIGHT_HAND; + } + } + + TouchExample.prototype = { + preload: function(entityID) { + _this.entityID = entityID; + }, + startNearGrab: function(entityID, data) { + createCopy(); + createSpringAction(TIMESCALE); + makeOriginalInvisible(); + setHand(Entities.getEntityProperties(_this.entityID).position); + }, + continueNearGrab: function() { + updateSpringAction(TIMESCALE); + }, + releaseGrab: function() { + deleteSpringAction(); + deleteCopy(); + makeOriginalVisible(); + } + }; + + return new TouchExample(); +}); \ No newline at end of file diff --git a/scripts/tutorials/nBody.js b/scripts/tutorials/nBody.js new file mode 100644 index 0000000000..01797201b2 --- /dev/null +++ b/scripts/tutorials/nBody.js @@ -0,0 +1,67 @@ +// +// nBody.js +// examples +// +// Created by Philip Rosedale on March 18, 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Create some spheres that obey gravity, which is great to teach physics. +// You can control how many to create by changing the value of 'n' below. +// Grab them and watch the others move around. +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var bodies = []; +var n = 3; +var radius = 0.1; +var G = 0.25; +var EARTH = "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/NBody/earth.fbx"; +var MOON = "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/NBody/moon.fbx"; + +var COLOR1 = { red: 51, green: 51, blue: 255 }; +var COLOR2 = { red: 51, green: 51, blue: 255 }; +var COLOR3 = { red: 51, green: 51, blue: 255 }; + +var inFront = Vec3.sum(Camera.getPosition(), Vec3.multiply(radius * 20, Quat.getFront(Camera.getOrientation()))); + +for (var i = 0; i < n; i++) { + bodies.push(Entities.addEntity({ + type: "Model", + modelURL: (i == 0) ? EARTH : MOON, + shapeType: "sphere", + dimensions: { x: radius * 2, y: radius * 2, z: radius * 2}, + position: Vec3.sum(inFront, { x: 0, y: i * 2 * radius, z: 0 }), + gravity: { x: 0, y: 0, z: 0 }, + damping: 0.0, + angularDamping: 0.0, + dynamic: true + })); +} + +Script.update.connect(function(dt) { + var props = []; + for (var i = 0; i < n; i++) { + props.push(Entities.getEntityProperties(bodies[i])); + } + for (var i = 0; i < n; i++) { + if (props[i].dynamic) { + var dv = { x: 0, y: 0, z: 0}; + for (var j = 0; j < n; j++) { + if (i != j) { + dv = Vec3.sum(dv, Vec3.multiply(G * dt / Vec3.distance(props[i].position, props[j].position), + Vec3.normalize(Vec3.subtract(props[j].position, props[i].position)))); + } + } + Entities.editEntity(bodies[i], { velocity: Vec3.sum(props[i].velocity, dv)}); + } + } +}); + +Script.scriptEnding.connect(function scriptEnding() { + for (var i = 0; i < n; i++) { + Entities.deleteEntity(bodies[i]); + } +}); \ No newline at end of file