Skip to content

feat: raycasting architecture with analytic primitives and quiver mesh BVH#5

Open
mtao wants to merge 5 commits into
feature/image-and-iofrom
feature/raycasting
Open

feat: raycasting architecture with analytic primitives and quiver mesh BVH#5
mtao wants to merge 5 commits into
feature/image-and-iofrom
feature/raycasting

Conversation

@mtao
Copy link
Copy Markdown
Owner

@mtao mtao commented Mar 29, 2026

Summary

Implements a raycasting architecture for ART with two geometry backends and a PBRT-inspired scene accelerator:

  1. Enriched core types + analytic primitives — Ray gains mutable tMax for closest-hit pruning (PBRT-style). Intersection enriched with geometric normal, UV, tangent vectors, geometry pointer, and primitive index. New primitives: Plane, Disk, Cylinder, Triangle. Camera renders with normal-based coloring.

  2. Quiver mesh raycasting via BVH — New MeshGeometry class wraps quiver::Mesh<2> with an AABB BVH for fast ray-triangle intersection. Bridges ART's rational/homogeneous types to quiver's double-precision spatial queries at the intersection boundary. Convenience factories for cube, tetrahedron, and single-triangle meshes.

  3. Scene accelerator refactor — Separates spatial acceleration from the logical scene tree following the PBRT Primitive/Aggregate pattern. SceneNode is now pure logical grouping (transforms + hierarchy). New SceneAccelerator abstract base with LinearAccelerator (brute-force ground truth) and BVHAccelerator (quiver AABB BVH over world-space bounding boxes).

Changes

Phase 1: Core Type Enrichment

  • Ray: added mutable Rational tMax (reset per-pixel, updated by intersect)
  • Intersection: geometric_normal, uv (Vector2d), dpdu/dpdv, geometry*, primitive_index
  • zipper_types.hpp: added Vector2d alias
  • Sphere/Box: updated with spherical/face-local UV, tangent vectors, tMax semantics
  • SceneNode: transforms normals by inverse-transpose, tangent vectors by linear part
  • Camera::render(): tMax reset per pixel, normal-based coloring

Phase 2: New Analytic Primitives

  • Plane, Disk, Cylinder, Triangle — full intersection with UV, tangent vectors, tMax
  • 10 intersection tests + 4 per-primitive test files

Phase 3: Quiver Mesh Raycasting

  • MeshGeometry: quiver mesh + AABB BVH wrapper implementing Geometry::intersect()
  • mesh_utils: make_mesh_geometry(), make_cube_mesh(), make_tetrahedron_mesh(), make_single_triangle_mesh()
  • quiver added as hard dependency via subprojects/quiver.wrap
  • 9 test cases covering hit/miss, tMax pruning, bounding box, construction

Scene Accelerator Refactor

  • New types: ScenePrimitive (flattened leaf: geometry + world transform), SceneAccelerator (abstract base), LinearAccelerator, BVHAccelerator
  • intersect_primitive() free function — shared helper for transform-aware ray-geometry intersection
  • Stripped SceneNode of bounding box and intersection logic — now pure logical grouping
  • Added Object::geometry_ptr() and InternalSceneNode::children() accessors
  • Camera::render() takes const SceneAccelerator& instead of SceneNode&
  • 6 accelerator test cases: flattening, Linear vs BVH agreement, transforms, empty scene

Infrastructure

  • Fixed mdspan.wrap (standalone instead of broken wrap-redirect into zipper subproject)

Test Results

All 79 test cases pass (77 passed, 2 skipped for optional EXR/PNG deps).

Dependencies

  • Based on feature/image-and-io with refactor/meson-modernize merged in
  • Requires quiver's main branch (fetched via subprojects/quiver.wrap)

mtao added 5 commits March 28, 2026 12:13
…ndency()

Switch zipper consumption from subproject().get_variable() to
dependency() with [provide] section in wrap file. Add
meson.override_dependency() for art and art-headers so downstream
projects can consume them via dependency().

Remove dead code: unused dl_lib (cc.find_library('dl')) and unused
TBB_dep (dependency('tbb')) that were declared but never referenced.

Add viewer option to meson_options.txt for future balsa::visualization
integration.
…gle primitives

Phase 1 — Core type enrichment:
- Ray gains mutable Rational tMax for PBRT-style closest-hit pruning
- Intersection enriched with geometric_normal, uv, dpdu/dpdv tangent
  vectors, geometry pointer, and primitive_index
- Vector2d alias added to zipper_types.hpp
- Sphere/Box intersect() updated with full field population and tMax
- SceneNode transforms normals (inverse-transpose) and tangent vectors
- Camera::render() resets tMax per pixel, uses normal-based coloring
- Fix mdspan.wrap (standalone instead of broken wrap-redirect)

Phase 2 — New analytic primitives:
- Plane: infinite z=0 plane with UV=(x,y) and constant normal
- Disk: unit disk at z=0 with polar UV and radius check
- Cylinder: z-axis unit cylinder z∈[0,1] r=1, quadratic intersection
- Triangle: Moller-Trumbore with optional per-vertex normals/UVs,
  PBRT dpdu/dpdv formula from UV differentials

All 64 tests pass (62 passed, 2 skipped for optional EXR/PNG).
…asting

Add MeshGeometry class wrapping quiver::Mesh<2> with AABB BVH for fast
ray-triangle intersection. Bridges ART's rational/homogeneous types to
quiver's double-precision spatial queries at the intersection boundary.

- MeshGeometry: quiver mesh + BVH wrapper implementing Geometry::intersect()
- mesh_utils: convenience factories (make_cube_mesh, make_tetrahedron_mesh,
  make_single_triangle_mesh, make_mesh_geometry)
- 9 test cases covering hit/miss, tMax pruning, bounding box, construction
- quiver added as hard dependency via subprojects/quiver.wrap
…ne graph

Separate spatial acceleration from the logical scene tree following the
PBRT Primitive/Aggregate pattern. SceneNode is now pure logical grouping
(transforms + hierarchy). Scene traversal and ray intersection are handled
by SceneAccelerator, which flattens the tree into ScenePrimitives with
world-space transforms.

- Add ScenePrimitive (geometry + world transform), SceneAccelerator (abstract),
  LinearAccelerator (brute-force), BVHAccelerator (quiver AABB BVH)
- Add intersect_primitive() free function for transform-aware ray-geometry tests
- Strip SceneNode of bounding box and intersection logic
- Add Object::geometry_ptr() and InternalSceneNode::children() accessors
- Update Camera::render() to accept SceneAccelerator instead of SceneNode
- Add test_accelerator.cpp with flattening, Linear vs BVH agreement, and
  transform hierarchy tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant