smpl_gloss_integration/
components.rs

1use nalgebra as na;
2use smpl_utils::numerical::{map, smootherstep};
3use std::ops::AddAssign;
4#[derive(Clone)]
5pub struct GlossInterop {
6    pub with_uv: bool,
7}
8impl Default for GlossInterop {
9    fn default() -> Self {
10        Self { with_uv: true }
11    }
12}
13/// Indication that an entity needs to be followed
14#[derive(Clone)]
15pub struct Follow;
16/// Enum for follower type
17#[derive(Clone)]
18pub enum FollowerType {
19    Cam,
20    Lights,
21    CamAndLights,
22}
23/// Parameters for the follower
24#[derive(Clone)]
25pub struct FollowParams {
26    /// Strength of the follower, this value being high would mean the follower
27    /// would tightly follow the entity
28    pub max_strength: f32,
29    pub dist_start: f32,
30    pub dist_end: f32,
31    /// Follower type chooses what would follow the entity - camera, lights, or
32    /// both
33    pub follower_type: FollowerType,
34    /// Whether to follow the mean of all entities with ``GlossInterop`` in the scene
35    pub follow_all: bool,
36}
37impl Default for FollowParams {
38    fn default() -> Self {
39        Self {
40            max_strength: 3.0,
41            dist_start: 0.1,
42            dist_end: 0.5,
43            follower_type: FollowerType::CamAndLights,
44            follow_all: true,
45        }
46    }
47}
48/// Resource to indicate that we should follow the animation of a certain entity
49#[derive(Clone)]
50pub struct Follower {
51    point: na::Point3<f32>,
52    is_first_time: bool,
53    pub params: FollowParams,
54}
55impl Follower {
56    pub fn new(params: FollowParams) -> Self {
57        Self {
58            point: na::Point3::default(),
59            is_first_time: true,
60            params,
61        }
62    }
63    /// Progress the follower by dt
64    pub fn update(&mut self, point_to_follow: &na::Point3<f32>, cur_follow: &na::Point3<f32>, dt_sec: f32) {
65        if self.is_first_time {
66            self.is_first_time = false;
67            self.point = *point_to_follow;
68        } else {
69            let diff = point_to_follow - cur_follow;
70            let dist = diff.norm();
71            let max_strength = self.params.max_strength * dt_sec;
72            let mut strength_normalized = map(dist, self.params.dist_start, self.params.dist_end, 0.0, 1.0);
73            strength_normalized = smootherstep(0.0, 1.0, strength_normalized);
74            strength_normalized = strength_normalized.clamp(0.2, 1.0);
75            let strength = (strength_normalized * max_strength).clamp(0.0, 1.0);
76            let prev_followed_point = self.point;
77            let cam_user_movement = cur_follow - prev_followed_point;
78            self.point.add_assign(diff * strength);
79            self.point.add_assign(cam_user_movement);
80        }
81    }
82    /// Get the point being followed
83    pub fn get_point_follow(&self, _name: &str) -> na::Point3<f32> {
84        self.point
85    }
86    /// Reset the follower
87    pub fn reset(&mut self) {
88        self.is_first_time = true;
89    }
90}