halfway through imgui, the context is really not ergonomic

master
mitchellhansen 4 years ago
parent 60ab3bebd8
commit 2370ce4974

@ -15,7 +15,7 @@ typed-arena = "2.0.1"
serde = { version = "1", features = ["derive"], optional = true } serde = { version = "1", features = ["derive"], optional = true }
log = "0.4" log = "0.4"
png = "0.16" png = "0.16"
winit = { version = "0.22.1", features = ["web-sys"] } winit = "0.24.0"
rand = { version = "0.7.2", features = ["wasm-bindgen"] } rand = { version = "0.7.2", features = ["wasm-bindgen"] }
bytemuck = "1" bytemuck = "1"
noise = "0.6" noise = "0.6"
@ -29,4 +29,7 @@ cgmath = "0.18.0"
rapier3d = { version = "0.5.0", features = ["simd-nightly", "parallel"] } rapier3d = { version = "0.5.0", features = ["simd-nightly", "parallel"] }
nalgebra = "0.24.1" nalgebra = "0.24.1"
legion = "0.3.1" legion = "0.3.1"
wgpu = "0.7.0" wgpu = "0.7.0"
imgui = "0.7.0"
imgui-wgpu = "0.14.0"
imgui-winit-support = "0.7.0"

@ -136,16 +136,14 @@ impl CameraController {
pub fn update_camera(&mut self, camera: &mut Camera, dt: f32) { pub fn update_camera(&mut self, camera: &mut Camera, dt: f32) {
// Move forward/backward and left/right // Move forward/backward and left/right
let (yaw_sin, yaw_cos) = camera.yaw.0.sin_cos();
let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize();
let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize();
let view_vector = Vector3::new( let view_vector = Vector3::new(
(1.0 * camera.pitch.0.sin() * camera.yaw.0.sin()), (1.0 * camera.pitch.0.sin() * camera.yaw.0.sin()),
(1.0 * camera.pitch.0.cos()), (1.0 * camera.pitch.0.cos()),
(1.0 * camera.pitch.0.sin() * camera.yaw.0.cos()), (1.0 * camera.pitch.0.sin() * camera.yaw.0.cos()),
); );
// Offset the yaw 90 degrees and set the pitch to level for our
// right / left hand translation vectors
let offset = camera.yaw.0 + PI/2.0; let offset = camera.yaw.0 + PI/2.0;
let pitch = PI/2.0; let pitch = PI/2.0;
let left_vector = Vector3::new( let left_vector = Vector3::new(
@ -156,19 +154,12 @@ impl CameraController {
camera.position += view_vector * (self.amount_forward - self.amount_backward) * self.speed * dt; camera.position += view_vector * (self.amount_forward - self.amount_backward) * self.speed * dt;
camera.position += left_vector * (self.amount_left - self.amount_right) * self.speed * dt; camera.position += left_vector * (self.amount_left - self.amount_right) * self.speed * dt;
// Move up/down. Since we don't use roll, we can just
// modify the y coordinate directly.
camera.position.y += (self.amount_up - self.amount_down) * self.speed * dt; camera.position.y += (self.amount_up - self.amount_down) * self.speed * dt;
// Rotate // Rotate
camera.yaw += Rad(self.rotate_horizontal) * self.sensitivity * dt; camera.yaw += Rad(self.rotate_horizontal) * self.sensitivity * dt;
camera.pitch += Rad(self.rotate_vertical) * self.sensitivity * dt; camera.pitch += Rad(self.rotate_vertical) * self.sensitivity * dt;
// If process_mouse isn't called every frame, these values
// will not get set to zero, and the camera will rotate
// when moving in a non cardinal direction.
self.rotate_horizontal = 0.0; self.rotate_horizontal = 0.0;
self.rotate_vertical = 0.0; self.rotate_vertical = 0.0;

@ -61,17 +61,4 @@ pub fn import_mesh(mesh_path: &str) -> (Vec<Vertex>, Vec<u32>) {
} }
(vertex_data.to_vec(), index_data.to_vec()) (vertex_data.to_vec(), index_data.to_vec())
}
pub fn create_plane(size: f32) -> (Vec<Vertex>, Vec<u32>) {
let vertex_data = [
vertex([size, -size, 0.0], [0.0, 0.0, 1.0]),
vertex([size, size, 0.0], [0.0, 0.0, 1.0]),
vertex([-size, -size, 0.0], [0.0, 0.0, 1.0]),
vertex([-size, size, 0.0], [0.0, 0.0, 1.0]),
];
let index_data: &[u32] = &[0, 1, 2, 2, 1, 3];
(vertex_data.to_vec(), index_data.to_vec())
} }

@ -1,3 +1,6 @@
extern crate imgui;
extern crate imgui_wgpu;
extern crate imgui_winit_support;
extern crate tobj; extern crate tobj;
extern crate winit; extern crate winit;
@ -8,9 +11,17 @@ use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use bytemuck::__core::ops::Range; use bytemuck::__core::ops::Range;
use cgmath::{Decomposed, Deg, Euler, InnerSpace, Quaternion, Rotation3, SquareMatrix, Point3, Rad}; use cgmath::{
Decomposed, Deg, Euler, InnerSpace, Point3, Quaternion, Rad, Rotation3, SquareMatrix,
};
use futures::executor::block_on;
use futures::task::LocalSpawn; use futures::task::LocalSpawn;
use gilrs::{Gamepad, Gilrs};
use gilrs::Event as GilEvent;
use imgui::*;
use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig};
use legion::*; use legion::*;
use rapier3d::counters::Timer;
use rapier3d::dynamics::{ use rapier3d::dynamics::{
IntegrationParameters, JointSet, RigidBody, RigidBodyBuilder, RigidBodyHandle, RigidBodySet, IntegrationParameters, JointSet, RigidBody, RigidBodyBuilder, RigidBodyHandle, RigidBodySet,
}; };
@ -20,30 +31,27 @@ use rapier3d::na::{Isometry, Isometry3, Vector, Vector3};
use rapier3d::pipeline::PhysicsPipeline; use rapier3d::pipeline::PhysicsPipeline;
use wgpu::{BindGroup, Buffer, TextureView}; use wgpu::{BindGroup, Buffer, TextureView};
use wgpu_subscriber; use wgpu_subscriber;
use winit::event::DeviceEvent::MouseMotion;
use winit::platform::unix::x11::ffi::Time;
use winit::{ use winit::{
event::{self, WindowEvent}, event::{self, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
}; };
use winit::event::DeviceEvent::MouseMotion;
use winit::platform::unix::x11::ffi::Time;
use winit::window::Window;
use gilrs::Event as GilEvent; use crate::camera::{Camera, CameraController};
use crate::components::{Collider, Color, LoopState, Physics, Position};
use crate::camera::{CameraController, Camera}; use crate::owned_event::{OwnedEvent, OwnedEventExtension};
use crate::components::{Collider, Color, Physics, Position, LoopState};
use crate::physics::PhysicsState; use crate::physics::PhysicsState;
use crate::render::Renderer; use crate::render::Renderer;
use crate::owned_event::{OwnedEventExtension, OwnedEvent};
use gilrs::{Gamepad, Gilrs};
use rapier3d::counters::Timer;
mod camera; mod camera;
mod components; mod components;
mod geometry; mod geometry;
mod light; mod light;
mod owned_event;
mod physics; mod physics;
mod render; mod render;
mod owned_event;
/* /*
@ -104,38 +112,36 @@ fn main() {
let mut builder = winit::window::WindowBuilder::new(); let mut builder = winit::window::WindowBuilder::new();
builder = builder.with_title("MVGE"); builder = builder.with_title("MVGE");
// I don't know what they are doing here
#[cfg(windows_OFF)] // TODO
{
use winit::platform::windows::WindowBuilderExtWindows;
builder = builder.with_no_redirection_bitmap(true);
}
let window = builder.build(&event_loop).unwrap(); let window = builder.build(&event_loop).unwrap();
// Load up the renderer (and the resources)
let mut renderer = {
let mut renderer = render::Renderer::init(&window);
entity_loading(&mut world, &mut renderer);
renderer
};
let mut resources = Resources::default(); let mut resources = Resources::default();
resources.insert(renderer);
let (physics_state, physics_pipeline) = // Load up all the resources
PhysicsState::build(rapier3d::math::Vector::new(0.0, -9.81, 0.05)); {
resources.insert(physics_state);
resources.insert(physics_pipeline);
resources.insert(LoopState { // The renderer
delta_time: Default::default(), let mut renderer = render::Renderer::init(&window, &mut imgui_context);
start_time: Instant::now(), entity_loading(&mut world, &mut renderer);
step_size: 0.01666, // 60hz resources.insert(renderer);
}); resources.insert(window);
// Physics
let (physics_state, physics_pipeline) =
PhysicsState::build(rapier3d::math::Vector::new(0.0, -9.81, 0.05));
resources.insert(physics_state);
resources.insert(physics_pipeline);
// Loop data
resources.insert(LoopState {
delta_time: Default::default(),
start_time: Instant::now(),
step_size: 0.01666, // 60hz
});
resources.insert(Vec::<OwnedEvent<OwnedEventExtension>>::new()); // And our event stack
resources.insert(Vec::<OwnedEvent<OwnedEventExtension>>::new());
};
let event_loop_proxy = event_loop.create_proxy(); let event_loop_proxy = event_loop.create_proxy();
@ -147,7 +153,12 @@ fn main() {
if gamepad_.name() == "PS4" { if gamepad_.name() == "PS4" {
gamepad = Some(gamepad_); gamepad = Some(gamepad_);
} }
println!("{} is {:?} {:?}", gamepad_.name(), gamepad_.power_info(), gamepad_.id()); println!(
"{} is {:?} {:?}",
gamepad_.name(),
gamepad_.power_info(),
gamepad_.id()
);
} }
let mut active_gamepad = None; let mut active_gamepad = None;
@ -155,9 +166,11 @@ fn main() {
while let Some(GilEvent { id, event, time }) = gilrs.next_event() { while let Some(GilEvent { id, event, time }) = gilrs.next_event() {
println!("{:?} New event from {}: {:?}", time, id, event); println!("{:?} New event from {}: {:?}", time, id, event);
active_gamepad = Some(id); active_gamepad = Some(id);
event_loop_proxy.send_event(OwnedEventExtension::GamepadEvent { event_loop_proxy
gil_event: GilEvent { id, event, time } .send_event(OwnedEventExtension::GamepadEvent {
}).ok(); gil_event: GilEvent { id, event, time },
})
.ok();
} }
// // You can also use cached gamepad state // // You can also use cached gamepad state
@ -171,29 +184,35 @@ fn main() {
} }
}); });
let mut elapsed_time: f32 = { // deltatime since last frame let mut elapsed_time: f32 = {
// deltatime since last frame
let loop_state = resources.get::<LoopState>().unwrap(); let loop_state = resources.get::<LoopState>().unwrap();
loop_state.start_time.elapsed() loop_state.start_time.elapsed()
}.as_secs_f32(); }
.as_secs_f32();
let mut delta_time: f32 = 0.0; let mut delta_time: f32 = 0.0;
let mut accumulator_time: f32 = 0.0; let mut accumulator_time: f32 = 0.0;
let mut current_time: f32 = elapsed_time; let mut current_time: f32 = elapsed_time;
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll; *control_flow = ControlFlow::Poll;
match event { match event {
event::Event::NewEvents(cause) => { event::Event::NewEvents(cause) => {
event_schedule.execute(&mut world, &mut resources); event_schedule.execute(&mut world, &mut resources);
resources.get_mut::<Vec<OwnedEvent<OwnedEventExtension>>>() resources
.unwrap().clear(); .get_mut::<Vec<OwnedEvent<OwnedEventExtension>>>()
.unwrap()
.clear();
} }
event::Event::MainEventsCleared => { event::Event::MainEventsCleared => {
let (step_size, elapsed_time) = {
let (step_size, elapsed_time) = { // deltatime since last frame // deltatime since last frame
let loop_state = resources.get::<LoopState>().unwrap(); let loop_state = resources.get::<LoopState>().unwrap();
(loop_state.step_size, loop_state.start_time.elapsed().as_secs_f32()) (
loop_state.step_size,
loop_state.start_time.elapsed().as_secs_f32(),
)
}; };
delta_time = elapsed_time - current_time; delta_time = elapsed_time - current_time;
current_time = elapsed_time; current_time = elapsed_time;
@ -225,9 +244,10 @@ fn main() {
.unwrap() .unwrap()
.resize(width, height); .resize(width, height);
} }
event::Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { event::Event::WindowEvent {
*control_flow = ControlFlow::Exit event: WindowEvent::CloseRequested,
} ..
} => *control_flow = ControlFlow::Exit,
event::Event::RedrawRequested(_) => { event::Event::RedrawRequested(_) => {
// Call the render system // Call the render system
render_schedule.execute(&mut world, &mut resources); render_schedule.execute(&mut world, &mut resources);
@ -235,11 +255,14 @@ fn main() {
_ => {} _ => {}
} }
resources.get_mut::<Vec<OwnedEvent<OwnedEventExtension>>>() resources
.unwrap().push(event.into()); .get_mut::<Vec<OwnedEvent<OwnedEventExtension>>>()
.unwrap()
.push(event.into());
}); });
} }
pub fn entity_loading(world: &mut World, renderer: &mut Renderer) { pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
let monkey_mesh = renderer.load_mesh_to_buffer("./resources/monkey.obj"); let monkey_mesh = renderer.load_mesh_to_buffer("./resources/monkey.obj");
@ -248,10 +271,10 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
position: Point3 { position: Point3 {
x: 0.0, x: 0.0,
y: 0.0, y: 0.0,
z: 10.0 z: 10.0,
}, },
yaw: Rad(-PI), yaw: Rad(-PI),
pitch: Rad(PI/2.0) pitch: Rad(PI / 2.0),
}, },
Color { Color {
r: 1.0, r: 1.0,
@ -272,8 +295,8 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
rot: Euler { rot: Euler {
x: Deg(0.0), x: Deg(0.0),
y: Deg(-25.0), y: Deg(-25.0),
z: Deg(0.0) z: Deg(0.0),
} },
}, },
Color { Color {
r: 1.0, r: 1.0,
@ -323,17 +346,11 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
)); ));
let mut dynamic_ball_body = RigidBodyBuilder::new_dynamic() let mut dynamic_ball_body = RigidBodyBuilder::new_dynamic()
.position(Isometry3::new( .position(Isometry3::new(Vector3::new(0.0, 0.0, 0.0), Vector::y()))
Vector3::new(0.0, 0.0, 0.0),
Vector::y(),
))
.build(); .build();
let mut static_floor_body = RigidBodyBuilder::new_static() let mut static_floor_body = RigidBodyBuilder::new_static()
.position(Isometry3::new( .position(Isometry3::new(Vector3::new(0.0, -8.0, 0.0), Vector::y()))
Vector3::new(0.0, -8.0, 0.0),
Vector::y(),
))
.build(); .build();
let ball_collider = ColliderBuilder::ball(1.5).build(); let ball_collider = ColliderBuilder::ball(1.5).build();

@ -96,6 +96,20 @@ pub fn update_camera(world: &mut SubWorld, #[resource] loop_state: &mut LoopStat
} }
} }
#[system]
#[write_component(Camera)]
pub fn update_imgui(
world: &mut SubWorld,
#[resource] loop_state: &mut LoopState,
#[resource] renderer: &mut Renderer,
) {
let mut query = <(&mut Camera, &mut CameraController)>::query();
for (mut camera, controller) in query.iter_mut(world) {
controller.update_camera(&mut camera, loop_state.step_size)
}
}
#[system] #[system]
#[write_component(Collider)] #[write_component(Collider)]
#[write_component(Physics)] #[write_component(Physics)]

@ -23,8 +23,12 @@ use winit::window::Window;
use crate::camera::{Camera, CameraController}; use crate::camera::{Camera, CameraController};
use crate::components::{Color, Mesh, Position, RangeCopy}; use crate::components::{Color, Mesh, Position, RangeCopy};
use crate::geometry::{create_plane, import_mesh, vertex, Vertex}; use crate::geometry::{import_mesh, vertex, Vertex};
use crate::light::{DirectionalLight, LightRaw}; use crate::light::{DirectionalLight, LightRaw};
use imgui_winit_support::WinitPlatform;
use imgui::*;
use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig};
use std::cell::RefCell;
#[cfg_attr(rustfmt, rustfmt_skip)] #[cfg_attr(rustfmt, rustfmt_skip)]
#[allow(unused)] #[allow(unused)]
@ -80,7 +84,12 @@ pub struct Pass {
#[write_component(Mesh)] #[write_component(Mesh)]
#[write_component(Color)] #[write_component(Color)]
#[write_component(DirectionalLight)] #[write_component(DirectionalLight)]
pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) { pub fn render_test(
world: &mut SubWorld,
#[resource] renderer: &mut Renderer,
#[resource] winit_window: &mut Window,
) {
let mut encoder = renderer let mut encoder = renderer
.device .device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
@ -88,6 +97,92 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
let frame = renderer.get_current_frame(); let frame = renderer.get_current_frame();
// set up imgui for rendering
// update delta time and prepare the frame
//renderer.imgui_platform.io_mut().update_delta_time(now - last_frame);
{
let mut imgui_context = imgui::Context::create();
imgui_context.set_ini_filename(None);
let font_size = 10.0 as f32;
//imgui_context.io_mut().font_global_scale = 10.0 as f32;
imgui_context.fonts().add_font(&[FontSource::DefaultFontData {
config: Some(imgui::FontConfig {
oversample_h: 1,
pixel_snap_h: true,
size_pixels: font_size,
..Default::default()
}),
}]);
// The imgui context lives as a resource for the render system to use
let mut platform = imgui_winit_support::WinitPlatform::init(imgui_context);
platform.attach_window(
imgui_context.io_mut(),
window,
imgui_winit_support::HiDpiMode::Default,
);
let clear_color = wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
};
let renderer_config = ImguiRendererConfig {
texture_format: sc_desc.format,
..Default::default()
};
let mut renderer = ImguiRenderer::new(imgui_context, &device, &queue, renderer_config);
renderer.imgui_platform
.prepare_frame(imgui_context.io_mut(), &winit_window)
.expect("Failed to prepare frame");
// get the frame and build a ui window
let ui = imgui_context.frame();
let window = imgui::Window::new(im_str!("Hello too"));
window
.size([400.0, 200.0], Condition::FirstUseEver)
.position([400.0, 200.0], Condition::FirstUseEver)
.build(&ui, || {
ui.text(im_str!("Frametime: {:?}", 10.0));
});
//ui.show_demo_window(&mut demo_open);
renderer.imgui_platform.prepare_render(&ui, &winit_window);
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.output.view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
}),
store: true,
},
}],
depth_stencil_attachment: None,
});
renderer.imgui_renderer
.render(ui.render(), &renderer.queue, &renderer.device, &mut rpass)
.expect("Rendering failed");
drop(rpass);
}
// Update the camera uniform buffers, need to make it support selection of // Update the camera uniform buffers, need to make it support selection of
// cameras // cameras
let mut query = <(&mut Camera)>::query(); let mut query = <(&mut Camera)>::query();
@ -253,6 +348,10 @@ pub struct Renderer {
light_uniform_buf: wgpu::Buffer, light_uniform_buf: wgpu::Buffer,
camera_projection: Matrix4<f32>, camera_projection: Matrix4<f32>,
imgui_platform: WinitPlatform,
imgui_renderer: ImguiRenderer,
} }
impl Renderer { impl Renderer {
@ -393,7 +492,8 @@ impl Renderer {
} }
} }
pub fn init(window: &Window) -> Renderer { pub fn init(window: &Window, imgui_context: &mut imgui::Context) -> Renderer {
// Grab the GPU instance, and query its features // Grab the GPU instance, and query its features
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY); let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let (size, surface) = unsafe { let (size, surface) = unsafe {
@ -804,6 +904,7 @@ impl Renderer {
label: Some("Depth Texture"), label: Some("Depth Texture"),
}); });
Renderer { Renderer {
swapchain: swap_chain, swapchain: swap_chain,
queue: queue, queue: queue,
@ -821,6 +922,8 @@ impl Renderer {
instance: Arc::new(instance), instance: Arc::new(instance),
views_given: 0, views_given: 0,
camera_projection: mx_projection, camera_projection: mx_projection,
imgui_platform: platform,
imgui_renderer: renderer
} }
} }

Loading…
Cancel
Save