Skip to main content

oxihuman_viewer/
reflection_ray_view.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Ray-traced reflection debug view stub.
6
7/// Reflection ray visualization config.
8#[derive(Debug, Clone)]
9pub struct ReflectionRayViewConfig {
10    pub max_bounces: usize,
11    pub intensity: f32,
12    pub enabled: bool,
13    pub show_miss: bool,
14}
15
16impl Default for ReflectionRayViewConfig {
17    fn default() -> Self {
18        ReflectionRayViewConfig {
19            max_bounces: 2,
20            intensity: 1.0,
21            enabled: true,
22            show_miss: true,
23        }
24    }
25}
26
27/// Create a new reflection ray view config.
28pub fn new_reflection_ray_view() -> ReflectionRayViewConfig {
29    ReflectionRayViewConfig::default()
30}
31
32/// Set max bounces.
33pub fn rrv_set_max_bounces(cfg: &mut ReflectionRayViewConfig, bounces: usize) {
34    cfg.max_bounces = bounces;
35}
36
37/// Set intensity.
38pub fn rrv_set_intensity(cfg: &mut ReflectionRayViewConfig, intensity: f32) {
39    cfg.intensity = intensity.max(0.0);
40}
41
42/// Enable or disable.
43pub fn rrv_set_enabled(cfg: &mut ReflectionRayViewConfig, enabled: bool) {
44    cfg.enabled = enabled;
45}
46
47/// Toggle miss ray display.
48pub fn rrv_toggle_miss(cfg: &mut ReflectionRayViewConfig) {
49    cfg.show_miss = !cfg.show_miss;
50}
51
52/// Compute reflected direction (stub: mirrors around normal).
53pub fn rrv_reflect(incident: [f32; 3], normal: [f32; 3]) -> [f32; 3] {
54    let dot = incident[0] * normal[0] + incident[1] * normal[1] + incident[2] * normal[2];
55    [
56        incident[0] - 2.0 * dot * normal[0],
57        incident[1] - 2.0 * dot * normal[1],
58        incident[2] - 2.0 * dot * normal[2],
59    ]
60}
61
62/// Return a JSON-like string.
63pub fn rrv_to_json(cfg: &ReflectionRayViewConfig) -> String {
64    format!(
65        r#"{{"max_bounces":{},"intensity":{:.4},"enabled":{}}}"#,
66        cfg.max_bounces, cfg.intensity, cfg.enabled
67    )
68}
69
70/// Return miss color.
71pub fn rrv_miss_color() -> [f32; 3] {
72    [0.1, 0.1, 0.2]
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn test_default_max_bounces() {
81        let c = new_reflection_ray_view();
82        assert_eq!(c.max_bounces, 2 /* default max bounces is 2 */,);
83    }
84
85    #[test]
86    fn test_set_max_bounces() {
87        let mut c = new_reflection_ray_view();
88        rrv_set_max_bounces(&mut c, 5);
89        assert_eq!(c.max_bounces, 5 /* max bounces must match */,);
90    }
91
92    #[test]
93    fn test_set_intensity() {
94        let mut c = new_reflection_ray_view();
95        rrv_set_intensity(&mut c, 1.5);
96        assert!((c.intensity - 1.5).abs() < 1e-5, /* intensity must match */);
97    }
98
99    #[test]
100    fn test_set_intensity_negative_clamps() {
101        let mut c = new_reflection_ray_view();
102        rrv_set_intensity(&mut c, -1.0);
103        assert!((c.intensity).abs() < 1e-6, /* negative intensity clamped to 0 */);
104    }
105
106    #[test]
107    fn test_set_enabled_false() {
108        let mut c = new_reflection_ray_view();
109        rrv_set_enabled(&mut c, false);
110        assert!(!c.enabled /* should be disabled */,);
111    }
112
113    #[test]
114    fn test_toggle_miss() {
115        let mut c = new_reflection_ray_view();
116        let before = c.show_miss;
117        rrv_toggle_miss(&mut c);
118        assert_ne!(
119            c.show_miss,
120            before, /* miss toggle should change state */
121        );
122    }
123
124    #[test]
125    fn test_reflect_normal_incidence() {
126        /* Incident along -Z, normal along +Z -> reflected along +Z */
127        let r = rrv_reflect([0.0, 0.0, -1.0], [0.0, 0.0, 1.0]);
128        assert!((r[2] - 1.0).abs() < 1e-5, /* reflected z component should be 1 */);
129    }
130
131    #[test]
132    fn test_to_json_contains_bounces() {
133        let c = new_reflection_ray_view();
134        let j = rrv_to_json(&c);
135        assert!(j.contains("max_bounces"), /* JSON must contain max_bounces */);
136    }
137
138    #[test]
139    fn test_miss_color_returns_three() {
140        let m = rrv_miss_color();
141        assert_eq!(m.len(), 3 /* miss color must be RGB */,);
142    }
143
144    #[test]
145    fn test_default_show_miss_true() {
146        let c = new_reflection_ray_view();
147        assert!(c.show_miss /* show_miss enabled by default */,);
148    }
149}