Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orthographic projection in 3D and Columbus view #5021

Merged
merged 53 commits into from
Mar 15, 2017
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
316ea87
Orthographic projection WIP.
bagnell Jan 31, 2017
ee297a3
Fix camera jittering when zooming. Temporarily disable atmosphere and…
bagnell Feb 1, 2017
4b0788a
Disable horizon culling and fog.
bagnell Feb 2, 2017
89fe621
Fix picking culling volume, view rectangle distance. Disable OIT.
bagnell Feb 2, 2017
1c57a52
Fix picking from depth buffer with orthographic projection. Fix zoomi…
bagnell Feb 2, 2017
72d7441
Fix when camera is in a reference frame not the identity.
bagnell Feb 3, 2017
c19cf65
Fix panning on terrain.
bagnell Feb 3, 2017
47174b4
Add separate centered and off-center orthographic frustums.
bagnell Feb 3, 2017
6daca54
Update aspect ratio on canvas resize.
bagnell Feb 3, 2017
d3aef4e
Disable environmental effects.
bagnell Feb 3, 2017
dc6d9a7
Fix OIT.
bagnell Feb 3, 2017
75a0367
Merge branch 'master' into ortho-3d
bagnell Feb 15, 2017
7b31fb9
Another fix for OIT.
bagnell Feb 16, 2017
08b1ff4
Only adjust orthographic frustum width on zoom. Makes panning and til…
bagnell Feb 17, 2017
34cf3e4
Fix viewing a rectangle in 3d.
bagnell Feb 17, 2017
4d92e00
Add projection picker widget. Still need svgs.
bagnell Feb 17, 2017
50f97b0
Fix mouse input camera interaction when in columbus view with an orth…
bagnell Feb 20, 2017
4ebcc64
Tweak adjusting the frustum width based on depth buffer pick or terra…
bagnell Feb 20, 2017
f7ee919
Fix issue with zoom where the camera wouldn't focus on the target pos…
bagnell Feb 20, 2017
303b568
Fix height and zoom when switching to orthographic mode.
bagnell Feb 20, 2017
b059be9
New icons for perspective and orthographic.
emackey Feb 21, 2017
110027f
Merge pull request #5020 from AnalyticalGraphicsInc/persp-ortho-icons
bagnell Feb 21, 2017
51b53b8
Rename OrthographicFrustumSpec -> OrthographicOffCenterFrustumSpec.
bagnell Feb 21, 2017
fbf5d77
Fix broken tests.
bagnell Feb 21, 2017
9e1f19f
Merge branch 'master' into ortho-3d
bagnell Feb 22, 2017
0af61cc
Remove slide animation when switching projection and correctly hide d…
bagnell Feb 22, 2017
4ab7c6d
Grey out the button when in 2D.
bagnell Feb 22, 2017
b09ab6e
Disable button, disable drop down and display orthographic icon in 2D.
bagnell Feb 22, 2017
e51da6a
Fix icon after morphs. Keep orthographic when morphing from 3D to 2D/…
bagnell Feb 22, 2017
b335fcc
Add checks for write types of frustums in the current scene mode.
bagnell Feb 22, 2017
5389dab
Fix shadows and OIT in orthographic.
bagnell Feb 23, 2017
4040a1b
Fix zooming issue.
bagnell Feb 24, 2017
d5d8ebd
Fix WGS84 to window coordinates.
bagnell Feb 27, 2017
0ada6b0
Enable fog with an orthographic projection.
bagnell Feb 27, 2017
45e26f8
Add tests.
bagnell Feb 28, 2017
4d7f8c7
Merge branch 'master' into ortho-3d
bagnell Mar 7, 2017
fa2200e
slightly extend skirts away from the mesh instead of dropping them st…
bagnell Mar 7, 2017
f32f814
Add flanges to heightmap tessellator.
bagnell Mar 8, 2017
b1b29ed
Preserve projection when morphing.
bagnell Mar 8, 2017
d8481d8
Adjust ortho frustum when moving camera, fix camera changed event, di…
bagnell Mar 8, 2017
403ffe3
Merge branch 'master' into ortho-3d
bagnell Mar 8, 2017
0ab7292
Fix tests.
bagnell Mar 9, 2017
dd5e8ce
Add projection picker tests.
bagnell Mar 9, 2017
cf71123
Disable VR button when in orthographic.
bagnell Mar 9, 2017
3937422
Deprecate OrthographicFrustum plane distance properties.
bagnell Mar 9, 2017
620c090
Code updates from review.
bagnell Mar 9, 2017
b0f06c5
Update debug camera for orthographic projections.
bagnell Mar 9, 2017
e13bc3d
Adjust frustum when morphing and when the camera is above a certain h…
bagnell Mar 13, 2017
6c7f5bb
Update CHANGES.md.
bagnell Mar 13, 2017
ad83a40
Merge branch 'master' into ortho-3d
bagnell Mar 14, 2017
e2ecaa0
Fix camera when click-dragging space close to the surface.
bagnell Mar 15, 2017
0dc974d
Merge branch 'master' into ortho-3d
bagnell Mar 15, 2017
9182136
Default to not creating the projection picker.
bagnell Mar 15, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Apps/Sandcastle/gallery/development/Shadows.html
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@
var frustumSize = 55.0;
var frustumNear = 1.0;
var frustumFar = 400.0;
var frustum = new Cesium.OrthographicFrustum();
var frustum = new Cesium.OrthographicOffCenterFrustum();
frustum.left = -frustumSize;
frustum.right = frustumSize;
frustum.bottom = -frustumSize;
Expand Down
11 changes: 0 additions & 11 deletions Source/Renderer/AutomaticUniforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,17 +530,6 @@ define([
}
}),

