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

Visualizer cleanup #1653

Merged
merged 14 commits into from
Apr 29, 2014
10 changes: 10 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ Beta Releases
* Renamed and moved `Scene.primitives.centralBody` moved to `Scene.globe`.
* Removed `CesiumWidget.centralBody` and `Viewer.centralBody`. Use `Scene.globe`.
* Renamed `CentralBody` to `Globe`.
* Refactored visualizers, removing `setDynamicObjectCollection`, `getDynamicObjectCollection`, `getScene`, and `removeAllPrimitives` which are all superfluous after the introduction of `DataSourceDisplay`. The affected classes are:
* `DynamicBillboardVisualizer`
* `DynamicConeVisualizerUsingCustomSensor`
* `DynamicLabelVisualizer`
* `DynamicModelVisualizer`
* `DynamicPathVisualizer`
* `DynamicPointVisualizer`
* `DynamicPyramidVisualizer`
* `DynamicVectorVisualizer`
* `GeometryVisualizer`
* Renamed Extent to Rectangle
* `Extent` -> `Rectangle`
* `ExtentGeometry` -> `RectangleGeomtry`
Expand Down
134 changes: 26 additions & 108 deletions Source/DynamicScene/DynamicBillboardVisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ define([
TextureAtlasBuilder) {
"use strict";

//Callback to create a callback so that we close over all of the proper values.
function textureReady(dynamicObject, billboardCollection, textureValue) {
return function(imageIndex) {
//By the time the texture was loaded, the billboard might already be
Expand All @@ -41,83 +40,41 @@ define([
}

/**
* A DynamicObject visualizer which maps the DynamicBillboard instance
* in DynamicObject.billboard to a Billboard primitive.
* A {@link Visualizer} which maps {@link DynamicObject#billboard} to a {@link Billboard}.
* @alias DynamicBillboardVisualizer
* @constructor
*
* @param {Scene} scene The scene the primitives will be rendered in.
* @param {DynamicObjectCollection} [dynamicObjectCollection] The dynamicObjectCollection to visualize.
*
* @see DynamicBillboard
* @see DynamicObject
* @see DynamicObjectCollection
* @see CompositeDynamicObjectCollection
* @see DynamicConeVisualizer
* @see DynamicConeVisualizerUsingCustomSensor
* @see DynamicLabelVisualizer
* @see DynamicPointVisualizer
* @see DynamicPyramidVisualizer
* @param {DynamicObjectCollection} dynamicObjectCollection The dynamicObjectCollection to visualize.
*/
var DynamicBillboardVisualizer = function(scene, dynamicObjectCollection) {
//>>includeStart('debug', pragmas.debug);
if (!defined(scene)) {
throw new DeveloperError('scene is required.');
}
if (!defined(dynamicObjectCollection)) {
throw new DeveloperError('dynamicObjectCollection is required.');
}
//>>includeEnd('debug');

this._scene = scene;
this._unusedIndexes = [];
this._dynamicObjectCollection = undefined;

var billboardCollection = this._billboardCollection = new BillboardCollection();
var atlas = this._textureAtlas = scene.createTextureAtlas();
this._textureAtlasBuilder = new TextureAtlasBuilder(atlas);
var billboardCollection = new BillboardCollection();
var atlas = scene.createTextureAtlas();
billboardCollection.textureAtlas = atlas;
scene.primitives.add(billboardCollection);
this.setDynamicObjectCollection(dynamicObjectCollection);
};
dynamicObjectCollection.collectionChanged.addEventListener(DynamicBillboardVisualizer.prototype._onObjectsRemoved, this);

/**
* Returns the scene being used by this visualizer.
*
* @returns {Scene} The scene being used by this visualizer.
*/
DynamicBillboardVisualizer.prototype.getScene = function() {
return this._scene;
};

/**
* Gets the DynamicObjectCollection being visualized.
*
* @returns {DynamicObjectCollection} The DynamicObjectCollection being visualized.
*/
DynamicBillboardVisualizer.prototype.getDynamicObjectCollection = function() {
return this._dynamicObjectCollection;
};

/**
* Sets the DynamicObjectCollection to visualize.
*
* @param dynamicObjectCollection The DynamicObjectCollection to visualizer.
*/
DynamicBillboardVisualizer.prototype.setDynamicObjectCollection = function(dynamicObjectCollection) {
var oldCollection = this._dynamicObjectCollection;
if (oldCollection !== dynamicObjectCollection) {
if (defined(oldCollection)) {
oldCollection.collectionChanged.removeEventListener(DynamicBillboardVisualizer.prototype._onObjectsRemoved, this);
this.removeAllPrimitives();
}
this._dynamicObjectCollection = dynamicObjectCollection;
if (defined(dynamicObjectCollection)) {
dynamicObjectCollection.collectionChanged.addEventListener(DynamicBillboardVisualizer.prototype._onObjectsRemoved, this);
}
}
this._scene = scene;
this._unusedIndexes = [];
this._textureAtlas = atlas;
this._billboardCollection = billboardCollection;
this._textureAtlasBuilder = new TextureAtlasBuilder(atlas);
this._dynamicObjectCollection = dynamicObjectCollection;
};

/**
* Updates all of the primitives created by this visualizer to match their
* Updates the primitives created by this visualizer to match their
* DynamicObject counterpart at the given time.
* @memberof DynamicBillboardVisualizer
*
* @param {JulianDate} time The time to update to.
* @returns {Boolean} This function always returns true.
Expand All @@ -131,64 +88,26 @@ define([

if (defined(this._dynamicObjectCollection)) {
var dynamicObjects = this._dynamicObjectCollection.getObjects();
for ( var i = 0, len = dynamicObjects.length; i < len; i++) {
for (var i = 0, len = dynamicObjects.length; i < len; i++) {
updateObject(this, time, dynamicObjects[i]);
}
}
return true;
};

/**
* Removes all primitives from the scene.
*/
DynamicBillboardVisualizer.prototype.removeAllPrimitives = function() {
if (defined(this._dynamicObjectCollection)) {
this._unusedIndexes = [];
this._billboardCollection.removeAll();
var dynamicObjects = this._dynamicObjectCollection.getObjects();
for ( var i = dynamicObjects.length - 1; i > -1; i--) {
dynamicObjects[i]._billboardVisualizerIndex = undefined;
}
}
};

/**
* Returns true if this object was destroyed; otherwise, false.
* <br /><br />
* If this object was destroyed, it should not be used; calling any function other than
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
*
* Removes and destroys all primitives created by this instance.
* @memberof DynamicBillboardVisualizer
*
* @returns {Boolean} True if this object was destroyed; otherwise, false.
*
* @see DynamicBillboardVisualizer#destroy
*/
DynamicBillboardVisualizer.prototype.isDestroyed = function() {
return false;
};

/**
* Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
* release of WebGL resources, instead of relying on the garbage collector to destroy this object.
* <br /><br />
* Once an object is destroyed, it should not be used; calling any function other than
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
* assign the return value (<code>undefined</code>) to the object as done in the example.
*
* @memberof DynamicBillboardVisualizer
*
* @returns {undefined}
*
* @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
*
* @see DynamicBillboardVisualizer#isDestroyed
*
* @example
* visualizer = visualizer && visualizer.destroy();
*/
DynamicBillboardVisualizer.prototype.destroy = function() {
this.setDynamicObjectCollection(undefined);
var dynamicObjectCollection = this._dynamicObjectCollection;
dynamicObjectCollection.collectionChanged.removeEventListener(DynamicBillboardVisualizer.prototype._onObjectsRemoved, this);

var dynamicObjects = dynamicObjectCollection.getObjects();
var length = dynamicObjects.length;
for (var i = 0; i < length; i++) {
dynamicObjects[i]._billboardVisualizerIndex = undefined;
}
this._scene.primitives.remove(this._billboardCollection);
return destroyObject(this);
};
Expand Down Expand Up @@ -247,7 +166,6 @@ define([
billboard._visualizerUrl = undefined;
billboard._visualizerTextureAvailable = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

You should keep isDestroyed throughout since it's part of the destroy "interface".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I got rid of it because Visualizers are not general purpose objects and their lifetime is completely managed by DataSourceDisplay. I could have renamed destroy to something else, but I didn't see the point. Adding isDestroyed here feels like consistency for the sake of consistency taken to far with no real benefit.

Now that's I've said my peace, if I didn't convince you I can put it back; but it just feels pointless.

Copy link
Contributor

Choose a reason for hiding this comment

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

Not convinced. These would be the first and only non-private classes in Cesium to break convention, and the private ones should be fixed. Imagine we have a Destroyable interface with those two methods. Maybe we should make one for documentation purposes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I'll put them back, but I think we really need to re-think our object lifetime strategy on the whole anyway.


// CZML_TODO Determine official defaults
billboard.color = Color.WHITE;
billboard.eyeOffset = Cartesian3.ZERO;
billboard.pixelOffset = Cartesian2.ZERO;
Expand Down
135 changes: 24 additions & 111 deletions Source/DynamicScene/DynamicConeVisualizerUsingCustomSensor.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ define([
MaterialProperty) {
"use strict";

//CZML_TODO DynamicConeVisualizerUsingCustomSensor is a temporary workaround
//because ComplexConicSensor has major performance issues. As soon as
//ComplexConicSensor is working, this class can be deleted and
//DynamicConeVisualizer is a drop in replacement that already does things
//"the right way".

var matrix3Scratch = new Matrix3();

function assignSpherical(index, array, clock, cone) {
Expand Down Expand Up @@ -77,79 +71,36 @@ define([
}

/**
* A DynamicObject visualizer which maps the DynamicCone instance
* in DynamicObject.cone to a CustomSensor primitive.
* A {@link Visualizer} which maps {@link DynamicObject#cone} to a {@link CustomSensor}.
* @alias DynamicConeVisualizerUsingCustomSensor
* @constructor
*
* @param {Scene} scene The scene the primitives will be rendered in.
* @param {DynamicObjectCollection} [dynamicObjectCollection] The dynamicObjectCollection to visualize.
*
* @see DynamicCone
* @see DynamicObject
* @see DynamicObjectCollection
* @see CompositeDynamicObjectCollection
* @see DynamicBillboardVisualizer
* @see DynamicConeVisualizer
* @see DynamicLabelVisualizer
* @see DynamicPointVisualizer
* @see DynamicPyramidVisualizer
* @param {DynamicObjectCollection} dynamicObjectCollection The dynamicObjectCollection to visualize.
*/
var DynamicConeVisualizerUsingCustomSensor = function(scene, dynamicObjectCollection) {
//>>includeStart('debug', pragmas.debug);
if (!defined(scene)) {
throw new DeveloperError('scene is required.');
}
if (!defined(dynamicObjectCollection)) {
throw new DeveloperError('dynamicObjectCollection is required.');
}
//>>includeEnd('debug');

dynamicObjectCollection.collectionChanged.addEventListener(DynamicConeVisualizerUsingCustomSensor.prototype._onObjectsRemoved, this);

this._scene = scene;
this._unusedIndexes = [];
this._primitives = scene.primitives;
this._coneCollection = [];
this._dynamicObjectCollection = undefined;
this.setDynamicObjectCollection(dynamicObjectCollection);
};

/**
* Returns the scene being used by this visualizer.
*
* @returns {Scene} The scene being used by this visualizer.
*/
DynamicConeVisualizerUsingCustomSensor.prototype.getScene = function() {
return this._scene;
};

/**
* Gets the DynamicObjectCollection being visualized.
*
* @returns {DynamicObjectCollection} The DynamicObjectCollection being visualized.
*/
DynamicConeVisualizerUsingCustomSensor.prototype.getDynamicObjectCollection = function() {
return this._dynamicObjectCollection;
};

/**
* Sets the DynamicObjectCollection to visualize.
*
* @param dynamicObjectCollection The DynamicObjectCollection to visualizer.
*/
DynamicConeVisualizerUsingCustomSensor.prototype.setDynamicObjectCollection = function(dynamicObjectCollection) {
var oldCollection = this._dynamicObjectCollection;
if (oldCollection !== dynamicObjectCollection) {
if (defined(oldCollection)) {
oldCollection.collectionChanged.removeEventListener(DynamicConeVisualizerUsingCustomSensor.prototype._onObjectsRemoved, this);
this.removeAllPrimitives();
}
this._dynamicObjectCollection = dynamicObjectCollection;
if (defined(dynamicObjectCollection)) {
dynamicObjectCollection.collectionChanged.addEventListener(DynamicConeVisualizerUsingCustomSensor.prototype._onObjectsRemoved, this);
}
}
this._dynamicObjectCollection = dynamicObjectCollection;
};

/**
* Updates all of the primitives created by this visualizer to match their
* Updates the primitives created by this visualizer to match their
* DynamicObject counterpart at the given time.
* @memberof DynamicLabelVisualizer
Copy link
Contributor

Choose a reason for hiding this comment

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

should be DynamicConeVisualizerUsingCustomSensor. Same for destroy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thought I caught all of these. Thanks.

*
* @param {JulianDate} time The time to update to.
* @returns {Boolean} This function always returns true.
Expand All @@ -171,62 +122,25 @@ define([
};

/**
* Removes all primitives from the scene.
* Removes and destroys all primitives created by this instance.
* @memberof DynamicLabelVisualizer
*/
DynamicConeVisualizerUsingCustomSensor.prototype.removeAllPrimitives = function() {
var i, len;
for (i = 0, len = this._coneCollection.length; i < len; i++) {
this._primitives.remove(this._coneCollection[i]);
DynamicConeVisualizerUsingCustomSensor.prototype.destroy = function() {
var dynamicObjectCollection = this._dynamicObjectCollection;
dynamicObjectCollection.collectionChanged.removeEventListener(DynamicConeVisualizerUsingCustomSensor.prototype._onObjectsRemoved, this);

var i;
var dynamicObjects = dynamicObjectCollection.getObjects();
var length = dynamicObjects.length;
for (i = 0; i < length; i++) {
dynamicObjects[i]._coneVisualizerIndex = undefined;
}

if (defined(this._dynamicObjectCollection)) {
var dynamicObjects = this._dynamicObjectCollection.getObjects();
for (i = dynamicObjects.length - 1; i > -1; i--) {
dynamicObjects[i]._coneVisualizerIndex = undefined;
}
length = this._coneCollection.length;
for (i = 0; i < length; i++) {
this._primitives.remove(this._coneCollection[i]);
}

this._unusedIndexes = [];
this._coneCollection = [];
};

/**
* Returns true if this object was destroyed; otherwise, false.
* <br /><br />
* If this object was destroyed, it should not be used; calling any function other than
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
*
* @memberof DynamicConeVisualizerUsingCustomSensor
*
* @returns {Boolean} True if this object was destroyed; otherwise, false.
*
* @see DynamicConeVisualizerUsingCustomSensor#destroy
*/
DynamicConeVisualizerUsingCustomSensor.prototype.isDestroyed = function() {
return false;
};

/**
* Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
* release of WebGL resources, instead of relying on the garbage collector to destroy this object.
* <br /><br />
* Once an object is destroyed, it should not be used; calling any function other than
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
* assign the return value (<code>undefined</code>) to the object as done in the example.
*
* @memberof DynamicConeVisualizerUsingCustomSensor
*
* @returns {undefined}
*
* @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
*
* @see DynamicConeVisualizerUsingCustomSensor#isDestroyed
*
* @example
* visualizer = visualizer && visualizer.destroy();
*/
DynamicConeVisualizerUsingCustomSensor.prototype.destroy = function() {
this.setDynamicObjectCollection(undefined);
return destroyObject(this);
};

Expand Down Expand Up @@ -280,7 +194,6 @@ define([
dynamicObject._coneVisualizerIndex = coneVisualizerIndex;
cone.id = dynamicObject;

// CZML_TODO Determine official defaults
cone.material = Material.fromType(Material.ColorType);
cone.intersectionColor = Color.clone(Color.YELLOW);
cone.intersectionWidth = 5.0;
Expand Down
Loading