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> {
root: &'a Assembly,
rays: UnsafeCell<Vec<Ray>>, // Should only be used from trace(), not any other methods
xform_stack: Vec<Matrix4x4>,
xform_stack_indices: Vec<usize>,
xform_stack: TransformStack,
isects: Vec<SurfaceIntersection>,
}
@ -21,8 +20,7 @@ impl<'a> Tracer<'a> {
Tracer {
root: assembly,
rays: UnsafeCell::new(Vec::new()),
xform_stack: Vec::new(),
xform_stack_indices: vec![0],
xform_stack: TransformStack::new(),
isects: Vec::new(),
}
}
@ -63,23 +61,10 @@ impl<'a> Tracer<'a> {
// Transform rays if needed
if let Some((xstart, xend)) = inst.transform_indices {
// Push transforms to stack
let mut combined = Vec::new();
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());
self.xform_stack.push(&assembly.xforms[xstart..xend]);
// Do transforms
let xstart = self.xform_stack_indices[self.xform_stack_indices.len() - 2];
let xend = self.xform_stack_indices[self.xform_stack_indices.len() - 1];
let xforms = &self.xform_stack[xstart..xend];
let xforms = self.xform_stack.top();
for ray in &mut rs[..] {
let id = ray.id;
let t = ray.time;
@ -102,17 +87,11 @@ impl<'a> Tracer<'a> {
// Un-transform rays if needed
if let Some(_) = inst.transform_indices {
// Pop transforms off stack
let xstart = self.xform_stack_indices[self.xform_stack_indices.len() - 2];
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();
self.xform_stack.pop();
// Undo transforms
if self.xform_stack.len() > 0 {
let xstart = self.xform_stack_indices[self.xform_stack_indices.len() - 2];
let xend = self.xform_stack_indices[self.xform_stack_indices.len() - 1];
let xforms = &self.xform_stack[xstart..xend];
let xforms = self.xform_stack.top();
if xforms.len() > 0 {
for ray in &mut rs[..] {
let id = ray.id;
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]
}
}