123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- import Check from "../../Core/Check.js";
- import defaultValue from "../../Core/defaultValue.js";
- import defined from "../../Core/defined.js";
- import Matrix4 from "../../Core/Matrix4.js";
- import ModelArticulationStage from "./ModelArticulationStage.js";
- /**
- * An in-memory representation of an articulation that affects nodes in the
- * {@link ModelSceneGraph}. This is defined in a model by the
- * <code>AGI_articulations</code> extension.
- *
- * @param {object} options An object containing the following options:
- * @param {ModelComponents.Articulation} options.articulation The articulation components from the 3D model.
- * @param {ModelSceneGraph} options.sceneGraph The scene graph this articulation belongs to.
- *
- * @alias ModelArticulation
- * @constructor
- *
- * @private
- */
- function ModelArticulation(options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const articulation = options.articulation;
- const sceneGraph = options.sceneGraph;
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.articulation", articulation);
- Check.typeOf.object("options.sceneGraph", sceneGraph);
- //>>includeEnd('debug');
- this._articulation = articulation;
- this._sceneGraph = sceneGraph;
- this._name = articulation.name;
- this._runtimeStages = [];
- this._runtimeStagesByName = {};
- // Will be populated as the runtime nodes are created
- this._runtimeNodes = [];
- // Set to true so that the first call to
- // ModelSceneGraph.applyArticulations will work.
- this._dirty = true;
- initialize(this);
- }
- Object.defineProperties(ModelArticulation.prototype, {
- /**
- * The internal articulation that this runtime articulation represents.
- *
- * @memberof ModelArticulation.prototype
- * @type {ModelComponents.Articulation}
- * @readonly
- *
- * @private
- */
- articulation: {
- get: function () {
- return this._articulation;
- },
- },
- /**
- * The scene graph that this articulation belongs to.
- *
- * @memberof ModelArticulation.prototype
- * @type {ModelSceneGraph}
- * @readonly
- *
- * @private
- */
- sceneGraph: {
- get: function () {
- return this._sceneGraph;
- },
- },
- /**
- * The name of this articulation.
- *
- * @memberof ModelArticulation.prototype
- * @type {string}
- * @readonly
- *
- * @private
- */
- name: {
- get: function () {
- return this._name;
- },
- },
- /**
- * The runtime stages that belong to this articulation.
- *
- * @memberof ModelArticulation.prototype
- * @type {ModelArticulationStage[]}
- * @readonly
- *
- * @private
- */
- runtimeStages: {
- get: function () {
- return this._runtimeStages;
- },
- },
- /**
- * The runtime nodes that are affected by this articulation.
- *
- * @memberof ModelArticulation.prototype
- * @type {ModelRuntimeNode[]}
- * @readonly
- *
- * @private
- */
- runtimeNodes: {
- get: function () {
- return this._runtimeNodes;
- },
- },
- });
- function initialize(runtimeArticulation) {
- const articulation = runtimeArticulation.articulation;
- const stages = articulation.stages;
- const length = stages.length;
- const runtimeStages = runtimeArticulation._runtimeStages;
- const runtimeStagesByName = runtimeArticulation._runtimeStagesByName;
- for (let i = 0; i < length; i++) {
- const stage = stages[i];
- const runtimeStage = new ModelArticulationStage({
- stage: stage,
- runtimeArticulation: runtimeArticulation,
- });
- // Store the stages in an array to preserve the order in which
- // they appeared in the 3D model.
- runtimeStages.push(runtimeStage);
- // Store the stages in a dictionary for retrieval by name.
- const stageName = stage.name;
- runtimeStagesByName[stageName] = runtimeStage;
- }
- }
- /**
- * Sets the current value of an articulation stage.
- *
- * @param {string} stageName The name of the articulation stage.
- * @param {number} value The numeric value of this stage of the articulation.
- *
- * @private
- */
- ModelArticulation.prototype.setArticulationStage = function (stageName, value) {
- const stage = this._runtimeStagesByName[stageName];
- if (defined(stage)) {
- stage.currentValue = value;
- }
- };
- const scratchArticulationMatrix = new Matrix4();
- const scratchNodeMatrix = new Matrix4();
- /**
- * Applies the chain of articulation stages to the transform of each node that
- * participates in the articulation. This only recomputes the node transforms
- * if any stage in the articulation has been modified.
- * <p>
- * Note that this will overwrite any existing transformations on participating
- * nodes.
- * </p>
- *
- * @private
- */
- ModelArticulation.prototype.apply = function () {
- if (!this._dirty) {
- return;
- }
- this._dirty = false;
- let articulationMatrix = Matrix4.clone(
- Matrix4.IDENTITY,
- scratchArticulationMatrix
- );
- let i;
- const stages = this._runtimeStages;
- const stagesLength = stages.length;
- // Compute the result of the articulation stages...
- for (i = 0; i < stagesLength; i++) {
- const stage = stages[i];
- articulationMatrix = stage.applyStageToMatrix(articulationMatrix);
- }
- // ...then apply it to the transforms of the affected nodes.
- const nodes = this._runtimeNodes;
- const nodesLength = nodes.length;
- for (i = 0; i < nodesLength; i++) {
- const node = nodes[i];
- const transform = Matrix4.multiplyTransformation(
- node.originalTransform,
- articulationMatrix,
- scratchNodeMatrix
- );
- node.transform = transform;
- }
- };
- export default ModelArticulation;
|