<!-- ★ Click anywhere to create new 3D art ★ -->

<div id="scene-container">
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   id="svg-doodle"
   version="1.1"
   viewBox="0 0 456.06533 219.00801"
   height="219.00801mm"
   width="456.06534mm">
  <defs>
    <filter
       height="2.7376001"
       y="-0.86879998"
       width="2.7376001"
       x="-0.86879998"
       id="filterAirbrush"
       style="color-interpolation-filters:sRGB">
      <feGaussianBlur
         id="feGaussianBlur5142"
         stdDeviation="28.460096" />
    </filter>
  </defs>
  <g
     transform="translate(454.504,-15.496001)"
     id="layer1">
    <circle
       r="32"
       cy="145"
       cx="-300"
       id="airbrush-2"
       style="opacity:1;fill:#d75bef;fill-opacity:1;stroke:none;filter:url(#filterAirbrush)" />
    <circle
       r="40"
       cy="130"
       cx="-355"
       id="airbrush-1"
       style="opacity:0.85;fill:#8ffff9;fill-opacity:1;filter:url(#filterAirbrush)" />
  </g>
  <circle
     r="32"
     cy="160"
     cx="200"
     id="airbrush-3"
     style="opacity:1.0;fill:#8ffff9;fill-opacity:1;stroke:none;filter:url(#filterAirbrush)"
     transform="matrix(0.58395083,0,0,0.58395083,200.82047,63.462674)" />
  <path
     id="path1993"
     d="m 400.06744,100.66194 c 72.92885,-31.602499 -11.93219,103.27126 -44.7406,81.399 -9.80758,-6.53838 13.42289,-46.32744 18.47355,-41.2768 4.85693,4.85693 -28.85382,23.21405 -34.06058,23.95787 -9.87208,1.41029 10.98899,-23.36022 12.70056,-21.64867 1.93656,1.93657 -20.87221,6.57975 -21.93732,6.63892 -15.17544,0.84308 -22.12464,-5.07354 -32.3287,-14.1438"
     style="fill:none;stroke:#000000;stroke-width:0.35px;stroke-opacity:0.75" />
  <path
     id="path2143"
     d="m 69.804124,120.62909 c -12.150349,23.79809 -6.270389,34.44835 3.673901,37.96366 C 115.8576,173.57393 210.21966,119.996 252.27455,99.810323 c 40.33216,-19.358794 -29.75854,45.849307 33.0651,23.676257 8.81687,-3.11183 16.9326,-6.52635 24.90089,-11.42992"
     style="fill:none;stroke:#000000;stroke-width:0.35px;stroke-opacity:0.75" />
  <path
     id="path2165"
     d="m 246.5596,29.189776 c -32.05941,5.699941 -72.91125,19.315369 -115.11558,48.168929 -4.56841,3.123254 -27.79632,22.404173 -21.22698,30.615845 6.58259,8.22823 43.65266,-14.273574 45.95878,-15.483019 17.69104,-9.27807 12.56985,-11.733918 12.38642,-11.747574 -21.01766,-1.56474 -104.852544,85.042733 -35.51438,58.374203"
     style="fill:none;stroke:#000000;stroke-width:0.35px;stroke-opacity:0.75" />
</svg>

</div>
<a id="credits" title="See more 3D madness" href="https://codepen.io/ScavengerFrontend" target="_blank">Code & design <br/> by Anna <br/>the Scavenger ↗</a>

<!-- MATCAP VERTEX SHADER --> 
<script type="x-shader/x-vertex" id="vs-matcap">

  varying vec2 vN;

	void main() {

		vec3 e = normalize( vec3( modelViewMatrix * vec4( position, 1.0 ) ) );
		vec3 n = normalize( normalMatrix * normal );

		vec3 r = reflect( e, n );
		float m = 2. * sqrt( pow( r.x, 2. ) + pow( r.y, 2. ) + pow( r.z + 1., 2. ) );
		vN = r.xy / m + .5;

		gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1. );

	}

</script>

<!-- MATCAP FRAGMENT SHADER --> 
<script type="x-shader/x-fragment" id="fs-matcap">

  uniform sampler2D tMatCap;

	varying vec2 vN;

	void main() {
		
		vec3 base = texture2D( tMatCap, vN ).rgb;
		gl_FragColor = vec4( base, 1.0 );

	}
	
</script>

<script>
  
  function getExportedPoints() {
    
    let curvePoints = [[-8.070780754089355, 2.9191834926605225, 4.158595561981201] ,
[-9.49313735961914, 2.7790331840515137, 3.255053997039795] ,
[-10.603548049926758, 2.3837854862213135, 2.483524799346924] ,
[-11.422452926635742, 1.7956944704055786, 1.8428080081939697] ,
[-11.970760345458984, 1.0710524320602417, 1.3302218914031982] ,
[-12.269862174987793, 0.26018792390823364, 0.9415957927703857] ,
[-12.34162425994873, -0.5925332307815552, 0.6712753176689148] ,
[-12.208386421203613, -1.4487091302871704, 0.5121195316314697] ,
[-11.892966270446777, -2.2759008407592773, 0.45550215244293213] ,
[-11.418651580810547, -3.0476317405700684, 0.49131134152412415] ,
[-10.809218406677246, -3.743389844894409, 0.6079492568969727] ,
[-10.088897705078125, -4.348624229431152, 0.7923325896263123] ,
[-9.282422065734863, -4.854750633239746, 1.0298926830291748] ,
[-8.414978981018066, -5.259143829345703, 1.304574728012085] ,
[-7.511950969696045, -5.5646514892578125, 1.5991381406784058] ,
[-6.597087383270264, -5.776509761810303, 1.8970268964767456] ,
[-5.691351413726807, -5.900374889373779, 2.1835649013519287] ,
[-4.812859058380127, -5.942228317260742, 2.4460158348083496] ,
[-3.9768805503845215, -5.9083757400512695, 2.6735804080963135] ,
[-3.19584321975708, -5.805451393127441, 2.857398748397827] ,
[-2.4793272018432617, -5.640408992767334, 2.9905478954315186] ,
[-1.8340680599212646, -5.420531272888184, 3.0680437088012695] ,
[-1.2639561891555786, -5.153426170349121, 3.086841583251953] ,
[-0.7700360417366028, -4.847024917602539, 3.045832872390747] ,
[-0.3505084216594696, -4.509585857391357, 2.9458491802215576] ,
[-0.0007269755005836487, -4.1496901512146, 2.789658784866333] ,
[0.28679361939430237, -3.7762460708618164, 2.58196759223938] ,
[0.5217897891998291, -3.3982667922973633, 2.3290679454803467] ,
[0.7140316367149353, -3.0240674018859863, 2.0375349521636963] ,
[0.8724225759506226, -2.660937786102295, 1.7136975526809692] ,
[1.0049803256988525, -2.315131425857544, 1.363624930381775] ,
[1.118836760520935, -1.9918698072433472, 0.9931286573410034] ,
[1.220237374305725, -1.695339322090149, 0.6077611446380615] ,
[1.314542531967163, -1.4286935329437256, 0.2128167450428009] ,
[1.4062268733978271, -1.1940512657165527, -0.18666867911815643] ,
[1.498878836631775, -0.9924982190132141, -0.585918128490448] ,
[1.5952012538909912, -0.824085533618927, -0.9804126024246216] ,
[1.69701087474823, -0.6878307461738586, -1.3658922910690308] ,
[1.8052394390106201, -0.5817174911499023, -1.7383556365966797] ,
[1.9199377298355103, -0.5027035474777222, -2.0940608978271484] ,
[2.0405075550079346, -0.4470594525337219, -2.429584503173828] ,
[2.1662421226501465, -0.4111606478691101, -2.741960048675537] ,
[2.296466112136841, -0.39168739318847656, -3.028712034225464] ,
[2.430529832839966, -0.3856259286403656, -3.287855863571167] ,
[2.5678162574768066, -0.39026859402656555, -3.517897367477417] ,
[2.707735061645508, -0.40321364998817444, -3.717833995819092] ,
[2.849729299545288, -0.42236563563346863, -3.8871560096740723] ,
[2.9932668209075928, -0.44593483209609985, -4.02584171295166] ,
[3.1378488540649414, -0.4724380075931549, -4.134364128112793] ,
[3.2830042839050293, -0.5006974339485168, -4.213683605194092] ,
[3.4282915592193604, -0.5298417806625366, -4.265255451202393] ,
[3.5732996463775635, -0.5593059062957764, -4.291024208068848] ,
[3.7176458835601807, -0.5888246893882751, -4.293412208557129] ,
[3.8609745502471924, -0.618326723575592, -4.275086879730225] ,
[4.002954483032227, -0.6477744579315186, -4.238608360290527] ,
[4.143277168273926, -0.677140474319458, -4.186374187469482] ,
[4.281656265258789, -0.7064068913459778, -4.120622158050537] ,
[4.417830467224121, -0.7355661392211914, -4.043430328369141] ,
[4.551558971405029, -0.7646205425262451, -3.9567134380340576] ,
[4.682626247406006, -0.7935821413993835, -3.8622288703918457] ,
[4.8108391761779785, -0.822473406791687, -3.7615725994110107] ,
[4.936026573181152, -0.8513261079788208, -3.6561787128448486] ,
[5.058041095733643, -0.8801823854446411, -3.547321081161499] ,
[5.176760196685791, -0.9090943932533264, -3.4361140727996826] ,
[5.292080879211426, -0.9381237626075745, -3.323509693145752] ,
[5.403923988342285, -0.9673398733139038, -3.2103018760681152] ,
[5.512204647064209, -0.9967900514602661, -3.09712815284729] ,
[5.616809368133545, -1.0264724493026733, -2.9844777584075928] ,
[5.717597961425781, -1.0563338994979858, -2.872690439224243] ,
[5.814397811889648, -1.086269497871399, -2.7619576454162598] ,
[5.907008647918701, -1.1161234378814697, -2.6523208618164062] ,
[5.9951982498168945, -1.1456875801086426, -2.543673038482666] ,
[6.078705787658691, -1.1747028827667236, -2.435757875442505] ,
[6.157243251800537, -1.2028589248657227, -2.328171730041504] ,
[6.2304887771606445, -1.2297930717468262, -2.2203590869903564] ,
[6.298093318939209, -1.2550922632217407, -2.1116182804107666] ,
[6.359676361083984, -1.27829110622406, -2.0010969638824463] ,
[6.414830207824707, -1.298872947692871, -1.8877941370010376] ,
[6.4631218910217285, -1.3162850141525269, -1.7706066370010376] ,
[6.504139423370361, -1.3300285339355469, -1.6486018896102905] ,
[6.537509441375732, -1.3397133350372314, -1.5211827754974365] ,
[6.562904357910156, -1.3450603485107422, -1.3880966901779175] ,
[6.5800371170043945, -1.3459012508392334, -1.2494345903396606] ,
[6.588669300079346, -1.3421801328659058, -1.105631947517395] ,
[6.588602066040039, -1.3339506387710571, -0.957467257976532] ,
[6.5796799659729, -1.321378469467163, -0.806063175201416] ,
[6.561792850494385, -1.304740071296692, -0.6528858542442322] ,
[6.534872531890869, -1.2844233512878418, -0.4997461140155792] ,
[6.498895168304443, -1.2609273195266724, -0.34879764914512634] ,
[6.4538798332214355, -1.2348613739013672, -0.20253852009773254] ,
[6.3998894691467285, -1.2069469690322876, -0.06380955874919891] ,
[6.33704948425293, -1.1779727935791016, 0.06433195620775223] ,
[6.265614986419678, -1.1486461162567139, 0.17906026542186737] ,
[6.186000347137451, -1.119533658027649, 0.2779542803764343] ,
[6.098771572113037, -1.0910605192184448, 0.35900014638900757] ,
[6.004656791687012, -1.0635110139846802, 0.4205924868583679] ,
[5.904536724090576, -1.0370279550552368, 0.4615336060523987] ,
[5.799452781677246, -1.0116122961044312, 0.4810332953929901] ,
[5.6905999183654785, -0.9871242046356201, 0.4787096679210663] ,
[5.57933235168457, -0.9632822275161743, 0.45458829402923584] ,
[5.467160224914551, -0.9396637082099915, 0.4091026782989502] ,
[5.355749130249023, -0.9157042503356934, 0.3430942893028259] ,
[5.246923923492432, -0.8906983733177185, 0.2578120827674866] ,
[5.14266300201416, -0.8638019561767578, 0.15491022169589996] ,
[5.04498815536499, -0.8341264724731445, 0.036330532282590866] ,
[4.955730438232422, -0.8009524941444397, -0.09595704823732376] ,
[4.876468181610107, -0.7637782692909241, -0.24001654982566833] ,
[4.808525562286377, -0.7223217487335205, -0.39394640922546387] ,
[4.752978801727295, -0.6765191555023193, -0.5558793544769287] ,
[4.7106499671936035, -0.6265261173248291, -0.7239821553230286] ,
[4.682108402252197, -0.5727168321609497, -0.8964561223983765] ,
[4.667673110961914, -0.5156846046447754, -1.0715372562408447] ,
[4.667410850524902, -0.4562416672706604, -1.2474950551986694] ,
[4.681136131286621, -0.3954189121723175, -1.4226338863372803] ,
[4.708411693572998, -0.3344663977622986, -1.5952924489974976] ,
[4.74854850769043, -0.27485305070877075, -1.763843297958374] ,
[4.80061149597168, -0.21825623512268066, -1.926697850227356] ,
[4.863521575927734, -0.16637633740901947, -2.082374334335327] ,
[4.936208248138428, -0.1206730380654335, -2.2295982837677] ,
[5.0176215171813965, -0.0823286920785904, -2.3673129081726074] ,
[5.106738567352295, -0.05224808305501938, -2.494682550430298] ,
[5.202563285827637, -0.03105824813246727, -2.6110918521881104] ,
[5.3041229248046875, -0.019108694046735764, -2.716144561767578] ,
[5.410470485687256, -0.016471315175294876, -2.809663772583008] ,
[5.5206828117370605, -0.022940414026379585, -2.891692876815796] ,
[5.633865833282471, -0.03803270310163498, -2.962496280670166] ,
[5.749146461486816, -0.06098726764321327, -3.0225560665130615] ,
[5.86568021774292, -0.09076564013957977, -3.072575330734253] ,
[5.982645034790039, -0.1260516494512558, -3.1134769916534424] ,
[6.099248886108398, -0.1652734875679016, -3.146383047103882] ,
[6.2147536277771, -0.20681464672088623, -3.1724159717559814] ,
[6.3284993171691895, -0.24920521676540375, -3.192518949508667] ,
[6.439906597137451, -0.29113683104515076, -3.207439661026001] ,
[6.5484771728515625, -0.331463098526001, -3.217733144760132] ,
[6.653792381286621, -0.36919933557510376, -3.2237606048583984] ,
[6.7555131912231445, -0.40352246165275574, -3.2256879806518555] ,
[6.8533830642700195, -0.4337712824344635, -3.2234885692596436] ,
[6.947225093841553, -0.4594462513923645, -3.2169406414031982] ,
[7.036943435668945, -0.48020970821380615, -3.2056288719177246] ,
[7.122519493103027, -0.4958854019641876, -3.18894362449646] ,
[7.2040181159973145, -0.5064592957496643, -3.1660823822021484] ,
[7.281586647033691, -0.5120788216590881, -3.136047124862671] ,
[7.355430603027344, -0.5130372047424316, -3.0976948738098145] ,
[7.425726413726807, -0.5096853971481323, -3.050002336502075] ,
[7.492563724517822, -0.502380907535553, -2.9922235012054443] ,
[7.555946350097656, -0.491485595703125, -2.9238922595977783] ,
[7.615785121917725, -0.47736579179763794, -2.8448245525360107] ,
[7.671905040740967, -0.4603922367095947, -2.7551181316375732] ,
[7.7240424156188965, -0.44094040989875793, -2.6551525592803955] ,
[7.771843910217285, -0.4193898141384125, -2.545588493347168] ,
[7.814866542816162, -0.3961244821548462, -2.427367687225342] ,
[7.8525824546813965, -0.3715331554412842, -2.30171537399292] ,
[7.884369850158691, -0.3460088074207306, -2.1701366901397705] ,
[7.909523963928223, -0.3199489712715149, -2.0344185829162598] ,
[7.927248477935791, -0.2937552332878113, -1.8966294527053833] ,
[7.93671178817749, -0.26781290769577026, -1.7589991092681885] ,
[7.937219619750977, -0.24242110550403595, -1.6235227584838867] ,
[7.928282737731934, -0.2177671641111374, -1.4918162822723389] ,
[7.9096150398254395, -0.19392645359039307, -1.3651118278503418] ,
[7.8811354637146, -0.17086203396320343, -1.2442591190338135] ,
[7.842962741851807, -0.14842496812343597, -1.1297253370285034] ,
[7.795423984527588, -0.12635408341884613, -1.021594524383545] ,
[7.739050388336182, -0.1042761355638504, -0.9195683598518372] ,
[7.674572944641113, -0.08170570433139801, -0.8229654431343079] ,
[7.602931022644043, -0.05804527923464775, -0.7307217121124268] ,
[7.525265693664551, -0.03258518874645233, -0.6413903832435608] ,
[7.442922592163086, -0.004503630101680756, -0.5531418919563293] ,
[7.35744571685791, 0.027130749076604843, -0.46377119421958923] ,
[7.270442008972168, 0.06326747685670853, -0.3709528148174286] ,
[7.183278560638428, 0.1046815738081932, -0.2727797031402588] ,
[7.097021579742432, 0.1519298404455185, -0.16788485646247864] ,
[7.012430667877197, 0.2053506076335907, -0.055442146956920624] ,
[6.929964542388916, 0.2650640606880188, 0.06483399122953415] ,
[6.849776268005371, 0.33097171783447266, 0.19268831610679626] ,
[6.771716594696045, 0.40275701880455017, 0.3273249566555023] ,
[6.695329189300537, 0.4798848032951355, 0.46740737557411194] ,
[6.619857311248779, 0.5616015195846558, 0.6110581755638123] ,
[6.544239044189453, 0.6469355821609497, 0.7558594346046448] ,
[6.467108726501465, 0.7346965074539185, 0.8988522887229919] ,
[6.386797904968262, 0.8234759569168091, 1.036537528038025] ,
[6.301348686218262, 0.91165691614151, 1.1649004220962524] ,
[6.208811283111572, 0.9975836277008057, 1.2798333168029785] ,
[6.107629299163818, 1.0797888040542603, 1.377705693244934] ,
[5.996697425842285, 1.1570254564285278, 1.4554412364959717] ,
[5.875353813171387, 1.2282640933990479, 1.5105141401290894] ,
[5.743390083312988, 1.2926958799362183, 1.5409537553787231] ,
[5.601042747497559, 1.349731206893921, 1.54534113407135] ,
[5.448997974395752, 1.398998737335205, 1.522810935974121] ,
[5.288388729095459, 1.4403470754623413, 1.4730499982833862] ,
[5.120798587799072, 1.473844289779663, 1.396299123764038] ,
[4.948257923126221, 1.49977707862854, 1.293351411819458] ,
[4.773245334625244, 1.5186519622802734, 1.1655528545379639] ,
[4.598687648773193, 1.5311943292617798, 1.0148029327392578] ,
[4.427916049957275, 1.5383307933807373, 0.8435196876525879] ,
[4.26426362991333, 1.5410231351852417, 0.6543317437171936] ,
[4.110719680786133, 1.5401253700256348, 0.44981300830841064] ,
[3.9699018001556396, 1.5363740921020508, 0.23246265947818756] ,
[3.8440585136413574, 1.5303865671157837, 0.004705176688730717] ,
[3.7350687980651855, 1.5226633548736572, -0.231109619140625] ,
[3.644441604614258, 1.513586401939392, -0.47270679473876953] ,
[3.5733137130737305, 1.5034185647964478, -0.7178858518600464] ,
[3.5224547386169434, 1.492305874824524, -0.9645213484764099] ,
[3.4922609329223633, 1.4802751541137695, -1.2105623483657837] ,
[3.482762098312378, 1.4672363996505737, -1.4540326595306396] ,
[3.49361515045166, 1.4529799222946167, -1.6930303573608398] ,
[3.5241079330444336, 1.4371792078018188, -1.9257290363311768] ,
[3.5731942653656006, 1.4194077253341675, -2.1503870487213135] ,
[3.6396737098693848, 1.3992410898208618, -2.365382194519043] ,
[3.7222957611083984, 1.3763115406036377, -2.5692436695098877] ,
[3.819760322570801, 1.3503094911575317, -2.760647773742676] ,
[3.930720806121826, 1.3209840059280396, -2.9384214878082275] ,
[4.053782939910889, 1.2881437540054321, -3.1015400886535645] ,
[4.187503814697266, 1.251655101776123, -3.249127149581909] ,
[4.330393314361572, 1.2114437818527222, -3.380455255508423] ,
[4.480912685394287, 1.167493462562561, -3.494946241378784] ,
[4.637475967407227, 1.119847297668457, -3.5921695232391357] ,
[4.798449516296387, 1.0686068534851074, -3.6718459129333496] ,
[4.962152481079102, 1.0139323472976685, -3.733842372894287] ,
[5.12685489654541, 0.9560427665710449, -3.7781755924224854] ,
[5.290838241577148, 0.8952159881591797, -3.8050029277801514] ,
[5.452580451965332, 0.8317902684211731, -3.814591646194458] ,
[5.610816955566406, 0.766164243221283, -3.807312488555908] ,
[5.764542102813721, 0.6987972259521484, -3.783637285232544] ,
[5.913013935089111, 0.6302090287208557, -3.744138240814209] ,
[6.055745601654053, 0.560979962348938, -3.689490795135498] ,
[6.192514896392822, 0.4917510449886322, -3.620471954345703] ,
[6.3233561515808105, 0.4232238233089447, -3.537959098815918] ,
[6.448564529418945, 0.3561602234840393, -3.44293212890625] ,
[6.568696975708008, 0.29138290882110596, -3.336472749710083] ,
[6.684568405151367, 0.22977496683597565, -3.2197632789611816] ,
[6.797255516052246, 0.17228029668331146, -3.0940895080566406] ,
[6.908087253570557, 0.11990094929933548, -2.9608347415924072] ,
[7.018500328063965, 0.07363240420818329, -2.8214223384857178] ,
[7.129726409912109, 0.034331824630498886, -2.677192211151123] ,
[7.242734909057617, 0.00269044516608119, -2.529372215270996] ,
[7.358227729797363, -0.020766926929354668, -2.3790829181671143] ,
[7.476641654968262, -0.03568157181143761, -2.2273335456848145] ,
[7.598145008087158, -0.04186096042394638, -2.0750226974487305] ,
[7.722645282745361, -0.039279017597436905, -1.9229403734207153] ,
[7.8497772216796875, -0.028075627982616425, -1.771765112876892] ,
[7.978915691375732, -0.008556997403502464, -1.622066617012024] ,
[8.109166145324707, 0.018804335966706276, -1.474303960800171] ,
[8.23936939239502, 0.05336977168917656, -1.3288263082504272] ,
[8.368101119995117, 0.09433433413505554, -1.1858727931976318] ,
[8.49367904663086, 0.1407347172498703, -1.0455751419067383] ,
[8.614339828491211, 0.19156982004642487, -0.9079978466033936] ,
[8.728452682495117, 0.2459554374217987, -0.773190438747406] ,
[8.834545135498047, 0.30314335227012634, -0.6411934494972229] ,
[8.931309700012207, 0.36252179741859436, -0.5120385885238647] ,
[9.017596244812012, 0.4236149191856384, -0.38574841618537903] ,
[9.092419624328613, 0.4860832095146179, -0.2623371183872223] ,
[9.154951095581055, 0.5497233867645264, -0.14180970191955566] ,
[9.204524993896484, 0.6144682168960571, -0.02416236139833927] ,
[9.240638732910156, 0.6803867220878601, 0.0906173586845398] ,
[9.262948036193848, 0.747684121131897, 0.20255103707313538] ,
[9.271269798278809, 0.8167018294334412, 0.31166893243789673] ,
[9.265582084655762, 0.887917160987854, 0.4180102050304413] ,
[9.246015548706055, 0.9619182348251343, 0.5216161608695984] ,
[9.212799072265625, 1.0391823053359985, 0.6224730610847473] ,
[9.1662015914917, 1.1198960542678833, 0.7204653024673462] ,
[9.106532096862793, 1.2039421796798706, 0.8153724074363708] ,
[9.034144401550293, 1.290900707244873, 0.9068688750267029] ,
[8.949431419372559, 1.38004732131958, 0.9945237636566162] ,
[8.852826118469238, 1.4703551530838013, 1.0778017044067383] ,
[8.744804382324219, 1.5604928731918335, 1.1560617685317993] ,
[8.625877380371094, 1.648826241493225, 1.22855806350708] ,
[8.496606826782227, 1.7334176301956177, 1.2944401502609253] ,
[8.357588768005371, 1.812026023864746, 1.3527519702911377] ,
[8.209458351135254, 1.8821061849594116, 1.4024322032928467] ,
[8.052897453308105, 1.9408105611801147, 1.4423155784606934] ,
[7.888639450073242, 1.985093355178833, 1.4711720943450928] ,
[7.717550277709961, 2.0122320652008057, 1.4879111051559448] ,
[7.5406575202941895, 2.020099639892578, 1.4916868209838867] ,
[7.3591628074646, 2.0071754455566406, 1.4819021224975586] ,
[7.174432754516602, 1.9725427627563477, 1.4582091569900513] ,
[6.988004684448242, 1.9158912897109985, 1.420508623123169] ,
[6.801581382751465, 1.8375147581100464, 1.3689498901367188] ,
[6.617035388946533, 1.73831307888031, 1.3039305210113525] ,
[6.436409950256348, 1.6197912693023682, 1.2260982990264893] ,
[6.261913299560547, 1.48405921459198, 1.1363484859466553] ,
[6.095924377441406, 1.3338325023651123, 1.035825490951538] ,
[5.940988540649414, 1.172431230545044, 0.9259225130081177] ,
[5.799820899963379, 1.0037788152694702, 0.8082805275917053] ,
[5.675164222717285, 0.8321670889854431, 0.6847031712532043] ,
[5.569394588470459, 0.6615538597106934, 0.5569003820419312] ,
[5.484376907348633, 0.4953310191631317, 0.42640379071235657] ,
[5.421470642089844, 0.33632129430770874, 0.29456597566604614] ,
[5.38152551651001, 0.186777263879776, 0.16255979239940643] ,
[5.364884853363037, 0.04838331788778305, 0.03137899935245514] ,
[5.371382236480713, -0.07774630188941956, -0.09816211462020874] ,
[5.400344371795654, -0.19106639921665192, -0.22542878985404968] ,
[5.450590133666992, -0.2916008234024048, -0.34996530413627625] ,
[5.5204267501831055, -0.37994304299354553, -0.4714954197406769] ,
[5.607660293579102, -0.45725584030151367, -0.5899224877357483] ,
[5.709580898284912, -0.5252709984779358, -0.7053288817405701] ,
[5.822987079620361, -0.5862795114517212, -0.817973792552948] ,
[5.944482326507568, -0.642830491065979, -0.928215503692627] ,
[6.071062088012695, -0.6971572041511536, -1.036361575126648] ,
[6.200228691101074, -0.751062273979187, -1.1426401138305664] ,
[6.32999324798584, -0.8059167861938477, -1.2471994161605835] ,
[6.458876609802246, -0.8626607656478882, -1.3501079082489014] ,
[6.585905075073242, -0.9218025803565979, -1.451353669166565] ,
[6.710616588592529, -0.98341965675354, -1.5508449077606201] ,
[6.8330535888671875, -1.0471577644348145, -1.6484102010726929] ,
[6.953770160675049, -1.1122313737869263, -1.7437976598739624] ,
[7.073827266693115, -1.1774239540100098, -1.8366758823394775] ,
[7.194794178009033, -1.2410873174667358, -1.926633596420288] ,
[7.3187479972839355, -1.3011423349380493, -2.013179302215576] ,
[7.448248386383057, -1.3551021814346313, -2.0957441329956055] ,
[7.585938453674316, -1.4004185199737549, -2.173725128173828] ,
[7.734071731567383, -1.4349040985107422, -2.2465381622314453] ,
[7.89444637298584, -1.4567795991897583, -2.313619375228882] ,
[8.068412780761719, -1.4646753072738647, -2.3744306564331055] ,
[8.25687313079834, -1.4576314687728882, -2.428457260131836] ,
[8.460274696350098, -1.4350968599319458, -2.4752066135406494] ,
[8.678616523742676, -1.3969297409057617, -2.5142111778259277] ,
[8.91144847869873, -1.3433979749679565, -2.545024871826172] ,
[9.157866477966309, -1.275178074836731, -2.5672271251678467] ,
[9.416522026062012, -1.1933561563491821, -2.580418825149536] ,
[9.685609817504883, -1.0994282960891724, -2.584226608276367] ,
[9.962879180908203, -0.9952983856201172, -2.5782978534698486] ,
[10.2456636428833, -0.8832412362098694, -2.5623135566711426] ,
[10.531184196472168, -0.7655846476554871, -2.5360496044158936] ,
[10.816783905029297, -0.6444634199142456, -2.4994280338287354] ,
[11.099943161010742, -0.5218054056167603, -2.4525210857391357] ,
[11.378273010253906, -0.3993285596370697, -2.395548105239868] ,
[11.64952564239502, -0.278543621301651, -2.328880786895752] ,
[11.911585807800293, -0.1607525497674942, -2.253037452697754] ,
[12.16247844696045, -0.047049205750226974, -2.168687343597412] ,
[12.400355339050293, 0.06168125197291374, -2.0766475200653076] ,
[12.623515129089355, 0.1647614985704422, -1.9778858423233032] ,
[12.830382347106934, 0.2617228627204895, -1.8735188245773315] ,
[13.019525527954102, 0.3523047864437103, -1.7648117542266846] ,
[13.189645767211914, 0.4364551603794098, -1.6531802415847778] ,
[13.339598655700684, 0.514306902885437, -1.5401455163955688] ,
[13.468512535095215, 0.5860714316368103, -1.4271432161331177] ,
[13.575824737548828, 0.6519846320152283, -1.315422773361206] ,
[13.661297798156738, 0.7123062610626221, -1.2060471773147583] ,
[13.725005149841309, 0.767318844795227, -1.0998913049697876] ,
[13.767345428466797, 0.8173284530639648, -0.9976428747177124] ,
[13.789036750793457, 0.8626644015312195, -0.899802029132843] ,
[13.79111099243164, 0.9036792516708374, -0.8066810965538025] ,
[13.774918556213379, 0.9407488107681274, -0.7184050679206848] ,
[13.742131233215332, 0.9742721915245056, -0.6349117159843445] ,
[13.694741249084473, 1.0046720504760742, -0.5559507608413696] ,
[13.635055541992188, 1.0323939323425293, -0.4810848534107208] ,
[13.565696716308594, 1.0579066276550293, -0.409689724445343] ,
[13.489471435546875, 1.0816882848739624, -0.34101253747940063] ,
[13.408965110778809, 1.104187250137329, -0.274337500333786] ,
[13.326427459716797, 1.1258093118667603, -0.2090378999710083] ,
[13.243766784667969, 1.1469184160232544, -0.1445763111114502] ,
[13.16254711151123, 1.1678355932235718, -0.08050509542226791] ,
[13.084000587463379, 1.1888400316238403, -0.0164661705493927] ,
[13.009010314941406, 1.210168480873108, 0.0478091761469841] ,
[12.93812370300293, 1.2320151329040527, 0.11249999701976776] ,
[12.87154483795166, 1.2545318603515625, 0.1776958405971527] ,
[12.8091402053833, 1.277828574180603, 0.2433966100215912] ,
[12.750431060791016, 1.3019723892211914, 0.30951282382011414] ,
[12.69460391998291, 1.3269882202148438, 0.37586528062820435] ,
[12.640504837036133, 1.3528581857681274, 0.4421863257884979] ,
[12.586779594421387, 1.3795034885406494, 0.5081432461738586] ,
[12.532108306884766, 1.4067535400390625, 0.5733822584152222] ,
[12.475244522094727, 1.4343386888504028, 0.6375357508659363] ,
[12.415027618408203, 1.4618918895721436, 0.7002228498458862] ,
[12.350373268127441, 1.4889469146728516, 0.7610498070716858] ,
[12.280279159545898, 1.5149391889572144, 0.8196091651916504] ,
[12.20382022857666, 1.539206624031067, 0.8754801750183105] ,
[12.120153427124023, 1.560988187789917, 0.9282288551330566] ,
[12.028510093688965, 1.5794240236282349, 0.9774078726768494] ,
[11.928203582763672, 1.5935566425323486, 1.0225564241409302] ,
[11.818634033203125, 1.6023308038711548, 1.0632009506225586] ,
[11.699268341064453, 1.6045911312103271, 1.0988539457321167] ,
[11.56966495513916, 1.5990970134735107, 1.129017949104309] ,
[11.429539680480957, 1.5846755504608154, 1.1532292366027832] ,
[11.278837203979492, 1.5604021549224854, 1.1711080074310303] ,
[11.117749214172363, 1.525620460510254, 1.1823641061782837] ,
[10.946710586547852, 1.47994065284729, 1.18679678440094] ,
[10.766400337219238, 1.4232420921325684, 1.1842951774597168] ,
[10.577740669250488, 1.3556709289550781, 1.1748371124267578] ,
[10.3818998336792, 1.2776418924331665, 1.1584910154342651] ,
[10.180288314819336, 1.1898365020751953, 1.1354143619537354] ,
[9.97455883026123, 1.0932049751281738, 1.1058539152145386] ,
[9.766610145568848, 0.988964855670929, 1.0701465606689453] ,
[9.558588027954102, 0.878601610660553, 1.0287185907363892] ,
[9.352874755859375, 0.7638683319091797, 0.9820854663848877] ,
[9.152067184448242, 0.6467544436454773, 0.9308443665504456] ,
[8.958686828613281, 0.5292488932609558, 0.8756112456321716] ,
[8.77500057220459, 0.413166344165802, 0.8169762492179871] ,
[8.602984428405762, 0.30013561248779297, 0.7554997205734253] ,
[8.44433879852295, 0.19160009920597076, 0.6917128562927246] ,
[8.300481796264648, 0.0888182520866394, 0.6261178255081177] ,
[8.172553062438965, -0.007136969361454248, 0.559187650680542] ,
[8.061413764953613, -0.09537798166275024, 0.491365522146225] ,
[7.9676408767700195, -0.17520247399806976, 0.42306604981422424] ,
[7.891534328460693, -0.2460935413837433, 0.35467419028282166] ,
[7.833113670349121, -0.3077195882797241, 0.28654593229293823] ,
[7.792115211486816, -0.3599343001842499, 0.21900762617588043] ,
[7.768001556396484, -0.40277668833732605, 0.15235695242881775] ,
[7.759986400604248, -0.43645694851875305, 0.08686710149049759] ,
[7.767190456390381, -0.4612937569618225, 0.022810472175478935] ,
[7.788722515106201, -0.4776851236820221, -0.03953104093670845] ,
[7.823671817779541, -0.48610761761665344, -0.09986534714698792] ,
[7.871113300323486, -0.4871159791946411, -0.15789049863815308] ,
[7.930105209350586, -0.4813435673713684, -0.21329441666603088] ,
[7.999692916870117, -0.4695020616054535, -0.2657550871372223] ,
[8.078902244567871, -0.45238152146339417, -0.3149404227733612] ,
[8.166747093200684, -0.4308505058288574, -0.3605082929134369] ,
[8.262222290039062, -0.40585601329803467, -0.4021066725254059] ,
[8.364310264587402, -0.378423273563385, -0.4393734037876129] ,
[8.47197437286377, -0.3496560752391815, -0.47193634510040283] ,
[8.5841646194458, -0.3207363188266754, -0.4994135797023773] ,
[8.699832916259766, -0.29286280274391174, -0.5214608907699585] ,
[8.81797981262207, -0.26709312200546265, -0.5378929376602173] ,
[8.937670707702637, -0.24429573118686676, -0.5487209558486938] ,
[9.058028221130371, -0.22514952719211578, -0.5541526079177856] ,
[9.178239822387695, -0.21014359593391418, -0.5545924305915833] ,
[9.297557830810547, -0.1995774358510971, -0.550641655921936] ,
[9.415291786193848, -0.1935608685016632, -0.5430982708930969] ,
[9.530818939208984, -0.19201412796974182, -0.5329567790031433] ,
[9.643573760986328, -0.1946677267551422, -0.5214086174964905] ,
[9.75306224822998, -0.20106251537799835, -0.5098418593406677] ,
[9.85883903503418, -0.2105497270822525, -0.4998410940170288] ,
[9.96053409576416, -0.22229090332984924, -0.49318796396255493] ,
[10.057831764221191, -0.2352636307477951, -0.4918521046638489] ,
[10.15048599243164, -0.24839946627616882, -0.49778684973716736] ,
[10.238316535949707, -0.2608214318752289, -0.5125767588615417] ,
[10.321211814880371, -0.27188658714294434, -0.5373743772506714] ,
[10.399131774902344, -0.2811857759952545, -0.572900652885437] ,
[10.472101211547852, -0.28854402899742126, -0.6194442510604858] ,
[10.540220260620117, -0.294020414352417, -0.6768620610237122] ,
[10.603652954101562, -0.29790791869163513, -0.7445790767669678] ,
[10.662632942199707, -0.3007334768772125, -0.8215881586074829] ,
[10.717467308044434, -0.3032582700252533, -0.9064505696296692] ,
[10.768525123596191, -0.30647724866867065, -0.9972953200340271] ,
[10.816250801086426, -0.31161943078041077, -1.0918197631835938] ,
[10.861152648925781, -0.3201479911804199, -1.1872888803482056] ,
[10.90380859375, -0.33373722434043884, -1.2805651426315308] ,
[10.944772720336914, -0.35398945212364197, -1.3684728145599365] ,
[10.984501838684082, -0.3821224868297577, -1.448197364807129] ,
[11.023341178894043, -0.418938010931015, -1.517329216003418] ,
[11.061521530151367, -0.46482089161872864, -1.573861002922058] ,
[11.099167823791504, -0.5197398662567139, -1.6161903142929077] ,
[11.136289596557617, -0.5832474231719971, -1.6431171894073486] ,
[11.172784805297852, -0.6544790863990784, -1.653845191001892] ,
[11.208443641662598, -0.7321544289588928, -1.6479827165603638] ,
[11.242940902709961, -0.8145765662193298, -1.6255402565002441] ,
[11.275842666625977, -0.8996317386627197, -1.586932897567749] ,
[11.306604385375977, -0.9847904443740845, -1.532978892326355] ,
[11.334567070007324, -1.0671061277389526, -1.4648997783660889] ,
[11.358980178833008, -1.143288254737854, -1.3842897415161133] ,
[11.379094123840332, -1.2102030515670776, -1.2928913831710815] ,
[11.394241333007812, -1.2652297019958496, -1.1924391984939575] ,
[11.403837203979492, -1.3062787055969238, -1.0846515893936157] ,
[11.407376289367676, -1.3317919969558716, -0.9712297320365906] ,
[11.404443740844727, -1.3407442569732666, -0.8538592457771301] ,
[11.394698143005371, -1.3326404094696045, -0.7342076301574707] ,
[11.377888679504395, -1.3075175285339355, -0.6139267086982727] ,
[11.353843688964844, -1.2659449577331543, -0.4946514368057251] ,
[11.322474479675293, -1.2090229988098145, -0.3780001997947693] ,
[11.283774375915527, -1.138384222984314, -0.26557454466819763] ,
[11.237823486328125, -1.0561922788619995, -0.1589595377445221] ,
[11.184782981872559, -0.965142011642456, -0.059723470360040665] ,
[11.124884605407715, -0.8683207631111145, 0.03059358522295952] ,
[11.058390617370605, -0.7686299681663513, 0.11052732169628143] ,
[10.985577583312988, -0.6685255765914917, 0.1787114292383194] ,
[10.90673542022705, -0.5700122117996216, 0.233877494931221] ,
[10.822154998779297, -0.4746415913105011, 0.27485525608062744] ,
[10.732151985168457, -0.38351428508758545, 0.3005726933479309] ,
[10.637039184570312, -0.29727858304977417, 0.3100557029247284] ,
[10.537151336669922, -0.21613064408302307, 0.30242830514907837] ,
[10.432831764221191, -0.13981498777866364, 0.2769131362438202] ,
[10.324431419372559, -0.06762391328811646, 0.2328301966190338] ,
[10.21231460571289, 0.0016021281480789185, 0.16959823668003082] ,
[10.096858024597168, 0.06947467476129532, 0.0867338627576828] ,
[9.97844409942627, 0.13805285096168518, -0.016146037727594376] ,
[9.857522964477539, 0.20961126685142517, -0.1392039805650711] ,
[9.734698295593262, 0.2860410213470459, -0.28207314014434814] ,
[9.61077880859375, 0.36868131160736084, -0.4437701106071472] ,
[9.486772537231445, 0.4583180844783783, -0.6226937770843506] ,
[9.363886833190918, 0.5551840662956238, -0.8166261315345764] ,
[9.243523597717285, 0.6589586734771729, -1.0227316617965698] ,
[9.127286911010742, 0.7687678933143616, -1.2375575304031372] ,
[9.016979217529297, 0.8831847310066223, -1.4570337533950806] ,
[8.91460132598877, 1.000228762626648, -1.676472783088684] ,
[8.82235336303711, 1.1173665523529053, -1.8905701637268066] ,
[8.742633819580078, 1.2315105199813843, -2.0934033393859863] ,
[8.678037643432617, 1.33902108669281, -2.2784335613250732] ,
[8.631352424621582, 1.435725212097168, -2.4385342597961426] ,
[8.605278015136719, 1.5173938274383545, -2.5666959285736084] ,
[8.601993560791016, 1.5805187225341797, -2.6571714878082275] ,
[8.62307357788086, 1.6224457025527954, -2.705674171447754] ,
[8.669502258300781, 1.6413745880126953, -2.709376811981201] ,
[8.741658210754395, 1.6363577842712402, -2.6669108867645264] ,
[8.839323997497559, 1.6073023080825806, -2.578366279602051] ,
[8.961682319641113, 1.5549697875976562, -2.445295572280884] ,
[9.10731315612793, 1.4809725284576416, -2.270705461502075] ,
[9.274208068847656, 1.387779951095581, -2.0590670108795166] ,
[9.459750175476074, 1.2787129878997803, -1.8163074254989624] ,
[9.660724639892578, 1.157947063446045, -1.5498143434524536] ,
[9.873320579528809, 1.0305111408233643, -1.2684346437454224] ,
[10.093170166015625, 0.9022254347801208, -0.9823716282844543] ,
[10.315862655639648, 0.7789648175239563, -0.7019800543785095] ,
[10.537477493286133, 0.6658888459205627, -0.43650251626968384] ,
[10.75464153289795, 0.567365825176239, -0.1939464956521988] ,
[10.964518547058105, 0.48697248101234436, 0.01891602948307991] ,
[11.164826393127441, 0.4274955093860626, 0.1965470314025879] ,
[11.3538179397583, 0.3909299969673157, 0.33464446663856506] ,
[11.530295372009277, 0.378480464220047, 0.43014052510261536] ,
[11.693603515625, 0.39055997133255005, 0.48120296001434326] ,
[11.84363079071045, 0.4267910420894623, 0.4872339367866516] ,
[11.980809211730957, 0.4860052764415741, 0.44887104630470276] ,
[12.10611629486084, 0.5662429332733154, 0.36798644065856934] ,
[12.221071243286133, 0.6647536754608154, 0.24768756330013275] ,
[12.327674865722656, 0.7780779004096985, 0.09221009910106659] ,
[12.427974700927734, 0.9025907516479492, -0.09378726035356522] ,
[12.523777961730957, 1.0348656177520752, -0.30569615960121155] ,
[12.616632461547852, 1.1716943979263306, -0.5389841198921204] ,
[12.707836151123047, 1.3100863695144653, -0.7891931533813477] ,
[12.798423767089844, 1.4472684860229492, -1.051940679550171] ,
[12.889178276062012, 1.5806857347488403, -1.322919249534607] ,
[12.98062515258789, 1.7080012559890747, -1.5978965759277344] ,
[13.073031425476074, 1.8270949125289917, -1.8727149963378906] ,
[13.166415214538574, 1.9360655546188354, -2.143293619155884] ,
[13.260529518127441, 2.033228635787964, -2.4056241512298584] ,
[13.354878425598145, 2.1171188354492188, -2.655775785446167] ,
[13.448702812194824, 2.1864867210388184, -2.8898913860321045] ,
[13.541048049926758, 2.2403247356414795, -3.10425066947937] ,
[13.630972862243652, 2.2779488563537598, -3.295506477355957] ,
[13.717629432678223, 2.2990365028381348, -3.460783004760742] ,
[13.800293922424316, 2.3036293983459473, -3.597684144973755] ,
[13.878334999084473, 2.2921290397644043, -3.70428729057312] ,
[13.951231002807617, 2.26530122756958, -3.779148578643799] ,
[14.018568992614746, 2.224273681640625, -3.8212990760803223] ,
[14.080041885375977, 2.170536756515503, -3.830246686935425] ,
[14.13544750213623, 2.105942964553833, -3.8059768676757812] ,
[14.184687614440918, 2.032707452774048, -3.748948574066162] ,
[14.227776527404785, 1.953407883644104, -3.6601004600524902] ,
[14.264833450317383, 1.8709841966629028, -3.5408456325531006] ,
[14.2960786819458, 1.7887345552444458, -3.3930726051330566] ,
[14.321853637695312, 1.710121750831604, -3.219067096710205] ,
[14.342630386352539, 1.6382951736450195, -3.0213212966918945] ,
[14.359012603759766, 1.575964093208313, -2.8024816513061523] ,
[14.371753692626953, 1.5253969430923462, -2.5653512477874756] ,
[14.381733894348145, 1.488419771194458, -2.3128879070281982] ,
[14.389979362487793, 1.4664191007614136, -2.048203468322754] ,
[14.397648811340332, 1.460339069366455, -1.7745659351348877] ,
[14.406042098999023, 1.4706830978393555, -1.4953988790512085] ,
[14.416595458984375, 1.4975134134292603, -1.214279294013977] ,
[14.43088436126709, 1.5404510498046875, -0.9349406957626343] ,
[14.450623512268066, 1.5986759662628174, -0.661271333694458] ,
[14.477657318115234, 1.6709263324737549, -0.39731407165527344] ,
[14.513973236083984, 1.7555056810379028, -0.14724618196487427] ,
[14.56156063079834, 1.8504093885421753, 0.08506555110216141] ,
[14.622227668762207, 1.95352041721344, 0.2967592775821686] ,
[14.697554588317871, 2.062642812728882, 0.48608848452568054] ,
[14.788919448852539, 2.1755006313323975, 0.6524221897125244] ,
[14.897478103637695, 2.289738893508911, 0.7962458729743958] ,
[15.024166107177734, 2.4029223918914795, 0.9191597700119019] ,
[15.169709205627441, 2.5125362873077393, 1.0238803625106812] ,
[15.334606170654297, 2.6159863471984863, 1.1142394542694092] ,
[15.51915168762207, 2.7105987071990967, 1.1951851844787598] ,
[15.723417282104492, 2.7936201095581055, 1.2727806568145752] ,
[15.947254180908203, 2.8622169494628906, 1.3542051315307617] ,
[16.190305709838867, 2.9134767055511475, 1.4477530717849731]];
  
  return {
    
    curvePoints
    
  }
    
}
  
