/** 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 {};
