@cesium/engine
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
121 lines (107 loc) • 3.35 kB
JavaScript
import Matrix4 from "../../Core/Matrix4.js";
import ModelUtility from "./ModelUtility.js";
import SceneMode from "../SceneMode.js";
/**
* The model matrix update stage is responsible for updating the model matrices and bounding volumes of the draw commands.
*
* @namespace ModelMatrixUpdateStage
*
* @private
*/
const ModelMatrixUpdateStage = {};
ModelMatrixUpdateStage.name = "ModelMatrixUpdateStage"; // Helps with debugging
/**
* Processes a runtime node. This modifies the following parts of the scene graph and draw commands:
* <ul>
* <li>updates the transforms the children of any nodes with a dirty transform</li>
* <li>updates the model matrix of each draw command in each primitive of the the dirty nodes and their children</li>
* <li>updates the bounding volume of each draw command in each primitive of the the dirty nodes and their children</li>
* </ul>
*
* @param {ModelRuntimeNode} runtimeNode
* @param {ModelSceneGraph} sceneGraph
* @param {FrameState} frameState
*
* @private
*/
ModelMatrixUpdateStage.update = function (runtimeNode, sceneGraph, frameState) {
// Skip the update stage if the model is being projected to 2D
const use2D = frameState.mode !== SceneMode.SCENE3D;
if (use2D && sceneGraph._model._projectTo2D) {
return;
}
if (runtimeNode._transformDirty) {
const modelMatrix = use2D
? sceneGraph._computedModelMatrix2D
: sceneGraph._computedModelMatrix;
updateRuntimeNode(
runtimeNode,
sceneGraph,
modelMatrix,
runtimeNode.transformToRoot,
);
runtimeNode._transformDirty = false;
}
};
/**
* Update the modelMatrix and cullFrace of the given draw command.
*
* @private
*/
function updateDrawCommand(drawCommand, modelMatrix, transformToRoot) {
drawCommand.modelMatrix = Matrix4.multiplyTransformation(
modelMatrix,
transformToRoot,
drawCommand.modelMatrix,
);
drawCommand.cullFace = ModelUtility.getCullFace(
drawCommand.modelMatrix,
drawCommand.primitiveType,
);
}
/**
* Recursively update all child runtime nodes and their runtime primitives.
*
* @private
*/
function updateRuntimeNode(
runtimeNode,
sceneGraph,
modelMatrix,
transformToRoot,
) {
let i;
// Apply the current node's transform to the end of the chain
transformToRoot = Matrix4.multiplyTransformation(
transformToRoot,
runtimeNode.transform,
new Matrix4(),
);
runtimeNode.updateComputedTransform();
const primitivesLength = runtimeNode.runtimePrimitives.length;
for (i = 0; i < primitivesLength; i++) {
const runtimePrimitive = runtimeNode.runtimePrimitives[i];
updateDrawCommand(
runtimePrimitive.drawCommand,
modelMatrix,
transformToRoot,
);
}
const childrenLength = runtimeNode.children.length;
for (i = 0; i < childrenLength; i++) {
const childRuntimeNode = sceneGraph._runtimeNodes[runtimeNode.children[i]];
// Update transformToRoot to accommodate changes in the transforms of this node and its ancestors
childRuntimeNode._transformToRoot = Matrix4.clone(
transformToRoot,
childRuntimeNode._transformToRoot,
);
updateRuntimeNode(
childRuntimeNode,
sceneGraph,
modelMatrix,
transformToRoot,
);
childRuntimeNode._transformDirty = false;
}
}
export default ModelMatrixUpdateStage;