mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-07 04:12:15 +00:00
e4844753cb9a836cda170d2a416412b3ca875ff1
40 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9a79588575 |
doc, engine, ui: placing the model returns its error; placements are checked where they are set
doc: world_state, world_state_reusing, state_in_frame_at, state_in_frame, face_point_state, face_point_names and construction_state return Result. A body that could not be placed, a frame that could not be inverted, a sketch plane or thread axis that did not survive the placement, or a failed placing worker used to leave things where they were without a word; now the call fails with what could not be placed. is_placement is the one test of an occurrence's placement (finite, a rotation that does not mirror, a translation within 1e9 mm). Opening a design names every occurrence that fails it; add_occurrence refuses one; a joint solution that would place an occurrence outside one is not applied and the joints placing it report it. engine: Session::world_state returns Result and keeps a failure in its cache as it keeps a placed model. bounds, home_camera, open_sketch_plane, the scene builders, the world previews, frames::to_local and auto_operation pass the error on; helpers answering "not found" take the placed model from their caller. Commands setting a placement check it (valid_position, exploded view, fastener at a point, STEP insert matrix). ui: panels, picks and hovers read the session's placed model through open_meshing::session_world; a model that cannot be placed shows no placed bodies, and the viewport says why across its bottom. Pictures and the control channel report the error. cli, mcp: snapshots, renders, benches and the oracle report the error; the kernel-case rig records it as the case's failure. Tests read the new Results with unwrap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt |
||
|
|
42997a62ed |
WIP kernel: Body::mesh(&MeshTolerance) as the one mesher (does not build yet)
Body::mesh / mesh_plan / mesh_of and MeshTolerance (chord, display, display_of, export_of) replace tessellate, tessellate_with, display_mesh*, display_plan*, reference_display_mesh_angular; every caller in kernel, doc, engine, io, ui-egui, gpu and the CLI renamed mechanically; the truck-mesher fallback, mesh_shells*, refined* removed; Body::new orients from the planner; truck-meshalgo dropped from Cargo.toml with the tests of its hooks. Still to fix: trait imports in tess/*, splitface/lumps/preview/step_in/boolean_record meshalgo uses, measure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt |
||
|
|
efa2cae0b4 |
Viewport: draw faded and see-through bodies from their plans with OIT (#7423)
* Viewport: palette-indexed scene and incremental appearance updates - Move triangle, line and instance colours and opacity into a per-scene palette (an R32Uint texture, WebGL2-safe); appearance edits update palette entries instead of vertex bytes. - Build CPU body triangles as one canonical vertex stream per block with opaque/glass/faded index lists; an opacity class change rewrites only the index list. - Cache resolved body appearances by a per-body key, so an edit resolves only the bodies whose look changed. - Split the model scene key from the session revision: selection and view-only commands no longer rebuild or upload the model scene. - Replace the O(n^2) section-index lookup and per-placement instance scan with hash lookups. Co-Authored-By: Claude Code <noreply@anthropic.com> * Viewport: skip unchanged palette work when rebuilding - Reuse each body's appearance key while the document is unchanged. - Leave a palette slot alone when its value did not change, and allocate every body's slots once before the build loop. Co-Authored-By: Claude Code <noreply@anthropic.com> * Viewport: measure scene rebuild cost by edit kind An ignored scale test times the scene build after selection, appearance, theme and one-body geometry edits at 200, 1,000 and 5,000 bodies. Co-Authored-By: Claude Code <noreply@anthropic.com> * Viewport: read faded grid alphas through the scene palette The grid-fade tests now resolve line palette indices instead of reading the line record's old colour byte. Co-Authored-By: Claude Code <noreply@anthropic.com> * Viewport: measure rebuild cost on few large meshes Adds the 20/100-torus case where a block rebuild used to re-emit a large part of the model. Co-Authored-By: Claude Code <noreply@anthropic.com> * Viewport: measure rebuild cost on an assembly Unique detailed parts plus one component placed many times, timed for selection, part and component colour, opacity, theme, hide and move. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: draw block classes as vertex runs, not index lists A body's vertices are three per triangle in mesh order, so each draw class is a few runs of the block's vertex buffer: all-opaque blocks need no index buffer, and an opacity class change uploads nothing. A fragmented class (more than 64 runs) falls back to one index buffer. Each triangle is written as one record into a block reserved up front, which takes the cold scene build of a 7.1M-triangle assembly from 97 ms to 55 ms (main: 83 ms). Also fix reindexing a block whose bodies are drawn elsewhere: it walked the mesh's triangles from that body's start, past its own vertices. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: draw the highlight's own block, and light faded bodies without copies The highlight scene keeps its feedback (a hovered face, a body copied on the CPU) in a block of its own; since blocks became vertex runs, only the model's blocks were drawn, so that feedback was uploaded and never shown. Draw the highlight's blocks with its triangles. Whole faded and see-through bodies (another component active, or an appearance below full opacity) were lit by copying every triangle on the CPU at each hover change: 85 ms for a design row of 812 bodies. They are now drawn again from the model's own block vertices, in the highlight palette with their slots set to the highlight colour, or as placements of the model's shared triangles. The picture is the same as the copy's. Adds a GPU frame benchmark for document-tree hover (ignored test). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: count scene uploads, and keep the sorted glass stream across colour edits Renderer::uploads reports the bytes the model scene's last change uploaded (geometry, placements, palette rows, planned colours, re-evaluated vertices). Without order-independent transparency the global glass stream is kept while the blocks' see-through triangles are the same, so a colour edit on a glass body uploads palette rows only. Tests assert both on a GPU. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: keep palette slots and looks without rehashing every body A rebuild found every body's palette slots by name and wrote them back, allocating and hashing a new key per body, and copied every shown name into a set to check the arena still belongs to the design. Slots are written back only when a body's faces grew, and the looks cache is pruned only when it holds more bodies than are shown. Adds the STEP-file benchmark (SOLIDCRAFT_SCALE_STEP) and the colour command's own time to the assembly benchmark. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: round-pick construction lines through the scene palette The axis and centre feedback for round picks (#4610) drew with a raw colour; on the palette scene it is interned once like the other construction geometry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: draw faded and see-through bodies from their plans with OIT A body faded outside the active component, or see-through, left the GPU tessellation path and was built triangle by triangle on the CPU, so working in a component of a large assembly rebuilt every other body. Where the renderer blends see-through surfaces order-independently (GpuTarget::oit, set by the renderer), a body whose faces share one class is drawn from its plan: chunks are split by class, opaque passes, AO and the section draw only opaque chunks, and the OIT pass draws the rest. The sorted fallback keeps them on the CPU. The model and its highlights decide through one rule (model_plan_class). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Code <noreply@anthropic.com> |
||
|
|
4b327bab1f |
Canvas: the value boxes do not cover the command window (#6608) (#6661)
* claim: #6608 * Canvas: keep value boxes clear of the command window (#6608) * Canvas: describe how value boxes clear the command window (#6608) * Canvas: keep the value boxes clear of the gizmo handles (#6608) * ui-egui: format the value box regression test (#6608) * gpu: the startup MSAA check skips when there is no GPU adapter The check needs a real adapter to draw the multisampled view and to resolve it, so on a machine with no software Vulkan adapter it is skipped, with the reason printed, instead of failing the build. SOLIDCRAFT_REQUIRE_GPU=1 still makes a missing adapter a failure, as in the CI job that has a software adapter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c6d361347f |
Section Analysis: the cap is marked by true depth, so far edges no longer take a cap band (#6328) (#6332)
With a section shown, the marking pass decided where the cap shows (the stencil) and wrote the depth everything after it tests against. #1768 gave it the faces' FACE_BIAS for the second job, so edges draw over their own faces (#1434). For the first job its slope part is unfair: next to an edge where a back face seen through the cut meets a front face, the front face won a band about a pixel wide although the back face is nearer. The cap skipped that band, and the edge line showed through the cut. #6363 marked those samples again from the back faces, pulled toward the eye as far as FACE_BIAS pushes. That closes the gaps beside the edges, but the pull also lets back faces win wherever they lie within the push of a front face, along every body's far silhouettes, and the cap hatches that band. On bherbruck's block, the band away from the cut went from 58 px orthographic and 534 px perspective before #6363 to 618 and 780 with it. In the app, his filleted hub showed it in every frame of a 36-step orbit in both projections. This replaces that pass. While a section is shown the opaque model now draws in four steps (`Cut`): 1. mark: the faces by their true depth (no push): colour, the stencil and depth; 2. a triangle over the viewport sets the depth back to the far plane, colour and stencil kept; 3. push: the faces again with FACE_BIAS, depth only, so the depth is what unsectioned frames have and edges draw over their faces as before; 4. cap: depth only, as #6728 made it; the mark pass has drawn the cap's colour and hatch, as fs_solid draws a back face seen through the cut. The window pass's depth reset and this one are one helper, `depth_reset_pipeline`, for either depth direction, and its passes are built by #6728's `solid_writes`. Unsectioned frames are unchanged. The CPU rasterizer already chose the cap by true depth. Tests (crates/gpu/tests/depth.rs), with the device's float depth and the 24-bit fallback: - a_cut_hides_the_edges_behind_it (new): bherbruck's block cut at y = -16, home view, orthographic and perspective. No edge shows through the cap, and away from the cut the picture is a box of just the kept part's: 0 px orthographic and 1 perspective (main: 618 and 780). - bherbruck's pocket and hub tests from #6363 are kept and pass (pocket 0 px; hub 1 and 2 px over its twelve views, as with #6363's pass). - an_edge_on_a_face_draws_whole_at_any_angle and an_edge_just_behind_a_face_stays_hidden_on_a_large_design also run with a section shown. In the app (safe mode, WARP), with 625 patterned cylinders cut by a section, the frame time is that of main (#6363): 33.5 against 34.3 ms at the home view, 34.1 against 35.2 ms with the model filling the view. Co-authored-by: bherbruck <brennen.herbruck@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
30e9b87b48 |
Render workspace uses the window's graphics backend on Windows (#6592) (#6629)
* claim: #6592 * Keep Windows Render setup on the viewport backend |
||
|
|
4ced1d7bcf |
Viewport: the grid fades with the distance instead of cutting off (#4214) (#4629)
* claim: #4214 * Viewport: the grid fades with the distance instead of cutting off (#4214) The ground grid stopped at a fixed distance from the view, so its edge showed as a cut across the picture. It now fades out with the distance from the middle of the view, and it is gone before either of the two lines that used to cut it: its own edge, and the picture's far plane. Each grid line is drawn in pieces, and each piece is as faint as the fade makes it at the distance where it lies. The 'under' batch is drawn by the overlay pipeline with alpha blending, so the colour's alpha reaches the frame. * The headless grid fades with the distance too (#4214) The headless path (solidcraft-cli snapshot, the home-page thumbnail, the MCP screenshot) drew the grid from the engine's palette, where a line had no alpha: the grid still ended in a cut, and at a low camera angle the cut was in the picture. A SceneLine now carries an alpha, the CPU rasterizer blends with it and the GPU capture passes it on, so the engine's grid can fade. The fade itself moves to the engine, next to the grid's other geometry, and both paths use it: the headless grid now reaches as far on the ground as the view is wide (the ground stretches as it is seen at a slant) and dissolves into the distance instead of ending in a line. * Fix the headless/viewport grid fade divergence (#4214) The engine stretched the grid's size with the slant of the plane it is seen at, the viewport stretched it only on the ground, so on a sketch's plane the picture's grid reached further than the window's (153.42 mm against 120.00 mm). Both now share one grid_ext, which the picture and the window draw the same grid from. * The grid fades out before the picture's far plane cuts the ground (#4214) The window's grid faded against a far plane of its own: the scene's radius clipped by the projection's camera (260 mm away at 400 mm of distance), while the picture itself cuts the ground at the far plane of its own projection (223.7 mm at the same distance, because the projection frames the scene's bounds and not its radius). The grid was still a third of its strength where the picture cut the ground, so the cut showed as a straight line across the view. The fade now ends at the far plane the picture's projection uses, and the grid is gone before that plane cuts the ground. The test that watched the fade now measures the ink of each row of the picture, and checks that the grid is already gone in the ten rows above the row where the far plane cuts the ground: the point it compared before lay beyond that plane, where both renders draw nothing at all, so the comparison was always true. |
||
|
|
36a60a70d9 | Graphics: 1x anti-aliasing where the multisampled view draws nothing (#5819, #5870) (#5832) | ||
|
|
0252f0bf30 |
Render preview: test that it never paints the last Design frame (#5119) (#5120)
#5187 fixed the frozen Render preview: product frames now set ss_ready themselves instead of keeping the flag from the last Design frame, so paint() no longer blits that stale offscreen picture. Nothing tested it. The new test draws a see-through Design frame (offscreen, for order-independent transparency) and then an opaque product frame on the same renderer, and checks the middle pixel shows the product. With the product branch's ss_ready update removed it fails with the stale red Design colour, [255, 129, 129, 255]. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
5012f33c85 |
Section Analysis: bodies behind the cut no longer colour the cap (#6328) (#6728)
The cap pass redraws every back face behind a marked pixel with depth test Always to put the section plane's depth there, and it also wrote colour. The last back face drawn painted the cut, so a body behind the cut (one inside another's hollow, an assembly's inner parts) showed through it in its own colour and outline, like an X-ray. The pass now writes depth only; the marking passes have already drawn the nearest back face's colour (the same split as #4622). Test: a_body_behind_the_cut_does_not_colour_the_cap in crates/gpu/tests/capture.rs (a red body in a green box's hollow, 4 mm behind the cut: the picture is the same with and without it, hatched and plain, orthographic and perspective). On main 472 pixels differ. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
13b4f6e98c |
Viewport: a selected edge's highlight no longer shows as a wedge on a grazing face (#3544)
* Viewport: lift selected and hovered edge highlights toward the eye A selected edge's highlight (3 px core, 6 px halo) is a screen-space band that was depth-tested at the edge's own depth. A face next to the edge seen at a grazing angle is pushed back by only about a pixel of its slope, so it buried part of the band, unevenly along the edge: the highlight showed as a thin wedge instead of a line. The band is now drawn like a thin cylinder around the edge: its depth is pulled toward the eye by half its width plus a pixel, measured on screen so it holds at every zoom. Plain model edges keep their depth (#1434 still holds); the part of a highlighted edge the model really hides stays dimmed through hidden_line. Not yet compiled or tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Viewport: lift an edge highlight by how steeply its faces are seen The first lift (half the band's width plus a pixel, the same on every edge) was not tied to the faces beside the edge. Each highlight segment now carries the normals of the two faces it borders (octahedral, packed with its width in the line's width slot, read as u32 by vs_line): the band is pulled toward the eye by its half width times how steeply those faces are seen, so a grazing face no longer buries it, and an edge seen square to its faces is not lifted at all. Test: a_selected_edge_on_a_grazing_face_draws_whole (tilts 60 to 88 degrees, small and large designs, orthographic and perspective; the band 5 mm behind a face stays hidden). Capturer::rgba_highlighted draws a highlight scene as the viewport does, for that test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8d63a9f4cb |
Theme: the viewport keeps the previous colours until the camera moves (#5802) (#5835)
* claim: #5802 * fix: repaint on a theme change and key the frame cache on the theme tints (#5802) theme::apply asks for a repaint, so the new visuals are painted on the next pass instead of waiting for another event to schedule one. The gpu frame cache key now includes the theme's hover and selection tints, so a picture cached under the previous theme's colours is not reused. * test(ui): settle egui's startup repaints before asserting the theme's repaint (#5802) * test(ui): name the call site that asks for the theme's repaint (#5802) * test(ui): apply the theme outside a pass so its repaint request stands alone (#5802) |
||
|
|
2741cd9a8b |
Section Analysis: edges behind the cut no longer show through the cap (#6328) (#6363)
Since #1768 the section's stencil marking draws every face with FACE_BIAS. Where a back face seen through the cut meets a front face along an edge (a pocket's wall and its side wall or floor, a fillet and the face it runs into), the slope push decided which was nearer beside that edge; a front face winning left those samples unmarked, the cap skipped them, and the edge, drawn at its own depth, showed through the hatch. In perspective, and while orbiting in orthographic too, edges popped in and out from frame to frame. A second marking pass draws the back faces only (front faces culled, depth test <=, no depth write), pulled toward the eye as far as FACE_BIAS pushes faces back, before the cap. The depth buffer keeps FACE_BIAS, so edges on visible faces still draw whole (#1434). Tests in crates/gpu/tests/depth.rs: a pocket 2 mm behind the cut, and a filleted hub with a bore and a cross hole seen from twelve directions, both depths, orthographic and perspective. On main the pocket shows 45 px of edges through the cap in perspective and the hub 25 px over the views; with this change 0 and at most 2. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
4b119dd471 |
Performance overlay: frame-time graph and histogram, triangles, draw calls (#2548) (#2549)
* Performance overlay: frame-time graph and histogram, triangles, draw calls (#2548) Net change of the perf-overlay branch, rebased onto main as one commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Document frame_rate_details in ui.prefs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> |
||
|
|
9e6e0b8df1 |
Render workspace: complete experimental ribbon, resources and effects integration (#5493) (#5494)
* wip(render): reconcile completed material and image pipeline source with 0.20 (#5493) Source-only integration reference for staged review, not a merge-ready aggregate. Donor: 0xlillith/solidcraft@aea20b0115. Upstream: |
||
|
|
b7b25f9e2b |
Render workspace: first basic delivery to main (#6050)
* Normalize UI container violation paths across platforms (#5599) Report repository-relative paths with forward slashes so diagnostics and the existing nested-package regression assertions agree on Windows and Unix. Keep the container detection rules unchanged. Validation: official ui-containers gate and all seven focused xtask tests passed; rustfmt and diff checks passed. Only xtask/dependencies were compiled; no application build or heavy tests. (cherry picked from commit |
||
|
|
9aaa8016e5 |
gpu tests: give the two test frames the new hover and selection tints (#5698)
#5109 added Frame::hover_tint and selection_tint; two test frames that landed alongside it didn't set them, so solidcraft-gpu's tests stopped compiling on main. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8301d1c48e |
Viewport: whole-body highlights reuse the model's own triangles (#4554) (#5109)
Hovering or selecting whole bodies -- a browser row, a History group, a body under the pointer in body-pick mode -- built a CPU copy of every body's triangles into the highlight scene. On a 40-body 4.3 MB STEP assembly that was 147 bodies, 70 MB of triangle copies and a 519 ms frame. The model already has the same geometry on the GPU. The highlight now names it and the renderer draws it again in the highlight colour: - bodies drawn from a display plan: the model's evaluated plan chunks, with a hover/selection tint uniform (the chunks stay resident in the model scene); - bodies drawn as placements of shared triangles: the same placements of the model's shared triangles, coloured per instance; - bodies the model builds on the CPU: their vertex range in the model scene's block. See-through and faded bodies keep the CPU feedback, which colours them; faces and edges highlighted on their own are unchanged. The highlight looks the same (verified side by side). On the assembly the highlight build drops from 519 ms to 9 ms and no longer copies any triangles; selecting the whole assembly takes 9-20 ms. Co-authored-by: Claude Code <noreply@anthropic.com> |
||
|
|
769dfff1a5 |
Section Analysis: a Hatch option (#4563) (#4565)
* claim: #4563 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Section Analysis: a Hatch option, off for a plain cut in the body's colour (#4563) The Section Analysis dialog gets a Hatch check box beside Flip, and inspect.section a hatch?: bool (default true), so scripts, the CLI and the control channel reach it too. Hatched, a cut is its body's colour tinted toward the cap colour with 45 degree stripes, as before; off, it is the body's own solid colour. The viewport (cap alpha in the uniform), the CPU rasterizer and ui.render follow it, and the section keeps it when hidden and shown again or edited. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0fb4a3e868 |
GPU tessellation: an empty plan no longer fails buffer validation (#5049) (#5104)
* claim: #5049 * GPU tessellation: an empty plan no longer fails buffer validation (#5049) Empty tessellation inputs were padded to 16 bytes, smaller than the shader's 32-byte vertex and 48-byte surface records, so wgpu refused the dispatch. Skip the dispatch when there is nothing to evaluate, and pad each empty buffer to one whole element of what the shader reads. |
||
|
|
5962f56f87 |
Viewport: reuse still pictures and draw scenes into a 1x window pass (#4820) (#5187)
* Viewport: show the picture it drew last when nothing changed (#4820) A frame redrew the whole scene whenever egui asked for a frame, even when the camera, scene, highlight and overlays were identical: pointer moves over empty space and UI animations over a still view paid for the full scene. The renderer now hashes everything the picture depends on (scene keys, camera, size, section, images, analysis, accessibility map, occlusion) and blits the last offscreen picture when the hash matches. The first still frame filters a supersampled picture down once and later frames copy it as it is. A frame with the same content costs a blit instead of a scene draw. Co-Authored-By: Claude Code <noreply@anthropic.com> * Viewport: draw the scene offscreen, into a 1x window pass (#4820) The scene keeps the app's depth, stencil and MSAA, but egui's window pass now has one sample and no depth. Whenever the two targets differ, the scene (product previews too) is drawn offscreen and blitted, so the UI pass no longer clears and resolves a multisampled window. Over 8 s of pointer moves on the 450E rotor head, the app's GPU intervals fell from 1325 ms to 1006 ms and egui_render from 892 ms to 509 ms; idle stays at 0%. A GPU test checks the split path's picture matches the direct one. Co-Authored-By: Claude Code <noreply@anthropic.com> * 3D mouse: a repeated report at rest asks for no frame (#4820) A device may repeat its latest report while the cap rests. Publishing it again asked egui for a frame although nothing changed. Only a report that changes the reading now asks for one; while the cap moves, the view asks for the next frame itself. Co-Authored-By: Claude Code <noreply@anthropic.com> --------- Co-authored-by: Claude Code <noreply@anthropic.com> |
||
|
|
8b1a722f06 |
Viewport: the ground shadow no longer sends every frame through the transparency path (#5230) (#5255)
* claim: #5230 * Viewport: draw the ground shadow on the direct path (#5230) The ground shadow went into the model's translucent triangles, so every frame with a body counted as see-through and took the order-independent transparency path. Give it its own batch, drawn alpha-blended after the opaque geometry as before, so only truly see-through bodies use that path. |
||
|
|
92d3a2fde5 |
GPU: a lost device stops drawing instead of crashing (#4172) (#4229)
* claim: #4172 * GPU: a lost device stops drawing instead of crashing (#4172) After the driver resets the GPU (Windows TDR), the first queue write to meet the lost device panicked inside wgpu-core (PendingWrites::activate unwrapping DeviceError::Lost). Nothing watched the device for its loss. - egui-wgpu: RenderState::device_lost (DeviceLost) is set by the device's lost callback. The painter draws nothing on a lost device, and before a frame's uploads it submits nothing (DeviceLost::probe), so a loss the driver reports is found by that submission instead of the first write. - Pictures (thumbnails of saves, ui.render) watch the same flag: on a lost device the capturer refuses with GpuError::DeviceLost without touching it, and the picture comes from the CPU rasterizer. Headless capturers watch their own devices. - The app, seeing the loss, closes keeping unsaved changes for recovery (as a forced quit does) and starts again; the new start says what happened. A second loss within ten minutes starts on the software renderer. The loss is noted in the crash journal. |
||
|
|
75261cd797 |
Viewport: order-independent transparency for see-through surfaces (#4734) (#4903)
* Viewport: levels of detail for large meshes (#4724) A large instanced mesh (20 k triangles or more) gets coarser copies, made once on a worker (`mesh_lod`): a quarter, a sixteenth and a sixty-fourth of its triangles, by quadric edge collapse (`geom::simplify`, after Garland and Heckbert 1997; no fold-overs, no sheets joined, open boundaries kept), each with its measured deviation from the full mesh. Each frame, as placements are culled, each is drawn from the coarsest copy whose deviation stays under 0.75 px where it stands (`placement_scale`, `level_for`). Until the copies are made the mesh is drawn in full; the scene is built again when they are. Display only: picking, measuring and exports keep the reference mesh. Outside the kernel. 25 placements of a 2 M-triangle STL, 3600 x 2190 px, 4x MSAA, M2 Max (`instanced_scene_gpu_benchmark`): 20.2 -> 1.2 ms a frame with all in view, 21.9 -> 2.9 ms close up. The copies take 10 s to make, on a worker. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: see-through and faded parts drawn as instances (#4888) See-through (an appearance's opacity) and faded (context around an active component) bodies in one colour are drawn as instances like opaque ones, their alpha in each placement's colour: one copy of the triangles, levels of detail and culling, no per-placement copies built on the window thread. Their placements are ordered back to front each frame (not their triangles one by one) for devices that sort see-through surfaces. The GPU benchmark gains `SOLIDCRAFT_BENCH_OPACITY` and the CPU share of each frame, and its pictures each placement's own triangles too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: order-independent transparency for see-through surfaces (#4734) The model's see-through surfaces (glass, faded context; instanced or not) were sorted back to front triangle by triangle on the window thread whenever the view turned. They are now drawn with weighted blended order- independent transparency (McGuire and Bavoil 2013): when there are any, the frame is drawn into the renderer's own textures (as supersampling does), the see-through surfaces gathered into a weighted colour and a revealage target against the frame's depth, laid over the frame in one full-screen pass, then the overlays drawn over them. Nothing is sorted. A device that cannot blend into float targets keeps the sorted way. 25 placements of a 2 M-triangle STL at opacity 0.5, M2 Max, 3600 x 2190 px: about 10 s a frame sorted, 21.6 ms (17.2 ms instanced, 2.8 ms with levels of detail). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
f843a3f83c |
Picking: remove the GPU pick buffer, the per-body BVHs answer alone (#4665) (#4666)
The pick buffer drew the model's surfaces and edge ids for every still view to narrow which edges a pick tests. Measured against the BVHs alone (release, M2 Max, 1400 x 900 view, 600 cursor positions), a pick costs 2-51 us through the BVHs and the tile saved 0-4 us of it, while each pass cost 0.7-12.5 ms of GPU time per still view, plus gathering its scene on the window thread, read-backs a frame or two late and repaints to wait for them (and, before, a copy of every triangle, which made it refuse models past 6 M triangles). Picks are unchanged: the BVHs give the same answers. `pick_timing_on_curved_models` gains eight layers of bodies seen from above (the pick buffer's best case) and `SOLIDCRAFT_BENCH_MESH` placements. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
981d23d1d2 |
Viewport: weld a large mesh's shared vertices quicker, and ahead of its first frame (#4679) (#4680)
`SharedTris::new` used the standard SipHash hasher and collected each triangle's corners into a Vec: 451 ms for a 2 M-triangle STL on the window thread. A quick hasher for the coordinates' bits and a fixed array make it 278 ms, and the background mesher that meshes an opened or inserted file's bodies now welds their large meshes too (`warm_shared_tris`), so the first scene that shows them takes the shared vertices ready-made. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
3d3dd27439 |
Viewport: leave out placements of an instanced mesh that are out of view (#4646) (#4647)
* claim: #4616 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: draw a part placed many times from one copy of its triangles (#4616) A part placed by many occurrences was drawn, framed and picked from a moved copy of its mesh per placement: on the CPU (the moved mesh and its scene bytes) and on the GPU (its vertices uploaded once per placement). - The model scene draws bodies that share a mesh as GPU instances: the shared triangles once, a rigid move and colour per placement (`InstancedMesh`, `vs_tri_inst`), in the solid, section and AO passes. `GpuScene::merged` expands them, so scene tests see world triangles. - `ModelBody::mesh_in_place`, `plan_mesh_in_place_at`, `mesh_bounds` and `display_identity` give the shared mesh, its placement, the exact box and an identity without making the moved copy. - Display refinement's body ids, Fit/Home bounds, the viewport's body boxes, the background mesher and picking use them (picking moves the ray into the part's frame and shares one pick index). 25 placements of a 2 M-triangle STL on an M2 Max: orbit 45 -> 37 ms a frame, footprint 41 -> 16 GB, 24 copies 39 -> 18 s. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: draw large meshes from shared, indexed vertices (#4637) An instanced mesh's vertices are shared between its triangles and drawn indexed (`SharedTris`). A flat-faceted mesh (an STL's facets) shares them by position alone and lights each fragment with its triangle's own plane (`vs_tri_inst_flat`, `fs_*_flat`), taken from the fragment's position relative to the eye so it stays exact at any zoom; its vertex outputs are kept few, since a tiled GPU stores every vertex's outputs. A body alone is drawn this way from 50 k triangles. A mesh too large for one buffer falls back to unshared vertices. `instanced_scene_gpu_benchmark` (manual, ignored): 25 placements of a 2 M- triangle STL at 3600 x 2190 px, 4x MSAA, M2 Max: 21.3 ms a frame for the placements' own triangles, 16.1 ms shared and indexed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Viewport: leave out placements of an instanced mesh that are out of view (#4646) Each frame `Batches::cull` keeps the placements whose box may be seen (`placed_box_in_view`: all eight corners past one side of the view in clip space, so it holds behind the eye too) and writes them again only when that set changes. The manual benchmark gains `SOLIDCRAFT_BENCH_CLOSE=1`: close up on the middle of 25 placements of a 2 M-triangle STL (13 in view), 3600 x 2190 px, 4x MSAA, M2 Max: 28.2 ms a frame for the placements' own triangles, 17.2 ms instanced and culled. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
93a2922c5e |
Display plans and the model cache for large STEP assemblies (#2814) (#4021)
* STEP import: mesh band faces that wrap around a closed surface correctly Fixes two related bugs that caused SolidCraft to fail to mesh a face wrapping all the way around a closed, non-periodic surface (a revolved ridge band, or a tube-shaped B-spline surface): a missing face, a folded/self-overlapping triangulation, or a hole in the rendered body. 1. Ring edges that run slightly off their surface. STEP files write a surface and the curves bounding it to the file's own declared uncertainty, so a ring edge can legitimately sit a few micrometres off the surface it bounds. The code finding where a ring edge crosses the planned split line compared against the edge's raw (off-surface) point using a hardcoded tolerance far stricter than the file's own precision, rejecting a valid cut. Now matches against the point on the surface directly below the ring crossing, respecting the file's declared tolerance. 2. Closed B-spline surfaces, their slits and their slivers. truck only treats the rotation of a revolved surface as periodic; a face on a B-spline surface whose control net closes on itself (a tube) wasn't recognized as wrapping around at all. This produced a folded face, a hole (a boundary loop landing a full period away from where it should cut), and one near-zero-width sliver face costing the entire body its tessellation plan. Adds periodicity detection for closed B-spline surfaces, period- aware hole-loop alignment, dropping of zero-width slit boundaries, and isolating a too-thin-to-triangulate face so it no longer takes the rest of the body down with it. The GPU shader's periodic wrap mirrors the CPU math so the two don't drift apart. Regression tests: band_faces_split_when_ring_edges_run_off_their_surface, band_face_with_a_zero_width_slit_is_still_meshed, a_sliver_face_too_thin_to_triangulate_does_not_cost_the_body_its_plan. Ablation-tested: disabling either mechanism in (2) reproduces its target test's original failure message while leaving the other test unaffected. * STEP import: mesh the band's split faces, not just split them jyviko asked whether a band wall missing from the interactive app's render was a shading issue or a genuinely missing face. It was missing: the ring- edge split fix made the band's topology correct, but plan_face still produced zero triangles for the two new sub-faces. Two causes, both in plan_face (crates/kernel/src/tess/mod.rs): 1. The tolerance for how far an imported boundary may lie off its surface was tied to the requested mesh's chord tolerance instead of to the body's own size. A finer display tolerance could then reject a boundary a coarser one had just accepted, so the face would drop out exactly when zooming in on it. 2. Near a sharp corner of this flat-panelled band, several boundary points that are legitimately a few micrometres apart (within the STEP file's own declared precision) all projected onto the same surface point. The boundary loop then repeated a point in (u, v), which a triangulator can't follow, so the face's plan failed outright. One face without a plan costs the whole body its plan, and the fallback mesher can't handle a closed B-spline surface either, leaving both halves of the split band with no triangles at all: present in the topology, invisible in every renderer, and absent from the body's volume. Fix: scale the off-surface tolerance to the body's own extent (new Rules::extent), and collapse a run of boundary nodes that land on the same surface point to one (drop_collapsed) before triangulating. Regression test additions to band_faces_split_when_ring_edges_run_off_their_surface: the body's volume now matches the analytic pentagon prism (was a third of it - only the top cap - before this fix); display_plan leaves no face without triangles from coarse to fine tolerance; and the actual tolerance and facet angle the viewport draws with gives the split band its full lateral area on both halves. Confirmed on review_band_big.step, the fixture behind the review screenshots: volume's relative error against the analytic pentagon prism drops from 1.4e-4 to 4.1e-6, and the band wall now occludes the floor grid behind it in a snapshot the same way the top and bottom caps always did. Full kernel suite: 739 tests, 0 failed. * STEP import: hold an imported boundary to the file's own tolerance, not the part's size jyviko: the off-surface acceptance added in the last commit (rules.extent * OFF_SURFACE) scaled with the part, so a 2 m part silently accepted a boundary 2 mm off its surface while a 20 mm copy of the same part accepted only 0.02 mm. A STEP file's own declared uncertainty does not grow with the part, so the bound shouldn't either. Body gains boundary_tol: Option<f64>, Some(file's declared tolerance) for a body read from STEP (crate::step_in::Units::tol, already used by the ring-split fix in split.rs), None for anything this kernel built. It's set before the import's own unmeshed-face check runs, and carried over by the two face-split operations that re-cut an imported surface (splitface.rs, outline.rs), since the file's uncertainty still describes those boundaries afterward. plan_face's accept now reads: the file's own tolerance when the body declares one, or the old chord-tolerance/extent bound otherwise. The old bound's tol * 10.0 term had to go too, not just the extent term: at a 2 m part's typical display tolerance that term alone is ~20 mm, nearly ten times the extent bound jyviko objected to, so keeping it would have left the exact 2 m/2 mm example still silently accepted. Two new tests in step_in/tests.rs: - band_faces_split_when_a_scaled_copy_runs_off_its_surface: the same band fixture at a realistic 2 m scale with the same absolute slop and declared uncertainty as the small one, meshes the same way at every chord tolerance from coarse to fine. - off_surface_budget_follows_the_file_not_the_part_size: the actual regression. The same off-surface error is accepted or refused the same way whether the part is 20 mm or 2 m; a 2 mm error against a 1 µm declared uncertainty is refused at both sizes now (accepted at 2 m under the old bound, refused at 20 mm - that asymmetry was the bug). Checked at both a coarse and a fine display tolerance. Known gap, not fixed here: a STEP-imported body saved into a .solidcraft design and reopened loses boundary_tol (native.rs's decoder has no field to read it from) and falls back to the old extent-based bound on reload. Today's design format has no concept of this value at all; persisting it is a real format change, out of scope for this fix. Full kernel suite: 776 tests, 0 failed. clippy -D warnings clean. * Display plans for STEP threads and pointed ends (#3847) Three faces cost a threaded or pointed STEP part its whole display plan, so it was drawn from the reference mesh: cracked, faceted, and never refined up close. - A loop through a pole (a cone's apex on the boundary) seemed to wind around the surface: the jump at the apex, unwrapped to the nearest copy, was arbitrary. The loop is turned to end where it leaves the pole, so the step that closes it is an ordinary one (`seam::close_through_pole`). - Projection onto a spline with hundreds of spans (a helical flank) restarted from a 16 x 16 grid and settled on another turn; it now starts from two points per span, capped. - Sag refinement no longer inserts a point exactly on a boundary side, which split the side and failed the face. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * tess: a refused face's edges are divided finer and it is planned again (#2814) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * tess: sliver faces plan empty; a face no method plans is filled flat from its nodes (#2814) A face whose boundary runs out and back along itself (two edges between the same vertices, a rounding apart, as STEP files write slivers) encloses nothing and is planned with no triangles. A face still refused after its edges are divided finer (a cusp, a sliver whose sides sag across each other, a small cap at a pole) is filled flat from its shared boundary nodes, so the rest of the body keeps its display plan instead of falling back to the reference mesh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * display mesh tests: a rim the chord tolerance leaves a line is divided again (#2814) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * portable B-rep: up to 8192 control points along a spline direction (#2814) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * solidcraft-cli: --debug logs what the engine reports to stderr Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * STEP import: a spline written over a tiny parameter range is read over one (#2814) Some writers parameterize splines over a few millionths (a humanoid robot's edges span 5.4e-6). The kernel tells parameters apart only to 1e-6, so over such a range it evaluated the curve's end wrongly, and trimming an edge to its vertices dropped a control point: the bodies could not be stored exactly and the whole model cache was left out of the design. The knots are now stretched to span one; the curve is the same and edges are trimmed by their vertices, so nothing read from the file refers to the old parameters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * model cache: a body keeps its file's declared accuracy (#2814) A body restored from the cache dropped the accuracy the file it was read from declares, so the planner held its boundaries to the kernel's own bound and a reopened design drew differently from the import. It is stored with the body's runtime values, and only when there is one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * tess: a boundary within a hundredth of its body lies on its surface, at every quality (#2814) #1721 held a body read from a file to the accuracy the file declares. A writer declares what it aims for, not a bound its edges keep: a 251-body robot assembly declaring 0.01 µm has boundaries 10 to 30 µm off their surfaces, and 95 of its bodies lost their display plans. The bound is a hundredth of the body again, what Normal quality always allowed, and now the same at every quality, so zooming in still never drops a face (#1721's point). A file declaring more raises it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * STEP import: keep faces whose edge vertices sit slightly off their curves Some exporters write an edge's vertex beside the end of its curve, further off than the accuracy the file declares (a surface export declares 0.01 mm and puts a vertex 0.19 mm off two spline ends). The reader refused such edges and left the face, and with single-face bodies the body, out. A vertex may now sit up to the file's tolerance or 1/1000 of the model's size (the diagonal around its VERTEX_POINTs), whichever is larger, never more than the existing 1 mm ceiling. Spline and open-conic edges have the end control point moved onto the vertex, so every such edge meets its vertices exactly. The file's declared accuracy still governs closed-curve, seam and circle checks. * tess, io: review clean-ups (#2814) - A sliver face is one whose loops are all slit: drop_slits finds it in the retry after a failed plan, so the pre-check on every face (folded) is gone. - The flat fill uses cdt::triangulate (a lenient fill that leaves out sides crossing one already kept) and its flood-fill inside test, and the plane from geom::Plane. - Refinement only builds its indexes when a face was refused, takes the faces to plan again from edge_faces, and re-samples edges on the pool; Rules::finer for the finer rules. - One PackageWriter::fits for the model cache, the preview and the thumbnail. - The band split's ring tolerance lives in split.rs; comments say what the off-surface bound is now. - The CLI logger prints Level::as_str(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM --------- Co-authored-by: David Lackovic <lackovicdavid1234@gmail.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> Co-authored-by: Ray <raykholo@users.noreply.github.com> |
||
|
|
511faedcfa |
Fix OpenGL startup with portable AO depth reads (#2888) (#2933)
* claim: #2888 * fix: preserve AO depth in a portable integer texture (#2888) |
||
|
|
26f42ae09b |
Snapshot: draw a see-through appearance see-through, and show a tool body inside its target (#2329) (#2330)
* Snapshot: draw a see-through appearance see-through, and give the CLI --body, --tool and --section A headless picture dropped a body's opacity: the scene carried only a colour, so a design with a translucent appearance was drawn opaque by `solidcraft-cli snapshot`, by MCP screenshots and in a design's thumbnail, although the window has always drawn it as glass. There was then no way to look at the body a cut would remove inside the material it meets: only a volume to measure and reason about, which hides exactly the errors a picture makes obvious (a tool that stops short, or lands in the wrong place). - `SceneMesh` carries the body's opacity; `view::build_scene` takes it from the design (`model_body_opacity`), and a selected body stays solid so the selection colour reads. - The GPU capture routes a see-through body into the scene's glass at its own alpha, as the viewport does; the CPU rasterizer draws the solid bodies first (they own the depth buffer), then the see-through ones blended over them, far sides before near sides and without writing depth, so what lies inside shows and a line between the two is not hidden. - `snapshot --body NAME:opacity=0.3,color=#rrggbb`, `--tool NAME` (that body solid in the tool colour, the rest see-through) and `--section z=27` run the commands the app itself runs (`appearance.assign`, `inspect.section`): the options are shortcuts, not a second renderer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Tests: measure the tool colour as it is drawn through a see-through target The tool-colour filter was derived on paper and demanded a red more than twice either other channel, which the target in front of it tints away (measured: (200, 108, 85) through opacity 0.3); and the colour check painted the tool, which a solid target hides. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fmt * Snapshot options: strip the colour's # rather than slicing it; README Slicing `value[1..]` on an input-derived string is what the house rules ask us not to write, even where a length check has already made it safe. The error a failed assignment reports now names the body rather than claiming it came from --body, since --tool reaches it too. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * --tool: assign the bodies around the tool in groups, not one command at a time Each appearance.assign is an undo step with a document snapshot behind it, so one per body made --tool cost grow with the size of the design for no reason: the bodies around the tool all get the same opacity, and the ones that share a colour can be named in one call. A design whose bodies all wear the default grey now costs two commands whatever its size. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Rasterizer: say where its glass and the GPU's differ Splitting each see-through body by facing orders its own two layers; it does not sort across bodies, which the GPU does. Worth stating rather than leaving a reader to find it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> |
||
|
|
a9c7616e7f |
Lines thinner than a pixel no longer vanish without multisampling (grid lines, #2823) (#2871)
* claim: #2823 * fix(view): lines thinner than a pixel no longer vanish without multisampling (#2823) A line quad narrower than a pixel covers no pixel centre when it falls between two rows, so the grid's 0.7 px lines came and went as the view zoomed where the viewport draws without 4x MSAA (some browsers and devices). Such lines are now drawn a pixel wide, faded by the width they lack. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
d8d04c9009 |
Tool modifiers: shared resolve, classic defaults, preview-safe Ctrl (#1616)
* Centralise tool modifiers with classic defaults and preview-safe Ctrl. Route sketch/selection chords through a shared resolver. Keep Alt snap suppress and dual toggle as defaults; optional Shift add-only and Ctrl snap mapping. Skip preview rollback while a manipulator drag is active. * Address #1616 review: classic snap suppress, single viewport owner, docs. Default suppress to Ctrl/Cmd or Alt; drop navigation set_suppressed; remove unused label_key; add preview rollback gate test; document sketch modifiers. * fix(#1616): correct Modifiers primary in tests; simplify rollback fixture. * Treat Ctrl as primary off macOS, and rustfmt the modifier files. |
||
|
|
8e762fee57 |
Add optional ambient occlusion and graphics quality presets (#1135)
Thanks @CypherNaught-0x. |
||
|
|
c5f3515073 |
Viewport: hidden edges no longer show through faces, and thin or coplanar faces stop z-fighting (#1434, #1739) (#1768)
Thanks @CamWight. |
||
|
|
8907da5e86 |
Viewport picking: a BVH per body mesh and a GPU pick buffer for visible edges (#1776)
Thanks @oursland. |
||
|
|
741265f214 |
Create Sketch shows the origin planes through the model (#1755) (#1757)
Thanks @pablopeza. |
||
|
|
1a0b33fcf3 |
Headless pictures draw on the GPU, with the viewport's pipelines (CPU rasterizer as last tier) (#1555)
Thanks @jyviko. |
||
|
|
ec64564f21 |
Fix the startup crash on D3D12 with FXC: CPU fallback for the tessellation pipeline, FXC-friendly shader (#1098) (#1099)
* GPU tessellation: a pipeline the device cannot build falls back to CPU meshing instead of crashing (#1098) Build the tessellation compute pipeline inside error scopes; TessGpu::new returns an error, and the viewport logs it and meshes bodies on the CPU. A Windows CI job builds the pipeline with D3D12's FXC on the WARP adapter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tessellation shader: basis functions in one-dimensional local arrays, so D3D12's FXC compiles it (#1098) FXC has to unroll loops that write an array inside a struct (Basis.n0/n1) or a 2-D array (ndu) by a counter, and cannot with run-time trip counts (X3511). A2.2 basis functions in a local 1-D array returned whole; derivatives from the degree p-1 functions; the pole step offsets computed rather than indexed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
587cf865b8 |
Display tessellation plans (4/4): one GPU dispatch for the scene, intersection edges by Newton (#806)
Packs the scene's planned bodies into one GPU upload and dispatch, and evaluates intersection edges by seeded Newton refinement from a fitted B-spline through exactly solved leader points, falling back to the previous evaluation near tangency. Intersection nodes carry their faces' parameters. This changes speed, not what the app draws. Part 4 of 4 of #303. Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> |
||
|
|
ff7a347013 |
Display tessellation plans (3/4): display meshes from plans, GPU evaluation in the viewport (#805)
Display meshes are built from tessellation plans, with GPU evaluation in the viewport. |