Last active
January 4, 2023 15:18
-
-
Save sketchpunk/dcf015a91f559dfdb6419031ed4a938a to your computer and use it in GitHub Desktop.
Round the edges of a multi part line or 2d polygon in a flat array of vec3
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
/* | |
const pnts = [ | |
-2,0,-2, | |
-2,0,2, | |
2,0,2, | |
4,0,1, | |
]; | |
const poly = roundedline( pnts ); | |
const buf = new Vec3Buffer( poly ); | |
for( let p of buf.iterLine( true ) ){ | |
Debug.pnt.add( p.a, 0x00ffff, 4 ); | |
if( p.isLast ) Debug.pnt.add( p.b, 0x00ffff, 4 ); | |
Debug.ln.add( p.a, p.b, 0x00ffff ); | |
} | |
*/ | |
function roundedline( pnts, radius=0.5, cells=6, isClosedLoop=true ){ | |
const cnt = pnts.length / 3; | |
const iEnd = ( !isClosedLoop )? cnt - 2 : cnt - 1; | |
const iStar = ( !isClosedLoop )? 0 : -1; | |
const n = [0,0,0]; // normal | |
const a = [0,0,0]; // 2 Lines connected by a center point | |
const b = [0,0,0]; | |
const c = [0,0,0]; | |
const ab = [0,0,0]; // Unit Vector | |
const bc = [0,0,0]; // Unit Vector | |
const miter = [0,0,0]; // Miter Direction | |
const cent = [0,0,0]; // Corner Center | |
const ea = [0,0,0]; // Edge Point A | |
const eb = [0,0,0]; // Edge Point B | |
const out = []; | |
let len, i, j; | |
// First Point | |
if( !isClosedLoop ) out.push( pnts[0], pnts[1], pnts[2] ); | |
for( i=iStar; i < iEnd; i++ ){ | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
// Get the 3 points | |
vec3_fromBuf( a, pnts, mod( i+0, cnt ) ); | |
vec3_fromBuf( b, pnts, mod( i+1, cnt ) ); | |
vec3_fromBuf( c, pnts, mod( i+2, cnt ) ); | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
vec3_sub( ab, b, a ); // Direction from A > B | |
vec3_norm( ab, ab ); | |
vec3_sub( bc, c, b ); // Direction from B > C | |
vec3_norm( bc, bc ); | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
// Find the miter direction | |
vec3_add( miter, ab, bc ); // Compute the Tangent between the two vectors | |
vec3_norm( miter, miter ); | |
vec3_rot_yn( miter, miter ); // Rotate it to make it the inner miter direction | |
// Get anchors that we can use to start the arc | |
vec3_negate( n, ab ); // Flip normal to it points from b > a | |
vec3_scaleAndAdd( ea, b, n, radius ); // First Anchor | |
vec3_scaleAndAdd( eb, b, bc, radius ); // Second Anchor | |
// find the intersection point from anchor+edge normal & miter | |
vec3_rot_yn( n, ab ); // Get the normal of the first edge | |
xzRay_Intersect( ea, n, b, miter, cent ); | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
// CREATE ARC | |
out.push( ...ea ); // Add First anchor as start of arc | |
len = vec3_dist( ea, cent ); // Whats the radius from the center to the arc, this is how long each arc pint needs to be | |
for( j=1; j < cells; j++ ){ | |
vec3_lerp( n, ea, eb, j / cells ); // Lerp between the two anchors | |
vec3_sub( n, n, cent ); // localize from center | |
vec3_norm( n, n ); // make a unit vector out of it | |
vec3_scaleAndAdd( n, cent, n, len ); // Scale it by radius & move it away from center | |
out.push( ...n ); | |
} | |
out.push( ...eb ); // Add Second anchor as end of arc | |
} | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
// Add the last point on the list | |
if( !isClosedLoop ){ | |
i = pnts.length-1; | |
out.push( pnts[i-2], pnts[i-1], pnts[i-0] ); | |
} | |
return out; | |
} |
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
function mod( a, b ){ | |
const v = a % b; | |
return ( v < 0 )? b + v : v; | |
} | |
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_lerp( out, a, b, t ){ | |
const ti = 1 - t; | |
out[ 0 ] = a[ 0 ] * ti + b[ 0 ] * t; | |
out[ 1 ] = a[ 1 ] * ti + b[ 1 ] * t; | |
out[ 2 ] = a[ 2 ] * ti + b[ 2 ] * t; | |
return out; | |
} | |
function vec3_dist( a, b ){ | |
return Math.sqrt( | |
( a[0] - b[0] )**2 + | |
( a[1] - b[1] )**2 + | |
( a[2] - b[2] )**2 | |
); | |
} | |
function vec3_rot_yp( out, a ){ | |
const x = a[ 0 ]; | |
out[ 0 ] = -a[ 2 ]; | |
out[ 1 ] = a[ 1 ]; | |
out[ 2 ] = x; | |
return out; | |
} | |
function vec3_rot_yn( out, a ){ | |
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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment