Add AffineTransform

This commit is contained in:
hal8174 2025-07-30 22:42:13 +02:00
parent 900fe532b5
commit e16a916413
Signed by: hal8174
SSH key fingerprint: SHA256:JwuqS+eVfISfKr+DkDQ6NWAbGd1jFAHkPpCM1yCnlTs
3 changed files with 219 additions and 0 deletions

View file

@ -0,0 +1,209 @@
use std::ops::{Mul, MulAssign};
use crate::prelude::*;
#[derive(Debug, Copy, Clone)]
pub struct AffineTransform {
mat: [[Float; 4]; 3],
inv: [[Float; 3]; 3],
}
impl AffineTransform {
pub fn identity() -> Self {
Self {
mat: [
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
],
inv: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
}
}
pub fn translation(pos: Pos3) -> Self {
Self {
mat: [
[1.0, 0.0, 0.0, pos.x()],
[0.0, 1.0, 0.0, pos.y()],
[0.0, 0.0, 1.0, pos.z()],
],
inv: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
}
}
pub fn scale(sx: Float, sy: Float, sz: Float) -> Self {
Self {
mat: [
[sx, 0.0, 0.0, 0.0],
[0.0, sy, 0.0, 0.0],
[0.0, 0.0, sz, 0.0],
],
inv: [
[1.0 / sx, 0.0, 0.0],
[0.0, 1.0 / sy, 0.0],
[0.0, 0.0, 1.0 / sz],
],
}
}
pub fn rotation(angle: Float, dir: Dir3) -> Self {
let mat = [
[
dir.x() * dir.x() * (1.0 - angle.cos()) + angle.cos(),
dir.x() * dir.y() * (1.0 - angle.cos()) - dir.z() * angle.sin(),
dir.x() * dir.z() * (1.0 - angle.cos()) + dir.y() * angle.sin(),
0.0,
],
[
dir.x() * dir.y() * (1.0 - angle.cos()) + dir.z() * angle.sin(),
dir.y() * dir.y() * (1.0 - angle.cos()) + angle.cos(),
dir.y() * dir.z() * (1.0 - angle.cos()) - dir.x() * angle.sin(),
0.0,
],
[
dir.x() * dir.z() * (1.0 - angle.cos()) - dir.y() * angle.sin(),
dir.y() * dir.z() * (1.0 - angle.cos()) + dir.x() * angle.sin(),
dir.z() * dir.z() * (1.0 - angle.cos()) + angle.cos(),
0.0,
],
];
Self {
mat,
inv: [
[mat[0][0], mat[1][0], mat[2][0]],
[mat[0][1], mat[1][1], mat[2][1]],
[mat[0][2], mat[1][2], mat[2][2]],
],
}
}
pub fn transform_pos(&self, pos: Pos3) -> Pos3 {
Pos3::new(
self.mat[0][0] * pos.x()
+ self.mat[0][1] * pos.y()
+ self.mat[0][2] * pos.z()
+ self.mat[0][3],
self.mat[1][0] * pos.x()
+ self.mat[1][1] * pos.y()
+ self.mat[1][2] * pos.z()
+ self.mat[1][3],
self.mat[2][0] * pos.x()
+ self.mat[2][1] * pos.y()
+ self.mat[2][2] * pos.z()
+ self.mat[2][3],
)
}
pub fn transform_normal(&self, pos: Pos3) -> Pos3 {
Pos3::new(
self.inv[0][0] * pos.x() + self.inv[0][1] * pos.y() + self.inv[0][2] * pos.z(),
self.inv[1][0] * pos.x() + self.inv[1][1] * pos.y() + self.inv[1][2] * pos.z(),
self.inv[2][0] * pos.x() + self.inv[2][1] * pos.y() + self.inv[2][2] * pos.z(),
)
}
}
impl Mul<AffineTransform> for AffineTransform {
type Output = AffineTransform;
fn mul(self, rhs: Self) -> Self::Output {
Self {
mat: [
[
self.mat[0][0] * rhs.mat[0][0]
+ self.mat[0][1] * rhs.mat[1][0]
+ self.mat[0][2] * rhs.mat[2][0]
+ self.mat[0][3],
self.mat[0][0] * rhs.mat[0][1]
+ self.mat[0][1] * rhs.mat[1][1]
+ self.mat[0][2] * rhs.mat[2][1]
+ self.mat[0][3],
self.mat[0][0] * rhs.mat[0][2]
+ self.mat[0][1] * rhs.mat[1][2]
+ self.mat[0][2] * rhs.mat[2][2]
+ self.mat[0][3],
self.mat[0][0] * rhs.mat[0][3]
+ self.mat[0][1] * rhs.mat[1][3]
+ self.mat[0][2] * rhs.mat[2][3]
+ self.mat[0][3],
],
[
self.mat[1][0] * rhs.mat[0][0]
+ self.mat[1][1] * rhs.mat[1][0]
+ self.mat[1][2] * rhs.mat[2][0]
+ self.mat[1][3],
self.mat[1][0] * rhs.mat[0][1]
+ self.mat[1][1] * rhs.mat[1][1]
+ self.mat[1][2] * rhs.mat[2][1]
+ self.mat[1][3],
self.mat[1][0] * rhs.mat[0][2]
+ self.mat[1][1] * rhs.mat[1][2]
+ self.mat[1][2] * rhs.mat[2][2]
+ self.mat[1][3],
self.mat[1][0] * rhs.mat[0][3]
+ self.mat[1][1] * rhs.mat[1][3]
+ self.mat[1][2] * rhs.mat[2][3]
+ self.mat[1][3],
],
[
self.mat[2][0] * rhs.mat[0][0]
+ self.mat[2][1] * rhs.mat[1][0]
+ self.mat[2][2] * rhs.mat[2][0]
+ self.mat[2][3],
self.mat[2][0] * rhs.mat[0][1]
+ self.mat[2][1] * rhs.mat[1][1]
+ self.mat[2][2] * rhs.mat[2][1]
+ self.mat[2][3],
self.mat[2][0] * rhs.mat[0][2]
+ self.mat[2][1] * rhs.mat[1][2]
+ self.mat[2][2] * rhs.mat[2][2]
+ self.mat[2][3],
self.mat[2][0] * rhs.mat[0][3]
+ self.mat[2][1] * rhs.mat[1][3]
+ self.mat[2][2] * rhs.mat[2][3]
+ self.mat[2][3],
],
],
inv: [
[
rhs.inv[0][0] * self.inv[0][0]
+ rhs.inv[0][1] * self.inv[1][0]
+ rhs.inv[0][2] * self.inv[2][0],
rhs.inv[0][0] * self.inv[0][1]
+ rhs.inv[0][1] * self.inv[1][1]
+ rhs.inv[0][2] * self.inv[2][1],
rhs.inv[0][0] * self.inv[0][2]
+ rhs.inv[0][1] * self.inv[1][2]
+ rhs.inv[0][2] * self.inv[2][2],
],
[
rhs.inv[1][0] * self.inv[0][0]
+ rhs.inv[1][1] * self.inv[1][0]
+ rhs.inv[1][2] * self.inv[2][0],
rhs.inv[1][0] * self.inv[0][1]
+ rhs.inv[1][1] * self.inv[1][1]
+ rhs.inv[1][2] * self.inv[2][1],
rhs.inv[1][0] * self.inv[0][2]
+ rhs.inv[1][1] * self.inv[1][2]
+ rhs.inv[1][2] * self.inv[2][2],
],
[
rhs.inv[2][0] * self.inv[0][0]
+ rhs.inv[2][1] * self.inv[1][0]
+ rhs.inv[2][2] * self.inv[2][0],
rhs.inv[2][0] * self.inv[0][1]
+ rhs.inv[2][1] * self.inv[1][1]
+ rhs.inv[2][2] * self.inv[2][1],
rhs.inv[2][0] * self.inv[0][2]
+ rhs.inv[2][1] * self.inv[1][2]
+ rhs.inv[2][2] * self.inv[2][2],
],
],
}
}
}
impl MulAssign<AffineTransform> for AffineTransform {
fn mul_assign(&mut self, rhs: AffineTransform) {
*self = *self * rhs
}
}

View file

@ -1,4 +1,5 @@
pub mod aabb;
pub mod affine_transform;
pub mod camera;
pub mod color;
pub mod light;

View file

@ -0,0 +1,9 @@
use ray_tracing_core::{affine_transform::AffineTransform, math::Dir3, prelude::*};
fn main() {
let mut t = AffineTransform::scale(1.0, 1.0, 2.0);
t *= AffineTransform::rotation(FloatConsts::PI, Dir3::up());
dbg!(t);
}