mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-17 02:49:12 +00:00
ifcviewer: move pick + raycast subsystem into ViewportCore (#84-t)
The whole pick pipeline (R32UInt + RGBA16F MRT, depth attachment, ping-pong staging, single-pixel + rect readback) plus the public pickObjectAt / pickSurfaceAt / picksInRect / pickMeshLocalAt / raycast API and the rayAabbSlab / rayTriMT / rayAABBHit helpers all move to ViewportCore. ViewportWindow keeps tiny forwarder methods so the bonsai input + tool callers (mouseRelease, marquee, section tool, Length/Area refinement) stay compiling. MeshLocalPick + RaycastHit follow as nested types on ViewportCore; ViewportWindow re-exports them as using-aliases to preserve the ViewportWindow::MeshLocalPick / ViewportWindow::RaycastHit names existing callers (and a couple of bonsai tests) reach for. State migrated: pick_color_texture_/_view_, pick_normal_texture_/_view_, pick_depth_texture_/_view_, pick_staging_buffer_, pick_normal_staging_buffer_, pick_w_/_h_, box_pick_staging_buffer_/_capacity_. The pick_pipeline_ itself was already aliased. The pick path no longer reaches into VW for any GPU state, so the render() / shutdown() callers become core_.X() forwards and the pick infrastructure can be exercised by the future web build without going through Qt.
This commit is contained in:
@@ -391,6 +391,76 @@ public:
|
||||
// Called from shutdown() before the device dies.
|
||||
void releaseEdgeResources();
|
||||
|
||||
// ---- Pick + raycast (#84-t) -------------------------------------------
|
||||
//
|
||||
// Build the pick pipeline. Reuses the main shader module's
|
||||
// vs_pick / fs_pick entry points + pipeline_layout_ (same bindings
|
||||
// as the main draw). Single-sample target. Returns false on
|
||||
// pipeline creation failure.
|
||||
bool buildPickPipeline();
|
||||
|
||||
// (Re)allocate the pick MRT attachments + readback staging buffers
|
||||
// to the supplied size. Idempotent when dimensions match.
|
||||
void ensurePickAttachments(int w, int h);
|
||||
|
||||
// Tear down every pick-owned wgpu resource (pipeline + MRTs +
|
||||
// staging buffers). Called from shutdown() before device_ dies.
|
||||
void releasePickResources();
|
||||
|
||||
// Encode + readback the single-pixel object_id + normal at (x, y).
|
||||
// Returns 0 on miss (or any guard failure). When `normal_out` is
|
||||
// non-null, decodes the RGBA16F normal MRT's first texel into a
|
||||
// unit world-space normal. Synchronous (interactive click path).
|
||||
std::uint32_t pickObjectAt(int x_pixels, int y_pixels,
|
||||
Eigen::Vector3f* normal_out = nullptr);
|
||||
|
||||
// Marquee box select: encode the pick pass, copy the (x, y, w, h)
|
||||
// sub-rect of the object_id MRT back, return the set of unique
|
||||
// non-zero ids. Synchronous (rare interaction).
|
||||
std::vector<std::uint32_t> picksInRect(int x, int y, int w, int h);
|
||||
|
||||
// Run pickObjectAt + raycast against every instance carrying the
|
||||
// hit object_id, then return the closest hit's world position,
|
||||
// world normal, and (optionally) the bounding-sphere radius. The
|
||||
// normal preference goes to the pick MRT's per-fragment value; the
|
||||
// AABB-face normal is a fallback.
|
||||
bool pickSurfaceAt(int x_pixels, int y_pixels,
|
||||
std::uint32_t& object_id_out,
|
||||
Eigen::Vector3f& world_pos_out,
|
||||
Eigen::Vector3f& world_normal_out,
|
||||
float* aabb_radius_out = nullptr);
|
||||
|
||||
// Per-pick result for the Area / Length / Volume tools. The
|
||||
// composed_transform mirrors InstanceCpu::transform so callers can
|
||||
// round-trip from mesh-local back to world without re-deriving it.
|
||||
struct MeshLocalPick {
|
||||
std::uint32_t object_id = 0;
|
||||
std::uint32_t model_id = 0;
|
||||
std::uint32_t mesh_id = 0;
|
||||
float mesh_local [3] = {0, 0, 0};
|
||||
float world_pos [3] = {0, 0, 0};
|
||||
float world_normal[3] = {0, 0, 0};
|
||||
float composed_transform[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
|
||||
};
|
||||
|
||||
// pickSurfaceAt + transform back into the picked instance's mesh-
|
||||
// local space, refined against the cached CPU mesh shadow when
|
||||
// available (Möller-Trumbore per-triangle). Output sits on a real
|
||||
// triangle, not the AABB face. Returns false on miss.
|
||||
bool pickMeshLocalAt(int x, int y, MeshLocalPick& out);
|
||||
|
||||
// Bonsai-side raycast helper. Walks every visible instance's
|
||||
// world-AABB, then Möller-Trumbore against the cached mesh
|
||||
// triangles. `dir` must be a unit vector — distance is the ray's
|
||||
// t parameter (= world distance only at |dir|=1).
|
||||
struct RaycastHit {
|
||||
std::uint32_t object_id = 0;
|
||||
float distance = 0.0f;
|
||||
float world_pos[3] = {0, 0, 0};
|
||||
float world_normal[3] = {0, 0, 0};
|
||||
};
|
||||
bool raycast(const float origin[3], const float dir[3], RaycastHit& out) const;
|
||||
|
||||
// ---- Cull (#84-p) -----------------------------------------------------
|
||||
//
|
||||
// Per-instance occlusion test, supplied by the caller. Wired by
|
||||
@@ -558,6 +628,24 @@ private:
|
||||
// main pass since the pick fragment also vertex-pulls instance data.
|
||||
WGPURenderPipeline pick_pipeline_ = nullptr;
|
||||
|
||||
// Pick render targets + readback staging. Single-sample, surface-
|
||||
// sized R32UInt for object_id + RGBA16F for the packed world-space
|
||||
// normal (the section tool drops perpendicular cuts at the picked
|
||||
// pixel). picksInRect grows box_pick_staging_buffer_ on demand for
|
||||
// marquee selection.
|
||||
WGPUTexture pick_color_texture_ = nullptr;
|
||||
WGPUTextureView pick_color_view_ = nullptr;
|
||||
WGPUTexture pick_normal_texture_ = nullptr;
|
||||
WGPUTextureView pick_normal_view_ = nullptr;
|
||||
WGPUTexture pick_depth_texture_ = nullptr;
|
||||
WGPUTextureView pick_depth_view_ = nullptr;
|
||||
WGPUBuffer pick_staging_buffer_ = nullptr;
|
||||
WGPUBuffer pick_normal_staging_buffer_ = nullptr;
|
||||
int pick_w_ = 0;
|
||||
int pick_h_ = 0;
|
||||
WGPUBuffer box_pick_staging_buffer_ = nullptr;
|
||||
std::uint64_t box_pick_staging_capacity_ = 0;
|
||||
|
||||
// ---- Frame uniforms + selection bind ----------------------------------
|
||||
//
|
||||
// The per-frame UBO (view-proj + lighting + section planes + xray
|
||||
|
||||
Reference in New Issue
Block a user