back to single threaded renderer, client server good now
This commit is contained in:
@@ -2,12 +2,12 @@ use winit::{application::ApplicationHandler, event::WindowEvent, event_loop::Con
|
|||||||
|
|
||||||
use super::Client;
|
use super::Client;
|
||||||
|
|
||||||
pub struct ClientApp {
|
pub struct ClientApp<'a> {
|
||||||
client: Option<Client>,
|
client: Option<Client<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientApp {
|
impl <'a> ClientApp<'a> {
|
||||||
fn client(&mut self) -> &mut Client {
|
fn client(&mut self) -> &mut Client<'a> {
|
||||||
self.client.as_mut().expect("bruh")
|
self.client.as_mut().expect("bruh")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ impl ClientApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplicationHandler for ClientApp {
|
impl ApplicationHandler for ClientApp<'_> {
|
||||||
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||||
if self.client.is_none() {
|
if self.client.is_none() {
|
||||||
self.client = Some(Client::new(event_loop));
|
self.client = Some(Client::new(event_loop));
|
||||||
|
|||||||
@@ -1,19 +1,7 @@
|
|||||||
use std::ops::{Deref, DerefMut};
|
use bevy_derive::{Deref, DerefMut};
|
||||||
|
|
||||||
use bevy_ecs::system::Resource;
|
use bevy_ecs::system::Resource;
|
||||||
|
|
||||||
use super::render::RendererChannel;
|
use super::render::RenderCommand;
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource, Deref, DerefMut, Default)]
|
||||||
pub struct RenderResource(pub RendererChannel);
|
pub struct RenderCommands(pub Vec<RenderCommand>);
|
||||||
impl Deref for RenderResource {
|
|
||||||
type Target = RendererChannel;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl DerefMut for RenderResource {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ use nalgebra::Rotation3;
|
|||||||
use ndarray::Array3;
|
use ndarray::Array3;
|
||||||
use winit::{dpi::PhysicalPosition, keyboard::KeyCode as Key, window::CursorGrabMode};
|
use winit::{dpi::PhysicalPosition, keyboard::KeyCode as Key, window::CursorGrabMode};
|
||||||
|
|
||||||
use crate::world::component::{VoxelGrid, VoxelGridBundle};
|
use crate::{
|
||||||
|
sync::ServerMessage,
|
||||||
|
world::component::{VoxelGrid, VoxelGridBundle},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{render::voxel::VoxelColor, Client};
|
use super::{render::voxel::VoxelColor, Client};
|
||||||
|
|
||||||
impl Client {
|
impl Client<'_> {
|
||||||
pub fn handle_input(&mut self, dt: &Duration) {
|
pub fn handle_input(&mut self, dt: &Duration) {
|
||||||
let dt = dt.as_secs_f32();
|
let dt = dt.as_secs_f32();
|
||||||
let Client {
|
let Client {
|
||||||
@@ -101,19 +104,24 @@ impl Client {
|
|||||||
state.camera.pos += *state.camera.down() * move_dist;
|
state.camera.pos += *state.camera.down() * move_dist;
|
||||||
}
|
}
|
||||||
if state.camera != old_camera {
|
if state.camera != old_camera {
|
||||||
self.renderer
|
self.render_commands
|
||||||
.send(super::render::RenderMessage::ViewUpdate(state.camera));
|
.push(super::render::RenderCommand::ViewUpdate(state.camera));
|
||||||
}
|
}
|
||||||
|
|
||||||
// fun
|
// fun
|
||||||
if input.just_pressed(Key::KeyF) {
|
if input.just_pressed(Key::KeyF) {
|
||||||
self.world.spawn(VoxelGridBundle {
|
self.server
|
||||||
pos: (state.camera.pos + 135.0 * 2.0 * *state.camera.forward()).into(),
|
.send(ServerMessage::SpawnVoxelGrid(VoxelGridBundle {
|
||||||
orientation: state.camera.orientation.into(),
|
pos: (state.camera.pos + 135.0 * 2.0 * *state.camera.forward()).into(),
|
||||||
grid: VoxelGrid::new(Array3::from_shape_fn((135, 135, 135), |(..)| {
|
orientation: state.camera.orientation.into(),
|
||||||
VoxelColor::white()
|
grid: VoxelGrid::new(Array3::from_shape_fn((135, 135, 135), |(x, y, z)| {
|
||||||
})),
|
if x == 0 || y == 0 || z == 0 || x == 134 || y == 134 || z == 134 {
|
||||||
});
|
VoxelColor::white()
|
||||||
|
} else {
|
||||||
|
VoxelColor::none()
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,26 +9,30 @@ mod state;
|
|||||||
mod system;
|
mod system;
|
||||||
|
|
||||||
pub use app::*;
|
pub use app::*;
|
||||||
use bevy_ecs::{system::SystemId, world::World};
|
use bevy_ecs::{entity::Entity, system::SystemId, world::World};
|
||||||
use component::RenderResource;
|
use component::RenderCommands;
|
||||||
use render::{RenderMessage, RendererChannel};
|
use render::RenderCommand;
|
||||||
|
use rsc::FRAME_TIME;
|
||||||
pub use state::*;
|
pub use state::*;
|
||||||
use system::voxel_grid::update_renderer;
|
use system::render::add_grid;
|
||||||
|
|
||||||
use crate::{server::Server, sync::ServerHandle, world::generation::generate};
|
use crate::{
|
||||||
|
server::Server,
|
||||||
|
sync::{ClientMessage, ServerHandle, ServerMessage},
|
||||||
|
};
|
||||||
|
|
||||||
use self::{input::Input, render::Renderer, ClientState};
|
use self::{input::Input, render::Renderer, ClientState};
|
||||||
use std::{sync::Arc, thread::JoinHandle, time::Instant};
|
use std::{collections::HashMap, sync::Arc, time::{Duration, Instant}};
|
||||||
use winit::{
|
use winit::{
|
||||||
event::WindowEvent,
|
event::WindowEvent,
|
||||||
window::{Window, WindowAttributes},
|
window::{Window, WindowAttributes},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client<'a> {
|
||||||
window: Arc<Window>,
|
window: Arc<Window>,
|
||||||
state: ClientState,
|
state: ClientState,
|
||||||
render_handle: Option<JoinHandle<()>>,
|
renderer: Renderer<'a>,
|
||||||
renderer: RendererChannel,
|
render_commands: Vec<RenderCommand>,
|
||||||
exit: bool,
|
exit: bool,
|
||||||
input: Input,
|
input: Input,
|
||||||
prev_update: Instant,
|
prev_update: Instant,
|
||||||
@@ -36,10 +40,18 @@ pub struct Client {
|
|||||||
keep_cursor: bool,
|
keep_cursor: bool,
|
||||||
world: World,
|
world: World,
|
||||||
server: ServerHandle,
|
server: ServerHandle,
|
||||||
bruh: SystemId,
|
server_id_map: HashMap<Entity, Entity>,
|
||||||
|
systems: ClientSystems,
|
||||||
|
target: Instant,
|
||||||
|
frame_time: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
pub struct ClientSystems {
|
||||||
|
render_add_grid: SystemId,
|
||||||
|
render_update_transform: SystemId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client<'_> {
|
||||||
pub fn new(event_loop: &winit::event_loop::ActiveEventLoop) -> Self {
|
pub fn new(event_loop: &winit::event_loop::ActiveEventLoop) -> Self {
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
let window = Arc::new(
|
let window = Arc::new(
|
||||||
@@ -48,27 +60,32 @@ impl Client {
|
|||||||
.expect("Failed to create window"),
|
.expect("Failed to create window"),
|
||||||
);
|
);
|
||||||
|
|
||||||
let (render_channel, render_handle) = Renderer::spawn(window.clone());
|
let renderer = Renderer::spawn(window.clone());
|
||||||
world.insert_resource(RenderResource(render_channel.clone()));
|
world.insert_resource(RenderCommands(Vec::new()));
|
||||||
let bruh = world.register_system(update_renderer);
|
|
||||||
|
|
||||||
let state = ClientState::new();
|
let state = ClientState::new();
|
||||||
let server = Server::spawn();
|
let server = ServerHandle::spawn(Server::start);
|
||||||
generate(&mut world);
|
server.send(ServerMessage::LoadWorld);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
window,
|
window,
|
||||||
exit: false,
|
exit: false,
|
||||||
render_handle: Some(render_handle),
|
renderer,
|
||||||
renderer: render_channel,
|
render_commands: Vec::new(),
|
||||||
state,
|
state,
|
||||||
input: Input::new(),
|
input: Input::new(),
|
||||||
prev_update: Instant::now(),
|
prev_update: Instant::now(),
|
||||||
grabbed_cursor: false,
|
grabbed_cursor: false,
|
||||||
keep_cursor: false,
|
keep_cursor: false,
|
||||||
|
systems: ClientSystems {
|
||||||
|
render_add_grid: world.register_system(add_grid),
|
||||||
|
render_update_transform: world.register_system(system::render::update_transform),
|
||||||
|
},
|
||||||
world,
|
world,
|
||||||
server,
|
server,
|
||||||
bruh,
|
server_id_map: HashMap::new(),
|
||||||
|
target: Instant::now(),
|
||||||
|
frame_time: FRAME_TIME,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,31 +98,51 @@ impl Client {
|
|||||||
self.input.end();
|
self.input.end();
|
||||||
|
|
||||||
self.recv();
|
self.recv();
|
||||||
self.world.run_system(self.bruh).expect("WHAT");
|
self.world
|
||||||
|
.run_system(self.systems.render_add_grid)
|
||||||
|
.expect("WHAT v2");
|
||||||
|
self.world
|
||||||
|
.run_system(self.systems.render_update_transform)
|
||||||
|
.expect("WHAT");
|
||||||
self.world.clear_trackers();
|
self.world.clear_trackers();
|
||||||
|
|
||||||
|
if now >= self.target {
|
||||||
|
self.target += self.frame_time;
|
||||||
|
let mut commands = std::mem::take(&mut self.render_commands);
|
||||||
|
let world_cmds = std::mem::take(&mut self.world.resource_mut::<RenderCommands>().0);
|
||||||
|
commands.extend(world_cmds);
|
||||||
|
self.renderer.handle_commands(commands);
|
||||||
|
self.renderer.draw();
|
||||||
|
}
|
||||||
|
|
||||||
if self.exit {
|
if self.exit {
|
||||||
self.renderer.send(RenderMessage::Exit);
|
self.server.send(ServerMessage::Stop);
|
||||||
// you know I'd like to do a timeout here...
|
self.server.join();
|
||||||
// only because I have an NVIDIA GPU HELP
|
|
||||||
self.render_handle
|
|
||||||
.take()
|
|
||||||
.expect("uh oh")
|
|
||||||
.join()
|
|
||||||
.expect("bruh");
|
|
||||||
event_loop.exit();
|
event_loop.exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv(&mut self) {
|
pub fn recv(&mut self) {
|
||||||
for msg in self.server.recv() {}
|
for msg in self.server.recv() {
|
||||||
|
match msg {
|
||||||
|
ClientMessage::SpawnVoxelGrid(entity, grid) => {
|
||||||
|
let cid = self.world.spawn(grid).id();
|
||||||
|
self.server_id_map.insert(entity, cid);
|
||||||
|
}
|
||||||
|
ClientMessage::PosUpdate(e, pos) => {
|
||||||
|
if let Some(id) = self.server_id_map.get(&e) {
|
||||||
|
self.world.entity_mut(*id).insert(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn window_event(&mut self, event: WindowEvent) {
|
pub fn window_event(&mut self, event: WindowEvent) {
|
||||||
match event {
|
match event {
|
||||||
WindowEvent::CloseRequested => self.exit = true,
|
WindowEvent::CloseRequested => self.exit = true,
|
||||||
WindowEvent::Resized(size) => self.renderer.send(RenderMessage::Resize(size)),
|
WindowEvent::Resized(size) => self.renderer.resize(size),
|
||||||
WindowEvent::RedrawRequested => self.renderer.send(RenderMessage::Draw),
|
WindowEvent::RedrawRequested => self.renderer.draw(),
|
||||||
WindowEvent::CursorLeft { .. } => {
|
WindowEvent::CursorLeft { .. } => {
|
||||||
self.input.clear();
|
self.input.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
83
src/client/render/command.rs
Normal file
83
src/client/render/command.rs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
use crate::client::camera::Camera;
|
||||||
|
|
||||||
|
use super::{voxel::VoxelColor, Renderer};
|
||||||
|
use bevy_ecs::entity::Entity;
|
||||||
|
use nalgebra::{Rotation3, Vector3};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use winit::window::Window;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum RenderCommand {
|
||||||
|
CreateVoxelGrid(CreateVoxelGrid),
|
||||||
|
UpdateGridTransform(UpdateGridTransform),
|
||||||
|
ViewUpdate(Camera),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CreateVoxelGrid {
|
||||||
|
pub id: Entity,
|
||||||
|
pub pos: Vector3<f32>,
|
||||||
|
pub orientation: Rotation3<f32>,
|
||||||
|
pub dimensions: Vector3<usize>,
|
||||||
|
pub grid: Vec<VoxelColor>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct UpdateGridTransform {
|
||||||
|
pub id: Entity,
|
||||||
|
pub pos: Vector3<f32>,
|
||||||
|
pub orientation: Rotation3<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Renderer<'a> {
|
||||||
|
pub fn spawn(window: Arc<Window>) -> Renderer<'a> {
|
||||||
|
let size = window.inner_size();
|
||||||
|
|
||||||
|
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||||
|
backends: wgpu::Backends::PRIMARY,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
let surface = instance
|
||||||
|
.create_surface(window)
|
||||||
|
.expect("Could not create window surface!");
|
||||||
|
Self::new(instance, surface, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_commands(&mut self, commands: Vec<RenderCommand>) {
|
||||||
|
let mut new_camera = false;
|
||||||
|
for cmd in commands {
|
||||||
|
match cmd {
|
||||||
|
RenderCommand::CreateVoxelGrid(desc) => {
|
||||||
|
self.voxel_pipeline.add_group(
|
||||||
|
&self.device,
|
||||||
|
&mut self.encoder,
|
||||||
|
&mut self.staging_belt,
|
||||||
|
desc,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
RenderCommand::ViewUpdate(camera) => {
|
||||||
|
new_camera = true;
|
||||||
|
self.camera = camera;
|
||||||
|
}
|
||||||
|
RenderCommand::UpdateGridTransform(update) => {
|
||||||
|
self.voxel_pipeline.update_transform(
|
||||||
|
&self.device,
|
||||||
|
&mut self.encoder,
|
||||||
|
&mut self.staging_belt,
|
||||||
|
update,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if new_camera {
|
||||||
|
self.voxel_pipeline.update_view(
|
||||||
|
&self.device,
|
||||||
|
&mut self.encoder,
|
||||||
|
&mut self.staging_belt,
|
||||||
|
self.size,
|
||||||
|
&self.camera,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
mod thread;
|
mod command;
|
||||||
mod util;
|
mod util;
|
||||||
pub mod voxel;
|
pub mod voxel;
|
||||||
|
|
||||||
pub use thread::*;
|
pub use command::*;
|
||||||
|
|
||||||
use super::camera::Camera;
|
use super::camera::Camera;
|
||||||
use crate::client::rsc::{CLEAR_COLOR, FRAME_TIME};
|
use crate::client::rsc::CLEAR_COLOR;
|
||||||
use nalgebra::Vector2;
|
use nalgebra::Vector2;
|
||||||
use smaa::{SmaaMode, SmaaTarget};
|
use smaa::{SmaaMode, SmaaTarget};
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
use voxel::VoxelPipeline;
|
use voxel::VoxelPipeline;
|
||||||
use winit::dpi::PhysicalSize;
|
use winit::dpi::PhysicalSize;
|
||||||
|
|
||||||
@@ -23,9 +22,6 @@ pub struct Renderer<'a> {
|
|||||||
voxel_pipeline: VoxelPipeline,
|
voxel_pipeline: VoxelPipeline,
|
||||||
smaa_target: SmaaTarget,
|
smaa_target: SmaaTarget,
|
||||||
camera: Camera,
|
camera: Camera,
|
||||||
|
|
||||||
frame_time: Duration,
|
|
||||||
target: Instant,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Renderer<'a> {
|
impl<'a> Renderer<'a> {
|
||||||
@@ -102,8 +98,6 @@ impl<'a> Renderer<'a> {
|
|||||||
config,
|
config,
|
||||||
queue,
|
queue,
|
||||||
smaa_target,
|
smaa_target,
|
||||||
frame_time: FRAME_TIME,
|
|
||||||
target: Instant::now(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
use crate::client::camera::Camera;
|
|
||||||
|
|
||||||
use super::{voxel::VoxelColor, Renderer};
|
|
||||||
use nalgebra::{Rotation3, Vector3};
|
|
||||||
use std::{
|
|
||||||
sync::{
|
|
||||||
mpsc::{channel, Receiver, Sender},
|
|
||||||
Arc,
|
|
||||||
},
|
|
||||||
thread::JoinHandle,
|
|
||||||
time::Instant,
|
|
||||||
};
|
|
||||||
use winit::{dpi::PhysicalSize, window::Window};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum RenderMessage {
|
|
||||||
Resize(PhysicalSize<u32>),
|
|
||||||
Draw,
|
|
||||||
CreateVoxelGrid(CreateVoxelGrid),
|
|
||||||
ViewUpdate(Camera),
|
|
||||||
Exit,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct CreateVoxelGrid {
|
|
||||||
pub pos: Vector3<f32>,
|
|
||||||
pub orientation: Rotation3<f32>,
|
|
||||||
pub dimensions: Vector3<usize>,
|
|
||||||
pub grid: Vec<VoxelColor>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Renderer<'_> {
|
|
||||||
pub fn spawn(window: Arc<Window>) -> (RendererChannel, JoinHandle<()>) {
|
|
||||||
let (s, mut r) = channel();
|
|
||||||
|
|
||||||
let size = window.inner_size();
|
|
||||||
|
|
||||||
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
|
||||||
backends: wgpu::Backends::PRIMARY,
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
|
|
||||||
let surface = instance
|
|
||||||
.create_surface(window)
|
|
||||||
.expect("Could not create window surface!");
|
|
||||||
(
|
|
||||||
RendererChannel(s),
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
Self::new(instance, surface, size).start(&mut r);
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start(&mut self, reciever: &mut Receiver<RenderMessage>) {
|
|
||||||
let mut new_camera = false;
|
|
||||||
'main: loop {
|
|
||||||
let now = Instant::now();
|
|
||||||
for msg in reciever.try_iter() {
|
|
||||||
match msg {
|
|
||||||
RenderMessage::CreateVoxelGrid(desc) => {
|
|
||||||
self.voxel_pipeline.add_group(
|
|
||||||
&self.device,
|
|
||||||
&mut self.encoder,
|
|
||||||
&mut self.staging_belt,
|
|
||||||
desc,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
RenderMessage::Draw => {
|
|
||||||
self.draw();
|
|
||||||
}
|
|
||||||
RenderMessage::Resize(size) => {
|
|
||||||
self.resize(size);
|
|
||||||
}
|
|
||||||
RenderMessage::Exit => {
|
|
||||||
break 'main;
|
|
||||||
}
|
|
||||||
RenderMessage::ViewUpdate(camera) => {
|
|
||||||
new_camera = true;
|
|
||||||
self.camera = camera;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if now >= self.target {
|
|
||||||
self.target = now + self.frame_time;
|
|
||||||
if new_camera {
|
|
||||||
self.voxel_pipeline.update_view(
|
|
||||||
&self.device,
|
|
||||||
&mut self.encoder,
|
|
||||||
&mut self.staging_belt,
|
|
||||||
self.size,
|
|
||||||
&self.camera,
|
|
||||||
);
|
|
||||||
new_camera = false;
|
|
||||||
}
|
|
||||||
self.draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct RendererChannel(Sender<RenderMessage>);
|
|
||||||
impl RendererChannel {
|
|
||||||
pub fn send(&self, msg: RenderMessage) {
|
|
||||||
// TODO: handle this properly
|
|
||||||
self.0.send(msg).expect("Failed to send renderer message");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,11 +4,15 @@ mod group;
|
|||||||
mod light;
|
mod light;
|
||||||
mod view;
|
mod view;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use bevy_ecs::entity::Entity;
|
||||||
pub use color::*;
|
pub use color::*;
|
||||||
|
|
||||||
use light::GlobalLight;
|
use light::GlobalLight;
|
||||||
use nalgebra::{Projective3, Transform3, Translation3, Vector2, Vector3};
|
use nalgebra::{Projective3, Transform3, Translation3, Vector2, Vector3};
|
||||||
|
|
||||||
|
use super::UpdateGridTransform;
|
||||||
use crate::client::{
|
use crate::client::{
|
||||||
camera::Camera,
|
camera::Camera,
|
||||||
render::{
|
render::{
|
||||||
@@ -16,6 +20,7 @@ use crate::client::{
|
|||||||
CreateVoxelGrid,
|
CreateVoxelGrid,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use {group::VoxelGroup, view::View};
|
use {group::VoxelGroup, view::View};
|
||||||
|
|
||||||
pub struct VoxelPipeline {
|
pub struct VoxelPipeline {
|
||||||
@@ -26,6 +31,7 @@ pub struct VoxelPipeline {
|
|||||||
voxel_groups: Storage<VoxelGroup>,
|
voxel_groups: Storage<VoxelGroup>,
|
||||||
voxels: Storage<VoxelColor>,
|
voxels: Storage<VoxelColor>,
|
||||||
global_lights: Storage<GlobalLight>,
|
global_lights: Storage<GlobalLight>,
|
||||||
|
id_map: HashMap<Entity, (usize, VoxelGroup)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VoxelPipeline {
|
impl VoxelPipeline {
|
||||||
@@ -123,6 +129,7 @@ impl VoxelPipeline {
|
|||||||
voxels,
|
voxels,
|
||||||
voxel_groups,
|
voxel_groups,
|
||||||
global_lights,
|
global_lights,
|
||||||
|
id_map: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +139,7 @@ impl VoxelPipeline {
|
|||||||
encoder: &mut wgpu::CommandEncoder,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
belt: &mut wgpu::util::StagingBelt,
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
CreateVoxelGrid {
|
CreateVoxelGrid {
|
||||||
|
id,
|
||||||
pos,
|
pos,
|
||||||
orientation,
|
orientation,
|
||||||
dimensions,
|
dimensions,
|
||||||
@@ -139,6 +147,7 @@ impl VoxelPipeline {
|
|||||||
}: CreateVoxelGrid,
|
}: CreateVoxelGrid,
|
||||||
) {
|
) {
|
||||||
let offset = self.voxels.len();
|
let offset = self.voxels.len();
|
||||||
|
|
||||||
let updates = [ArrBufUpdate {
|
let updates = [ArrBufUpdate {
|
||||||
offset,
|
offset,
|
||||||
data: &grid,
|
data: &grid,
|
||||||
@@ -160,10 +169,13 @@ impl VoxelPipeline {
|
|||||||
offset: self.voxel_groups.len(),
|
offset: self.voxel_groups.len(),
|
||||||
data: &[group],
|
data: &[group],
|
||||||
}];
|
}];
|
||||||
let size = self.voxel_groups.len() + 1;
|
let i = self.voxel_groups.len();
|
||||||
|
let size = i + 1;
|
||||||
self.voxel_groups
|
self.voxel_groups
|
||||||
.update(device, encoder, belt, size, &updates);
|
.update(device, encoder, belt, size, &updates);
|
||||||
|
|
||||||
|
self.id_map.insert(id, (i, group));
|
||||||
|
|
||||||
self.bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
self.bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
layout: &self.bind_group_layout,
|
layout: &self.bind_group_layout,
|
||||||
entries: &[
|
entries: &[
|
||||||
@@ -176,6 +188,30 @@ impl VoxelPipeline {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_transform(
|
||||||
|
&mut self,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
|
update: UpdateGridTransform,
|
||||||
|
) {
|
||||||
|
if let Some((i, group)) = self.id_map.get_mut(&update.id) {
|
||||||
|
let proj = Projective3::identity()
|
||||||
|
* Translation3::from(update.pos)
|
||||||
|
* update.orientation
|
||||||
|
* Translation3::from(-group.dimensions.cast() / 2.0);
|
||||||
|
group.transform = proj;
|
||||||
|
group.transform_inv = proj.inverse();
|
||||||
|
let updates = [ArrBufUpdate {
|
||||||
|
offset: *i,
|
||||||
|
data: &[*group],
|
||||||
|
}];
|
||||||
|
let size = self.voxel_groups.len();
|
||||||
|
self.voxel_groups
|
||||||
|
.update(device, encoder, belt, size, &updates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_view(
|
pub fn update_view(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
pub mod voxel_grid;
|
pub mod render;
|
||||||
|
|||||||
50
src/client/system/render.rs
Normal file
50
src/client/system/render.rs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
use bevy_ecs::{
|
||||||
|
entity::Entity,
|
||||||
|
query::{Added, Changed, Or},
|
||||||
|
system::{Query, ResMut},
|
||||||
|
};
|
||||||
|
use nalgebra::Vector3;
|
||||||
|
use ndarray::Axis;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
client::{
|
||||||
|
component::RenderCommands,
|
||||||
|
render::{CreateVoxelGrid, RenderCommand, UpdateGridTransform},
|
||||||
|
},
|
||||||
|
world::component::{Orientation, Pos, VoxelGrid},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn add_grid(
|
||||||
|
query: Query<
|
||||||
|
(Entity, &Pos, &Orientation, &VoxelGrid),
|
||||||
|
Or<(Added<Pos>, Added<Orientation>, Added<VoxelGrid>)>,
|
||||||
|
>,
|
||||||
|
mut renderer: ResMut<RenderCommands>,
|
||||||
|
) {
|
||||||
|
for (id, pos, orientation, grid) in query.iter() {
|
||||||
|
renderer.push(RenderCommand::CreateVoxelGrid(CreateVoxelGrid {
|
||||||
|
id,
|
||||||
|
pos: **pos,
|
||||||
|
orientation: **orientation,
|
||||||
|
dimensions: Vector3::new(
|
||||||
|
grid.len_of(Axis(0)),
|
||||||
|
grid.len_of(Axis(1)),
|
||||||
|
grid.len_of(Axis(2)),
|
||||||
|
),
|
||||||
|
grid: grid.iter().cloned().collect(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_transform(
|
||||||
|
query: Query<(Entity, &Pos, &Orientation), Or<(Changed<Pos>, Changed<Orientation>)>>,
|
||||||
|
mut renderer: ResMut<RenderCommands>,
|
||||||
|
) {
|
||||||
|
for (id, pos, orientation) in query.iter() {
|
||||||
|
renderer.push(RenderCommand::UpdateGridTransform(UpdateGridTransform {
|
||||||
|
id,
|
||||||
|
pos: **pos,
|
||||||
|
orientation: **orientation,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
use bevy_ecs::{
|
|
||||||
query::{Changed, Or},
|
|
||||||
system::{Query, Res},
|
|
||||||
};
|
|
||||||
use nalgebra::Vector3;
|
|
||||||
use ndarray::Axis;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
client::{
|
|
||||||
component::RenderResource,
|
|
||||||
render::{CreateVoxelGrid, RenderMessage},
|
|
||||||
},
|
|
||||||
world::component::{Orientation, Pos, VoxelGrid},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn update_renderer(
|
|
||||||
query: Query<
|
|
||||||
(&Pos, &Orientation, &VoxelGrid),
|
|
||||||
Or<(Changed<Pos>, Changed<Orientation>, Changed<VoxelGrid>)>,
|
|
||||||
>,
|
|
||||||
renderer: Res<RenderResource>,
|
|
||||||
) {
|
|
||||||
for (pos, orientation, grid) in query.iter() {
|
|
||||||
println!("YAY");
|
|
||||||
renderer.send(RenderMessage::CreateVoxelGrid(CreateVoxelGrid {
|
|
||||||
pos: **pos,
|
|
||||||
orientation: **orientation,
|
|
||||||
dimensions: Vector3::new(
|
|
||||||
grid.len_of(Axis(0)),
|
|
||||||
grid.len_of(Axis(1)),
|
|
||||||
grid.len_of(Axis(2)),
|
|
||||||
),
|
|
||||||
grid: grid.iter().cloned().collect(),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,6 @@ use client::ClientApp;
|
|||||||
use winit::event_loop::EventLoop;
|
use winit::event_loop::EventLoop;
|
||||||
|
|
||||||
mod client;
|
mod client;
|
||||||
mod util;
|
|
||||||
mod world;
|
mod world;
|
||||||
mod server;
|
mod server;
|
||||||
mod sync;
|
mod sync;
|
||||||
|
|||||||
@@ -1,36 +1,57 @@
|
|||||||
mod rsc;
|
mod rsc;
|
||||||
|
mod system;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
sync::{client_server_channel, ClientHandle, ServerHandle},
|
sync::{ClientChannel, ClientMessage, ClientSender, ServerMessage},
|
||||||
world::generation::generate,
|
world::{
|
||||||
|
component::{Orientation, Pos, Synced, VoxelGrid, VoxelGridBundle},
|
||||||
|
generation::generate,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use bevy_ecs::world::World;
|
use bevy_ecs::{entity::Entity, query::With, system::SystemId, world::World};
|
||||||
use rsc::UPDATE_TIME;
|
use rsc::UPDATE_TIME;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
update_time: Duration,
|
update_time: Duration,
|
||||||
target: Instant,
|
target: Instant,
|
||||||
client: ClientHandle,
|
client: ClientChannel,
|
||||||
world: World,
|
world: World,
|
||||||
|
systems: ServerSystems,
|
||||||
|
mov: Vec<Entity>,
|
||||||
|
stop: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ServerSystems {
|
||||||
|
sync_pos: SystemId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServerSystems {
|
||||||
|
pub fn new(world: &mut World) -> Self {
|
||||||
|
Self {
|
||||||
|
sync_pos: world.register_system(system::sync::pos),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
pub fn new(ch: ClientHandle) -> Self {
|
pub fn new(client: ClientChannel) -> Self {
|
||||||
|
let mut world = World::new();
|
||||||
|
world.insert_resource(ClientSender(client.sender()));
|
||||||
|
let systems = ServerSystems::new(&mut world);
|
||||||
Self {
|
Self {
|
||||||
client: ch,
|
client,
|
||||||
world: World::new(),
|
world,
|
||||||
|
systems,
|
||||||
target: Instant::now(),
|
target: Instant::now(),
|
||||||
update_time: UPDATE_TIME,
|
update_time: UPDATE_TIME,
|
||||||
|
mov: Vec::new(),
|
||||||
|
stop: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn() -> ServerHandle {
|
pub fn start(ch: ClientChannel) {
|
||||||
let (ch, sh) = client_server_channel();
|
Self::new(ch).run();
|
||||||
std::thread::spawn(|| {
|
|
||||||
Self::new(ch).run();
|
|
||||||
});
|
|
||||||
sh
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
@@ -40,13 +61,49 @@ impl Server {
|
|||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
if now >= self.target {
|
if now >= self.target {
|
||||||
self.target += self.update_time;
|
self.target += self.update_time;
|
||||||
|
let mut q = self.world.query::<(Entity, &mut Pos)>();
|
||||||
|
for (e, mut p) in q.iter_mut(&mut self.world) {
|
||||||
|
if self.mov.contains(&e) {
|
||||||
|
p.x += 0.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.world.run_system(self.systems.sync_pos).unwrap();
|
||||||
|
self.world.clear_trackers();
|
||||||
|
}
|
||||||
|
if self.stop {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv(&mut self) {
|
pub fn recv(&mut self) {
|
||||||
for msg in self.client.recv() {
|
for msg in self.client.recv() {
|
||||||
|
match msg {
|
||||||
|
ServerMessage::LoadWorld => {
|
||||||
|
let mut q = self
|
||||||
|
.world
|
||||||
|
.query_filtered::<(Entity, &Pos, &Orientation, &VoxelGrid), With<Synced>>();
|
||||||
|
// ePOG
|
||||||
|
for (e, p, o, g) in q.iter(&self.world) {
|
||||||
|
self.client.send(ClientMessage::SpawnVoxelGrid(
|
||||||
|
e,
|
||||||
|
VoxelGridBundle {
|
||||||
|
pos: *p,
|
||||||
|
orientation: *o,
|
||||||
|
grid: g.clone(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ServerMessage::SpawnVoxelGrid(grid) => {
|
||||||
|
let e = self.world.spawn((grid.clone(), Synced)).id();
|
||||||
|
self.mov.push(e);
|
||||||
|
self.client.send(ClientMessage::SpawnVoxelGrid(e, grid));
|
||||||
|
}
|
||||||
|
ServerMessage::Stop => {
|
||||||
|
self.stop = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/server/system/mod.rs
Normal file
1
src/server/system/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod sync;
|
||||||
9
src/server/system/sync.rs
Normal file
9
src/server/system/sync.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use bevy_ecs::{entity::Entity, query::Changed, system::{Query, Res}};
|
||||||
|
|
||||||
|
use crate::{sync::{ClientMessage, ClientSender}, world::component::{Pos, Synced}};
|
||||||
|
|
||||||
|
pub fn pos(query: Query<(Entity, &Synced, &Pos), Changed<Pos>>, client: Res<ClientSender>) {
|
||||||
|
for (e, _, pos) in query.iter() {
|
||||||
|
client.send(ClientMessage::PosUpdate(e, *pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,48 +1,28 @@
|
|||||||
use std::sync::mpsc::{channel, Receiver, Sender, TryIter};
|
pub mod thread;
|
||||||
|
|
||||||
use bevy_ecs::{
|
use crate::world::component::{Pos, VoxelGridBundle};
|
||||||
component::{Component, TableStorage},
|
use bevy_ecs::{entity::Entity, system::Resource};
|
||||||
entity::Entity,
|
use std::sync::mpsc::Sender;
|
||||||
};
|
use thread::{ThreadChannel, ThreadHandle};
|
||||||
|
|
||||||
pub enum ServerMessage {}
|
pub enum ServerMessage {
|
||||||
|
Stop,
|
||||||
|
LoadWorld,
|
||||||
|
SpawnVoxelGrid(VoxelGridBundle),
|
||||||
|
}
|
||||||
|
|
||||||
pub enum ClientMessage {
|
pub enum ClientMessage {
|
||||||
LoadWorld(Vec<(Entity, Vec<Box<dyn Component<Storage = TableStorage>>>)>),
|
SpawnVoxelGrid(Entity, VoxelGridBundle),
|
||||||
|
PosUpdate(Entity, Pos),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ServerHandle {
|
pub type ClientChannel = ThreadChannel<ClientMessage, ServerMessage>;
|
||||||
send: Sender<ServerMessage>,
|
pub type ServerHandle = ThreadHandle<ServerMessage, ClientMessage>;
|
||||||
recv: Receiver<ClientMessage>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ServerHandle {
|
#[derive(Resource, Clone)]
|
||||||
pub fn send(&self, msg: ServerMessage) {
|
pub struct ClientSender(pub Sender<ClientMessage>);
|
||||||
self.send.send(msg).expect("BOOOOOO");
|
impl ClientSender {
|
||||||
}
|
|
||||||
pub fn recv(&self) -> TryIter<ClientMessage> {
|
|
||||||
self.recv.try_iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ClientHandle {
|
|
||||||
send: Sender<ClientMessage>,
|
|
||||||
recv: Receiver<ServerMessage>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClientHandle {
|
|
||||||
pub fn send(&self, msg: ClientMessage) {
|
pub fn send(&self, msg: ClientMessage) {
|
||||||
self.send.send(msg).expect("YOU HAVE FAILED THE MISSION");
|
self.0.send(msg).expect("YOU HAVE FAILED THE MISSION");
|
||||||
}
|
|
||||||
pub fn recv(&self) -> TryIter<ServerMessage> {
|
|
||||||
self.recv.try_iter()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client_server_channel() -> (ClientHandle, ServerHandle) {
|
|
||||||
let (cs, sr) = channel();
|
|
||||||
let (ss, cr) = channel();
|
|
||||||
let sh = ServerHandle { send: ss, recv: sr };
|
|
||||||
let ch = ClientHandle { send: cs, recv: cr };
|
|
||||||
(ch, sh)
|
|
||||||
}
|
|
||||||
|
|||||||
53
src/sync/thread.rs
Normal file
53
src/sync/thread.rs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
use std::{
|
||||||
|
sync::mpsc::{channel, Receiver, Sender, TryIter},
|
||||||
|
thread::JoinHandle,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ThreadHandle<SendMsg, RecvMsg> {
|
||||||
|
pub channel: ThreadChannel<SendMsg, RecvMsg>,
|
||||||
|
pub handle: Option<JoinHandle<()>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SendMsg: Send + 'static, RecvMsg: Send + 'static> ThreadHandle<SendMsg, RecvMsg> {
|
||||||
|
pub fn send(&self, msg: SendMsg) {
|
||||||
|
self.channel.send(msg);
|
||||||
|
}
|
||||||
|
pub fn recv(&self) -> TryIter<RecvMsg> {
|
||||||
|
self.channel.recv()
|
||||||
|
}
|
||||||
|
pub fn join(&mut self) {
|
||||||
|
self.handle.take().map(|h| h.join());
|
||||||
|
}
|
||||||
|
pub fn spawn<F: FnOnce(ThreadChannel<RecvMsg, SendMsg>) + Send + 'static>(f: F) -> Self {
|
||||||
|
let (hs, tr) = channel();
|
||||||
|
let (ts, hr) = channel();
|
||||||
|
|
||||||
|
let th = ThreadChannel { send: ts, recv: tr };
|
||||||
|
let run = || {
|
||||||
|
f(th);
|
||||||
|
};
|
||||||
|
let handle = std::thread::spawn(run);
|
||||||
|
ThreadHandle {
|
||||||
|
channel: ThreadChannel { send: hs, recv: hr },
|
||||||
|
handle: Some(handle),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ThreadChannel<SendMsg, RecvMsg> {
|
||||||
|
send: Sender<SendMsg>,
|
||||||
|
recv: Receiver<RecvMsg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SendMsg, RecvMsg> ThreadChannel<SendMsg, RecvMsg> {
|
||||||
|
pub fn sender(&self) -> Sender<SendMsg> {
|
||||||
|
self.send.clone()
|
||||||
|
}
|
||||||
|
pub fn send(&self, msg: SendMsg) {
|
||||||
|
// TODO: handle this properly
|
||||||
|
self.send.send(msg).expect("Failed to send message");
|
||||||
|
}
|
||||||
|
pub fn recv(&self) -> TryIter<RecvMsg> {
|
||||||
|
self.recv.try_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
pub mod swap_buf;
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
use std::ops::{Deref, DerefMut, Add};
|
|
||||||
|
|
||||||
pub struct SwapBuffer<T> {
|
|
||||||
read: Vec<T>,
|
|
||||||
write: Vec<T>,
|
|
||||||
modify: Vec<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Default + Copy + Clone + Add<Output = T>> SwapBuffer<T> {
|
|
||||||
pub fn new(size: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
read: vec![T::default(); size],
|
|
||||||
write: vec![T::default(); size],
|
|
||||||
modify: vec![T::default(); size],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn swap(&mut self) {
|
|
||||||
std::mem::swap(&mut self.read, &mut self.write);
|
|
||||||
for (m, r) in self.modify.iter_mut().zip(&mut self.read) {
|
|
||||||
*r = *r + *m;
|
|
||||||
*m = T::default();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rwm(&mut self) -> (&mut Vec<T>, &mut Vec<T>, &mut Vec<T>) {
|
|
||||||
(&mut self.read, &mut self.write, &mut self.modify)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for SwapBuffer<T> {
|
|
||||||
type Target = Vec<T>;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.read
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> DerefMut for SwapBuffer<T> {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.read
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -7,9 +7,12 @@ use ndarray::{Array3, ArrayBase, Dim, SliceArg};
|
|||||||
|
|
||||||
use crate::client::render::voxel::VoxelColor;
|
use crate::client::render::voxel::VoxelColor;
|
||||||
|
|
||||||
#[derive(Debug, Component, Default, Deref, DerefMut)]
|
#[derive(Debug, Clone, Copy, Component, Default)]
|
||||||
|
pub struct Synced;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Component, Default, Deref, DerefMut)]
|
||||||
pub struct Pos(pub Vector3<f32>);
|
pub struct Pos(pub Vector3<f32>);
|
||||||
#[derive(Debug, Component, Default, Deref, DerefMut)]
|
#[derive(Debug, Clone, Copy, Component, Default, Deref, DerefMut)]
|
||||||
pub struct Orientation(pub Rotation3<f32>);
|
pub struct Orientation(pub Rotation3<f32>);
|
||||||
|
|
||||||
pub type VoxelGrid = TrackedGrid<VoxelColor>;
|
pub type VoxelGrid = TrackedGrid<VoxelColor>;
|
||||||
@@ -62,7 +65,7 @@ impl From<Rotation3<f32>> for Orientation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle, Clone)]
|
||||||
pub struct VoxelGridBundle {
|
pub struct VoxelGridBundle {
|
||||||
pub pos: Pos,
|
pub pos: Pos,
|
||||||
pub orientation: Orientation,
|
pub orientation: Orientation,
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
use std::{ops::Deref, sync::mpsc::{channel, Receiver, Sender}};
|
|
||||||
|
|
||||||
pub type EntityID = usize;
|
|
||||||
|
|
||||||
pub struct Component<T> {
|
|
||||||
id: EntityID,
|
|
||||||
val: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for Component<T> {
|
|
||||||
type Target = T;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ComponentVec<T> {
|
|
||||||
vec: Vec<Component<T>>,
|
|
||||||
changes: Vec<EntityID>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> IntoIterator for &'a ComponentVec<T> {
|
|
||||||
type Item = &'a Component<T>;
|
|
||||||
type IntoIter = std::slice::Iter<'a, Component<T>>;
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
(&self.vec).into_iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ComponentMut<'a, T> {
|
|
||||||
cmp: &'a Component<T>,
|
|
||||||
send: Sender<EntityID>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ComponentMutIter<'a, T> {
|
|
||||||
iter: std::slice::IterMut<'a, Component<T>>,
|
|
||||||
recv: Receiver<EntityID>,
|
|
||||||
send: Sender<EntityID>,
|
|
||||||
i: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> Iterator for ComponentMutIter<'a, T> {
|
|
||||||
type Item = ComponentMut<'a, T>;
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
self.iter.next().map(|c| ComponentMut {
|
|
||||||
cmp: c,
|
|
||||||
send: self.send.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> IntoIterator for &'a mut ComponentVec<T> {
|
|
||||||
type Item = ComponentMut<'a, T>;
|
|
||||||
type IntoIter = ComponentMutIter<'a, T>;
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
let (send, recv) = channel();
|
|
||||||
ComponentMutIter {
|
|
||||||
iter: (&mut self.vec).into_iter(),
|
|
||||||
recv,
|
|
||||||
send,
|
|
||||||
i: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
mod component;
|
|
||||||
mod world;
|
|
||||||
pub use component::*;
|
|
||||||
pub use world::*;
|
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
pub struct World {
|
|
||||||
}
|
|
||||||
|
|
||||||
impl World {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
use nalgebra::{Rotation3, Vector3};
|
|
||||||
|
|
||||||
use super::component::VoxelGrid;
|
|
||||||
|
|
||||||
#[derive(GlobalEvent)]
|
|
||||||
pub struct SpawnVoxelGrid {
|
|
||||||
pub pos: Vector3<f32>,
|
|
||||||
pub orientation: Rotation3<f32>,
|
|
||||||
pub grid: VoxelGrid,
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -5,11 +5,11 @@ use ndarray::Array3;
|
|||||||
|
|
||||||
use crate::client::render::voxel::VoxelColor;
|
use crate::client::render::voxel::VoxelColor;
|
||||||
|
|
||||||
use super::component::VoxelGridBundle;
|
use super::component::{Synced, VoxelGridBundle};
|
||||||
|
|
||||||
pub fn generate(world: &mut World) {
|
pub fn generate(world: &mut World) {
|
||||||
let dim = (15, 10, 10);
|
let dim = (15, 10, 10);
|
||||||
world.spawn(VoxelGridBundle {
|
world.spawn((VoxelGridBundle {
|
||||||
pos: Vector3::new(0.0, 0.0, 20.0).into(),
|
pos: Vector3::new(0.0, 0.0, 20.0).into(),
|
||||||
orientation: Rotation3::from_axis_angle(&Vector3::y_axis(), 0.5).into(),
|
orientation: Rotation3::from_axis_angle(&Vector3::y_axis(), 0.5).into(),
|
||||||
grid: VoxelGrid::new(Array3::from_shape_fn(dim, |(x, y, z)| {
|
grid: VoxelGrid::new(Array3::from_shape_fn(dim, |(x, y, z)| {
|
||||||
@@ -33,10 +33,10 @@ pub fn generate(world: &mut World) {
|
|||||||
VoxelColor::none()
|
VoxelColor::none()
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
});
|
}, Synced));
|
||||||
|
|
||||||
let dim = (1000, 2, 1000);
|
let dim = (1000, 2, 1000);
|
||||||
world.spawn(VoxelGridBundle {
|
world.spawn((VoxelGridBundle {
|
||||||
pos: Vector3::new(0.0, -2.1, 0.0).into(),
|
pos: Vector3::new(0.0, -2.1, 0.0).into(),
|
||||||
orientation: Rotation3::identity().into(),
|
orientation: Rotation3::identity().into(),
|
||||||
grid: VoxelGrid::new(Array3::from_shape_fn(dim, |(x, y, z)| {
|
grid: VoxelGrid::new(Array3::from_shape_fn(dim, |(x, y, z)| {
|
||||||
@@ -53,10 +53,10 @@ pub fn generate(world: &mut World) {
|
|||||||
VoxelColor::none()
|
VoxelColor::none()
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
});
|
}, Synced));
|
||||||
|
|
||||||
let dim = (3, 3, 3);
|
let dim = (3, 3, 3);
|
||||||
world.spawn(VoxelGridBundle {
|
world.spawn((VoxelGridBundle {
|
||||||
pos: Vector3::new(0.0, 0.0, 16.5).into(),
|
pos: Vector3::new(0.0, 0.0, 16.5).into(),
|
||||||
orientation: (Rotation3::from_axis_angle(&Vector3::y_axis(), std::f32::consts::PI / 4.0)
|
orientation: (Rotation3::from_axis_angle(&Vector3::y_axis(), std::f32::consts::PI / 4.0)
|
||||||
* Rotation3::from_axis_angle(
|
* Rotation3::from_axis_angle(
|
||||||
@@ -70,5 +70,5 @@ pub fn generate(world: &mut World) {
|
|||||||
b: 255,
|
b: 255,
|
||||||
a: 255,
|
a: 255,
|
||||||
})),
|
})),
|
||||||
});
|
}, Synced));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user