1use bytemuck::{Pod, Zeroable};
4use glam::{Mat4, Vec2, Vec3A, vec2};
5
6use crate::{Boundable, Transformable, aabb::Aabb, ray::Ray};
7
8#[derive(Clone, Copy, Default, Debug, Zeroable)]
9pub struct Triangle {
10 pub v0: Vec3A,
11 pub v1: Vec3A,
12 pub v2: Vec3A,
13}
14
15unsafe impl Pod for Triangle {}
16
17impl Triangle {
18 #[inline(always)]
20 pub fn compute_normal(&self) -> Vec3A {
21 let e1 = self.v1 - self.v0;
22 let e2 = self.v2 - self.v0;
23 e1.cross(e2).normalize_or_zero()
24 }
25
26 #[inline(always)]
28 pub fn aabb(&self) -> Aabb {
29 Aabb::from_points(&[self.v0, self.v1, self.v2])
30 }
31
32 #[inline(always)]
35 pub fn intersect(&self, ray: &Ray) -> f32 {
36 let cull_backface = false;
41 let e1 = self.v0 - self.v1;
42 let e2 = self.v2 - self.v0;
43 let n = e1.cross(e2);
44
45 let c = self.v0 - ray.origin;
46 let r = ray.direction.cross(c);
47 let inv_det = 1.0 / n.dot(ray.direction);
48
49 let u = r.dot(e2) * inv_det;
50 let v = r.dot(e1) * inv_det;
51 let w = 1.0 - u - v;
52
53 let hit = u.to_bits() | v.to_bits() | w.to_bits();
62 let valid = if cull_backface {
63 (inv_det.to_bits() | hit) & 0x8000_0000 == 0
64 } else {
65 inv_det != 0.0 && hit & 0x8000_0000 == 0
66 };
67
68 if valid {
69 let t = n.dot(c) * inv_det;
70 if t >= ray.tmin && t <= ray.tmax {
71 return t;
72 }
73 }
74
75 f32::INFINITY
76 }
77
78 #[cfg(all(
80 any(target_arch = "x86", target_arch = "x86_64"),
81 target_feature = "sse2"
82 ))]
83 pub fn intersect_embree(&self, ray: &Ray) -> f32 {
84 let cull_backface = false;
89 let v0 = self.v0;
90 let e1 = self.v0 - self.v1;
91 let e2 = self.v2 - self.v0;
92 let ng = e1.cross(e2);
93
94 let o = ray.origin;
96 let d = ray.direction;
97 let c = v0 - o;
98 let r = c.cross(d);
99 let den = (-ng).dot(d);
100 let abs_den = den.abs();
101
102 fn signmsk(x: f32) -> f32 {
103 #[cfg(target_arch = "x86")]
104 use std::arch::x86::*;
105 #[cfg(target_arch = "x86_64")]
106 use std::arch::x86_64::*;
107 unsafe {
108 let mask = _mm_set1_ps(-0.0);
109 let x_vec = _mm_set_ss(x);
110 let sign_bit = _mm_and_ps(x_vec, mask);
111 _mm_cvtss_f32(sign_bit)
112 }
117 }
118
119 let sgn_den = signmsk(den).to_bits();
120
121 let u = f32::from_bits(r.dot(e2).to_bits() ^ sgn_den);
123 let v = f32::from_bits(r.dot(e1).to_bits() ^ sgn_den);
124 let w = abs_den - u - v;
135 let valid = if cull_backface {
136 ((-den).to_bits() | u.to_bits() | v.to_bits() | (abs_den - u - v).to_bits())
137 & 0x8000_0000
138 == 0
139 } else {
140 den != 0.0 && ((u.to_bits() | v.to_bits() | w.to_bits()) & 0x8000_0000) == 0
141 };
142
143 if !valid {
144 return f32::INFINITY;
145 }
146
147 let t = f32::from_bits((-ng).dot(c).to_bits() ^ sgn_den);
149
150 if abs_den * ray.tmin < t && t <= abs_den * ray.tmax {
151 return t;
152 }
153
154 f32::INFINITY
155 }
156
157 #[inline(always)]
158 pub fn compute_barycentric(&self, ray: &Ray) -> Vec2 {
159 let e1 = self.v0 - self.v1;
160 let e2 = self.v2 - self.v0;
161 let ng = e1.cross(e2).normalize_or_zero();
162 let r = ray.direction.cross(self.v0 - ray.origin);
163 vec2(r.dot(e2), r.dot(e1)) / ng.dot(ray.direction)
164 }
165}
166
167impl Boundable for Triangle {
168 #[inline(always)]
169 fn aabb(&self) -> Aabb {
170 self.aabb()
171 }
172}
173
174impl Transformable for &mut Triangle {
175 fn transform(&mut self, matrix: &Mat4) {
176 self.v0 = matrix.transform_point3a(self.v0);
177 self.v1 = matrix.transform_point3a(self.v1);
178 self.v2 = matrix.transform_point3a(self.v2);
179 }
180}
181
182impl<T> Transformable for T
183where
184 T: AsMut<[Triangle]>,
185{
186 fn transform(&mut self, matrix: &Mat4) {
187 self.as_mut().iter_mut().for_each(|mut triangle| {
188 triangle.transform(matrix);
189 });
190 }
191}