Created
February 13, 2017 06:00
-
-
Save EddyLuten/59a76b04aea3e201398d997b4534d2d2 to your computer and use it in GitHub Desktop.
Trace.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::io::prelude::*; | |
use std::fs::File; | |
use std::path::Path; | |
use std::error::Error; | |
struct Vector3D { | |
x: f32, | |
y: f32, | |
z: f32, | |
} | |
struct Sphere { | |
position: Vector3D, | |
radius: f32, | |
} | |
struct Ray { | |
origin: Vector3D, | |
direction: Vector3D, | |
} | |
impl Vector3D { | |
fn dot(&self, other: &Vector3D) -> f32 { | |
self.x * other.x + self.y * other.y + self.z * other.z | |
} | |
fn sub(&self, other: &Vector3D) -> Vector3D { | |
Vector3D { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z } | |
} | |
fn magnitude(&self) -> f32 { | |
self.dot(self).sqrt() | |
} | |
fn normalize(&mut self) { | |
let s = 1.0 / self.magnitude(); | |
self.x *= s; | |
self.y *= s; | |
self.z *= s; | |
} | |
} | |
impl Sphere { | |
fn intersects(&self, ray: &Ray) -> bool { | |
let oc = self.position.sub(&ray.origin); | |
let tca = oc.dot(&ray.direction); | |
if tca < 0.0 { return false; } | |
let l2oc = oc.dot(&oc); | |
let sr2 = self.radius * self.radius; | |
let d2 = l2oc - (tca * tca); | |
let t2hc = sr2 - d2; | |
return !(t2hc < 0.0 && l2oc >= sr2) | |
} | |
} | |
fn main() { | |
const WIDTH: usize = 640; | |
const HEIGHT: usize = 480; | |
const F_WIDTH: f32 = WIDTH as f32; | |
const F_HEIGHT: f32 = HEIGHT as f32; | |
const HALF_WIDTH: f32 = F_WIDTH * 0.5; | |
const HALF_HEIGHT: f32 = F_HEIGHT * 0.5; | |
const ASPECT: f32 = F_WIDTH / F_HEIGHT; | |
let mut pixels: Vec<u8> = Vec::with_capacity(WIDTH * HEIGHT * 3); | |
let sphere = Sphere { | |
position: Vector3D { x: 0.0, y: 0.0, z: -5.0 }, | |
radius: 0.5 | |
}; | |
let mut ray = Ray { | |
origin: Vector3D { x: 0.0, y: 0.0, z: 0.0 }, | |
direction: Vector3D { x: 0.0, y: 0.0, z: 0.0 } | |
}; | |
for y in 0..HEIGHT { | |
for x in 0..WIDTH { | |
let mut pixel = [0, 0, 0]; | |
let rx = (x as f32 - HALF_WIDTH) / F_WIDTH * ASPECT; | |
let ry = (y as f32 - HALF_HEIGHT) / F_HEIGHT; | |
ray.direction = Vector3D { x: rx, y: ry, z: -3.0 }; | |
ray.direction.normalize(); | |
if sphere.intersects(&ray) { | |
pixel = [255, 255, 255]; | |
} | |
pixels.extend_from_slice(&pixel); | |
} | |
} | |
let path = Path::new("out.ppm"); | |
let mut file = match File::create(&path) { | |
Err(why) => panic!("Couldn't create {}: {}", path.display(), why.description()), | |
Ok(file) => file, | |
}; | |
write!(&mut file, "P6 {} {} 255\n", WIDTH, HEIGHT); | |
file.write(pixels.as_slice()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment