@ -1,38 +1,28 @@
@@ -1,38 +1,28 @@
function push _point ( s , x , y , u , v , r , g , b , type ) {
function push _point _xy ( s , x , y ) {
ser _f32 ( s , x ) ;
ser _f32 ( s , y ) ;
}
function push _point _xyrgb ( s , x , y , r , g , b ) {
ser _f32 ( s , x ) ;
ser _f32 ( s , y ) ;
ser _f32 ( s , u ) ;
ser _f32 ( s , v ) ;
// ser_u8(s, Math.floor(Math.random() * 255));
// ser_u8(s, Math.floor(Math.random() * 255));
// ser_u8(s, Math.floor(Math.random() * 255));
ser _u8 ( s , r ) ;
ser _u8 ( s , g ) ;
ser _u8 ( s , b ) ;
ser _u8 ( s , type ) ;
}
function push _circle ( s , cx , cy , radius , r , g , b ) {
push _point ( s , cx - radius , cy - radius , 0 , 0 , r , g , b , 1 ) ;
push _point ( s , cx - radius , cy + radius , 0 , 1 , r , g , b , 1 ) ;
push _point ( s , cx + radius , cy - radius , 1 , 0 , r , g , b , 1 ) ;
push _point ( s , cx + radius , cy + radius , 1 , 1 , r , g , b , 1 ) ;
push _point ( s , cx + radius , cy - radius , 1 , 0 , r , g , b , 1 ) ;
push _point ( s , cx - radius , cy + radius , 0 , 1 , r , g , b , 1 ) ;
ser _align ( s , 4 ) ;
}
function push _quad ( s , p1x , p1y , p2x , p2y , p3x , p3 y , p4x , p4y , r , g , b ) {
push _point ( s , p1x , p1y , 0 , 0 , r , g , b , 0 ) ;
push _point ( s , p2x , p2y , 0 , 1 , r , g , b , 0 ) ;
push _point ( s , p3x , p3y , 1 , 0 , r , g , b , 0 ) ;
function push _quad _xyrgb ( s , p1x , p1y , p4x , p4y , r , g , b ) {
push _point _xyrgb ( s , p1x , p1y , r , g , b ) ;
push _point _xyrgb ( s , p4x , p1y , r , g , b ) ;
push _point _xyrgb ( s , p1x , p4y , r , g , b ) ;
push _point ( s , p4x , p4y , 1 , 1 , r , g , b , 0 ) ;
push _point ( s , p3x , p3y , 1 , 0 , r , g , b , 0 ) ;
push _point ( s , p2x , p2y , 0 , 1 , r , g , b , 0 ) ;
push _point _xyrgb ( s , p4x , p4y , r , g , b ) ;
push _point _xyrgb ( s , p1x , p4y , r , g , b ) ;
push _point _xyrgb ( s , p4x , p1y , r , g , b ) ;
}
function push _stroke ( s , stroke ) {
function push _stroke ( context , stroke ) {
const stroke _width = stroke . width ;
const points = stroke . points ;
const color _u32 = stroke . color ;
@ -45,47 +35,29 @@ function push_stroke(s, stroke) {
@@ -45,47 +35,29 @@ function push_stroke(s, stroke) {
return ;
}
if ( points . length === 1 ) {
push _circle ( s , points [ 0 ] . x , points [ 0 ] . y , stroke _width / 2 , r , g , b ) ;
return ;
}
for ( let i = 0 ; i < points . length - 1 ; ++ i ) {
const px = points [ i ] . x ;
const py = points [ i ] . y ;
const nextpx = points [ i + 1 ] . x ;
const nextpy = points [ i + 1 ] . y ;
const d1x = nextpx - px ;
const d1y = nextpy - py ;
const points _from = context . point _serializer . offset / ( 4 * 2 ) ; // 4 is sizeof(f32) btw, just sain'
const points _to = points _from + points . length ;
// Perpendicular to (d1x, d1y), points to the LEFT
let perp1x = - d1y ;
let perp1y = d1x ;
ser _u32 ( context . index _serializer , points _from ) ;
ser _u32 ( context . index _serializer , points _to ) ;
const perpnorm1 = Math . sqrt ( perp1x * perp1x + perp1y * perp1y ) ;
let min _x , min _y , max _x , max _y ;
perp1x /= perpnorm1 ;
perp1y /= perpnorm1 ;
min _x = Math . floor ( points [ 0 ] . x ) ;
max _x = Math . ceil ( points [ 0 ] . x ) ;
const s1x = px + perp1x * stroke _width / 2 ;
const s1y = py + perp1y * stroke _width / 2 ;
const s2x = px - perp1x * stroke _width / 2 ;
const s2y = py - perp1y * stroke _width / 2 ;
min _y = Math . floor ( points [ 0 ] . y ) ;
max _y = Math . ceil ( points [ 0 ] . y ) ;
const s3x = nextpx + perp1x * stroke _width / 2 ;
const s3y = nextpy + perp1y * stroke _width / 2 ;
const s4x = nextpx - perp1x * stroke _width / 2 ;
const s4y = nextpy - perp1y * stroke _width / 2 ;
push _quad ( s , s2x , s2y , s1x , s1y , s4x , s4y , s3x , s3y , r , g , b ) ;
push _circle ( s , px , py , stroke _width / 2 , r , g , b ) ;
for ( const p of points ) {
min _x = Math . min ( min _x , Math . floor ( p . x ) ) ;
min _y = Math . min ( min _y , Math . floor ( p . y ) ) ;
max _x = Math . max ( max _x , Math . ceil ( p . x ) ) ;
max _y = Math . max ( max _y , Math . ceil ( p . y ) ) ;
push _point _xy ( context . point _serializer , p . x , p . y ) ;
}
const lastp = points [ points . length - 1 ] ;
push _circle ( s , lastp . x , lastp . y , stroke _width / 2 , r , g , b ) ;
push _quad _xyrgb ( context . quad _serializer , min _x , min _y , max _x , max _y , r , g , b ) ;
}
function geometry _prepare _stroke ( state ) {
@ -104,48 +76,67 @@ function geometry_prepare_stroke(state) {
@@ -104,48 +76,67 @@ function geometry_prepare_stroke(state) {
function geometry _add _stroke ( state , context , stroke ) {
if ( ! state . online || ! stroke ) return ;
const bytes _left = context . static _stroke _serializer . size - context . static _stroke _serializer . offset ;
const bytes _needed = ( stroke . points . length * 12 + 6 ) * config . bytes _per _point ;
const bytes _left = context . point _serializer . size - context . point _serializer . offset ;
const bytes _needed = stroke . points . length * config . bytes _per _point ;
if ( bytes _left < bytes _needed ) {
const old _view = context . static _stroke _serializer . strview ;
const old _offset = context . static _stroke _serializer . offset ;
const new _size = Math . ceil ( ( context . static _stroke _serializer . size + bytes _needed ) * 1.62 ) ;
const extend _points _by = Math . ceil ( ( context . point _serializer . size + bytes _needed ) * 1.62 ) ;
const extend _indices _by = Math . ceil ( ( context . index _serializer . size + stroke . points . length * 4 * 2 ) * 1.62 ) ;
const extend _quads _by = Math . ceil ( ( context . quad _serializer . size + 6 * ( 4 * 3 ) ) * 1.62 ) ;
context . static _stroke _serializer = serializer _create ( new _size ) ;
context . static _stroke _serializer . strview . set ( old _view ) ;
context . static _stroke _serializer . offset = old _offset ;
context . point _serializer = ser _extend ( context . point _serializer , extend _points _by ) ;
context . index _serializer = ser _extend ( context . index _serializer , extend _indices _by ) ;
context . quad _serializer = ser _extend ( context . quad _serializer , extend _quads _by ) ;
}
push _stroke ( context . static _stroke _serializer , stroke ) ;
push _stroke ( context , stroke ) ;
}
function recompute _dynamic _data ( state , context ) {
let bytes _needed = 0 ;
function geometry _delete _stroke ( state , context , stroke _index ) {
// NEXT: deleted wrong stroke
let offset = 0 ;
for ( let i = 0 ; i < stroke _index ; ++ i ) {
const event = state . events [ i ] ;
for ( const player _id in state . players ) {
const player = state . players [ player _id ] ;
if ( player . points . length > 0 ) {
bytes _needed += ( player . points . length * 12 + 6 ) * config . bytes _per _point ;
if ( event . type === EVENT . STROKE ) {
offset += ( event . points . length * 12 + 6 ) * config . bytes _per _point ;
}
}
if ( bytes _needed > context . dynamic _stroke _serializer . size ) {
context . dynamic _stroke _serializer = serializer _create ( Math . ceil ( bytes _needed * 1.62 ) ) ;
} else {
context . dynamic _stroke _serializer . offset = 0 ;
}
const stroke = state . events [ stroke _index ] ;
for ( const player _id in state . players ) {
// player has the same data as their current stroke: points, color, width
const player = state . players [ player _id ] ;
if ( player . points . length > 0 ) {
push _stroke ( context . dynamic _stroke _serializer , player ) ;
}
for ( let i = 0 ; i < stroke . points . length * 12 + 6 ; ++ i ) {
context . static _stroke _serializer . view . setUint8 ( offset + config . bytes _per _point - 1 , 125 ) ;
offset += config . bytes _per _point ;
}
}
function recompute _dynamic _data ( state , context ) {
// let bytes_needed = 0;
// for (const player_id in state.players) {
// const player = state.players[player_id];
// if (player.points.length > 0) {
// bytes_needed += player.points.length * config.bytes_per_point;
// }
// }
// if (bytes_needed > context.dynamic_stroke_serializer.size) {
// context.dynamic_stroke_serializer = serializer_create(Math.ceil(bytes_needed * 1.62));
// } else {
// context.dynamic_stroke_serializer.offset = 0;
// }
// for (const player_id in state.players) {
// // player has the same data as their current stroke: points, color, width
// const player = state.players[player_id];
// if (player.points.length > 0) {
// push_stroke(context.dynamic_stroke_serializer, player);
// }
// }
}
function geometry _add _point ( state , context , player _id , point ) {
if ( ! state . online ) return ;
state . players [ player _id ] . points . push ( point ) ;
@ -162,15 +153,15 @@ function add_image(context, image_id, bitmap, p) {
@@ -162,15 +153,15 @@ function add_image(context, image_id, bitmap, p) {
const x = p . x ;
const y = p . y ;
const gl = context . gl ;
const id = Object . keys ( context . textures ) . length ;
const id = Object . keys ( context . textures [ 'image' ] ) . length ;
context . textures [ id ] = {
context . textures [ 'image' ] [ id ] = {
'texture' : gl . createTexture ( ) ,
'image_id' : image _id
} ;
gl . bindTexture ( gl . TEXTURE _2D , context . textures [ id ] . texture ) ;
gl . texImage2D ( gl . TEXTURE _2D , 0 , gl . RGBA , gl . RGBA , gl . UNSIGNED _BYTE , bitmap ) ;
gl . texImage2D ( gl . TEXTURE _2D , 0 , gl . RGBA , gl . RGBA , gl . UNSIGNED _BYTE , bitmap ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _MIN _FILTER , gl . LINEAR ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _S , gl . CLAMP _TO _EDGE ) ;
gl . texParameteri ( gl . TEXTURE _2D , gl . TEXTURE _WRAP _T , gl . CLAMP _TO _EDGE ) ;
@ -202,10 +193,10 @@ function move_image(context, image_event) {
@@ -202,10 +193,10 @@ function move_image(context, image_event) {
const x = image _event . x ;
const y = image _event . y ;
const count = Object . keys ( context . textures ) . length ;
const count = Object . keys ( context . textures [ 'image' ] ) . length ;
for ( let id = 0 ; id < count ; ++ id ) {
const image = context . textures [ id ] ;
const image = context . textures [ 'image' ] [ id ] ;
if ( image . image _id === image _event . image _id ) {
context . quad _positions [ id * 12 + 0 ] = x ;
context . quad _positions [ id * 12 + 1 ] = y ;