rendering code and api crate
This commit is contained in:
102
crates/bevy_xr/src/camera.rs
Normal file
102
crates/bevy_xr/src/camera.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
use bevy::app::{App, Plugin};
|
||||
use bevy::core_pipeline::core_3d::graph::Core3d;
|
||||
use bevy::core_pipeline::core_3d::Camera3d;
|
||||
use bevy::core_pipeline::tonemapping::{DebandDither, Tonemapping};
|
||||
use bevy::ecs::bundle::Bundle;
|
||||
use bevy::ecs::component::Component;
|
||||
use bevy::ecs::reflect::ReflectComponent;
|
||||
use bevy::math::{Mat4, Vec3A};
|
||||
use bevy::reflect::Reflect;
|
||||
use bevy::render::camera::{
|
||||
Camera, CameraMainTextureUsages, CameraProjection, CameraProjectionPlugin, CameraRenderGraph,
|
||||
Exposure,
|
||||
};
|
||||
use bevy::render::primitives::Frustum;
|
||||
use bevy::render::view::{ColorGrading, VisibleEntities};
|
||||
use bevy::transform::components::{GlobalTransform, Transform};
|
||||
|
||||
pub struct XrCameraPlugin;
|
||||
|
||||
impl Plugin for XrCameraPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_plugins(CameraProjectionPlugin::<XrProjection>::default());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Component, Reflect, Debug)]
|
||||
#[reflect(Component)]
|
||||
pub struct XrProjection {
|
||||
pub projection_matrix: Mat4,
|
||||
pub near: f32,
|
||||
pub far: f32,
|
||||
}
|
||||
|
||||
impl Default for XrProjection {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
near: 0.1,
|
||||
far: 1000.,
|
||||
projection_matrix: Mat4::IDENTITY,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker component for an XR view. It is the backends responsibility to update this.
|
||||
#[derive(Clone, Copy, Component, Debug, Default)]
|
||||
pub struct XrView;
|
||||
|
||||
impl CameraProjection for XrProjection {
|
||||
fn get_projection_matrix(&self) -> Mat4 {
|
||||
self.projection_matrix
|
||||
}
|
||||
|
||||
fn update(&mut self, _width: f32, _height: f32) {}
|
||||
|
||||
fn far(&self) -> f32 {
|
||||
self.far
|
||||
}
|
||||
|
||||
// TODO calculate this properly
|
||||
fn get_frustum_corners(&self, _z_near: f32, _z_far: f32) -> [Vec3A; 8] {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub struct XrCameraBundle {
|
||||
pub camera: Camera,
|
||||
pub camera_render_graph: CameraRenderGraph,
|
||||
pub projection: XrProjection,
|
||||
pub visible_entities: VisibleEntities,
|
||||
pub frustum: Frustum,
|
||||
pub transform: Transform,
|
||||
pub global_transform: GlobalTransform,
|
||||
pub camera_3d: Camera3d,
|
||||
pub tonemapping: Tonemapping,
|
||||
pub dither: DebandDither,
|
||||
pub color_grading: ColorGrading,
|
||||
pub exposure: Exposure,
|
||||
pub main_texture_usages: CameraMainTextureUsages,
|
||||
pub view: XrView,
|
||||
}
|
||||
|
||||
impl Default for XrCameraBundle {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
camera_render_graph: CameraRenderGraph::new(Core3d),
|
||||
camera: Default::default(),
|
||||
projection: Default::default(),
|
||||
visible_entities: Default::default(),
|
||||
frustum: Default::default(),
|
||||
transform: Default::default(),
|
||||
global_transform: Default::default(),
|
||||
camera_3d: Default::default(),
|
||||
tonemapping: Default::default(),
|
||||
color_grading: Default::default(),
|
||||
exposure: Default::default(),
|
||||
main_texture_usages: Default::default(),
|
||||
dither: DebandDither::Enabled,
|
||||
view: XrView,
|
||||
}
|
||||
}
|
||||
}
|
||||
2
crates/bevy_xr/src/lib.rs
Normal file
2
crates/bevy_xr/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod camera;
|
||||
pub mod session;
|
||||
89
crates/bevy_xr/src/session.rs
Normal file
89
crates/bevy_xr/src/session.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use bevy::app::{App, Plugin, PreUpdate};
|
||||
use bevy::ecs::event::{Event, EventReader, EventWriter};
|
||||
use bevy::ecs::system::Local;
|
||||
|
||||
pub struct XrSessionPlugin;
|
||||
|
||||
impl Plugin for XrSessionPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_event::<CreateXrSession>()
|
||||
.add_event::<BeginXrSession>()
|
||||
.add_event::<EndXrSession>()
|
||||
.add_event::<XrSessionState>()
|
||||
.add_event::<XrInstanceCreated>()
|
||||
.add_event::<XrInstanceDestroyed>()
|
||||
.add_systems(PreUpdate, handle_xr_events);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_xr_events(
|
||||
mut instance_created: EventReader<XrInstanceCreated>,
|
||||
mut session_state: EventReader<XrSessionState>,
|
||||
mut instance_destroyed: EventReader<XrInstanceDestroyed>,
|
||||
mut create_session: EventWriter<CreateXrSession>,
|
||||
mut begin_session: EventWriter<BeginXrSession>,
|
||||
mut has_instance: Local<bool>,
|
||||
mut local_session_state: Local<Option<XrSessionState>>,
|
||||
) {
|
||||
// Don't do anything if no events recieved
|
||||
if instance_created.is_empty() && instance_destroyed.is_empty() && session_state.is_empty() {
|
||||
return;
|
||||
}
|
||||
if !instance_created.is_empty() {
|
||||
*has_instance = true;
|
||||
instance_created.clear();
|
||||
}
|
||||
if !instance_destroyed.is_empty() {
|
||||
*has_instance = false;
|
||||
instance_destroyed.clear();
|
||||
}
|
||||
for state in session_state.read() {
|
||||
*local_session_state = Some(*state);
|
||||
}
|
||||
if *has_instance {
|
||||
if local_session_state.is_none() {
|
||||
create_session.send_default();
|
||||
} else if matches!(*local_session_state, Some(XrSessionState::Ready)) {
|
||||
begin_session.send_default();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Event sent to backends to create an XR session
|
||||
#[derive(Event, Clone, Copy, Default)]
|
||||
pub struct CreateXrSession;
|
||||
|
||||
/// Event sent to backends to begin an XR session
|
||||
#[derive(Event, Clone, Copy, Default)]
|
||||
pub struct BeginXrSession;
|
||||
|
||||
/// Event sent to backends to end an XR session.
|
||||
#[derive(Event, Clone, Copy, Default)]
|
||||
pub struct EndXrSession;
|
||||
|
||||
// /// Event sent to backends to destroy an XR session.
|
||||
// #[derive(Event, Clone, Copy, Default)]
|
||||
// pub struct DestroyXrSession;
|
||||
|
||||
/// Event sent from backends to inform the frontend of the session state.
|
||||
#[derive(Event, Clone, Copy)]
|
||||
pub enum XrSessionState {
|
||||
/// The session is in an idle state. Either just created or stopped
|
||||
Idle,
|
||||
/// The session is ready. You may send a [`BeginXrSession`] event.
|
||||
Ready,
|
||||
/// The session is running.
|
||||
Running,
|
||||
/// The session is being stopped
|
||||
Stopping,
|
||||
/// The session is destroyed
|
||||
Destroyed,
|
||||
}
|
||||
|
||||
/// Event sent from backends to inform the frontend that the instance was created.
|
||||
#[derive(Event, Clone, Copy, Default)]
|
||||
pub struct XrInstanceCreated;
|
||||
|
||||
/// Event sent from backends to inform the frontend that the instance was destroyed.
|
||||
#[derive(Event, Clone, Copy, Default)]
|
||||
pub struct XrInstanceDestroyed;
|
||||
Reference in New Issue
Block a user