From 0c7ef49a3508f1956a26b1b89102cb69bbd6cd15 Mon Sep 17 00:00:00 2001 From: dengqn <434500374@qq.com> Date: Thu, 31 Jul 2025 18:12:20 +0800 Subject: [PATCH] 3.The vec3 Class --- src/image.rs | 24 +++++++++-- src/main.rs | 15 ++++++- src/vec3.rs | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 src/vec3.rs diff --git a/src/image.rs b/src/image.rs index 0017c1e..c5a5515 100644 --- a/src/image.rs +++ b/src/image.rs @@ -1,3 +1,16 @@ +use crate::vec3; + + +pub type Color = vec3::Vec3; + + +impl Color { + pub fn to_color(self) -> String { + return format!("{} {} {}\n", (self.x * 256.0) as u8, (self.y * 256.0) as u8, (self.z * 256.0) as u8); + } +} + + /* * -------width(i)------- * | @@ -22,12 +35,15 @@ pub fn gen_gradient_ppm_p3(width: i32, height: i32) -> String { let mut img_content = format!("P3\n{} {}\n255\n", width, height); for j in 0..height { + println!("scan line {}/{} ", j + 1, height); for i in 0..width { - let r = 256.0 * (i as f32 / (width-1) as f32); - let g = 256.0 * (j as f32 / (height-1) as f32); - let b = 256.0 * ((i+j) as f32 / (width + height - 2) as f32); + let r = i as f32 / (width-1) as f32; + let g = j as f32 / (height-1) as f32; + let b = (i+j) as f32 / (width + height - 2) as f32; + + let color = Color::new(r, g, b); + img_content.push_str(color.to_color().as_str()); - img_content.push_str(format!("{} {} {}", r as u8, g as u8, b as u8).as_str()); img_content.push('\n'); } } diff --git a/src/main.rs b/src/main.rs index efcc1ad..7f010b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,23 @@ use write_file_util::{write_image}; -use image::{gen_gradient_ppm_p3}; +use image::{gen_gradient_ppm_p3, Color}; +use vec3::{Vec3}; mod image; mod write_file_util; +mod vec3; fn main() { let ppm_content = gen_gradient_ppm_p3(400, 225); + + let v1 = Vec3::new(1.0, 1.0, 1.0); + let v2 = Vec3::new(1.0, 1.0, 1.0); + + println!("v: {:#} + {:#} => {:#}", v1, v2, v1 + v2); + println!("v: {:#} + {:#} => {:#}", v1, v2, v1 - v2); + println!("v: {:#} + {:#} => {:#}", v1, v2, v1.dot(v2)); + println!("v: {:#} + {:#} => {:#}", v1, v2, v1.cross(v2)); + + println!("color: {:#}", Color::new(0.3, 0.4, 1.0).to_color()); + write_image(ppm_content, "./target/test.ppm".to_string()) } diff --git a/src/vec3.rs b/src/vec3.rs new file mode 100644 index 0000000..3c43797 --- /dev/null +++ b/src/vec3.rs @@ -0,0 +1,116 @@ + +use std::{fmt::Display, ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}}; +use std::fmt; +/* +* [3] +*/ +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Vec3 { + pub x: f32, + pub y: f32, + pub z: f32, +} + +impl Display for Vec3 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "({}, {}, {})", self.x, self.y, self.z) + } +} + +impl Vec3 { + pub fn new(x: f32, y: f32, z: f32) -> Self { + Vec3 { x, y, z } + } + + /// 点积运算 + pub fn dot(self, other: Vec3) -> f32 { + self.x * other.x + self.y * other.y + self.z * other.z + } + + /// 叉积运算 + pub fn cross(self, other: Vec3) -> Vec3 { + Vec3 { + 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, + } + } + + /// 向量长度 + fn magnitude(self) -> f32 { + (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt() + } +} + +impl Add for Vec3 { + type Output = Self; + + fn add(self, other: Self) -> Self { + Vec3 { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z } + } +} + +// 向量减法: Vec3 - Vec3 +impl Sub for Vec3 { + type Output = Self; + + fn sub(self, other: Self) -> Self { + Vec3 { + x: self.x - other.x, + y: self.y - other.y, + z: self.z - other.z, + } + } +} + +// 标量乘法: Vec3 * f32 +impl Mul for Vec3 { + type Output = Self; + + fn mul(self, scalar: f32) -> Self { + Vec3 { + x: self.x * scalar, + y: self.y * scalar, + z: self.z * scalar, + } + } +} + +// 标量乘法: f32 * Vec3 (反向操作) +impl Mul for f32 { + type Output = Vec3; + + fn mul(self, vec: Vec3) -> Vec3 { + vec * self + } +} + +// 标量除法: Vec3 / f32 +impl Div for Vec3 { + type Output = Self; + + fn div(self, scalar: f32) -> Self { + if scalar == 0.0 { + panic!("Division by zero"); + } + Vec3 { + x: self.x / scalar, + y: self.y / scalar, + z: self.z / scalar, + } + } +} + +// 加法赋值: Vec3 += Vec3 +impl AddAssign for Vec3 { + fn add_assign(&mut self, other: Self) { + *self = *self + other; + } +} + +// 标量乘法赋值: Vec3 *= f32 +impl MulAssign for Vec3 { + fn mul_assign(&mut self, scalar: f32) { + *self = *self * scalar; + } +} \ No newline at end of file