As seen here: paulbourke.net/geometry/supershape
Export to GIF as different frames to rotate in 3D.
Log in to post a comment.
// LL 2021 // Supershapes / Superformula: http://paulbourke.net/geometry/supershape/ // Variations: // https://turtletoy.net/turtle/6976a7ffc8#p_m=10,p_n1=100,p_n2=100,p_n3=99.98,p_a=0.76,p_b=0.74,t_m=10,t_n1=100,t_n2=100,t_n3=100,t_a=0.3,t_b=0.42,density=446,scale=165.97,loops=2,opacity=0.47,mapping=0,noisy=0 // https://turtletoy.net/turtle/6976a7ffc8#p_m=1,p_n1=1,p_n2=1,p_n3=1,p_a=1.03,p_b=1.62,t_m=1,t_n1=7.85,t_n2=7.85,t_n3=8.34,t_a=1.67,t_b=1.67,density=1593,scale=31.46,loops=20,opacity=0.08,mapping=0,noisy=0 // https://turtletoy.net/turtle/6976a7ffc8#p_m=6,p_n1=-0.68,p_n2=22.77,p_n3=0.75,p_a=2.99,p_b=0.64,t_m=3,t_n1=65.9,t_n2=0.35,t_n3=49.59,t_a=1.05,t_b=0.28,density=818,scale=40,loops=1,opacity=-0.1,mapping=1,noisy=0 // https://turtletoy.net/turtle/6976a7ffc8#p_m=2,p_n1=9.29,p_n2=9.29,p_n3=9.66,p_a=1,p_b=1,t_m=4.8,t_n1=10.16,t_n2=10.16,t_n3=10.16,t_a=1.91,t_b=0.55,density=1081,scale=40,loops=2,opacity=0.1,mapping=0,noisy=0 // https://turtletoy.net/turtle/6976a7ffc8#p_m=10,p_n1=63.9,p_n2=63.41,p_n3=63.41,p_a=1,p_b=1,t_m=10,t_n1=19.99,t_n2=19.86,t_n3=19.86,t_a=1.91,t_b=0.55,density=1049,scale=29.24,loops=1,opacity=0.1,mapping=1,noisy=0 const turtle = new Turtle(); const p_m = 0; // min=0 max=10 step=0.1 const p_n1 = 1; // min=-1 max=100 step=0.01 const p_n2 = 1; // min=-1 max=100 step=0.01 const p_n3 = 1; // min=-1 max=100 step=0.01 const p_a = 1; // min=0.01 max=10 step=0.01 const p_b = 1; // min=0.01 max=10 step=0.01 const t_m = 0; // min=0 max=10 step=0.1 const t_n1 = 1; // min=-1 max=100 step=0.01 const t_n2 = 1; // min=-1 max=100 step=0.01 const t_n3 = 1; // min=-1 max=100 step=0.01 const t_a = 1; // min=0.01 max=10 step=0.01 const t_b = 1; // min=0.01 max=10 step=0.01 const density = 500; // min=1 max=2000 step=1 const scale = 40; // min=0 max=200 step=0.01 const loops = 1; // min=1 max=20 step=0.1 const opacity = 0.1; // min=-1 max=1 step=0.01 const mapping = 1; // min=0 max=1 step=1 (Spherical,Toroidal) const noisy = 0; // min=0 max=1 step=1 (No,Yes) const camera_angle = 0.14; /// min=0 max=1 step=0.01 const camera_height = 150; /// min=0 max=500 step=1 const camera_distance = 400; const exaggeration = 1; /// min=0 max=2 step=0.01 const shuffle_i = 0; /// min=0 max=1 step=1 (No,Yes) let shuffled_i; Canvas.setpenopacity(opacity); function walk(i, t) { if (i==0) { reset_random(); init_shuffle(); cameraPos = [camera_distance * Math.cos(Math.PI * 2 * (camera_angle + t)), camera_height, camera_distance * Math.sin(Math.PI * 2 * (camera_angle + t))]; viewProjectionMatrix = setupCamera(cameraPos, cameraLookAt); } const ii = shuffled_i.shift(); const ip = (ii % density) + (noisy ? random() : 0); const it = Math.floor(ii / density) + (noisy ? random() : 0); const phi = -Math.PI/2 + Math.PI * ip / density * loops * (mapping + 1); const theta = -Math.PI + Math.PI * 2 * it / density * loops; const p_r = getR(p_m, p_n1, p_n2, p_n3, p_a, p_b, phi); const t_r = getR(t_m, t_n1, t_n2, t_n3, t_a, t_b, theta); var x, y, z; if (mapping == 0) { // Spherical x = p_r * Math.cos(phi) * t_r * Math.cos(theta); y = p_r * Math.sin(phi) * t_r * Math.cos(theta); z = t_r * Math.sin(theta); } else { // Toroidal x = Math.cos(phi) * (p_r + t_r * Math.cos(theta)); y = Math.sin(phi) * (p_r + t_r * Math.cos(theta)); z = t_r * Math.sin(theta); } dot(x, y, z); return (i+1) < density * density; } function dot(x, y, z) { const max_r = 0.1, min_r = 0.1, step = 1; [x, y] = project(x * scale, y * scale, z * scale); if (Math.abs(x-max_r) <= 100 && Math.abs(y-max_r) <= 100) { for (var r = max_r; r >= min_r; r -= step) { turtle.jump(x, y-r); turtle.circle(r); } } } function getR(m, n1, n2, n3, a, b, angle) { const t1 = Math.pow(Math.abs(Math.cos(m * angle / 4) / a), n2); const t2 = Math.pow(Math.abs(Math.sin(m * angle / 4) / b), n3); var r = Math.pow(t1 + t2, 1/n1); if (Math.abs(r) != 0) { r = 1 / r; } return r; } function project(x, y, z) { const p = transform4([x, z * -exaggeration, y, 1], viewProjectionMatrix); const s = 50; return [ p[0]/p[3]*s, -p[1]/p[3]*s ]; } function init_shuffle() { shuffled_i = Array.from({length: density * density}, (_,id) => id); if (!shuffle_i) return; var current_index = shuffled_i.length, random_index; while (current_index > 0) { random_index = Math.floor(mrandom() * current_index--); [ shuffled_i[current_index], shuffled_i[random_index] ] = [ shuffled_i[random_index], shuffled_i[current_index] ]; } } //////////////////////////////////////////////////////////////// // Projection from reinder's https://turtletoy.net/turtle/b3acf08303 let cameraPos, viewProjectionMatrix; const cameraLookAt = [0,0,0]; function setupCamera(t,e){const m=lookAt4m(t,e,[0,1,0]),n=perspective4m(.25,1);return multiply4m(n,m)} function lookAt4m(o,n,r){const s=new Float32Array(16);n=normalize3(sub3(o,n)),r=normalize3(cross3(r,n));const t=normalize3(cross3(n,r));return s[0]=r[0],s[1]=t[0],s[2]=n[0],s[3]=0,s[4]=r[1],s[5]=t[1],s[6]=n[1],s[7]=0,s[8]=r[2],s[9]=t[2],s[10]=n[2],s[11]=0,s[12]=-(r[0]*o[0]+r[1]*o[1]+r[2]*o[2]),s[13]=-(t[0]*o[0]+t[1]*o[1]+t[2]*o[2]),s[14]=-(n[0]*o[0]+n[1]*o[1]+n[2]*o[2]),s[15]=1,s} function perspective4m(t,n){const e=new Float32Array(16).fill(0,0);return e[5]=1/Math.tan(t/2),e[0]=e[5]/n,e[10]=e[11]=-1,e} function multiply4m(t,r){const l=new Float32Array(16);for(let n=0;16>n;n+=4)for(let o=0;4>o;o++)l[n+o]=r[n+0]*t[0+o]+r[n+1]*t[4+o]+r[n+2]*t[8+o]+r[n+3]*t[12+o];return l} function transform4(r,n){const t=new Float32Array(4);for(let o=0;4>o;o++)t[o]=n[o]*r[0]+n[o+4]*r[1]+n[o+8]*r[2]+n[o+12];return t} function normalize3(a) { return scale3(a,1/len3(a)); } function scale3(a,b) { return [a[0]*b,a[1]*b,a[2]*b]; } function len3(a) { return Math.sqrt(dot3(a,a)); } function sub3(a,b) { return [a[0]-b[0],a[1]-b[1],a[2]-b[2]]; } function dot3(a,b) { return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]; } function cross3(a,b) { return [a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]]; } // Cached random for animations function mrandom() { return Math.random(); } function random() { while (rand_index >= rand_cache.length) rand_cache.push(mrandom()); return rand_cache[rand_index++]; } function reset_random() { rand_index = 0; } const rand_cache = []; var rand_index = 0;