fix(export): unbreak bakes and STL/OBJ exports on malformed/placeholder meshes (#466)
- roof-system: replace BoxGeometry placeholders (initial swap + empty-roof merged shell) with a group-less degenerate geometry — a Box's 6 groups against the roof's 4-material array crashed GLTFExporter on every scene with a segment-less roof node (prod: 'reading isShaderMaterial'), and count-0 groups crash MeshBVH's packed-tree build. - glb-export: sanitizeMaterialGroups pass repairs any mesh whose geometry groups don't line up with its material array before GLTFExporter runs. - export-manager: give neutralised (attribute-less) meshes an empty position attribute before STL/OBJ export — both exporters read position.count unconditionally. - bake-exporter: log the full error stack so the bake worker's console relay captures it in the job's error trail. - viewer: host-controlled disablePostFx prop (Viewer → PostProcessing) that skips building the SSGI/denoise pipeline entirely; the ?disable=postFx URL flag previously only bypassed it per-frame while still allocating it. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
9b5e229770
commit
f6ffb93a39
@@ -345,6 +345,14 @@ interface ViewerProps {
|
||||
*/
|
||||
sceneReadyKey?: string | number | null
|
||||
onSceneReadyChange?: (ready: boolean) => void
|
||||
/**
|
||||
* Skip the TSL post-processing pipeline (SSGI/denoise/ink/outline) and render
|
||||
* the scene directly. For headless/capture surfaces (the bake page) where
|
||||
* frame quality is irrelevant: on a software-rasterised worker the pipeline
|
||||
* consumes the whole CPU budget and bakes time out. Equivalent to the
|
||||
* `?disable=postFx` diagnostic URL flag, but host-controlled.
|
||||
*/
|
||||
disablePostFx?: boolean
|
||||
}
|
||||
|
||||
/** Imperative handle exposed via `ref` on `<Viewer>`. */
|
||||
@@ -371,6 +379,7 @@ const Viewer = forwardRef<ViewerHandle, ViewerProps>(function Viewer(
|
||||
isolate,
|
||||
sceneReadyKey,
|
||||
onSceneReadyChange,
|
||||
disablePostFx = false,
|
||||
},
|
||||
ref,
|
||||
) {
|
||||
@@ -549,7 +558,7 @@ const Viewer = forwardRef<ViewerHandle, ViewerProps>(function Viewer(
|
||||
kind's `def.system` is loaded via lazy() and rendered here,
|
||||
ordered by `system.priority`. */}
|
||||
<RegisteredSystems />
|
||||
<PostProcessing hoverStyles={hoverStyles} />
|
||||
<PostProcessing disablePostFx={disablePostFx} hoverStyles={hoverStyles} />
|
||||
{selectionManager === 'default' && <SelectionManager />}
|
||||
{(perf || PERF_OVERLAY_ENABLED) && <PerfMonitor />}
|
||||
{children}
|
||||
|
||||
@@ -126,8 +126,11 @@ function sanitizeOutlineObjects(objects: Object3D[]) {
|
||||
|
||||
const PostProcessingPasses = ({
|
||||
hoverStyles = DEFAULT_HOVER_STYLES,
|
||||
disablePostFx = false,
|
||||
}: {
|
||||
hoverStyles?: HoverStyles
|
||||
/** Host-controlled equivalent of `?disable=postFx` — see the Viewer prop. */
|
||||
disablePostFx?: boolean
|
||||
}) => {
|
||||
const { gl: renderer, invalidate, scene, camera, size } = useThree()
|
||||
const renderPipelineRef = useRef<RenderPipeline | null>(null)
|
||||
@@ -264,6 +267,19 @@ const PostProcessingPasses = ({
|
||||
}
|
||||
|
||||
const perfDisable = readPerfDisableFlags()
|
||||
|
||||
// postFx off (host prop or ?disable=postFx): never allocate the pipeline —
|
||||
// useFrame's null-pipeline branch direct-renders. Before this check the
|
||||
// URL flag only skipped the pipeline at render time; the build still
|
||||
// allocated every pass.
|
||||
if (disablePostFx || perfDisable.postFx) {
|
||||
hasPipelineErrorRef.current = false
|
||||
if (renderPipelineRef.current) {
|
||||
renderPipelineRef.current.dispose()
|
||||
}
|
||||
renderPipelineRef.current = null
|
||||
return
|
||||
}
|
||||
const ssgiEnabled = shading === 'rendered' && SSGI_PARAMS.enabled && !perfDisable.ao
|
||||
const denoiseEnabled = ssgiEnabled && !perfDisable.denoise
|
||||
const outlineEnabled = !perfDisable.outline
|
||||
@@ -521,6 +537,7 @@ const PostProcessingPasses = ({
|
||||
// whole pipeline. The uniform refs below are stable (useMemo), so they
|
||||
// never trigger a rebuild either.
|
||||
camera,
|
||||
disablePostFx,
|
||||
hoverHiddenColor,
|
||||
hoverPulseMix,
|
||||
hoverStrength,
|
||||
@@ -556,7 +573,12 @@ const PostProcessingPasses = ({
|
||||
sanitizeOutlineObjects(outliner.selectedObjects)
|
||||
sanitizeOutlineObjects(outliner.hoveredObjects)
|
||||
|
||||
if (PERF_POST_FX_DISABLED || hasPipelineErrorRef.current || !renderPipelineRef.current) {
|
||||
if (
|
||||
disablePostFx ||
|
||||
PERF_POST_FX_DISABLED ||
|
||||
hasPipelineErrorRef.current ||
|
||||
!renderPipelineRef.current
|
||||
) {
|
||||
try {
|
||||
if ((renderer as any).setClearAlpha) {
|
||||
;(renderer as any).setClearAlpha(transparentBackground ? 0 : 1)
|
||||
|
||||
Reference in New Issue
Block a user