Files
solvecraft/examples/studio
bherbruck 03b8f4138b New designs save as .sc; .solidcraft files still open (#7325)
* claim: new designs save as .sc

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* New designs save as .sc; .solidcraft files still open and keep their name on Save

DESIGN_EXT is now "sc"; DESIGN_EXTS lists sc, solidcraft and solvecraft and
every open path (dialogs, drag-drop, recent files, CLI, MCP, links, the web
picker) accepts all three. Save of an opened .solidcraft file writes that
file; Save As, autosave, recovery and crash reports use .sc. Windows, macOS
and Linux register .sc alongside the older extensions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Update UI tests for the .sc default extension

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 22:41:40 +00:00
..

Original SolidCraft studio scenes

These are editable command recipes, not imported models or triangle meshes. Every part is authored here from sketches, extrusions, primitive solids, boolean cuts and swept pipes. There are no manufacturer logos, copied product assets or external textures. author_scene.py is the optional local authoring tool; the application reads the emitted JSON without Python.

Lighting study

stage1.json is a five-body study of a hollow rounded black shell, an exploded lid, a chrome sphere and puck over a real floor. stage1-render.json supplies three rectangular softboxes and a neutral environment, with no clear-coat or transmission overrides. This separates lighting review from material review.

Exploded coffee machine

coffee-exploded.json contains 32 named B-rep bodies. The cylindrical brewing head has an open horizontal bore, separate collar, recessed shower screen and capsule slot in its floating roof. A round swept chrome lever has ball ends. Other parts include a hollow D tank and detached matte lid, a hollow ribbed bin, D drip tray, a 42-hole stainless grate, rounded cap, nine-slot/four-hole service panel, eight slotted zinc screws and an S cable ending in a two-pin plug.

The tank is cut from one extruded solid, leaving 3 mm walls and a 4 mm base. Its semicircle is a 64-chord editable sketch: maximum outer radial deviation from the ideal 43 mm circle is 43*(1-cos(pi/128)) = 0.01295 mm. This is a deliberate geometry fixture approximation. The analytic-arc version produced unpaired tessellation edges at the current 1e-6 mm dielectric topology check; we did not relax that check or repair the renderer mesh silently. The emitted tank has 532 triangles with paired opposite directed edges; the bin has 178. Both pass an independent OBJ edge check at the same 1e-6 mm position precision. These counts describe the baseline CLI and are to be rechecked after integration.

coffee-exploded-render.json adds seven coated-plastic bodies and two closed dielectric bodies. Body indices and names are both explicit and must match render.scene; editing the body list requires regenerating those indices. Smoky brown tank absorption is [0.045, 0.075, 0.12] per mm at IOR 1.586; the bin is nearly colourless at IOR 1.49. The black lid is opaque and matte. Metal is isotropic GGX; the grate is satin, not a claim of anisotropic brushed shading.

Both render requests are 1920 by 1080, use an explicit front-left camera 30 degrees above horizontal, and have no lens override or depth of field. Three large area lights and a neutral environment illuminate a real white-grey floor. The floor extends beyond the camera's horizon intersection and fills the image; it is a finite large studio floor, not an infinite-plane/shadow-catcher feature.

For a true cyclorama, stage1-sweep.json and coffee-exploded-sweep.json replace only that floor with an extruded, closed YZ cross-section. Its exact circular inner curve is tangent to the horizontal floor and vertical wall; the concentric outer curve gives constant thickness. There is no geometric crease or separate floor/wall overlap at either join. author_sweep.py regenerates these variants from the baseline recipes. Use the corresponding baseline render request; all object, light and camera coordinates, appearances, body names and body ordinals are unchanged.

The stage1 sweep is 3000 mm wide, with a 4 mm thickness, a floor starting at y=-1500, a 200 mm inner radius starting at y=250,z=0, and a rear wall at y=450 rising to z=1500. The coffee sweep scales these dimensions by 2.8: 8400 mm width, 11.2 mm thickness, floor start y=-4200, a 560 mm curve starting at y=700,z=0, and wall y=1260 rising to z=4200. Both are real shadow-receiving opaque CAD solids, not image backplates. Integrated GPU comparison determines the final lighting presentation; existing flat-floor evidence remains separate.

materials.json maps semantic names to intended material classes. Saved appearances remain the opaque PBR preview. Runtime optical controls belong to the render request, independently of engineering material properties.

Geometry review

The recipes were initially replayed and saved with the compatible pre-existing CLI during authoring. The integrating worker rebuilds the exact source and repeats replay, geometry checks and GPU preflight before publishing render evidence. Reference volumes below are calculated from the authored dimensions; the measurement command integrates a tessellation, so a relative tolerance of 0.0003 is appropriate for these isolated checks.

Body Analytic volume, mm³
Coated curved shell 65805.30723760049
Floating coated lid 25908.18530717959
Chrome sphere 102160.40430453529
Chrome floating puck 12666.901579274047
Open brewing head 265024.75625683495
Perforated stainless grate 15815.487854690262

For the tank use the polygon area, not the ideal circle: with D(r,b)=2*r*b+32*r*r*sin(pi/64), its volume is 171*D(43,45)-167*D(40,42). Every body must have positive finite measured volume and one kernel shell; transparent boundaries additionally require paired opposite edges, one connected triangle shell and positive signed volume.

Example replay (outputs belong outside the repository):

solidcraft-cli run examples/studio/coffee-exploded.json --save coffee.sc
solidcraft-cli eval coffee.sc --json-out coffee-measurements.json

Use the evidence runner with the paired render-request JSON to capture runtime lighting/material controls. The plain render CLI does not load that JSON as its request automatically.

Thick tumblers in an original room

tumblers.json is a separate 69-body scene. Two thick, open, tapered glass tumblers rest on a dark walnut table, with a filleted upholstered sofa, soft rectangular cushions, a potted plant, and a real slatted window behind them. author_tumblers.py defines every dimension. The glass is made by revolving closed radial sections: tall outer radii 36/42 mm and height 112 mm, 4.5 mm walls and a 9 mm bottom; short radii 37/43 mm and height 94 mm, 5 mm walls and a 10 mm bottom. These are analytic curved B-reps, not polygon replacements.

tumblers-render.json supplies a warm small area light behind the blind slats, two broad fill panels, two closed dielectric overrides and a thin lens. It is 1920 by 1080, with a 5.5 mm aperture radius and 670 mm axial focus distance. The blind shadows require real light transport; the recipe contains no painted shadow texture. tumblers-materials.json lists semantic material classes and suggested world-coordinate texture projections. The scene's saved walnut and linen appearances are plain colours: grain, woven texture and normal-map transport must be provided by the integrating renderer and are not implied by these material names.

tumblers-sun.json and tumblers-sun-render.json are a separate daylight variation; the original studio-lit recipe and request are unchanged. The only geometry change is a real 1850 by 1080 mm opening through the rear wall at x = -1450..400, z = 760..1840. Without this opening, the intact rear wall would occlude the infinite sun even where rays passed between the modelled blinds. The sun points toward [-0.4, 1, 0.4], has a finite 0.00465 rad angular radius, and uses warm radiance [18000, 16500, 14000]. An original procedural sky gradient supplies cooler fill; it is an artistic gradient, not an atmospheric simulation or an imported environment photograph. No extra area lights are used in this variation. The camera, lens, glass and sample settings are retained.

From the table point [0, 0, 480], the central sun ray reaches [-576, 1440, 1056] at the blind front and [-800, 2000, 1280] at the rear-wall opening. The ray is above the sofa; the blind slats, 12 mm thick and 45 mm apart, therefore produce real directional shadow stripes on the table. Their 52 mm depth also affects the occluded band width. Finite-disk softness and the final visible pattern must be checked in a GPU render; these analytic coordinates do not substitute for it.

On the authoring baseline the two tumbler meshes have 4856 and 4160 triangles. Independent topology checks using Euclidean 1e-6 mm seam matching find zero unpaired directed edges. Rounded integer keys alone rejected a few points on opposite sides of a quantization boundary despite their sub-tolerance distance. The accompanying renderer fix searches adjacent cells at the same tolerance; it preserves original vertices, winding and connected-shell checks. Integration must rerun those tests and GPU admission before claiming this scene rendered.

All three scenes have positive finite measured volume and one kernel shell per body on the authoring baseline. The evidence report must state the exact rebuilt source and backend; the initial CPU snapshots are composition checks only.

Runtime showcase requests (render validation pending)

First generate the original local resource files from the repository root:

python examples/studio/author_showcase.py

The source tree contains generators, editable scenes and runtime requests only. The four PNG maps and RGBE gradient are generated on demand into ignored paths in examples/studio/textures; they are not committed source assets. A fresh checkout must run this command before replaying a textured or HDR showcase request. The script uses only Python's standard library and downloads nothing.

Run the production studio_evidence example from the repository root so its scoped VFS resolves these generated relative resource paths. Rendered outputs belong outside the source tree and may be published only as evidence on the results branch. Use these pairs:

Scene recipe Runtime request Lighting
tumblers.json tumblers-textures-render.json Three finite studio panels and constant fill
tumblers-sun.json tumblers-sun-textures-render.json Finite sun through actual window/blinds and original procedural sky
tumblers-sun.json tumblers-hdr-textures-render.json Same finite sun and authored RGBE sky fixture

These requested settings are not a completed visual milestone. The requests use 1920x1080, 2048 samples, depth16, seed1948, one final aces_fitted output transform, 5.5mm aperture radius and 670mm axial focus. The two closed glass tumblers explicitly enable shadow_transmission. Their matching *-blocked-render.json controls differ only by setting those two flags false. This isolates the optional straight shadow connection; it is not a refracted-caustic solver. Physical camera/reflection/refraction paths remain active.

Thirteen opaque body bindings add the original walnut and woven-linen colour and OpenGL normal maps. Their 26MiB normalized pixels are below the32MiB texture cap. Mapping uses explicit planar world frames; the normal maps do not model yarn geometry and the side faces are not triplanar. Glass stays smooth and unmapped. See texture provenance and textures/manifest.json.

The locally generated HDR file contains only an original analytic gradient, sampled at512x256 and quantized to Radiance RGBE with declared linear-sRGB/D65 primaries. It contains no sun disk or downloaded imagery. The separate finite sun remains identical between the procedural-sky and HDR requests. RGBE quantization means these two inputs need not produce byte-identical renders. textures/environment-manifest.json records its hash, dimensions and authoring parameters.

Regenerate the original room with python examples/studio/author_tumblers.py and the textures/HDR/portable requests with python examples/studio/author_showcase.py. These scripts use Python's standard library. They do not modify the coffee or stage1 recipes. Source validation and asset hashes do not constitute GPU evidence: the final report must include the actual backend, rebuilt source, full-resolution image, metadata and matched blocked-shadow control.