Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/math/render_primitives.rs
6592 views
1
//! This example demonstrates how each of Bevy's math primitives look like in 2D and 3D with meshes
2
//! and with gizmos
3
4
use bevy::{input::common_conditions::input_just_pressed, math::Isometry2d, prelude::*};
5
6
const LEFT_RIGHT_OFFSET_2D: f32 = 200.0;
7
const LEFT_RIGHT_OFFSET_3D: f32 = 2.0;
8
9
fn main() {
10
let mut app = App::new();
11
12
app.add_plugins(DefaultPlugins)
13
.init_state::<PrimitiveSelected>()
14
.init_state::<CameraActive>();
15
16
// cameras
17
app.add_systems(Startup, (setup_cameras, setup_lights, setup_ambient_light))
18
.add_systems(
19
Update,
20
(
21
update_active_cameras.run_if(state_changed::<CameraActive>),
22
switch_cameras.run_if(input_just_pressed(KeyCode::KeyC)),
23
),
24
);
25
26
// text
27
28
// PostStartup since we need the cameras to exist
29
app.add_systems(PostStartup, setup_text);
30
app.add_systems(
31
Update,
32
(update_text.run_if(state_changed::<PrimitiveSelected>),),
33
);
34
35
// primitives
36
app.add_systems(Startup, (spawn_primitive_2d, spawn_primitive_3d))
37
.add_systems(
38
Update,
39
(
40
switch_to_next_primitive.run_if(input_just_pressed(KeyCode::ArrowUp)),
41
switch_to_previous_primitive.run_if(input_just_pressed(KeyCode::ArrowDown)),
42
draw_gizmos_2d.run_if(in_mode(CameraActive::Dim2)),
43
draw_gizmos_3d.run_if(in_mode(CameraActive::Dim3)),
44
update_primitive_meshes
45
.run_if(state_changed::<PrimitiveSelected>.or(state_changed::<CameraActive>)),
46
rotate_primitive_2d_meshes,
47
rotate_primitive_3d_meshes,
48
),
49
);
50
51
app.run();
52
}
53
54
/// State for tracking which of the two cameras (2D & 3D) is currently active
55
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, States, Default, Reflect)]
56
enum CameraActive {
57
#[default]
58
/// 2D Camera is active
59
Dim2,
60
/// 3D Camera is active
61
Dim3,
62
}
63
64
/// State for tracking which primitives are currently displayed
65
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, States, Default, Reflect)]
66
enum PrimitiveSelected {
67
#[default]
68
RectangleAndCuboid,
69
CircleAndSphere,
70
Ellipse,
71
Triangle,
72
Plane,
73
Line,
74
Segment,
75
Polyline,
76
Polygon,
77
RegularPolygon,
78
Capsule,
79
Cylinder,
80
Cone,
81
ConicalFrustum,
82
Torus,
83
Tetrahedron,
84
Arc,
85
CircularSector,
86
CircularSegment,
87
}
88
89
impl std::fmt::Display for PrimitiveSelected {
90
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91
let name = match self {
92
PrimitiveSelected::RectangleAndCuboid => String::from("Rectangle/Cuboid"),
93
PrimitiveSelected::CircleAndSphere => String::from("Circle/Sphere"),
94
other => format!("{other:?}"),
95
};
96
write!(f, "{name}")
97
}
98
}
99
100
impl PrimitiveSelected {
101
const ALL: [Self; 19] = [
102
Self::RectangleAndCuboid,
103
Self::CircleAndSphere,
104
Self::Ellipse,
105
Self::Triangle,
106
Self::Plane,
107
Self::Line,
108
Self::Segment,
109
Self::Polyline,
110
Self::Polygon,
111
Self::RegularPolygon,
112
Self::Capsule,
113
Self::Cylinder,
114
Self::Cone,
115
Self::ConicalFrustum,
116
Self::Torus,
117
Self::Tetrahedron,
118
Self::Arc,
119
Self::CircularSector,
120
Self::CircularSegment,
121
];
122
123
fn next(self) -> Self {
124
Self::ALL
125
.into_iter()
126
.cycle()
127
.skip_while(|&x| x != self)
128
.nth(1)
129
.unwrap()
130
}
131
132
fn previous(self) -> Self {
133
Self::ALL
134
.into_iter()
135
.rev()
136
.cycle()
137
.skip_while(|&x| x != self)
138
.nth(1)
139
.unwrap()
140
}
141
}
142
143
const SMALL_2D: f32 = 50.0;
144
const BIG_2D: f32 = 100.0;
145
146
const SMALL_3D: f32 = 0.5;
147
const BIG_3D: f32 = 1.0;
148
149
// primitives
150
const RECTANGLE: Rectangle = Rectangle {
151
half_size: Vec2::new(SMALL_2D, BIG_2D),
152
};
153
const CUBOID: Cuboid = Cuboid {
154
half_size: Vec3::new(BIG_3D, SMALL_3D, BIG_3D),
155
};
156
157
const CIRCLE: Circle = Circle { radius: BIG_2D };
158
const SPHERE: Sphere = Sphere { radius: BIG_3D };
159
160
const ELLIPSE: Ellipse = Ellipse {
161
half_size: Vec2::new(BIG_2D, SMALL_2D),
162
};
163
164
const TRIANGLE_2D: Triangle2d = Triangle2d {
165
vertices: [
166
Vec2::new(BIG_2D, 0.0),
167
Vec2::new(0.0, BIG_2D),
168
Vec2::new(-BIG_2D, 0.0),
169
],
170
};
171
172
const TRIANGLE_3D: Triangle3d = Triangle3d {
173
vertices: [
174
Vec3::new(BIG_3D, 0.0, 0.0),
175
Vec3::new(0.0, BIG_3D, 0.0),
176
Vec3::new(-BIG_3D, 0.0, 0.0),
177
],
178
};
179
180
const PLANE_2D: Plane2d = Plane2d { normal: Dir2::Y };
181
const PLANE_3D: Plane3d = Plane3d {
182
normal: Dir3::Y,
183
half_size: Vec2::new(BIG_3D, BIG_3D),
184
};
185
186
const LINE2D: Line2d = Line2d { direction: Dir2::X };
187
const LINE3D: Line3d = Line3d { direction: Dir3::X };
188
189
const SEGMENT_2D: Segment2d = Segment2d {
190
vertices: [Vec2::new(-BIG_2D / 2., 0.), Vec2::new(BIG_2D / 2., 0.)],
191
};
192
193
const SEGMENT_3D: Segment3d = Segment3d {
194
vertices: [
195
Vec3::new(-BIG_3D / 2., 0., 0.),
196
Vec3::new(BIG_3D / 2., 0., 0.),
197
],
198
};
199
200
const REGULAR_POLYGON: RegularPolygon = RegularPolygon {
201
circumcircle: Circle { radius: BIG_2D },
202
sides: 5,
203
};
204
205
const CAPSULE_2D: Capsule2d = Capsule2d {
206
radius: SMALL_2D,
207
half_length: SMALL_2D,
208
};
209
const CAPSULE_3D: Capsule3d = Capsule3d {
210
radius: SMALL_3D,
211
half_length: SMALL_3D,
212
};
213
214
const CYLINDER: Cylinder = Cylinder {
215
radius: SMALL_3D,
216
half_height: SMALL_3D,
217
};
218
219
const CONE: Cone = Cone {
220
radius: BIG_3D,
221
height: BIG_3D,
222
};
223
224
const CONICAL_FRUSTUM: ConicalFrustum = ConicalFrustum {
225
radius_top: BIG_3D,
226
radius_bottom: SMALL_3D,
227
height: BIG_3D,
228
};
229
230
const ANNULUS: Annulus = Annulus {
231
inner_circle: Circle { radius: SMALL_2D },
232
outer_circle: Circle { radius: BIG_2D },
233
};
234
235
const TORUS: Torus = Torus {
236
minor_radius: SMALL_3D / 2.0,
237
major_radius: SMALL_3D * 1.5,
238
};
239
240
const TETRAHEDRON: Tetrahedron = Tetrahedron {
241
vertices: [
242
Vec3::new(-BIG_3D, 0.0, 0.0),
243
Vec3::new(BIG_3D, 0.0, 0.0),
244
Vec3::new(0.0, 0.0, -BIG_3D * 1.67),
245
Vec3::new(0.0, BIG_3D * 1.67, -BIG_3D * 0.5),
246
],
247
};
248
249
const ARC: Arc2d = Arc2d {
250
radius: BIG_2D,
251
half_angle: std::f32::consts::FRAC_PI_4,
252
};
253
254
const CIRCULAR_SECTOR: CircularSector = CircularSector {
255
arc: Arc2d {
256
radius: BIG_2D,
257
half_angle: std::f32::consts::FRAC_PI_4,
258
},
259
};
260
261
const CIRCULAR_SEGMENT: CircularSegment = CircularSegment {
262
arc: Arc2d {
263
radius: BIG_2D,
264
half_angle: std::f32::consts::FRAC_PI_4,
265
},
266
};
267
268
fn setup_cameras(mut commands: Commands) {
269
let start_in_2d = true;
270
let make_camera = |is_active| Camera {
271
is_active,
272
..Default::default()
273
};
274
275
commands.spawn((Camera2d, make_camera(start_in_2d)));
276
277
commands.spawn((
278
Camera3d::default(),
279
make_camera(!start_in_2d),
280
Transform::from_xyz(0.0, 10.0, 0.0).looking_at(Vec3::ZERO, Vec3::Z),
281
));
282
}
283
284
fn setup_ambient_light(mut ambient_light: ResMut<AmbientLight>) {
285
ambient_light.brightness = 50.0;
286
}
287
288
fn setup_lights(mut commands: Commands) {
289
commands.spawn((
290
PointLight {
291
intensity: 5000.0,
292
..default()
293
},
294
Transform::from_translation(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 2.0, 0.0))
295
.looking_at(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 0.0, 0.0), Vec3::Y),
296
));
297
}
298
299
/// Marker component for header text
300
#[derive(Debug, Clone, Component, Default, Reflect)]
301
pub struct HeaderText;
302
303
/// Marker component for header node
304
#[derive(Debug, Clone, Component, Default, Reflect)]
305
pub struct HeaderNode;
306
307
fn update_active_cameras(
308
state: Res<State<CameraActive>>,
309
camera_2d: Single<(Entity, &mut Camera), With<Camera2d>>,
310
camera_3d: Single<(Entity, &mut Camera), (With<Camera3d>, Without<Camera2d>)>,
311
mut text: Query<&mut UiTargetCamera, With<HeaderNode>>,
312
) {
313
let (entity_2d, mut cam_2d) = camera_2d.into_inner();
314
let (entity_3d, mut cam_3d) = camera_3d.into_inner();
315
let is_camera_2d_active = matches!(*state.get(), CameraActive::Dim2);
316
317
cam_2d.is_active = is_camera_2d_active;
318
cam_3d.is_active = !is_camera_2d_active;
319
320
let active_camera = if is_camera_2d_active {
321
entity_2d
322
} else {
323
entity_3d
324
};
325
326
text.iter_mut().for_each(|mut target_camera| {
327
*target_camera = UiTargetCamera(active_camera);
328
});
329
}
330
331
fn switch_cameras(current: Res<State<CameraActive>>, mut next: ResMut<NextState<CameraActive>>) {
332
let next_state = match current.get() {
333
CameraActive::Dim2 => CameraActive::Dim3,
334
CameraActive::Dim3 => CameraActive::Dim2,
335
};
336
next.set(next_state);
337
}
338
339
fn setup_text(mut commands: Commands, cameras: Query<(Entity, &Camera)>) {
340
let active_camera = cameras
341
.iter()
342
.find_map(|(entity, camera)| camera.is_active.then_some(entity))
343
.expect("run condition ensures existence");
344
commands.spawn((
345
HeaderNode,
346
Node {
347
justify_self: JustifySelf::Center,
348
top: px(5),
349
..Default::default()
350
},
351
UiTargetCamera(active_camera),
352
children![(
353
Text::default(),
354
HeaderText,
355
TextLayout::new_with_justify(Justify::Center),
356
children![
357
TextSpan::new("Primitive: "),
358
TextSpan(format!("{text}", text = PrimitiveSelected::default())),
359
TextSpan::new("\n\n"),
360
TextSpan::new(
361
"Press 'C' to switch between 2D and 3D mode\n\
362
Press 'Up' or 'Down' to switch to the next/previous primitive",
363
),
364
TextSpan::new("\n\n"),
365
TextSpan::new("(If nothing is displayed, there's no rendering support yet)",),
366
]
367
)],
368
));
369
}
370
371
fn update_text(
372
primitive_state: Res<State<PrimitiveSelected>>,
373
header: Query<Entity, With<HeaderText>>,
374
mut writer: TextUiWriter,
375
) {
376
let new_text = format!("{text}", text = primitive_state.get());
377
header.iter().for_each(|header_text| {
378
if let Some(mut text) = writer.get_text(header_text, 2) {
379
(*text).clone_from(&new_text);
380
};
381
});
382
}
383
384
fn switch_to_next_primitive(
385
current: Res<State<PrimitiveSelected>>,
386
mut next: ResMut<NextState<PrimitiveSelected>>,
387
) {
388
let next_state = current.get().next();
389
next.set(next_state);
390
}
391
392
fn switch_to_previous_primitive(
393
current: Res<State<PrimitiveSelected>>,
394
mut next: ResMut<NextState<PrimitiveSelected>>,
395
) {
396
let next_state = current.get().previous();
397
next.set(next_state);
398
}
399
400
fn in_mode(active: CameraActive) -> impl Fn(Res<State<CameraActive>>) -> bool {
401
move |state| *state.get() == active
402
}
403
404
fn draw_gizmos_2d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
405
const POSITION: Vec2 = Vec2::new(-LEFT_RIGHT_OFFSET_2D, 0.0);
406
let angle = time.elapsed_secs();
407
let isometry = Isometry2d::new(POSITION, Rot2::radians(angle));
408
let color = Color::WHITE;
409
410
#[expect(
411
clippy::match_same_arms,
412
reason = "Certain primitives don't have any 2D rendering support yet."
413
)]
414
match state.get() {
415
PrimitiveSelected::RectangleAndCuboid => {
416
gizmos.primitive_2d(&RECTANGLE, isometry, color);
417
}
418
PrimitiveSelected::CircleAndSphere => {
419
gizmos.primitive_2d(&CIRCLE, isometry, color);
420
}
421
PrimitiveSelected::Ellipse => drop(gizmos.primitive_2d(&ELLIPSE, isometry, color)),
422
PrimitiveSelected::Triangle => gizmos.primitive_2d(&TRIANGLE_2D, isometry, color),
423
PrimitiveSelected::Plane => gizmos.primitive_2d(&PLANE_2D, isometry, color),
424
PrimitiveSelected::Line => drop(gizmos.primitive_2d(&LINE2D, isometry, color)),
425
PrimitiveSelected::Segment => {
426
drop(gizmos.primitive_2d(&SEGMENT_2D, isometry, color));
427
}
428
PrimitiveSelected::Polyline => gizmos.primitive_2d(
429
&Polyline2d {
430
vertices: vec![
431
Vec2::new(-BIG_2D, -SMALL_2D),
432
Vec2::new(-SMALL_2D, SMALL_2D),
433
Vec2::new(SMALL_2D, -SMALL_2D),
434
Vec2::new(BIG_2D, SMALL_2D),
435
],
436
},
437
isometry,
438
color,
439
),
440
PrimitiveSelected::Polygon => gizmos.primitive_2d(
441
&Polygon {
442
vertices: vec![
443
Vec2::new(-BIG_2D, -SMALL_2D),
444
Vec2::new(BIG_2D, -SMALL_2D),
445
Vec2::new(BIG_2D, SMALL_2D),
446
Vec2::new(0.0, 0.0),
447
Vec2::new(-BIG_2D, SMALL_2D),
448
],
449
},
450
isometry,
451
color,
452
),
453
PrimitiveSelected::RegularPolygon => {
454
gizmos.primitive_2d(&REGULAR_POLYGON, isometry, color);
455
}
456
PrimitiveSelected::Capsule => gizmos.primitive_2d(&CAPSULE_2D, isometry, color),
457
PrimitiveSelected::Cylinder => {}
458
PrimitiveSelected::Cone => {}
459
PrimitiveSelected::ConicalFrustum => {}
460
PrimitiveSelected::Torus => drop(gizmos.primitive_2d(&ANNULUS, isometry, color)),
461
PrimitiveSelected::Tetrahedron => {}
462
PrimitiveSelected::Arc => gizmos.primitive_2d(&ARC, isometry, color),
463
PrimitiveSelected::CircularSector => {
464
gizmos.primitive_2d(&CIRCULAR_SECTOR, isometry, color);
465
}
466
PrimitiveSelected::CircularSegment => {
467
gizmos.primitive_2d(&CIRCULAR_SEGMENT, isometry, color);
468
}
469
}
470
}
471
472
/// Marker for primitive meshes to record in which state they should be visible in
473
#[derive(Debug, Clone, Component, Default, Reflect)]
474
pub struct PrimitiveData {
475
camera_mode: CameraActive,
476
primitive_state: PrimitiveSelected,
477
}
478
479
/// Marker for meshes of 2D primitives
480
#[derive(Debug, Clone, Component, Default)]
481
pub struct MeshDim2;
482
483
/// Marker for meshes of 3D primitives
484
#[derive(Debug, Clone, Component, Default)]
485
pub struct MeshDim3;
486
487
fn spawn_primitive_2d(
488
mut commands: Commands,
489
mut materials: ResMut<Assets<ColorMaterial>>,
490
mut meshes: ResMut<Assets<Mesh>>,
491
) {
492
const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_2D, 0.0, 0.0);
493
let material: Handle<ColorMaterial> = materials.add(Color::WHITE);
494
let camera_mode = CameraActive::Dim2;
495
[
496
Some(RECTANGLE.mesh().build()),
497
Some(CIRCLE.mesh().build()),
498
Some(ELLIPSE.mesh().build()),
499
Some(TRIANGLE_2D.mesh().build()),
500
None, // plane
501
None, // line
502
None, // segment
503
None, // polyline
504
None, // polygon
505
Some(REGULAR_POLYGON.mesh().build()),
506
Some(CAPSULE_2D.mesh().build()),
507
None, // cylinder
508
None, // cone
509
None, // conical frustum
510
Some(ANNULUS.mesh().build()),
511
None, // tetrahedron
512
]
513
.into_iter()
514
.zip(PrimitiveSelected::ALL)
515
.for_each(|(maybe_mesh, state)| {
516
if let Some(mesh) = maybe_mesh {
517
commands.spawn((
518
MeshDim2,
519
PrimitiveData {
520
camera_mode,
521
primitive_state: state,
522
},
523
Mesh2d(meshes.add(mesh)),
524
MeshMaterial2d(material.clone()),
525
Transform::from_translation(POSITION),
526
));
527
}
528
});
529
}
530
531
fn spawn_primitive_3d(
532
mut commands: Commands,
533
mut materials: ResMut<Assets<StandardMaterial>>,
534
mut meshes: ResMut<Assets<Mesh>>,
535
) {
536
const POSITION: Vec3 = Vec3::new(-LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
537
let material: Handle<StandardMaterial> = materials.add(Color::WHITE);
538
let camera_mode = CameraActive::Dim3;
539
[
540
Some(CUBOID.mesh().build()),
541
Some(SPHERE.mesh().build()),
542
None, // ellipse
543
Some(TRIANGLE_3D.mesh().build()),
544
Some(PLANE_3D.mesh().build()),
545
None, // line
546
None, // segment
547
None, // polyline
548
None, // polygon
549
None, // regular polygon
550
Some(CAPSULE_3D.mesh().build()),
551
Some(CYLINDER.mesh().build()),
552
None, // cone
553
None, // conical frustum
554
Some(TORUS.mesh().build()),
555
Some(TETRAHEDRON.mesh().build()),
556
]
557
.into_iter()
558
.zip(PrimitiveSelected::ALL)
559
.for_each(|(maybe_mesh, state)| {
560
if let Some(mesh) = maybe_mesh {
561
commands.spawn((
562
MeshDim3,
563
PrimitiveData {
564
camera_mode,
565
primitive_state: state,
566
},
567
Mesh3d(meshes.add(mesh)),
568
MeshMaterial3d(material.clone()),
569
Transform::from_translation(POSITION),
570
));
571
}
572
});
573
}
574
575
fn update_primitive_meshes(
576
camera_state: Res<State<CameraActive>>,
577
primitive_state: Res<State<PrimitiveSelected>>,
578
mut primitives: Query<(&mut Visibility, &PrimitiveData)>,
579
) {
580
primitives.iter_mut().for_each(|(mut vis, primitive)| {
581
let visible = primitive.camera_mode == *camera_state.get()
582
&& primitive.primitive_state == *primitive_state.get();
583
*vis = if visible {
584
Visibility::Inherited
585
} else {
586
Visibility::Hidden
587
};
588
});
589
}
590
591
fn rotate_primitive_2d_meshes(
592
mut primitives_2d: Query<
593
(&mut Transform, &ViewVisibility),
594
(With<PrimitiveData>, With<MeshDim2>),
595
>,
596
time: Res<Time>,
597
) {
598
let rotation_2d = Quat::from_mat3(&Mat3::from_angle(time.elapsed_secs()));
599
primitives_2d
600
.iter_mut()
601
.filter(|(_, vis)| vis.get())
602
.for_each(|(mut transform, _)| {
603
transform.rotation = rotation_2d;
604
});
605
}
606
607
fn rotate_primitive_3d_meshes(
608
mut primitives_3d: Query<
609
(&mut Transform, &ViewVisibility),
610
(With<PrimitiveData>, With<MeshDim3>),
611
>,
612
time: Res<Time>,
613
) {
614
let rotation_3d = Quat::from_rotation_arc(
615
Vec3::Z,
616
Vec3::new(
617
ops::sin(time.elapsed_secs()),
618
ops::cos(time.elapsed_secs()),
619
ops::sin(time.elapsed_secs()) * 0.5,
620
)
621
.try_normalize()
622
.unwrap_or(Vec3::Z),
623
);
624
primitives_3d
625
.iter_mut()
626
.filter(|(_, vis)| vis.get())
627
.for_each(|(mut transform, _)| {
628
transform.rotation = rotation_3d;
629
});
630
}
631
632
fn draw_gizmos_3d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
633
const POSITION: Vec3 = Vec3::new(LEFT_RIGHT_OFFSET_3D, 0.0, 0.0);
634
let rotation = Quat::from_rotation_arc(
635
Vec3::Z,
636
Vec3::new(
637
ops::sin(time.elapsed_secs()),
638
ops::cos(time.elapsed_secs()),
639
ops::sin(time.elapsed_secs()) * 0.5,
640
)
641
.try_normalize()
642
.unwrap_or(Vec3::Z),
643
);
644
let isometry = Isometry3d::new(POSITION, rotation);
645
let color = Color::WHITE;
646
let resolution = 10;
647
648
#[expect(
649
clippy::match_same_arms,
650
reason = "Certain primitives don't have any 3D rendering support yet."
651
)]
652
match state.get() {
653
PrimitiveSelected::RectangleAndCuboid => {
654
gizmos.primitive_3d(&CUBOID, isometry, color);
655
}
656
PrimitiveSelected::CircleAndSphere => drop(
657
gizmos
658
.primitive_3d(&SPHERE, isometry, color)
659
.resolution(resolution),
660
),
661
PrimitiveSelected::Ellipse => {}
662
PrimitiveSelected::Triangle => gizmos.primitive_3d(&TRIANGLE_3D, isometry, color),
663
PrimitiveSelected::Plane => drop(gizmos.primitive_3d(&PLANE_3D, isometry, color)),
664
PrimitiveSelected::Line => gizmos.primitive_3d(&LINE3D, isometry, color),
665
PrimitiveSelected::Segment => gizmos.primitive_3d(&SEGMENT_3D, isometry, color),
666
PrimitiveSelected::Polyline => gizmos.primitive_3d(
667
&Polyline3d {
668
vertices: vec![
669
Vec3::new(-BIG_3D, -SMALL_3D, -SMALL_3D),
670
Vec3::new(SMALL_3D, SMALL_3D, 0.0),
671
Vec3::new(-SMALL_3D, -SMALL_3D, 0.0),
672
Vec3::new(BIG_3D, SMALL_3D, SMALL_3D),
673
],
674
},
675
isometry,
676
color,
677
),
678
PrimitiveSelected::Polygon => {}
679
PrimitiveSelected::RegularPolygon => {}
680
PrimitiveSelected::Capsule => drop(
681
gizmos
682
.primitive_3d(&CAPSULE_3D, isometry, color)
683
.resolution(resolution),
684
),
685
PrimitiveSelected::Cylinder => drop(
686
gizmos
687
.primitive_3d(&CYLINDER, isometry, color)
688
.resolution(resolution),
689
),
690
PrimitiveSelected::Cone => drop(
691
gizmos
692
.primitive_3d(&CONE, isometry, color)
693
.resolution(resolution),
694
),
695
PrimitiveSelected::ConicalFrustum => {
696
gizmos.primitive_3d(&CONICAL_FRUSTUM, isometry, color);
697
}
698
699
PrimitiveSelected::Torus => drop(
700
gizmos
701
.primitive_3d(&TORUS, isometry, color)
702
.minor_resolution(resolution)
703
.major_resolution(resolution),
704
),
705
PrimitiveSelected::Tetrahedron => {
706
gizmos.primitive_3d(&TETRAHEDRON, isometry, color);
707
}
708
709
PrimitiveSelected::Arc => {}
710
PrimitiveSelected::CircularSector => {}
711
PrimitiveSelected::CircularSegment => {}
712
}
713
}
714
715