mirror of
https://github.com/aljazceru/notedeck.git
synced 2025-12-18 17:14:21 +01:00
dave: move quaternion to its own file
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use std::num::NonZeroU64;
|
use std::num::NonZeroU64;
|
||||||
|
|
||||||
use crate::vec3::Vec3;
|
use crate::{Vec3, Quaternion};
|
||||||
use eframe::egui_wgpu::{self, wgpu};
|
use eframe::egui_wgpu::{self, wgpu};
|
||||||
use egui::{Rect, Response};
|
use egui::{Rect, Response};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
@@ -10,88 +10,6 @@ pub struct DaveAvatar {
|
|||||||
rot_dir: Vec3,
|
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
|
// Matrix utilities for perspective projection
|
||||||
fn perspective_matrix(fovy_radians: f32, aspect: f32, near: f32, far: f32) -> [f32; 16] {
|
fn perspective_matrix(fovy_radians: f32, aspect: f32, near: f32, far: f32) -> [f32; 16] {
|
||||||
let f = 1.0 / (fovy_radians / 2.0).tan();
|
let f = 1.0 / (fovy_radians / 2.0).tan();
|
||||||
|
|||||||
@@ -25,8 +25,12 @@ use avatar::DaveAvatar;
|
|||||||
use egui::{Rect, Vec2};
|
use egui::{Rect, Vec2};
|
||||||
use egui_wgpu::RenderState;
|
use egui_wgpu::RenderState;
|
||||||
|
|
||||||
|
pub use vec3::Vec3;
|
||||||
|
pub use quaternion::Quaternion;
|
||||||
|
|
||||||
mod avatar;
|
mod avatar;
|
||||||
mod vec3;
|
mod vec3;
|
||||||
|
mod quaternion;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
|
|||||||
83
crates/notedeck_dave/src/quaternion.rs
Normal file
83
crates/notedeck_dave/src/quaternion.rs
Normal file
@@ -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,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user