Skip to content

Instantly share code, notes, and snippets.

@EddyLuten
Created February 13, 2017 06:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EddyLuten/59a76b04aea3e201398d997b4534d2d2 to your computer and use it in GitHub Desktop.
Save EddyLuten/59a76b04aea3e201398d997b4534d2d2 to your computer and use it in GitHub Desktop.
Trace.rs
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