-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Clamping to 3D Tiles #6934
Clamping to 3D Tiles #6934
Conversation
Thanks for the pull request @lilleyse!
Reviewers, don't forget to make sure that:
I am a bot who helps you make Cesium awesome! Contributions to my configuration are welcome. 🌍 🌎 🌏 |
I'm thinking about breaking this out into several PRs to help make reviewing easier: one with general Scene cleanup, one with rendering using separate views, and one with the ray picking additions. Stay tuned... |
3dcc232
to
a5c894a
Compare
@@ -0,0 +1,130 @@ | |||
<!DOCTYPE html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing the thumbnail? Perhaps gallery/development/Clamp to Tileset.jpg
is in the wrong location?
} | ||
}); | ||
|
||
function toggleShow(show) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this will be done a lot - at least for clamping models where we want to exclude them from the pick - would it be better for scene.sampleHeight
to take an optional array of primitives to exclude/hide?
Just don't assume show
was true when resetting a primitive that was passed in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking the same thing and was going to leave a comment about that. Added now.
Will need #7024 to be fixed before entities can be accepted in the array.
|
||
function calculatePosition(offset) { | ||
var currentPosition = Cesium.Cartesian3.lerp(startPosition, endPosition, offset, new Cesium.Cartesian3()); | ||
var currentCartographic = Cesium.Cartographic.fromCartesian(currentPosition); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this line until the end of the function also basically be a helper in the Cesium API, e.g.,
scene.clampToHeight(cartesian);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this helper function but I feel like it is kind of trivial and not deserving of a function in Scene. In general it doesn't seem like we have two functions that perform the same task but with cartesian vs. cartographic inputs.
This is what it looks like, what do you think?
/**
* Clamps the given Cartesian position to the scene geometry along the geodetic surface normal.
* May be used to clamp objects to the globe, 3D Tiles, or primitives in the scene.
* <p>
* This function only samples height from globe tiles and 3D Tiles that are rendered in the current view. All other
* primitives are sampled regardless of visibility.
* </p>
*
* @param {Cartesian3} cartesian The Cartesian position.
* @param {Object[]} primitivesToExclude A list of primitives and/or entities to exclude when clamping.
* @param {Cartesian3} [result] An optional object to return the clamped position.
* @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided. This may be <code>undefined</code> if there is nothing to clamp to.
*/
Scene.prototype.clampToHeight = function(cartesian, primitivesToExclude, result) {
var globe = this.globe;
var ellipsoid = defined(globe) ? globe.ellipsoid : this.mapProjection.ellipsoid;
var cartographic = Cartographic.fromCartesian(cartesian, ellipsoid, scratchPickCartographic);
var height = this.sampleHeight(cartographic, primitivesToExclude);
if (defined(height)) {
cartographic.height = height;
return Cartographic.toCartesian(cartographic, ellipsoid, result);
}
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems OK to me. It feels trivial to you, but to the end user I think it is separate enough use cases. If we end up with too many functions on Scene
, we can evaluate grouping them into a new sub-object or elsewhere.
Source/Scene/Scene.js
Outdated
width: 0.01, | ||
aspectRatio: 1.0, | ||
near: 0.1, | ||
far: 500000000.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure about hardcoding this value? Seems arbitrary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just grabbed this directly from OrthographicFrustum
. I'll just let it use OrthographicFrustum
's default instead of hardcoding here.
Basically it just has to be a large number.
Source/Scene/Scene.js
Outdated
var scratchRight = new Cartesian3(); | ||
var scratchUp = new Cartesian3(); | ||
|
||
function pickFromRay(scene, ray, pickPosition, pickObject) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it cleaner to put the picking functions in a separate private file just so Scene.js isn't so large?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's just these two function pickFromRay
and drillPick
I don't think it helps to separate them out. pickFromRay
is calling a bunch of Scene's internal function anyways and it would be less clean to move it to another file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
Source/Scene/Scene.js
Outdated
}; | ||
|
||
/** | ||
* Returns a list of objects, each containing a `primitive` property, for all primitives hit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What other properties does each object have? Why not just return an array of primitives?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is copied from the pick
and drillPick
doc.
I don't think the set of properties is standardized. Model has it's own pick object that includes the node, 3D Tiles uses Cesium3DTileFeature
, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, can this and the other functions provide a bit more context?
Let's wait on |
0935d13
to
77b445f
Compare
…turn early in Sandcastle demo
@lilleyse I would like to wait for the next release to merge this in. This is a pretty big change to be merging in at the last minute. Is there any reason it has to make this release? |
I agree with @hpinkos. Given the regressions we introduced in traversal last release, I'm very hesitant to merge this before the release on Monday without an extremely good reason. |
b29cf7c
to
def0ddd
Compare
Yes it's a bit close to the release for comfort. But if it helps most of the new functionality is relatively isolated and the more sweeping changes in #7039, #6958, and #6957 were merged earlier in the month and have had a longer time to sit in master. I am a little worried that #7069 and the related changes I have queued up for this branch are cutting it too close. One option might be to merge this PR without that change and add it for the next release. #6934 (comment) has more context about the problem. @pjcozzi would this be an acceptable approach? |
Could we at least attempt to review and test that PR? If I am following that is needed so Cesium doesn't render the scene twice for the pick for the common clamping case , right? Feels pretty important and something we knew to address awhile ago. |
It's already been reviewed/tested/merged, I didn't share @lilleyse's reservation about the change (though I'm the one that originally recommended so I'm clearly biased). |
@lilleyse please bump when this is ready for full testing. (I assume that will be today?) |
Thought dump because I'm at bit of an impasse for getting the excluded objects feature to be robust and run in a single render. Technicals aside, there's a major design problem with the approach. Then the thinking is, offload that logic to the app instead. That was the original approach I tried but it is cumbersome: scene.postRender.addEventListener(function() {
entity.show = false;
var height = scene.sampleHeight(cartographic);
entity.show = true;
}); This only works now that #7069 is merged. If #7069 is reverted I don't think it's possible to chain (pre/post)(Render/Update) events to replicate this behavior if scene.postRender.addEventListener(function() {
entity.show = false;
viewer._dataSourceDisplay.update(viewer.clock.currentTime);
var height = scene.sampleHeight(cartographic);
entity.show = true;
}); Which looks pretty bad. The reasons for reverting #7069 are:
Some alternative approaches that we might need to take:
The last option is the most user friendly and efficient, but is it bad practice to be adding functions like this to |
Sorry I don't have the time to digest all of the above, but just some drive-by comments:
|
I reverted back to the older (slower) approach. I don't think I'll have a good fix in time, but with the hope of improving this later here are some of the approaches I tried:
|
Looks good to me. |
Congratulations on closing the issue! I found these Cesium forum links in the comments above: https://groups.google.com/d/msg/cesium-dev/XdogF4bIbNQ/9WdgDqs9BwAJ If this issue affects any of these threads, please post a comment like the following:
I am a bot who helps you make Cesium awesome! Contributions to my configuration are welcome. 🌍 🌎 🌏 |
Fixes #6080
This adds support for sampling the height of geometry in the scene at a given position. The most common use case for this is to clamp objects to 3D Tiles. Unlike
pick
,pickPosition
, and others this approach works mostly independent of the current camera view.Added to the public API:
scene.sampleHeight
- takes a cartographic position and returns a height.Private functions that will have lots of use in the future
scene.pickFromRay
scene.pickPositionFromRay
scene.drillPickFromRay
scene.drillPickPositionFromRay
Underlying this
Scene.js
now has a concept of Views where each view contains framebuffers, command lists, cameras, and viewports specific to that view. The pick-ray functions uses a view with a 1x1 orthographic camera.While working on this I've been thinking a lot about how we might eventually support multiple views on the same screen. I think this PR brings us like 50% there but there is still a lot of work to do.
drawingBufferWidth/Height
is hard coded almost everywhere...For reviewing I recommend reading the commits in order. I did a bunch of cleanup as I tried to fully wrap my head around
Scene.js
. A lot of the log depth changes were added so that derived commands would not thrash when going between rendering the scene with log depth and then rendering the 1x1 orthographic pass.To do:
Clamp To Tileset
development demoAfter:
Ground%20Clamping.html
Later PR:
sampleHeight
working for offscreen 3D Tiles and globe