async compute tasks working

This commit is contained in:
Lillian Vixe 2024-04-03 17:22:35 -07:00
parent 3eaf009872
commit f8f4a04638
5 changed files with 90 additions and 30 deletions

View file

@ -1,3 +1 @@
[target.wasm32-unknown-unknown]
runner = "wasm-server-runner"

11
.vscode/settings.json vendored
View file

@ -1,16 +1,5 @@
{
"rust-analyzer.linkedProjects": [
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml"
],
"rust-analyzer.cargo.target": "wasm32-unknown-unknown"
}

View file

@ -580,6 +580,7 @@ fn ray_octtree_visitor<T: Clone>(
#[test]
pub fn test_ray_x_octtree() {
use bevy::math::Quat;
let mut oct = OctTree::new(Vec3::new(0., 1., 0.), 0);
oct.set_voxel_at_location(Vec3::new(1., 0., 0.), 1);
let obby = OBB::new(
@ -635,6 +636,7 @@ pub fn test_ray_x_octtree() {
}
#[test]
pub fn test_ray_x_bounding_collisions() {
use bevy::math::Quat;
let abounds: OBB = OBB::new(
Vec3::new(10., 0., 0.),
Quat::from_rotation_y(f32::to_radians(90.)),
@ -673,6 +675,7 @@ pub fn test_sphere_collisions() {
}
#[test]
pub fn test_obb_collisions() {
use bevy::math::Quat;
{
let first = OBB::new(
Vec3::new(0., 0., 0.),
@ -711,6 +714,7 @@ pub fn test_ray_x_sphere_collisions() {
}
#[test]
pub fn test_sphere_x_obb_collisions() {
use bevy::math::Quat;
let obb = OBB::new(
Vec3::ZERO,
Quat::from_rotation_y(f32::to_radians(45.)),
@ -725,6 +729,7 @@ pub fn test_sphere_x_obb_collisions() {
#[test]
pub fn test_oct_x_oct_collisions() {
use bevy::math::Quat;
let oct1 = OctTree::new(Vec3::splat(10.), 10);
let oct2 = OctTree::new(Vec3::splat(10.), 1);
let x = octtree_overlap(
@ -820,6 +825,7 @@ pub fn test_oct_x_oct_collisions() {
#[test]
pub fn test_sphere_internal_transform() {
use bevy::math::Quat;
let pos = Vec3::new(0., 10., 0.);
let size = 10;
let obby = OBB::new(

View file

@ -6,19 +6,28 @@ use bevy::app::Update;
use bevy::asset::Assets;
use bevy::asset::Handle;
use bevy::ecs::component::Component;
use bevy::ecs::system::CommandQueue;
use bevy::ecs::system::Commands;
use bevy::ecs::system::Query;
use bevy::ecs::system::Res;
use bevy::ecs::system::ResMut;
use bevy::ecs::world::World;
use bevy::math::Vec3;
use bevy::render::color::Color;
use bevy::render::mesh::Indices;
use bevy::render::mesh::Mesh;
use bevy::render::mesh::PrimitiveTopology;
use bevy::render::render_asset::RenderAssetUsages;
use bevy::tasks::block_on;
use bevy::tasks::futures_lite::future;
use bevy::tasks::AsyncComputeTaskPool;
use bevy::tasks::Task;
use bevy::time::Time;
use bevy::utils::hashbrown::HashMap;
use rand::Rng;
use self::octtree::Path;
pub mod fps_display;
pub mod inputs;
pub mod intersections;
@ -132,30 +141,54 @@ impl Plugin for OctTreePlugin {
pub struct OctTreeModelComponent {
pub model: octtree::OctTree<Color>,
pub handle: Option<Handle<Mesh>>,
pub task: Option<Task<CommandQueue>>,
//TODO: add Option<> handle for remeshing-event for async-computing it - so if it gets edited again we can cancel the old one and let it run a new mesher async compute
}
/// schedules re-meshing updates of the models used to represent oct-tree data. collisions are instantly updated (as any update to the oct-tree itself updates the data used for collisioning, so we can be lazy about when the visuals kick in (to an extent, of course). as such, we want to kick them into an async updater for the meshes used)
pub fn oct_tree_edit_updater(
mut query: Query<&mut OctTreeModelComponent>,
mut mesh_assets: ResMut<Assets<Mesh>>,
mesh_assets: ResMut<Assets<Mesh>>,
) {
for mut model in &mut query {
if model.handle.is_none() && model.model.needs_update {
let meshed = model.render_as_mesh();
let handle = mesh_assets.add(meshed);
model.handle = Some(handle);
// TODO: refactor to spawn remeshing async task, put in the model
model.model.needs_update = false;
} else if model.model.needs_update && model.handle.is_some() {
//
let meshed = model.render_as_mesh();
mesh_assets.insert(model.handle.clone().unwrap(), meshed);
if model.model.needs_update && model.task.is_none() {
if model.handle.is_none() {
model.handle = Some(mesh_assets.reserve_handle());
}
let thread_pool = AsyncComputeTaskPool::get();
let handle = model.handle.clone().unwrap();
let pre_collect = model.model.collect_voxels();
let task = thread_pool.spawn(async move {
let meshed = OctTreeModelComponent::deferred_render(pre_collect);
let mut command_queue = CommandQueue::default();
command_queue.push(move |world: &mut World| {
let mut mesh_assets = world.resource_mut::<Assets<Mesh>>();
mesh_assets.insert(handle, meshed);
});
return command_queue;
});
model.task = Some(task);
model.model.needs_update = false;
}
}
}
pub fn oct_tree_edit_task_catcher(
mut query: Query<&mut OctTreeModelComponent>,
mut commands: Commands,
) {
for mut model in &mut query {
if model.task.is_some() {
if let Some(mut commands_queue) =
block_on(future::poll_once(&mut model.task.as_mut().unwrap()))
{
commands.append(&mut commands_queue);
model.task = None;
}
}
}
}
//TODO: event that takes finished remeshing events and emits an event to be caught with the relevant mesh to update the meshdata
impl OctTreeModelComponent {
pub fn new(
@ -166,14 +199,47 @@ impl OctTreeModelComponent {
return OctTreeModelComponent {
model: model,
handle: Some(mesh_assets.unwrap().reserve_handle()),
task: None,
};
} else {
return OctTreeModelComponent {
model: model,
handle: None,
task: None,
};
}
}
pub fn deferred_render(elements: Vec<(Path, Vec3, Color)>) -> Mesh {
let mut vertices = Vec::new();
let mut normals = Vec::new();
let mut indices = Vec::new();
let mut colors = Vec::new();
let mut lookup = HashMap::new();
{
for (_, loc, col) in elements {
lookup.insert(as_ia(loc), col);
}
}
for (loc, col) in &lookup {
emit_cube_at(
as_v(*loc),
&mut vertices,
&mut indices,
&mut normals,
&mut colors,
*col,
lookup.get(&as_ia(as_v(*loc) + Vec3::X)).is_none(),
lookup.get(&as_ia(as_v(*loc) + Vec3::NEG_X)).is_none(),
lookup.get(&as_ia(as_v(*loc) + Vec3::Y)).is_none(),
lookup.get(&as_ia(as_v(*loc) + Vec3::NEG_Y)).is_none(),
lookup.get(&as_ia(as_v(*loc) + Vec3::Z)).is_none(),
lookup.get(&as_ia(as_v(*loc) + Vec3::NEG_Z)).is_none(),
None, // will let me do custom per-vox normals later. that requires extra calculation im not doing yet
);
}
return as_mesh(vertices, indices, normals, colors);
}
pub fn render_as_mesh(&self) -> Mesh {
let mut vertices = Vec::new();
let mut normals = Vec::new();
@ -182,7 +248,7 @@ impl OctTreeModelComponent {
let mut lookup = HashMap::new();
{
let elements = self.model.collect_voxels();
let elements: Vec<(Path, Vec3, Color)> = self.model.collect_voxels();
for (_, loc, col) in elements {
lookup.insert(as_ia(loc), col);
}
@ -481,13 +547,13 @@ pub fn occasional_change(
time: Res<Time>,
mut query: Query<(&mut OctTreeModelComponent, &mut ChangeOnTimerRandomized)>,
) {
const INTERVAL: f32 = 2.;
const INTERVAL: f32 = 4.;
for (mut model, mut timer) in &mut query {
//
timer.timer += time.delta_seconds();
if timer.timer > INTERVAL {
let mut rng = rand::thread_rng();
for _ in 0..10000000 {
for _ in 0..100000 {
let x: f32 = rng.gen_range(-10.0..10.0);
let y: f32 = rng.gen_range(-10.0..10.0);
let z: f32 = rng.gen_range(-10.0..10.0);

View file

@ -4,8 +4,8 @@ pub mod mesh_plugin {
use crate::{
orbit_camera::orbit_camera::*,
vvlib::{
iterate_voxels, occasional_change, octtree::OctTree, ChangeOnTimerRandomized,
OctTreeModelComponent, VoxelIterativeBuildTest,
iterate_voxels, occasional_change, oct_tree_edit_task_catcher, octtree::OctTree,
ChangeOnTimerRandomized, OctTreeModelComponent, VoxelIterativeBuildTest,
},
};
@ -16,6 +16,7 @@ pub mod mesh_plugin {
app.add_systems(Update, pan_orbit_camera);
app.add_systems(Update, iterate_voxels);
app.add_systems(Update, occasional_change);
app.add_systems(PostUpdate, oct_tree_edit_task_catcher);
}
}
@ -37,7 +38,7 @@ pub mod mesh_plugin {
..default()
},
model_oct,
VoxelIterativeBuildTest { count: 10000000 },
VoxelIterativeBuildTest { count: 100 },
ChangeOnTimerRandomized { timer: 0. },
))
.id();