pub struct Renderable {
pub mesh: CpuMeshHandle,
pub base_mesh: CpuMeshHandle,
pub material: MaterialHandle,
}Expand description
Renderable component: references renderer-managed resources. Vulkan-minded: material -> pipeline/layout + descriptors.
The mesh here is a CPU-side asset handle. RenderAssets stores the actual CpuMesh
and uploads it to the renderer on demand.
Fields§
§mesh: CpuMeshHandleThe mesh actually used for rendering.
base_mesh: CpuMeshHandleThe “base” mesh this renderable was derived from.
For UV-baked variants (e.g. text glyphs), mesh is a dynamically-registered clone, while
base_mesh stays as the original (typically CpuMeshHandle::QUAD_2D).
For normal renderables, base_mesh == mesh.
material: MaterialHandleImplementations§
Source§impl Renderable
impl Renderable
Sourcepub fn new(mesh: CpuMeshHandle, material: MaterialHandle) -> Self
pub fn new(mesh: CpuMeshHandle, material: MaterialHandle) -> Self
Examples found in repository?
examples/simple-demo.rs (line 40)
6fn build_demo_scene_7_shapes(universe: &mut engine::Universe) {
7 use engine::ecs::component::{
8 Camera3DComponent, ColorComponent, EmissiveComponent, GLTFComponent, InputComponent,
9 InputTransformModeComponent, PointLightComponent, RenderableComponent, TextureComponent,
10 TransformComponent,
11 };
12 use engine::graphics::BuiltinMeshType;
13 use engine::graphics::primitives::MaterialHandle;
14
15 // Built-in CPU meshes are pre-registered; just fetch stable handles.
16 let tri_mesh = universe.render_assets.get_mesh(BuiltinMeshType::Triangle2D);
17 let square_mesh = universe.render_assets.get_mesh(BuiltinMeshType::Quad2D);
18 let tetra_mesh = universe
19 .render_assets
20 .get_mesh(BuiltinMeshType::Tetrahedron);
21
22 fn spawn(
23 universe: &mut engine::Universe,
24 mesh: engine::graphics::primitives::CpuMeshHandle,
25 x: f32,
26 y: f32,
27 s: f32,
28 r: f32,
29 color: [f32; 4],
30 input_driven: bool,
31 emissive: bool,
32 ) -> engine::ecs::ComponentId {
33 let transform = universe.world.add_component(
34 TransformComponent::new()
35 .with_position(x, y, 0.0)
36 .with_scale(s, s, 1.0)
37 .with_rotation_euler(0.0, 0.0, r),
38 );
39 let renderable = universe.world.add_component(RenderableComponent::new(
40 engine::graphics::primitives::Renderable::new(mesh, MaterialHandle::TOON_MESH),
41 ));
42 let color_c = universe.world.add_component(ColorComponent { rgba: color });
43
44 if emissive {
45 let emissive_c = universe.world.add_component(EmissiveComponent::on());
46 let _ = universe.attach(renderable, emissive_c);
47 }
48
49 // Topology: (optional Input) -> Transform -> Renderable
50 let _ = universe.attach(transform, renderable);
51 let _ = universe.attach(renderable, color_c);
52
53 if input_driven {
54 let input = universe
55 .world
56 .add_component(InputComponent::new().with_speed(0.5));
57 let _ = universe.attach(input, transform);
58 universe.add(input);
59 } else {
60 universe.add(transform);
61 }
62
63 transform
64 }
65
66 fn spawn_3d(
67 universe: &mut engine::Universe,
68 mesh: engine::graphics::primitives::CpuMeshHandle,
69 x: f32,
70 y: f32,
71 z: f32,
72 s: f32,
73 rx: f32,
74 ry: f32,
75 rz: f32,
76 color: [f32; 4],
77 ) -> engine::ecs::ComponentId {
78 let transform = universe.world.add_component(
79 TransformComponent::new()
80 .with_position(x, y, z)
81 .with_scale(s, s, s)
82 .with_rotation_euler(rx, ry, rz),
83 );
84 let renderable = universe.world.add_component(RenderableComponent::new(
85 engine::graphics::primitives::Renderable::new(mesh, MaterialHandle::TOON_MESH),
86 ));
87 let color_c = universe.world.add_component(ColorComponent { rgba: color });
88
89 let _ = universe.attach(transform, renderable);
90 let _ = universe.attach(renderable, color_c);
91 universe.add(transform);
92
93 transform
94 }
95
96 // Spawn shapes.
97 // One triangle is input-driven (WASD/QE). Build a small "rig" so both the triangle
98 // and the camera can be driven by the same InputComponent.
99
100 // Topology: Input -> (InputTransformMode) -> RigTransform -> (CameraTransform -> Camera3D), (TriRootTransform -> ...)
101 let tri_input = universe
102 .world
103 .add_component(InputComponent::new().with_speed(0.5));
104 let input_mode = universe
105 .world
106 .add_component(InputTransformModeComponent::forward_z().with_roll_axis_y());
107 let _ = universe.attach(tri_input, input_mode);
108
109 // Start pulled back so the demo meshes at z=0 are in view.
110 // The camera will be attached directly under this transform, so there is no local
111 // camera offset that would cause orbiting when yawing.
112 let rig_transform = universe
113 .world
114 .add_component(TransformComponent::new().with_position(0.0, 0.0, 2.5));
115 let _ = universe.attach(tri_input, rig_transform);
116
117 // Camera: attached directly to the rig transform.
118 let camera3d = universe.world.add_component(Camera3DComponent::new());
119 let _ = universe.attach(rig_transform, camera3d);
120
121 // Topology: I { T { C3D } } — add a small camera-attached controls hint.
122 example_util::spawn_desktop_camera_controls_hint(universe, rig_transform);
123
124 let tri_root_transform = universe
125 .world
126 .add_component(TransformComponent::new().with_position(0.5, 0.50, 0.0));
127
128 // Visual transform under the root; this is where we apply rotation/scale.
129 let tri_visual_transform = universe.world.add_component(
130 TransformComponent::new()
131 .with_scale(0.30, 0.30, 1.0)
132 .with_rotation_euler(0.0, 0.0, (2.0 * 3.14159 / 3.0) + 3.14159),
133 );
134 let tri_renderable = universe.world.add_component(RenderableComponent::new(
135 engine::graphics::primitives::Renderable::new(tri_mesh, MaterialHandle::TOON_MESH),
136 ));
137 let tri_color = universe
138 .world
139 .add_component(ColorComponent::rgba(0.2, 1.0, 0.2, 1.0));
140
141 let _ = universe.attach(rig_transform, tri_root_transform);
142 let _ = universe.attach(tri_root_transform, tri_visual_transform);
143 let _ = universe.attach(tri_visual_transform, tri_renderable);
144 let _ = universe.attach(tri_renderable, tri_color);
145
146 let tri_light = universe.world.add_component(
147 PointLightComponent::new()
148 .with_distance(10.0)
149 .with_color(1.0, 1.0, 1.0),
150 );
151
152 let light_transform = universe.world.add_component(
153 TransformComponent::new()
154 .with_position(0.5, 0.50, 1.0)
155 .with_scale(0.1, 0.1, 0.1),
156 );
157
158 let _ = universe.attach(light_transform, tri_light);
159
160 universe.add(tri_input);
161 universe.add(light_transform);
162
163 spawn(
164 universe,
165 square_mesh,
166 -0.80,
167 -0.30,
168 0.25,
169 0.0,
170 [1.0, 0.2, 0.2, 1.0],
171 false,
172 true,
173 );
174 spawn(
175 universe,
176 square_mesh,
177 -0.40,
178 -0.30,
179 0.25,
180 0.0,
181 [1.0, 0.6, 0.2, 1.0],
182 false,
183 true,
184 );
185
186 // 3D primitive: tetrahedron.
187 spawn_3d(
188 universe,
189 tetra_mesh,
190 0.55,
191 -0.15,
192 0.0,
193 0.35,
194 0.75,
195 0.55,
196 0.0,
197 [0.2, 0.7, 1.0, 1.0],
198 );
199 spawn(
200 universe,
201 square_mesh,
202 0.00,
203 -0.30,
204 0.25,
205 0.0,
206 [1.0, 1.0, 0.2, 1.0],
207 false,
208 true,
209 );
210 spawn(
211 universe,
212 square_mesh,
213 0.40,
214 -0.30,
215 0.25,
216 0.0,
217 [0.2, 0.6, 1.0, 1.0],
218 false,
219 true,
220 );
221 spawn(
222 universe,
223 square_mesh,
224 0.80,
225 -0.30,
226 0.25,
227 0.0,
228 [0.8, 0.2, 1.0, 1.0],
229 false,
230 true,
231 );
232 spawn(
233 universe,
234 tri_mesh,
235 0.30,
236 0.35,
237 0.30,
238 -3.14159,
239 [1.0, 1.0, 1.0, 1.0],
240 false,
241 false,
242 );
243
244 // Textured square.
245 let tex_transform = universe.world.add_component(
246 TransformComponent::new()
247 .with_position(0.0, 0.1, 0.0)
248 .with_scale(0.45, 0.45, 1.0),
249 );
250 let tex_renderable = universe.world.add_component(RenderableComponent::new(
251 engine::graphics::primitives::Renderable::new(square_mesh, MaterialHandle::TOON_MESH),
252 ));
253 let tex_color = universe
254 .world
255 .add_component(ColorComponent::rgba(1.0, 1.0, 1.0, 1.0));
256 let tex = universe.world.add_component(TextureComponent::from_dds(
257 "assets/textures/cat-face-amused.dds",
258 ));
259
260 let _ = universe.attach(tex_transform, tex_renderable);
261 let _ = universe.attach(tex_renderable, tex_color);
262 let _ = universe.attach(tex_renderable, tex);
263 universe.add(tex_transform);
264
265 // glTF: color-cat
266 // Attach GLTFComponent under a Transform so GLTFSystem can use it as an anchor.
267 let cat_anchor = universe.world.add_component(
268 TransformComponent::new()
269 .with_position(0.0, -0.10, -4.0)
270 .with_scale(0.50, 0.50, 0.50)
271 .with_rotation_euler(0.0, 0.0, 0.0),
272 );
273 let cat_gltf = universe
274 .world
275 .add_component(GLTFComponent::new("assets/models/color-cat.2.glb"));
276 let _ = universe.attach(cat_anchor, cat_gltf);
277 universe.add(cat_anchor);
278}More examples
examples/vr-input.rs (lines 78-81)
62fn spawn_sun_background(universe: &mut engine::Universe) {
63 let bg_root = universe
64 .world
65 .add_component(engine::ecs::component::BackgroundComponent::new());
66 universe.add(bg_root);
67
68 let circle_mesh = universe.render_assets.get_mesh(BuiltinMeshType::Circle2D);
69
70 // Big yellow disk.
71 let sun_t = universe.world.add_component(
72 TransformComponent::new()
73 .with_position(2.0, 1.5, -8.0)
74 .with_scale(3.5, 3.5, 3.5),
75 );
76 let sun_r = universe
77 .world
78 .add_component(RenderableComponent::new(Renderable::new(
79 circle_mesh,
80 MaterialHandle::TOON_MESH,
81 )));
82 let sun_color = universe
83 .world
84 .add_component(ColorComponent::rgba(1.0, 0.85, 0.15, 1.0));
85 let sun_emissive = universe.world.add_component(EmissiveComponent::on());
86
87 let _ = universe.attach(bg_root, sun_t);
88 let _ = universe.attach(sun_t, sun_r);
89 let _ = universe.attach(sun_r, sun_color);
90 let _ = universe.attach(sun_r, sun_emissive);
91
92 // Small white highlight disk.
93 let highlight_t = universe.world.add_component(
94 TransformComponent::new()
95 .with_position(-0.35, 0.35, -0.01)
96 .with_scale(0.45, 0.45, 0.45),
97 );
98 let highlight_r = universe
99 .world
100 .add_component(RenderableComponent::new(Renderable::new(
101 circle_mesh,
102 MaterialHandle::TOON_MESH,
103 )));
104 let highlight_color = universe
105 .world
106 .add_component(ColorComponent::rgba(1.0, 1.0, 1.0, 1.0));
107 let highlight_emissive = universe.world.add_component(EmissiveComponent::on());
108
109 let _ = universe.attach(sun_t, highlight_t);
110 let _ = universe.attach(highlight_t, highlight_r);
111 let _ = universe.attach(highlight_r, highlight_color);
112 let _ = universe.attach(highlight_r, highlight_emissive);
113}examples/example_util/mod.rs (lines 162-165)
105pub fn spawn_cloud_ring(
106 universe: &mut engine::Universe,
107 bg_root: engine::ecs::ComponentId,
108 p: CloudRingParams,
109) {
110 if p.cloud_count == 0 || p.radius == 0.0 {
111 return;
112 }
113
114 let cube_mesh = universe
115 .render_assets
116 .get_mesh(engine::graphics::BuiltinMeshType::Cube);
117
118 let step = std::f32::consts::TAU / (p.cloud_count as f32);
119 let angle_jitter = p.angle_jitter.clamp(0.0, 1.0);
120 let high_y_probability = p.high_y_probability.clamp(0.0, 1.0);
121
122 for i in 0..p.cloud_count {
123 let seed_i = p.seed ^ i.wrapping_mul(0x9E37_79B9);
124 let jitter = (rand01(seed_i ^ 0xa53a_9d2d) - 0.5) * step * angle_jitter;
125 let a = (i as f32) * step + jitter;
126 let cx = p.radius * a.cos();
127 let cz = p.radius * a.sin();
128
129 let cy = if rand01(seed_i ^ 0x7f4a_7c15) < high_y_probability {
130 p.center_y * p.high_y_multiplier
131 } else {
132 p.center_y
133 };
134
135 let center_tx = universe.world.add_component(
136 engine::ecs::component::TransformComponent::new().with_position(cx, cy, cz),
137 );
138 let _ = universe.attach(bg_root, center_tx);
139
140 let base_seed = seed_i ^ 0x243f_6a88;
141 for puff_i in 0..p.puffs_per_cloud {
142 let seed = base_seed ^ puff_i.wrapping_mul(1_103_515_245);
143
144 let ox = (rand01(seed ^ 0x68bc_21eb) - 0.5) * 9.0;
145 let oy = (rand01(seed ^ 0x02e5_be93) - 0.5) * 4.0;
146 let oz = (rand01(seed ^ 0xa1d3_4f2b) - 0.5) * 9.0;
147
148 let base = 0.7 + rand01(seed ^ 0x9e37_79b9) * 2.8;
149 let sx = base * (0.7 + rand01(seed ^ 0x243f_6a88) * 0.9);
150 let sy = base * (0.6 + rand01(seed ^ 0x85a3_08d3) * 1.0);
151 let sz = base * (0.7 + rand01(seed ^ 0x1319_8a2e) * 0.9);
152
153 let tx = universe.world.add_component(
154 engine::ecs::component::TransformComponent::new()
155 .with_position(ox, oy, oz)
156 .with_scale(sx, sy, sz),
157 );
158 let renderable =
159 universe
160 .world
161 .add_component(engine::ecs::component::RenderableComponent::new(
162 engine::graphics::primitives::Renderable::new(
163 cube_mesh,
164 engine::graphics::primitives::MaterialHandle::TOON_MESH,
165 ),
166 ));
167
168 let t = rand01(seed ^ 0x7f4a_7c15);
169 let r = 0.70 + 0.10 * t;
170 let g = 0.72 + 0.10 * t;
171 let b = 0.80 + 0.12 * t;
172 let color = universe
173 .world
174 .add_component(engine::ecs::component::ColorComponent::rgba(r, g, b, 1.0));
175
176 let _ = universe.attach(center_tx, tx);
177 let _ = universe.attach(tx, renderable);
178 let _ = universe.attach(renderable, color);
179 }
180 }
181}examples/mesh-factory-example.rs (lines 107-110)
55 fn spawn_labeled_mesh(
56 universe: &mut engine::Universe,
57 x: f32,
58 y: f32,
59 label: &str,
60 mesh: engine::graphics::primitives::CpuMeshHandle,
61 scale: [f32; 3],
62 color: [f32; 4],
63 ) {
64 use engine::ecs::component::{
65 ActionComponent, AnimationComponent, AnimationState, ColorComponent, EmissiveComponent,
66 KeyframeComponent, RenderableComponent, TextComponent, TransformComponent,
67 };
68 use engine::graphics::primitives::{MaterialHandle, Renderable};
69
70 // Mesh.
71 let root = universe.world.add_component(
72 TransformComponent::new()
73 .with_position(x, y, 0.0)
74 .with_scale(scale[0], scale[1], scale[2]),
75 );
76
77 // Spin each shape around its own +Y axis using AnimationComponent + keyframes.
78 // We fill [0, 2) beats densely so it looks smooth.
79 let anim = universe
80 .world
81 .add_component(AnimationComponent::new().with_state(AnimationState::Looping));
82 let _ = universe.attach(root, anim);
83
84 let steps: usize = 64;
85 for i in 0..steps {
86 let beat = (i as f64) * (2.0 / (steps as f64));
87 let kf = universe.world.add_component(KeyframeComponent::new(beat));
88 let _ = universe.attach(anim, kf);
89
90 // Full turn over 2 beats.
91 let angle = (std::f64::consts::TAU * (beat / 2.0)) as f32;
92 let rotation = utils::math::quat_from_axis_angle([0.0, 1.0, 0.0], angle);
93
94 let action_cid = universe.world.add_component(ActionComponent::new(
95 engine::ecs::IntentValue::UpdateTransform {
96 component_ids: vec![root],
97 translation: [x, y, 0.0],
98 rotation_quat_xyzw: rotation,
99 scale,
100 },
101 ));
102 let _ = universe.attach(kf, action_cid);
103 }
104
105 let renderable = universe
106 .world
107 .add_component(RenderableComponent::new(Renderable::new(
108 mesh,
109 MaterialHandle::TOON_MESH,
110 )));
111 let color_c = universe
112 .world
113 .add_component(ColorComponent::rgba(color[0], color[1], color[2], color[3]));
114 let emissive = universe.world.add_component(EmissiveComponent::on());
115
116 let _ = universe.attach(root, renderable);
117 let _ = universe.attach(renderable, color_c);
118 let _ = universe.attach(renderable, emissive);
119
120 universe.add(root);
121
122 // Label (separate transform so we can scale text independently).
123 let text_root = universe.world.add_component(
124 TransformComponent::new()
125 .with_position(x, y + 0.75, 0.05)
126 .with_scale(0.09, 0.09, 1.0),
127 );
128 let text = universe
129 .world
130 .add_component(TextComponent::with_word_wrap_tokens(
131 label,
132 LABEL_WRAP_AT,
133 ["::", "(", ")", ",", "."],
134 ));
135 let text_color = universe
136 .world
137 .add_component(ColorComponent::rgba(1.0, 1.0, 1.0, 1.0));
138 let text_emissive = universe.world.add_component(EmissiveComponent::on());
139 let _ = universe.attach(text_root, text);
140 let _ = universe.attach(text, text_color);
141 let _ = universe.attach(text, text_emissive);
142 universe.add(text_root);
143 }examples/openxr.rs (lines 107-110)
6fn main() {
7 mittens_engine::example_support::ensure_model_assets();
8 utils::logger::init();
9
10 let world = engine::ecs::World::default();
11 let mut universe = engine::Universe::new(world);
12
13 let background = universe
14 .world
15 .add_component(engine::ecs::component::BackgroundColorComponent::new());
16 let background_c = universe
17 .world
18 .add_component(engine::ecs::component::ColorComponent::rgba(
19 0.3, 0.1, 1.0, 1.0,
20 ));
21 let _ = universe.world.add_child(background, background_c);
22 universe.add(background);
23
24 // --- Camera rig (WASD/QE) ---
25 // Keep this similar to the main demo so we can fly around the cube field.
26 let input = universe
27 .world
28 .add_component(engine::ecs::component::InputComponent::new().with_speed(1.5));
29 let input_mode = universe.world.add_component(
30 engine::ecs::component::InputTransformModeComponent::forward_z().with_roll_axis_y(),
31 );
32 let _ = universe.attach(input, input_mode);
33
34 // Start pulled back so the grid is in view.
35 let rig_transform = universe.world.add_component(
36 engine::ecs::component::TransformComponent::new().with_position(0.0, 0.0, 4.0),
37 );
38 let _ = universe.attach(input, rig_transform);
39
40 let camera3d = universe
41 .world
42 .add_component(engine::ecs::component::Camera3DComponent::new());
43 let _ = universe.attach(rig_transform, camera3d);
44
45 // Topology: I { T { C3D } } — add a small camera-attached controls hint.
46 example_util::spawn_desktop_camera_controls_hint(&mut universe, rig_transform);
47
48 // Simple point light so the toon shader reads well.
49 let light = universe.world.add_component(
50 engine::ecs::component::PointLightComponent::new()
51 .with_distance(50.0)
52 .with_color(1.0, 1.0, 1.0),
53 );
54 let light_transform = universe.world.add_component(
55 engine::ecs::component::TransformComponent::new().with_position(0.0, 5.0, 2.0),
56 );
57 let _ = universe.attach(light_transform, light);
58
59 universe.add(input);
60 universe.add(light_transform);
61
62 // --- 16x16x16 cube grid ---
63 let cube_mesh = universe
64 .render_assets
65 .get_mesh(engine::graphics::BuiltinMeshType::Cube);
66
67 let n: usize = 32;
68 let cube_scale: f32 = 0.10;
69 let gap: f32 = 0.50;
70 let step: f32 = cube_scale + gap;
71
72 // Center positions around 0 by subtracting half the extent (in steps).
73 let half_extent_x = (n as f32 - 1.0) * step * 0.5;
74 let half_extent_y = (n as f32 - 1.0) * step * 0.5;
75 let half_extent_z = (n as f32 - 1.0) * step * 0.5;
76
77 // Move the whole container up/back based on its content size, plus the requested offsets.
78 // - up by +0.5 and by half the content height
79 // - back by -(0.5 + 1.0) and by half the content depth
80 let container_offset_y = half_extent_y + 0.5;
81 let container_offset_z = -(half_extent_z + 1.0 + 0.5);
82
83 let container = universe.world.add_component(
84 engine::ecs::component::TransformComponent::new().with_position(
85 0.0,
86 container_offset_y,
87 container_offset_z,
88 ),
89 );
90
91 for z in 0..n {
92 for y in 0..n {
93 for x in 0..n {
94 let px = x as f32 * step - half_extent_x;
95 let py = y as f32 * step - half_extent_y;
96 let pz = z as f32 * step - half_extent_z;
97
98 let tx = universe.world.add_component(
99 engine::ecs::component::TransformComponent::new()
100 .with_position(px, py, pz)
101 .with_scale(cube_scale, cube_scale, cube_scale),
102 );
103 let renderable =
104 universe
105 .world
106 .add_component(engine::ecs::component::RenderableComponent::new(
107 engine::graphics::primitives::Renderable::new(
108 cube_mesh,
109 engine::graphics::primitives::MaterialHandle::TOON_MESH,
110 ),
111 ));
112
113 let denom = (n - 1) as f32;
114 let color = engine::ecs::component::ColorComponent::rgba(
115 f32::sin(x as f32 / 10.0),
116 y as f32 / denom,
117 z as f32 / denom,
118 1.0,
119 );
120 let color_c = universe.world.add_component(color);
121
122 let _ = universe.attach(container, tx);
123 let _ = universe.attach(tx, renderable);
124 let _ = universe.attach(renderable, color_c);
125 }
126 }
127 }
128
129 universe.add(container);
130 universe.systems.process_commands(
131 &mut universe.world,
132 &mut universe.visuals,
133 &mut universe.render_assets,
134 &mut universe.command_queue,
135 );
136
137 let xr_input = universe
138 .world
139 .add_component(engine::ecs::component::InputXRComponent::on());
140 let xr_gamepad = universe
141 .world
142 .add_component(engine::ecs::component::InputXRGamepadComponent::new().speed(1.5));
143 let xr_head = universe
144 .world
145 .add_component(engine::ecs::component::TransformComponent::new());
146 let camera_xr = universe
147 .world
148 .add_component(engine::ecs::component::CameraXRComponent::on());
149 let _ = universe.attach(xr_input, xr_head);
150 let _ = universe.attach(xr_input, xr_gamepad);
151 let _ = universe.attach(xr_head, camera_xr);
152 universe.add(xr_input);
153
154 // Add an OpenXR component so OpenXRSystem initializes and starts polling events.
155 let xr_root = universe
156 .world
157 .add_component(engine::ecs::component::XrComponent::on());
158 universe.add(xr_root);
159 universe.systems.process_commands(
160 &mut universe.world,
161 &mut universe.visuals,
162 &mut universe.render_assets,
163 &mut universe.command_queue,
164 );
165
166 universe.enable_repl();
167 engine::Windowing::run_app(universe).expect("Windowing failed");
168}examples/gestures-and-gizmos.rs (lines 52-55)
13fn build_gestures_and_gizmos_scene(universe: &mut engine::Universe) -> Scene {
14 use engine::ecs::component::{
15 BackgroundColorComponent, BackgroundComponent, Camera3DComponent, ColorComponent,
16 DirectionalLightComponent, InputComponent, InputTransformModeComponent, PointerComponent,
17 RaycastableComponent, RenderableComponent, TransformComponent, TransformGizmoComponent,
18 };
19 use engine::graphics::BuiltinMeshType;
20 use engine::graphics::primitives::{MaterialHandle, Renderable};
21
22 let tri_mesh = universe.render_assets.get_mesh(BuiltinMeshType::Triangle2D);
23 let cube_mesh = universe.render_assets.get_mesh(BuiltinMeshType::Cube);
24 let tetra_mesh = universe
25 .render_assets
26 .get_mesh(BuiltinMeshType::Tetrahedron);
27
28 // BackgroundColor { C.rgba }
29 let bg_color = universe
30 .world
31 .add_component(BackgroundColorComponent::new());
32 let bg_color_c = universe
33 .world
34 .add_component(ColorComponent::rgba(0.90, 0.90, 0.90, 1.0));
35 let _ = universe.world.add_child(bg_color, bg_color_c);
36 universe.add(bg_color);
37
38 // ambient light
39 let ambient = universe
40 .world
41 .add_component(AmbientLightComponent::rgb(0.25, 0.25, 0.25));
42 universe.add(ambient);
43
44 // ground plane
45 let ground_tx = universe.world.add_component(
46 TransformComponent::new()
47 .with_position(0.0, -2.5, 0.0)
48 .with_scale(20.0, 1.0, 20.0),
49 );
50 let ground_r = universe
51 .world
52 .add_component(RenderableComponent::new(Renderable::new(
53 universe.render_assets.get_mesh(BuiltinMeshType::Cube),
54 MaterialHandle::TOON_MESH,
55 )));
56 let ground_c = universe
57 .world
58 .add_component(ColorComponent::rgba(0.75, 0.75, 0.75, 1.0));
59 let _ = universe.attach(ground_tx, ground_r);
60 let _ = universe.attach(ground_r, ground_c);
61 let _ = universe.add(ground_tx);
62
63 // Background {
64 // with_occlusion_and_lighting()
65 // // using the example utils to add clouds to the background
66 // }
67 let bg_root = universe
68 .world
69 .add_component(BackgroundComponent::new().with_occlusion_and_lighting());
70 universe.add(bg_root);
71
72 // DirectionalLight {
73 // T { translate [1, 1, 1] }
74 // }
75 // Directional lights encode their direction in the node's world position.
76 let sun_t = universe
77 .world
78 .add_component(TransformComponent::new().with_position(1.0, 1.0, 1.0));
79 let sun = universe
80 .world
81 .add_component(DirectionalLightComponent::new());
82 let _ = universe.attach(sun_t, sun);
83 universe.add(sun_t);
84
85 // i = input
86 // t = transform
87 // c3d = camera3d
88 //
89 // I {
90 // T {
91 // C3D { with_fps_rotation().with_roll_axis_y() }
92 // }
93 // }
94 let input = universe
95 .world
96 .add_component(InputComponent::new().with_speed(2.5));
97 let input_mode = universe.world.add_component(
98 InputTransformModeComponent::forward_z()
99 .with_fps_rotation()
100 .with_roll_axis_y(),
101 );
102
103 let _ = universe.attach(input, input_mode);
104
105 // Forward is -Z, so put the camera at +Z looking toward the origin.
106 let rig_t = universe
107 .world
108 .add_component(TransformComponent::new().with_position(0.0, 0.0, 3.5));
109 let _ = universe.attach(input, rig_t);
110
111 let cam = universe
112 .world
113 .add_component(Camera3DComponent::new().with_far(600.0).with_fov(70.0));
114 let _ = universe.attach(rig_t, cam);
115
116 // Opt-in: treat this camera rig as a pointer source.
117 let pointer = universe.world.add_component(PointerComponent::new());
118 let _ = universe.attach(cam, pointer);
119
120 // Topology: I { T { C3D } } — add a small camera-attached controls hint.
121 example_util::spawn_desktop_camera_controls_hint(universe, rig_t);
122
123 fn spawn_shape_with_gizmo(
124 universe: &mut engine::Universe,
125 mesh: engine::graphics::primitives::CpuMeshHandle,
126 pos: [f32; 3],
127 scale: [f32; 3],
128 rot_euler: [f32; 3],
129 color: [f32; 4],
130 ) {
131 let t = universe.world.add_component(
132 TransformComponent::new()
133 .with_position(pos[0], pos[1], pos[2])
134 .with_scale(scale[0], scale[1], scale[2])
135 .with_rotation_euler(rot_euler[0], rot_euler[1], rot_euler[2]),
136 );
137 let r = universe
138 .world
139 .add_component(RenderableComponent::new(Renderable::new(
140 mesh,
141 MaterialHandle::TOON_MESH,
142 )));
143 let c = universe
144 .world
145 .add_component(ColorComponent::rgba(color[0], color[1], color[2], color[3]));
146 let rc = universe
147 .world
148 .add_component(RaycastableComponent::enabled());
149 let g = universe.world.add_component(TransformGizmoComponent::new());
150
151 let _ = universe.attach(t, r);
152 let _ = universe.attach(r, c);
153 let _ = universe.attach(r, rc);
154 let _ = universe.attach(t, g);
155
156 universe.add(t);
157 }
158
159 fn spawn_shape_raycastable_no_gizmo(
160 universe: &mut engine::Universe,
161 mesh: engine::graphics::primitives::CpuMeshHandle,
162 pos: [f32; 3],
163 scale: [f32; 3],
164 rot_euler: [f32; 3],
165 color: [f32; 4],
166 ) {
167 let t = universe.world.add_component(
168 TransformComponent::new()
169 .with_position(pos[0], pos[1], pos[2])
170 .with_scale(scale[0], scale[1], scale[2])
171 .with_rotation_euler(rot_euler[0], rot_euler[1], rot_euler[2]),
172 );
173 let r = universe
174 .world
175 .add_component(RenderableComponent::new(Renderable::new(
176 mesh,
177 MaterialHandle::TOON_MESH,
178 )));
179 let c = universe
180 .world
181 .add_component(ColorComponent::rgba(color[0], color[1], color[2], color[3]));
182 let rc = universe
183 .world
184 .add_component(RaycastableComponent::enabled());
185
186 let _ = universe.attach(t, r);
187 let _ = universe.attach(r, c);
188 let _ = universe.attach(r, rc);
189
190 universe.add(t);
191 }
192
193 spawn_shape_with_gizmo(
194 universe,
195 tri_mesh,
196 [-1.2, 0.0, 0.0],
197 [0.65, 0.65, 0.65],
198 [0.0, 0.0, 0.0],
199 [0.2, 0.9, 0.25, 1.0],
200 );
201 spawn_shape_with_gizmo(
202 universe,
203 cube_mesh,
204 [0.0, 0.0, 0.0],
205 [0.55, 0.55, 0.55],
206 [0.0, 0.0, 0.0],
207 [0.95, 0.25, 0.2, 1.0],
208 );
209 spawn_shape_with_gizmo(
210 universe,
211 tetra_mesh,
212 [1.2, 0.0, 0.0],
213 [0.7, 0.7, 0.7],
214 [0.0, 0.0, 0.0],
215 [0.2, 0.55, 1.0, 1.0],
216 );
217
218 // Standalone tetrahedron: no gizmo, but explicitly raycastable.
219 // This helps isolate tetra picking vs gizmo-handle interception.
220 spawn_shape_raycastable_no_gizmo(
221 universe,
222 tetra_mesh,
223 [2.6, -0.6, 0.0],
224 [0.95, 0.95, 0.95],
225 [0.0, 0.0, 0.0],
226 [0.85, 0.85, 1.0, 1.0],
227 );
228
229 universe.add(input);
230
231 Scene { bg_root }
232}Additional examples can be found in:
pub fn with_base_mesh(self, base_mesh: CpuMeshHandle) -> Self
Trait Implementations§
Source§impl Clone for Renderable
impl Clone for Renderable
Source§fn clone(&self) -> Renderable
fn clone(&self) -> Renderable
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreAuto Trait Implementations§
impl Freeze for Renderable
impl RefUnwindSafe for Renderable
impl Send for Renderable
impl Sync for Renderable
impl Unpin for Renderable
impl UnsafeUnpin for Renderable
impl UnwindSafe for Renderable
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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.