1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use derive_more::From;

use crate::{
	newtypes::{Global, Local},
	BoneKind, UnitQuat,
};

/// The different kinds of edges.
#[derive(Debug, Eq, PartialEq, Hash, From, Copy, Clone)]
pub enum EdgeKind {
	/// Represents a regular bone in the skeleton.
	Bone(BoneKind),
	/// Represents a tracker that is providing pose information as an input to the
	/// skeleton.
	InputTracker,
	/// Represents a computed/synthetic tracker that will act as an output tracker for
	/// the skeleton.
	OutputTracker,
}

/// `Edge`s represent the connections between the [`Node`]s of the
/// skeleton.
///
/// Edges have a global rotation, represented as a unit quaternion. To
/// get an edge's position, you can get the position of either of its two attached
/// `Node`s.
///
/// Note that by convention, the directionality of edges points towards the top of the
/// skeleton. So the head of the edge would also be the tail of an edge closer to the
/// top of the skeleton. This is simply to give the parent and child of an edge a
/// consistent meaning.
///
/// For more information, see the [`skeleton`](crate::skeleton) module.
///
/// [`Node`]: crate::skeleton::Node
#[non_exhaustive]
pub struct Edge {
	pub kind: EdgeKind,
	/// Input rotation in global space. If it is unconstrained, it is `None`.
	pub input_rot_g: Option<Global<UnitQuat>>,
	/// Local rotation of the edge with respect to the parent edge at calibration time.
	/// Maps from parent frame to child frame.
	pub calib_rot_l: Local<UnitQuat>,
	/// Length of the edge. May be set by the user, or may be computed at calibration.
	pub length: f32,
	/// The output rotation of the edge. Solving the skeleton updates this.
	pub output_rot_g: Global<UnitQuat>,
}
impl Edge {
	pub fn new(kind: impl Into<EdgeKind>, length: f32) -> Self {
		let kind = kind.into();
		let calib_rot_l = match kind {
			EdgeKind::Bone(k) => k.calibration_rotation_local(),
			_ => UnitQuat::identity().into(),
		};
		Self {
			kind,
			input_rot_g: None,
			calib_rot_l,
			length,
			output_rot_g: Default::default(),
		}
	}
}