Created
January 14, 2019 14:13
-
-
Save ysnrkdm/dc3370f55b22d2314b6dedee7698067f to your computer and use it in GitHub Desktop.
vector.rs - レンダリングエンジン用のベクトルデータ構造
This file contains hidden or 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
#![feature(trace_macros)] | |
use std::ops::{Add, Sub, Mul, Div, Neg, AddAssign, MulAssign}; | |
#[derive(Copy, Clone, Debug)] | |
#[repr(C)] | |
pub struct Vector3 { | |
pub x: f64, | |
pub y: f64, | |
pub z: f64, | |
} | |
impl Vector3 { | |
//<editor-fold desc="Constructors"> | |
pub fn new(x: f64, y: f64, z: f64) -> Vector3 { | |
Vector3 {x, y, z} | |
} | |
pub fn all_of(v: f64) -> Vector3 { | |
Vector3 {x: v, y: v, z: v} | |
} | |
pub fn zero() -> Vector3 { | |
Vector3::all_of(0.0) | |
} | |
pub fn one() -> Vector3 { | |
Vector3::all_of(1.0) | |
} | |
//</editor-fold> | |
pub fn norm(&self) -> f64 { | |
(self.x * self.x + self.y * self.y + self.z * self.z) | |
} | |
pub fn length(&self) -> f64 { | |
self.norm().sqrt() | |
} | |
pub fn normalized(&self) -> Vector3 { | |
let inv_len = self.length().recip(); | |
Vector3 { | |
x: self.x * inv_len, | |
y: self.y * inv_len, | |
z: self.z * inv_len, | |
} | |
} | |
pub fn dot(&self, other: &Vector3) -> f64 { | |
self.x * other.x + self.y * other.y + self.z * other.z | |
} | |
pub fn cross(&self, other: &Vector3) -> Vector3 { | |
Vector3 { | |
x: self.y * other.z - self.z * other.y, | |
y: self.z * other.x - self.x * other.z, | |
z: self.x * other.y - self.y * other.x, | |
} | |
} | |
pub fn reflect(&self, normal: &Vector3) -> Vector3 { | |
(*self) - 2.0 * self.dot(&normal) * (*normal) | |
} | |
pub fn refract(&self, normal: &Vector3, refractive_index: f64) -> Vector3 { | |
let k = 1.0 - refractive_index * refractive_index * (1.0 - normal.dot(self) * self.dot(normal)); | |
if k < 0.0 { | |
Vector3::zero() | |
} else { | |
refractive_index * *self - (refractive_index * self.dot(normal) + k.sqrt()) * *normal | |
} | |
} | |
} | |
macro_rules! impl_op_v2v_for { | |
($trait_: ident, $templ_type_: ident, $for_: ident, $op_: ident, $($member_: ident),*) => { | |
impl $trait_<$templ_type_> for $for_ { | |
type Output = $for_; | |
fn $op_(self, other: $for_) -> $for_ { | |
$for_ { | |
$($member_: $trait_::$op_(self.$member_, other.$member_),)* | |
} | |
} | |
} | |
} | |
} | |
macro_rules! impl_op_v2f_for { | |
($trait_: ident, $templ_type_: ident, $for_: ident, $op_: ident, $($member_: ident),*) => { | |
impl $trait_<$templ_type_> for $for_ { | |
type Output = $for_; | |
fn $op_(self, other: $templ_type_) -> $for_ { | |
$for_ { | |
$( | |
$member_: $trait_::$op_(self.$member_, other), | |
)* | |
} | |
} | |
} | |
} | |
} | |
macro_rules! impl_ops_for_xyz { | |
($macro_name_: ident, $to_type_: ident, $with_type: ident, $(($trait_: ident, $op_fn_: ident)),*) => { | |
$( | |
$macro_name_!($trait_, $with_type, $to_type_, $op_fn_, x, y, z); | |
)* | |
} | |
} | |
//trace_macros!(true); | |
impl_ops_for_xyz!(impl_op_v2v_for, Vector3, Vector3, (Add, add), (Sub, sub), (Mul, mul), (Div, div)); | |
impl_ops_for_xyz!(impl_op_v2f_for, Vector3, f64, (Add, add), (Sub, sub), (Mul, mul), (Div, div)); | |
impl Mul<Vector3> for f64 { | |
type Output = Vector3; | |
fn mul(self, other: Vector3) -> Vector3 { | |
other * self | |
} | |
} | |
impl Neg for Vector3 { | |
type Output = Vector3; | |
fn neg(self) -> Vector3 { | |
Vector3 { | |
x: -self.x, | |
y: -self.y, | |
z: -self.z, | |
} | |
} | |
} | |
impl AddAssign for Vector3 { | |
fn add_assign(&mut self, other: Vector3) { | |
self.x += other.x; | |
self.y += other.y; | |
self.z += other.z; | |
} | |
} | |
impl MulAssign for Vector3 { | |
fn mul_assign(&mut self, other: Vector3) { | |
self.x *= other.x; | |
self.y *= other.y; | |
self.z *= other.z; | |
} | |
} | |
impl MulAssign<f64> for Vector3 { | |
fn mul_assign(&mut self, other: f64) { | |
self.x *= other; | |
self.y *= other; | |
self.z *= other; | |
} | |
} | |
#[derive(Copy, Clone, Debug)] | |
#[repr(C)] | |
pub struct Vector2 { | |
pub x: f64, | |
pub y: f64, | |
} | |
impl Vector2 { | |
pub fn new(x: f64, y: f64) -> Vector2 { | |
Vector2 {x, y} | |
} | |
pub fn all_of(v: f64) -> Vector2 { | |
Vector2 {x: v, y: v} | |
} | |
pub fn zero() -> Vector2 { | |
Vector2::all_of(0.0) | |
} | |
pub fn norm(&self) -> f64 { | |
self.x * self.x + self.y * self.y | |
} | |
pub fn length(&self) -> f64 { | |
self.norm().sqrt() | |
} | |
pub fn normalized(&self) -> Vector2 { | |
let inv_len = self.length().recip(); | |
Vector2 { | |
x: self.x * inv_len, | |
y: self.y * inv_len, | |
} | |
} | |
pub fn dot(&self, other: Vector2) -> f64 { | |
self.x * other.x + self.y * other.y | |
} | |
pub fn cross(&self, other: Vector2) -> f64 { | |
self.x * other.y - other.x * self.y | |
} | |
} | |
macro_rules! impl_ops_for_xy { | |
($macro_name_: ident, $to_type_: ident, $with_type: ident, $(($trait_: ident, $op_fn_: ident)),*) => { | |
$( | |
$macro_name_!($trait_, $with_type, $to_type_, $op_fn_, x, y); | |
)* | |
} | |
} | |
//trace_macros!(true); | |
impl_ops_for_xy!(impl_op_v2v_for, Vector2, Vector2, (Add, add), (Sub, sub), (Mul, mul), (Div, div)); | |
impl_ops_for_xy!(impl_op_v2f_for, Vector2, f64, (Add, add), (Sub, sub), (Mul, mul), (Div, div)); | |
impl Mul<Vector2> for f64 { | |
type Output = Vector2; | |
fn mul(self, other: Vector2) -> Vector2 { | |
other * self | |
} | |
} | |
impl Neg for Vector2 { | |
type Output = Vector2; | |
fn neg(self) -> Vector2 { | |
Vector2 { | |
x: -self.x, | |
y: -self.y | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment