diff --git a/README.md b/README.md index 499ac15..39333a1 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Release: + GC stalls!!! + Stroke previews get connected when drawn without panning on touch devices + Redraw HTML (cursors) on local canvas moves - - New strokes dissapear on the HMH desk + + New strokes dissapear on the HMH desk - Debug - Restore ability to limit event range * Listeners/events/multiplayer @@ -51,7 +51,7 @@ Bonus: * Handle pressure + Add pressure data to quads + Account for pressure in quad/bbox calc - * Adjust curve simplification to include pressure info + + Adjust curve simplification to include pressure info - Migrate old non-pressure desks - Check out e.pressure on touch devices - Send pressure in PREDRAW event diff --git a/client/client_recv.js b/client/client_recv.js index ace817d..6b6bf68 100644 --- a/client/client_recv.js +++ b/client/client_recv.js @@ -105,28 +105,13 @@ function des_event(d, state = null) { const width = des_u16(d); const color = des_u32(d); - const coords = des_f32array(d, point_count * 2); - const press = des_u8array(d, point_count); + event.coords = des_f32array(d, point_count * 2); + event.press = des_u8array(d, point_count); des_align(d, 4); - wasm_ensure_by(state, 1, coords.length); - - const coordinates = state.wasm.buffers['coordinates']; - const pressures = state.wasm.buffers['pressures']; - - tv_add(state.wasm.buffers['coords_from'].tv, coordinates.tv.size + point_count * 2); - state.wasm.buffers['coords_from'].used += 4; // 4 bytes, not 4 ints - // TODO: remove, this is duplicate data - event.coords_from = coordinates.tv.size; - event.coords_to = coordinates.tv.size + point_count * 2; - tv_append(coordinates.tv, coords); - state.wasm.buffers['coordinates'].used += point_count * 2 * 4; - - tv_append(pressures.tv, press); - state.wasm.buffers['pressures'].used += point_count; event.stroke_id = stroke_id; @@ -255,6 +240,28 @@ function handle_event(state, context, event, options = {}) { } case EVENT.STROKE: { + const point_count = event.coords.length / 2; + + wasm_ensure_by(state, 1, event.coords.length); + + const coordinates = state.wasm.buffers['coordinates']; + const pressures = state.wasm.buffers['pressures']; + + event.coords_from = coordinates.tv.size; + event.coords_to = coordinates.tv.size + point_count * 2; + + tv_add(state.wasm.buffers['coords_from'].tv, coordinates.tv.size + point_count * 2); + state.wasm.buffers['coords_from'].used += 4; // 4 bytes, not 4 ints + + tv_append(coordinates.tv, event.coords); + state.wasm.buffers['coordinates'].used += point_count * 2 * 4; + + tv_append(pressures.tv, event.press); + state.wasm.buffers['pressures'].used += point_count; + + delete event.coords; + delete event.press; + // TODO: do not do this for my own strokes when we bake locally geometry_clear_player(state, context, event.user_id); need_draw = true; diff --git a/client/math.js b/client/math.js index c9769e6..432fa39 100644 --- a/client/math.js +++ b/client/math.js @@ -91,8 +91,8 @@ function process_stroke(state, zoom, stroke) { return npoints; } -function rdp_find_max2(points, start, end) { - const EPS = 0.25; +function rdp_find_max2(zoom, points, start, end) { + const EPS = 1.0 / zoom; let result = -1; let max_dist = 0; @@ -119,7 +119,7 @@ function rdp_find_max2(points, start, end) { const x = rx + a.x; const y = ry + a.y; - const dist = Math.abs(y - a.y); + const dist = Math.abs(y - a.y) + Math.abs(a.pressure - p.pressure) / 255 + Math.abs(b.pressure - p.pressure) / 255; if (dist > EPS && dist > max_dist) { result = i; @@ -130,30 +130,30 @@ function rdp_find_max2(points, start, end) { return result; } -function process_rdp_r2(points, start, end) { +function process_rdp_r2(zoom, points, start, end) { let result = []; - const max = rdp_find_max2(points, start, end); + const max = rdp_find_max2(zoom, points, start, end); if (max !== -1) { - const before = process_rdp_r2(points, start, max); - const after = process_rdp_r2(points, max, end); + const before = process_rdp_r2(zoom, points, start, max); + const after = process_rdp_r2(zoom, points, max, end); result = [...before, points[max], ...after]; } return result; } -function process_rdp2(points) { - const result = process_rdp_r2(points, 0, points.length - 1); +function process_rdp2(zoom, points) { + const result = process_rdp_r2(zoom, points, 0, points.length - 1); result.unshift(points[0]); result.push(points[points.length - 1]); return result; } // TODO: unify with regular process stroke -function process_stroke2(points) { - const result = process_rdp2(points); +function process_stroke2(zoom, points) { + const result = process_rdp2(zoom, points); return result; } diff --git a/client/wasm/lod.c b/client/wasm/lod.c index bec7683..233359f 100644 --- a/client/wasm/lod.c +++ b/client/wasm/lod.c @@ -32,7 +32,7 @@ alloc_dynamic(int size) } static int -rdp_find_max(float *coordinates, float zoom, int coords_from, +rdp_find_max(float *coordinates, unsigned char *pressures, float zoom, int coords_from, int segment_start, int segment_end) { float EPS = 1.0 / zoom; @@ -44,7 +44,10 @@ rdp_find_max(float *coordinates, float zoom, int coords_from, float ay = coordinates[coords_from + segment_start * 2 + 1]; float bx = coordinates[coords_from + segment_end * 2 + 0]; float by = coordinates[coords_from + segment_end * 2 + 1]; - + + unsigned char ap = pressures[coords_from / 2 + segment_start]; + unsigned char bp = pressures[coords_from / 2 + segment_end]; + float dx = bx - ax; float dy = by - ay; @@ -56,10 +59,13 @@ rdp_find_max(float *coordinates, float zoom, int coords_from, float px = coordinates[coords_from + i * 2 + 0]; float py = coordinates[coords_from + i * 2 + 1]; + unsigned char pp = pressures[coords_from + i]; + float apx = px - ax; float apy = py - ay; float dist = __builtin_fabsf(apx * dir_nx + apy * dir_ny); + //+ __builtin_abs(pp - ap) / 255.0f + __builtin_abs(pp - bp) / 255.0f; if (dist > EPS && dist > max_dist) { result = i; @@ -124,7 +130,7 @@ do_lod(int *clipped_indices, int clipped_count, float zoom, if (type == 1) { segments[segments_head++] = start; } else { - int max = rdp_find_max(coordinates, zoom, coords_from, start, end); + int max = rdp_find_max(coordinates, pressures, zoom, coords_from, start, end); if (max != -1) { segment_count += 1; diff --git a/client/wasm/lod.wasm b/client/wasm/lod.wasm index b11d67b..324b0df 100755 Binary files a/client/wasm/lod.wasm and b/client/wasm/lod.wasm differ diff --git a/client/webgl_geometry.js b/client/webgl_geometry.js index 314844f..7d7bce4 100644 --- a/client/webgl_geometry.js +++ b/client/webgl_geometry.js @@ -26,7 +26,7 @@ function geometry_prepare_stroke(state) { return null; } - const points = process_stroke2(state.players[state.me].points); + const points = process_stroke2(state.canvas.zoom, state.players[state.me].points); return { 'color': state.players[state.me].color, @@ -43,7 +43,7 @@ function geometry_write_instances(state, context) { const segment_count = do_lod(state, context); - if (config.debug_print) console.debug('instances:', state.segments.count, 'rdp max:', state.stats.rdp_max_count, 'rdp segments:', state.stats.rdp_segments); + if (config.debug_print) console.debug('instances:', segment_count, 'rdp max:', state.stats.rdp_max_count, 'rdp segments:', state.stats.rdp_segments); return segment_count; }