</script>
:root {
  --purple: #e8cbf9;
  --grey: #2b2b2b;
  --seagreen: #61a69f;
  --beige: #c6a49b;
  --lightgrey: #c8c3c2;
  --lightbeige: #e0c6bf;
}

body {
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: var(--lightbeige);
  transition: background 250ms ease-in;
  font-size: 16px;
  font-family: Arial;
}

#scene-container {
  position: absolute;
}

#credits {
  position: absolute;
  bottom: 0;
  right: 0;
  text-transform: none;
  text-decoration: none;
  color: black;
  padding: 0.35rem 0.5rem;
  margin: 0.75rem 0.75rem;
  font-size: 0.75rem;
  border: 1.5px solid black;
  transition: background 200ms ease-in;
  border-radius: 0.2rem;
  opacity: 0;
}

#credits:hover {
  background: rgba(255, 235, 195, 0.8);
  background: #fff1bc;
  background: rgba(255, 251, 215, 0.8);
}


a[title]:hover::after {
  background: purple;
}

#svg-doodle {
  position: absolute;
  width: 100vw;
  max-width: 100vw;
  height: 100%;
  max-height: 100vh;
  display: block;
  margin: auto;
  z-index: -1;
  opacity: 0;
  opacity: 1;
}

@keyframes fadeIn {
  
  0% { opacity: 0.0; }
  85% { opacity: 0.0; }
  100% { opacity: 1; }

}

@media(max-width: 800px) {
  
  #credits {
    padding: 0.25rem 0.4rem;
    margin: 0.5rem 0.5rem;
    border: 1px solid black;
    bottom: auto;
    right: 0;
  }
  
}
/*

  ★ Click anywhere to generate new 3D art ★
  
  What is creativity? 
  This is a tribute to my wandering mind.
  
  Typography designed by me in Blender, rest generated in three.js.
  
  Anna the Scavenger, March 2021
  https://twitter.com/ouchpixels
  
  License: You can remix, adapt, and build upon my code non-commercially.
   
*/

import {
  
  WebGLRenderer, Scene, PerspectiveCamera, 
  Group, GammaEncoding, Mesh,
  MeshStandardMaterial, ShaderMaterial,
  DoubleSide, TextureLoader, DirectionalLight, HemisphereLight,
  SphereBufferGeometry, TorusBufferGeometry, PlaneBufferGeometry, TubeGeometry, ParametricGeometry, CatmullRomCurve3, BufferGeometry, CylinderGeometry,
  Vector2, Vector3, Color
 
} from "https://unpkg.com/three@0.127.0/build/three.module.js";

import { GLTFLoader } from "https://unpkg.com/three@0.127.0/examples/jsm/loaders/GLTFLoader.js";

// ASSETS

let textureOldGoldURL = "https://assets.codepen.io/911157/matcapCop.jpg";
let modelURL = "https://assets.codepen.io/911157/creativityDoodle_by_Anna_the_Scavenger.glb";

// LANDSCAPE / PORTRAIT

let isMobile = /(Android|iPhone|iOS|iPod|iPad)/i.test(navigator.userAgent);
let windowRatio = window.innerWidth / window.innerHeight;
let isLandscape = (windowRatio > 1) ? true : false;

// MOUSE 

let mouse = new Vector2(0, 0); // -1 to 1 - interactivity
let mouseX = 0; // 0 to 1 - animation timeline 
let mouseY = 0; // 0 to 1 - animation timeline 

let lettersParams = {

  scale: 3.75,
  position: new Vector3(0, -10, 0),
  dotOffset: new Vector3(13, 24, 0),
  dotScale: 1,
  dot2Offset: new Vector3(41.5, 26.5, 0),
  dot2Scale: 1,

}

let doodleParams = {

  curve: new CatmullRomCurve3(),
  scale: 3.5,
  position: new Vector3(-36, -39, -10),
  tubeThickness: 0.25,
  tubeTubularSegments: 500,
  ballScale: 1

}

Sketch();

function Sketch() {
  
  let scene, camera, renderer;
  
  let container = document.body.querySelector("#scene-container");
  let airbrush1 = document.body.querySelector("#airbrush-1");
  let airbrush2 = document.body.querySelector("#airbrush-2");
  let airbrush3 = document.body.querySelector("#airbrush-3");
  
  // MATERIALS + COLOR PALETTE
  
  let materials = initMaterials();
  let currentPalette = getPalette();
  
  // MESHES
  
  let letters, dot, dot2;
  let ball;
  let sprinklesEndGroup = new Group();
  
  // ANIMATION TIMELINES
  
  let lettersTL;
  let sprinklesTL;
  
  creditsAnimation();
  updateSVGPalette();
  init();
  render();
  
  function init() {
    
    scene = new Scene();
    
    initRenderer();
    initCamera();
    initLights();
    
    loadModel();
    
    initSprinkles();
    initSprinklesTimeline();
    
    container.addEventListener("click", onButtonClick);
    document.addEventListener("mousemove", onMouseMove);
    document.addEventListener("touchmove", onTouchMove, false);
    window.addEventListener("resize", onWindowResize);
    
  }
  
  function creditsAnimation() {
    
    const credits = document.querySelector("#credits");
    credits.style.animation = "fadeIn 6s ease-in forwards";
    
  }
  
  function initCamera() {
    
    camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.set(0, 10, 150);
    camera.lookAt(0, 0, 0);
    camera.position.z = (windowRatio > 2) ? ((200 / windowRatio) + 80) : (250 / windowRatio);
    scene.add(camera);
        
  }
  
  function initLights() {
    
    const hemLight = new HemisphereLight(0xddeeff, 0x202020, 3);
    hemLight.position.set(0, 50, -150);
    scene.add(hemLight);
    
    const hemLight2 = new HemisphereLight(0xddeeff, 0x202020, 2);
    hemLight2.position.set(0, 50, 250);
    scene.add(hemLight2);

    const dirLight = new DirectionalLight(0xffffff, 1.25);
    dirLight.position.set(-50, 50, 200);
    scene.add(dirLight);
    
    const dirLight2 = new DirectionalLight(0xffffff, 1.25);
    dirLight2.position.set(50, 0, 20);
    dirLight2.target.position.set(0, 100, 50);
    scene.add(dirLight2);

    const dirLight3 = new DirectionalLight(0xb200ff, 5);
    dirLight3.position.set(50, 10, 10);
    dirLight3.target.position.set(50, 150, -50);
    scene.add(dirLight3);
    
  }
  
  function initRenderer() {
    
    renderer = new WebGLRenderer({ antialias: true, alpha: true });
	  renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.physicallyCorrectLights = true;
    renderer.outputEncoding = GammaEncoding;
    renderer.gammaFactor = 2.2;
    renderer.setPixelRatio(window.devicePixelRatio > 1.5 ? Math.min(window.devicePixelRatio, 1.4) : Math.min(window.devicePixelRatio, 1.25));
    container.appendChild(renderer.domElement);
    
  }
  
  function initMaterials() {
    
    const green = new MeshStandardMaterial({
      color: 0x38b7b7,
      metalness: 0.5,
      roughness: 0.5
    });
    green.color.convertSRGBToLinear();
    
    const apricot2 = new MeshStandardMaterial({
      color: 0xfc997e,
      metalness: 0.1,
      roughness: 0
    });
    apricot2.color.convertSRGBToLinear();
    
    const greenClassic = new MeshStandardMaterial({
      color: 0x02664b, 
		  roughness: 0.0,
			metalness: 0.2,
			flatShading: false
	  });
    greenClassic.color.convertSRGBToLinear();
    
    const seagreen = new MeshStandardMaterial({
      color: 0x1bbaac,
      metalness: 0.3,
      roughness: 0.1
    });
    seagreen.color.convertSRGBToLinear();
    
    const black = new MeshStandardMaterial({
      color: 0x000000,
      metalness: 0.5,
      roughness: 0
    });
    
    const white = new MeshStandardMaterial({
      color: 0xffffff,
      metalness: 0.4,
      roughness: 0.0,
      flatShading: false
    });
    white.color.convertSRGBToLinear();
    
    const purple = new MeshStandardMaterial({
      color: 0xce93ff,
      metalness: 0.3,
      roughness: 0.0
    });
    purple.color.convertSRGBToLinear();
    
    const blue = new MeshStandardMaterial({
      color: 0x7589c6,
      metalness: 0.35,
      roughness: 0.0
    });
    blue.color.convertSRGBToLinear();
        
    const brick = new MeshStandardMaterial({
      color: 0xbf3e24,
		  roughness: 0.1,
			metalness: 0.4,
      flatShading: false
	  });
    brick.color.convertSRGBToLinear();

    const lemon = new MeshStandardMaterial({
      color: 0xf7b23b,
		  roughness: 0.1,
			metalness: 0.3,
      flatShading: false
	  });
    lemon.color.convertSRGBToLinear();

    const textureOldGold = new TextureLoader().load(textureOldGoldURL);
    
    const gold = new ShaderMaterial({
      
      transparent: false,
      side: DoubleSide,
      uniforms: {
        tMatCap: {
          type: "t",
          value: textureOldGold
        }
      },
      vertexShader: document.querySelector("#vs-matcap").textContent,
      fragmentShader: document.querySelector("#fs-matcap").textContent  
      
    });
    
    return {
      
      white, black, lemon, brick, apricot2,
      blue, purple, green, seagreen, greenClassic,
      gold
      
    }
    
  }
  
  function getPalette() {
    
    let palettePastel = [materials.purple, materials.seagreen, materials.white, materials.black];
    let paletteFlamingo = [materials.purple, materials.apricot2, materials.white, materials.black, materials.seagreen];
    let paletteWarm = [materials.lemon, materials.brick, materials.blue, materials.green, materials.black, materials.gold];
    let paletteWarm2 = [materials.lemon, materials.brick, materials.blue, materials.green, materials.black, materials.gold, materials.white];
    let paletteWarm3 = [materials.lemon, materials.brick, materials.black, materials.greenClassic, materials.blue, materials.white];
    let paletteElegant = [materials.blue, materials.black, materials.gold, materials.lemon, materials.green, materials.black, materials.blue];
        
    let colorPalettes = [
      
      {
        materials: palettePastel,
        background: ["rgb(193, 181, 194)", "rgb(210, 175, 213)", "rgb(245, 224, 245)"],
        svg: ["rgb(87, 221, 202)", "rgb(154, 87, 221)"]
      },
      {
        materials: paletteFlamingo,
        background: ["rgb(43, 42, 42)", "rgb(255, 213, 213)"],
        svg: ["rgb(94, 208, 198)", "rgb(196, 113, 242)"]
      },
      {
        materials: paletteWarm,
        background: ["rgb(234, 215, 211)", "rgb(241, 212, 176)"],
        svg: ["rgb(232, 27, 17)", "rgb(117, 151, 232)"]
        
      },
      {
        materials: paletteWarm2,
        background: ["rgb(162, 169, 172)"],
        svg: ["rgb(99, 117, 255)", "rgb(255, 87, 59)"]
      },
      {
        materials: paletteWarm3,
        background: ["rgb(193, 178, 175)", "rgb(220, 207, 205)", "rgb(235, 188, 161)"],
        svg: ["rgb(68, 128, 86)", "rgb(67, 122, 227)"]
      },
      {
        materials: paletteElegant,
        background: ["#EAD7D3", "rgb(171, 178, 205)", "rgb(181, 182, 194)"],
        svg: ["rgb(255, 199, 112)", "#745bef"]
      }
      
    ];
    
    let chosenPalette = getRandomFromArr(colorPalettes);
        
    return chosenPalette;
    
  }
  
  function loadModel() {
   
    let loader = new GLTFLoader();

    loader.load(

      modelURL, function (gltf) {

        gltf.scene.traverse(function(child) {

          if (child instanceof Mesh) {
            
            child.geometry.computeVertexNormals();
            child.material = getRandomFromArr(currentPalette.materials);

          }

        });

        letters = gltf.scene;
        letters.position.copy(lettersParams.position);
        let scale = lettersParams.scale;
        letters.scale.set(scale, scale, scale);
        scene.add(letters);
        
        // DOTS FOR I'S
        
        let sphereGeom = new SphereBufferGeometry(4.25, 16, 16);
        let randomMat = getRandomFromArr(currentPalette.materials);
        let randomMat2 = getRandomFromArr(currentPalette.materials);
    
        dot = new Mesh(sphereGeom, randomMat);
        dot.position.x = lettersParams.position.x + lettersParams.dotOffset.x;
        dot.position.y = lettersParams.position.y + lettersParams.dotOffset.y;
        let dotScale = lettersParams.dotScale;
        dot.scale.set(dotScale, dotScale, dotScale);
        scene.add(dot);
    
        dot2 = dot.clone();
        dot2.material = randomMat2;
        dot2.position.x = lettersParams.position.x + lettersParams.dot2Offset.x;
        dot2.position.y = lettersParams.position.y + lettersParams.dot2Offset.y;
        let dot2Scale = lettersParams.dot2Scale;
        dot2.scale.set(dot2Scale, dot2Scale, dot2Scale);
        scene.add(dot2);
        
        initTube();
        
        initLettersTimeline();
       
      },

      function (xhr) {
        
        console.log((xhr.loaded / xhr.total * 100) + '% loaded');
        
      },

      function (error) {
        
        console.log("GLTF loading error");
        
      }

    );
  }
  
  function initSprinkles() {
    
    const sphereGeom = new SphereBufferGeometry(0.5, 5, 5);
    const cylinderGeom = new CylinderGeometry(0.5, 0.5, 3.5, 10);
    
    let geoms = [sphereGeom, cylinderGeom];
    
    const randomMat = getRandomFromArr(currentPalette.materials);
    
    let radius = 14;
        
    for (let i = 0; i < 35; i++) {
      
      let c = new Mesh(getRandomFromArr(geoms), getRandomFromArr(currentPalette.materials));
      
      let u = Math.random();
      let v = Math.random();
      let theta = 2 * Math.PI * u;
      let phi = Math.acos(2 * v - 1);
      let x =  (radius * Math.sin(phi) * Math.cos(theta)) + getRandomInRange(0, 20);
      let y =  (radius * Math.sin(phi) * Math.sin(theta));
      let z =  (radius * Math.cos(phi));
      c.position.set(x, y, z);
      c.rotation.z = getRandomInRange(0, 2 * Math.PI);
      c.scale.set(0, 0, 0);
      sprinklesEndGroup.add(c);
      
    }
    
    sprinklesEndGroup.position.set(42, -37.5, -45);
    scene.add(sprinklesEndGroup);
    
  }
  
  function initTube() {
    
    // POINTS TUBE
    
    let points = getExportedPoints().curvePoints;
    
    const doodleMesh = closedCapsTube(points, doodleParams.tubeThickness, 20);
    const scale = doodleParams.scale;
    doodleMesh.scale.set(scale, scale, scale);
    doodleMesh.position.copy(doodleParams.position);
    scene.add(doodleMesh);
    
    let randomMat = getRandomFromArr(currentPalette.materials);
    
    ball = new Mesh(new SphereBufferGeometry(3.25, 12, 12), randomMat);
    ball.scale.set(doodleParams.ballScale, doodleParams.ballScale, doodleParams.ballScale);
    let pos = doodleParams.curve.getPointAt(1.0 - Math.abs(mouseX));
    pos.multiplyScalar(doodleParams.scale);
    ball.position.x = doodleParams.position.x + pos.x + 0.25;
    ball.position.y = doodleParams.position.y + pos.y + 0.25;
    ball.position.z = doodleParams.position.z + pos.z + 0.25;
    scene.add(ball);
    
  }
  
  function closedCapsTube(pts, thickness, segments) {  
  
    const closedTubeGroup = new Group();
    let tubeMat = getRandomFromArr(currentPalette.materials);
  
    // CURVE SHAPING THE SCULPTURE

    let points = pts;
    let pScale = 1.5;

    for (let i = 0; i < points.length; i++) {

      let x = points[i][0] * pScale;
      let y = points[i][1] * pScale;
      let z = points[i][2] * pScale;
      points[i] = new Vector3(x, z, -y);

    }
   
    let curve = new CatmullRomCurve3(points);
    let p = curve.getPoints(100);
    let curveSmooth = new CatmullRomCurve3(p);
    doodleParams.curve = curveSmooth;  
    let geom = new TubeGeometry(curveSmooth, doodleParams.tubeTubularSegments, thickness, 6, false);
    let tube = new Mesh(geom, tubeMat);
    closedTubeGroup.add(tube);
  
    // TUBE START POINTS
  
    let pos = geom.attributes.position;
    let startPoints = [];
    startPoints.push(curve.getPoint(0));
  
    for (let i = 0; i <= geom.parameters.radialSegments; i++) {

      startPoints.push(new Vector3().fromBufferAttribute(pos, i));

    }

    let pointsStartGeom = new BufferGeometry().setFromPoints(startPoints);
    let psgPos = pointsStartGeom.attributes.position;
    let indexStart = [];
  
    for (let i = 1; i < psgPos.count - 1; i++) {

      indexStart.push(0, i, i + 1);

    }
    pointsStartGeom.setIndex(indexStart);
    pointsStartGeom.computeVertexNormals();
  
    // CAP MESH START
  
    let capStart = new Mesh(pointsStartGeom, tubeMat);
    closedTubeGroup.add(capStart);
  
    // TUBE END POINTS

    let endPoints = [];
    endPoints.push(curve.getPoint(1));

    for (let i = (geom.parameters.radialSegments + 1) * geom.parameters.tubularSegments; i < pos.count; i++) {

      endPoints.push(new Vector3().fromBufferAttribute(pos, i));

    }

    let pointsEndGeom = new BufferGeometry().setFromPoints(endPoints);
    let pegPos = pointsEndGeom.attributes.position;
    let indexEnd = [];

    for (let i = 1; i < pegPos.count - 1; i++) {

      indexEnd.push(0, i + 1, i);

    }
    
    pointsEndGeom.setIndex(indexEnd);
    pointsEndGeom.computeVertexNormals();
  
    // CAP MESH END

    let capEnd = new Mesh(pointsEndGeom, tubeMat);
    closedTubeGroup.add(capEnd);
    
    return closedTubeGroup;
  
  }
  
  function render() {
    
    requestAnimationFrame(render);
    renderer.render(scene, camera);
    
    moveBallAlongCurve();
    
    sprinklesTL.progress(Math.abs(1.0 - mouseX));
    
    if ( letters ) {
      
      letters.rotation.x = -0.05 * Math.PI * (mouse.x);
      letters.rotation.y = -0.025 * Math.PI * (mouse.y);
      
    } else {
      
      return;
      
    }
    
  }
  
  // *** EVENT LISTENERS ***
  
  function onWindowResize() {
    
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
        
  }
  
  function onMouseMove() {
    
    event.preventDefault();
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
	  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    mouseX = convertRange(mouse.x, [-1, 1], [0, 1]);
        
  }
  
  function onTouchMove(e) {
    
	  let x = e.changedTouches[0].clientX;
    let y = e.changedTouches[0].clientY;
    
    mouse.x = (x / window.innerWidth) * 2 - 1;
    mouse.y = (y / window.innerWidth) * 2 - 1;
    mouseX = convertRange(mouse.x, [-1, 1], [0, 1]);
      
  }
  
  function onButtonClick() {
    
    currentPalette = getPalette();
    
    document.body.style.background = getRandomFromArr(currentPalette.background);
    updateMaterialsPalette();
    updateSVGPalette();
     
  }
  
  function updateMaterialsPalette() {
        
    if (letters) {
      
      scene.traverse(function(child) {

        if (child instanceof Mesh) {
            
          child.material = getRandomFromArr(currentPalette.materials);
            
        }

      });
      
      let randomMat = getRandomFromArr(currentPalette.materials);
      
      lettersTL.play(0);
      
    } else {
      
      return;
      
    }
    
  }
  
  function updateSVGPalette() {
    
    airbrush1.style.fill = currentPalette.svg[0];
    airbrush2.style.fill = currentPalette.svg[1];
    airbrush3.style.fill = currentPalette.svg[1];
    
  }
  
  // *** ANIMATION ***
  
  function moveBallAlongCurve() {
    
    if (ball) {
      
      let pos = doodleParams.curve.getPointAt(1.0 - Math.abs(mouseX));
      pos.multiplyScalar(doodleParams.scale);
      ball.position.x = doodleParams.position.x + pos.x + 0.25;
      ball.position.y = doodleParams.position.y + pos.y + 0.25;
      ball.position.z = doodleParams.position.z + pos.z + 0.25;
      
    } else {
      
      return;
    
    }
  
  }
  
  function initLettersTimeline() {
  
    lettersTL = gsap.timeline({paused: true, yoyo: false, defaults: {ease: "elastic"}});
  
    lettersTL
      .add("typo")
      .to({}, {x: 4, duration: 2, ease: "elastic"}, "typo")
      .to(letters.scale, {x: 4, duration: 1.4}, "typo")
      .to(letters.scale, {y: 4, duration: 1.4}, "typo")
      .to(letters.scale, {z: 4, duration: 1.4}, "typo")
    
      .to(dot.position, {y: 16, duration: 1.0}, "typo+=0.2")
      .to(dot.scale, {x: 1.05, duration: 0.85}, "typo+=0.35")
      .to(dot.scale, {y: 1.05, duration: 0.85}, "typo+=0.35")
      .to(dot.scale, {z: 1.05, duration: 0.85}, "typo+=0.35")

      .to(dot2.position, {y: 19.25, duration: 1.0}, "typo+=0.4")
      .to(dot2.position, {x: 42, duration: 0.9, ease: "linear"}, "typo+=0.4")
      .to(dot2.scale, {x: 1.05, duration: 0.85}, "typo+=0.35")
      .to(dot2.scale, {y: 1.05, duration: 0.85}, "typo+=0.35")
      .to(dot2.scale, {z: 1.05, duration: 0.85}, "typo+=0.35")

    ;
    
  }
  
  function initSprinklesTimeline() {
    
    sprinklesTL = gsap.timeline({paused: true, yoyo: false, defaults: {ease: "power2.easeOut"}});
    let endScales = sprinklesEndGroup.children.map(a => a.scale);
    
    sprinklesTL
      .to({}, {x: 0, duration: 5, ease: "elastic" })
      .add("doodleEnd")
      .to(endScales, {x: 1, stagger: {amount: 2.5}}, "doodleEnd")
      .to(endScales, {y: 1, stagger: {amount: 2.5}}, "doodleEnd")
      .to(endScales, {z: 1, stagger: {amount: 2.5}}, "doodleEnd")
    ;
    
  }
  
}

// *** UTILS ***

function getRandomInRange(min, max) {
  
  return Math.random() * (max - min) + min; 

}

function getRandomFromArr(array) {
  
  let randomElement = array[Math.floor(Math.random() * array.length)];
  
  return randomElement;
  
}

function convertRange(value, r1, r2) { 
  
  return (value - r1[0]) * (r2[1] - r2[0]) / (r1[1] - r1[0]) + r2[0];
  
}


External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://unpkg.co/gsap@3/dist/gsap.min.js