Last active
January 4, 2023 15:18
-
-
Save sketchpunk/5d4a11d6721daed5a9cd2924aa327d06 to your computer and use it in GitHub Desktop.
Polyline from flat array of Vector 3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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 }; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// #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