@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.
202 lines • 8.62 kB
JavaScript
/** This file must only contain pure code and pure imports */
import { Mesh } from "../mesh.pure.js";
import { BoundingInfo } from "../../Culling/boundingInfo.js";
import { PickingInfo } from "../../Collisions/pickingInfo.js";
import { Vector3 } from "../../Maths/math.vector.pure.js";
/**
* Class used as a proxy mesh for a part of a compound Gaussian Splatting mesh
*/
export class GaussianSplattingPartProxyMesh extends Mesh {
/**
* Gets the index of the part in the compound mesh
*/
get partIndex() {
return this._partIndex;
}
/**
* Backward-compatible alias for the owning compound mesh.
* @deprecated Use `compoundSplatMesh` instead.
*/
get proxiedMesh() {
return this.compoundSplatMesh;
}
/**
* Creates a new Gaussian Splatting part proxy mesh
* @param name The name of the proxy mesh
* @param scene The scene the proxy mesh belongs to
* @param compoundSplatMesh The compound mesh that owns this part proxy
* @param partIndex The index of the part in the compound mesh
* @param boundingInfo Local-space bounds of the part inside the compound mesh
* @param vertexCount Number of splats owned by the part
* @param splatsDataOffset Offset of the part in the compound splat ordering
* @param shDataOffset Offset of the part in the compound SH textures
*/
constructor(name, scene, compoundSplatMesh, partIndex, boundingInfo, vertexCount, splatsDataOffset, shDataOffset = splatsDataOffset) {
super(name, scene);
this._partIndex = partIndex;
this._vertexCount = vertexCount;
this._splatsDataOffset = splatsDataOffset;
this._shDataOffset = shDataOffset;
this._minimum = boundingInfo.minimum.clone();
this._maximum = boundingInfo.maximum.clone();
this.compoundSplatMesh = compoundSplatMesh;
this._applyBoundingInfo();
this.compoundSplatMesh.setWorldMatrixForPart(this.partIndex, this.getWorldMatrix());
// Update the compound mesh's part matrix when this proxy's world matrix changes.
this.onAfterWorldMatrixUpdateObservable.add(() => {
this.compoundSplatMesh.setWorldMatrixForPart(this.partIndex, this.getWorldMatrix());
});
}
/**
* Updates the bounding info of this proxy mesh from its stored part metadata.
*/
updateBoundingInfoFromPartData() {
this._applyBoundingInfo();
}
/**
* Backward-compatible alias retained while callers move away from source-mesh based semantics.
*/
updateBoundingInfoFromProxiedMesh() {
this.updateBoundingInfoFromPartData();
}
_applyBoundingInfo() {
this.setBoundingInfo(new BoundingInfo(this._minimum.clone(), this._maximum.clone()));
}
/**
* Returns the class name
* @returns "GaussianSplattingPartProxyMesh"
*/
getClassName() {
return "GaussianSplattingPartProxyMesh";
}
/**
* Updates the part index for this proxy mesh.
* This should only be called internally when parts are removed from the compound mesh.
* @param newPartIndex the new part index
* @internal
*/
updatePartIndex(newPartIndex) {
this._partIndex = newPartIndex;
}
/**
* Updates the per-part metadata for this proxy mesh.
* This is used internally when compound parts are rebuilt and re-indexed.
* @param vertexCount the number of splats owned by the part
* @param splatsDataOffset the new splat offset in the compound
* @param shDataOffset the new SH texel offset in the compound
* @internal
*/
updatePartMetadata(vertexCount, splatsDataOffset, shDataOffset = splatsDataOffset) {
this._vertexCount = vertexCount;
this._splatsDataOffset = splatsDataOffset;
this._shDataOffset = shDataOffset;
}
/**
* Gets whether the part is visible
*/
get isVisible() {
return this.compoundSplatMesh.getPartVisibility(this.partIndex) > 0;
}
/**
* Sets whether the part is visible
*/
set isVisible(value) {
this.compoundSplatMesh.setPartVisibility(this.partIndex, value ? 1.0 : 0.0);
}
/**
* Gets the visibility of the part (0.0 to 1.0)
*/
get visibility() {
return this.compoundSplatMesh.getPartVisibility(this.partIndex);
}
/**
* Sets the visibility of the part (0.0 to 1.0)
*/
set visibility(value) {
this.compoundSplatMesh.setPartVisibility(this.partIndex, value);
}
/**
* Checks if a ray intersects with this proxy mesh using only bounding info
* @param ray defines the ray to test
* @returns the picking info with this mesh set as pickedMesh if hit
*/
intersects(ray) {
const pickingInfo = new PickingInfo();
const boundingInfo = this.getBoundingInfo();
if (!boundingInfo) {
return pickingInfo;
}
// Always check against bounding info for proxy meshes
if (!ray.intersectsSphere(boundingInfo.boundingSphere) || !ray.intersectsBox(boundingInfo.boundingBox)) {
return pickingInfo;
}
// If we hit the bounding volume, report this mesh as picked
pickingInfo.hit = true;
pickingInfo.pickedMesh = this;
pickingInfo.distance = Vector3.Distance(ray.origin, boundingInfo.boundingSphere.center);
pickingInfo.subMeshId = 0;
return pickingInfo;
}
/**
* Serialize current GaussianSplattingPartProxyMesh
* @param serializationObject defines the object which will receive the serialization data
* @returns the serialized object
*/
serialize(serializationObject = {}) {
serializationObject = super.serialize(serializationObject);
// GaussianSplattingPartProxyMesh needs no SubMesh, Geometry, or Material
serializationObject.subMeshes = [];
serializationObject.geometryUniqueId = undefined;
serializationObject.geometryId = undefined;
serializationObject.materialUniqueId = undefined;
serializationObject.materialId = undefined;
serializationObject.instances = [];
serializationObject.actions = undefined;
serializationObject.type = this.getClassName();
serializationObject.compoundSplatMeshId = this.compoundSplatMesh.id;
// Part metadata is needed to reconnect the proxy to the correct compound segment.
serializationObject.partIndex = this._partIndex;
serializationObject.vertexCount = this._vertexCount;
serializationObject.splatsDataOffset = this._splatsDataOffset;
serializationObject.shDataOffset = this._shDataOffset;
const boundingInfo = this.getBoundingInfo();
serializationObject.boundingInfo = {
minimum: boundingInfo.minimum.asArray(),
maximum: boundingInfo.maximum.asArray(),
};
return serializationObject;
}
/**
* Parses a serialized GaussianSplattingPartProxyMesh
* @param parsedMesh the serialized mesh
* @param scene the scene to create the GaussianSplattingPartProxyMesh in
* @returns the created GaussianSplattingPartProxyMesh
*/
static Parse(parsedMesh, scene) {
const partIndex = parsedMesh.partIndex;
const compoundSplatMesh = parsedMesh.compoundSplatMesh ?? scene.getLastMeshById(parsedMesh.compoundSplatMeshId);
if (!compoundSplatMesh) {
throw new Error(`GaussianSplattingPartProxyMesh: compound mesh not found with ID ${parsedMesh.compoundSplatMeshId}`);
}
const minimum = Vector3.FromArray(parsedMesh.boundingInfo.minimum);
const maximum = Vector3.FromArray(parsedMesh.boundingInfo.maximum);
const boundingInfo = new BoundingInfo(minimum, maximum);
const vertexCount = parsedMesh.vertexCount ?? 0;
const splatsDataOffset = parsedMesh.splatsDataOffset ?? 0;
const shDataOffset = parsedMesh.shDataOffset ?? splatsDataOffset;
return new GaussianSplattingPartProxyMesh(parsedMesh.name, scene, compoundSplatMesh, partIndex, boundingInfo, vertexCount, splatsDataOffset, shDataOffset);
}
}
let _Registered = false;
/**
* Register side effects for gaussianSplattingPartProxyMesh.
* Safe to call multiple times; only the first call has an effect.
*/
export function RegisterGaussianSplattingPartProxyMesh() {
if (_Registered) {
return;
}
_Registered = true;
Mesh._GaussianSplattingPartProxyMeshParser = GaussianSplattingPartProxyMesh.Parse;
}
//# sourceMappingURL=gaussianSplattingPartProxyMesh.pure.js.map