rotation improve perf and numerical instabilities

This commit is contained in:
Matthieu Baumann
2025-09-23 17:20:16 +02:00
parent f0fc39d2c8
commit 032bb57517
7 changed files with 4802 additions and 4773 deletions

View File

@@ -11,7 +11,7 @@
let aladin;
A.init.then(() => {
aladin = A.aladin('#aladin-lite-div', {survey: "https://cds.unistra.fr/~boch/bug-al-om-change-relative-url/CDS_P_GALEXGR6_7_FUV", target: "05 40 59.12 -02 27 04.1", fov: 2, log: false});
aladin = A.aladin('#aladin-lite-div', {survey: "./data/hips/CDS_P_DSS2_color", target: "05 40 59.12 -02 27 04.1", fov: 2, log: false});
});
</script>

View File

@@ -495,7 +495,7 @@ impl App {
self.inertia.is_some()
}
pub(crate) fn update(&mut self, dt: DeltaTime) -> Result<bool, JsValue> {
pub(crate) fn update(&mut self, dt: f64) -> Result<bool, JsValue> {
// a timer stopping the frame if it takes too long
// useful for garanting a framerate
let rendering_timer = Time::now();
@@ -1731,7 +1731,6 @@ impl App {
}
} else {
/* 1. Rotate by computing the angle between the last and current position */
let d = math::vector::angle3(&prev_pos, &cur_pos);
let axis = prev_pos.cross(cur_pos).normalize();

View File

@@ -12,16 +12,16 @@ pub struct Inertia {
// Vector of rotation
axis: Vector3<f64>,
// The time when the inertia begins
time_start: Time,
time_prev: Time,
north_up: bool,
}
impl Inertia {
pub fn new(ampl: f64, axis: Vector3<f64>, north_up: bool) -> Self {
Inertia {
time_start: Time::now(),
time_prev: Time::now(),
ampl,
speed: ampl,
speed: (ampl * 0.5).min(0.1),
axis,
north_up,
}
@@ -52,18 +52,22 @@ impl Inertia {
}
}*/
pub fn apply(&mut self, camera: &mut CameraViewPort, proj: &ProjectionType, _dt: DeltaTime) {
let t = ((Time::now() - self.time_start).as_millis() / 1000.0) as f64;
pub fn apply(&mut self, camera: &mut CameraViewPort, proj: &ProjectionType, dt: f64) {
self.time_prev = Time::now();
// Initial angular velocity
let v0 = self.ampl * 0.5;
//let v0 = self.ampl * 0.5;
// Friction coefficient (tweak this)
let damping = 2.5;
let damping = 5e-3;
self.speed *= (-damping * dt).exp();
let delta_angle = self.speed * dt;
// Exponential decay of angular velocity
self.speed = (v0 * (-damping * t).exp()).min(3.0);
// self.speed = (v0 * (-damping * t).exp()).min(3.0);
camera.apply_axis_rotation(&self.axis, self.speed.to_angle(), proj);
//camera.apply_axis_rotation(&self.axis, self.speed.to_angle(), proj);
camera.apply_axis_rotation(&self.axis, delta_angle.to_angle(), proj);
if self.north_up {
camera.set_position_angle(0.0.to_angle(), proj);

View File

@@ -194,15 +194,15 @@ impl WebClient {
///
/// # Return
/// Whether the view is moving or not
pub fn update(&mut self, dt: f32) -> Result<bool, JsValue> {
pub fn update(&mut self, dt: f64) -> Result<bool, JsValue> {
// dt refers to the time taking (in ms) rendering the previous frame
self.dt = DeltaTime::from_millis(dt);
self.dt = DeltaTime::from_millis(dt as f32);
// Update the application and get back the
// world coordinates of the center of projection in (ra, dec)
self.app.update(
// Time of the previous frame rendering
self.dt,
dt,
)
}

View File

@@ -1,5 +1,6 @@
use crate::math;
use crate::math::angle::ToAngle;
use cgmath::One;
use cgmath::Vector3;
use cgmath::{BaseFloat, InnerSpace};
use cgmath::{Euler, Quaternion};
@@ -111,27 +112,50 @@ where
// Define a rotation from an axis and a angle
pub fn from_axis_angle(axis: &Vector3<S>, angle: Angle<S>) -> Rotation<S> {
let angle: Rad<S> = angle.into();
let mat = Matrix3::from_axis_angle(axis.normalize(), angle);
(&mat).into()
let half = angle.0 * S::from(0.5).unwrap();
let (s, c) = half.sin_cos();
let axis = axis.normalize();
let q = Quaternion::new(c, axis.x * s, axis.y * s, axis.z * s);
Rotation(q)
}
// Define a rotation from a normalized vector
pub fn from_sky_position(pos: &Vector3<S>) -> Rotation<S> {
let (lon, lat) = math::lonlat::xyz_to_radec(pos);
let qy = Self::from_axis_angle(&Vector3::unit_y(), lon);
let qx = Self::from_axis_angle(&Vector3::unit_x(), -lat);
(qy * qx)
}
/*pub fn from_sky_position(pos: &Vector3<S>) -> Rotation<S> {
let (lon, lat) = math::lonlat::xyz_to_radec(pos);
let rot_y = Matrix3::from_angle_y(lon);
let rot_x = Matrix3::from_angle_x(-lat);
let mat = rot_y * rot_x;
(&(mat)).into()
}
}*/
// Apply a rotation to a position
pub fn rotate(&self, pos_world_space: &Vector3<S>) -> Vector3<S> {
let w2m: &Matrix3<S> = &self.into();
pub fn rotate(&self, v: &Vector3<S>) -> Vector3<S> {
/*let w2m: &Matrix3<S> = &self.into();
w2m * v*/
let qvec = self.0.v; // vector part of the quaternion
w2m * pos_world_space
// uv = qvec × v
let uv = qvec.cross(*v);
// uuv = qvec × uv
let uuv = qvec.cross(uv);
// v' = v + 2 * (uv * q.w + uuv)
*v + ((uv * self.0.s) + uuv) * (S::from(2.0).unwrap())
}
pub fn inv_rotate(&self, pos_model_space: &Vector3<S>) -> Vector3<S> {
let w2m: &Matrix3<S> = &self.into();
let m2w = w2m.transpose();

File diff suppressed because it is too large Load Diff

View File

@@ -1392,8 +1392,10 @@ export let View = (function () {
// Elapsed time since last loop
const now = performance.now();
const elapsedTime = now - timestamp;
this.dt = elapsedTime;
const elapsedTime = now - this.prevTime;
this.prevTime = now;
//this.dt = elapsedTime;
this.moving = this.wasm.update(elapsedTime);