feat(raytracer): add minimal implementation
This commit is contained in:
parent
369293598f
commit
a1ccb33a6e
151
Cargo.lock
generated
151
Cargo.lock
generated
@ -2,6 +2,15 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "approx"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "as-any"
|
name = "as-any"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@ -20,6 +29,12 @@ version = "2.6.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -133,15 +148,53 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"as-any",
|
"as-any",
|
||||||
"futures",
|
"futures",
|
||||||
|
"nalgebra",
|
||||||
"nix",
|
"nix",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matrixmultiply"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.4"
|
version = "2.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nalgebra"
|
||||||
|
version = "0.33.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"matrixmultiply",
|
||||||
|
"nalgebra-macros",
|
||||||
|
"num-complex",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"simba",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nalgebra-macros"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.29.0"
|
version = "0.29.0"
|
||||||
@ -154,6 +207,60 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
@ -184,6 +291,34 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rawpointer"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "safe_arch"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simba"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"num-complex",
|
||||||
|
"num-traits",
|
||||||
|
"paste",
|
||||||
|
"wide",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
@ -204,8 +339,24 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.13"
|
version = "1.0.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wide"
|
||||||
|
version = "0.7.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b828f995bf1e9622031f8009f8481a85406ce1f4d4588ff746d872043e855690"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"safe_arch",
|
||||||
|
]
|
||||||
|
|||||||
@ -21,4 +21,5 @@ path = "src/bin/repl.rs"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
as-any = "0.3.1"
|
as-any = "0.3.1"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
nalgebra = "0.33.2"
|
||||||
nix = "0.29.0"
|
nix = "0.29.0"
|
||||||
|
|||||||
5
src/bin/rt_demo.rs
Normal file
5
src/bin/rt_demo.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use lispers::raytracer::{scene::Scene, types::Light};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let scene = Scene::new();
|
||||||
|
}
|
||||||
@ -1,2 +1,3 @@
|
|||||||
pub mod lisp;
|
pub mod lisp;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
pub mod raytracer;
|
||||||
|
|||||||
70
src/raytracer/camera.rs
Normal file
70
src/raytracer/camera.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use super::{
|
||||||
|
scene::Scene,
|
||||||
|
types::{Point3, Ray, Scalar, Vector3},
|
||||||
|
};
|
||||||
|
// use image::Rgb32FImage;
|
||||||
|
|
||||||
|
pub struct Camera {
|
||||||
|
position: Point3,
|
||||||
|
up: Vector3,
|
||||||
|
right: Vector3,
|
||||||
|
upper_left: Point3,
|
||||||
|
x_dir: Vector3,
|
||||||
|
y_dir: Vector3,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Camera {
|
||||||
|
pub fn new(
|
||||||
|
position: Point3,
|
||||||
|
direction: Vector3,
|
||||||
|
up: Vector3,
|
||||||
|
fovy: Scalar,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
) -> Camera {
|
||||||
|
let aspect_ratio = width as Scalar / height as Scalar;
|
||||||
|
let fovx = fovy * aspect_ratio;
|
||||||
|
let right = direction.cross(&up).normalize();
|
||||||
|
let x_dir = right * (fovx / 2.0).tan();
|
||||||
|
let y_dir = -up * (fovy / 2.0).tan();
|
||||||
|
let upper_left = position + direction - x_dir + y_dir;
|
||||||
|
|
||||||
|
Camera {
|
||||||
|
position,
|
||||||
|
up,
|
||||||
|
right,
|
||||||
|
upper_left,
|
||||||
|
x_dir,
|
||||||
|
y_dir,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Camera {
|
||||||
|
pub fn ray_at_relative(&self, x: Scalar, y: Scalar) -> Ray {
|
||||||
|
let x_dir = self.x_dir * x;
|
||||||
|
let y_dir = self.y_dir * y;
|
||||||
|
Ray::new(
|
||||||
|
self.position,
|
||||||
|
(self.upper_left + x_dir - y_dir - self.position).normalize(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ray_at(&self, x: usize, y: usize) -> Ray {
|
||||||
|
let x = x as Scalar / self.width as Scalar;
|
||||||
|
let y = y as Scalar / self.height as Scalar;
|
||||||
|
self.ray_at_relative(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn render(&self, scene: &Scene, depth: u32) -> Rgb32FImage {
|
||||||
|
// Rgb32FImage::from_fn(self.width, self.height, |x, y| {
|
||||||
|
// let ray = self.ray_at(x, y);
|
||||||
|
// let color = scene.trace(&ray, depth);
|
||||||
|
// color.into()
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
}
|
||||||
5
src/raytracer/mod.rs
Normal file
5
src/raytracer/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
pub mod camera;
|
||||||
|
pub mod scene;
|
||||||
|
pub mod sphere;
|
||||||
|
pub mod types;
|
||||||
|
pub mod vec;
|
||||||
89
src/raytracer/scene.rs
Normal file
89
src/raytracer/scene.rs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
use super::types::Color;
|
||||||
|
use super::types::Intersect;
|
||||||
|
use super::types::Light;
|
||||||
|
use super::types::Material;
|
||||||
|
use super::types::Point3;
|
||||||
|
use super::types::Ray;
|
||||||
|
use super::types::Scalar;
|
||||||
|
use super::types::Vector3;
|
||||||
|
use super::vec::reflect;
|
||||||
|
extern crate nalgebra as na;
|
||||||
|
|
||||||
|
pub struct Scene {
|
||||||
|
objects: Vec<Box<dyn Intersect>>,
|
||||||
|
lights: Vec<Light>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scene {
|
||||||
|
pub fn new() -> Scene {
|
||||||
|
Scene {
|
||||||
|
objects: Vec::new(),
|
||||||
|
lights: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_object(&mut self, obj: Box<dyn Intersect>) {
|
||||||
|
self.objects.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_light(&mut self, light: Light) {
|
||||||
|
self.lights.push(light);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trace(&self, ray: &Ray, depth: u32) -> Color {
|
||||||
|
if depth == 0 {
|
||||||
|
return na::Vector3::new(0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
match self
|
||||||
|
.objects
|
||||||
|
.iter()
|
||||||
|
.filter_map(|obj| obj.intersect(ray))
|
||||||
|
.min_by(|(_, _, t1, _), (_, _, t2, _)| t1.partial_cmp(t2).unwrap())
|
||||||
|
{
|
||||||
|
None => {
|
||||||
|
return na::Vector3::new(0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
Some((isect_pt, isect_norm, isect_dist, material)) => {
|
||||||
|
// Lighting of material at the intersection point
|
||||||
|
let color =
|
||||||
|
self.lighting(-&ray.direction, material, isect_pt, isect_norm, isect_dist);
|
||||||
|
|
||||||
|
// Calculate reflections, if the material has mirror properties
|
||||||
|
if material.mirror > 0.0 {
|
||||||
|
let new_ray = Ray {
|
||||||
|
origin: isect_pt,
|
||||||
|
direction: reflect(ray.direction, isect_norm),
|
||||||
|
};
|
||||||
|
return (1.0 - material.mirror) * color
|
||||||
|
+ material.mirror * self.trace(&new_ray, depth - 1);
|
||||||
|
} else {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lighting(
|
||||||
|
&self,
|
||||||
|
view: Vector3,
|
||||||
|
material: &Material,
|
||||||
|
isect_pt: Point3,
|
||||||
|
isect_norm: Vector3,
|
||||||
|
isect_dist: Scalar,
|
||||||
|
) -> Color {
|
||||||
|
let mut color: Color = na::Vector3::new(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
for light in &self.lights {
|
||||||
|
let l = (isect_pt - light.position).normalize();
|
||||||
|
let cos_theta = l.dot(&isect_norm);
|
||||||
|
|
||||||
|
if cos_theta > 0.0 {
|
||||||
|
// Diffuse
|
||||||
|
color += material.diffuse_color.component_mul(&light.color) * cos_theta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
color
|
||||||
|
}
|
||||||
|
}
|
||||||
49
src/raytracer/sphere.rs
Normal file
49
src/raytracer/sphere.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use super::types::{Intersect, Material, Point3, Ray, Scalar, Vector3};
|
||||||
|
|
||||||
|
extern crate nalgebra as na;
|
||||||
|
|
||||||
|
pub struct Sphere {
|
||||||
|
center: Point3,
|
||||||
|
radius: Scalar,
|
||||||
|
material: Material,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Numerical error tolerance
|
||||||
|
const EPSILON: Scalar = 1e-5;
|
||||||
|
|
||||||
|
impl Intersect for Sphere {
|
||||||
|
fn intersect<'a>(&'a self, ray: &Ray) -> Option<(Point3, Vector3, Scalar, &'a Material)> {
|
||||||
|
let co = ray.origin - self.center;
|
||||||
|
|
||||||
|
let a = ray.direction.dot(&ray.direction);
|
||||||
|
let b = 2.0 * ray.direction.dot(&co);
|
||||||
|
let c = co.dot(&co) - (self.radius * self.radius);
|
||||||
|
let d = b * b - 4.0 * a * c;
|
||||||
|
|
||||||
|
if d >= 0.0 {
|
||||||
|
let e = d.sqrt();
|
||||||
|
let t1 = (-b - e) / (2.0 * a);
|
||||||
|
let t2 = (-b + e) / (2.0 * a);
|
||||||
|
let mut t = Scalar::MAX;
|
||||||
|
|
||||||
|
if t1 > EPSILON && t1 < t {
|
||||||
|
t = t1;
|
||||||
|
}
|
||||||
|
if t2 > EPSILON && t2 < t {
|
||||||
|
t = t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if t < Scalar::MAX {
|
||||||
|
let isect_pt: Point3 = ray.origin + ray.direction * t;
|
||||||
|
return Some((
|
||||||
|
isect_pt,
|
||||||
|
(isect_pt - self.center) / self.radius,
|
||||||
|
t,
|
||||||
|
&self.material,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
58
src/raytracer/types.rs
Normal file
58
src/raytracer/types.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
extern crate nalgebra as na;
|
||||||
|
|
||||||
|
pub type Scalar = f32;
|
||||||
|
pub type Vector3 = na::Vector3<Scalar>;
|
||||||
|
pub type Point3 = na::Point3<Scalar>;
|
||||||
|
pub type Color = Vector3;
|
||||||
|
|
||||||
|
pub trait Intersect {
|
||||||
|
fn intersect<'a>(&'a self, ray: &Ray) -> Option<(Point3, Vector3, Scalar, &'a Material)>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Light {
|
||||||
|
pub position: Point3,
|
||||||
|
pub color: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Light {
|
||||||
|
pub fn new(position: Point3, color: Color) -> Light {
|
||||||
|
Light { position, color }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Ray {
|
||||||
|
pub origin: Point3,
|
||||||
|
pub direction: Vector3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ray {
|
||||||
|
pub fn new(origin: Point3, direction: Vector3) -> Ray {
|
||||||
|
Ray { origin, direction }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Material {
|
||||||
|
pub ambient_color: Color,
|
||||||
|
pub diffuse_color: Color,
|
||||||
|
pub specular_color: Color,
|
||||||
|
pub shinyness: Scalar,
|
||||||
|
pub mirror: Scalar,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Material {
|
||||||
|
pub fn new(
|
||||||
|
ambient_color: Color,
|
||||||
|
diffuse_color: Color,
|
||||||
|
specular_color: Color,
|
||||||
|
shinyness: Scalar,
|
||||||
|
mirror: Scalar,
|
||||||
|
) -> Material {
|
||||||
|
Material {
|
||||||
|
ambient_color,
|
||||||
|
diffuse_color,
|
||||||
|
specular_color,
|
||||||
|
shinyness,
|
||||||
|
mirror,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/raytracer/vec.rs
Normal file
14
src/raytracer/vec.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use super::types::Vector3;
|
||||||
|
|
||||||
|
extern crate nalgebra as na;
|
||||||
|
|
||||||
|
pub fn reflect(v: Vector3, n: Vector3) -> Vector3 {
|
||||||
|
v - 2.0 * v.dot(&n) * n
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rotate(v: &Vector3, axis: &Vector3, angle: f32) -> Vector3 {
|
||||||
|
//let axis = na::Unit::new_normalize(axis);
|
||||||
|
//let rot = na::Rotation3::from_axis_angle(&axis, angle);
|
||||||
|
//(rot * v)
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user