Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example for Camera::viewport_to_world #7179

Merged
merged 14 commits into from
Sep 11, 2023
21 changes: 21 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,16 @@ description = "Changes the transform of a sprite"
category = "2D Rendering"
wasm = true

[[example]]
name = "2d_viewport_to_world"
path = "examples/2d/2d_viewport_to_world.rs"

[package.metadata.example.2d_viewport_to_world]
name = "2D Viewport To World"
description = "Demonstrates how to use the `Camera::viewport_to_world_2d` method"
category = "2D Rendering"
wasm = true

[[example]]
name = "rotation"
path = "examples/2d/rotation.rs"
Expand Down Expand Up @@ -467,6 +477,17 @@ description = "A scene showcasing the built-in 3D shapes"
category = "3D Rendering"
wasm = true

[[example]]
name = "3d_viewport_to_world"
path = "examples/3d/3d_viewport_to_world.rs"
doc-scrape-examples = true

[package.metadata.example.3d_viewport_to_world]
name = "3D Viewport To World"
description = "Demonstrates how to use the `Camera::viewport_to_world` method"
category = "3D Rendering"
wasm = true

[[example]]
name = "generate_custom_mesh"
path = "examples/3d/generate_custom_mesh.rs"
Expand Down
34 changes: 34 additions & 0 deletions examples/2d/2d_viewport_to_world.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//! This example demonstrates how to use the `Camera::viewport_to_world_2d` method.

use bevy::prelude::*;

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, draw_cursor)
.run();
}

fn draw_cursor(
camera_query: Query<(&Camera, &GlobalTransform)>,
windows: Query<&Window>,
mut gizmos: Gizmos,
) {
let (camera, camera_transform) = camera_query.single();

let Some(cursor_position) = windows.single().cursor_position() else {
return;
};

// Calculate a world position based on the cursor's position.
let Some(point) = camera.viewport_to_world_2d(camera_transform, cursor_position) else {
return;
};

gizmos.circle_2d(point, 10., Color::WHITE);
}

fn setup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
}
70 changes: 70 additions & 0 deletions examples/3d/3d_viewport_to_world.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//! This example demonstrates how to use the `Camera::viewport_to_world` method.

use bevy::prelude::*;

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, draw_cursor)
.run();
}

fn draw_cursor(
camera_query: Query<(&Camera, &GlobalTransform)>,
ground_query: Query<&GlobalTransform, With<Ground>>,
windows: Query<&Window>,
mut gizmos: Gizmos,
) {
let (camera, camera_transform) = camera_query.single();
let ground = ground_query.single();

let Some(cursor_position) = windows.single().cursor_position() else {
return;
};

// Calculate a ray pointing from the camera into the world based on the cursor's position.
let Some(ray) = camera.viewport_to_world(camera_transform, cursor_position) else {
return;
};

// Calculate if and where the ray is hitting the ground plane.
let Some(distance) = ray.intersect_plane(ground.translation(), ground.up()) else {
return;
};
let point = ray.get_point(distance);

// Draw a circle just above the ground plane at that position.
gizmos.circle(point + ground.up() * 0.01, ground.up(), 0.2, Color::WHITE);
}

#[derive(Component)]
struct Ground;

fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// plane
commands.spawn((
PbrBundle {
mesh: meshes.add(shape::Plane::from_size(20.).into()),
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
..default()
},
Ground,
));

// light
commands.spawn(DirectionalLightBundle {
transform: Transform::from_translation(Vec3::ONE).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});

// camera
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(15.0, 5.0, 15.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
2 changes: 2 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ Example | Description
[2D Gizmos](../examples/2d/2d_gizmos.rs) | A scene showcasing 2D gizmos
[2D Rotation](../examples/2d/rotation.rs) | Demonstrates rotating entities in 2D with quaternions
[2D Shapes](../examples/2d/2d_shapes.rs) | Renders a rectangle, circle, and hexagon
[2D Viewport To World](../examples/2d/2d_viewport_to_world.rs) | Demonstrates how to use the `Camera::viewport_to_world_2d` method
[Custom glTF vertex attribute 2D](../examples/2d/custom_gltf_vertex_attribute.rs) | Renders a glTF mesh in 2D with a custom vertex attribute
[Manual Mesh 2D](../examples/2d/mesh2d_manual.rs) | Renders a custom mesh "manually" with "mid-level" renderer apis
[Mesh 2D](../examples/2d/mesh2d.rs) | Renders a 2d mesh
Expand All @@ -116,6 +117,7 @@ Example | Description
[3D Gizmos](../examples/3d/3d_gizmos.rs) | A scene showcasing 3D gizmos
[3D Scene](../examples/3d/3d_scene.rs) | Simple 3D scene with basic shapes and lighting
[3D Shapes](../examples/3d/3d_shapes.rs) | A scene showcasing the built-in 3D shapes
[3D Viewport To World](../examples/3d/3d_viewport_to_world.rs) | Demonstrates how to use the `Camera::viewport_to_world` method
[Anti-aliasing](../examples/3d/anti_aliasing.rs) | Compares different anti-aliasing methods
[Atmospheric Fog](../examples/3d/atmospheric_fog.rs) | A scene showcasing the atmospheric fog effect
[Blend Modes](../examples/3d/blend_modes.rs) | Showcases different blend modes
Expand Down
Loading