Split xform stack out into its own type.

This is mainly just to make the tracer code read more cleanly.
All of the pushing and popping logic obscured the big picture
and made things a bit confusing.
This commit is contained in:
Nathan Vegdahl 2016-05-28 14:15:05 -07:00
parent 56b5267b7a
commit ef31093dcb

View File

@ -11,8 +11,7 @@ use surface::SurfaceIntersection;
pub struct Tracer<'a> { pub struct Tracer<'a> {
root: &'a Assembly, root: &'a Assembly,
rays: UnsafeCell<Vec<Ray>>, // Should only be used from trace(), not any other methods rays: UnsafeCell<Vec<Ray>>, // Should only be used from trace(), not any other methods
xform_stack: Vec<Matrix4x4>, xform_stack: TransformStack,
xform_stack_indices: Vec<usize>,
isects: Vec<SurfaceIntersection>, isects: Vec<SurfaceIntersection>,
} }
@ -21,8 +20,7 @@ impl<'a> Tracer<'a> {
Tracer { Tracer {
root: assembly, root: assembly,
rays: UnsafeCell::new(Vec::new()), rays: UnsafeCell::new(Vec::new()),
xform_stack: Vec::new(), xform_stack: TransformStack::new(),
xform_stack_indices: vec![0],
isects: Vec::new(), isects: Vec::new(),
} }
} }
@ -63,23 +61,10 @@ impl<'a> Tracer<'a> {
// Transform rays if needed // Transform rays if needed
if let Some((xstart, xend)) = inst.transform_indices { if let Some((xstart, xend)) = inst.transform_indices {
// Push transforms to stack // Push transforms to stack
let mut combined = Vec::new(); self.xform_stack.push(&assembly.xforms[xstart..xend]);
if self.xform_stack.len() == 0 {
self.xform_stack.extend(&assembly.xforms[xstart..xend]);
} else {
let x2start = self.xform_stack_indices[self.xform_stack_indices.len() - 2];
let x2end = self.xform_stack_indices[self.xform_stack_indices.len() - 1];
multiply_matrix_slices(&self.xform_stack[x2start..x2end],
&assembly.xforms[xstart..xend],
&mut combined);
self.xform_stack.extend(&combined);
}
self.xform_stack_indices.push(self.xform_stack.len());
// Do transforms // Do transforms
let xstart = self.xform_stack_indices[self.xform_stack_indices.len() - 2]; let xforms = self.xform_stack.top();
let xend = self.xform_stack_indices[self.xform_stack_indices.len() - 1];
let xforms = &self.xform_stack[xstart..xend];
for ray in &mut rs[..] { for ray in &mut rs[..] {
let id = ray.id; let id = ray.id;
let t = ray.time; let t = ray.time;
@ -102,17 +87,11 @@ impl<'a> Tracer<'a> {
// Un-transform rays if needed // Un-transform rays if needed
if let Some(_) = inst.transform_indices { if let Some(_) = inst.transform_indices {
// Pop transforms off stack // Pop transforms off stack
let xstart = self.xform_stack_indices[self.xform_stack_indices.len() - 2]; self.xform_stack.pop();
let xend = self.xform_stack_indices[self.xform_stack_indices.len() - 1];
let l = self.xform_stack.len();
self.xform_stack.resize(l - (xend - xstart), Matrix4x4::new());
self.xform_stack_indices.pop();
// Undo transforms // Undo transforms
if self.xform_stack.len() > 0 { let xforms = self.xform_stack.top();
let xstart = self.xform_stack_indices[self.xform_stack_indices.len() - 2]; if xforms.len() > 0 {
let xend = self.xform_stack_indices[self.xform_stack_indices.len() - 1];
let xforms = &self.xform_stack[xstart..xend];
for ray in &mut rs[..] { for ray in &mut rs[..] {
let id = ray.id; let id = ray.id;
let t = ray.time; let t = ray.time;
@ -138,3 +117,77 @@ impl<'a> Tracer<'a> {
} }
} }
} }
struct TransformStack {
stack: Vec<Matrix4x4>,
stack_indices: Vec<usize>,
scratch_space: Vec<Matrix4x4>,
}
impl TransformStack {
fn new() -> TransformStack {
let mut ts = TransformStack {
stack: Vec::new(),
stack_indices: Vec::new(),
scratch_space: Vec::new(),
};
ts.stack_indices.push(0);
ts.stack_indices.push(0);
ts
}
fn with_capacity(capacity: usize) -> TransformStack {
let mut ts = TransformStack {
stack: Vec::with_capacity(capacity),
stack_indices: Vec::with_capacity(capacity),
scratch_space: Vec::with_capacity(capacity),
};
ts.stack_indices.push(0);
ts.stack_indices.push(0);
ts
}
fn push(&mut self, xforms: &[Matrix4x4]) {
assert!(xforms.len() > 0);
if self.stack.len() == 0 {
self.stack.extend(xforms);
} else {
let sil = self.stack_indices.len();
let i1 = self.stack_indices[sil - 2];
let i2 = self.stack_indices[sil - 1];
self.scratch_space.clear();
multiply_matrix_slices(&self.stack[i1..i2], xforms, &mut self.scratch_space);
self.stack.extend(&self.scratch_space);
}
self.stack_indices.push(self.stack.len());
}
fn pop(&mut self) {
assert!(self.stack_indices.len() > 1);
let sl = self.stack.len();
let sil = self.stack_indices.len();
let i1 = self.stack_indices[sil - 2];
let i2 = self.stack_indices[sil - 1];
self.stack.truncate(sl - (i2 - i1));
self.stack_indices.pop();
}
fn top<'a>(&'a self) -> &'a [Matrix4x4] {
let sil = self.stack_indices.len();
let i1 = self.stack_indices[sil - 2];
let i2 = self.stack_indices[sil - 1];
&self.stack[i1..i2]
}
}