diff --git a/Cargo.lock b/Cargo.lock index 284c825..8fb7f80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,4 +1,64 @@ [root] name = "psychopath" version = "0.1.0" +dependencies = [ + "docopt 0.6.78 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "docopt" +version = "0.6.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "regex 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-serialize" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strsim" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index bf7ae73..b1f99c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,3 +2,7 @@ name = "psychopath" version = "0.1.0" authors = ["Nathan Vegdahl "] + +[dependencies] +docopt = "0.6" +rustc-serialize = "0.3" \ No newline at end of file diff --git a/src/image.rs b/src/image.rs new file mode 100644 index 0000000..3c5cb6c --- /dev/null +++ b/src/image.rs @@ -0,0 +1,83 @@ +#![allow(dead_code)] + +use std::io; +use std::io::Write; +use std::path::Path; +use std::fs::File; + +#[derive(Debug, Clone)] +pub struct Image { + data: Vec<(u8, u8, u8)>, + res: (usize, usize), +} + +impl Image { + pub fn new(width: usize, height: usize) -> Image { + Image { + data: vec![(0,0,0); width * height], + res: (width, height), + } + } + + pub fn width(&self) -> usize { + self.res.0 + } + + pub fn height(&self) -> usize { + self.res.1 + } + + pub fn get(&self, x: usize, y: usize) -> (u8, u8, u8) { + assert!(x < self.res.0); + assert!(y < self.res.1); + + self.data[self.res.0 * y + x] + } + + pub fn set(&mut self, x: usize, y: usize, value: (u8, u8, u8)) { + assert!(x < self.res.0); + assert!(y < self.res.1); + + self.data[self.res.0 * y + x] = value; + } + + pub fn write_ascii_ppm(&self, path: &Path) -> io::Result<()> { + // Open file. + let mut f = io::BufWriter::new(try!(File::create(path))); + + // Write header + try!(write!(f, "P3\n{} {}\n255\n", self.res.0, self.res.1)); + + // Write pixels + for y in 0..self.res.1 { + for x in 0..self.res.0 { + let (r, g, b) = self.get(x, y); + try!(write!(f, "{} {} {} ", r, g, b)); + } + try!(write!(f, "\n")); + } + + // Done + Ok(()) + } + + pub fn write_binary_ppm(&self, path: &Path) -> io::Result<()> { + // Open file. + let mut f = io::BufWriter::new(try!(File::create(path))); + + // Write header + try!(write!(f, "P6\n{} {}\n255\n", self.res.0, self.res.1)); + + // Write pixels + for y in 0..self.res.1 { + for x in 0..self.res.0 { + let (r, g, b) = self.get(x, y); + let d = [r, g, b]; + try!(f.write_all(&d)); + } + } + + // Done + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index 3768197..9d9a54f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,58 @@ +extern crate rustc_serialize; +extern crate docopt; + mod math; mod lerp; mod float4; +mod ray; +mod image; + +use std::path::Path; + +use docopt::Docopt; + +use image::Image; + +// ---------------------------------------------------------------- + +const VERSION: &'static str = env!("CARGO_PKG_VERSION"); + +const USAGE: &'static str = r#" +Psychopath + +Usage: + psychopath + 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 main() { - println!("Hello, world!"); + // Parse command line arguments. + let args: Args = Docopt::new(USAGE.replace("", 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; + } + + // Write output image + let mut img = Image::new(512, 512); + img.set(256, 256, (255, 255, 255)); + let _ = img.write_binary_ppm(Path::new(&args.arg_imgpath)); } diff --git a/src/ray.rs b/src/ray.rs new file mode 100644 index 0000000..197f0c5 --- /dev/null +++ b/src/ray.rs @@ -0,0 +1,23 @@ +#![allow(dead_code)] + +use math::{Vector, Point, Matrix4x4}; + +#[derive(Debug, Copy, Clone)] +pub struct Ray { + pub orig: Point, + pub dir: Vector, +} + +impl Ray { + pub fn new(orig: Point, dir: Vector) -> Ray { + Ray { + orig: orig, + dir: dir, + } + } + + pub fn transform(&mut self, mat: &Matrix4x4) { + self.orig = self.orig * *mat; + self.dir = self.dir * *mat; + } +}