pub struct OrbitCamera {
pub target: Vec3,
pub distance: f32,
pub azimuth: f32,
pub elevation: f32,
pub fov: f32,
pub mode: OrbitMode,
pub sensitivity: f32,
pub zoom_sensitivity: f32,
pub min_distance: f32,
pub max_distance: f32,
}Expand description
Fields§
§target: Vec3Point the camera orbits around.
distance: f32Distance from target.
azimuth: f32Horizontal angle in radians (yaw).
elevation: f32Vertical angle in radians (pitch), clamped to avoid gimbal lock.
fov: f32Field of view in radians.
mode: OrbitModeControl mode.
sensitivity: f32Mouse sensitivity for interactive mode.
zoom_sensitivity: f32Scroll zoom sensitivity.
min_distance: f32Minimum distance from target.
max_distance: f32Maximum distance from target.
Implementations§
Source§impl OrbitCamera
impl OrbitCamera
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
examples/sphere.rs (line 9)
5fn main() {
6 run_with_config(AppConfig::new().title("Raymarched Sphere"), |ctx| {
7 ctx.hot_effect_world("examples/shaders/sphere.wgsl");
8
9 let mut orbit = OrbitCamera::new()
10 .target(Vec3::ZERO)
11 .distance(3.0)
12 .elevation(0.3)
13 .fov(90.0)
14 .mode(OrbitMode::AutoRotate { speed: 0.5 });
15
16 move |frame| {
17 orbit.update(frame.input, frame.dt);
18 frame.set_camera(orbit.camera());
19 }
20 });
21}More examples
examples/stl_loader.rs (line 35)
10fn main() {
11 run_with_config(
12 AppConfig::new().title("STL Loader Demo").size(1280, 720),
13 |ctx| {
14 ctx.default_font(18.0);
15 ctx.background_color(Color::rgb(0.08, 0.08, 0.12));
16 ctx.enable_mesh_rendering();
17
18 // Load the chess piece STL with the fluent API
19 // - centered() moves the bounding box center to origin
20 // - normalized() scales to fit in a unit cube
21 // - scaled() then scales to desired size
22 let chess_piece = ctx
23 .load("examples/assets/models/chess.stl")
24 .centered()
25 .upright()
26 .normalized()
27 .scaled(2.0)
28 .unwrap();
29
30 // Create some primitive meshes for the scene
31 let plane = ctx.mesh_plane(10.0);
32 let cube = ctx.mesh_cube();
33
34 // Orbit camera for viewing the model
35 let mut orbit = OrbitCamera::new()
36 .target(Vec3::new(0.0, 1.0, 0.0))
37 .distance(5.0)
38 .elevation(0.4)
39 .fov(60.0)
40 .mode(OrbitMode::AutoRotate { speed: 0.3 });
41
42 let mut time = 0.0f32;
43
44 move |frame| {
45 time += frame.dt;
46
47 // Update camera
48 orbit.update(frame.input, frame.dt);
49 frame.set_camera(orbit.camera());
50
51 // Draw the floor
52 frame
53 .mesh(plane)
54 .transform(Transform::new())
55 .color(Color::rgb(0.15, 0.15, 0.18))
56 .draw();
57
58 // Draw the chess piece on a pedestal
59 // Pedestal base
60 frame
61 .mesh(cube)
62 .transform(
63 Transform::new()
64 .position(Vec3::new(0.0, 0.15, 0.0))
65 .scale(Vec3::new(1.5, 0.3, 1.5)),
66 )
67 .color(Color::rgb(0.2, 0.2, 0.25))
68 .draw();
69
70 // The chess piece - positioned on top of pedestal
71 // Slowly bobbing up and down
72 let bob = (time * 1.5).sin() * 0.05;
73 frame
74 .mesh(chess_piece)
75 .transform(
76 Transform::new()
77 .position(Vec3::new(0.0, 1.3 + bob, 0.0))
78 .rotation(Quat::from_rotation_y(time * 0.2)),
79 )
80 .color(Color::rgb(0.9, 0.85, 0.7))
81 .draw();
82
83 // Some decorative elements around the scene
84 let decoration_color = Color::rgb(0.3, 0.25, 0.35);
85 for i in 0..4 {
86 let angle = (i as f32) * std::f32::consts::FRAC_PI_2 + time * 0.1;
87 let radius = 3.0;
88 let x = angle.cos() * radius;
89 let z = angle.sin() * radius;
90 let height = 0.3 + (time + i as f32).sin().abs() * 0.2;
91
92 frame
93 .mesh(cube)
94 .transform(
95 Transform::new()
96 .position(Vec3::new(x, height, z))
97 .scale(Vec3::new(0.4, height * 2.0, 0.4))
98 .rotation(Quat::from_rotation_y(time + i as f32)),
99 )
100 .color(decoration_color)
101 .draw();
102 }
103
104 // UI text
105 frame.text(10.0, 10.0, "STL Model Loading Demo");
106 frame.text_color(
107 10.0,
108 35.0,
109 "Drag mouse to orbit, scroll to zoom",
110 Color::rgb(0.6, 0.6, 0.6),
111 );
112 frame.text_color(
113 10.0,
114 55.0,
115 &format!("FPS: {:.0}", frame.fps()),
116 Color::rgb(0.5, 0.5, 0.5),
117 );
118 }
119 },
120 );
121}examples/black_hole.rs (line 28)
4fn main() {
5 run_with_config(AppConfig::new().title("Black Hole"), |ctx| {
6 // Setup: configure render pipeline and load assets
7 ctx.default_font(16.0);
8
9 // Hot-reloadable shaders - edit the files and see changes live!
10 ctx.hot_effect_world("examples/shaders/black_hole.wgsl");
11
12 // Enable 3D mesh rendering (after background, before post-process)
13 ctx.enable_mesh_rendering();
14
15 // Add post-processing after mesh rendering
16 ctx.hot_post_process_world("examples/shaders/gravitational_lensing.wgsl");
17
18 // Create a cube mesh
19 let cube = ctx.mesh_cube();
20
21 // Create a procedural blocky noise texture (16x16 for that pixelated look)
22 let texture = ctx.texture_blocky_noise(16, 42);
23
24 // Create a 2D sprite for the UI (same procedural texture, rendered in 2D layer)
25 let sprite = ctx.sprite_blocky_noise(32, 123);
26
27 // Camera: auto-rotate or interactive orbit
28 let mut orbit = OrbitCamera::new()
29 .target(Vec3::ZERO)
30 .distance(32.0)
31 .elevation(0.3)
32 .fov(80.0)
33 .mode(OrbitMode::Interactive);
34
35 // State for toggling cube visibility
36 let mut cube_visible = true;
37
38 // Frame loop
39 move |frame| {
40 orbit.update(frame.input, frame.dt);
41 frame.set_camera(orbit.camera());
42
43 // Animate the cubes: hover above the black hole and rotate
44 let hover_height = 8.0 + (frame.time * 0.5).sin() * 0.5;
45
46 // Draw a 3x3 grid of textured cubes (if visible)
47 if cube_visible {
48 let spacing = 12.0;
49 for row in 0..3 {
50 for col in 0..3 {
51 let idx = row * 3 + col;
52 // Offset rotation per cube for visual variety
53 let phase = idx as f32 * 0.3;
54 let rotation = Quat::from_euler(
55 glam::EulerRot::YXZ,
56 frame.time * 0.7 + phase,
57 frame.time * 0.5 + phase,
58 frame.time * 0.3 + phase,
59 );
60
61 let x = (col as f32 - 1.0) * spacing;
62 let z = (row as f32 - 1.0) * spacing;
63
64 frame
65 .mesh(cube)
66 .transform(
67 Transform::new()
68 .position(Vec3::new(x, hover_height, z))
69 .rotation(rotation)
70 .uniform_scale(3.0),
71 )
72 .texture(texture)
73 .draw();
74 }
75 }
76 }
77
78 // Draw debug overlay
79 let y = frame.panel_titled(10.0, 10.0, 300.0, 120.0, "Debug Overlay");
80 frame.text(18.0, y + 8.0, &format!("FPS: {:.1}", frame.fps()));
81 frame.text_color(
82 18.0,
83 y + 28.0,
84 &format!("Time: {:.1}s", frame.time),
85 Color::rgba(0.7, 0.7, 0.7, 1.0),
86 );
87
88 // Draw the 2D sprite in the bottom-right corner (clickable toggle for cube visibility)
89 let sprite_x = frame.width() as f32 - 80.0;
90 let sprite_y = frame.height() as f32 - 80.0;
91 let sprite_w = 64.0;
92 let sprite_h = 64.0;
93
94 // Check for click on sprite
95 if frame.input.mouse_pressed(MouseButton::Left) {
96 let mouse_pos = frame.input.mouse_position();
97 if mouse_pos.x >= sprite_x
98 && mouse_pos.x <= sprite_x + sprite_w
99 && mouse_pos.y >= sprite_y
100 && mouse_pos.y <= sprite_y + sprite_h
101 {
102 cube_visible = !cube_visible;
103 }
104 }
105
106 // Draw sprite with tint based on cube visibility
107 let tint = if cube_visible {
108 Color::WHITE
109 } else {
110 Color::rgba(0.4, 0.4, 0.4, 1.0) // Grayed out when cube is hidden
111 };
112 frame.sprite_scaled_tinted(sprite, sprite_x, sprite_y, sprite_w, sprite_h, tint);
113
114 // Draw label above the sprite
115 let label = if cube_visible {
116 "Cubes: Shown"
117 } else {
118 "Cubes: Hidden"
119 };
120 frame.text(sprite_x - 40.0, sprite_y - 20.0, label);
121 }
122 });
123}examples/scenes.rs (line 42)
18fn main() {
19 run_with_scenes_config(
20 AppConfig::new()
21 .title("Scene Management Demo")
22 .size(1280, 720),
23 |ctx| {
24 ctx.default_font(18.0);
25
26 // Shared assets - available to all scenes
27 let cube = ctx.mesh_cube();
28 let plane = ctx.mesh_plane(30.0);
29
30 // Track current transition type
31 let transition_type = std::rc::Rc::new(std::cell::RefCell::new(TransitionType::Fade));
32 let transition_type_1 = transition_type.clone();
33 let transition_type_2 = transition_type.clone();
34
35 // =========================================================
36 // Scene 1: External view (ship floating in space)
37 // =========================================================
38 ctx.scene("external", |scene| {
39 scene.background_color(Color::rgb(0.02, 0.02, 0.05));
40 scene.enable_mesh_rendering();
41
42 let mut orbit = OrbitCamera::new()
43 .target(Vec3::ZERO)
44 .distance(8.0)
45 .elevation(0.3)
46 .fov(75.0)
47 .mode(OrbitMode::AutoRotate { speed: 0.2 });
48
49 let cube = cube;
50 let transition_type = transition_type_1;
51
52 move |frame| {
53 orbit.update(frame.input, frame.dt);
54 frame.set_camera(orbit.camera());
55
56 // Update transition type based on key presses
57 if frame.input.key_pressed(KeyCode::Digit1) {
58 *transition_type.borrow_mut() = TransitionType::Instant;
59 }
60 if frame.input.key_pressed(KeyCode::Digit2) {
61 *transition_type.borrow_mut() = TransitionType::Fade;
62 }
63 if frame.input.key_pressed(KeyCode::Digit3) {
64 *transition_type.borrow_mut() = TransitionType::Crossfade;
65 }
66
67 // Capture time before building meshes
68 let time = frame.time;
69 let ship_rotation = Quat::from_rotation_y(time * 0.1);
70
71 // Draw a simple "ship" - main body
72 frame
73 .mesh(cube)
74 .transform(
75 Transform::new()
76 .scale(Vec3::new(2.0, 0.5, 3.0))
77 .rotation(ship_rotation),
78 )
79 .color(Color::rgb(0.4, 0.4, 0.5))
80 .draw();
81
82 // Wings
83 for x in [-1.5, 1.5] {
84 frame
85 .mesh(cube)
86 .transform(
87 Transform::new()
88 .position(Vec3::new(x, 0.0, 0.0))
89 .scale(Vec3::new(1.5, 0.1, 1.0))
90 .rotation(ship_rotation),
91 )
92 .color(Color::rgb(0.3, 0.3, 0.4))
93 .draw();
94 }
95
96 // Cockpit (blue tinted)
97 frame
98 .mesh(cube)
99 .transform(
100 Transform::new()
101 .position(Vec3::new(0.0, 0.3, 0.8))
102 .scale(Vec3::new(0.6, 0.3, 0.4))
103 .rotation(ship_rotation),
104 )
105 .color(Color::rgb(0.2, 0.3, 0.5))
106 .draw();
107
108 // Engine glow
109 frame
110 .mesh(cube)
111 .transform(
112 Transform::new()
113 .position(Vec3::new(0.0, 0.0, -1.6))
114 .scale(Vec3::new(0.4, 0.3, 0.2))
115 .rotation(ship_rotation),
116 )
117 .color(Color::rgb(0.8, 0.4, 0.2))
118 .draw();
119
120 // Some "stars" (small cubes in the distance)
121 let star_positions = [
122 Vec3::new(10.0, 5.0, -15.0),
123 Vec3::new(-12.0, 8.0, -20.0),
124 Vec3::new(8.0, -3.0, -18.0),
125 Vec3::new(-6.0, 10.0, -25.0),
126 Vec3::new(15.0, -5.0, -22.0),
127 ];
128 for pos in star_positions {
129 frame
130 .mesh(cube)
131 .transform(Transform::new().position(pos).scale(Vec3::splat(0.1)))
132 .color(Color::rgb(0.9, 0.9, 1.0))
133 .draw();
134 }
135
136 // UI
137 frame.text(10.0, 10.0, "EXTERNAL VIEW");
138 frame.text(10.0, 35.0, "Press ENTER to enter cockpit");
139 frame.text_color(
140 10.0,
141 60.0,
142 &format!(
143 "Transition: {} (1-3 to change)",
144 transition_type.borrow().name()
145 ),
146 Color::rgb(0.6, 0.6, 0.6),
147 );
148
149 // Switch to cockpit on Enter
150 if frame.input.key_pressed(KeyCode::Enter) {
151 let transition = transition_type.borrow().to_transition();
152 frame.switch_to_with("cockpit", transition);
153 }
154 }
155 });
156
157 // =========================================================
158 // Scene 2: Cockpit interior view
159 // =========================================================
160 ctx.scene("cockpit", |scene| {
161 scene.background_color(Color::rgb(0.05, 0.03, 0.03));
162 scene.enable_mesh_rendering();
163
164 let cube = cube;
165 let plane = plane;
166 let transition_type = transition_type_2;
167 let mut look_yaw = 0.0_f32;
168
169 move |frame| {
170 // Simple look around with arrow keys
171 if frame.input.key_down(KeyCode::ArrowLeft) {
172 look_yaw += 1.5 * frame.dt;
173 }
174 if frame.input.key_down(KeyCode::ArrowRight) {
175 look_yaw -= 1.5 * frame.dt;
176 }
177
178 // Build camera with current look direction
179 let camera = hoplite::Camera::new()
180 .at(Vec3::new(0.0, 1.0, 0.0))
181 .looking_at(Vec3::new(look_yaw.sin(), 1.0, -look_yaw.cos()))
182 .with_fov(90.0);
183 frame.set_camera(camera);
184
185 // Update transition type based on key presses
186 if frame.input.key_pressed(KeyCode::Digit1) {
187 *transition_type.borrow_mut() = TransitionType::Instant;
188 }
189 if frame.input.key_pressed(KeyCode::Digit2) {
190 *transition_type.borrow_mut() = TransitionType::Fade;
191 }
192 if frame.input.key_pressed(KeyCode::Digit3) {
193 *transition_type.borrow_mut() = TransitionType::Crossfade;
194 }
195
196 // Capture time for animations
197 let time = frame.time;
198
199 // Draw cockpit interior
200 // Floor
201 frame
202 .mesh(plane)
203 .transform(Transform::new().scale(Vec3::splat(0.3)))
204 .color(Color::rgb(0.15, 0.12, 0.12))
205 .draw();
206
207 // Console in front
208 frame
209 .mesh(cube)
210 .transform(
211 Transform::new()
212 .position(Vec3::new(0.0, 0.6, -1.5))
213 .scale(Vec3::new(2.0, 0.8, 0.3)),
214 )
215 .color(Color::rgb(0.2, 0.2, 0.25))
216 .draw();
217
218 // Display screens on console
219 let screen_positions = [-0.6, 0.0, 0.6];
220 for (i, x) in screen_positions.iter().enumerate() {
221 let glow = (time * 2.0 + i as f32).sin() * 0.1 + 0.5;
222 frame
223 .mesh(cube)
224 .transform(
225 Transform::new()
226 .position(Vec3::new(*x, 0.9, -1.3))
227 .scale(Vec3::new(0.4, 0.3, 0.05)),
228 )
229 .color(Color::rgb(0.1, glow * 0.5, glow))
230 .draw();
231 }
232
233 // Side panels
234 for x in [-1.2, 1.2] {
235 frame
236 .mesh(cube)
237 .transform(
238 Transform::new()
239 .position(Vec3::new(x, 1.0, -0.5))
240 .scale(Vec3::new(0.1, 1.5, 2.0)),
241 )
242 .color(Color::rgb(0.12, 0.1, 0.1))
243 .draw();
244 }
245
246 // Ceiling
247 frame
248 .mesh(cube)
249 .transform(
250 Transform::new()
251 .position(Vec3::new(0.0, 2.2, -0.5))
252 .scale(Vec3::new(2.5, 0.1, 3.0)),
253 )
254 .color(Color::rgb(0.08, 0.08, 0.1))
255 .draw();
256
257 // Window (brighter area showing "space")
258 frame
259 .mesh(cube)
260 .transform(
261 Transform::new()
262 .position(Vec3::new(0.0, 1.5, -2.0))
263 .scale(Vec3::new(1.8, 0.8, 0.02)),
264 )
265 .color(Color::rgb(0.02, 0.02, 0.08))
266 .draw();
267
268 // Blinking warning lights
269 let blink = if (time * 3.0).sin() > 0.0 { 0.8 } else { 0.2 };
270 for x in [-0.9, 0.9] {
271 frame
272 .mesh(cube)
273 .transform(
274 Transform::new()
275 .position(Vec3::new(x, 1.8, -1.4))
276 .scale(Vec3::splat(0.08)),
277 )
278 .color(Color::rgb(blink, blink * 0.2, 0.0))
279 .draw();
280 }
281
282 // UI
283 frame.text(10.0, 10.0, "COCKPIT VIEW");
284 frame.text(10.0, 35.0, "Arrow keys to look around");
285 frame.text(10.0, 60.0, "Press ESCAPE for external view");
286 frame.text_color(
287 10.0,
288 85.0,
289 &format!(
290 "Transition: {} (1-3 to change)",
291 transition_type.borrow().name()
292 ),
293 Color::rgb(0.6, 0.6, 0.6),
294 );
295
296 // Switch back to external on Escape
297 if frame.input.key_pressed(KeyCode::Escape) {
298 let transition = transition_type.borrow().to_transition();
299 frame.switch_to_with("external", transition);
300 }
301 }
302 });
303
304 // Start in external view
305 ctx.start_scene("external");
306 },
307 );
308}Sourcepub fn target(self, target: impl Into<Vec3>) -> Self
pub fn target(self, target: impl Into<Vec3>) -> Self
Set the target point to orbit around.
Examples found in repository?
examples/sphere.rs (line 10)
5fn main() {
6 run_with_config(AppConfig::new().title("Raymarched Sphere"), |ctx| {
7 ctx.hot_effect_world("examples/shaders/sphere.wgsl");
8
9 let mut orbit = OrbitCamera::new()
10 .target(Vec3::ZERO)
11 .distance(3.0)
12 .elevation(0.3)
13 .fov(90.0)
14 .mode(OrbitMode::AutoRotate { speed: 0.5 });
15
16 move |frame| {
17 orbit.update(frame.input, frame.dt);
18 frame.set_camera(orbit.camera());
19 }
20 });
21}More examples
examples/stl_loader.rs (line 36)
10fn main() {
11 run_with_config(
12 AppConfig::new().title("STL Loader Demo").size(1280, 720),
13 |ctx| {
14 ctx.default_font(18.0);
15 ctx.background_color(Color::rgb(0.08, 0.08, 0.12));
16 ctx.enable_mesh_rendering();
17
18 // Load the chess piece STL with the fluent API
19 // - centered() moves the bounding box center to origin
20 // - normalized() scales to fit in a unit cube
21 // - scaled() then scales to desired size
22 let chess_piece = ctx
23 .load("examples/assets/models/chess.stl")
24 .centered()
25 .upright()
26 .normalized()
27 .scaled(2.0)
28 .unwrap();
29
30 // Create some primitive meshes for the scene
31 let plane = ctx.mesh_plane(10.0);
32 let cube = ctx.mesh_cube();
33
34 // Orbit camera for viewing the model
35 let mut orbit = OrbitCamera::new()
36 .target(Vec3::new(0.0, 1.0, 0.0))
37 .distance(5.0)
38 .elevation(0.4)
39 .fov(60.0)
40 .mode(OrbitMode::AutoRotate { speed: 0.3 });
41
42 let mut time = 0.0f32;
43
44 move |frame| {
45 time += frame.dt;
46
47 // Update camera
48 orbit.update(frame.input, frame.dt);
49 frame.set_camera(orbit.camera());
50
51 // Draw the floor
52 frame
53 .mesh(plane)
54 .transform(Transform::new())
55 .color(Color::rgb(0.15, 0.15, 0.18))
56 .draw();
57
58 // Draw the chess piece on a pedestal
59 // Pedestal base
60 frame
61 .mesh(cube)
62 .transform(
63 Transform::new()
64 .position(Vec3::new(0.0, 0.15, 0.0))
65 .scale(Vec3::new(1.5, 0.3, 1.5)),
66 )
67 .color(Color::rgb(0.2, 0.2, 0.25))
68 .draw();
69
70 // The chess piece - positioned on top of pedestal
71 // Slowly bobbing up and down
72 let bob = (time * 1.5).sin() * 0.05;
73 frame
74 .mesh(chess_piece)
75 .transform(
76 Transform::new()
77 .position(Vec3::new(0.0, 1.3 + bob, 0.0))
78 .rotation(Quat::from_rotation_y(time * 0.2)),
79 )
80 .color(Color::rgb(0.9, 0.85, 0.7))
81 .draw();
82
83 // Some decorative elements around the scene
84 let decoration_color = Color::rgb(0.3, 0.25, 0.35);
85 for i in 0..4 {
86 let angle = (i as f32) * std::f32::consts::FRAC_PI_2 + time * 0.1;
87 let radius = 3.0;
88 let x = angle.cos() * radius;
89 let z = angle.sin() * radius;
90 let height = 0.3 + (time + i as f32).sin().abs() * 0.2;
91
92 frame
93 .mesh(cube)
94 .transform(
95 Transform::new()
96 .position(Vec3::new(x, height, z))
97 .scale(Vec3::new(0.4, height * 2.0, 0.4))
98 .rotation(Quat::from_rotation_y(time + i as f32)),
99 )
100 .color(decoration_color)
101 .draw();
102 }
103
104 // UI text
105 frame.text(10.0, 10.0, "STL Model Loading Demo");
106 frame.text_color(
107 10.0,
108 35.0,
109 "Drag mouse to orbit, scroll to zoom",
110 Color::rgb(0.6, 0.6, 0.6),
111 );
112 frame.text_color(
113 10.0,
114 55.0,
115 &format!("FPS: {:.0}", frame.fps()),
116 Color::rgb(0.5, 0.5, 0.5),
117 );
118 }
119 },
120 );
121}examples/black_hole.rs (line 29)
4fn main() {
5 run_with_config(AppConfig::new().title("Black Hole"), |ctx| {
6 // Setup: configure render pipeline and load assets
7 ctx.default_font(16.0);
8
9 // Hot-reloadable shaders - edit the files and see changes live!
10 ctx.hot_effect_world("examples/shaders/black_hole.wgsl");
11
12 // Enable 3D mesh rendering (after background, before post-process)
13 ctx.enable_mesh_rendering();
14
15 // Add post-processing after mesh rendering
16 ctx.hot_post_process_world("examples/shaders/gravitational_lensing.wgsl");
17
18 // Create a cube mesh
19 let cube = ctx.mesh_cube();
20
21 // Create a procedural blocky noise texture (16x16 for that pixelated look)
22 let texture = ctx.texture_blocky_noise(16, 42);
23
24 // Create a 2D sprite for the UI (same procedural texture, rendered in 2D layer)
25 let sprite = ctx.sprite_blocky_noise(32, 123);
26
27 // Camera: auto-rotate or interactive orbit
28 let mut orbit = OrbitCamera::new()
29 .target(Vec3::ZERO)
30 .distance(32.0)
31 .elevation(0.3)
32 .fov(80.0)
33 .mode(OrbitMode::Interactive);
34
35 // State for toggling cube visibility
36 let mut cube_visible = true;
37
38 // Frame loop
39 move |frame| {
40 orbit.update(frame.input, frame.dt);
41 frame.set_camera(orbit.camera());
42
43 // Animate the cubes: hover above the black hole and rotate
44 let hover_height = 8.0 + (frame.time * 0.5).sin() * 0.5;
45
46 // Draw a 3x3 grid of textured cubes (if visible)
47 if cube_visible {
48 let spacing = 12.0;
49 for row in 0..3 {
50 for col in 0..3 {
51 let idx = row * 3 + col;
52 // Offset rotation per cube for visual variety
53 let phase = idx as f32 * 0.3;
54 let rotation = Quat::from_euler(
55 glam::EulerRot::YXZ,
56 frame.time * 0.7 + phase,
57 frame.time * 0.5 + phase,
58 frame.time * 0.3 + phase,
59 );
60
61 let x = (col as f32 - 1.0) * spacing;
62 let z = (row as f32 - 1.0) * spacing;
63
64 frame
65 .mesh(cube)
66 .transform(
67 Transform::new()
68 .position(Vec3::new(x, hover_height, z))
69 .rotation(rotation)
70 .uniform_scale(3.0),
71 )
72 .texture(texture)
73 .draw();
74 }
75 }
76 }
77
78 // Draw debug overlay
79 let y = frame.panel_titled(10.0, 10.0, 300.0, 120.0, "Debug Overlay");
80 frame.text(18.0, y + 8.0, &format!("FPS: {:.1}", frame.fps()));
81 frame.text_color(
82 18.0,
83 y + 28.0,
84 &format!("Time: {:.1}s", frame.time),
85 Color::rgba(0.7, 0.7, 0.7, 1.0),
86 );
87
88 // Draw the 2D sprite in the bottom-right corner (clickable toggle for cube visibility)
89 let sprite_x = frame.width() as f32 - 80.0;
90 let sprite_y = frame.height() as f32 - 80.0;
91 let sprite_w = 64.0;
92 let sprite_h = 64.0;
93
94 // Check for click on sprite
95 if frame.input.mouse_pressed(MouseButton::Left) {
96 let mouse_pos = frame.input.mouse_position();
97 if mouse_pos.x >= sprite_x
98 && mouse_pos.x <= sprite_x + sprite_w
99 && mouse_pos.y >= sprite_y
100 && mouse_pos.y <= sprite_y + sprite_h
101 {
102 cube_visible = !cube_visible;
103 }
104 }
105
106 // Draw sprite with tint based on cube visibility
107 let tint = if cube_visible {
108 Color::WHITE
109 } else {
110 Color::rgba(0.4, 0.4, 0.4, 1.0) // Grayed out when cube is hidden
111 };
112 frame.sprite_scaled_tinted(sprite, sprite_x, sprite_y, sprite_w, sprite_h, tint);
113
114 // Draw label above the sprite
115 let label = if cube_visible {
116 "Cubes: Shown"
117 } else {
118 "Cubes: Hidden"
119 };
120 frame.text(sprite_x - 40.0, sprite_y - 20.0, label);
121 }
122 });
123}examples/scenes.rs (line 43)
18fn main() {
19 run_with_scenes_config(
20 AppConfig::new()
21 .title("Scene Management Demo")
22 .size(1280, 720),
23 |ctx| {
24 ctx.default_font(18.0);
25
26 // Shared assets - available to all scenes
27 let cube = ctx.mesh_cube();
28 let plane = ctx.mesh_plane(30.0);
29
30 // Track current transition type
31 let transition_type = std::rc::Rc::new(std::cell::RefCell::new(TransitionType::Fade));
32 let transition_type_1 = transition_type.clone();
33 let transition_type_2 = transition_type.clone();
34
35 // =========================================================
36 // Scene 1: External view (ship floating in space)
37 // =========================================================
38 ctx.scene("external", |scene| {
39 scene.background_color(Color::rgb(0.02, 0.02, 0.05));
40 scene.enable_mesh_rendering();
41
42 let mut orbit = OrbitCamera::new()
43 .target(Vec3::ZERO)
44 .distance(8.0)
45 .elevation(0.3)
46 .fov(75.0)
47 .mode(OrbitMode::AutoRotate { speed: 0.2 });
48
49 let cube = cube;
50 let transition_type = transition_type_1;
51
52 move |frame| {
53 orbit.update(frame.input, frame.dt);
54 frame.set_camera(orbit.camera());
55
56 // Update transition type based on key presses
57 if frame.input.key_pressed(KeyCode::Digit1) {
58 *transition_type.borrow_mut() = TransitionType::Instant;
59 }
60 if frame.input.key_pressed(KeyCode::Digit2) {
61 *transition_type.borrow_mut() = TransitionType::Fade;
62 }
63 if frame.input.key_pressed(KeyCode::Digit3) {
64 *transition_type.borrow_mut() = TransitionType::Crossfade;
65 }
66
67 // Capture time before building meshes
68 let time = frame.time;
69 let ship_rotation = Quat::from_rotation_y(time * 0.1);
70
71 // Draw a simple "ship" - main body
72 frame
73 .mesh(cube)
74 .transform(
75 Transform::new()
76 .scale(Vec3::new(2.0, 0.5, 3.0))
77 .rotation(ship_rotation),
78 )
79 .color(Color::rgb(0.4, 0.4, 0.5))
80 .draw();
81
82 // Wings
83 for x in [-1.5, 1.5] {
84 frame
85 .mesh(cube)
86 .transform(
87 Transform::new()
88 .position(Vec3::new(x, 0.0, 0.0))
89 .scale(Vec3::new(1.5, 0.1, 1.0))
90 .rotation(ship_rotation),
91 )
92 .color(Color::rgb(0.3, 0.3, 0.4))
93 .draw();
94 }
95
96 // Cockpit (blue tinted)
97 frame
98 .mesh(cube)
99 .transform(
100 Transform::new()
101 .position(Vec3::new(0.0, 0.3, 0.8))
102 .scale(Vec3::new(0.6, 0.3, 0.4))
103 .rotation(ship_rotation),
104 )
105 .color(Color::rgb(0.2, 0.3, 0.5))
106 .draw();
107
108 // Engine glow
109 frame
110 .mesh(cube)
111 .transform(
112 Transform::new()
113 .position(Vec3::new(0.0, 0.0, -1.6))
114 .scale(Vec3::new(0.4, 0.3, 0.2))
115 .rotation(ship_rotation),
116 )
117 .color(Color::rgb(0.8, 0.4, 0.2))
118 .draw();
119
120 // Some "stars" (small cubes in the distance)
121 let star_positions = [
122 Vec3::new(10.0, 5.0, -15.0),
123 Vec3::new(-12.0, 8.0, -20.0),
124 Vec3::new(8.0, -3.0, -18.0),
125 Vec3::new(-6.0, 10.0, -25.0),
126 Vec3::new(15.0, -5.0, -22.0),
127 ];
128 for pos in star_positions {
129 frame
130 .mesh(cube)
131 .transform(Transform::new().position(pos).scale(Vec3::splat(0.1)))
132 .color(Color::rgb(0.9, 0.9, 1.0))
133 .draw();
134 }
135
136 // UI
137 frame.text(10.0, 10.0, "EXTERNAL VIEW");
138 frame.text(10.0, 35.0, "Press ENTER to enter cockpit");
139 frame.text_color(
140 10.0,
141 60.0,
142 &format!(
143 "Transition: {} (1-3 to change)",
144 transition_type.borrow().name()
145 ),
146 Color::rgb(0.6, 0.6, 0.6),
147 );
148
149 // Switch to cockpit on Enter
150 if frame.input.key_pressed(KeyCode::Enter) {
151 let transition = transition_type.borrow().to_transition();
152 frame.switch_to_with("cockpit", transition);
153 }
154 }
155 });
156
157 // =========================================================
158 // Scene 2: Cockpit interior view
159 // =========================================================
160 ctx.scene("cockpit", |scene| {
161 scene.background_color(Color::rgb(0.05, 0.03, 0.03));
162 scene.enable_mesh_rendering();
163
164 let cube = cube;
165 let plane = plane;
166 let transition_type = transition_type_2;
167 let mut look_yaw = 0.0_f32;
168
169 move |frame| {
170 // Simple look around with arrow keys
171 if frame.input.key_down(KeyCode::ArrowLeft) {
172 look_yaw += 1.5 * frame.dt;
173 }
174 if frame.input.key_down(KeyCode::ArrowRight) {
175 look_yaw -= 1.5 * frame.dt;
176 }
177
178 // Build camera with current look direction
179 let camera = hoplite::Camera::new()
180 .at(Vec3::new(0.0, 1.0, 0.0))
181 .looking_at(Vec3::new(look_yaw.sin(), 1.0, -look_yaw.cos()))
182 .with_fov(90.0);
183 frame.set_camera(camera);
184
185 // Update transition type based on key presses
186 if frame.input.key_pressed(KeyCode::Digit1) {
187 *transition_type.borrow_mut() = TransitionType::Instant;
188 }
189 if frame.input.key_pressed(KeyCode::Digit2) {
190 *transition_type.borrow_mut() = TransitionType::Fade;
191 }
192 if frame.input.key_pressed(KeyCode::Digit3) {
193 *transition_type.borrow_mut() = TransitionType::Crossfade;
194 }
195
196 // Capture time for animations
197 let time = frame.time;
198
199 // Draw cockpit interior
200 // Floor
201 frame
202 .mesh(plane)
203 .transform(Transform::new().scale(Vec3::splat(0.3)))
204 .color(Color::rgb(0.15, 0.12, 0.12))
205 .draw();
206
207 // Console in front
208 frame
209 .mesh(cube)
210 .transform(
211 Transform::new()
212 .position(Vec3::new(0.0, 0.6, -1.5))
213 .scale(Vec3::new(2.0, 0.8, 0.3)),
214 )
215 .color(Color::rgb(0.2, 0.2, 0.25))
216 .draw();
217
218 // Display screens on console
219 let screen_positions = [-0.6, 0.0, 0.6];
220 for (i, x) in screen_positions.iter().enumerate() {
221 let glow = (time * 2.0 + i as f32).sin() * 0.1 + 0.5;
222 frame
223 .mesh(cube)
224 .transform(
225 Transform::new()
226 .position(Vec3::new(*x, 0.9, -1.3))
227 .scale(Vec3::new(0.4, 0.3, 0.05)),
228 )
229 .color(Color::rgb(0.1, glow * 0.5, glow))
230 .draw();
231 }
232
233 // Side panels
234 for x in [-1.2, 1.2] {
235 frame
236 .mesh(cube)
237 .transform(
238 Transform::new()
239 .position(Vec3::new(x, 1.0, -0.5))
240 .scale(Vec3::new(0.1, 1.5, 2.0)),
241 )
242 .color(Color::rgb(0.12, 0.1, 0.1))
243 .draw();
244 }
245
246 // Ceiling
247 frame
248 .mesh(cube)
249 .transform(
250 Transform::new()
251 .position(Vec3::new(0.0, 2.2, -0.5))
252 .scale(Vec3::new(2.5, 0.1, 3.0)),
253 )
254 .color(Color::rgb(0.08, 0.08, 0.1))
255 .draw();
256
257 // Window (brighter area showing "space")
258 frame
259 .mesh(cube)
260 .transform(
261 Transform::new()
262 .position(Vec3::new(0.0, 1.5, -2.0))
263 .scale(Vec3::new(1.8, 0.8, 0.02)),
264 )
265 .color(Color::rgb(0.02, 0.02, 0.08))
266 .draw();
267
268 // Blinking warning lights
269 let blink = if (time * 3.0).sin() > 0.0 { 0.8 } else { 0.2 };
270 for x in [-0.9, 0.9] {
271 frame
272 .mesh(cube)
273 .transform(
274 Transform::new()
275 .position(Vec3::new(x, 1.8, -1.4))
276 .scale(Vec3::splat(0.08)),
277 )
278 .color(Color::rgb(blink, blink * 0.2, 0.0))
279 .draw();
280 }
281
282 // UI
283 frame.text(10.0, 10.0, "COCKPIT VIEW");
284 frame.text(10.0, 35.0, "Arrow keys to look around");
285 frame.text(10.0, 60.0, "Press ESCAPE for external view");
286 frame.text_color(
287 10.0,
288 85.0,
289 &format!(
290 "Transition: {} (1-3 to change)",
291 transition_type.borrow().name()
292 ),
293 Color::rgb(0.6, 0.6, 0.6),
294 );
295
296 // Switch back to external on Escape
297 if frame.input.key_pressed(KeyCode::Escape) {
298 let transition = transition_type.borrow().to_transition();
299 frame.switch_to_with("external", transition);
300 }
301 }
302 });
303
304 // Start in external view
305 ctx.start_scene("external");
306 },
307 );
308}Sourcepub fn distance(self, distance: f32) -> Self
pub fn distance(self, distance: f32) -> Self
Set the distance from target.
Examples found in repository?
examples/sphere.rs (line 11)
5fn main() {
6 run_with_config(AppConfig::new().title("Raymarched Sphere"), |ctx| {
7 ctx.hot_effect_world("examples/shaders/sphere.wgsl");
8
9 let mut orbit = OrbitCamera::new()
10 .target(Vec3::ZERO)
11 .distance(3.0)
12 .elevation(0.3)
13 .fov(90.0)
14 .mode(OrbitMode::AutoRotate { speed: 0.5 });
15
16 move |frame| {
17 orbit.update(frame.input, frame.dt);
18 frame.set_camera(orbit.camera());
19 }
20 });
21}More examples
examples/stl_loader.rs (line 37)
10fn main() {
11 run_with_config(
12 AppConfig::new().title("STL Loader Demo").size(1280, 720),
13 |ctx| {
14 ctx.default_font(18.0);
15 ctx.background_color(Color::rgb(0.08, 0.08, 0.12));
16 ctx.enable_mesh_rendering();
17
18 // Load the chess piece STL with the fluent API
19 // - centered() moves the bounding box center to origin
20 // - normalized() scales to fit in a unit cube
21 // - scaled() then scales to desired size
22 let chess_piece = ctx
23 .load("examples/assets/models/chess.stl")
24 .centered()
25 .upright()
26 .normalized()
27 .scaled(2.0)
28 .unwrap();
29
30 // Create some primitive meshes for the scene
31 let plane = ctx.mesh_plane(10.0);
32 let cube = ctx.mesh_cube();
33
34 // Orbit camera for viewing the model
35 let mut orbit = OrbitCamera::new()
36 .target(Vec3::new(0.0, 1.0, 0.0))
37 .distance(5.0)
38 .elevation(0.4)
39 .fov(60.0)
40 .mode(OrbitMode::AutoRotate { speed: 0.3 });
41
42 let mut time = 0.0f32;
43
44 move |frame| {
45 time += frame.dt;
46
47 // Update camera
48 orbit.update(frame.input, frame.dt);
49 frame.set_camera(orbit.camera());
50
51 // Draw the floor
52 frame
53 .mesh(plane)
54 .transform(Transform::new())
55 .color(Color::rgb(0.15, 0.15, 0.18))
56 .draw();
57
58 // Draw the chess piece on a pedestal
59 // Pedestal base
60 frame
61 .mesh(cube)
62 .transform(
63 Transform::new()
64 .position(Vec3::new(0.0, 0.15, 0.0))
65 .scale(Vec3::new(1.5, 0.3, 1.5)),
66 )
67 .color(Color::rgb(0.2, 0.2, 0.25))
68 .draw();
69
70 // The chess piece - positioned on top of pedestal
71 // Slowly bobbing up and down
72 let bob = (time * 1.5).sin() * 0.05;
73 frame
74 .mesh(chess_piece)
75 .transform(
76 Transform::new()
77 .position(Vec3::new(0.0, 1.3 + bob, 0.0))
78 .rotation(Quat::from_rotation_y(time * 0.2)),
79 )
80 .color(Color::rgb(0.9, 0.85, 0.7))
81 .draw();
82
83 // Some decorative elements around the scene
84 let decoration_color = Color::rgb(0.3, 0.25, 0.35);
85 for i in 0..4 {
86 let angle = (i as f32) * std::f32::consts::FRAC_PI_2 + time * 0.1;
87 let radius = 3.0;
88 let x = angle.cos() * radius;
89 let z = angle.sin() * radius;
90 let height = 0.3 + (time + i as f32).sin().abs() * 0.2;
91
92 frame
93 .mesh(cube)
94 .transform(
95 Transform::new()
96 .position(Vec3::new(x, height, z))
97 .scale(Vec3::new(0.4, height * 2.0, 0.4))
98 .rotation(Quat::from_rotation_y(time + i as f32)),
99 )
100 .color(decoration_color)
101 .draw();
102 }
103
104 // UI text
105 frame.text(10.0, 10.0, "STL Model Loading Demo");
106 frame.text_color(
107 10.0,
108 35.0,
109 "Drag mouse to orbit, scroll to zoom",
110 Color::rgb(0.6, 0.6, 0.6),
111 );
112 frame.text_color(
113 10.0,
114 55.0,
115 &format!("FPS: {:.0}", frame.fps()),
116 Color::rgb(0.5, 0.5, 0.5),
117 );
118 }
119 },
120 );
121}examples/black_hole.rs (line 30)
4fn main() {
5 run_with_config(AppConfig::new().title("Black Hole"), |ctx| {
6 // Setup: configure render pipeline and load assets
7 ctx.default_font(16.0);
8
9 // Hot-reloadable shaders - edit the files and see changes live!
10 ctx.hot_effect_world("examples/shaders/black_hole.wgsl");
11
12 // Enable 3D mesh rendering (after background, before post-process)
13 ctx.enable_mesh_rendering();
14
15 // Add post-processing after mesh rendering
16 ctx.hot_post_process_world("examples/shaders/gravitational_lensing.wgsl");
17
18 // Create a cube mesh
19 let cube = ctx.mesh_cube();
20
21 // Create a procedural blocky noise texture (16x16 for that pixelated look)
22 let texture = ctx.texture_blocky_noise(16, 42);
23
24 // Create a 2D sprite for the UI (same procedural texture, rendered in 2D layer)
25 let sprite = ctx.sprite_blocky_noise(32, 123);
26
27 // Camera: auto-rotate or interactive orbit
28 let mut orbit = OrbitCamera::new()
29 .target(Vec3::ZERO)
30 .distance(32.0)
31 .elevation(0.3)
32 .fov(80.0)
33 .mode(OrbitMode::Interactive);
34
35 // State for toggling cube visibility
36 let mut cube_visible = true;
37
38 // Frame loop
39 move |frame| {
40 orbit.update(frame.input, frame.dt);
41 frame.set_camera(orbit.camera());
42
43 // Animate the cubes: hover above the black hole and rotate
44 let hover_height = 8.0 + (frame.time * 0.5).sin() * 0.5;
45
46 // Draw a 3x3 grid of textured cubes (if visible)
47 if cube_visible {
48 let spacing = 12.0;
49 for row in 0..3 {
50 for col in 0..3 {
51 let idx = row * 3 + col;
52 // Offset rotation per cube for visual variety
53 let phase = idx as f32 * 0.3;
54 let rotation = Quat::from_euler(
55 glam::EulerRot::YXZ,
56 frame.time * 0.7 + phase,
57 frame.time * 0.5 + phase,
58 frame.time * 0.3 + phase,
59 );
60
61 let x = (col as f32 - 1.0) * spacing;
62 let z = (row as f32 - 1.0) * spacing;
63
64 frame
65 .mesh(cube)
66 .transform(
67 Transform::new()
68 .position(Vec3::new(x, hover_height, z))
69 .rotation(rotation)
70 .uniform_scale(3.0),
71 )
72 .texture(texture)
73 .draw();
74 }
75 }
76 }
77
78 // Draw debug overlay
79 let y = frame.panel_titled(10.0, 10.0, 300.0, 120.0, "Debug Overlay");
80 frame.text(18.0, y + 8.0, &format!("FPS: {:.1}", frame.fps()));
81 frame.text_color(
82 18.0,
83 y + 28.0,
84 &format!("Time: {:.1}s", frame.time),
85 Color::rgba(0.7, 0.7, 0.7, 1.0),
86 );
87
88 // Draw the 2D sprite in the bottom-right corner (clickable toggle for cube visibility)
89 let sprite_x = frame.width() as f32 - 80.0;
90 let sprite_y = frame.height() as f32 - 80.0;
91 let sprite_w = 64.0;
92 let sprite_h = 64.0;
93
94 // Check for click on sprite
95 if frame.input.mouse_pressed(MouseButton::Left) {
96 let mouse_pos = frame.input.mouse_position();
97 if mouse_pos.x >= sprite_x
98 && mouse_pos.x <= sprite_x + sprite_w
99 && mouse_pos.y >= sprite_y
100 && mouse_pos.y <= sprite_y + sprite_h
101 {
102 cube_visible = !cube_visible;
103 }
104 }
105
106 // Draw sprite with tint based on cube visibility
107 let tint = if cube_visible {
108 Color::WHITE
109 } else {
110 Color::rgba(0.4, 0.4, 0.4, 1.0) // Grayed out when cube is hidden
111 };
112 frame.sprite_scaled_tinted(sprite, sprite_x, sprite_y, sprite_w, sprite_h, tint);
113
114 // Draw label above the sprite
115 let label = if cube_visible {
116 "Cubes: Shown"
117 } else {
118 "Cubes: Hidden"
119 };
120 frame.text(sprite_x - 40.0, sprite_y - 20.0, label);
121 }
122 });
123}examples/scenes.rs (line 44)
18fn main() {
19 run_with_scenes_config(
20 AppConfig::new()
21 .title("Scene Management Demo")
22 .size(1280, 720),
23 |ctx| {
24 ctx.default_font(18.0);
25
26 // Shared assets - available to all scenes
27 let cube = ctx.mesh_cube();
28 let plane = ctx.mesh_plane(30.0);
29
30 // Track current transition type
31 let transition_type = std::rc::Rc::new(std::cell::RefCell::new(TransitionType::Fade));
32 let transition_type_1 = transition_type.clone();
33 let transition_type_2 = transition_type.clone();
34
35 // =========================================================
36 // Scene 1: External view (ship floating in space)
37 // =========================================================
38 ctx.scene("external", |scene| {
39 scene.background_color(Color::rgb(0.02, 0.02, 0.05));
40 scene.enable_mesh_rendering();
41
42 let mut orbit = OrbitCamera::new()
43 .target(Vec3::ZERO)
44 .distance(8.0)
45 .elevation(0.3)
46 .fov(75.0)
47 .mode(OrbitMode::AutoRotate { speed: 0.2 });
48
49 let cube = cube;
50 let transition_type = transition_type_1;
51
52 move |frame| {
53 orbit.update(frame.input, frame.dt);
54 frame.set_camera(orbit.camera());
55
56 // Update transition type based on key presses
57 if frame.input.key_pressed(KeyCode::Digit1) {
58 *transition_type.borrow_mut() = TransitionType::Instant;
59 }
60 if frame.input.key_pressed(KeyCode::Digit2) {
61 *transition_type.borrow_mut() = TransitionType::Fade;
62 }
63 if frame.input.key_pressed(KeyCode::Digit3) {
64 *transition_type.borrow_mut() = TransitionType::Crossfade;
65 }
66
67 // Capture time before building meshes
68 let time = frame.time;
69 let ship_rotation = Quat::from_rotation_y(time * 0.1);
70
71 // Draw a simple "ship" - main body
72 frame
73 .mesh(cube)
74 .transform(
75 Transform::new()
76 .scale(Vec3::new(2.0, 0.5, 3.0))
77 .rotation(ship_rotation),
78 )
79 .color(Color::rgb(0.4, 0.4, 0.5))
80 .draw();
81
82 // Wings
83 for x in [-1.5, 1.5] {
84 frame
85 .mesh(cube)
86 .transform(
87 Transform::new()
88 .position(Vec3::new(x, 0.0, 0.0))
89 .scale(Vec3::new(1.5, 0.1, 1.0))
90 .rotation(ship_rotation),
91 )
92 .color(Color::rgb(0.3, 0.3, 0.4))
93 .draw();
94 }
95
96 // Cockpit (blue tinted)
97 frame
98 .mesh(cube)
99 .transform(
100 Transform::new()
101 .position(Vec3::new(0.0, 0.3, 0.8))
102 .scale(Vec3::new(0.6, 0.3, 0.4))
103 .rotation(ship_rotation),
104 )
105 .color(Color::rgb(0.2, 0.3, 0.5))
106 .draw();
107
108 // Engine glow
109 frame
110 .mesh(cube)
111 .transform(
112 Transform::new()
113 .position(Vec3::new(0.0, 0.0, -1.6))
114 .scale(Vec3::new(0.4, 0.3, 0.2))
115 .rotation(ship_rotation),
116 )
117 .color(Color::rgb(0.8, 0.4, 0.2))
118 .draw();
119
120 // Some "stars" (small cubes in the distance)
121 let star_positions = [
122 Vec3::new(10.0, 5.0, -15.0),
123 Vec3::new(-12.0, 8.0, -20.0),
124 Vec3::new(8.0, -3.0, -18.0),
125 Vec3::new(-6.0, 10.0, -25.0),
126 Vec3::new(15.0, -5.0, -22.0),
127 ];
128 for pos in star_positions {
129 frame
130 .mesh(cube)
131 .transform(Transform::new().position(pos).scale(Vec3::splat(0.1)))
132 .color(Color::rgb(0.9, 0.9, 1.0))
133 .draw();
134 }
135
136 // UI
137 frame.text(10.0, 10.0, "EXTERNAL VIEW");
138 frame.text(10.0, 35.0, "Press ENTER to enter cockpit");
139 frame.text_color(
140 10.0,
141 60.0,
142 &format!(
143 "Transition: {} (1-3 to change)",
144 transition_type.borrow().name()
145 ),
146 Color::rgb(0.6, 0.6, 0.6),
147 );
148
149 // Switch to cockpit on Enter
150 if frame.input.key_pressed(KeyCode::Enter) {
151 let transition = transition_type.borrow().to_transition();
152 frame.switch_to_with("cockpit", transition);
153 }
154 }
155 });
156
157 // =========================================================
158 // Scene 2: Cockpit interior view
159 // =========================================================
160 ctx.scene("cockpit", |scene| {
161 scene.background_color(Color::rgb(0.05, 0.03, 0.03));
162 scene.enable_mesh_rendering();
163
164 let cube = cube;
165 let plane = plane;
166 let transition_type = transition_type_2;
167 let mut look_yaw = 0.0_f32;
168
169 move |frame| {
170 // Simple look around with arrow keys
171 if frame.input.key_down(KeyCode::ArrowLeft) {
172 look_yaw += 1.5 * frame.dt;
173 }
174 if frame.input.key_down(KeyCode::ArrowRight) {
175 look_yaw -= 1.5 * frame.dt;
176 }
177
178 // Build camera with current look direction
179 let camera = hoplite::Camera::new()
180 .at(Vec3::new(0.0, 1.0, 0.0))
181 .looking_at(Vec3::new(look_yaw.sin(), 1.0, -look_yaw.cos()))
182 .with_fov(90.0);
183 frame.set_camera(camera);
184
185 // Update transition type based on key presses
186 if frame.input.key_pressed(KeyCode::Digit1) {
187 *transition_type.borrow_mut() = TransitionType::Instant;
188 }
189 if frame.input.key_pressed(KeyCode::Digit2) {
190 *transition_type.borrow_mut() = TransitionType::Fade;
191 }
192 if frame.input.key_pressed(KeyCode::Digit3) {
193 *transition_type.borrow_mut() = TransitionType::Crossfade;
194 }
195
196 // Capture time for animations
197 let time = frame.time;
198
199 // Draw cockpit interior
200 // Floor
201 frame
202 .mesh(plane)
203 .transform(Transform::new().scale(Vec3::splat(0.3)))
204 .color(Color::rgb(0.15, 0.12, 0.12))
205 .draw();
206
207 // Console in front
208 frame
209 .mesh(cube)
210 .transform(
211 Transform::new()
212 .position(Vec3::new(0.0, 0.6, -1.5))
213 .scale(Vec3::new(2.0, 0.8, 0.3)),
214 )
215 .color(Color::rgb(0.2, 0.2, 0.25))
216 .draw();
217
218 // Display screens on console
219 let screen_positions = [-0.6, 0.0, 0.6];
220 for (i, x) in screen_positions.iter().enumerate() {
221 let glow = (time * 2.0 + i as f32).sin() * 0.1 + 0.5;
222 frame
223 .mesh(cube)
224 .transform(
225 Transform::new()
226 .position(Vec3::new(*x, 0.9, -1.3))
227 .scale(Vec3::new(0.4, 0.3, 0.05)),
228 )
229 .color(Color::rgb(0.1, glow * 0.5, glow))
230 .draw();
231 }
232
233 // Side panels
234 for x in [-1.2, 1.2] {
235 frame
236 .mesh(cube)
237 .transform(
238 Transform::new()
239 .position(Vec3::new(x, 1.0, -0.5))
240 .scale(Vec3::new(0.1, 1.5, 2.0)),
241 )
242 .color(Color::rgb(0.12, 0.1, 0.1))
243 .draw();
244 }
245
246 // Ceiling
247 frame
248 .mesh(cube)
249 .transform(
250 Transform::new()
251 .position(Vec3::new(0.0, 2.2, -0.5))
252 .scale(Vec3::new(2.5, 0.1, 3.0)),
253 )
254 .color(Color::rgb(0.08, 0.08, 0.1))
255 .draw();
256
257 // Window (brighter area showing "space")
258 frame
259 .mesh(cube)
260 .transform(
261 Transform::new()
262 .position(Vec3::new(0.0, 1.5, -2.0))
263 .scale(Vec3::new(1.8, 0.8, 0.02)),
264 )
265 .color(Color::rgb(0.02, 0.02, 0.08))
266 .draw();
267
268 // Blinking warning lights
269 let blink = if (time * 3.0).sin() > 0.0 { 0.8 } else { 0.2 };
270 for x in [-0.9, 0.9] {
271 frame
272 .mesh(cube)
273 .transform(
274 Transform::new()
275 .position(Vec3::new(x, 1.8, -1.4))
276 .scale(Vec3::splat(0.08)),
277 )
278 .color(Color::rgb(blink, blink * 0.2, 0.0))
279 .draw();
280 }
281
282 // UI
283 frame.text(10.0, 10.0, "COCKPIT VIEW");
284 frame.text(10.0, 35.0, "Arrow keys to look around");
285 frame.text(10.0, 60.0, "Press ESCAPE for external view");
286 frame.text_color(
287 10.0,
288 85.0,
289 &format!(
290 "Transition: {} (1-3 to change)",
291 transition_type.borrow().name()
292 ),
293 Color::rgb(0.6, 0.6, 0.6),
294 );
295
296 // Switch back to external on Escape
297 if frame.input.key_pressed(KeyCode::Escape) {
298 let transition = transition_type.borrow().to_transition();
299 frame.switch_to_with("external", transition);
300 }
301 }
302 });
303
304 // Start in external view
305 ctx.start_scene("external");
306 },
307 );
308}Sourcepub fn mode(self, mode: OrbitMode) -> Self
pub fn mode(self, mode: OrbitMode) -> Self
Set the control mode.
Examples found in repository?
examples/sphere.rs (line 14)
5fn main() {
6 run_with_config(AppConfig::new().title("Raymarched Sphere"), |ctx| {
7 ctx.hot_effect_world("examples/shaders/sphere.wgsl");
8
9 let mut orbit = OrbitCamera::new()
10 .target(Vec3::ZERO)
11 .distance(3.0)
12 .elevation(0.3)
13 .fov(90.0)
14 .mode(OrbitMode::AutoRotate { speed: 0.5 });
15
16 move |frame| {
17 orbit.update(frame.input, frame.dt);
18 frame.set_camera(orbit.camera());
19 }
20 });
21}More examples
examples/stl_loader.rs (line 40)
10fn main() {
11 run_with_config(
12 AppConfig::new().title("STL Loader Demo").size(1280, 720),
13 |ctx| {
14 ctx.default_font(18.0);
15 ctx.background_color(Color::rgb(0.08, 0.08, 0.12));
16 ctx.enable_mesh_rendering();
17
18 // Load the chess piece STL with the fluent API
19 // - centered() moves the bounding box center to origin
20 // - normalized() scales to fit in a unit cube
21 // - scaled() then scales to desired size
22 let chess_piece = ctx
23 .load("examples/assets/models/chess.stl")
24 .centered()
25 .upright()
26 .normalized()
27 .scaled(2.0)
28 .unwrap();
29
30 // Create some primitive meshes for the scene
31 let plane = ctx.mesh_plane(10.0);
32 let cube = ctx.mesh_cube();
33
34 // Orbit camera for viewing the model
35 let mut orbit = OrbitCamera::new()
36 .target(Vec3::new(0.0, 1.0, 0.0))
37 .distance(5.0)
38 .elevation(0.4)
39 .fov(60.0)
40 .mode(OrbitMode::AutoRotate { speed: 0.3 });
41
42 let mut time = 0.0f32;
43
44 move |frame| {
45 time += frame.dt;
46
47 // Update camera
48 orbit.update(frame.input, frame.dt);
49 frame.set_camera(orbit.camera());
50
51 // Draw the floor
52 frame
53 .mesh(plane)
54 .transform(Transform::new())
55 .color(Color::rgb(0.15, 0.15, 0.18))
56 .draw();
57
58 // Draw the chess piece on a pedestal
59 // Pedestal base
60 frame
61 .mesh(cube)
62 .transform(
63 Transform::new()
64 .position(Vec3::new(0.0, 0.15, 0.0))
65 .scale(Vec3::new(1.5, 0.3, 1.5)),
66 )
67 .color(Color::rgb(0.2, 0.2, 0.25))
68 .draw();
69
70 // The chess piece - positioned on top of pedestal
71 // Slowly bobbing up and down
72 let bob = (time * 1.5).sin() * 0.05;
73 frame
74 .mesh(chess_piece)
75 .transform(
76 Transform::new()
77 .position(Vec3::new(0.0, 1.3 + bob, 0.0))
78 .rotation(Quat::from_rotation_y(time * 0.2)),
79 )
80 .color(Color::rgb(0.9, 0.85, 0.7))
81 .draw();
82
83 // Some decorative elements around the scene
84 let decoration_color = Color::rgb(0.3, 0.25, 0.35);
85 for i in 0..4 {
86 let angle = (i as f32) * std::f32::consts::FRAC_PI_2 + time * 0.1;
87 let radius = 3.0;
88 let x = angle.cos() * radius;
89 let z = angle.sin() * radius;
90 let height = 0.3 + (time + i as f32).sin().abs() * 0.2;
91
92 frame
93 .mesh(cube)
94 .transform(
95 Transform::new()
96 .position(Vec3::new(x, height, z))
97 .scale(Vec3::new(0.4, height * 2.0, 0.4))
98 .rotation(Quat::from_rotation_y(time + i as f32)),
99 )
100 .color(decoration_color)
101 .draw();
102 }
103
104 // UI text
105 frame.text(10.0, 10.0, "STL Model Loading Demo");
106 frame.text_color(
107 10.0,
108 35.0,
109 "Drag mouse to orbit, scroll to zoom",
110 Color::rgb(0.6, 0.6, 0.6),
111 );
112 frame.text_color(
113 10.0,
114 55.0,
115 &format!("FPS: {:.0}", frame.fps()),
116 Color::rgb(0.5, 0.5, 0.5),
117 );
118 }
119 },
120 );
121}examples/black_hole.rs (line 33)
4fn main() {
5 run_with_config(AppConfig::new().title("Black Hole"), |ctx| {
6 // Setup: configure render pipeline and load assets
7 ctx.default_font(16.0);
8
9 // Hot-reloadable shaders - edit the files and see changes live!
10 ctx.hot_effect_world("examples/shaders/black_hole.wgsl");
11
12 // Enable 3D mesh rendering (after background, before post-process)
13 ctx.enable_mesh_rendering();
14
15 // Add post-processing after mesh rendering
16 ctx.hot_post_process_world("examples/shaders/gravitational_lensing.wgsl");
17
18 // Create a cube mesh
19 let cube = ctx.mesh_cube();
20
21 // Create a procedural blocky noise texture (16x16 for that pixelated look)
22 let texture = ctx.texture_blocky_noise(16, 42);
23
24 // Create a 2D sprite for the UI (same procedural texture, rendered in 2D layer)
25 let sprite = ctx.sprite_blocky_noise(32, 123);
26
27 // Camera: auto-rotate or interactive orbit
28 let mut orbit = OrbitCamera::new()
29 .target(Vec3::ZERO)
30 .distance(32.0)
31 .elevation(0.3)
32 .fov(80.0)
33 .mode(OrbitMode::Interactive);
34
35 // State for toggling cube visibility
36 let mut cube_visible = true;
37
38 // Frame loop
39 move |frame| {
40 orbit.update(frame.input, frame.dt);
41 frame.set_camera(orbit.camera());
42
43 // Animate the cubes: hover above the black hole and rotate
44 let hover_height = 8.0 + (frame.time * 0.5).sin() * 0.5;
45
46 // Draw a 3x3 grid of textured cubes (if visible)
47 if cube_visible {
48 let spacing = 12.0;
49 for row in 0..3 {
50 for col in 0..3 {
51 let idx = row * 3 + col;
52 // Offset rotation per cube for visual variety
53 let phase = idx as f32 * 0.3;
54 let rotation = Quat::from_euler(
55 glam::EulerRot::YXZ,
56 frame.time * 0.7 + phase,
57 frame.time * 0.5 + phase,
58 frame.time * 0.3 + phase,
59 );
60
61 let x = (col as f32 - 1.0) * spacing;
62 let z = (row as f32 - 1.0) * spacing;
63
64 frame
65 .mesh(cube)
66 .transform(
67 Transform::new()
68 .position(Vec3::new(x, hover_height, z))
69 .rotation(rotation)
70 .uniform_scale(3.0),
71 )
72 .texture(texture)
73 .draw();
74 }
75 }
76 }
77
78 // Draw debug overlay
79 let y = frame.panel_titled(10.0, 10.0, 300.0, 120.0, "Debug Overlay");
80 frame.text(18.0, y + 8.0, &format!("FPS: {:.1}", frame.fps()));
81 frame.text_color(
82 18.0,
83 y + 28.0,
84 &format!("Time: {:.1}s", frame.time),
85 Color::rgba(0.7, 0.7, 0.7, 1.0),
86 );
87
88 // Draw the 2D sprite in the bottom-right corner (clickable toggle for cube visibility)
89 let sprite_x = frame.width() as f32 - 80.0;
90 let sprite_y = frame.height() as f32 - 80.0;
91 let sprite_w = 64.0;
92 let sprite_h = 64.0;
93
94 // Check for click on sprite
95 if frame.input.mouse_pressed(MouseButton::Left) {
96 let mouse_pos = frame.input.mouse_position();
97 if mouse_pos.x >= sprite_x
98 && mouse_pos.x <= sprite_x + sprite_w
99 && mouse_pos.y >= sprite_y
100 && mouse_pos.y <= sprite_y + sprite_h
101 {
102 cube_visible = !cube_visible;
103 }
104 }
105
106 // Draw sprite with tint based on cube visibility
107 let tint = if cube_visible {
108 Color::WHITE
109 } else {
110 Color::rgba(0.4, 0.4, 0.4, 1.0) // Grayed out when cube is hidden
111 };
112 frame.sprite_scaled_tinted(sprite, sprite_x, sprite_y, sprite_w, sprite_h, tint);
113
114 // Draw label above the sprite
115 let label = if cube_visible {
116 "Cubes: Shown"
117 } else {
118 "Cubes: Hidden"
119 };
120 frame.text(sprite_x - 40.0, sprite_y - 20.0, label);
121 }
122 });
123}examples/scenes.rs (line 47)
18fn main() {
19 run_with_scenes_config(
20 AppConfig::new()
21 .title("Scene Management Demo")
22 .size(1280, 720),
23 |ctx| {
24 ctx.default_font(18.0);
25
26 // Shared assets - available to all scenes
27 let cube = ctx.mesh_cube();
28 let plane = ctx.mesh_plane(30.0);
29
30 // Track current transition type
31 let transition_type = std::rc::Rc::new(std::cell::RefCell::new(TransitionType::Fade));
32 let transition_type_1 = transition_type.clone();
33 let transition_type_2 = transition_type.clone();
34
35 // =========================================================
36 // Scene 1: External view (ship floating in space)
37 // =========================================================
38 ctx.scene("external", |scene| {
39 scene.background_color(Color::rgb(0.02, 0.02, 0.05));
40 scene.enable_mesh_rendering();
41
42 let mut orbit = OrbitCamera::new()
43 .target(Vec3::ZERO)
44 .distance(8.0)
45 .elevation(0.3)
46 .fov(75.0)
47 .mode(OrbitMode::AutoRotate { speed: 0.2 });
48
49 let cube = cube;
50 let transition_type = transition_type_1;
51
52 move |frame| {
53 orbit.update(frame.input, frame.dt);
54 frame.set_camera(orbit.camera());
55
56 // Update transition type based on key presses
57 if frame.input.key_pressed(KeyCode::Digit1) {
58 *transition_type.borrow_mut() = TransitionType::Instant;
59 }
60 if frame.input.key_pressed(KeyCode::Digit2) {
61 *transition_type.borrow_mut() = TransitionType::Fade;
62 }
63 if frame.input.key_pressed(KeyCode::Digit3) {
64 *transition_type.borrow_mut() = TransitionType::Crossfade;
65 }
66
67 // Capture time before building meshes
68 let time = frame.time;
69 let ship_rotation = Quat::from_rotation_y(time * 0.1);
70
71 // Draw a simple "ship" - main body
72 frame
73 .mesh(cube)
74 .transform(
75 Transform::new()
76 .scale(Vec3::new(2.0, 0.5, 3.0))
77 .rotation(ship_rotation),
78 )
79 .color(Color::rgb(0.4, 0.4, 0.5))
80 .draw();
81
82 // Wings
83 for x in [-1.5, 1.5] {
84 frame
85 .mesh(cube)
86 .transform(
87 Transform::new()
88 .position(Vec3::new(x, 0.0, 0.0))
89 .scale(Vec3::new(1.5, 0.1, 1.0))
90 .rotation(ship_rotation),
91 )
92 .color(Color::rgb(0.3, 0.3, 0.4))
93 .draw();
94 }
95
96 // Cockpit (blue tinted)
97 frame
98 .mesh(cube)
99 .transform(
100 Transform::new()
101 .position(Vec3::new(0.0, 0.3, 0.8))
102 .scale(Vec3::new(0.6, 0.3, 0.4))
103 .rotation(ship_rotation),
104 )
105 .color(Color::rgb(0.2, 0.3, 0.5))
106 .draw();
107
108 // Engine glow
109 frame
110 .mesh(cube)
111 .transform(
112 Transform::new()
113 .position(Vec3::new(0.0, 0.0, -1.6))
114 .scale(Vec3::new(0.4, 0.3, 0.2))
115 .rotation(ship_rotation),
116 )
117 .color(Color::rgb(0.8, 0.4, 0.2))
118 .draw();
119
120 // Some "stars" (small cubes in the distance)
121 let star_positions = [
122 Vec3::new(10.0, 5.0, -15.0),
123 Vec3::new(-12.0, 8.0, -20.0),
124 Vec3::new(8.0, -3.0, -18.0),
125 Vec3::new(-6.0, 10.0, -25.0),
126 Vec3::new(15.0, -5.0, -22.0),
127 ];
128 for pos in star_positions {
129 frame
130 .mesh(cube)
131 .transform(Transform::new().position(pos).scale(Vec3::splat(0.1)))
132 .color(Color::rgb(0.9, 0.9, 1.0))
133 .draw();
134 }
135
136 // UI
137 frame.text(10.0, 10.0, "EXTERNAL VIEW");
138 frame.text(10.0, 35.0, "Press ENTER to enter cockpit");
139 frame.text_color(
140 10.0,
141 60.0,
142 &format!(
143 "Transition: {} (1-3 to change)",
144 transition_type.borrow().name()
145 ),
146 Color::rgb(0.6, 0.6, 0.6),
147 );
148
149 // Switch to cockpit on Enter
150 if frame.input.key_pressed(KeyCode::Enter) {
151 let transition = transition_type.borrow().to_transition();
152 frame.switch_to_with("cockpit", transition);
153 }
154 }
155 });
156
157 // =========================================================
158 // Scene 2: Cockpit interior view
159 // =========================================================
160 ctx.scene("cockpit", |scene| {
161 scene.background_color(Color::rgb(0.05, 0.03, 0.03));
162 scene.enable_mesh_rendering();
163
164 let cube = cube;
165 let plane = plane;
166 let transition_type = transition_type_2;
167 let mut look_yaw = 0.0_f32;
168
169 move |frame| {
170 // Simple look around with arrow keys
171 if frame.input.key_down(KeyCode::ArrowLeft) {
172 look_yaw += 1.5 * frame.dt;
173 }
174 if frame.input.key_down(KeyCode::ArrowRight) {
175 look_yaw -= 1.5 * frame.dt;
176 }
177
178 // Build camera with current look direction
179 let camera = hoplite::Camera::new()
180 .at(Vec3::new(0.0, 1.0, 0.0))
181 .looking_at(Vec3::new(look_yaw.sin(), 1.0, -look_yaw.cos()))
182 .with_fov(90.0);
183 frame.set_camera(camera);
184
185 // Update transition type based on key presses
186 if frame.input.key_pressed(KeyCode::Digit1) {
187 *transition_type.borrow_mut() = TransitionType::Instant;
188 }
189 if frame.input.key_pressed(KeyCode::Digit2) {
190 *transition_type.borrow_mut() = TransitionType::Fade;
191 }
192 if frame.input.key_pressed(KeyCode::Digit3) {
193 *transition_type.borrow_mut() = TransitionType::Crossfade;
194 }
195
196 // Capture time for animations
197 let time = frame.time;
198
199 // Draw cockpit interior
200 // Floor
201 frame
202 .mesh(plane)
203 .transform(Transform::new().scale(Vec3::splat(0.3)))
204 .color(Color::rgb(0.15, 0.12, 0.12))
205 .draw();
206
207 // Console in front
208 frame
209 .mesh(cube)
210 .transform(
211 Transform::new()
212 .position(Vec3::new(0.0, 0.6, -1.5))
213 .scale(Vec3::new(2.0, 0.8, 0.3)),
214 )
215 .color(Color::rgb(0.2, 0.2, 0.25))
216 .draw();
217
218 // Display screens on console
219 let screen_positions = [-0.6, 0.0, 0.6];
220 for (i, x) in screen_positions.iter().enumerate() {
221 let glow = (time * 2.0 + i as f32).sin() * 0.1 + 0.5;
222 frame
223 .mesh(cube)
224 .transform(
225 Transform::new()
226 .position(Vec3::new(*x, 0.9, -1.3))
227 .scale(Vec3::new(0.4, 0.3, 0.05)),
228 )
229 .color(Color::rgb(0.1, glow * 0.5, glow))
230 .draw();
231 }
232
233 // Side panels
234 for x in [-1.2, 1.2] {
235 frame
236 .mesh(cube)
237 .transform(
238 Transform::new()
239 .position(Vec3::new(x, 1.0, -0.5))
240 .scale(Vec3::new(0.1, 1.5, 2.0)),
241 )
242 .color(Color::rgb(0.12, 0.1, 0.1))
243 .draw();
244 }
245
246 // Ceiling
247 frame
248 .mesh(cube)
249 .transform(
250 Transform::new()
251 .position(Vec3::new(0.0, 2.2, -0.5))
252 .scale(Vec3::new(2.5, 0.1, 3.0)),
253 )
254 .color(Color::rgb(0.08, 0.08, 0.1))
255 .draw();
256
257 // Window (brighter area showing "space")
258 frame
259 .mesh(cube)
260 .transform(
261 Transform::new()
262 .position(Vec3::new(0.0, 1.5, -2.0))
263 .scale(Vec3::new(1.8, 0.8, 0.02)),
264 )
265 .color(Color::rgb(0.02, 0.02, 0.08))
266 .draw();
267
268 // Blinking warning lights
269 let blink = if (time * 3.0).sin() > 0.0 { 0.8 } else { 0.2 };
270 for x in [-0.9, 0.9] {
271 frame
272 .mesh(cube)
273 .transform(
274 Transform::new()
275 .position(Vec3::new(x, 1.8, -1.4))
276 .scale(Vec3::splat(0.08)),
277 )
278 .color(Color::rgb(blink, blink * 0.2, 0.0))
279 .draw();
280 }
281
282 // UI
283 frame.text(10.0, 10.0, "COCKPIT VIEW");
284 frame.text(10.0, 35.0, "Arrow keys to look around");
285 frame.text(10.0, 60.0, "Press ESCAPE for external view");
286 frame.text_color(
287 10.0,
288 85.0,
289 &format!(
290 "Transition: {} (1-3 to change)",
291 transition_type.borrow().name()
292 ),
293 Color::rgb(0.6, 0.6, 0.6),
294 );
295
296 // Switch back to external on Escape
297 if frame.input.key_pressed(KeyCode::Escape) {
298 let transition = transition_type.borrow().to_transition();
299 frame.switch_to_with("external", transition);
300 }
301 }
302 });
303
304 // Start in external view
305 ctx.start_scene("external");
306 },
307 );
308}Sourcepub fn fov(self, fov_degrees: f32) -> Self
pub fn fov(self, fov_degrees: f32) -> Self
Set the field of view in degrees.
Examples found in repository?
examples/sphere.rs (line 13)
5fn main() {
6 run_with_config(AppConfig::new().title("Raymarched Sphere"), |ctx| {
7 ctx.hot_effect_world("examples/shaders/sphere.wgsl");
8
9 let mut orbit = OrbitCamera::new()
10 .target(Vec3::ZERO)
11 .distance(3.0)
12 .elevation(0.3)
13 .fov(90.0)
14 .mode(OrbitMode::AutoRotate { speed: 0.5 });
15
16 move |frame| {
17 orbit.update(frame.input, frame.dt);
18 frame.set_camera(orbit.camera());
19 }
20 });
21}More examples
examples/stl_loader.rs (line 39)
10fn main() {
11 run_with_config(
12 AppConfig::new().title("STL Loader Demo").size(1280, 720),
13 |ctx| {
14 ctx.default_font(18.0);
15 ctx.background_color(Color::rgb(0.08, 0.08, 0.12));
16 ctx.enable_mesh_rendering();
17
18 // Load the chess piece STL with the fluent API
19 // - centered() moves the bounding box center to origin
20 // - normalized() scales to fit in a unit cube
21 // - scaled() then scales to desired size
22 let chess_piece = ctx
23 .load("examples/assets/models/chess.stl")
24 .centered()
25 .upright()
26 .normalized()
27 .scaled(2.0)
28 .unwrap();
29
30 // Create some primitive meshes for the scene
31 let plane = ctx.mesh_plane(10.0);
32 let cube = ctx.mesh_cube();
33
34 // Orbit camera for viewing the model
35 let mut orbit = OrbitCamera::new()
36 .target(Vec3::new(0.0, 1.0, 0.0))
37 .distance(5.0)
38 .elevation(0.4)
39 .fov(60.0)
40 .mode(OrbitMode::AutoRotate { speed: 0.3 });
41
42 let mut time = 0.0f32;
43
44 move |frame| {
45 time += frame.dt;
46
47 // Update camera
48 orbit.update(frame.input, frame.dt);
49 frame.set_camera(orbit.camera());
50
51 // Draw the floor
52 frame
53 .mesh(plane)
54 .transform(Transform::new())
55 .color(Color::rgb(0.15, 0.15, 0.18))
56 .draw();
57
58 // Draw the chess piece on a pedestal
59 // Pedestal base
60 frame
61 .mesh(cube)
62 .transform(
63 Transform::new()
64 .position(Vec3::new(0.0, 0.15, 0.0))
65 .scale(Vec3::new(1.5, 0.3, 1.5)),
66 )
67 .color(Color::rgb(0.2, 0.2, 0.25))
68 .draw();
69
70 // The chess piece - positioned on top of pedestal
71 // Slowly bobbing up and down
72 let bob = (time * 1.5).sin() * 0.05;
73 frame
74 .mesh(chess_piece)
75 .transform(
76 Transform::new()
77 .position(Vec3::new(0.0, 1.3 + bob, 0.0))
78 .rotation(Quat::from_rotation_y(time * 0.2)),
79 )
80 .color(Color::rgb(0.9, 0.85, 0.7))
81 .draw();
82
83 // Some decorative elements around the scene
84 let decoration_color = Color::rgb(0.3, 0.25, 0.35);
85 for i in 0..4 {
86 let angle = (i as f32) * std::f32::consts::FRAC_PI_2 + time * 0.1;
87 let radius = 3.0;
88 let x = angle.cos() * radius;
89 let z = angle.sin() * radius;
90 let height = 0.3 + (time + i as f32).sin().abs() * 0.2;
91
92 frame
93 .mesh(cube)
94 .transform(
95 Transform::new()
96 .position(Vec3::new(x, height, z))
97 .scale(Vec3::new(0.4, height * 2.0, 0.4))
98 .rotation(Quat::from_rotation_y(time + i as f32)),
99 )
100 .color(decoration_color)
101 .draw();
102 }
103
104 // UI text
105 frame.text(10.0, 10.0, "STL Model Loading Demo");
106 frame.text_color(
107 10.0,
108 35.0,
109 "Drag mouse to orbit, scroll to zoom",
110 Color::rgb(0.6, 0.6, 0.6),
111 );
112 frame.text_color(
113 10.0,
114 55.0,
115 &format!("FPS: {:.0}", frame.fps()),
116 Color::rgb(0.5, 0.5, 0.5),
117 );
118 }
119 },
120 );
121}examples/black_hole.rs (line 32)
4fn main() {
5 run_with_config(AppConfig::new().title("Black Hole"), |ctx| {
6 // Setup: configure render pipeline and load assets
7 ctx.default_font(16.0);
8
9 // Hot-reloadable shaders - edit the files and see changes live!
10 ctx.hot_effect_world("examples/shaders/black_hole.wgsl");
11
12 // Enable 3D mesh rendering (after background, before post-process)
13 ctx.enable_mesh_rendering();
14
15 // Add post-processing after mesh rendering
16 ctx.hot_post_process_world("examples/shaders/gravitational_lensing.wgsl");
17
18 // Create a cube mesh
19 let cube = ctx.mesh_cube();
20
21 // Create a procedural blocky noise texture (16x16 for that pixelated look)
22 let texture = ctx.texture_blocky_noise(16, 42);
23
24 // Create a 2D sprite for the UI (same procedural texture, rendered in 2D layer)
25 let sprite = ctx.sprite_blocky_noise(32, 123);
26
27 // Camera: auto-rotate or interactive orbit
28 let mut orbit = OrbitCamera::new()
29 .target(Vec3::ZERO)
30 .distance(32.0)
31 .elevation(0.3)
32 .fov(80.0)
33 .mode(OrbitMode::Interactive);
34
35 // State for toggling cube visibility
36 let mut cube_visible = true;
37
38 // Frame loop
39 move |frame| {
40 orbit.update(frame.input, frame.dt);
41 frame.set_camera(orbit.camera());
42
43 // Animate the cubes: hover above the black hole and rotate
44 let hover_height = 8.0 + (frame.time * 0.5).sin() * 0.5;
45
46 // Draw a 3x3 grid of textured cubes (if visible)
47 if cube_visible {
48 let spacing = 12.0;
49 for row in 0..3 {
50 for col in 0..3 {
51 let idx = row * 3 + col;
52 // Offset rotation per cube for visual variety
53 let phase = idx as f32 * 0.3;
54 let rotation = Quat::from_euler(
55 glam::EulerRot::YXZ,
56 frame.time * 0.7 + phase,
57 frame.time * 0.5 + phase,
58 frame.time * 0.3 + phase,
59 );
60
61 let x = (col as f32 - 1.0) * spacing;
62 let z = (row as f32 - 1.0) * spacing;
63
64 frame
65 .mesh(cube)
66 .transform(
67 Transform::new()
68 .position(Vec3::new(x, hover_height, z))
69 .rotation(rotation)
70 .uniform_scale(3.0),
71 )
72 .texture(texture)
73 .draw();
74 }
75 }
76 }
77
78 // Draw debug overlay
79 let y = frame.panel_titled(10.0, 10.0, 300.0, 120.0, "Debug Overlay");
80 frame.text(18.0, y + 8.0, &format!("FPS: {:.1}", frame.fps()));
81 frame.text_color(
82 18.0,
83 y + 28.0,
84 &format!("Time: {:.1}s", frame.time),
85 Color::rgba(0.7, 0.7, 0.7, 1.0),
86 );
87
88 // Draw the 2D sprite in the bottom-right corner (clickable toggle for cube visibility)
89 let sprite_x = frame.width() as f32 - 80.0;
90 let sprite_y = frame.height() as f32 - 80.0;
91 let sprite_w = 64.0;
92 let sprite_h = 64.0;
93
94 // Check for click on sprite
95 if frame.input.mouse_pressed(MouseButton::Left) {
96 let mouse_pos = frame.input.mouse_position();
97 if mouse_pos.x >= sprite_x
98 && mouse_pos.x <= sprite_x + sprite_w
99 && mouse_pos.y >= sprite_y
100 && mouse_pos.y <= sprite_y + sprite_h
101 {
102 cube_visible = !cube_visible;
103 }
104 }
105
106 // Draw sprite with tint based on cube visibility
107 let tint = if cube_visible {
108 Color::WHITE
109 } else {
110 Color::rgba(0.4, 0.4, 0.4, 1.0) // Grayed out when cube is hidden
111 };
112 frame.sprite_scaled_tinted(sprite, sprite_x, sprite_y, sprite_w, sprite_h, tint);
113
114 // Draw label above the sprite
115 let label = if cube_visible {
116 "Cubes: Shown"
117 } else {
118 "Cubes: Hidden"
119 };
120 frame.text(sprite_x - 40.0, sprite_y - 20.0, label);
121 }
122 });
123}examples/scenes.rs (line 46)
18fn main() {
19 run_with_scenes_config(
20 AppConfig::new()
21 .title("Scene Management Demo")
22 .size(1280, 720),
23 |ctx| {
24 ctx.default_font(18.0);
25
26 // Shared assets - available to all scenes
27 let cube = ctx.mesh_cube();
28 let plane = ctx.mesh_plane(30.0);
29
30 // Track current transition type
31 let transition_type = std::rc::Rc::new(std::cell::RefCell::new(TransitionType::Fade));
32 let transition_type_1 = transition_type.clone();
33 let transition_type_2 = transition_type.clone();
34
35 // =========================================================
36 // Scene 1: External view (ship floating in space)
37 // =========================================================
38 ctx.scene("external", |scene| {
39 scene.background_color(Color::rgb(0.02, 0.02, 0.05));
40 scene.enable_mesh_rendering();
41
42 let mut orbit = OrbitCamera::new()
43 .target(Vec3::ZERO)
44 .distance(8.0)
45 .elevation(0.3)
46 .fov(75.0)
47 .mode(OrbitMode::AutoRotate { speed: 0.2 });
48
49 let cube = cube;
50 let transition_type = transition_type_1;
51
52 move |frame| {
53 orbit.update(frame.input, frame.dt);
54 frame.set_camera(orbit.camera());
55
56 // Update transition type based on key presses
57 if frame.input.key_pressed(KeyCode::Digit1) {
58 *transition_type.borrow_mut() = TransitionType::Instant;
59 }
60 if frame.input.key_pressed(KeyCode::Digit2) {
61 *transition_type.borrow_mut() = TransitionType::Fade;
62 }
63 if frame.input.key_pressed(KeyCode::Digit3) {
64 *transition_type.borrow_mut() = TransitionType::Crossfade;
65 }
66
67 // Capture time before building meshes
68 let time = frame.time;
69 let ship_rotation = Quat::from_rotation_y(time * 0.1);
70
71 // Draw a simple "ship" - main body
72 frame
73 .mesh(cube)
74 .transform(
75 Transform::new()
76 .scale(Vec3::new(2.0, 0.5, 3.0))
77 .rotation(ship_rotation),
78 )
79 .color(Color::rgb(0.4, 0.4, 0.5))
80 .draw();
81
82 // Wings
83 for x in [-1.5, 1.5] {
84 frame
85 .mesh(cube)
86 .transform(
87 Transform::new()
88 .position(Vec3::new(x, 0.0, 0.0))
89 .scale(Vec3::new(1.5, 0.1, 1.0))
90 .rotation(ship_rotation),
91 )
92 .color(Color::rgb(0.3, 0.3, 0.4))
93 .draw();
94 }
95
96 // Cockpit (blue tinted)
97 frame
98 .mesh(cube)
99 .transform(
100 Transform::new()
101 .position(Vec3::new(0.0, 0.3, 0.8))
102 .scale(Vec3::new(0.6, 0.3, 0.4))
103 .rotation(ship_rotation),
104 )
105 .color(Color::rgb(0.2, 0.3, 0.5))
106 .draw();
107
108 // Engine glow
109 frame
110 .mesh(cube)
111 .transform(
112 Transform::new()
113 .position(Vec3::new(0.0, 0.0, -1.6))
114 .scale(Vec3::new(0.4, 0.3, 0.2))
115 .rotation(ship_rotation),
116 )
117 .color(Color::rgb(0.8, 0.4, 0.2))
118 .draw();
119
120 // Some "stars" (small cubes in the distance)
121 let star_positions = [
122 Vec3::new(10.0, 5.0, -15.0),
123 Vec3::new(-12.0, 8.0, -20.0),
124 Vec3::new(8.0, -3.0, -18.0),
125 Vec3::new(-6.0, 10.0, -25.0),
126 Vec3::new(15.0, -5.0, -22.0),
127 ];
128 for pos in star_positions {
129 frame
130 .mesh(cube)
131 .transform(Transform::new().position(pos).scale(Vec3::splat(0.1)))
132 .color(Color::rgb(0.9, 0.9, 1.0))
133 .draw();
134 }
135
136 // UI
137 frame.text(10.0, 10.0, "EXTERNAL VIEW");
138 frame.text(10.0, 35.0, "Press ENTER to enter cockpit");
139 frame.text_color(
140 10.0,
141 60.0,
142 &format!(
143 "Transition: {} (1-3 to change)",
144 transition_type.borrow().name()
145 ),
146 Color::rgb(0.6, 0.6, 0.6),
147 );
148
149 // Switch to cockpit on Enter
150 if frame.input.key_pressed(KeyCode::Enter) {
151 let transition = transition_type.borrow().to_transition();
152 frame.switch_to_with("cockpit", transition);
153 }
154 }
155 });
156
157 // =========================================================
158 // Scene 2: Cockpit interior view
159 // =========================================================
160 ctx.scene("cockpit", |scene| {
161 scene.background_color(Color::rgb(0.05, 0.03, 0.03));
162 scene.enable_mesh_rendering();
163
164 let cube = cube;
165 let plane = plane;
166 let transition_type = transition_type_2;
167 let mut look_yaw = 0.0_f32;
168
169 move |frame| {
170 // Simple look around with arrow keys
171 if frame.input.key_down(KeyCode::ArrowLeft) {
172 look_yaw += 1.5 * frame.dt;
173 }
174 if frame.input.key_down(KeyCode::ArrowRight) {
175 look_yaw -= 1.5 * frame.dt;
176 }
177
178 // Build camera with current look direction
179 let camera = hoplite::Camera::new()
180 .at(Vec3::new(0.0, 1.0, 0.0))
181 .looking_at(Vec3::new(look_yaw.sin(), 1.0, -look_yaw.cos()))
182 .with_fov(90.0);
183 frame.set_camera(camera);
184
185 // Update transition type based on key presses
186 if frame.input.key_pressed(KeyCode::Digit1) {
187 *transition_type.borrow_mut() = TransitionType::Instant;
188 }
189 if frame.input.key_pressed(KeyCode::Digit2) {
190 *transition_type.borrow_mut() = TransitionType::Fade;
191 }
192 if frame.input.key_pressed(KeyCode::Digit3) {
193 *transition_type.borrow_mut() = TransitionType::Crossfade;
194 }
195
196 // Capture time for animations
197 let time = frame.time;
198
199 // Draw cockpit interior
200 // Floor
201 frame
202 .mesh(plane)
203 .transform(Transform::new().scale(Vec3::splat(0.3)))
204 .color(Color::rgb(0.15, 0.12, 0.12))
205 .draw();
206
207 // Console in front
208 frame
209 .mesh(cube)
210 .transform(
211 Transform::new()
212 .position(Vec3::new(0.0, 0.6, -1.5))
213 .scale(Vec3::new(2.0, 0.8, 0.3)),
214 )
215 .color(Color::rgb(0.2, 0.2, 0.25))
216 .draw();
217
218 // Display screens on console
219 let screen_positions = [-0.6, 0.0, 0.6];
220 for (i, x) in screen_positions.iter().enumerate() {
221 let glow = (time * 2.0 + i as f32).sin() * 0.1 + 0.5;
222 frame
223 .mesh(cube)
224 .transform(
225 Transform::new()
226 .position(Vec3::new(*x, 0.9, -1.3))
227 .scale(Vec3::new(0.4, 0.3, 0.05)),
228 )
229 .color(Color::rgb(0.1, glow * 0.5, glow))
230 .draw();
231 }
232
233 // Side panels
234 for x in [-1.2, 1.2] {
235 frame
236 .mesh(cube)
237 .transform(
238 Transform::new()
239 .position(Vec3::new(x, 1.0, -0.5))
240 .scale(Vec3::new(0.1, 1.5, 2.0)),
241 )
242 .color(Color::rgb(0.12, 0.1, 0.1))
243 .draw();
244 }
245
246 // Ceiling
247 frame
248 .mesh(cube)
249 .transform(
250 Transform::new()
251 .position(Vec3::new(0.0, 2.2, -0.5))
252 .scale(Vec3::new(2.5, 0.1, 3.0)),
253 )
254 .color(Color::rgb(0.08, 0.08, 0.1))
255 .draw();
256
257 // Window (brighter area showing "space")
258 frame
259 .mesh(cube)
260 .transform(
261 Transform::new()
262 .position(Vec3::new(0.0, 1.5, -2.0))
263 .scale(Vec3::new(1.8, 0.8, 0.02)),
264 )
265 .color(Color::rgb(0.02, 0.02, 0.08))
266 .draw();
267
268 // Blinking warning lights
269 let blink = if (time * 3.0).sin() > 0.0 { 0.8 } else { 0.2 };
270 for x in [-0.9, 0.9] {
271 frame
272 .mesh(cube)
273 .transform(
274 Transform::new()
275 .position(Vec3::new(x, 1.8, -1.4))
276 .scale(Vec3::splat(0.08)),
277 )
278 .color(Color::rgb(blink, blink * 0.2, 0.0))
279 .draw();
280 }
281
282 // UI
283 frame.text(10.0, 10.0, "COCKPIT VIEW");
284 frame.text(10.0, 35.0, "Arrow keys to look around");
285 frame.text(10.0, 60.0, "Press ESCAPE for external view");
286 frame.text_color(
287 10.0,
288 85.0,
289 &format!(
290 "Transition: {} (1-3 to change)",
291 transition_type.borrow().name()
292 ),
293 Color::rgb(0.6, 0.6, 0.6),
294 );
295
296 // Switch back to external on Escape
297 if frame.input.key_pressed(KeyCode::Escape) {
298 let transition = transition_type.borrow().to_transition();
299 frame.switch_to_with("external", transition);
300 }
301 }
302 });
303
304 // Start in external view
305 ctx.start_scene("external");
306 },
307 );
308}Sourcepub fn azimuth(self, azimuth: f32) -> Self
pub fn azimuth(self, azimuth: f32) -> Self
Set the initial azimuth (horizontal angle) in radians.
Sourcepub fn elevation(self, elevation: f32) -> Self
pub fn elevation(self, elevation: f32) -> Self
Set the initial elevation (vertical angle) in radians.
Examples found in repository?
examples/sphere.rs (line 12)
5fn main() {
6 run_with_config(AppConfig::new().title("Raymarched Sphere"), |ctx| {
7 ctx.hot_effect_world("examples/shaders/sphere.wgsl");
8
9 let mut orbit = OrbitCamera::new()
10 .target(Vec3::ZERO)
11 .distance(3.0)
12 .elevation(0.3)
13 .fov(90.0)
14 .mode(OrbitMode::AutoRotate { speed: 0.5 });
15
16 move |frame| {
17 orbit.update(frame.input, frame.dt);
18 frame.set_camera(orbit.camera());
19 }
20 });
21}More examples
examples/stl_loader.rs (line 38)
10fn main() {
11 run_with_config(
12 AppConfig::new().title("STL Loader Demo").size(1280, 720),
13 |ctx| {
14 ctx.default_font(18.0);
15 ctx.background_color(Color::rgb(0.08, 0.08, 0.12));
16 ctx.enable_mesh_rendering();
17
18 // Load the chess piece STL with the fluent API
19 // - centered() moves the bounding box center to origin
20 // - normalized() scales to fit in a unit cube
21 // - scaled() then scales to desired size
22 let chess_piece = ctx
23 .load("examples/assets/models/chess.stl")
24 .centered()
25 .upright()
26 .normalized()
27 .scaled(2.0)
28 .unwrap();
29
30 // Create some primitive meshes for the scene
31 let plane = ctx.mesh_plane(10.0);
32 let cube = ctx.mesh_cube();
33
34 // Orbit camera for viewing the model
35 let mut orbit = OrbitCamera::new()
36 .target(Vec3::new(0.0, 1.0, 0.0))
37 .distance(5.0)
38 .elevation(0.4)
39 .fov(60.0)
40 .mode(OrbitMode::AutoRotate { speed: 0.3 });
41
42 let mut time = 0.0f32;
43
44 move |frame| {
45 time += frame.dt;
46
47 // Update camera
48 orbit.update(frame.input, frame.dt);
49 frame.set_camera(orbit.camera());
50
51 // Draw the floor
52 frame
53 .mesh(plane)
54 .transform(Transform::new())
55 .color(Color::rgb(0.15, 0.15, 0.18))
56 .draw();
57
58 // Draw the chess piece on a pedestal
59 // Pedestal base
60 frame
61 .mesh(cube)
62 .transform(
63 Transform::new()
64 .position(Vec3::new(0.0, 0.15, 0.0))
65 .scale(Vec3::new(1.5, 0.3, 1.5)),
66 )
67 .color(Color::rgb(0.2, 0.2, 0.25))
68 .draw();
69
70 // The chess piece - positioned on top of pedestal
71 // Slowly bobbing up and down
72 let bob = (time * 1.5).sin() * 0.05;
73 frame
74 .mesh(chess_piece)
75 .transform(
76 Transform::new()
77 .position(Vec3::new(0.0, 1.3 + bob, 0.0))
78 .rotation(Quat::from_rotation_y(time * 0.2)),
79 )
80 .color(Color::rgb(0.9, 0.85, 0.7))
81 .draw();
82
83 // Some decorative elements around the scene
84 let decoration_color = Color::rgb(0.3, 0.25, 0.35);
85 for i in 0..4 {
86 let angle = (i as f32) * std::f32::consts::FRAC_PI_2 + time * 0.1;
87 let radius = 3.0;
88 let x = angle.cos() * radius;
89 let z = angle.sin() * radius;
90 let height = 0.3 + (time + i as f32).sin().abs() * 0.2;
91
92 frame
93 .mesh(cube)
94 .transform(
95 Transform::new()
96 .position(Vec3::new(x, height, z))
97 .scale(Vec3::new(0.4, height * 2.0, 0.4))
98 .rotation(Quat::from_rotation_y(time + i as f32)),
99 )
100 .color(decoration_color)
101 .draw();
102 }
103
104 // UI text
105 frame.text(10.0, 10.0, "STL Model Loading Demo");
106 frame.text_color(
107 10.0,
108 35.0,
109 "Drag mouse to orbit, scroll to zoom",
110 Color::rgb(0.6, 0.6, 0.6),
111 );
112 frame.text_color(
113 10.0,
114 55.0,
115 &format!("FPS: {:.0}", frame.fps()),
116 Color::rgb(0.5, 0.5, 0.5),
117 );
118 }
119 },
120 );
121}examples/black_hole.rs (line 31)
4fn main() {
5 run_with_config(AppConfig::new().title("Black Hole"), |ctx| {
6 // Setup: configure render pipeline and load assets
7 ctx.default_font(16.0);
8
9 // Hot-reloadable shaders - edit the files and see changes live!
10 ctx.hot_effect_world("examples/shaders/black_hole.wgsl");
11
12 // Enable 3D mesh rendering (after background, before post-process)
13 ctx.enable_mesh_rendering();
14
15 // Add post-processing after mesh rendering
16 ctx.hot_post_process_world("examples/shaders/gravitational_lensing.wgsl");
17
18 // Create a cube mesh
19 let cube = ctx.mesh_cube();
20
21 // Create a procedural blocky noise texture (16x16 for that pixelated look)
22 let texture = ctx.texture_blocky_noise(16, 42);
23
24 // Create a 2D sprite for the UI (same procedural texture, rendered in 2D layer)
25 let sprite = ctx.sprite_blocky_noise(32, 123);
26
27 // Camera: auto-rotate or interactive orbit
28 let mut orbit = OrbitCamera::new()
29 .target(Vec3::ZERO)
30 .distance(32.0)
31 .elevation(0.3)
32 .fov(80.0)
33 .mode(OrbitMode::Interactive);
34
35 // State for toggling cube visibility
36 let mut cube_visible = true;
37
38 // Frame loop
39 move |frame| {
40 orbit.update(frame.input, frame.dt);
41 frame.set_camera(orbit.camera());
42
43 // Animate the cubes: hover above the black hole and rotate
44 let hover_height = 8.0 + (frame.time * 0.5).sin() * 0.5;
45
46 // Draw a 3x3 grid of textured cubes (if visible)
47 if cube_visible {
48 let spacing = 12.0;
49 for row in 0..3 {
50 for col in 0..3 {
51 let idx = row * 3 + col;
52 // Offset rotation per cube for visual variety
53 let phase = idx as f32 * 0.3;
54 let rotation = Quat::from_euler(
55 glam::EulerRot::YXZ,
56 frame.time * 0.7 + phase,
57 frame.time * 0.5 + phase,
58 frame.time * 0.3 + phase,
59 );
60
61 let x = (col as f32 - 1.0) * spacing;
62 let z = (row as f32 - 1.0) * spacing;
63
64 frame
65 .mesh(cube)
66 .transform(
67 Transform::new()
68 .position(Vec3::new(x, hover_height, z))
69 .rotation(rotation)
70 .uniform_scale(3.0),
71 )
72 .texture(texture)
73 .draw();
74 }
75 }
76 }
77
78 // Draw debug overlay
79 let y = frame.panel_titled(10.0, 10.0, 300.0, 120.0, "Debug Overlay");
80 frame.text(18.0, y + 8.0, &format!("FPS: {:.1}", frame.fps()));
81 frame.text_color(
82 18.0,
83 y + 28.0,
84 &format!("Time: {:.1}s", frame.time),
85 Color::rgba(0.7, 0.7, 0.7, 1.0),
86 );
87
88 // Draw the 2D sprite in the bottom-right corner (clickable toggle for cube visibility)
89 let sprite_x = frame.width() as f32 - 80.0;
90 let sprite_y = frame.height() as f32 - 80.0;
91 let sprite_w = 64.0;
92 let sprite_h = 64.0;
93
94 // Check for click on sprite
95 if frame.input.mouse_pressed(MouseButton::Left) {
96 let mouse_pos = frame.input.mouse_position();
97 if mouse_pos.x >= sprite_x
98 && mouse_pos.x <= sprite_x + sprite_w
99 && mouse_pos.y >= sprite_y
100 && mouse_pos.y <= sprite_y + sprite_h
101 {
102 cube_visible = !cube_visible;
103 }
104 }
105
106 // Draw sprite with tint based on cube visibility
107 let tint = if cube_visible {
108 Color::WHITE
109 } else {
110 Color::rgba(0.4, 0.4, 0.4, 1.0) // Grayed out when cube is hidden
111 };
112 frame.sprite_scaled_tinted(sprite, sprite_x, sprite_y, sprite_w, sprite_h, tint);
113
114 // Draw label above the sprite
115 let label = if cube_visible {
116 "Cubes: Shown"
117 } else {
118 "Cubes: Hidden"
119 };
120 frame.text(sprite_x - 40.0, sprite_y - 20.0, label);
121 }
122 });
123}examples/scenes.rs (line 45)
18fn main() {
19 run_with_scenes_config(
20 AppConfig::new()
21 .title("Scene Management Demo")
22 .size(1280, 720),
23 |ctx| {
24 ctx.default_font(18.0);
25
26 // Shared assets - available to all scenes
27 let cube = ctx.mesh_cube();
28 let plane = ctx.mesh_plane(30.0);
29
30 // Track current transition type
31 let transition_type = std::rc::Rc::new(std::cell::RefCell::new(TransitionType::Fade));
32 let transition_type_1 = transition_type.clone();
33 let transition_type_2 = transition_type.clone();
34
35 // =========================================================
36 // Scene 1: External view (ship floating in space)
37 // =========================================================
38 ctx.scene("external", |scene| {
39 scene.background_color(Color::rgb(0.02, 0.02, 0.05));
40 scene.enable_mesh_rendering();
41
42 let mut orbit = OrbitCamera::new()
43 .target(Vec3::ZERO)
44 .distance(8.0)
45 .elevation(0.3)
46 .fov(75.0)
47 .mode(OrbitMode::AutoRotate { speed: 0.2 });
48
49 let cube = cube;
50 let transition_type = transition_type_1;
51
52 move |frame| {
53 orbit.update(frame.input, frame.dt);
54 frame.set_camera(orbit.camera());
55
56 // Update transition type based on key presses
57 if frame.input.key_pressed(KeyCode::Digit1) {
58 *transition_type.borrow_mut() = TransitionType::Instant;
59 }
60 if frame.input.key_pressed(KeyCode::Digit2) {
61 *transition_type.borrow_mut() = TransitionType::Fade;
62 }
63 if frame.input.key_pressed(KeyCode::Digit3) {
64 *transition_type.borrow_mut() = TransitionType::Crossfade;
65 }
66
67 // Capture time before building meshes
68 let time = frame.time;
69 let ship_rotation = Quat::from_rotation_y(time * 0.1);
70
71 // Draw a simple "ship" - main body
72 frame
73 .mesh(cube)
74 .transform(
75 Transform::new()
76 .scale(Vec3::new(2.0, 0.5, 3.0))
77 .rotation(ship_rotation),
78 )
79 .color(Color::rgb(0.4, 0.4, 0.5))
80 .draw();
81
82 // Wings
83 for x in [-1.5, 1.5] {
84 frame
85 .mesh(cube)
86 .transform(
87 Transform::new()
88 .position(Vec3::new(x, 0.0, 0.0))
89 .scale(Vec3::new(1.5, 0.1, 1.0))
90 .rotation(ship_rotation),
91 )
92 .color(Color::rgb(0.3, 0.3, 0.4))
93 .draw();
94 }
95
96 // Cockpit (blue tinted)
97 frame
98 .mesh(cube)
99 .transform(
100 Transform::new()
101 .position(Vec3::new(0.0, 0.3, 0.8))
102 .scale(Vec3::new(0.6, 0.3, 0.4))
103 .rotation(ship_rotation),
104 )
105 .color(Color::rgb(0.2, 0.3, 0.5))
106 .draw();
107
108 // Engine glow
109 frame
110 .mesh(cube)
111 .transform(
112 Transform::new()
113 .position(Vec3::new(0.0, 0.0, -1.6))
114 .scale(Vec3::new(0.4, 0.3, 0.2))
115 .rotation(ship_rotation),
116 )
117 .color(Color::rgb(0.8, 0.4, 0.2))
118 .draw();
119
120 // Some "stars" (small cubes in the distance)
121 let star_positions = [
122 Vec3::new(10.0, 5.0, -15.0),
123 Vec3::new(-12.0, 8.0, -20.0),
124 Vec3::new(8.0, -3.0, -18.0),
125 Vec3::new(-6.0, 10.0, -25.0),
126 Vec3::new(15.0, -5.0, -22.0),
127 ];
128 for pos in star_positions {
129 frame
130 .mesh(cube)
131 .transform(Transform::new().position(pos).scale(Vec3::splat(0.1)))
132 .color(Color::rgb(0.9, 0.9, 1.0))
133 .draw();
134 }
135
136 // UI
137 frame.text(10.0, 10.0, "EXTERNAL VIEW");
138 frame.text(10.0, 35.0, "Press ENTER to enter cockpit");
139 frame.text_color(
140 10.0,
141 60.0,
142 &format!(
143 "Transition: {} (1-3 to change)",
144 transition_type.borrow().name()
145 ),
146 Color::rgb(0.6, 0.6, 0.6),
147 );
148
149 // Switch to cockpit on Enter
150 if frame.input.key_pressed(KeyCode::Enter) {
151 let transition = transition_type.borrow().to_transition();
152 frame.switch_to_with("cockpit", transition);
153 }
154 }
155 });
156
157 // =========================================================
158 // Scene 2: Cockpit interior view
159 // =========================================================
160 ctx.scene("cockpit", |scene| {
161 scene.background_color(Color::rgb(0.05, 0.03, 0.03));
162 scene.enable_mesh_rendering();
163
164 let cube = cube;
165 let plane = plane;
166 let transition_type = transition_type_2;
167 let mut look_yaw = 0.0_f32;
168
169 move |frame| {
170 // Simple look around with arrow keys
171 if frame.input.key_down(KeyCode::ArrowLeft) {
172 look_yaw += 1.5 * frame.dt;
173 }
174 if frame.input.key_down(KeyCode::ArrowRight) {
175 look_yaw -= 1.5 * frame.dt;
176 }
177
178 // Build camera with current look direction
179 let camera = hoplite::Camera::new()
180 .at(Vec3::new(0.0, 1.0, 0.0))
181 .looking_at(Vec3::new(look_yaw.sin(), 1.0, -look_yaw.cos()))
182 .with_fov(90.0);
183 frame.set_camera(camera);
184
185 // Update transition type based on key presses
186 if frame.input.key_pressed(KeyCode::Digit1) {
187 *transition_type.borrow_mut() = TransitionType::Instant;
188 }
189 if frame.input.key_pressed(KeyCode::Digit2) {
190 *transition_type.borrow_mut() = TransitionType::Fade;
191 }
192 if frame.input.key_pressed(KeyCode::Digit3) {
193 *transition_type.borrow_mut() = TransitionType::Crossfade;
194 }
195
196 // Capture time for animations
197 let time = frame.time;
198
199 // Draw cockpit interior
200 // Floor
201 frame
202 .mesh(plane)
203 .transform(Transform::new().scale(Vec3::splat(0.3)))
204 .color(Color::rgb(0.15, 0.12, 0.12))
205 .draw();
206
207 // Console in front
208 frame
209 .mesh(cube)
210 .transform(
211 Transform::new()
212 .position(Vec3::new(0.0, 0.6, -1.5))
213 .scale(Vec3::new(2.0, 0.8, 0.3)),
214 )
215 .color(Color::rgb(0.2, 0.2, 0.25))
216 .draw();
217
218 // Display screens on console
219 let screen_positions = [-0.6, 0.0, 0.6];
220 for (i, x) in screen_positions.iter().enumerate() {
221 let glow = (time * 2.0 + i as f32).sin() * 0.1 + 0.5;
222 frame
223 .mesh(cube)
224 .transform(
225 Transform::new()
226 .position(Vec3::new(*x, 0.9, -1.3))
227 .scale(Vec3::new(0.4, 0.3, 0.05)),
228 )
229 .color(Color::rgb(0.1, glow * 0.5, glow))
230 .draw();
231 }
232
233 // Side panels
234 for x in [-1.2, 1.2] {
235 frame
236 .mesh(cube)
237 .transform(
238 Transform::new()
239 .position(Vec3::new(x, 1.0, -0.5))
240 .scale(Vec3::new(0.1, 1.5, 2.0)),
241 )
242 .color(Color::rgb(0.12, 0.1, 0.1))
243 .draw();
244 }
245
246 // Ceiling
247 frame
248 .mesh(cube)
249 .transform(
250 Transform::new()
251 .position(Vec3::new(0.0, 2.2, -0.5))
252 .scale(Vec3::new(2.5, 0.1, 3.0)),
253 )
254 .color(Color::rgb(0.08, 0.08, 0.1))
255 .draw();
256
257 // Window (brighter area showing "space")
258 frame
259 .mesh(cube)
260 .transform(
261 Transform::new()
262 .position(Vec3::new(0.0, 1.5, -2.0))
263 .scale(Vec3::new(1.8, 0.8, 0.02)),
264 )
265 .color(Color::rgb(0.02, 0.02, 0.08))
266 .draw();
267
268 // Blinking warning lights
269 let blink = if (time * 3.0).sin() > 0.0 { 0.8 } else { 0.2 };
270 for x in [-0.9, 0.9] {
271 frame
272 .mesh(cube)
273 .transform(
274 Transform::new()
275 .position(Vec3::new(x, 1.8, -1.4))
276 .scale(Vec3::splat(0.08)),
277 )
278 .color(Color::rgb(blink, blink * 0.2, 0.0))
279 .draw();
280 }
281
282 // UI
283 frame.text(10.0, 10.0, "COCKPIT VIEW");
284 frame.text(10.0, 35.0, "Arrow keys to look around");
285 frame.text(10.0, 60.0, "Press ESCAPE for external view");
286 frame.text_color(
287 10.0,
288 85.0,
289 &format!(
290 "Transition: {} (1-3 to change)",
291 transition_type.borrow().name()
292 ),
293 Color::rgb(0.6, 0.6, 0.6),
294 );
295
296 // Switch back to external on Escape
297 if frame.input.key_pressed(KeyCode::Escape) {
298 let transition = transition_type.borrow().to_transition();
299 frame.switch_to_with("external", transition);
300 }
301 }
302 });
303
304 // Start in external view
305 ctx.start_scene("external");
306 },
307 );
308}Sourcepub fn sensitivity(self, sensitivity: f32) -> Self
pub fn sensitivity(self, sensitivity: f32) -> Self
Set mouse sensitivity for interactive mode.
Sourcepub fn zoom_sensitivity(self, sensitivity: f32) -> Self
pub fn zoom_sensitivity(self, sensitivity: f32) -> Self
Set scroll zoom sensitivity.
Sourcepub fn distance_limits(self, min: f32, max: f32) -> Self
pub fn distance_limits(self, min: f32, max: f32) -> Self
Set distance limits.
Sourcepub fn update(&mut self, input: &Input, dt: f32)
pub fn update(&mut self, input: &Input, dt: f32)
Update the camera based on input and delta time.
Examples found in repository?
examples/sphere.rs (line 17)
5fn main() {
6 run_with_config(AppConfig::new().title("Raymarched Sphere"), |ctx| {
7 ctx.hot_effect_world("examples/shaders/sphere.wgsl");
8
9 let mut orbit = OrbitCamera::new()
10 .target(Vec3::ZERO)
11 .distance(3.0)
12 .elevation(0.3)
13 .fov(90.0)
14 .mode(OrbitMode::AutoRotate { speed: 0.5 });
15
16 move |frame| {
17 orbit.update(frame.input, frame.dt);
18 frame.set_camera(orbit.camera());
19 }
20 });
21}More examples
examples/stl_loader.rs (line 48)
10fn main() {
11 run_with_config(
12 AppConfig::new().title("STL Loader Demo").size(1280, 720),
13 |ctx| {
14 ctx.default_font(18.0);
15 ctx.background_color(Color::rgb(0.08, 0.08, 0.12));
16 ctx.enable_mesh_rendering();
17
18 // Load the chess piece STL with the fluent API
19 // - centered() moves the bounding box center to origin
20 // - normalized() scales to fit in a unit cube
21 // - scaled() then scales to desired size
22 let chess_piece = ctx
23 .load("examples/assets/models/chess.stl")
24 .centered()
25 .upright()
26 .normalized()
27 .scaled(2.0)
28 .unwrap();
29
30 // Create some primitive meshes for the scene
31 let plane = ctx.mesh_plane(10.0);
32 let cube = ctx.mesh_cube();
33
34 // Orbit camera for viewing the model
35 let mut orbit = OrbitCamera::new()
36 .target(Vec3::new(0.0, 1.0, 0.0))
37 .distance(5.0)
38 .elevation(0.4)
39 .fov(60.0)
40 .mode(OrbitMode::AutoRotate { speed: 0.3 });
41
42 let mut time = 0.0f32;
43
44 move |frame| {
45 time += frame.dt;
46
47 // Update camera
48 orbit.update(frame.input, frame.dt);
49 frame.set_camera(orbit.camera());
50
51 // Draw the floor
52 frame
53 .mesh(plane)
54 .transform(Transform::new())
55 .color(Color::rgb(0.15, 0.15, 0.18))
56 .draw();
57
58 // Draw the chess piece on a pedestal
59 // Pedestal base
60 frame
61 .mesh(cube)
62 .transform(
63 Transform::new()
64 .position(Vec3::new(0.0, 0.15, 0.0))
65 .scale(Vec3::new(1.5, 0.3, 1.5)),
66 )
67 .color(Color::rgb(0.2, 0.2, 0.25))
68 .draw();
69
70 // The chess piece - positioned on top of pedestal
71 // Slowly bobbing up and down
72 let bob = (time * 1.5).sin() * 0.05;
73 frame
74 .mesh(chess_piece)
75 .transform(
76 Transform::new()
77 .position(Vec3::new(0.0, 1.3 + bob, 0.0))
78 .rotation(Quat::from_rotation_y(time * 0.2)),
79 )
80 .color(Color::rgb(0.9, 0.85, 0.7))
81 .draw();
82
83 // Some decorative elements around the scene
84 let decoration_color = Color::rgb(0.3, 0.25, 0.35);
85 for i in 0..4 {
86 let angle = (i as f32) * std::f32::consts::FRAC_PI_2 + time * 0.1;
87 let radius = 3.0;
88 let x = angle.cos() * radius;
89 let z = angle.sin() * radius;
90 let height = 0.3 + (time + i as f32).sin().abs() * 0.2;
91
92 frame
93 .mesh(cube)
94 .transform(
95 Transform::new()
96 .position(Vec3::new(x, height, z))
97 .scale(Vec3::new(0.4, height * 2.0, 0.4))
98 .rotation(Quat::from_rotation_y(time + i as f32)),
99 )
100 .color(decoration_color)
101 .draw();
102 }
103
104 // UI text
105 frame.text(10.0, 10.0, "STL Model Loading Demo");
106 frame.text_color(
107 10.0,
108 35.0,
109 "Drag mouse to orbit, scroll to zoom",
110 Color::rgb(0.6, 0.6, 0.6),
111 );
112 frame.text_color(
113 10.0,
114 55.0,
115 &format!("FPS: {:.0}", frame.fps()),
116 Color::rgb(0.5, 0.5, 0.5),
117 );
118 }
119 },
120 );
121}examples/black_hole.rs (line 40)
4fn main() {
5 run_with_config(AppConfig::new().title("Black Hole"), |ctx| {
6 // Setup: configure render pipeline and load assets
7 ctx.default_font(16.0);
8
9 // Hot-reloadable shaders - edit the files and see changes live!
10 ctx.hot_effect_world("examples/shaders/black_hole.wgsl");
11
12 // Enable 3D mesh rendering (after background, before post-process)
13 ctx.enable_mesh_rendering();
14
15 // Add post-processing after mesh rendering
16 ctx.hot_post_process_world("examples/shaders/gravitational_lensing.wgsl");
17
18 // Create a cube mesh
19 let cube = ctx.mesh_cube();
20
21 // Create a procedural blocky noise texture (16x16 for that pixelated look)
22 let texture = ctx.texture_blocky_noise(16, 42);
23
24 // Create a 2D sprite for the UI (same procedural texture, rendered in 2D layer)
25 let sprite = ctx.sprite_blocky_noise(32, 123);
26
27 // Camera: auto-rotate or interactive orbit
28 let mut orbit = OrbitCamera::new()
29 .target(Vec3::ZERO)
30 .distance(32.0)
31 .elevation(0.3)
32 .fov(80.0)
33 .mode(OrbitMode::Interactive);
34
35 // State for toggling cube visibility
36 let mut cube_visible = true;
37
38 // Frame loop
39 move |frame| {
40 orbit.update(frame.input, frame.dt);
41 frame.set_camera(orbit.camera());
42
43 // Animate the cubes: hover above the black hole and rotate
44 let hover_height = 8.0 + (frame.time * 0.5).sin() * 0.5;
45
46 // Draw a 3x3 grid of textured cubes (if visible)
47 if cube_visible {
48 let spacing = 12.0;
49 for row in 0..3 {
50 for col in 0..3 {
51 let idx = row * 3 + col;
52 // Offset rotation per cube for visual variety
53 let phase = idx as f32 * 0.3;
54 let rotation = Quat::from_euler(
55 glam::EulerRot::YXZ,
56 frame.time * 0.7 + phase,
57 frame.time * 0.5 + phase,
58 frame.time * 0.3 + phase,
59 );
60
61 let x = (col as f32 - 1.0) * spacing;
62 let z = (row as f32 - 1.0) * spacing;
63
64 frame
65 .mesh(cube)
66 .transform(
67 Transform::new()
68 .position(Vec3::new(x, hover_height, z))
69 .rotation(rotation)
70 .uniform_scale(3.0),
71 )
72 .texture(texture)
73 .draw();
74 }
75 }
76 }
77
78 // Draw debug overlay
79 let y = frame.panel_titled(10.0, 10.0, 300.0, 120.0, "Debug Overlay");
80 frame.text(18.0, y + 8.0, &format!("FPS: {:.1}", frame.fps()));
81 frame.text_color(
82 18.0,
83 y + 28.0,
84 &format!("Time: {:.1}s", frame.time),
85 Color::rgba(0.7, 0.7, 0.7, 1.0),
86 );
87
88 // Draw the 2D sprite in the bottom-right corner (clickable toggle for cube visibility)
89 let sprite_x = frame.width() as f32 - 80.0;
90 let sprite_y = frame.height() as f32 - 80.0;
91 let sprite_w = 64.0;
92 let sprite_h = 64.0;
93
94 // Check for click on sprite
95 if frame.input.mouse_pressed(MouseButton::Left) {
96 let mouse_pos = frame.input.mouse_position();
97 if mouse_pos.x >= sprite_x
98 && mouse_pos.x <= sprite_x + sprite_w
99 && mouse_pos.y >= sprite_y
100 && mouse_pos.y <= sprite_y + sprite_h
101 {
102 cube_visible = !cube_visible;
103 }
104 }
105
106 // Draw sprite with tint based on cube visibility
107 let tint = if cube_visible {
108 Color::WHITE
109 } else {
110 Color::rgba(0.4, 0.4, 0.4, 1.0) // Grayed out when cube is hidden
111 };
112 frame.sprite_scaled_tinted(sprite, sprite_x, sprite_y, sprite_w, sprite_h, tint);
113
114 // Draw label above the sprite
115 let label = if cube_visible {
116 "Cubes: Shown"
117 } else {
118 "Cubes: Hidden"
119 };
120 frame.text(sprite_x - 40.0, sprite_y - 20.0, label);
121 }
122 });
123}examples/scenes.rs (line 53)
18fn main() {
19 run_with_scenes_config(
20 AppConfig::new()
21 .title("Scene Management Demo")
22 .size(1280, 720),
23 |ctx| {
24 ctx.default_font(18.0);
25
26 // Shared assets - available to all scenes
27 let cube = ctx.mesh_cube();
28 let plane = ctx.mesh_plane(30.0);
29
30 // Track current transition type
31 let transition_type = std::rc::Rc::new(std::cell::RefCell::new(TransitionType::Fade));
32 let transition_type_1 = transition_type.clone();
33 let transition_type_2 = transition_type.clone();
34
35 // =========================================================
36 // Scene 1: External view (ship floating in space)
37 // =========================================================
38 ctx.scene("external", |scene| {
39 scene.background_color(Color::rgb(0.02, 0.02, 0.05));
40 scene.enable_mesh_rendering();
41
42 let mut orbit = OrbitCamera::new()
43 .target(Vec3::ZERO)
44 .distance(8.0)
45 .elevation(0.3)
46 .fov(75.0)
47 .mode(OrbitMode::AutoRotate { speed: 0.2 });
48
49 let cube = cube;
50 let transition_type = transition_type_1;
51
52 move |frame| {
53 orbit.update(frame.input, frame.dt);
54 frame.set_camera(orbit.camera());
55
56 // Update transition type based on key presses
57 if frame.input.key_pressed(KeyCode::Digit1) {
58 *transition_type.borrow_mut() = TransitionType::Instant;
59 }
60 if frame.input.key_pressed(KeyCode::Digit2) {
61 *transition_type.borrow_mut() = TransitionType::Fade;
62 }
63 if frame.input.key_pressed(KeyCode::Digit3) {
64 *transition_type.borrow_mut() = TransitionType::Crossfade;
65 }
66
67 // Capture time before building meshes
68 let time = frame.time;
69 let ship_rotation = Quat::from_rotation_y(time * 0.1);
70
71 // Draw a simple "ship" - main body
72 frame
73 .mesh(cube)
74 .transform(
75 Transform::new()
76 .scale(Vec3::new(2.0, 0.5, 3.0))
77 .rotation(ship_rotation),
78 )
79 .color(Color::rgb(0.4, 0.4, 0.5))
80 .draw();
81
82 // Wings
83 for x in [-1.5, 1.5] {
84 frame
85 .mesh(cube)
86 .transform(
87 Transform::new()
88 .position(Vec3::new(x, 0.0, 0.0))
89 .scale(Vec3::new(1.5, 0.1, 1.0))
90 .rotation(ship_rotation),
91 )
92 .color(Color::rgb(0.3, 0.3, 0.4))
93 .draw();
94 }
95
96 // Cockpit (blue tinted)
97 frame
98 .mesh(cube)
99 .transform(
100 Transform::new()
101 .position(Vec3::new(0.0, 0.3, 0.8))
102 .scale(Vec3::new(0.6, 0.3, 0.4))
103 .rotation(ship_rotation),
104 )
105 .color(Color::rgb(0.2, 0.3, 0.5))
106 .draw();
107
108 // Engine glow
109 frame
110 .mesh(cube)
111 .transform(
112 Transform::new()
113 .position(Vec3::new(0.0, 0.0, -1.6))
114 .scale(Vec3::new(0.4, 0.3, 0.2))
115 .rotation(ship_rotation),
116 )
117 .color(Color::rgb(0.8, 0.4, 0.2))
118 .draw();
119
120 // Some "stars" (small cubes in the distance)
121 let star_positions = [
122 Vec3::new(10.0, 5.0, -15.0),
123 Vec3::new(-12.0, 8.0, -20.0),
124 Vec3::new(8.0, -3.0, -18.0),
125 Vec3::new(-6.0, 10.0, -25.0),
126 Vec3::new(15.0, -5.0, -22.0),
127 ];
128 for pos in star_positions {
129 frame
130 .mesh(cube)
131 .transform(Transform::new().position(pos).scale(Vec3::splat(0.1)))
132 .color(Color::rgb(0.9, 0.9, 1.0))
133 .draw();
134 }
135
136 // UI
137 frame.text(10.0, 10.0, "EXTERNAL VIEW");
138 frame.text(10.0, 35.0, "Press ENTER to enter cockpit");
139 frame.text_color(
140 10.0,
141 60.0,
142 &format!(
143 "Transition: {} (1-3 to change)",
144 transition_type.borrow().name()
145 ),
146 Color::rgb(0.6, 0.6, 0.6),
147 );
148
149 // Switch to cockpit on Enter
150 if frame.input.key_pressed(KeyCode::Enter) {
151 let transition = transition_type.borrow().to_transition();
152 frame.switch_to_with("cockpit", transition);
153 }
154 }
155 });
156
157 // =========================================================
158 // Scene 2: Cockpit interior view
159 // =========================================================
160 ctx.scene("cockpit", |scene| {
161 scene.background_color(Color::rgb(0.05, 0.03, 0.03));
162 scene.enable_mesh_rendering();
163
164 let cube = cube;
165 let plane = plane;
166 let transition_type = transition_type_2;
167 let mut look_yaw = 0.0_f32;
168
169 move |frame| {
170 // Simple look around with arrow keys
171 if frame.input.key_down(KeyCode::ArrowLeft) {
172 look_yaw += 1.5 * frame.dt;
173 }
174 if frame.input.key_down(KeyCode::ArrowRight) {
175 look_yaw -= 1.5 * frame.dt;
176 }
177
178 // Build camera with current look direction
179 let camera = hoplite::Camera::new()
180 .at(Vec3::new(0.0, 1.0, 0.0))
181 .looking_at(Vec3::new(look_yaw.sin(), 1.0, -look_yaw.cos()))
182 .with_fov(90.0);
183 frame.set_camera(camera);
184
185 // Update transition type based on key presses
186 if frame.input.key_pressed(KeyCode::Digit1) {
187 *transition_type.borrow_mut() = TransitionType::Instant;
188 }
189 if frame.input.key_pressed(KeyCode::Digit2) {
190 *transition_type.borrow_mut() = TransitionType::Fade;
191 }
192 if frame.input.key_pressed(KeyCode::Digit3) {
193 *transition_type.borrow_mut() = TransitionType::Crossfade;
194 }
195
196 // Capture time for animations
197 let time = frame.time;
198
199 // Draw cockpit interior
200 // Floor
201 frame
202 .mesh(plane)
203 .transform(Transform::new().scale(Vec3::splat(0.3)))
204 .color(Color::rgb(0.15, 0.12, 0.12))
205 .draw();
206
207 // Console in front
208 frame
209 .mesh(cube)
210 .transform(
211 Transform::new()
212 .position(Vec3::new(0.0, 0.6, -1.5))
213 .scale(Vec3::new(2.0, 0.8, 0.3)),
214 )
215 .color(Color::rgb(0.2, 0.2, 0.25))
216 .draw();
217
218 // Display screens on console
219 let screen_positions = [-0.6, 0.0, 0.6];
220 for (i, x) in screen_positions.iter().enumerate() {
221 let glow = (time * 2.0 + i as f32).sin() * 0.1 + 0.5;
222 frame
223 .mesh(cube)
224 .transform(
225 Transform::new()
226 .position(Vec3::new(*x, 0.9, -1.3))
227 .scale(Vec3::new(0.4, 0.3, 0.05)),
228 )
229 .color(Color::rgb(0.1, glow * 0.5, glow))
230 .draw();
231 }
232
233 // Side panels
234 for x in [-1.2, 1.2] {
235 frame
236 .mesh(cube)
237 .transform(
238 Transform::new()
239 .position(Vec3::new(x, 1.0, -0.5))
240 .scale(Vec3::new(0.1, 1.5, 2.0)),
241 )
242 .color(Color::rgb(0.12, 0.1, 0.1))
243 .draw();
244 }
245
246 // Ceiling
247 frame
248 .mesh(cube)
249 .transform(
250 Transform::new()
251 .position(Vec3::new(0.0, 2.2, -0.5))
252 .scale(Vec3::new(2.5, 0.1, 3.0)),
253 )
254 .color(Color::rgb(0.08, 0.08, 0.1))
255 .draw();
256
257 // Window (brighter area showing "space")
258 frame
259 .mesh(cube)
260 .transform(
261 Transform::new()
262 .position(Vec3::new(0.0, 1.5, -2.0))
263 .scale(Vec3::new(1.8, 0.8, 0.02)),
264 )
265 .color(Color::rgb(0.02, 0.02, 0.08))
266 .draw();
267
268 // Blinking warning lights
269 let blink = if (time * 3.0).sin() > 0.0 { 0.8 } else { 0.2 };
270 for x in [-0.9, 0.9] {
271 frame
272 .mesh(cube)
273 .transform(
274 Transform::new()
275 .position(Vec3::new(x, 1.8, -1.4))
276 .scale(Vec3::splat(0.08)),
277 )
278 .color(Color::rgb(blink, blink * 0.2, 0.0))
279 .draw();
280 }
281
282 // UI
283 frame.text(10.0, 10.0, "COCKPIT VIEW");
284 frame.text(10.0, 35.0, "Arrow keys to look around");
285 frame.text(10.0, 60.0, "Press ESCAPE for external view");
286 frame.text_color(
287 10.0,
288 85.0,
289 &format!(
290 "Transition: {} (1-3 to change)",
291 transition_type.borrow().name()
292 ),
293 Color::rgb(0.6, 0.6, 0.6),
294 );
295
296 // Switch back to external on Escape
297 if frame.input.key_pressed(KeyCode::Escape) {
298 let transition = transition_type.borrow().to_transition();
299 frame.switch_to_with("external", transition);
300 }
301 }
302 });
303
304 // Start in external view
305 ctx.start_scene("external");
306 },
307 );
308}Sourcepub fn camera(&self) -> Camera
pub fn camera(&self) -> Camera
Get the current camera state.
Examples found in repository?
examples/sphere.rs (line 18)
5fn main() {
6 run_with_config(AppConfig::new().title("Raymarched Sphere"), |ctx| {
7 ctx.hot_effect_world("examples/shaders/sphere.wgsl");
8
9 let mut orbit = OrbitCamera::new()
10 .target(Vec3::ZERO)
11 .distance(3.0)
12 .elevation(0.3)
13 .fov(90.0)
14 .mode(OrbitMode::AutoRotate { speed: 0.5 });
15
16 move |frame| {
17 orbit.update(frame.input, frame.dt);
18 frame.set_camera(orbit.camera());
19 }
20 });
21}More examples
examples/stl_loader.rs (line 49)
10fn main() {
11 run_with_config(
12 AppConfig::new().title("STL Loader Demo").size(1280, 720),
13 |ctx| {
14 ctx.default_font(18.0);
15 ctx.background_color(Color::rgb(0.08, 0.08, 0.12));
16 ctx.enable_mesh_rendering();
17
18 // Load the chess piece STL with the fluent API
19 // - centered() moves the bounding box center to origin
20 // - normalized() scales to fit in a unit cube
21 // - scaled() then scales to desired size
22 let chess_piece = ctx
23 .load("examples/assets/models/chess.stl")
24 .centered()
25 .upright()
26 .normalized()
27 .scaled(2.0)
28 .unwrap();
29
30 // Create some primitive meshes for the scene
31 let plane = ctx.mesh_plane(10.0);
32 let cube = ctx.mesh_cube();
33
34 // Orbit camera for viewing the model
35 let mut orbit = OrbitCamera::new()
36 .target(Vec3::new(0.0, 1.0, 0.0))
37 .distance(5.0)
38 .elevation(0.4)
39 .fov(60.0)
40 .mode(OrbitMode::AutoRotate { speed: 0.3 });
41
42 let mut time = 0.0f32;
43
44 move |frame| {
45 time += frame.dt;
46
47 // Update camera
48 orbit.update(frame.input, frame.dt);
49 frame.set_camera(orbit.camera());
50
51 // Draw the floor
52 frame
53 .mesh(plane)
54 .transform(Transform::new())
55 .color(Color::rgb(0.15, 0.15, 0.18))
56 .draw();
57
58 // Draw the chess piece on a pedestal
59 // Pedestal base
60 frame
61 .mesh(cube)
62 .transform(
63 Transform::new()
64 .position(Vec3::new(0.0, 0.15, 0.0))
65 .scale(Vec3::new(1.5, 0.3, 1.5)),
66 )
67 .color(Color::rgb(0.2, 0.2, 0.25))
68 .draw();
69
70 // The chess piece - positioned on top of pedestal
71 // Slowly bobbing up and down
72 let bob = (time * 1.5).sin() * 0.05;
73 frame
74 .mesh(chess_piece)
75 .transform(
76 Transform::new()
77 .position(Vec3::new(0.0, 1.3 + bob, 0.0))
78 .rotation(Quat::from_rotation_y(time * 0.2)),
79 )
80 .color(Color::rgb(0.9, 0.85, 0.7))
81 .draw();
82
83 // Some decorative elements around the scene
84 let decoration_color = Color::rgb(0.3, 0.25, 0.35);
85 for i in 0..4 {
86 let angle = (i as f32) * std::f32::consts::FRAC_PI_2 + time * 0.1;
87 let radius = 3.0;
88 let x = angle.cos() * radius;
89 let z = angle.sin() * radius;
90 let height = 0.3 + (time + i as f32).sin().abs() * 0.2;
91
92 frame
93 .mesh(cube)
94 .transform(
95 Transform::new()
96 .position(Vec3::new(x, height, z))
97 .scale(Vec3::new(0.4, height * 2.0, 0.4))
98 .rotation(Quat::from_rotation_y(time + i as f32)),
99 )
100 .color(decoration_color)
101 .draw();
102 }
103
104 // UI text
105 frame.text(10.0, 10.0, "STL Model Loading Demo");
106 frame.text_color(
107 10.0,
108 35.0,
109 "Drag mouse to orbit, scroll to zoom",
110 Color::rgb(0.6, 0.6, 0.6),
111 );
112 frame.text_color(
113 10.0,
114 55.0,
115 &format!("FPS: {:.0}", frame.fps()),
116 Color::rgb(0.5, 0.5, 0.5),
117 );
118 }
119 },
120 );
121}examples/black_hole.rs (line 41)
4fn main() {
5 run_with_config(AppConfig::new().title("Black Hole"), |ctx| {
6 // Setup: configure render pipeline and load assets
7 ctx.default_font(16.0);
8
9 // Hot-reloadable shaders - edit the files and see changes live!
10 ctx.hot_effect_world("examples/shaders/black_hole.wgsl");
11
12 // Enable 3D mesh rendering (after background, before post-process)
13 ctx.enable_mesh_rendering();
14
15 // Add post-processing after mesh rendering
16 ctx.hot_post_process_world("examples/shaders/gravitational_lensing.wgsl");
17
18 // Create a cube mesh
19 let cube = ctx.mesh_cube();
20
21 // Create a procedural blocky noise texture (16x16 for that pixelated look)
22 let texture = ctx.texture_blocky_noise(16, 42);
23
24 // Create a 2D sprite for the UI (same procedural texture, rendered in 2D layer)
25 let sprite = ctx.sprite_blocky_noise(32, 123);
26
27 // Camera: auto-rotate or interactive orbit
28 let mut orbit = OrbitCamera::new()
29 .target(Vec3::ZERO)
30 .distance(32.0)
31 .elevation(0.3)
32 .fov(80.0)
33 .mode(OrbitMode::Interactive);
34
35 // State for toggling cube visibility
36 let mut cube_visible = true;
37
38 // Frame loop
39 move |frame| {
40 orbit.update(frame.input, frame.dt);
41 frame.set_camera(orbit.camera());
42
43 // Animate the cubes: hover above the black hole and rotate
44 let hover_height = 8.0 + (frame.time * 0.5).sin() * 0.5;
45
46 // Draw a 3x3 grid of textured cubes (if visible)
47 if cube_visible {
48 let spacing = 12.0;
49 for row in 0..3 {
50 for col in 0..3 {
51 let idx = row * 3 + col;
52 // Offset rotation per cube for visual variety
53 let phase = idx as f32 * 0.3;
54 let rotation = Quat::from_euler(
55 glam::EulerRot::YXZ,
56 frame.time * 0.7 + phase,
57 frame.time * 0.5 + phase,
58 frame.time * 0.3 + phase,
59 );
60
61 let x = (col as f32 - 1.0) * spacing;
62 let z = (row as f32 - 1.0) * spacing;
63
64 frame
65 .mesh(cube)
66 .transform(
67 Transform::new()
68 .position(Vec3::new(x, hover_height, z))
69 .rotation(rotation)
70 .uniform_scale(3.0),
71 )
72 .texture(texture)
73 .draw();
74 }
75 }
76 }
77
78 // Draw debug overlay
79 let y = frame.panel_titled(10.0, 10.0, 300.0, 120.0, "Debug Overlay");
80 frame.text(18.0, y + 8.0, &format!("FPS: {:.1}", frame.fps()));
81 frame.text_color(
82 18.0,
83 y + 28.0,
84 &format!("Time: {:.1}s", frame.time),
85 Color::rgba(0.7, 0.7, 0.7, 1.0),
86 );
87
88 // Draw the 2D sprite in the bottom-right corner (clickable toggle for cube visibility)
89 let sprite_x = frame.width() as f32 - 80.0;
90 let sprite_y = frame.height() as f32 - 80.0;
91 let sprite_w = 64.0;
92 let sprite_h = 64.0;
93
94 // Check for click on sprite
95 if frame.input.mouse_pressed(MouseButton::Left) {
96 let mouse_pos = frame.input.mouse_position();
97 if mouse_pos.x >= sprite_x
98 && mouse_pos.x <= sprite_x + sprite_w
99 && mouse_pos.y >= sprite_y
100 && mouse_pos.y <= sprite_y + sprite_h
101 {
102 cube_visible = !cube_visible;
103 }
104 }
105
106 // Draw sprite with tint based on cube visibility
107 let tint = if cube_visible {
108 Color::WHITE
109 } else {
110 Color::rgba(0.4, 0.4, 0.4, 1.0) // Grayed out when cube is hidden
111 };
112 frame.sprite_scaled_tinted(sprite, sprite_x, sprite_y, sprite_w, sprite_h, tint);
113
114 // Draw label above the sprite
115 let label = if cube_visible {
116 "Cubes: Shown"
117 } else {
118 "Cubes: Hidden"
119 };
120 frame.text(sprite_x - 40.0, sprite_y - 20.0, label);
121 }
122 });
123}examples/scenes.rs (line 54)
18fn main() {
19 run_with_scenes_config(
20 AppConfig::new()
21 .title("Scene Management Demo")
22 .size(1280, 720),
23 |ctx| {
24 ctx.default_font(18.0);
25
26 // Shared assets - available to all scenes
27 let cube = ctx.mesh_cube();
28 let plane = ctx.mesh_plane(30.0);
29
30 // Track current transition type
31 let transition_type = std::rc::Rc::new(std::cell::RefCell::new(TransitionType::Fade));
32 let transition_type_1 = transition_type.clone();
33 let transition_type_2 = transition_type.clone();
34
35 // =========================================================
36 // Scene 1: External view (ship floating in space)
37 // =========================================================
38 ctx.scene("external", |scene| {
39 scene.background_color(Color::rgb(0.02, 0.02, 0.05));
40 scene.enable_mesh_rendering();
41
42 let mut orbit = OrbitCamera::new()
43 .target(Vec3::ZERO)
44 .distance(8.0)
45 .elevation(0.3)
46 .fov(75.0)
47 .mode(OrbitMode::AutoRotate { speed: 0.2 });
48
49 let cube = cube;
50 let transition_type = transition_type_1;
51
52 move |frame| {
53 orbit.update(frame.input, frame.dt);
54 frame.set_camera(orbit.camera());
55
56 // Update transition type based on key presses
57 if frame.input.key_pressed(KeyCode::Digit1) {
58 *transition_type.borrow_mut() = TransitionType::Instant;
59 }
60 if frame.input.key_pressed(KeyCode::Digit2) {
61 *transition_type.borrow_mut() = TransitionType::Fade;
62 }
63 if frame.input.key_pressed(KeyCode::Digit3) {
64 *transition_type.borrow_mut() = TransitionType::Crossfade;
65 }
66
67 // Capture time before building meshes
68 let time = frame.time;
69 let ship_rotation = Quat::from_rotation_y(time * 0.1);
70
71 // Draw a simple "ship" - main body
72 frame
73 .mesh(cube)
74 .transform(
75 Transform::new()
76 .scale(Vec3::new(2.0, 0.5, 3.0))
77 .rotation(ship_rotation),
78 )
79 .color(Color::rgb(0.4, 0.4, 0.5))
80 .draw();
81
82 // Wings
83 for x in [-1.5, 1.5] {
84 frame
85 .mesh(cube)
86 .transform(
87 Transform::new()
88 .position(Vec3::new(x, 0.0, 0.0))
89 .scale(Vec3::new(1.5, 0.1, 1.0))
90 .rotation(ship_rotation),
91 )
92 .color(Color::rgb(0.3, 0.3, 0.4))
93 .draw();
94 }
95
96 // Cockpit (blue tinted)
97 frame
98 .mesh(cube)
99 .transform(
100 Transform::new()
101 .position(Vec3::new(0.0, 0.3, 0.8))
102 .scale(Vec3::new(0.6, 0.3, 0.4))
103 .rotation(ship_rotation),
104 )
105 .color(Color::rgb(0.2, 0.3, 0.5))
106 .draw();
107
108 // Engine glow
109 frame
110 .mesh(cube)
111 .transform(
112 Transform::new()
113 .position(Vec3::new(0.0, 0.0, -1.6))
114 .scale(Vec3::new(0.4, 0.3, 0.2))
115 .rotation(ship_rotation),
116 )
117 .color(Color::rgb(0.8, 0.4, 0.2))
118 .draw();
119
120 // Some "stars" (small cubes in the distance)
121 let star_positions = [
122 Vec3::new(10.0, 5.0, -15.0),
123 Vec3::new(-12.0, 8.0, -20.0),
124 Vec3::new(8.0, -3.0, -18.0),
125 Vec3::new(-6.0, 10.0, -25.0),
126 Vec3::new(15.0, -5.0, -22.0),
127 ];
128 for pos in star_positions {
129 frame
130 .mesh(cube)
131 .transform(Transform::new().position(pos).scale(Vec3::splat(0.1)))
132 .color(Color::rgb(0.9, 0.9, 1.0))
133 .draw();
134 }
135
136 // UI
137 frame.text(10.0, 10.0, "EXTERNAL VIEW");
138 frame.text(10.0, 35.0, "Press ENTER to enter cockpit");
139 frame.text_color(
140 10.0,
141 60.0,
142 &format!(
143 "Transition: {} (1-3 to change)",
144 transition_type.borrow().name()
145 ),
146 Color::rgb(0.6, 0.6, 0.6),
147 );
148
149 // Switch to cockpit on Enter
150 if frame.input.key_pressed(KeyCode::Enter) {
151 let transition = transition_type.borrow().to_transition();
152 frame.switch_to_with("cockpit", transition);
153 }
154 }
155 });
156
157 // =========================================================
158 // Scene 2: Cockpit interior view
159 // =========================================================
160 ctx.scene("cockpit", |scene| {
161 scene.background_color(Color::rgb(0.05, 0.03, 0.03));
162 scene.enable_mesh_rendering();
163
164 let cube = cube;
165 let plane = plane;
166 let transition_type = transition_type_2;
167 let mut look_yaw = 0.0_f32;
168
169 move |frame| {
170 // Simple look around with arrow keys
171 if frame.input.key_down(KeyCode::ArrowLeft) {
172 look_yaw += 1.5 * frame.dt;
173 }
174 if frame.input.key_down(KeyCode::ArrowRight) {
175 look_yaw -= 1.5 * frame.dt;
176 }
177
178 // Build camera with current look direction
179 let camera = hoplite::Camera::new()
180 .at(Vec3::new(0.0, 1.0, 0.0))
181 .looking_at(Vec3::new(look_yaw.sin(), 1.0, -look_yaw.cos()))
182 .with_fov(90.0);
183 frame.set_camera(camera);
184
185 // Update transition type based on key presses
186 if frame.input.key_pressed(KeyCode::Digit1) {
187 *transition_type.borrow_mut() = TransitionType::Instant;
188 }
189 if frame.input.key_pressed(KeyCode::Digit2) {
190 *transition_type.borrow_mut() = TransitionType::Fade;
191 }
192 if frame.input.key_pressed(KeyCode::Digit3) {
193 *transition_type.borrow_mut() = TransitionType::Crossfade;
194 }
195
196 // Capture time for animations
197 let time = frame.time;
198
199 // Draw cockpit interior
200 // Floor
201 frame
202 .mesh(plane)
203 .transform(Transform::new().scale(Vec3::splat(0.3)))
204 .color(Color::rgb(0.15, 0.12, 0.12))
205 .draw();
206
207 // Console in front
208 frame
209 .mesh(cube)
210 .transform(
211 Transform::new()
212 .position(Vec3::new(0.0, 0.6, -1.5))
213 .scale(Vec3::new(2.0, 0.8, 0.3)),
214 )
215 .color(Color::rgb(0.2, 0.2, 0.25))
216 .draw();
217
218 // Display screens on console
219 let screen_positions = [-0.6, 0.0, 0.6];
220 for (i, x) in screen_positions.iter().enumerate() {
221 let glow = (time * 2.0 + i as f32).sin() * 0.1 + 0.5;
222 frame
223 .mesh(cube)
224 .transform(
225 Transform::new()
226 .position(Vec3::new(*x, 0.9, -1.3))
227 .scale(Vec3::new(0.4, 0.3, 0.05)),
228 )
229 .color(Color::rgb(0.1, glow * 0.5, glow))
230 .draw();
231 }
232
233 // Side panels
234 for x in [-1.2, 1.2] {
235 frame
236 .mesh(cube)
237 .transform(
238 Transform::new()
239 .position(Vec3::new(x, 1.0, -0.5))
240 .scale(Vec3::new(0.1, 1.5, 2.0)),
241 )
242 .color(Color::rgb(0.12, 0.1, 0.1))
243 .draw();
244 }
245
246 // Ceiling
247 frame
248 .mesh(cube)
249 .transform(
250 Transform::new()
251 .position(Vec3::new(0.0, 2.2, -0.5))
252 .scale(Vec3::new(2.5, 0.1, 3.0)),
253 )
254 .color(Color::rgb(0.08, 0.08, 0.1))
255 .draw();
256
257 // Window (brighter area showing "space")
258 frame
259 .mesh(cube)
260 .transform(
261 Transform::new()
262 .position(Vec3::new(0.0, 1.5, -2.0))
263 .scale(Vec3::new(1.8, 0.8, 0.02)),
264 )
265 .color(Color::rgb(0.02, 0.02, 0.08))
266 .draw();
267
268 // Blinking warning lights
269 let blink = if (time * 3.0).sin() > 0.0 { 0.8 } else { 0.2 };
270 for x in [-0.9, 0.9] {
271 frame
272 .mesh(cube)
273 .transform(
274 Transform::new()
275 .position(Vec3::new(x, 1.8, -1.4))
276 .scale(Vec3::splat(0.08)),
277 )
278 .color(Color::rgb(blink, blink * 0.2, 0.0))
279 .draw();
280 }
281
282 // UI
283 frame.text(10.0, 10.0, "COCKPIT VIEW");
284 frame.text(10.0, 35.0, "Arrow keys to look around");
285 frame.text(10.0, 60.0, "Press ESCAPE for external view");
286 frame.text_color(
287 10.0,
288 85.0,
289 &format!(
290 "Transition: {} (1-3 to change)",
291 transition_type.borrow().name()
292 ),
293 Color::rgb(0.6, 0.6, 0.6),
294 );
295
296 // Switch back to external on Escape
297 if frame.input.key_pressed(KeyCode::Escape) {
298 let transition = transition_type.borrow().to_transition();
299 frame.switch_to_with("external", transition);
300 }
301 }
302 });
303
304 // Start in external view
305 ctx.start_scene("external");
306 },
307 );
308}Trait Implementations§
Source§impl Clone for OrbitCamera
impl Clone for OrbitCamera
Source§fn clone(&self) -> OrbitCamera
fn clone(&self) -> OrbitCamera
Returns a duplicate of the value. Read more
1.0.0§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Debug for OrbitCamera
impl Debug for OrbitCamera
Auto Trait Implementations§
impl Freeze for OrbitCamera
impl RefUnwindSafe for OrbitCamera
impl Send for OrbitCamera
impl Sync for OrbitCamera
impl Unpin for OrbitCamera
impl UnwindSafe for OrbitCamera
Blanket Implementations§
§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§unsafe fn clone_to_uninit(&self, dest: *mut u8)
unsafe fn clone_to_uninit(&self, dest: *mut u8)
🔬This is a nightly-only experimental API. (
clone_to_uninit)Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Convert
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Convert
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Convert
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Convert
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
Read this value from the supplied reader. Same as
ReadEndian::read_from_little_endian().