Here are the applicable parts of the prototype. Just for a general overview:
load() - adds the event handling for pre/post rendering. Grabs the JSON encoded data, which is just a single data point moving east by a fraction of a degree in each time step.
displayTimeMoment() - performs the swapping in/out of time frames
storeTimeMoment() - actually builds the primitive to display a time frame.
Currently I'm sending the data to Cesium using JSON, but I think I'm going to move to directly importing it with a .Net->JavaScript conversion function I found.
I'm still just prototyping and trying to figure out what Cesium's best practices are now while I'm using a very small and simple example. (so I'm more than happy to listen to suggestions in general)
The big issue in the code below that I'm really confused with is that the rendering can display time frames out of order even though I set asynchronous to false and then even put a mutex (named 'canModifyData') in the pre/post rendering events to make sure I couldnt load time frame 'x+1' until 'x' finishes.
////////////////////////////////////////////////////////////
var load = function (url) {
if (!Cesium.defined(url)) {
throw new Cesium.DeveloperError('url is required.');
}
//Use 'when' to load the URL into a json object
//and then process is with the `load` function.
return Cesium.when(Cesium.loadJson(url), function (json)
{
timeSeriesData = json.data;
for (var i = 0; i < timeSeriesData.length; i++) {
var timeMomentData = timeSeriesData[i].attributes;
var timeMoment = timeMomentData.momentData;
var time = timeMomentData.Time;
storeTimeMoment(time, timeMoment, scene);
}
startAnimation();
//Subscribe to the preRender. Remove old frames, Set new pending frames to current.
scene.preRender.addEventListener(function () {
canModifyData = false;
//Remove the old cylinder once the new one is ready.
if (Cesium.defined(newPrimitive) && newPrimitive.length > 0)
{
var newPrimitiveReady = true;
for (var i = 0; i < newPrimitive.length; i++)
{
if (!newPrimitive._state === Cesium.PrimitiveState.COMPLETE)
{
newPrimitiveReady = false;
break;
}
}
//Remove old primitives if we can replace with new ones.
if (Cesium.defined(currentPrimitive) && newPrimitiveReady)
{
scene.primitives.remove(currentPrimitive);
}
currentPrimitive = newPrimitive;
newPrimitive = undefined;
}
});
//Subscribe to the postRender. Stop new rendering until this has fired.
scene.postRender.addEventListener(function () {
canModifyData = true;
});
}).otherwise(function (error) {
return Cesium.when.reject(error);
});
};
//Handles one moment of time series data.
var storeTimeMoment = function (time, timeMoment)
{
var instances = ;
//Add each data point to the time moment
for (var j = 0; j < timeMoment.length; j++) {
var point3d = timeMoment[j];
circleInstance = new Cesium.GeometryInstance({
geometry: new Cesium.CircleGeometry({
center: Cesium.Cartesian3.fromDegrees(point3d.x, point3d.y),
radius: 2500.0,
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
}),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 0.0, 0.0, 0.5))
},
id: 'circle'
});
instances.push(circleInstance);
}
primitive = new Cesium.Primitive({
geometryInstances: instances,
appearance: new Cesium.PerInstanceColorAppearance({
translucent: false,
closed: true
}),
vertexCacheOptimize: true,
allowPicking: true,
releaseGeometryInstances: false,
asynchronous: false
});
bufferedTimes.push(time);
bufferedTimeSeries.push(primitive);
};
//Removes all "non current" (pending) primitives. Adds new time step's primitives to Cesium.
var displayTimeMoment = function ()
{
//Stop if no data or at end of data.
if (bufferedTimeSeries.length == 0 || animationIndex >= bufferedTimeSeries.length)
{
stopAnimation();
return;
}
//remove any currently pending primitive display
if (Cesium.defined(newPrimitive))
{
scene.primitives.remove(newPrimitive);
}
//Add new primitives to cesium.
newPrimitive = bufferedTimeSeries[animationIndex];
scene.primitives.add(newPrimitive);
animationIndex++;
};
var startAnimation = function () {
if (!running) {
animationIndex = 0;
canModifyData = true;
clock.shouldAnimate = true;
running = true;
removeCallback = eventHelper.add(clock.onTick, onTick);
}
};
var stopAnimation = function () {
if (running) {
canModifyData = false;
removeCallback();
clock.shouldAnimate = false;
running = false;
}
};
var onTick = function () {
if (canModifyData) {
displayTimeMoment();
}
};