Compare commits
No commits in common. "072b54cafece52e9e565d938ec2d1863bc3fceca" and "b3deecc02f3e31762d403cbf0d4d7f4f8be426bc" have entirely different histories.
072b54cafe
...
b3deecc02f
|
|
@ -1,3 +1,2 @@
|
||||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||||
*.tiff filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.data filter=lfs diff=lfs merge=lfs -text
|
*.data filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct DemRenderer {
|
pub struct DemRenderer {
|
||||||
pub source: Rc<Dem>,
|
source: Rc<Dem>,
|
||||||
pipeline: wgpu::RenderPipeline,
|
pipeline: wgpu::RenderPipeline,
|
||||||
bind_group: wgpu::BindGroup,
|
bind_group: wgpu::BindGroup,
|
||||||
vertex_buffer: wgpu::Buffer,
|
vertex_buffer: wgpu::Buffer,
|
||||||
|
|
@ -577,5 +577,5 @@ fn get_animated_camera_position(animation_phase: f32, dem_size: f32) -> glam::Ve
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[cfg(test)]
|
#[cfg(test)]
|
||||||
//mod tests;
|
mod tests;
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ async fn run_compute_shader_test(
|
||||||
required_features: wgpu::Features::empty(),
|
required_features: wgpu::Features::empty(),
|
||||||
required_limits: wgpu::Limits::downlevel_defaults(),
|
required_limits: wgpu::Limits::downlevel_defaults(),
|
||||||
memory_hints: wgpu::MemoryHints::MemoryUsage,
|
memory_hints: wgpu::MemoryHints::MemoryUsage,
|
||||||
trace: wgpu::Trace::Off,
|
|
||||||
},
|
},
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -87,7 +87,7 @@ async fn run_compute_shader_test(
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let buffer_slice = staging_buffer.slice(..);
|
let buffer_slice = staging_buffer.slice(..);
|
||||||
buffer_slice.map_async(wgpu::MapMode::Read, move |v| tx.send(v).unwrap());
|
buffer_slice.map_async(wgpu::MapMode::Read, move |v| tx.send(v).unwrap());
|
||||||
assert!(device.poll(wgpu::PollType::wait()).unwrap().wait_finished());
|
device.poll(wgpu::Maintain::wait()).panic_on_timeout();
|
||||||
if let Ok(Ok(())) = rx.recv() {
|
if let Ok(Ok(())) = rx.recv() {
|
||||||
buffer_slice.get_mapped_range().to_vec()
|
buffer_slice.get_mapped_range().to_vec()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -99,7 +99,7 @@ async fn run_compute_shader_test(
|
||||||
#[derive(Clone, Copy, Pod, Zeroable)]
|
#[derive(Clone, Copy, Pod, Zeroable)]
|
||||||
struct Vec3 {
|
struct Vec3 {
|
||||||
elements: [f32; 3],
|
elements: [f32; 3],
|
||||||
_padding: f32,
|
_padding: f32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -114,7 +114,7 @@ struct TestInput {
|
||||||
fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
|
fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
|
||||||
Vec3 {
|
Vec3 {
|
||||||
elements: [x, y, z],
|
elements: [x, y, z],
|
||||||
_padding: 0.0,
|
_padding: 0.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::mvu::{Event, File, FrameTimer, MvuApp, Size2i};
|
use crate::mvu::{Event, File, MvuApp, Size2i, FrameTimer};
|
||||||
use {
|
use {
|
||||||
log::info,
|
log::info,
|
||||||
std::borrow::Cow,
|
std::borrow::Cow,
|
||||||
|
|
@ -11,9 +11,6 @@ mod dem_renderer;
|
||||||
mod raster;
|
mod raster;
|
||||||
use dem_renderer::DemRenderer;
|
use dem_renderer::DemRenderer;
|
||||||
|
|
||||||
mod statistics_reporter;
|
|
||||||
use statistics_reporter::StatisticsReporter;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
dem: Option<Rc<raster::Dem>>,
|
dem: Option<Rc<raster::Dem>>,
|
||||||
|
|
@ -33,7 +30,6 @@ struct Context {
|
||||||
queue: Queue,
|
queue: Queue,
|
||||||
scene_data: Option<DemRenderer>,
|
scene_data: Option<DemRenderer>,
|
||||||
frame_timer: Box<dyn FrameTimer>,
|
frame_timer: Box<dyn FrameTimer>,
|
||||||
statistics_reporter: StatisticsReporter,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -63,17 +59,14 @@ impl MvuApp<Model> for App {
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("Failed to find an appropriate adapter");
|
.expect("Failed to find an appropriate adapter");
|
||||||
info!(
|
info!("Using {} backend with {}", adapter.get_info().backend, adapter.get_info().name);
|
||||||
"Using {} backend with {}",
|
|
||||||
adapter.get_info().backend,
|
|
||||||
adapter.get_info().name
|
|
||||||
);
|
|
||||||
|
|
||||||
let (device, queue) = adapter
|
let (device, queue) = adapter
|
||||||
.request_device(&wgpu::DeviceDescriptor {
|
.request_device(&wgpu::DeviceDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
required_features: wgpu::Features::empty(),
|
required_features: wgpu::Features::empty(),
|
||||||
required_limits: wgpu::Limits::default().using_resolution(adapter.limits()),
|
required_limits: wgpu::Limits::default()
|
||||||
|
.using_resolution(adapter.limits()),
|
||||||
memory_hints: wgpu::MemoryHints::MemoryUsage,
|
memory_hints: wgpu::MemoryHints::MemoryUsage,
|
||||||
trace: Trace::Off,
|
trace: Trace::Off,
|
||||||
})
|
})
|
||||||
|
|
@ -130,8 +123,7 @@ impl MvuApp<Model> for App {
|
||||||
render_pipeline,
|
render_pipeline,
|
||||||
queue,
|
queue,
|
||||||
scene_data: None,
|
scene_data: None,
|
||||||
frame_timer,
|
frame_timer: frame_timer,
|
||||||
statistics_reporter: StatisticsReporter::new(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
info!("Initialized {}x{}.", size.width, size.height);
|
info!("Initialized {}x{}.", size.width, size.height);
|
||||||
|
|
@ -157,22 +149,14 @@ impl MvuApp<Model> for App {
|
||||||
match event {
|
match event {
|
||||||
Event::MouseButtonPressed => model,
|
Event::MouseButtonPressed => model,
|
||||||
Event::OpenTestFile(file_path) => open_test_file(file_path, model.clone()),
|
Event::OpenTestFile(file_path) => open_test_file(file_path, model.clone()),
|
||||||
Event::ClearScene => clear_scene(model.clone()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn view(&mut self, model: Rc<Model>) -> Result<(), Box<dyn std::error::Error>> {
|
async fn view(&mut self, model: Rc<Model>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if let Some(context) = &mut self.context {
|
if let Some(context) = &mut self.context {
|
||||||
context.frame_timer.mark_frame_start();
|
context.frame_timer.mark_frame_start();
|
||||||
context
|
if context.scene_data.is_none() {
|
||||||
.statistics_reporter
|
|
||||||
.log_frame_time_seconds(context.frame_timer.get_frame_time_seconds());
|
|
||||||
if let Some(dem) = &model.dem {
|
if let Some(dem) = &model.dem {
|
||||||
if context
|
|
||||||
.scene_data
|
|
||||||
.as_ref()
|
|
||||||
.is_none_or(|scene_data| scene_data.source.id != dem.id)
|
|
||||||
{
|
|
||||||
context.scene_data = Some(DemRenderer::new(
|
context.scene_data = Some(DemRenderer::new(
|
||||||
dem.clone(),
|
dem.clone(),
|
||||||
&context.device,
|
&context.device,
|
||||||
|
|
@ -180,8 +164,6 @@ impl MvuApp<Model> for App {
|
||||||
&context.queue,
|
&context.queue,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
context.scene_data = None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let frame = context
|
let frame = context
|
||||||
|
|
@ -233,10 +215,3 @@ fn open_test_file(file: Box<dyn File>, model: Rc<Model>) -> Rc<Model> {
|
||||||
let dem = Some(Rc::new(raster::Dem::load_from_image(file)));
|
let dem = Some(Rc::new(raster::Dem::load_from_image(file)));
|
||||||
Rc::new(Model { dem, ..*model })
|
Rc::new(Model { dem, ..*model })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_scene(model: Rc<Model>) -> Rc<Model> {
|
|
||||||
Rc::new(Model {
|
|
||||||
dem: None,
|
|
||||||
..*model
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::mvu::File;
|
use crate::mvu::File;
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Dem {
|
pub struct Dem {
|
||||||
|
|
@ -12,7 +11,6 @@ pub struct Dem {
|
||||||
pub z_min: f32,
|
pub z_min: f32,
|
||||||
pub z_max: f32,
|
pub z_max: f32,
|
||||||
pub grid: Vec<u16>,
|
pub grid: Vec<u16>,
|
||||||
pub id: Id,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for Dem {
|
impl std::fmt::Debug for Dem {
|
||||||
|
|
@ -48,18 +46,6 @@ pub struct DemBvhLayer {
|
||||||
pub data: Vec<u16>,
|
pub data: Vec<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
|
||||||
pub struct Id(u32);
|
|
||||||
|
|
||||||
impl Id {
|
|
||||||
fn get_next() -> Self {
|
|
||||||
NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
|
||||||
Self(NEXT_ID.load(Ordering::SeqCst))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static NEXT_ID: AtomicU32 = AtomicU32::new(0);
|
|
||||||
|
|
||||||
/// Find the smallest number that's larger then the input and that is also one
|
/// Find the smallest number that's larger then the input and that is also one
|
||||||
/// less than a power of two.
|
/// less than a power of two.
|
||||||
fn round_bound(v: u32) -> u32 {
|
fn round_bound(v: u32) -> u32 {
|
||||||
|
|
@ -212,7 +198,6 @@ impl Dem {
|
||||||
z_min,
|
z_min,
|
||||||
z_max,
|
z_max,
|
||||||
grid,
|
grid,
|
||||||
id: Id::get_next(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
@ -298,7 +283,6 @@ mod tests {
|
||||||
z_min: z1.min(z2),
|
z_min: z1.min(z2),
|
||||||
z_max: z1.max(z2),
|
z_max: z1.max(z2),
|
||||||
grid,
|
grid,
|
||||||
id: Id::get_next()
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.boxed()
|
.boxed()
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ impl File for std::io::Cursor<Vec<u8>> {}
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
MouseButtonPressed,
|
MouseButtonPressed,
|
||||||
OpenTestFile(Box<dyn File>),
|
OpenTestFile(Box<dyn File>),
|
||||||
ClearScene,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
|
|
||||||
|
|
@ -112,16 +112,6 @@ impl PteropusCanvas {
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
pub async fn clear_scene(&mut self) {
|
|
||||||
self.model = self
|
|
||||||
.app
|
|
||||||
.lock()
|
|
||||||
.expect("get app mutex")
|
|
||||||
.update(Rc::clone(&self.model), Event::ClearScene)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_canvas(&self) -> HtmlCanvasElement {
|
pub fn get_canvas(&self) -> HtmlCanvasElement {
|
||||||
let window = web_sys::window().expect("get window");
|
let window = web_sys::window().expect("get window");
|
||||||
let document = window.document().expect("get HTML document");
|
let document = window.document().expect("get HTML document");
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,61 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Pteropus</title>
|
<title>Pteropus</title>
|
||||||
<link rel="stylesheet" href="pteropus-frame.css">
|
<style>
|
||||||
|
#pteropus-canvas {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="whole-window">
|
|
||||||
<script type="module" src="pteropus-frame.js"></script>
|
|
||||||
<canvas id="pteropus-canvas"></canvas>
|
<canvas id="pteropus-canvas"></canvas>
|
||||||
<div id="bottom-panel">
|
<script type="module">
|
||||||
<input type="file" id="file-upload-file-input" accept="image/tiff, .tif, .tiff">
|
import init, {init_pteropus} from '../pkg/pteropus.js';
|
||||||
<button id="clear-scene-button">Clear Scene</button>
|
|
||||||
<button id="load-small-sample-button">Load Small Sample</button>
|
function fileDragOverHandler(event) {
|
||||||
<button id="load-medium-sample-button">Load Medium Sample</button>
|
event.preventDefault();
|
||||||
<button id="load-large-sample-button">Load Large Sample</button>
|
}
|
||||||
</div>
|
|
||||||
</div>
|
async function run() {
|
||||||
</body>
|
await init();
|
||||||
|
|
||||||
|
let pteropus = await init_pteropus();
|
||||||
|
|
||||||
|
let test_file_data = null;
|
||||||
|
let needs_resize = true;
|
||||||
|
|
||||||
|
let mainCanvas = document.getElementById("pteropus-canvas");
|
||||||
|
mainCanvas.addEventListener("drop", async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
test_file_data = event.dataTransfer.files[0]
|
||||||
|
});
|
||||||
|
mainCanvas.addEventListener("dragover", fileDragOverHandler);
|
||||||
|
const resizeObserver = new ResizeObserver((entries) => {
|
||||||
|
needs_resize = true;
|
||||||
|
});
|
||||||
|
resizeObserver.observe(mainCanvas)
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
await pteropus.render();
|
||||||
|
// TODO: I really want to do this asynchronously, with the drop
|
||||||
|
// event listener calling pteropus_load_file directly, but I need
|
||||||
|
// to figure out how to get that to work.
|
||||||
|
if(test_file_data) {
|
||||||
|
await pteropus.load_file(test_file_data);
|
||||||
|
test_file_data = null
|
||||||
|
}
|
||||||
|
if(needs_resize) {
|
||||||
|
await pteropus.on_resize();
|
||||||
|
needs_resize = false;
|
||||||
|
}
|
||||||
|
await new Promise(requestAnimationFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
BIN
web/large_sample.tiff (Stored with Git LFS)
BIN
web/large_sample.tiff (Stored with Git LFS)
Binary file not shown.
BIN
web/medium_sample.tiff (Stored with Git LFS)
BIN
web/medium_sample.tiff (Stored with Git LFS)
Binary file not shown.
|
|
@ -1,27 +0,0 @@
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#whole-window {
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pteropus-canvas {
|
|
||||||
display: flex;
|
|
||||||
flex-grow: 1;
|
|
||||||
margin: 0.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bottom-panel {
|
|
||||||
display: flex;
|
|
||||||
flex-grow: 0;
|
|
||||||
margin: 0.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin-left: 0.2rem;
|
|
||||||
margin-right: 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
import init, {init_pteropus} from '../pkg/pteropus.js';
|
|
||||||
|
|
||||||
function fileDragOverHandler(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function run() {
|
|
||||||
await init();
|
|
||||||
|
|
||||||
let pteropus = await init_pteropus();
|
|
||||||
|
|
||||||
let test_file_data = null;
|
|
||||||
let needs_resize = true;
|
|
||||||
let clear_scene = false;
|
|
||||||
|
|
||||||
let mainCanvas = document.getElementById("pteropus-canvas");
|
|
||||||
mainCanvas.addEventListener("drop", async (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
test_file_data = event.dataTransfer.files[0]
|
|
||||||
});
|
|
||||||
mainCanvas.addEventListener("dragover", fileDragOverHandler);
|
|
||||||
const resizeObserver = new ResizeObserver((entries) => {
|
|
||||||
needs_resize = true;
|
|
||||||
});
|
|
||||||
resizeObserver.observe(mainCanvas);
|
|
||||||
|
|
||||||
let fileUploadButton = document.getElementById("file-upload-file-input");
|
|
||||||
fileUploadButton.addEventListener("change", () => {
|
|
||||||
const files = fileUploadButton.files;
|
|
||||||
if(files.length > 0) {
|
|
||||||
test_file_data = files[0]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let clearSceneButton = document.getElementById("clear-scene-button");
|
|
||||||
clearSceneButton.addEventListener("click", () => {
|
|
||||||
clear_scene = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
buttonId: "load-small-sample-button",
|
|
||||||
url: "small_sample.tiff"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buttonId: "load-medium-sample-button",
|
|
||||||
url: "medium_sample.tiff"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buttonId: "load-large-sample-button",
|
|
||||||
url: "large_sample.tiff"
|
|
||||||
}
|
|
||||||
].forEach( (sample) => {
|
|
||||||
let loadSampleButton = document.getElementById(sample.buttonId);
|
|
||||||
loadSampleButton.addEventListener("click", async () => {
|
|
||||||
const response = await fetch(sample.url);
|
|
||||||
if(!response.ok) {
|
|
||||||
console.error("Couild not load sample file.")
|
|
||||||
}
|
|
||||||
test_file_data = await response.blob()
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
await pteropus.render();
|
|
||||||
if(needs_resize) {
|
|
||||||
await pteropus.on_resize();
|
|
||||||
needs_resize = false;
|
|
||||||
}
|
|
||||||
if(clear_scene) {
|
|
||||||
await pteropus.clear_scene();
|
|
||||||
clear_scene = false;
|
|
||||||
}
|
|
||||||
// TODO: I really want to do this asynchronously, with the drop
|
|
||||||
// event listener calling pteropus_load_file directly, but I need
|
|
||||||
// to figure out how to get that to work.
|
|
||||||
if(test_file_data) {
|
|
||||||
await pteropus.load_file(test_file_data);
|
|
||||||
test_file_data = null
|
|
||||||
}
|
|
||||||
await new Promise(requestAnimationFrame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
run();
|
|
||||||
BIN
web/small_sample.tiff (Stored with Git LFS)
BIN
web/small_sample.tiff (Stored with Git LFS)
Binary file not shown.
Loading…
Reference in New Issue