Andrew Meadowsarchive remaining JS scriptsc0b446c10 years agoHistory
497 lines · 14.2 KB · JavaScript
RawDownload
// //  solarsystem.js//  example //  //  Created by Bridget Went, 5/28/15.//  Copyright 2015 High Fidelity, Inc.//  //  A project to build a virtual physics classroom to simulate the solar system, gravity, and orbital physics. //// //  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// CreateSimulation = function() {    Script.include("https://hifi-public.s3.amazonaws.com/eric/scripts/tween.js");    Script.include('games/satellite.js');     var trailsEnabled = this.trailsEnabled = true;     var DAMPING = this.DAMPING = 0.0;    var LIFETIME = this.LIFETIME = 6000;    var BASE_URL = this.BASE_URL = "https://s3.amazonaws.com/hifi-public/marketplace/hificontent/Scripts/planets/planets/";     // Save intiial avatar and camera position    var startingPosition = this.startingPosition = {        x: 8000,        y: 8000,        z: 8000    };    MyAvatar.position = startingPosition;    var cameraStart = this.cameraStart = Camera.getOrientation();      // Place the sun    var MAX_RANGE = this.MAX_RANGE = 100.0;    var center = this.center = Vec3.sum(startingPosition, Vec3.multiply(MAX_RANGE, Vec3.normalize(Quat.getFront(Camera.getOrientation()))));    var SUN_SIZE = this.SUN_SIZE = 7.0;     var theSun = this.theSun = Entities.addEntity({        type: "Model",        modelURL: BASE_URL + "sun.fbx",        position: center,        dimensions: {            x: SUN_SIZE,            y: SUN_SIZE,            z: SUN_SIZE        },        angularVelocity: {            x: 0.0,            y: 0.1,            z: 0.0        },        angularDamping: DAMPING,        damping: DAMPING,        ignoreCollisions: false,        lifetime: LIFETIME,        dynamic: false    });       // Reference values for physical constants    var referenceRadius = this.referenceRadius = 15.0;    var referenceDiameter = this.referenceDiameter = 0.6;    var referencePeriod = this.referencePeriod = 3.0;    var LARGE_BODY_MASS = this.LARGE_BODY_MASS = 250.0;    var SMALL_BODY_MASS = this.SMALL_BODY_MASS = LARGE_BODY_MASS * 0.000000333;    var GRAVITY = this.GRAVITY = (Math.pow(referenceRadius, 3.0) / Math.pow((referencePeriod / (2.0 * Math.PI)), 2.0)) / LARGE_BODY_MASS;    var REFERENCE_GRAVITY = this.REFERENCE_GRAVITY = GRAVITY;     var planets = this.planets = [];    var MAX_POINTS_PER_LINE = this.MAX_POINTS_PER_LINE = 40;    var LINE_DIM = this.LINE_DIM = 200;    var LINE_WIDTH = this.LINE_WIDTH = 20;     var VELOCITY_OFFSET_Y = this.VELOCITY_OFFSET_Y = -0.3;    var VELOCITY_OFFSET_Z = this.VELOCITY_OFFSET_Z = 0.9;     var index = this.index = 0;     this.computeLocalPoint = function(linePos, worldPoint) {        var localPoint = Vec3.subtract(worldPoint, linePos);        return localPoint;    }     // Create a new line    this.newLine = function(lineStack, point, period, color) {        if (elapsed < period) {            var line = Entities.addEntity({                position: point,                type: "Line",                color: color,                dimensions: {                    x: LINE_DIM,                    y: LINE_DIM,                    z: LINE_DIM                },                lifetime: LIFETIME,                lineWidth: LINE_WIDTH            });            lineStack.push(line);        } else {            // Begin overwriting first lines after one full revolution (one period)            var firstLine = lineStack.shift();            Entities.editEntity(firstLine, {                position: point,                linePoints: [{                    x: 0.0,                    y: 0.0,                    z: 0.0                }]            });            lineStack.push(firstLine);         }        var points = [];        points.push(computeLocalPoint(point, point));        return points;    }     this.pause = function() {        if (paused) {            return;        }        for (var i = 0; i < planets.length; ++i) {            Entities.editEntity(planets[i].planet, {                velocity: {                    x: 0.0,                    y: 0.0,                    z: 0.0                }            });            planets[i].label = new PlanetLabel(planets[i].name, i);            planets[i].label.show();        }        paused = true;    }     this.resume = function() {        if (!paused) {            return;        }        for (var i = 0; i < planets.length; ++i) {            planets[i].label.hide();        }        paused = false;    }     var Planet = function(name, trailColor, radiusScale, sizeScale) {        this.name = name;        this.trailColor = trailColor;         this.trail = [];        this.lineStack = [];         this.radius = radiusScale * referenceRadius;        this.position = Vec3.sum(center, {            x: this.radius,            y: 0.0,            z: 0.0        });        this.startPosition = this.position;        this.period = (2.0 * Math.PI) * Math.sqrt(Math.pow(this.radius, 3.0) / (GRAVITY * LARGE_BODY_MASS));         this.initialVelocity = Math.sqrt((GRAVITY * LARGE_BODY_MASS) / this.radius);         this.velocity = Vec3.multiply(this.initialVelocity, Vec3.normalize({            x: 0,            y: VELOCITY_OFFSET_Y,            z: VELOCITY_OFFSET_Z        }));        this.dimensions = sizeScale * referenceDiameter;        this.sizeScale = sizeScale;         this.planet = Entities.addEntity({            type: "Model",            modelURL: BASE_URL + name + ".fbx",            position: this.position,            dimensions: {                x: this.dimensions,                y: this.dimensions,                z: this.dimensions            },            velocity: this.velocity,            angularDamping: DAMPING,            damping: DAMPING,            ignoreCollisions: false,            lifetime: LIFETIME,            dynamic: false,        });         this.computeAcceleration = function() {            var acc = -(GRAVITY * LARGE_BODY_MASS) * Math.pow(this.radius, (-2.0));            return acc;        };         this.update = function(deltaTime) {            var between = Vec3.subtract(this.position, center);            var speed = this.computeAcceleration(this.radius) * deltaTime;            var vel = Vec3.multiply(speed, Vec3.normalize(between));             // Update velocity and position            this.velocity = Vec3.sum(this.velocity, vel);            this.position = Vec3.sum(this.position, Vec3.multiply(deltaTime, this.velocity));            Entities.editEntity(this.planet, {                velocity: this.velocity,                position: this.position            });             if (trailsEnabled) {                this.updateTrail();            }        };         this.clearTrails = function() {            elapsed = 0.0;            for (var j = 0; j < this.lineStack.length; ++j) {                Entities.editEntity(this.lineStack[j], {                    visible: false                });            }         }        this.resetTrails = function() {            elapsed = 0.0;            this.trail = [];            this.lineStack = [];            //add the first line to both the line entity stack and the trail            this.trail.push(newLine(this.lineStack, this.position, this.period, this.trailColor));         };         this.updateTrail = function() {            var point = this.position;            var linePos = Entities.getEntityProperties(this.lineStack[this.lineStack.length - 1]).position;             this.trail.push(computeLocalPoint(linePos, point));             Entities.editEntity(this.lineStack[this.lineStack.length - 1], {                linePoints: this.trail            });             if (this.trail.length == MAX_POINTS_PER_LINE) {                this.trail = newLine(this.lineStack, point, this.period, this.trailColor);            }        };         this.zoom = function() {            if (!paused) {                pause();            }            this.tweening = true;            var tweenTime = 1000;            var startingPosition = MyAvatar.position;            var endingPosition = Vec3.sum({                x: 0,                y: 0,                z: this.sizeScale            }, this.position);            var currentProps = {                x: startingPosition.x,                y: startingPosition.y,                z: startingPosition.z,            };            var endProps = {                x: endingPosition.x,                y: endingPosition.y,                z: endingPosition.z,            };             var moveTween = new TWEEN.Tween(currentProps).            to(endProps, tweenTime).            easing(TWEEN.Easing.Cubic.InOut).            onUpdate(function() {                MyAvatar.position = {                    x: currentProps.x,                    y: currentProps.y,                    z: currentProps.z                };            }).start();             moveTween.onComplete(function() {                Camera.lookAt(endingPosition);                this.tweening = false;            });         }         index++;        this.resetTrails();     }      var MERCURY_LINE_COLOR = {        red: 255,        green: 255,        blue: 255    };    var VENUS_LINE_COLOR = {        red: 255,        green: 160,        blue: 110    };    var EARTH_LINE_COLOR = {        red: 10,        green: 150,        blue: 160    };    var MARS_LINE_COLOR = {        red: 180,        green: 70,        blue: 10    };    var JUPITER_LINE_COLOR = {        red: 250,        green: 140,        blue: 0    };    var SATURN_LINE_COLOR = {        red: 235,        green: 215,        blue: 0    };    var URANUS_LINE_COLOR = {        red: 135,        green: 205,        blue: 240    };    var NEPTUNE_LINE_COLOR = {        red: 30,        green: 140,        blue: 255    };    var PLUTO_LINE_COLOR = {        red: 255,        green: 255,        blue: 255    };     this.initPlanets = function() {        planets.push(new Planet("mercury", MERCURY_LINE_COLOR, 0.387, 0.383));        planets.push(new Planet("venus", VENUS_LINE_COLOR, 0.723, 0.949));        planets.push(new Planet("earth", EARTH_LINE_COLOR, 1.0, 1.0));        planets.push(new Planet("mars", MARS_LINE_COLOR, 1.52, 0.532));        planets.push(new Planet("jupiter", JUPITER_LINE_COLOR, 5.20, 11.21));        planets.push(new Planet("saturn", SATURN_LINE_COLOR, 9.58, 9.45));        planets.push(new Planet("uranus", URANUS_LINE_COLOR, 19.20, 4.01));        planets.push(new Planet("neptune", NEPTUNE_LINE_COLOR, 30.05, 3.88));        planets.push(new Planet("pluto", PLUTO_LINE_COLOR, 39.48, 0.186));    }    initPlanets();     var LABEL_X = 8.0;    var LABEL_Y = 3.0;    var LABEL_Z = 1.0;    var LABEL_DIST = 8.0;    var TEXT_HEIGHT = 1.0;     var PlanetLabel = function(name, index) {        var text = name + "                    Speed: " + Vec3.length(planets[index].velocity).toFixed(2);        this.labelPos = Vec3.sum(planets[index].position, {            x: 0.0,            y: LABEL_DIST,            z: LABEL_DIST        });        this.linePos = planets[index].position;         this.line = Entities.addEntity({            type: "Line",            position: this.linePos,            dimensions: {                x: 20,                y: 20,                z: 20            },            lineWidth: LINE_WIDTH,            color: {                red: 255,                green: 255,                blue: 255            },            linePoints: [{                    x: 0,                    y: 0,                    z: 0                },                computeLocalPoint(this.linePos, this.labelPos)            ],            visible: false        });         this.label = Entities.addEntity({            type: "Text",            text: text,            lineHeight: TEXT_HEIGHT,            dimensions: {                x: LABEL_X,                y: LABEL_Y,                z: LABEL_Z            },            position: this.labelPos,            backgroundColor: {                red: 10,                green: 10,                blue: 10            },            faceCamera: true,            visible: false        });         this.show = function() {            this.showing = true;            Entities.editEntity(this.line, {                visible: true            });            Entities.editEntity(this.label, {                visible: true            });        }         this.hide = function() {            this.showing = false;            Entities.editEntity(this.line, {                visible: false            });            Entities.editEntity(this.label, {                visible: false            });        }    }     var planetLines = [];    var trails = this.trails = [];    var paused = this.paused = false;     var time = 0;    var elapsed;    var TIME_STEP = 80;     this.update = function(deltaTime) {        for (var i = 0; i < planets.length; ++i) {            if (paused) {                return;            }            planets[i].update(deltaTime);        }         time++;        if (time % TIME_STEP == 0) {            elapsed++;        }     }     Script.include('planets-ui.js');     // Clean up models, UI panels, lines, and button overlays    this.scriptEnding = function() {         Entities.deleteEntity(theSun);        for (var i = 0; i < planets.length; ++i) {            Entities.deleteEntity(planets[i].planet);        }        var e = Entities.findEntities(MyAvatar.position, 10000);        for (i = 0; i < e.length; i++) {            var props = Entities.getEntityProperties(e[i]);            if (props.type === "Line" || props.type === "Text") {                Entities.deleteEntity(e[i]);            }        }    };     this.restart = function() {        if (paused) {            resume();        }        for (var i = 0; i < planets.length; ++i) {            Entities.deleteEntity(planets[i].planet);            planets[i].clearTrails();        }        time = 0.0;        elapsed = 0.0;        planets.length = 0;        initPlanets();          MyAvatar.position = startingPosition;        Camera.setPosition(cameraStart);    }; }CreateSimulation(); Script.update.connect(update);Script.scriptEnding.connect(scriptEnding);