From d4f174677cb4e07acf08c516805ac36eb162ae96 Mon Sep 17 00:00:00 2001 From: Andreas Sundquist Date: Tue, 17 Jun 2025 18:32:42 -0700 Subject: [PATCH] Add examples/webxr/ single-html example. Linked in index.html. Improved the experimental hands.ts interface. Fixed issue with single-camera WebXR. Added valley.spz to assets.json, added to assets repo. --- examples/assets.json | 4 ++ examples/webxr/index.html | 134 ++++++++++++++++++++++++++++++++++++++ index.html | 1 + src/SparkRenderer.ts | 5 +- src/SplatEdit.ts | 4 +- src/hands.ts | 5 +- 6 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 examples/webxr/index.html diff --git a/examples/assets.json b/examples/assets.json index 5cf95d3..1997065 100644 --- a/examples/assets.json +++ b/examples/assets.json @@ -98,5 +98,9 @@ "arrow.glb": { "url": "https://sparkjs.dev/assets/models/arrow.glb", "directory": "models" + }, + "valley.spz": { + "url": "https://sparkjs.dev/assets/splats/valley.spz", + "directory": "splats" } } diff --git a/examples/webxr/index.html b/examples/webxr/index.html new file mode 100644 index 0000000..7cf10c5 --- /dev/null +++ b/examples/webxr/index.html @@ -0,0 +1,134 @@ + + + + + + + Spark • WebXR + + + + + + + + + diff --git a/index.html b/index.html index 420956d..07fe9cd 100644 --- a/index.html +++ b/index.html @@ -142,6 +142,7 @@
  • Dynamic Lighting
  • Particle Animation
  • Particle Simulation
  • +
  • WebXR
  • Editor
  • Viewer
  • diff --git a/src/SparkRenderer.ts b/src/SparkRenderer.ts index 7e25256..818c0e6 100644 --- a/src/SparkRenderer.ts +++ b/src/SparkRenderer.ts @@ -375,10 +375,7 @@ export class SparkRenderer extends THREE.Mesh { // In WebXR mode we are called multiple times, once for each eye, // so use their average to compute the sort center. const cameras = renderer.xr.getCamera().cameras; - this.defaultCameras = [ - cameras[0].matrixWorld, - cameras[1].matrixWorld, - ]; + this.defaultCameras = cameras.map((camera) => camera.matrixWorld); this.defaultView.viewToWorld = averageOriginToWorlds(this.defaultCameras) ?? new THREE.Matrix4(); } diff --git a/src/SplatEdit.ts b/src/SplatEdit.ts index d6578ff..4591de8 100644 --- a/src/SplatEdit.ts +++ b/src/SplatEdit.ts @@ -208,7 +208,9 @@ export class SplatEdit extends THREE.Object3D { if (this.sdfs == null) { this.sdfs = []; } - this.sdfs.push(sdf); + if (!this.sdfs.includes(sdf)) { + this.sdfs.push(sdf); + } } removeSdf(sdf: SplatEditSdf) { diff --git a/src/hands.ts b/src/hands.ts index 670e4ae..38f2932 100644 --- a/src/hands.ts +++ b/src/hands.ts @@ -240,8 +240,6 @@ export class XrHands { onFrame: () => { let splatIndex = 0; for (const handedness of HANDS) { - const active = this.values[`${handedness}MiddleThumb`]; - const xrHand = this.hands[handedness]; for (const [index, segment] of JOINT_SEGMENTS.entries()) { for (let i = 1; i < segment.length; ++i) { @@ -274,8 +272,6 @@ export class XrHands { if (handedness === "right") { color.set(1 - color.r, 1 - color.g, 1 - color.b); } - - color.lerp(WHITE, active); opacity = 0.75; } mesh.packedSplats.setSplat( @@ -294,6 +290,7 @@ export class XrHands { mesh.packedSplats.numSplats = splatIndex; mesh.packedSplats.needsUpdate = true; mesh.numSplats = splatIndex; + mesh.updateVersion(); }, }); return mesh;