diff --git a/src/client/components/Viewer.tsx b/src/client/components/Viewer.tsx index 9c1060a..9d8338f 100644 --- a/src/client/components/Viewer.tsx +++ b/src/client/components/Viewer.tsx @@ -26,9 +26,15 @@ function Model({ stl }: { stl: ArrayBuffer }) { // Needs preserveDrawingBuffer on the GL context (set on below). function CaptureBridge({ captureRef }: { captureRef: MutableRefObject<(() => string | null) | null> }) { const gl = useThree((s) => s.gl); + const scene = useThree((s) => s.scene); + const camera = useThree((s) => s.camera); useEffect(() => { captureRef.current = () => { try { + // Force a synchronous render into the (preserved) drawing buffer right + // before reading it — otherwise toDataURL can grab a pre-render black + // frame on the first/heavy model and the verifier thinks it's empty. + gl.render(scene, camera); return gl.domElement.toDataURL("image/png"); } catch { return null; @@ -37,7 +43,7 @@ function CaptureBridge({ captureRef }: { captureRef: MutableRefObject<(() => str return () => { captureRef.current = null; }; - }, [gl, captureRef]); + }, [gl, scene, camera, captureRef]); return null; } diff --git a/src/worker/prompts.ts b/src/worker/prompts.ts index a059c82..e5a65ca 100644 --- a/src/worker/prompts.ts +++ b/src/worker/prompts.ts @@ -62,15 +62,15 @@ You'll be given a script and the runtime error it threw. Fix the bug and return // Vision judge. Sees a render of the model and the request; decides if it's a // faithful match. Deliberately lenient about style/colour/detail — only flags // clear structural or feature mismatches worth an automatic refine. -export const VERIFY_SYSTEM = `You are Chisel's quality checker. You are shown a 3D render of a CAD model and the user's original request. Judge whether the model is a reasonable, recognizable match for what was asked. +export const VERIFY_SYSTEM = `You are Chisel's geometry checker for a CAD tool. You are shown a rendered 3D CAD model and the user's text request. Your ONLY job is to judge whether a solid 3D object is present and its shape is a reasonable structural match for the request. -Be pragmatic, not pedantic: -- Colour is always red and lighting is neutral — IGNORE those. -- Minor proportions, surface finish, and small stylistic choices are fine. -- ONLY fail if a requested FEATURE is missing/wrong, the object is unrecognizable, the geometry is clearly broken (holes, stray fragments, collapsed shape), or it's obviously not the requested object. +Rules: +- Treat every model as neutral CAD geometry. Do NOT comment on, judge, or refuse based on what the object represents or depicts — subject matter is irrelevant to a shape-fidelity check, and this is a purely visual/geometric comparison. +- The model is always rendered in solid red on a dark grid. IGNORE colour, lighting, materials, and small stylistic/proportion differences. +- Return matches:false ONLY if: the scene is genuinely empty (literally no object), the geometry is clearly broken (stray disconnected fragments, collapsed/degenerate shape), or the shape is unrecognizable as anything like the request. When in doubt, return matches:true. Respond with ONLY a JSON object, no prose, no code fence: -{"matches": true|false, "critique": "one sentence — if matches:false, the single most important concrete fix, phrased as an instruction (e.g. 'The handle is missing; add a looped handle on one side.')"}`; +{"matches": true|false, "critique": "if matches:false, one sentence with the single most important concrete geometry fix, phrased as an instruction"}`; export function editContext(previousScript: string): string { return `Here is the current design script. Edit it per my next message and return the full updated script.\n\n\`\`\`javascript\n${previousScript}\n\`\`\``;