/**
* @private
*/
czm_inverseProjectionOIT : new AutomaticUniform({
size : 1,
datatype : WebGLConstants.FLOAT_MAT4,
getValue : function(uniformState) {
return uniformState.inverseProjectionOIT;
}
}),

/**
* An automatic GLSL uniform representing a 4x4 projection transformation matrix with the far plane at infinity,
* that transforms eye coordinates to clip coordinates. Clip coordinates is the
Expand Down
34 changes: 8 additions & 26 deletions Source/Renderer/UniformState.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ define([
'../Core/Matrix4',
'../Core/Simon1994PlanetaryPositions',
'../Core/Transforms',
'../Scene/OrthographicFrustum',
'../Scene/SceneMode'
], function(
BoundingRectangle,
Expand All @@ -28,6 +29,7 @@ define([
Matrix4,
Simon1994PlanetaryPositions,
Transforms,
OrthographicFrustum,
SceneMode) {
'use strict';

Expand Down Expand Up @@ -80,9 +82,6 @@ define([
this._inverseProjectionDirty = true;
this._inverseProjection = new Matrix4();

this._inverseProjectionOITDirty = true;
this._inverseProjectionOIT = new Matrix4();

this._modelViewDirty = true;
this._modelView = new Matrix4();

Expand Down Expand Up @@ -147,6 +146,7 @@ define([
this._frustum2DWidth = 0.0;
this._eyeHeight2D = new Cartesian2();
this._resolutionScale = 1.0;
this._orthographicIn3D = false;

this._fogDensity = undefined;

Expand Down Expand Up @@ -393,17 +393,6 @@ define([
}
},

/**
* @memberof UniformState.prototype
* @private
*/
inverseProjectionOIT : {
get : function() {
cleanInverseProjectionOIT(this);
return this._inverseProjectionOIT;
}
},

