Skip to content

Commit 56b2c9d

Browse files
authored
Try #68:
2 parents a2b57de + cba1d9d commit 56b2c9d

File tree

3 files changed

+290
-1
lines changed

3 files changed

+290
-1
lines changed

godot-core/src/builtin/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ mod math;
4242
mod node_path;
4343
mod others;
4444
mod packed_array;
45+
mod quaternion;
4546
mod string;
4647
mod string_name;
4748
mod variant;
@@ -63,6 +64,7 @@ pub use math::*;
6364
pub use node_path::*;
6465
pub use others::*;
6566
pub use packed_array::*;
67+
pub use quaternion::*;
6668
pub use string::*;
6769
pub use string_name::*;
6870
pub use variant::*;

godot-core/src/builtin/others.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use sys::{ffi_methods, GodotFfi};
1616
impl_builtin_stub!(Rect2, OpaqueRect2);
1717
impl_builtin_stub!(Rect2i, OpaqueRect2i);
1818
impl_builtin_stub!(Plane, OpaquePlane);
19-
impl_builtin_stub!(Quaternion, OpaqueQuaternion);
2019
impl_builtin_stub!(Aabb, OpaqueAabb);
2120
impl_builtin_stub!(Basis, OpaqueBasis);
2221
impl_builtin_stub!(Transform2D, OpaqueTransform2D);

