The function in question, calls _freeze()
on each mesh
public freezeActiveMeshes(skipEvaluateActiveMeshes = false): Scene {
this.executeWhenReady(() => {
if (!this.activeCamera) {
return;
}
if (!this._frustumPlanes) {
this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix());
}
this._evaluateActiveMeshes();
this._activeMeshesFrozen = true;
this._skipEvaluateActiveMeshesCompletely = skipEvaluateActiveMeshes;
for (var index = 0; index < this._activeMeshes.length; index++) {
this._activeMeshes.data[index]._freeze();
}
});
return this;
}
At the AbstractMesh
level, _freeze()
does not do anything:
public _freeze() {
// Do nothing
}
It is over ridden in Mesh
, but it does not really do anything, but set some values for instances. I think this has something to do with materials??
public _freeze() {
if (!this.subMeshes) {
return;
}
// Prepare batches
for (var index = 0; index < this.subMeshes.length; index++) {
this._getInstancesRenderList(index);
}
this._effectiveMaterial = null;
this._instanceDataStorage.isFrozen = true;
}
It should call freezeWorldMatrix() on TransformNode:
public freezeWorldMatrix(newWorldMatrix: Nullable<Matrix> = null): TransformNode {
if (newWorldMatrix) {
this._worldMatrix = newWorldMatrix;
} else {
this._isWorldMatrixFrozen = false; // no guarantee world is not already frozen, switch off temporarily
this.computeWorldMatrix(true);
}
this._isDirty = false;
this._isWorldMatrixFrozen = true;
return this;
}
The test I used to cause me to go through this is that after freezeActiveMeshes()
, after scene.render()
has run at least once, is myMesh.isWorldMatrixFrozen
still returns false.
Hi @JCPalmer
I think there’s been a misunderstanding!
scene.freezeActiveMeshes() will stop the evaluation of which meshes are “active” /in frustum (camera view) and thus which meshes should be included when doing rendering calculations, etc.
mesh.freezeWorldMatrix() is the correct function if you wish to freeze the world matrix of a mesh.
something like this should do the job for all meshes:
scene.meshes.forEach(m => { m.freezeWorldMatrix() } );
2 Likes
To add to @aWeirdo, nothing stop you to update mesh position/translation/scale even when the active mesh list has been frozen.
Freezing the creation of the active mesh list and freezing the mesh world matrices are two separate process.
Ok, I can freeze all myself, which is sort of ironic in that the scene I am just starting actual assembly of, has a massive amount of animation. Since I have a formal animation sub-system, I know just what frames & which meshes need to be computed below application level. Also helps that I supporting root bone translation / rotation, so meshes with armatures never move / rotate.
While 95% of the meshes will always evaluate as active, some will not. Will just set those to alwaysSelectAsActiveMesh
to avoid a wasteful isInFrustum
check.
So what does, Mesh._freeze()
accomplish?
In addition to “What does the undocumented mesh._freeze() / mesh._freeze()
do?” to close this topic out, just a note for anyone else trying to manage all worldmatrix computation themselves.
Use freezeWorldMatrix()
to accomplish a one time calc, not computeWorldMatrix(true)
. Reason is in the first few lines:
public computeWorldMatrix(force?: boolean): Matrix {
if (this._isWorldMatrixFrozen && !this._isDirty) {
return this._worldMatrix;
}
. . .
}
Even though you indicated true
for force
, it is not consulted for some reason till later (don’t think I did that). You need to rely on _isDirty
being set to true
. I was setting via LerpToRef
, and this did not “dirty it”. You can also manually set, but if using typescript & not in a mesh subclass, you must set _isDirty
indirectly.
I wrote the part of freezeWorldMatrix()
which does the one time “final” set. It temporarily turns off the frozen switch inside. Cleaner than doin it yourself.
Also, what about the kids? This is my final code (with the less desirable way in comments):
if ((this._doingRotation || this._doingMovePOV) && this._isMesh && (<BABYLON.AbstractMesh> this._node).isWorldMatrixFrozen) {
console.log('computing matrix');
// (<BABYLON.AbstractMesh> this._node)["_isDirty"] = true;
// (<BABYLON.AbstractMesh> this._node).computeWorldMatrix(true);
(<BABYLON.AbstractMesh> this._node).freezeWorldMatrix();
for (const kid of this._node.getChildMeshes() ) {
if (kid.isWorldMatrixFrozen || TimelineControl.computeWrldMatSkipped) {
// kid["_isDirty"] = true;
// kid.computeWorldMatrix(true);
kid.freezeWorldMatrix();
}
}
}
1 Like