Skip to main content

oxihuman_viewer/
render_queue.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3
4//! Render command queue.
5
6#![allow(dead_code)]
7
8#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub struct DrawCall {
11    pub mesh_id: u32,
12    pub material_id: u32,
13    pub transform: [f32; 16],
14    pub layer: u32,
15}
16
17#[allow(dead_code)]
18#[derive(Debug, Clone)]
19pub struct RenderQueue {
20    calls: Vec<DrawCall>,
21}
22
23#[allow(dead_code)]
24pub fn new_render_queue() -> RenderQueue {
25    RenderQueue { calls: Vec::new() }
26}
27
28#[allow(dead_code)]
29pub fn rq_push(rq: &mut RenderQueue, call: DrawCall) {
30    rq.calls.push(call);
31}
32
33#[allow(dead_code)]
34pub fn rq_sort_by_layer(rq: &mut RenderQueue) {
35    rq.calls.sort_by_key(|c| c.layer);
36}
37
38#[allow(dead_code)]
39pub fn rq_clear(rq: &mut RenderQueue) {
40    rq.calls.clear();
41}
42
43#[allow(dead_code)]
44pub fn rq_len(rq: &RenderQueue) -> usize {
45    rq.calls.len()
46}
47
48#[allow(dead_code)]
49pub fn rq_is_empty(rq: &RenderQueue) -> bool {
50    rq.calls.is_empty()
51}
52
53#[allow(dead_code)]
54pub fn rq_get(rq: &RenderQueue, index: usize) -> Option<&DrawCall> {
55    rq.calls.get(index)
56}
57
58#[allow(dead_code)]
59pub fn rq_drain(rq: &mut RenderQueue) -> Vec<DrawCall> {
60    std::mem::take(&mut rq.calls)
61}
62
63#[allow(dead_code)]
64pub fn rq_to_json(rq: &RenderQueue) -> String {
65    let entries: Vec<String> = rq
66        .calls
67        .iter()
68        .map(|c| {
69            format!(
70                r#"{{"mesh_id":{},"material_id":{},"layer":{}}}"#,
71                c.mesh_id, c.material_id, c.layer
72            )
73        })
74        .collect();
75    format!("[{}]", entries.join(","))
76}
77
78fn make_identity_transform() -> [f32; 16] {
79    [
80        1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
81    ]
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    fn make_call(mesh_id: u32, layer: u32) -> DrawCall {
89        DrawCall {
90            mesh_id,
91            material_id: 0,
92            transform: make_identity_transform(),
93            layer,
94        }
95    }
96
97    #[test]
98    fn test_new_queue_empty() {
99        let rq = new_render_queue();
100        assert!(rq_is_empty(&rq));
101        assert_eq!(rq_len(&rq), 0);
102    }
103
104    #[test]
105    fn test_push_increases_len() {
106        let mut rq = new_render_queue();
107        rq_push(&mut rq, make_call(1, 0));
108        assert_eq!(rq_len(&rq), 1);
109    }
110
111    #[test]
112    fn test_sort_by_layer() {
113        let mut rq = new_render_queue();
114        rq_push(&mut rq, make_call(1, 5));
115        rq_push(&mut rq, make_call(2, 1));
116        rq_push(&mut rq, make_call(3, 3));
117        rq_sort_by_layer(&mut rq);
118        assert_eq!(rq_get(&rq, 0).expect("should succeed").layer, 1);
119        assert_eq!(rq_get(&rq, 2).expect("should succeed").layer, 5);
120    }
121
122    #[test]
123    fn test_clear() {
124        let mut rq = new_render_queue();
125        rq_push(&mut rq, make_call(1, 0));
126        rq_clear(&mut rq);
127        assert!(rq_is_empty(&rq));
128    }
129
130    #[test]
131    fn test_get_valid_index() {
132        let mut rq = new_render_queue();
133        rq_push(&mut rq, make_call(42, 0));
134        assert_eq!(rq_get(&rq, 0).expect("should succeed").mesh_id, 42);
135    }
136
137    #[test]
138    fn test_get_out_of_bounds() {
139        let rq = new_render_queue();
140        assert!(rq_get(&rq, 0).is_none());
141    }
142
143    #[test]
144    fn test_drain_empties_queue() {
145        let mut rq = new_render_queue();
146        rq_push(&mut rq, make_call(1, 0));
147        rq_push(&mut rq, make_call(2, 1));
148        let drained = rq_drain(&mut rq);
149        assert_eq!(drained.len(), 2);
150        assert!(rq_is_empty(&rq));
151    }
152
153    #[test]
154    fn test_to_json_non_empty() {
155        let mut rq = new_render_queue();
156        rq_push(&mut rq, make_call(7, 2));
157        let j = rq_to_json(&rq);
158        assert!(j.contains("mesh_id"));
159    }
160
161    #[test]
162    fn test_to_json_empty() {
163        let rq = new_render_queue();
164        assert_eq!(rq_to_json(&rq), "[]");
165    }
166}