1use std::f32::consts::PI;
17
18#[cfg(not(target_arch = "wasm32"))]
19use bevy::pbr::wireframe::{WireframeConfig, WireframePlugin};
20use bevy::{
21 asset::RenderAssetUsages,
22 color::palettes::basic::SILVER,
23 prelude::*,
24 render::render_resource::{Extent3d, TextureDimension, TextureFormat},
25};
26
27fn main() {
28 App::new()
29 .add_plugins((
30 DefaultPlugins.set(ImagePlugin::default_nearest()),
31 #[cfg(not(target_arch = "wasm32"))]
32 WireframePlugin::default(),
33 ))
34 .add_systems(Startup, setup)
35 .add_systems(
36 Update,
37 (
38 rotate,
39 #[cfg(not(target_arch = "wasm32"))]
40 toggle_wireframe,
41 ),
42 )
43 .run();
44}
45
46#[derive(Component)]
48struct Shape;
49
50const SHAPES_X_EXTENT: f32 = 14.0;
51const EXTRUSION_X_EXTENT: f32 = 16.0;
52const Z_EXTENT: f32 = 5.0;
53
54fn setup(
55 mut commands: Commands,
56 mut meshes: ResMut<Assets<Mesh>>,
57 mut images: ResMut<Assets<Image>>,
58 mut materials: ResMut<Assets<StandardMaterial>>,
59) {
60 let debug_material = materials.add(StandardMaterial {
61 base_color_texture: Some(images.add(uv_debug_texture())),
62 ..default()
63 });
64
65 let shapes = [
66 meshes.add(Cuboid::default()),
67 meshes.add(Tetrahedron::default()),
68 meshes.add(Capsule3d::default()),
69 meshes.add(Torus::default()),
70 meshes.add(Cylinder::default()),
71 meshes.add(Cone::default()),
72 meshes.add(ConicalFrustum::default()),
73 meshes.add(Sphere::default().mesh().ico(5).unwrap()),
74 meshes.add(Sphere::default().mesh().uv(32, 18)),
75 meshes.add(Segment3d::default()),
76 meshes.add(Polyline3d::new(vec![
77 Vec3::new(-0.5, 0.0, 0.0),
78 Vec3::new(0.5, 0.0, 0.0),
79 Vec3::new(0.0, 0.5, 0.0),
80 ])),
81 ];
82
83 let extrusions = [
84 meshes.add(Extrusion::new(Rectangle::default(), 1.)),
85 meshes.add(Extrusion::new(Capsule2d::default(), 1.)),
86 meshes.add(Extrusion::new(Annulus::default(), 1.)),
87 meshes.add(Extrusion::new(Circle::default(), 1.)),
88 meshes.add(Extrusion::new(Ellipse::default(), 1.)),
89 meshes.add(Extrusion::new(RegularPolygon::default(), 1.)),
90 meshes.add(Extrusion::new(Triangle2d::default(), 1.)),
91 ];
92
93 let num_shapes = shapes.len();
94
95 for (i, shape) in shapes.into_iter().enumerate() {
96 commands.spawn((
97 Mesh3d(shape),
98 MeshMaterial3d(debug_material.clone()),
99 Transform::from_xyz(
100 -SHAPES_X_EXTENT / 2. + i as f32 / (num_shapes - 1) as f32 * SHAPES_X_EXTENT,
101 2.0,
102 Z_EXTENT / 2.,
103 )
104 .with_rotation(Quat::from_rotation_x(-PI / 4.)),
105 Shape,
106 ));
107 }
108
109 let num_extrusions = extrusions.len();
110
111 for (i, shape) in extrusions.into_iter().enumerate() {
112 commands.spawn((
113 Mesh3d(shape),
114 MeshMaterial3d(debug_material.clone()),
115 Transform::from_xyz(
116 -EXTRUSION_X_EXTENT / 2.
117 + i as f32 / (num_extrusions - 1) as f32 * EXTRUSION_X_EXTENT,
118 2.0,
119 -Z_EXTENT / 2.,
120 )
121 .with_rotation(Quat::from_rotation_x(-PI / 4.)),
122 Shape,
123 ));
124 }
125
126 commands.spawn((
127 PointLight {
128 shadows_enabled: true,
129 intensity: 10_000_000.,
130 range: 100.0,
131 shadow_depth_bias: 0.2,
132 ..default()
133 },
134 Transform::from_xyz(8.0, 16.0, 8.0),
135 ));
136
137 commands.spawn((
139 Mesh3d(meshes.add(Plane3d::default().mesh().size(50.0, 50.0).subdivisions(10))),
140 MeshMaterial3d(materials.add(Color::from(SILVER))),
141 ));
142
143 commands.spawn((
144 Camera3d::default(),
145 Transform::from_xyz(0.0, 7., 14.0).looking_at(Vec3::new(0., 1., 0.), Vec3::Y),
146 ));
147
148 #[cfg(not(target_arch = "wasm32"))]
149 commands.spawn((
150 Text::new("Press space to toggle wireframes"),
151 Node {
152 position_type: PositionType::Absolute,
153 top: px(12),
154 left: px(12),
155 ..default()
156 },
157 ));
158}
159
160fn rotate(mut query: Query<&mut Transform, With<Shape>>, time: Res<Time>) {
161 for mut transform in &mut query {
162 transform.rotate_y(time.delta_secs() / 2.);
163 }
164}
165
166fn uv_debug_texture() -> Image {
168 const TEXTURE_SIZE: usize = 8;
169
170 let mut palette: [u8; 32] = [
171 255, 102, 159, 255, 255, 159, 102, 255, 236, 255, 102, 255, 121, 255, 102, 255, 102, 255,
172 198, 255, 102, 198, 255, 255, 121, 102, 255, 255, 236, 102, 255, 255,
173 ];
174
175 let mut texture_data = [0; TEXTURE_SIZE * TEXTURE_SIZE * 4];
176 for y in 0..TEXTURE_SIZE {
177 let offset = TEXTURE_SIZE * y * 4;
178 texture_data[offset..(offset + TEXTURE_SIZE * 4)].copy_from_slice(&palette);
179 palette.rotate_right(4);
180 }
181
182 Image::new_fill(
183 Extent3d {
184 width: TEXTURE_SIZE as u32,
185 height: TEXTURE_SIZE as u32,
186 depth_or_array_layers: 1,
187 },
188 TextureDimension::D2,
189 &texture_data,
190 TextureFormat::Rgba8UnormSrgb,
191 RenderAssetUsages::RENDER_WORLD,
192 )
193}
194
195#[cfg(not(target_arch = "wasm32"))]
196fn toggle_wireframe(
197 mut wireframe_config: ResMut<WireframeConfig>,
198 keyboard: Res<ButtonInput<KeyCode>>,
199) {
200 if keyboard.just_pressed(KeyCode::Space) {
201 wireframe_config.global = !wireframe_config.global;
202 }
203}