diff --git a/client/speed.js b/client/speed.js index 0cff410..28406d0 100644 --- a/client/speed.js +++ b/client/speed.js @@ -52,7 +52,6 @@ function do_lod_wasm(state, context) { const segments_from = state.wasm.exports.alloc((context.clipped_indices.size + 1) * 4); const segments = state.wasm.exports.alloc(state.segments.capacity * 4); const coordinates = state.wasm.exports.alloc(state.coordinates.size * 4); - const mem = new Uint8Array(state.wasm.exports.memory.buffer); mem.set(tv_bytes(context.clipped_indices), clipped_indices); @@ -71,6 +70,8 @@ function do_lod_wasm(state, context) { // copy result back const wasm_segments = new Uint32Array(state.wasm.exports.memory.buffer, segments, segment_count); const wasm_segments_from = new Uint32Array(state.wasm.exports.memory.buffer, segments_from, context.clipped_indices.size + 1); + const wasm_points = new Float32Array(state.wasm.exports.memory.buffer, coordinates + state.coordinates.size * 4, segment_count * 2); + const wasm_ids = new Uint32Array(state.wasm.exports.memory.buffer, coordinates + (state.coordinates.size + segment_count * 2) * 4, segment_count); state.segments.data.set(wasm_segments); state.segments.size = segment_count; @@ -78,8 +79,16 @@ function do_lod_wasm(state, context) { state.segments_from.data.set(wasm_segments_from); state.segments_from.size = context.clipped_indices.size + 1; - state.wasm.exports.total_free(); + tv_ensure(context.instance_data_points, segment_count * 2); + tv_ensure(context.instance_data_ids, segment_count); + context.instance_data_points.data.set(wasm_points); + context.instance_data_points.size = segment_count * 2; + + context.instance_data_ids.data.set(wasm_ids); + context.instance_data_ids.size = segment_count; + + state.wasm.exports.total_free(); return segment_count; } @@ -164,5 +173,47 @@ function do_lod(state, context) { state.segments_from.size = context.clipped_indices.size + 1; state.segments.size = segments_head; + write_coordinates(state, context); + return segments_head; } + +function write_coordinates(state, context) { + tv_ensure(context.instance_data_points, state.segments.size * 2); + tv_ensure(context.instance_data_ids, state.segments.size); + + tv_clear(context.instance_data_points); + tv_clear(context.instance_data_ids); + + const clipped = context.clipped_indices.data; + const segments_from = state.segments_from.data; + const segments = state.segments.data; + const coords = state.coordinates.data; + const events = state.events; + + // TODO: move this loop to WASM + for (let i = 0; i < state.segments_from.size - 1; ++i) { + const stroke_index = clipped[i]; + const coords_from = state.events[stroke_index].coords_from; + const from = segments_from[i]; + const to = segments_from[i + 1]; + + for (let j = from; j < to; ++j) { + const base_this = segments[j]; + + const ax = coords[coords_from + base_this * 2 + 0]; + const ay = coords[coords_from + base_this * 2 + 1]; + + tv_add(context.instance_data_points, ax); + tv_add(context.instance_data_points, ay); + + // Pack 1 into highest bit of stroke_index if we should not draw a segemtn from this + // point to the next one + if (j != to - 1) { + tv_add(context.instance_data_ids, stroke_index); + } else { + tv_add(context.instance_data_ids, stroke_index | (1 << 31)); + } + } + } +} diff --git a/client/wasm/lod.c b/client/wasm/lod.c index d911079..eddf487 100644 --- a/client/wasm/lod.c +++ b/client/wasm/lod.c @@ -130,6 +130,37 @@ do_lod(int *clipped_indices, int clipped_count, float zoom, } segments_from[clipped_count] = segments_head; + + // Write actual coordinates (points) and stroke ids + float *points = alloc(segments_head * 2 * 4); + int *ids = alloc(segments_head * 4); + + int phead = 0; + int ihead = 0; + + for (int i = 0; i < clipped_count; ++i) { + int stroke_index = clipped_indices[i]; + + // TODO: convert to a proper CSR, save half the memory + int base_stroke = stroke_coords_from[stroke_index]; + int from = segments_from[i]; + int to = segments_from[i + 1]; + + for (int j = from; j < to; ++j) { + int point_index = segments[j]; + float x = coordinates[base_stroke + point_index * 2 + 0]; + float y = coordinates[base_stroke + point_index * 2 + 1]; + + points[phead++] = x; + points[phead++] = y; + + if (j != to - 1) { + ids[ihead++] = stroke_index; + } else { + ids[ihead++] = stroke_index | (1 << 31); + } + } + } return(segments_head); } diff --git a/client/wasm/lod.wasm b/client/wasm/lod.wasm index 9c0c4f3..67a5163 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 0b252bd..da0740b 100644 --- a/client/webgl_geometry.js +++ b/client/webgl_geometry.js @@ -49,47 +49,9 @@ function geometry_write_instances(state, context) { const segment_count = do_lod(state, context); - tv_ensure(context.instance_data_points, state.segments.size * 2); - tv_ensure(context.instance_data_ids, state.segments.size); - - tv_clear(context.instance_data_points); - tv_clear(context.instance_data_ids); - - const clipped = context.clipped_indices.data; - const segments_from = state.segments_from.data; - const segments = state.segments.data; - const coords = state.coordinates.data; - const events = state.events; - - // TODO: move this loop to WASM - for (let i = 0; i < state.segments_from.size - 1; ++i) { - const stroke_index = clipped[i]; - const coords_from = state.events[stroke_index].coords_from; - const from = segments_from[i]; - const to = segments_from[i + 1]; - - for (let j = from; j < to; ++j) { - const base_this = segments[j]; - - const ax = coords[coords_from + base_this * 2 + 0]; - const ay = coords[coords_from + base_this * 2 + 1]; - - tv_add(context.instance_data_points, ax); - tv_add(context.instance_data_points, ay); - - // Pack 1 into highest bit of stroke_index if we should not draw a segemtn from this - // point to the next one - if (j != to - 1) { - tv_add(context.instance_data_ids, stroke_index); - } else { - tv_add(context.instance_data_ids, stroke_index | (1 << 31)); - } - } - } - if (config.debug_print) console.debug('instances:', state.segments.count, 'rdp max:', state.stats.rdp_max_count, 'rdp segments:', state.stats.rdp_segments); - return state.segments.size; + return segment_count; } function geometry_add_stroke(state, context, stroke, stroke_index, skip_bvh = false) {