Skip to main content

oxihuman_morph/
data_driven_rig.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Data-driven rigging system stub.
6
7/// A sample of captured rig state used for data-driven training.
8#[derive(Debug, Clone)]
9pub struct RigSample {
10    pub pose_params: Vec<f32>,
11    pub shape_output: Vec<f32>,
12}
13
14/// Data-driven rig that maps pose parameters to shape deltas.
15#[derive(Debug, Clone)]
16pub struct DataDrivenRig {
17    pub samples: Vec<RigSample>,
18    pub param_dim: usize,
19    pub shape_dim: usize,
20    pub enabled: bool,
21}
22
23impl DataDrivenRig {
24    pub fn new(param_dim: usize, shape_dim: usize) -> Self {
25        DataDrivenRig {
26            samples: Vec::new(),
27            param_dim,
28            shape_dim,
29            enabled: true,
30        }
31    }
32}
33
34/// Create a new data-driven rig.
35pub fn new_data_driven_rig(param_dim: usize, shape_dim: usize) -> DataDrivenRig {
36    DataDrivenRig::new(param_dim, shape_dim)
37}
38
39/// Add a training sample to the rig.
40pub fn ddr_add_sample(rig: &mut DataDrivenRig, sample: RigSample) {
41    rig.samples.push(sample);
42}
43
44/// Evaluate the rig for a pose (stub: zeroed output).
45pub fn ddr_evaluate(rig: &DataDrivenRig, _pose: &[f32]) -> Vec<f32> {
46    /* Stub: returns zeroed shape output */
47    vec![0.0; rig.shape_dim]
48}
49
50/// Return sample count.
51pub fn ddr_sample_count(rig: &DataDrivenRig) -> usize {
52    rig.samples.len()
53}
54
55/// Enable or disable the rig.
56pub fn ddr_set_enabled(rig: &mut DataDrivenRig, enabled: bool) {
57    rig.enabled = enabled;
58}
59
60/// Clear all training samples.
61pub fn ddr_clear_samples(rig: &mut DataDrivenRig) {
62    rig.samples.clear();
63}
64
65/// Serialize to JSON-like string.
66pub fn ddr_to_json(rig: &DataDrivenRig) -> String {
67    format!(
68        r#"{{"param_dim":{},"shape_dim":{},"samples":{},"enabled":{}}}"#,
69        rig.param_dim,
70        rig.shape_dim,
71        rig.samples.len(),
72        rig.enabled
73    )
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn test_new_dims() {
82        let rig = new_data_driven_rig(10, 20);
83        assert_eq!(rig.param_dim, 10 /* param_dim must match */,);
84        assert_eq!(rig.shape_dim, 20 /* shape_dim must match */,);
85    }
86
87    #[test]
88    fn test_no_samples_initially() {
89        let rig = new_data_driven_rig(5, 5);
90        assert_eq!(
91            ddr_sample_count(&rig),
92            0, /* must have no samples initially */
93        );
94    }
95
96    #[test]
97    fn test_add_sample() {
98        let mut rig = new_data_driven_rig(3, 3);
99        ddr_add_sample(
100            &mut rig,
101            RigSample {
102                pose_params: vec![0.1, 0.2, 0.3],
103                shape_output: vec![0.0, 0.0, 0.0],
104            },
105        );
106        assert_eq!(ddr_sample_count(&rig), 1 /* one sample after add */,);
107    }
108
109    #[test]
110    fn test_evaluate_length() {
111        let rig = new_data_driven_rig(4, 6);
112        let out = ddr_evaluate(&rig, &[0.0; 4]);
113        assert_eq!(out.len(), 6 /* output length must match shape_dim */,);
114    }
115
116    #[test]
117    fn test_evaluate_zeroed() {
118        let rig = new_data_driven_rig(2, 4);
119        let out = ddr_evaluate(&rig, &[1.0, 0.5]);
120        assert!(out.iter().all(|&v| v.abs() < 1e-6), /* stub must return zeros */);
121    }
122
123    #[test]
124    fn test_set_enabled() {
125        let mut rig = new_data_driven_rig(2, 2);
126        ddr_set_enabled(&mut rig, false);
127        assert!(!rig.enabled /* enabled must be false */,);
128    }
129
130    #[test]
131    fn test_clear_samples() {
132        let mut rig = new_data_driven_rig(2, 2);
133        ddr_add_sample(
134            &mut rig,
135            RigSample {
136                pose_params: vec![0.0; 2],
137                shape_output: vec![0.0; 2],
138            },
139        );
140        ddr_clear_samples(&mut rig);
141        assert_eq!(ddr_sample_count(&rig), 0 /* samples must be cleared */,);
142    }
143
144    #[test]
145    fn test_to_json() {
146        let rig = new_data_driven_rig(4, 8);
147        let j = ddr_to_json(&rig);
148        assert!(j.contains("\"param_dim\""), /* json must contain param_dim */);
149    }
150
151    #[test]
152    fn test_enabled_by_default() {
153        let rig = new_data_driven_rig(1, 1);
154        assert!(rig.enabled /* enabled by default */,);
155    }
156
157    #[test]
158    fn test_many_samples() {
159        let mut rig = new_data_driven_rig(2, 2);
160        for _ in 0..10 {
161            ddr_add_sample(
162                &mut rig,
163                RigSample {
164                    pose_params: vec![0.0; 2],
165                    shape_output: vec![0.0; 2],
166                },
167            );
168        }
169        assert_eq!(
170            ddr_sample_count(&rig),
171            10, /* ten samples must be stored */
172        );
173    }
174}