pub struct MeshLoader<'a> { /* private fields */ }Expand description
A fluent builder for loading geometry and registering it as a mesh.
Created by SetupContext::load or SetupContext::load_stl_bytes.
Chain transformation methods and call .unwrap() or .build() to get a MeshId.
§Example
use hoplite::*;
run(|ctx| {
ctx.enable_mesh_rendering();
// Load and transform in one fluent chain
let model = ctx.load("spaceship.stl")
.centered() // Center at origin
.normalized() // Fit in unit cube
.scaled(3.0) // Scale up
.unwrap();
move |frame| {
frame.draw_mesh(model, Transform::new(), Color::WHITE);
}
});Implementations§
Source§impl<'a> MeshLoader<'a>
impl<'a> MeshLoader<'a>
Sourcepub fn centered(self) -> Self
pub fn centered(self) -> Self
Center the geometry at the origin.
Moves the geometry so its bounding box center is at (0, 0, 0).
Examples found in repository?
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}Sourcepub fn normalized(self) -> Self
pub fn normalized(self) -> Self
Scale the geometry to fit within a unit cube.
The geometry will fit within -0.5 to 0.5 on all axes, preserving aspect ratio.
Examples found in repository?
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}Sourcepub fn scaled(self, factor: f32) -> Self
pub fn scaled(self, factor: f32) -> Self
Apply a uniform scale factor.
Examples found in repository?
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}Sourcepub fn translated(self, offset: Vec3) -> Self
pub fn translated(self, offset: Vec3) -> Self
Translate the geometry by an offset.
Sourcepub fn smooth_normals(self) -> Self
pub fn smooth_normals(self) -> Self
Recalculate smooth vertex normals.
Computes normals by averaging face normals at each vertex. Useful for STL files which only store face normals.
Sourcepub fn upright(self) -> Self
pub fn upright(self) -> Self
Reorient the geometry from Z-up to Y-up.
Many 3D modeling tools (Blender, etc.) export with Z as the up axis, while game engines typically use Y-up. This applies a -90 degree rotation around the X axis to convert between them.
Examples found in repository?
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}Sourcepub fn rotated_by(self, rotation: Quat) -> Self
pub fn rotated_by(self, rotation: Quat) -> Self
Rotate the geometry by a custom quaternion.
Sourcepub fn build(self) -> Result<MeshId, GeometryError>
pub fn build(self) -> Result<MeshId, GeometryError>
Build the mesh and register it, returning the MeshId.
Returns an error if loading or parsing failed.
Sourcepub fn unwrap(self) -> MeshId
pub fn unwrap(self) -> MeshId
Build the mesh and register it, panicking on error.
This is the most common way to finalize loading.
§Panics
Panics if the geometry could not be loaded.
Examples found in repository?
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}Auto Trait Implementations§
impl<'a> Freeze for MeshLoader<'a>
impl<'a> !RefUnwindSafe for MeshLoader<'a>
impl<'a> !Send for MeshLoader<'a>
impl<'a> !Sync for MeshLoader<'a>
impl<'a> Unpin for MeshLoader<'a>
impl<'a> !UnwindSafe for MeshLoader<'a>
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
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>
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>
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)
&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)
&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> 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>
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>
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 more