godot-core/src/builtin/quaternion.rs

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
*/
6+
use std::ops::*;
7+
8+
use godot_ffi as sys;
9+
use sys::{ffi_methods, GodotFfi};
10+
11+
use crate::builtin::{math::*, vector3::*};
12+
13+
#[derive(Default, Copy, Clone, Debug, PartialEq)]
14+
#[repr(C)]
15+
pub struct Quaternion {
16+
x: f32,
17+
y: f32,
18+
z: f32,
19+
w: f32,
20+
}
21+
22+
impl Quaternion {
23+
pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
24+
Self { x, y, z, w }
25+
}
26+
27+
pub fn from_angle_axis(axis: Vector3, angle: f32) -> Self {
28+
let d = axis.length();
29+
if d == 0.0 {
30+
Self::new(0.0, 0.0, 0.0, 0.0)
31+
} else {
32+
let sin_angle = (angle * 0.5).sin();
33+
let cos_angle = (angle * 0.5).cos();
34+
let s = sin_angle / d;
35+
let x = axis.x * s;
36+
let y = axis.y * s;
37+
let z = axis.z * s;
38+
let w = cos_angle;
39+
Self::new(x, y, z, w)
40+
}
41+
}
42+
43+
pub fn angle_to(self, to: Self) -> f32 {
44+
self.to_glam().angle_between(to.to_glam())
45+
}
46+
47+
pub fn dot(self, with: Self) -> f32 {
48+
self.to_glam().dot(with.to_glam())
49+
}
50+
51+
pub fn to_exp(self) -> Self {
52+
let mut v = Vector3::new(self.x, self.y, self.z);
53+
let theta = v.length();
54+
v = v.normalized();
55+
if theta < CMP_EPSILON || !v.is_normalized() {
56+
return Self::new(0.0, 0.0, 0.0, 1.0);
57+
}
58+
Self::from_angle_axis(v, theta)
59+
}
60+
61+
pub fn from_euler(self, euler: Vector3) -> Self {
62+
let half_a1 = euler.y * 0.5;
63+
let half_a2 = euler.x * 0.5;
64+
let half_a3 = euler.z * 0.5;
65+
let cos_a1 = half_a1.cos();
66+
let sin_a1 = half_a1.sin();
67+
let cos_a2 = half_a2.cos();
68+
let sin_a2 = half_a2.sin();
69+
let cos_a3 = half_a3.cos();
70+
let sin_a3 = half_a3.sin();
71+
Self::new(
72+
sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3,
73+
sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3,
74+
-sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3,
75+
sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3,
76+
)
77+
}
78+
79+
pub fn get_angle(self) -> f32 {
80+
2.0 * self.w.acos()
81+
}
82+
83+
pub fn get_axis(self) -> Vector3 {
84+
if self.w.abs() > 1.0 - CMP_EPSILON {
85+
return Vector3::new(self.x, self.y, self.z);
86+
}
87+
let r = 1.0 / (1.0 - self.w * self.w).sqrt();
88+
Vector3::new(self.x * r, self.y * r, self.z * r)
89+
}
90+
91+
pub fn inverse(self) -> Self {
92+
Quaternion::new(-self.x, -self.y, -self.z, self.w)
93+
}
94+
95+
pub fn is_equal_approx(self, to: Self) -> bool {
96+
is_equal_approx(self.x, to.x)
97+
&& is_equal_approx(self.y, to.y)
98+
&& is_equal_approx(self.z, to.z)
99+
&& is_equal_approx(self.w, to.w)
100+
}
101+
102+
pub fn is_finite(self) -> bool {
103+
self.x.is_finite() && self.y.is_finite() && self.z.is_finite() && self.w.is_finite()
104+
}
105+
106+
pub fn is_normalized(self) -> bool {
107+
is_equal_approx(self.length_squared(), 1.0) /*,UNIT_EPSILON)*/
108+
}
109+
110+
pub fn length(self) -> f32 {
111+
self.length_squared().sqrt()
112+
}
113+
114+
pub fn length_squared(self) -> f32 {
115+
self.dot(self)
116+
}
117+
118+
pub fn log(self) -> Self {
119+
let v = self.get_axis() * self.get_angle();
120+
Self::new(v.x, v.y, v.z, 0.0)
121+
}
122+
123+
pub fn normalized(self) -> Self {
124+
self / self.length()
125+
}
126+
127+
pub fn slerp(self, to: Self, weight: f32) -> Self {
128+
let mut cosom = self.dot(to);
129+
let to1: Self;
130+
let omega: f32;
131+
let sinom: f32;
132+
let scale0: f32;
133+
let scale1: f32;
134+
if cosom < 0.0 {
135+
cosom = -cosom;
136+
to1 = -to;
137+
} else {
138+
to1 = to;
139+
}
140+
141+
if 1.0 - cosom > CMP_EPSILON {
142+
omega = cosom.acos();
143+
sinom = omega.sin();
144+
scale0 = ((1.0 - weight) * omega).sin() / sinom;
145+
scale1 = (weight * omega).sin() / sinom;
146+
} else {
147+
scale0 = 1.0 - weight;
148+
scale1 = weight;
149+
}
150+
Self::new(
151+
scale0 * self.x + scale1 * to1.x,
152+
scale0 * self.y + scale1 * to1.y,
153+
scale0 * self.z + scale1 * to1.z,
154+
scale0 * self.w + scale1 * to1.w,
155+
)
156+
}
157+
158+
pub fn slerpni(self, to: Self, weight: f32) -> Self {
159+
let dot = self.dot(to);
160+
if dot.abs() > 0.9999 {
161+
return self;
162+
}
163+
let theta = dot.acos();
164+
let sin_t = 1.0 / theta.sin();
165+
let new_factor = (weight * theta).sin() * sin_t;
166+
let inv_factor = ((1.0 - weight) * theta).sin() * sin_t;
167+
Self::new(
168+
inv_factor * self.x + new_factor * to.x,
169+
inv_factor * self.y + new_factor * to.y,
170+
inv_factor * self.z + new_factor * to.z,
171+
inv_factor * self.w + new_factor * to.w,
172+
)
173+
}
174+
175+
pub fn from_glam(quat: glam::Quat) -> Self {
176+
Self::new(quat.x, quat.y, quat.z, quat.w)
177+
}
178+
179+
pub fn to_glam(self) -> glam::Quat {
180+
glam::Quat::from_xyzw(self.x, self.y, self.z, self.w)
181+
}
182+
}
183+
184+
impl Add for Quaternion {
185+
type Output = Self;
186+
187+
fn add(self, other: Self) -> Self {
188+
Self::new(
189+
self.x + other.x,
190+
self.y + other.y,
191+
self.z + other.z,
192+
self.w + other.w,
193+
)
194+
}
195+
}
196+
197+
impl AddAssign for Quaternion {
198+
fn add_assign(&mut self, other: Self) {
199+
*self = *self + other
200+
}
201+
}
202+
203+
impl Sub for Quaternion {
204+
type Output = Self;
205+
206+
fn sub(self, other: Self) -> Self {
207+
Self::new(
208+
self.x - other.x,
209+
self.y - other.y,
210+
self.z - other.z,
211+
self.w - other.w,
212+
)
213+
}
214+
}
215+
216+
impl SubAssign for Quaternion {
217+
fn sub_assign(&mut self, other: Self) {
218+
*self = *self - other
219+
}
220+
}
221+
222+
impl Mul<Quaternion> for Quaternion {
223+
type Output = Self;
224+
225+
fn mul(self, other: Quaternion) -> Self {
226+
let x = self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y;
227+
let y = self.w * other.y + self.y * other.w + self.z * other.x - self.x * other.z;
228+
let z = self.w * other.z + self.z * other.w + self.x * other.y - self.y * other.x;
229+
let w = self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z;
230+
Self::new(x, y, z, w)
231+
}
232+
}
233+
234+
impl MulAssign<Quaternion> for Quaternion {
235+
fn mul_assign(&mut self, other: Quaternion) {
236+
*self = *self * other
237+
}
238+
}
239+
240+
impl Mul<f32> for Quaternion {
241+
type Output = Self;
242+
243+
fn mul(self, other: f32) -> Self {
244+
Quaternion::new(
245+
self.x * other,
246+
self.y * other,
247+
self.z * other,
248+
self.w * other,
249+
)
250+
}
251+
}
252+
253+
impl MulAssign<f32> for Quaternion {
254+
fn mul_assign(&mut self, other: f32) {
255+
*self = *self * other
256+
}
257+
}
258+
259+
impl Div<f32> for Quaternion {
260+
type Output = Self;
261+
262+
fn div(self, other: f32) -> Self {
263+
Self::new(
264+
self.x / other,
265+
self.y / other,
266+
self.z / other,
267+
self.w / other,
268+
)
269+
}
270+
}
271+
272+
impl DivAssign<f32> for Quaternion {
273+
fn div_assign(&mut self, other: f32) {
274+
*self = *self / other
275+
}
276+
}
277+
278+
impl Neg for Quaternion {
279+
type Output = Self;
280+
281+
fn neg(self) -> Self {
282+
Self::new(-self.x, -self.y, -self.z, -self.w)
283+
}
284+
}
285+
286+
impl GodotFfi for Quaternion {
287+
ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
288+
}

0 commit comments

Comments
 (0)