1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use std::iter;
use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use byteorder::{LittleEndian, ReadBytesExt};
use light_arena::Allocator;
use bxdf::{self, BSDF, BxDF};
use material::Material;
use geometry::Intersection;
pub struct Merl {
brdf: Vec<f32>,
n_theta_h: usize,
n_theta_d: usize,
n_phi_d: usize,
}
impl Merl {
pub fn load_file(path: &Path) -> Merl {
let file = match File::open(path) {
Ok(f) => f,
Err(e) => {
panic!("material::Merl::load_file - failed to open {:?} due to {}", path, e);
},
};
let mut reader = BufReader::new(file);
let n_theta_h = 90;
let n_theta_d = 90;
let n_phi_d = 180;
let dims = [reader.read_i32::<LittleEndian>().unwrap() as usize,
reader.read_i32::<LittleEndian>().unwrap() as usize,
reader.read_i32::<LittleEndian>().unwrap() as usize];
if n_theta_h != dims[0] || n_theta_d != dims[1] || n_phi_d != dims[2] {
panic!("material::Merl::load_file - Invalid MERL file header, aborting");
}
let n_vals = n_theta_h * n_theta_d * n_phi_d;
let mut brdf = Vec::with_capacity(3 * n_vals);
brdf.extend(iter::repeat(0.0).take(3 * n_vals));
let scaling = [1.0 / 1500.0, 1.0 / 1500.0, 1.66 / 1500.0];
for (c, s) in scaling.iter().enumerate() {
for i in 0..n_vals {
let x = (reader.read_f64::<LittleEndian>().unwrap() * s) as f32;
brdf[3 * i + c] = f32::max(0.0, x);
}
}
Merl { brdf: brdf, n_theta_h: n_theta_h, n_theta_d: n_theta_d, n_phi_d: n_phi_d }
}
}
impl Material for Merl {
fn bsdf<'a, 'b, 'c>(&'a self, hit: &Intersection<'a, 'b>,
alloc: &'c Allocator) -> BSDF<'c> where 'a: 'c {
let bxdfs = alloc.alloc_slice::<&BxDF>(1);
bxdfs[0] = alloc.alloc(bxdf::Merl::new(&self.brdf[..], self.n_theta_h, self.n_theta_d, self.n_phi_d));
BSDF::new(bxdfs, 1.0, &hit.dg)
}
}