//! This example demonstrates how you can add your own custom primitives to bevy highlighting //! traits you may want to implement for your primitives to achieve different functionalities. use std::f32::consts::{PI, SQRT_2}; use bevy::{ color::palettes::css::{RED, WHITE}, input::common_conditions::input_just_pressed, math::{ bounding::{ Aabb2d, Bounded2d, Bounded3d, BoundedExtrusion, BoundingCircle, BoundingVolume, }, Isometry2d, }, prelude::*, render::{ camera::ScalingMode, mesh::{Extrudable, ExtrusionBuilder, PerimeterSegment}, render_asset::RenderAssetUsages, }, }; const HEART: Heart = Heart::new(0.5); const EXTRUSION: Extrusion = Extrusion { base_shape: Heart::new(0.5), half_depth: 0.5, }; // The transform of the camera in 2D const TRANSFORM_2D: Transform = Transform { translation: Vec3::ZERO, rotation: Quat::IDENTITY, scale: Vec3::ONE, }; // The projection used for the camera in 2D const PROJECTION_2D: Projection = Projection::Orthographic(OrthographicProjection { near: -1.0, far: 10.0, scale: 1.0, viewport_origin: Vec2::new(0.5, 0.5), scaling_mode: ScalingMode::AutoMax { max_width: 8.0, max_height: 20.0, }, area: Rect { min: Vec2::NEG_ONE, max: Vec2::ONE, }, }); // The transform of the camera in 3D const TRANSFORM_3D: Transform = Transform { translation: Vec3::ZERO, // The camera is pointing at the 3D shape rotation: Quat::from_xyzw(-0.14521316, -0.0, -0.0, 0.98940045), scale: Vec3::ONE, }; // The projection used for the camera in 3D const PROJECTION_3D: Projection = Projection::Perspective(PerspectiveProjection { fov: PI / 4.0, near: 0.1, far: 1000.0, aspect_ratio: 1.0, }); /// State for tracking the currently displayed shape #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, States, Default, Reflect)] enum CameraActive { #[default] /// The 2D shape is displayed Dim2, /// The 3D shape is displayed Dim3, } /// State for tracking the currently displayed shape #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, States, Default, Reflect)] enum BoundingShape { #[default] /// No bounding shapes None, /// The bounding sphere or circle of the shape BoundingSphere, /// The Axis Aligned Bounding Box (AABB) of the shape BoundingBox, } /// A marker component for our 2D shapes so we can query them separately from the camera #[derive(Component)] struct Shape2d; /// A marker component for our 3D shapes so we can query them separately from the camera #[derive(Component)] struct Shape3d; fn main() { App::new() .add_plugins(DefaultPlugins) .init_state::() .init_state::() .add_systems(Startup, setup) .add_systems( Update, ( (rotate_2d_shapes, bounding_shapes_2d).run_if(in_state(CameraActive::Dim2)), (rotate_3d_shapes, bounding_shapes_3d).run_if(in_state(CameraActive::Dim3)), update_bounding_shape.run_if(input_just_pressed(KeyCode::KeyB)), switch_cameras.run_if(input_just_pressed(KeyCode::Space)), ), ) .run(); } fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { // Spawn the camera commands.spawn(Camera3dBundle { transform: TRANSFORM_2D, projection: PROJECTION_2D, ..Default::default() }); // Spawn the 2D heart commands.spawn(( PbrBundle { // We can use the methods defined on the meshbuilder to customize the mesh. mesh: meshes.add(HEART.mesh().resolution(50)), material: materials.add(StandardMaterial { emissive: RED.into(), base_color: RED.into(), ..Default::default() }), transform: Transform::from_xyz(0.0, 0.0, 0.0), ..default() }, Shape2d, )); // Spawn an extrusion of the heart. commands.spawn(( PbrBundle { transform: Transform::from_xyz(0., -3., -10.) .with_rotation(Quat::from_rotation_x(-PI / 4.)), // We can set a custom resolution for the round parts of the extrusion aswell. mesh: meshes.add(EXTRUSION.mesh().resolution(50)), material: materials.add(StandardMaterial { base_color: RED.into(), ..Default::default() }), ..Default::default() }, Shape3d, )); // Point light for 3D commands.spawn(PointLightBundle { point_light: PointLight { shadows_enabled: true, intensity: 10_000_000., range: 100.0, shadow_depth_bias: 0.2, ..default() }, transform: Transform::from_xyz(8.0, 12.0, 1.0), ..default() }); // Example instructions commands.spawn( TextBundle::from_section( "Press 'B' to toggle between no bounding shapes, bounding boxes (AABBs) and bounding spheres / circles\n\ Press 'Space' to switch between 3D and 2D", TextStyle::default(), ) .with_style(Style { position_type: PositionType::Absolute, top: Val::Px(12.0), left: Val::Px(12.0), ..default() }), ); } // Rotate the 2D shapes. fn rotate_2d_shapes(mut shapes: Query<&mut Transform, With>, time: Res