/**
* @memberof UniformState.prototype
* @type {Matrix4}
Expand Down Expand Up @@ -834,7 +823,6 @@ define([
Matrix4.clone(matrix, uniformState._projection);

uniformState._inverseProjectionDirty = true;
uniformState._inverseProjectionOITDirty = true;
uniformState._viewProjectionDirty = true;
uniformState._inverseViewProjectionDirty = true;
uniformState._modelViewProjectionDirty = true;
Expand Down Expand Up @@ -896,6 +884,8 @@ define([
this._entireFrustum.x = camera.frustum.near;
this._entireFrustum.y = camera.frustum.far;
this.updateFrustum(camera.frustum);

this._orthographicIn3D = this._mode !== SceneMode.SCENE2D && camera.frustum instanceof OrthographicFrustum;
};

/**
Expand Down Expand Up @@ -987,18 +977,10 @@ define([
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);
if (uniformState._mode !== SceneMode.SCENE2D && uniformState._mode !== SceneMode.MORPHING && !uniformState._orthographicIn3D) {
Matrix4.inverse(uniformState._projection, uniformState._inverseProjection);
} else {
Matrix4.clone(Matrix4.IDENTITY, uniformState._inverseProjectionOIT);
Matrix4.clone(Matrix4.ZERO, uniformState._inverseProjection);
}
}
}
Expand Down
168 changes: 130 additions & 38 deletions Source/Scene/Camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ define([
'../Core/Transforms',
'./CameraFlightPath',
'./MapMode2D',
'./OrthographicFrustum',
'./OrthographicOffCenterFrustum',
'./PerspectiveFrustum',
'./SceneMode'
], function(
Expand Down Expand Up @@ -55,6 +57,8 @@ define([
Transforms,
CameraFlightPath,
MapMode2D,
OrthographicFrustum,
OrthographicOffCenterFrustum,
PerspectiveFrustum,
SceneMode) {
'use strict';
Expand Down Expand Up @@ -898,6 +902,13 @@ define([
if (!defined(mode)) {
throw new DeveloperError('mode is required.');
}
if (mode === SceneMode.SCENE2D && !(this.frustum instanceof OrthographicOffCenterFrustum)) {
throw new DeveloperError('An OrthographicOffCenterFrustum is required in 2D.');
}
if ((mode === SceneMode.SCENE3D || mode === SceneMode.COLUMBUS_VIEW) &&
(!(this.frustum instanceof PerspectiveFrustum) && !(this.frustum instanceof OrthographicFrustum))) {
throw new DeveloperError('A PerspectiveFrustum or OrthographicFrustum is required in 3D and Columbus view');
}
//>>includeEnd('debug');

var updateFrustum = false;
Expand Down Expand Up @@ -958,6 +969,42 @@ define([
updateMembers(this);
};

var scratchAdjustOrtghographicFrustumMousePosition = new Cartesian2();
var pickGlobeScratchRay = new Ray();
var scratchRayIntersection = new Cartesian3();

Camera.prototype._adjustOrthographicFrustum = function() {
if (!(this.frustum instanceof OrthographicFrustum)) {
return;
}

if (!Matrix4.equals(Matrix4.IDENTITY, this.transform)) {
this.frustum.width = Cartesian3.magnitude(this.position);
return;
}

var scene = this._scene;
var globe = scene._globe;
var rayIntersection;

if (defined(globe)) {
var mousePosition = scratchAdjustOrtghographicFrustumMousePosition;
mousePosition.x = scene.drawingBufferWidth / 2.0;
mousePosition.y = scene.drawingBufferHeight / 2.0;

var ray = this.getPickRay(mousePosition, pickGlobeScratchRay);
rayIntersection = globe.pick(ray, scene, scratchRayIntersection);
if (defined(rayIntersection)) {
this.frustum.width = Cartesian3.distance(rayIntersection, this.positionWC);
}
}

if (!defined(globe) || (!defined(rayIntersection))) {
var distance = this.positionCartographic.height;
this.frustum.width = distance;
}
};

var scratchSetViewCartesian = new Cartesian3();
var scratchSetViewTransform1 = new Matrix4();
var scratchSetViewTransform2 = new Matrix4();
Expand All @@ -981,6 +1028,8 @@ define([
Cartesian3.cross(camera.direction, camera.up, camera.right);

camera._setTransform(currentTransform);

camera._adjustOrthographicFrustum();
}

function setViewCV(camera, position,hpr, convert) {
Expand All @@ -1005,6 +1054,8 @@ define([
Cartesian3.cross(camera.direction, camera.up, camera.right);

camera._setTransform(currentTransform);

camera._adjustOrthographicFrustum();
}

function setView2D(camera, position, hpr, convert) {
Expand Down Expand Up @@ -1973,6 +2024,8 @@ define([
Cartesian3.normalize(this.right, this.right);
Cartesian3.cross(this.right, this.direction, this.up);
Cartesian3.normalize(this.up, this.up);

this._adjustOrthographicFrustum();
};

var viewRectangle3DCartographic1 = new Cartographic();
Expand Down Expand Up @@ -2080,38 +2133,58 @@ define([
Cartesian3.normalize(right, right);
var up = Cartesian3.cross(right, direction, cameraRF.up);

var tanPhi = Math.tan(camera.frustum.fovy * 0.5);
var tanTheta = camera.frustum.aspectRatio * tanPhi;
var d;
if (camera.frustum instanceof OrthographicFrustum) {
var width = Math.max(Cartesian3.distance(northEast, northWest), Cartesian3.distance(southEast, southWest));
var height = Math.max(Cartesian3.distance(northEast, southEast), Cartesian3.distance(northWest, southWest));

var rightScalar;
var topScalar;
var ratio = camera.frustum._offCenterFrustum.right / camera.frustum._offCenterFrustum.top;
var heightRatio = height * ratio;
if (width > heightRatio) {
rightScalar = width;
topScalar = rightScalar / ratio;
} else {
topScalar = height;
rightScalar = heightRatio;
}

var d = Math.max(
computeD(direction, up, northWest, tanPhi),
computeD(direction, up, southEast, tanPhi),
computeD(direction, up, northEast, tanPhi),
computeD(direction, up, southWest, tanPhi),
computeD(direction, up, northCenter, tanPhi),
computeD(direction, up, southCenter, tanPhi),
computeD(direction, right, northWest, tanTheta),
computeD(direction, right, southEast, tanTheta),
computeD(direction, right, northEast, tanTheta),
computeD(direction, right, southWest, tanTheta),
computeD(direction, right, northCenter, tanTheta),
computeD(direction, right, southCenter, tanTheta));

// If the rectangle crosses the equator, compute D at the equator, too, because that's the
// widest part of the rectangle when projected onto the globe.
if (south < 0 && north > 0) {
var equatorCartographic = viewRectangle3DCartographic1;
equatorCartographic.longitude = west;
equatorCartographic.latitude = 0.0;
equatorCartographic.height = 0.0;
var equatorPosition = ellipsoid.cartographicToCartesian(equatorCartographic, viewRectangle3DEquator);
Cartesian3.subtract(equatorPosition, center, equatorPosition);
d = Math.max(d, computeD(direction, up, equatorPosition, tanPhi), computeD(direction, right, equatorPosition, tanTheta));

equatorCartographic.longitude = east;
equatorPosition = ellipsoid.cartographicToCartesian(equatorCartographic, viewRectangle3DEquator);
Cartesian3.subtract(equatorPosition, center, equatorPosition);
d = Math.max(d, computeD(direction, up, equatorPosition, tanPhi), computeD(direction, right, equatorPosition, tanTheta));
d = Math.max(rightScalar, topScalar);
} else {
var tanPhi = Math.tan(camera.frustum.fovy * 0.5);
var tanTheta = camera.frustum.aspectRatio * tanPhi;

d = Math.max(
computeD(direction, up, northWest, tanPhi),
computeD(direction, up, southEast, tanPhi),
computeD(direction, up, northEast, tanPhi),
computeD(direction, up, southWest, tanPhi),
computeD(direction, up, northCenter, tanPhi),
computeD(direction, up, southCenter, tanPhi),
computeD(direction, right, northWest, tanTheta),
computeD(direction, right, southEast, tanTheta),
computeD(direction, right, northEast, tanTheta),
computeD(direction, right, southWest, tanTheta),
computeD(direction, right, northCenter, tanTheta),
computeD(direction, right, southCenter, tanTheta));

// If the rectangle crosses the equator, compute D at the equator, too, because that's the
// widest part of the rectangle when projected onto the globe.
if (south < 0 && north > 0) {
var equatorCartographic = viewRectangle3DCartographic1;
equatorCartographic.longitude = west;
equatorCartographic.latitude = 0.0;
equatorCartographic.height = 0.0;
var equatorPosition = ellipsoid.cartographicToCartesian(equatorCartographic, viewRectangle3DEquator);
Cartesian3.subtract(equatorPosition, center, equatorPosition);
d = Math.max(d, computeD(direction, up, equatorPosition, tanPhi), computeD(direction, right, equatorPosition, tanTheta));

equatorCartographic.longitude = east;
equatorPosition = ellipsoid.cartographicToCartesian(equatorCartographic, viewRectangle3DEquator);
Cartesian3.subtract(equatorPosition, center, equatorPosition);
d = Math.max(d, computeD(direction, up, equatorPosition, tanPhi), computeD(direction, right, equatorPosition, tanTheta));
}
}

return Cartesian3.add(center, Cartesian3.multiplyByScalar(direction, -d, viewRectangle3DEquator), result);
Expand Down Expand Up @@ -2141,12 +2214,18 @@ define([
Matrix4.multiplyByPoint(transform, southWest, southWest);
Matrix4.multiplyByPoint(invTransform, southWest, southWest);

var tanPhi = Math.tan(camera.frustum.fovy * 0.5);
var tanTheta = camera.frustum.aspectRatio * tanPhi;

result.x = (northEast.x - southWest.x) * 0.5 + southWest.x;
result.y = (northEast.y - southWest.y) * 0.5 + southWest.y;
result.z = Math.max((northEast.x - southWest.x) / tanTheta, (northEast.y - southWest.y) / tanPhi) * 0.5;

if (defined(camera.frustum.fovy)) {
var tanPhi = Math.tan(camera.frustum.fovy * 0.5);
var tanTheta = camera.frustum.aspectRatio * tanPhi;
result.z = Math.max((northEast.x - southWest.x) / tanTheta, (northEast.y - southWest.y) / tanPhi) * 0.5;
} else {
var width = northEast.x - southWest.x;
var height = northEast.y - southWest.y;
result.z = Math.max(width, height);
}

return result;
}
Expand Down Expand Up @@ -2339,10 +2418,14 @@ define([
var width = canvas.clientWidth;
var height = canvas.clientHeight;

var frustum = camera.frustum;
if (!defined(frustum.top)) {
frustum = frustum._offCenterFrustum;
}
var x = (2.0 / width) * windowPosition.x - 1.0;
x *= (camera.frustum.right - camera.frustum.left) * 0.5;
x *= (frustum.right - frustum.left) * 0.5;
var y = (2.0 / height) * (height - windowPosition.y) - 1.0;
y *= (camera.frustum.top - camera.frustum.bottom) * 0.5;
y *= (frustum.top - frustum.bottom) * 0.5;

var origin = result.origin;
Cartesian3.clone(camera.position, origin);
Expand All @@ -2354,6 +2437,10 @@ define([

Cartesian3.clone(camera.directionWC, result.direction);

if (camera._mode === SceneMode.COLUMBUS_VIEW) {
Cartesian3.fromElements(result.origin.z, result.origin.x, result.origin.y, result.origin);
}

return result;
}

Expand Down Expand Up @@ -2675,6 +2762,9 @@ define([

function distanceToBoundingSphere2D(camera, radius) {
var frustum = camera.frustum;
if (!defined(frustum.top)) {
frustum = frustum._offCenterFrustum;
}

var right, top;
var ratio = frustum.right / frustum.top;
Expand Down Expand Up @@ -2703,8 +2793,10 @@ define([
var radius = boundingSphere.radius;
if (radius === 0.0) {
offset.range = MINIMUM_ZOOM;
} else if (camera.frustum instanceof OrthographicFrustum || camera._mode === SceneMode.SCENE2D) {
offset.range = distanceToBoundingSphere2D(camera, radius);
} else {
offset.range = camera._mode === SceneMode.SCENE2D ? distanceToBoundingSphere2D(camera, radius) : distanceToBoundingSphere3D(camera, radius);
offset.range = distanceToBoundingSphere3D(camera, radius);
}
}

Expand Down
Loading