Offscreen rendering with view swap

This commit is contained in:
hodasemi 2023-05-15 08:48:46 +02:00
parent 13a912d228
commit 87cf72bbe5
2 changed files with 95 additions and 185 deletions

View file

@ -106,9 +106,6 @@ fn update_ui_side_panel(
mut global_state: ResMut<GlobalState>, mut global_state: ResMut<GlobalState>,
mut object_infos: ResMut<ObjectInfos>, mut object_infos: ResMut<ObjectInfos>,
mut commands: Commands, mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut standard_materials: ResMut<Assets<StandardMaterial>>,
mut color_materials: ResMut<Assets<ColorMaterial>>,
) { ) {
let offscreen_texture_id = contexts.image_id(&global_state.offscreen_image).unwrap(); let offscreen_texture_id = contexts.image_id(&global_state.offscreen_image).unwrap();
@ -127,32 +124,53 @@ fn update_ui_side_panel(
if ui.button("Change to 3D View").clicked() { if ui.button("Change to 3D View").clicked() {
global_state.view_2d = false; global_state.view_2d = false;
// object_infos.iter_mut().for_each(|polygon| { // remove render layer and add camera with default render target
// polygon.swap_to_3d( let mut cam_3d = commands.entity(global_state.camera_3d);
// &global_state, cam_3d.remove::<RenderLayers>();
// &mut commands, cam_3d.remove::<Camera>();
// &mut meshes, cam_3d.insert(Camera::default());
// &mut standard_materials,
// ) // add render layer and add camera with offscreen render target
// }); let mut cam_2d = commands.entity(global_state.camera_2d);
cam_2d.insert(global_state.offscreen_render_layer);
cam_2d.remove::<Camera>();
cam_2d.insert(Camera {
target: RenderTarget::Image(global_state.offscreen_image.clone()),
..default()
});
object_infos
.iter_mut()
.for_each(|polygon| polygon.swap_to_3d(&global_state, &mut commands));
} }
} else { } else {
if ui.button("Change to 2D View").clicked() { if ui.button("Change to 2D View").clicked() {
global_state.view_2d = true; global_state.view_2d = true;
// object_infos.iter_mut().for_each(|polygon| { // add render layer and add camera with offscreen render target
// polygon.swap_to_2d( let mut cam_3d = commands.entity(global_state.camera_3d);
// &global_state, cam_3d.insert(global_state.offscreen_render_layer);
// &mut commands, cam_3d.remove::<Camera>();
// &mut meshes, cam_3d.insert(Camera {
// &mut color_materials, target: RenderTarget::Image(global_state.offscreen_image.clone()),
// ) ..default()
// }); });
// remove render layer and add camera with default render target
let mut cam_2d = commands.entity(global_state.camera_2d);
cam_2d.remove::<RenderLayers>();
cam_2d.remove::<Camera>();
cam_2d.insert(Camera::default());
object_infos
.iter_mut()
.for_each(|polygon| polygon.swap_to_2d(&global_state, &mut commands));
} }
} }
if global_state.view_2d { if global_state.view_2d {
if global_state.polygon_started { if global_state.polygon_started {
// print list of coordinates of current polygon
if let Some(polygon) = object_infos.active_polygon() { if let Some(polygon) = object_infos.active_polygon() {
for (index, point) in polygon.points().iter().enumerate() { for (index, point) in polygon.points().iter().enumerate() {
ui.label(&format!("{}: ({}, {})", index, point.x, point.y)); ui.label(&format!("{}: ({}, {})", index, point.x, point.y));
@ -228,9 +246,11 @@ fn on_resize_system(
// When resolution is being changed // When resolution is being changed
global_state.window_extent = Vec2::new(e.width, e.height); global_state.window_extent = Vec2::new(e.width, e.height);
let center = (global_state.window_extent * 0.5).extend(0.0);
for mut transform in &mut camera { for mut transform in &mut camera {
*transform = Transform::from_xyz(200.0, -600.0, 600.0) *transform = Transform::from_xyz(center.x + 200.0, center.y - 600.0, 600.0)
.looking_at((global_state.window_extent * 0.5).extend(0.0), Vec3::Z); .looking_at(center, Vec3::Z);
} }
} }
} }

View file

@ -2,7 +2,7 @@ use std::slice::IterMut;
use bevy::{ use bevy::{
prelude::*, prelude::*,
render::{mesh::Indices, render_resource::PrimitiveTopology}, render::{mesh::Indices, render_resource::PrimitiveTopology, view::RenderLayers},
sprite::MaterialMesh2dBundle, sprite::MaterialMesh2dBundle,
}; };
@ -16,7 +16,10 @@ struct CollectionIDs {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
struct FinishedIDs { struct FinishedIDs {
// 2d plane
plane: Entity, plane: Entity,
// 3d object
object: Entity, object: Entity,
} }
@ -50,178 +53,65 @@ pub struct Polygon {
impl Polygon { impl Polygon {
const PROXIMITY_THRESHOLD: f32 = 10.0; const PROXIMITY_THRESHOLD: f32 = 10.0;
// pub fn swap_to_3d( pub fn swap_to_3d(&mut self, global_state: &GlobalState, commands: &mut Commands) {
// &mut self, match &self.state {
// global_state: &GlobalState, PolygonState::Collection(collection_ids) => {
// commands: &mut Commands, // add render layer to all points
// meshes: &mut ResMut<Assets<Mesh>>, for point in collection_ids.points.iter() {
// materials: &mut ResMut<Assets<StandardMaterial>>, let mut handle = commands.entity(*point);
// ) {
// debug_assert!(self.state.is_2d());
// // clear all 2d entities handle.insert(global_state.offscreen_render_layer);
// let finished = match self.state.two_dimensional_mut() { }
// PolygonState::Collection(collection_ids) => {
// for point in collection_ids.points.iter() {
// commands.entity(*point).despawn();
// }
// for line in collection_ids.lines.iter() { // also add render layer to all lines
// commands.entity(*line).despawn(); for line in collection_ids.points.iter() {
// } let mut handle = commands.entity(*line);
// false handle.insert(global_state.offscreen_render_layer);
// } }
// PolygonState::Finished(mesh) => { }
// commands.entity(*mesh).despawn(); PolygonState::Finished(finished_ids) => {
// add render layer to 2d plane
commands
.entity(finished_ids.plane)
.insert(global_state.offscreen_render_layer);
// true // remove render layer from 3d object
// } commands
// }; .entity(finished_ids.object)
.remove::<RenderLayers>();
}
}
}
// self.state = PolygonView::ThreeDimensional(if finished { pub fn swap_to_2d(&mut self, global_state: &GlobalState, commands: &mut Commands) {
// let vertices: Vec<Vec3> = self match &self.state {
// .points PolygonState::Collection(collection_ids) => {
// .iter() // remove render layer from all points
// .map(|p| vec![p.extend(0.0), p.extend(global_state.extrusion_height)]) for point in collection_ids.points.iter() {
// .flatten() let mut handle = commands.entity(*point);
// .collect();
// let indices = Indices::U32({ handle.remove::<RenderLayers>();
// let mut v = Vec::new(); }
// for i in 0..self.points.len() { // remove render layer from all lines
// let index = (i as u32) * 2; for line in collection_ids.points.iter() {
let mut handle = commands.entity(*line);
// // create quads from 4 adjacent points handle.remove::<RenderLayers>();
// v.push(index); }
// v.push((index + 2) % vertices.len() as u32); }
// v.push(index + 1); PolygonState::Finished(finished_ids) => {
// v.push(index + 1); // remove render layer from 2d plane
// v.push((index + 2) % vertices.len() as u32); commands.entity(finished_ids.plane).remove::<RenderLayers>();
// v.push((index + 3) % vertices.len() as u32);
// }
// // TODO: proper ear cutting algo // add render layer to 3d object
// for i in 2..self.points.len() as u32 { commands
// let index = (i as u32) * 2 + 1; .entity(finished_ids.object)
.insert(global_state.offscreen_render_layer);
// v.push(1); }
// v.push(index - 2); }
// v.push(index); }
// }
// v
// });
// let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
// mesh.set_indices(Some(indices));
// mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, vertices);
// let mesh_id = commands
// .spawn(MaterialMeshBundle {
// mesh: meshes.add(mesh).into(),
// transform: Transform::default(),
// material: materials.add(StandardMaterial::from(Color::BLACK)),
// ..default()
// })
// .id();
// Some(mesh_id)
// } else {
// None
// });
// }
// pub fn swap_to_2d(
// &mut self,
// global_state: &GlobalState,
// commands: &mut Commands,
// meshes: &mut ResMut<Assets<Mesh>>,
// materials: &mut ResMut<Assets<ColorMaterial>>,
// ) {
// debug_assert!(self.state.is_3d());
// // clear 3d entity
// let finished = match self.state.three_dimensional_mut() {
// Some(mesh_id) => {
// commands.entity(*mesh_id).despawn();
// true
// }
// None => false,
// };
// self.state = PolygonView::TwoDimensional(if finished {
// // create triangle mesh
// let triangle_mesh = self.create_triangulated_mesh();
// let triangle_id = commands
// .spawn(MaterialMesh2dBundle {
// mesh: meshes.add(triangle_mesh).into(),
// transform: Transform::default()
// .with_translation((-global_state.window_extent * 0.5).extend(0.0)),
// material: materials.add(ColorMaterial::from(Color::BLACK)),
// ..default()
// })
// .id();
// // store triangle entity id in state
// PolygonState::Finished(triangle_id)
// } else {
// // create point meshes for every point
// let point_ids = self
// .points
// .iter()
// .map(|&point| {
// commands
// .spawn(MaterialMesh2dBundle {
// mesh: meshes.add(Mesh::from(shape::Quad::default())).into(),
// transform: Transform::default()
// .with_scale(Vec3::splat(4.0))
// .with_translation(
// (point - (global_state.window_extent * 0.5)).extend(0.0),
// ),
// material: materials.add(ColorMaterial::from(Color::BLACK)),
// ..default()
// })
// .id()
// })
// .collect();
// // draw lines between the points
// let line_ids = (1..self.points.len())
// .map(|i| {
// let previous_point = self.points[i - 1];
// let point = self.points[i];
// let a = Vec2::X.angle_between((point - previous_point).normalize());
// commands
// .spawn(MaterialMesh2dBundle {
// mesh: meshes
// .add(Self::create_line_mesh(previous_point, point))
// .into(),
// transform: Transform::default()
// .with_translation(
// (previous_point - (global_state.window_extent * 0.5))
// .extend(0.0),
// )
// .with_rotation(Quat::from_rotation_z(a)),
// material: materials.add(ColorMaterial::from(Color::BLACK)),
// ..default()
// })
// .id()
// })
// .collect();
// PolygonState::Collection(CollectionIDs {
// points: point_ids,
// lines: line_ids,
// })
// });
// }
pub fn points(&self) -> &[Vec2] { pub fn points(&self) -> &[Vec2] {
&self.points &self.points