Refactoring, Completed Simple Sphere and Surface Normal Sphere
This commit is contained in:
parent
b368aad313
commit
c53beb8cc1
2
ria-weekend/Cargo.lock
generated
2
ria-weekend/Cargo.lock
generated
|
@ -1,3 +1,5 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
extern crate ria_weekend;
|
|
||||||
|
|
||||||
use ria_weekend::{demo::Demo, ray, ray::Ray, vec3::Vec3};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let demo = Demo::new("surface_normal_sphere");
|
|
||||||
let dimensions = demo.dimensions();
|
|
||||||
|
|
||||||
let mut buf = String::new();
|
|
||||||
// linear interpolation based on y coordinate
|
|
||||||
// top to down
|
|
||||||
let color = |ray: Ray| -> Vec3 {
|
|
||||||
// center at z=-1. xy axis cuts sphere in half
|
|
||||||
// blending parameter
|
|
||||||
let t = ray_hit_sphere(Vec3::new(0.0, 0.0, 1.0), 0.5, &ray);
|
|
||||||
if t > 0.0 {
|
|
||||||
// For all rays that hit sphere, return red color
|
|
||||||
// This will result in a sphere that is red in color
|
|
||||||
let N = ray.point_at_parameter(t) - Vec3::new(0.0, 0.0, -1.0);
|
|
||||||
return Vec3::new(N.x() + 1.0, N.y() + 1.0, N.z() + 1.0) * 0.5;
|
|
||||||
}
|
|
||||||
let unit_direction = ray.direction().unit_vector();
|
|
||||||
// For rays that don't hit sphere, It'll paint the gradient as the background
|
|
||||||
// Linear gradient depends on y
|
|
||||||
let t = 0.5 * (unit_direction.y() + 1.0);
|
|
||||||
|
|
||||||
// start color + end color
|
|
||||||
Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.0, 0.0, 0.0) * t
|
|
||||||
};
|
|
||||||
|
|
||||||
ray::create_ray_demo(&mut buf, dimensions, color);
|
|
||||||
|
|
||||||
demo.save_as_ppm(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ray_hit_sphere(center: Vec3, radius: f32, ray: &Ray) -> f32 {
|
|
||||||
// dot(A + t*B - C, A + t*B - C) = R*R
|
|
||||||
// when expanded we get
|
|
||||||
// t * t * dot(B, B) + 2 * t * dot(B, A-C) + dot(A-C, A-C) - R*R = 0
|
|
||||||
|
|
||||||
// A-C
|
|
||||||
let ac = ray.origin() - center;
|
|
||||||
let a = ray.direction().dot(&ray.direction());
|
|
||||||
let b = 2.0 * ac.dot(&ray.direction());
|
|
||||||
let c = ac.dot(&ac) - radius * radius;
|
|
||||||
let discriminant = b * b - 4.0 * a * c;
|
|
||||||
|
|
||||||
if discriminant >= 0.0 {
|
|
||||||
// return quadratic root
|
|
||||||
(-b + discriminant.sqrt()) / (2.0 * a)
|
|
||||||
} else {
|
|
||||||
-1.0
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,9 +9,13 @@ impl crate::Demo for LinearInterpolationY {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, buf: &mut Vec<u8>, w: usize, h: usize) {
|
fn render(&self, buf: &mut Vec<u8>, w: usize, h: usize) {
|
||||||
let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0);
|
// in my case, The resolution is 1200x800
|
||||||
let horizontal = Vec3::new(4.0, 0.0, 0.0);
|
// These numbers are calculated by first calculating the aspect ratio
|
||||||
let vertical = Vec3::new(0.0, 2.0, 0.0);
|
// and then just figuring out lower left corner, Width(2 x aspect ratio width)
|
||||||
|
// Height(2 x aspect ratio height)
|
||||||
|
let lower_left_corner = Vec3::new(-3.0, -2.0, -1.0);
|
||||||
|
let horizontal = Vec3::new(6.0, 0.0, 0.0);
|
||||||
|
let vertical = Vec3::new(0.0, 4.0, 0.0);
|
||||||
// Observer position
|
// Observer position
|
||||||
let origin = Vec3::new(0.0, 0.0, 0.0);
|
let origin = Vec3::new(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
@ -25,9 +29,9 @@ impl crate::Demo for LinearInterpolationY {
|
||||||
|
|
||||||
let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
||||||
let color = calc_color(ray);
|
let color = calc_color(ray);
|
||||||
let ir = (255.99 * color[0]) as u8;
|
let ir = (255.99 * color.r()) as u8;
|
||||||
let ig = (255.99 * color[1]) as u8;
|
let ig = (255.99 * color.g()) as u8;
|
||||||
let ib = (255.99 * color[2]) as u8;
|
let ib = (255.99 * color.b()) as u8;
|
||||||
|
|
||||||
buf[offset] = ir;
|
buf[offset] = ir;
|
||||||
buf[offset + 1] = ig;
|
buf[offset + 1] = ig;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
mod linear_interpolation_y;
|
mod linear_interpolation_y;
|
||||||
mod simple_sphere;
|
|
||||||
mod ppm_example;
|
mod ppm_example;
|
||||||
|
mod simple_sphere;
|
||||||
|
mod surface_normal_sphere;
|
||||||
|
|
||||||
pub use linear_interpolation_y::LinearInterpolationY;
|
pub use linear_interpolation_y::LinearInterpolationY;
|
||||||
pub use simple_sphere::SimpleSphere;
|
|
||||||
pub use ppm_example::PpmExample;
|
pub use ppm_example::PpmExample;
|
||||||
|
pub use simple_sphere::SimpleSphere;
|
||||||
|
pub use surface_normal_sphere::SurfaceNormalSphere;
|
||||||
|
|
|
@ -12,9 +12,9 @@ impl crate::Demo for PpmExample {
|
||||||
for i in 0..w {
|
for i in 0..w {
|
||||||
let color = Vec3::new((i as f32) / (w as f32), (j as f32) / (h as f32), 0.2);
|
let color = Vec3::new((i as f32) / (w as f32), (j as f32) / (h as f32), 0.2);
|
||||||
|
|
||||||
let ir = (255.99 * color[0]) as u8;
|
let ir = (255.99 * color.r()) as u8;
|
||||||
let ig = (255.99 * color[1]) as u8;
|
let ig = (255.99 * color.g()) as u8;
|
||||||
let ib = (255.99 * color[2]) as u8;
|
let ib = (255.99 * color.b()) as u8;
|
||||||
|
|
||||||
buf[offset] = ir;
|
buf[offset] = ir;
|
||||||
buf[offset + 1] = ig;
|
buf[offset + 1] = ig;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::{ray::Ray, vec3::Vec3};
|
use crate::{ray::Ray, vec3::Vec3};
|
||||||
|
|
||||||
|
const RADIUS: f32 = 0.8;
|
||||||
|
|
||||||
pub struct SimpleSphere;
|
pub struct SimpleSphere;
|
||||||
|
|
||||||
impl crate::Demo for SimpleSphere {
|
impl crate::Demo for SimpleSphere {
|
||||||
|
@ -8,9 +10,13 @@ impl crate::Demo for SimpleSphere {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, buf: &mut Vec<u8>, w: usize, h: usize) {
|
fn render(&self, buf: &mut Vec<u8>, w: usize, h: usize) {
|
||||||
let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0);
|
// in my case, The resolution is 1200x800
|
||||||
let horizontal = Vec3::new(4.0, 0.0, 0.0);
|
// These numbers are calculated by first calculating the aspect ratio
|
||||||
let vertical = Vec3::new(0.0, 2.0, 0.0);
|
// and then just figuring out lower left corner, Width(2 x aspect ratio width)
|
||||||
|
// Height(2 x aspect ratio height)
|
||||||
|
let lower_left_corner = Vec3::new(-3.0, -2.0, -1.0);
|
||||||
|
let horizontal = Vec3::new(6.0, 0.0, 0.0);
|
||||||
|
let vertical = Vec3::new(0.0, 4.0, 0.0);
|
||||||
// Observer position
|
// Observer position
|
||||||
let origin = Vec3::new(0.0, 0.0, 0.0);
|
let origin = Vec3::new(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
@ -24,9 +30,9 @@ impl crate::Demo for SimpleSphere {
|
||||||
|
|
||||||
let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
||||||
let color = calc_color(ray);
|
let color = calc_color(ray);
|
||||||
let ir = (255.99 * color[0]) as u8;
|
let ir = (255.99 * color.r()) as u8;
|
||||||
let ig = (255.99 * color[1]) as u8;
|
let ig = (255.99 * color.g()) as u8;
|
||||||
let ib = (255.99 * color[2]) as u8;
|
let ib = (255.99 * color.b()) as u8;
|
||||||
|
|
||||||
buf[offset] = ir;
|
buf[offset] = ir;
|
||||||
buf[offset + 1] = ig;
|
buf[offset + 1] = ig;
|
||||||
|
@ -38,15 +44,20 @@ impl crate::Demo for SimpleSphere {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ray_hit_sphere(center: Vec3, radius: f32, ray: &Ray) -> bool {
|
fn ray_hit_sphere(center: Vec3, radius: f32, ray: &Ray) -> bool {
|
||||||
// dot(A + t*B - C, A + t*B - C) = R*R
|
// For a point to lie on a circle,
|
||||||
// when expanded we get
|
// (x-cx)^2 + (y-cy)^2 + (z-cz)^2 = R * R
|
||||||
// t * t * dot(B, B) + 2 * t * dot(B, A-C) + dot(A-C, A-C) - R*R = 0
|
// should hold true
|
||||||
|
// Aforementioned equation can be rewritten as,
|
||||||
|
// dot(p-c, p-c) since the dot product of dis-similar axises will be zero
|
||||||
|
// the expansion of this dot product will result in the same equation
|
||||||
|
// i.e. t * t * dot(B,B) + 2 * t * dot(B, A-C) + dot(A-C, A-C)
|
||||||
|
|
||||||
|
// Vector from circle center to point
|
||||||
|
let pc = ray.origin() - center;
|
||||||
|
|
||||||
// A-C
|
|
||||||
let ac = ray.origin() - center;
|
|
||||||
let a = ray.direction().dot(&ray.direction());
|
let a = ray.direction().dot(&ray.direction());
|
||||||
let b = 2.0 * ac.dot(&ray.direction());
|
let b = 2.0 * pc.dot(&ray.direction());
|
||||||
let c = ac.dot(&ac) - radius * radius;
|
let c = pc.dot(&pc) - radius * radius;
|
||||||
let discriminant = b * b - 4.0 * a * c;
|
let discriminant = b * b - 4.0 * a * c;
|
||||||
|
|
||||||
discriminant > 0.0
|
discriminant > 0.0
|
||||||
|
@ -55,8 +66,8 @@ fn ray_hit_sphere(center: Vec3, radius: f32, ray: &Ray) -> bool {
|
||||||
fn calc_color(ray: Ray) -> Vec3 {
|
fn calc_color(ray: Ray) -> Vec3 {
|
||||||
// linear interpolation based on y coordinate
|
// linear interpolation based on y coordinate
|
||||||
// top to down
|
// top to down
|
||||||
// center at z=-1. xy axis cuts sphere in half
|
// center at z=-1. xy axis cuts sphere in 4 parts
|
||||||
if ray_hit_sphere(Vec3::new(0.0, 0.0, 1.0), 0.5, &ray) {
|
if ray_hit_sphere(Vec3::new(0.0, 0.0, -1.0), RADIUS, &ray) {
|
||||||
// For all rays that hit sphere, return red color
|
// For all rays that hit sphere, return red color
|
||||||
// This will result in a sphere that is red in color
|
// This will result in a sphere that is red in color
|
||||||
return Vec3::new(1.0, 0.0, 0.0);
|
return Vec3::new(1.0, 0.0, 0.0);
|
||||||
|
|
79
ria-weekend/src/demos/surface_normal_sphere.rs
Normal file
79
ria-weekend/src/demos/surface_normal_sphere.rs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
use crate::{demo::Demo, ray, ray::Ray, vec3::Vec3};
|
||||||
|
|
||||||
|
const RADIUS: f32 = 0.8;
|
||||||
|
pub struct SurfaceNormalSphere;
|
||||||
|
|
||||||
|
impl crate::Demo for SurfaceNormalSphere {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
"surface_normal_sphere".to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&self, buf: &mut Vec<u8>, w: usize, h: usize) {
|
||||||
|
// in my case, The resolution is 1200x800
|
||||||
|
// These numbers are calculated by first calculating the aspect ratio
|
||||||
|
// and then just figuring out lower left corner, Width(2 x aspect ratio width)
|
||||||
|
// Height(2 x aspect ratio height)
|
||||||
|
let lower_left_corner = Vec3::new(-3.0, -2.0, -1.0);
|
||||||
|
let horizontal = Vec3::new(6.0, 0.0, 0.0);
|
||||||
|
let vertical = Vec3::new(0.0, 4.0, 0.0);
|
||||||
|
// Observer position
|
||||||
|
let origin = Vec3::new(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
let mut offset = 0;
|
||||||
|
for j in 0..h {
|
||||||
|
for i in 0..w {
|
||||||
|
let u = i as f32 / w as f32;
|
||||||
|
let v = j as f32 / h as f32;
|
||||||
|
|
||||||
|
let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
||||||
|
let color = calculate_color(ray);
|
||||||
|
let ir = (255.99 * color.r()) as u8;
|
||||||
|
let ig = (255.99 * color.g()) as u8;
|
||||||
|
let ib = (255.99 * color.b()) as u8;
|
||||||
|
|
||||||
|
buf[offset] = ir;
|
||||||
|
buf[offset + 1] = ig;
|
||||||
|
buf[offset + 2] = ib;
|
||||||
|
offset += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_color(ray: Ray) -> Vec3 {
|
||||||
|
// center at z=-1. xy axis cuts sphere in half
|
||||||
|
// blending parameter
|
||||||
|
let t = ray_hit_sphere(Vec3::new(0.0, 0.0, -1.0), RADIUS, &ray);
|
||||||
|
if t > 0.0 {
|
||||||
|
// For all rays that hit sphere, return red color
|
||||||
|
// This will result in a sphere that is red in color
|
||||||
|
let n = (ray.point_at_parameter(t) - Vec3::new(0.0, 0.0, -1.0)).unit_vector();
|
||||||
|
return Vec3::new(n.x() + 1.0, n.y() + 1.0, n.z() + 1.0) * 0.5;
|
||||||
|
}
|
||||||
|
let unit_direction = ray.direction().unit_vector();
|
||||||
|
// For rays that don't hit sphere, It'll paint the gradient as the background
|
||||||
|
// Linear gradient depends on y
|
||||||
|
let t = 0.5 * (unit_direction.y() + 1.0);
|
||||||
|
|
||||||
|
// start color + end color
|
||||||
|
Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ray_hit_sphere(center: Vec3, radius: f32, ray: &Ray) -> f32 {
|
||||||
|
// dot(A + t*B - C, A + t*B - C) = R*R
|
||||||
|
// when expanded we get
|
||||||
|
// t * t * dot(B, B) + 2 * t * dot(B, A-C) + dot(A-C, A-C) - R*R = 0
|
||||||
|
|
||||||
|
let oc = ray.origin() - center;
|
||||||
|
let a = ray.direction().dot(&ray.direction());
|
||||||
|
let b = 2.0 * oc.dot(&ray.direction());
|
||||||
|
let c = oc.dot(&oc) - radius * radius;
|
||||||
|
let discriminant = b * b - 4.0 * a * c;
|
||||||
|
|
||||||
|
if discriminant >= 0.0 {
|
||||||
|
// return quadratic root
|
||||||
|
(-b - discriminant.sqrt()) / (2.0 * a)
|
||||||
|
} else {
|
||||||
|
-1.0
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ mod ray;
|
||||||
mod vec3;
|
mod vec3;
|
||||||
|
|
||||||
use demo::Demo;
|
use demo::Demo;
|
||||||
use demos::{LinearInterpolationY, PpmExample, SimpleSphere};
|
use demos::{LinearInterpolationY, PpmExample, SimpleSphere, SurfaceNormalSphere};
|
||||||
use sdl2::{
|
use sdl2::{
|
||||||
event::{Event, WindowEvent},
|
event::{Event, WindowEvent},
|
||||||
keyboard::Keycode,
|
keyboard::Keycode,
|
||||||
|
@ -19,7 +19,7 @@ fn main() -> Result<(), String> {
|
||||||
let sdl_ctx = sdl2::init()?;
|
let sdl_ctx = sdl2::init()?;
|
||||||
let video_subsys = sdl_ctx.video()?;
|
let video_subsys = sdl_ctx.video()?;
|
||||||
|
|
||||||
let (mut width, mut height): (usize, usize) = (500, 500);
|
let (mut width, mut height): (usize, usize) = (1200, 800);
|
||||||
|
|
||||||
let mut window = video_subsys
|
let mut window = video_subsys
|
||||||
.window("Ray tracing in a weekend", width as u32, height as u32)
|
.window("Ray tracing in a weekend", width as u32, height as u32)
|
||||||
|
@ -35,7 +35,7 @@ fn main() -> Result<(), String> {
|
||||||
.build()
|
.build()
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
// Buffer to store a RGBA framebuffer
|
// RGBA framebuffer
|
||||||
let mut buffer = vec![0; height * width * 4];
|
let mut buffer = vec![0; height * width * 4];
|
||||||
|
|
||||||
let texture_creator = canvas.texture_creator();
|
let texture_creator = canvas.texture_creator();
|
||||||
|
@ -43,10 +43,10 @@ fn main() -> Result<(), String> {
|
||||||
.create_texture_static(PixelFormatEnum::BGR888, width as u32, height as u32)
|
.create_texture_static(PixelFormatEnum::BGR888, width as u32, height as u32)
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let mut active_demo: Box<Demo> = Box::new(LinearInterpolationY);
|
let mut active_demo: Box<dyn Demo> = Box::new(PpmExample);
|
||||||
|
|
||||||
//println!("{:?} {:?} {:?}", texture.query(), texture.color_mod(), texture.alpha_mod());
|
//println!("{:?} {:?} {:?}", texture.query(), texture.color_mod(), texture.alpha_mod());
|
||||||
|
let mut should_update = true;
|
||||||
loop {
|
loop {
|
||||||
for event in event_pump.poll_iter() {
|
for event in event_pump.poll_iter() {
|
||||||
match event {
|
match event {
|
||||||
|
@ -58,15 +58,31 @@ fn main() -> Result<(), String> {
|
||||||
Event::KeyUp {
|
Event::KeyUp {
|
||||||
keycode: Some(Keycode::Num1),
|
keycode: Some(Keycode::Num1),
|
||||||
..
|
..
|
||||||
} => active_demo = Box::new(PpmExample),
|
} => {
|
||||||
|
should_update = true;
|
||||||
|
active_demo = Box::new(PpmExample);
|
||||||
|
}
|
||||||
Event::KeyUp {
|
Event::KeyUp {
|
||||||
keycode: Some(Keycode::Num2),
|
keycode: Some(Keycode::Num2),
|
||||||
..
|
..
|
||||||
} => active_demo = Box::new(LinearInterpolationY),
|
} => {
|
||||||
|
should_update = true;
|
||||||
|
active_demo = Box::new(LinearInterpolationY);
|
||||||
|
}
|
||||||
Event::KeyUp {
|
Event::KeyUp {
|
||||||
keycode: Some(Keycode::Num3),
|
keycode: Some(Keycode::Num3),
|
||||||
..
|
..
|
||||||
} => active_demo = Box::new(SimpleSphere),
|
} => {
|
||||||
|
should_update = true;
|
||||||
|
active_demo = Box::new(SimpleSphere);
|
||||||
|
}
|
||||||
|
Event::KeyUp {
|
||||||
|
keycode: Some(Keycode::Num4),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
should_update = true;
|
||||||
|
active_demo = Box::new(SurfaceNormalSphere);
|
||||||
|
}
|
||||||
Event::KeyUp {
|
Event::KeyUp {
|
||||||
keycode: Some(Keycode::S),
|
keycode: Some(Keycode::S),
|
||||||
..
|
..
|
||||||
|
@ -81,14 +97,17 @@ fn main() -> Result<(), String> {
|
||||||
texture = texture_creator
|
texture = texture_creator
|
||||||
.create_texture_static(PixelFormatEnum::BGR888, width as u32, height as u32)
|
.create_texture_static(PixelFormatEnum::BGR888, width as u32, height as u32)
|
||||||
.expect("error in resizing texture");
|
.expect("error in resizing texture");
|
||||||
|
should_update = true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if should_update {
|
||||||
active_demo.render(&mut buffer, width, height);
|
active_demo.render(&mut buffer, width, height);
|
||||||
texture.update(None, &buffer, width * 4);
|
texture.update(None, &buffer, width * 4);
|
||||||
canvas.copy(&texture, None, None);
|
canvas.copy(&texture, None, None);
|
||||||
canvas.present();
|
canvas.present();
|
||||||
|
should_update = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::vec3::Vec3;
|
use crate::vec3::Vec3;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Ray {
|
pub struct Ray {
|
||||||
a: Vec3,
|
a: Vec3,
|
||||||
b: Vec3,
|
b: Vec3,
|
||||||
|
@ -9,13 +10,16 @@ impl Ray {
|
||||||
pub fn new(a: Vec3, b: Vec3) -> Ray {
|
pub fn new(a: Vec3, b: Vec3) -> Ray {
|
||||||
Ray { a, b }
|
Ray { a, b }
|
||||||
}
|
}
|
||||||
pub fn origin(&self) -> Vec3 {
|
#[inline]
|
||||||
return self.a;
|
pub const fn origin(&self) -> Vec3 {
|
||||||
|
self.a
|
||||||
}
|
}
|
||||||
pub fn direction(&self) -> Vec3 {
|
#[inline]
|
||||||
return self.b;
|
pub const fn direction(&self) -> Vec3 {
|
||||||
|
self.b
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn point_at_parameter(&self, t: f32) -> Vec3 {
|
pub fn point_at_parameter(&self, t: f32) -> Vec3 {
|
||||||
return self.a + self.b * t;
|
self.a + self.b * t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,43 +6,51 @@ pub struct Vec3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vec3 {
|
impl Vec3 {
|
||||||
|
#[inline]
|
||||||
pub fn new(a: f32, b: f32, c: f32) -> Vec3 {
|
pub fn new(a: f32, b: f32, c: f32) -> Vec3 {
|
||||||
Vec3 { inner: [a, b, c] }
|
Vec3 { inner: [a, b, c] }
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn x(&self) -> f32 {
|
pub fn x(&self) -> f32 {
|
||||||
self[0]
|
self[0]
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn y(&self) -> f32 {
|
pub fn y(&self) -> f32 {
|
||||||
self[1]
|
self[1]
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn z(&self) -> f32 {
|
pub fn z(&self) -> f32 {
|
||||||
self[2]
|
self[2]
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn r(&self) -> f32 {
|
pub fn r(&self) -> f32 {
|
||||||
self[0]
|
self[0]
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn g(&self) -> f32 {
|
pub fn g(&self) -> f32 {
|
||||||
self[1]
|
self[1]
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn b(&self) -> f32 {
|
pub fn b(&self) -> f32 {
|
||||||
self[2]
|
self[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn length(&self) -> f32 {
|
pub fn length(&self) -> f32 {
|
||||||
self.sq_len().sqrt()
|
self.sq_len().sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn sq_len(&self) -> f32 {
|
pub fn sq_len(&self) -> f32 {
|
||||||
self[0] * self[0]
|
self[0] * self[0] + self[1] * self[1] + self[2] * self[2]
|
||||||
+ self[1] * self[1]
|
|
||||||
+ self[2] * self[2]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn dot(&self, v: &Vec3) -> f32 {
|
pub fn dot(&self, v: &Vec3) -> f32 {
|
||||||
self[0] * v[0] + self[1] * v[1] + self[2] * v[2]
|
self[0] * v[0] + self[1] * v[1] + self[2] * v[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn cross(&self, v: &Vec3) -> Vec3 {
|
pub fn cross(&self, v: &Vec3) -> Vec3 {
|
||||||
Vec3 {
|
Vec3 {
|
||||||
inner: [
|
inner: [
|
||||||
|
@ -52,7 +60,7 @@ impl Vec3 {
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn unit_vector(&self) -> Vec3 {
|
pub fn unit_vector(&self) -> Vec3 {
|
||||||
let length = self.length();
|
let length = self.length();
|
||||||
Vec3 {
|
Vec3 {
|
||||||
|
@ -66,11 +74,7 @@ impl Add for Vec3 {
|
||||||
|
|
||||||
fn add(self, o: Vec3) -> Vec3 {
|
fn add(self, o: Vec3) -> Vec3 {
|
||||||
Vec3 {
|
Vec3 {
|
||||||
inner: [
|
inner: [self[0] + o[0], self[1] + o[1], self[2] + o[2]],
|
||||||
self[0] + o[0],
|
|
||||||
self[1] + o[1],
|
|
||||||
self[2] + o[2],
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,11 +84,7 @@ impl Sub for Vec3 {
|
||||||
|
|
||||||
fn sub(self, o: Vec3) -> Vec3 {
|
fn sub(self, o: Vec3) -> Vec3 {
|
||||||
Vec3 {
|
Vec3 {
|
||||||
inner: [
|
inner: [self[0] - o[0], self[1] - o[1], self[2] - o[2]],
|
||||||
self[0] - o[0],
|
|
||||||
self[1] - o[1],
|
|
||||||
self[2] - o[2],
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,11 +119,7 @@ impl Div<Vec3> for Vec3 {
|
||||||
|
|
||||||
fn div(self, o: Vec3) -> Vec3 {
|
fn div(self, o: Vec3) -> Vec3 {
|
||||||
Vec3 {
|
Vec3 {
|
||||||
inner: [
|
inner: [self[0] / o[0], self[1] / o[1], self[2] / o[2]],
|
||||||
self[0] / o[0],
|
|
||||||
self[1] / o[1],
|
|
||||||
self[2] / o[2],
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user