Add existing to tracked
This commit is contained in:
+410
@@ -0,0 +1,410 @@
|
||||
import Check from "../../Core/Check.js";
|
||||
import defined from "../../Core/defined.js";
|
||||
import destroyObject from "../../Core/destroyObject.js";
|
||||
import DeveloperError from "../../Core/DeveloperError.js";
|
||||
|
||||
import ImageryConfiguration from "./ImageryConfiguration.js";
|
||||
import ModelPrimitiveImagery from "./ModelPrimitiveImagery.js";
|
||||
|
||||
/**
|
||||
* A class managing the draping of imagery on a <code>Model</code>.
|
||||
*
|
||||
* An instance of this class is created in the Model constructor. It will
|
||||
* create the data structures that carry the information that is required
|
||||
* for mapping imagery textures on model primitives.
|
||||
*
|
||||
* It offers two functions for managing the lifecycle of this draping process:
|
||||
*
|
||||
* The <code>update</code> function is called from the <code>Model.update</code>
|
||||
* function in each frame. It will create one <code>ModelPrimitiveImagery</code>
|
||||
* instance for each primitive that appears in the model, and call the
|
||||
* <code>update</code> function of these instances, respectively.
|
||||
*
|
||||
* The <code>ready</code> getter will be used to determine whether the
|
||||
* draping computations are done, and the update process of the <code>Model</code>
|
||||
* can continue, eventually causing the <code>model.ready</code> flag to
|
||||
* become <code>true</code>. The model imagery counts as "ready" when all
|
||||
* the imagery layers of the model are <code>ready</code>, and all the
|
||||
* <code>ModelPrimitiveImagery</code> instances are <code>ready</code>.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
class ModelImagery {
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param {Model} model The model
|
||||
* @throws {DeveloperError} If the model is not defined
|
||||
*/
|
||||
constructor(model) {
|
||||
//>>includeStart('debug', pragmas.debug);
|
||||
Check.defined("model", model);
|
||||
//>>includeEnd('debug');
|
||||
|
||||
/**
|
||||
* The model that this instance was created for.
|
||||
*
|
||||
* @type {Model}
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
this._model = model;
|
||||
|
||||
/**
|
||||
* One <code<ModelPrimitiveImagery</code> for each primitive
|
||||
* that appears in the model.
|
||||
*
|
||||
* Initially, this is <code>undefined</code>. When the <code>update</code>
|
||||
* function is called and all imagery layers that are associated with the
|
||||
* model are <code>ready</code>, this is initialized with one instance
|
||||
* of a <code>ModelPrimitiveImagery</code> per runtime primitive (i.e. one for
|
||||
* each <code>model.sceneGraph._runtimeNodes[n]._runtimePrimitives[p]</code>)
|
||||
*
|
||||
* @type {ModelPrimitiveImagery[]|undefined}
|
||||
* @private
|
||||
*/
|
||||
this._modelPrimitiveImageries = undefined;
|
||||
|
||||
/**
|
||||
* One <code>ImageryConfiguration</code> object for each <code>ImageryLayer</code>
|
||||
* that is associated with the model.
|
||||
*
|
||||
* This is used for determining whether the configuration (relevant property
|
||||
* values) of an imagery layer has been changed since the previous
|
||||
* <code>update</code> call, which should cause the draw commands of the
|
||||
* model to be reset.
|
||||
*
|
||||
* @type {ImageryConfiguration[]}
|
||||
* @private
|
||||
*/
|
||||
this._imageryConfigurations = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* The update function that is called from <code>Model.update</code> in
|
||||
* each frame.
|
||||
*
|
||||
* This checks whether the imagery layer objects that are associated
|
||||
* with the model are all <code>ready</code>. If they are not yet
|
||||
* ready, then nothing is done.
|
||||
*
|
||||
* Otherwise, this just calls the <code>update</code> function of
|
||||
* the <code>_modelPrimitiveImageries</code> (creating them if they had
|
||||
* not been created yet).
|
||||
*
|
||||
* @param {FrameState} frameState The frame state
|
||||
*/
|
||||
update(frameState) {
|
||||
//>>includeStart('debug', pragmas.debug);
|
||||
Check.defined("frameState", frameState);
|
||||
//>>includeEnd('debug');
|
||||
|
||||
if (!this._hasImagery) {
|
||||
// When there is no imagery, make sure to delete any model primitive
|
||||
// imageries that may previously have been created
|
||||
this._deleteModelPrimitiveImageries();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._allImageryLayersReady) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!defined(this._modelPrimitiveImageries)) {
|
||||
this._modelPrimitiveImageries = this._createModelPrimitiveImageries();
|
||||
}
|
||||
this._updateModelPrimitiveImageries(frameState);
|
||||
|
||||
this._checkForModifiedImageryConfigurations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the <code>ModelPrimitiveImagery</code> array that contains
|
||||
* one <code>ModelPrimitiveImagery</code> for each primitive that is
|
||||
* contained in the model.
|
||||
*
|
||||
* @returns {ModelPrimitiveImagery[]} The model primitive imageries
|
||||
* @private
|
||||
*/
|
||||
_createModelPrimitiveImageries() {
|
||||
const model = this._model;
|
||||
const runtimeNodesAndPrimitives = this._collectRuntimeNodesAndPrimitives();
|
||||
const modelPrimitiveImageries = [];
|
||||
const length = runtimeNodesAndPrimitives.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const runtimeNodeAndPrimitive = runtimeNodesAndPrimitives[i];
|
||||
const runtimeNode = runtimeNodeAndPrimitive.runtimeNode;
|
||||
const runtimePrimitive = runtimeNodeAndPrimitive.runtimePrimitive;
|
||||
const modelPrimitiveImagery = new ModelPrimitiveImagery(
|
||||
model,
|
||||
runtimeNode,
|
||||
runtimePrimitive,
|
||||
);
|
||||
runtimePrimitive.primitive.modelPrimitiveImagery = modelPrimitiveImagery;
|
||||
modelPrimitiveImageries.push(modelPrimitiveImagery);
|
||||
}
|
||||
return modelPrimitiveImageries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes all runtime nodes and primitives of the model.
|
||||
*
|
||||
* This is just the array that contains a
|
||||
* <code>{ runtimeNode, runtimePrimitive }</code>
|
||||
* for each
|
||||
* <code>model.sceneGraph._runtimeNodes[n]._runtimePrimitives[p]</code>.
|
||||
*
|
||||
* @returns {object[]} The runtime nodes and primitives
|
||||
* @private
|
||||
*/
|
||||
_collectRuntimeNodesAndPrimitives() {
|
||||
const model = this._model;
|
||||
const sceneGraph = model.sceneGraph;
|
||||
const runtimeNodes = sceneGraph._runtimeNodes;
|
||||
const runtimeNodesAndPrimitives = [];
|
||||
for (let i = 0; i < runtimeNodes.length; i++) {
|
||||
const runtimeNode = runtimeNodes[i];
|
||||
if (!defined(runtimeNode)) {
|
||||
continue;
|
||||
}
|
||||
for (let j = 0; j < runtimeNode.runtimePrimitives.length; j++) {
|
||||
const runtimePrimitive = runtimeNode.runtimePrimitives[j];
|
||||
runtimeNodesAndPrimitives.push({
|
||||
runtimeNode: runtimeNode,
|
||||
runtimePrimitive: runtimePrimitive,
|
||||
});
|
||||
}
|
||||
}
|
||||
return runtimeNodesAndPrimitives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Just calls <code>update</code> on each <code>ModelPrimitiveImagery</code>
|
||||
* as part of the <code>update</code> of this class.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_updateModelPrimitiveImageries(frameState) {
|
||||
//>>includeStart('debug', pragmas.debug);
|
||||
Check.defined("frameState", frameState);
|
||||
//>>includeEnd('debug');
|
||||
|
||||
if (!defined(this._modelPrimitiveImageries)) {
|
||||
throw new DeveloperError(
|
||||
"The modelPrimitiveImageries have not been created",
|
||||
);
|
||||
}
|
||||
|
||||
const modelPrimitiveImageries = this._modelPrimitiveImageries;
|
||||
const length = modelPrimitiveImageries.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const modelPrimitiveImagery = modelPrimitiveImageries[i];
|
||||
modelPrimitiveImagery.update(frameState);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy and delete all <code>ModelPrimitiveImagery</code> instances
|
||||
* if they already have been created.
|
||||
*/
|
||||
_deleteModelPrimitiveImageries() {
|
||||
const modelPrimitiveImageries = this._modelPrimitiveImageries;
|
||||
if (!defined(modelPrimitiveImageries)) {
|
||||
return;
|
||||
}
|
||||
const length = modelPrimitiveImageries.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const modelPrimitiveImagery = modelPrimitiveImageries[i];
|
||||
modelPrimitiveImagery.destroy();
|
||||
}
|
||||
delete this._modelPrimitiveImageries;
|
||||
this._model.resetDrawCommands();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this instance is "ready".
|
||||
*
|
||||
* This means that all imagery layers that are associated with the model
|
||||
* are <code>ready</code>, and all <code>ModelPrimitiveImagery</code>
|
||||
* instances are <code>ready</code>.
|
||||
*
|
||||
* When this is <code>true</code>, then the mapping computations are
|
||||
* complete and the structures containing the mapping information have
|
||||
* been initialized. Otherwise, subsequent calls to <code>update</code>
|
||||
* will perform the necessary computation until this getter eventually
|
||||
* returns <code>true</code>.
|
||||
*
|
||||
* @returns {boolean} Whether this instance is "ready"
|
||||
*/
|
||||
get ready() {
|
||||
if (!this._hasImagery) {
|
||||
return true;
|
||||
}
|
||||
if (!this._allImageryLayersReady) {
|
||||
return false;
|
||||
}
|
||||
if (!this._allModelPrimitiveImageriesReady) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the model has imagery layers associated with it.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
get _hasImagery() {
|
||||
const model = this._model;
|
||||
const imageryLayers = model.imageryLayers;
|
||||
return defined(imageryLayers) && imageryLayers.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether all imagery layers that are associated with the
|
||||
* model are <code>ready</code>.
|
||||
*
|
||||
* If the model does not have imagery, then this always returns
|
||||
* <code>true</code>. Otherwise, it returns whether each imagery
|
||||
* layer is <code>ready</code>.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
get _allImageryLayersReady() {
|
||||
if (!this._hasImagery) {
|
||||
return true;
|
||||
}
|
||||
const imageryLayers = this._model.imageryLayers;
|
||||
const length = imageryLayers.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const imageryLayer = imageryLayers.get(i);
|
||||
if (!imageryLayer.ready) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether all <code>ModelPrimitiveImagery</code> instances
|
||||
* are are <code>ready</code>.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
get _allModelPrimitiveImageriesReady() {
|
||||
const modelPrimitiveImageries = this._modelPrimitiveImageries;
|
||||
if (!defined(modelPrimitiveImageries)) {
|
||||
return false;
|
||||
}
|
||||
const length = modelPrimitiveImageries.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const modelPrimitiveImagery = modelPrimitiveImageries[i];
|
||||
if (!modelPrimitiveImagery.ready) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether any of the settings of any imagery layer (like alpha
|
||||
* or hue) has been changed since the last call to the <code>update</code>
|
||||
* function.
|
||||
*
|
||||
* If this is the case, the draw commands of the model will be reset.
|
||||
*/
|
||||
_checkForModifiedImageryConfigurations() {
|
||||
if (this._imageryConfigurationsModified()) {
|
||||
this._updateImageryConfigurations();
|
||||
const model = this._model;
|
||||
model.resetDrawCommands();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether any setting of an imagery layer (like alpha or hue) has
|
||||
* been changed since the last time the <code>ImageryConfiguration</code>
|
||||
* objects have been updated.
|
||||
*
|
||||
* @returns {boolean} Whether there was a modification
|
||||
*/
|
||||
_imageryConfigurationsModified() {
|
||||
const model = this._model;
|
||||
const imageryLayers = model.imageryLayers;
|
||||
const imageryConfigurations = this._imageryConfigurations;
|
||||
if (imageryLayers.length !== imageryConfigurations.length) {
|
||||
return true;
|
||||
}
|
||||
for (let i = 0; i < imageryLayers.length; i++) {
|
||||
const imageryLayer = imageryLayers.get(i);
|
||||
const imageryConfiguration = imageryConfigurations[i];
|
||||
|
||||
if (imageryLayer.show !== imageryConfiguration.show) {
|
||||
return true;
|
||||
}
|
||||
if (imageryLayer.alpha !== imageryConfiguration.alpha) {
|
||||
return true;
|
||||
}
|
||||
if (imageryLayer.brightness !== imageryConfiguration.brightness) {
|
||||
return true;
|
||||
}
|
||||
if (imageryLayer.contrast !== imageryConfiguration.contrast) {
|
||||
return true;
|
||||
}
|
||||
if (imageryLayer.hue !== imageryConfiguration.hue) {
|
||||
return true;
|
||||
}
|
||||
if (imageryLayer.saturation !== imageryConfiguration.saturation) {
|
||||
return true;
|
||||
}
|
||||
if (imageryLayer.gamma !== imageryConfiguration.gamma) {
|
||||
return true;
|
||||
}
|
||||
if (imageryLayer.colorToAlpha !== imageryConfiguration.colorToAlpha) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create one <code>ImageryConfiguration</code> object for each imagery
|
||||
* layer that appears in the model, and store them as the
|
||||
* <code>_imageryConfigurations</code>.
|
||||
*/
|
||||
_updateImageryConfigurations() {
|
||||
const model = this._model;
|
||||
const imageryLayers = model.imageryLayers;
|
||||
const imageryConfigurations = this._imageryConfigurations;
|
||||
imageryConfigurations.length = imageryLayers.length;
|
||||
for (let i = 0; i < imageryLayers.length; i++) {
|
||||
const imageryLayer = imageryLayers.get(i);
|
||||
imageryConfigurations[i] = new ImageryConfiguration(imageryLayer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this object was destroyed.
|
||||
*
|
||||
* If this object was destroyed, calling any function other than
|
||||
* <code>isDestroyed</code> will result in a {@link DeveloperError}.
|
||||
*
|
||||
* @returns {boolean} Whether this object was destroyed
|
||||
*/
|
||||
isDestroyed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys this object and all its resources.
|
||||
*/
|
||||
destroy() {
|
||||
if (this.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
this._deleteModelPrimitiveImageries();
|
||||
return destroyObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
export default ModelImagery;
|
||||
Reference in New Issue
Block a user