0%

RayTracing.vol2

Github Repo


定义 Vec3 使用了元组结构体,其中每个字段的类型都为 f32,对 Vec3 进行初始化调用定义, 实现加、减、取反、数乘、复合算数赋值(关于自定义运算符 Trait 可在 https://doc.rust-lang.org 找到)、点乘与叉乘的方法,并且定义了 Vec3 的两个 type alias Color 与 Point3.

[lib.rs] 对 Vec3 结构体进行定义,定义 Vec3 的一些简单方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
use std::ops::{Add,AddAssign,Div,DivAssign,Mul,MulAssign,Neg,Sub};

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Vec3(pub f32, pub f32, pub f32);

impl Default for Vec3 {
fn default() -> Self {
Vec3(0.0, 0.0, 0.0)
}
} //没有必要

impl Vec3 {
pub fn new(e0: f32, e1: f32, e2: f32) -> Vec3 {
Vec3(e0, e1, e2)
}
pub fn x(&self) -> f32 {
self.0
}
pub fn y(&self) -> f32 {
self.1
}
pub fn z(&self) -> f32 {
self.2
}
pub fn length_squared(&self) -> f32 {
self.0 * self.0 + self.1 * self.1 + self.2 * self.2
}
pub fn length(&self) -> f32 {
self.length_squared().sqrt()
}
}

关于 Vec3 类的构造方式有两种,一种是直接 let v = Vec3(2.0,3.0,4.0);,另一种是 let v = Vec3::new(2.0,3.0,4.0);,我原本在第四行定义的为pub struct Vec3(f32, f32, f32);,这种定义方法会导致在其他 crate 中无法使用第一种构造方法,只能使用第二种。

[lib.rs] 定义 Vec3 的加减取反 Trait
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
impl Neg for Vec3 {
type Output = Self;

fn neg(self) -> Self {
Vec3(-self.0, -self.1, -self.2)
}
}

impl Add for Vec3 {
type Output = Vec3;
fn add(self, other: Self) -> Self {
Vec3(self.0 + other.0, self.1 + other.1, self.2 + other.2)
}
}

impl Sub for Vec3 {
type Output = Vec3;

fn sub(self, other: Self) -> Self {
Vec3(self.0 - other.0, self.1 - other.1, self.2 - other.2)
}
}
[lib.rs] 定义 Vec3 的数乘除 Trait
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
impl Mul for Vec3 {
type Output = Vec3;

fn mul(self, other: Vec3) -> Self {
Vec3(self.0 * other.0, self.1 * other.1, self.2 * other.2)
}
}

impl Mul<f32> for Vec3 {
type Output = Self;

fn mul(self, other: f32) -> Self {
Vec3(self.0 * other, self.1 * other, self.2 * other)
}
}

impl Mul<Vec3> for f32 {
type Output = Vec3;

fn mul(self, other: Vec3) -> Vec3 {
other * self
}
}

impl Div<f32> for Vec3 {
type Output = Self;

fn div(self, other: f32) -> Self {
self * (1.0 / other)
}
}

关于 Vec3 的乘法 Trait,要注意的是需要定义两次,因为乘法左右两边数据结构不同,需要定义f32*Vec3 与 Vec3*f32

[lib.rs] 定义 Vec3 的复合算数赋值 Trait
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
impl AddAssign<Vec3> for Vec3 {
fn add_assign(&mut self, other: Vec3) {
*self = Self(self.0 + other.0, self.1 + other.1, self.2 + other.2);
}
}

impl MulAssign<f32> for Vec3 {
fn mul_assign(&mut self, other: f32) {
*self = Self(self.0 * other, self.1 * other, self.2 * other);
}
}

impl DivAssign<f32> for Vec3 {
fn div_assign(&mut self, other: f32) {
*self *= 1.0 / other;
}
}
[lib.rs] 实现 Vec3 的点乘叉乘和单位向量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
pub fn dot(u: Vec3, v: Vec3) -> f32 {
u.0 * v.0 + u.1 * v.1 + u.2 * v.2
}

pub fn cross(u: Vec3, v: Vec3) -> Vec3 {
Vec3(
u.1 * v.2 - u.2 * v.1,
u.2 * v.0 - u.0 * v.2,
u.0 * v.1 - u.1 * v.0,
)
}

pub fn unit_vector(u: Vec3) -> Vec3 {
u / u.length()
}

pub type Point3 = Vec3;
pub type Color = Vec3;
[color.rs] 规范返回值
1
2
3
4
5
6
7
8
9
10
11
12
use ray::Color;

pub fn write_color(pixel_color: Color) -> String {
unsafe {
format!(
"{} {} {}\n",
(255.999 * pixel_color.x()).to_int_unchecked::<u16>(),
(255.999 * pixel_color.y()).to_int_unchecked::<u16>(),
(255.999 * pixel_color.z()).to_int_unchecked::<u16>()
)
}
}
[main.rs] 重构 main 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mod color;
mod rayh;
use color::*;
use ray::Vec3;

const IMAGE_WIDTH: u16 = 256;
const IMAGE_HEIGHT: u16 = 256;

fn main() {
println! {"P3\n{} {}\n255",IMAGE_WIDTH,IMAGE_HEIGHT};
for j in (0..IMAGE_HEIGHT).rev() {
eprintln!("\rScanlines remaining:{}", j);
for i in 0..IMAGE_WIDTH {
let pixel_color = Vec3::new(
i as f32 / (IMAGE_WIDTH - 1) as f32,
j as f32 / (IMAGE_HEIGHT - 1) as f32,
0.25 as f32,
);
print!("{}", write_color(pixel_color));
}
}
eprintln!("\nDone");
}