Skip to content

Instantly share code, notes, and snippets.

@sketchpunk
Last active January 4, 2023 15:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sketchpunk/5d4a11d6721daed5a9cd2924aa327d06 to your computer and use it in GitHub Desktop.
Save sketchpunk/5d4a11d6721daed5a9cd2924aa327d06 to your computer and use it in GitHub Desktop.
Polyline from flat array of Vector 3
/*
NOTES
https://blog.scottlogic.com/2019/11/18/drawing-lines-with-webgl.html
EXAMPLE
const pnts = [
-2,0,-2,
-2,0,2,
2,0,2,
4,0,0,
];
const buf = new Vec3Buffer( pnts );
for( let p of buf.iterLine( true ) ){
Debug.pnt.add( p.a, 0x00ff00, 5 );
Debug.ln.add( p.a, p.b, 0x00ff00 );
}
const poly = polyLine( pnts );
buf.useBuffer( poly.outer );
for( let p of buf.iterLine( true ) ){
Debug.pnt.add( p.a, 0xffffff, 4 );
Debug.ln.add( p.a, p.b, 0xffffff );
}
buf.useBuffer( poly.inner );
for( let p of buf.iterLine( true ) ){
Debug.pnt.add( p.a, 0xffffff, 4 );
Debug.ln.add( p.a, p.b, 0xffffff );
}
*/
function polyLine( pnts, radius=0.3, isClosedLoop=false ){
const cnt = pnts.length / 3;
const iEnd = ( isClosedLoop )? cnt : cnt - 1;
const prev = [0,0,0];
const cur = [0,0,0];
const n = [0,0,0];
const dAry = [];
let i;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Find Direction of each segment
vec3_fromBuf( prev, pnts, 0 ); // Get first Point
for( i=1; i <= iEnd; i++ ){
// ---------------------------------------
// Get Point
vec3_fromBuf( cur, pnts, i % cnt );
// ---------------------------------------
// Compute Line Direction
vec3_sub( n, cur, prev );
vec3_norm( n, n );
dAry.push( n.slice() );
// ---------------------------------------
vec3_copy( prev, cur );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create Outer & Inner Points
// if closed loop, use the last point as the previous point
if( isClosedLoop ) vec3_copy( prev, dAry[ dAry.length-1 ] );
else vec3_set( prev, 0, 0, 0 );
const v = [0,0,0];
const p = [0,0,0];
const miter = [0,0,0];
let scl;
const outer = [];
const inner = [];
for( i=0; i < iEnd; i++ ){
vec3_copy( cur, dAry[ i ] );
vec3_fromBuf( p, pnts, i );
// ---------------------------------------
// Find Tangent by combinding the line directions
// This is like a mid vector between the two vectors
vec3_add( miter, cur, prev );
vec3_norm( miter, miter );
// ---------------------------------------
// Get miter direction by doing a 90 deg rotation of tangent
vec3_perp_y( miter, miter );
// Rotate the curreng segment's direction by 90
// degrees to get its normal direction
vec3_perp_y( n, cur );
// ---------------------------------------
// Distance for the mighter is size over dot of miter and normal
scl = radius / vec3_dot( miter, n );
vec3_scaleAndAdd( v, p, miter, scl ); // Outer Point
outer.push( ...v );
vec3_negate( miter, miter ); // Flip Direction
vec3_scaleAndAdd( v, p, miter, scl ); // Inner Point
inner.push( ...v );
// ---------------------------------------
vec3_copy( prev, cur );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Handle last point when not closed loop
if( !isClosedLoop ){
// Last Point
vec3_fromBuf( p, pnts, iEnd );
// Get normal of last segment
vec3_copy( n, dAry[ dAry.length-1 ] );
vec3_perp_y( n, n );
vec3_scaleAndAdd( v, p, n, scl ); // Outer Point
outer.push( ...v );
vec3_negate( n, n ); // Flip Direction
vec3_scaleAndAdd( v, p, n, scl ); // Inner Point
inner.push( ...v );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return { outer, inner };
}
// #region MATHS
function vec3_fromBuf( out, buf, i ){
i *= 3;
out[ 0 ] = buf[ i+0 ];
out[ 1 ] = buf[ i+1 ];
out[ 2 ] = buf[ i+2 ];
return out;
}
function vec3_copy( out, a ){
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
return out;
}
function vec3_negate( out, a ){
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
return out;
}
function vec3_set( out, x, y, z ){
out[0] = x;
out[1] = y;
out[2] = z;
return out;
}
function vec3_add( out, a, b ){
out[ 0 ] = a[ 0 ] + b[ 0 ];
out[ 1 ] = a[ 1 ] + b[ 1 ];
out[ 2 ] = a[ 2 ] + b[ 2 ];
return out;
}
function vec3_sub( out, a, b ){
out[ 0 ] = a[ 0 ] - b[ 0 ];
out[ 1 ] = a[ 1 ] - b[ 1 ];
out[ 2 ] = a[ 2 ] - b[ 2 ];
return out;
}
function vec3_norm( out, a ){
let mag = Math.sqrt( a[ 0 ]**2 + a[ 1 ]**2 + a[ 2 ]**2 );
if( mag != 0 ){
mag = 1 / mag;
out[ 0 ] = a[ 0 ] * mag;
out[ 1 ] = a[ 1 ] * mag;
out[ 2 ] = a[ 2 ] * mag;
}
return out;
}
function vec3_dot( a, b ){ return a[ 0 ] * b[ 0 ] + a[ 1 ] * b[ 1 ] + a[ 2 ] * b[ 2 ]; }
function vec3_perp_y( out, a ){
// perpendicular
const x = a[ 0 ];
out[ 0 ] = -a[ 2 ];
out[ 1 ] = a[ 1 ];
out[ 2 ] = x;
return out;
}
function vec3_scaleAndAdd( out, add, v, s ){
out[ 0 ] = v[ 0 ] * s + add[ 0 ];
out[ 1 ] = v[ 1 ] * s + add[ 1 ];
out[ 2 ] = v[ 2 ] * s + add[ 2 ];
return out;
}
// #endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment