@ -1,42 +1,25 @@
@@ -1,42 +1,25 @@
function push _stroke ( s , stroke , stroke _index ) {
const points = stroke . points ;
if ( points . length < 2 ) {
return ;
}
for ( let i = 0 ; i < points . length - 1 ; ++ i ) {
const from = points [ i ] ;
const to = points [ i + 1 ] ;
ser _f32 ( s , from . x ) ;
ser _f32 ( s , from . y ) ;
ser _f32 ( s , to . x ) ;
ser _f32 ( s , to . y ) ;
ser _u32 ( s , stroke _index ) ;
}
}
function geometry _prepare _stroke ( state ) {
if ( ! state . online ) {
return null ;
}
if ( state . players [ state . me ] . points . length === 0 ) {
const player = state . players [ state . me ] ;
const stroke = player . strokes [ player . strokes . length - 1 ] ; // MY OWN player.strokes should never be bigger than 1 element
if ( stroke . points . length === 0 ) {
return null ;
}
const points = process _stroke2 ( state . canvas . zoom , state . players [ state . me ] . points ) ;
const points = process _stroke2 ( state . canvas . zoom , stroke . points ) ;
return {
'color' : state . players [ state . me ] . color ,
'width' : state . players [ state . me ] . width ,
'color' : stroke . color ,
'width' : stroke . width ,
'points' : points ,
'user_id' : state . me ,
} ;
}
async function geometry _write _instances ( state , context , callback ) {
state . stats . rdp _max _count = 0 ;
state . stats . rdp _segments = 0 ;
@ -56,6 +39,7 @@ function geometry_add_dummy_stroke(context) {
@@ -56,6 +39,7 @@ function geometry_add_dummy_stroke(context) {
ser _u16 ( context . stroke _data , 0 ) ;
}
// Real stroke, add forever
function geometry _add _stroke ( state , context , stroke , stroke _index , skip _bvh = false ) {
if ( ! state . online || ! stroke || stroke . coords _to - stroke . coords _from === 0 || stroke . deleted ) return ;
@ -83,9 +67,11 @@ function recompute_dynamic_data(state, context) {
@@ -83,9 +67,11 @@ function recompute_dynamic_data(state, context) {
for ( const player _id in state . players ) {
const player = state . players [ player _id ] ;
if ( player . points . length > 0 ) {
total _points += player . points . length ;
total _strokes += 1 ;
for ( const stroke of player . strokes ) {
if ( ! stroke . empty && stroke . points . length > 0 ) {
total _points += stroke . points . length ;
total _strokes += 1 ;
}
}
}
@ -106,44 +92,69 @@ function recompute_dynamic_data(state, context) {
@@ -106,44 +92,69 @@ function recompute_dynamic_data(state, context) {
// player has the same data as their current stroke: points, color, width
const player = state . players [ player _id ] ;
for ( let i = 0 ; i < player . points . length ; ++ i ) {
const p = player . points [ i ] ;
tv _add ( context . dynamic _instance _points , p . x ) ;
tv _add ( context . dynamic _instance _points , p . y ) ;
tv _add ( context . dynamic _instance _pressure , p . pressure ) ;
if ( i !== player . points . length - 1 ) {
tv _add ( context . dynamic _instance _ids , stroke _index ) ;
} else {
tv _add ( context . dynamic _instance _ids , stroke _index | ( 1 << 31 ) ) ;
for ( const stroke of player . strokes ) {
if ( ! stroke . empty && stroke . points . length > 0 ) {
for ( let i = 0 ; i < stroke . points . length ; ++ i ) {
const p = stroke . points [ i ] ;
tv _add ( context . dynamic _instance _points , p . x ) ;
tv _add ( context . dynamic _instance _points , p . y ) ;
tv _add ( context . dynamic _instance _pressure , p . pressure ) ;
if ( i !== stroke . points . length - 1 ) {
tv _add ( context . dynamic _instance _ids , stroke _index ) ;
} else {
tv _add ( context . dynamic _instance _ids , stroke _index | ( 1 << 31 ) ) ;
}
}
const color _u32 = stroke . color ;
const r = ( color _u32 >> 16 ) & 0xFF ;
const g = ( color _u32 >> 8 ) & 0xFF ;
const b = color _u32 & 0xFF ;
ser _u16 ( context . dynamic _stroke _data , r ) ;
ser _u16 ( context . dynamic _stroke _data , g ) ;
ser _u16 ( context . dynamic _stroke _data , b ) ;
ser _u16 ( context . dynamic _stroke _data , stroke . width ) ;
stroke _index += 1 ; // TODO: proper player Z order
}
}
if ( player . points . length > 0 ) {
const color _u32 = player . color ;
const r = ( color _u32 >> 16 ) & 0xFF ;
const g = ( color _u32 >> 8 ) & 0xFF ;
const b = color _u32 & 0xFF ;
ser _u16 ( context . dynamic _stroke _data , r ) ;
ser _u16 ( context . dynamic _stroke _data , g ) ;
ser _u16 ( context . dynamic _stroke _data , b ) ;
ser _u16 ( context . dynamic _stroke _data , player . width ) ;
stroke _index += 1 ; // TODO: proper player Z order
}
}
context . dynamic _segment _count = total _points ;
context . dynamic _stroke _count = total _strokes ;
}
function geometry _add _point ( state , context , player _id , point , is _pen , raw = false ) {
function geometry _start _prestroke ( state , player _id ) {
if ( ! state . online ) return ;
const player = state . players [ player _id ] ;
player . strokes . push ( {
'empty' : false ,
'points' : [ ] ,
'head' : null ,
'color' : player . color ,
'width' : player . width ,
} ) ;
player . current _prestroke = true ;
}
function geometry _end _prestroke ( state , player _id ) {
if ( ! state . online ) return ;
const player = state . players [ player _id ] ;
player . current _prestroke = false ;
}
function geometry _add _prepoint ( state , context , player _id , point , is _pen , raw = false ) {
if ( ! state . online ) return ;
const player = state . players [ player _id ] ;
const points = player . points ;
const stroke = player . strokes [ player . strokes . length - 1 ] ;
const points = stroke . points ;
if ( point . pressure < config . min _pressure ) {
point . pressure = config . min _pressure ;
@ -152,30 +163,35 @@ function geometry_add_point(state, context, player_id, point, is_pen, raw = fals
@@ -152,30 +163,35 @@ function geometry_add_point(state, context, player_id, point, is_pen, raw = fals
if ( points . length > 0 && ! raw ) {
// pulled from "perfect-freehand" package. MIT
// https://github.com/steveruizok/perfect-freehand/
const streamline = 0.5 ;
const streamline = 0.7 5 ;
const t = 0.15 + ( 1 - streamline ) * 0.85
const smooth _pressure = exponential _smoothing ( points , point , 3 ) ;
points . push ( {
'x' : player . dynamic _ head. x * t + point . x * ( 1 - t ) ,
'y' : player . dynamic _ head. y * t + point . y * ( 1 - t ) ,
'pressure' : is _pen ? player . dynamic _ head. pressure * t + smooth _pressure * ( 1 - t ) : point . pressure ,
'x' : stroke . head . x * t + point . x * ( 1 - t ) ,
'y' : stroke . head . y * t + point . y * ( 1 - t ) ,
'pressure' : is _pen ? stroke . head . pressure * t + smooth _pressure * ( 1 - t ) : point . pressure ,
} ) ;
if ( is _pen ) {
point . pressure = smooth _pressure ;
}
} else {
state . players [ player _id ] . points . push ( point ) ;
points . push ( point ) ;
}
stroke . head = point ;
recompute _dynamic _data ( state , context ) ;
player . dynamic _head = point ;
}
function geometry _clear _player ( state , context , player _id ) {
// Remove prestroke from dynamic data (usually because it's now a real stroke)
function geometry _clear _oldest _prestroke ( state , context , player _id ) {
if ( ! state . online ) return ;
state . players [ player _id ] . points . length = 0 ;
const player = state . players [ player _id ] ;
player . strokes . shift ( ) ;
recompute _dynamic _data ( state , context ) ;
}