From f79abe5f16db88f6c5b844ff52e942a25c19677b Mon Sep 17 00:00:00 2001 From: strikerM Date: Thu, 12 Jan 2017 10:38:47 +0200 Subject: [PATCH] refactor code, added comments and license headers --- examples/StarField.js | 13 +-- src/layer/StarFieldLayer.js | 136 +++++++++++++++++++++++++------- src/shaders/StarFieldProgram.js | 62 ++++++++------- 3 files changed, 143 insertions(+), 68 deletions(-) diff --git a/examples/StarField.js b/examples/StarField.js index 42d1185c..7a12d420 100644 --- a/examples/StarField.js +++ b/examples/StarField.js @@ -2,9 +2,6 @@ * Copyright (C) 2014 United States Government as represented by the Administrator of the * National Aeronautics and Space Administration. All Rights Reserved. */ -/** - * @version $Id: BasicExample.js 3320 2015-07-15 20:53:05Z dcollins $ - */ requirejs([ '../src/WorldWind', @@ -25,16 +22,14 @@ requirejs([ var starFieldLayer = new WorldWind.StarFieldLayer(); var atmosphereLayer = new WorldWind.AtmosphereLayer(); wwd.addLayer(BMNGLayer); - wwd.addLayer(atmosphereLayer); wwd.addLayer(starFieldLayer); - atmosphereLayer.lightLocation = sunCalculator(new Date()); var layerManger = new LayerManager(wwd); wwd.redraw(); - wwd._redrawCallbacks.push(runSunSimulation1); + wwd._redrawCallbacks.push(runSunSimulation); var sunSimulationCheckBox = document.getElementById('sun-simulation'); var doRunSimulation = false; @@ -48,17 +43,17 @@ requirejs([ if (!doRunSimulation) { var date = new Date(); atmosphereLayer.lightLocation = sunCalculator(date); - starFieldLayer.date = date; + starFieldLayer.time = date; } wwd.redraw(); } - function runSunSimulation1(wwd, stage) { + function runSunSimulation(wwd, stage) { if (stage === WorldWind.AFTER_REDRAW && doRunSimulation) { timeStamp += (factor * 60 * 1000); var date = new Date(timeStamp); atmosphereLayer.lightLocation = sunCalculator(date); - starFieldLayer.date = date; + starFieldLayer.time = date; wwd.redraw(); } } diff --git a/src/layer/StarFieldLayer.js b/src/layer/StarFieldLayer.js index 104ed818..710d7e05 100644 --- a/src/layer/StarFieldLayer.js +++ b/src/layer/StarFieldLayer.js @@ -1,7 +1,10 @@ -/** - * Created by Florin on 12/22/2016. +/* + * Copyright (C) 2014 United States Government as represented by the Administrator of the + * National Aeronautics and Space Administration. All Rights Reserved. + */ +/** + * @exports StarFieldLayer */ - define([ './Layer', '../geom/Matrix', @@ -12,47 +15,100 @@ define([ StarFieldProgram) { 'use strict'; - var StarFieldLayer = function () { + /** + * Constructs a layer showing bright stars visible from the Earth with the naked eye. + * @alias StarFieldLayer + * @constructor + * @classdesc Provides a layer showing bright stars visible from the Earth with the naked eye. + * @param {URL} starDataSource optional url for the stars data. + * @augments Layer + */ + var StarFieldLayer = function (starDataSource) { Layer.call(this, 'StarField'); + // The StarField Layer is not pickable. this.pickEnabled = false; - this._date = new Date(); - this._positions = []; + //Documented in defineProperties below. + this._starDataSource = starDataSource || + WorldWind.configuration.baseUrl + 'examples/data/stars.json'; + + //Internal use only. + //The MVP matrix of this layer. this._matrix = Matrix.fromIdentity(); + + //Internal use only. + //gpu cache key for this layer vbo. this._positionsVboCacheKey = null; + //Internal use only. + this._numStars = 0; + + //Internal use only. this._starData = null; + + //Internal use only. + //A flag to indicate the star data is currently being retrieved. this._loadStarted = false; }; StarFieldLayer.prototype = Object.create(Layer.prototype); Object.defineProperties(StarFieldLayer.prototype, { - date: { + /** + * Url for the stars data. + * @memberof StarFieldLayer.prototype + * @type {URL} + */ + starDataSource: { get: function () { - return this._date; + return this._starDataSource; }, set: function (value) { - this._date = value; + this._starDataSource = value; + this.invalidateStarData(); } } }); + // Documented in superclass. StarFieldLayer.prototype.doRender = function (dc) { + if (dc.globe.is2D()) { + return; + } + if (!this._starData) { this.fetchStarData(); return; } - if (!this._positions.length) { - this.createGeometry(dc); + this.beginRendering(dc); + try { + this.doDraw(dc); } + finally { + this.endRendering(dc); + } + }; + // Internal. Intentionally not documented. + StarFieldLayer.prototype.beginRendering = function (dc) { dc.findAndBindProgram(StarFieldProgram); + }; + + // Internal. Intentionally not documented. + StarFieldLayer.prototype.doDraw = function (dc) { + var gl = dc.currentGlContext; + this.loadUniforms(dc); + this.loadAttributes(dc); + gl.depthMask(false); + gl.drawArrays(gl.POINTS, 0, this._numStars); + }; + + // Internal. Intentionally not documented. + StarFieldLayer.prototype.loadUniforms = function (dc) { var gl = dc.currentGlContext; var program = dc.currentProgram; - var gpuResourceCache = dc.gpuResourceCache; //multiplyByScale is necessary until the new camera implementation with the infinite projection matrix var eyePoint = dc.navigatorState.eyePoint; @@ -62,21 +118,29 @@ define([ this._matrix.multiplyByScale(altitude, altitude, altitude); program.loadModelviewProjection(gl, this._matrix); - var JD = this.julianDate(this._date); + var JD = this.julianDate(this.time); //this subtraction does not work properly on the GPU, it must be done on the CPU //possibly due to precision loss //number of days (positive or negative) since Greenwich noon, Terrestrial Time, on 1 January 2000 (J2000.0) - program.loadJD(gl, JD - 2451545.0); + program.loadNumDays(gl, JD - 2451545.0); + }; + + // Internal. Intentionally not documented. + StarFieldLayer.prototype.loadAttributes = function (dc) { + var gl = dc.currentGlContext; + var gpuResourceCache = dc.gpuResourceCache; if (!this._positionsVboCacheKey) { - this._positionsVboCacheKey = dc.gpuResourceCache.generateCacheKey(); + this._positionsVboCacheKey = gpuResourceCache.generateCacheKey(); } var vboId = gpuResourceCache.resourceForKey(this._positionsVboCacheKey); if (!vboId) { vboId = gl.createBuffer(); - gpuResourceCache.putResource(this._positionsVboCacheKey, vboId, this._positions.length * 4); + var positions = this.createGeometry(); + gpuResourceCache.putResource(this._positionsVboCacheKey, vboId, positions.length * 4); gl.bindBuffer(gl.ARRAY_BUFFER, vboId); - gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this._positions), gl.STATIC_DRAW); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); + this._numStars = Math.floor(positions.length / 4); } else { gl.bindBuffer(gl.ARRAY_BUFFER, vboId); @@ -85,14 +149,16 @@ define([ gl.enableVertexAttribArray(0); gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0); - - gl.depthMask(false); - - gl.drawArrays(gl.POINTS, 0, Math.floor(this._positions.length / 4)); - - gl.depthMask(true); }; + // Internal. Intentionally not documented. + StarFieldLayer.prototype.endRendering = function (dc) { + var gl = dc.currentGlContext; + gl.depthMask(true); + gl.disableVertexAttribArray(0); + }; + + // Internal. Intentionally not documented. StarFieldLayer.prototype.fetchStarData = function () { if (this._loadStarted) { return; @@ -124,26 +190,30 @@ define([ self._loadStarted = false; }; - xhr.open('GET', './data/stars.json', true); + xhr.open('GET', this._starDataSource, true); xhr.send(); }; + // Internal. Intentionally not documented. StarFieldLayer.prototype.createGeometry = function () { var data = this._starData.data; + var positions = []; for (var i = 0, len = data.length; i < len; i++) { var starInfo = data[i]; - var dec = starInfo[2]; //for latitude - var ra = starInfo[1]; //for longitude - var mag = starInfo[3]; - var pSize = mag < 4 ? 2 : 1; - this._positions.push(dec, ra, pSize, mag); + var declination = starInfo[2]; //for latitude + var rightAscension = starInfo[1]; //for longitude + var magnitude = starInfo[3]; + var pointSize = magnitude < 4 ? 2 : 1; + positions.push(declination, rightAscension, pointSize, magnitude); } + return positions; }; + // Internal. Intentionally not documented. StarFieldLayer.prototype.julianDate = function julianDate(date) { //http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html - //date = date || new Date(); + date = date || new Date(); var year = date.getUTCFullYear(); var month = date.getUTCMonth() + 1; var day = date.getUTCDate(); @@ -166,6 +236,12 @@ define([ }; + // Internal. Intentionally not documented. + StarFieldLayer.prototype.invalidateStarData = function (){ + this._starData = null; + this._positionsVboCacheKey = null; + }; + return StarFieldLayer; }); \ No newline at end of file diff --git a/src/shaders/StarFieldProgram.js b/src/shaders/StarFieldProgram.js index 81f5c1b2..3dded55d 100644 --- a/src/shaders/StarFieldProgram.js +++ b/src/shaders/StarFieldProgram.js @@ -3,17 +3,14 @@ * National Aeronautics and Space Administration. All Rights Reserved. */ /** - * @exports BasicProgram - * @version $Id: BasicProgram.js 3327 2015-07-21 19:03:39Z dcollins $ + * @exports StarFieldProgram */ define([ '../error/ArgumentError', - '../util/Color', '../shaders/GpuProgram', '../util/Logger' ], function (ArgumentError, - Color, GpuProgram, Logger) { "use strict"; @@ -22,48 +19,39 @@ define([ * Constructs a new program. * Initializes, compiles and links this GLSL program with the source code for its vertex and fragment shaders. *

- * This method creates WebGL shaders for the program's shader sources and attaches them to a new GLSL program. This - * method then compiles the shaders and then links the program if compilation is successful. Use the bind method to make the - * program current during rendering. + * This method creates WebGL shaders for the program's shader sources and attaches them to a new GLSL program. + * This method then compiles the shaders and then links the program if compilation is successful. + * Use the bind method to make the program current during rendering. * - * @alias BasicProgram + * @alias StarFieldProgram * @constructor * @augments GpuProgram - * @classdesc BasicProgram is a GLSL program that draws geometry in a solid color. + * @classdesc StarFieldProgram is a GLSL program that draws points representing stars. * @param {WebGLRenderingContext} gl The current WebGL context. - * @throws {ArgumentError} If the shaders cannot be compiled, or linking of - * the compiled shaders into a program fails. + * @throws {ArgumentError} If the shaders cannot be compiled, or linking of the compiled shaders into a program + * fails. */ var StarFieldProgram = function (gl) { var vertexShaderSource = 'attribute vec4 vertexPoint;\n' + 'uniform mat4 mvpMatrix;\n' + - 'uniform float JD;\n' + + 'uniform float numDays;\n' + 'varying float mag;\n' + - 'const float altitude = 1.0;\n' + //67310000.0 - 'float normalizeAngle(float angle) {\n' + ' float angleDivisions = angle / 360.0;\n' + ' return 360.0 * (angleDivisions - floor(angleDivisions));\n' + '}\n' + - 'float normalizedDegreesLongitude(float angle) {\n' + - ' float na = angle + 179.0;\n' + - ' return mod((mod(na, 360.0) + 360.0), 360.0) - 179.0;\n' + - '}\n' + - 'vec3 computePosition(float dec, float ra) {\n' + - //' float n = JD - 2451545.0;\n' + - ' float GMST = normalizeAngle(280.46061837 + 360.98564736629 * JD);\n' + + ' float GMST = normalizeAngle(280.46061837 + 360.98564736629 * numDays);\n' + ' float lon = 180.0 - normalizeAngle(GMST - ra);\n' + - //' lon = normalizedDegreesLongitude(lon);\n' + ' float latRad = radians(dec);\n' + ' float lonRad = radians(lon);\n' + - ' float radCosLat = altitude * cos(latRad);\n' + - ' return vec3(radCosLat * sin(lonRad), altitude * sin(latRad), radCosLat * cos(lonRad));\n' + + ' float radCosLat = cos(latRad);\n' + + ' return vec3(radCosLat * sin(lonRad), sin(latRad), radCosLat * cos(lonRad));\n' + '}\n' + 'void main() {\n' + @@ -83,11 +71,10 @@ define([ 'void main() {\n' + ' gl_FragColor = mix(white, grey, mag);\n' + //doesn't appear to be correct - //' gl_FragColor = white;\n' + '}'; // Call to the superclass, which performs shader program compiling and linking. - GpuProgram.call(this, gl, vertexShaderSource, fragmentShaderSource, ['vertexPoint']); + GpuProgram.call(this, gl, vertexShaderSource, fragmentShaderSource, ["vertexPoint"]); /** * The WebGL location for this program's 'vertexPoint' attribute. @@ -103,7 +90,12 @@ define([ */ this.mvpMatrixLocation = this.uniformLocation(gl, "mvpMatrix"); - this.JDLocation = this.uniformLocation(gl, "JD"); + /** + * The WebGL location for this program's 'numDays' uniform. + * @type {WebGLUniformLocation} + * @readonly + */ + this.numDaysLocation = this.uniformLocation(gl, "numDays"); }; /** @@ -132,8 +124,20 @@ define([ this.loadUniformMatrix(gl, matrix, this.mvpMatrixLocation); }; - StarFieldProgram.prototype.loadJD = function(gl, JD){ - gl.uniform1f(this.JDLocation, JD); + /** + * Loads the specified number as the value of this program's 'numDays' uniform variable. + * + * @param {WebGLRenderingContext} gl The current WebGL context. + * @param {Number} numDays The number of days (positive or negative) since Greenwich noon, Terrestrial Time, + * on 1 January 2000 (J2000.0) + * @throws {ArgumentError} If the specified number is null or undefined. + */ + StarFieldProgram.prototype.loadNumDays = function (gl, numDays) { + if (!numDays) { + throw new ArgumentError( + Logger.logMessage(Logger.LEVEL_SEVERE, "StarFieldProgram", "loadNumDays", "missingNumDays")); + } + gl.uniform1f(this.numDaysLocation, numDays); }; return StarFieldProgram;