/*global define*/ define([ '../Core/BoundingRectangle', '../Core/Cartesian2', '../Core/Cartesian3', '../Core/Cartesian4', '../Core/Cartographic', '../Core/defined', '../Core/defineProperties', '../Core/EncodedCartesian3', '../Core/Math', '../Core/Matrix3', '../Core/Matrix4', '../Core/Simon1994PlanetaryPositions', '../Core/Transforms', '../Scene/SceneMode' ], function( BoundingRectangle, Cartesian2, Cartesian3, Cartesian4, Cartographic, defined, defineProperties, EncodedCartesian3, CesiumMath, Matrix3, Matrix4, Simon1994PlanetaryPositions, Transforms, SceneMode) { "use strict"; /** * @private */ var UniformState = function() { this._viewport = new BoundingRectangle(); this._viewportCartesian4 = new Cartesian4(); this._viewportDirty = false; this._viewportOrthographicMatrix = Matrix4.clone(Matrix4.IDENTITY); this._viewportTransformation = Matrix4.clone(Matrix4.IDENTITY); this._model = Matrix4.clone(Matrix4.IDENTITY); this._view = Matrix4.clone(Matrix4.IDENTITY); this._inverseView = Matrix4.clone(Matrix4.IDENTITY); this._projection = Matrix4.clone(Matrix4.IDENTITY); this._infiniteProjection = Matrix4.clone(Matrix4.IDENTITY); this._entireFrustum = new Cartesian2(); this._currentFrustum = new Cartesian2(); this._frameState = undefined; this._temeToPseudoFixed = Matrix3.clone(Matrix4.IDENTITY); // Derived members this._view3DDirty = true; this._view3D = new Matrix4(); this._inverseView3DDirty = true; this._inverseView3D = new Matrix4(); this._inverseModelDirty = true; this._inverseModel = new Matrix4(); this._inverseTransposeModelDirty = true; this._inverseTransposeModel = new Matrix3(); this._viewRotation = new Matrix3(); this._inverseViewRotation = new Matrix3(); this._viewRotation3D = new Matrix3(); this._inverseViewRotation3D = new Matrix3(); this._inverseProjectionDirty = true; this._inverseProjection = new Matrix4(); this._inverseProjectionOITDirty = true; this._inverseProjectionOIT = new Matrix4(); this._modelViewDirty = true; this._modelView = new Matrix4(); this._modelView3DDirty = true; this._modelView3D = new Matrix4(); this._modelViewRelativeToEyeDirty = true; this._modelViewRelativeToEye = new Matrix4(); this._inverseModelViewDirty = true; this._inverseModelView = new Matrix4(); this._inverseModelView3DDirty = true; this._inverseModelView3D = new Matrix4(); this._viewProjectionDirty = true; this._viewProjection = new Matrix4(); this._inverseViewProjectionDirty = true; this._inverseViewProjection = new Matrix4(); this._modelViewProjectionDirty = true; this._modelViewProjection = new Matrix4(); this._inverseModelViewProjectionDirty = true; this._inverseModelViewProjection = new Matrix4(); this._modelViewProjectionRelativeToEyeDirty = true; this._modelViewProjectionRelativeToEye = new Matrix4(); this._modelViewInfiniteProjectionDirty = true; this._modelViewInfiniteProjection = new Matrix4(); this._normalDirty = true; this._normal = new Matrix3(); this._normal3DDirty = true; this._normal3D = new Matrix3(); this._inverseNormalDirty = true; this._inverseNormal = new Matrix3(); this._inverseNormal3DDirty = true; this._inverseNormal3D = new Matrix3(); this._encodedCameraPositionMCDirty = true; this._encodedCameraPositionMC = new EncodedCartesian3(); this._cameraPosition = new Cartesian3(); this._sunPositionWC = new Cartesian3(); this._sunPositionColumbusView = new Cartesian3(); this._sunDirectionWC = new Cartesian3(); this._sunDirectionEC = new Cartesian3(); this._moonDirectionEC = new Cartesian3(); this._mode = undefined; this._mapProjection = undefined; this._cameraDirection = new Cartesian3(); this._cameraRight = new Cartesian3(); this._cameraUp = new Cartesian3(); this._frustum2DWidth = 0.0; this._eyeHeight2D = new Cartesian2(); this._resolutionScale = 1.0; }; defineProperties(UniformState.prototype, { /** * @memberof UniformState.prototype * @type {FrameState} * @readonly */ frameState : { get : function() { return this._frameState; } }, /** * @memberof UniformState.prototype * @type {BoundingRectangle} */ viewport : { get : function() { return this._viewport; }, set : function(viewport) { if (!BoundingRectangle.equals(viewport, this._viewport)) { BoundingRectangle.clone(viewport, this._viewport); var v = this._viewport; var vc = this._viewportCartesian4; vc.x = v.x; vc.y = v.y; vc.z = v.width; vc.w = v.height; this._viewportDirty = true; } } }, /** * @memberof UniformState.prototype * @private */ viewportCartesian4 : { get : function() { return this._viewportCartesian4; } }, viewportOrthographic : { get : function() { cleanViewport(this); return this._viewportOrthographicMatrix; } }, viewportTransformation : { get : function() { cleanViewport(this); return this._viewportTransformation; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ model : { get : function() { return this._model; }, set : function(matrix) { Matrix4.clone(matrix, this._model); this._modelView3DDirty = true; this._inverseModelView3DDirty = true; this._inverseModelDirty = true; this._inverseTransposeModelDirty = true; this._modelViewDirty = true; this._inverseModelViewDirty = true; this._viewProjectionDirty = true; this._inverseViewProjectionDirty = true; this._modelViewRelativeToEyeDirty = true; this._inverseModelViewDirty = true; this._modelViewProjectionDirty = true; this._inverseModelViewProjectionDirty = true; this._modelViewProjectionRelativeToEyeDirty = true; this._modelViewInfiniteProjectionDirty = true; this._normalDirty = true; this._inverseNormalDirty = true; this._normal3DDirty = true; this._inverseNormal3DDirty = true; this._encodedCameraPositionMCDirty = true; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ inverseModel : { get : function() { if (this._inverseModelDirty) { this._inverseModelDirty = false; Matrix4.inverse(this._model, this._inverseModel); } return this._inverseModel; } }, /** * @memberof UniformState.prototype * @private */ inverseTranposeModel : { get : function() { var m = this._inverseTransposeModel; if (this._inverseTransposeModelDirty) { this._inverseTransposeModelDirty = false; Matrix4.getRotation(this.inverseModel, m); Matrix3.transpose(m, m); } return m; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ view : { get : function() { return this._view; } }, /** * The 3D view matrix. In 3D mode, this is identical to {@link UniformState#view}, * but in 2D and Columbus View it is a synthetic matrix based on the equivalent position * of the camera in the 3D world. * @memberof UniformState.prototype * @type {Matrix4} */ view3D : { get : function() { if (this._view3DDirty) { if (this._mode === SceneMode.SCENE3D) { Matrix4.clone(this._view, this._view3D); } else { view2Dto3D(this._cameraPosition, this._cameraDirection, this._cameraRight, this._cameraUp, this._frustum2DWidth, this._mode, this._mapProjection, this._view3D); } Matrix4.getRotation(this._view3D, this._viewRotation3D); this._view3DDirty = false; } return this._view3D; } }, /** * The 3x3 rotation matrix of the current view matrix ({@link UniformState#view}). * @memberof UniformState.prototype * @type {Matrix3} */ viewRotation : { get : function() { return this._viewRotation; } }, /** * @memberof UniformState.prototype * @type {Matrix3} */ viewRotation3D : { get : function() { var view3D = this.view3D; return this._viewRotation3D; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ inverseView : { get : function() { return this._inverseView; } }, /** * the 4x4 inverse-view matrix that transforms from eye to 3D world coordinates. In 3D mode, this is * identical to {@link UniformState#inverseView}, but in 2D and Columbus View it is a synthetic matrix * based on the equivalent position of the camera in the 3D world. * @memberof UniformState.prototype * @type {Matrix4} */ inverseView3D : { get : function() { if (this._inverseView3DDirty) { Matrix4.inverseTransformation(this.view3D, this._inverseView3D); Matrix4.getRotation(this._inverseView3D, this._inverseViewRotation3D); this._inverseView3DDirty = false; } return this._inverseView3D; } }, /** * @memberof UniformState.prototype * @type {Matrix3} */ inverseViewRotation : { get : function() { return this._inverseViewRotation; } }, /** * The 3x3 rotation matrix of the current 3D inverse-view matrix ({@link UniformState#inverseView3D}). * @memberof UniformState.prototype * @type {Matrix3} */ inverseViewRotation3D : { get : function() { var inverseView = this.inverseView3D; return this._inverseViewRotation3D; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ projection : { get : function() { return this._projection; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ inverseProjection : { get : function() { cleanInverseProjection(this); return this._inverseProjection; } }, /** * @memberof UniformState.prototype * @private */ inverseProjectionOIT : { get : function() { cleanInverseProjectionOIT(this); return this._inverseProjectionOIT; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ infiniteProjection : { get : function() { return this._infiniteProjection; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ modelView : { get : function() { cleanModelView(this); return this._modelView; } }, /** * The 3D model-view matrix. In 3D mode, this is equivalent to {@link UniformState#modelView}. In 2D and * Columbus View, however, it is a synthetic matrix based on the equivalent position of the camera in the 3D world. * @memberof UniformState.prototype * @type {Matrix4} */ modelView3D : { get : function() { cleanModelView3D(this); return this._modelView3D; } }, /** * Model-view relative to eye matrix. * * @memberof UniformState.prototype * @type {Matrix4} */ modelViewRelativeToEye : { get : function() { cleanModelViewRelativeToEye(this); return this._modelViewRelativeToEye; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ inverseModelView : { get : function() { cleanInverseModelView(this); return this._inverseModelView; } }, /** * The inverse of the 3D model-view matrix. In 3D mode, this is equivalent to {@link UniformState#inverseModelView}. * In 2D and Columbus View, however, it is a synthetic matrix based on the equivalent position of the camera in the 3D world. * @memberof UniformState.prototype * @type {Matrix4} */ inverseModelView3D : { get : function() { cleanInverseModelView3D(this); return this._inverseModelView3D; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ viewProjection : { get : function() { cleanViewProjection(this); return this._viewProjection; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ inverseViewProjection : { get : function() { cleanInverseViewProjection(this); return this._inverseViewProjection; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ modelViewProjection : { get : function() { cleanModelViewProjection(this); return this._modelViewProjection; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ inverseModelViewProjection : { get : function() { cleanInverseModelViewProjection(this); return this._inverseModelViewProjection; } }, /** * Model-view-projection relative to eye matrix. * * @memberof UniformState.prototype * @type {Matrix4} */ modelViewProjectionRelativeToEye : { get : function() { cleanModelViewProjectionRelativeToEye(this); return this._modelViewProjectionRelativeToEye; } }, /** * @memberof UniformState.prototype * @type {Matrix4} */ modelViewInfiniteProjection : { get : function() { cleanModelViewInfiniteProjection(this); return this._modelViewInfiniteProjection; } }, /** * A 3x3 normal transformation matrix that transforms normal vectors in model coordinates to * eye coordinates. * @memberof UniformState.prototype * @type {Matrix3} */ normal : { get : function() { cleanNormal(this); return this._normal; } }, /** * A 3x3 normal transformation matrix that transforms normal vectors in 3D model * coordinates to eye coordinates. In 3D mode, this is identical to * {@link UniformState#normal}, but in 2D and Columbus View it represents the normal transformation * matrix as if the camera were at an equivalent location in 3D mode. * @memberof UniformState.prototype * @type {Matrix3} */ normal3D : { get : function() { cleanNormal3D(this); return this._normal3D; } }, /** * An inverse 3x3 normal transformation matrix that transforms normal vectors in model coordinates * to eye coordinates. * @memberof UniformState.prototype * @type {Matrix3} */ inverseNormal : { get : function() { cleanInverseNormal(this); return this._inverseNormal; } }, /** * An inverse 3x3 normal transformation matrix that transforms normal vectors in eye coordinates * to 3D model coordinates. In 3D mode, this is identical to * {@link UniformState#inverseNormal}, but in 2D and Columbus View it represents the normal transformation * matrix as if the camera were at an equivalent location in 3D mode. * @memberof UniformState.prototype * @type {Matrix3} */ inverseNormal3D : { get : function() { cleanInverseNormal3D(this); return this._inverseNormal3D; } }, /** * The near distance (x) and the far distance (y) of the frustum defined by the camera. * This is the largest possible frustum, not an individual frustum used for multi-frustum rendering. * @memberof UniformState.prototype * @type {Cartesian2} */ entireFrustum : { get : function() { return this._entireFrustum; } }, /** * The near distance (x) and the far distance (y) of the frustum defined by the camera. * This is the individual frustum used for multi-frustum rendering. * @memberof UniformState.prototype * @type {Cartesian2} */ currentFrustum : { get : function() { return this._currentFrustum; } }, /** * The the height (x) and the height squared (y) * in meters of the camera above the 2D world plane. This uniform is only valid * when the {@link SceneMode} equal to SCENE2D. * @memberof UniformState.prototype * @type {Cartesian2} */ eyeHeight2D : { get : function() { return this._eyeHeight2D; } }, /** * The sun position in 3D world coordinates at the current scene time. * @memberof UniformState.prototype * @type {Cartesian3} */ sunPositionWC : { get : function() { return this._sunPositionWC; } }, /** * The sun position in 2D world coordinates at the current scene time. * @memberof UniformState.prototype * @type {Cartesian3} */ sunPositionColumbusView : { get : function(){ return this._sunPositionColumbusView; } }, /** * A normalized vector to the sun in 3D world coordinates at the current scene time. Even in 2D or * Columbus View mode, this returns the position of the sun in the 3D scene. * @memberof UniformState.prototype * @type {Cartesian3} */ sunDirectionWC : { get : function() { return this._sunDirectionWC; } }, /** * A normalized vector to the sun in eye coordinates at the current scene time. In 3D mode, this * returns the actual vector from the camera position to the sun position. In 2D and Columbus View, it returns * the vector from the equivalent 3D camera position to the position of the sun in the 3D scene. * @memberof UniformState.prototype * @type {Cartesian3} */ sunDirectionEC : { get : function() { return this._sunDirectionEC; } }, /** * A normalized vector to the moon in eye coordinates at the current scene time. In 3D mode, this * returns the actual vector from the camera position to the moon position. In 2D and Columbus View, it returns * the vector from the equivalent 3D camera position to the position of the moon in the 3D scene. * @memberof UniformState.prototype * @type {Cartesian3} */ moonDirectionEC : { get : function() { return this._moonDirectionEC; } }, /** * The high bits of the camera position. * @memberof UniformState.prototype * @type {Cartesian3} */ encodedCameraPositionMCHigh : { get : function() { cleanEncodedCameraPositionMC(this); return this._encodedCameraPositionMC.high; } }, /** * The low bits of the camera position. * @memberof UniformState.prototype * @type {Cartesian3} */ encodedCameraPositionMCLow : { get : function() { cleanEncodedCameraPositionMC(this); return this._encodedCameraPositionMC.low; } }, /** * A 3x3 matrix that transforms from True Equator Mean Equinox (TEME) axes to the * pseudo-fixed axes at the Scene's current time. * @memberof UniformState.prototype * @type {Matrix3} */ temeToPseudoFixedMatrix : { get : function() { return this._temeToPseudoFixed; } }, /** * Gets the scaling factor for transforming from the canvas * pixel space to canvas coordinate space. * @memberof UniformState.prototype * @type {Number} */ resolutionScale : { get : function() { return this._resolutionScale; } } }); function setView(uniformState, matrix) { Matrix4.clone(matrix, uniformState._view); Matrix4.getRotation(matrix, uniformState._viewRotation); uniformState._view3DDirty = true; uniformState._inverseView3DDirty = true; uniformState._modelViewDirty = true; uniformState._modelView3DDirty = true; uniformState._modelViewRelativeToEyeDirty = true; uniformState._inverseModelViewDirty = true; uniformState._inverseModelView3DDirty = true; uniformState._viewProjectionDirty = true; uniformState._modelViewProjectionDirty = true; uniformState._modelViewProjectionRelativeToEyeDirty = true; uniformState._modelViewInfiniteProjectionDirty = true; uniformState._normalDirty = true; uniformState._inverseNormalDirty = true; uniformState._normal3DDirty = true; uniformState._inverseNormal3DDirty = true; } function setInverseView(uniformState, matrix) { Matrix4.clone(matrix, uniformState._inverseView); Matrix4.getRotation(matrix, uniformState._inverseViewRotation); } function setProjection(uniformState, matrix) { Matrix4.clone(matrix, uniformState._projection); uniformState._inverseProjectionDirty = true; uniformState._inverseProjectionOITDirty = true; uniformState._viewProjectionDirty = true; uniformState._modelViewProjectionDirty = true; uniformState._modelViewProjectionRelativeToEyeDirty = true; } function setInfiniteProjection(uniformState, matrix) { Matrix4.clone(matrix, uniformState._infiniteProjection); uniformState._modelViewInfiniteProjectionDirty = true; } function setCamera(uniformState, camera) { Cartesian3.clone(camera.positionWC, uniformState._cameraPosition); Cartesian3.clone(camera.directionWC, uniformState._cameraDirection); Cartesian3.clone(camera.rightWC, uniformState._cameraRight); Cartesian3.clone(camera.upWC, uniformState._cameraUp); uniformState._encodedCameraPositionMCDirty = true; } var transformMatrix = new Matrix3(); var sunCartographicScratch = new Cartographic(); function setSunAndMoonDirections(uniformState, frameState) { if (!defined(Transforms.computeIcrfToFixedMatrix(frameState.time, transformMatrix))) { transformMatrix = Transforms.computeTemeToPseudoFixedMatrix(frameState.time, transformMatrix); } var position = Simon1994PlanetaryPositions.computeSunPositionInEarthInertialFrame(frameState.time, uniformState._sunPositionWC); Matrix3.multiplyByVector(transformMatrix, position, position); Cartesian3.normalize(position, uniformState._sunDirectionWC); position = Matrix3.multiplyByVector(uniformState.viewRotation3D, position, uniformState._sunDirectionEC); Cartesian3.normalize(position, position); position = Simon1994PlanetaryPositions.computeMoonPositionInEarthInertialFrame(frameState.time, uniformState._moonDirectionEC); Matrix3.multiplyByVector(transformMatrix, position, position); Matrix3.multiplyByVector(uniformState.viewRotation3D, position, position); Cartesian3.normalize(position, position); var projection = frameState.mapProjection; var ellipsoid = projection.ellipsoid; var sunCartographic = ellipsoid.cartesianToCartographic(uniformState._sunPositionWC, sunCartographicScratch); projection.project(sunCartographic, uniformState._sunPositionColumbusView); } /** * Synchronizes the frustum's state with the uniform state. This is called * by the {@link Scene} when rendering to ensure that automatic GLSL uniforms * are set to the right value. * * @param {Object} frustum The frustum to synchronize with. */ UniformState.prototype.updateFrustum = function(frustum) { setProjection(this, frustum.projectionMatrix); if (defined(frustum.infiniteProjectionMatrix)) { setInfiniteProjection(this, frustum.infiniteProjectionMatrix); } this._currentFrustum.x = frustum.near; this._currentFrustum.y = frustum.far; }; /** * Synchronizes frame state with the uniform state. This is called * by the {@link Scene} when rendering to ensure that automatic GLSL uniforms * are set to the right value. * * @param {FrameState} frameState The frameState to synchronize with. */ UniformState.prototype.update = function(context, frameState) { this._mode = frameState.mode; this._mapProjection = frameState.mapProjection; var canvas = context._canvas; this._resolutionScale = canvas.width / canvas.clientWidth; var camera = frameState.camera; setView(this, camera.viewMatrix); setInverseView(this, camera.inverseViewMatrix); setCamera(this, camera); if (frameState.mode === SceneMode.SCENE2D) { this._frustum2DWidth = camera.frustum.right - camera.frustum.left; this._eyeHeight2D.x = this._frustum2DWidth * 0.5; this._eyeHeight2D.y = this._eyeHeight2D.x * this._eyeHeight2D.x; } else { this._frustum2DWidth = 0.0; this._eyeHeight2D.x = 0.0; this._eyeHeight2D.y = 0.0; } setSunAndMoonDirections(this, frameState); this._entireFrustum.x = camera.frustum.near; this._entireFrustum.y = camera.frustum.far; this.updateFrustum(camera.frustum); this._frameState = frameState; this._temeToPseudoFixed = Transforms.computeTemeToPseudoFixedMatrix(frameState.time, this._temeToPseudoFixed); }; function cleanViewport(uniformState) { if (uniformState._viewportDirty) { var v = uniformState._viewport; Matrix4.computeOrthographicOffCenter(v.x, v.x + v.width, v.y, v.y + v.height, 0.0, 1.0, uniformState._viewportOrthographicMatrix); Matrix4.computeViewportTransformation(v, 0.0, 1.0, uniformState._viewportTransformation); uniformState._viewportDirty = false; } } function cleanInverseProjection(uniformState) { if (uniformState._inverseProjectionDirty) { uniformState._inverseProjectionDirty = false; Matrix4.inverse(uniformState._projection, uniformState._inverseProjection); } } function cleanInverseProjectionOIT(uniformState) { if (uniformState._inverseProjectionOITDirty) { uniformState._inverseProjectionOITDirty = false; if (uniformState._mode !== SceneMode.SCENE2D && uniformState._mode !== SceneMode.MORPHING) { Matrix4.inverse(uniformState._projection, uniformState._inverseProjectionOIT); } else { Matrix4.clone(Matrix4.IDENTITY, uniformState._inverseProjectionOIT); } } } // Derived function cleanModelView(uniformState) { if (uniformState._modelViewDirty) { uniformState._modelViewDirty = false; Matrix4.multiplyTransformation(uniformState._view, uniformState._model, uniformState._modelView); } } function cleanModelView3D(uniformState) { if (uniformState._modelView3DDirty) { uniformState._modelView3DDirty = false; Matrix4.multiplyTransformation(uniformState.view3D, uniformState._model, uniformState._modelView3D); } } function cleanInverseModelView(uniformState) { if (uniformState._inverseModelViewDirty) { uniformState._inverseModelViewDirty = false; Matrix4.inverse(uniformState.modelView, uniformState._inverseModelView); } } function cleanInverseModelView3D(uniformState) { if (uniformState._inverseModelView3DDirty) { uniformState._inverseModelView3DDirty = false; Matrix4.inverse(uniformState.modelView3D, uniformState._inverseModelView3D); } } function cleanViewProjection(uniformState) { if (uniformState._viewProjectionDirty) { uniformState._viewProjectionDirty = false; Matrix4.multiply(uniformState._projection, uniformState._view, uniformState._viewProjection); } } function cleanInverseViewProjection(uniformState) { if (uniformState._inverseViewProjectionDirty) { uniformState._inverseViewProjectionDirty = false; Matrix4.inverse(uniformState.viewProjection, uniformState._inverseViewProjection); } } function cleanModelViewProjection(uniformState) { if (uniformState._modelViewProjectionDirty) { uniformState._modelViewProjectionDirty = false; Matrix4.multiply(uniformState._projection, uniformState.modelView, uniformState._modelViewProjection); } } function cleanModelViewRelativeToEye(uniformState) { if (uniformState._modelViewRelativeToEyeDirty) { uniformState._modelViewRelativeToEyeDirty = false; var mv = uniformState.modelView; var mvRte = uniformState._modelViewRelativeToEye; mvRte[0] = mv[0]; mvRte[1] = mv[1]; mvRte[2] = mv[2]; mvRte[3] = mv[3]; mvRte[4] = mv[4]; mvRte[5] = mv[5]; mvRte[6] = mv[6]; mvRte[7] = mv[7]; mvRte[8] = mv[8]; mvRte[9] = mv[9]; mvRte[10] = mv[10]; mvRte[11] = mv[11]; mvRte[12] = 0.0; mvRte[13] = 0.0; mvRte[14] = 0.0; mvRte[15] = mv[15]; } } function cleanInverseModelViewProjection(uniformState) { if (uniformState._inverseModelViewProjectionDirty) { uniformState._inverseModelViewProjectionDirty = false; Matrix4.inverse(uniformState.modelViewProjection, uniformState._inverseModelViewProjection); } } function cleanModelViewProjectionRelativeToEye(uniformState) { if (uniformState._modelViewProjectionRelativeToEyeDirty) { uniformState._modelViewProjectionRelativeToEyeDirty = false; Matrix4.multiply(uniformState._projection, uniformState.modelViewRelativeToEye, uniformState._modelViewProjectionRelativeToEye); } } function cleanModelViewInfiniteProjection(uniformState) { if (uniformState._modelViewInfiniteProjectionDirty) { uniformState._modelViewInfiniteProjectionDirty = false; Matrix4.multiply(uniformState._infiniteProjection, uniformState.modelView, uniformState._modelViewInfiniteProjection); } } function cleanNormal(uniformState) { if (uniformState._normalDirty) { uniformState._normalDirty = false; var m = uniformState._normal; Matrix4.getRotation(uniformState.inverseModelView, m); Matrix3.transpose(m, m); } } function cleanNormal3D(uniformState) { if (uniformState._normal3DDirty) { uniformState._normal3DDirty = false; var m = uniformState._normal3D; Matrix4.getRotation(uniformState.inverseModelView3D, m); Matrix3.transpose(m, m); } } function cleanInverseNormal(uniformState) { if (uniformState._inverseNormalDirty) { uniformState._inverseNormalDirty = false; Matrix4.getRotation(uniformState.inverseModelView, uniformState._inverseNormal); } } function cleanInverseNormal3D(uniformState) { if (uniformState._inverseNormal3DDirty) { uniformState._inverseNormal3DDirty = false; Matrix4.getRotation(uniformState.inverseModelView3D, uniformState._inverseNormal3D); } } var cameraPositionMC = new Cartesian3(); function cleanEncodedCameraPositionMC(uniformState) { if (uniformState._encodedCameraPositionMCDirty) { uniformState._encodedCameraPositionMCDirty = false; Matrix4.multiplyByPoint(uniformState.inverseModel, uniformState._cameraPosition, cameraPositionMC); EncodedCartesian3.fromCartesian(cameraPositionMC, uniformState._encodedCameraPositionMC); } } var view2Dto3DPScratch = new Cartesian3(); var view2Dto3DRScratch = new Cartesian3(); var view2Dto3DUScratch = new Cartesian3(); var view2Dto3DDScratch = new Cartesian3(); var view2Dto3DCartographicScratch = new Cartographic(); var view2Dto3DCartesian3Scratch = new Cartesian3(); var view2Dto3DMatrix4Scratch = new Matrix4(); function view2Dto3D(position2D, direction2D, right2D, up2D, frustum2DWidth, mode, projection, result) { // The camera position and directions are expressed in the 2D coordinate system where the Y axis is to the East, // the Z axis is to the North, and the X axis is out of the map. Express them instead in the ENU axes where // X is to the East, Y is to the North, and Z is out of the local horizontal plane. var p = view2Dto3DPScratch; p.x = position2D.y; p.y = position2D.z; p.z = position2D.x; var r = view2Dto3DRScratch; r.x = right2D.y; r.y = right2D.z; r.z = right2D.x; var u = view2Dto3DUScratch; u.x = up2D.y; u.y = up2D.z; u.z = up2D.x; var d = view2Dto3DDScratch; d.x = direction2D.y; d.y = direction2D.z; d.z = direction2D.x; // In 2D, the camera height is always 12.7 million meters. // The apparent height is equal to half the frustum width. if (mode === SceneMode.SCENE2D) { p.z = frustum2DWidth * 0.5; } // Compute the equivalent camera position in the real (3D) world. // In 2D and Columbus View, the camera can travel outside the projection, and when it does so // there's not really any corresponding location in the real world. So clamp the unprojected // longitude and latitude to their valid ranges. var cartographic = projection.unproject(p, view2Dto3DCartographicScratch); cartographic.longitude = CesiumMath.clamp(cartographic.longitude, -Math.PI, Math.PI); cartographic.latitude = CesiumMath.clamp(cartographic.latitude, -CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO); var ellipsoid = projection.ellipsoid; var position3D = ellipsoid.cartographicToCartesian(cartographic, view2Dto3DCartesian3Scratch); // Compute the rotation from the local ENU at the real world camera position to the fixed axes. var enuToFixed = Transforms.eastNorthUpToFixedFrame(position3D, ellipsoid, view2Dto3DMatrix4Scratch); // Transform each camera direction to the fixed axes. Matrix4.multiplyByPointAsVector(enuToFixed, r, r); Matrix4.multiplyByPointAsVector(enuToFixed, u, u); Matrix4.multiplyByPointAsVector(enuToFixed, d, d); // Compute the view matrix based on the new fixed-frame camera position and directions. if (!defined(result)) { result = new Matrix4(); } result[0] = r.x; result[1] = u.x; result[2] = -d.x; result[3] = 0.0; result[4] = r.y; result[5] = u.y; result[6] = -d.y; result[7] = 0.0; result[8] = r.z; result[9] = u.z; result[10] = -d.z; result[11] = 0.0; result[12] = -Cartesian3.dot(r, position3D); result[13] = -Cartesian3.dot(u, position3D); result[14] = Cartesian3.dot(d, position3D); result[15] = 1.0; return result; } return UniformState; });