I have a simple project with an Entity and a Camera that can follow it.
I now would like to make that Entity (a small plane) have animations; landing gear to move at certain times, propeller to spin at varying speeds, etc. These animations exist on the model file, now I need to access them.
Before, I was passing the Entity a Position and Orientation, Cesium would update it’s location smoothly, and the Camera could track the Entity smoothly.
Now, I have implemented a Model which does not accept a PositionProperty and instead takes a modelMatrix which I am manually updating every tick().
The above approach seems to work fine but there are multiple downsides:
The Camera cannot natively track a Model, only an Entity.
Updating Camera position/orientation manually isn’t as visually smooth as the built-in trackedEntity.
Overall, this would be much simpler if I could just wrap my Model in an Entity and animate the Model when needed.
Is there a better approach to having a camera-trackable, granularly-animatable “Entity” in Cesium while maintaining the native fluid framerate?
Here’s a little recording using a Model and updating modelMatrix and Camera position manually.
I occasionally hold the camera still to show that the plane does move rather smoothly, but the camera following the model looks very jiittery/laggy.
You didn’t show us your code, so its hard to say… but I think you need to update the camera position/orientation from a postUpdate handler, to ensure that its up to date when the model gets redrawn:
viewer.scene.postUpdate.addEventListener(() => { /* do the updates here */ });
I think you may also find viewer.scene.camera.lookAt an easy way to set the camera position (assuming you’re not already doing so).
Sorry, that code is buried deep inside a large project, and I don’t really have time to separate out a small example… it also depends on a pull request I made a while ago.
But that pull request (if it ever gets accepted) adds a new sandcastle example involving that model accelerating along a straight road (the pull request is to give better control over the animations). That example takes a simpler approach to handling the tracking.
What it does is create a label entity (but you could use any entity), and sets that as the trackedEntity, and then positions it just above the model as the model moves. If you wanted to take that approach, you’d probably want a Point, and just position it exactly where the model is, every time you update the model. You’d set it up.something like:
var modelProxy = viewer.entities.add({/* whatever */});
viewer.trackedEntity = modelProxy;
modelProxy.viewFrom = new Cesium.Cartesian3(-10.0, 7.0, 4.0);
And then set modelProxy.position to match the model’s position every time you move it. I think this is probably pretty close to your original entity code, except you’re now using a proxy entity to do the tracking…
Oh I actually happened upon that pull request when initially researching this topic! I hope it gets accepted.
Your approach of creating an Entity and moving it with the Model as a sort of Camera-target-proxy sounds close to an approach I tried, but seemed to be ignoring the great functionality that an Entity already has; position as a PositionProperty, which Cesium uses to keep the movement smooth via interpolation. But I have a feeling that’s where I run into the choppy camera movement is by trying to combine it’s hidden interpolation handling and my own manual movement onTick.
I’ll try to re-implement this approach and use the postUpdate() you mentioned in your earlier reply.
Another approach I’m working on now and am curious about your thoughts on, is adding a Model to an extended ModelGraphics class and displaying the animating Model as the Entity. The goal being keeping all the native Entity functionality and including all the Model functionality minus changing location with ModelMatrix. This approach has proven to be difficult to implement but may be worth it in the long run, still unsure.