@onerjs/core 8.42.9 → 8.43.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ import { VertexData } from "../mesh.vertexData.js";
4
4
  import { Matrix, TmpVectors, Vector2, Vector3 } from "../../Maths/math.vector.js";
5
5
  import { Quaternion } from "../../Maths/math.vector.js";
6
6
  import { Logger } from "../../Misc/logger.js";
7
- import { GaussianSplattingMaterial, GaussianSplattingMaxPartCount } from "../../Materials/GaussianSplatting/gaussianSplattingMaterial.js";
7
+ import { GaussianSplattingMaterial, GetGaussianSplattingMaxPartCount } from "../../Materials/GaussianSplatting/gaussianSplattingMaterial.js";
8
8
  import { RawTexture } from "../../Materials/Textures/rawTexture.js";
9
9
 
10
10
  import "../thinInstanceMesh.js";
@@ -12,7 +12,6 @@ import { ToHalfFloat } from "../../Misc/textureTools.js";
12
12
  import { Scalar } from "../../Maths/math.scalar.js";
13
13
  import { runCoroutineSync, runCoroutineAsync, createYieldingScheduler } from "../../Misc/coroutine.js";
14
14
  import { EngineStore } from "../../Engines/engineStore.js";
15
- import { Camera } from "../../Cameras/camera.js";
16
15
  import { ImportMeshAsync } from "../../Loading/sceneLoader.js";
17
16
  import { GaussianSplattingPartProxyMesh } from "./gaussianSplattingPartProxyMesh.js";
18
17
  const IsNative = typeof _native !== "undefined";
