forked from 1b-agent/opencadstudio-upstream
docs(rendering): drop completed roadmap phases
Phase 1.1 (entity AABB), 1.2 (ViewVolume), 1.3 (CPU cull), 3.1 (sub-pixel
cull), and 3.5 (text simplification) are all live in tree — remove them
from the roadmap. Implementation Order and Key Files tables trimmed to
the still-pending work. TEMPORARY Insert sub-entity guard section now
notes which "proper fix" already landed (per-block cache, def72e4) and
which is still open.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
4d58a905e0
commit
5344d0d6d6
1 file changed
+15
-92
+15
-92
@@ -16,66 +16,11 @@ Current pipeline order:
|
||||
|
||||
**Goal:** Skip CPU upload and draw calls for entities outside the camera view.
|
||||
|
||||
### 1.1 Entity AABB
|
||||
### 1.4 Scissor Rects (Partial — Hatch/Image still pending)
|
||||
|
||||
Compute axis-aligned bounding boxes during tessellation and store alongside each model.
|
||||
|
||||
```rust
|
||||
// Attach to WireModel, MeshModel, HatchModel, ImageModel
|
||||
pub struct Aabb2 {
|
||||
pub min: DVec2,
|
||||
pub max: DVec2,
|
||||
}
|
||||
|
||||
pub struct Aabb3 {
|
||||
pub min: DVec3,
|
||||
pub max: DVec3,
|
||||
}
|
||||
```
|
||||
|
||||
- `WireModel` / `HatchModel` → `Aabb2` (XY plane for 2D; full 3D AABB for 3D wires)
|
||||
- `MeshModel` → `Aabb3`
|
||||
- `ImageModel` → `Aabb2` from insertion point + extents
|
||||
|
||||
Compute once at tessellation time (`scene/tessellate.rs`), store in the model structs, invalidate
|
||||
with the geometry epoch.
|
||||
|
||||
### 1.2 Camera Frustum / Viewport Rectangle
|
||||
|
||||
Extract view bounds from `camera.rs` each frame:
|
||||
|
||||
- **Orthographic (2D):** viewport rectangle in world space — a simple `Aabb2` test suffices.
|
||||
- **Perspective (3D):** extract 6 frustum planes from the view-projection matrix.
|
||||
|
||||
```rust
|
||||
pub enum ViewVolume {
|
||||
Ortho(Aabb2),
|
||||
Frustum([Vec4; 6]), // plane equations
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3 CPU-Side Cull Before Upload
|
||||
|
||||
In `pipeline/mod.rs`, before collecting wire/hatch/mesh draw calls:
|
||||
|
||||
```rust
|
||||
fn is_visible(aabb: &Aabb2, view: &ViewVolume) -> bool {
|
||||
match view {
|
||||
ViewVolume::Ortho(rect) => aabb_overlap_2d(aabb, rect),
|
||||
ViewVolume::Frustum(planes) => aabb_inside_frustum(aabb, planes),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Filter entity lists before the upload loop. Skip `queue.write_buffer` entirely for invisible
|
||||
entities — saves both CPU and GPU bus bandwidth.
|
||||
|
||||
### 1.4 Scissor Rects (Already Partial)
|
||||
|
||||
Viewport scissoring for wires already exists (`wire_pixel_scissors`). Extend same logic to
|
||||
hatch and image passes.
|
||||
|
||||
**Estimated gain:** 50–90% draw call reduction for typical workflows (zoomed in on one region).
|
||||
Viewport scissoring for wires already exists (`wire_pixel_scissors` / `WireModel.vp_scissor`).
|
||||
Extend same logic to hatch and image passes so paper-space viewport content is clipped at the
|
||||
GPU stage instead of overdrawn.
|
||||
|
||||
---
|
||||
|
||||
@@ -119,18 +64,6 @@ let candidates = scene.quadtree.query_rect(view_aabb);
|
||||
|
||||
**Goal:** Reduce geometric complexity when entities are small or far away.
|
||||
|
||||
### 3.1 Screen-Space Size Filter (Sub-Pixel Cull)
|
||||
|
||||
Before drawing, compute projected pixel size of entity AABB diagonal. Skip entities whose
|
||||
projected size is below a threshold (e.g. < 0.5 px).
|
||||
|
||||
```rust
|
||||
let screen_px = project_size(aabb, camera);
|
||||
if screen_px < MIN_VISIBLE_PX { continue; }
|
||||
```
|
||||
|
||||
Applies to all entity types. Effectively free — just a float comparison after AABB cull.
|
||||
|
||||
### 3.2 Wire LOD — Curve Segment Reduction
|
||||
|
||||
Arcs, ellipses, and splines tessellate to N segments (currently fixed). Replace with
|
||||
@@ -185,11 +118,6 @@ pub struct MeshModel {
|
||||
Build LOD 0 eagerly; build LOD 1 & 2 lazily in a background thread (already have
|
||||
async tessellation pattern from `truck_tess.rs`).
|
||||
|
||||
### 3.5 Text & Dimension Simplification
|
||||
|
||||
At low zoom, dimension text and annotation geometry become unreadable. Replace with
|
||||
simplified bounding-box proxies or skip entirely below a legibility threshold.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — GPU-Side Culling (Advanced)
|
||||
@@ -233,16 +161,12 @@ Relevant only for perspective (3D) mode with many overlapping solids.
|
||||
## Implementation Order
|
||||
|
||||
```
|
||||
Phase 1.1 Entity AABB computation low risk, high impact
|
||||
Phase 1.2 ViewVolume extraction low risk
|
||||
Phase 1.3 CPU cull before upload immediate draw call reduction
|
||||
Phase 1.4 Scissor for hatch/image low complexity
|
||||
Phase 2.1 Quadtree for 2D medium complexity, scales 2D docs
|
||||
Phase 3.1 Sub-pixel cull trivial, free perf
|
||||
Phase 3.2 Wire curve LOD medium, affects tessellation cache
|
||||
Phase 3.3 Hatch LOD low complexity
|
||||
Phase 3.4 Mesh LOD high complexity, background thread
|
||||
Phase 2.2 Octree for 3D medium, needed for dense 3D
|
||||
Phase 3.5 Text/dim simplification low complexity
|
||||
Phase 4.1 Indirect draw + GPU cull high complexity, defer
|
||||
Phase 4.2 Hi-Z occlusion high complexity, 3D only, last
|
||||
```
|
||||
@@ -253,25 +177,22 @@ Phase 4.2 Hi-Z occlusion high complexity, 3D only, last
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `src/scene/wire_model.rs` | Add `Aabb2` field to `WireModel` |
|
||||
| `src/scene/mesh_model.rs` | Add `Aabb3`, LOD mesh array |
|
||||
| `src/scene/hatch_model.rs` | Add `Aabb2` field |
|
||||
| `src/scene/image_model.rs` | Add `Aabb2` field |
|
||||
| `src/scene/tessellate.rs` | Compute AABB during tessellation; adaptive arc segments |
|
||||
| `src/scene/tessellate.rs` | Adaptive arc segments |
|
||||
| `src/scene/truck_tess.rs` | Multi-resolution mesh tessellation |
|
||||
| `src/scene/camera.rs` | Expose `ViewVolume` extraction |
|
||||
| `src/scene/mod.rs` | Quadtree/octree; LOD epoch tracking |
|
||||
| `src/scene/pipeline/mod.rs` | Cull entities before upload loops |
|
||||
| `src/scene/pipeline/mod.rs` | Cull hatch/image entities before upload loops |
|
||||
| `src/shaders/cull.wgsl` | New — Phase 4 compute culling shader |
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
- **Phase 1 target:** Large drawing (100k wires), zoomed to 5% view → render time drops
|
||||
proportional to visible fraction.
|
||||
- **Phase 2 target:** Pan/zoom frame cost O(visible) not O(total).
|
||||
- **Phase 3 target:** Complex solid scene at far zoom → mesh triangle count < 10% of full detail.
|
||||
- **Phase 4 target:** GPU-cull overhead < 0.5 ms for 1M entity scene.
|
||||
|
||||
---
|
||||
|
||||
@@ -293,9 +214,10 @@ common in civil/infrastructure drawings — the user shouldn't have to see them
|
||||
as crosses.
|
||||
|
||||
**Proper fixes that would let us drop this guard:**
|
||||
1. Per-block tessellation cache — tessellate a block once, then per-Insert
|
||||
apply the transform to cached wire vertices. Helps when the same block is
|
||||
inserted multiple times; doesn't fully solve single-Insert huge blocks.
|
||||
1. ~~Per-block tessellation cache~~ — **LANDED** (`def72e4`): block defns are
|
||||
tessellated once and per-Insert reuses the cached wires via
|
||||
`block_cache::expand_insert`. The guard now only fires on the legacy
|
||||
fallback path; consider lowering or removing it.
|
||||
2. Lazy / background Insert tessellation — show marker first, fill in detail
|
||||
on a background thread, redraw when ready.
|
||||
3. Per-sub-entity hardening — find why a single sub can hang tessellation
|
||||
@@ -303,11 +225,12 @@ as crosses.
|
||||
root cause; combine with sub-count budget per frame instead of a hard cap.
|
||||
4. xref attach metadata respected — DWG carries an "unloaded" state for xref
|
||||
blocks; honour it instead of always inlining xref content on open.
|
||||
(Attempted in `e88a946`, reverted in `0996b75` — the on-disk bit was
|
||||
unreliable as a Loaded/Unloaded signal.)
|
||||
|
||||
When any of (1)–(3) lands, delete the `INSERT_SUB_LIMIT` block in
|
||||
When any of (2)–(3) lands, delete the `INSERT_SUB_LIMIT` block in
|
||||
`tessellate_entity` (search for `INSERT_SUB_LIMIT`).
|
||||
|
||||
Related companion fix in `src/app/update.rs`: after `resolve_xrefs`, a second
|
||||
`purge_corrupt_entities` pass runs against the newly inlined xref content.
|
||||
That one is not a hack — it should stay even after the Insert guard goes.
|
||||
- **Phase 4 target:** GPU-cull overhead < 0.5 ms for 1M entity scene.
|
||||
Reference in new issue
Block a user