ray-trace-w1/src/math_utils.rs

64 lines
2.0 KiB
Rust

use crate::types_defined::{Ray, Vec3};
pub fn clamp(value: f32, low: f32, high: f32) -> f32 {
if value < low {
return low;
}
if value > high {
return high;
}
return value;
}
pub fn near_zero(v: Vec3) -> bool {
const EPSILON: f32 = 1e-4;
v.x.abs() < EPSILON && v.y.abs() < EPSILON && v.z.abs() < EPSILON
}
pub fn reflect(v: Vec3, n: Vec3) -> Vec3 {
v - ((2.0 * v.dot(n)) * n)
}
// v, normal, 折射率
pub fn refract(uv: Vec3, n: Vec3, etai_over_etat: f32) -> Vec3 {
// auto cos_theta = std::fmin(dot(-uv, n), 1.0);
// vec3 r_out_perp = etai_over_etat * (uv + cos_theta*n);
// vec3 r_out_parallel = -std::sqrt(std::fabs(1.0 - r_out_perp.length_squared())) * n;
// return r_out_perp + r_out_parallel;
let cos_theta = (-uv.dot(n)).min(1.0);
let r_out_perp = etai_over_etat * (uv + cos_theta * n);
let r_out_parallel = -(f32::sqrt(f32::abs(1.0 - r_out_perp.length()))) * n;
r_out_perp + r_out_parallel
// let v_normalized = v;
// let n_normalized = n.normalize();
// let cos_theta = f32::min(-v_normalized.dot(n_normalized), 1.0);
// let sin_theta = (1.0 - cos_theta * cos_theta).sqrt();
// // 检查是否全内反射(无法折射)
// if etai_over_etat * sin_theta > 1.0 {
// return reflect(v_normalized, n)
// }
// let r_out_perp = etai_over_etat * (v_normalized + cos_theta * n_normalized);
// let discriminant = 1.0 - r_out_perp.length_squared();
// // if discriminant < 0.0 {
// // return -1.0 * v; // 全内反射,返回零向量(或改为反射)
// // }
// let r_out_parallel = -discriminant * n_normalized;
// r_out_perp + r_out_parallel
}
pub fn is_front_face(r: &Ray, outward_normal: Vec3) -> bool {
r.direction.dot(outward_normal) < 0.0
}
pub fn front_face_normal(r: &Ray, outward_normal: Vec3) -> Vec3 {
if is_front_face(r, outward_normal) {
outward_normal
} else {
-1. * outward_normal
}
}