stl_loader/
stl_loader.rs

1//! STL Model Loading Demo - demonstrates loading 3D models from STL files.
2//!
3//! This example shows the fluent geometry loading API:
4//! - Load STL files with `ctx.load("path.stl")`
5//! - Center, normalize, and scale models with chained methods
6//! - Orbit around the model with mouse drag or auto-rotate
7
8use hoplite::{AppConfig, Color, OrbitCamera, OrbitMode, Quat, Transform, Vec3, run_with_config};
9
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}