notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit cb7a3adacf5c84e6d9d0ec74c94c186a3d5e39c5
parent 31aae7f3152bc8c152f23c2dfaee8376cd3a1e11
Author: William Casarin <jb55@jb55.com>
Date:   Wed, 26 Mar 2025 06:45:30 -0700

dave: move quaternion to its own file

Diffstat:
Mcrates/notedeck_dave/src/avatar.rs | 84+------------------------------------------------------------------------------
Mcrates/notedeck_dave/src/lib.rs | 4++++
Acrates/notedeck_dave/src/quaternion.rs | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 88 insertions(+), 83 deletions(-)

diff --git a/crates/notedeck_dave/src/avatar.rs b/crates/notedeck_dave/src/avatar.rs @@ -1,6 +1,6 @@ use std::num::NonZeroU64; -use crate::vec3::Vec3; +use crate::{Vec3, Quaternion}; use eframe::egui_wgpu::{self, wgpu}; use egui::{Rect, Response}; use rand::Rng; @@ -10,88 +10,6 @@ pub struct DaveAvatar { rot_dir: Vec3, } -// A simple quaternion implementation -struct Quaternion { - x: f32, - y: f32, - z: f32, - w: f32, -} - -impl Quaternion { - // Create identity quaternion - fn identity() -> Self { - Self { - x: 0.0, - y: 0.0, - z: 0.0, - w: 1.0, - } - } - - // Create from axis-angle representation - fn from_axis_angle(axis: &Vec3, angle: f32) -> Self { - let half_angle = angle * 0.5; - let s = half_angle.sin(); - Self { - x: axis.x * s, - y: axis.y * s, - z: axis.z * s, - w: half_angle.cos(), - } - } - - // Multiply two quaternions (combines rotations) - fn multiply(&self, other: &Self) -> Self { - Self { - x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y, - y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.x, - z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w, - w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z, - } - } - - // Convert quaternion to 4x4 matrix (for 3D transformation with homogeneous coordinates) - fn to_matrix4(&self) -> [f32; 16] { - // Normalize quaternion - let magnitude = - (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt(); - let x = self.x / magnitude; - let y = self.y / magnitude; - let z = self.z / magnitude; - let w = self.w / magnitude; - - let x2 = x * x; - let y2 = y * y; - let z2 = z * z; - let xy = x * y; - let xz = x * z; - let yz = y * z; - let wx = w * x; - let wy = w * y; - let wz = w * z; - - // Row-major 3x3 rotation matrix components - let m00 = 1.0 - 2.0 * (y2 + z2); - let m01 = 2.0 * (xy - wz); - let m02 = 2.0 * (xz + wy); - - let m10 = 2.0 * (xy + wz); - let m11 = 1.0 - 2.0 * (x2 + z2); - let m12 = 2.0 * (yz - wx); - - let m20 = 2.0 * (xz - wy); - let m21 = 2.0 * (yz + wx); - let m22 = 1.0 - 2.0 * (x2 + y2); - - // Convert 3x3 rotation matrix to 4x4 transformation matrix - // Note: This is column-major for WGPU - [ - m00, m10, m20, 0.0, m01, m11, m21, 0.0, m02, m12, m22, 0.0, 0.0, 0.0, 0.0, 1.0, - ] - } -} - // Matrix utilities for perspective projection fn perspective_matrix(fovy_radians: f32, aspect: f32, near: f32, far: f32) -> [f32; 16] { let f = 1.0 / (fovy_radians / 2.0).tan(); diff --git a/crates/notedeck_dave/src/lib.rs b/crates/notedeck_dave/src/lib.rs @@ -25,8 +25,12 @@ use avatar::DaveAvatar; use egui::{Rect, Vec2}; use egui_wgpu::RenderState; +pub use vec3::Vec3; +pub use quaternion::Quaternion; + mod avatar; mod vec3; +mod quaternion; #[derive(Debug, Clone)] pub enum Message { diff --git a/crates/notedeck_dave/src/quaternion.rs b/crates/notedeck_dave/src/quaternion.rs @@ -0,0 +1,83 @@ +use crate::Vec3; + +// A simple quaternion implementation +pub struct Quaternion { + pub x: f32, + pub y: f32, + pub z: f32, + pub w: f32, +} + +impl Quaternion { + // Create identity quaternion + pub fn identity() -> Self { + Self { + x: 0.0, + y: 0.0, + z: 0.0, + w: 1.0, + } + } + + // Create from axis-angle representation + pub fn from_axis_angle(axis: &Vec3, angle: f32) -> Self { + let half_angle = angle * 0.5; + let s = half_angle.sin(); + Self { + x: axis.x * s, + y: axis.y * s, + z: axis.z * s, + w: half_angle.cos(), + } + } + + // Multiply two quaternions (combines rotations) + pub fn multiply(&self, other: &Self) -> Self { + Self { + x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y, + y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.x, + z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w, + w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z, + } + } + + // Convert quaternion to 4x4 matrix (for 3D transformation with homogeneous coordinates) + pub fn to_matrix4(&self) -> [f32; 16] { + // Normalize quaternion + let magnitude = + (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt(); + let x = self.x / magnitude; + let y = self.y / magnitude; + let z = self.z / magnitude; + let w = self.w / magnitude; + + let x2 = x * x; + let y2 = y * y; + let z2 = z * z; + let xy = x * y; + let xz = x * z; + let yz = y * z; + let wx = w * x; + let wy = w * y; + let wz = w * z; + + // Row-major 3x3 rotation matrix components + let m00 = 1.0 - 2.0 * (y2 + z2); + let m01 = 2.0 * (xy - wz); + let m02 = 2.0 * (xz + wy); + + let m10 = 2.0 * (xy + wz); + let m11 = 1.0 - 2.0 * (x2 + z2); + let m12 = 2.0 * (yz - wx); + + let m20 = 2.0 * (xz - wy); + let m21 = 2.0 * (yz + wx); + let m22 = 1.0 - 2.0 * (x2 + y2); + + // Convert 3x3 rotation matrix to 4x4 transformation matrix + // Note: This is column-major for WGPU + [ + m00, m10, m20, 0.0, m01, m11, m21, 0.0, m02, m12, m22, 0.0, 0.0, 0.0, 0.0, 1.0, + ] + } +}