@@ -332,7 +331,6 @@ export class GaussianSplattingMesh extends Mesh {
332
331
  this._vertexCount = 0;
333
332
  this._worker = null;
334
333
  this._modelViewProjectionMatrix = Matrix.Identity();
335
- this._viewProjectionMatrix = Matrix.Identity();
336
334
  this._canPostToWorker = true;
337
335
  this._readyToDisplay = false;
338
336
  this._covariancesATexture = null;
@@ -429,10 +427,10 @@ export class GaussianSplattingMesh extends Mesh {
429
427
  const cameraProjectionMatrix = camera.getProjectionMatrix();
430
428
  const cameraViewProjectionMatrix = TmpVectors.Matrix[0];
431
429
  cameraViewMatrix.multiplyToRef(cameraProjectionMatrix, cameraViewProjectionMatrix);
432
- this._viewProjectionMatrix.copyFrom(cameraViewProjectionMatrix);
430
+ const modelMatrix = this.getWorldMatrix();
433
431
  const modelViewMatrix = TmpVectors.Matrix[1];
434
- this.getWorldMatrix().multiplyToRef(cameraViewMatrix, modelViewMatrix);
435
- modelViewMatrix.multiplyToRef(cameraProjectionMatrix, this._modelViewProjectionMatrix);
432
+ modelMatrix.multiplyToRef(cameraViewMatrix, modelViewMatrix);
433
+ modelMatrix.multiplyToRef(cameraViewProjectionMatrix, this._modelViewProjectionMatrix);
436
434
  // return vector used to compute distance to camera
437
435
  const localDirection = TmpVectors.Vector3[1];
438
436
  localDirection.set(modelViewMatrix.m[2], modelViewMatrix.m[6], modelViewMatrix.m[10]);
@@ -470,6 +468,15 @@ export class GaussianSplattingMesh extends Mesh {
470
468
  cameraMesh.reservedDataStore = { hidden: true };
471
469
  cameraMesh.setEnabled(false);
472
470
  cameraMesh.material = this.material;
471
+ if (cameraMesh.material && cameraMesh.material instanceof GaussianSplattingMaterial) {
472
+ const gsMaterial = cameraMesh.material;
473
+ // GaussianSplattingMaterial source mesh may not have been set yet.
474
+ // This happens for cloned resources from asset containers for instance,
475
+ // where material is cloned before mesh.
476
+ if (!gsMaterial.getSourceMesh()) {
477
+ gsMaterial.setSourceMesh(this);
478
+ }
479
+ }
473
480
  GaussianSplattingMesh._MakeSplatGeometryForMesh(cameraMesh);
474
481
  const newViewInfos = {
475
482
  camera: camera,
@@ -497,12 +504,13 @@ export class GaussianSplattingMesh extends Mesh {
497
504
  cameraViewInfos.frameIdLastUpdate = frameId;
498
505
  this._canPostToWorker = false;
499
506
  if (this._worker) {
507
+ const cameraViewMatrix = camera.getViewMatrix();
500
508
  this._worker.postMessage({
501
- modelViewProjection: this._modelViewProjectionMatrix.m,
502
- viewProjection: this._viewProjectionMatrix.m,
509
+ worldMatrix: this.getWorldMatrix().m,
510
+ cameraForward: [cameraViewMatrix.m[2], cameraViewMatrix.m[6], cameraViewMatrix.m[10]],
511
+ cameraPosition: [camera.globalPosition.x, camera.globalPosition.y, camera.globalPosition.z],
503
512
  depthMix: this._depthMix,
504
513
  cameraId: camera.uniqueId,
505
- depthScale: camera.mode === Camera.ORTHOGRAPHIC_CAMERA ? (camera.maxZ - camera.minZ) / 2.0 : 1.0,
506
514
  }, [this._depthMix.buffer]);
507
515
  }
508
516
  else if (Native?.sortSplats) {
@@ -1306,7 +1314,6 @@ export class GaussianSplattingMesh extends Mesh {
1306
1314
  newGS._vertexCount = this._vertexCount;
1307
1315
  newGS._copyTextures(this);
1308
1316
  newGS._modelViewProjectionMatrix = Matrix.Identity();
1309
- newGS._viewProjectionMatrix = Matrix.Identity();
1310
1317
  newGS._splatPositions = this._splatPositions;
1311
1318
  newGS._readyToDisplay = false;
1312
1319
  newGS._disableDepthSort = this._disableDepthSort;
@@ -1798,8 +1805,9 @@ export class GaussianSplattingMesh extends Mesh {
1798
1805
  * @returns a placeholder mesh that can be used to manipulate the part transform
1799
1806
  */
1800
1807
  addPart(other, disposeOther = true) {
1801
- if (this.partCount >= GaussianSplattingMaxPartCount) {
1802
- throw new Error(`Cannot add part, as the maximum part count (${GaussianSplattingMaxPartCount}) has been reached`);
1808
+ const maxPartCount = GetGaussianSplattingMaxPartCount(this._scene.getEngine());
1809
+ if (this.partCount >= maxPartCount) {
1810
+ throw new Error(`Cannot add part, as the maximum part count (${maxPartCount}) has been reached`);
1803
1811
  }
1804
1812
  const splatCountA = this._vertexCount;
1805
1813
  const splatsDataA = splatCountA == 0 ? new ArrayBuffer(0) : this.splatsData;
@@ -2060,17 +2068,6 @@ GaussianSplattingMesh._CreateWorker = function (self) {
2060
2068
  let floatMix;
2061
2069
  let partIndices;
2062
2070
  let partMatrices;
2063
- function multiplyMatrices(matrix1, matrix2) {
2064
- const result = new Float32Array(16);
2065
- for (let i = 0; i < 4; i++) {
2066
- for (let j = 0; j < 4; j++) {
2067
- for (let k = 0; k < 4; k++) {
2068
- result[j * 4 + i] += matrix1[k * 4 + i] * matrix2[j * 4 + k];
2069
- }
2070
- }
2071
- }
2072
- return result;
2073
- }
2074
2071
  self.onmessage = (e) => {
2075
2072
  // updated on init
2076
2073
  if (e.data.positions) {
@@ -2087,12 +2084,13 @@ GaussianSplattingMesh._CreateWorker = function (self) {
2087
2084
  // update on view changed
2088
2085
  else {
2089
2086
  const cameraId = e.data.cameraId;
2090
- const globalModelViewProjection = e.data.modelViewProjection;
2091
- const viewProjection = e.data.viewProjection;
2087
+ const globalWorldMatrix = e.data.worldMatrix;
2088
+ const cameraForward = e.data.cameraForward;
2089
+ const cameraPosition = e.data.cameraPosition;
2092
2090
  const vertexCountPadded = (positions.length / 4 + 15) & ~0xf;
2093
- if (!positions || !globalModelViewProjection) {
2091
+ if (!positions || !cameraForward) {
2094
2092
  // Sanity check, it shouldn't happen!
2095
- throw new Error("positions or modelViewProjection matrix is not defined!");
2093
+ throw new Error("positions or camera info is not defined!");
2096
2094
  }
2097
2095
  depthMix = e.data.depthMix;
2098
2096
  indices = new Uint32Array(depthMix.buffer);
@@ -2101,25 +2099,37 @@ GaussianSplattingMesh._CreateWorker = function (self) {
2101
2099
  for (let j = 0; j < vertexCountPadded; j++) {
2102
2100
  indices[2 * j] = j;
2103
2101
  }
2104
- const depthScale = e.data.depthScale;
2102
+ // depth = dot(cameraForward, worldPos - cameraPos)
2103
+ const camDot = cameraForward[0] * cameraPosition[0] + cameraForward[1] * cameraPosition[1] + cameraForward[2] * cameraPosition[2];
2104
+ const computeDepthCoeffs = (m) => {
2105
+ return [
2106
+ cameraForward[0] * m[0] + cameraForward[1] * m[1] + cameraForward[2] * m[2],
2107
+ cameraForward[0] * m[4] + cameraForward[1] * m[5] + cameraForward[2] * m[6],
2108
+ cameraForward[0] * m[8] + cameraForward[1] * m[9] + cameraForward[2] * m[10],
2109
+ cameraForward[0] * m[12] + cameraForward[1] * m[13] + cameraForward[2] * m[14] - camDot,
2110
+ ];
2111
+ };
2105
2112
  if (partMatrices && partIndices) {
2106
- // If there are rig node matrices, we use them instead of the global model view proj
2107
- // Precompute modelViewProj for each rig node
2108
- const modelViewProjs = partMatrices.map((model) => multiplyMatrices(viewProjection, model));
2113
+ // Precompute depth coefficients for each rig node
2114
+ const depthCoeffs = partMatrices.map((m) => computeDepthCoeffs(m));
2109
2115
  // NB: For performance reasons, we assume that part indices are valid
2110
2116
  const length = partIndices.length;
2111
2117
  for (let j = 0; j < vertexCountPadded; j++) {
2112
2118
  // NB: We need this 'min' because vertex array is padded, not partIndices
2113
2119
  const partIndex = partIndices[Math.min(j, length - 1)];
2114
- const mvp = modelViewProjs[partIndex];
2115
- floatMix[2 * j + 1] = 10000 - (mvp[2] * positions[4 * j + 0] + mvp[6] * positions[4 * j + 1] + mvp[10] * positions[4 * j + 2] + mvp[14]) * depthScale;
2120
+ const coeff = depthCoeffs[partIndex];
2121
+ floatMix[2 * j + 1] = coeff[0] * positions[4 * j + 0] + coeff[1] * positions[4 * j + 1] + coeff[2] * positions[4 * j + 2] + coeff[3];
2122
+ // instead of using minus to sort back to front, we use bitwise not operator to invert the order of indices
2123
+ // might not be faster but a minus sign implies a reference value that may not be enough and will decrease floatting precision
2124
+ indices[2 * j + 1] = ~indices[2 * j + 1];
2116
2125
  }
2117
2126
  }
2118
2127
  else {
2119
- // If there are no rig node matrices, we use the global model view proj
2120
- const mvp = globalModelViewProjection;
2128
+ // Compute depth coefficients from global world matrix
2129
+ const [a, b, c, d] = computeDepthCoeffs(globalWorldMatrix);
2121
2130
  for (let j = 0; j < vertexCountPadded; j++) {
2122
- floatMix[2 * j + 1] = 10000 - (mvp[2] * positions[4 * j + 0] + mvp[6] * positions[4 * j + 1] + mvp[10] * positions[4 * j + 2] + mvp[14]) * depthScale;
2131
+ floatMix[2 * j + 1] = a * positions[4 * j + 0] + b * positions[4 * j + 1] + c * positions[4 * j + 2] + d;
2132
+ indices[2 * j + 1] = ~indices[2 * j + 1];
2123
2133
  }
2124
2134
  }
2125
2135
  depthMix.sort();