# 3D System and Rendering Pipeline ## Coordinate Conventions ### World Space: Z-up, Y-forward - X = right - Y = forward - Z = up - `look_at` up parameter: `{0, 0, 1}` - Camera default position: along +Y axis, looking toward origin ### View Space: X-right, Y-up, -Z-forward (standard NDC) - Camera looks down **-Z** in view space - `perspective()` encodes this via `m[11] = -1` - Independent of world-space convention — set by `look_at` construction ### Screen Space: Y-up, origin at bottom-left - `uv` in `[0,1]`: `(0,0)` = bottom-left, `(1,1)` = top-right - `st` in `[-1,1]`: NDC directly, y-up - WebGPU textures are y-down `(0,0)` at top — use `textureSampleYUp()` when sampling with `uv` ### NDC → Screen - WebGPU NDC: y-up (`+1` = top) - WebGPU framebuffer: y-down (pixel row 0 at top) - `uv.y = 0` → NDC `y = -1` → bottom of framebuffer ✓ ### Rasterized 3D and the Y-flip rule The fullscreen post-process VS (`fullscreen_uv_vs.wgsl`) uses **Y-up UVs** (`uv.y=0` = bottom of screen). `textureSample(tex, s, uv)` with those UVs samples the **top** of the input texture at the bottom of the screen — a Y-flip. SDF effects are authored Y-down and appear correct after this flip. Rasterized effects (RotatingCube, Hybrid3D) render into an offscreen texture and are consumed by the post-process chain, so they must **pre-flip** their geometry to compensate: - **`mat4::perspective()`** uses `m[5] = -t` (negated Y scale) — renders geometry upside-down into the texture so the post-process chain flips it right-side up. - **Rasterized pipelines** with `cullMode = Back` must set `frontFace = WGPUFrontFace_CW` — the Y-flip reverses winding order on screen, so CW becomes the visible (front) face. - Pipelines with `cullMode = None` (SDF proxy hull, skybox) need no winding change. **Do not** set `m[5] = +t` or use `frontFace = WGPUFrontFace_CCW` (default) in rasterized 3D pipelines — the result will be upside-down with back-faces culled. ## Core Concept Hybrid SDF/rasterization pipeline with physics and collision detection. ## Object Representation Each object has: - Bounding volume (box/capsule) - SDF function (signed distance field) - Ray-intersection query support - Material/shader association ## Render Pipeline 1. Move camera and lights along paths 2. Transform and cull bounding volumes (BVH) 3. Project visible volumes to screen 4. Raymarch SDF inside proxy geometry (fragment shader) 5. Multi-pass for shadow maps ## Visual Debugging (Task #39) Debug mode (`!STRIP_ALL`) provides: - Wireframe bounding volumes - Camera/object trajectories - Collision point visualization - Ray-intersection display - Light visualization (direction, cone, shadow maps) ## BVH Acceleration Structure ### Purpose Efficient spatial queries for rendering (GPU) and physics (CPU). ### Node Layout ```cpp struct BVHNode { float min_x, min_y, min_z; int32_t left_idx; // < 0 = leaf node float max_x, max_y, max_z; int32_t right_idx; // leaf: object_index }; ``` WGSL: ```wgsl struct BVHNode { min: vec3, left_idx: i32, max: vec3, obj_idx_or_right: i32, }; @group(0) @binding(2) var bvh_nodes: array; ``` ### Construction (CPU) Rebuild every frame (< 100 objects): 1. Calculate AABBs for all objects 2. Recursive midpoint split (largest variance axis) 3. Linearize tree for GPU upload ### Traversal (GPU) Fixed-size stack (no recursion in WGSL): ```wgsl fn map_scene(pos: vec3) -> f32 { var min_dist = 10000.0; var stack: array; // Push root, iterate until stack empty // Check AABB, evaluate leaf SDFs return min_dist; } ``` ## Physics & Collision System ### Components Extend `Object3D` with: - Mass/InverseMass - Velocity (linear) - Restitution (bounciness) - Friction ### Broad Phase Reuse BVH for O(N log N) collision detection. ### Narrow Phase **Proxy Point Probing** (SDF-based): 1. Transform probe points into neighbor's local space 2. Evaluate SDF at probe points 3. If `d < 0`: collision detected - Penetration depth: `p = -d` - Normal: `∇SDF` via central differences - Contact point: `P_world - N * p` ### Collision Response (Position Based Dynamics) 1. Integrate position: `p_pred = p + v * dt` 2. Broad phase: Find collision pairs (BVH) 3. Narrow phase: Resolve penetrations on `p_pred` 4. Update velocity: `v = (p_pred - p) / dt` 5. Finalize: `p = p_pred` ### Rotation & Angular Momentum - Quaternion-based orientation - Angular velocity `vec3` - Integration: `q = q + 0.5 * dt * [0, w] * q` - Collision impulses affect both linear and angular momentum ## Integration Plan 1. **CPU-Side SDF Library**: `src/3d/sdf_cpu.h` (sdSphere, sdBox, sdTorus) 2. **Physics System**: `src/3d/physics.h/cc` (Update, ResolveCollision) 3. **Main Loop**: Call `PhysicsSystem::Update` before `Renderer3D::render` ## Future Tasks - **Task #36**: Blender exporter (convert scenes to binary format) - **Task #40**: Advanced lighting & transparency (multi-ray-casting) - **Task #39**: Visual debugging system (wireframes, trajectories)