Fix mesh uploading.#40
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds/adjusts Spark rendering integrations to improve Gaussian splat lighting, skinned-mesh depth handling, and worker-based model preview loading.
Changes:
- Introduces
SparkSceneLightingBridgeand wires it intoEffectRendererfor dynamic lighting edits. - Patches Spark composite rendering to render skinned-mesh depth via a WebGL pre-pass and cleans up related resources.
- Refactors the model-preview worker to lazy-load heavy modules and expand DOM/event polyfills; adds a Bun patched dependency for
@querielo/spark.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.config.ts | Restricts React refresh processing via include/exclude. |
| patches/@querielo%2Fspark@2.0.0.patch | Patches Spark’s renderable-object detection to avoid instanceof. |
| package.json | Registers Bun patchedDependencies for @querielo/spark. |
| bun.lock | Locks patched dependency mapping. |
| client/packages/editor-oss/src/render/SparkLightingBridge.ts | New dynamic lighting bridge that converts Three lights to Spark SDF edits. |
| client/packages/editor-oss/src/render/SparkCompositeBridge.ts | Adds skinned-mesh depth workaround using WebGLRenderer and manages temporary state. |
| client/packages/editor-oss/src/render/EffectRenderer.js | Creates/updates/disposes the scene lighting bridge during render lifecycle. |
| client/packages/editor-oss/src/helper/light/VolumePointLightHelper.js | Reimplements helper as LineSegments with explicit dispose/update. |
| client/packages/editor-oss/src/editor/assets/v2/.../render.worker.ts | Improves worker polyfills and lazy-loads GLTFLoader/ModelPreviewRenderer. |
| client/packages/editor-oss/src/editor/assets/v2/.../ModelPreviewRenderer.ts | Tunes preview lighting and only enables Spark composite for Gaussian splats. |
| client/packages/editor-oss/src/editor/Editor.ts | Improves selection boundary logic for skinned meshes. |
| client/packages/editor-oss/src/assets/js/loaders/SparkGaussianSplatLoader.ts | Enables editable: true for loaded splat meshes. |
| client/packages/editor-oss/src/assets/js/animations/poseFit.ts | Removes computeBoneTexture call after pose application. |
| client/packages/editor-oss/src/EngineRuntime.ts | Changes WebGPU/WebGL forcing logic (currently hard-coded). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| private createWebGPURenderer(overrideForceWebGL?: boolean): WebGPURenderer { | ||
| const forceWebGL = overrideForceWebGL ?? (this.editor?.scene?.userData?.rendering?.forceWebGL || false); | ||
| const forceWebGL = !true; |
Comment on lines
+422
to
+427
| private syncSdfColor(sdf: SplatEditSdf, light: Light, overrides: SparkLightOverrides, strength: number): void { | ||
| sdf.opacity = isFiniteNumber(overrides.opacity) ? Math.min(1, Math.max(0, overrides.opacity)) : 0; | ||
| sdf.color | ||
| .copy(getLightColor(light, overrides, this.lightColor)) | ||
| .multiplyScalar(strength); | ||
| } |
Comment on lines
+126
to
+162
| async function updateModelPayload(payload: ArrayBuffer) { | ||
| if (!renderer) return; | ||
|
|
||
| const { GLTFLoader } = await import('three/examples/jsm/loaders/GLTFLoader.js'); | ||
| const loader = new GLTFLoader(); | ||
|
|
||
| let renderer: ModelPreviewRenderer | undefined; | ||
| try { | ||
| loader.parse( | ||
| payload, | ||
| '', | ||
| (gltf) => { | ||
| renderer?.updateModel(gltf.scene); | ||
| }, | ||
| (error) => { | ||
| const payloadType = payload ? payload.constructor?.name ?? typeof payload : typeof payload; | ||
| const sizeInfo = | ||
| payload instanceof ArrayBuffer | ||
| ? `, byteLength=${payload.byteLength}` | ||
| : ''; | ||
| console.error( | ||
| `Worker: Failed to parse GLB (payloadType=${payloadType}${sizeInfo})`, | ||
| error, | ||
| ); | ||
| }, | ||
| ); | ||
| } catch (err) { | ||
| const payloadType = payload ? payload.constructor?.name ?? typeof payload : typeof payload; | ||
| const sizeInfo = | ||
| payload instanceof ArrayBuffer | ||
| ? `, byteLength=${payload.byteLength}` | ||
| : ''; | ||
| console.error( | ||
| `Worker: Failed to parse model (payloadType=${payloadType}${sizeInfo})`, | ||
| err, | ||
| ); | ||
| } | ||
| } |
Comment on lines
+124
to
+152
| const restoreSkeletons = (snapshots: Map<Skeleton, SkeletonState>) => { | ||
| for (const [skeleton, snapshot] of snapshots) { | ||
| const compactLength = skeleton.bones.length * 16; | ||
| const currentBoneTexture = skeleton.boneTexture; | ||
|
|
||
| skeleton.boneMatrices = compactSkeletonMatrices( | ||
| skeleton.boneMatrices, | ||
| snapshot.boneMatrices, | ||
| compactLength, | ||
| ); | ||
| skeleton.previousBoneMatrices = compactSkeletonMatrices( | ||
| skeleton.previousBoneMatrices, | ||
| snapshot.previousBoneMatrices, | ||
| compactLength, | ||
| ); | ||
|
|
||
| if (currentBoneTexture && currentBoneTexture !== snapshot.boneTexture) { | ||
| currentBoneTexture.dispose(); | ||
| } | ||
|
|
||
| if (snapshot.boneTexture) { | ||
| snapshot.boneTexture.dispose(); | ||
| } | ||
|
|
||
| // WebGLRenderer creates a padded boneTexture/boneMatrices pair. The | ||
| // surrounding WebGPU renderer expects compact bone matrix buffers. | ||
| skeleton.boneTexture = null; | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Screen.Recording.2026-06-05.at.14.37.44.mp4
This fixes the skinned-mesh interop path inside the Spark composite bridge when the scene uses both WebGPU and the temporary WebGL depth pass.
Why this fixes it
WebGL and WebGPU were sharing mutable skinning state across the bridge:
This change makes the WebGL pass explicitly transactional: