there is a map
Some checks failed
build and test / wxbox - latest (push) Has been cancelled
Verify Latest Dependencies / Verify Latest Dependencies (push) Has been cancelled

This commit is contained in:
core 2025-03-08 15:30:13 -05:00
parent 13aa62ecbc
commit d5aea97931
8 changed files with 227 additions and 74 deletions

85
Cargo.lock generated
View file

@ -2354,6 +2354,16 @@ dependencies = [
"libc",
]
[[package]]
name = "matrixmultiply"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a"
dependencies = [
"autocfg",
"rawpointer",
]
[[package]]
name = "maybe-rayon"
version = "0.1.1"
@ -2460,6 +2470,33 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "nalgebra"
version = "0.33.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b"
dependencies = [
"approx",
"matrixmultiply",
"num-complex",
"num-rational",
"num-traits",
"simba",
"typenum",
]
[[package]]
name = "nalgebra-glm"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e441f43bccdf40cb6bd4294321e6983c5bc7b9886112d19fd4c9813976b117e4"
dependencies = [
"approx",
"nalgebra",
"num-traits",
"simba",
]
[[package]]
name = "native-tls"
version = "0.2.12"
@ -2577,6 +2614,15 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [
"num-traits",
]
[[package]]
name = "num-conv"
version = "0.1.0"
@ -3267,6 +3313,12 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "rawpointer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
[[package]]
name = "rayon"
version = "1.10.0"
@ -3497,6 +3549,15 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "safe_arch"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
dependencies = [
"bytemuck",
]
[[package]]
name = "same-file"
version = "1.0.6"
@ -3668,6 +3729,19 @@ dependencies = [
"libc",
]
[[package]]
name = "simba"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa"
dependencies = [
"approx",
"num-complex",
"num-traits",
"paste",
"wide",
]
[[package]]
name = "simd-adler32"
version = "0.3.7"
@ -4721,6 +4795,16 @@ dependencies = [
"web-sys",
]
[[package]]
name = "wide"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22"
dependencies = [
"bytemuck",
"safe_arch",
]
[[package]]
name = "winapi"
version = "0.3.9"
@ -5114,6 +5198,7 @@ dependencies = [
"ehttp",
"glow",
"image",
"nalgebra-glm",
"poll-promise",
"tracing",
"tracing-subscriber",

View file

@ -14,6 +14,7 @@ poll-promise = "0.3"
ehttp = "0.5"
image = "0.25"
bytemuck = "1.22"
nalgebra-glm = "0.19"
[target.'cfg(target_arch = "wasm32")'.dependencies]
tracing-web = "0.1"

View file

@ -94,7 +94,7 @@
}
}
</style>
<link rel="modulepreload" href="/wxbox-client-b2e1a3e7de3c6850.js" crossorigin="anonymous" integrity="sha384-nDqexAJ4zOC1UgJKvlu7tZO/Xu13qGp8nhmNPBCjCZhoWJ2FIphBbxmj+dwXs9Uw"><link rel="preload" href="/wxbox-client-b2e1a3e7de3c6850_bg.wasm" crossorigin="anonymous" integrity="sha384-Qv6lJAdZwj0oPiGat7p3dWQwZr1TtBEsq1J/pIPFPRI4IcAQ2r5ulP2rCVt+eFeN" as="fetch" type="application/wasm"></head>
<link rel="modulepreload" href="/wxbox-client-f7fb5fe8b7aea995.js" crossorigin="anonymous" integrity="sha384-wkhAe67T8C73+DmlG8JEq34RPAIiO8Jf+d3BH/nrBQ1b1NjMqo8csITaVtpbPBwV"><link rel="preload" href="/wxbox-client-f7fb5fe8b7aea995_bg.wasm" crossorigin="anonymous" integrity="sha384-S4pqZqxf4w0VeQcOCwl5kVOUPKF32nnmgmF2zfXPZumbEf5Gr524gAl4j0hlT2/K" as="fetch" type="application/wasm"></head>
<body>
<!-- The WASM code will resize the canvas dynamically -->
@ -111,8 +111,8 @@
<script type="module">
import init, * as bindings from '/wxbox-client-b2e1a3e7de3c6850.js';
const wasm = await init({ module_or_path: '/wxbox-client-b2e1a3e7de3c6850_bg.wasm' });
import init, * as bindings from '/wxbox-client-f7fb5fe8b7aea995.js';
const wasm = await init({ module_or_path: '/wxbox-client-f7fb5fe8b7aea995_bg.wasm' });
window.wasmBindings = bindings;

