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

Added heightReference to models #3938

Merged
merged 8 commits into from
May 23, 2016
Merged

Added heightReference to models #3938

merged 8 commits into from
May 23, 2016

Conversation

tfili
Copy link
Contributor

@tfili tfili commented May 19, 2016

Adds a heightReference property for models. If you use it scene is also required. This will render models on terrain (or relative to it). Tests were also added in ModelSpec.js.

In order to get this working properly #3921 was fixed. The issue was that the QuadTreePrimitive removes the updateHeight callback once we get to the highest resolution tile. If we changed terrain providers we never add the callback again. I added a terrainProviderChanged event to Globe and Scene and hooked them up to the Billboard and Model so it updates the clamped positions when the provider is changed.

Tests were added to Globe to make sure the event fires and to BillboardCollection and Model to make sure it gets the event when the provider is changed.

CHANGES.md was also updated.

@pjcozzi
Copy link
Contributor

pjcozzi commented May 19, 2016

All sounds good, thanks @tfili. I will do a quick look. @bagnell can you do a full review and merge when ready?


var scene = this._billboardCollection._scene;
if (defined(scene)) {
scene.terrainProviderChanged.addEventListener(function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to do this once for the billboard collection, then loop over all the billboards in the collection? Save O(n) memory?

@pjcozzi
Copy link
Contributor

pjcozzi commented May 19, 2016

@tfili did you test this in Sandcastle with all the options that modify the model matrix like minimum pixel size and maximum scale?

* @type {Event}
* @readonly
*/
terrainProviderChanged : {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add to CHANGES.md. You could also make the Globe event private and only document this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the terrainProvider is public on both Scene and Globe it would be a little weird to have this private on the Globe.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean will anyone use it on the Globe directly? Or will everyone use it through Scene? If the later, then why not keep the API surface area small and not provide two ways to do the same thing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I'm all for reducing the API surface area, I'm not sure having the event only on the scene makes sense here. We should stay consistent with what we've done elsewhere and we made a choice to have the globe be a separate documented class and since the property is there publicly, the event should be too.

Whenever we get around to doing a large API cleanup, then I could see us making a lot of these things private; but we shouldn't just start now because it will make the API even more disjoint.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

@tfili
Copy link
Contributor Author

tfili commented May 19, 2016

@pjcozzi I tested with most of the options. I'll give it a quick run through with all the combinations just to be sure. Other than that I think I took care of everything else. @bagnell have a look when you get a chance.

@tfili
Copy link
Contributor Author

tfili commented May 20, 2016

Looks to checkout with all model options.

@bagnell
Copy link
Contributor

bagnell commented May 23, 2016

If you animate the model matrix with a model clamped to ground, the model only seems to update when the camera moves. Here is the example I used that is supposed to have a model and billboard clamped to ground at the same location:

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;

function createModel(url, height, heading, pitch, roll) {
    height = Cesium.defaultValue(height, 0.0);
    heading = Cesium.defaultValue(heading, 0.0);
    pitch = Cesium.defaultValue(pitch, 0.0);
    roll = Cesium.defaultValue(roll, 0.0);

    var origin = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, height);
    var modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(origin, heading, pitch, roll);

    scene.primitives.removeAll(); // Remove previous model
    var model = scene.primitives.add(Cesium.Model.fromGltf({
        scene : scene,
        url : url,
        modelMatrix : modelMatrix,
        minimumPixelSize : 128,
        heightReference : Cesium.HeightReference.CLAMP_TO_GROUND
    }));

    var billboardCollection = viewer.scene.primitives.add(new Cesium.BillboardCollection({
        scene : viewer.scene
    }));
    var billboard = billboardCollection.add({
        position : origin,
        image : '../images/facility.gif',
        heightReference : Cesium.HeightReference.CLAMP_TO_GROUND
    });

    model.readyPromise.then(function(model) {
        // Play and loop all animations at half-speed
        model.activeAnimations.addAll({
            speedup : 0.5,
            loop : Cesium.ModelAnimationLoop.REPEAT
        });

        var camera = viewer.camera;

        viewer.scene.postRender.addEventListener(function(scene, time) {
            var ellipsoid = viewer.scene.mapProjection.ellipsoid;

            var modelMatrix = model.modelMatrix;
            var currentPosition = Cesium.Cartesian3.fromCartesian4(Cesium.Matrix4.getColumn(modelMatrix, 3, new Cesium.Cartesian4()), new Cesium.Cartesian3());
            var currentCarto = ellipsoid.cartesianToCartographic(currentPosition);
            currentCarto.longitude += Cesium.Math.toRadians(0.000001);
            var p = ellipsoid.cartographicToCartesian(currentCarto);
            Cesium.Matrix4.setColumn(modelMatrix, 3, Cesium.Cartesian4.fromElements(p.x, p.y, p.z, 1.0), modelMatrix);

            billboard.position = Cesium.Cartesian3.clone(p);

            var position = Cesium.Cartesian3.clone(camera.position);
            camera.lookAtTransform(model.modelMatrix);
            camera.position = position;
        });

        // Zoom to model
        var controller = scene.screenSpaceCameraController;
        var r = 2.0 * Math.max(model.boundingSphere.radius, camera.frustum.near);
        controller.minimumZoomDistance = r * 0.5;

        var center = Cesium.Matrix4.multiplyByPoint(model.modelMatrix, model.boundingSphere.center, new Cesium.Cartesian3());
        var heading = Cesium.Math.toRadians(230.0);
        var pitch = Cesium.Math.toRadians(-20.0);
        camera.lookAt(center, new Cesium.HeadingPitchRange(heading, pitch, r * 2.0));
    }).otherwise(function(error){
        window.alert(error);
    });
}

var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function(movement) {
    var pick = scene.pick(movement.endPosition);
    if (Cesium.defined(pick) && Cesium.defined(pick.node) && Cesium.defined(pick.mesh)) {
        // Output glTF node and mesh under the mouse. 
        console.log('node: ' + pick.node.name + '. mesh: ' + pick.mesh.name);
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

createModel('../../SampleData/models/CesiumMan/Cesium_Man.glb');

@tfili
Copy link
Contributor Author

tfili commented May 23, 2016

@bagnell Should be good to go.

@bagnell bagnell merged commit fa354c8 into master May 23, 2016
@bagnell bagnell deleted the models-on-terrain branch May 23, 2016 19:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants