@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
267 lines (266 loc) • 13.7 kB
TypeScript
/** This file must only contain pure code and pure imports */
import { type Nullable } from "../../types.js";
import { type Scene } from "../../scene.pure.js";
import { Matrix, Vector3 } from "../../Maths/math.vector.pure.js";
import { type Vector2 } from "../../Maths/math.vector.js";
import { type Effect } from "../../Materials/effect.pure.js";
import { GaussianSplattingMeshBase } from "./gaussianSplattingMeshBase.pure.js";
import { GaussianSplattingPartProxyMesh } from "./gaussianSplattingPartProxyMesh.pure.js";
import { BoundingInfo } from "../../Culling/boundingInfo.js";
import { type BaseTexture } from "../../Materials/Textures/baseTexture.pure.js";
import { type AbstractMesh } from "../abstractMesh.pure.js";
interface IGaussianSplattingPartSource {
name: string;
_vertexCount: number;
_splatsData: Nullable<ArrayBuffer | ArrayBufferView>;
_shData: Nullable<Uint8Array[]>;
_shDegree: number;
isCompound: boolean;
getWorldMatrix(): Matrix;
getBoundingInfo(): BoundingInfo;
dispose(): void;
}
/**
* Class used to render a Gaussian Splatting mesh. Supports both single-cloud and compound
* (multi-part) rendering. In compound mode, multiple Gaussian Splatting source meshes are
* merged into one draw call while retaining per-part world-matrix control via
* addPart/addParts and removePart.
*/
export declare class GaussianSplattingMesh extends GaussianSplattingMeshBase {
/**
* Proxy meshes indexed by part index. Maintained in sync with _partMatrices.
*/
private _partProxies;
/** Part 0 local-space AABB when owned directly (not proxied). Set on first addPart, cleared on dispose/reset. */
private _part0LocalMin;
private _part0LocalMax;
/**
* World matrices for each part, indexed by part index.
*/
protected _partMatrices: Matrix[];
/** When true, suppresses the sort trigger inside setWorldMatrixForPart during batch rebuilds. */
private _rebuilding;
/**
* Visibility values for each part (0.0 to 1.0), indexed by part index.
*/
protected _partVisibility: number[];
private _partIndicesTexture;
private _partIndices;
/** Gets the part indices texture used for compound rendering */
get partIndicesTexture(): Nullable<BaseTexture>;
/**
* Creates a new GaussianSplattingMesh
* @param name the name of the mesh
* @param url optional URL to load a Gaussian Splatting file from
* @param scene the hosting scene
* @param keepInRam whether to keep the raw splat data in RAM after uploading to GPU
* @param needsRotationScaleTextures generate rotation and scale matrix textures required for voxel-based IBL shadows
*/
constructor(name: string, url?: Nullable<string>, scene?: Nullable<Scene>, keepInRam?: boolean, needsRotationScaleTextures?: boolean);
/**
* Returns the class name
* @returns "GaussianSplattingMesh"
*/
getClassName(): string;
/**
* Is this node ready to be used/rendered.
* Force-syncs every part proxy's world matrix into `_partMatrices` BEFORE delegating to
* the base readiness check. This guarantees that any pending proxy transform changes
* (for example a user-set `proxy.position`) are reflected in the next sort post, so the
* base `isReady` will only return true once `sortAppliedId === sortRequestId` for that
* up-to-date state. Without this, the proxy's `onAfterWorldMatrixUpdateObservable` would
* fire during the first render and queue a fresh sort AFTER readiness was reported,
* leaving the rendered frame with stale splat order on `renderCount=1` runs.
* @param completeCheck defines if a complete check (including materials and lights) has to be done (false by default)
* @returns true when ready
*/
isReady(completeCheck?: boolean): boolean;
/**
* Recomputes compound local-space bounds from part 0's stored AABB (if unproxied) plus all
* proxy world AABBs inverse-transformed to compound-local space. All 8 corners of each proxy
* AABB are transformed so the result is correct under non-identity compound rotation/scale.
*/
private _updateBoundingInfoFromProxies;
/**
* Override for compound meshes: recomputes bounds from proxy world extents instead of
* local bounds × world matrix, which is wrong for proxied parts with independent transforms.
* @returns this mesh
*/
_updateBoundingInfo(): AbstractMesh;
/**
* Replaces the base hierarchy bounds computation for compound meshes: computes world bounds
* from scratch by iterating part 0's local AABB and all proxy meshes, rather than delegating
* to the base _children traversal which never reaches proxies (they are not parented to the
* compound). Visibility per-part is respected; invisible parts are excluded.
* @param includeDescendants when true, includes descendants (default: true)
* @param predicate optional filter predicate
* @returns world-space min/max of the hierarchy bounding box
*/
getHierarchyBoundingVectors(includeDescendants?: boolean, predicate?: Nullable<(abstractMesh: AbstractMesh) => boolean>): {
min: Vector3;
max: Vector3;
};
/**
* Disposes proxy meshes and clears part data in addition to the base class GPU resources.
* @param doNotRecurse Set to true to not recurse into each children
*/
dispose(doNotRecurse?: boolean): void;
/**
* Posts the initial per-part data to the sort worker after it has been created.
* Sends the current part matrices and group index array so the worker can correctly
* weight depth values per part.
* @param worker the newly created sort worker
*/
protected _onWorkerCreated(worker: Worker): void;
/**
* Stores the raw part index array, padded to texture length, so the worker and GPU texture
* creation step have access to it.
* @param partIndices - the raw part indices array received during a data load
* @param textureLength - the padded texture length to allocate into
*/
protected _onIndexDataReceived(partIndices: Uint8Array, textureLength: number): void;
/**
* Returns `true` when at least one part has been added to this compound mesh.
* Returns `false` before any parts are added, so the mesh renders in normal
* (non-compound) mode until the first addPart/addParts call. This matches the
* old base-class behavior of `this._partMatrices.length > 0` and avoids
* binding unset partWorld uniforms (which would cause division-by-zero in the
* Gaussian projection Jacobian and produce huge distorted splats).
* @internal
*/
get isCompound(): boolean;
/**
* During a removePart rebuild, keep the existing sort worker alive rather than
* tearing it down and spinning up a new one. This avoids startup latency and the
* transient state window where a stale sort could fire against an incomplete
* partMatrices array.
* Outside of a rebuild the base-class behaviour is used unchanged.
*/
protected _instantiateWorker(): void;
/**
* Ensures the part-index GPU texture exists at the start of an incremental update.
* Called before the sub-texture upload so the correct texture is available for the first batch.
* @param textureSize - current texture dimensions
*/
protected _onIncrementalUpdateStart(textureSize: Vector2): void;
/**
* Posts positions (via super) and then additionally posts the current part-index array
* to the sort worker so it can associate each splat with its part.
*/
protected _notifyWorkerNewData(): void;
/**
* Binds all compound-specific shader uniforms: the group index texture, per-part world
* matrices, and per-part visibility values.
* @param effect the shader effect that is being bound
* @internal
*/
bindExtraEffectUniforms(effect: Effect): void;
/**
* Gets the number of parts in the compound.
*/
get partCount(): number;
/**
* Gets the part visibility array.
*/
get partVisibility(): number[];
/**
* Sets the world matrix for a specific part of the compound.
* This will trigger a re-sort of the mesh.
* The `_partMatrices` array is automatically extended when `partIndex >= partCount`.
* @param partIndex index of the part
* @param worldMatrix the world matrix to set
*/
setWorldMatrixForPart(partIndex: number, worldMatrix: Matrix): void;
/**
* Gets the world matrix for a specific part of the compound.
* @param partIndex index of the part, that must be between 0 and partCount - 1
* @returns the world matrix for the part, or the current world matrix of the mesh if the part is not found
*/
getWorldMatrixForPart(partIndex: number): Matrix;
/**
* Gets the visibility for a specific part of the compound.
* @param partIndex index of the part, that must be between 0 and partCount - 1
* @returns the visibility value (0.0 to 1.0) for the part
*/
getPartVisibility(partIndex: number): number;
/**
* Sets the visibility for a specific part of the compound.
* @param partIndex index of the part, that must be between 0 and partCount - 1
* @param value the visibility value (0.0 to 1.0) to set
*/
setPartVisibility(partIndex: number, value: number): void;
protected _copyTextures(source: GaussianSplattingMeshBase): void;
protected _onUpdateTextures(textureSize: Vector2): void;
protected _updateSubTextures(splatPositions: Float32Array, covA: Uint16Array, covB: Uint16Array, colorArray: Uint8Array, lineStart: number, lineCount: number, sh?: Uint8Array[], partIndices?: Uint8Array): void;
/**
* Creates the part indices GPU texture the first time an incremental addPart introduces
* compound data. Has no effect if the texture already exists or no partIndices are provided.
* @param textureSize - Current texture dimensions
* @param partIndices - Part index data; if undefined the method is a no-op
*/
protected _ensurePartIndicesTexture(textureSize: Vector2, partIndices: Uint8Array | undefined): void;
private _appendPartSourceToArrays;
private _createRetainedPartSource;
private _retainMergedPartData;
/**
* Core implementation for adding one or more source parts as new
* parts. Writes directly into texture-sized CPU arrays, updates the retained merged source
* buffers, and uploads in one pass.
*
* @param others - Source meshes to append (must each be non-compound and fully loaded)
* @param disposeOthers - Dispose source meshes after appending
* @returns Proxy meshes and their assigned part indices
*/
protected _addPartsInternal(others: IGaussianSplattingPartSource[], disposeOthers: boolean): {
proxyMeshes: GaussianSplattingPartProxyMesh[];
assignedPartIndices: number[];
};
/**
* Add another mesh to this mesh, as a new part. This makes the current mesh a compound, if not already.
* The source mesh's splat data is read directly and copied into the compound's retained source buffers.
* @param other - The other mesh to add. Must be fully loaded before calling this method.
* @param disposeOther - Whether to dispose the other mesh after adding it to the current mesh.
* @returns a placeholder mesh that can be used to manipulate the part transform
* @deprecated Use {@link GaussianSplattingCompoundMesh.addPart} instead.
*/
addPart(other: GaussianSplattingMesh, disposeOther?: boolean): GaussianSplattingPartProxyMesh;
/**
* Remove a part from this compound mesh.
* The remaining parts are rebuilt directly from the compound mesh's retained source buffers.
* The current mesh is reset to a plain (single-part) state and then each remaining source is
* re-added via addParts.
* @param index - The index of the part to remove
* @deprecated Use {@link GaussianSplattingCompoundMesh.removePart} instead.
*/
removePart(index: number): void;
/**
* Serialize current GaussianSplattingMesh
* @param serializationObject defines the object which will receive the serialization data
* @param encoding the encoding of binary data, defaults to base64 for json serialize,
* kept for future internal use like cloning where base64 encoding wastes cycles and memory
* @returns the serialized object
*/
serialize(serializationObject?: any, encoding?: string): any;
/**
* Internal helper to parses a serialized GaussianSplattingMesh or GaussianSplattingCompoundMesh
* @param parsedMesh the serialized mesh
* @param scene the scene to create the GaussianSplattingMesh or GaussianSplattingCompoundMesh in
* @param ctor the constructor of the mesh to create
* @returns the created GaussianSplattingMesh
* @internal
*/
static _ParseInternal<T extends GaussianSplattingMesh>(parsedMesh: any, scene: Scene, ctor: new (name: string, url: Nullable<string>, scene: Nullable<Scene>, keepInRam: boolean) => T): T;
/**
* Parses a serialized GaussianSplattingMesh
* @param parsedMesh the serialized mesh
* @param scene the scene to create the GaussianSplattingMesh in
* @returns the created GaussianSplattingMesh
*/
static Parse(parsedMesh: any, scene: Scene): GaussianSplattingMesh;
}
/**
* Register side effects for gaussianSplattingMesh.
* Safe to call multiple times; only the first call has an effect.
*/
export declare function RegisterGaussianSplattingMesh(): void;
export {};