mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-06 20:02:16 +00:00
stack/render-11087
80 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1b55174743 |
Render: isolate lens saves and retain bounded previews
Save only lens parameters on existing CPU/GPU jobs while keeping unrelated draft settings dirty. Retain pinned checkpoints through preview and status, and release host-only snapshots outside the status lock. Use the admitted PNG bound for registered-executor checkpoint slots. Preserve executor work credits, final publication and regrade ownership. Add regression coverage and align help, translations and capability documentation. |
||
|
|
8829c1c3c5 | Render: restore saved shots, progressive images and exports | ||
|
|
9a274f91df |
Planned bodies: smaller GPU chunks, and a chunk keeps its colours while they are unchanged (#5490)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
|
|
ef2f485e15 |
Extend viewport AO to the existing virtual ground (#3413) (#11979)
* claim: #3413 * feat(gpu): extend viewport AO to the virtual ground * test(gpu): retain measured AO render attachments * perf: initialize ground AO pipeline with concurrent jobs * fix(gpu): size ground AO receiver for the current frame radius * fix(viewport): retain orbit caches when ground AO visibility changes |
||
|
|
727bb23c7e |
Section Analysis: a body standing on another keeps its own cap, also in CPU pictures (#4622)
Where one body stands on another (a post on a plate), the post's bottom, seen through the cut, and the plate's top are the same plane. In the CPU rasterizer (headless pictures without a GPU) the plate's top won that depth tie and showed through the post's cut. The cut now wins a tie by a few f32 steps (DEPTH_EPS). The viewport already draws this right since #6363 and #6728; a GPU regression test now covers it, both creation orders, orthographic and perspective, with both depth formats. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
46ce12b7f0 | perf(ui): reuse assembly rendering caches during orbit (#2889) | ||
|
|
464f4ac748 |
Intel OpenGL: restore the grid and sketch axes (#8053) (#11573)
* claim: #8053 * Intel OpenGL: restore the grid and sketch axes |
||
|
|
2aa45ef3ee |
GPU path tracer: compile the path pipeline one at a time per process (#6706) (#6813)
Each path test opens its own device and compiles the path pipeline. On a cold driver cache that takes minutes and gigabytes per compile, and libtest ran one per CPU thread side by side: on NVIDIA the solidcraft-gpu tests ran for hours and committed ~80 GB. Executor::new now holds a process-wide lock while it compiles; the first compile fills the driver's cache and the waiting ones get the pipeline from there. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
dc38349cbf |
Layer split stage 1: the B-rep record, native body file and Vec/Plane come from solidcore-record (#11496)
* Kernel: the B-rep record and the native body file come from solidcore-record SolidCraft's portable B-rep record (`solidcraft_geom::brep`: brep.rs, topology, history, envelope, part, curve2) and the native body file (`solidcraft_kernel::native`: the tagged binary codec and the container) move to solidcore's `solidcore-record` crate: geometry as data, with structural validation and no maths (solidcore's docs/layers.md, stage 1). Every caller uses `solidcore_record::brep` and `solidcore_record::native`; the old copies are deleted. What computes from coordinates stays with the kernel, in geom's `brep`: - `brep::check`: the record's geometric checks (orthonormal frames, non-degenerate planes, unit revolution axes, non-singular placements). `check::validate` and `check::validate_built` are the record's validation and these together, and every caller of `Brep::validate` uses them, so what is accepted is unchanged; - `brep::label`: a surface's natural ranges (a cone's apex), `curve_interval`, `edge_curve_interval` and `form_turns`; - `brep::pcurve::eval`: a pcurve's point; - `geometry::check`, `placement::moved` and `split_edges` become functions on the record. The kernel's native module keeps the conversion between a body and its saved record (metadata.rs) and checks the decoded record's geometry. `native/analytic.rs`, which no module declared, is deleted. solidcore-record is pinned to its rev on solidcore's `layer-record` branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NvoxKMbMFSQU8tzRtoJhtT * Geometry: Vec2, Vec3, Plane and the profile types come from solidcore-record The plain data of vectors and points, sketch planes and planar profiles (`Seg2`, `Loop2`, `Region2`) moves to `solidcore-record`, with its constants and component-wise operators only (owner decision, solidcore layer split). Their geometry stays in geom as traits: `Vec2Geom`, `Vec3Geom`, `PlaneGeom`, `Seg2Geom`, `Loop2Geom`, `Region2Geom`, `Seg2ArcFit`, `Loop2ArcFit` and `Region2ArcFit`, in scope with `use solidcraft_geom::prelude::*`. Every caller names the types from `solidcore_record`; geom no longer defines or re-exports them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NvoxKMbMFSQU8tzRtoJhtT * Kernel: pin solidcore-record to solidcore main f5e8e9a29 solidcore-record is merged on solidcore main (tangency-labs/solidcore#2519); its crate there is identical to the rev pinned before but for its clippy configuration. The lock is regenerated against the merged rev. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NvoxKMbMFSQU8tzRtoJhtT --------- Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c5ccb9201d |
Wave 43/45: smlib: rustfmt after the C++ kernel's removal (and 1 more)
2 commits, squashed; the originals stay reachable from branch jyviko/merge-main-develop-solidcore (#11360). - |
||
|
|
28e983e191 |
Wave 39/45: diagnostics.kernel takes a typed contract, as main's other diagnostics commands do
1 commits, squashed; the originals stay reachable from branch jyviko/merge-main-develop-solidcore (#11360).
-
|
||
|
|
ea772a0438 |
Merge develop into main: SolidCraft on the SMLib kernel (v1.1.0-alpha) (#11351)
* UI: rim and wall picking tests for a circle of arcs that is one wall A circle drawn as two half arcs now extrudes to one full-turn wall with its seam edge, and each rim is one closed edge (tangency-labs/smlib#67). The tests keep their intent on that body: a rim clicked once is one item, measured and highlighted whole and picked from either side; a wall picked either side of its seam is the same surface, lit whole, and toggles off from the other side; every face is its own patch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fillets: a later round at a corner where earlier rounds meet blends them again with it The owner's ruling of 2026-10-30: a later fillet on an edge at a vertex where earlier rounds already meet in a mitre makes the corner rounding all of them at once makes, one smooth patch, the mitre gone. A body made by constant-radius rounds keeps what they were made on and which edges they rounded at which radius; a later round reaching such a corner blends the earlier rounds' edges (from the earliest of those meeting there on) with the new edges in one SMLib blend of the body before them. The result's history is put over the body the later round was given: an earlier round's face is that face trimmed anew (its name kept), the corner patch and the new rounds are the later fillet's. A picked mitre seam has no round of its own: it is refused unless a new edge of its radius meets it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tests: a later r3 round at an r2 mitre, through the Fillet feature, makes the all-at-once corner Two box edges rounded r2 in one fillet, then the upright edge at their mitre r3 in a second fillet (tangent chain on, so the seam comes with it): 10 faces, 7928.743041 mm³ as fillet_radii of the box gives, the r2 rounds' names kept, the r3 round and the corner patch the second fillet's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Kernel: a body's record of rounds goes with its history, and can be read back The rounds that made a body are over the body its history is over: a new history (an operation carrying a step's result back to its own operands) leaves the record out, so a later round never reads one history against another body. Body::rounds gives the record and Body::with_rounds_of takes one back, checked (edges of the body before them, a fillet's radii, the body's history over that body), for a saved model to keep it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Model cache: a body made by rounds keeps them, so a later round blends them the same after opening A design gave another body when opened from its model cache: the rounds a body was made of lived only in memory, so a later round at their mitre was built sequentially (or refused, as too large) after opening and blended with them when evaluated anew. The saved model now records, per kernel body made by rounds, the body they were made on (a place in the bodies, stored once though no state holds it) and the edges with their radii; reading it attaches them back down each chain, and a thinned model keeps those bodies with the bodies made from them. Model cache format 7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tests: a corner patch of rounds 2/3/4 takes no more than the strips leave in its block three_rounds_at_a_corner bounded the patch's extra cut at 3 mm³ beyond the strips, a figure with no derivation; SMLib's all-at-once body at radii 2, 3, 4 takes 3.099 (V 7878.579574 against strips 7881.678). That body is the strips' outside the block its patch lies in: its rounds are the strips' cylinders ending at a's section y = rc, b's x = 20 − rc and c's rails where they meet a's and b's (the patch's four corners, now asserted), so the patch takes at most what the strips leave in that block (11.86 at 2/2/3, 32.69 at 2/3/4). The lower bound is that block; the upper one, at most the strips' volume, stays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tests: the io crate's hand-built saved models list their rounds, as format 7 records do Model cache format 7 ( |
||
|
|
a9fa61ce77 |
Viewport: the shader compiles in browsers again, so the web app's 3D view isn't black (#11080) (#11107)
* claim: #11080 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Viewport: the shader compiles in browsers again (#11080) The ambient occlusion turn added in #9335 mixed `<<` and `|` without parentheses. naga accepts that, so the desktop app ran, but browsers' WGSL compiler refuses it: the sc_viewport module was invalid, every pipeline built from it failed, and the web app drew nothing once a design was open. The line gets its parentheses, and a test checks every shader in the repository for the rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
325917f2ae |
Ambient occlusion: no artifacts on the preview or on hollow bodies (#9327) (#9335)
* Ambient occlusion: the radius follows what the frame draws (#9327) In an empty design the radius came from the model's box, which is empty, so a preview got the smallest radius and the depth map's precision showed as specks. It now comes from the box the depth range uses, and with nothing to draw there is no occlusion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Ambient occlusion: the term drawn once and blurred by depth (#9327) The lit pass worked the term out for every fragment it shaded, under a pattern that changed from pixel to pixel, which read as grain. The term now has its own texture, drawn once for each pixel of the prepass, with a fixed 4 x 4 pattern, and a 4 x 4 blur that keeps to each pixel's plane takes the pattern out without crossing an edge. The lit pass reads the result. The prepass and the term share their pipelines and draw walk. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
862807ffc9 |
Lost GPU: the per-frame probe meets a D3D12 device reset before the first upload does (#6528) (#7767)
* claim: #6528 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Lost GPU: the per-frame probe opens a command list, as the upload would (#6528) On a reset D3D12 device the empty submission before a frame's uploads went through (it only signals a fence), and the first queue write then panicked inside wgpu-core (PendingWrites::activate unwrapping Lost). The probe now submits a command buffer with a debug marker: finishing it makes the same begin_encoding call, through a path where wgpu loses the device and runs its lost callback instead of panicking. The picture capturer's probe does the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
7366fe0ecc |
Blur behind panels: render path, zero cost when off (#8876) (#9809)
* claim: #8876 * Add optional viewport-only Kawase blur and native UI composition * Fix vendored panel hook imports and deprecated float constant import * Drain texture updates in the full GPU blur fixture * Hold the blur evidence fixture camera fixed across radii * Address blur compositor lint checks * Share animated Render preview background with blur source * Use resolved Design background for blur source * Exercise blur rendering independently of software adapter policy in CI * Use stock egui hosts instead of vendoring the full crate * Preserve feature-window open handling with stock egui hosts * Target the native Window in close-handling regression fixture |
||
|
|
3385d1c570 |
Viewport: dark parts keep their shape: linear-light shading and a sky fill (#7974) (#9028)
* claim: #7974 * Viewport: dark parts keep their shape: linear-light shading and a sky fill (#7974) Preferences > Graphics "Keep the shape of dark parts" (off by default) shades the viewport in linear light: the key light and eye fill over a sky fill that grows as a face turns up, plus the 4% of that sky every dielectric reflects (a little more toward grazing), encoded to sRGB once. Near-black faces keep a gradient; light and mid-grey faces stay within a few levels of the sRGB shading. The world's up direction and the switch ride in a new `sky` vec4 at the end of the viewport uniform, and the frame key, so turning it on redraws. Off, the shader takes the old path unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
526cdfd247 |
Zebra: flat faces keep one stripe colour while the view turns (#2153) (#9761)
* claim: #2153 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Zebra: flat faces keep one stripe colour while the view turns (#2153) A face whose normal lies in the upright plane through the view (every horizontal face) reflects straight ahead, where the zebra's sideways coordinate is zero: exactly on the edge between a black and a white stripe. Rounding then picked one or the other from frame to frame, so the face flickered while the camera orbited. Straight ahead is now white. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
2cf8df2ef6 |
Section caps: a body touching another along a curved face keeps its own cap (#9407) (#9665)
* claim: #9407 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Section caps: a body touching another along a curved face keeps its own cap (#9407) Seen through a cut, a far wall and another body's face lying on it (a shaft in its bore, a ring in its housing) are the same surface faceted two ways, so the marking pass let the other body's face win in streaks. The section's passes now first count the faces behind the cut in the stencil (back +1, front -1): where the count says the cut runs through a body but a front face won, the back faces are drawn again pulled toward the eye by a few pixels and take the cap back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
332f96c26a |
Point clouds: colour and filter by any property the file carries (#8816) (#8819)
* Point clouds: colour and filter by any property of a PLY file, on range tracks (#5151) A PLY file's other vertex properties are kept as named numbers on the points (whole-numbered for integer types; a comment `property: 0 name, 1 name` names a label's values). A cloud is coloured by any of them, a ramp or a palette for whole numbers, and filtered by up to eight, each a range or a set of named values. The GPU colours and filters the points itself, so editing a range uploads nothing. In the Edit Point Cloud card each range is a track, as in an audio editor: a histogram of the property over what the other filters keep, stacked by colour, under an overview strip. Ranges are drawn, moved, snapped to colour changes, typed (Start, End, Length, relative values) and played (Space or Play). The automatic colour range is exactly the values the property takes over what the filters keep. pointcloud.insert and pointcloud.edit take color_by: <property>, color_range and filters; pointcloud.list reports them with the properties. docs/point-clouds.md describes it all. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Point clouds: note the saved properties, colouring and filters as a pending format change (#8816) A design now saves a cloud's per-point columns and their value names, colouring by a property and filters; an older release must refuse it instead of dropping them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
44a9f9ee42 |
GPU path tracer: the path shader compiles on NVIDIA's Vulkan driver (#6705) (#6850)
Native compilers inline every call, and `main` inlined 33 BVH walks: three sample_path calls, and a shadow walk per light source family. NVIDIA's compiler (driver 610.88) crashed in nvgpucomp64.dll or ran out of memory. - main settles the adaptive budget first, then samples at one call site. - direct_light takes over direct_studio, visible and the fixed-light loop: one loop over the sources with one shadow-ray call site, drawing random numbers in the same order. - next_vertex (a select) replaces (a+1u)%3u: after a BVH walk that index crashed NVIDIA's compiler within seconds. main now inlines 5 BVH walks; main_inlines_few_bvh_walks counts them with naga, so the limit holds without an NVIDIA GPU. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
46a2d6b53c |
ui-egui offscreen tests pick their GPU by SOLIDCRAFT_GPU (#9052)
offscreen_device() asked wgpu for its default adapter and ignored the SOLIDCRAFT_GPU policy that headless pictures follow, so with SOLIDCRAFT_GPU=software the ui-egui offscreen tests still opened the hardware GPU. Under hardware or software the adapter now comes from solidcraft_gpu::select (new pick_among, which pick uses too); under cpu there is none; unset (auto) keeps wgpu's default adapter as before. Part of #9040. Claude-Session: https://claude.ai/code/session_013WUFq6QFBqmZjxwaKy2J1M Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8a6a064d37 |
Headless pictures: draw counts come back with the picture they count (#7521) (#7522)
* claim: #7521 * fix: headless pictures return their draw counts with the picture `the_renderer_counts_what_it_draws` drew with `Capturer::rgba` and then read `Capturer::last_stats()`. The capturer is shared with the binary's other tests, which draw on it from parallel threads, so another picture could land between the two calls and the test read its counts (e.g. 10224 triangles for the empty design). `Capturer::rgba_with_stats` returns the picture and its counts, read while the call still holds the device. `last_stats()` is removed; this test was its only caller (the performance overlay reads the viewport renderer's own stats handle). New test `pictures_drawn_at_once_each_count_their_own` draws empty and box designs from eight threads on the shared capturer. Against the old pair it failed 25 of 40 full runs of the `capture` binary; it passes with the new call. * fix: a headless picture waits for its read-back's answer A picture maps its read-back buffer, waits for its submission with `device.poll(PollType::Wait)`, and then checked once with `try_recv` whether the map callback had run. wgpu calls a finished mapping's callback from whichever thread next maintains the device, in a poll or in any `queue.submit`, after it lets go of the device. When another thread got there first, the wait returned with the mapping done but its callback not yet called, and the picture failed with "not supported yet: reading a picture back without waiting for the browser", the error meant for a browser. On the shared capturer, the other thread is another picture's device check (`probe_lost` submits nothing before it takes the capturer's lock), so the `capture` tests failed now and then: `bad_picture_sizes_are_errors` (its last 8 x 8 picture), `pictures_show_a_plain_cut_without_the_hatch`, `pictures_blend_a_line_that_is_not_opaque`. In the app, the window's frames are submitted on the device its thumbnails and `ui.render` pictures are drawn on. A native picture now waits for the answer, up to the picture timeout; a browser still answers later, on its own. New test `pictures_read_back_while_another_thread_uses_the_device`: 2,000 small pictures while another thread polls their device. Without the fix it failed 19 of 20 runs (1 to 7 pictures each); with it, 150 of 150 runs pass. `bad_picture_sizes_are_errors` now prints the error it gets. |
||
|
|
d11d268597 |
Render: reject excessive pixel work during preflight (#5088) (#5728)
* claim: #5088 * fix: reject excessive render pixel work during preflight (#5088) |
||
|
|
cb05e1e0f7 |
GPU path tracer: run on Metal on macOS (#7183) (#7185)
* claim: #7183 * GPU path tracer runs on Metal on macOS, not only Vulkan (#3217) |
||
|
|
884c47496b |
Render preview: geometry budget from the device, readable refusals (#4127) (#4154)
* claim: #4127 * Render preview: geometry budget from the device, readable refusals (#4127) The Render preview refused every scene over a fixed 128 MiB of geometry. On desktop the budget now follows the device's buffer limit (eight of its largest buffers, at most 2 GiB; 2 GiB with the usual 256 MiB buffers). The web keeps 128 MiB. The product upload runs under its own GPU error scopes: an allocation the device refuses is reported in the preview instead of reaching the device's uncaptured-error handler, and the half-uploaded batches are dropped. Buffer uploads map the buffer themselves so a refused buffer fails the upload rather than panicking in create_buffer_init. Refusals name the geometry size and the limit and say how to get under it, on a theme panel card that stays readable on any preview background. * Render preview: keep the previous geometry budget behind a preference (#4127) * Render preview: adapt the device budget to main's GPU upload errors (#4127) |
||
|
|
3cc10acafa |
Render lights: uniform light list, solo and mute, and the Light editor (#6281) (#7265)
* Render lights: uniform light list, solo and mute, and the Light editor * Render lights: Lighting and Light editors to the approved design * Render lights: the scale-test frame carries the product light list * Restore the stable Render light mute target on the shared eye control * fix: validate the viewport BRDF probe with current shader dependencies * fix: compile legacy lighting controls only for tests * fix: scope the legacy lighting preset import to tests * fix: reuse the merged Add Light label and translations * test: enable the implemented Add Light radial action * fix: restrict the legacy CPU vector editor to tests * test: reveal Output before checking Lights browser focus * test: use the published Browser card rectangle for Output scrolling * test: reveal Output children before exercising editor navigation |
||
|
|
0baf49b25f |
Windows: never load a dxcompiler.dll found on PATH; FXC unless DXC ships beside the app (#6756) (#7923)
* claim: #6756 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Windows: never load a dxcompiler.dll found on PATH; FXC unless DXC ships beside the app (#6756) wgpu's Dx12Compiler::Auto loads dxcompiler.dll by name, so Windows takes the first one on PATH. SolidCraft ships none, and DXC 1.8.2505 from other programs' folders (Obsidian, NVIDIA SDK Manager) crashed every start with EXCEPTION_ILLEGAL_INSTRUCTION during the viewport shader compile. solidcraft_gpu::dx12_compiler() now chooses: WGPU_DX12_COMPILER as wgpu reads it when it names a compiler; otherwise DXC from the dxcompiler.dll beside the program, by its full path, else FXC. The window, the headless/CLI instance and the test helpers start with it, and dx12_compiles_with_fxc follows it. WGPU_DX12_COMPILER=dxc keeps the old lookup. Fixes #6756 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
3b983dc550 |
Viewport: vertex markers where edges are drawn (#7834) (#8119)
* claim: #7834 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Viewport: vertex markers where edges are drawn (#7834) Each body's vertices (the ends of its pickable edges, once each) show as small screen-space squares in the edge colour in the styles that draw edges: shaded with edges, wireframe, and shaded with hidden edges, where hidden vertices show faintly like hidden edges. Plain shaded draws none. A marker is a lifted line from the vertex to itself in the body's block, so it is instanced with the edges, cached with them, and depth-tested like a highlight band. The existing vertex hover ring stays on top. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Viewport tests: count edge segments apart from vertex markers (#7834) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Vertex markers: an option, off by default (#7834) Adds the Vertex markers preference (Preferences > Graphics, off by default) and draws the dots only when it is on. 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> |
||
|
|
e6dc105134 |
Point clouds: insert PLY, XYZ and PTS scans as a modelling reference (#5151) (#5381)
* Point clouds: insert PLY, XYZ and PTS scans as a modelling reference (#5151) A point cloud is kept in the design as a reference, drawn as depth-tested dots and never a body. - io: a PLY reader (ASCII, binary little/big endian; x, y, z of any numeric type, optional colours, other elements skipped; counts checked against the file) and XYZ/PTS text, thinned evenly past max_points. PLY meshes with faces can also come in through file.insert_mesh. - doc: Document.point_clouds (shared f32 points relative to an f64 origin, colours, units, rigid placement, size and colour), stored as a binary container part; format change in pending/point-clouds.rs. - engine: pointcloud.insert / edit / delete / list; doc.open opens a cloud as a new design; selection.delete takes point_clouds; view bounds include them. - gpu: an instanced point-sprite pipeline (16 bytes a point). - ui: Browser Point Clouds folder with eyes, menu and an Edit Point Cloud card; drop, Open, Insert and file dialogs take .ply/.xyz/.pts; a CPU viewport fallback; messages in en, en-GB, ja, zh, de and ko. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Point clouds: colour by the file, one colour or height, from the UI (#5151) The Edit Point Cloud card gets Color By (File Colors, Single Color, Height). Height is a blue-to-red ramp over design Z, between the cloud's own two heights or, by default, a range worked out from the points (all but the lowest and highest 2 %, from an even sample). pointcloud.insert and pointcloud.edit take color_by and height_range; pointcloud.list reports them. The colour of each point is worked out in one place (PointCloud::shade) for the GPU and CPU viewports. Also: the card's dropdowns compare the picked index (a dropdown's response doesn't report the pick, so File Units did not change either). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Point clouds: integrate format registration and viewport caches (#5151) * Point clouds: satisfy current UI audits and document comparisons (#5151) Route model RGB data through the theme conversion boundary, provide a compact ribbon label, and include point clouds in the new document comparison. Gate the Unix-only CLI-link helper and test so Windows all-target checks remain buildable after the rebase. * Point clouds: isolate translations for current main (#5151) Move the existing 74 messages unchanged into one pending locale file and attribute it through a pending row, following the current repository workflow. Repository checks, 50 tooling tests, final workspace Clippy, wasm and generated-catalog equality checks passed after the rebase. * Point clouds: fit the rebased code to main's GpuTarget and Frame Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Compare point clouds when reusing placement-independent results Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Point clouds: complete command help and required translations (#5151) * Point clouds: size the save cap from the raised limit after the rebase 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> |
||
|
|
aae2c5e417 |
Assemblies: edit a linked component in place, with the assembly around it (#7672) (#7819)
* Links: update linked designs that changed while the assembly's tab was away A design coming back to its tab compares the modification time and size of its linked design files with what they were when it went to the background, and runs Update Links on the worker thread for those that changed: saved in another tab, another window or by a checkout. Preference update_changed_links (Design, Linked designs) turns it off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Docs: the assembly guide says linked designs update when their tab returns Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Links: Vietnamese strings, now that vi is a complete catalog Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Links: remember what each design last read, so an update that fails is tried again A design's linked files are now recorded as the design last read them: when Update Links reads a link without an error, or when the link is first seen. Coming back to the tab reads again what differs, one link per run, so a file that cannot be read holds up no other and is tried again the next time, and a part changed while the assembly was shown is taken up on its next return. Closing several tabs together reads nothing on the way, and the web build, which keeps no file times, looks at nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Links: no read during a save-changes prompt, records for adopted designs and missing files A tab shown to answer "save changes?" reads no link before its save, and Cancel there or on a batch lets the tab left in front read what it skipped. A design opened in place of the blank one records its links at once, a link whose file is missing is recorded as missing so it is read when the file comes back, and a read queued for a design that is no longer shown by the time it starts is dropped. More changed links than can wait at once are read on the next return. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Assemblies: edit a linked component in place, with the assembly around it Activating a linked component opens the design it comes from in a tab of its own, with the rest of the assembly drawn faded around it where the component sits, so the part's own history, browser and commands are at hand. Finish Editing in the browser saves the part, goes back to the assembly and closes the part's tab when the edit opened it; coming back to the assembly updates the changed link (or Finish Editing runs Update Links when that is turned off). Update Links in the part also reads the assembly's links again, off the window thread, and redraws the assembly around the part; a result for an assembly changed meanwhile is dropped with a message. The part is an ordinary tab, so saving, autosave, recovery, closing and quitting treat it as any other design. The model scene's ghost triangles are now drawn (only the preview's were). Preference edit_linked_in_place turns it off. Builds on the update of changed links when an assembly's tab returns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: a double-click opens it, Activate only activates A double-click on a linked component edits it in place, in the browser as on a face in the view (around the placement clicked), and the component's menu gets Edit in Place. Activate and the browser's radio button make it the active component as they always did, so a linked component can still be activated without opening its design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Double-click on a component's face: edit a linked one in place, activate any other A double-click on a face in the view activates the component the body belongs to, at that placement, as a double-click on its row does; a linked one is edited in place. Bodies of the design itself or of the active component are left alone, and so is a double-click with a modifier. One preference, double_click_components, covers both gestures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: fixes from review An edit whose part never opens is forgotten instead of starting on a later open of the same file, and the web build starts the edit after its synchronous open. Finish Editing goes on only for a save into the linked file and in the part's own tab, waits for a "changed on disk" answer, and says so when the part was saved elsewhere. Showing the assembly no longer drops a refresh, which now records the links it read so coming back reads nothing twice. The faded assembly is worked out once per picture, a bad mesh index skips its whole triangle, and the last two status texts come from the catalogs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: Finish Editing on the MODEL tab and the mouse's back button Finish Editing is a command now, component.finish_edit, with its schemas: the app window answers it, anywhere else nothing changes, as with view.fit. While a linked design is edited in place the MODEL tab ends with a FINISH EDITING panel, pinned at the right as FINISH SKETCH is, with a new left-arrow icon; the browser keeps only the line naming the assembly. The mouse's back button, or a keyboard's Back key, finishes too unless a dialog, tool or sketch is open. The assembly guide describes editing in place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: fixes from the second review Saving the assembly waits while it reads its links for the part Finish Editing waits for dialogs, tools, sketches and prompts open in the part, also when run as a command The assembly reads the edited part explicitly when it does not check its links on its own The FINISH EDITING panel cannot be customized A tab opened by an edit stays that edit's to close when the part is entered again The mouse's back button finishes editing; the keyboard's only while no text field has focus Refreshing the assembly keeps its selection and active component Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: fixes from the third review component.finish_edit run as a command opens nothing and answers with an error when it cannot finish; engine.batch and engine.script refuse it A double-click or Edit in Place while a dialog, tool or sketch is open in the assembly keeps it open What changes in the assembly while it reads its links without changing its document stays: picks, activation, components dragged but not captured Showing the assembly while it reads its links starts no second read A new or opened design in the part's tab ends the edit Finish Editing keeps the part's tab open while its agent chat runs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: Update Links run as a command in the part refreshes the assembly too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: the ribbon button reads Finish Edit, as Finish Sketch does A bare "Finish" took the catalogs' surface-finish translation (German "Oberfläche"). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: fixes from the fourth review Finish Edit waits while the part's agent is in the middle of its turn, instead of keeping the tab of any chat open A part saved while its assembly refreshes is read again when the edit finishes: the refresh records the files as it found them A double-click on a linked component while something is open in the assembly says so instead of activating it Commands are recognised in any spelling the engine takes, so engine.batch and engine.script cannot slip Finish Edit through Update Links run as a command refreshes the assembly from the control channel only, not for the app's own reads Moves of components the refresh removed are not carried over, and a refusal is one message The command description and the guide say that the command does not save the part Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: the command is Finish Edit, as Finish Sketch is Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: a command to start it, and fixes from the full review Added component.edit_in_place {component, path?}: the double-click and Edit in Place in the menu run it, and as a command it asks nothing, so a network location not allowed yet or a design open elsewhere makes it fail instead Finish Edit asked by the part's own agent finishes once that agent's turn ends; the button still waits for the turn The parameters and design properties panels, with text typed and not applied yet, hold up entering and finishing an edit A refresh is not taken up under an undo, a queued command or a feature still being computed in the assembly Refusals say what holds them up (a refresh, a file being read or written) instead of nothing The browser strip names the assembly that is refreshing, not any assembly The schema description says the command does not save the part Korean strings for every new message Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: fixes from the second full review The MCP batch tool refuses component.edit_in_place and component.finish_edit as steps instead of sending them one by one Edit in Place asked while the assembly's agent is in its turn opens the part once the turn ends; a double-click then is refused rather than stopping the agent Both commands answer queued: true when they wait for the agent's turn, and stopping the agent forgets what it queued An undo, a queued command or a delete check running in the design holds up entering and finishing an edit A refresh redraws every edit of the assembly, the parts in other tabs too In an assembly never saved, a double-click activates the linked component as before The control and MCP docs list the new batch and script refusals, and the commands list every way they fail Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: fixes from the third full review The MCP batch tool refuses the two commands however a step names them, an execute step too A queued Edit in Place is checked fully when asked for, a second one is refused, and both queued requests wait for what runs in the design instead of being dropped Disconnecting the agent forgets what it queued, as stopping it does Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit in place: help text for the Finish Edit button main now requires help for every toolbar command (#7134), and Finish Edit is one. Written in every language the branch's catalog carries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
a4d1b5b6a9 |
Viewport: fewer ambient occlusion samples while the view moves (#7165) (#7214)
* feat: Fewer ambient occlusion samples while the view moves (#7165) - Draw AO with 8 samples while the view moves, 32 once it has held still for 0.25 s - Share the settle tracking with adaptive supersampling and repaint when it settles - ui.screenshot waits for the full-quality frame (at most half a second) - Test the sample choice, the uniform slot, and ghosting at both counts * fix: Set the AO sample count in the scale test frame - scale_tests.rs, new on main, builds a gpu::Frame without ao_samples - Use AO_SAMPLES, as the other still-frame builders do --------- Co-authored-by: P'tite Tête <asso@ptitetete.com> |
||
|
|
110efa3598 | Render: allow picking in the product view with a Body, Face or Component filter and outline the selection in the product pass only (#6426) | ||
|
|
e0e2c566e7 |
Viewport: clear new resolve targets so AMD Direct3D 12 shows the scene (#6828) (#7399)
* claim: #6828 * Viewport: clear new resolve targets so AMD Direct3D 12 shows the scene (#6828) With anti-aliasing above 1x the scene is drawn multisampled and resolved into textures that nothing but the resolve writes. wgpu counts the resolve as their first write and never clears them. Direct3D 12 requires a render target placed in reused memory to be cleared, discarded or copied over first, and some AMD Radeon drivers then show the uncleared texture as transparent, a flat colour or speckles: no grid, origin planes or bodies (#6828, #7157, #6613, #7052). Each new resolve texture (the frame's colour and the see-through sums) is now cleared once when it is made. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
5dc95ef7f6 |
Viewport: a frame the GPU has no memory for is drawn smaller, not a crash (#7296) (#7398)
* claim: #7296 * Viewport: a frame the GPU has no memory for is drawn smaller, not a crash (#7296) The viewport's offscreen frame, its see-through targets and the cached still picture were created with no error scope, so a texture the card had no video memory for went to wgpu's default handler and closed the app ("wgpu error: Out of Memory" on a GT 740). They are now created under error scopes; a refused frame lowers the renderer's frame budget and is asked for again smaller (less supersampling, or the view's own frame drawn smaller and filtered up), refused OIT targets fall back to sorted see-through surfaces, and the status line says once that the view is drawn at a lower quality. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Locales: Arabic and Hebrew for the new strings ar and he are complete catalogs on main now (#3458): every new message needs them. The pending-messages test compares right-to-left messages in display order once #7532 lands (#7527). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * GPU memory test: targets take the OIT flag main added (#7296) The test's two GpuTarget initializers predate the oit field and no longer compiled once the branch met main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Locales: Vietnamese for the new strings Vietnamese became a complete catalog on main (#5823), so every new English message needs it too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
3574956d29 |
Graphics: the window no longer waits for Direct3D 12 shader compiles (#4860) (#7288)
* claim: #4860 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Graphics: the window no longer waits for Direct3D 12 shader compiles (#4860) On Direct3D 12, wgpu compiles every pipeline's shaders with FXC when the pipeline is made, and nothing is kept between launches, so the window waited seconds for the viewport. - The GPU tessellation shader, most of that time, compiles on a thread of its own. Bodies are built on the CPU until it is ready, then drawn from their plans; where it never compiles they stay on the CPU, as before. - The viewport's pipelines build in parallel, one job per fragment shader (solidcraft_gpu::concurrent). A job that errs, panics or cannot start runs again on the calling thread, so errors reach the caller's scopes. Threads only on Vulkan, Metal and D3D12 with FXC. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1c109be836 |
Headless pictures: no highlight left over from the picture before (#7225) (#7326)
* claim: #7225 * fix: headless pictures no longer keep the previous picture's highlight Capturer::rgba_highlighted left the highlight slot empty when a picture had no highlight. The renderer keeps its last highlight scene while the slot is empty, so a selected edge's band drawn for one picture showed in the next one on the same capturer. The depth tests share their capturers across test threads, so they failed at random: an edge "192 of 612 px drawn", a washer showing through its plate, a cut showing what lies behind it. A picture now always gets a highlight scene of its own, empty without one. Clearing the leak showed that a_selected_edge_on_a_grazing_face_draws_whole passed at 88 degrees in a design of radius 30 only by counting the leaked band: its reference line lies 143 mm behind the sheet's middle, past that design's far plane, and drew nothing. The small design now holds the edge. New test: a_picture_without_a_highlight_shows_none_of_the_one_before. Full `--test depth` runs on Apple silicon: 10 of 10 failed before, 0 of 20 after. |
||
|
|
76879f8b39 |
Viewport: write hover edges as one record per line, colours interned once (#7416)
Hovering many bodies re-emits every edge in the highlight's colours. Each edge interned its three colours into the palette again, each segment was written in eight small appends, and segments without their faces' normals encoded the same zero normals again. Lines are now one record, the edge colours are interned once per highlight, the buffers are reserved per edge, and the shared width word is worked out once. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
514b0c84f9 |
Viewport: hold the blocks the sorted glass stream was taken from (#6970)
The no-OIT glass cache compared the blocks' vertex and run buffers by address without holding them, so a freed buffer's address could come back for other contents. It now holds them and compares with Arc::ptr_eq. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
ddca1054ab |
Viewport: leave bodies out of the view out of their blocks' draws (#7436)
Instanced placements were culled per view, but a block drew every body in it whatever the camera saw. Blocks now keep each body's vertex span and box; when the view changes, each class's runs are drawn without the bodies whose boxes are out of the view. A block whose bodies are all in view draws its runs as they are. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
e29075376c |
Curvature Map: a scale that lightens steadily from flat to tight (#975) (#6136)
The blue, green, red scale's lightness rose and then fell (L* 44 up to 72 and back to 50), so a flat face and a tight radius looked alike with hue lost, and its upper part merged for a red-green loss. The stops are now dark blue, a middle grey-gold and light yellow in one straight blend, as measured in the issue: L* rises the whole way and every quarter step stays clear for normal, protan, deutan and tritan vision. 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> |