View file

@ -102,6 +102,20 @@ function getDataViewMemory0() {
return cachedDataViewMemory0;
}
let cachedFloat32ArrayMemory0 = null;
function getFloat32ArrayMemory0() {
if (cachedFloat32ArrayMemory0 === null || cachedFloat32ArrayMemory0.byteLength === 0) {
cachedFloat32ArrayMemory0 = new Float32Array(wasm.memory.buffer);
}
return cachedFloat32ArrayMemory0;
}
function getArrayF32FromWasm0(ptr, len) {
ptr = ptr >>> 0;
return getFloat32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
}
const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined')
? { register: () => {}, unregister: () => {} }
: new FinalizationRegistry(state => {
@ -198,7 +212,7 @@ function debugString(val) {
return className;
}
function __wbg_adapter_32(arg0, arg1, arg2) {
wasm.closure1003_externref_shim(arg0, arg1, arg2);
wasm.closure1007_externref_shim(arg0, arg1, arg2);
}
function takeFromExternrefTable0(idx) {
@ -214,7 +228,7 @@ function __wbg_adapter_35(arg0, arg1) {
}
function __wbg_adapter_40(arg0, arg1, arg2) {
wasm.closure1689_externref_shim(arg0, arg1, arg2);
wasm.closure1693_externref_shim(arg0, arg1, arg2);
}
/**
@ -1534,6 +1548,12 @@ function __wbg_get_imports() {
imports.wbg.__wbg_uniform2f_8174f619e86c3ba2 = function(arg0, arg1, arg2, arg3) {
arg0.uniform2f(arg1, arg2, arg3);
};
imports.wbg.__wbg_uniformMatrix4fv_b684a40949b2ff0b = function(arg0, arg1, arg2, arg3, arg4) {
arg0.uniformMatrix4fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4));
};
imports.wbg.__wbg_uniformMatrix4fv_fa5c91b7cee9bfd5 = function(arg0, arg1, arg2, arg3, arg4) {
arg0.uniformMatrix4fv(arg1, arg2 !== 0, getArrayF32FromWasm0(arg3, arg4));
};
imports.wbg.__wbg_url_5327bc0a41a9b085 = function(arg0, arg1) {
const ret = arg1.url;
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
@ -1613,20 +1633,20 @@ function __wbg_get_imports() {
const ret = false;
return ret;
};
imports.wbg.__wbindgen_closure_wrapper3632 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1004, __wbg_adapter_32);
imports.wbg.__wbindgen_closure_wrapper3642 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1008, __wbg_adapter_32);
return ret;
};
imports.wbg.__wbindgen_closure_wrapper3634 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1004, __wbg_adapter_35);
imports.wbg.__wbindgen_closure_wrapper3644 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1008, __wbg_adapter_35);
return ret;
};
imports.wbg.__wbindgen_closure_wrapper3636 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1004, __wbg_adapter_32);
imports.wbg.__wbindgen_closure_wrapper3646 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1008, __wbg_adapter_32);
return ret;
};
imports.wbg.__wbindgen_closure_wrapper6213 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1690, __wbg_adapter_40);
imports.wbg.__wbindgen_closure_wrapper6223 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1694, __wbg_adapter_40);
return ret;
};
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
@ -1700,6 +1720,7 @@ function __wbg_finalize_init(instance, module) {
wasm = instance.exports;
__wbg_init.__wbindgen_wasm_module = module;
cachedDataViewMemory0 = null;
cachedFloat32ArrayMemory0 = null;
cachedUint8ArrayMemory0 = null;

View file

@ -11,7 +11,7 @@ use poll_promise::Promise;
use tracing::{debug, warn};
use crate::map::osm::OSMBaselayer;
use crate::map::render::{ExtraRenderOptions, MapRender};
use crate::map::tiles::{LayerManager, LayerSource, Tile};
use crate::map::tiles::{LayerId, LayerManager, LayerSource, Tile, XCoord, YCoord, ZoomLevel};
pub struct Map {
pub layer_manager: LayerManager,
@ -57,8 +57,8 @@ impl Map {
})
} else { 0.0 };
self.lat += xy_delta.y as f64 * 0.001;
self.long += xy_delta.x as f64 * 0.001;
self.lat += xy_delta.y as f64 * 0.0005;
self.long -= xy_delta.x as f64 * 0.0005;
self.zoom += z_delta as f64 * 0.01;
if self.zoom < 3.0 { self.zoom = 3.0 };
if self.zoom > 19.0 { self.zoom = 19.0 };
@ -104,24 +104,14 @@ impl Map {
// for each tile, determine pixel coordinates, then offset by the tile fractionals
for x in 0..tiles_x {
for x in 0..=tiles_x+2 {
let tile_x = tilex + x;
for y in 0..tiles_y {
for y in 0..=tiles_y+2 {
let tile_y = tiley + y;
let start_pixel_x = x as isize * 256 - x_tile_frac as isize;
let start_pixel_y = y as isize * 256 - y_tile_frac as isize;
let end_pixel_x = start_pixel_x + 256 - x_tile_frac as isize;
let end_pixel_y = start_pixel_y + 256 -y_tile_frac as isize;
let startx_zerotoone = start_pixel_x as f64 / viewport_width as f64;
let starty_zerotoone = start_pixel_y as f64 / viewport_height as f64;
let endx_zerotoone = end_pixel_x as f64 / viewport_width as f64;
let endy_zerotoone = end_pixel_y as f64 / viewport_height as f64;
let pixel_x = 512_f32 * x as f32 - (2.0*x_tile_frac as f32);
let pixel_y = (-512_f32 * y as f32) + (2.0*y_tile_frac as f32);
let startx_opengl = startx_zerotoone * 2.0 - 1.0;
let starty_opengl = starty_zerotoone * 2.0 - 1.0;
let endx_opengl = endx_zerotoone * 2.0 - 1.0;
let endy_opengl = endy_zerotoone * 2.0 - 1.0;
// download the tile
let tile = self.layer_manager.tiles.entry((z_clamped as usize, tile_x, tile_y, OSMBaselayer::SOURCE_ID))
@ -151,14 +141,9 @@ impl Map {
});
tiles.push(TilesetTile {
sp_x: start_pixel_x as f32,
sp_xclip: startx_opengl as f32,
sp_y: start_pixel_y as f32,
sp_yclip: starty_opengl as f32,
ep_x: end_pixel_x as f32,
ep_xclip: endy_opengl as f32,
ep_y: end_pixel_y as f32,
ep_yclip: endy_opengl as f32,
tileid: (z_clamped as usize, tile_x, tile_y, OSMBaselayer::SOURCE_ID),
x: pixel_x,
y: pixel_y,
tile: match tile.promise.ready() {
None => None,
Some(r) => match r {
@ -184,9 +169,11 @@ impl Map {
let tileset = self.load_tiles(ctx, rect.width() as usize, rect.height() as usize);
let render = self.render.clone();
let options = self.options;
let width = rect.width();
let height = rect.height();
let cb = egui_glow::CallbackFn::new(move |_info, painter| {
let tileset = tileset.clone();
render.lock().unwrap().paint(painter.gl(), tileset, options);
render.lock().unwrap().paint(painter.gl(), width, height, tileset, options);
});
ui.painter().add(egui::PaintCallback {
rect,
@ -201,14 +188,9 @@ struct Tileset {
}
#[derive(Clone)]
struct TilesetTile {
sp_x: f32,
sp_xclip: f32,
sp_y: f32,
sp_yclip: f32,
ep_x: f32,
ep_xclip: f32,
ep_y: f32,
ep_yclip: f32,
tileid: (ZoomLevel, XCoord, YCoord, LayerId),
x: f32,
y: f32,
tile: Option<DynamicImage>
}

View file

@ -1,8 +1,11 @@
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::io::Cursor;
use std::mem;
use glow::{Buffer, HasContext, PixelUnpackData, Program, Texture, VertexArray};
use image::{DynamicImage, EncodableLayout, ImageReader};
use tracing::{debug, error, warn};
use crate::map::tiles::{LayerId, XCoord, YCoord, ZoomLevel};
use crate::map::Tileset;
pub struct MapRender {
@ -11,6 +14,7 @@ pub struct MapRender {
ebo: Buffer,
shader_program: Program,
test_texture: Texture,
texture_cache: HashMap<(ZoomLevel, XCoord, YCoord, LayerId), Texture>
}
#[allow(unsafe_code)]
@ -98,6 +102,7 @@ impl MapRender {
vao,
ebo,
test_texture,
texture_cache: HashMap::new()
})
}
}
@ -111,17 +116,15 @@ impl MapRender {
}
}
pub fn paint(&self, gl: &glow::Context, tileset: Tileset, options: ExtraRenderOptions) {
pub fn paint(&mut self, gl: &glow::Context, width: f32, height: f32, tileset: Tileset, options: ExtraRenderOptions) {
use glow::HasContext as _;
let verticies: &[f32] = &[
// X Y Z S T
0.5, 0.5, 0.0, 1.0, 1.0, // top right
0.5, -0.5, 0.0, 1.0, 0.0, // bottom right
-0.5, -0.5, 0.0, 0.0, 0.0, // bottom left
-0.5, 0.5, 0.0, 0.0, 1.0, // top left
1.0, 1.0, 0.0, 1.0, 1.0, // top right
1.0, -1.0, 0.0, 1.0, 0.0, // bottom right
-1.0, -1.0, 0.0, 0.0, 0.0, // bottom left
-1.0, 1.0, 0.0, 0.0, 1.0, // top left
];
let indicies: &[u32] = &[
0, 1, 3,
@ -132,6 +135,40 @@ impl MapRender {
gl.clear_color(0.5, 0.1, 0.1, 1.0);
gl.clear(glow::COLOR_BUFFER_BIT);
let lock = tileset.tiles.lock().unwrap();
for tile in lock.iter() {
let this_tile_img_data = &tile.tile;
let texture_cache_img_data = self.texture_cache.entry(tile.tileid);
if let Entry::Vacant(_) = texture_cache_img_data { if this_tile_img_data.is_none() { continue; } } // nothing to render yet
let texture = texture_cache_img_data
.or_insert_with(|| {
let img = this_tile_img_data.as_ref().unwrap();
let img_rgb8 = img.flipv().into_rgb8();
let w = img_rgb8.width();
let h = img_rgb8.height();
let raw = img_rgb8.into_raw();
let texture = gl.create_texture().unwrap();
gl.bind_texture(glow::TEXTURE_2D, Some(texture));
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::REPEAT as i32);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, glow::REPEAT as i32);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::NEAREST as i32);
gl.tex_image_2d(
glow::TEXTURE_2D,
0,
glow::RGB as i32,
w as i32,
h as i32,
0,
glow::RGB,
glow::UNSIGNED_BYTE,
PixelUnpackData::Slice(Some(&raw)),
);
gl.generate_mipmap(glow::TEXTURE_2D);
texture
});
gl.bind_vertex_array(Some(self.vao));
gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vbo));
@ -145,17 +182,42 @@ impl MapRender {
gl.enable_vertex_attrib_array(0);
gl.enable_vertex_attrib_array(1);
gl.use_program(Some(self.shader_program));
debug!("{} {}", tile.x, tile.y);
let w = 256.0_f32;
let h = 256.0_f32;
let x = (tile.x + w) / width - 1.0;
let y = (tile.y - h) / width + 1.0;
let transform = nalgebra_glm::translate(&nalgebra_glm::Mat4::identity(), &nalgebra_glm::vec3(x, y, 0.0));
let width = w / width;
let height = h / height;
let transform = nalgebra_glm::scale(&transform, &nalgebra_glm::vec3(width, height, 1.0));
// screenspace-ify:
// map to 0 to 1 space
gl.uniform_matrix_4_f32_slice(
gl.get_uniform_location(self.shader_program, "transform").as_ref(),
false,
(&transform).into(),
);
gl.active_texture(glow::TEXTURE0);
gl.bind_texture(glow::TEXTURE_2D, Some(self.test_texture));
gl.bind_texture(glow::TEXTURE_2D, Some(*texture));
gl.bind_vertex_array(Some(self.vao));
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.ebo));
gl.draw_elements(glow::TRIANGLES, 6, glow::UNSIGNED_INT, 0);
}
}
}

View file

@ -4,7 +4,9 @@ layout (location = 1) in vec2 aTexCoord;
out vec2 texCoord;
uniform mat4 transform;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
texCoord = aTexCoord;
gl_Position = transform * vec4(aPos, 1.0f);
texCoord = vec2(aTexCoord.x, aTexCoord.y);
}