|
|
|
@ -1,21 +1,13 @@
@@ -1,21 +1,13 @@
|
|
|
|
|
function push_circle_at(positions, cl, r, g, b, c, o) { |
|
|
|
|
positions.push(c.x + o[0].x, c.y + o[0].y, c.x + o[4].x, c.y + o[4].y, c.x + o[8].x, c.y + o[8].y); |
|
|
|
|
positions.push(c.x + o[4].x, c.y + o[4].y, c.x + o[0].x, c.y + o[0].y, c.x + o[2].x, c.y + o[2].y); |
|
|
|
|
positions.push(c.x + o[8].x, c.y + o[8].y, c.x + o[4].x, c.y + o[4].y, c.x + o[6].x, c.y + o[6].y); |
|
|
|
|
positions.push(c.x + o[0].x, c.y + o[0].y, c.x + o[8].x, c.y + o[8].y, c.x + o[10].x, c.y + o[10].y); |
|
|
|
|
positions.push(c.x + o[2].x, c.y + o[2].y, c.x + o[0].x, c.y + o[0].y, c.x + o[1].x, c.y + o[1].y); |
|
|
|
|
positions.push(c.x + o[4].x, c.y + o[4].y, c.x + o[2].x, c.y + o[2].y, c.x + o[3].x, c.y + o[3].y); |
|
|
|
|
positions.push(c.x + o[6].x, c.y + o[6].y, c.x + o[4].x, c.y + o[4].y, c.x + o[5].x, c.y + o[5].y); |
|
|
|
|
positions.push(c.x + o[8].x, c.y + o[8].y, c.x + o[6].x, c.y + o[6].y, c.x + o[7].x, c.y + o[7].y); |
|
|
|
|
positions.push(c.x + o[10].x, c.y + o[10].y, c.x + o[8].x, c.y + o[8].y, c.x + o[9].x, c.y + o[9].y); |
|
|
|
|
positions.push(c.x + o[0].x, c.y + o[0].y, c.x + o[10].x, c.y + o[10].y, c.x + o[11].x, c.y + o[11].y); |
|
|
|
|
|
|
|
|
|
for (let i = 0; i < 3 * 10; ++i) { |
|
|
|
|
function push_circle_at(circle_positions, cl, r, g, b, c, radius) { |
|
|
|
|
circle_positions.push(c.x - radius, c.y - radius, c.x - radius, c.y + radius, c.x + radius, c.y - radius); |
|
|
|
|
circle_positions.push(c.x + radius, c.y + radius, c.x + radius, c.y - radius, c.x - radius, c.y + radius); |
|
|
|
|
|
|
|
|
|
for (let i = 0; i < 6; ++i) { |
|
|
|
|
cl.push(r, g, b); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function push_stroke(state, stroke, positions, colors) { |
|
|
|
|
function push_stroke(state, stroke, positions, colors, circle_positions, circle_colors) { |
|
|
|
|
const starting_length = positions.length; |
|
|
|
|
const stroke_width = stroke.width; |
|
|
|
|
const points = stroke.points; |
|
|
|
@ -35,15 +27,6 @@ function push_stroke(state, stroke, positions, colors) {
@@ -35,15 +27,6 @@ function push_stroke(state, stroke, positions, colors) {
|
|
|
|
|
const POINTS = 12; |
|
|
|
|
const phi_step = 2 * Math.PI / POINTS; |
|
|
|
|
|
|
|
|
|
const circle_offsets = []; |
|
|
|
|
|
|
|
|
|
for (let i = 0; i < POINTS; ++i) { |
|
|
|
|
const phi = phi_step * i; |
|
|
|
|
const ox = stroke_width / 2 * Math.cos(phi); |
|
|
|
|
const oy = stroke_width / 2 * Math.sin(phi); |
|
|
|
|
circle_offsets.push({'x': ox, 'y': oy}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (let i = 0; i < points.length - 1; ++i) { |
|
|
|
|
const px = points[i].x; |
|
|
|
|
const py = points[i].y; |
|
|
|
@ -85,11 +68,10 @@ function push_stroke(state, stroke, positions, colors) {
@@ -85,11 +68,10 @@ function push_stroke(state, stroke, positions, colors) {
|
|
|
|
|
// "poke out" of the rectangle
|
|
|
|
|
const angle = Math.atan(Math.abs(s3x - s4x), Math.abs(s3y - s4y)); |
|
|
|
|
|
|
|
|
|
push_circle_at(positions, colors, r, g, b, points[i], circle_offsets); |
|
|
|
|
push_circle_at(circle_positions, circle_colors, r, g, b, points[i], stroke_width / 2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO: angle
|
|
|
|
|
push_circle_at(positions, colors, r, g, b, points[points.length - 1], circle_offsets); |
|
|
|
|
push_circle_at(circle_positions, circle_colors, r, g, b, points[points.length - 1], stroke_width / 2); |
|
|
|
|
|
|
|
|
|
stroke.popcount = positions.length - starting_length; |
|
|
|
|
} |
|
|
|
@ -127,17 +109,25 @@ function get_static_stroke(state) {
@@ -127,17 +109,25 @@ function get_static_stroke(state) {
|
|
|
|
|
function add_static_stroke(state, context, stroke, relax = false) { |
|
|
|
|
if (!state.online || !stroke) return; |
|
|
|
|
|
|
|
|
|
push_stroke(state, stroke, context.static_positions, context.static_colors); |
|
|
|
|
push_stroke(state, stroke, context.static_positions, context.static_colors, context.static_circle_positions, context.static_circle_colors); |
|
|
|
|
|
|
|
|
|
if (!relax) { |
|
|
|
|
// TODO: incremental
|
|
|
|
|
|
|
|
|
|
context.static_positions_f32 = new Float32Array(context.static_positions); |
|
|
|
|
context.static_colors_u8 = new Uint8Array(context.static_colors); |
|
|
|
|
|
|
|
|
|
context.static_circle_positions_f32 = new Float32Array(context.static_circle_positions); |
|
|
|
|
context.static_circle_colors_u8 = new Uint8Array(context.static_circle_colors); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function recompute_static_data(context) { |
|
|
|
|
context.static_positions_f32 = new Float32Array(context.static_positions); |
|
|
|
|
context.static_colors_u8 = new Uint8Array(context.static_colors); |
|
|
|
|
|
|
|
|
|
context.static_circle_positions_f32 = new Float32Array(context.static_circle_positions); |
|
|
|
|
context.static_circle_colors_u8 = new Uint8Array(context.static_circle_colors); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function total_dynamic_positions(context) { |
|
|
|
@ -150,17 +140,33 @@ function total_dynamic_positions(context) {
@@ -150,17 +140,33 @@ function total_dynamic_positions(context) {
|
|
|
|
|
return total_dynamic_length; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function total_dynamic_circle_positions(context) { |
|
|
|
|
let total_dynamic_length = 0; |
|
|
|
|
|
|
|
|
|
for (const player_id in context.dynamic_circle_positions) { |
|
|
|
|
total_dynamic_length += context.dynamic_circle_positions[player_id].length; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return total_dynamic_length; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function recompute_dynamic_data(state, context) { |
|
|
|
|
const total_dynamic_length = total_dynamic_positions(context); |
|
|
|
|
const total_dynamic_circles_length = total_dynamic_circle_positions(context); |
|
|
|
|
|
|
|
|
|
context.dynamic_positions_f32 = new Float32Array(total_dynamic_length); |
|
|
|
|
context.dynamic_colors_u8 = new Uint8Array(total_dynamic_length / 2 * 3); |
|
|
|
|
|
|
|
|
|
context.dynamic_circle_positions_f32 = new Float32Array(total_dynamic_circles_length); |
|
|
|
|
context.dynamic_circle_colors_u8 = new Uint8Array(total_dynamic_circles_length / 2 * 3); |
|
|
|
|
|
|
|
|
|
let at = 0; |
|
|
|
|
let at_circle = 0; |
|
|
|
|
|
|
|
|
|
for (const player_id in context.dynamic_positions) { |
|
|
|
|
context.dynamic_positions_f32.set(context.dynamic_positions[player_id], at); |
|
|
|
|
|
|
|
|
|
context.dynamic_circle_positions_f32.set(context.dynamic_circle_positions[player_id], at_circle); |
|
|
|
|
|
|
|
|
|
const color_u32 = state.players[player_id].color; |
|
|
|
|
|
|
|
|
|
const r = (color_u32 >> 16) & 0xFF; |
|
|
|
@ -173,7 +179,14 @@ function recompute_dynamic_data(state, context) {
@@ -173,7 +179,14 @@ function recompute_dynamic_data(state, context) {
|
|
|
|
|
context.dynamic_colors_u8[at / 2 * 3 + i * 3 + 2] = b; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (let i = 0; i < context.dynamic_circle_positions[player_id].length; ++i) { |
|
|
|
|
context.dynamic_circle_colors_u8[at_circle / 2 * 3 + i * 3 + 0] = r; |
|
|
|
|
context.dynamic_circle_colors_u8[at_circle / 2 * 3 + i * 3 + 1] = g; |
|
|
|
|
context.dynamic_circle_colors_u8[at_circle / 2 * 3 + i * 3 + 2] = b; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
at += context.dynamic_positions[player_id].length; |
|
|
|
|
at_circle += context.dynamic_circle_positions[player_id].length; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -189,6 +202,9 @@ function update_dynamic_stroke(state, context, player_id, point) {
@@ -189,6 +202,9 @@ function update_dynamic_stroke(state, context, player_id, point) {
|
|
|
|
|
|
|
|
|
|
context.dynamic_positions[player_id] = []; |
|
|
|
|
context.dynamic_colors[player_id] = []; |
|
|
|
|
|
|
|
|
|
context.dynamic_circle_positions[player_id] = []; |
|
|
|
|
context.dynamic_circle_colors[player_id] = []; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
state.current_strokes[player_id].color = state.players[player_id].color; |
|
|
|
@ -198,8 +214,15 @@ function update_dynamic_stroke(state, context, player_id, point) {
@@ -198,8 +214,15 @@ function update_dynamic_stroke(state, context, player_id, point) {
|
|
|
|
|
context.dynamic_positions[player_id].length = 0; |
|
|
|
|
context.dynamic_colors[player_id].length = 0; |
|
|
|
|
|
|
|
|
|
context.dynamic_circle_positions[player_id].length = 0; |
|
|
|
|
context.dynamic_circle_colors[player_id].length = 0; |
|
|
|
|
|
|
|
|
|
state.current_strokes[player_id].points.push(point); |
|
|
|
|
push_stroke(state, state.current_strokes[player_id], context.dynamic_positions[player_id], context.dynamic_colors[player_id]); |
|
|
|
|
|
|
|
|
|
push_stroke(state, state.current_strokes[player_id], |
|
|
|
|
context.dynamic_positions[player_id], context.dynamic_colors[player_id], |
|
|
|
|
context.dynamic_circle_positions[player_id], context.dynamic_circle_colors[player_id] |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
recompute_dynamic_data(state, context); |
|
|
|
|
} |
|
|
|
@ -212,6 +235,7 @@ function clear_dynamic_stroke(state, context, player_id) {
@@ -212,6 +235,7 @@ function clear_dynamic_stroke(state, context, player_id) {
|
|
|
|
|
state.current_strokes[player_id].color = state.players[state.me].color; |
|
|
|
|
state.current_strokes[player_id].width = state.players[state.me].width; |
|
|
|
|
context.dynamic_positions[player_id].length = 0; |
|
|
|
|
context.dynamic_circle_positions[player_id].length = 0; |
|
|
|
|
recompute_dynamic_data(state, context); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|