Skip to main content

openxr/
openxr.rs

1use mittens_engine::{engine, utils};
2
3#[path = "example_util/mod.rs"]
4mod example_util;
5
6fn main() {
7    mittens_engine::example_support::ensure_model_assets();
8    utils::logger::init();
9
10    let world = engine::ecs::World::default();
11    let mut universe = engine::Universe::new(world);
12
13    let background = universe
14        .world
15        .add_component(engine::ecs::component::BackgroundColorComponent::new());
16    let background_c = universe
17        .world
18        .add_component(engine::ecs::component::ColorComponent::rgba(
19            0.3, 0.1, 1.0, 1.0,
20        ));
21    let _ = universe.world.add_child(background, background_c);
22    universe.add(background);
23
24    // --- Camera rig (WASD/QE) ---
25    // Keep this similar to the main demo so we can fly around the cube field.
26    let input = universe
27        .world
28        .add_component(engine::ecs::component::InputComponent::new().with_speed(1.5));
29    let input_mode = universe.world.add_component(
30        engine::ecs::component::InputTransformModeComponent::forward_z().with_roll_axis_y(),
31    );
32    let _ = universe.attach(input, input_mode);
33
34    // Start pulled back so the grid is in view.
35    let rig_transform = universe.world.add_component(
36        engine::ecs::component::TransformComponent::new().with_position(0.0, 0.0, 4.0),
37    );
38    let _ = universe.attach(input, rig_transform);
39
40    let camera3d = universe
41        .world
42        .add_component(engine::ecs::component::Camera3DComponent::new());
43    let _ = universe.attach(rig_transform, camera3d);
44
45    // Topology: I { T { C3D } } — add a small camera-attached controls hint.
46    example_util::spawn_desktop_camera_controls_hint(&mut universe, rig_transform);
47
48    // Simple point light so the toon shader reads well.
49    let light = universe.world.add_component(
50        engine::ecs::component::PointLightComponent::new()
51            .with_distance(50.0)
52            .with_color(1.0, 1.0, 1.0),
53    );
54    let light_transform = universe.world.add_component(
55        engine::ecs::component::TransformComponent::new().with_position(0.0, 5.0, 2.0),
56    );
57    let _ = universe.attach(light_transform, light);
58
59    universe.add(input);
60    universe.add(light_transform);
61
62    // --- 16x16x16 cube grid ---
63    let cube_mesh = universe
64        .render_assets
65        .get_mesh(engine::graphics::BuiltinMeshType::Cube);
66
67    let n: usize = 32;
68    let cube_scale: f32 = 0.10;
69    let gap: f32 = 0.50;
70    let step: f32 = cube_scale + gap;
71
72    // Center positions around 0 by subtracting half the extent (in steps).
73    let half_extent_x = (n as f32 - 1.0) * step * 0.5;
74    let half_extent_y = (n as f32 - 1.0) * step * 0.5;
75    let half_extent_z = (n as f32 - 1.0) * step * 0.5;
76
77    // Move the whole container up/back based on its content size, plus the requested offsets.
78    // - up by +0.5 and by half the content height
79    // - back by -(0.5 + 1.0) and by half the content depth
80    let container_offset_y = half_extent_y + 0.5;
81    let container_offset_z = -(half_extent_z + 1.0 + 0.5);
82
83    let container = universe.world.add_component(
84        engine::ecs::component::TransformComponent::new().with_position(
85            0.0,
86            container_offset_y,
87            container_offset_z,
88        ),
89    );
90
91    for z in 0..n {
92        for y in 0..n {
93            for x in 0..n {
94                let px = x as f32 * step - half_extent_x;
95                let py = y as f32 * step - half_extent_y;
96                let pz = z as f32 * step - half_extent_z;
97
98                let tx = universe.world.add_component(
99                    engine::ecs::component::TransformComponent::new()
100                        .with_position(px, py, pz)
101                        .with_scale(cube_scale, cube_scale, cube_scale),
102                );
103                let renderable =
104                    universe
105                        .world
106                        .add_component(engine::ecs::component::RenderableComponent::new(
107                            engine::graphics::primitives::Renderable::new(
108                                cube_mesh,
109                                engine::graphics::primitives::MaterialHandle::TOON_MESH,
110                            ),
111                        ));
112
113                let denom = (n - 1) as f32;
114                let color = engine::ecs::component::ColorComponent::rgba(
115                    f32::sin(x as f32 / 10.0),
116                    y as f32 / denom,
117                    z as f32 / denom,
118                    1.0,
119                );
120                let color_c = universe.world.add_component(color);
121
122                let _ = universe.attach(container, tx);
123                let _ = universe.attach(tx, renderable);
124                let _ = universe.attach(renderable, color_c);
125            }
126        }
127    }
128
129    universe.add(container);
130    universe.systems.process_commands(
131        &mut universe.world,
132        &mut universe.visuals,
133        &mut universe.render_assets,
134        &mut universe.command_queue,
135    );
136
137    let xr_input = universe
138        .world
139        .add_component(engine::ecs::component::InputXRComponent::on());
140    let xr_gamepad = universe
141        .world
142        .add_component(engine::ecs::component::InputXRGamepadComponent::new().speed(1.5));
143    let xr_head = universe
144        .world
145        .add_component(engine::ecs::component::TransformComponent::new());
146    let camera_xr = universe
147        .world
148        .add_component(engine::ecs::component::CameraXRComponent::on());
149    let _ = universe.attach(xr_input, xr_head);
150    let _ = universe.attach(xr_input, xr_gamepad);
151    let _ = universe.attach(xr_head, camera_xr);
152    universe.add(xr_input);
153
154    // Add an OpenXR component so OpenXRSystem initializes and starts polling events.
155    let xr_root = universe
156        .world
157        .add_component(engine::ecs::component::XrComponent::on());
158    universe.add(xr_root);
159    universe.systems.process_commands(
160        &mut universe.world,
161        &mut universe.visuals,
162        &mut universe.render_assets,
163        &mut universe.command_queue,
164    );
165
166    universe.enable_repl();
167    engine::Windowing::run_app(universe).expect("Windowing failed");
168}