# Efficient Animation (moving from Google Earth to Cesium)

**URL:** <https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015>\
**Category:** CesiumJS\
**Created:** [February 16, 2015, 9:16am UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015 "2015-02-16T09:16:15Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alexander\_Entin](https://avatars.discourse-cdn.com/v4/letter/a/71e660/32.png) [@Alexander\_Entin](https://community.cesium.com/u/Alexander_Entin)\
**Post date:** [February 16, 2015, 9:16am UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/1 "2015-02-16T09:16:15Z")

</div>

Gents,

I need to animate multiple small circles. At most there could be few hundred.

Here is [an example](https://www.youtube.com/watch?v=vJ2Da_WAbHE#t=40)

In GE I generated and processed KML each frame with acceptable performance.

In Cesium I combine all lines in one primitive and all dots into another and replace primitives each frame.

This performs trice worse, which is unacceptable and could be a show-stopper.

Actually, there is no need to re-create the whole thing each frame. Some parts only need to be updated once per second. But the whole “dashboard” should move along the model smoothly.

Now, I’m about to try drawing it on canvas and then giving it to Cesium as a ground overlay (each frame).

And my questions:

1. What are possible ways to improve performance of current implementation?

2. How can I move multiple geometries at once? Will this improve performance comparing to re-creating them? (move each frame, but re-create rarely)

3. I found myself implementing something like Entity API on top of geometries/appearances just to be able to combine multiple geometries into one primitive. Can I control this in Entity API or CZML?

4. Do you think that “canvas + ground overlay” could work?

5. Can you propose another, possibly better, solution?

Thank you.

var appearance = new C.PerInstanceColorAppearance({ flat: true })

var instances = \_.map(o.circle, function(circle) {

var color = circle.fill || circle.stroke || C.Color.WHITE

return new C.GeometryInstance({

geometry: new (circle.fill ? C.CircleGeometry : C.CircleOutlineGeometry)({

center: C.c3(circle.center, circle.alt)

, radius: circle.radius

, vertexFormat: appearance.vertexFormat

})

, attributes: {

color: C.ColorGeometryInstanceAttribute.fromColor(color)

}

})

})

…

o.primitive = new C.Primitive({

geometryInstances: instances

, appearance: appearance

, asynchronous: o.asynchronous

})

…

f.primitives.remove(prev)

…

f.primitives.add(o.primitive)

---

<div class="post-metadata">

**Author:** ![Alexander\_Entin](https://avatars.discourse-cdn.com/v4/letter/a/71e660/32.png) [@Alexander\_Entin](https://community.cesium.com/u/Alexander_Entin)\
**Post date:** [February 16, 2015, 11:23am UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/2 "2015-02-16T11:23:40Z")

</div>

Just tried “canvas + ground overlay”.

Works, but flickers badly with white.

Why? Can anything be done?

var appearance = new C.MaterialAppearance({

material: C.Material.fromType(‘Image’, {

image: o.rectangle.material // canvas.toDataURL()

})

})

instances = new C.GeometryInstance({

geometry: new C.RectangleGeometry({

rectangle: o.rectangle.coordinates

, vertexFormat: appearance.vertexFormat

})

})

…

asynchronous: false

---

<div class="post-metadata">

**Author:** ![Alexander\_Entin](https://avatars.discourse-cdn.com/v4/letter/a/71e660/32.png) [@Alexander\_Entin](https://community.cesium.com/u/Alexander_Entin)\
**Post date:** [February 16, 2015, 3:59pm UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/3 "2015-02-16T15:59:56Z")

</div>

“All dots in one primitive replaced each frame” implementation spends a lot of time in EllipseGeometry.createGeometry and GeometryPipeline.combineInstances.  
Looks like it is time to try to reuse the same geometry in multiple instances and NOT combine instances.

Please, give me some hints as to what to explore.

---

<div class="post-metadata">

**Author:** ![patrick](https://sea2.discourse-cdn.com/cesium/user_avatar/community.cesium.com/patrick/32/2045_2.png) [@patrick](https://community.cesium.com/u/patrick)\
**Post date:** [February 16, 2015, 11:56pm UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/4 "2015-02-16T23:56:55Z")

</div>

Hi,

For a batching strategy, you could probably put all static circles in one Primitive, and then have one Primitive per circle for moving ones.

These performance tips for creating circles will also be useful: [https://groups.google.com/forum/#!searchin/cesium-dev/granularity/cesium-dev/CzkZXqX6axQ/p5vtAzTlQQsJ](https://groups.google.com/forum/#!searchin/cesium-dev/granularity/cesium-dev/CzkZXqX6axQ/p5vtAzTlQQsJ)

Patrick

---

<div class="post-metadata">

**Author:** ![Alexander\_Entin](https://avatars.discourse-cdn.com/v4/letter/a/71e660/32.png) [@Alexander\_Entin](https://community.cesium.com/u/Alexander_Entin)\
**Post date:** [February 17, 2015, 2:38pm UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/5 "2015-02-17T14:38:27Z")

</div>

Thanks!

So, now I try to move primitives using **primitive.modelMatrix** (to avoid re-creation):

- create “unit” geometry

- use it in multiple primitives

- scale and place using **primitive.modelMatrix**

- paint via **primitive.appearance**

It works with EllipsoidGeometry but I do not understand how to do the same for CircleGeometry.

Please, advise.

var C = Cesium

var p = C.Cartesian3.fromDegrees(144.767305, -38.339623)

var viewer = new C.Viewer(‘cesiumContainer’);

var geometry = new C.EllipsoidGeometry()

var alt = 1e-6

/\*

// trying to do the same with circle fails:

// - exceptions with zero center or w/o it

// - nothing visible with near-zero center

var geometry = new C.CircleGeometry({

radius: 1

, center: new C.Cartesian3(0, 0, alt) // C.Cartesian3.ZERO

})

\*/

var primitive = viewer.scene.primitives.add(new C.Primitive({

geometryInstances: new C.GeometryInstance({ geometry: geometry })

, appearance: new C.MaterialAppearance()

, modelMatrix: C.Transforms.eastNorthUpToFixedFrame§

// , debugShowBoundingVolume: true

}))

// scale, move and paint

setTimeout(function() {

p.x += 5

var m = C.Transforms.eastNorthUpToFixedFrame§

C.Matrix4.multiplyByUniformScale(m, 2, m)

primitive.modelMatrix = m

primitive.appearance.material = C.Material.fromType(‘Color’, { color: C.Color.BLUE })

}, 3000)

viewer.camera.flyTo({

destination: p

, duration: 0

})

---

<div class="post-metadata">

**Author:** ![patrick](https://sea2.discourse-cdn.com/cesium/user_avatar/community.cesium.com/patrick/32/2045_2.png) [@patrick](https://community.cesium.com/u/patrick)\
**Post date:** [February 17, 2015, 8:33pm UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/6 "2015-02-17T20:33:25Z")

</div>

A circle geometry is different than an ellipsoid. The the circle depends on the curvature of Earth’s ellipsoid so it needs to be recomputed for each point for it to be correct; a simple affine transformation in a 4x4 matrix is not enough.

With that said, if the circle radius is reasonably small, you could get away with it, but I suspect you’ll need to write a custom geometry that creates the circle in, for example, the xy plane (would not be too hard).

Patrick

---

<div class="post-metadata">

**Author:** ![Alexander\_Entin](https://avatars.discourse-cdn.com/v4/letter/a/71e660/32.png) [@Alexander\_Entin](https://community.cesium.com/u/Alexander_Entin)\
**Post date:** [February 17, 2015, 10:06pm UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/7 "2015-02-17T22:06:37Z")

</div>

Thank you again.

I now experiment with degenerate cylinders and think they will do the trick.

---

<div class="post-metadata">

**Author:** ![patrick](https://sea2.discourse-cdn.com/cesium/user_avatar/community.cesium.com/patrick/32/2045_2.png) [@patrick](https://community.cesium.com/u/patrick)\
**Post date:** [February 17, 2015, 11:30pm UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/8 "2015-02-17T23:30:13Z")

</div>

Ah, yes. Good idea. That should do it.

Patrick

---

<div class="post-metadata">

**Author:** ![Alexander\_Entin](https://avatars.discourse-cdn.com/v4/letter/a/71e660/32.png) [@Alexander\_Entin](https://community.cesium.com/u/Alexander_Entin)\
**Post date:** [February 18, 2015, 10:37am UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/9 "2015-02-18T10:37:55Z")

</div>

Can you comment on remaining questions?

These are not of major importance ATM for me, but still interesting.

Thank you.

---

<div class="post-metadata">

**Author:** ![patrick](https://sea2.discourse-cdn.com/cesium/user_avatar/community.cesium.com/patrick/32/2045_2.png) [@patrick](https://community.cesium.com/u/patrick)\
**Post date:** [February 19, 2015, 11:15pm UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/10 "2015-02-19T23:15:42Z")

</div>

Hi,

> 1. How can I move multiple geometries at once?

> Batching makes this hard. I would put each in a separate Primitive and then move each primitive.

> 1. I found myself implementing something like Entity API on top of geometries/appearances just to be able to combine multiple geometries into one primitive. Can I control this in Entity API or CZML?

> The Entity API abstracts away the batching detail and tries to do a good job for the most common cases since a typical user should not have to determine how to batch geometry. I don’t believe we currently expose anything to influence the batching at this layer.

Patrick

---

<div class="post-metadata">

**Author:** ![Matt\_Amato](https://sea2.discourse-cdn.com/cesium/user_avatar/community.cesium.com/matt_amato/32/1993_2.png) [@Matt\_Amato](https://community.cesium.com/u/Matt_Amato)\
**Post date:** [February 20, 2015, 2:51am UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/11 "2015-02-20T02:51:21Z")

</div>

Alexander, I know you had some questions in other threads that I haven’t gotten around to answering yet, but hopefully will soon. I’ve had my head down on KML and related things that need to be done for 1.7. One thing I will mention briefly is that when working with entities, it will batch dynamic objects separately and automatically as long as you give it a property that changes over time. For a more concrete example, assume you wanted to set the height of a polygon, the simple way to do this is:

entity.polygon.height = 3;

What you are really doing (under the hood) is creating a ConstantProperty with a value of 3. It’s shorthand for actually writing.

entity.polygon.height = new ConstantProperty(3);

If you plan on height changing, then simply re-assigning height is not the best way to do it. Instead you would want to use a time-dynamic property. Which property you use really depends on the nature of the animation and change. For example, SampledProperty is useful if you want data to be interpolated and change every frame (like a position or a circle growing and shrinking). Assuming you had three times (t1, t2, r3)

var property = new Cesium.SampledProperty(Number);

property.addSample(t1, 30);

property.addSample(t2, 15);

property.addSample(t3, 45);

entity.polygon.height = property;

So by default, height is undefined until t1, at which case it’s 30, it will linearly decrease until t2, when it will be 15, and then increase to 45 by t3. Since height is not a per-instance attribute, having a polygon with a dynamic height will cause the entity system to automatically batch it separately from the static data.

The “catch-all” dynamic property is the CallbackProperty

var height = 0;

entity.polygon.height = new Cesium.CallbackProperty(function(time, result){

return height;

}, false);

CallbackProperty let’s you specify your own function to calculate the property value. The second parameter is a boolean indicating if the value is constant (so passing false makes the property dynamic). So in the above example, we can change height at our leisure and the entity system will automatically pick it up. It will also notice that the property is dynamic and so it will be batches separately.

There are quite a few other properties as well (TimeIntervalCollectionProperty is another useful one) but I won’t try and go into them here. I plan on writing a new tutorial that follows up Visualizing Spatial Data and concentrates on time-dynamic stuff as soon as 1.7 is out. In the mean time, I hope this sheds some light on the subject for you (even though I’m sure I glossed over a lot of the details).

Hope that helps,

Matt

---

<div class="post-metadata">

**Author:** ![Alexander\_Entin](https://avatars.discourse-cdn.com/v4/letter/a/71e660/32.png) [@Alexander\_Entin](https://community.cesium.com/u/Alexander_Entin)\
**Post date:** [February 26, 2015, 1:00pm UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/12 "2015-02-26T13:00:19Z")

</div>

So, I just need to be explicit on what’s dynamic and Entity API will apply batching and other optimizations as appropriate.

Thanks!

---

<div class="post-metadata">

**Author:** ![Matt\_Amato](https://sea2.discourse-cdn.com/cesium/user_avatar/community.cesium.com/matt_amato/32/1993_2.png) [@Matt\_Amato](https://community.cesium.com/u/Matt_Amato)\
**Post date:** [February 26, 2015, 2:02pm UTC](https://community.cesium.com/t/efficient-animation-moving-from-google-earth-to-cesium/2015/13 "2015-02-26T14:02:53Z")

</div>

Yes, exactly. The benefit of this approach is that when we further improve batching or optimize support for dynamic geometry; anyone using the Entity API gets those optimizations without having to change anything. I actually expect to implement a bunch of performance improvement for dynamic entity geometry for the 1.8 release (April 1st)
