diff --git a/src/ifcviewer/ViewportCore.cpp b/src/ifcviewer/ViewportCore.cpp index 2c1d47d359..bb2475a37f 100644 --- a/src/ifcviewer/ViewportCore.cpp +++ b/src/ifcviewer/ViewportCore.cpp @@ -4582,3 +4582,24 @@ void ViewportCore::configureSurface(int width_px, int height_px) { edge_bind_group_ = nullptr; } } + +// =========================================================================== +// Small cross-chunk + capture helpers (#84-v) +// =========================================================================== + +void ViewportCore::buildModelBindGroup(ModelGpuData& m) { + if (!m.mesh_storage || !m.instance_storage) { + // Empty model — no chunks, no bind groups; the draw loop will skip. + return; + } + for (std::size_t ci = 0; ci < m.chunks.size(); ++ci) { + buildChunkBindGroup(m, ci); + } +} + +void ViewportCore::captureNextFrameToPng(const std::string& path, + bool quit_after) { + pending_screenshot_path_ = path; + pending_screenshot_quit_ = quit_after; + host_->requestFrame(); +} diff --git a/src/ifcviewer/ViewportCore.h b/src/ifcviewer/ViewportCore.h index 3b073aaab4..d315d7eb91 100644 --- a/src/ifcviewer/ViewportCore.h +++ b/src/ifcviewer/ViewportCore.h @@ -323,6 +323,21 @@ public: void uploadInstanceChunk(const InstanceChunk& chunk); void finalizeModel(std::uint32_t model_id); + // ---- Cross-chunk + screenshot capture (#84-v) ------------------------- + // + // Rebuild every chunk's bind group for the supplied model. No-op + // when the model has no GPU storage yet (empty load — the chunk + // draw loop skips it anyway). + void buildModelBindGroup(ModelGpuData& m); + + // Arm a one-shot screenshot capture. The next render() encodes a + // surface-to-buffer copy alongside the main pass, maps it back to + // RGBA8, and saves a PNG at `path`. `quit_after` requests host + // shutdown once the capture writes — the host's quit() decides + // when (synchronously or queued). + void captureNextFrameToPng(const std::string& path, bool quit_after); + bool pending_screenshot_quit_ = false; + // ---- Surface configuration (#84-u) ------------------------------------ // // Configure the swapchain at the given physical size. Picks a present diff --git a/src/ifcviewer/ViewportWindow.cpp b/src/ifcviewer/ViewportWindow.cpp index 0fa31c5104..2d8d2b91f1 100644 --- a/src/ifcviewer/ViewportWindow.cpp +++ b/src/ifcviewer/ViewportWindow.cpp @@ -247,6 +247,7 @@ ViewportWindow::ViewportWindow(QWindow* parent) streaming_blocked_oom_this_frame_(core_.streaming_blocked_oom_this_frame_), streaming_debug_ (core_.streaming_debug_), pending_screenshot_path_(core_.pending_screenshot_path_), + pending_screenshot_quit_(core_.pending_screenshot_quit_), lod1_dbg_count_ (core_.lod1_dbg_count_), lod0_dbg_eligible_count_(core_.lod0_dbg_eligible_count_), lod0_dbg_no_lod1_count_ (core_.lod0_dbg_no_lod1_count_), @@ -2431,15 +2432,7 @@ void ViewportWindow::ensureSelectionFlagsBuffer() { core_.ensureSelectionFlagsBu // uploadSelectionFlagsIfDirty moved to ViewportCore (#84-k). void ViewportWindow::uploadSelectionFlagsIfDirty() { core_.uploadSelectionFlagsIfDirty(); } -void ViewportWindow::buildModelBindGroup(ModelGpuData& m) { - if (!m.mesh_storage || !m.instance_storage) { - // Empty model — no chunks, no bind groups; the draw loop will skip. - return; - } - for (size_t ci = 0; ci < m.chunks.size(); ++ci) { - core_.buildChunkBindGroup(m, ci); - } -} +void ViewportWindow::buildModelBindGroup(ModelGpuData& m) { core_.buildModelBindGroup(m); } // buildChunkBindGroup moved to ViewportCore (#84-n). @@ -2685,11 +2678,7 @@ void ViewportWindow::applyNavPreset(const char* name) { #include #include -void ViewportWindow::captureNextFrameToPng(const std::string& path, bool quit_after) { - pending_screenshot_path_ = path; - pending_screenshot_quit_ = quit_after; - if (isExposed()) requestUpdate(); -} +void ViewportWindow::captureNextFrameToPng(const std::string& path, bool quit_after) { core_.captureNextFrameToPng(path, quit_after); } // ----------------------------------------------------------------------------- // Mouse navigation — orbit, pan, zoom diff --git a/src/ifcviewer/ViewportWindow.h b/src/ifcviewer/ViewportWindow.h index e3a8ad035b..df10b53cd0 100644 --- a/src/ifcviewer/ViewportWindow.h +++ b/src/ifcviewer/ViewportWindow.h @@ -937,7 +937,7 @@ private: // observes the non-empty value to switch into the sync chunk-load // fallback so the first-frame capture isn't an empty buffer. std::string& pending_screenshot_path_; - bool pending_screenshot_quit_ = false; + bool& pending_screenshot_quit_; // Mouse navigation state. LMB drag orbits, MMB drag pans, wheel zooms. // LMB-click-without-drag picks the object under the cursor. No