From 3d4ac7f57b1068cdecbe7efcf9cbbc42d52b9a03 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Fri, 21 Jun 2019 23:02:44 +0900 Subject: [PATCH] Created a RayBatch type, which stores multiple rays is SoA layout. --- src/ray.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 4 deletions(-) diff --git a/src/ray.rs b/src/ray.rs index cf91b74..d2cf51f 100644 --- a/src/ray.rs +++ b/src/ray.rs @@ -4,8 +4,99 @@ use float4::Float4; use crate::math::{Matrix4x4, Point, Vector}; -const OCCLUSION_FLAG: u32 = 1; -const DONE_FLAG: u32 = 1 << 1; +type FlagType = u8; +const OCCLUSION_FLAG: FlagType = 1; +const DONE_FLAG: FlagType = 1 << 1; + +/// A batch of rays, stored in SoA layout. +#[derive(Debug)] +pub struct RayBatch { + pub orig_world: Vec, + pub dir_world: Vec, + pub orig_accel: Vec, + pub dir_inv_accel: Vec, + pub max_t: Vec, + pub time: Vec, + pub wavelength: Vec, + pub flags: Vec, +} + +impl RayBatch { + /// Creates a new empty ray batch. + pub fn new() -> RayBatch { + RayBatch { + orig_world: Vec::new(), + dir_world: Vec::new(), + orig_accel: Vec::new(), + dir_inv_accel: Vec::new(), + max_t: Vec::new(), + time: Vec::new(), + wavelength: Vec::new(), + flags: Vec::new(), + } + } + + /// Creates a new empty ray batch, with pre-allocated capacity for + /// `n` rays. + pub fn with_capacity(n: usize) -> RayBatch { + RayBatch { + orig_world: Vec::with_capacity(n), + dir_world: Vec::with_capacity(n), + orig_accel: Vec::with_capacity(n), + dir_inv_accel: Vec::with_capacity(n), + max_t: Vec::with_capacity(n), + time: Vec::with_capacity(n), + wavelength: Vec::with_capacity(n), + flags: Vec::with_capacity(n), + } + } + + /// Clear all rays, settings the size of the batch back to zero. + /// + /// Capacity is maintained. + pub fn clear(&mut self) { + self.orig_world.clear(); + self.dir_world.clear(); + self.orig_accel.clear(); + self.dir_inv_accel.clear(); + self.max_t.clear(); + self.time.clear(); + self.wavelength.clear(); + self.flags.clear(); + } + + /// Returns whether the given ray (at index `idx`) is an occlusion ray. + pub fn is_occlusion(&self, idx: usize) -> bool { + (self.flags[idx] & OCCLUSION_FLAG) != 0 + } + + /// Returns whether the given ray (at index `idx`) has finished traversal. + pub fn is_done(&self, idx: usize) -> bool { + (self.flags[idx] & DONE_FLAG) != 0 + } + + /// Marks the given ray (at index `idx`) as an occlusion ray. + pub fn mark_occlusion(&mut self, idx: usize) { + self.flags[idx] |= OCCLUSION_FLAG + } + + /// Marks the given ray (at index `idx`) as having finished traversal. + pub fn mark_done(&mut self, idx: usize) { + self.flags[idx] |= DONE_FLAG + } + + /// Updates the accel data of the given ray (at index `idx`) with the + /// given world-to-local-space transform matrix. + /// + /// This should be called when entering (and exiting) traversal of a + /// new transform space. + pub fn update_accel(&mut self, idx: usize, xform: &Matrix4x4) { + self.orig_accel[idx] = self.orig_world[idx] * *xform; + self.dir_inv_accel[idx] = Vector { + co: Float4::splat(1.0) / (self.dir_world[idx] * *xform).co, + }; + } +} #[derive(Debug, Copy, Clone)] pub struct Ray { @@ -14,7 +105,7 @@ pub struct Ray { pub max_t: f32, pub time: f32, pub wavelength: f32, - pub flags: u32, + pub flags: FlagType, } impl Ray { @@ -56,7 +147,7 @@ pub struct AccelRay { pub dir_inv: Vector, pub max_t: f32, pub time: f32, - pub flags: u32, + pub flags: FlagType, pub id: u32, }