Renamed "forge" to "spark". Updated meta-references and future domain. (#40)

This commit is contained in:
Andreas Sundquist
2025-06-09 13:50:08 -07:00
committed by GitHub
parent ea9e4e3da9
commit acb541cc4e
72 changed files with 396 additions and 395 deletions
+1 -1
View File
@@ -535,7 +535,7 @@ export class PackedSplats {
// Executes a dyno program specified by generator which is any DynoBlock that
// maps { index: "int" } to { gsplat: Gsplat }. This is called in
// ForgeRenderer.updateInternal() to re-generate Gsplats in the scene for
// SparkRenderer.updateInternal() to re-generate Gsplats in the scene for
// SplatGenerator instances whose version is newer than what was generated
// for it last time.
generate({
+1 -1
View File
@@ -9,7 +9,7 @@ import { getTextureSize } from "./utils";
// Readback can be used to run a Dyno program that maps an index to a 32-bit
// RGBA8 value, which is the only allowed, portable readback format for WebGL2.
// Using data packing and conversion you can read back any 32-bit value, which
// Forge uses to read back 2 float16 Gsplat distance values per index.
// Spark uses to read back 2 float16 Gsplat distance values per index.
export type Rgba8Readback = Dyno<{ index: "int" }, { rgba8: "vec4" }>;
+52 -52
View File
@@ -1,8 +1,8 @@
import * as THREE from "three";
import { ForgeViewpoint, type ForgeViewpointOptions } from "./ForgeViewpoint";
import { PackedSplats } from "./PackedSplats";
import { RgbaArray } from "./RgbaArray";
import { SparkViewpoint, type SparkViewpointOptions } from "./SparkViewpoint";
import { type GeneratorMapping, SplatAccumulator } from "./SplatAccumulator";
import { SplatEdit } from "./SplatEdit";
import { SplatGenerator, SplatModifier } from "./SplatGenerator";
@@ -25,7 +25,7 @@ import {
withinCoorientDist,
} from "./utils";
// ForgeRenderer aggregates splats from multiple generators into a single
// SparkRenderer aggregates splats from multiple generators into a single
// accumulated collection per frame. In normal operation we only need a
// maximum of 3 accumulators: One currently being viewed, one currently
// being sorted, and one more for generating the next frame. Accumulators
@@ -36,17 +36,17 @@ import {
const MAX_ACCUMULATORS = 5;
// Scene.onBeforeRender monkey-patch to
// inject a ForgeRenderer into a scene with SplatMeshes if there isn't
// inject a SparkRenderer into a scene with SplatMeshes if there isn't
// one already. Restore original Scene.onBeforeRenderer and Scene.add when done.
let hasSplatMesh = false;
let hasForgeRenderer = false;
let hasSparkRenderer = false;
let forgeRendererInstance: ForgeRenderer;
let sparkRendererInstance: SparkRenderer;
const sceneAdd = THREE.Scene.prototype.add;
THREE.Scene.prototype.add = function (object) {
hasSplatMesh = hasSplatMesh || object instanceof SplatMesh;
hasForgeRenderer = hasForgeRenderer || object instanceof ForgeRenderer;
hasSparkRenderer = hasSparkRenderer || object instanceof SparkRenderer;
sceneAdd.call(this, object);
return this;
};
@@ -56,22 +56,22 @@ THREE.Scene.prototype.onBeforeRender = function (renderer) {
if (!hasSplatMesh) {
return;
}
if (!hasForgeRenderer) {
const forge = forgeRendererInstance || new ForgeRenderer({ renderer });
this.add(forge);
if (!hasSparkRenderer) {
const spark = sparkRendererInstance || new SparkRenderer({ renderer });
this.add(spark);
}
THREE.Scene.prototype.onBeforeRender = sceneOnBeforeRender;
THREE.Scene.prototype.add = sceneAdd;
};
export type ForgeRendererOptions = {
// Pass in your THREE.WebGLRenderer instance so Forge can perform work
export type SparkRendererOptions = {
// Pass in your THREE.WebGLRenderer instance so Spark can perform work
// outside the usual render loop. Should be created with antialias: false
// (default setting) as WebGL anti-aliasing doesn't improve Gaussian Splatting
// rendering and significantly reduces performance.
renderer: THREE.WebGLRenderer;
// Pass in a THREE.Clock to synchronize time-based effects across different
// systems. Alternatively, you can set the ForgeRenderer properties time and
// systems. Alternatively, you can set the SparkRenderer properties time and
// deltaTime directly. (default: new THREE.Clock)
clock?: THREE.Clock;
// Controls whether to check and automatically update Gsplat collection after
@@ -81,7 +81,7 @@ export type ForgeRendererOptions = {
// this must be false in order to complete rendering as soon as possible.
// (default: false)
preUpdate?: boolean;
// Distance threshold for ForgeRenderer movement triggering a Gsplat update at
// Distance threshold for SparkRenderer movement triggering a Gsplat update at
// the new origin. (default: 1.0)
originDistance?: number;
// Maximum standard deviations from the center to render Gaussians. Values
@@ -109,16 +109,16 @@ export type ForgeRendererOptions = {
// 1.0 clips any centers that are exactly out of bounds, while 1.4 clips
// centers that are 40% beyond the bounds. (default: 1.4)
clipXY?: number;
// Configures the ForgeViewpointOptions for the default ForgeViewpoint
// associated with this ForgeRenderer. Notable option: sortRadial (sort by
// Configures the SparkViewpointOptions for the default SparkViewpoint
// associated with this SparkRenderer. Notable option: sortRadial (sort by
// radial distance or Z-depth)
view?: ForgeViewpointOptions;
view?: SparkViewpointOptions;
};
export class ForgeRenderer extends THREE.Mesh {
export class SparkRenderer extends THREE.Mesh {
renderer: THREE.WebGLRenderer;
material: THREE.ShaderMaterial;
uniforms: ReturnType<typeof ForgeRenderer.makeUniforms>;
uniforms: ReturnType<typeof SparkRenderer.makeUniforms>;
autoUpdate: boolean;
preUpdate: boolean;
@@ -140,10 +140,10 @@ export class ForgeRenderer extends THREE.Mesh {
private freeAccumulators: SplatAccumulator[];
// Total number of accumulators currently allocated
private accumulatorCount: number;
// Default ForgeViewpoint used for rendering to the canvas
defaultView: ForgeViewpoint;
// List of ForgeViewpoints with autoUpdate enabled
autoViewpoints: ForgeViewpoint[] = [];
// Default SparkViewpoint used for rendering to the canvas
defaultView: SparkViewpoint;
// List of SparkViewpoints with autoUpdate enabled
autoViewpoints: SparkViewpoint[] = [];
// Dynos used to transform Gsplats to the accumulator coordinate system
private rotateToAccumulator = new DynoVec4({ value: new THREE.Quaternion() });
@@ -159,7 +159,7 @@ export class ForgeRenderer extends THREE.Mesh {
// Should be set to the defaultView, but can be temporarily changed to another
// viewpoint using prepareViewpoint() for rendering from a different viewpoint.
viewpoint: ForgeViewpoint;
viewpoint: SparkViewpoint;
// Holds data needed to perform a scheduled Gsplat update.
private pendingUpdate: {
@@ -167,8 +167,8 @@ export class ForgeRenderer extends THREE.Mesh {
originToWorld: THREE.Matrix4;
} | null = null;
// Internal ForgeViewpoint used for environment map rendering.
private envViewpoint: ForgeViewpoint | null = null;
// Internal SparkViewpoint used for environment map rendering.
private envViewpoint: SparkViewpoint | null = null;
// Data and buffers used for environment map rendering
private static cubeRender: {
@@ -179,8 +179,8 @@ export class ForgeRenderer extends THREE.Mesh {
} | null = null;
private static pmrem: THREE.PMREMGenerator | null = null;
constructor(options: ForgeRendererOptions) {
const uniforms = ForgeRenderer.makeUniforms();
constructor(options: SparkRendererOptions) {
const uniforms = SparkRenderer.makeUniforms();
const shaders = getShaders();
const material = new THREE.ShaderMaterial({
glslVersion: THREE.GLSL3,
@@ -240,19 +240,19 @@ export class ForgeRenderer extends THREE.Mesh {
this.accumulatorCount += 1;
}
// Create a default ForgeViewpoint that is used when we call render()
// Create a default SparkViewpoint that is used when we call render()
// on the scene and has the sorted Gsplat collection from that viewpoint.
this.defaultView = new ForgeViewpoint({
this.defaultView = new SparkViewpoint({
...options.view,
autoUpdate: true,
forge: this,
spark: this,
});
this.viewpoint = this.defaultView;
this.prepareViewpoint(this.viewpoint);
this.clock = options.clock ? cloneClock(options.clock) : new THREE.Clock();
forgeRendererInstance = this;
sparkRendererInstance = this;
}
static makeUniforms() {
@@ -323,15 +323,15 @@ export class ForgeRenderer extends THREE.Mesh {
}
}
newViewpoint(options: ForgeViewpointOptions) {
// Create a new ForgeViewpoint for this ForgeRenderer.
// Note that every ForgeRenderer has an initial forge.defaultView: ForgeViewpoint
newViewpoint(options: SparkViewpointOptions) {
// Create a new SparkViewpoint for this SparkRenderer.
// Note that every SparkRenderer has an initial spark.defaultView: SparkViewpoint
// from construction, which is used for the default canvas render loop.
// Calling this method allows you to create additional viewpoints, which can be
// updated automatically each frame (performing Gsplat sorting every time there
// is an update), or updated on-demand for controlled rendering for video render
// or similar applications.
return new ForgeViewpoint({ ...options, forge: this });
return new SparkViewpoint({ ...options, spark: this });
}
onBeforeRender(
@@ -339,7 +339,7 @@ export class ForgeRenderer extends THREE.Mesh {
scene: THREE.Scene,
camera: THREE.Camera,
) {
// Called by Three.js before rendering this ForgeRenderer.
// Called by Three.js before rendering this SparkRenderer.
// At this point we can't modify the geometry or material, all these must
// be set in the scene already before this is called. Update the uniforms
// to render the Gsplats from the current active viewpoint.
@@ -433,7 +433,7 @@ export class ForgeRenderer extends THREE.Mesh {
// Note that the client expects to be able to call render() at any point
// to update the canvas, so we must switch the viewpoint back to
// defaultView when we're finished.
prepareViewpoint(viewpoint?: ForgeViewpoint) {
prepareViewpoint(viewpoint?: SparkViewpoint) {
this.viewpoint = viewpoint ?? this.viewpoint;
if (this.viewpoint.display) {
@@ -449,13 +449,13 @@ export class ForgeRenderer extends THREE.Mesh {
}
}
// If forge.autoUpdate is false then you must manually call
// forge.update({ scene }) to have the scene Gsplats be re-generated.
// If spark.autoUpdate is false then you must manually call
// spark.update({ scene }) to have the scene Gsplats be re-generated.
update({
scene,
viewToWorld,
}: { scene: THREE.Scene; viewToWorld?: THREE.Matrix4 }) {
// Compute the transform for the ForgeRenderer to use as origin
// Compute the transform for the SparkRenderer to use as origin
// for Gsplat generation and accumulation.
const originToWorld = this.matrixWorld.clone();
// Either do the update now, or in the next "tick" depending on preUpdate
@@ -493,7 +493,7 @@ export class ForgeRenderer extends THREE.Mesh {
return false;
}
// Figure out the frame of the ForgeRenderer and current view
// Figure out the frame of the SparkRenderer and current view
if (!originToWorld) {
originToWorld = this.active.toWorld;
}
@@ -710,13 +710,13 @@ export class ForgeRenderer extends THREE.Mesh {
this.envViewpoint = this.newViewpoint({ sort360: true });
}
if (
!ForgeRenderer.cubeRender ||
ForgeRenderer.cubeRender.target.width !== size ||
ForgeRenderer.cubeRender.near !== near ||
ForgeRenderer.cubeRender.far !== far
!SparkRenderer.cubeRender ||
SparkRenderer.cubeRender.target.width !== size ||
SparkRenderer.cubeRender.near !== near ||
SparkRenderer.cubeRender.far !== far
) {
if (ForgeRenderer.cubeRender) {
ForgeRenderer.cubeRender.target.dispose();
if (SparkRenderer.cubeRender) {
SparkRenderer.cubeRender.target.dispose();
}
const target = new THREE.WebGLCubeRenderTarget(size, {
format: THREE.RGBAFormat,
@@ -724,18 +724,18 @@ export class ForgeRenderer extends THREE.Mesh {
minFilter: THREE.LinearMipMapLinearFilter,
});
const camera = new THREE.CubeCamera(near, far, target);
ForgeRenderer.cubeRender = { target, camera, near, far };
SparkRenderer.cubeRender = { target, camera, near, far };
}
if (!ForgeRenderer.pmrem) {
ForgeRenderer.pmrem = new THREE.PMREMGenerator(renderer ?? this.renderer);
if (!SparkRenderer.pmrem) {
SparkRenderer.pmrem = new THREE.PMREMGenerator(renderer ?? this.renderer);
}
// Prepare the viewpoint, sorting Gsplats for this view origin.
const viewToWorld = new THREE.Matrix4().setPosition(worldCenter);
await this.envViewpoint?.prepare({ scene, viewToWorld, update });
const { target, camera } = ForgeRenderer.cubeRender;
const { target, camera } = SparkRenderer.cubeRender;
camera.position.copy(worldCenter);
// Save the visibility state of objects we want to hide before render
@@ -756,7 +756,7 @@ export class ForgeRenderer extends THREE.Mesh {
}
// Pre-filter the cube map using THREE.PMREMGenerator
return ForgeRenderer.pmrem?.fromCubemap(target.texture).texture;
return SparkRenderer.pmrem?.fromCubemap(target.texture).texture;
}
// Utility function to recursively set the envMap property for any
+42 -42
View File
@@ -1,8 +1,8 @@
import * as THREE from "three";
import type { ForgeRenderer } from "./ForgeRenderer";
import { DynoPackedSplats } from "./PackedSplats";
import { Readback } from "./Readback";
import type { SparkRenderer } from "./SparkRenderer";
import type { SplatAccumulator } from "./SplatAccumulator";
import { SplatGeometry } from "./SplatGeometry";
import {
@@ -28,8 +28,8 @@ import {
import { withWorker } from "./splatWorker";
import { FreeList, withinCoorientDist } from "./utils";
export type ForgeViewpointOptions = {
// Controls whether to auto-update its sort order whenever the ForgeRenderer
export type SparkViewpointOptions = {
// Controls whether to auto-update its sort order whenever the SparkRenderer
// updates the Gsplats. If you expect to render/display from this viewpoint
// most frames, set this to true. (default: false)
autoUpdate?: boolean;
@@ -75,22 +75,22 @@ export type ForgeViewpointOptions = {
depthBias?: number;
// Set this to true if rendering a 360 to disable "behind the viewpoint"
// culling during sorting. This is set automatically when rendering 360 envMaps
// using the ForgeRenderer.renderEnvMap() utility function. (default: false)
// using the SparkRenderer.renderEnvMap() utility function. (default: false)
sort360?: boolean;
};
// A ForgeViewpoint is created from and tied to a ForgeRenderer, and represents
// A SparkViewpoint is created from and tied to a SparkRenderer, and represents
// an independent viewpoint of all the scene Gsplats and their sort order. Making
// these viewpoints explicit allows us to have multiple, simultaneous viewpoint
// renders, for example for camera preview panes or overhead map views.
//
// When creating a ForgeRenderer it automatically creates a default viewpoint
// When creating a SparkRenderer it automatically creates a default viewpoint
// .defaultView that is used in the normal render loop when drawing to the canvas,
// and is automatically updated whenever the camera moves. Additional viewpoints
// can be created and configured separately.
export class ForgeViewpoint {
forge: ForgeRenderer;
export class SparkViewpoint {
spark: SparkRenderer;
autoUpdate: boolean;
camera?: THREE.Camera;
viewToWorld: THREE.Matrix4;
@@ -127,8 +127,8 @@ export class ForgeViewpoint {
private readback: Uint16Array = new Uint16Array(0);
private orderingFreelist: FreeList<Uint32Array, number>;
constructor(options: ForgeViewpointOptions & { forge: ForgeRenderer }) {
this.forge = options.forge;
constructor(options: SparkViewpointOptions & { spark: SparkRenderer }) {
this.spark = options.spark;
this.camera = options.camera;
this.viewToWorld = options.viewToWorld ?? new THREE.Matrix4();
@@ -179,7 +179,7 @@ export class ForgeViewpoint {
this.setAutoUpdate(options.autoUpdate ?? false);
}
// Call this when you are done with the ForgeViewpoint and want to
// Call this when you are done with the SparkViewpoint and want to
// free up its resources (GPU targets, pixel buffers, etc.)
dispose() {
this.setAutoUpdate(false);
@@ -192,25 +192,25 @@ export class ForgeViewpoint {
this.back = undefined;
}
if (this.display) {
this.forge.releaseAccumulator(this.display.accumulator);
this.spark.releaseAccumulator(this.display.accumulator);
this.display.geometry.dispose();
this.display = null;
}
if (this.pending?.accumulator) {
this.forge.releaseAccumulator(this.pending.accumulator);
this.spark.releaseAccumulator(this.pending.accumulator);
this.pending = null;
}
}
// Use this function to change whether this viewpoint will auto-update
// its sort order whenever the attached ForgeRenderer updates the Gsplats.
// its sort order whenever the attached SparkRenderer updates the Gsplats.
// Turn this on or off depending on whether you expect to do renders from
// this viewpoint most frames.
setAutoUpdate(autoUpdate: boolean) {
if (!this.autoUpdate && autoUpdate) {
this.forge.autoViewpoints.push(this);
this.spark.autoViewpoints.push(this);
} else if (this.autoUpdate && !autoUpdate) {
this.forge.autoViewpoints = this.forge.autoViewpoints.filter(
this.spark.autoViewpoints = this.spark.autoViewpoints.filter(
(v) => v !== this,
);
}
@@ -247,7 +247,7 @@ export class ForgeViewpoint {
// Force an update, possibly with origin centered at this camera
// to yield the best quality output.
const originToWorld = forceOrigin ? this.viewToWorld : undefined;
const updated = this.forge.updateInternal({ scene, originToWorld });
const updated = this.spark.updateInternal({ scene, originToWorld });
if (updated) {
break;
}
@@ -255,9 +255,9 @@ export class ForgeViewpoint {
await new Promise((resolve) => setTimeout(resolve, 10));
}
const accumulator = this.forge.active;
const accumulator = this.spark.active;
if (accumulator !== this.display?.accumulator) {
this.forge.active.refCount += 1;
this.spark.active.refCount += 1;
}
await this.sortUpdate({ accumulator, viewToWorld: this.viewToWorld });
}
@@ -271,7 +271,7 @@ export class ForgeViewpoint {
}: { scene: THREE.Scene; camera?: THREE.Camera }) {
const target = this.back ?? this.target;
if (!target) {
throw new Error("Must initialize ForgeViewpoint with target");
throw new Error("Must initialize SparkViewpoint with target");
}
camera = camera ?? this.camera;
@@ -287,13 +287,13 @@ export class ForgeViewpoint {
this.viewToWorld = camera.matrixWorld.clone();
try {
this.forge.renderer.setRenderTarget(target);
this.forge.prepareViewpoint(this);
this.spark.renderer.setRenderTarget(target);
this.spark.prepareViewpoint(this);
this.forge.renderer.render(scene, camera);
this.spark.renderer.render(scene, camera);
} finally {
this.forge.prepareViewpoint(this.forge.defaultView);
this.forge.renderer.setRenderTarget(null);
this.spark.prepareViewpoint(this.spark.defaultView);
this.spark.renderer.setRenderTarget(null);
}
if (target !== this.target) {
@@ -310,14 +310,14 @@ export class ForgeViewpoint {
// will reuse the same buffers to minimize memory allocations.
async readTarget(): Promise<Uint8Array> {
if (!this.target) {
throw new Error("Must initialize ForgeViewpoint with target");
throw new Error("Must initialize SparkViewpoint with target");
}
const { width, height } = this.target;
const byteSize = width * height * 4;
if (!this.superPixels || this.superPixels.length < byteSize) {
this.superPixels = new Uint8Array(byteSize);
}
await this.forge.renderer.readRenderTargetPixelsAsync(
await this.spark.renderer.readRenderTargetPixelsAsync(
this.target,
0,
0,
@@ -370,7 +370,7 @@ export class ForgeViewpoint {
// Render out a viewpoint as a Uint8Array of RGBA values for the provided scene
// and any camera/viewToWorld viewpoint overrides. By default update is true,
// which triggers its ForgeRenderer to check and potentially update the Gsplats.
// which triggers its SparkRenderer to check and potentially update the Gsplats.
// Setting update to false disables this and sorts the Gsplats as they are.
// Setting forceOrigin (default: false) to true forces the view update to
// recalculate the splats with this view origin, potentially altering any
@@ -401,8 +401,8 @@ export class ForgeViewpoint {
return this.readTarget();
}
// This is called automatically by ForgeRenderer, there is no need to call it!
// The method cannot be private because then ForgeRenderer would
// This is called automatically by SparkRenderer, there is no need to call it!
// The method cannot be private because then SparkRenderer would
// not be able to call it.
autoPoll({ accumulator }: { accumulator?: SplatAccumulator }) {
if (this.camera) {
@@ -423,7 +423,7 @@ export class ForgeViewpoint {
// Splat mapping has not changed, so reuse the existing sorted
// geometry to show updates faster. We will still fire off
// a re-sort if necessary. First release old accumulator.
this.forge.releaseAccumulator(this.display.accumulator);
this.spark.releaseAccumulator(this.display.accumulator);
this.display.accumulator = accumulator;
displayed = true;
}
@@ -462,7 +462,7 @@ export class ForgeViewpoint {
this.pending?.accumulator &&
this.pending.accumulator !== this.display?.accumulator
) {
this.forge.releaseAccumulator(this.pending.accumulator);
this.spark.releaseAccumulator(this.pending.accumulator);
}
this.pending = { accumulator, viewToWorld: this.viewToWorld, displayed };
@@ -479,7 +479,7 @@ export class ForgeViewpoint {
const { viewToWorld, displayed } = this.pending;
let accumulator = this.pending.accumulator ?? this.display?.accumulator;
if (!accumulator) {
accumulator = this.forge.active;
accumulator = this.spark.active;
accumulator.refCount += 1;
}
this.pending = null;
@@ -508,7 +508,7 @@ export class ForgeViewpoint {
}
this.sortingCheck = true;
accumulator = accumulator ?? this.forge.active;
accumulator = accumulator ?? this.spark.active;
const { numSplats, maxSplats } = accumulator.splats;
let activeSplats = 0;
let ordering = this.orderingFreelist.alloc(maxSplats);
@@ -523,7 +523,7 @@ export class ForgeViewpoint {
dynoDepthBias,
dynoSort360,
dynoSplats,
} = ForgeViewpoint.makeSorter();
} = SparkViewpoint.makeSorter();
const halfMaxSplats = Math.ceil(maxSplats / 2);
this.readback = reader.ensureBuffer(halfMaxSplats, this.readback);
@@ -542,7 +542,7 @@ export class ForgeViewpoint {
dynoSplats.packedSplats = accumulator.splats;
await reader.renderReadback({
renderer: this.forge.renderer,
renderer: this.spark.renderer,
reader: doubleSortReader,
count: Math.ceil(numSplats / 2),
readback: this.readback,
@@ -595,7 +595,7 @@ export class ForgeViewpoint {
};
} else {
if (!displayed && accumulator !== this.display.accumulator) {
this.forge.releaseAccumulator(this.display.accumulator);
this.spark.releaseAccumulator(this.display.accumulator);
this.display.accumulator = accumulator;
}
@@ -611,8 +611,8 @@ export class ForgeViewpoint {
}
this.orderingFreelist.free(oldOrdering);
}
if (this.forge.viewpoint === this) {
this.forge.prepareViewpoint(this);
if (this.spark.viewpoint === this) {
this.spark.prepareViewpoint(this);
}
}
@@ -632,7 +632,7 @@ export class ForgeViewpoint {
} | null = null;
private static makeSorter() {
if (!ForgeViewpoint.dynos) {
if (!SparkViewpoint.dynos) {
const dynoSortRadial = new DynoBool({ value: true });
const dynoOrigin = new DynoVec3({ value: new THREE.Vector3() });
const dynoDirection = new DynoVec3({ value: new THREE.Vector3() });
@@ -676,7 +676,7 @@ export class ForgeViewpoint {
},
);
ForgeViewpoint.dynos = {
SparkViewpoint.dynos = {
dynoSortRadial,
dynoOrigin,
dynoDirection,
@@ -687,7 +687,7 @@ export class ForgeViewpoint {
doubleSortReader,
};
}
return ForgeViewpoint.dynos;
return SparkViewpoint.dynos;
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ export class SplatAccumulator {
toWorld = new THREE.Matrix4();
// An array of all Gsplat mappings that were used for generation
mapping: GeneratorMapping[] = [];
// Number of ForgeViewpoints (or other) that reference this accumulator, used
// Number of SparkViewpoints (or other) that reference this accumulator, used
// to figure out when it can be recycled for use
refCount = 0;
+1 -1
View File
@@ -11,7 +11,7 @@ import {
} from "./dyno";
import { newArray } from "./utils";
// Forge provides the ability to apply "edits" to Gsplats as part of the standard
// Spark provides the ability to apply "edits" to Gsplats as part of the standard
// SplatMesh pipeline. These edits take the form of a sequence of operations,
// applied one at a time to the set of Gsplats in its packedSplats. Each operation
// evaluates a 7-dimensional field (RGBA and XYZ displacement) at each point in
+1 -1
View File
@@ -139,7 +139,7 @@ export class SplatTransformer {
}
// SplatGenerator is an Object3D that can be placed anywhere in the scene
// to generate Gsplats into the world for ForgeRenderer. All Gsplats from
// to generate Gsplats into the world for SparkRenderer. All Gsplats from
// SplatGenerators across the scene will be accumulated into a single
// SplatAccumulator, which are sorted and rendered together.
//
+1 -1
View File
@@ -1,6 +1,6 @@
import * as THREE from "three";
// SplatGeometry is an internal class used by ForgeRenderer to render a collection
// SplatGeometry is an internal class used by SparkRenderer to render a collection
// of Gsplats in a single draw call by extending THREE.InstancedBufferGeometry.
// Each Gsplat is drawn as two triangles, with the order of the Gsplats determined
// by the instance attribute "ordering".
+2 -2
View File
@@ -1,6 +1,6 @@
import * as THREE from "three";
import init_wasm, { raycast_splats } from "forge-internal-rs";
import init_wasm, { raycast_splats } from "spark-internal-rs";
import { PackedSplats } from "./PackedSplats";
import { type RgbaArray, readRgbaArray } from "./RgbaArray";
import { SplatEdit, SplatEditSdf, SplatEdits } from "./SplatEdit";
@@ -389,7 +389,7 @@ export class SplatMesh extends SplatGenerator {
this.constructGenerator(this.context);
}
// This is called automatically by ForgeRenderer and you should not have to
// This is called automatically by SparkRenderer and you should not have to
// call it. It updates parameters for the generated pipeline and calls
// updateGenerator() if the pipeline needs to change.
update({
+3 -3
View File
@@ -1,6 +1,6 @@
import * as THREE from "three";
// Forge controls for keyboard + mouse, game pad, or mobile multi-touch
// Spark controls for keyboard + mouse, game pad, or mobile multi-touch
const DEFAULT_MOVEMENT_SPEED = 1.0;
const DEFAULT_ROLL_SPEED = 2.0;
@@ -54,11 +54,11 @@ const ARROW_KEYCODE_ROTATE = {
Delete: new THREE.Vector3(1, 0, 0),
};
// ForgeControls provides simple, intuitive controls for navigating 3D space that
// SparkControls provides simple, intuitive controls for navigating 3D space that
// use the keyboard + mouse, game pad, or mobile multi-touch. Internally it
// instantiates and updates a `FpsMovement` and `PointerControls` instance.
export class ForgeControls {
export class SparkControls {
fpsMovement: FpsMovement;
pointerControls: PointerControls;
lastTime = 0;
+3 -3
View File
@@ -1,5 +1,5 @@
export { ForgeRenderer, type ForgeRendererOptions } from "./ForgeRenderer";
export { ForgeViewpoint, type ForgeViewpointOptions } from "./ForgeViewpoint";
export { SparkRenderer, type SparkRendererOptions } from "./SparkRenderer";
export { SparkViewpoint, type SparkViewpointOptions } from "./SparkViewpoint";
export * as dyno from "./dyno";
@@ -70,7 +70,7 @@ export {
HandMovement,
} from "./hands";
export { ForgeControls, FpsMovement, PointerControls } from "./controls";
export { SparkControls, FpsMovement, PointerControls } from "./controls";
export {
isMobile,
+2 -2
View File
@@ -1,7 +1,7 @@
import { Gunzip } from "fflate";
import * as THREE from "three";
// Miscellaneous utility functions for Forge
// Miscellaneous utility functions for Spark
import {
LN_RESCALE,
@@ -598,7 +598,7 @@ export function unpackSplat(
// Compute a texture array size that is large enough to fit numSplats. The most
// common 2D texture size in WebGL2 is 4096x4096 which only allows for 16M splats,
// so Forge stores Gsplat data in a 2D texture array, which most platforms support
// so Spark stores Gsplat data in a 2D texture array, which most platforms support
// up to 2048x2048x2048 = 8G splats. Allocations that fit within a single 2D texture
// array layer will be rounded up to fill an entire texture row. Once a texture
// array layer is filled, the allocation will be rounded up to fill an entire layer.
+2 -2
View File
@@ -1,4 +1,4 @@
import init_wasm, { sort_splats } from "forge-internal-rs";
import init_wasm, { sort_splats } from "spark-internal-rs";
import type { TranscodeSpzInput } from "./SplatLoader";
import { unpackAntiSplat } from "./antisplat";
import {
@@ -24,7 +24,7 @@ import {
setPackedSplatScales,
} from "./utils";
// WebWorker for Forge's background CPU tasks, such as Gsplat file decoding
// WebWorker for Spark's background CPU tasks, such as Gsplat file decoding
// and sorting.
async function onMessage(event: MessageEvent) {