This isn't a good implementation by any means. It's just to get things started.
127 lines
3.4 KiB
Rust
127 lines
3.4 KiB
Rust
extern crate rustc_serialize;
|
|
extern crate docopt;
|
|
|
|
mod math;
|
|
mod algorithm;
|
|
mod lerp;
|
|
mod float4;
|
|
mod ray;
|
|
mod bbox;
|
|
mod data_tree;
|
|
mod image;
|
|
mod triangle;
|
|
mod bvh;
|
|
mod halton;
|
|
|
|
use std::path::Path;
|
|
|
|
use docopt::Docopt;
|
|
|
|
use image::Image;
|
|
use math::{Point, Vector, fast_logit};
|
|
use ray::Ray;
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
|
|
|
const USAGE: &'static str = r#"
|
|
Psychopath <VERSION>
|
|
|
|
Usage:
|
|
psychopath <imgpath>
|
|
psychopath (-h | --help)
|
|
psychopath --version
|
|
|
|
Options:
|
|
-h --help Show this screen.
|
|
--version Show version.
|
|
"#;
|
|
|
|
#[derive(Debug, RustcDecodable)]
|
|
struct Args {
|
|
arg_imgpath: String,
|
|
flag_version: bool,
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
fn hash_u32(n: u32, seed: u32) -> u32 {
|
|
let mut hash = n;
|
|
|
|
for _ in 0..3 {
|
|
hash = hash.wrapping_mul(1936502639);
|
|
hash ^= hash.wrapping_shr(16);
|
|
hash = hash.wrapping_add(seed);
|
|
}
|
|
|
|
return hash;
|
|
}
|
|
|
|
fn main() {
|
|
// Parse command line arguments.
|
|
let args: Args = Docopt::new(USAGE.replace("<VERSION>", VERSION))
|
|
.and_then(|d| d.decode())
|
|
.unwrap_or_else(|e| e.exit());
|
|
|
|
// Print version and exit if requested.
|
|
if args.flag_version {
|
|
println!("Psychopath {}", VERSION);
|
|
return;
|
|
}
|
|
|
|
// Generate a scene of triangles
|
|
let mut triangles = {
|
|
let mut triangles = Vec::new();
|
|
for x in 0..10 {
|
|
for y in 0..10 {
|
|
let cx = x as f32 * 32.0;
|
|
let cy = y as f32 * 32.0;
|
|
triangles.push((Point::new(cx, cy, 1.0),
|
|
Point::new(cx + 32.0, cy, 1.0),
|
|
Point::new(cx, cy + 32.0, 1.0)));
|
|
}
|
|
}
|
|
triangles
|
|
};
|
|
let scene = bvh::BVH::from_triangles(&mut triangles[..]);
|
|
println!("Scene built.");
|
|
|
|
// Write output image of ray-traced triangle
|
|
let mut img = Image::new(512, 512);
|
|
for y in 0..img.height() {
|
|
for x in 0..img.width() {
|
|
let mut r = 0.0;
|
|
let mut g = 0.0;
|
|
let mut b = 0.0;
|
|
let offset = hash_u32(((x as u32) << 16) ^ (y as u32), 0);
|
|
const SAMPLES: usize = 64;
|
|
for si in 0..SAMPLES {
|
|
let ray = Ray::new(Point::new(x as f32 +
|
|
fast_logit(halton::sample(0, offset + si as u32),
|
|
1.5),
|
|
y as f32 +
|
|
fast_logit(halton::sample(3, offset + si as u32),
|
|
1.5),
|
|
0.0),
|
|
Vector::new(0.0, 0.0, 1.0));
|
|
if bvh::intersect_bvh(&scene, &ray) {
|
|
r += 1.0;
|
|
g += 1.0;
|
|
b += 1.0;
|
|
// r += u;
|
|
// g += v;
|
|
// b += (1.0 - u - v).max(0.0);
|
|
}
|
|
}
|
|
r *= 255.0 / SAMPLES as f32;
|
|
g *= 255.0 / SAMPLES as f32;
|
|
b *= 255.0 / SAMPLES as f32;
|
|
|
|
img.set(x, y, (r as u8, g as u8, b as u8));
|
|
}
|
|
}
|
|
let _ = img.write_binary_ppm(Path::new(&args.arg_imgpath));
|
|
}
|