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 } }