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
|
||||
*.tiff filter=lfs diff=lfs merge=lfs -text
|
||||
*.data filter=lfs diff=lfs merge=lfs -text
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use {
|
|||
};
|
||||
|
||||
pub struct DemRenderer {
|
||||
pub source: Rc<Dem>,
|
||||
source: Rc<Dem>,
|
||||
pipeline: wgpu::RenderPipeline,
|
||||
bind_group: wgpu::BindGroup,
|
||||
vertex_buffer: wgpu::Buffer,
|
||||
|
|
@ -577,5 +577,5 @@ fn get_animated_camera_position(animation_phase: f32, dem_size: f32) -> glam::Ve
|
|||
)
|
||||
}
|
||||
|
||||
//#[cfg(test)]
|
||||
//mod tests;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ async fn run_compute_shader_test(
|
|||
required_features: wgpu::Features::empty(),
|
||||
required_limits: wgpu::Limits::downlevel_defaults(),
|
||||
memory_hints: wgpu::MemoryHints::MemoryUsage,
|
||||
trace: wgpu::Trace::Off,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
@ -87,7 +87,7 @@ async fn run_compute_shader_test(
|
|||
let (tx, rx) = channel();
|
||||
let buffer_slice = staging_buffer.slice(..);
|
||||
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() {
|
||||
buffer_slice.get_mapped_range().to_vec()
|
||||
} else {
|
||||
|
|
@ -99,7 +99,7 @@ async fn run_compute_shader_test(
|
|||
#[derive(Clone, Copy, Pod, Zeroable)]
|
||||
struct Vec3 {
|
||||
elements: [f32; 3],
|
||||
_padding: f32,
|
||||
_padding: f32
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
|
@ -114,7 +114,7 @@ struct TestInput {
|
|||
fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
|
||||
Vec3 {
|
||||
elements: [x, y, z],
|
||||
_padding: 0.0,
|
||||
_padding: 0.0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ fn test_shaders() {
|
|||
bytemuck::cast_slice(&input_buffer),
|
||||
input_buffer.len() * 4,
|
||||
)))
|
||||
.to_vec();
|
||||
.to_vec();
|
||||
assert!(dbg!(output_buffer[0]) >= 0.0);
|
||||
assert!(dbg!(output_buffer[1]) < 0.0);
|
||||
assert!(dbg!(output_buffer[2]) >= 0.0);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use crate::mvu::{Event, File, FrameTimer, MvuApp, Size2i};
|
||||
use crate::mvu::{Event, File, MvuApp, Size2i, FrameTimer};
|
||||
use {
|
||||
log::info,
|
||||
std::borrow::Cow,
|
||||
|
|
@ -11,9 +11,6 @@ mod dem_renderer;
|
|||
mod raster;
|
||||
use dem_renderer::DemRenderer;
|
||||
|
||||
mod statistics_reporter;
|
||||
use statistics_reporter::StatisticsReporter;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Model {
|
||||
dem: Option<Rc<raster::Dem>>,
|
||||
|
|
@ -33,7 +30,6 @@ struct Context {
|
|||
queue: Queue,
|
||||
scene_data: Option<DemRenderer>,
|
||||
frame_timer: Box<dyn FrameTimer>,
|
||||
statistics_reporter: StatisticsReporter,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -63,17 +59,14 @@ impl MvuApp<Model> for App {
|
|||
})
|
||||
.await
|
||||
.expect("Failed to find an appropriate adapter");
|
||||
info!(
|
||||
"Using {} backend with {}",
|
||||
adapter.get_info().backend,
|
||||
adapter.get_info().name
|
||||
);
|
||||
info!("Using {} backend with {}", adapter.get_info().backend, adapter.get_info().name);
|
||||
|
||||
let (device, queue) = adapter
|
||||
.request_device(&wgpu::DeviceDescriptor {
|
||||
label: None,
|
||||
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,
|
||||
trace: Trace::Off,
|
||||
})
|
||||
|
|
@ -130,8 +123,7 @@ impl MvuApp<Model> for App {
|
|||
render_pipeline,
|
||||
queue,
|
||||
scene_data: None,
|
||||
frame_timer,
|
||||
statistics_reporter: StatisticsReporter::new(),
|
||||
frame_timer: frame_timer,
|
||||
});
|
||||
|
||||
info!("Initialized {}x{}.", size.width, size.height);
|
||||
|
|
@ -157,22 +149,14 @@ impl MvuApp<Model> for App {
|
|||
match event {
|
||||
Event::MouseButtonPressed => model,
|
||||
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>> {
|
||||
if let Some(context) = &mut self.context {
|
||||
context.frame_timer.mark_frame_start();
|
||||
context
|
||||
.statistics_reporter
|
||||
.log_frame_time_seconds(context.frame_timer.get_frame_time_seconds());
|
||||
if let Some(dem) = &model.dem {
|
||||
if context
|
||||
.scene_data
|
||||
.as_ref()
|
||||
.is_none_or(|scene_data| scene_data.source.id != dem.id)
|
||||
{
|
||||
if context.scene_data.is_none() {
|
||||
if let Some(dem) = &model.dem {
|
||||
context.scene_data = Some(DemRenderer::new(
|
||||
dem.clone(),
|
||||
&context.device,
|
||||
|
|
@ -180,8 +164,6 @@ impl MvuApp<Model> for App {
|
|||
&context.queue,
|
||||
))
|
||||
}
|
||||
} else {
|
||||
context.scene_data = None;
|
||||
}
|
||||
|
||||
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)));
|
||||
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 std::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Dem {
|
||||
|
|
@ -12,7 +11,6 @@ pub struct Dem {
|
|||
pub z_min: f32,
|
||||
pub z_max: f32,
|
||||
pub grid: Vec<u16>,
|
||||
pub id: Id,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Dem {
|
||||
|
|
@ -48,18 +46,6 @@ pub struct DemBvhLayer {
|
|||
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
|
||||
/// less than a power of two.
|
||||
fn round_bound(v: u32) -> u32 {
|
||||
|
|
@ -212,7 +198,6 @@ impl Dem {
|
|||
z_min,
|
||||
z_max,
|
||||
grid,
|
||||
id: Id::get_next(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
|
@ -298,7 +283,6 @@ mod tests {
|
|||
z_min: z1.min(z2),
|
||||
z_max: z1.max(z2),
|
||||
grid,
|
||||
id: Id::get_next()
|
||||
},
|
||||
)
|
||||
.boxed()
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ impl File for std::io::Cursor<Vec<u8>> {}
|
|||
pub enum Event {
|
||||
MouseButtonPressed,
|
||||
OpenTestFile(Box<dyn File>),
|
||||
ClearScene,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
|
|||
|
|
@ -112,16 +112,6 @@ impl PteropusCanvas {
|
|||
.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 {
|
||||
let window = web_sys::window().expect("get window");
|
||||
let document = window.document().expect("get HTML document");
|
||||
|
|
|
|||
|
|
@ -2,20 +2,61 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Pteropus</title>
|
||||
<link rel="stylesheet" href="pteropus-frame.css">
|
||||
<style>
|
||||
#pteropus-canvas {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="whole-window">
|
||||
<script type="module" src="pteropus-frame.js"></script>
|
||||
<body>
|
||||
<canvas id="pteropus-canvas"></canvas>
|
||||
<div id="bottom-panel">
|
||||
<input type="file" id="file-upload-file-input" accept="image/tiff, .tif, .tiff">
|
||||
<button id="clear-scene-button">Clear Scene</button>
|
||||
<button id="load-small-sample-button">Load Small Sample</button>
|
||||
<button id="load-medium-sample-button">Load Medium Sample</button>
|
||||
<button id="load-large-sample-button">Load Large Sample</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script type="module">
|
||||
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 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>
|
||||
|
|
|
|||
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