From c46182ec1c72b2ee05a229b7a0407a79b8aa7c63 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 19 May 2016 13:41:21 -0400 Subject: [PATCH 1/5] Fix models in 2D near the IDL. --- Source/Scene/Model.js | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index 95514011b692..bd5778e3a841 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -2489,7 +2489,7 @@ define([ }; } - function createCommand(model, gltfNode, runtimeNode, context) { + function createCommand(model, gltfNode, runtimeNode, context, scene3DOnly) { var nodeCommands = model._nodeCommands; var pickIds = model._pickIds; var allowPicking = model.allowPicking; @@ -2629,11 +2629,20 @@ define([ }); } + var command2D; + + if (!scene3DOnly) { + command2D = DrawCommand.shallowClone(command); + command2D.boundingVolume = new BoundingSphere(); + command2D.modelMatrix = new Matrix4(); + } + var nodeCommand = { show : true, boundingSphere : boundingSphere, command : command, - pickCommand : pickCommand + pickCommand : pickCommand, + command2D : command2D }; runtimeNode.commands.push(nodeCommand); nodeCommands.push(nodeCommand); @@ -2641,7 +2650,7 @@ define([ } } - function createRuntimeNodes(model, context) { + function createRuntimeNodes(model, context, scene3DOnly) { var loadResources = model._loadResources; if (!loadResources.finishedEverythingButTextureCreation()) { @@ -2699,7 +2708,7 @@ define([ } if (defined(gltfNode.meshes)) { - createCommand(model, gltfNode, runtimeNode, context); + createCommand(model, gltfNode, runtimeNode, context, scene3DOnly); } var children = gltfNode.children; @@ -2720,6 +2729,7 @@ define([ function createResources(model, frameState) { var context = frameState.context; + var scene3DOnly = frameState.scene3DOnly; if (model._loadRendererResourcesFromCache) { var resources = model._rendererResources; @@ -2757,8 +2767,8 @@ define([ // Could use copy-on-write if it is worth it. Probably overkill. } - createUniformMaps(model, context); // using glTF materials/techniques - createRuntimeNodes(model, context); // using glTF scene + createUniformMaps(model, context); // using glTF materials/techniques + createRuntimeNodes(model, context, scene3DOnly); // using glTF scene } /////////////////////////////////////////////////////////////////////////// @@ -2829,6 +2839,13 @@ define([ Matrix4.clone(command.modelMatrix, pickCommand.modelMatrix); BoundingSphere.clone(command.boundingVolume, pickCommand.boundingVolume); } + + command = primitiveCommand.command2D; + if (defined(command) && model._mode === SceneMode.SCENE2D) { + Matrix4.clone(nodeMatrix, command.modelMatrix); + command.modelMatrix[13] -= CesiumMath.sign(command.modelMatrix[13]) * 2.0 * CesiumMath.PI * projection.ellipsoid.maximumRadius; + BoundingSphere.transform(primitiveCommand.boundingSphere, command.modelMatrix, command.boundingVolume); + } } } } @@ -3287,7 +3304,17 @@ define([ for (i = 0; i < length; ++i) { nc = nodeCommands[i]; if (nc.show) { - commandList.push(nc.command); + var command = nc.command; + commandList.push(command); + + if (!frameState.scene3DOnly) { + var boundingVolume = command.boundingVolume; + var idl2D = frameState.mapProjection.ellipsoid.maximumRadius * CesiumMath.PI; + if (frameState.mode === SceneMode.SCENE2D && + (boundingVolume.center.y + boundingVolume.radius > idl2D || boundingVolume.center.y - boundingVolume.radius < idl2D)) { + commandList.push(nc.command2D); + } + } } } } From 24ecefba90203723dfd03a90fd71a85ee5af0ceb Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 19 May 2016 14:49:38 -0400 Subject: [PATCH 2/5] Fix picking when the model crosses the IDL and more updates from review. --- Source/Scene/Model.js | 44 +++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index bd5778e3a841..3a4654266318 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -2630,11 +2630,17 @@ define([ } var command2D; - + var pickCommand2D; if (!scene3DOnly) { command2D = DrawCommand.shallowClone(command); command2D.boundingVolume = new BoundingSphere(); command2D.modelMatrix = new Matrix4(); + + if (allowPicking) { + pickCommand2D = DrawCommand.shallowClone(pickCommand); + pickCommand2D.boundingVolume = new BoundingSphere(); + pickCommand2D.modelMatrix = new Matrix4(); + } } var nodeCommand = { @@ -2642,7 +2648,8 @@ define([ boundingSphere : boundingSphere, command : command, pickCommand : pickCommand, - command2D : command2D + command2D : command2D, + pickCommand2D : pickCommand2D }; runtimeNode.commands.push(nodeCommand); nodeCommands.push(nodeCommand); @@ -2840,11 +2847,21 @@ define([ BoundingSphere.clone(command.boundingVolume, pickCommand.boundingVolume); } + // If the model crosses the IDL in 2D, it will be drawn in one viewport, but part of it + // will be clipped by the viewport. We create a second command that translates the model + // model matrix to the opposite side of the map so the part that was clipped in one viewport + // is drawn in the other. command = primitiveCommand.command2D; if (defined(command) && model._mode === SceneMode.SCENE2D) { Matrix4.clone(nodeMatrix, command.modelMatrix); command.modelMatrix[13] -= CesiumMath.sign(command.modelMatrix[13]) * 2.0 * CesiumMath.PI * projection.ellipsoid.maximumRadius; BoundingSphere.transform(primitiveCommand.boundingSphere, command.modelMatrix, command.boundingVolume); + + if (allowPicking) { + var pickCommand2D = primitiveCommand.pickCommand2D; + Matrix4.clone(command.modelMatrix, pickCommand2D.modelMatrix); + BoundingSphere.clone(command.boundingVolume, pickCommand2D.boundingVolume); + } } } } @@ -3300,6 +3317,9 @@ define([ var i; var nc; + var idl2D = frameState.mapProjection.ellipsoid.maximumRadius * CesiumMath.PI; + var boundingVolume; + if (passes.render) { for (i = 0; i < length; ++i) { nc = nodeCommands[i]; @@ -3307,13 +3327,10 @@ define([ var command = nc.command; commandList.push(command); - if (!frameState.scene3DOnly) { - var boundingVolume = command.boundingVolume; - var idl2D = frameState.mapProjection.ellipsoid.maximumRadius * CesiumMath.PI; - if (frameState.mode === SceneMode.SCENE2D && - (boundingVolume.center.y + boundingVolume.radius > idl2D || boundingVolume.center.y - boundingVolume.radius < idl2D)) { - commandList.push(nc.command2D); - } + boundingVolume = command.boundingVolume; + if (frameState.mode === SceneMode.SCENE2D && + (boundingVolume.center.y + boundingVolume.radius > idl2D || boundingVolume.center.y - boundingVolume.radius < idl2D)) { + commandList.push(nc.command2D); } } } @@ -3323,7 +3340,14 @@ define([ for (i = 0; i < length; ++i) { nc = nodeCommands[i]; if (nc.show) { - commandList.push(nc.pickCommand); + var pickCommand = nc.pickCommand; + commandList.push(pickCommand); + + boundingVolume = pickCommand.boundingVolume; + if (frameState.mode === SceneMode.SCENE2D && + (boundingVolume.center.y + boundingVolume.radius > idl2D || boundingVolume.center.y - boundingVolume.radius < idl2D)) { + commandList.push(nc.pickCommand2D); + } } } } From d1bbe1c85560f418c21260c23e6b43ca7bf2e5c2 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 19 May 2016 16:04:10 -0400 Subject: [PATCH 3/5] Add test for rendering a model on the IDL. --- Specs/Scene/ModelSpec.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Specs/Scene/ModelSpec.js b/Specs/Scene/ModelSpec.js index e34cb84c87ee..9a4a38ff8926 100644 --- a/Specs/Scene/ModelSpec.js +++ b/Specs/Scene/ModelSpec.js @@ -226,6 +226,14 @@ defineSuite([ verifyRender(texturedBoxModel); }); + it('renders in 2D over the IDL', function() { + return when(loadModel(texturedBoxUrl)).then(function(model) { + model.modelMatrix = Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(180.0, 0.0, 100.0)); + scene.morphTo2D(0.0); + verifyRender(model); + }); + }); + it('resolves readyPromise', function() { return texturedBoxModel.readyPromise.then(function(model) { verifyRender(model); From 282781a075b0c7999da44f6fe535355b01023a2d Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 23 May 2016 11:41:03 -0400 Subject: [PATCH 4/5] Fix conversion from model matrix to 2D. --- Source/Core/Transforms.js | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/Source/Core/Transforms.js b/Source/Core/Transforms.js index 8246f024a8c7..937485935caf 100644 --- a/Source/Core/Transforms.js +++ b/Source/Core/Transforms.js @@ -830,6 +830,8 @@ define([ var scratchCartesian4NewXAxis = new Cartesian4(); var scratchCartesian4NewYAxis = new Cartesian4(); var scratchCartesian4NewZAxis = new Cartesian4(); + var scratchFromENU = new Matrix4(); + var scratchToENU = new Matrix4(); /** * @private @@ -852,6 +854,9 @@ define([ var origin = Matrix4.getColumn(matrix, 3, scratchCartesian4Origin); var cartographic = ellipsoid.cartesianToCartographic(origin, scratchCartographic); + var fromENU = Transforms.eastNorthUpToFixedFrame(origin, ellipsoid, scratchFromENU); + var toENU = Matrix4.inverseTransformation(fromENU, scratchToENU); + var projectedPosition = projection.project(cartographic, scratchCartesian3Projection); var newOrigin = scratchCartesian4NewOrigin; newOrigin.x = projectedPosition.z; @@ -861,31 +866,13 @@ define([ var xAxis = Matrix4.getColumn(matrix, 0, scratchCartesian3); var xScale = Cartesian3.magnitude(xAxis); - Cartesian4.add(xAxis, origin, xAxis); - ellipsoid.cartesianToCartographic(xAxis, cartographic); - - projection.project(cartographic, projectedPosition); - var newXAxis = scratchCartesian4NewXAxis; - newXAxis.x = projectedPosition.z; - newXAxis.y = projectedPosition.x; - newXAxis.z = projectedPosition.y; - newXAxis.w = 0.0; - - Cartesian3.subtract(newXAxis, newOrigin, newXAxis); + var newXAxis = Matrix4.multiplyByVector(toENU, xAxis, scratchCartesian4NewXAxis); + Cartesian4.fromElements(newXAxis.z, newXAxis.x, newXAxis.y, 0.0, newXAxis); var yAxis = Matrix4.getColumn(matrix, 1, scratchCartesian3); var yScale = Cartesian3.magnitude(yAxis); - Cartesian4.add(yAxis, origin, yAxis); - ellipsoid.cartesianToCartographic(yAxis, cartographic); - - projection.project(cartographic, projectedPosition); - var newYAxis = scratchCartesian4NewYAxis; - newYAxis.x = projectedPosition.z; - newYAxis.y = projectedPosition.x; - newYAxis.z = projectedPosition.y; - newYAxis.w = 0.0; - - Cartesian3.subtract(newYAxis, newOrigin, newYAxis); + var newYAxis = Matrix4.multiplyByVector(toENU, yAxis, scratchCartesian4NewYAxis); + Cartesian4.fromElements(newYAxis.z, newYAxis.x, newYAxis.y, 0.0, newYAxis); var zAxis = Matrix4.getColumn(matrix, 2, scratchCartesian3); var zScale = Cartesian3.magnitude(zAxis); From 81c8c5affaa5cf3307d5291805c124e24c43aec5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 24 May 2016 13:19:32 -0400 Subject: [PATCH 5/5] Fix jsHint error. --- Source/Scene/Model.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index 9b7520a27929..1566ee372544 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -3161,8 +3161,6 @@ define([ /////////////////////////////////////////////////////////////////////////// - var scratchCartographic = new Cartographic(); - function getUpdateHeightCallback(model, ellipsoid, cartoPosition) { return function (clampedPosition) { if (model.heightReference === HeightReference.RELATIVE_TO_GROUND) {