<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>PNPT. 9</title>
    <link>https://pnpt.tistory.com/</link>
    <description>20년차 UX 디자이너 + 이런 저런 얘기들.</description>
    <language>ko</language>
    <pubDate>Wed, 15 Apr 2026 18:00:29 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>ARTBRAIN</managingEditor>
    <image>
      <title>PNPT. 9</title>
      <url>https://tistory1.daumcdn.net/tistory/3881830/attach/61212eba255642bbbf5c5333d5499e07</url>
      <link>https://pnpt.tistory.com</link>
    </image>
    <item>
      <title>클로드로 만든 맥용 라디오 복합(?) 플레이어 : RAPI</title>
      <link>https://pnpt.tistory.com/206</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;844&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SiNl1/dJMcahRzmTx/3BU3uMnjQPYtoV7flLHwAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SiNl1/dJMcahRzmTx/3BU3uMnjQPYtoV7flLHwAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SiNl1/dJMcahRzmTx/3BU3uMnjQPYtoV7flLHwAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSiNl1%2FdJMcahRzmTx%2F3BU3uMnjQPYtoV7flLHwAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1300&quot; height=&quot;844&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;844&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거 만드느라 클로드로 &lt;s&gt;40&lt;/s&gt; &lt;b&gt;70&lt;/b&gt;불을 썼어. 클로드 코드가 중독성이 있다더니 정말이네.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 만든 앱은 라디오 앱이고, 이 앱 역시 내 지식의 범위와 개인적인 필요에 의한 거야. 그래도 저번 주에 만든 앱 &lt;a href=&quot;https://www.panopt.net/205&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;HAKA&lt;/a&gt;보다는 조금 더 미지의 영역까지 손을 뻗어 봤는데, 아무래도 내가 모르는 부분이 있다 보니 그만큼 어설픈 지시를 했고, 그만큼 클로드도 에러를 내더라구.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 업무 중에 일정 정도의 소음이 필요해. 그리고 그게 &lt;b&gt;약간&lt;/b&gt;의 내러티브를 갖고 있으면 좋아.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 회사의 주변 사람들이 하는 이야기는 대부분 업무 얘기니까 대충 흘려듣기 어려워서 집중하게 되고, 음악은 지나치게 몰입하게 되어서 작업에 영향을 주기도 해. 오디오북도 시도해 봤는데, 그건 완전 &quot;이야기&quot;라서, 내용을 놓치면 다시 돌려 듣게 되더라구. ^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 요즘 하는 건 대충 몇 개의 팟캐스트, 혹은 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(소리로만 듣는)&lt;/span&gt; 유튜브를 연속재생으로 걸어놓고, 듣는둥 마는둥 하는 편이야. 나름 이 'verbal ambient sound'를 업무의 배경음악으로 사용하고 있는데, 이것도 한 번 리스트가 다 돌아가면 다시 조작해야 해서 귀찮아. 역시 라디오만한 게 없나 싶었어. 틀어 놓으면 24시간 알아서 돌아가고, 맥락 파악하지 않아도 되고, 가끔 살짝 마음 싣고 들었다가 나와도 부담없고.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라디오 앱 하나 만들어 볼까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10여 년 전에 만들어 본 적이 있었거든. 당연히 플래시로. ^^ 라디오의 특성인지는 모르겠지만, asf 주소 하나만 걸어 놓으면 계속 재생하더라구. 지금도 그런지는 모르겠지만, 암튼 좀 만만해 보였어. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;라디오가 기본적으로 가져야 할 play, stop, volume, mute 등은 - 모르긴 몰라도 쉽게 수행할 수 있을 것 같았어.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;그래서 이번에는 약간 비틀어 보기로 했어.&lt;/b&gt;그런데 저번 주에 만든 &lt;a href=&quot;https://www.panopt.net/205&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;HAKA 앱&lt;/a&gt;은 너무 난이도가 낮았다고 생각해서, 시작부터 간단한 허들을 만들고 시작했어.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;볼륨과 채널을 선형적으로 조작하지 않고 평면에서 조작하게 하자.&lt;/li&gt;
&lt;li&gt;채널 이동을 스위치로 딸깍 넘기지 않고, 디졸브&lt;span style=&quot;color: #8cb3be;&quot;&gt; (초기 아이디어는 각 채널이 서로 상관관계를 맺도록 만들려 했음)&lt;/span&gt; 되도록 하자.&lt;/li&gt;
&lt;li&gt;이전 HAKA에서 못했던 Liquid Glass를 시도해 보자. &lt;span style=&quot;color: #7e98b1;&quot;&gt;이것저것 쌓고 나서 만들면 어려울 것 같으니&lt;/span&gt; 그것먼저 시도해 보자.&lt;/li&gt;
&lt;li&gt;회사 업무로는 충족하지 못하는, 아티스틱한 시도를 해보자.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1676&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bv6kQs/dJMcabcJGFI/wEOavj9vdp4BjDMd1eWJV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bv6kQs/dJMcabcJGFI/wEOavj9vdp4BjDMd1eWJV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bv6kQs/dJMcabcJGFI/wEOavj9vdp4BjDMd1eWJV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbv6kQs%2FdJMcabcJGFI%2FwEOavj9vdp4BjDMd1eWJV1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1676&quot; height=&quot;612&quot; data-origin-width=&quot;1676&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어는 간단해. 아래에 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(내가 자주 듣는)&lt;/span&gt; 세 개 채널을 두고, 그걸 원 안으로 넣으면 재생이 시작되는 건데, 원의 중심으로 갈수록 볼륨이 커지고, 아래 블러되는 색상의 크기도 커져.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1676&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG9Xfe/dJMcaiiEfB4/M34UkwIwPSHBbLEKpVhFgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG9Xfe/dJMcaiiEfB4/M34UkwIwPSHBbLEKpVhFgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG9Xfe/dJMcaiiEfB4/M34UkwIwPSHBbLEKpVhFgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG9Xfe%2FdJMcaiiEfB4%2FM34UkwIwPSHBbLEKpVhFgK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1676&quot; height=&quot;612&quot; data-origin-width=&quot;1676&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 가운데 선을 기준으로, 버튼&lt;span style=&quot;color: #8cb3be;&quot;&gt;(89.1)&lt;/span&gt;이 선 위에 있으면 양쪽 스피커/이어폰에서 같은 음량으로 소리가 나지만, 한쪽으로 치우치는 경우, 그 쪽 방향의 스피커/이어폰에서만 소리가 나게 하고 싶었어. 근데... &lt;b&gt;요게 제일 오래 걸렸어.&lt;/b&gt; 나는 좌우 음량 조절이 쉽게 분리되는 건 줄 알았는데, 정말 쉽지 않더라구. 이걸 구현하느라 정말 다양한 시도를 했어. 내가 요청한 시도로도 해봤고, 클로드가 알아서 솔루션을 찾아보기도 했는데, 우연히 내 맥에 깔려 있던 IINA라는 동영상 재생 앱에서 제공하는 오픈소스를 클로드가 찾아서, 그걸로 구현했어. &lt;span style=&quot;color: #8cb3be;&quot;&gt;(하지만 아직도 에러가 많고, 해결은 됐지만 정답은 아닌 느낌) &lt;/span&gt;듣다보면 좌우 채널의 소리가 싱크가 안맞는 경우가 생겨. &lt;b&gt;아마도 하나의 채널을 양쪽 스피커/이어폰에 할당하는 방식이 아니라, 두 개의 사운드를 양쪽으로 동시에 보내는 구조인가 봐.&lt;/b&gt; 왼쪽 귀보다 오른쪽 귀가 약간 딜레이가 생기면 마치 에코같이 울림이 생기는데, 그럴 때는 잠깐 원의 바깥으로 채널을 뺐다가 넣으면 고쳐지긴 해^^&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1676&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWJgXp/dJMcadn5baX/k7QrkZKrUDzS4RDjOSlRE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWJgXp/dJMcadn5baX/k7QrkZKrUDzS4RDjOSlRE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWJgXp/dJMcadn5baX/k7QrkZKrUDzS4RDjOSlRE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWJgXp%2FdJMcadn5baX%2Fk7QrkZKrUDzS4RDjOSlRE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1676&quot; height=&quot;612&quot; data-origin-width=&quot;1676&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 두 개가 되니까, 이제 세 개의 라디오를 동시에 트는^^ &lt;span style=&quot;color: #8cb3be;&quot;&gt;왜 하나 싶긴 하지만 해보고 싶었던&lt;/span&gt; 뭔가 아티스틱하고 예쁜 그림이 만들어졌어. 왼쪽 귀로 91.9를 들으며 오른쪽 귀로 89.1을 듣는 것도 되고, 107.7을 메인으로 들으면서, 두 채널을 작게 틀어놓아서 뭔가 정신없이 들을 수도 있어. 굳이 의의를 찾자면, 세 개 라디오를 대충 소음처럼 듣다가 좋아하는 음악이 나오는 상황이면 그 채널을 키워서 크게 듣는 용도?^^&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTSoJD/dJMcaiiEf1n/7AHRBJSib4XlsEuWH99dKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTSoJD/dJMcaiiEf1n/7AHRBJSib4XlsEuWH99dKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTSoJD/dJMcaiiEf1n/7AHRBJSib4XlsEuWH99dKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTSoJD%2FdJMcaiiEf1n%2F7AHRBJSib4XlsEuWH99dKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1540&quot; height=&quot;612&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 앱에서는 기능을 다 구현해 놓은 상태에서 liquid glass를 구현하려다 보니 클로드가 기존 내용을 '쥔' 상태에서 시도하느라 결국 구현하지 못했는데, 이번에는 처음 테이블을 만들 때 liquid glass 먼저 구현하고, 그 위에 이런저런 기능을 추가했어.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이름은 RAPI. Radio + Pie.&lt;/b&gt; &lt;br /&gt;이전에 만든 Haka가 Hanja + Kanji다보니 이름은 계속 이런 식으로 갈 것 같네.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;오픈소스들을 내재화하느라, 이번 파일은 용량이 좀 커. 48메가 정도 됨.&lt;br /&gt;&lt;a href=&quot;https://drive.google.com/file/d/174smb5hqGKfy5kjs8FbJxuZwrBjA1920/view?usp=sharing&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;링크는 여기&lt;/b&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로, Apple Developer ID 없이 제작한 것이니까 처음 열 때는&lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;[시스템 설정 - 개인정보 보호 및 보안 - 확인 없이 열기]&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;를 해야 하고, 이 앱을 사용하는 과정에서의 문제..라는 게 있을까 싶지만, 암튼 책임은 사용자의 몫입니다아. 그래도 뭐 안 심어놓았고, 심을 줄도 모르니 안심하십셔.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;사용&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;방법&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;1. 앱을 처음 켰을 때, 뭔가 안 되는 것 같으면 처음에는 껐다 켜시오. 가끔 이상합디다.&amp;nbsp;&lt;span style=&quot;color: #8cb3be;&quot;&gt;(코맨드 Q)&lt;/span&gt;&lt;br /&gt;2. 각 주파수를 원으로 끌어다 놓고 빼면서 놀면 됩니다. 참고로, 각 채널의 &lt;b&gt;점&lt;/b&gt; 위치가 실제로 작동하는 거여요. 가운데 선에 있어야 좌우 음량이 동일하게 나오는 것인데... 대개 20대 중반이 넘어가면 좌우 청력이 미묘하게 다르답니다. &lt;span style=&quot;color: #8cb3be;&quot;&gt;저도 30년 넘게 귀에 이어폰 꽂고 살다 보니 왼쪽 귀가 살짝 난청. ㅠㅠ&amp;nbsp;&lt;/span&gt;&lt;br /&gt;3. 왼쪽 상단에 화살표 버튼은, 각 주파수 버튼을 원래 자리로 돌려놓는 용도입니다. 버튼이 원 밖으로 나가는 거니 즉시 stop 기능으로 써도 무방. 단축키는 코맨드 R &lt;span style=&quot;color: #8cb3be;&quot;&gt;(&lt;b&gt;R&lt;/b&gt;estore default)&lt;/span&gt;&lt;br /&gt;4. 항상 맨 위에 놓는 버튼은 오른쪽 위쪽에 있고, 단축키는 코맨드 T&lt;span style=&quot;color: #8cb3be;&quot;&gt; (Always on &lt;b&gt;T&lt;/b&gt;op)&lt;br /&gt;&lt;/span&gt;5. 오래 쓰거나 가끔 모종의 이유로 에코 같은 게 생기면, 원 밖으로 그 채널을 뺐다가 넣거나 코맨드 R로 원복하고 다시 틀어봐.&lt;br /&gt;6. 맥용, 실리콘용 앱이고, 최신 OS에서만 liquid glass가 작동함.&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;아하하. 또 버전 업데이트 하겠지?&amp;nbsp;&lt;br /&gt;근데 돈이 없어. 3일 동안 클로드가 십 몇만 원 가져갔음. ㅠㅠ&lt;br /&gt;오늘이 월요일인데, 목요일까지 못쓴대.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Update&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.0.1 &lt;/b&gt;&amp;nbsp;2026.04.14&lt;br /&gt;* 에코현상 해결 : 좌우 채널이 인스턴스를 동시에 쓰는 탓에 생기는 문제를 인스턴스 단일화로 해결. 틱틱 끊기는 잡음이 있을 수 있다고 하는데, 아직은 이상없어 보임. 에코가 없어졌는지는 충분히 안써봐서 모르겠는데, 음질은 확실히 전보다 나아졌음&lt;/p&gt;</description>
      <category>IMG/COD</category>
      <category>라디오앱</category>
      <category>코드</category>
      <category>클로드</category>
      <category>클로드코드</category>
      <author>ARTBRAIN</author>
      <guid isPermaLink="true">https://pnpt.tistory.com/206</guid>
      <comments>https://pnpt.tistory.com/206#entry206comment</comments>
      <pubDate>Mon, 13 Apr 2026 23:12:18 +0900</pubDate>
    </item>
    <item>
      <title>클로드로 4시간 걸린 맥용 한자 공부 앱 : HAKA</title>
      <link>https://pnpt.tistory.com/205</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;난 꽤 오랜 취미로 언어 공부를 하고 있는데, 흥미가 이끄는 대로 하다 보니 무엇 하나 깊이 파고든 건 없더라구. 목표가 없으니 늘지 않는 것 같아서 작년부터 JLPT니, DELF, TestDaF 등등의 시험을 볼 궁리를 하고 있는데, 우선 제일 쉬운&lt;span style=&quot;color: #8cb3be;&quot;&gt;(?)&lt;/span&gt; 한자 3급을 먼저 따보려고 올해 1월부터 한자를 공부중이야.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 회사원이 각 잡고 공부하는 게 어디 쉽나. 회사 일, 가족 일에 밀려서 대충대충 하고 있지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 오늘은 회사를 좀 일찍 마치고 귀가했어. &lt;br /&gt;어라? 갑자기 시간이 생겼네? ^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로드를 켜서 &quot;한자를 &lt;b&gt;평소에&lt;/b&gt; 익힐 수 있는 앱&quot;을 만들어보자 하고 맥용 네이티브 앱을 만들어 보았는데... &lt;br /&gt;&lt;b&gt;허망하리만큼 쉽고 단순해서 놀랐어.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 몇 번의 의견 교환으로 MVP를 완료한 게 20분, 로컬로 만들려 했던 초기 아이디어를 네이버 한자사전 API를 사용해 온라인화하는 수정 작업이 30분, &lt;b&gt;불투명한 디자인에서 네가티브한 디자인으로 수정하는 데 40분 정도. 투명도와 블러 값 미세 조정하다 타협하기까지 40분&lt;/b&gt;, &lt;b&gt;편의 기능 추가하고 글자 크기, 패딩 값, 색상과 폰트 웨이트, 아이콘 디테일과 각종 간격 수정에 1시간&lt;/b&gt;, 아이콘 그리기와 앱 아이콘 만들기 합쳐 10분, 에러 잡는데 30분 ... 다 해서 많이 잡아야 4시간 정도 걸린 것 같아.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;890&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDdpjw/dJMcahYlqgq/2YfaiDo8LIN3vxwLTxyhRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDdpjw/dJMcahYlqgq/2YfaiDo8LIN3vxwLTxyhRK/img.png&quot; data-alt=&quot;우측이 초안, 좌측이 버전 1.05&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDdpjw/dJMcahYlqgq/2YfaiDo8LIN3vxwLTxyhRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDdpjw%2FdJMcahYlqgq%2F2YfaiDo8LIN3vxwLTxyhRK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1462&quot; height=&quot;890&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;890&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;우측이 초안, 좌측이 버전 1.05&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 본업 바이브 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(디테일 집착의 시간ㅠㅠ)&lt;/span&gt;를 빼면 2시간도 안걸린 셈이지. 이게 말이 돼?&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;* 제작 속도가 빨랐던 건, 앱 자체의 난도가 낮은 것도 한몫했을거야. 플래시가 여전히 존재했다면 이건 4시간... 아니, 하루면 만들었을 것 같아. 그냥 데이터 테이블 행렬 잘 짜고, 그걸 불러와서 입력값과 매칭되는 데이터를 보여주기만 하면 되니까. 완전히 '모르는' 기능을 만들기에는 내적인 두려움이 있었나 봄^^&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 기능 설명을 하자면,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IyhJH/dJMcaaZbN4J/BJX7hugnVcYhHmc7AXES6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IyhJH/dJMcaaZbN4J/BJX7hugnVcYhHmc7AXES6k/img.png&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;684&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IyhJH/dJMcaaZbN4J/BJX7hugnVcYhHmc7AXES6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIyhJH%2FdJMcaaZbN4J%2FBJX7hugnVcYhHmc7AXES6k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;848&quot; height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w4LtN/dJMcagd3L3K/jVZWtRsBuIA9CRqf1qRtDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w4LtN/dJMcagd3L3K/jVZWtRsBuIA9CRqf1qRtDk/img.png&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;684&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w4LtN/dJMcagd3L3K/jVZWtRsBuIA9CRqf1qRtDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw4LtN%2FdJMcagd3L3K%2FjVZWtRsBuIA9CRqf1qRtDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;848&quot; height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적인 용도로 만든 앱이니까 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;무조건 내가 쓰기 편하게.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;맥 윈도우에 항상 떠야 하는 좌상단의 닫기/최대화/최소화 버튼을 지웠어. 맨 윗줄을 날린 거지. 나는 그거 안쓰니까^^ &lt;span style=&quot;color: #8cb3be;&quot;&gt;(코맨드+Q로 닫음)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;연속적으로 입력할 수 있도록, 엔터를 치면 한자가 뜨고 다시 엔터를 누르면 인풋창에 쓴 텍스트가 지워지고 다시 대기모드로 돌아가도록 했어. &lt;span style=&quot;color: #8cb3be;&quot;&gt;(개인적으로는 커서를 이동시키는 일을 적게 하고 싶어. 키보드만 치는 방향으로 진화하는 중)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/11pLn/dJMcaibSWyD/GjiHrbFbKU7wReBkfwGtyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/11pLn/dJMcaibSWyD/GjiHrbFbKU7wReBkfwGtyk/img.png&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;684&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/11pLn/dJMcaibSWyD/GjiHrbFbKU7wReBkfwGtyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F11pLn%2FdJMcaibSWyD%2FGjiHrbFbKU7wReBkfwGtyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;848&quot; height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpnSE5/dJMcajoedoM/jkFRv8UQ6wyuTBfgJv6f1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpnSE5/dJMcajoedoM/jkFRv8UQ6wyuTBfgJv6f1k/img.png&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;684&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpnSE5/dJMcajoedoM/jkFRv8UQ6wyuTBfgJv6f1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpnSE5%2FdJMcajoedoM%2FjkFRv8UQ6wyuTBfgJv6f1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;848&quot; height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공부할 목적이니까 동음이의어가 있으면 무조건 다 보여주기&lt;/li&gt;
&lt;li&gt;문장을 쓰면 한자에 해당하는 부분만 한자로 써 주고, 좌우 방향키를 이용하여 단어간 이동 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(요기서 약간의 trade off 발생, 긴 문장을 쓰면 에러가 뜨는 건 아직 못 잡음)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;오른쪽 위에 작은 핀 = 항상 위에 고정&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/th7s9/dJMcaf0t03P/QFU5dyEBWN8nT57TdfEQQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/th7s9/dJMcaf0t03P/QFU5dyEBWN8nT57TdfEQQ0/img.png&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;684&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/th7s9/dJMcaf0t03P/QFU5dyEBWN8nT57TdfEQQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fth7s9%2FdJMcaf0t03P%2FQFU5dyEBWN8nT57TdfEQQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;848&quot; height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GR0wf/dJMcadBxFCj/uIUD7JRxtXhYEJChWAWhEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GR0wf/dJMcadBxFCj/uIUD7JRxtXhYEJChWAWhEk/img.png&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;684&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GR0wf/dJMcadBxFCj/uIUD7JRxtXhYEJChWAWhEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGR0wf%2FdJMcadBxFCj%2FuIUD7JRxtXhYEJChWAWhEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;848&quot; height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 번 검색했던 한자를 다시 검색하면 볼드하게, 두번째는 노란색으로 보이도록. 눈에 익게 하는 게 목적이니까. &lt;span style=&quot;color: #8cb3be;&quot;&gt;(실제로 써보니 금세 다 노래져서 횟수와 단계를 늘임)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;코맨드+E를 누르면 저장했던 검색내용 지우기, 지우면 한자 강조 기능 초기화&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;730&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nlA89/dJMcaiCUF7v/nELa7sZkzeBPdojgM6sB4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nlA89/dJMcaiCUF7v/nELa7sZkzeBPdojgM6sB4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nlA89/dJMcaiCUF7v/nELa7sZkzeBPdojgM6sB4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnlA89%2FdJMcaiCUF7v%2FnELa7sZkzeBPdojgM6sB4k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1510&quot; height=&quot;730&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;730&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리사이징도 되고 창 이동도 되지만, 상단 바&lt;span style=&quot;color: #8cb3be;&quot;&gt;(닫기버튼이 있는 줄)가&lt;/span&gt; 보기 싫어 지워버렸기 때문에 쵸큼 불편함&lt;/li&gt;
&lt;li&gt;그리고 보시다시피, 에러도 여전히 많음&lt;/li&gt;
&lt;li&gt;애플같은 글래스모피즘&lt;span style=&quot;color: #8cb3be;&quot;&gt;(?)&lt;/span&gt;을 구현하거나 Background Blur를 보다 정밀하게 조정하고 싶었는데, 여러 번 시도해도 잘 안되더라구. 그런데 애플 문서를 좀 찾아보니 내가 얼마나 말도 안되는 요구를 클로드에게 한 건지 알게 되었음. &lt;span style=&quot;color: #8cb3be;&quot;&gt;클로드에게 사과 백 번 함. 그래도 시간 되면 또 시도해볼 예정.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;원래는 한국 한자와 일본 한자도 함께 공부할 목적으로 이름을 HAKA&lt;span style=&quot;color: #8cb3be;&quot;&gt;(Hanja+Kanji)&lt;/span&gt;로 지었는데, 일본한자의 모양이 다른데다가 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(폰트 임베드 필요해짐)&lt;/span&gt;, 두 개의 사전을 긁어와야 해서 내가 원하는 속도가 나오지 않았음. 걍 한국 한자만 하는 걸로 일단락.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고작 한자사전의 위젯에 불과하지만, 하다보니 이런저런 기능 붙이고 재밌네. 소리도 넣고, 에러 메시지도 써보고, 라이선스 안전한 DB로도 교체해 보고... 아직은 한~참 멀었겠지만, 예전에 플래시를 처음 배우던 그 밤 같아. &lt;span style=&quot;color: #8cb3be;&quot;&gt;(하루에 천 리를 걸었더랬지!)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정식으로 승인받은 앱이 아니어서, 열려면 &lt;span style=&quot;color: #7e98b1;&quot;&gt;[시스템 설정 - 개인정보 보호 및 보안 - 확인 없이 열기]&lt;/span&gt;를 하면 됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, &lt;b&gt;이 앱의 정확성이나 문제를 내가 보장하진 않습니다요.&lt;/b&gt; 앱을 사용하면서 생기는 문제는 사람의 책임이야. 그렇다고 내가 불법적인 것을 심어놓지는 않았으니 그건 안심해도 좋아. 내 공부용으로 만든 거니 데이터의 신뢰성은 내가 보기엔 괜찮은 것 같고. &lt;span style=&quot;color: #8cb3be;&quot;&gt;(오타는 좀 있음)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/LJXju/dJMcai3Yi98/fPWm8xKCF4Z48LHxSBT8H0/01haka.dmg?attach=1&amp;amp;knm=tfile.dmg&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;01haka.dmg&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;6.86MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;br /&gt;Updates&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;b&gt;1.01&lt;/b&gt;. 2026. 04.11 8:52 AM&lt;br /&gt;&amp;middot; 효과음 추가 : 성공과 실패에 따라 다른 beep음 추가&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; 검색 실패 시 6개의 영어 문구 중 하나를 랜덤으로 출력&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; 동음이의어의 한자와 훈/음을 시각적으로 연결하기 어려워서 옆에 작은 숫자를 붙임&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot; &lt;span&gt;그 중 가장 사용 빈도 높은 걸 앞에 두고 빨간 점 표기&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; 데이터를 지울 때 (Erase Records) 팝업으로 경고하던 걸 없애고 바로 지움. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(팝업에서 계속 에러가 생겨서 우회한 것임)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; 한자를 연속으로 드래그해서 선택할 수 있도록 함 &lt;span style=&quot;color: #7e98b1;&quot;&gt;(기존엔 한 글자씩만 선택됐었음) &lt;span style=&quot;color: #f89009;&quot;&gt;- update. 취소하고 컴마 단위로 선택하게 변경&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; 완전 오프라인 전환 &lt;span style=&quot;color: #7e98b1;&quot;&gt;(libhangul hanja.txt을 사용해서 외부 API 의존성 제거) &lt;span style=&quot;color: #f89009;&quot;&gt;- update. 단어의 의미는 online 일 때만 작동&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; DMG 패키징 &lt;span style=&quot;color: #7e98b1;&quot;&gt;(해보고 싶어서. 근데 나처럼 캐주얼한 사용자는 걍 zip으로 묶어 올리는 게 더 나을 듯. 은근 번거롭네.)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.02&lt;/b&gt;. 2026. 04.11 12:22 PM&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; 괄호 안에 훈과 음을 넣으면, 그 한자를 찾아 줌 : 정확하게 쓰지 않으면 못 찾음. ㅠㅠ&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #7e98b1;&quot;&gt;(예 : (포도 포), 띄어쓰기해줘야 함)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&amp;middot;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 앱 아이콘 조금 바꿈 : 피그마에 Glass 이펙트 써볼까 해서. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(과정이 귀찮으나, 실무에 비하면 엄청 쉽지. 암요!)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&amp;middot; Always on Top에 단축키 할당 &lt;span style=&quot;color: #7e98b1;&quot;&gt;(코맨드+T)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; 비프 사운드와 한글 데이터에 대한 라이선스 기재함&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;b&gt;1.03&lt;/b&gt; 2026. 04.11 7:38 PM&lt;br /&gt;&amp;middot;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 방향키로 단어 간 이동 시, 활성단어가 좌측정렬되도록 수정 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(동음이의어 제외)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&amp;middot;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; 훈과 음의 정렬 버그 수정 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(상단 정렬로 수정함)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.04&lt;/b&gt; 2026. 04.12 3:50 PM&lt;br /&gt;&amp;middot; &lt;span style=&quot;background-color: #ffffff; color: #121212; text-align: start;&quot;&gt;한국어기초사전 Open API 추가 : 저작권 표기 추가 &lt;span style=&quot;background-color: #ffffff; color: #121212; text-align: start;&quot;&gt;&quot;Definitions by Korean Learners' Dictionary, NIKL (&lt;span style=&quot;color: #8cb3be;&quot;&gt;CC BY-SA 2.0 KR)&lt;/span&gt;&quot;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; 두 글자 이상의 단어일 때, 그 의미를 한국어 기초사전 API 통해 제공, 일일 50,000회 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(온라인일 때만 동작)&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;middot;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 한국어문회 기준 급수 표기 (특급 &lt;span style=&quot;color: #121212; text-align: start;&quot;&gt;●,1급 &lt;span style=&quot;color: #121212; text-align: start;&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;●&lt;/span&gt;, 2급 &lt;span style=&quot;color: #f3c000; text-align: start;&quot;&gt;●&lt;/span&gt;, 3급 &lt;span style=&quot;color: #a6bc00; text-align: start;&quot;&gt;●&lt;/span&gt;, 4급~5급 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;❹❺&lt;/span&gt;, 6~8급 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;⑥⑦⑧&lt;/span&gt;, 기타&amp;nbsp; &lt;span style=&quot;color: #121212; text-align: start;&quot;&gt;&lt;span style=&quot;color: #dddddd;&quot;&gt;●&lt;/span&gt;) &lt;span style=&quot;color: #8cb3be;&quot;&gt;- 난 어차피 3급 이상만 식별되면 되니까^^&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; 아이콘 색상 또 바꿔 봄&lt;br /&gt;&amp;middot;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 한자의 검색이 반복될 때 변하는 규칙을 변경, &lt;span style=&quot;color: #8cb3be;&quot;&gt;(10회마다 한 단계씩 올라가는 것으로 변경, 총 6단계)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;middot;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 한 글자 검색 추가 + 괄호를 사용해서 훈과 음을 찾아 검색하거나 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(서울 경)&lt;/span&gt;, 훈만 검색할 수 있음 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(서울)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;746&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdepPo/dJMcafGfboC/SwLNd912oh1yoyTrLgNTG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdepPo/dJMcafGfboC/SwLNd912oh1yoyTrLgNTG1/img.png&quot; data-alt=&quot;당연히 쓸 때는 우측이 더 보기 편함 (코맨드+G)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdepPo/dJMcafGfboC/SwLNd912oh1yoyTrLgNTG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdepPo%2FdJMcafGfboC%2FSwLNd912oh1yoyTrLgNTG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1516&quot; height=&quot;746&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;746&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;당연히 쓸 때는 우측이 더 보기 편함 (코맨드+G)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.05&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;2026. 04.13 9:534 PM&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;middot;&lt;span&gt; 기본 모드를 Liquid Glass 모드로 하고, &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #121212; text-align: start;&quot;&gt;Command+G를 눌러서 기존 모드를 선택할 수 있게 함 &lt;span style=&quot;color: #8cb3be;&quot;&gt;(OS26 이하에서는 토글되지 않고 기존 모드로만 작동)&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;middot;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;방향키 작동 버그 수정&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #121212; text-align: start;&quot;&gt;&amp;middot;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 스크롤바 디테일 수정&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #121212; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래부터 토큰 제공량이 박했던 클로드가 최근에 더 가난해진 덕분에... 돈을 더 많이 뜯어감.&lt;br /&gt;Extra 사용량 구매 : 15불 가까이 썼네. ㅠㅠ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1338&quot; data-origin-height=&quot;614&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSluxC/dJMcaakAYAc/jChRXmHB5MghzjkhKxYacK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSluxC/dJMcaakAYAc/jChRXmHB5MghzjkhKxYacK/img.png&quot; data-alt=&quot;비싼 것 같다가도 하는 거 보면...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSluxC/dJMcaakAYAc/jChRXmHB5MghzjkhKxYacK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSluxC%2FdJMcaakAYAc%2FjChRXmHB5MghzjkhKxYacK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1338&quot; height=&quot;614&quot; data-origin-width=&quot;1338&quot; data-origin-height=&quot;614&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;비싼 것 같다가도 하는 거 보면...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IMG/COD</category>
      <category>코딩</category>
      <category>클로드</category>
      <author>ARTBRAIN</author>
      <guid isPermaLink="true">https://pnpt.tistory.com/205</guid>
      <comments>https://pnpt.tistory.com/205#entry205comment</comments>
      <pubDate>Fri, 10 Apr 2026 23:03:31 +0900</pubDate>
    </item>
    <item>
      <title>클로드는 문제를 재밌게 해결해주네</title>
      <link>https://pnpt.tistory.com/204</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;AI로 이미지를 열심히 만들다가 현타가 왔어.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만들어진 이미지는 예쁘지만 뭔가 애매하게 불편해. 심지어 약간 비위가 상하는 느낌이야. 이 &lt;b&gt;AI 멀미&lt;/b&gt;는 생각보다 심각했고, 나는 이 멀미를 해결하고 싶어서 20년만에 카메라도 샀어. 조금 정밀한, 제대로 된 이미지를 보면 조금 해소가 되지 않을까 싶었거든.&amp;nbsp;&lt;b&gt;AI 멀미&lt;/b&gt;는 카메라 덕에 좀 나았어. 하지만, 완전한 해결책은 아니었지. &lt;b&gt;AI는 업무에서는 어쨌든 계속 써야 하는 도구잖아. 완전히 멀어질 수도 없어서, 이것저것 공부하던 중에... 우리 회사에서 박람회에 참가하게 되었다는 뉴스를 들었어. &lt;/b&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;(음. 귀찮은데)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넓은 부스를 분양받아서 세 자회사가 나눠 써야 하는 상황이더라구. 딱히 총괄하는 헤드도 없어서 논의가 꽤 피상적으로 흘러갔어. AI 이미지만 만들던 내가, 뭐 도울 게 있을까 싶어서 클로드로 간단한 html을 만들어 봤는데... 클로드 코딩, 이거 꽤나 쉽고 재밌네?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;style&gt;
    *,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
    body{font-family:'Segoe UI',system-ui,sans-serif}
    #booth-container{position:relative;width:100%;height:800px;overflow:hidden;background:#0d0d0d;border-radius:8px}
    #booth-container canvas{position:absolute;inset:0}
    #hud{position:absolute;inset:0;pointer-events:none;padding:22px;z-index:10;
      display:flex;flex-direction:column;justify-content:space-between;align-items:center}
    #header{align-self:flex-start}
    #info-panel{visibility:hidden;width:0;height:0;padding:0;margin:0;overflow:hidden}
    #info-panel h1{display:none}
    .ctrl-table{display:none}
    #controls-hint{display:none}
    #hover-tag{position:absolute;left:0;top:0;z-index:10;background:rgba(10,10,0,.92);
      border:1px solid rgba(255,220,0,.55);border-radius:8px;padding:7px 13px;
      color:#ffe066;font-size:12px;font-weight:600;pointer-events:none;
      opacity:0;transition:opacity .1s;white-space:nowrap;
      box-shadow:0 2px 12px rgba(0,0,0,.5)}
    #hover-tag.on{opacity:1}
  &lt;/style&gt;
&lt;/div&gt;
&lt;div id=&quot;booth-container&quot;&gt;
&lt;div id=&quot;hud&quot;&gt;
&lt;div id=&quot;header&quot;&gt;
&lt;div id=&quot;info-panel&quot;&gt;
&lt;h1&gt; &amp;nbsp; 조작법&lt;/h1&gt;
&lt;table class=&quot;ctrl-table&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;key&quot;&gt;드래그&lt;/td&gt;
&lt;td class=&quot;val&quot;&gt;회전&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;key&quot;&gt;우클릭 드래그&lt;/td&gt;
&lt;td class=&quot;val&quot;&gt;이동&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;key&quot;&gt;스크롤&lt;/td&gt;
&lt;td class=&quot;val&quot;&gt;줌 인/아웃&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;key&quot;&gt;&amp;larr;&amp;uarr;&amp;rarr;&amp;darr;&lt;/td&gt;
&lt;td class=&quot;val&quot;&gt;키보드 회전&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;sep&quot;&gt;
&lt;td colspan=&quot;2&quot;&gt;인터랙션&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;key&quot;&gt;선분 클릭&lt;/td&gt;
&lt;td class=&quot;val&quot;&gt;격벽 순환 (없음&amp;rarr;1m&amp;rarr;2m&amp;rarr;4m)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;key&quot;&gt;셀 클릭&lt;/td&gt;
&lt;td class=&quot;val&quot;&gt;색상 순환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;key&quot;&gt;노드 드래그&lt;/td&gt;
&lt;td class=&quot;val&quot;&gt;위치 자유 이동&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;controls-hint&quot;&gt;  드래그: 회전 &amp;nbsp;|&amp;nbsp; 우클릭: 패닝 &amp;nbsp;|&amp;nbsp; 스크롤: 줌 &amp;nbsp;|&amp;nbsp; &amp;larr;&amp;uarr;&amp;rarr;&amp;darr;: 회전 &amp;nbsp;|&amp;nbsp; &lt;span style=&quot;color: rgba(255,255,100,.6);&quot;&gt;노란 선 클릭 &amp;rarr; 격벽 생성/제거&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;hover-tag&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;script&gt;
console.warn('Scripts &quot;build/three.js&quot; and &quot;build/three.min.js&quot; are deprecated with r150+, and will be removed with r160. Please use ES Modules or alternatives: https://threejs.org/docs/index.html#manual/en/introduction/Installation'),
/**
 * @license
 * Copyright 2010-2023 Three.js Authors
 * SPDX-License-Identifier: MIT
 */
function(t,e){&quot;object&quot;==typeof exports&amp;&amp;&quot;undefined&quot;!=typeof module?e(exports):&quot;function&quot;==typeof define&amp;&amp;define.amd?define([&quot;exports&quot;],e):e((t=&quot;undefined&quot;!=typeof globalThis?globalThis:t||self).THREE={})}(this,(function(t){&quot;use strict&quot;;const e=&quot;160&quot;,n=1,i=2,r=3,s=0,a=1,o=100,l=204,c=205,h=0,u=1,d=2,p=0,m=1,f=2,g=3,_=4,v=5,x=6,y=&quot;attached&quot;,M=&quot;detached&quot;,S=300,b=301,T=302,E=303,w=304,A=306,R=1e3,C=1001,L=1002,P=1003,I=1004,U=1005,D=1006,N=1007,O=1008,F=1009,B=1012,z=1013,G=1014,H=1015,V=1016,k=1017,W=1018,X=1020,j=1023,q=1026,Y=1027,Z=1029,J=1031,K=1033,$=33776,Q=33777,tt=33778,et=33779,nt=35840,it=35841,rt=35842,st=35843,at=36196,ot=37492,lt=37496,ct=37808,ht=37809,ut=37810,dt=37811,pt=37812,mt=37813,ft=37814,gt=37815,_t=37816,vt=37817,xt=37818,yt=37819,Mt=37820,St=37821,bt=36492,Tt=36494,Et=36495,wt=36284,At=36285,Rt=36286,Ct=2300,Lt=2301,Pt=2302,It=2400,Ut=2401,Dt=2402,Nt=2500,Ot=2501,Ft=3e3,Bt=3001,zt=&quot;&quot;,Gt=&quot;srgb&quot;,Ht=&quot;srgb-linear&quot;,Vt=&quot;display-p3&quot;,kt=&quot;display-p3-linear&quot;,Wt=&quot;linear&quot;,Xt=&quot;srgb&quot;,jt=&quot;rec709&quot;,qt=&quot;p3&quot;,Yt=7680,Zt=35044,Jt=&quot;300 es&quot;,Kt=1035,$t=2e3,Qt=2001;class te{addEventListener(t,e){void 0===this._listeners&amp;&amp;(this._listeners={});const n=this._listeners;void 0===n[t]&amp;&amp;(n[t]=[]),-1===n[t].indexOf(e)&amp;&amp;n[t].push(e)}hasEventListener(t,e){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[t]&amp;&amp;-1!==n[t].indexOf(e)}removeEventListener(t,e){if(void 0===this._listeners)return;const n=this._listeners[t];if(void 0!==n){const t=n.indexOf(e);-1!==t&amp;&amp;n.splice(t,1)}}dispatchEvent(t){if(void 0===this._listeners)return;const e=this._listeners[t.type];if(void 0!==e){t.target=this;const n=e.slice(0);for(let e=0,i=n.length;e&lt;i;e++)n[e].call(this,t);t.target=null}}}const ee=[&quot;00&quot;,&quot;01&quot;,&quot;02&quot;,&quot;03&quot;,&quot;04&quot;,&quot;05&quot;,&quot;06&quot;,&quot;07&quot;,&quot;08&quot;,&quot;09&quot;,&quot;0a&quot;,&quot;0b&quot;,&quot;0c&quot;,&quot;0d&quot;,&quot;0e&quot;,&quot;0f&quot;,&quot;10&quot;,&quot;11&quot;,&quot;12&quot;,&quot;13&quot;,&quot;14&quot;,&quot;15&quot;,&quot;16&quot;,&quot;17&quot;,&quot;18&quot;,&quot;19&quot;,&quot;1a&quot;,&quot;1b&quot;,&quot;1c&quot;,&quot;1d&quot;,&quot;1e&quot;,&quot;1f&quot;,&quot;20&quot;,&quot;21&quot;,&quot;22&quot;,&quot;23&quot;,&quot;24&quot;,&quot;25&quot;,&quot;26&quot;,&quot;27&quot;,&quot;28&quot;,&quot;29&quot;,&quot;2a&quot;,&quot;2b&quot;,&quot;2c&quot;,&quot;2d&quot;,&quot;2e&quot;,&quot;2f&quot;,&quot;30&quot;,&quot;31&quot;,&quot;32&quot;,&quot;33&quot;,&quot;34&quot;,&quot;35&quot;,&quot;36&quot;,&quot;37&quot;,&quot;38&quot;,&quot;39&quot;,&quot;3a&quot;,&quot;3b&quot;,&quot;3c&quot;,&quot;3d&quot;,&quot;3e&quot;,&quot;3f&quot;,&quot;40&quot;,&quot;41&quot;,&quot;42&quot;,&quot;43&quot;,&quot;44&quot;,&quot;45&quot;,&quot;46&quot;,&quot;47&quot;,&quot;48&quot;,&quot;49&quot;,&quot;4a&quot;,&quot;4b&quot;,&quot;4c&quot;,&quot;4d&quot;,&quot;4e&quot;,&quot;4f&quot;,&quot;50&quot;,&quot;51&quot;,&quot;52&quot;,&quot;53&quot;,&quot;54&quot;,&quot;55&quot;,&quot;56&quot;,&quot;57&quot;,&quot;58&quot;,&quot;59&quot;,&quot;5a&quot;,&quot;5b&quot;,&quot;5c&quot;,&quot;5d&quot;,&quot;5e&quot;,&quot;5f&quot;,&quot;60&quot;,&quot;61&quot;,&quot;62&quot;,&quot;63&quot;,&quot;64&quot;,&quot;65&quot;,&quot;66&quot;,&quot;67&quot;,&quot;68&quot;,&quot;69&quot;,&quot;6a&quot;,&quot;6b&quot;,&quot;6c&quot;,&quot;6d&quot;,&quot;6e&quot;,&quot;6f&quot;,&quot;70&quot;,&quot;71&quot;,&quot;72&quot;,&quot;73&quot;,&quot;74&quot;,&quot;75&quot;,&quot;76&quot;,&quot;77&quot;,&quot;78&quot;,&quot;79&quot;,&quot;7a&quot;,&quot;7b&quot;,&quot;7c&quot;,&quot;7d&quot;,&quot;7e&quot;,&quot;7f&quot;,&quot;80&quot;,&quot;81&quot;,&quot;82&quot;,&quot;83&quot;,&quot;84&quot;,&quot;85&quot;,&quot;86&quot;,&quot;87&quot;,&quot;88&quot;,&quot;89&quot;,&quot;8a&quot;,&quot;8b&quot;,&quot;8c&quot;,&quot;8d&quot;,&quot;8e&quot;,&quot;8f&quot;,&quot;90&quot;,&quot;91&quot;,&quot;92&quot;,&quot;93&quot;,&quot;94&quot;,&quot;95&quot;,&quot;96&quot;,&quot;97&quot;,&quot;98&quot;,&quot;99&quot;,&quot;9a&quot;,&quot;9b&quot;,&quot;9c&quot;,&quot;9d&quot;,&quot;9e&quot;,&quot;9f&quot;,&quot;a0&quot;,&quot;a1&quot;,&quot;a2&quot;,&quot;a3&quot;,&quot;a4&quot;,&quot;a5&quot;,&quot;a6&quot;,&quot;a7&quot;,&quot;a8&quot;,&quot;a9&quot;,&quot;aa&quot;,&quot;ab&quot;,&quot;ac&quot;,&quot;ad&quot;,&quot;ae&quot;,&quot;af&quot;,&quot;b0&quot;,&quot;b1&quot;,&quot;b2&quot;,&quot;b3&quot;,&quot;b4&quot;,&quot;b5&quot;,&quot;b6&quot;,&quot;b7&quot;,&quot;b8&quot;,&quot;b9&quot;,&quot;ba&quot;,&quot;bb&quot;,&quot;bc&quot;,&quot;bd&quot;,&quot;be&quot;,&quot;bf&quot;,&quot;c0&quot;,&quot;c1&quot;,&quot;c2&quot;,&quot;c3&quot;,&quot;c4&quot;,&quot;c5&quot;,&quot;c6&quot;,&quot;c7&quot;,&quot;c8&quot;,&quot;c9&quot;,&quot;ca&quot;,&quot;cb&quot;,&quot;cc&quot;,&quot;cd&quot;,&quot;ce&quot;,&quot;cf&quot;,&quot;d0&quot;,&quot;d1&quot;,&quot;d2&quot;,&quot;d3&quot;,&quot;d4&quot;,&quot;d5&quot;,&quot;d6&quot;,&quot;d7&quot;,&quot;d8&quot;,&quot;d9&quot;,&quot;da&quot;,&quot;db&quot;,&quot;dc&quot;,&quot;dd&quot;,&quot;de&quot;,&quot;df&quot;,&quot;e0&quot;,&quot;e1&quot;,&quot;e2&quot;,&quot;e3&quot;,&quot;e4&quot;,&quot;e5&quot;,&quot;e6&quot;,&quot;e7&quot;,&quot;e8&quot;,&quot;e9&quot;,&quot;ea&quot;,&quot;eb&quot;,&quot;ec&quot;,&quot;ed&quot;,&quot;ee&quot;,&quot;ef&quot;,&quot;f0&quot;,&quot;f1&quot;,&quot;f2&quot;,&quot;f3&quot;,&quot;f4&quot;,&quot;f5&quot;,&quot;f6&quot;,&quot;f7&quot;,&quot;f8&quot;,&quot;f9&quot;,&quot;fa&quot;,&quot;fb&quot;,&quot;fc&quot;,&quot;fd&quot;,&quot;fe&quot;,&quot;ff&quot;];let ne=1234567;const ie=Math.PI/180,re=180/Math.PI;function se(){const t=4294967295*Math.random()|0,e=4294967295*Math.random()|0,n=4294967295*Math.random()|0,i=4294967295*Math.random()|0;return(ee[255&amp;t]+ee[t&gt;&gt;8&amp;255]+ee[t&gt;&gt;16&amp;255]+ee[t&gt;&gt;24&amp;255]+&quot;-&quot;+ee[255&amp;e]+ee[e&gt;&gt;8&amp;255]+&quot;-&quot;+ee[e&gt;&gt;16&amp;15|64]+ee[e&gt;&gt;24&amp;255]+&quot;-&quot;+ee[63&amp;n|128]+ee[n&gt;&gt;8&amp;255]+&quot;-&quot;+ee[n&gt;&gt;16&amp;255]+ee[n&gt;&gt;24&amp;255]+ee[255&amp;i]+ee[i&gt;&gt;8&amp;255]+ee[i&gt;&gt;16&amp;255]+ee[i&gt;&gt;24&amp;255]).toLowerCase()}function ae(t,e,n){return Math.max(e,Math.min(n,t))}function oe(t,e){return(t%e+e)%e}function le(t,e,n){return(1-n)*t+n*e}function ce(t){return 0==(t&amp;t-1)&amp;&amp;0!==t}function he(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}function ue(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return t/4294967295;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int32Array:return Math.max(t/2147483647,-1);case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error(&quot;Invalid component type.&quot;)}}function de(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return Math.round(4294967295*t);case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int32Array:return Math.round(2147483647*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error(&quot;Invalid component type.&quot;)}}const pe={DEG2RAD:ie,RAD2DEG:re,generateUUID:se,clamp:ae,euclideanModulo:oe,mapLinear:function(t,e,n,i,r){return i+(t-e)*(r-i)/(n-e)},inverseLerp:function(t,e,n){return t!==e?(n-t)/(e-t):0},lerp:le,damp:function(t,e,n,i){return le(t,e,1-Math.exp(-n*i))},pingpong:function(t,e=1){return e-Math.abs(oe(t,2*e)-e)},smoothstep:function(t,e,n){return t&lt;=e?0:t&gt;=n?1:(t=(t-e)/(n-e))*t*(3-2*t)},smootherstep:function(t,e,n){return t&lt;=e?0:t&gt;=n?1:(t=(t-e)/(n-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){void 0!==t&amp;&amp;(ne=t);let e=ne+=1831565813;return e=Math.imul(e^e&gt;&gt;&gt;15,1|e),e^=e+Math.imul(e^e&gt;&gt;&gt;7,61|e),((e^e&gt;&gt;&gt;14)&gt;&gt;&gt;0)/4294967296},degToRad:function(t){return t*ie},radToDeg:function(t){return t*re},isPowerOfTwo:ce,ceilPowerOfTwo:function(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))},floorPowerOfTwo:he,setQuaternionFromProperEuler:function(t,e,n,i,r){const s=Math.cos,a=Math.sin,o=s(n/2),l=a(n/2),c=s((e+i)/2),h=a((e+i)/2),u=s((e-i)/2),d=a((e-i)/2),p=s((i-e)/2),m=a((i-e)/2);switch(r){case&quot;XYX&quot;:t.set(o*h,l*u,l*d,o*c);break;case&quot;YZY&quot;:t.set(l*d,o*h,l*u,o*c);break;case&quot;ZXZ&quot;:t.set(l*u,l*d,o*h,o*c);break;case&quot;XZX&quot;:t.set(o*h,l*m,l*p,o*c);break;case&quot;YXY&quot;:t.set(l*p,o*h,l*m,o*c);break;case&quot;ZYZ&quot;:t.set(l*m,l*p,o*h,o*c);break;default:console.warn(&quot;THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: &quot;+r)}},normalize:de,denormalize:ue};class me{constructor(t=0,e=0){me.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error(&quot;index is out of range: &quot;+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error(&quot;index is out of range: &quot;+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,n=this.y,i=t.elements;return this.x=i[0]*e+i[3]*n+i[6],this.y=i[1]*e+i[4]*n+i[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(ae(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this}equals(t){return t.x===this.x&amp;&amp;t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const n=Math.cos(e),i=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*n-s*i+t.x,this.y=r*i+s*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class fe{constructor(t,e,n,i,r,s,a,o,l){fe.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==t&amp;&amp;this.set(t,e,n,i,r,s,a,o,l)}set(t,e,n,i,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=i,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=n,c[7]=s,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],m=i[0],f=i[3],g=i[6],_=i[1],v=i[4],x=i[7],y=i[2],M=i[5],S=i[8];return r[0]=s*m+a*_+o*y,r[3]=s*f+a*v+o*M,r[6]=s*g+a*x+o*S,r[1]=l*m+c*_+h*y,r[4]=l*f+c*v+h*M,r[7]=l*g+c*x+h*S,r[2]=u*m+d*_+p*y,r[5]=u*f+d*v+p*M,r[8]=u*g+d*x+p*S,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8];return e*s*c-e*a*l-n*r*c+n*a*o+i*r*l-i*s*o}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=c*s-a*l,u=a*o-c*r,d=l*r-s*o,p=e*h+n*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=h*m,t[1]=(i*l-c*n)*m,t[2]=(a*n-i*s)*m,t[3]=u*m,t[4]=(c*e-i*o)*m,t[5]=(i*r-a*e)*m,t[6]=d*m,t[7]=(n*o-l*e)*m,t[8]=(s*e-n*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,n,i,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*s+l*a)+s+t,-i*l,i*o,-i*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){return this.premultiply(ge.makeScale(t,e)),this}rotate(t){return this.premultiply(ge.makeRotation(-t)),this}translate(t,e){return this.premultiply(ge.makeTranslation(t,e)),this}makeTranslation(t,e){return t.isVector2?this.set(1,0,t.x,0,1,t.y,0,0,1):this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,n,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t&lt;9;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n&lt;9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const ge=new fe;function _e(t){for(let e=t.length-1;e&gt;=0;--e)if(t[e]&gt;=65535)return!0;return!1}const ve={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function xe(t,e){return new ve[t](e)}function ye(t){return document.createElementNS(&quot;http://www.w3.org/1999/xhtml&quot;,t)}function Me(){const t=ye(&quot;canvas&quot;);return t.style.display=&quot;block&quot;,t}const Se={};function be(t){t in Se||(Se[t]=!0,console.warn(t))}const Te=(new fe).set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),Ee=(new fe).set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),we={[Ht]:{transfer:Wt,primaries:jt,toReference:t=&gt;t,fromReference:t=&gt;t},[Gt]:{transfer:Xt,primaries:jt,toReference:t=&gt;t.convertSRGBToLinear(),fromReference:t=&gt;t.convertLinearToSRGB()},[kt]:{transfer:Wt,primaries:qt,toReference:t=&gt;t.applyMatrix3(Ee),fromReference:t=&gt;t.applyMatrix3(Te)},[Vt]:{transfer:Xt,primaries:qt,toReference:t=&gt;t.convertSRGBToLinear().applyMatrix3(Ee),fromReference:t=&gt;t.applyMatrix3(Te).convertLinearToSRGB()}},Ae=new Set([Ht,kt]),Re={enabled:!0,_workingColorSpace:Ht,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(t){if(!Ae.has(t))throw new Error(`Unsupported working color space, &quot;${t}&quot;.`);this._workingColorSpace=t},convert:function(t,e,n){if(!1===this.enabled||e===n||!e||!n)return t;const i=we[e].toReference;return(0,we[n].fromReference)(i(t))},fromWorkingColorSpace:function(t,e){return this.convert(t,this._workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this._workingColorSpace)},getPrimaries:function(t){return we[t].primaries},getTransfer:function(t){return t===zt?Wt:we[t].transfer}};function Ce(t){return t&lt;.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function Le(t){return t&lt;.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}let Pe;class Ie{static getDataURL(t){if(/^data:/i.test(t.src))return t.src;if(&quot;undefined&quot;==typeof HTMLCanvasElement)return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{void 0===Pe&amp;&amp;(Pe=ye(&quot;canvas&quot;)),Pe.width=t.width,Pe.height=t.height;const n=Pe.getContext(&quot;2d&quot;);t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=Pe}return e.width&gt;2048||e.height&gt;2048?(console.warn(&quot;THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons&quot;,t),e.toDataURL(&quot;image/jpeg&quot;,.6)):e.toDataURL(&quot;image/png&quot;)}static sRGBToLinear(t){if(&quot;undefined&quot;!=typeof HTMLImageElement&amp;&amp;t instanceof HTMLImageElement||&quot;undefined&quot;!=typeof HTMLCanvasElement&amp;&amp;t instanceof HTMLCanvasElement||&quot;undefined&quot;!=typeof ImageBitmap&amp;&amp;t instanceof ImageBitmap){const e=ye(&quot;canvas&quot;);e.width=t.width,e.height=t.height;const n=e.getContext(&quot;2d&quot;);n.drawImage(t,0,0,t.width,t.height);const i=n.getImageData(0,0,t.width,t.height),r=i.data;for(let t=0;t&lt;r.length;t++)r[t]=255*Ce(r[t]/255);return n.putImageData(i,0,0),e}if(t.data){const e=t.data.slice(0);for(let t=0;t&lt;e.length;t++)e instanceof Uint8Array||e instanceof Uint8ClampedArray?e[t]=Math.floor(255*Ce(e[t]/255)):e[t]=Ce(e[t]);return{data:e,width:t.width,height:t.height}}return console.warn(&quot;THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.&quot;),t}}let Ue=0;class De{constructor(t=null){this.isSource=!0,Object.defineProperty(this,&quot;id&quot;,{value:Ue++}),this.uuid=se(),this.data=t,this.version=0}set needsUpdate(t){!0===t&amp;&amp;this.version++}toJSON(t){const e=void 0===t||&quot;string&quot;==typeof t;if(!e&amp;&amp;void 0!==t.images[this.uuid])return t.images[this.uuid];const n={uuid:this.uuid,url:&quot;&quot;},i=this.data;if(null!==i){let t;if(Array.isArray(i)){t=[];for(let e=0,n=i.length;e&lt;n;e++)i[e].isDataTexture?t.push(Ne(i[e].image)):t.push(Ne(i[e]))}else t=Ne(i);n.url=t}return e||(t.images[this.uuid]=n),n}}function Ne(t){return&quot;undefined&quot;!=typeof HTMLImageElement&amp;&amp;t instanceof HTMLImageElement||&quot;undefined&quot;!=typeof HTMLCanvasElement&amp;&amp;t instanceof HTMLCanvasElement||&quot;undefined&quot;!=typeof ImageBitmap&amp;&amp;t instanceof ImageBitmap?Ie.getDataURL(t):t.data?{data:Array.from(t.data),width:t.width,height:t.height,type:t.data.constructor.name}:(console.warn(&quot;THREE.Texture: Unable to serialize Texture.&quot;),{})}let Oe=0;class Fe extends te{constructor(t=Fe.DEFAULT_IMAGE,e=Fe.DEFAULT_MAPPING,n=1001,i=1001,r=1006,s=1008,a=1023,o=1009,l=Fe.DEFAULT_ANISOTROPY,c=&quot;&quot;){super(),this.isTexture=!0,Object.defineProperty(this,&quot;id&quot;,{value:Oe++}),this.uuid=se(),this.name=&quot;&quot;,this.source=new De(t),this.mipmaps=[],this.mapping=e,this.channel=0,this.wrapS=n,this.wrapT=i,this.magFilter=r,this.minFilter=s,this.anisotropy=l,this.format=a,this.internalFormat=null,this.type=o,this.offset=new me(0,0),this.repeat=new me(1,1),this.center=new me(0,0),this.rotation=0,this.matrixAutoUpdate=!0,this.matrix=new fe,this.generateMipmaps=!0,this.premultiplyAlpha=!1,this.flipY=!0,this.unpackAlignment=4,&quot;string&quot;==typeof c?this.colorSpace=c:(be(&quot;THREE.Texture: Property .encoding has been replaced by .colorSpace.&quot;),this.colorSpace=c===Bt?Gt:zt),this.userData={},this.version=0,this.onUpdate=null,this.isRenderTargetTexture=!1,this.needsPMREMUpdate=!1}get image(){return this.source.data}set image(t=null){this.source.data=t}updateMatrix(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y)}clone(){return(new this.constructor).copy(this)}copy(t){return this.name=t.name,this.source=t.source,this.mipmaps=t.mipmaps.slice(0),this.mapping=t.mapping,this.channel=t.channel,this.wrapS=t.wrapS,this.wrapT=t.wrapT,this.magFilter=t.magFilter,this.minFilter=t.minFilter,this.anisotropy=t.anisotropy,this.format=t.format,this.internalFormat=t.internalFormat,this.type=t.type,this.offset.copy(t.offset),this.repeat.copy(t.repeat),this.center.copy(t.center),this.rotation=t.rotation,this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrix.copy(t.matrix),this.generateMipmaps=t.generateMipmaps,this.premultiplyAlpha=t.premultiplyAlpha,this.flipY=t.flipY,this.unpackAlignment=t.unpackAlignment,this.colorSpace=t.colorSpace,this.userData=JSON.parse(JSON.stringify(t.userData)),this.needsUpdate=!0,this}toJSON(t){const e=void 0===t||&quot;string&quot;==typeof t;if(!e&amp;&amp;void 0!==t.textures[this.uuid])return t.textures[this.uuid];const n={metadata:{version:4.6,type:&quot;Texture&quot;,generator:&quot;Texture.toJSON&quot;},uuid:this.uuid,name:this.name,image:this.source.toJSON(t).uuid,mapping:this.mapping,channel:this.channel,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],center:[this.center.x,this.center.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],format:this.format,internalFormat:this.internalFormat,type:this.type,colorSpace:this.colorSpace,minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY,generateMipmaps:this.generateMipmaps,premultiplyAlpha:this.premultiplyAlpha,unpackAlignment:this.unpackAlignment};return Object.keys(this.userData).length&gt;0&amp;&amp;(n.userData=this.userData),e||(t.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:&quot;dispose&quot;})}transformUv(t){if(this.mapping!==S)return t;if(t.applyMatrix3(this.matrix),t.x&lt;0||t.x&gt;1)switch(this.wrapS){case R:t.x=t.x-Math.floor(t.x);break;case C:t.x=t.x&lt;0?0:1;break;case L:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y&lt;0||t.y&gt;1)switch(this.wrapT){case R:t.y=t.y-Math.floor(t.y);break;case C:t.y=t.y&lt;0?0:1;break;case L:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&amp;&amp;(t.y=1-t.y),t}set needsUpdate(t){!0===t&amp;&amp;(this.version++,this.source.needsUpdate=!0)}get encoding(){return be(&quot;THREE.Texture: Property .encoding has been replaced by .colorSpace.&quot;),this.colorSpace===Gt?Bt:Ft}set encoding(t){be(&quot;THREE.Texture: Property .encoding has been replaced by .colorSpace.&quot;),this.colorSpace=t===Bt?Gt:zt}}Fe.DEFAULT_IMAGE=null,Fe.DEFAULT_MAPPING=S,Fe.DEFAULT_ANISOTROPY=1;class Be{constructor(t=0,e=0,n=0,i=1){Be.prototype.isVector4=!0,this.x=t,this.y=e,this.z=n,this.w=i}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,n,i){return this.x=t,this.y=e,this.z=n,this.w=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error(&quot;index is out of range: &quot;+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error(&quot;index is out of range: &quot;+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*n+s[8]*i+s[12]*r,this.y=s[1]*e+s[5]*n+s[9]*i+s[13]*r,this.z=s[2]*e+s[6]*n+s[10]*i+s[14]*r,this.w=s[3]*e+s[7]*n+s[11]*i+s[15]*r,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e&lt;1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,n,i,r;const s=.01,a=.1,o=t.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],m=o[2],f=o[6],g=o[10];if(Math.abs(c-u)&lt;s&amp;&amp;Math.abs(h-m)&lt;s&amp;&amp;Math.abs(p-f)&lt;s){if(Math.abs(c+u)&lt;a&amp;&amp;Math.abs(h+m)&lt;a&amp;&amp;Math.abs(p+f)&lt;a&amp;&amp;Math.abs(l+d+g-3)&lt;a)return this.set(1,0,0,0),this;e=Math.PI;const t=(l+1)/2,o=(d+1)/2,_=(g+1)/2,v=(c+u)/4,x=(h+m)/4,y=(p+f)/4;return t&gt;o&amp;&amp;t&gt;_?t&lt;s?(n=0,i=.707106781,r=.707106781):(n=Math.sqrt(t),i=v/n,r=x/n):o&gt;_?o&lt;s?(n=.707106781,i=0,r=.707106781):(i=Math.sqrt(o),n=v/i,r=y/i):_&lt;s?(n=.707106781,i=.707106781,r=0):(r=Math.sqrt(_),n=x/r,i=y/r),this.set(n,i,r,e),this}let _=Math.sqrt((f-p)*(f-p)+(h-m)*(h-m)+(u-c)*(u-c));return Math.abs(_)&lt;.001&amp;&amp;(_=1),this.x=(f-p)/_,this.y=(h-m)/_,this.z=(u-c)/_,this.w=Math.acos((l+d+g-1)/2),this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this.w=Math.min(this.w,t.w),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this.w=Math.max(this.w,t.w),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this.w=Math.max(t.w,Math.min(e.w,this.w)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this.w=Math.max(t,Math.min(e,this.w)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this.w=Math.trunc(this.w),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z+this.w*t.w}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this.w+=(t.w-this.w)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this.w=t.w+(e.w-t.w)*n,this}equals(t){return t.x===this.x&amp;&amp;t.y===this.y&amp;&amp;t.z===this.z&amp;&amp;t.w===this.w}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this.w=t[e+3],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t[e+3]=this.w,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this.w=t.getW(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this.w=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z,yield this.w}}class ze extends te{constructor(t=1,e=1,n={}){super(),this.isRenderTarget=!0,this.width=t,this.height=e,this.depth=1,this.scissor=new Be(0,0,t,e),this.scissorTest=!1,this.viewport=new Be(0,0,t,e);const i={width:t,height:e,depth:1};void 0!==n.encoding&amp;&amp;(be(&quot;THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace.&quot;),n.colorSpace=n.encoding===Bt?Gt:zt),n=Object.assign({generateMipmaps:!1,internalFormat:null,minFilter:D,depthBuffer:!0,stencilBuffer:!1,depthTexture:null,samples:0},n),this.texture=new Fe(i,n.mapping,n.wrapS,n.wrapT,n.magFilter,n.minFilter,n.format,n.type,n.anisotropy,n.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.flipY=!1,this.texture.generateMipmaps=n.generateMipmaps,this.texture.internalFormat=n.internalFormat,this.depthBuffer=n.depthBuffer,this.stencilBuffer=n.stencilBuffer,this.depthTexture=n.depthTexture,this.samples=n.samples}setSize(t,e,n=1){this.width===t&amp;&amp;this.height===e&amp;&amp;this.depth===n||(this.width=t,this.height=e,this.depth=n,this.texture.image.width=t,this.texture.image.height=e,this.texture.image.depth=n,this.dispose()),this.viewport.set(0,0,t,e),this.scissor.set(0,0,t,e)}clone(){return(new this.constructor).copy(this)}copy(t){this.width=t.width,this.height=t.height,this.depth=t.depth,this.scissor.copy(t.scissor),this.scissorTest=t.scissorTest,this.viewport.copy(t.viewport),this.texture=t.texture.clone(),this.texture.isRenderTargetTexture=!0;const e=Object.assign({},t.texture.image);return this.texture.source=new De(e),this.depthBuffer=t.depthBuffer,this.stencilBuffer=t.stencilBuffer,null!==t.depthTexture&amp;&amp;(this.depthTexture=t.depthTexture.clone()),this.samples=t.samples,this}dispose(){this.dispatchEvent({type:&quot;dispose&quot;})}}class Ge extends ze{constructor(t=1,e=1,n={}){super(t,e,n),this.isWebGLRenderTarget=!0}}class He extends Fe{constructor(t=null,e=1,n=1,i=1){super(null),this.isDataArrayTexture=!0,this.image={data:t,width:e,height:n,depth:i},this.magFilter=P,this.minFilter=P,this.wrapR=C,this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}}class Ve extends Fe{constructor(t=null,e=1,n=1,i=1){super(null),this.isData3DTexture=!0,this.image={data:t,width:e,height:n,depth:i},this.magFilter=P,this.minFilter=P,this.wrapR=C,this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}}class ke{constructor(t=0,e=0,n=0,i=1){this.isQuaternion=!0,this._x=t,this._y=e,this._z=n,this._w=i}static slerpFlat(t,e,n,i,r,s,a){let o=n[i+0],l=n[i+1],c=n[i+2],h=n[i+3];const u=r[s+0],d=r[s+1],p=r[s+2],m=r[s+3];if(0===a)return t[e+0]=o,t[e+1]=l,t[e+2]=c,void(t[e+3]=h);if(1===a)return t[e+0]=u,t[e+1]=d,t[e+2]=p,void(t[e+3]=m);if(h!==m||o!==u||l!==d||c!==p){let t=1-a;const e=o*u+l*d+c*p+h*m,n=e&gt;=0?1:-1,i=1-e*e;if(i&gt;Number.EPSILON){const r=Math.sqrt(i),s=Math.atan2(r,e*n);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*n;if(o=o*t+u*r,l=l*t+d*r,c=c*t+p*r,h=h*t+m*r,t===1-a){const t=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=t,l*=t,c*=t,h*=t}}t[e]=o,t[e+1]=l,t[e+2]=c,t[e+3]=h}static multiplyQuaternionsFlat(t,e,n,i,r,s){const a=n[i],o=n[i+1],l=n[i+2],c=n[i+3],h=r[s],u=r[s+1],d=r[s+2],p=r[s+3];return t[e]=a*p+c*h+o*d-l*u,t[e+1]=o*p+c*u+l*h-a*d,t[e+2]=l*p+c*d+a*u-o*h,t[e+3]=c*p-a*h-o*u-l*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,n,i){return this._x=t,this._y=e,this._z=n,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e=!0){const n=t._x,i=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(n/2),c=a(i/2),h=a(r/2),u=o(n/2),d=o(i/2),p=o(r/2);switch(s){case&quot;XYZ&quot;:this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case&quot;YXZ&quot;:this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case&quot;ZXY&quot;:this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case&quot;ZYX&quot;:this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case&quot;YZX&quot;:this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case&quot;XZY&quot;:this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn(&quot;THREE.Quaternion: .setFromEuler() encountered an unknown order: &quot;+s)}return!0===e&amp;&amp;this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,i=Math.sin(n);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],i=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=n+a+h;if(u&gt;0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(c-o)*t,this._y=(r-l)*t,this._z=(s-i)*t}else if(n&gt;a&amp;&amp;n&gt;h){const t=2*Math.sqrt(1+n-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(i+s)/t,this._z=(r+l)/t}else if(a&gt;h){const t=2*Math.sqrt(1+a-n-h);this._w=(r-l)/t,this._x=(i+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-n-a);this._w=(s-i)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return n&lt;Number.EPSILON?(n=0,Math.abs(t.x)&gt;Math.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(ae(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(0===n)return this;const i=Math.min(1,e/n);return this.slerp(t,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const n=t._x,i=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=n*c+s*a+i*l-r*o,this._y=i*c+s*o+r*a-n*l,this._z=r*c+s*l+n*o-i*a,this._w=s*c-n*a-i*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const n=this._x,i=this._y,r=this._z,s=this._w;let a=s*t._w+n*t._x+i*t._y+r*t._z;if(a&lt;0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,a=-a):this.copy(t),a&gt;=1)return this._w=s,this._x=n,this._y=i,this._z=r,this;const o=1-a*a;if(o&lt;=Number.EPSILON){const t=1-e;return this._w=t*s+e*this._w,this._x=t*n+e*this._x,this._y=t*i+e*this._y,this._z=t*r+e*this._z,this.normalize(),this}const l=Math.sqrt(o),c=Math.atan2(l,a),h=Math.sin((1-e)*c)/l,u=Math.sin(e*c)/l;return this._w=s*h+this._w*u,this._x=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,n){return this.copy(t).slerp(e,n)}random(){const t=Math.random(),e=Math.sqrt(1-t),n=Math.sqrt(t),i=2*Math.PI*Math.random(),r=2*Math.PI*Math.random();return this.set(e*Math.cos(i),n*Math.sin(r),n*Math.cos(r),e*Math.sin(i))}equals(t){return t._x===this._x&amp;&amp;t._y===this._y&amp;&amp;t._z===this._z&amp;&amp;t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class We{constructor(t=0,e=0,n=0){We.prototype.isVector3=!0,this.x=t,this.y=e,this.z=n}set(t,e,n){return void 0===n&amp;&amp;(n=this.z),this.x=t,this.y=e,this.z=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error(&quot;index is out of range: &quot;+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error(&quot;index is out of range: &quot;+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(je.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(je.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*i,this.y=r[1]*e+r[4]*n+r[7]*i,this.z=r[2]*e+r[5]*n+r[8]*i,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=t.elements,s=1/(r[3]*e+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*i+r[12])*s,this.y=(r[1]*e+r[5]*n+r[9]*i+r[13])*s,this.z=(r[2]*e+r[6]*n+r[10]*i+r[14])*s,this}applyQuaternion(t){const e=this.x,n=this.y,i=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=2*(s*i-a*n),c=2*(a*e-r*i),h=2*(r*n-s*e);return this.x=e+o*l+s*h-a*c,this.y=n+o*c+a*l-r*h,this.z=i+o*h+r*c-s*l,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*i,this.y=r[1]*e+r[5]*n+r[9]*i,this.z=r[2]*e+r[6]*n+r[10]*i,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,i=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=i*o-r*a,this.y=r*s-n*o,this.z=n*a-i*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return Xe.copy(this).projectOnVector(t),this.sub(Xe)}reflect(t){return this.sub(Xe.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(ae(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,i=this.z-t.z;return e*e+n*n+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,n){const i=Math.sin(e)*t;return this.x=i*Math.sin(n),this.y=Math.cos(e)*t,this.z=i*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=i,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,this}equals(t){return t.x===this.x&amp;&amp;t.y===this.y&amp;&amp;t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=2*(Math.random()-.5),e=Math.random()*Math.PI*2,n=Math.sqrt(1-t**2);return this.x=n*Math.cos(e),this.y=n*Math.sin(e),this.z=t,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Xe=new We,je=new ke;class qe{constructor(t=new We(1/0,1/0,1/0),e=new We(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){this.makeEmpty();for(let e=0,n=t.length;e&lt;n;e+=3)this.expandByPoint(Ze.fromArray(t,e));return this}setFromBufferAttribute(t){this.makeEmpty();for(let e=0,n=t.count;e&lt;n;e++)this.expandByPoint(Ze.fromBufferAttribute(t,e));return this}setFromPoints(t){this.makeEmpty();for(let e=0,n=t.length;e&lt;n;e++)this.expandByPoint(t[e]);return this}setFromCenterAndSize(t,e){const n=Ze.copy(e).multiplyScalar(.5);return this.min.copy(t).sub(n),this.max.copy(t).add(n),this}setFromObject(t,e=!1){return this.makeEmpty(),this.expandByObject(t,e)}clone(){return(new this.constructor).copy(this)}copy(t){return this.min.copy(t.min),this.max.copy(t.max),this}makeEmpty(){return this.min.x=this.min.y=this.min.z=1/0,this.max.x=this.max.y=this.max.z=-1/0,this}isEmpty(){return this.max.x&lt;this.min.x||this.max.y&lt;this.min.y||this.max.z&lt;this.min.z}getCenter(t){return this.isEmpty()?t.set(0,0,0):t.addVectors(this.min,this.max).multiplyScalar(.5)}getSize(t){return this.isEmpty()?t.set(0,0,0):t.subVectors(this.max,this.min)}expandByPoint(t){return this.min.min(t),this.max.max(t),this}expandByVector(t){return this.min.sub(t),this.max.add(t),this}expandByScalar(t){return this.min.addScalar(-t),this.max.addScalar(t),this}expandByObject(t,e=!1){t.updateWorldMatrix(!1,!1);const n=t.geometry;if(void 0!==n){const i=n.getAttribute(&quot;position&quot;);if(!0===e&amp;&amp;void 0!==i&amp;&amp;!0!==t.isInstancedMesh)for(let e=0,n=i.count;e&lt;n;e++)!0===t.isMesh?t.getVertexPosition(e,Ze):Ze.fromBufferAttribute(i,e),Ze.applyMatrix4(t.matrixWorld),this.expandByPoint(Ze);else void 0!==t.boundingBox?(null===t.boundingBox&amp;&amp;t.computeBoundingBox(),Je.copy(t.boundingBox)):(null===n.boundingBox&amp;&amp;n.computeBoundingBox(),Je.copy(n.boundingBox)),Je.applyMatrix4(t.matrixWorld),this.union(Je)}const i=t.children;for(let t=0,n=i.length;t&lt;n;t++)this.expandByObject(i[t],e);return this}containsPoint(t){return!(t.x&lt;this.min.x||t.x&gt;this.max.x||t.y&lt;this.min.y||t.y&gt;this.max.y||t.z&lt;this.min.z||t.z&gt;this.max.z)}containsBox(t){return this.min.x&lt;=t.min.x&amp;&amp;t.max.x&lt;=this.max.x&amp;&amp;this.min.y&lt;=t.min.y&amp;&amp;t.max.y&lt;=this.max.y&amp;&amp;this.min.z&lt;=t.min.z&amp;&amp;t.max.z&lt;=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return!(t.max.x&lt;this.min.x||t.min.x&gt;this.max.x||t.max.y&lt;this.min.y||t.min.y&gt;this.max.y||t.max.z&lt;this.min.z||t.min.z&gt;this.max.z)}intersectsSphere(t){return this.clampPoint(t.center,Ze),Ze.distanceToSquared(t.center)&lt;=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x&gt;0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y&gt;0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z&gt;0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e&lt;=-t.constant&amp;&amp;n&gt;=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(rn),sn.subVectors(this.max,rn),Ke.subVectors(t.a,rn),$e.subVectors(t.b,rn),Qe.subVectors(t.c,rn),tn.subVectors($e,Ke),en.subVectors(Qe,$e),nn.subVectors(Ke,Qe);let e=[0,-tn.z,tn.y,0,-en.z,en.y,0,-nn.z,nn.y,tn.z,0,-tn.x,en.z,0,-en.x,nn.z,0,-nn.x,-tn.y,tn.x,0,-en.y,en.x,0,-nn.y,nn.x,0];return!!ln(e,Ke,$e,Qe,sn)&amp;&amp;(e=[1,0,0,0,1,0,0,0,1],!!ln(e,Ke,$e,Qe,sn)&amp;&amp;(an.crossVectors(tn,en),e=[an.x,an.y,an.z],ln(e,Ke,$e,Qe,sn)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Ze).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=.5*this.getSize(Ze).length()),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&amp;&amp;this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(Ye[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),Ye[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),Ye[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),Ye[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),Ye[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),Ye[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),Ye[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),Ye[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(Ye)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&amp;&amp;t.max.equals(this.max)}}const Ye=[new We,new We,new We,new We,new We,new We,new We,new We],Ze=new We,Je=new qe,Ke=new We,$e=new We,Qe=new We,tn=new We,en=new We,nn=new We,rn=new We,sn=new We,an=new We,on=new We;function ln(t,e,n,i,r){for(let s=0,a=t.length-3;s&lt;=a;s+=3){on.fromArray(t,s);const a=r.x*Math.abs(on.x)+r.y*Math.abs(on.y)+r.z*Math.abs(on.z),o=e.dot(on),l=n.dot(on),c=i.dot(on);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))&gt;a)return!1}return!0}const cn=new qe,hn=new We,un=new We;class dn{constructor(t=new We,e=-1){this.isSphere=!0,this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;void 0!==e?n.copy(e):cn.setFromPoints(t).getCenter(n);let i=0;for(let e=0,r=t.length;e&lt;r;e++)i=Math.max(i,n.distanceToSquared(t[e]));return this.radius=Math.sqrt(i),this}copy(t){return this.center.copy(t.center),this.radius=t.radius,this}isEmpty(){return this.radius&lt;0}makeEmpty(){return this.center.set(0,0,0),this.radius=-1,this}containsPoint(t){return t.distanceToSquared(this.center)&lt;=this.radius*this.radius}distanceToPoint(t){return t.distanceTo(this.center)-this.radius}intersectsSphere(t){const e=this.radius+t.radius;return t.center.distanceToSquared(this.center)&lt;=e*e}intersectsBox(t){return t.intersectsSphere(this)}intersectsPlane(t){return Math.abs(t.distanceToPoint(this.center))&lt;=this.radius}clampPoint(t,e){const n=this.center.distanceToSquared(t);return e.copy(t),n&gt;this.radius*this.radius&amp;&amp;(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;hn.subVectors(t,this.center);const e=hn.lengthSq();if(e&gt;this.radius*this.radius){const t=Math.sqrt(e),n=.5*(t-this.radius);this.center.addScaledVector(hn,n/t),this.radius+=n}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(!0===this.center.equals(t.center)?this.radius=Math.max(this.radius,t.radius):(un.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(hn.copy(t.center).add(un)),this.expandByPoint(hn.copy(t.center).sub(un))),this)}equals(t){return t.center.equals(this.center)&amp;&amp;t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const pn=new We,mn=new We,fn=new We,gn=new We,_n=new We,vn=new We,xn=new We;class yn{constructor(t=new We,e=new We(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,pn)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n&lt;0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=pn.subVectors(t,this.origin).dot(this.direction);return e&lt;0?this.origin.distanceToSquared(t):(pn.copy(this.origin).addScaledVector(this.direction,e),pn.distanceToSquared(t))}distanceSqToSegment(t,e,n,i){mn.copy(t).add(e).multiplyScalar(.5),fn.copy(e).sub(t).normalize(),gn.copy(this.origin).sub(mn);const r=.5*t.distanceTo(e),s=-this.direction.dot(fn),a=gn.dot(this.direction),o=-gn.dot(fn),l=gn.lengthSq(),c=Math.abs(1-s*s);let h,u,d,p;if(c&gt;0)if(h=s*o-a,u=s*a-o,p=r*c,h&gt;=0)if(u&gt;=-p)if(u&lt;=p){const t=1/c;h*=t,u*=t,d=h*(h+s*u+2*a)+u*(s*h+u+2*o)+l}else u=r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u&lt;=-p?(h=Math.max(0,-(-s*r+a)),u=h&gt;0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u&lt;=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(s*r+a)),u=h&gt;0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=s&gt;0?-r:r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;return n&amp;&amp;n.copy(this.origin).addScaledVector(this.direction,h),i&amp;&amp;i.copy(mn).addScaledVector(fn,u),d}intersectSphere(t,e){pn.subVectors(t.center,this.origin);const n=pn.dot(this.direction),i=pn.dot(pn)-n*n,r=t.radius*t.radius;if(i&gt;r)return null;const s=Math.sqrt(r-i),a=n-s,o=n+s;return o&lt;0?null:a&lt;0?this.at(o,e):this.at(a,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)&lt;=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const n=-(this.origin.dot(t.normal)+t.constant)/e;return n&gt;=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return null===n?null:this.at(n,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e&lt;0}intersectBox(t,e){let n,i,r,s,a,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l&gt;=0?(n=(t.min.x-u.x)*l,i=(t.max.x-u.x)*l):(n=(t.max.x-u.x)*l,i=(t.min.x-u.x)*l),c&gt;=0?(r=(t.min.y-u.y)*c,s=(t.max.y-u.y)*c):(r=(t.max.y-u.y)*c,s=(t.min.y-u.y)*c),n&gt;s||r&gt;i?null:((r&gt;n||isNaN(n))&amp;&amp;(n=r),(s&lt;i||isNaN(i))&amp;&amp;(i=s),h&gt;=0?(a=(t.min.z-u.z)*h,o=(t.max.z-u.z)*h):(a=(t.max.z-u.z)*h,o=(t.min.z-u.z)*h),n&gt;o||a&gt;i?null:((a&gt;n||n!=n)&amp;&amp;(n=a),(o&lt;i||i!=i)&amp;&amp;(i=o),i&lt;0?null:this.at(n&gt;=0?n:i,e)))}intersectsBox(t){return null!==this.intersectBox(t,pn)}intersectTriangle(t,e,n,i,r){_n.subVectors(e,t),vn.subVectors(n,t),xn.crossVectors(_n,vn);let s,a=this.direction.dot(xn);if(a&gt;0){if(i)return null;s=1}else{if(!(a&lt;0))return null;s=-1,a=-a}gn.subVectors(this.origin,t);const o=s*this.direction.dot(vn.crossVectors(gn,vn));if(o&lt;0)return null;const l=s*this.direction.dot(_n.cross(gn));if(l&lt;0)return null;if(o+l&gt;a)return null;const c=-s*gn.dot(xn);return c&lt;0?null:this.at(c/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&amp;&amp;t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class Mn{constructor(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){Mn.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==t&amp;&amp;this.set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f)}set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){const g=this.elements;return g[0]=t,g[4]=e,g[8]=n,g[12]=i,g[1]=r,g[5]=s,g[9]=a,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=m,g[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new Mn).fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,i=1/Sn.setFromMatrixColumn(t,0).length(),r=1/Sn.setFromMatrixColumn(t,1).length(),s=1/Sn.setFromMatrixColumn(t,2).length();return e[0]=n[0]*i,e[1]=n[1]*i,e[2]=n[2]*i,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*s,e[9]=n[9]*s,e[10]=n[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,n=t.x,i=t.y,r=t.z,s=Math.cos(n),a=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if(&quot;XYZ&quot;===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=n+i*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=i+n*l,e[10]=s*o}else if(&quot;YXZ&quot;===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t+r*a,e[4]=i*a-n,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=n*a-i,e[6]=r+t*a,e[10]=s*o}else if(&quot;ZXY&quot;===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=i+n*a,e[1]=n+i*a,e[5]=s*c,e[9]=r-t*a,e[2]=-s*l,e[6]=a,e[10]=s*o}else if(&quot;ZYX&quot;===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=i*l-n,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=n*l-i,e[2]=-l,e[6]=a*o,e[10]=s*o}else if(&quot;YZX&quot;===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=i*h+n,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=n*h+i,e[10]=t-r*h}else if(&quot;XZY&quot;===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=-h,e[8]=l*c,e[1]=t*h+r,e[5]=s*c,e[9]=n*h-i,e[2]=i*h-n,e[6]=a*c,e[10]=r*h+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(Tn,t,En)}lookAt(t,e,n){const i=this.elements;return Rn.subVectors(t,e),0===Rn.lengthSq()&amp;&amp;(Rn.z=1),Rn.normalize(),wn.crossVectors(n,Rn),0===wn.lengthSq()&amp;&amp;(1===Math.abs(n.z)?Rn.x+=1e-4:Rn.z+=1e-4,Rn.normalize(),wn.crossVectors(n,Rn)),wn.normalize(),An.crossVectors(Rn,wn),i[0]=wn.x,i[4]=An.x,i[8]=Rn.x,i[1]=wn.y,i[5]=An.y,i[9]=Rn.y,i[2]=wn.z,i[6]=An.z,i[10]=Rn.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],m=n[6],f=n[10],g=n[14],_=n[3],v=n[7],x=n[11],y=n[15],M=i[0],S=i[4],b=i[8],T=i[12],E=i[1],w=i[5],A=i[9],R=i[13],C=i[2],L=i[6],P=i[10],I=i[14],U=i[3],D=i[7],N=i[11],O=i[15];return r[0]=s*M+a*E+o*C+l*U,r[4]=s*S+a*w+o*L+l*D,r[8]=s*b+a*A+o*P+l*N,r[12]=s*T+a*R+o*I+l*O,r[1]=c*M+h*E+u*C+d*U,r[5]=c*S+h*w+u*L+d*D,r[9]=c*b+h*A+u*P+d*N,r[13]=c*T+h*R+u*I+d*O,r[2]=p*M+m*E+f*C+g*U,r[6]=p*S+m*w+f*L+g*D,r[10]=p*b+m*A+f*P+g*N,r[14]=p*T+m*R+f*I+g*O,r[3]=_*M+v*E+x*C+y*U,r[7]=_*S+v*w+x*L+y*D,r[11]=_*b+v*A+x*P+y*N,r[15]=_*T+v*R+x*I+y*O,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[4],i=t[8],r=t[12],s=t[1],a=t[5],o=t[9],l=t[13],c=t[2],h=t[6],u=t[10],d=t[14];return t[3]*(+r*o*h-i*l*h-r*a*u+n*l*u+i*a*d-n*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-i*s*d+i*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+n*s*d+r*a*c-n*l*c)+t[15]*(-i*a*c-e*o*h+e*a*u+i*s*h-n*s*u+n*o*c)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,n){const i=this.elements;return t.isVector3?(i[12]=t.x,i[13]=t.y,i[14]=t.z):(i[12]=t,i[13]=e,i[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=t[9],u=t[10],d=t[11],p=t[12],m=t[13],f=t[14],g=t[15],_=h*f*l-m*u*l+m*o*d-a*f*d-h*o*g+a*u*g,v=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,x=c*m*l-p*h*l+p*a*d-s*m*d-c*a*g+s*h*g,y=p*h*o-c*m*o-p*a*u+s*m*u+c*a*f-s*h*f,M=e*_+n*v+i*x+r*y;if(0===M)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const S=1/M;return t[0]=_*S,t[1]=(m*u*r-h*f*r-m*i*d+n*f*d+h*i*g-n*u*g)*S,t[2]=(a*f*r-m*o*r+m*i*l-n*f*l-a*i*g+n*o*g)*S,t[3]=(h*o*r-a*u*r-h*i*l+n*u*l+a*i*d-n*o*d)*S,t[4]=v*S,t[5]=(c*f*r-p*u*r+p*i*d-e*f*d-c*i*g+e*u*g)*S,t[6]=(p*o*r-s*f*r-p*i*l+e*f*l+s*i*g-e*o*g)*S,t[7]=(s*u*r-c*o*r+c*i*l-e*u*l-s*i*d+e*o*d)*S,t[8]=x*S,t[9]=(p*h*r-c*m*r-p*n*d+e*m*d+c*n*g-e*h*g)*S,t[10]=(s*m*r-p*a*r+p*n*l-e*m*l-s*n*g+e*a*g)*S,t[11]=(c*a*r-s*h*r-c*n*l+e*h*l+s*n*d-e*a*d)*S,t[12]=y*S,t[13]=(c*m*i-p*h*i+p*n*u-e*m*u-c*n*f+e*h*f)*S,t[14]=(p*a*i-s*m*i-p*n*o+e*m*o+s*n*f-e*a*f)*S,t[15]=(s*h*i-c*a*i+c*n*o-e*h*o-s*n*u+e*a*u)*S,this}scale(t){const e=this.elements,n=t.x,i=t.y,r=t.z;return e[0]*=n,e[4]*=i,e[8]*=r,e[1]*=n,e[5]*=i,e[9]*=r,e[2]*=n,e[6]*=i,e[10]*=r,e[3]*=n,e[7]*=i,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],i=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,i))}makeTranslation(t,e,n){return t.isVector3?this.set(1,0,0,t.x,0,1,0,t.y,0,0,1,t.z,0,0,0,1):this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),i=Math.sin(e),r=1-n,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+n,l*a-i*o,l*o+i*a,0,l*a+i*o,c*a+n,c*o-i*s,0,l*o-i*a,c*o+i*s,r*o*o+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,i,r,s){return this.set(1,n,r,0,t,1,s,0,e,i,1,0,0,0,0,1),this}compose(t,e,n){const i=this.elements,r=e._x,s=e._y,a=e._z,o=e._w,l=r+r,c=s+s,h=a+a,u=r*l,d=r*c,p=r*h,m=s*c,f=s*h,g=a*h,_=o*l,v=o*c,x=o*h,y=n.x,M=n.y,S=n.z;return i[0]=(1-(m+g))*y,i[1]=(d+x)*y,i[2]=(p-v)*y,i[3]=0,i[4]=(d-x)*M,i[5]=(1-(u+g))*M,i[6]=(f+_)*M,i[7]=0,i[8]=(p+v)*S,i[9]=(f-_)*S,i[10]=(1-(u+m))*S,i[11]=0,i[12]=t.x,i[13]=t.y,i[14]=t.z,i[15]=1,this}decompose(t,e,n){const i=this.elements;let r=Sn.set(i[0],i[1],i[2]).length();const s=Sn.set(i[4],i[5],i[6]).length(),a=Sn.set(i[8],i[9],i[10]).length();this.determinant()&lt;0&amp;&amp;(r=-r),t.x=i[12],t.y=i[13],t.z=i[14],bn.copy(this);const o=1/r,l=1/s,c=1/a;return bn.elements[0]*=o,bn.elements[1]*=o,bn.elements[2]*=o,bn.elements[4]*=l,bn.elements[5]*=l,bn.elements[6]*=l,bn.elements[8]*=c,bn.elements[9]*=c,bn.elements[10]*=c,e.setFromRotationMatrix(bn),n.x=r,n.y=s,n.z=a,this}makePerspective(t,e,n,i,r,s,a=2e3){const o=this.elements,l=2*r/(e-t),c=2*r/(n-i),h=(e+t)/(e-t),u=(n+i)/(n-i);let d,p;if(a===$t)d=-(s+r)/(s-r),p=-2*s*r/(s-r);else{if(a!==Qt)throw new Error(&quot;THREE.Matrix4.makePerspective(): Invalid coordinate system: &quot;+a);d=-s/(s-r),p=-s*r/(s-r)}return o[0]=l,o[4]=0,o[8]=h,o[12]=0,o[1]=0,o[5]=c,o[9]=u,o[13]=0,o[2]=0,o[6]=0,o[10]=d,o[14]=p,o[3]=0,o[7]=0,o[11]=-1,o[15]=0,this}makeOrthographic(t,e,n,i,r,s,a=2e3){const o=this.elements,l=1/(e-t),c=1/(n-i),h=1/(s-r),u=(e+t)*l,d=(n+i)*c;let p,m;if(a===$t)p=(s+r)*h,m=-2*h;else{if(a!==Qt)throw new Error(&quot;THREE.Matrix4.makeOrthographic(): Invalid coordinate system: &quot;+a);p=r*h,m=-1*h}return o[0]=2*l,o[4]=0,o[8]=0,o[12]=-u,o[1]=0,o[5]=2*c,o[9]=0,o[13]=-d,o[2]=0,o[6]=0,o[10]=m,o[14]=-p,o[3]=0,o[7]=0,o[11]=0,o[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t&lt;16;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n&lt;16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}const Sn=new We,bn=new Mn,Tn=new We(0,0,0),En=new We(1,1,1),wn=new We,An=new We,Rn=new We,Cn=new Mn,Ln=new ke;class Pn{constructor(t=0,e=0,n=0,i=Pn.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=n,this._order=i}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,n,i=this._order){return this._x=t,this._y=e,this._z=n,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,n=!0){const i=t.elements,r=i[0],s=i[4],a=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(e){case&quot;XYZ&quot;:this._y=Math.asin(ae(a,-1,1)),Math.abs(a)&lt;.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-s,r)):(this._x=Math.atan2(u,l),this._z=0);break;case&quot;YXZ&quot;:this._x=Math.asin(-ae(c,-1,1)),Math.abs(c)&lt;.9999999?(this._y=Math.atan2(a,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case&quot;ZXY&quot;:this._x=Math.asin(ae(u,-1,1)),Math.abs(u)&lt;.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-s,l)):(this._y=0,this._z=Math.atan2(o,r));break;case&quot;ZYX&quot;:this._y=Math.asin(-ae(h,-1,1)),Math.abs(h)&lt;.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-s,l));break;case&quot;YZX&quot;:this._z=Math.asin(ae(o,-1,1)),Math.abs(o)&lt;.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(a,d));break;case&quot;XZY&quot;:this._z=Math.asin(-ae(s,-1,1)),Math.abs(s)&lt;.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(a,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn(&quot;THREE.Euler: .setFromRotationMatrix() encountered an unknown order: &quot;+e)}return this._order=e,!0===n&amp;&amp;this._onChangeCallback(),this}setFromQuaternion(t,e,n){return Cn.makeRotationFromQuaternion(t),this.setFromRotationMatrix(Cn,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return Ln.setFromEuler(this),this.setFromQuaternion(Ln,t)}equals(t){return t._x===this._x&amp;&amp;t._y===this._y&amp;&amp;t._z===this._z&amp;&amp;t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&amp;&amp;(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}Pn.DEFAULT_ORDER=&quot;XYZ&quot;;class In{constructor(){this.mask=1}set(t){this.mask=(1&lt;&lt;t|0)&gt;&gt;&gt;0}enable(t){this.mask|=1&lt;&lt;t|0}enableAll(){this.mask=-1}toggle(t){this.mask^=1&lt;&lt;t|0}disable(t){this.mask&amp;=~(1&lt;&lt;t|0)}disableAll(){this.mask=0}test(t){return 0!=(this.mask&amp;t.mask)}isEnabled(t){return 0!=(this.mask&amp;(1&lt;&lt;t|0))}}let Un=0;const Dn=new We,Nn=new ke,On=new Mn,Fn=new We,Bn=new We,zn=new We,Gn=new ke,Hn=new We(1,0,0),Vn=new We(0,1,0),kn=new We(0,0,1),Wn={type:&quot;added&quot;},Xn={type:&quot;removed&quot;};class jn extends te{constructor(){super(),this.isObject3D=!0,Object.defineProperty(this,&quot;id&quot;,{value:Un++}),this.uuid=se(),this.name=&quot;&quot;,this.type=&quot;Object3D&quot;,this.parent=null,this.children=[],this.up=jn.DEFAULT_UP.clone();const t=new We,e=new Pn,n=new ke,i=new We(1,1,1);e._onChange((function(){n.setFromEuler(e,!1)})),n._onChange((function(){e.setFromQuaternion(n,void 0,!1)})),Object.defineProperties(this,{position:{configurable:!0,enumerable:!0,value:t},rotation:{configurable:!0,enumerable:!0,value:e},quaternion:{configurable:!0,enumerable:!0,value:n},scale:{configurable:!0,enumerable:!0,value:i},modelViewMatrix:{value:new Mn},normalMatrix:{value:new fe}}),this.matrix=new Mn,this.matrixWorld=new Mn,this.matrixAutoUpdate=jn.DEFAULT_MATRIX_AUTO_UPDATE,this.matrixWorldAutoUpdate=jn.DEFAULT_MATRIX_WORLD_AUTO_UPDATE,this.matrixWorldNeedsUpdate=!1,this.layers=new In,this.visible=!0,this.castShadow=!1,this.receiveShadow=!1,this.frustumCulled=!0,this.renderOrder=0,this.animations=[],this.userData={}}onBeforeShadow(){}onAfterShadow(){}onBeforeRender(){}onAfterRender(){}applyMatrix4(t){this.matrixAutoUpdate&amp;&amp;this.updateMatrix(),this.matrix.premultiply(t),this.matrix.decompose(this.position,this.quaternion,this.scale)}applyQuaternion(t){return this.quaternion.premultiply(t),this}setRotationFromAxisAngle(t,e){this.quaternion.setFromAxisAngle(t,e)}setRotationFromEuler(t){this.quaternion.setFromEuler(t,!0)}setRotationFromMatrix(t){this.quaternion.setFromRotationMatrix(t)}setRotationFromQuaternion(t){this.quaternion.copy(t)}rotateOnAxis(t,e){return Nn.setFromAxisAngle(t,e),this.quaternion.multiply(Nn),this}rotateOnWorldAxis(t,e){return Nn.setFromAxisAngle(t,e),this.quaternion.premultiply(Nn),this}rotateX(t){return this.rotateOnAxis(Hn,t)}rotateY(t){return this.rotateOnAxis(Vn,t)}rotateZ(t){return this.rotateOnAxis(kn,t)}translateOnAxis(t,e){return Dn.copy(t).applyQuaternion(this.quaternion),this.position.add(Dn.multiplyScalar(e)),this}translateX(t){return this.translateOnAxis(Hn,t)}translateY(t){return this.translateOnAxis(Vn,t)}translateZ(t){return this.translateOnAxis(kn,t)}localToWorld(t){return this.updateWorldMatrix(!0,!1),t.applyMatrix4(this.matrixWorld)}worldToLocal(t){return this.updateWorldMatrix(!0,!1),t.applyMatrix4(On.copy(this.matrixWorld).invert())}lookAt(t,e,n){t.isVector3?Fn.copy(t):Fn.set(t,e,n);const i=this.parent;this.updateWorldMatrix(!0,!1),Bn.setFromMatrixPosition(this.matrixWorld),this.isCamera||this.isLight?On.lookAt(Bn,Fn,this.up):On.lookAt(Fn,Bn,this.up),this.quaternion.setFromRotationMatrix(On),i&amp;&amp;(On.extractRotation(i.matrixWorld),Nn.setFromRotationMatrix(On),this.quaternion.premultiply(Nn.invert()))}add(t){if(arguments.length&gt;1){for(let t=0;t&lt;arguments.length;t++)this.add(arguments[t]);return this}return t===this?(console.error(&quot;THREE.Object3D.add: object can't be added as a child of itself.&quot;,t),this):(t&amp;&amp;t.isObject3D?(null!==t.parent&amp;&amp;t.parent.remove(t),t.parent=this,this.children.push(t),t.dispatchEvent(Wn)):console.error(&quot;THREE.Object3D.add: object not an instance of THREE.Object3D.&quot;,t),this)}remove(t){if(arguments.length&gt;1){for(let t=0;t&lt;arguments.length;t++)this.remove(arguments[t]);return this}const e=this.children.indexOf(t);return-1!==e&amp;&amp;(t.parent=null,this.children.splice(e,1),t.dispatchEvent(Xn)),this}removeFromParent(){const t=this.parent;return null!==t&amp;&amp;t.remove(this),this}clear(){return this.remove(...this.children)}attach(t){return this.updateWorldMatrix(!0,!1),On.copy(this.matrixWorld).invert(),null!==t.parent&amp;&amp;(t.parent.updateWorldMatrix(!0,!1),On.multiply(t.parent.matrixWorld)),t.applyMatrix4(On),this.add(t),t.updateWorldMatrix(!1,!0),this}getObjectById(t){return this.getObjectByProperty(&quot;id&quot;,t)}getObjectByName(t){return this.getObjectByProperty(&quot;name&quot;,t)}getObjectByProperty(t,e){if(this[t]===e)return this;for(let n=0,i=this.children.length;n&lt;i;n++){const i=this.children[n].getObjectByProperty(t,e);if(void 0!==i)return i}}getObjectsByProperty(t,e,n=[]){this[t]===e&amp;&amp;n.push(this);const i=this.children;for(let r=0,s=i.length;r&lt;s;r++)i[r].getObjectsByProperty(t,e,n);return n}getWorldPosition(t){return this.updateWorldMatrix(!0,!1),t.setFromMatrixPosition(this.matrixWorld)}getWorldQuaternion(t){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(Bn,t,zn),t}getWorldScale(t){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(Bn,Gn,t),t}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(e[8],e[9],e[10]).normalize()}raycast(){}traverse(t){t(this);const e=this.children;for(let n=0,i=e.length;n&lt;i;n++)e[n].traverse(t)}traverseVisible(t){if(!1===this.visible)return;t(this);const e=this.children;for(let n=0,i=e.length;n&lt;i;n++)e[n].traverseVisible(t)}traverseAncestors(t){const e=this.parent;null!==e&amp;&amp;(t(e),e.traverseAncestors(t))}updateMatrix(){this.matrix.compose(this.position,this.quaternion,this.scale),this.matrixWorldNeedsUpdate=!0}updateMatrixWorld(t){this.matrixAutoUpdate&amp;&amp;this.updateMatrix(),(this.matrixWorldNeedsUpdate||t)&amp;&amp;(null===this.parent?this.matrixWorld.copy(this.matrix):this.matrixWorld.multiplyMatrices(this.parent.matrixWorld,this.matrix),this.matrixWorldNeedsUpdate=!1,t=!0);const e=this.children;for(let n=0,i=e.length;n&lt;i;n++){const i=e[n];!0!==i.matrixWorldAutoUpdate&amp;&amp;!0!==t||i.updateMatrixWorld(t)}}updateWorldMatrix(t,e){const n=this.parent;if(!0===t&amp;&amp;null!==n&amp;&amp;!0===n.matrixWorldAutoUpdate&amp;&amp;n.updateWorldMatrix(!0,!1),this.matrixAutoUpdate&amp;&amp;this.updateMatrix(),null===this.parent?this.matrixWorld.copy(this.matrix):this.matrixWorld.multiplyMatrices(this.parent.matrixWorld,this.matrix),!0===e){const t=this.children;for(let e=0,n=t.length;e&lt;n;e++){const n=t[e];!0===n.matrixWorldAutoUpdate&amp;&amp;n.updateWorldMatrix(!1,!0)}}}toJSON(t){const e=void 0===t||&quot;string&quot;==typeof t,n={};e&amp;&amp;(t={geometries:{},materials:{},textures:{},images:{},shapes:{},skeletons:{},animations:{},nodes:{}},n.metadata={version:4.6,type:&quot;Object&quot;,generator:&quot;Object3D.toJSON&quot;});const i={};function r(e,n){return void 0===e[n.uuid]&amp;&amp;(e[n.uuid]=n.toJSON(t)),n.uuid}if(i.uuid=this.uuid,i.type=this.type,&quot;&quot;!==this.name&amp;&amp;(i.name=this.name),!0===this.castShadow&amp;&amp;(i.castShadow=!0),!0===this.receiveShadow&amp;&amp;(i.receiveShadow=!0),!1===this.visible&amp;&amp;(i.visible=!1),!1===this.frustumCulled&amp;&amp;(i.frustumCulled=!1),0!==this.renderOrder&amp;&amp;(i.renderOrder=this.renderOrder),Object.keys(this.userData).length&gt;0&amp;&amp;(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&amp;&amp;(i.matrixAutoUpdate=!1),this.isInstancedMesh&amp;&amp;(i.type=&quot;InstancedMesh&quot;,i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&amp;&amp;(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&amp;&amp;(i.type=&quot;BatchedMesh&quot;,i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((t=&gt;({boxInitialized:t.boxInitialized,boxMin:t.box.min.toArray(),boxMax:t.box.max.toArray(),sphereInitialized:t.sphereInitialized,sphereRadius:t.sphere.radius,sphereCenter:t.sphere.center.toArray()}))),i.maxGeometryCount=this._maxGeometryCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(t),null!==this.boundingSphere&amp;&amp;(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&amp;&amp;(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&amp;&amp;(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&amp;&amp;(i.background=this.background.toJSON(t).uuid)),this.environment&amp;&amp;this.environment.isTexture&amp;&amp;!0!==this.environment.isRenderTargetTexture&amp;&amp;(i.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(t.geometries,this.geometry);const e=this.geometry.parameters;if(void 0!==e&amp;&amp;void 0!==e.shapes){const n=e.shapes;if(Array.isArray(n))for(let e=0,i=n.length;e&lt;i;e++){const i=n[e];r(t.shapes,i)}else r(t.shapes,n)}}if(this.isSkinnedMesh&amp;&amp;(i.bindMode=this.bindMode,i.bindMatrix=this.bindMatrix.toArray(),void 0!==this.skeleton&amp;&amp;(r(t.skeletons,this.skeleton),i.skeleton=this.skeleton.uuid)),void 0!==this.material)if(Array.isArray(this.material)){const e=[];for(let n=0,i=this.material.length;n&lt;i;n++)e.push(r(t.materials,this.material[n]));i.material=e}else i.material=r(t.materials,this.material);if(this.children.length&gt;0){i.children=[];for(let e=0;e&lt;this.children.length;e++)i.children.push(this.children[e].toJSON(t).object)}if(this.animations.length&gt;0){i.animations=[];for(let e=0;e&lt;this.animations.length;e++){const n=this.animations[e];i.animations.push(r(t.animations,n))}}if(e){const e=s(t.geometries),i=s(t.materials),r=s(t.textures),a=s(t.images),o=s(t.shapes),l=s(t.skeletons),c=s(t.animations),h=s(t.nodes);e.length&gt;0&amp;&amp;(n.geometries=e),i.length&gt;0&amp;&amp;(n.materials=i),r.length&gt;0&amp;&amp;(n.textures=r),a.length&gt;0&amp;&amp;(n.images=a),o.length&gt;0&amp;&amp;(n.shapes=o),l.length&gt;0&amp;&amp;(n.skeletons=l),c.length&gt;0&amp;&amp;(n.animations=c),h.length&gt;0&amp;&amp;(n.nodes=h)}return n.object=i,n;function s(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.animations=t.animations.slice(),this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e&lt;t.children.length;e++){const n=t.children[e];this.add(n.clone())}return this}}jn.DEFAULT_UP=new We(0,1,0),jn.DEFAULT_MATRIX_AUTO_UPDATE=!0,jn.DEFAULT_MATRIX_WORLD_AUTO_UPDATE=!0;const qn=new We,Yn=new We,Zn=new We,Jn=new We,Kn=new We,$n=new We,Qn=new We,ti=new We,ei=new We,ni=new We;let ii=!1;class ri{constructor(t=new We,e=new We,n=new We){this.a=t,this.b=e,this.c=n}static getNormal(t,e,n,i){i.subVectors(n,e),qn.subVectors(t,e),i.cross(qn);const r=i.lengthSq();return r&gt;0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,n,i,r){qn.subVectors(i,e),Yn.subVectors(n,e),Zn.subVectors(t,e);const s=qn.dot(qn),a=qn.dot(Yn),o=qn.dot(Zn),l=Yn.dot(Yn),c=Yn.dot(Zn),h=s*l-a*a;if(0===h)return r.set(0,0,0),null;const u=1/h,d=(l*o-a*c)*u,p=(s*c-a*o)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,n,i){return null!==this.getBarycoord(t,e,n,i,Jn)&amp;&amp;(Jn.x&gt;=0&amp;&amp;Jn.y&gt;=0&amp;&amp;Jn.x+Jn.y&lt;=1)}static getUV(t,e,n,i,r,s,a,o){return!1===ii&amp;&amp;(console.warn(&quot;THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().&quot;),ii=!0),this.getInterpolation(t,e,n,i,r,s,a,o)}static getInterpolation(t,e,n,i,r,s,a,o){return null===this.getBarycoord(t,e,n,i,Jn)?(o.x=0,o.y=0,&quot;z&quot;in o&amp;&amp;(o.z=0),&quot;w&quot;in o&amp;&amp;(o.w=0),null):(o.setScalar(0),o.addScaledVector(r,Jn.x),o.addScaledVector(s,Jn.y),o.addScaledVector(a,Jn.z),o)}static isFrontFacing(t,e,n,i){return qn.subVectors(n,e),Yn.subVectors(t,e),qn.cross(Yn).dot(i)&lt;0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,i){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[i]),this}setFromAttributeAndIndices(t,e,n,i){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,i),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return qn.subVectors(this.c,this.b),Yn.subVectors(this.a,this.b),.5*qn.cross(Yn).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return ri.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return ri.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,n,i,r){return!1===ii&amp;&amp;(console.warn(&quot;THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().&quot;),ii=!0),ri.getInterpolation(t,this.a,this.b,this.c,e,n,i,r)}getInterpolation(t,e,n,i,r){return ri.getInterpolation(t,this.a,this.b,this.c,e,n,i,r)}containsPoint(t){return ri.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return ri.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,i=this.b,r=this.c;let s,a;Kn.subVectors(i,n),$n.subVectors(r,n),ti.subVectors(t,n);const o=Kn.dot(ti),l=$n.dot(ti);if(o&lt;=0&amp;&amp;l&lt;=0)return e.copy(n);ei.subVectors(t,i);const c=Kn.dot(ei),h=$n.dot(ei);if(c&gt;=0&amp;&amp;h&lt;=c)return e.copy(i);const u=o*h-c*l;if(u&lt;=0&amp;&amp;o&gt;=0&amp;&amp;c&lt;=0)return s=o/(o-c),e.copy(n).addScaledVector(Kn,s);ni.subVectors(t,r);const d=Kn.dot(ni),p=$n.dot(ni);if(p&gt;=0&amp;&amp;d&lt;=p)return e.copy(r);const m=d*l-o*p;if(m&lt;=0&amp;&amp;l&gt;=0&amp;&amp;p&lt;=0)return a=l/(l-p),e.copy(n).addScaledVector($n,a);const f=c*p-d*h;if(f&lt;=0&amp;&amp;h-c&gt;=0&amp;&amp;d-p&gt;=0)return Qn.subVectors(r,i),a=(h-c)/(h-c+(d-p)),e.copy(i).addScaledVector(Qn,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(n).addScaledVector(Kn,s).addScaledVector($n,a)}equals(t){return t.a.equals(this.a)&amp;&amp;t.b.equals(this.b)&amp;&amp;t.c.equals(this.c)}}const si={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},ai={h:0,s:0,l:0},oi={h:0,s:0,l:0};function li(t,e,n){return n&lt;0&amp;&amp;(n+=1),n&gt;1&amp;&amp;(n-=1),n&lt;1/6?t+6*(e-t)*n:n&lt;.5?e:n&lt;2/3?t+6*(e-t)*(2/3-n):t}class ci{constructor(t,e,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(t,e,n)}set(t,e,n){if(void 0===e&amp;&amp;void 0===n){const e=t;e&amp;&amp;e.isColor?this.copy(e):&quot;number&quot;==typeof e?this.setHex(e):&quot;string&quot;==typeof e&amp;&amp;this.setStyle(e)}else this.setRGB(t,e,n);return this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=Gt){return t=Math.floor(t),this.r=(t&gt;&gt;16&amp;255)/255,this.g=(t&gt;&gt;8&amp;255)/255,this.b=(255&amp;t)/255,Re.toWorkingColorSpace(this,e),this}setRGB(t,e,n,i=Re.workingColorSpace){return this.r=t,this.g=e,this.b=n,Re.toWorkingColorSpace(this,i),this}setHSL(t,e,n,i=Re.workingColorSpace){if(t=oe(t,1),e=ae(e,0,1),n=ae(n,0,1),0===e)this.r=this.g=this.b=n;else{const i=n&lt;=.5?n*(1+e):n+e-n*e,r=2*n-i;this.r=li(r,i,t+1/3),this.g=li(r,i,t),this.b=li(r,i,t-1/3)}return Re.toWorkingColorSpace(this,i),this}setStyle(t,e=Gt){function n(e){void 0!==e&amp;&amp;parseFloat(e)&lt;1&amp;&amp;console.warn(&quot;THREE.Color: Alpha component of &quot;+t+&quot; will be ignored.&quot;)}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const s=i[1],a=i[2];switch(s){case&quot;rgb&quot;:case&quot;rgba&quot;:if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case&quot;hsl&quot;:case&quot;hsla&quot;:if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:console.warn(&quot;THREE.Color: Unknown color model &quot;+t)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(t)){const n=i[1],r=n.length;if(3===r)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,e);if(6===r)return this.setHex(parseInt(n,16),e);console.warn(&quot;THREE.Color: Invalid hex color &quot;+t)}else if(t&amp;&amp;t.length&gt;0)return this.setColorName(t,e);return this}setColorName(t,e=Gt){const n=si[t.toLowerCase()];return void 0!==n?this.setHex(n,e):console.warn(&quot;THREE.Color: Unknown color &quot;+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=Ce(t.r),this.g=Ce(t.g),this.b=Ce(t.b),this}copyLinearToSRGB(t){return this.r=Le(t.r),this.g=Le(t.g),this.b=Le(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=Gt){return Re.fromWorkingColorSpace(hi.copy(this),t),65536*Math.round(ae(255*hi.r,0,255))+256*Math.round(ae(255*hi.g,0,255))+Math.round(ae(255*hi.b,0,255))}getHexString(t=Gt){return(&quot;000000&quot;+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=Re.workingColorSpace){Re.fromWorkingColorSpace(hi.copy(this),e);const n=hi.r,i=hi.g,r=hi.b,s=Math.max(n,i,r),a=Math.min(n,i,r);let o,l;const c=(a+s)/2;if(a===s)o=0,l=0;else{const t=s-a;switch(l=c&lt;=.5?t/(s+a):t/(2-s-a),s){case n:o=(i-r)/t+(i&lt;r?6:0);break;case i:o=(r-n)/t+2;break;case r:o=(n-i)/t+4}o/=6}return t.h=o,t.s=l,t.l=c,t}getRGB(t,e=Re.workingColorSpace){return Re.fromWorkingColorSpace(hi.copy(this),e),t.r=hi.r,t.g=hi.g,t.b=hi.b,t}getStyle(t=Gt){Re.fromWorkingColorSpace(hi.copy(this),t);const e=hi.r,n=hi.g,i=hi.b;return t!==Gt?`color(${t} ${e.toFixed(3)} ${n.toFixed(3)} ${i.toFixed(3)})`:`rgb(${Math.round(255*e)},${Math.round(255*n)},${Math.round(255*i)})`}offsetHSL(t,e,n){return this.getHSL(ai),this.setHSL(ai.h+t,ai.s+e,ai.l+n)}add(t){return this.r+=t.r,this.g+=t.g,this.b+=t.b,this}addColors(t,e){return this.r=t.r+e.r,this.g=t.g+e.g,this.b=t.b+e.b,this}addScalar(t){return this.r+=t,this.g+=t,this.b+=t,this}sub(t){return this.r=Math.max(0,this.r-t.r),this.g=Math.max(0,this.g-t.g),this.b=Math.max(0,this.b-t.b),this}multiply(t){return this.r*=t.r,this.g*=t.g,this.b*=t.b,this}multiplyScalar(t){return this.r*=t,this.g*=t,this.b*=t,this}lerp(t,e){return this.r+=(t.r-this.r)*e,this.g+=(t.g-this.g)*e,this.b+=(t.b-this.b)*e,this}lerpColors(t,e,n){return this.r=t.r+(e.r-t.r)*n,this.g=t.g+(e.g-t.g)*n,this.b=t.b+(e.b-t.b)*n,this}lerpHSL(t,e){this.getHSL(ai),t.getHSL(oi);const n=le(ai.h,oi.h,e),i=le(ai.s,oi.s,e),r=le(ai.l,oi.l,e);return this.setHSL(n,i,r),this}setFromVector3(t){return this.r=t.x,this.g=t.y,this.b=t.z,this}applyMatrix3(t){const e=this.r,n=this.g,i=this.b,r=t.elements;return this.r=r[0]*e+r[3]*n+r[6]*i,this.g=r[1]*e+r[4]*n+r[7]*i,this.b=r[2]*e+r[5]*n+r[8]*i,this}equals(t){return t.r===this.r&amp;&amp;t.g===this.g&amp;&amp;t.b===this.b}fromArray(t,e=0){return this.r=t[e],this.g=t[e+1],this.b=t[e+2],this}toArray(t=[],e=0){return t[e]=this.r,t[e+1]=this.g,t[e+2]=this.b,t}fromBufferAttribute(t,e){return this.r=t.getX(e),this.g=t.getY(e),this.b=t.getZ(e),this}toJSON(){return this.getHex()}*[Symbol.iterator](){yield this.r,yield this.g,yield this.b}}const hi=new ci;ci.NAMES=si;let ui=0;class di extends te{constructor(){super(),this.isMaterial=!0,Object.defineProperty(this,&quot;id&quot;,{value:ui++}),this.uuid=se(),this.name=&quot;&quot;,this.type=&quot;Material&quot;,this.blending=1,this.side=s,this.vertexColors=!1,this.opacity=1,this.transparent=!1,this.alphaHash=!1,this.blendSrc=l,this.blendDst=c,this.blendEquation=o,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.blendColor=new ci(0,0,0),this.blendAlpha=0,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=Yt,this.stencilZFail=Yt,this.stencilZPass=Yt,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.forceSinglePass=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(t){this._alphaTest&gt;0!=t&gt;0&amp;&amp;this.version++,this._alphaTest=t}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const n=t[e];if(void 0===n){console.warn(`THREE.Material: parameter '${e}' has value of undefined.`);continue}const i=this[e];void 0!==i?i&amp;&amp;i.isColor?i.set(n):i&amp;&amp;i.isVector3&amp;&amp;n&amp;&amp;n.isVector3?i.copy(n):this[e]=n:console.warn(`THREE.Material: '${e}' is not a property of THREE.${this.type}.`)}}toJSON(t){const e=void 0===t||&quot;string&quot;==typeof t;e&amp;&amp;(t={textures:{},images:{}});const n={metadata:{version:4.6,type:&quot;Material&quot;,generator:&quot;Material.toJSON&quot;}};function i(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}if(n.uuid=this.uuid,n.type=this.type,&quot;&quot;!==this.name&amp;&amp;(n.name=this.name),this.color&amp;&amp;this.color.isColor&amp;&amp;(n.color=this.color.getHex()),void 0!==this.roughness&amp;&amp;(n.roughness=this.roughness),void 0!==this.metalness&amp;&amp;(n.metalness=this.metalness),void 0!==this.sheen&amp;&amp;(n.sheen=this.sheen),this.sheenColor&amp;&amp;this.sheenColor.isColor&amp;&amp;(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&amp;&amp;(n.sheenRoughness=this.sheenRoughness),this.emissive&amp;&amp;this.emissive.isColor&amp;&amp;(n.emissive=this.emissive.getHex()),this.emissiveIntensity&amp;&amp;1!==this.emissiveIntensity&amp;&amp;(n.emissiveIntensity=this.emissiveIntensity),this.specular&amp;&amp;this.specular.isColor&amp;&amp;(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&amp;&amp;(n.specularIntensity=this.specularIntensity),this.specularColor&amp;&amp;this.specularColor.isColor&amp;&amp;(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&amp;&amp;(n.shininess=this.shininess),void 0!==this.clearcoat&amp;&amp;(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&amp;&amp;(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&amp;&amp;this.clearcoatMap.isTexture&amp;&amp;(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&amp;&amp;this.clearcoatRoughnessMap.isTexture&amp;&amp;(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&amp;&amp;this.clearcoatNormalMap.isTexture&amp;&amp;(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.iridescence&amp;&amp;(n.iridescence=this.iridescence),void 0!==this.iridescenceIOR&amp;&amp;(n.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&amp;&amp;(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&amp;&amp;this.iridescenceMap.isTexture&amp;&amp;(n.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&amp;&amp;this.iridescenceThicknessMap.isTexture&amp;&amp;(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),void 0!==this.anisotropy&amp;&amp;(n.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&amp;&amp;(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&amp;&amp;this.anisotropyMap.isTexture&amp;&amp;(n.anisotropyMap=this.anisotropyMap.toJSON(t).uuid),this.map&amp;&amp;this.map.isTexture&amp;&amp;(n.map=this.map.toJSON(t).uuid),this.matcap&amp;&amp;this.matcap.isTexture&amp;&amp;(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&amp;&amp;this.alphaMap.isTexture&amp;&amp;(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&amp;&amp;this.lightMap.isTexture&amp;&amp;(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&amp;&amp;this.aoMap.isTexture&amp;&amp;(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&amp;&amp;this.bumpMap.isTexture&amp;&amp;(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&amp;&amp;this.normalMap.isTexture&amp;&amp;(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&amp;&amp;this.displacementMap.isTexture&amp;&amp;(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&amp;&amp;this.roughnessMap.isTexture&amp;&amp;(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&amp;&amp;this.metalnessMap.isTexture&amp;&amp;(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&amp;&amp;this.emissiveMap.isTexture&amp;&amp;(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&amp;&amp;this.specularMap.isTexture&amp;&amp;(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&amp;&amp;this.specularIntensityMap.isTexture&amp;&amp;(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&amp;&amp;this.specularColorMap.isTexture&amp;&amp;(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&amp;&amp;this.envMap.isTexture&amp;&amp;(n.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&amp;&amp;(n.combine=this.combine)),void 0!==this.envMapIntensity&amp;&amp;(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&amp;&amp;(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&amp;&amp;(n.refractionRatio=this.refractionRatio),this.gradientMap&amp;&amp;this.gradientMap.isTexture&amp;&amp;(n.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&amp;&amp;(n.transmission=this.transmission),this.transmissionMap&amp;&amp;this.transmissionMap.isTexture&amp;&amp;(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&amp;&amp;(n.thickness=this.thickness),this.thicknessMap&amp;&amp;this.thicknessMap.isTexture&amp;&amp;(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&amp;&amp;this.attenuationDistance!==1/0&amp;&amp;(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&amp;&amp;(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&amp;&amp;(n.size=this.size),null!==this.shadowSide&amp;&amp;(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&amp;&amp;(n.sizeAttenuation=this.sizeAttenuation),1!==this.blending&amp;&amp;(n.blending=this.blending),this.side!==s&amp;&amp;(n.side=this.side),!0===this.vertexColors&amp;&amp;(n.vertexColors=!0),this.opacity&lt;1&amp;&amp;(n.opacity=this.opacity),!0===this.transparent&amp;&amp;(n.transparent=!0),this.blendSrc!==l&amp;&amp;(n.blendSrc=this.blendSrc),this.blendDst!==c&amp;&amp;(n.blendDst=this.blendDst),this.blendEquation!==o&amp;&amp;(n.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&amp;&amp;(n.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&amp;&amp;(n.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&amp;&amp;(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&amp;&amp;this.blendColor.isColor&amp;&amp;(n.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&amp;&amp;(n.blendAlpha=this.blendAlpha),3!==this.depthFunc&amp;&amp;(n.depthFunc=this.depthFunc),!1===this.depthTest&amp;&amp;(n.depthTest=this.depthTest),!1===this.depthWrite&amp;&amp;(n.depthWrite=this.depthWrite),!1===this.colorWrite&amp;&amp;(n.colorWrite=this.colorWrite),255!==this.stencilWriteMask&amp;&amp;(n.stencilWriteMask=this.stencilWriteMask),519!==this.stencilFunc&amp;&amp;(n.stencilFunc=this.stencilFunc),0!==this.stencilRef&amp;&amp;(n.stencilRef=this.stencilRef),255!==this.stencilFuncMask&amp;&amp;(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==Yt&amp;&amp;(n.stencilFail=this.stencilFail),this.stencilZFail!==Yt&amp;&amp;(n.stencilZFail=this.stencilZFail),this.stencilZPass!==Yt&amp;&amp;(n.stencilZPass=this.stencilZPass),!0===this.stencilWrite&amp;&amp;(n.stencilWrite=this.stencilWrite),void 0!==this.rotation&amp;&amp;0!==this.rotation&amp;&amp;(n.rotation=this.rotation),!0===this.polygonOffset&amp;&amp;(n.polygonOffset=!0),0!==this.polygonOffsetFactor&amp;&amp;(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&amp;&amp;(n.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&amp;&amp;1!==this.linewidth&amp;&amp;(n.linewidth=this.linewidth),void 0!==this.dashSize&amp;&amp;(n.dashSize=this.dashSize),void 0!==this.gapSize&amp;&amp;(n.gapSize=this.gapSize),void 0!==this.scale&amp;&amp;(n.scale=this.scale),!0===this.dithering&amp;&amp;(n.dithering=!0),this.alphaTest&gt;0&amp;&amp;(n.alphaTest=this.alphaTest),!0===this.alphaHash&amp;&amp;(n.alphaHash=!0),!0===this.alphaToCoverage&amp;&amp;(n.alphaToCoverage=!0),!0===this.premultipliedAlpha&amp;&amp;(n.premultipliedAlpha=!0),!0===this.forceSinglePass&amp;&amp;(n.forceSinglePass=!0),!0===this.wireframe&amp;&amp;(n.wireframe=!0),this.wireframeLinewidth&gt;1&amp;&amp;(n.wireframeLinewidth=this.wireframeLinewidth),&quot;round&quot;!==this.wireframeLinecap&amp;&amp;(n.wireframeLinecap=this.wireframeLinecap),&quot;round&quot;!==this.wireframeLinejoin&amp;&amp;(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&amp;&amp;(n.flatShading=!0),!1===this.visible&amp;&amp;(n.visible=!1),!1===this.toneMapped&amp;&amp;(n.toneMapped=!1),!1===this.fog&amp;&amp;(n.fog=!1),Object.keys(this.userData).length&gt;0&amp;&amp;(n.userData=this.userData),e){const e=i(t.textures),r=i(t.images);e.length&gt;0&amp;&amp;(n.textures=e),r.length&gt;0&amp;&amp;(n.images=r)}return n}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.blendColor.copy(t.blendColor),this.blendAlpha=t.blendAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let n=null;if(null!==e){const t=e.length;n=new Array(t);for(let i=0;i!==t;++i)n[i]=e[i].clone()}return this.clippingPlanes=n,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaHash=t.alphaHash,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:&quot;dispose&quot;})}set needsUpdate(t){!0===t&amp;&amp;this.version++}}class pi extends di{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type=&quot;MeshBasicMaterial&quot;,this.color=new ci(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=h,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap=&quot;round&quot;,this.wireframeLinejoin=&quot;round&quot;,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}const mi=fi();function fi(){const t=new ArrayBuffer(4),e=new Float32Array(t),n=new Uint32Array(t),i=new Uint32Array(512),r=new Uint32Array(512);for(let t=0;t&lt;256;++t){const e=t-127;e&lt;-27?(i[t]=0,i[256|t]=32768,r[t]=24,r[256|t]=24):e&lt;-14?(i[t]=1024&gt;&gt;-e-14,i[256|t]=1024&gt;&gt;-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e&lt;=15?(i[t]=e+15&lt;&lt;10,i[256|t]=e+15&lt;&lt;10|32768,r[t]=13,r[256|t]=13):e&lt;128?(i[t]=31744,i[256|t]=64512,r[t]=24,r[256|t]=24):(i[t]=31744,i[256|t]=64512,r[t]=13,r[256|t]=13)}const s=new Uint32Array(2048),a=new Uint32Array(64),o=new Uint32Array(64);for(let t=1;t&lt;1024;++t){let e=t&lt;&lt;13,n=0;for(;0==(8388608&amp;e);)e&lt;&lt;=1,n-=8388608;e&amp;=-8388609,n+=947912704,s[t]=e|n}for(let t=1024;t&lt;2048;++t)s[t]=939524096+(t-1024&lt;&lt;13);for(let t=1;t&lt;31;++t)a[t]=t&lt;&lt;23;a[31]=1199570944,a[32]=2147483648;for(let t=33;t&lt;63;++t)a[t]=2147483648+(t-32&lt;&lt;23);a[63]=3347054592;for(let t=1;t&lt;64;++t)32!==t&amp;&amp;(o[t]=1024);return{floatView:e,uint32View:n,baseTable:i,shiftTable:r,mantissaTable:s,exponentTable:a,offsetTable:o}}function gi(t){Math.abs(t)&gt;65504&amp;&amp;console.warn(&quot;THREE.DataUtils.toHalfFloat(): Value out of range.&quot;),t=ae(t,-65504,65504),mi.floatView[0]=t;const e=mi.uint32View[0],n=e&gt;&gt;23&amp;511;return mi.baseTable[n]+((8388607&amp;e)&gt;&gt;mi.shiftTable[n])}function _i(t){const e=t&gt;&gt;10;return mi.uint32View[0]=mi.mantissaTable[mi.offsetTable[e]+(1023&amp;t)]+mi.exponentTable[e],mi.floatView[0]}const vi={toHalfFloat:gi,fromHalfFloat:_i},xi=new We,yi=new me;class Mi{constructor(t,e,n=!1){if(Array.isArray(t))throw new TypeError(&quot;THREE.BufferAttribute: array should be a Typed Array.&quot;);this.isBufferAttribute=!0,this.name=&quot;&quot;,this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=n,this.usage=Zt,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.gpuType=H,this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&amp;&amp;this.version++}get updateRange(){return console.warn(&quot;THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.&quot;),this._updateRange}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this.gpuType=t.gpuType,this}copyAt(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let i=0,r=this.itemSize;i&lt;r;i++)this.array[t+i]=e.array[n+i];return this}copyArray(t){return this.array.set(t),this}applyMatrix3(t){if(2===this.itemSize)for(let e=0,n=this.count;e&lt;n;e++)yi.fromBufferAttribute(this,e),yi.applyMatrix3(t),this.setXY(e,yi.x,yi.y);else if(3===this.itemSize)for(let e=0,n=this.count;e&lt;n;e++)xi.fromBufferAttribute(this,e),xi.applyMatrix3(t),this.setXYZ(e,xi.x,xi.y,xi.z);return this}applyMatrix4(t){for(let e=0,n=this.count;e&lt;n;e++)xi.fromBufferAttribute(this,e),xi.applyMatrix4(t),this.setXYZ(e,xi.x,xi.y,xi.z);return this}applyNormalMatrix(t){for(let e=0,n=this.count;e&lt;n;e++)xi.fromBufferAttribute(this,e),xi.applyNormalMatrix(t),this.setXYZ(e,xi.x,xi.y,xi.z);return this}transformDirection(t){for(let e=0,n=this.count;e&lt;n;e++)xi.fromBufferAttribute(this,e),xi.transformDirection(t),this.setXYZ(e,xi.x,xi.y,xi.z);return this}set(t,e=0){return this.array.set(t,e),this}getComponent(t,e){let n=this.array[t*this.itemSize+e];return this.normalized&amp;&amp;(n=ue(n,this.array)),n}setComponent(t,e,n){return this.normalized&amp;&amp;(n=de(n,this.array)),this.array[t*this.itemSize+e]=n,this}getX(t){let e=this.array[t*this.itemSize];return this.normalized&amp;&amp;(e=ue(e,this.array)),e}setX(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.array[t*this.itemSize]=e,this}getY(t){let e=this.array[t*this.itemSize+1];return this.normalized&amp;&amp;(e=ue(e,this.array)),e}setY(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.array[t*this.itemSize+1]=e,this}getZ(t){let e=this.array[t*this.itemSize+2];return this.normalized&amp;&amp;(e=ue(e,this.array)),e}setZ(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.array[t*this.itemSize+2]=e,this}getW(t){let e=this.array[t*this.itemSize+3];return this.normalized&amp;&amp;(e=ue(e,this.array)),e}setW(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.array[t*this.itemSize+3]=e,this}setXY(t,e,n){return t*=this.itemSize,this.normalized&amp;&amp;(e=de(e,this.array),n=de(n,this.array)),this.array[t+0]=e,this.array[t+1]=n,this}setXYZ(t,e,n,i){return t*=this.itemSize,this.normalized&amp;&amp;(e=de(e,this.array),n=de(n,this.array),i=de(i,this.array)),this.array[t+0]=e,this.array[t+1]=n,this.array[t+2]=i,this}setXYZW(t,e,n,i,r){return t*=this.itemSize,this.normalized&amp;&amp;(e=de(e,this.array),n=de(n,this.array),i=de(i,this.array),r=de(r,this.array)),this.array[t+0]=e,this.array[t+1]=n,this.array[t+2]=i,this.array[t+3]=r,this}onUpload(t){return this.onUploadCallback=t,this}clone(){return new this.constructor(this.array,this.itemSize).copy(this)}toJSON(){const t={itemSize:this.itemSize,type:this.array.constructor.name,array:Array.from(this.array),normalized:this.normalized};return&quot;&quot;!==this.name&amp;&amp;(t.name=this.name),this.usage!==Zt&amp;&amp;(t.usage=this.usage),t}}class Si extends Mi{constructor(t,e,n){super(new Uint16Array(t),e,n)}}class bi extends Mi{constructor(t,e,n){super(new Uint32Array(t),e,n)}}class Ti extends Mi{constructor(t,e,n){super(new Float32Array(t),e,n)}}let Ei=0;const wi=new Mn,Ai=new jn,Ri=new We,Ci=new qe,Li=new qe,Pi=new We;class Ii extends te{constructor(){super(),this.isBufferGeometry=!0,Object.defineProperty(this,&quot;id&quot;,{value:Ei++}),this.uuid=se(),this.name=&quot;&quot;,this.type=&quot;BufferGeometry&quot;,this.index=null,this.attributes={},this.morphAttributes={},this.morphTargetsRelative=!1,this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.drawRange={start:0,count:1/0},this.userData={}}getIndex(){return this.index}setIndex(t){return Array.isArray(t)?this.index=new(_e(t)?bi:Si)(t,1):this.index=t,this}getAttribute(t){return this.attributes[t]}setAttribute(t,e){return this.attributes[t]=e,this}deleteAttribute(t){return delete this.attributes[t],this}hasAttribute(t){return void 0!==this.attributes[t]}addGroup(t,e,n=0){this.groups.push({start:t,count:e,materialIndex:n})}clearGroups(){this.groups=[]}setDrawRange(t,e){this.drawRange.start=t,this.drawRange.count=e}applyMatrix4(t){const e=this.attributes.position;void 0!==e&amp;&amp;(e.applyMatrix4(t),e.needsUpdate=!0);const n=this.attributes.normal;if(void 0!==n){const e=(new fe).getNormalMatrix(t);n.applyNormalMatrix(e),n.needsUpdate=!0}const i=this.attributes.tangent;return void 0!==i&amp;&amp;(i.transformDirection(t),i.needsUpdate=!0),null!==this.boundingBox&amp;&amp;this.computeBoundingBox(),null!==this.boundingSphere&amp;&amp;this.computeBoundingSphere(),this}applyQuaternion(t){return wi.makeRotationFromQuaternion(t),this.applyMatrix4(wi),this}rotateX(t){return wi.makeRotationX(t),this.applyMatrix4(wi),this}rotateY(t){return wi.makeRotationY(t),this.applyMatrix4(wi),this}rotateZ(t){return wi.makeRotationZ(t),this.applyMatrix4(wi),this}translate(t,e,n){return wi.makeTranslation(t,e,n),this.applyMatrix4(wi),this}scale(t,e,n){return wi.makeScale(t,e,n),this.applyMatrix4(wi),this}lookAt(t){return Ai.lookAt(t),Ai.updateMatrix(),this.applyMatrix4(Ai.matrix),this}center(){return this.computeBoundingBox(),this.boundingBox.getCenter(Ri).negate(),this.translate(Ri.x,Ri.y,Ri.z),this}setFromPoints(t){const e=[];for(let n=0,i=t.length;n&lt;i;n++){const i=t[n];e.push(i.x,i.y,i.z||0)}return this.setAttribute(&quot;position&quot;,new Ti(e,3)),this}computeBoundingBox(){null===this.boundingBox&amp;&amp;(this.boundingBox=new qe);const t=this.attributes.position,e=this.morphAttributes.position;if(t&amp;&amp;t.isGLBufferAttribute)return console.error('THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set &quot;mesh.frustumCulled&quot; to &quot;false&quot;.',this),void this.boundingBox.set(new We(-1/0,-1/0,-1/0),new We(1/0,1/0,1/0));if(void 0!==t){if(this.boundingBox.setFromBufferAttribute(t),e)for(let t=0,n=e.length;t&lt;n;t++){const n=e[t];Ci.setFromBufferAttribute(n),this.morphTargetsRelative?(Pi.addVectors(this.boundingBox.min,Ci.min),this.boundingBox.expandByPoint(Pi),Pi.addVectors(this.boundingBox.max,Ci.max),this.boundingBox.expandByPoint(Pi)):(this.boundingBox.expandByPoint(Ci.min),this.boundingBox.expandByPoint(Ci.max))}}else this.boundingBox.makeEmpty();(isNaN(this.boundingBox.min.x)||isNaN(this.boundingBox.min.y)||isNaN(this.boundingBox.min.z))&amp;&amp;console.error('THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The &quot;position&quot; attribute is likely to have NaN values.',this)}computeBoundingSphere(){null===this.boundingSphere&amp;&amp;(this.boundingSphere=new dn);const t=this.attributes.position,e=this.morphAttributes.position;if(t&amp;&amp;t.isGLBufferAttribute)return console.error('THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set &quot;mesh.frustumCulled&quot; to &quot;false&quot;.',this),void this.boundingSphere.set(new We,1/0);if(t){const n=this.boundingSphere.center;if(Ci.setFromBufferAttribute(t),e)for(let t=0,n=e.length;t&lt;n;t++){const n=e[t];Li.setFromBufferAttribute(n),this.morphTargetsRelative?(Pi.addVectors(Ci.min,Li.min),Ci.expandByPoint(Pi),Pi.addVectors(Ci.max,Li.max),Ci.expandByPoint(Pi)):(Ci.expandByPoint(Li.min),Ci.expandByPoint(Li.max))}Ci.getCenter(n);let i=0;for(let e=0,r=t.count;e&lt;r;e++)Pi.fromBufferAttribute(t,e),i=Math.max(i,n.distanceToSquared(Pi));if(e)for(let r=0,s=e.length;r&lt;s;r++){const s=e[r],a=this.morphTargetsRelative;for(let e=0,r=s.count;e&lt;r;e++)Pi.fromBufferAttribute(s,e),a&amp;&amp;(Ri.fromBufferAttribute(t,e),Pi.add(Ri)),i=Math.max(i,n.distanceToSquared(Pi))}this.boundingSphere.radius=Math.sqrt(i),isNaN(this.boundingSphere.radius)&amp;&amp;console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The &quot;position&quot; attribute is likely to have NaN values.',this)}}computeTangents(){const t=this.index,e=this.attributes;if(null===t||void 0===e.position||void 0===e.normal||void 0===e.uv)return void console.error(&quot;THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)&quot;);const n=t.array,i=e.position.array,r=e.normal.array,s=e.uv.array,a=i.length/3;!1===this.hasAttribute(&quot;tangent&quot;)&amp;&amp;this.setAttribute(&quot;tangent&quot;,new Mi(new Float32Array(4*a),4));const o=this.getAttribute(&quot;tangent&quot;).array,l=[],c=[];for(let t=0;t&lt;a;t++)l[t]=new We,c[t]=new We;const h=new We,u=new We,d=new We,p=new me,m=new me,f=new me,g=new We,_=new We;function v(t,e,n){h.fromArray(i,3*t),u.fromArray(i,3*e),d.fromArray(i,3*n),p.fromArray(s,2*t),m.fromArray(s,2*e),f.fromArray(s,2*n),u.sub(h),d.sub(h),m.sub(p),f.sub(p);const r=1/(m.x*f.y-f.x*m.y);isFinite(r)&amp;&amp;(g.copy(u).multiplyScalar(f.y).addScaledVector(d,-m.y).multiplyScalar(r),_.copy(d).multiplyScalar(m.x).addScaledVector(u,-f.x).multiplyScalar(r),l[t].add(g),l[e].add(g),l[n].add(g),c[t].add(_),c[e].add(_),c[n].add(_))}let x=this.groups;0===x.length&amp;&amp;(x=[{start:0,count:n.length}]);for(let t=0,e=x.length;t&lt;e;++t){const e=x[t],i=e.start;for(let t=i,r=i+e.count;t&lt;r;t+=3)v(n[t+0],n[t+1],n[t+2])}const y=new We,M=new We,S=new We,b=new We;function T(t){S.fromArray(r,3*t),b.copy(S);const e=l[t];y.copy(e),y.sub(S.multiplyScalar(S.dot(e))).normalize(),M.crossVectors(b,e);const n=M.dot(c[t])&lt;0?-1:1;o[4*t]=y.x,o[4*t+1]=y.y,o[4*t+2]=y.z,o[4*t+3]=n}for(let t=0,e=x.length;t&lt;e;++t){const e=x[t],i=e.start;for(let t=i,r=i+e.count;t&lt;r;t+=3)T(n[t+0]),T(n[t+1]),T(n[t+2])}}computeVertexNormals(){const t=this.index,e=this.getAttribute(&quot;position&quot;);if(void 0!==e){let n=this.getAttribute(&quot;normal&quot;);if(void 0===n)n=new Mi(new Float32Array(3*e.count),3),this.setAttribute(&quot;normal&quot;,n);else for(let t=0,e=n.count;t&lt;e;t++)n.setXYZ(t,0,0,0);const i=new We,r=new We,s=new We,a=new We,o=new We,l=new We,c=new We,h=new We;if(t)for(let u=0,d=t.count;u&lt;d;u+=3){const d=t.getX(u+0),p=t.getX(u+1),m=t.getX(u+2);i.fromBufferAttribute(e,d),r.fromBufferAttribute(e,p),s.fromBufferAttribute(e,m),c.subVectors(s,r),h.subVectors(i,r),c.cross(h),a.fromBufferAttribute(n,d),o.fromBufferAttribute(n,p),l.fromBufferAttribute(n,m),a.add(c),o.add(c),l.add(c),n.setXYZ(d,a.x,a.y,a.z),n.setXYZ(p,o.x,o.y,o.z),n.setXYZ(m,l.x,l.y,l.z)}else for(let t=0,a=e.count;t&lt;a;t+=3)i.fromBufferAttribute(e,t+0),r.fromBufferAttribute(e,t+1),s.fromBufferAttribute(e,t+2),c.subVectors(s,r),h.subVectors(i,r),c.cross(h),n.setXYZ(t+0,c.x,c.y,c.z),n.setXYZ(t+1,c.x,c.y,c.z),n.setXYZ(t+2,c.x,c.y,c.z);this.normalizeNormals(),n.needsUpdate=!0}}normalizeNormals(){const t=this.attributes.normal;for(let e=0,n=t.count;e&lt;n;e++)Pi.fromBufferAttribute(t,e),Pi.normalize(),t.setXYZ(e,Pi.x,Pi.y,Pi.z)}toNonIndexed(){function t(t,e){const n=t.array,i=t.itemSize,r=t.normalized,s=new n.constructor(e.length*i);let a=0,o=0;for(let r=0,l=e.length;r&lt;l;r++){a=t.isInterleavedBufferAttribute?e[r]*t.data.stride+t.offset:e[r]*i;for(let t=0;t&lt;i;t++)s[o++]=n[a++]}return new Mi(s,i,r)}if(null===this.index)return console.warn(&quot;THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.&quot;),this;const e=new Ii,n=this.index.array,i=this.attributes;for(const r in i){const s=t(i[r],n);e.setAttribute(r,s)}const r=this.morphAttributes;for(const i in r){const s=[],a=r[i];for(let e=0,i=a.length;e&lt;i;e++){const i=t(a[e],n);s.push(i)}e.morphAttributes[i]=s}e.morphTargetsRelative=this.morphTargetsRelative;const s=this.groups;for(let t=0,n=s.length;t&lt;n;t++){const n=s[t];e.addGroup(n.start,n.count,n.materialIndex)}return e}toJSON(){const t={metadata:{version:4.6,type:&quot;BufferGeometry&quot;,generator:&quot;BufferGeometry.toJSON&quot;}};if(t.uuid=this.uuid,t.type=this.type,&quot;&quot;!==this.name&amp;&amp;(t.name=this.name),Object.keys(this.userData).length&gt;0&amp;&amp;(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const n in e)void 0!==e[n]&amp;&amp;(t[n]=e[n]);return t}t.data={attributes:{}};const e=this.index;null!==e&amp;&amp;(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const n=this.attributes;for(const e in n){const i=n[e];t.data.attributes[e]=i.toJSON(t.data)}const i={};let r=!1;for(const e in this.morphAttributes){const n=this.morphAttributes[e],s=[];for(let e=0,i=n.length;e&lt;i;e++){const i=n[e];s.push(i.toJSON(t.data))}s.length&gt;0&amp;&amp;(i[e]=s,r=!0)}r&amp;&amp;(t.data.morphAttributes=i,t.data.morphTargetsRelative=this.morphTargetsRelative);const s=this.groups;s.length&gt;0&amp;&amp;(t.data.groups=JSON.parse(JSON.stringify(s)));const a=this.boundingSphere;return null!==a&amp;&amp;(t.data.boundingSphere={center:a.center.toArray(),radius:a.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const n=t.index;null!==n&amp;&amp;this.setIndex(n.clone(e));const i=t.attributes;for(const t in i){const n=i[t];this.setAttribute(t,n.clone(e))}const r=t.morphAttributes;for(const t in r){const n=[],i=r[t];for(let t=0,r=i.length;t&lt;r;t++)n.push(i[t].clone(e));this.morphAttributes[t]=n}this.morphTargetsRelative=t.morphTargetsRelative;const s=t.groups;for(let t=0,e=s.length;t&lt;e;t++){const e=s[t];this.addGroup(e.start,e.count,e.materialIndex)}const a=t.boundingBox;null!==a&amp;&amp;(this.boundingBox=a.clone());const o=t.boundingSphere;return null!==o&amp;&amp;(this.boundingSphere=o.clone()),this.drawRange.start=t.drawRange.start,this.drawRange.count=t.drawRange.count,this.userData=t.userData,this}dispose(){this.dispatchEvent({type:&quot;dispose&quot;})}}const Ui=new Mn,Di=new yn,Ni=new dn,Oi=new We,Fi=new We,Bi=new We,zi=new We,Gi=new We,Hi=new We,Vi=new me,ki=new me,Wi=new me,Xi=new We,ji=new We,qi=new We,Yi=new We,Zi=new We;class Ji extends jn{constructor(t=new Ii,e=new pi){super(),this.isMesh=!0,this.type=&quot;Mesh&quot;,this.geometry=t,this.material=e,this.updateMorphTargets()}copy(t,e){return super.copy(t,e),void 0!==t.morphTargetInfluences&amp;&amp;(this.morphTargetInfluences=t.morphTargetInfluences.slice()),void 0!==t.morphTargetDictionary&amp;&amp;(this.morphTargetDictionary=Object.assign({},t.morphTargetDictionary)),this.material=Array.isArray(t.material)?t.material.slice():t.material,this.geometry=t.geometry,this}updateMorphTargets(){const t=this.geometry.morphAttributes,e=Object.keys(t);if(e.length&gt;0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t&lt;e;t++){const e=n[t].name||String(t);this.morphTargetInfluences.push(0),this.morphTargetDictionary[e]=t}}}}getVertexPosition(t,e){const n=this.geometry,i=n.attributes.position,r=n.morphAttributes.position,s=n.morphTargetsRelative;e.fromBufferAttribute(i,t);const a=this.morphTargetInfluences;if(r&amp;&amp;a){Hi.set(0,0,0);for(let n=0,i=r.length;n&lt;i;n++){const i=a[n],o=r[n];0!==i&amp;&amp;(Gi.fromBufferAttribute(o,t),s?Hi.addScaledVector(Gi,i):Hi.addScaledVector(Gi.sub(e),i))}e.add(Hi)}return e}raycast(t,e){const n=this.geometry,i=this.material,r=this.matrixWorld;if(void 0!==i){if(null===n.boundingSphere&amp;&amp;n.computeBoundingSphere(),Ni.copy(n.boundingSphere),Ni.applyMatrix4(r),Di.copy(t.ray).recast(t.near),!1===Ni.containsPoint(Di.origin)){if(null===Di.intersectSphere(Ni,Oi))return;if(Di.origin.distanceToSquared(Oi)&gt;(t.far-t.near)**2)return}Ui.copy(r).invert(),Di.copy(t.ray).applyMatrix4(Ui),null!==n.boundingBox&amp;&amp;!1===Di.intersectsBox(n.boundingBox)||this._computeIntersections(t,e,Di)}}_computeIntersections(t,e,n){let i;const r=this.geometry,s=this.material,a=r.index,o=r.attributes.position,l=r.attributes.uv,c=r.attributes.uv1,h=r.attributes.normal,u=r.groups,d=r.drawRange;if(null!==a)if(Array.isArray(s))for(let r=0,o=u.length;r&lt;o;r++){const o=u[r],p=s[o.materialIndex];for(let r=Math.max(o.start,d.start),s=Math.min(a.count,Math.min(o.start+o.count,d.start+d.count));r&lt;s;r+=3){i=Ki(this,p,t,n,l,c,h,a.getX(r),a.getX(r+1),a.getX(r+2)),i&amp;&amp;(i.faceIndex=Math.floor(r/3),i.face.materialIndex=o.materialIndex,e.push(i))}}else{for(let r=Math.max(0,d.start),o=Math.min(a.count,d.start+d.count);r&lt;o;r+=3){i=Ki(this,s,t,n,l,c,h,a.getX(r),a.getX(r+1),a.getX(r+2)),i&amp;&amp;(i.faceIndex=Math.floor(r/3),e.push(i))}}else if(void 0!==o)if(Array.isArray(s))for(let r=0,a=u.length;r&lt;a;r++){const a=u[r],p=s[a.materialIndex];for(let r=Math.max(a.start,d.start),s=Math.min(o.count,Math.min(a.start+a.count,d.start+d.count));r&lt;s;r+=3){i=Ki(this,p,t,n,l,c,h,r,r+1,r+2),i&amp;&amp;(i.faceIndex=Math.floor(r/3),i.face.materialIndex=a.materialIndex,e.push(i))}}else{for(let r=Math.max(0,d.start),a=Math.min(o.count,d.start+d.count);r&lt;a;r+=3){i=Ki(this,s,t,n,l,c,h,r,r+1,r+2),i&amp;&amp;(i.faceIndex=Math.floor(r/3),e.push(i))}}}}function Ki(t,e,n,i,r,o,l,c,h,u){t.getVertexPosition(c,Fi),t.getVertexPosition(h,Bi),t.getVertexPosition(u,zi);const d=function(t,e,n,i,r,o,l,c){let h;if(h=e.side===a?i.intersectTriangle(l,o,r,!0,c):i.intersectTriangle(r,o,l,e.side===s,c),null===h)return null;Zi.copy(c),Zi.applyMatrix4(t.matrixWorld);const u=n.ray.origin.distanceTo(Zi);return u&lt;n.near||u&gt;n.far?null:{distance:u,point:Zi.clone(),object:t}}(t,e,n,i,Fi,Bi,zi,Yi);if(d){r&amp;&amp;(Vi.fromBufferAttribute(r,c),ki.fromBufferAttribute(r,h),Wi.fromBufferAttribute(r,u),d.uv=ri.getInterpolation(Yi,Fi,Bi,zi,Vi,ki,Wi,new me)),o&amp;&amp;(Vi.fromBufferAttribute(o,c),ki.fromBufferAttribute(o,h),Wi.fromBufferAttribute(o,u),d.uv1=ri.getInterpolation(Yi,Fi,Bi,zi,Vi,ki,Wi,new me),d.uv2=d.uv1),l&amp;&amp;(Xi.fromBufferAttribute(l,c),ji.fromBufferAttribute(l,h),qi.fromBufferAttribute(l,u),d.normal=ri.getInterpolation(Yi,Fi,Bi,zi,Xi,ji,qi,new We),d.normal.dot(i.direction)&gt;0&amp;&amp;d.normal.multiplyScalar(-1));const t={a:c,b:h,c:u,normal:new We,materialIndex:0};ri.getNormal(Fi,Bi,zi,t.normal),d.face=t}return d}class $i extends Ii{constructor(t=1,e=1,n=1,i=1,r=1,s=1){super(),this.type=&quot;BoxGeometry&quot;,this.parameters={width:t,height:e,depth:n,widthSegments:i,heightSegments:r,depthSegments:s};const a=this;i=Math.floor(i),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,n,i,r,s,p,m,f,g,_){const v=s/f,x=p/g,y=s/2,M=p/2,S=m/2,b=f+1,T=g+1;let E=0,w=0;const A=new We;for(let s=0;s&lt;T;s++){const a=s*x-M;for(let o=0;o&lt;b;o++){const u=o*v-y;A[t]=u*i,A[e]=a*r,A[n]=S,l.push(A.x,A.y,A.z),A[t]=0,A[e]=0,A[n]=m&gt;0?1:-1,c.push(A.x,A.y,A.z),h.push(o/f),h.push(1-s/g),E+=1}}for(let t=0;t&lt;g;t++)for(let e=0;e&lt;f;e++){const n=u+e+b*t,i=u+e+b*(t+1),r=u+(e+1)+b*(t+1),s=u+(e+1)+b*t;o.push(n,i,s),o.push(i,r,s),w+=6}a.addGroup(d,w,_),d+=w,u+=E}p(&quot;z&quot;,&quot;y&quot;,&quot;x&quot;,-1,-1,n,e,t,s,r,0),p(&quot;z&quot;,&quot;y&quot;,&quot;x&quot;,1,-1,n,e,-t,s,r,1),p(&quot;x&quot;,&quot;z&quot;,&quot;y&quot;,1,1,t,n,e,i,s,2),p(&quot;x&quot;,&quot;z&quot;,&quot;y&quot;,1,-1,t,n,-e,i,s,3),p(&quot;x&quot;,&quot;y&quot;,&quot;z&quot;,1,-1,t,e,n,i,r,4),p(&quot;x&quot;,&quot;y&quot;,&quot;z&quot;,-1,-1,t,e,-n,i,r,5),this.setIndex(o),this.setAttribute(&quot;position&quot;,new Ti(l,3)),this.setAttribute(&quot;normal&quot;,new Ti(c,3)),this.setAttribute(&quot;uv&quot;,new Ti(h,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new $i(t.width,t.height,t.depth,t.widthSegments,t.heightSegments,t.depthSegments)}}function Qi(t){const e={};for(const n in t){e[n]={};for(const i in t[n]){const r=t[n][i];r&amp;&amp;(r.isColor||r.isMatrix3||r.isMatrix4||r.isVector2||r.isVector3||r.isVector4||r.isTexture||r.isQuaternion)?r.isRenderTargetTexture?(console.warn(&quot;UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().&quot;),e[n][i]=null):e[n][i]=r.clone():Array.isArray(r)?e[n][i]=r.slice():e[n][i]=r}}return e}function tr(t){const e={};for(let n=0;n&lt;t.length;n++){const i=Qi(t[n]);for(const t in i)e[t]=i[t]}return e}function er(t){return null===t.getRenderTarget()?t.outputColorSpace:Re.workingColorSpace}const nr={clone:Qi,merge:tr};class ir extends di{constructor(t){super(),this.isShaderMaterial=!0,this.type=&quot;ShaderMaterial&quot;,this.defines={},this.uniforms={},this.uniformsGroups=[],this.vertexShader=&quot;void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}&quot;,this.fragmentShader=&quot;void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}&quot;,this.linewidth=1,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.clipping=!1,this.forceSinglePass=!0,this.extensions={derivatives:!1,fragDepth:!1,drawBuffers:!1,shaderTextureLOD:!1,clipCullDistance:!1},this.defaultAttributeValues={color:[1,1,1],uv:[0,0],uv1:[0,0]},this.index0AttributeName=void 0,this.uniformsNeedUpdate=!1,this.glslVersion=null,void 0!==t&amp;&amp;this.setValues(t)}copy(t){return super.copy(t),this.fragmentShader=t.fragmentShader,this.vertexShader=t.vertexShader,this.uniforms=Qi(t.uniforms),this.uniformsGroups=function(t){const e=[];for(let n=0;n&lt;t.length;n++)e.push(t[n].clone());return e}(t.uniformsGroups),this.defines=Object.assign({},t.defines),this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.fog=t.fog,this.lights=t.lights,this.clipping=t.clipping,this.extensions=Object.assign({},t.extensions),this.glslVersion=t.glslVersion,this}toJSON(t){const e=super.toJSON(t);e.glslVersion=this.glslVersion,e.uniforms={};for(const n in this.uniforms){const i=this.uniforms[n].value;i&amp;&amp;i.isTexture?e.uniforms[n]={type:&quot;t&quot;,value:i.toJSON(t).uuid}:i&amp;&amp;i.isColor?e.uniforms[n]={type:&quot;c&quot;,value:i.getHex()}:i&amp;&amp;i.isVector2?e.uniforms[n]={type:&quot;v2&quot;,value:i.toArray()}:i&amp;&amp;i.isVector3?e.uniforms[n]={type:&quot;v3&quot;,value:i.toArray()}:i&amp;&amp;i.isVector4?e.uniforms[n]={type:&quot;v4&quot;,value:i.toArray()}:i&amp;&amp;i.isMatrix3?e.uniforms[n]={type:&quot;m3&quot;,value:i.toArray()}:i&amp;&amp;i.isMatrix4?e.uniforms[n]={type:&quot;m4&quot;,value:i.toArray()}:e.uniforms[n]={value:i}}Object.keys(this.defines).length&gt;0&amp;&amp;(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader,e.lights=this.lights,e.clipping=this.clipping;const n={};for(const t in this.extensions)!0===this.extensions[t]&amp;&amp;(n[t]=!0);return Object.keys(n).length&gt;0&amp;&amp;(e.extensions=n),e}}class rr extends jn{constructor(){super(),this.isCamera=!0,this.type=&quot;Camera&quot;,this.matrixWorldInverse=new Mn,this.projectionMatrix=new Mn,this.projectionMatrixInverse=new Mn,this.coordinateSystem=$t}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this.coordinateSystem=t.coordinateSystem,this}getWorldDirection(t){return super.getWorldDirection(t).negate()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}class sr extends rr{constructor(t=50,e=1,n=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type=&quot;PerspectiveCamera&quot;,this.fov=t,this.zoom=1,this.near=n,this.far=i,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*re*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*ie*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*re*Math.atan(Math.tan(.5*ie*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(t,e,n,i,r,s){this.aspect=t/e,null===this.view&amp;&amp;(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&amp;&amp;(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*ie*this.fov)/this.zoom,n=2*e,i=this.aspect*n,r=-.5*i;const s=this.view;if(null!==this.view&amp;&amp;this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*i/t,e-=s.offsetY*n/a,i*=s.width/t,n*=s.height/a}const a=this.filmOffset;0!==a&amp;&amp;(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-n,t,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&amp;&amp;(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const ar=-90;class or extends jn{constructor(t,e,n){super(),this.type=&quot;CubeCamera&quot;,this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new sr(ar,1,t,e);i.layers=this.layers,this.add(i);const r=new sr(ar,1,t,e);r.layers=this.layers,this.add(r);const s=new sr(ar,1,t,e);s.layers=this.layers,this.add(s);const a=new sr(ar,1,t,e);a.layers=this.layers,this.add(a);const o=new sr(ar,1,t,e);o.layers=this.layers,this.add(o);const l=new sr(ar,1,t,e);l.layers=this.layers,this.add(l)}updateCoordinateSystem(){const t=this.coordinateSystem,e=this.children.concat(),[n,i,r,s,a,o]=e;for(const t of e)this.remove(t);if(t===$t)n.up.set(0,1,0),n.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),s.up.set(0,0,1),s.lookAt(0,-1,0),a.up.set(0,1,0),a.lookAt(0,0,1),o.up.set(0,1,0),o.lookAt(0,0,-1);else{if(t!==Qt)throw new Error(&quot;THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: &quot;+t);n.up.set(0,-1,0),n.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),s.up.set(0,0,-1),s.lookAt(0,-1,0),a.up.set(0,-1,0),a.lookAt(0,0,1),o.up.set(0,-1,0),o.lookAt(0,0,-1)}for(const t of e)this.add(t),t.updateMatrixWorld()}update(t,e){null===this.parent&amp;&amp;this.updateMatrixWorld();const{renderTarget:n,activeMipmapLevel:i}=this;this.coordinateSystem!==t.coordinateSystem&amp;&amp;(this.coordinateSystem=t.coordinateSystem,this.updateCoordinateSystem());const[r,s,a,o,l,c]=this.children,h=t.getRenderTarget(),u=t.getActiveCubeFace(),d=t.getActiveMipmapLevel(),p=t.xr.enabled;t.xr.enabled=!1;const m=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0,i),t.render(e,r),t.setRenderTarget(n,1,i),t.render(e,s),t.setRenderTarget(n,2,i),t.render(e,a),t.setRenderTarget(n,3,i),t.render(e,o),t.setRenderTarget(n,4,i),t.render(e,l),n.texture.generateMipmaps=m,t.setRenderTarget(n,5,i),t.render(e,c),t.setRenderTarget(h,u,d),t.xr.enabled=p,n.texture.needsPMREMUpdate=!0}}class lr extends Fe{constructor(t,e,n,i,r,s,a,o,l,c){super(t=void 0!==t?t:[],e=void 0!==e?e:b,n,i,r,s,a,o,l,c),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class cr extends Ge{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const n={width:t,height:t,depth:1},i=[n,n,n,n,n,n];void 0!==e.encoding&amp;&amp;(be(&quot;THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace.&quot;),e.colorSpace=e.encoding===Bt?Gt:zt),this.texture=new lr(i,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&amp;&amp;e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:D}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:&quot;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include &lt;begin_vertex&gt;\n\t\t\t\t\t#include &lt;project_vertex&gt;\n\n\t\t\t\t}\n\t\t\t&quot;,fragmentShader:&quot;\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include &lt;common&gt;\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t&quot;},i=new $i(5,5,5),r=new ir({name:&quot;CubemapFromEquirect&quot;,uniforms:Qi(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:a,blending:0});r.uniforms.tEquirect.value=e;const s=new Ji(i,r),o=e.minFilter;e.minFilter===O&amp;&amp;(e.minFilter=D);return new or(1,10,this).update(t,s),e.minFilter=o,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,n,i){const r=t.getRenderTarget();for(let r=0;r&lt;6;r++)t.setRenderTarget(this,r),t.clear(e,n,i);t.setRenderTarget(r)}}const hr=new We,ur=new We,dr=new fe;class pr{constructor(t=new We(1,0,0),e=0){this.isPlane=!0,this.normal=t,this.constant=e}set(t,e){return this.normal.copy(t),this.constant=e,this}setComponents(t,e,n,i){return this.normal.set(t,e,n),this.constant=i,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,n){const i=hr.subVectors(n,e).cross(ur.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(i,t),this}copy(t){return this.normal.copy(t.normal),this.constant=t.constant,this}normalize(){const t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(t){return this.normal.dot(t)+this.constant}distanceToSphere(t){return this.distanceToPoint(t.center)-t.radius}projectPoint(t,e){return e.copy(t).addScaledVector(this.normal,-this.distanceToPoint(t))}intersectLine(t,e){const n=t.delta(hr),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/i;return r&lt;0||r&gt;1?null:e.copy(t.start).addScaledVector(n,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e&lt;0&amp;&amp;n&gt;0||n&lt;0&amp;&amp;e&gt;0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||dr.getNormalMatrix(t),i=this.coplanarPoint(hr).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&amp;&amp;t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const mr=new dn,fr=new We;class gr{constructor(t=new pr,e=new pr,n=new pr,i=new pr,r=new pr,s=new pr){this.planes=[t,e,n,i,r,s]}set(t,e,n,i,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(n),a[3].copy(i),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let n=0;n&lt;6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t,e=2e3){const n=this.planes,i=t.elements,r=i[0],s=i[1],a=i[2],o=i[3],l=i[4],c=i[5],h=i[6],u=i[7],d=i[8],p=i[9],m=i[10],f=i[11],g=i[12],_=i[13],v=i[14],x=i[15];if(n[0].setComponents(o-r,u-l,f-d,x-g).normalize(),n[1].setComponents(o+r,u+l,f+d,x+g).normalize(),n[2].setComponents(o+s,u+c,f+p,x+_).normalize(),n[3].setComponents(o-s,u-c,f-p,x-_).normalize(),n[4].setComponents(o-a,u-h,f-m,x-v).normalize(),e===$t)n[5].setComponents(o+a,u+h,f+m,x+v).normalize();else{if(e!==Qt)throw new Error(&quot;THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: &quot;+e);n[5].setComponents(a,h,m,v).normalize()}return this}intersectsObject(t){if(void 0!==t.boundingSphere)null===t.boundingSphere&amp;&amp;t.computeBoundingSphere(),mr.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;null===e.boundingSphere&amp;&amp;e.computeBoundingSphere(),mr.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(mr)}intersectsSprite(t){return mr.center.set(0,0,0),mr.radius=.7071067811865476,mr.applyMatrix4(t.matrixWorld),this.intersectsSphere(mr)}intersectsSphere(t){const e=this.planes,n=t.center,i=-t.radius;for(let t=0;t&lt;6;t++){if(e[t].distanceToPoint(n)&lt;i)return!1}return!0}intersectsBox(t){const e=this.planes;for(let n=0;n&lt;6;n++){const i=e[n];if(fr.x=i.normal.x&gt;0?t.max.x:t.min.x,fr.y=i.normal.y&gt;0?t.max.y:t.min.y,fr.z=i.normal.z&gt;0?t.max.z:t.min.z,i.distanceToPoint(fr)&lt;0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n&lt;6;n++)if(e[n].distanceToPoint(t)&lt;0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function _r(){let t=null,e=!1,n=null,i=null;function r(e,s){n(e,s),i=t.requestAnimationFrame(r)}return{start:function(){!0!==e&amp;&amp;null!==n&amp;&amp;(i=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(i),e=!1},setAnimationLoop:function(t){n=t},setContext:function(e){t=e}}}function vr(t,e){const n=e.isWebGL2,i=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&amp;&amp;(t=t.data),i.get(t)},remove:function(e){e.isInterleavedBufferAttribute&amp;&amp;(e=e.data);const n=i.get(e);n&amp;&amp;(t.deleteBuffer(n.buffer),i.delete(e))},update:function(e,r){if(e.isGLBufferAttribute){const t=i.get(e);return void((!t||t.version&lt;e.version)&amp;&amp;i.set(e,{buffer:e.buffer,type:e.type,bytesPerElement:e.elementSize,version:e.version}))}e.isInterleavedBufferAttribute&amp;&amp;(e=e.data);const s=i.get(e);if(void 0===s)i.set(e,function(e,i){const r=e.array,s=e.usage,a=r.byteLength,o=t.createBuffer();let l;if(t.bindBuffer(i,o),t.bufferData(i,r,s),e.onUploadCallback(),r instanceof Float32Array)l=t.FLOAT;else if(r instanceof Uint16Array)if(e.isFloat16BufferAttribute){if(!n)throw new Error(&quot;THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.&quot;);l=t.HALF_FLOAT}else l=t.UNSIGNED_SHORT;else if(r instanceof Int16Array)l=t.SHORT;else if(r instanceof Uint32Array)l=t.UNSIGNED_INT;else if(r instanceof Int32Array)l=t.INT;else if(r instanceof Int8Array)l=t.BYTE;else if(r instanceof Uint8Array)l=t.UNSIGNED_BYTE;else{if(!(r instanceof Uint8ClampedArray))throw new Error(&quot;THREE.WebGLAttributes: Unsupported buffer data format: &quot;+r);l=t.UNSIGNED_BYTE}return{buffer:o,type:l,bytesPerElement:r.BYTES_PER_ELEMENT,version:e.version,size:a}}(e,r));else if(s.version&lt;e.version){if(s.size!==e.array.byteLength)throw new Error(&quot;THREE.WebGLAttributes: The size of the buffer attribute's array buffer does not match the original size. Resizing buffer attributes is not supported.&quot;);!function(e,i,r){const s=i.array,a=i._updateRange,o=i.updateRanges;if(t.bindBuffer(r,e),-1===a.count&amp;&amp;0===o.length&amp;&amp;t.bufferSubData(r,0,s),0!==o.length){for(let e=0,i=o.length;e&lt;i;e++){const i=o[e];n?t.bufferSubData(r,i.start*s.BYTES_PER_ELEMENT,s,i.start,i.count):t.bufferSubData(r,i.start*s.BYTES_PER_ELEMENT,s.subarray(i.start,i.start+i.count))}i.clearUpdateRanges()}-1!==a.count&amp;&amp;(n?t.bufferSubData(r,a.offset*s.BYTES_PER_ELEMENT,s,a.offset,a.count):t.bufferSubData(r,a.offset*s.BYTES_PER_ELEMENT,s.subarray(a.offset,a.offset+a.count)),a.count=-1),i.onUploadCallback()}(s.buffer,e,r),s.version=e.version}}}}class xr extends Ii{constructor(t=1,e=1,n=1,i=1){super(),this.type=&quot;PlaneGeometry&quot;,this.parameters={width:t,height:e,widthSegments:n,heightSegments:i};const r=t/2,s=e/2,a=Math.floor(n),o=Math.floor(i),l=a+1,c=o+1,h=t/a,u=e/o,d=[],p=[],m=[],f=[];for(let t=0;t&lt;c;t++){const e=t*u-s;for(let n=0;n&lt;l;n++){const i=n*h-r;p.push(i,-e,0),m.push(0,0,1),f.push(n/a),f.push(1-t/o)}}for(let t=0;t&lt;o;t++)for(let e=0;e&lt;a;e++){const n=e+l*t,i=e+l*(t+1),r=e+1+l*(t+1),s=e+1+l*t;d.push(n,i,s),d.push(i,r,s)}this.setIndex(d),this.setAttribute(&quot;position&quot;,new Ti(p,3)),this.setAttribute(&quot;normal&quot;,new Ti(m,3)),this.setAttribute(&quot;uv&quot;,new Ti(f,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new xr(t.width,t.height,t.widthSegments,t.heightSegments)}}const yr={alphahash_fragment:&quot;#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a &lt; getAlphaHashThreshold( vPosition ) ) discard;\n#endif&quot;,alphahash_pars_fragment:&quot;#ifdef USE_ALPHAHASH\n\tconst float ALPHA_HASH_SCALE = 0.05;\n\tfloat hash2D( vec2 value ) {\n\t\treturn fract( 1.0e4 * sin( 17.0 * value.x + 0.1 * value.y ) * ( 0.1 + abs( sin( 13.0 * value.y + value.x ) ) ) );\n\t}\n\tfloat hash3D( vec3 value ) {\n\t\treturn hash2D( vec2( hash2D( value.xy ), value.z ) );\n\t}\n\tfloat getAlphaHashThreshold( vec3 position ) {\n\t\tfloat maxDeriv = max(\n\t\t\tlength( dFdx( position.xyz ) ),\n\t\t\tlength( dFdy( position.xyz ) )\n\t\t);\n\t\tfloat pixScale = 1.0 / ( ALPHA_HASH_SCALE * maxDeriv );\n\t\tvec2 pixScales = vec2(\n\t\t\texp2( floor( log2( pixScale ) ) ),\n\t\t\texp2( ceil( log2( pixScale ) ) )\n\t\t);\n\t\tvec2 alpha = vec2(\n\t\t\thash3D( floor( pixScales.x * position.xyz ) ),\n\t\t\thash3D( floor( pixScales.y * position.xyz ) )\n\t\t);\n\t\tfloat lerpFactor = fract( log2( pixScale ) );\n\t\tfloat x = ( 1.0 - lerpFactor ) * alpha.x + lerpFactor * alpha.y;\n\t\tfloat a = min( lerpFactor, 1.0 - lerpFactor );\n\t\tvec3 cases = vec3(\n\t\t\tx * x / ( 2.0 * a * ( 1.0 - a ) ),\n\t\t\t( x - 0.5 * a ) / ( 1.0 - a ),\n\t\t\t1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )\n\t\t);\n\t\tfloat threshold = ( x &lt; ( 1.0 - a ) )\n\t\t\t? ( ( x &lt; a ) ? cases.x : cases.y )\n\t\t\t: cases.z;\n\t\treturn clamp( threshold , 1.0e-6, 1.0 );\n\t}\n#endif&quot;,alphamap_fragment:&quot;#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif&quot;,alphamap_pars_fragment:&quot;#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif&quot;,alphatest_fragment:&quot;#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a &lt; alphaTest ) discard;\n#endif&quot;,alphatest_pars_fragment:&quot;#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif&quot;,aomap_fragment:&quot;#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_CLEARCOAT ) \n\t\tclearcoatSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_SHEEN ) \n\t\tsheenSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_ENVMAP ) &amp;&amp; defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometryNormal, geometryViewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif&quot;,aomap_pars_fragment:&quot;#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif&quot;,batching_pars_vertex:&quot;#ifdef USE_BATCHING\n\tattribute float batchId;\n\tuniform highp sampler2D batchingTexture;\n\tmat4 getBatchingMatrix( const in float i ) {\n\t\tint size = textureSize( batchingTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( batchingTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( batchingTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( batchingTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( batchingTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif&quot;,batching_vertex:&quot;#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( batchId );\n#endif&quot;,begin_vertex:&quot;vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif&quot;,beginnormal_vertex:&quot;vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif&quot;,bsdfs:&quot;float G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n} // validated&quot;,iridescence_fragment:&quot;#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660,  0.0556434,\n\t\t-1.5371385,  1.8760108, -0.2040259,\n\t\t-0.4985314,  0.0415560,  1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq &lt; 0.0 ) {\n\t\t\treturn vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR &lt; outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] &lt; iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] &lt; iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] &lt; iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m &lt;= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif&quot;,bumpmap_pars_fragment:&quot;#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = normalize( dFdx( surf_pos.xyz ) );\n\t\tvec3 vSigmaY = normalize( dFdy( surf_pos.xyz ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif&quot;,clipping_planes_fragment:&quot;#if NUM_CLIPPING_PLANES &gt; 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i &lt; UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) &gt; plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES &lt; NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i &lt; NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) &gt; plane.w ) &amp;&amp; clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif&quot;,clipping_planes_pars_fragment:&quot;#if NUM_CLIPPING_PLANES &gt; 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif&quot;,clipping_planes_pars_vertex:&quot;#if NUM_CLIPPING_PLANES &gt; 0\n\tvarying vec3 vClipPosition;\n#endif&quot;,clipping_planes_vertex:&quot;#if NUM_CLIPPING_PLANES &gt; 0\n\tvClipPosition = - mvPosition.xyz;\n#endif&quot;,color_fragment:&quot;#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif&quot;,color_pars_fragment:&quot;#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif&quot;,color_pars_vertex:&quot;#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif&quot;,color_vertex:&quot;#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif&quot;,common:&quot;#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated&quot;,cube_uv_reflection_fragment:&quot;#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x &gt; absDirection.z ) {\n\t\t\tif ( absDirection.x &gt; absDirection.y )\n\t\t\t\tface = direction.x &gt; 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y &gt; 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z &gt; absDirection.y )\n\t\t\t\tface = direction.z &gt; 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y &gt; 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face &gt; 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness &gt;= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness &gt;= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness &gt;= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness &gt;= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif&quot;,defaultnormal_vertex:&quot;vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif&quot;,displacementmap_pars_vertex:&quot;#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif&quot;,displacementmap_vertex:&quot;#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif&quot;,emissivemap_fragment:&quot;#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif&quot;,emissivemap_pars_fragment:&quot;#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif&quot;,colorspace_fragment:&quot;gl_FragColor = linearToOutputTexel( gl_FragColor );&quot;,colorspace_pars_fragment:&quot;\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn sRGBTransferOETF( value );\n}&quot;,envmap_fragment:&quot;#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif&quot;,envmap_common_pars_fragment:&quot;#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif&quot;,envmap_pars_fragment:&quot;#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif&quot;,envmap_pars_vertex:&quot;#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif&quot;,envmap_physical_pars_fragment:&quot;#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif&quot;,envmap_vertex:&quot;#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif&quot;,fog_vertex:&quot;#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif&quot;,fog_pars_vertex:&quot;#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif&quot;,fog_fragment:&quot;#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif&quot;,fog_pars_fragment:&quot;#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif&quot;,gradientmap_pars_fragment:&quot;#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}&quot;,lightmap_fragment:&quot;#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif&quot;,lightmap_pars_fragment:&quot;#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif&quot;,lights_lambert_fragment:&quot;LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;&quot;,lights_lambert_pars_fragment:&quot;varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert&quot;,lights_pars_begin:&quot;uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance &gt; 0.0 &amp;&amp; decayExponent &gt; 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance &gt; 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS &gt; 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS &gt; 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS &gt; 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation &gt; 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS &gt; 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS &gt; 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif&quot;,lights_toon_fragment:&quot;ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;&quot;,lights_toon_pars_fragment:&quot;varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon&quot;,lights_phong_fragment:&quot;BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;&quot;,lights_phong_pars_fragment:&quot;varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong&quot;,lights_physical_fragment:&quot;PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif&quot;,lights_physical_pars_fragment:&quot;struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n    float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n    float x2 = x * x;\n    float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n    return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x &gt; 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) &lt; 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness &lt; 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness &lt; 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness &lt; 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS &gt; 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(    0, 1,    0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}&quot;,lights_fragment_begin:&quot;\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence &gt; 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS &gt; 0 ) &amp;&amp; defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) &amp;&amp; NUM_POINT_LIGHT_SHADOWS &gt; 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i &lt; NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) &amp;&amp; ( UNROLLED_LOOP_INDEX &lt; NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible &amp;&amp; receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS &gt; 0 ) &amp;&amp; defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) &amp;&amp; NUM_SPOT_LIGHT_SHADOWS &gt; 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i &lt; NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX &lt; NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX &lt; NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX &lt; NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) &amp;&amp; ( UNROLLED_LOOP_INDEX &lt; NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible &amp;&amp; receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS &gt; 0 ) &amp;&amp; defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) &amp;&amp; NUM_DIR_LIGHT_SHADOWS &gt; 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i &lt; NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) &amp;&amp; ( UNROLLED_LOOP_INDEX &lt; NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible &amp;&amp; receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS &gt; 0 ) &amp;&amp; defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i &lt; NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS &gt; 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i &lt; NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif&quot;,lights_fragment_maps:&quot;#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) &amp;&amp; defined( STANDARD ) &amp;&amp; defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) &amp;&amp; defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif&quot;,lights_fragment_end:&quot;#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif&quot;,logdepthbuf_fragment:&quot;#if defined( USE_LOGDEPTHBUF ) &amp;&amp; defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif&quot;,logdepthbuf_pars_fragment:&quot;#if defined( USE_LOGDEPTHBUF ) &amp;&amp; defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif&quot;,logdepthbuf_pars_vertex:&quot;#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif&quot;,logdepthbuf_vertex:&quot;#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif&quot;,map_fragment:&quot;#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif&quot;,map_pars_fragment:&quot;#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif&quot;,map_particle_fragment:&quot;#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif&quot;,map_particle_pars_fragment:&quot;#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif&quot;,metalnessmap_fragment:&quot;float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif&quot;,metalnessmap_pars_fragment:&quot;#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif&quot;,morphcolor_vertex:&quot;#if defined( USE_MORPHCOLORS ) &amp;&amp; defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i &lt; MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif&quot;,morphnormal_vertex:&quot;#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i &lt; MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif&quot;,morphtarget_pars_vertex:&quot;#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif&quot;,morphtarget_vertex:&quot;#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i &lt; MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif&quot;,normal_fragment_begin:&quot;float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) &amp;&amp; ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) &amp;&amp; ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;&quot;,normal_fragment_maps:&quot;#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif&quot;,normal_pars_fragment:&quot;#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif&quot;,normal_pars_vertex:&quot;#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif&quot;,normal_vertex:&quot;#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif&quot;,normalmap_pars_fragment:&quot;#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) &amp;&amp; ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif&quot;,clearcoat_normal_fragment_begin:&quot;#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif&quot;,clearcoat_normal_fragment_maps:&quot;#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif&quot;,clearcoat_pars_fragment:&quot;#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif&quot;,iridescence_pars_fragment:&quot;#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif&quot;,opaque_fragment:&quot;#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );&quot;,packing:&quot;vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}&quot;,premultiplied_alpha_fragment:&quot;#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif&quot;,project_vertex:&quot;vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;&quot;,dithering_fragment:&quot;#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif&quot;,dithering_pars_fragment:&quot;#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif&quot;,roughnessmap_fragment:&quot;float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif&quot;,roughnessmap_pars_fragment:&quot;#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif&quot;,shadowmap_pars_fragment:&quot;#if NUM_SPOT_LIGHT_COORDS &gt; 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS &gt; 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS &gt; 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS &gt; 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS &gt; 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x &gt;= 0.0 &amp;&amp; shadowCoord.x &lt;= 1.0 &amp;&amp; shadowCoord.y &gt;= 0.0 &amp;&amp; shadowCoord.y &lt;= 1.0;\n\t\tbool frustumTest = inFrustum &amp;&amp; shadowCoord.z &lt;= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t  texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t  f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t  texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t  f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z &gt;= almostOne ) {\n\t\t\tif ( v.z &gt; 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x &gt;= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y &gt;= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif&quot;,shadowmap_pars_vertex:&quot;#if NUM_SPOT_LIGHT_COORDS &gt; 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS &gt; 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS &gt; 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS &gt; 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif&quot;,shadowmap_vertex:&quot;#if ( defined( USE_SHADOWMAP ) &amp;&amp; ( NUM_DIR_LIGHT_SHADOWS &gt; 0 || NUM_POINT_LIGHT_SHADOWS &gt; 0 ) ) || ( NUM_SPOT_LIGHT_COORDS &gt; 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS &gt; 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i &lt; NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS &gt; 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i &lt; NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS &gt; 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i &lt; NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) &amp;&amp; UNROLLED_LOOP_INDEX &lt; NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif&quot;,shadowmask_pars_fragment:&quot;float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS &gt; 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i &lt; NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS &gt; 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i &lt; NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS &gt; 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i &lt; NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}&quot;,skinbase_vertex:&quot;#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif&quot;,skinning_pars_vertex:&quot;#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif&quot;,skinning_vertex:&quot;#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif&quot;,skinnormal_vertex:&quot;#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif&quot;,specularmap_fragment:&quot;float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif&quot;,specularmap_pars_fragment:&quot;#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif&quot;,tonemapping_fragment:&quot;#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif&quot;,tonemapping_pars_fragment:&quot;#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3(  1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108,  1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605,  1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor *= toneMappingExposure;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\treturn color;\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }&quot;,transmission_fragment:&quot;#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif&quot;,transmission_pars_fragment:&quot;#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a *  a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif&quot;,uv_pars_fragment:&quot;#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif&quot;,uv_pars_vertex:&quot;#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif&quot;,uv_vertex:&quot;#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif&quot;,worldpos_vertex:&quot;#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS &gt; 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif&quot;,background_vert:&quot;varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}&quot;,background_frag:&quot;uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n}&quot;,backgroundCube_vert:&quot;varying vec3 vWorldDirection;\n#include &lt;common&gt;\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\tgl_Position.z = gl_Position.w;\n}&quot;,backgroundCube_frag:&quot;#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include &lt;cube_uv_reflection_fragment&gt;\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n}&quot;,cube_vert:&quot;varying vec3 vWorldDirection;\n#include &lt;common&gt;\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\tgl_Position.z = gl_Position.w;\n}&quot;,cube_frag:&quot;uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n}&quot;,depth_vert:&quot;#include &lt;common&gt;\n#include &lt;batching_pars_vertex&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;displacementmap_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;skinning_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include &lt;uv_vertex&gt;\n\t#include &lt;batching_vertex&gt;\n\t#include &lt;skinbase_vertex&gt;\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include &lt;beginnormal_vertex&gt;\n\t\t#include &lt;morphnormal_vertex&gt;\n\t\t#include &lt;skinnormal_vertex&gt;\n\t#endif\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;skinning_vertex&gt;\n\t#include &lt;displacementmap_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\tvHighPrecisionZW = gl_Position.zw;\n}&quot;,depth_frag:&quot;#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include &lt;common&gt;\n#include &lt;packing&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;map_pars_fragment&gt;\n#include &lt;alphamap_pars_fragment&gt;\n#include &lt;alphatest_pars_fragment&gt;\n#include &lt;alphahash_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include &lt;map_fragment&gt;\n\t#include &lt;alphamap_fragment&gt;\n\t#include &lt;alphatest_fragment&gt;\n\t#include &lt;alphahash_fragment&gt;\n\t#include &lt;logdepthbuf_fragment&gt;\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}&quot;,distanceRGBA_vert:&quot;#define DISTANCE\nvarying vec3 vWorldPosition;\n#include &lt;common&gt;\n#include &lt;batching_pars_vertex&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;displacementmap_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;skinning_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvoid main() {\n\t#include &lt;uv_vertex&gt;\n\t#include &lt;batching_vertex&gt;\n\t#include &lt;skinbase_vertex&gt;\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include &lt;beginnormal_vertex&gt;\n\t\t#include &lt;morphnormal_vertex&gt;\n\t\t#include &lt;skinnormal_vertex&gt;\n\t#endif\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;skinning_vertex&gt;\n\t#include &lt;displacementmap_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;worldpos_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\tvWorldPosition = worldPosition.xyz;\n}&quot;,distanceRGBA_frag:&quot;#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include &lt;common&gt;\n#include &lt;packing&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;map_pars_fragment&gt;\n#include &lt;alphamap_pars_fragment&gt;\n#include &lt;alphatest_pars_fragment&gt;\n#include &lt;alphahash_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main () {\n\t#include &lt;clipping_planes_fragment&gt;\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include &lt;map_fragment&gt;\n\t#include &lt;alphamap_fragment&gt;\n\t#include &lt;alphatest_fragment&gt;\n\t#include &lt;alphahash_fragment&gt;\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}&quot;,equirect_vert:&quot;varying vec3 vWorldDirection;\n#include &lt;common&gt;\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;project_vertex&gt;\n}&quot;,equirect_frag:&quot;uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include &lt;common&gt;\nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n}&quot;,linedashed_vert:&quot;uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include &lt;common&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;color_pars_vertex&gt;\n#include &lt;fog_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include &lt;uv_vertex&gt;\n\t#include &lt;color_vertex&gt;\n\t#include &lt;morphcolor_vertex&gt;\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\t#include &lt;fog_vertex&gt;\n}&quot;,linedashed_frag:&quot;uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include &lt;common&gt;\n#include &lt;color_pars_fragment&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;map_pars_fragment&gt;\n#include &lt;fog_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\tif ( mod( vLineDistance, totalSize ) &gt; dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include &lt;logdepthbuf_fragment&gt;\n\t#include &lt;map_fragment&gt;\n\t#include &lt;color_fragment&gt;\n\toutgoingLight = diffuseColor.rgb;\n\t#include &lt;opaque_fragment&gt;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n\t#include &lt;fog_fragment&gt;\n\t#include &lt;premultiplied_alpha_fragment&gt;\n}&quot;,meshbasic_vert:&quot;#include &lt;common&gt;\n#include &lt;batching_pars_vertex&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;envmap_pars_vertex&gt;\n#include &lt;color_pars_vertex&gt;\n#include &lt;fog_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;skinning_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvoid main() {\n\t#include &lt;uv_vertex&gt;\n\t#include &lt;color_vertex&gt;\n\t#include &lt;morphcolor_vertex&gt;\n\t#include &lt;batching_vertex&gt;\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include &lt;beginnormal_vertex&gt;\n\t\t#include &lt;morphnormal_vertex&gt;\n\t\t#include &lt;skinbase_vertex&gt;\n\t\t#include &lt;skinnormal_vertex&gt;\n\t\t#include &lt;defaultnormal_vertex&gt;\n\t#endif\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;skinning_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\t#include &lt;worldpos_vertex&gt;\n\t#include &lt;envmap_vertex&gt;\n\t#include &lt;fog_vertex&gt;\n}&quot;,meshbasic_frag:&quot;uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include &lt;common&gt;\n#include &lt;dithering_pars_fragment&gt;\n#include &lt;color_pars_fragment&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;map_pars_fragment&gt;\n#include &lt;alphamap_pars_fragment&gt;\n#include &lt;alphatest_pars_fragment&gt;\n#include &lt;alphahash_pars_fragment&gt;\n#include &lt;aomap_pars_fragment&gt;\n#include &lt;lightmap_pars_fragment&gt;\n#include &lt;envmap_common_pars_fragment&gt;\n#include &lt;envmap_pars_fragment&gt;\n#include &lt;fog_pars_fragment&gt;\n#include &lt;specularmap_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include &lt;logdepthbuf_fragment&gt;\n\t#include &lt;map_fragment&gt;\n\t#include &lt;color_fragment&gt;\n\t#include &lt;alphamap_fragment&gt;\n\t#include &lt;alphatest_fragment&gt;\n\t#include &lt;alphahash_fragment&gt;\n\t#include &lt;specularmap_fragment&gt;\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include &lt;aomap_fragment&gt;\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include &lt;envmap_fragment&gt;\n\t#include &lt;opaque_fragment&gt;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n\t#include &lt;fog_fragment&gt;\n\t#include &lt;premultiplied_alpha_fragment&gt;\n\t#include &lt;dithering_fragment&gt;\n}&quot;,meshlambert_vert:&quot;#define LAMBERT\nvarying vec3 vViewPosition;\n#include &lt;common&gt;\n#include &lt;batching_pars_vertex&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;displacementmap_pars_vertex&gt;\n#include &lt;envmap_pars_vertex&gt;\n#include &lt;color_pars_vertex&gt;\n#include &lt;fog_pars_vertex&gt;\n#include &lt;normal_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;skinning_pars_vertex&gt;\n#include &lt;shadowmap_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvoid main() {\n\t#include &lt;uv_vertex&gt;\n\t#include &lt;color_vertex&gt;\n\t#include &lt;morphcolor_vertex&gt;\n\t#include &lt;batching_vertex&gt;\n\t#include &lt;beginnormal_vertex&gt;\n\t#include &lt;morphnormal_vertex&gt;\n\t#include &lt;skinbase_vertex&gt;\n\t#include &lt;skinnormal_vertex&gt;\n\t#include &lt;defaultnormal_vertex&gt;\n\t#include &lt;normal_vertex&gt;\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;skinning_vertex&gt;\n\t#include &lt;displacementmap_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\tvViewPosition = - mvPosition.xyz;\n\t#include &lt;worldpos_vertex&gt;\n\t#include &lt;envmap_vertex&gt;\n\t#include &lt;shadowmap_vertex&gt;\n\t#include &lt;fog_vertex&gt;\n}&quot;,meshlambert_frag:&quot;#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include &lt;common&gt;\n#include &lt;packing&gt;\n#include &lt;dithering_pars_fragment&gt;\n#include &lt;color_pars_fragment&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;map_pars_fragment&gt;\n#include &lt;alphamap_pars_fragment&gt;\n#include &lt;alphatest_pars_fragment&gt;\n#include &lt;alphahash_pars_fragment&gt;\n#include &lt;aomap_pars_fragment&gt;\n#include &lt;lightmap_pars_fragment&gt;\n#include &lt;emissivemap_pars_fragment&gt;\n#include &lt;envmap_common_pars_fragment&gt;\n#include &lt;envmap_pars_fragment&gt;\n#include &lt;fog_pars_fragment&gt;\n#include &lt;bsdfs&gt;\n#include &lt;lights_pars_begin&gt;\n#include &lt;normal_pars_fragment&gt;\n#include &lt;lights_lambert_pars_fragment&gt;\n#include &lt;shadowmap_pars_fragment&gt;\n#include &lt;bumpmap_pars_fragment&gt;\n#include &lt;normalmap_pars_fragment&gt;\n#include &lt;specularmap_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include &lt;logdepthbuf_fragment&gt;\n\t#include &lt;map_fragment&gt;\n\t#include &lt;color_fragment&gt;\n\t#include &lt;alphamap_fragment&gt;\n\t#include &lt;alphatest_fragment&gt;\n\t#include &lt;alphahash_fragment&gt;\n\t#include &lt;specularmap_fragment&gt;\n\t#include &lt;normal_fragment_begin&gt;\n\t#include &lt;normal_fragment_maps&gt;\n\t#include &lt;emissivemap_fragment&gt;\n\t#include &lt;lights_lambert_fragment&gt;\n\t#include &lt;lights_fragment_begin&gt;\n\t#include &lt;lights_fragment_maps&gt;\n\t#include &lt;lights_fragment_end&gt;\n\t#include &lt;aomap_fragment&gt;\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include &lt;envmap_fragment&gt;\n\t#include &lt;opaque_fragment&gt;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n\t#include &lt;fog_fragment&gt;\n\t#include &lt;premultiplied_alpha_fragment&gt;\n\t#include &lt;dithering_fragment&gt;\n}&quot;,meshmatcap_vert:&quot;#define MATCAP\nvarying vec3 vViewPosition;\n#include &lt;common&gt;\n#include &lt;batching_pars_vertex&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;color_pars_vertex&gt;\n#include &lt;displacementmap_pars_vertex&gt;\n#include &lt;fog_pars_vertex&gt;\n#include &lt;normal_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;skinning_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvoid main() {\n\t#include &lt;uv_vertex&gt;\n\t#include &lt;color_vertex&gt;\n\t#include &lt;morphcolor_vertex&gt;\n\t#include &lt;batching_vertex&gt;\n\t#include &lt;beginnormal_vertex&gt;\n\t#include &lt;morphnormal_vertex&gt;\n\t#include &lt;skinbase_vertex&gt;\n\t#include &lt;skinnormal_vertex&gt;\n\t#include &lt;defaultnormal_vertex&gt;\n\t#include &lt;normal_vertex&gt;\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;skinning_vertex&gt;\n\t#include &lt;displacementmap_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\t#include &lt;fog_vertex&gt;\n\tvViewPosition = - mvPosition.xyz;\n}&quot;,meshmatcap_frag:&quot;#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include &lt;common&gt;\n#include &lt;dithering_pars_fragment&gt;\n#include &lt;color_pars_fragment&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;map_pars_fragment&gt;\n#include &lt;alphamap_pars_fragment&gt;\n#include &lt;alphatest_pars_fragment&gt;\n#include &lt;alphahash_pars_fragment&gt;\n#include &lt;fog_pars_fragment&gt;\n#include &lt;normal_pars_fragment&gt;\n#include &lt;bumpmap_pars_fragment&gt;\n#include &lt;normalmap_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include &lt;logdepthbuf_fragment&gt;\n\t#include &lt;map_fragment&gt;\n\t#include &lt;color_fragment&gt;\n\t#include &lt;alphamap_fragment&gt;\n\t#include &lt;alphatest_fragment&gt;\n\t#include &lt;alphahash_fragment&gt;\n\t#include &lt;normal_fragment_begin&gt;\n\t#include &lt;normal_fragment_maps&gt;\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include &lt;opaque_fragment&gt;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n\t#include &lt;fog_fragment&gt;\n\t#include &lt;premultiplied_alpha_fragment&gt;\n\t#include &lt;dithering_fragment&gt;\n}&quot;,meshnormal_vert:&quot;#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include &lt;common&gt;\n#include &lt;batching_pars_vertex&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;displacementmap_pars_vertex&gt;\n#include &lt;normal_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;skinning_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvoid main() {\n\t#include &lt;uv_vertex&gt;\n\t#include &lt;batching_vertex&gt;\n\t#include &lt;beginnormal_vertex&gt;\n\t#include &lt;morphnormal_vertex&gt;\n\t#include &lt;skinbase_vertex&gt;\n\t#include &lt;skinnormal_vertex&gt;\n\t#include &lt;defaultnormal_vertex&gt;\n\t#include &lt;normal_vertex&gt;\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;skinning_vertex&gt;\n\t#include &lt;displacementmap_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}&quot;,meshnormal_frag:&quot;#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include &lt;packing&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;normal_pars_fragment&gt;\n#include &lt;bumpmap_pars_fragment&gt;\n#include &lt;normalmap_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\t#include &lt;logdepthbuf_fragment&gt;\n\t#include &lt;normal_fragment_begin&gt;\n\t#include &lt;normal_fragment_maps&gt;\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}&quot;,meshphong_vert:&quot;#define PHONG\nvarying vec3 vViewPosition;\n#include &lt;common&gt;\n#include &lt;batching_pars_vertex&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;displacementmap_pars_vertex&gt;\n#include &lt;envmap_pars_vertex&gt;\n#include &lt;color_pars_vertex&gt;\n#include &lt;fog_pars_vertex&gt;\n#include &lt;normal_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;skinning_pars_vertex&gt;\n#include &lt;shadowmap_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvoid main() {\n\t#include &lt;uv_vertex&gt;\n\t#include &lt;color_vertex&gt;\n\t#include &lt;morphcolor_vertex&gt;\n\t#include &lt;batching_vertex&gt;\n\t#include &lt;beginnormal_vertex&gt;\n\t#include &lt;morphnormal_vertex&gt;\n\t#include &lt;skinbase_vertex&gt;\n\t#include &lt;skinnormal_vertex&gt;\n\t#include &lt;defaultnormal_vertex&gt;\n\t#include &lt;normal_vertex&gt;\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;skinning_vertex&gt;\n\t#include &lt;displacementmap_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\tvViewPosition = - mvPosition.xyz;\n\t#include &lt;worldpos_vertex&gt;\n\t#include &lt;envmap_vertex&gt;\n\t#include &lt;shadowmap_vertex&gt;\n\t#include &lt;fog_vertex&gt;\n}&quot;,meshphong_frag:&quot;#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include &lt;common&gt;\n#include &lt;packing&gt;\n#include &lt;dithering_pars_fragment&gt;\n#include &lt;color_pars_fragment&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;map_pars_fragment&gt;\n#include &lt;alphamap_pars_fragment&gt;\n#include &lt;alphatest_pars_fragment&gt;\n#include &lt;alphahash_pars_fragment&gt;\n#include &lt;aomap_pars_fragment&gt;\n#include &lt;lightmap_pars_fragment&gt;\n#include &lt;emissivemap_pars_fragment&gt;\n#include &lt;envmap_common_pars_fragment&gt;\n#include &lt;envmap_pars_fragment&gt;\n#include &lt;fog_pars_fragment&gt;\n#include &lt;bsdfs&gt;\n#include &lt;lights_pars_begin&gt;\n#include &lt;normal_pars_fragment&gt;\n#include &lt;lights_phong_pars_fragment&gt;\n#include &lt;shadowmap_pars_fragment&gt;\n#include &lt;bumpmap_pars_fragment&gt;\n#include &lt;normalmap_pars_fragment&gt;\n#include &lt;specularmap_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include &lt;logdepthbuf_fragment&gt;\n\t#include &lt;map_fragment&gt;\n\t#include &lt;color_fragment&gt;\n\t#include &lt;alphamap_fragment&gt;\n\t#include &lt;alphatest_fragment&gt;\n\t#include &lt;alphahash_fragment&gt;\n\t#include &lt;specularmap_fragment&gt;\n\t#include &lt;normal_fragment_begin&gt;\n\t#include &lt;normal_fragment_maps&gt;\n\t#include &lt;emissivemap_fragment&gt;\n\t#include &lt;lights_phong_fragment&gt;\n\t#include &lt;lights_fragment_begin&gt;\n\t#include &lt;lights_fragment_maps&gt;\n\t#include &lt;lights_fragment_end&gt;\n\t#include &lt;aomap_fragment&gt;\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include &lt;envmap_fragment&gt;\n\t#include &lt;opaque_fragment&gt;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n\t#include &lt;fog_fragment&gt;\n\t#include &lt;premultiplied_alpha_fragment&gt;\n\t#include &lt;dithering_fragment&gt;\n}&quot;,meshphysical_vert:&quot;#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include &lt;common&gt;\n#include &lt;batching_pars_vertex&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;displacementmap_pars_vertex&gt;\n#include &lt;color_pars_vertex&gt;\n#include &lt;fog_pars_vertex&gt;\n#include &lt;normal_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;skinning_pars_vertex&gt;\n#include &lt;shadowmap_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvoid main() {\n\t#include &lt;uv_vertex&gt;\n\t#include &lt;color_vertex&gt;\n\t#include &lt;morphcolor_vertex&gt;\n\t#include &lt;batching_vertex&gt;\n\t#include &lt;beginnormal_vertex&gt;\n\t#include &lt;morphnormal_vertex&gt;\n\t#include &lt;skinbase_vertex&gt;\n\t#include &lt;skinnormal_vertex&gt;\n\t#include &lt;defaultnormal_vertex&gt;\n\t#include &lt;normal_vertex&gt;\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;skinning_vertex&gt;\n\t#include &lt;displacementmap_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\tvViewPosition = - mvPosition.xyz;\n\t#include &lt;worldpos_vertex&gt;\n\t#include &lt;shadowmap_vertex&gt;\n\t#include &lt;fog_vertex&gt;\n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}&quot;,meshphysical_frag:&quot;#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include &lt;common&gt;\n#include &lt;packing&gt;\n#include &lt;dithering_pars_fragment&gt;\n#include &lt;color_pars_fragment&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;map_pars_fragment&gt;\n#include &lt;alphamap_pars_fragment&gt;\n#include &lt;alphatest_pars_fragment&gt;\n#include &lt;alphahash_pars_fragment&gt;\n#include &lt;aomap_pars_fragment&gt;\n#include &lt;lightmap_pars_fragment&gt;\n#include &lt;emissivemap_pars_fragment&gt;\n#include &lt;iridescence_fragment&gt;\n#include &lt;cube_uv_reflection_fragment&gt;\n#include &lt;envmap_common_pars_fragment&gt;\n#include &lt;envmap_physical_pars_fragment&gt;\n#include &lt;fog_pars_fragment&gt;\n#include &lt;lights_pars_begin&gt;\n#include &lt;normal_pars_fragment&gt;\n#include &lt;lights_physical_pars_fragment&gt;\n#include &lt;transmission_pars_fragment&gt;\n#include &lt;shadowmap_pars_fragment&gt;\n#include &lt;bumpmap_pars_fragment&gt;\n#include &lt;normalmap_pars_fragment&gt;\n#include &lt;clearcoat_pars_fragment&gt;\n#include &lt;iridescence_pars_fragment&gt;\n#include &lt;roughnessmap_pars_fragment&gt;\n#include &lt;metalnessmap_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include &lt;logdepthbuf_fragment&gt;\n\t#include &lt;map_fragment&gt;\n\t#include &lt;color_fragment&gt;\n\t#include &lt;alphamap_fragment&gt;\n\t#include &lt;alphatest_fragment&gt;\n\t#include &lt;alphahash_fragment&gt;\n\t#include &lt;roughnessmap_fragment&gt;\n\t#include &lt;metalnessmap_fragment&gt;\n\t#include &lt;normal_fragment_begin&gt;\n\t#include &lt;normal_fragment_maps&gt;\n\t#include &lt;clearcoat_normal_fragment_begin&gt;\n\t#include &lt;clearcoat_normal_fragment_maps&gt;\n\t#include &lt;emissivemap_fragment&gt;\n\t#include &lt;lights_physical_fragment&gt;\n\t#include &lt;lights_fragment_begin&gt;\n\t#include &lt;lights_fragment_maps&gt;\n\t#include &lt;lights_fragment_end&gt;\n\t#include &lt;aomap_fragment&gt;\n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include &lt;transmission_fragment&gt;\n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include &lt;opaque_fragment&gt;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n\t#include &lt;fog_fragment&gt;\n\t#include &lt;premultiplied_alpha_fragment&gt;\n\t#include &lt;dithering_fragment&gt;\n}&quot;,meshtoon_vert:&quot;#define TOON\nvarying vec3 vViewPosition;\n#include &lt;common&gt;\n#include &lt;batching_pars_vertex&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;displacementmap_pars_vertex&gt;\n#include &lt;color_pars_vertex&gt;\n#include &lt;fog_pars_vertex&gt;\n#include &lt;normal_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;skinning_pars_vertex&gt;\n#include &lt;shadowmap_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvoid main() {\n\t#include &lt;uv_vertex&gt;\n\t#include &lt;color_vertex&gt;\n\t#include &lt;morphcolor_vertex&gt;\n\t#include &lt;batching_vertex&gt;\n\t#include &lt;beginnormal_vertex&gt;\n\t#include &lt;morphnormal_vertex&gt;\n\t#include &lt;skinbase_vertex&gt;\n\t#include &lt;skinnormal_vertex&gt;\n\t#include &lt;defaultnormal_vertex&gt;\n\t#include &lt;normal_vertex&gt;\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;skinning_vertex&gt;\n\t#include &lt;displacementmap_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\tvViewPosition = - mvPosition.xyz;\n\t#include &lt;worldpos_vertex&gt;\n\t#include &lt;shadowmap_vertex&gt;\n\t#include &lt;fog_vertex&gt;\n}&quot;,meshtoon_frag:&quot;#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include &lt;common&gt;\n#include &lt;packing&gt;\n#include &lt;dithering_pars_fragment&gt;\n#include &lt;color_pars_fragment&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;map_pars_fragment&gt;\n#include &lt;alphamap_pars_fragment&gt;\n#include &lt;alphatest_pars_fragment&gt;\n#include &lt;alphahash_pars_fragment&gt;\n#include &lt;aomap_pars_fragment&gt;\n#include &lt;lightmap_pars_fragment&gt;\n#include &lt;emissivemap_pars_fragment&gt;\n#include &lt;gradientmap_pars_fragment&gt;\n#include &lt;fog_pars_fragment&gt;\n#include &lt;bsdfs&gt;\n#include &lt;lights_pars_begin&gt;\n#include &lt;normal_pars_fragment&gt;\n#include &lt;lights_toon_pars_fragment&gt;\n#include &lt;shadowmap_pars_fragment&gt;\n#include &lt;bumpmap_pars_fragment&gt;\n#include &lt;normalmap_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include &lt;logdepthbuf_fragment&gt;\n\t#include &lt;map_fragment&gt;\n\t#include &lt;color_fragment&gt;\n\t#include &lt;alphamap_fragment&gt;\n\t#include &lt;alphatest_fragment&gt;\n\t#include &lt;alphahash_fragment&gt;\n\t#include &lt;normal_fragment_begin&gt;\n\t#include &lt;normal_fragment_maps&gt;\n\t#include &lt;emissivemap_fragment&gt;\n\t#include &lt;lights_toon_fragment&gt;\n\t#include &lt;lights_fragment_begin&gt;\n\t#include &lt;lights_fragment_maps&gt;\n\t#include &lt;lights_fragment_end&gt;\n\t#include &lt;aomap_fragment&gt;\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include &lt;opaque_fragment&gt;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n\t#include &lt;fog_fragment&gt;\n\t#include &lt;premultiplied_alpha_fragment&gt;\n\t#include &lt;dithering_fragment&gt;\n}&quot;,points_vert:&quot;uniform float size;\nuniform float scale;\n#include &lt;common&gt;\n#include &lt;color_pars_vertex&gt;\n#include &lt;fog_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include &lt;color_vertex&gt;\n\t#include &lt;morphcolor_vertex&gt;\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\t#include &lt;worldpos_vertex&gt;\n\t#include &lt;fog_vertex&gt;\n}&quot;,points_frag:&quot;uniform vec3 diffuse;\nuniform float opacity;\n#include &lt;common&gt;\n#include &lt;color_pars_fragment&gt;\n#include &lt;map_particle_pars_fragment&gt;\n#include &lt;alphatest_pars_fragment&gt;\n#include &lt;alphahash_pars_fragment&gt;\n#include &lt;fog_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include &lt;logdepthbuf_fragment&gt;\n\t#include &lt;map_particle_fragment&gt;\n\t#include &lt;color_fragment&gt;\n\t#include &lt;alphatest_fragment&gt;\n\t#include &lt;alphahash_fragment&gt;\n\toutgoingLight = diffuseColor.rgb;\n\t#include &lt;opaque_fragment&gt;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n\t#include &lt;fog_fragment&gt;\n\t#include &lt;premultiplied_alpha_fragment&gt;\n}&quot;,shadow_vert:&quot;#include &lt;common&gt;\n#include &lt;batching_pars_vertex&gt;\n#include &lt;fog_pars_vertex&gt;\n#include &lt;morphtarget_pars_vertex&gt;\n#include &lt;skinning_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;shadowmap_pars_vertex&gt;\nvoid main() {\n\t#include &lt;batching_vertex&gt;\n\t#include &lt;beginnormal_vertex&gt;\n\t#include &lt;morphnormal_vertex&gt;\n\t#include &lt;skinbase_vertex&gt;\n\t#include &lt;skinnormal_vertex&gt;\n\t#include &lt;defaultnormal_vertex&gt;\n\t#include &lt;begin_vertex&gt;\n\t#include &lt;morphtarget_vertex&gt;\n\t#include &lt;skinning_vertex&gt;\n\t#include &lt;project_vertex&gt;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;worldpos_vertex&gt;\n\t#include &lt;shadowmap_vertex&gt;\n\t#include &lt;fog_vertex&gt;\n}&quot;,shadow_frag:&quot;uniform vec3 color;\nuniform float opacity;\n#include &lt;common&gt;\n#include &lt;packing&gt;\n#include &lt;fog_pars_fragment&gt;\n#include &lt;bsdfs&gt;\n#include &lt;lights_pars_begin&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;shadowmap_pars_fragment&gt;\n#include &lt;shadowmask_pars_fragment&gt;\nvoid main() {\n\t#include &lt;logdepthbuf_fragment&gt;\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n\t#include &lt;fog_fragment&gt;\n}&quot;,sprite_vert:&quot;uniform float rotation;\nuniform vec2 center;\n#include &lt;common&gt;\n#include &lt;uv_pars_vertex&gt;\n#include &lt;fog_pars_vertex&gt;\n#include &lt;logdepthbuf_pars_vertex&gt;\n#include &lt;clipping_planes_pars_vertex&gt;\nvoid main() {\n\t#include &lt;uv_vertex&gt;\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include &lt;logdepthbuf_vertex&gt;\n\t#include &lt;clipping_planes_vertex&gt;\n\t#include &lt;fog_vertex&gt;\n}&quot;,sprite_frag:&quot;uniform vec3 diffuse;\nuniform float opacity;\n#include &lt;common&gt;\n#include &lt;uv_pars_fragment&gt;\n#include &lt;map_pars_fragment&gt;\n#include &lt;alphamap_pars_fragment&gt;\n#include &lt;alphatest_pars_fragment&gt;\n#include &lt;alphahash_pars_fragment&gt;\n#include &lt;fog_pars_fragment&gt;\n#include &lt;logdepthbuf_pars_fragment&gt;\n#include &lt;clipping_planes_pars_fragment&gt;\nvoid main() {\n\t#include &lt;clipping_planes_fragment&gt;\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include &lt;logdepthbuf_fragment&gt;\n\t#include &lt;map_fragment&gt;\n\t#include &lt;alphamap_fragment&gt;\n\t#include &lt;alphatest_fragment&gt;\n\t#include &lt;alphahash_fragment&gt;\n\toutgoingLight = diffuseColor.rgb;\n\t#include &lt;opaque_fragment&gt;\n\t#include &lt;tonemapping_fragment&gt;\n\t#include &lt;colorspace_fragment&gt;\n\t#include &lt;fog_fragment&gt;\n}&quot;},Mr={common:{diffuse:{value:new ci(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new fe},alphaMap:{value:null},alphaMapTransform:{value:new fe},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new fe}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new fe}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new fe}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new fe},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new fe},normalScale:{value:new me(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new fe},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new fe}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new fe}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new fe}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new ci(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new ci(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new fe},alphaTest:{value:0},uvTransform:{value:new fe}},sprite:{diffuse:{value:new ci(16777215)},opacity:{value:1},center:{value:new me(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new fe},alphaMap:{value:null},alphaMapTransform:{value:new fe},alphaTest:{value:0}}},Sr={basic:{uniforms:tr([Mr.common,Mr.specularmap,Mr.envmap,Mr.aomap,Mr.lightmap,Mr.fog]),vertexShader:yr.meshbasic_vert,fragmentShader:yr.meshbasic_frag},lambert:{uniforms:tr([Mr.common,Mr.specularmap,Mr.envmap,Mr.aomap,Mr.lightmap,Mr.emissivemap,Mr.bumpmap,Mr.normalmap,Mr.displacementmap,Mr.fog,Mr.lights,{emissive:{value:new ci(0)}}]),vertexShader:yr.meshlambert_vert,fragmentShader:yr.meshlambert_frag},phong:{uniforms:tr([Mr.common,Mr.specularmap,Mr.envmap,Mr.aomap,Mr.lightmap,Mr.emissivemap,Mr.bumpmap,Mr.normalmap,Mr.displacementmap,Mr.fog,Mr.lights,{emissive:{value:new ci(0)},specular:{value:new ci(1118481)},shininess:{value:30}}]),vertexShader:yr.meshphong_vert,fragmentShader:yr.meshphong_frag},standard:{uniforms:tr([Mr.common,Mr.envmap,Mr.aomap,Mr.lightmap,Mr.emissivemap,Mr.bumpmap,Mr.normalmap,Mr.displacementmap,Mr.roughnessmap,Mr.metalnessmap,Mr.fog,Mr.lights,{emissive:{value:new ci(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:yr.meshphysical_vert,fragmentShader:yr.meshphysical_frag},toon:{uniforms:tr([Mr.common,Mr.aomap,Mr.lightmap,Mr.emissivemap,Mr.bumpmap,Mr.normalmap,Mr.displacementmap,Mr.gradientmap,Mr.fog,Mr.lights,{emissive:{value:new ci(0)}}]),vertexShader:yr.meshtoon_vert,fragmentShader:yr.meshtoon_frag},matcap:{uniforms:tr([Mr.common,Mr.bumpmap,Mr.normalmap,Mr.displacementmap,Mr.fog,{matcap:{value:null}}]),vertexShader:yr.meshmatcap_vert,fragmentShader:yr.meshmatcap_frag},points:{uniforms:tr([Mr.points,Mr.fog]),vertexShader:yr.points_vert,fragmentShader:yr.points_frag},dashed:{uniforms:tr([Mr.common,Mr.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:yr.linedashed_vert,fragmentShader:yr.linedashed_frag},depth:{uniforms:tr([Mr.common,Mr.displacementmap]),vertexShader:yr.depth_vert,fragmentShader:yr.depth_frag},normal:{uniforms:tr([Mr.common,Mr.bumpmap,Mr.normalmap,Mr.displacementmap,{opacity:{value:1}}]),vertexShader:yr.meshnormal_vert,fragmentShader:yr.meshnormal_frag},sprite:{uniforms:tr([Mr.sprite,Mr.fog]),vertexShader:yr.sprite_vert,fragmentShader:yr.sprite_frag},background:{uniforms:{uvTransform:{value:new fe},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:yr.background_vert,fragmentShader:yr.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1}},vertexShader:yr.backgroundCube_vert,fragmentShader:yr.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:yr.cube_vert,fragmentShader:yr.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:yr.equirect_vert,fragmentShader:yr.equirect_frag},distanceRGBA:{uniforms:tr([Mr.common,Mr.displacementmap,{referencePosition:{value:new We},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:yr.distanceRGBA_vert,fragmentShader:yr.distanceRGBA_frag},shadow:{uniforms:tr([Mr.lights,Mr.fog,{color:{value:new ci(0)},opacity:{value:1}}]),vertexShader:yr.shadow_vert,fragmentShader:yr.shadow_frag}};Sr.physical={uniforms:tr([Sr.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new fe},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new fe},clearcoatNormalScale:{value:new me(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new fe},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new fe},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new fe},sheen:{value:0},sheenColor:{value:new ci(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new fe},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new fe},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new fe},transmissionSamplerSize:{value:new me},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new fe},attenuationDistance:{value:0},attenuationColor:{value:new ci(0)},specularColor:{value:new ci(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new fe},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new fe},anisotropyVector:{value:new me},anisotropyMap:{value:null},anisotropyMapTransform:{value:new fe}}]),vertexShader:yr.meshphysical_vert,fragmentShader:yr.meshphysical_frag};const br={r:0,b:0,g:0};function Tr(t,e,n,i,r,o,l){const c=new ci(0);let h,u,d=!0===o?0:1,p=null,m=0,f=null;function g(e,n){e.getRGB(br,er(t)),i.buffers.color.setClear(br.r,br.g,br.b,n,l)}return{getClearColor:function(){return c},setClearColor:function(t,e=1){c.set(t),d=e,g(c,d)},getClearAlpha:function(){return d},setClearAlpha:function(t){d=t,g(c,d)},render:function(o,_){let v=!1,x=!0===_.isScene?_.background:null;if(x&amp;&amp;x.isTexture){x=(_.backgroundBlurriness&gt;0?n:e).get(x)}null===x?g(c,d):x&amp;&amp;x.isColor&amp;&amp;(g(x,1),v=!0);const y=t.xr.getEnvironmentBlendMode();&quot;additive&quot;===y?i.buffers.color.setClear(0,0,0,1,l):&quot;alpha-blend&quot;===y&amp;&amp;i.buffers.color.setClear(0,0,0,0,l),(t.autoClear||v)&amp;&amp;t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),x&amp;&amp;(x.isCubeTexture||x.mapping===A)?(void 0===u&amp;&amp;(u=new Ji(new $i(1,1,1),new ir({name:&quot;BackgroundCubeMaterial&quot;,uniforms:Qi(Sr.backgroundCube.uniforms),vertexShader:Sr.backgroundCube.vertexShader,fragmentShader:Sr.backgroundCube.fragmentShader,side:a,depthTest:!1,depthWrite:!1,fog:!1})),u.geometry.deleteAttribute(&quot;normal&quot;),u.geometry.deleteAttribute(&quot;uv&quot;),u.onBeforeRender=function(t,e,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(u.material,&quot;envMap&quot;,{get:function(){return this.uniforms.envMap.value}}),r.update(u)),u.material.uniforms.envMap.value=x,u.material.uniforms.flipEnvMap.value=x.isCubeTexture&amp;&amp;!1===x.isRenderTargetTexture?-1:1,u.material.uniforms.backgroundBlurriness.value=_.backgroundBlurriness,u.material.uniforms.backgroundIntensity.value=_.backgroundIntensity,u.material.toneMapped=Re.getTransfer(x.colorSpace)!==Xt,p===x&amp;&amp;m===x.version&amp;&amp;f===t.toneMapping||(u.material.needsUpdate=!0,p=x,m=x.version,f=t.toneMapping),u.layers.enableAll(),o.unshift(u,u.geometry,u.material,0,0,null)):x&amp;&amp;x.isTexture&amp;&amp;(void 0===h&amp;&amp;(h=new Ji(new xr(2,2),new ir({name:&quot;BackgroundMaterial&quot;,uniforms:Qi(Sr.background.uniforms),vertexShader:Sr.background.vertexShader,fragmentShader:Sr.background.fragmentShader,side:s,depthTest:!1,depthWrite:!1,fog:!1})),h.geometry.deleteAttribute(&quot;normal&quot;),Object.defineProperty(h.material,&quot;map&quot;,{get:function(){return this.uniforms.t2D.value}}),r.update(h)),h.material.uniforms.t2D.value=x,h.material.uniforms.backgroundIntensity.value=_.backgroundIntensity,h.material.toneMapped=Re.getTransfer(x.colorSpace)!==Xt,!0===x.matrixAutoUpdate&amp;&amp;x.updateMatrix(),h.material.uniforms.uvTransform.value.copy(x.matrix),p===x&amp;&amp;m===x.version&amp;&amp;f===t.toneMapping||(h.material.needsUpdate=!0,p=x,m=x.version,f=t.toneMapping),h.layers.enableAll(),o.unshift(h,h.geometry,h.material,0,0,null))}}}function Er(t,e,n,i){const r=t.getParameter(t.MAX_VERTEX_ATTRIBS),s=i.isWebGL2?null:e.get(&quot;OES_vertex_array_object&quot;),a=i.isWebGL2||null!==s,o={},l=p(null);let c=l,h=!1;function u(e){return i.isWebGL2?t.bindVertexArray(e):s.bindVertexArrayOES(e)}function d(e){return i.isWebGL2?t.deleteVertexArray(e):s.deleteVertexArrayOES(e)}function p(t){const e=[],n=[],i=[];for(let t=0;t&lt;r;t++)e[t]=0,n[t]=0,i[t]=0;return{geometry:null,program:null,wireframe:!1,newAttributes:e,enabledAttributes:n,attributeDivisors:i,object:t,attributes:{},index:null}}function m(){const t=c.newAttributes;for(let e=0,n=t.length;e&lt;n;e++)t[e]=0}function f(t){g(t,0)}function g(n,r){const s=c.newAttributes,a=c.enabledAttributes,o=c.attributeDivisors;if(s[n]=1,0===a[n]&amp;&amp;(t.enableVertexAttribArray(n),a[n]=1),o[n]!==r){(i.isWebGL2?t:e.get(&quot;ANGLE_instanced_arrays&quot;))[i.isWebGL2?&quot;vertexAttribDivisor&quot;:&quot;vertexAttribDivisorANGLE&quot;](n,r),o[n]=r}}function _(){const e=c.newAttributes,n=c.enabledAttributes;for(let i=0,r=n.length;i&lt;r;i++)n[i]!==e[i]&amp;&amp;(t.disableVertexAttribArray(i),n[i]=0)}function v(e,n,i,r,s,a,o){!0===o?t.vertexAttribIPointer(e,n,i,s,a):t.vertexAttribPointer(e,n,i,r,s,a)}function x(){y(),h=!0,c!==l&amp;&amp;(c=l,u(c.object))}function y(){l.geometry=null,l.program=null,l.wireframe=!1}return{setup:function(r,l,d,x,y){let M=!1;if(a){const e=function(e,n,r){const a=!0===r.wireframe;let l=o[e.id];void 0===l&amp;&amp;(l={},o[e.id]=l);let c=l[n.id];void 0===c&amp;&amp;(c={},l[n.id]=c);let h=c[a];void 0===h&amp;&amp;(h=p(i.isWebGL2?t.createVertexArray():s.createVertexArrayOES()),c[a]=h);return h}(x,d,l);c!==e&amp;&amp;(c=e,u(c.object)),M=function(t,e,n,i){const r=c.attributes,s=e.attributes;let a=0;const o=n.getAttributes();for(const e in o){if(o[e].location&gt;=0){const n=r[e];let i=s[e];if(void 0===i&amp;&amp;(&quot;instanceMatrix&quot;===e&amp;&amp;t.instanceMatrix&amp;&amp;(i=t.instanceMatrix),&quot;instanceColor&quot;===e&amp;&amp;t.instanceColor&amp;&amp;(i=t.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&amp;&amp;n.data!==i.data)return!0;a++}}return c.attributesNum!==a||c.index!==i}(r,x,d,y),M&amp;&amp;function(t,e,n,i){const r={},s=e.attributes;let a=0;const o=n.getAttributes();for(const e in o){if(o[e].location&gt;=0){let n=s[e];void 0===n&amp;&amp;(&quot;instanceMatrix&quot;===e&amp;&amp;t.instanceMatrix&amp;&amp;(n=t.instanceMatrix),&quot;instanceColor&quot;===e&amp;&amp;t.instanceColor&amp;&amp;(n=t.instanceColor));const i={};i.attribute=n,n&amp;&amp;n.data&amp;&amp;(i.data=n.data),r[e]=i,a++}}c.attributes=r,c.attributesNum=a,c.index=i}(r,x,d,y)}else{const t=!0===l.wireframe;c.geometry===x.id&amp;&amp;c.program===d.id&amp;&amp;c.wireframe===t||(c.geometry=x.id,c.program=d.id,c.wireframe=t,M=!0)}null!==y&amp;&amp;n.update(y,t.ELEMENT_ARRAY_BUFFER),(M||h)&amp;&amp;(h=!1,function(r,s,a,o){if(!1===i.isWebGL2&amp;&amp;(r.isInstancedMesh||o.isInstancedBufferGeometry)&amp;&amp;null===e.get(&quot;ANGLE_instanced_arrays&quot;))return;m();const l=o.attributes,c=a.getAttributes(),h=s.defaultAttributeValues;for(const e in c){const s=c[e];if(s.location&gt;=0){let a=l[e];if(void 0===a&amp;&amp;(&quot;instanceMatrix&quot;===e&amp;&amp;r.instanceMatrix&amp;&amp;(a=r.instanceMatrix),&quot;instanceColor&quot;===e&amp;&amp;r.instanceColor&amp;&amp;(a=r.instanceColor)),void 0!==a){const e=a.normalized,l=a.itemSize,c=n.get(a);if(void 0===c)continue;const h=c.buffer,u=c.type,d=c.bytesPerElement,p=!0===i.isWebGL2&amp;&amp;(u===t.INT||u===t.UNSIGNED_INT||a.gpuType===z);if(a.isInterleavedBufferAttribute){const n=a.data,i=n.stride,c=a.offset;if(n.isInstancedInterleavedBuffer){for(let t=0;t&lt;s.locationSize;t++)g(s.location+t,n.meshPerAttribute);!0!==r.isInstancedMesh&amp;&amp;void 0===o._maxInstanceCount&amp;&amp;(o._maxInstanceCount=n.meshPerAttribute*n.count)}else for(let t=0;t&lt;s.locationSize;t++)f(s.location+t);t.bindBuffer(t.ARRAY_BUFFER,h);for(let t=0;t&lt;s.locationSize;t++)v(s.location+t,l/s.locationSize,u,e,i*d,(c+l/s.locationSize*t)*d,p)}else{if(a.isInstancedBufferAttribute){for(let t=0;t&lt;s.locationSize;t++)g(s.location+t,a.meshPerAttribute);!0!==r.isInstancedMesh&amp;&amp;void 0===o._maxInstanceCount&amp;&amp;(o._maxInstanceCount=a.meshPerAttribute*a.count)}else for(let t=0;t&lt;s.locationSize;t++)f(s.location+t);t.bindBuffer(t.ARRAY_BUFFER,h);for(let t=0;t&lt;s.locationSize;t++)v(s.location+t,l/s.locationSize,u,e,l*d,l/s.locationSize*t*d,p)}}else if(void 0!==h){const n=h[e];if(void 0!==n)switch(n.length){case 2:t.vertexAttrib2fv(s.location,n);break;case 3:t.vertexAttrib3fv(s.location,n);break;case 4:t.vertexAttrib4fv(s.location,n);break;default:t.vertexAttrib1fv(s.location,n)}}}}_()}(r,l,d,x),null!==y&amp;&amp;t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,n.get(y).buffer))},reset:x,resetDefaultState:y,dispose:function(){x();for(const t in o){const e=o[t];for(const t in e){const n=e[t];for(const t in n)d(n[t].object),delete n[t];delete e[t]}delete o[t]}},releaseStatesOfGeometry:function(t){if(void 0===o[t.id])return;const e=o[t.id];for(const t in e){const n=e[t];for(const t in n)d(n[t].object),delete n[t];delete e[t]}delete o[t.id]},releaseStatesOfProgram:function(t){for(const e in o){const n=o[e];if(void 0===n[t.id])continue;const i=n[t.id];for(const t in i)d(i[t].object),delete i[t];delete n[t.id]}},initAttributes:m,enableAttribute:f,disableUnusedAttributes:_}}function wr(t,e,n,i){const r=i.isWebGL2;let s;this.setMode=function(t){s=t},this.render=function(e,i){t.drawArrays(s,e,i),n.update(i,s,1)},this.renderInstances=function(i,a,o){if(0===o)return;let l,c;if(r)l=t,c=&quot;drawArraysInstanced&quot;;else if(l=e.get(&quot;ANGLE_instanced_arrays&quot;),c=&quot;drawArraysInstancedANGLE&quot;,null===l)return void console.error(&quot;THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.&quot;);l[c](s,i,a,o),n.update(a,s,o)},this.renderMultiDraw=function(t,i,r){if(0===r)return;const a=e.get(&quot;WEBGL_multi_draw&quot;);if(null===a)for(let e=0;e&lt;r;e++)this.render(t[e],i[e]);else{a.multiDrawArraysWEBGL(s,t,0,i,0,r);let e=0;for(let t=0;t&lt;r;t++)e+=i[t];n.update(e,s,1)}}}function Ar(t,e,n){let i;function r(e){if(&quot;highp&quot;===e){if(t.getShaderPrecisionFormat(t.VERTEX_SHADER,t.HIGH_FLOAT).precision&gt;0&amp;&amp;t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.HIGH_FLOAT).precision&gt;0)return&quot;highp&quot;;e=&quot;mediump&quot;}return&quot;mediump&quot;===e&amp;&amp;t.getShaderPrecisionFormat(t.VERTEX_SHADER,t.MEDIUM_FLOAT).precision&gt;0&amp;&amp;t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.MEDIUM_FLOAT).precision&gt;0?&quot;mediump&quot;:&quot;lowp&quot;}const s=&quot;undefined&quot;!=typeof WebGL2RenderingContext&amp;&amp;&quot;WebGL2RenderingContext&quot;===t.constructor.name;let a=void 0!==n.precision?n.precision:&quot;highp&quot;;const o=r(a);o!==a&amp;&amp;(console.warn(&quot;THREE.WebGLRenderer:&quot;,a,&quot;not supported, using&quot;,o,&quot;instead.&quot;),a=o);const l=s||e.has(&quot;WEBGL_draw_buffers&quot;),c=!0===n.logarithmicDepthBuffer,h=t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS),u=t.getParameter(t.MAX_VERTEX_TEXTURE_IMAGE_UNITS),d=t.getParameter(t.MAX_TEXTURE_SIZE),p=t.getParameter(t.MAX_CUBE_MAP_TEXTURE_SIZE),m=t.getParameter(t.MAX_VERTEX_ATTRIBS),f=t.getParameter(t.MAX_VERTEX_UNIFORM_VECTORS),g=t.getParameter(t.MAX_VARYING_VECTORS),_=t.getParameter(t.MAX_FRAGMENT_UNIFORM_VECTORS),v=u&gt;0,x=s||e.has(&quot;OES_texture_float&quot;);return{isWebGL2:s,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==i)return i;if(!0===e.has(&quot;EXT_texture_filter_anisotropic&quot;)){const n=e.get(&quot;EXT_texture_filter_anisotropic&quot;);i=t.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else i=0;return i},getMaxPrecision:r,precision:a,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:m,maxVertexUniforms:f,maxVaryings:g,maxFragmentUniforms:_,vertexTextures:v,floatFragmentTextures:x,floatVertexTextures:v&amp;&amp;x,maxSamples:s?t.getParameter(t.MAX_SAMPLES):0}}function Rr(t){const e=this;let n=null,i=0,r=!1,s=!1;const a=new pr,o=new fe,l={value:null,needsUpdate:!1};function c(t,n,i,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=i+4*s,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length&lt;e)&amp;&amp;(c=new Float32Array(e));for(let e=0,n=i;e!==s;++e,n+=4)a.copy(t[e]).applyMatrix4(r,o),a.normal.toArray(c,n),c[n+3]=a.constant}l.value=c,l.needsUpdate=!0}return e.numPlanes=s,e.numIntersection=0,c}this.uniform=l,this.numPlanes=0,this.numIntersection=0,this.init=function(t,e){const n=0!==t.length||e||0!==i||r;return r=e,i=t.length,n},this.beginShadows=function(){s=!0,c(null)},this.endShadows=function(){s=!1},this.setGlobalState=function(t,e){n=c(t,e,0)},this.setState=function(a,o,h){const u=a.clippingPlanes,d=a.clipIntersection,p=a.clipShadows,m=t.get(a);if(!r||null===u||0===u.length||s&amp;&amp;!p)s?c(null):function(){l.value!==n&amp;&amp;(l.value=n,l.needsUpdate=i&gt;0);e.numPlanes=i,e.numIntersection=0}();else{const t=s?0:i,e=4*t;let r=m.clippingState||null;l.value=r,r=c(u,o,e,h);for(let t=0;t!==e;++t)r[t]=n[t];m.clippingState=r,this.numIntersection=d?this.numPlanes:0,this.numPlanes+=t}}}function Cr(t){let e=new WeakMap;function n(t,e){return e===E?t.mapping=b:e===w&amp;&amp;(t.mapping=T),t}function i(t){const n=t.target;n.removeEventListener(&quot;dispose&quot;,i);const r=e.get(n);void 0!==r&amp;&amp;(e.delete(n),r.dispose())}return{get:function(r){if(r&amp;&amp;r.isTexture){const s=r.mapping;if(s===E||s===w){if(e.has(r)){return n(e.get(r).texture,r.mapping)}{const s=r.image;if(s&amp;&amp;s.height&gt;0){const a=new cr(s.height/2);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener(&quot;dispose&quot;,i),n(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}class Lr extends rr{constructor(t=-1,e=1,n=1,i=-1,r=.1,s=2e3){super(),this.isOrthographicCamera=!0,this.type=&quot;OrthographicCamera&quot;,this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=n,this.bottom=i,this.near=r,this.far=s,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=null===t.view?null:Object.assign({},t.view),this}setViewOffset(t,e,n,i,r,s){null===this.view&amp;&amp;(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&amp;&amp;(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-t,s=n+t,a=i+e,o=i-e;if(null!==this.view&amp;&amp;this.view.enabled){const t=(this.right-this.left)/this.view.fullWidth/this.zoom,e=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=t*this.view.offsetX,s=r+t*this.view.width,a-=e*this.view.offsetY,o=a-e*this.view.height}this.projectionMatrix.makeOrthographic(r,s,a,o,this.near,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,null!==this.view&amp;&amp;(e.object.view=Object.assign({},this.view)),e}}const Pr=[.125,.215,.35,.446,.526,.582],Ir=20,Ur=new Lr,Dr=new ci;let Nr=null,Or=0,Fr=0;const Br=(1+Math.sqrt(5))/2,zr=1/Br,Gr=[new We(1,1,1),new We(-1,1,1),new We(1,1,-1),new We(-1,1,-1),new We(0,Br,zr),new We(0,Br,-zr),new We(zr,0,Br),new We(-zr,0,Br),new We(Br,zr,0),new We(-Br,zr,0)];class Hr{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,n=.1,i=100){Nr=this._renderer.getRenderTarget(),Or=this._renderer.getActiveCubeFace(),Fr=this._renderer.getActiveMipmapLevel(),this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,n,i,r),e&gt;0&amp;&amp;this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){null===this._cubemapMaterial&amp;&amp;(this._cubemapMaterial=Xr(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&amp;&amp;(this._equirectMaterial=Wr(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&amp;&amp;this._cubemapMaterial.dispose(),null!==this._equirectMaterial&amp;&amp;this._equirectMaterial.dispose()}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&amp;&amp;this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&amp;&amp;this._pingPongRenderTarget.dispose();for(let t=0;t&lt;this._lodPlanes.length;t++)this._lodPlanes[t].dispose()}_cleanup(t){this._renderer.setRenderTarget(Nr,Or,Fr),t.scissorTest=!1,kr(t,0,0,t.width,t.height)}_fromTexture(t,e){t.mapping===b||t.mapping===T?this._setSize(0===t.image.length?16:t.image[0].width||t.image[0].image.width):this._setSize(t.image.width/4),Nr=this._renderer.getRenderTarget(),Or=this._renderer.getActiveCubeFace(),Fr=this._renderer.getActiveMipmapLevel();const n=e||this._allocateTargets();return this._textureToCubeUV(t,n),this._applyPMREM(n),this._cleanup(n),n}_allocateTargets(){const t=3*Math.max(this._cubeSize,112),e=4*this._cubeSize,n={magFilter:D,minFilter:D,generateMipmaps:!1,type:V,format:j,colorSpace:Ht,depthBuffer:!1},i=Vr(t,e,n);if(null===this._pingPongRenderTarget||this._pingPongRenderTarget.width!==t||this._pingPongRenderTarget.height!==e){null!==this._pingPongRenderTarget&amp;&amp;this._dispose(),this._pingPongRenderTarget=Vr(t,e,n);const{_lodMax:i}=this;({sizeLods:this._sizeLods,lodPlanes:this._lodPlanes,sigmas:this._sigmas}=function(t){const e=[],n=[],i=[];let r=t;const s=t-4+1+Pr.length;for(let a=0;a&lt;s;a++){const s=Math.pow(2,r);n.push(s);let o=1/s;a&gt;t-4?o=Pr[a-t+4-1]:0===a&amp;&amp;(o=0),i.push(o);const l=1/(s-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,m=3,f=2,g=1,_=new Float32Array(m*p*d),v=new Float32Array(f*p*d),x=new Float32Array(g*p*d);for(let t=0;t&lt;d;t++){const e=t%3*2/3-1,n=t&gt;2?0:-1,i=[e,n,0,e+2/3,n,0,e+2/3,n+1,0,e,n,0,e+2/3,n+1,0,e,n+1,0];_.set(i,m*p*t),v.set(u,f*p*t);const r=[t,t,t,t,t,t];x.set(r,g*p*t)}const y=new Ii;y.setAttribute(&quot;position&quot;,new Mi(_,m)),y.setAttribute(&quot;uv&quot;,new Mi(v,f)),y.setAttribute(&quot;faceIndex&quot;,new Mi(x,g)),e.push(y),r&gt;4&amp;&amp;r--}return{lodPlanes:e,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(t,e,n){const i=new Float32Array(Ir),r=new We(0,1,0),s=new ir({name:&quot;SphericalGaussianBlur&quot;,defines:{n:Ir,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${t}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:jr(),fragmentShader:&quot;\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include &lt;cube_uv_reflection_fragment&gt;\n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i &lt; n; i++ ) {\n\n\t\t\t\t\tif ( i &gt;= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t&quot;,blending:0,depthTest:!1,depthWrite:!1});return s}(i,t,e)}return i}_compileMaterial(t){const e=new Ji(this._lodPlanes[0],t);this._renderer.compile(e,Ur)}_sceneToCubeUV(t,e,n,i){const r=new sr(90,1,e,n),s=[1,-1,1,1,1,1],o=[1,1,1,-1,-1,-1],l=this._renderer,c=l.autoClear,h=l.toneMapping;l.getClearColor(Dr),l.toneMapping=p,l.autoClear=!1;const u=new pi({name:&quot;PMREM.Background&quot;,side:a,depthWrite:!1,depthTest:!1}),d=new Ji(new $i,u);let m=!1;const f=t.background;f?f.isColor&amp;&amp;(u.color.copy(f),t.background=null,m=!0):(u.color.copy(Dr),m=!0);for(let e=0;e&lt;6;e++){const n=e%3;0===n?(r.up.set(0,s[e],0),r.lookAt(o[e],0,0)):1===n?(r.up.set(0,0,s[e]),r.lookAt(0,o[e],0)):(r.up.set(0,s[e],0),r.lookAt(0,0,o[e]));const a=this._cubeSize;kr(i,n*a,e&gt;2?a:0,a,a),l.setRenderTarget(i),m&amp;&amp;l.render(d,r),l.render(t,r)}d.geometry.dispose(),d.material.dispose(),l.toneMapping=h,l.autoClear=c,t.background=f}_textureToCubeUV(t,e){const n=this._renderer,i=t.mapping===b||t.mapping===T;i?(null===this._cubemapMaterial&amp;&amp;(this._cubemapMaterial=Xr()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===t.isRenderTargetTexture?-1:1):null===this._equirectMaterial&amp;&amp;(this._equirectMaterial=Wr());const r=i?this._cubemapMaterial:this._equirectMaterial,s=new Ji(this._lodPlanes[0],r);r.uniforms.envMap.value=t;const a=this._cubeSize;kr(e,0,0,3*a,2*a),n.setRenderTarget(e),n.render(s,Ur)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;for(let e=1;e&lt;this._lodPlanes.length;e++){const n=Math.sqrt(this._sigmas[e]*this._sigmas[e]-this._sigmas[e-1]*this._sigmas[e-1]),i=Gr[(e-1)%Gr.length];this._blur(t,e-1,e,n,i)}e.autoClear=n}_blur(t,e,n,i,r){const s=this._pingPongRenderTarget;this._halfBlur(t,s,e,n,i,&quot;latitudinal&quot;,r),this._halfBlur(s,t,n,n,i,&quot;longitudinal&quot;,r)}_halfBlur(t,e,n,i,r,s,a){const o=this._renderer,l=this._blurMaterial;&quot;latitudinal&quot;!==s&amp;&amp;&quot;longitudinal&quot;!==s&amp;&amp;console.error(&quot;blur direction must be either latitudinal or longitudinal!&quot;);const c=new Ji(this._lodPlanes[i],l),h=l.uniforms,u=this._sizeLods[n]-1,d=isFinite(r)?Math.PI/(2*u):2*Math.PI/39,p=r/d,m=isFinite(r)?1+Math.floor(3*p):Ir;m&gt;Ir&amp;&amp;console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const f=[];let g=0;for(let t=0;t&lt;Ir;++t){const e=t/p,n=Math.exp(-e*e/2);f.push(n),0===t?g+=n:t&lt;m&amp;&amp;(g+=2*n)}for(let t=0;t&lt;f.length;t++)f[t]=f[t]/g;h.envMap.value=t.texture,h.samples.value=m,h.weights.value=f,h.latitudinal.value=&quot;latitudinal&quot;===s,a&amp;&amp;(h.poleAxis.value=a);const{_lodMax:_}=this;h.dTheta.value=d,h.mipInt.value=_-n;const v=this._sizeLods[i];kr(e,3*v*(i&gt;_-4?i-_+4:0),4*(this._cubeSize-v),3*v,2*v),o.setRenderTarget(e),o.render(c,Ur)}}function Vr(t,e,n){const i=new Ge(t,e,n);return i.texture.mapping=A,i.texture.name=&quot;PMREM.cubeUv&quot;,i.scissorTest=!0,i}function kr(t,e,n,i,r){t.viewport.set(e,n,i,r),t.scissor.set(e,n,i,r)}function Wr(){return new ir({name:&quot;EquirectangularToCubeUV&quot;,uniforms:{envMap:{value:null}},vertexShader:jr(),fragmentShader:&quot;\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include &lt;common&gt;\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t&quot;,blending:0,depthTest:!1,depthWrite:!1})}function Xr(){return new ir({name:&quot;CubemapToCubeUV&quot;,uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:jr(),fragmentShader:&quot;\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t&quot;,blending:0,depthTest:!1,depthWrite:!1})}function jr(){return&quot;\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t&quot;}function qr(t){let e=new WeakMap,n=null;function i(t){const n=t.target;n.removeEventListener(&quot;dispose&quot;,i);const r=e.get(n);void 0!==r&amp;&amp;(e.delete(n),r.dispose())}return{get:function(r){if(r&amp;&amp;r.isTexture){const s=r.mapping,a=s===E||s===w,o=s===b||s===T;if(a||o){if(r.isRenderTargetTexture&amp;&amp;!0===r.needsPMREMUpdate){r.needsPMREMUpdate=!1;let i=e.get(r);return null===n&amp;&amp;(n=new Hr(t)),i=a?n.fromEquirectangular(r,i):n.fromCubemap(r,i),e.set(r,i),i.texture}if(e.has(r))return e.get(r).texture;{const s=r.image;if(a&amp;&amp;s&amp;&amp;s.height&gt;0||o&amp;&amp;s&amp;&amp;function(t){let e=0;const n=6;for(let i=0;i&lt;n;i++)void 0!==t[i]&amp;&amp;e++;return e===n}(s)){null===n&amp;&amp;(n=new Hr(t));const s=a?n.fromEquirectangular(r):n.fromCubemap(r);return e.set(r,s),r.addEventListener(&quot;dispose&quot;,i),s.texture}return null}}}return r},dispose:function(){e=new WeakMap,null!==n&amp;&amp;(n.dispose(),n=null)}}}function Yr(t){const e={};function n(n){if(void 0!==e[n])return e[n];let i;switch(n){case&quot;WEBGL_depth_texture&quot;:i=t.getExtension(&quot;WEBGL_depth_texture&quot;)||t.getExtension(&quot;MOZ_WEBGL_depth_texture&quot;)||t.getExtension(&quot;WEBKIT_WEBGL_depth_texture&quot;);break;case&quot;EXT_texture_filter_anisotropic&quot;:i=t.getExtension(&quot;EXT_texture_filter_anisotropic&quot;)||t.getExtension(&quot;MOZ_EXT_texture_filter_anisotropic&quot;)||t.getExtension(&quot;WEBKIT_EXT_texture_filter_anisotropic&quot;);break;case&quot;WEBGL_compressed_texture_s3tc&quot;:i=t.getExtension(&quot;WEBGL_compressed_texture_s3tc&quot;)||t.getExtension(&quot;MOZ_WEBGL_compressed_texture_s3tc&quot;)||t.getExtension(&quot;WEBKIT_WEBGL_compressed_texture_s3tc&quot;);break;case&quot;WEBGL_compressed_texture_pvrtc&quot;:i=t.getExtension(&quot;WEBGL_compressed_texture_pvrtc&quot;)||t.getExtension(&quot;WEBKIT_WEBGL_compressed_texture_pvrtc&quot;);break;default:i=t.getExtension(n)}return e[n]=i,i}return{has:function(t){return null!==n(t)},init:function(t){t.isWebGL2?(n(&quot;EXT_color_buffer_float&quot;),n(&quot;WEBGL_clip_cull_distance&quot;)):(n(&quot;WEBGL_depth_texture&quot;),n(&quot;OES_texture_float&quot;),n(&quot;OES_texture_half_float&quot;),n(&quot;OES_texture_half_float_linear&quot;),n(&quot;OES_standard_derivatives&quot;),n(&quot;OES_element_index_uint&quot;),n(&quot;OES_vertex_array_object&quot;),n(&quot;ANGLE_instanced_arrays&quot;)),n(&quot;OES_texture_float_linear&quot;),n(&quot;EXT_color_buffer_half_float&quot;),n(&quot;WEBGL_multisampled_render_to_texture&quot;)},get:function(t){const e=n(t);return null===e&amp;&amp;console.warn(&quot;THREE.WebGLRenderer: &quot;+t+&quot; extension not supported.&quot;),e}}}function Zr(t,e,n,i){const r={},s=new WeakMap;function a(t){const o=t.target;null!==o.index&amp;&amp;e.remove(o.index);for(const t in o.attributes)e.remove(o.attributes[t]);for(const t in o.morphAttributes){const n=o.morphAttributes[t];for(let t=0,i=n.length;t&lt;i;t++)e.remove(n[t])}o.removeEventListener(&quot;dispose&quot;,a),delete r[o.id];const l=s.get(o);l&amp;&amp;(e.remove(l),s.delete(o)),i.releaseStatesOfGeometry(o),!0===o.isInstancedBufferGeometry&amp;&amp;delete o._maxInstanceCount,n.memory.geometries--}function o(t){const n=[],i=t.index,r=t.attributes.position;let a=0;if(null!==i){const t=i.array;a=i.version;for(let e=0,i=t.length;e&lt;i;e+=3){const i=t[e+0],r=t[e+1],s=t[e+2];n.push(i,r,r,s,s,i)}}else{if(void 0===r)return;{const t=r.array;a=r.version;for(let e=0,i=t.length/3-1;e&lt;i;e+=3){const t=e+0,i=e+1,r=e+2;n.push(t,i,i,r,r,t)}}}const o=new(_e(n)?bi:Si)(n,1);o.version=a;const l=s.get(t);l&amp;&amp;e.remove(l),s.set(t,o)}return{get:function(t,e){return!0===r[e.id]||(e.addEventListener(&quot;dispose&quot;,a),r[e.id]=!0,n.memory.geometries++),e},update:function(n){const i=n.attributes;for(const n in i)e.update(i[n],t.ARRAY_BUFFER);const r=n.morphAttributes;for(const n in r){const i=r[n];for(let n=0,r=i.length;n&lt;r;n++)e.update(i[n],t.ARRAY_BUFFER)}},getWireframeAttribute:function(t){const e=s.get(t);if(e){const n=t.index;null!==n&amp;&amp;e.version&lt;n.version&amp;&amp;o(t)}else o(t);return s.get(t)}}}function Jr(t,e,n,i){const r=i.isWebGL2;let s,a,o;this.setMode=function(t){s=t},this.setIndex=function(t){a=t.type,o=t.bytesPerElement},this.render=function(e,i){t.drawElements(s,i,a,e*o),n.update(i,s,1)},this.renderInstances=function(i,l,c){if(0===c)return;let h,u;if(r)h=t,u=&quot;drawElementsInstanced&quot;;else if(h=e.get(&quot;ANGLE_instanced_arrays&quot;),u=&quot;drawElementsInstancedANGLE&quot;,null===h)return void console.error(&quot;THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.&quot;);h[u](s,l,a,i*o,c),n.update(l,s,c)},this.renderMultiDraw=function(t,i,r){if(0===r)return;const l=e.get(&quot;WEBGL_multi_draw&quot;);if(null===l)for(let e=0;e&lt;r;e++)this.render(t[e]/o,i[e]);else{l.multiDrawElementsWEBGL(s,i,0,a,t,0,r);let e=0;for(let t=0;t&lt;r;t++)e+=i[t];n.update(e,s,1)}}}function Kr(t){const e={frame:0,calls:0,triangles:0,points:0,lines:0};return{memory:{geometries:0,textures:0},render:e,programs:null,autoReset:!0,reset:function(){e.calls=0,e.triangles=0,e.points=0,e.lines=0},update:function(n,i,r){switch(e.calls++,i){case t.TRIANGLES:e.triangles+=r*(n/3);break;case t.LINES:e.lines+=r*(n/2);break;case t.LINE_STRIP:e.lines+=r*(n-1);break;case t.LINE_LOOP:e.lines+=r*n;break;case t.POINTS:e.points+=r*n;break;default:console.error(&quot;THREE.WebGLInfo: Unknown draw mode:&quot;,i)}}}}function $r(t,e){return t[0]-e[0]}function Qr(t,e){return Math.abs(e[1])-Math.abs(t[1])}function ts(t,e,n){const i={},r=new Float32Array(8),s=new WeakMap,a=new Be,o=[];for(let t=0;t&lt;8;t++)o[t]=[t,0];return{update:function(l,c,h){const u=l.morphTargetInfluences;if(!0===e.isWebGL2){const d=c.morphAttributes.position||c.morphAttributes.normal||c.morphAttributes.color,p=void 0!==d?d.length:0;let m=s.get(c);if(void 0===m||m.count!==p){void 0!==m&amp;&amp;m.texture.dispose();const _=void 0!==c.morphAttributes.position,v=void 0!==c.morphAttributes.normal,x=void 0!==c.morphAttributes.color,y=c.morphAttributes.position||[],M=c.morphAttributes.normal||[],S=c.morphAttributes.color||[];let b=0;!0===_&amp;&amp;(b=1),!0===v&amp;&amp;(b=2),!0===x&amp;&amp;(b=3);let T=c.attributes.position.count*b,E=1;T&gt;e.maxTextureSize&amp;&amp;(E=Math.ceil(T/e.maxTextureSize),T=e.maxTextureSize);const w=new Float32Array(T*E*4*p),A=new He(w,T,E,p);A.type=H,A.needsUpdate=!0;const R=4*b;for(let L=0;L&lt;p;L++){const P=y[L],I=M[L],U=S[L],D=T*E*4*L;for(let N=0;N&lt;P.count;N++){const O=N*R;!0===_&amp;&amp;(a.fromBufferAttribute(P,N),w[D+O+0]=a.x,w[D+O+1]=a.y,w[D+O+2]=a.z,w[D+O+3]=0),!0===v&amp;&amp;(a.fromBufferAttribute(I,N),w[D+O+4]=a.x,w[D+O+5]=a.y,w[D+O+6]=a.z,w[D+O+7]=0),!0===x&amp;&amp;(a.fromBufferAttribute(U,N),w[D+O+8]=a.x,w[D+O+9]=a.y,w[D+O+10]=a.z,w[D+O+11]=4===U.itemSize?a.w:1)}}function C(){A.dispose(),s.delete(c),c.removeEventListener(&quot;dispose&quot;,C)}m={count:p,texture:A,size:new me(T,E)},s.set(c,m),c.addEventListener(&quot;dispose&quot;,C)}let f=0;for(let F=0;F&lt;u.length;F++)f+=u[F];const g=c.morphTargetsRelative?1:1-f;h.getUniforms().setValue(t,&quot;morphTargetBaseInfluence&quot;,g),h.getUniforms().setValue(t,&quot;morphTargetInfluences&quot;,u),h.getUniforms().setValue(t,&quot;morphTargetsTexture&quot;,m.texture,n),h.getUniforms().setValue(t,&quot;morphTargetsTextureSize&quot;,m.size)}else{const B=void 0===u?0:u.length;let z=i[c.id];if(void 0===z||z.length!==B){z=[];for(let X=0;X&lt;B;X++)z[X]=[X,0];i[c.id]=z}for(let j=0;j&lt;B;j++){const q=z[j];q[0]=j,q[1]=u[j]}z.sort(Qr);for(let Y=0;Y&lt;8;Y++)Y&lt;B&amp;&amp;z[Y][1]?(o[Y][0]=z[Y][0],o[Y][1]=z[Y][1]):(o[Y][0]=Number.MAX_SAFE_INTEGER,o[Y][1]=0);o.sort($r);const G=c.morphAttributes.position,V=c.morphAttributes.normal;let k=0;for(let Z=0;Z&lt;8;Z++){const J=o[Z],K=J[0],$=J[1];K!==Number.MAX_SAFE_INTEGER&amp;&amp;$?(G&amp;&amp;c.getAttribute(&quot;morphTarget&quot;+Z)!==G[K]&amp;&amp;c.setAttribute(&quot;morphTarget&quot;+Z,G[K]),V&amp;&amp;c.getAttribute(&quot;morphNormal&quot;+Z)!==V[K]&amp;&amp;c.setAttribute(&quot;morphNormal&quot;+Z,V[K]),r[Z]=$,k+=$):(G&amp;&amp;!0===c.hasAttribute(&quot;morphTarget&quot;+Z)&amp;&amp;c.deleteAttribute(&quot;morphTarget&quot;+Z),V&amp;&amp;!0===c.hasAttribute(&quot;morphNormal&quot;+Z)&amp;&amp;c.deleteAttribute(&quot;morphNormal&quot;+Z),r[Z]=0)}const W=c.morphTargetsRelative?1:1-k;h.getUniforms().setValue(t,&quot;morphTargetBaseInfluence&quot;,W),h.getUniforms().setValue(t,&quot;morphTargetInfluences&quot;,r)}}}}function es(t,e,n,i){let r=new WeakMap;function s(t){const e=t.target;e.removeEventListener(&quot;dispose&quot;,s),n.remove(e.instanceMatrix),null!==e.instanceColor&amp;&amp;n.remove(e.instanceColor)}return{update:function(a){const o=i.render.frame,l=a.geometry,c=e.get(a,l);if(r.get(c)!==o&amp;&amp;(e.update(c),r.set(c,o)),a.isInstancedMesh&amp;&amp;(!1===a.hasEventListener(&quot;dispose&quot;,s)&amp;&amp;a.addEventListener(&quot;dispose&quot;,s),r.get(a)!==o&amp;&amp;(n.update(a.instanceMatrix,t.ARRAY_BUFFER),null!==a.instanceColor&amp;&amp;n.update(a.instanceColor,t.ARRAY_BUFFER),r.set(a,o))),a.isSkinnedMesh){const t=a.skeleton;r.get(t)!==o&amp;&amp;(t.update(),r.set(t,o))}return c},dispose:function(){r=new WeakMap}}}class ns extends Fe{constructor(t,e,n,i,r,s,a,o,l,c){if((c=void 0!==c?c:q)!==q&amp;&amp;c!==Y)throw new Error(&quot;DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat&quot;);void 0===n&amp;&amp;c===q&amp;&amp;(n=G),void 0===n&amp;&amp;c===Y&amp;&amp;(n=X),super(null,i,r,s,a,o,c,n,l),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=void 0!==a?a:P,this.minFilter=void 0!==o?o:P,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(t){return super.copy(t),this.compareFunction=t.compareFunction,this}toJSON(t){const e=super.toJSON(t);return null!==this.compareFunction&amp;&amp;(e.compareFunction=this.compareFunction),e}}const is=new Fe,rs=new ns(1,1);rs.compareFunction=515;const ss=new He,as=new Ve,os=new lr,ls=[],cs=[],hs=new Float32Array(16),us=new Float32Array(9),ds=new Float32Array(4);function ps(t,e,n){const i=t[0];if(i&lt;=0||i&gt;0)return t;const r=e*n;let s=ls[r];if(void 0===s&amp;&amp;(s=new Float32Array(r),ls[r]=s),0!==e){i.toArray(s,0);for(let i=1,r=0;i!==e;++i)r+=n,t[i].toArray(s,r)}return s}function ms(t,e){if(t.length!==e.length)return!1;for(let n=0,i=t.length;n&lt;i;n++)if(t[n]!==e[n])return!1;return!0}function fs(t,e){for(let n=0,i=e.length;n&lt;i;n++)t[n]=e[n]}function gs(t,e){let n=cs[e];void 0===n&amp;&amp;(n=new Int32Array(e),cs[e]=n);for(let i=0;i!==e;++i)n[i]=t.allocateTextureUnit();return n}function _s(t,e){const n=this.cache;n[0]!==e&amp;&amp;(t.uniform1f(this.addr,e),n[0]=e)}function vs(t,e){const n=this.cache;if(void 0!==e.x)n[0]===e.x&amp;&amp;n[1]===e.y||(t.uniform2f(this.addr,e.x,e.y),n[0]=e.x,n[1]=e.y);else{if(ms(n,e))return;t.uniform2fv(this.addr,e),fs(n,e)}}function xs(t,e){const n=this.cache;if(void 0!==e.x)n[0]===e.x&amp;&amp;n[1]===e.y&amp;&amp;n[2]===e.z||(t.uniform3f(this.addr,e.x,e.y,e.z),n[0]=e.x,n[1]=e.y,n[2]=e.z);else if(void 0!==e.r)n[0]===e.r&amp;&amp;n[1]===e.g&amp;&amp;n[2]===e.b||(t.uniform3f(this.addr,e.r,e.g,e.b),n[0]=e.r,n[1]=e.g,n[2]=e.b);else{if(ms(n,e))return;t.uniform3fv(this.addr,e),fs(n,e)}}function ys(t,e){const n=this.cache;if(void 0!==e.x)n[0]===e.x&amp;&amp;n[1]===e.y&amp;&amp;n[2]===e.z&amp;&amp;n[3]===e.w||(t.uniform4f(this.addr,e.x,e.y,e.z,e.w),n[0]=e.x,n[1]=e.y,n[2]=e.z,n[3]=e.w);else{if(ms(n,e))return;t.uniform4fv(this.addr,e),fs(n,e)}}function Ms(t,e){const n=this.cache,i=e.elements;if(void 0===i){if(ms(n,e))return;t.uniformMatrix2fv(this.addr,!1,e),fs(n,e)}else{if(ms(n,i))return;ds.set(i),t.uniformMatrix2fv(this.addr,!1,ds),fs(n,i)}}function Ss(t,e){const n=this.cache,i=e.elements;if(void 0===i){if(ms(n,e))return;t.uniformMatrix3fv(this.addr,!1,e),fs(n,e)}else{if(ms(n,i))return;us.set(i),t.uniformMatrix3fv(this.addr,!1,us),fs(n,i)}}function bs(t,e){const n=this.cache,i=e.elements;if(void 0===i){if(ms(n,e))return;t.uniformMatrix4fv(this.addr,!1,e),fs(n,e)}else{if(ms(n,i))return;hs.set(i),t.uniformMatrix4fv(this.addr,!1,hs),fs(n,i)}}function Ts(t,e){const n=this.cache;n[0]!==e&amp;&amp;(t.uniform1i(this.addr,e),n[0]=e)}function Es(t,e){const n=this.cache;if(void 0!==e.x)n[0]===e.x&amp;&amp;n[1]===e.y||(t.uniform2i(this.addr,e.x,e.y),n[0]=e.x,n[1]=e.y);else{if(ms(n,e))return;t.uniform2iv(this.addr,e),fs(n,e)}}function ws(t,e){const n=this.cache;if(void 0!==e.x)n[0]===e.x&amp;&amp;n[1]===e.y&amp;&amp;n[2]===e.z||(t.uniform3i(this.addr,e.x,e.y,e.z),n[0]=e.x,n[1]=e.y,n[2]=e.z);else{if(ms(n,e))return;t.uniform3iv(this.addr,e),fs(n,e)}}function As(t,e){const n=this.cache;if(void 0!==e.x)n[0]===e.x&amp;&amp;n[1]===e.y&amp;&amp;n[2]===e.z&amp;&amp;n[3]===e.w||(t.uniform4i(this.addr,e.x,e.y,e.z,e.w),n[0]=e.x,n[1]=e.y,n[2]=e.z,n[3]=e.w);else{if(ms(n,e))return;t.uniform4iv(this.addr,e),fs(n,e)}}function Rs(t,e){const n=this.cache;n[0]!==e&amp;&amp;(t.uniform1ui(this.addr,e),n[0]=e)}function Cs(t,e){const n=this.cache;if(void 0!==e.x)n[0]===e.x&amp;&amp;n[1]===e.y||(t.uniform2ui(this.addr,e.x,e.y),n[0]=e.x,n[1]=e.y);else{if(ms(n,e))return;t.uniform2uiv(this.addr,e),fs(n,e)}}function Ls(t,e){const n=this.cache;if(void 0!==e.x)n[0]===e.x&amp;&amp;n[1]===e.y&amp;&amp;n[2]===e.z||(t.uniform3ui(this.addr,e.x,e.y,e.z),n[0]=e.x,n[1]=e.y,n[2]=e.z);else{if(ms(n,e))return;t.uniform3uiv(this.addr,e),fs(n,e)}}function Ps(t,e){const n=this.cache;if(void 0!==e.x)n[0]===e.x&amp;&amp;n[1]===e.y&amp;&amp;n[2]===e.z&amp;&amp;n[3]===e.w||(t.uniform4ui(this.addr,e.x,e.y,e.z,e.w),n[0]=e.x,n[1]=e.y,n[2]=e.z,n[3]=e.w);else{if(ms(n,e))return;t.uniform4uiv(this.addr,e),fs(n,e)}}function Is(t,e,n){const i=this.cache,r=n.allocateTextureUnit();i[0]!==r&amp;&amp;(t.uniform1i(this.addr,r),i[0]=r);const s=this.type===t.SAMPLER_2D_SHADOW?rs:is;n.setTexture2D(e||s,r)}function Us(t,e,n){const i=this.cache,r=n.allocateTextureUnit();i[0]!==r&amp;&amp;(t.uniform1i(this.addr,r),i[0]=r),n.setTexture3D(e||as,r)}function Ds(t,e,n){const i=this.cache,r=n.allocateTextureUnit();i[0]!==r&amp;&amp;(t.uniform1i(this.addr,r),i[0]=r),n.setTextureCube(e||os,r)}function Ns(t,e,n){const i=this.cache,r=n.allocateTextureUnit();i[0]!==r&amp;&amp;(t.uniform1i(this.addr,r),i[0]=r),n.setTexture2DArray(e||ss,r)}function Os(t,e){t.uniform1fv(this.addr,e)}function Fs(t,e){const n=ps(e,this.size,2);t.uniform2fv(this.addr,n)}function Bs(t,e){const n=ps(e,this.size,3);t.uniform3fv(this.addr,n)}function zs(t,e){const n=ps(e,this.size,4);t.uniform4fv(this.addr,n)}function Gs(t,e){const n=ps(e,this.size,4);t.uniformMatrix2fv(this.addr,!1,n)}function Hs(t,e){const n=ps(e,this.size,9);t.uniformMatrix3fv(this.addr,!1,n)}function Vs(t,e){const n=ps(e,this.size,16);t.uniformMatrix4fv(this.addr,!1,n)}function ks(t,e){t.uniform1iv(this.addr,e)}function Ws(t,e){t.uniform2iv(this.addr,e)}function Xs(t,e){t.uniform3iv(this.addr,e)}function js(t,e){t.uniform4iv(this.addr,e)}function qs(t,e){t.uniform1uiv(this.addr,e)}function Ys(t,e){t.uniform2uiv(this.addr,e)}function Zs(t,e){t.uniform3uiv(this.addr,e)}function Js(t,e){t.uniform4uiv(this.addr,e)}function Ks(t,e,n){const i=this.cache,r=e.length,s=gs(n,r);ms(i,s)||(t.uniform1iv(this.addr,s),fs(i,s));for(let t=0;t!==r;++t)n.setTexture2D(e[t]||is,s[t])}function $s(t,e,n){const i=this.cache,r=e.length,s=gs(n,r);ms(i,s)||(t.uniform1iv(this.addr,s),fs(i,s));for(let t=0;t!==r;++t)n.setTexture3D(e[t]||as,s[t])}function Qs(t,e,n){const i=this.cache,r=e.length,s=gs(n,r);ms(i,s)||(t.uniform1iv(this.addr,s),fs(i,s));for(let t=0;t!==r;++t)n.setTextureCube(e[t]||os,s[t])}function ta(t,e,n){const i=this.cache,r=e.length,s=gs(n,r);ms(i,s)||(t.uniform1iv(this.addr,s),fs(i,s));for(let t=0;t!==r;++t)n.setTexture2DArray(e[t]||ss,s[t])}class ea{constructor(t,e,n){this.id=t,this.addr=n,this.cache=[],this.type=e.type,this.setValue=function(t){switch(t){case 5126:return _s;case 35664:return vs;case 35665:return xs;case 35666:return ys;case 35674:return Ms;case 35675:return Ss;case 35676:return bs;case 5124:case 35670:return Ts;case 35667:case 35671:return Es;case 35668:case 35672:return ws;case 35669:case 35673:return As;case 5125:return Rs;case 36294:return Cs;case 36295:return Ls;case 36296:return Ps;case 35678:case 36198:case 36298:case 36306:case 35682:return Is;case 35679:case 36299:case 36307:return Us;case 35680:case 36300:case 36308:case 36293:return Ds;case 36289:case 36303:case 36311:case 36292:return Ns}}(e.type)}}class na{constructor(t,e,n){this.id=t,this.addr=n,this.cache=[],this.type=e.type,this.size=e.size,this.setValue=function(t){switch(t){case 5126:return Os;case 35664:return Fs;case 35665:return Bs;case 35666:return zs;case 35674:return Gs;case 35675:return Hs;case 35676:return Vs;case 5124:case 35670:return ks;case 35667:case 35671:return Ws;case 35668:case 35672:return Xs;case 35669:case 35673:return js;case 5125:return qs;case 36294:return Ys;case 36295:return Zs;case 36296:return Js;case 35678:case 36198:case 36298:case 36306:case 35682:return Ks;case 35679:case 36299:case 36307:return $s;case 35680:case 36300:case 36308:case 36293:return Qs;case 36289:case 36303:case 36311:case 36292:return ta}}(e.type)}}class ia{constructor(t){this.id=t,this.seq=[],this.map={}}setValue(t,e,n){const i=this.seq;for(let r=0,s=i.length;r!==s;++r){const s=i[r];s.setValue(t,e[s.id],n)}}}const ra=/(\w+)(\])?(\[|\.)?/g;function sa(t,e){t.seq.push(e),t.map[e.id]=e}function aa(t,e,n){const i=t.name,r=i.length;for(ra.lastIndex=0;;){const s=ra.exec(i),a=ra.lastIndex;let o=s[1];const l=&quot;]&quot;===s[2],c=s[3];if(l&amp;&amp;(o|=0),void 0===c||&quot;[&quot;===c&amp;&amp;a+2===r){sa(n,void 0===c?new ea(o,t,e):new na(o,t,e));break}{let t=n.map[o];void 0===t&amp;&amp;(t=new ia(o),sa(n,t)),n=t}}}class oa{constructor(t,e){this.seq=[],this.map={};const n=t.getProgramParameter(e,t.ACTIVE_UNIFORMS);for(let i=0;i&lt;n;++i){const n=t.getActiveUniform(e,i);aa(n,t.getUniformLocation(e,n.name),this)}}setValue(t,e,n,i){const r=this.map[e];void 0!==r&amp;&amp;r.setValue(t,n,i)}setOptional(t,e,n){const i=e[n];void 0!==i&amp;&amp;this.setValue(t,n,i)}static upload(t,e,n,i){for(let r=0,s=e.length;r!==s;++r){const s=e[r],a=n[s.id];!1!==a.needsUpdate&amp;&amp;s.setValue(t,a.value,i)}}static seqWithValue(t,e){const n=[];for(let i=0,r=t.length;i!==r;++i){const r=t[i];r.id in e&amp;&amp;n.push(r)}return n}}function la(t,e,n){const i=t.createShader(e);return t.shaderSource(i,n),t.compileShader(i),i}const ca=37297;let ha=0;function ua(t,e,n){const i=t.getShaderParameter(e,t.COMPILE_STATUS),r=t.getShaderInfoLog(e).trim();if(i&amp;&amp;&quot;&quot;===r)return&quot;&quot;;const s=/ERROR: 0:(\d+)/.exec(r);if(s){const i=parseInt(s[1]);return n.toUpperCase()+&quot;\n\n&quot;+r+&quot;\n\n&quot;+function(t,e){const n=t.split(&quot;\n&quot;),i=[],r=Math.max(e-6,0),s=Math.min(e+6,n.length);for(let t=r;t&lt;s;t++){const r=t+1;i.push(`${r===e?&quot;&gt;&quot;:&quot; &quot;} ${r}: ${n[t]}`)}return i.join(&quot;\n&quot;)}(t.getShaderSource(e),i)}return r}function da(t,e){const n=function(t){const e=Re.getPrimaries(Re.workingColorSpace),n=Re.getPrimaries(t);let i;switch(e===n?i=&quot;&quot;:e===qt&amp;&amp;n===jt?i=&quot;LinearDisplayP3ToLinearSRGB&quot;:e===jt&amp;&amp;n===qt&amp;&amp;(i=&quot;LinearSRGBToLinearDisplayP3&quot;),t){case Ht:case kt:return[i,&quot;LinearTransferOETF&quot;];case Gt:case Vt:return[i,&quot;sRGBTransferOETF&quot;];default:return console.warn(&quot;THREE.WebGLProgram: Unsupported color space:&quot;,t),[i,&quot;LinearTransferOETF&quot;]}}(e);return`vec4 ${t}( vec4 value ) { return ${n[0]}( ${n[1]}( value ) ); }`}function pa(t,e){let n;switch(e){case m:n=&quot;Linear&quot;;break;case f:n=&quot;Reinhard&quot;;break;case g:n=&quot;OptimizedCineon&quot;;break;case _:n=&quot;ACESFilmic&quot;;break;case x:n=&quot;AgX&quot;;break;case v:n=&quot;Custom&quot;;break;default:console.warn(&quot;THREE.WebGLProgram: Unsupported toneMapping:&quot;,e),n=&quot;Linear&quot;}return&quot;vec3 &quot;+t+&quot;( vec3 color ) { return &quot;+n+&quot;ToneMapping( color ); }&quot;}function ma(t){return&quot;&quot;!==t}function fa(t,e){const n=e.numSpotLightShadows+e.numSpotLightMaps-e.numSpotLightShadowsWithMaps;return t.replace(/NUM_DIR_LIGHTS/g,e.numDirLights).replace(/NUM_SPOT_LIGHTS/g,e.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,e.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,n).replace(/NUM_RECT_AREA_LIGHTS/g,e.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,e.numPointLights).replace(/NUM_HEMI_LIGHTS/g,e.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,e.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,e.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,e.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,e.numPointLightShadows)}function ga(t,e){return t.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const _a=/^[ \t]*#include +&lt;([\w\d./]+)&gt;/gm;function va(t){return t.replace(_a,ya)}const xa=new Map([[&quot;encodings_fragment&quot;,&quot;colorspace_fragment&quot;],[&quot;encodings_pars_fragment&quot;,&quot;colorspace_pars_fragment&quot;],[&quot;output_fragment&quot;,&quot;opaque_fragment&quot;]]);function ya(t,e){let n=yr[e];if(void 0===n){const t=xa.get(e);if(void 0===t)throw new Error(&quot;Can not resolve #include &lt;&quot;+e+&quot;&gt;&quot;);n=yr[t],console.warn('THREE.WebGLRenderer: Shader chunk &quot;%s&quot; has been deprecated. Use &quot;%s&quot; instead.',e,t)}return va(n)}const Ma=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*&lt;\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function Sa(t){return t.replace(Ma,ba)}function ba(t,e,n,i){let r=&quot;&quot;;for(let t=parseInt(e);t&lt;parseInt(n);t++)r+=i.replace(/\[\s*i\s*\]/g,&quot;[ &quot;+t+&quot; ]&quot;).replace(/UNROLLED_LOOP_INDEX/g,t);return r}function Ta(t){let e=&quot;precision &quot;+t.precision+&quot; float;\nprecision &quot;+t.precision+&quot; int;&quot;;return&quot;highp&quot;===t.precision?e+=&quot;\n#define HIGH_PRECISION&quot;:&quot;mediump&quot;===t.precision?e+=&quot;\n#define MEDIUM_PRECISION&quot;:&quot;lowp&quot;===t.precision&amp;&amp;(e+=&quot;\n#define LOW_PRECISION&quot;),e}function Ea(t,e,s,a){const o=t.getContext(),l=s.defines;let c=s.vertexShader,m=s.fragmentShader;const f=function(t){let e=&quot;SHADOWMAP_TYPE_BASIC&quot;;return t.shadowMapType===n?e=&quot;SHADOWMAP_TYPE_PCF&quot;:t.shadowMapType===i?e=&quot;SHADOWMAP_TYPE_PCF_SOFT&quot;:t.shadowMapType===r&amp;&amp;(e=&quot;SHADOWMAP_TYPE_VSM&quot;),e}(s),g=function(t){let e=&quot;ENVMAP_TYPE_CUBE&quot;;if(t.envMap)switch(t.envMapMode){case b:case T:e=&quot;ENVMAP_TYPE_CUBE&quot;;break;case A:e=&quot;ENVMAP_TYPE_CUBE_UV&quot;}return e}(s),_=function(t){let e=&quot;ENVMAP_MODE_REFLECTION&quot;;t.envMap&amp;&amp;t.envMapMode===T&amp;&amp;(e=&quot;ENVMAP_MODE_REFRACTION&quot;);return e}(s),v=function(t){let e=&quot;ENVMAP_BLENDING_NONE&quot;;if(t.envMap)switch(t.combine){case h:e=&quot;ENVMAP_BLENDING_MULTIPLY&quot;;break;case u:e=&quot;ENVMAP_BLENDING_MIX&quot;;break;case d:e=&quot;ENVMAP_BLENDING_ADD&quot;}return e}(s),x=function(t){const e=t.envMapCubeUVHeight;if(null===e)return null;const n=Math.log2(e)-2,i=1/e;return{texelWidth:1/(3*Math.max(Math.pow(2,n),112)),texelHeight:i,maxMip:n}}(s),y=s.isWebGL2?&quot;&quot;:function(t){return[t.extensionDerivatives||t.envMapCubeUVHeight||t.bumpMap||t.normalMapTangentSpace||t.clearcoatNormalMap||t.flatShading||&quot;physical&quot;===t.shaderID?&quot;#extension GL_OES_standard_derivatives : enable&quot;:&quot;&quot;,(t.extensionFragDepth||t.logarithmicDepthBuffer)&amp;&amp;t.rendererExtensionFragDepth?&quot;#extension GL_EXT_frag_depth : enable&quot;:&quot;&quot;,t.extensionDrawBuffers&amp;&amp;t.rendererExtensionDrawBuffers?&quot;#extension GL_EXT_draw_buffers : require&quot;:&quot;&quot;,(t.extensionShaderTextureLOD||t.envMap||t.transmission)&amp;&amp;t.rendererExtensionShaderTextureLod?&quot;#extension GL_EXT_shader_texture_lod : enable&quot;:&quot;&quot;].filter(ma).join(&quot;\n&quot;)}(s),M=function(t){return[t.extensionClipCullDistance?&quot;#extension GL_ANGLE_clip_cull_distance : require&quot;:&quot;&quot;].filter(ma).join(&quot;\n&quot;)}(s),S=function(t){const e=[];for(const n in t){const i=t[n];!1!==i&amp;&amp;e.push(&quot;#define &quot;+n+&quot; &quot;+i)}return e.join(&quot;\n&quot;)}(l),E=o.createProgram();let w,R,C=s.glslVersion?&quot;#version &quot;+s.glslVersion+&quot;\n&quot;:&quot;&quot;;s.isRawShaderMaterial?(w=[&quot;#define SHADER_TYPE &quot;+s.shaderType,&quot;#define SHADER_NAME &quot;+s.shaderName,S].filter(ma).join(&quot;\n&quot;),w.length&gt;0&amp;&amp;(w+=&quot;\n&quot;),R=[y,&quot;#define SHADER_TYPE &quot;+s.shaderType,&quot;#define SHADER_NAME &quot;+s.shaderName,S].filter(ma).join(&quot;\n&quot;),R.length&gt;0&amp;&amp;(R+=&quot;\n&quot;)):(w=[Ta(s),&quot;#define SHADER_TYPE &quot;+s.shaderType,&quot;#define SHADER_NAME &quot;+s.shaderName,S,s.extensionClipCullDistance?&quot;#define USE_CLIP_DISTANCE&quot;:&quot;&quot;,s.batching?&quot;#define USE_BATCHING&quot;:&quot;&quot;,s.instancing?&quot;#define USE_INSTANCING&quot;:&quot;&quot;,s.instancingColor?&quot;#define USE_INSTANCING_COLOR&quot;:&quot;&quot;,s.useFog&amp;&amp;s.fog?&quot;#define USE_FOG&quot;:&quot;&quot;,s.useFog&amp;&amp;s.fogExp2?&quot;#define FOG_EXP2&quot;:&quot;&quot;,s.map?&quot;#define USE_MAP&quot;:&quot;&quot;,s.envMap?&quot;#define USE_ENVMAP&quot;:&quot;&quot;,s.envMap?&quot;#define &quot;+_:&quot;&quot;,s.lightMap?&quot;#define USE_LIGHTMAP&quot;:&quot;&quot;,s.aoMap?&quot;#define USE_AOMAP&quot;:&quot;&quot;,s.bumpMap?&quot;#define USE_BUMPMAP&quot;:&quot;&quot;,s.normalMap?&quot;#define USE_NORMALMAP&quot;:&quot;&quot;,s.normalMapObjectSpace?&quot;#define USE_NORMALMAP_OBJECTSPACE&quot;:&quot;&quot;,s.normalMapTangentSpace?&quot;#define USE_NORMALMAP_TANGENTSPACE&quot;:&quot;&quot;,s.displacementMap?&quot;#define USE_DISPLACEMENTMAP&quot;:&quot;&quot;,s.emissiveMap?&quot;#define USE_EMISSIVEMAP&quot;:&quot;&quot;,s.anisotropy?&quot;#define USE_ANISOTROPY&quot;:&quot;&quot;,s.anisotropyMap?&quot;#define USE_ANISOTROPYMAP&quot;:&quot;&quot;,s.clearcoatMap?&quot;#define USE_CLEARCOATMAP&quot;:&quot;&quot;,s.clearcoatRoughnessMap?&quot;#define USE_CLEARCOAT_ROUGHNESSMAP&quot;:&quot;&quot;,s.clearcoatNormalMap?&quot;#define USE_CLEARCOAT_NORMALMAP&quot;:&quot;&quot;,s.iridescenceMap?&quot;#define USE_IRIDESCENCEMAP&quot;:&quot;&quot;,s.iridescenceThicknessMap?&quot;#define USE_IRIDESCENCE_THICKNESSMAP&quot;:&quot;&quot;,s.specularMap?&quot;#define USE_SPECULARMAP&quot;:&quot;&quot;,s.specularColorMap?&quot;#define USE_SPECULAR_COLORMAP&quot;:&quot;&quot;,s.specularIntensityMap?&quot;#define USE_SPECULAR_INTENSITYMAP&quot;:&quot;&quot;,s.roughnessMap?&quot;#define USE_ROUGHNESSMAP&quot;:&quot;&quot;,s.metalnessMap?&quot;#define USE_METALNESSMAP&quot;:&quot;&quot;,s.alphaMap?&quot;#define USE_ALPHAMAP&quot;:&quot;&quot;,s.alphaHash?&quot;#define USE_ALPHAHASH&quot;:&quot;&quot;,s.transmission?&quot;#define USE_TRANSMISSION&quot;:&quot;&quot;,s.transmissionMap?&quot;#define USE_TRANSMISSIONMAP&quot;:&quot;&quot;,s.thicknessMap?&quot;#define USE_THICKNESSMAP&quot;:&quot;&quot;,s.sheenColorMap?&quot;#define USE_SHEEN_COLORMAP&quot;:&quot;&quot;,s.sheenRoughnessMap?&quot;#define USE_SHEEN_ROUGHNESSMAP&quot;:&quot;&quot;,s.mapUv?&quot;#define MAP_UV &quot;+s.mapUv:&quot;&quot;,s.alphaMapUv?&quot;#define ALPHAMAP_UV &quot;+s.alphaMapUv:&quot;&quot;,s.lightMapUv?&quot;#define LIGHTMAP_UV &quot;+s.lightMapUv:&quot;&quot;,s.aoMapUv?&quot;#define AOMAP_UV &quot;+s.aoMapUv:&quot;&quot;,s.emissiveMapUv?&quot;#define EMISSIVEMAP_UV &quot;+s.emissiveMapUv:&quot;&quot;,s.bumpMapUv?&quot;#define BUMPMAP_UV &quot;+s.bumpMapUv:&quot;&quot;,s.normalMapUv?&quot;#define NORMALMAP_UV &quot;+s.normalMapUv:&quot;&quot;,s.displacementMapUv?&quot;#define DISPLACEMENTMAP_UV &quot;+s.displacementMapUv:&quot;&quot;,s.metalnessMapUv?&quot;#define METALNESSMAP_UV &quot;+s.metalnessMapUv:&quot;&quot;,s.roughnessMapUv?&quot;#define ROUGHNESSMAP_UV &quot;+s.roughnessMapUv:&quot;&quot;,s.anisotropyMapUv?&quot;#define ANISOTROPYMAP_UV &quot;+s.anisotropyMapUv:&quot;&quot;,s.clearcoatMapUv?&quot;#define CLEARCOATMAP_UV &quot;+s.clearcoatMapUv:&quot;&quot;,s.clearcoatNormalMapUv?&quot;#define CLEARCOAT_NORMALMAP_UV &quot;+s.clearcoatNormalMapUv:&quot;&quot;,s.clearcoatRoughnessMapUv?&quot;#define CLEARCOAT_ROUGHNESSMAP_UV &quot;+s.clearcoatRoughnessMapUv:&quot;&quot;,s.iridescenceMapUv?&quot;#define IRIDESCENCEMAP_UV &quot;+s.iridescenceMapUv:&quot;&quot;,s.iridescenceThicknessMapUv?&quot;#define IRIDESCENCE_THICKNESSMAP_UV &quot;+s.iridescenceThicknessMapUv:&quot;&quot;,s.sheenColorMapUv?&quot;#define SHEEN_COLORMAP_UV &quot;+s.sheenColorMapUv:&quot;&quot;,s.sheenRoughnessMapUv?&quot;#define SHEEN_ROUGHNESSMAP_UV &quot;+s.sheenRoughnessMapUv:&quot;&quot;,s.specularMapUv?&quot;#define SPECULARMAP_UV &quot;+s.specularMapUv:&quot;&quot;,s.specularColorMapUv?&quot;#define SPECULAR_COLORMAP_UV &quot;+s.specularColorMapUv:&quot;&quot;,s.specularIntensityMapUv?&quot;#define SPECULAR_INTENSITYMAP_UV &quot;+s.specularIntensityMapUv:&quot;&quot;,s.transmissionMapUv?&quot;#define TRANSMISSIONMAP_UV &quot;+s.transmissionMapUv:&quot;&quot;,s.thicknessMapUv?&quot;#define THICKNESSMAP_UV &quot;+s.thicknessMapUv:&quot;&quot;,s.vertexTangents&amp;&amp;!1===s.flatShading?&quot;#define USE_TANGENT&quot;:&quot;&quot;,s.vertexColors?&quot;#define USE_COLOR&quot;:&quot;&quot;,s.vertexAlphas?&quot;#define USE_COLOR_ALPHA&quot;:&quot;&quot;,s.vertexUv1s?&quot;#define USE_UV1&quot;:&quot;&quot;,s.vertexUv2s?&quot;#define USE_UV2&quot;:&quot;&quot;,s.vertexUv3s?&quot;#define USE_UV3&quot;:&quot;&quot;,s.pointsUvs?&quot;#define USE_POINTS_UV&quot;:&quot;&quot;,s.flatShading?&quot;#define FLAT_SHADED&quot;:&quot;&quot;,s.skinning?&quot;#define USE_SKINNING&quot;:&quot;&quot;,s.morphTargets?&quot;#define USE_MORPHTARGETS&quot;:&quot;&quot;,s.morphNormals&amp;&amp;!1===s.flatShading?&quot;#define USE_MORPHNORMALS&quot;:&quot;&quot;,s.morphColors&amp;&amp;s.isWebGL2?&quot;#define USE_MORPHCOLORS&quot;:&quot;&quot;,s.morphTargetsCount&gt;0&amp;&amp;s.isWebGL2?&quot;#define MORPHTARGETS_TEXTURE&quot;:&quot;&quot;,s.morphTargetsCount&gt;0&amp;&amp;s.isWebGL2?&quot;#define MORPHTARGETS_TEXTURE_STRIDE &quot;+s.morphTextureStride:&quot;&quot;,s.morphTargetsCount&gt;0&amp;&amp;s.isWebGL2?&quot;#define MORPHTARGETS_COUNT &quot;+s.morphTargetsCount:&quot;&quot;,s.doubleSided?&quot;#define DOUBLE_SIDED&quot;:&quot;&quot;,s.flipSided?&quot;#define FLIP_SIDED&quot;:&quot;&quot;,s.shadowMapEnabled?&quot;#define USE_SHADOWMAP&quot;:&quot;&quot;,s.shadowMapEnabled?&quot;#define &quot;+f:&quot;&quot;,s.sizeAttenuation?&quot;#define USE_SIZEATTENUATION&quot;:&quot;&quot;,s.numLightProbes&gt;0?&quot;#define USE_LIGHT_PROBES&quot;:&quot;&quot;,s.useLegacyLights?&quot;#define LEGACY_LIGHTS&quot;:&quot;&quot;,s.logarithmicDepthBuffer?&quot;#define USE_LOGDEPTHBUF&quot;:&quot;&quot;,s.logarithmicDepthBuffer&amp;&amp;s.rendererExtensionFragDepth?&quot;#define USE_LOGDEPTHBUF_EXT&quot;:&quot;&quot;,&quot;uniform mat4 modelMatrix;&quot;,&quot;uniform mat4 modelViewMatrix;&quot;,&quot;uniform mat4 projectionMatrix;&quot;,&quot;uniform mat4 viewMatrix;&quot;,&quot;uniform mat3 normalMatrix;&quot;,&quot;uniform vec3 cameraPosition;&quot;,&quot;uniform bool isOrthographic;&quot;,&quot;#ifdef USE_INSTANCING&quot;,&quot;\tattribute mat4 instanceMatrix;&quot;,&quot;#endif&quot;,&quot;#ifdef USE_INSTANCING_COLOR&quot;,&quot;\tattribute vec3 instanceColor;&quot;,&quot;#endif&quot;,&quot;attribute vec3 position;&quot;,&quot;attribute vec3 normal;&quot;,&quot;attribute vec2 uv;&quot;,&quot;#ifdef USE_UV1&quot;,&quot;\tattribute vec2 uv1;&quot;,&quot;#endif&quot;,&quot;#ifdef USE_UV2&quot;,&quot;\tattribute vec2 uv2;&quot;,&quot;#endif&quot;,&quot;#ifdef USE_UV3&quot;,&quot;\tattribute vec2 uv3;&quot;,&quot;#endif&quot;,&quot;#ifdef USE_TANGENT&quot;,&quot;\tattribute vec4 tangent;&quot;,&quot;#endif&quot;,&quot;#if defined( USE_COLOR_ALPHA )&quot;,&quot;\tattribute vec4 color;&quot;,&quot;#elif defined( USE_COLOR )&quot;,&quot;\tattribute vec3 color;&quot;,&quot;#endif&quot;,&quot;#if ( defined( USE_MORPHTARGETS ) &amp;&amp; ! defined( MORPHTARGETS_TEXTURE ) )&quot;,&quot;\tattribute vec3 morphTarget0;&quot;,&quot;\tattribute vec3 morphTarget1;&quot;,&quot;\tattribute vec3 morphTarget2;&quot;,&quot;\tattribute vec3 morphTarget3;&quot;,&quot;\t#ifdef USE_MORPHNORMALS&quot;,&quot;\t\tattribute vec3 morphNormal0;&quot;,&quot;\t\tattribute vec3 morphNormal1;&quot;,&quot;\t\tattribute vec3 morphNormal2;&quot;,&quot;\t\tattribute vec3 morphNormal3;&quot;,&quot;\t#else&quot;,&quot;\t\tattribute vec3 morphTarget4;&quot;,&quot;\t\tattribute vec3 morphTarget5;&quot;,&quot;\t\tattribute vec3 morphTarget6;&quot;,&quot;\t\tattribute vec3 morphTarget7;&quot;,&quot;\t#endif&quot;,&quot;#endif&quot;,&quot;#ifdef USE_SKINNING&quot;,&quot;\tattribute vec4 skinIndex;&quot;,&quot;\tattribute vec4 skinWeight;&quot;,&quot;#endif&quot;,&quot;\n&quot;].filter(ma).join(&quot;\n&quot;),R=[y,Ta(s),&quot;#define SHADER_TYPE &quot;+s.shaderType,&quot;#define SHADER_NAME &quot;+s.shaderName,S,s.useFog&amp;&amp;s.fog?&quot;#define USE_FOG&quot;:&quot;&quot;,s.useFog&amp;&amp;s.fogExp2?&quot;#define FOG_EXP2&quot;:&quot;&quot;,s.map?&quot;#define USE_MAP&quot;:&quot;&quot;,s.matcap?&quot;#define USE_MATCAP&quot;:&quot;&quot;,s.envMap?&quot;#define USE_ENVMAP&quot;:&quot;&quot;,s.envMap?&quot;#define &quot;+g:&quot;&quot;,s.envMap?&quot;#define &quot;+_:&quot;&quot;,s.envMap?&quot;#define &quot;+v:&quot;&quot;,x?&quot;#define CUBEUV_TEXEL_WIDTH &quot;+x.texelWidth:&quot;&quot;,x?&quot;#define CUBEUV_TEXEL_HEIGHT &quot;+x.texelHeight:&quot;&quot;,x?&quot;#define CUBEUV_MAX_MIP &quot;+x.maxMip+&quot;.0&quot;:&quot;&quot;,s.lightMap?&quot;#define USE_LIGHTMAP&quot;:&quot;&quot;,s.aoMap?&quot;#define USE_AOMAP&quot;:&quot;&quot;,s.bumpMap?&quot;#define USE_BUMPMAP&quot;:&quot;&quot;,s.normalMap?&quot;#define USE_NORMALMAP&quot;:&quot;&quot;,s.normalMapObjectSpace?&quot;#define USE_NORMALMAP_OBJECTSPACE&quot;:&quot;&quot;,s.normalMapTangentSpace?&quot;#define USE_NORMALMAP_TANGENTSPACE&quot;:&quot;&quot;,s.emissiveMap?&quot;#define USE_EMISSIVEMAP&quot;:&quot;&quot;,s.anisotropy?&quot;#define USE_ANISOTROPY&quot;:&quot;&quot;,s.anisotropyMap?&quot;#define USE_ANISOTROPYMAP&quot;:&quot;&quot;,s.clearcoat?&quot;#define USE_CLEARCOAT&quot;:&quot;&quot;,s.clearcoatMap?&quot;#define USE_CLEARCOATMAP&quot;:&quot;&quot;,s.clearcoatRoughnessMap?&quot;#define USE_CLEARCOAT_ROUGHNESSMAP&quot;:&quot;&quot;,s.clearcoatNormalMap?&quot;#define USE_CLEARCOAT_NORMALMAP&quot;:&quot;&quot;,s.iridescence?&quot;#define USE_IRIDESCENCE&quot;:&quot;&quot;,s.iridescenceMap?&quot;#define USE_IRIDESCENCEMAP&quot;:&quot;&quot;,s.iridescenceThicknessMap?&quot;#define USE_IRIDESCENCE_THICKNESSMAP&quot;:&quot;&quot;,s.specularMap?&quot;#define USE_SPECULARMAP&quot;:&quot;&quot;,s.specularColorMap?&quot;#define USE_SPECULAR_COLORMAP&quot;:&quot;&quot;,s.specularIntensityMap?&quot;#define USE_SPECULAR_INTENSITYMAP&quot;:&quot;&quot;,s.roughnessMap?&quot;#define USE_ROUGHNESSMAP&quot;:&quot;&quot;,s.metalnessMap?&quot;#define USE_METALNESSMAP&quot;:&quot;&quot;,s.alphaMap?&quot;#define USE_ALPHAMAP&quot;:&quot;&quot;,s.alphaTest?&quot;#define USE_ALPHATEST&quot;:&quot;&quot;,s.alphaHash?&quot;#define USE_ALPHAHASH&quot;:&quot;&quot;,s.sheen?&quot;#define USE_SHEEN&quot;:&quot;&quot;,s.sheenColorMap?&quot;#define USE_SHEEN_COLORMAP&quot;:&quot;&quot;,s.sheenRoughnessMap?&quot;#define USE_SHEEN_ROUGHNESSMAP&quot;:&quot;&quot;,s.transmission?&quot;#define USE_TRANSMISSION&quot;:&quot;&quot;,s.transmissionMap?&quot;#define USE_TRANSMISSIONMAP&quot;:&quot;&quot;,s.thicknessMap?&quot;#define USE_THICKNESSMAP&quot;:&quot;&quot;,s.vertexTangents&amp;&amp;!1===s.flatShading?&quot;#define USE_TANGENT&quot;:&quot;&quot;,s.vertexColors||s.instancingColor?&quot;#define USE_COLOR&quot;:&quot;&quot;,s.vertexAlphas?&quot;#define USE_COLOR_ALPHA&quot;:&quot;&quot;,s.vertexUv1s?&quot;#define USE_UV1&quot;:&quot;&quot;,s.vertexUv2s?&quot;#define USE_UV2&quot;:&quot;&quot;,s.vertexUv3s?&quot;#define USE_UV3&quot;:&quot;&quot;,s.pointsUvs?&quot;#define USE_POINTS_UV&quot;:&quot;&quot;,s.gradientMap?&quot;#define USE_GRADIENTMAP&quot;:&quot;&quot;,s.flatShading?&quot;#define FLAT_SHADED&quot;:&quot;&quot;,s.doubleSided?&quot;#define DOUBLE_SIDED&quot;:&quot;&quot;,s.flipSided?&quot;#define FLIP_SIDED&quot;:&quot;&quot;,s.shadowMapEnabled?&quot;#define USE_SHADOWMAP&quot;:&quot;&quot;,s.shadowMapEnabled?&quot;#define &quot;+f:&quot;&quot;,s.premultipliedAlpha?&quot;#define PREMULTIPLIED_ALPHA&quot;:&quot;&quot;,s.numLightProbes&gt;0?&quot;#define USE_LIGHT_PROBES&quot;:&quot;&quot;,s.useLegacyLights?&quot;#define LEGACY_LIGHTS&quot;:&quot;&quot;,s.decodeVideoTexture?&quot;#define DECODE_VIDEO_TEXTURE&quot;:&quot;&quot;,s.logarithmicDepthBuffer?&quot;#define USE_LOGDEPTHBUF&quot;:&quot;&quot;,s.logarithmicDepthBuffer&amp;&amp;s.rendererExtensionFragDepth?&quot;#define USE_LOGDEPTHBUF_EXT&quot;:&quot;&quot;,&quot;uniform mat4 viewMatrix;&quot;,&quot;uniform vec3 cameraPosition;&quot;,&quot;uniform bool isOrthographic;&quot;,s.toneMapping!==p?&quot;#define TONE_MAPPING&quot;:&quot;&quot;,s.toneMapping!==p?yr.tonemapping_pars_fragment:&quot;&quot;,s.toneMapping!==p?pa(&quot;toneMapping&quot;,s.toneMapping):&quot;&quot;,s.dithering?&quot;#define DITHERING&quot;:&quot;&quot;,s.opaque?&quot;#define OPAQUE&quot;:&quot;&quot;,yr.colorspace_pars_fragment,da(&quot;linearToOutputTexel&quot;,s.outputColorSpace),s.useDepthPacking?&quot;#define DEPTH_PACKING &quot;+s.depthPacking:&quot;&quot;,&quot;\n&quot;].filter(ma).join(&quot;\n&quot;)),c=va(c),c=fa(c,s),c=ga(c,s),m=va(m),m=fa(m,s),m=ga(m,s),c=Sa(c),m=Sa(m),s.isWebGL2&amp;&amp;!0!==s.isRawShaderMaterial&amp;&amp;(C=&quot;#version 300 es\n&quot;,w=[M,&quot;precision mediump sampler2DArray;&quot;,&quot;#define attribute in&quot;,&quot;#define varying out&quot;,&quot;#define texture2D texture&quot;].join(&quot;\n&quot;)+&quot;\n&quot;+w,R=[&quot;precision mediump sampler2DArray;&quot;,&quot;#define varying in&quot;,s.glslVersion===Jt?&quot;&quot;:&quot;layout(location = 0) out highp vec4 pc_fragColor;&quot;,s.glslVersion===Jt?&quot;&quot;:&quot;#define gl_FragColor pc_fragColor&quot;,&quot;#define gl_FragDepthEXT gl_FragDepth&quot;,&quot;#define texture2D texture&quot;,&quot;#define textureCube texture&quot;,&quot;#define texture2DProj textureProj&quot;,&quot;#define texture2DLodEXT textureLod&quot;,&quot;#define texture2DProjLodEXT textureProjLod&quot;,&quot;#define textureCubeLodEXT textureLod&quot;,&quot;#define texture2DGradEXT textureGrad&quot;,&quot;#define texture2DProjGradEXT textureProjGrad&quot;,&quot;#define textureCubeGradEXT textureGrad&quot;].join(&quot;\n&quot;)+&quot;\n&quot;+R);const L=C+w+c,P=C+R+m,I=la(o,o.VERTEX_SHADER,L),U=la(o,o.FRAGMENT_SHADER,P);function D(e){if(t.debug.checkShaderErrors){const n=o.getProgramInfoLog(E).trim(),i=o.getShaderInfoLog(I).trim(),r=o.getShaderInfoLog(U).trim();let s=!0,a=!0;if(!1===o.getProgramParameter(E,o.LINK_STATUS))if(s=!1,&quot;function&quot;==typeof t.debug.onShaderError)t.debug.onShaderError(o,E,I,U);else{const t=ua(o,I,&quot;vertex&quot;),e=ua(o,U,&quot;fragment&quot;);console.error(&quot;THREE.WebGLProgram: Shader Error &quot;+o.getError()+&quot; - VALIDATE_STATUS &quot;+o.getProgramParameter(E,o.VALIDATE_STATUS)+&quot;\n\nProgram Info Log: &quot;+n+&quot;\n&quot;+t+&quot;\n&quot;+e)}else&quot;&quot;!==n?console.warn(&quot;THREE.WebGLProgram: Program Info Log:&quot;,n):&quot;&quot;!==i&amp;&amp;&quot;&quot;!==r||(a=!1);a&amp;&amp;(e.diagnostics={runnable:s,programLog:n,vertexShader:{log:i,prefix:w},fragmentShader:{log:r,prefix:R}})}o.deleteShader(I),o.deleteShader(U),N=new oa(o,E),O=function(t,e){const n={},i=t.getProgramParameter(e,t.ACTIVE_ATTRIBUTES);for(let r=0;r&lt;i;r++){const i=t.getActiveAttrib(e,r),s=i.name;let a=1;i.type===t.FLOAT_MAT2&amp;&amp;(a=2),i.type===t.FLOAT_MAT3&amp;&amp;(a=3),i.type===t.FLOAT_MAT4&amp;&amp;(a=4),n[s]={type:i.type,location:t.getAttribLocation(e,s),locationSize:a}}return n}(o,E)}let N,O;o.attachShader(E,I),o.attachShader(E,U),void 0!==s.index0AttributeName?o.bindAttribLocation(E,0,s.index0AttributeName):!0===s.morphTargets&amp;&amp;o.bindAttribLocation(E,0,&quot;position&quot;),o.linkProgram(E),this.getUniforms=function(){return void 0===N&amp;&amp;D(this),N},this.getAttributes=function(){return void 0===O&amp;&amp;D(this),O};let F=!1===s.rendererExtensionParallelShaderCompile;return this.isReady=function(){return!1===F&amp;&amp;(F=o.getProgramParameter(E,ca)),F},this.destroy=function(){a.releaseStatesOfProgram(this),o.deleteProgram(E),this.program=void 0},this.type=s.shaderType,this.name=s.shaderName,this.id=ha++,this.cacheKey=e,this.usedTimes=1,this.program=E,this.vertexShader=I,this.fragmentShader=U,this}let wa=0;class Aa{constructor(){this.shaderCache=new Map,this.materialCache=new Map}update(t){const e=t.vertexShader,n=t.fragmentShader,i=this._getShaderStage(e),r=this._getShaderStage(n),s=this._getShaderCacheForMaterial(t);return!1===s.has(i)&amp;&amp;(s.add(i),i.usedTimes++),!1===s.has(r)&amp;&amp;(s.add(r),r.usedTimes++),this}remove(t){const e=this.materialCache.get(t);for(const t of e)t.usedTimes--,0===t.usedTimes&amp;&amp;this.shaderCache.delete(t.code);return this.materialCache.delete(t),this}getVertexShaderID(t){return this._getShaderStage(t.vertexShader).id}getFragmentShaderID(t){return this._getShaderStage(t.fragmentShader).id}dispose(){this.shaderCache.clear(),this.materialCache.clear()}_getShaderCacheForMaterial(t){const e=this.materialCache;let n=e.get(t);return void 0===n&amp;&amp;(n=new Set,e.set(t,n)),n}_getShaderStage(t){const e=this.shaderCache;let n=e.get(t);return void 0===n&amp;&amp;(n=new Ra(t),e.set(t,n)),n}}class Ra{constructor(t){this.id=wa++,this.code=t,this.usedTimes=0}}function Ca(t,e,n,i,r,s,o){const l=new In,c=new Aa,h=[],u=r.isWebGL2,d=r.logarithmicDepthBuffer,m=r.vertexTextures;let f=r.precision;const g={MeshDepthMaterial:&quot;depth&quot;,MeshDistanceMaterial:&quot;distanceRGBA&quot;,MeshNormalMaterial:&quot;normal&quot;,MeshBasicMaterial:&quot;basic&quot;,MeshLambertMaterial:&quot;lambert&quot;,MeshPhongMaterial:&quot;phong&quot;,MeshToonMaterial:&quot;toon&quot;,MeshStandardMaterial:&quot;physical&quot;,MeshPhysicalMaterial:&quot;physical&quot;,MeshMatcapMaterial:&quot;matcap&quot;,LineBasicMaterial:&quot;basic&quot;,LineDashedMaterial:&quot;dashed&quot;,PointsMaterial:&quot;points&quot;,ShadowMaterial:&quot;shadow&quot;,SpriteMaterial:&quot;sprite&quot;};function _(t){return 0===t?&quot;uv&quot;:`uv${t}`}return{getParameters:function(s,l,h,v,x){const y=v.fog,M=x.geometry,S=s.isMeshStandardMaterial?v.environment:null,b=(s.isMeshStandardMaterial?n:e).get(s.envMap||S),T=b&amp;&amp;b.mapping===A?b.image.height:null,E=g[s.type];null!==s.precision&amp;&amp;(f=r.getMaxPrecision(s.precision),f!==s.precision&amp;&amp;console.warn(&quot;THREE.WebGLProgram.getParameters:&quot;,s.precision,&quot;not supported, using&quot;,f,&quot;instead.&quot;));const w=M.morphAttributes.position||M.morphAttributes.normal||M.morphAttributes.color,R=void 0!==w?w.length:0;let C,L,P,I,U=0;if(void 0!==M.morphAttributes.position&amp;&amp;(U=1),void 0!==M.morphAttributes.normal&amp;&amp;(U=2),void 0!==M.morphAttributes.color&amp;&amp;(U=3),E){const t=Sr[E];C=t.vertexShader,L=t.fragmentShader}else C=s.vertexShader,L=s.fragmentShader,c.update(s),P=c.getVertexShaderID(s),I=c.getFragmentShaderID(s);const D=t.getRenderTarget(),N=!0===x.isInstancedMesh,O=!0===x.isBatchedMesh,F=!!s.map,B=!!s.matcap,z=!!b,G=!!s.aoMap,H=!!s.lightMap,V=!!s.bumpMap,k=!!s.normalMap,W=!!s.displacementMap,X=!!s.emissiveMap,j=!!s.metalnessMap,q=!!s.roughnessMap,Y=s.anisotropy&gt;0,Z=s.clearcoat&gt;0,J=s.iridescence&gt;0,K=s.sheen&gt;0,$=s.transmission&gt;0,Q=Y&amp;&amp;!!s.anisotropyMap,tt=Z&amp;&amp;!!s.clearcoatMap,et=Z&amp;&amp;!!s.clearcoatNormalMap,nt=Z&amp;&amp;!!s.clearcoatRoughnessMap,it=J&amp;&amp;!!s.iridescenceMap,rt=J&amp;&amp;!!s.iridescenceThicknessMap,st=K&amp;&amp;!!s.sheenColorMap,at=K&amp;&amp;!!s.sheenRoughnessMap,ot=!!s.specularMap,lt=!!s.specularColorMap,ct=!!s.specularIntensityMap,ht=$&amp;&amp;!!s.transmissionMap,ut=$&amp;&amp;!!s.thicknessMap,dt=!!s.gradientMap,pt=!!s.alphaMap,mt=s.alphaTest&gt;0,ft=!!s.alphaHash,gt=!!s.extensions,_t=!!M.attributes.uv1,vt=!!M.attributes.uv2,xt=!!M.attributes.uv3;let yt=p;return s.toneMapped&amp;&amp;(null!==D&amp;&amp;!0!==D.isXRRenderTarget||(yt=t.toneMapping)),{isWebGL2:u,shaderID:E,shaderType:s.type,shaderName:s.name,vertexShader:C,fragmentShader:L,defines:s.defines,customVertexShaderID:P,customFragmentShaderID:I,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:f,batching:O,instancing:N,instancingColor:N&amp;&amp;null!==x.instanceColor,supportsVertexTextures:m,outputColorSpace:null===D?t.outputColorSpace:!0===D.isXRRenderTarget?D.texture.colorSpace:Ht,map:F,matcap:B,envMap:z,envMapMode:z&amp;&amp;b.mapping,envMapCubeUVHeight:T,aoMap:G,lightMap:H,bumpMap:V,normalMap:k,displacementMap:m&amp;&amp;W,emissiveMap:X,normalMapObjectSpace:k&amp;&amp;1===s.normalMapType,normalMapTangentSpace:k&amp;&amp;0===s.normalMapType,metalnessMap:j,roughnessMap:q,anisotropy:Y,anisotropyMap:Q,clearcoat:Z,clearcoatMap:tt,clearcoatNormalMap:et,clearcoatRoughnessMap:nt,iridescence:J,iridescenceMap:it,iridescenceThicknessMap:rt,sheen:K,sheenColorMap:st,sheenRoughnessMap:at,specularMap:ot,specularColorMap:lt,specularIntensityMap:ct,transmission:$,transmissionMap:ht,thicknessMap:ut,gradientMap:dt,opaque:!1===s.transparent&amp;&amp;1===s.blending,alphaMap:pt,alphaTest:mt,alphaHash:ft,combine:s.combine,mapUv:F&amp;&amp;_(s.map.channel),aoMapUv:G&amp;&amp;_(s.aoMap.channel),lightMapUv:H&amp;&amp;_(s.lightMap.channel),bumpMapUv:V&amp;&amp;_(s.bumpMap.channel),normalMapUv:k&amp;&amp;_(s.normalMap.channel),displacementMapUv:W&amp;&amp;_(s.displacementMap.channel),emissiveMapUv:X&amp;&amp;_(s.emissiveMap.channel),metalnessMapUv:j&amp;&amp;_(s.metalnessMap.channel),roughnessMapUv:q&amp;&amp;_(s.roughnessMap.channel),anisotropyMapUv:Q&amp;&amp;_(s.anisotropyMap.channel),clearcoatMapUv:tt&amp;&amp;_(s.clearcoatMap.channel),clearcoatNormalMapUv:et&amp;&amp;_(s.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:nt&amp;&amp;_(s.clearcoatRoughnessMap.channel),iridescenceMapUv:it&amp;&amp;_(s.iridescenceMap.channel),iridescenceThicknessMapUv:rt&amp;&amp;_(s.iridescenceThicknessMap.channel),sheenColorMapUv:st&amp;&amp;_(s.sheenColorMap.channel),sheenRoughnessMapUv:at&amp;&amp;_(s.sheenRoughnessMap.channel),specularMapUv:ot&amp;&amp;_(s.specularMap.channel),specularColorMapUv:lt&amp;&amp;_(s.specularColorMap.channel),specularIntensityMapUv:ct&amp;&amp;_(s.specularIntensityMap.channel),transmissionMapUv:ht&amp;&amp;_(s.transmissionMap.channel),thicknessMapUv:ut&amp;&amp;_(s.thicknessMap.channel),alphaMapUv:pt&amp;&amp;_(s.alphaMap.channel),vertexTangents:!!M.attributes.tangent&amp;&amp;(k||Y),vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&amp;&amp;!!M.attributes.color&amp;&amp;4===M.attributes.color.itemSize,vertexUv1s:_t,vertexUv2s:vt,vertexUv3s:xt,pointsUvs:!0===x.isPoints&amp;&amp;!!M.attributes.uv&amp;&amp;(F||pt),fog:!!y,useFog:!0===s.fog,fogExp2:y&amp;&amp;y.isFogExp2,flatShading:!0===s.flatShading,sizeAttenuation:!0===s.sizeAttenuation,logarithmicDepthBuffer:d,skinning:!0===x.isSkinnedMesh,morphTargets:void 0!==M.morphAttributes.position,morphNormals:void 0!==M.morphAttributes.normal,morphColors:void 0!==M.morphAttributes.color,morphTargetsCount:R,morphTextureStride:U,numDirLights:l.directional.length,numPointLights:l.point.length,numSpotLights:l.spot.length,numSpotLightMaps:l.spotLightMap.length,numRectAreaLights:l.rectArea.length,numHemiLights:l.hemi.length,numDirLightShadows:l.directionalShadowMap.length,numPointLightShadows:l.pointShadowMap.length,numSpotLightShadows:l.spotShadowMap.length,numSpotLightShadowsWithMaps:l.numSpotLightShadowsWithMaps,numLightProbes:l.numLightProbes,numClippingPlanes:o.numPlanes,numClipIntersection:o.numIntersection,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&amp;&amp;h.length&gt;0,shadowMapType:t.shadowMap.type,toneMapping:yt,useLegacyLights:t._useLegacyLights,decodeVideoTexture:F&amp;&amp;!0===s.map.isVideoTexture&amp;&amp;Re.getTransfer(s.map.colorSpace)===Xt,premultipliedAlpha:s.premultipliedAlpha,doubleSided:2===s.side,flipSided:s.side===a,useDepthPacking:s.depthPacking&gt;=0,depthPacking:s.depthPacking||0,index0AttributeName:s.index0AttributeName,extensionDerivatives:gt&amp;&amp;!0===s.extensions.derivatives,extensionFragDepth:gt&amp;&amp;!0===s.extensions.fragDepth,extensionDrawBuffers:gt&amp;&amp;!0===s.extensions.drawBuffers,extensionShaderTextureLOD:gt&amp;&amp;!0===s.extensions.shaderTextureLOD,extensionClipCullDistance:gt&amp;&amp;s.extensions.clipCullDistance&amp;&amp;i.has(&quot;WEBGL_clip_cull_distance&quot;),rendererExtensionFragDepth:u||i.has(&quot;EXT_frag_depth&quot;),rendererExtensionDrawBuffers:u||i.has(&quot;WEBGL_draw_buffers&quot;),rendererExtensionShaderTextureLod:u||i.has(&quot;EXT_shader_texture_lod&quot;),rendererExtensionParallelShaderCompile:i.has(&quot;KHR_parallel_shader_compile&quot;),customProgramCacheKey:s.customProgramCacheKey()}},getProgramCacheKey:function(e){const n=[];if(e.shaderID?n.push(e.shaderID):(n.push(e.customVertexShaderID),n.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)n.push(t),n.push(e.defines[t]);return!1===e.isRawShaderMaterial&amp;&amp;(!function(t,e){t.push(e.precision),t.push(e.outputColorSpace),t.push(e.envMapMode),t.push(e.envMapCubeUVHeight),t.push(e.mapUv),t.push(e.alphaMapUv),t.push(e.lightMapUv),t.push(e.aoMapUv),t.push(e.bumpMapUv),t.push(e.normalMapUv),t.push(e.displacementMapUv),t.push(e.emissiveMapUv),t.push(e.metalnessMapUv),t.push(e.roughnessMapUv),t.push(e.anisotropyMapUv),t.push(e.clearcoatMapUv),t.push(e.clearcoatNormalMapUv),t.push(e.clearcoatRoughnessMapUv),t.push(e.iridescenceMapUv),t.push(e.iridescenceThicknessMapUv),t.push(e.sheenColorMapUv),t.push(e.sheenRoughnessMapUv),t.push(e.specularMapUv),t.push(e.specularColorMapUv),t.push(e.specularIntensityMapUv),t.push(e.transmissionMapUv),t.push(e.thicknessMapUv),t.push(e.combine),t.push(e.fogExp2),t.push(e.sizeAttenuation),t.push(e.morphTargetsCount),t.push(e.morphAttributeCount),t.push(e.numDirLights),t.push(e.numPointLights),t.push(e.numSpotLights),t.push(e.numSpotLightMaps),t.push(e.numHemiLights),t.push(e.numRectAreaLights),t.push(e.numDirLightShadows),t.push(e.numPointLightShadows),t.push(e.numSpotLightShadows),t.push(e.numSpotLightShadowsWithMaps),t.push(e.numLightProbes),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.depthPacking)}(n,e),function(t,e){l.disableAll(),e.isWebGL2&amp;&amp;l.enable(0);e.supportsVertexTextures&amp;&amp;l.enable(1);e.instancing&amp;&amp;l.enable(2);e.instancingColor&amp;&amp;l.enable(3);e.matcap&amp;&amp;l.enable(4);e.envMap&amp;&amp;l.enable(5);e.normalMapObjectSpace&amp;&amp;l.enable(6);e.normalMapTangentSpace&amp;&amp;l.enable(7);e.clearcoat&amp;&amp;l.enable(8);e.iridescence&amp;&amp;l.enable(9);e.alphaTest&amp;&amp;l.enable(10);e.vertexColors&amp;&amp;l.enable(11);e.vertexAlphas&amp;&amp;l.enable(12);e.vertexUv1s&amp;&amp;l.enable(13);e.vertexUv2s&amp;&amp;l.enable(14);e.vertexUv3s&amp;&amp;l.enable(15);e.vertexTangents&amp;&amp;l.enable(16);e.anisotropy&amp;&amp;l.enable(17);e.alphaHash&amp;&amp;l.enable(18);e.batching&amp;&amp;l.enable(19);t.push(l.mask),l.disableAll(),e.fog&amp;&amp;l.enable(0);e.useFog&amp;&amp;l.enable(1);e.flatShading&amp;&amp;l.enable(2);e.logarithmicDepthBuffer&amp;&amp;l.enable(3);e.skinning&amp;&amp;l.enable(4);e.morphTargets&amp;&amp;l.enable(5);e.morphNormals&amp;&amp;l.enable(6);e.morphColors&amp;&amp;l.enable(7);e.premultipliedAlpha&amp;&amp;l.enable(8);e.shadowMapEnabled&amp;&amp;l.enable(9);e.useLegacyLights&amp;&amp;l.enable(10);e.doubleSided&amp;&amp;l.enable(11);e.flipSided&amp;&amp;l.enable(12);e.useDepthPacking&amp;&amp;l.enable(13);e.dithering&amp;&amp;l.enable(14);e.transmission&amp;&amp;l.enable(15);e.sheen&amp;&amp;l.enable(16);e.opaque&amp;&amp;l.enable(17);e.pointsUvs&amp;&amp;l.enable(18);e.decodeVideoTexture&amp;&amp;l.enable(19);t.push(l.mask)}(n,e),n.push(t.outputColorSpace)),n.push(e.customProgramCacheKey),n.join()},getUniforms:function(t){const e=g[t.type];let n;if(e){const t=Sr[e];n=nr.clone(t.uniforms)}else n=t.uniforms;return n},acquireProgram:function(e,n){let i;for(let t=0,e=h.length;t&lt;e;t++){const e=h[t];if(e.cacheKey===n){i=e,++i.usedTimes;break}}return void 0===i&amp;&amp;(i=new Ea(t,n,e,s),h.push(i)),i},releaseProgram:function(t){if(0==--t.usedTimes){const e=h.indexOf(t);h[e]=h[h.length-1],h.pop(),t.destroy()}},releaseShaderCache:function(t){c.remove(t)},programs:h,dispose:function(){c.dispose()}}}function La(){let t=new WeakMap;return{get:function(e){let n=t.get(e);return void 0===n&amp;&amp;(n={},t.set(e,n)),n},remove:function(e){t.delete(e)},update:function(e,n,i){t.get(e)[n]=i},dispose:function(){t=new WeakMap}}}function Pa(t,e){return t.groupOrder!==e.groupOrder?t.groupOrder-e.groupOrder:t.renderOrder!==e.renderOrder?t.renderOrder-e.renderOrder:t.material.id!==e.material.id?t.material.id-e.material.id:t.z!==e.z?t.z-e.z:t.id-e.id}function Ia(t,e){return t.groupOrder!==e.groupOrder?t.groupOrder-e.groupOrder:t.renderOrder!==e.renderOrder?t.renderOrder-e.renderOrder:t.z!==e.z?e.z-t.z:t.id-e.id}function Ua(){const t=[];let e=0;const n=[],i=[],r=[];function s(n,i,r,s,a,o){let l=t[e];return void 0===l?(l={id:n.id,object:n,geometry:i,material:r,groupOrder:s,renderOrder:n.renderOrder,z:a,group:o},t[e]=l):(l.id=n.id,l.object=n,l.geometry=i,l.material=r,l.groupOrder=s,l.renderOrder=n.renderOrder,l.z=a,l.group=o),e++,l}return{opaque:n,transmissive:i,transparent:r,init:function(){e=0,n.length=0,i.length=0,r.length=0},push:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission&gt;0?i.push(h):!0===a.transparent?r.push(h):n.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission&gt;0?i.unshift(h):!0===a.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=e,i=t.length;n&lt;i;n++){const e=t[n];if(null===e.id)break;e.id=null,e.object=null,e.geometry=null,e.material=null,e.group=null}},sort:function(t,e){n.length&gt;1&amp;&amp;n.sort(t||Pa),i.length&gt;1&amp;&amp;i.sort(e||Ia),r.length&gt;1&amp;&amp;r.sort(e||Ia)}}}function Da(){let t=new WeakMap;return{get:function(e,n){const i=t.get(e);let r;return void 0===i?(r=new Ua,t.set(e,[r])):n&gt;=i.length?(r=new Ua,i.push(r)):r=i[n],r},dispose:function(){t=new WeakMap}}}function Na(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case&quot;DirectionalLight&quot;:n={direction:new We,color:new ci};break;case&quot;SpotLight&quot;:n={position:new We,direction:new We,color:new ci,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case&quot;PointLight&quot;:n={position:new We,color:new ci,distance:0,decay:0};break;case&quot;HemisphereLight&quot;:n={direction:new We,skyColor:new ci,groundColor:new ci};break;case&quot;RectAreaLight&quot;:n={color:new ci,position:new We,halfWidth:new We,halfHeight:new We}}return t[e.id]=n,n}}}let Oa=0;function Fa(t,e){return(e.castShadow?2:0)-(t.castShadow?2:0)+(e.map?1:0)-(t.map?1:0)}function Ba(t,e){const n=new Na,i=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case&quot;DirectionalLight&quot;:case&quot;SpotLight&quot;:n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new me};break;case&quot;PointLight&quot;:n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new me,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=n,n}}}(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let t=0;t&lt;9;t++)r.probe.push(new We);const s=new We,a=new Mn,o=new Mn;return{setup:function(s,a){let o=0,l=0,c=0;for(let t=0;t&lt;9;t++)r.probe[t].set(0,0,0);let h=0,u=0,d=0,p=0,m=0,f=0,g=0,_=0,v=0,x=0,y=0;s.sort(Fa);const M=!0===a?Math.PI:1;for(let t=0,e=s.length;t&lt;e;t++){const e=s[t],a=e.color,S=e.intensity,b=e.distance,T=e.shadow&amp;&amp;e.shadow.map?e.shadow.map.texture:null;if(e.isAmbientLight)o+=a.r*S*M,l+=a.g*S*M,c+=a.b*S*M;else if(e.isLightProbe){for(let t=0;t&lt;9;t++)r.probe[t].addScaledVector(e.sh.coefficients[t],S);y++}else if(e.isDirectionalLight){const t=n.get(e);if(t.color.copy(e.color).multiplyScalar(e.intensity*M),e.castShadow){const t=e.shadow,n=i.get(e);n.shadowBias=t.bias,n.shadowNormalBias=t.normalBias,n.shadowRadius=t.radius,n.shadowMapSize=t.mapSize,r.directionalShadow[h]=n,r.directionalShadowMap[h]=T,r.directionalShadowMatrix[h]=e.shadow.matrix,f++}r.directional[h]=t,h++}else if(e.isSpotLight){const t=n.get(e);t.position.setFromMatrixPosition(e.matrixWorld),t.color.copy(a).multiplyScalar(S*M),t.distance=b,t.coneCos=Math.cos(e.angle),t.penumbraCos=Math.cos(e.angle*(1-e.penumbra)),t.decay=e.decay,r.spot[d]=t;const s=e.shadow;if(e.map&amp;&amp;(r.spotLightMap[v]=e.map,v++,s.updateMatrices(e),e.castShadow&amp;&amp;x++),r.spotLightMatrix[d]=s.matrix,e.castShadow){const t=i.get(e);t.shadowBias=s.bias,t.shadowNormalBias=s.normalBias,t.shadowRadius=s.radius,t.shadowMapSize=s.mapSize,r.spotShadow[d]=t,r.spotShadowMap[d]=T,_++}d++}else if(e.isRectAreaLight){const t=n.get(e);t.color.copy(a).multiplyScalar(S),t.halfWidth.set(.5*e.width,0,0),t.halfHeight.set(0,.5*e.height,0),r.rectArea[p]=t,p++}else if(e.isPointLight){const t=n.get(e);if(t.color.copy(e.color).multiplyScalar(e.intensity*M),t.distance=e.distance,t.decay=e.decay,e.castShadow){const t=e.shadow,n=i.get(e);n.shadowBias=t.bias,n.shadowNormalBias=t.normalBias,n.shadowRadius=t.radius,n.shadowMapSize=t.mapSize,n.shadowCameraNear=t.camera.near,n.shadowCameraFar=t.camera.far,r.pointShadow[u]=n,r.pointShadowMap[u]=T,r.pointShadowMatrix[u]=e.shadow.matrix,g++}r.point[u]=t,u++}else if(e.isHemisphereLight){const t=n.get(e);t.skyColor.copy(e.color).multiplyScalar(S*M),t.groundColor.copy(e.groundColor).multiplyScalar(S*M),r.hemi[m]=t,m++}}p&gt;0&amp;&amp;(e.isWebGL2?!0===t.has(&quot;OES_texture_float_linear&quot;)?(r.rectAreaLTC1=Mr.LTC_FLOAT_1,r.rectAreaLTC2=Mr.LTC_FLOAT_2):(r.rectAreaLTC1=Mr.LTC_HALF_1,r.rectAreaLTC2=Mr.LTC_HALF_2):!0===t.has(&quot;OES_texture_float_linear&quot;)?(r.rectAreaLTC1=Mr.LTC_FLOAT_1,r.rectAreaLTC2=Mr.LTC_FLOAT_2):!0===t.has(&quot;OES_texture_half_float_linear&quot;)?(r.rectAreaLTC1=Mr.LTC_HALF_1,r.rectAreaLTC2=Mr.LTC_HALF_2):console.error(&quot;THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.&quot;)),r.ambient[0]=o,r.ambient[1]=l,r.ambient[2]=c;const S=r.hash;S.directionalLength===h&amp;&amp;S.pointLength===u&amp;&amp;S.spotLength===d&amp;&amp;S.rectAreaLength===p&amp;&amp;S.hemiLength===m&amp;&amp;S.numDirectionalShadows===f&amp;&amp;S.numPointShadows===g&amp;&amp;S.numSpotShadows===_&amp;&amp;S.numSpotMaps===v&amp;&amp;S.numLightProbes===y||(r.directional.length=h,r.spot.length=d,r.rectArea.length=p,r.point.length=u,r.hemi.length=m,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=g,r.pointShadowMap.length=g,r.spotShadow.length=_,r.spotShadowMap.length=_,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=g,r.spotLightMatrix.length=_+v-x,r.spotLightMap.length=v,r.numSpotLightShadowsWithMaps=x,r.numLightProbes=y,S.directionalLength=h,S.pointLength=u,S.spotLength=d,S.rectAreaLength=p,S.hemiLength=m,S.numDirectionalShadows=f,S.numPointShadows=g,S.numSpotShadows=_,S.numSpotMaps=v,S.numLightProbes=y,r.version=Oa++)},setupView:function(t,e){let n=0,i=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e&lt;d;e++){const d=t[e];if(d.isDirectionalLight){const t=r.directional[n];t.direction.setFromMatrixPosition(d.matrixWorld),s.setFromMatrixPosition(d.target.matrixWorld),t.direction.sub(s),t.direction.transformDirection(u),n++}else if(d.isSpotLight){const t=r.spot[l];t.position.setFromMatrixPosition(d.matrixWorld),t.position.applyMatrix4(u),t.direction.setFromMatrixPosition(d.matrixWorld),s.setFromMatrixPosition(d.target.matrixWorld),t.direction.sub(s),t.direction.transformDirection(u),l++}else if(d.isRectAreaLight){const t=r.rectArea[c];t.position.setFromMatrixPosition(d.matrixWorld),t.position.applyMatrix4(u),o.identity(),a.copy(d.matrixWorld),a.premultiply(u),o.extractRotation(a),t.halfWidth.set(.5*d.width,0,0),t.halfHeight.set(0,.5*d.height,0),t.halfWidth.applyMatrix4(o),t.halfHeight.applyMatrix4(o),c++}else if(d.isPointLight){const t=r.point[i];t.position.setFromMatrixPosition(d.matrixWorld),t.position.applyMatrix4(u),i++}else if(d.isHemisphereLight){const t=r.hemi[h];t.direction.setFromMatrixPosition(d.matrixWorld),t.direction.transformDirection(u),h++}}},state:r}}function za(t,e){const n=new Ba(t,e),i=[],r=[];return{init:function(){i.length=0,r.length=0},state:{lightsArray:i,shadowsArray:r,lights:n},setupLights:function(t){n.setup(i,t)},setupLightsView:function(t){n.setupView(i,t)},pushLight:function(t){i.push(t)},pushShadow:function(t){r.push(t)}}}function Ga(t,e){let n=new WeakMap;return{get:function(i,r=0){const s=n.get(i);let a;return void 0===s?(a=new za(t,e),n.set(i,[a])):r&gt;=s.length?(a=new za(t,e),s.push(a)):a=s[r],a},dispose:function(){n=new WeakMap}}}class Ha extends di{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type=&quot;MeshDepthMaterial&quot;,this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class Va extends di{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type=&quot;MeshDistanceMaterial&quot;,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}function ka(t,e,i){let o=new gr;const l=new me,c=new me,h=new Be,u=new Ha({depthPacking:3201}),d=new Va,p={},m=i.maxTextureSize,f={[s]:a,[a]:s,2:2},g=new ir({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new me},radius:{value:4}},vertexShader:&quot;void main() {\n\tgl_Position = vec4( position, 1.0 );\n}&quot;,fragmentShader:&quot;uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include &lt;packing&gt;\nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples &lt;= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples &lt;= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i &lt; samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}&quot;}),_=g.clone();_.defines.HORIZONTAL_PASS=1;const v=new Ii;v.setAttribute(&quot;position&quot;,new Mi(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const x=new Ji(v,g),y=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=n;let M=this.type;function S(n,i){const r=e.update(x);g.defines.VSM_SAMPLES!==n.blurSamples&amp;&amp;(g.defines.VSM_SAMPLES=n.blurSamples,_.defines.VSM_SAMPLES=n.blurSamples,g.needsUpdate=!0,_.needsUpdate=!0),null===n.mapPass&amp;&amp;(n.mapPass=new Ge(l.x,l.y)),g.uniforms.shadow_pass.value=n.map.texture,g.uniforms.resolution.value=n.mapSize,g.uniforms.radius.value=n.radius,t.setRenderTarget(n.mapPass),t.clear(),t.renderBufferDirect(i,null,r,g,x,null),_.uniforms.shadow_pass.value=n.mapPass.texture,_.uniforms.resolution.value=n.mapSize,_.uniforms.radius.value=n.radius,t.setRenderTarget(n.map),t.clear(),t.renderBufferDirect(i,null,r,_,x,null)}function b(e,n,i,s){let a=null;const o=!0===i.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(void 0!==o)a=o;else if(a=!0===i.isPointLight?d:u,t.localClippingEnabled&amp;&amp;!0===n.clipShadows&amp;&amp;Array.isArray(n.clippingPlanes)&amp;&amp;0!==n.clippingPlanes.length||n.displacementMap&amp;&amp;0!==n.displacementScale||n.alphaMap&amp;&amp;n.alphaTest&gt;0||n.map&amp;&amp;n.alphaTest&gt;0){const t=a.uuid,e=n.uuid;let i=p[t];void 0===i&amp;&amp;(i={},p[t]=i);let r=i[e];void 0===r&amp;&amp;(r=a.clone(),i[e]=r,n.addEventListener(&quot;dispose&quot;,E)),a=r}if(a.visible=n.visible,a.wireframe=n.wireframe,a.side=s===r?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:f[n.side],a.alphaMap=n.alphaMap,a.alphaTest=n.alphaTest,a.map=n.map,a.clipShadows=n.clipShadows,a.clippingPlanes=n.clippingPlanes,a.clipIntersection=n.clipIntersection,a.displacementMap=n.displacementMap,a.displacementScale=n.displacementScale,a.displacementBias=n.displacementBias,a.wireframeLinewidth=n.wireframeLinewidth,a.linewidth=n.linewidth,!0===i.isPointLight&amp;&amp;!0===a.isMeshDistanceMaterial){t.properties.get(a).light=i}return a}function T(n,i,s,a,l){if(!1===n.visible)return;if(n.layers.test(i.layers)&amp;&amp;(n.isMesh||n.isLine||n.isPoints)&amp;&amp;(n.castShadow||n.receiveShadow&amp;&amp;l===r)&amp;&amp;(!n.frustumCulled||o.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,n.matrixWorld);const r=e.update(n),o=n.material;if(Array.isArray(o)){const e=r.groups;for(let c=0,h=e.length;c&lt;h;c++){const h=e[c],u=o[h.materialIndex];if(u&amp;&amp;u.visible){const e=b(n,u,a,l);n.onBeforeShadow(t,n,i,s,r,e,h),t.renderBufferDirect(s,null,r,e,n,h),n.onAfterShadow(t,n,i,s,r,e,h)}}}else if(o.visible){const e=b(n,o,a,l);n.onBeforeShadow(t,n,i,s,r,e,null),t.renderBufferDirect(s,null,r,e,n,null),n.onAfterShadow(t,n,i,s,r,e,null)}}const c=n.children;for(let t=0,e=c.length;t&lt;e;t++)T(c[t],i,s,a,l)}function E(t){t.target.removeEventListener(&quot;dispose&quot;,E);for(const e in p){const n=p[e],i=t.target.uuid;if(i in n){n[i].dispose(),delete n[i]}}}this.render=function(e,n,i){if(!1===y.enabled)return;if(!1===y.autoUpdate&amp;&amp;!1===y.needsUpdate)return;if(0===e.length)return;const s=t.getRenderTarget(),a=t.getActiveCubeFace(),u=t.getActiveMipmapLevel(),d=t.state;d.setBlending(0),d.buffers.color.setClear(1,1,1,1),d.buffers.depth.setTest(!0),d.setScissorTest(!1);const p=M!==r&amp;&amp;this.type===r,f=M===r&amp;&amp;this.type!==r;for(let s=0,a=e.length;s&lt;a;s++){const a=e[s],u=a.shadow;if(void 0===u){console.warn(&quot;THREE.WebGLShadowMap:&quot;,a,&quot;has no shadow.&quot;);continue}if(!1===u.autoUpdate&amp;&amp;!1===u.needsUpdate)continue;l.copy(u.mapSize);const g=u.getFrameExtents();if(l.multiply(g),c.copy(u.mapSize),(l.x&gt;m||l.y&gt;m)&amp;&amp;(l.x&gt;m&amp;&amp;(c.x=Math.floor(m/g.x),l.x=c.x*g.x,u.mapSize.x=c.x),l.y&gt;m&amp;&amp;(c.y=Math.floor(m/g.y),l.y=c.y*g.y,u.mapSize.y=c.y)),null===u.map||!0===p||!0===f){const t=this.type!==r?{minFilter:P,magFilter:P}:{};null!==u.map&amp;&amp;u.map.dispose(),u.map=new Ge(l.x,l.y,t),u.map.texture.name=a.name+&quot;.shadowMap&quot;,u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const _=u.getViewportCount();for(let t=0;t&lt;_;t++){const e=u.getViewport(t);h.set(c.x*e.x,c.y*e.y,c.x*e.z,c.y*e.w),d.viewport(h),u.updateMatrices(a,t),o=u.getFrustum(),T(n,i,u.camera,a,this.type)}!0!==u.isPointLightShadow&amp;&amp;this.type===r&amp;&amp;S(u,i),u.needsUpdate=!1}M=this.type,y.needsUpdate=!1,t.setRenderTarget(s,a,u)}}function Wa(t,e,n){const i=n.isWebGL2;const r=new function(){let e=!1;const n=new Be;let i=null;const r=new Be(0,0,0,0);return{setMask:function(n){i===n||e||(t.colorMask(n,n,n,n),i=n)},setLocked:function(t){e=t},setClear:function(e,i,s,a,o){!0===o&amp;&amp;(e*=a,i*=a,s*=a),n.set(e,i,s,a),!1===r.equals(n)&amp;&amp;(t.clearColor(e,i,s,a),r.copy(n))},reset:function(){e=!1,i=null,r.set(-1,0,0,0)}}},s=new function(){let e=!1,n=null,i=null,r=null;return{setTest:function(e){e?j(t.DEPTH_TEST):q(t.DEPTH_TEST)},setMask:function(i){n===i||e||(t.depthMask(i),n=i)},setFunc:function(e){if(i!==e){switch(e){case 0:t.depthFunc(t.NEVER);break;case 1:t.depthFunc(t.ALWAYS);break;case 2:t.depthFunc(t.LESS);break;case 3:default:t.depthFunc(t.LEQUAL);break;case 4:t.depthFunc(t.EQUAL);break;case 5:t.depthFunc(t.GEQUAL);break;case 6:t.depthFunc(t.GREATER);break;case 7:t.depthFunc(t.NOTEQUAL)}i=e}},setLocked:function(t){e=t},setClear:function(e){r!==e&amp;&amp;(t.clearDepth(e),r=e)},reset:function(){e=!1,n=null,i=null,r=null}}},h=new function(){let e=!1,n=null,i=null,r=null,s=null,a=null,o=null,l=null,c=null;return{setTest:function(n){e||(n?j(t.STENCIL_TEST):q(t.STENCIL_TEST))},setMask:function(i){n===i||e||(t.stencilMask(i),n=i)},setFunc:function(e,n,a){i===e&amp;&amp;r===n&amp;&amp;s===a||(t.stencilFunc(e,n,a),i=e,r=n,s=a)},setOp:function(e,n,i){a===e&amp;&amp;o===n&amp;&amp;l===i||(t.stencilOp(e,n,i),a=e,o=n,l=i)},setLocked:function(t){e=t},setClear:function(e){c!==e&amp;&amp;(t.clearStencil(e),c=e)},reset:function(){e=!1,n=null,i=null,r=null,s=null,a=null,o=null,l=null,c=null}}},u=new WeakMap,d=new WeakMap;let p={},m={},f=new WeakMap,g=[],_=null,v=!1,x=null,y=null,M=null,S=null,b=null,T=null,E=null,w=new ci(0,0,0),A=0,R=!1,C=null,L=null,P=null,I=null,U=null;const D=t.getParameter(t.MAX_COMBINED_TEXTURE_IMAGE_UNITS);let N=!1,O=0;const F=t.getParameter(t.VERSION);-1!==F.indexOf(&quot;WebGL&quot;)?(O=parseFloat(/^WebGL (\d)/.exec(F)[1]),N=O&gt;=1):-1!==F.indexOf(&quot;OpenGL ES&quot;)&amp;&amp;(O=parseFloat(/^OpenGL ES (\d)/.exec(F)[1]),N=O&gt;=2);let B=null,z={};const G=t.getParameter(t.SCISSOR_BOX),H=t.getParameter(t.VIEWPORT),V=(new Be).fromArray(G),k=(new Be).fromArray(H);function W(e,n,r,s){const a=new Uint8Array(4),o=t.createTexture();t.bindTexture(e,o),t.texParameteri(e,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(e,t.TEXTURE_MAG_FILTER,t.NEAREST);for(let o=0;o&lt;r;o++)!i||e!==t.TEXTURE_3D&amp;&amp;e!==t.TEXTURE_2D_ARRAY?t.texImage2D(n+o,0,t.RGBA,1,1,0,t.RGBA,t.UNSIGNED_BYTE,a):t.texImage3D(n,0,t.RGBA,1,1,s,0,t.RGBA,t.UNSIGNED_BYTE,a);return o}const X={};function j(e){!0!==p[e]&amp;&amp;(t.enable(e),p[e]=!0)}function q(e){!1!==p[e]&amp;&amp;(t.disable(e),p[e]=!1)}X[t.TEXTURE_2D]=W(t.TEXTURE_2D,t.TEXTURE_2D,1),X[t.TEXTURE_CUBE_MAP]=W(t.TEXTURE_CUBE_MAP,t.TEXTURE_CUBE_MAP_POSITIVE_X,6),i&amp;&amp;(X[t.TEXTURE_2D_ARRAY]=W(t.TEXTURE_2D_ARRAY,t.TEXTURE_2D_ARRAY,1,1),X[t.TEXTURE_3D]=W(t.TEXTURE_3D,t.TEXTURE_3D,1,1)),r.setClear(0,0,0,1),s.setClear(1),h.setClear(0),j(t.DEPTH_TEST),s.setFunc(3),K(!1),$(1),j(t.CULL_FACE),J(0);const Y={[o]:t.FUNC_ADD,101:t.FUNC_SUBTRACT,102:t.FUNC_REVERSE_SUBTRACT};if(i)Y[103]=t.MIN,Y[104]=t.MAX;else{const t=e.get(&quot;EXT_blend_minmax&quot;);null!==t&amp;&amp;(Y[103]=t.MIN_EXT,Y[104]=t.MAX_EXT)}const Z={200:t.ZERO,201:t.ONE,202:t.SRC_COLOR,[l]:t.SRC_ALPHA,210:t.SRC_ALPHA_SATURATE,208:t.DST_COLOR,206:t.DST_ALPHA,203:t.ONE_MINUS_SRC_COLOR,[c]:t.ONE_MINUS_SRC_ALPHA,209:t.ONE_MINUS_DST_COLOR,207:t.ONE_MINUS_DST_ALPHA,211:t.CONSTANT_COLOR,212:t.ONE_MINUS_CONSTANT_COLOR,213:t.CONSTANT_ALPHA,214:t.ONE_MINUS_CONSTANT_ALPHA};function J(e,n,i,r,s,a,l,c,h,u){if(0!==e){if(!1===v&amp;&amp;(j(t.BLEND),v=!0),5===e)s=s||n,a=a||i,l=l||r,n===y&amp;&amp;s===b||(t.blendEquationSeparate(Y[n],Y[s]),y=n,b=s),i===M&amp;&amp;r===S&amp;&amp;a===T&amp;&amp;l===E||(t.blendFuncSeparate(Z[i],Z[r],Z[a],Z[l]),M=i,S=r,T=a,E=l),!1!==c.equals(w)&amp;&amp;h===A||(t.blendColor(c.r,c.g,c.b,h),w.copy(c),A=h),x=e,R=!1;else if(e!==x||u!==R){if(y===o&amp;&amp;b===o||(t.blendEquation(t.FUNC_ADD),y=o,b=o),u)switch(e){case 1:t.blendFuncSeparate(t.ONE,t.ONE_MINUS_SRC_ALPHA,t.ONE,t.ONE_MINUS_SRC_ALPHA);break;case 2:t.blendFunc(t.ONE,t.ONE);break;case 3:t.blendFuncSeparate(t.ZERO,t.ONE_MINUS_SRC_COLOR,t.ZERO,t.ONE);break;case 4:t.blendFuncSeparate(t.ZERO,t.SRC_COLOR,t.ZERO,t.SRC_ALPHA);break;default:console.error(&quot;THREE.WebGLState: Invalid blending: &quot;,e)}else switch(e){case 1:t.blendFuncSeparate(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA,t.ONE,t.ONE_MINUS_SRC_ALPHA);break;case 2:t.blendFunc(t.SRC_ALPHA,t.ONE);break;case 3:t.blendFuncSeparate(t.ZERO,t.ONE_MINUS_SRC_COLOR,t.ZERO,t.ONE);break;case 4:t.blendFunc(t.ZERO,t.SRC_COLOR);break;default:console.error(&quot;THREE.WebGLState: Invalid blending: &quot;,e)}M=null,S=null,T=null,E=null,w.set(0,0,0),A=0,x=e,R=u}}else!0===v&amp;&amp;(q(t.BLEND),v=!1)}function K(e){C!==e&amp;&amp;(e?t.frontFace(t.CW):t.frontFace(t.CCW),C=e)}function $(e){0!==e?(j(t.CULL_FACE),e!==L&amp;&amp;(1===e?t.cullFace(t.BACK):2===e?t.cullFace(t.FRONT):t.cullFace(t.FRONT_AND_BACK))):q(t.CULL_FACE),L=e}function Q(e,n,i){e?(j(t.POLYGON_OFFSET_FILL),I===n&amp;&amp;U===i||(t.polygonOffset(n,i),I=n,U=i)):q(t.POLYGON_OFFSET_FILL)}return{buffers:{color:r,depth:s,stencil:h},enable:j,disable:q,bindFramebuffer:function(e,n){return m[e]!==n&amp;&amp;(t.bindFramebuffer(e,n),m[e]=n,i&amp;&amp;(e===t.DRAW_FRAMEBUFFER&amp;&amp;(m[t.FRAMEBUFFER]=n),e===t.FRAMEBUFFER&amp;&amp;(m[t.DRAW_FRAMEBUFFER]=n)),!0)},drawBuffers:function(i,r){let s=g,a=!1;if(i)if(s=f.get(r),void 0===s&amp;&amp;(s=[],f.set(r,s)),i.isWebGLMultipleRenderTargets){const e=i.texture;if(s.length!==e.length||s[0]!==t.COLOR_ATTACHMENT0){for(let n=0,i=e.length;n&lt;i;n++)s[n]=t.COLOR_ATTACHMENT0+n;s.length=e.length,a=!0}}else s[0]!==t.COLOR_ATTACHMENT0&amp;&amp;(s[0]=t.COLOR_ATTACHMENT0,a=!0);else s[0]!==t.BACK&amp;&amp;(s[0]=t.BACK,a=!0);a&amp;&amp;(n.isWebGL2?t.drawBuffers(s):e.get(&quot;WEBGL_draw_buffers&quot;).drawBuffersWEBGL(s))},useProgram:function(e){return _!==e&amp;&amp;(t.useProgram(e),_=e,!0)},setBlending:J,setMaterial:function(e,n){2===e.side?q(t.CULL_FACE):j(t.CULL_FACE);let i=e.side===a;n&amp;&amp;(i=!i),K(i),1===e.blending&amp;&amp;!1===e.transparent?J(0):J(e.blending,e.blendEquation,e.blendSrc,e.blendDst,e.blendEquationAlpha,e.blendSrcAlpha,e.blendDstAlpha,e.blendColor,e.blendAlpha,e.premultipliedAlpha),s.setFunc(e.depthFunc),s.setTest(e.depthTest),s.setMask(e.depthWrite),r.setMask(e.colorWrite);const o=e.stencilWrite;h.setTest(o),o&amp;&amp;(h.setMask(e.stencilWriteMask),h.setFunc(e.stencilFunc,e.stencilRef,e.stencilFuncMask),h.setOp(e.stencilFail,e.stencilZFail,e.stencilZPass)),Q(e.polygonOffset,e.polygonOffsetFactor,e.polygonOffsetUnits),!0===e.alphaToCoverage?j(t.SAMPLE_ALPHA_TO_COVERAGE):q(t.SAMPLE_ALPHA_TO_COVERAGE)},setFlipSided:K,setCullFace:$,setLineWidth:function(e){e!==P&amp;&amp;(N&amp;&amp;t.lineWidth(e),P=e)},setPolygonOffset:Q,setScissorTest:function(e){e?j(t.SCISSOR_TEST):q(t.SCISSOR_TEST)},activeTexture:function(e){void 0===e&amp;&amp;(e=t.TEXTURE0+D-1),B!==e&amp;&amp;(t.activeTexture(e),B=e)},bindTexture:function(e,n,i){void 0===i&amp;&amp;(i=null===B?t.TEXTURE0+D-1:B);let r=z[i];void 0===r&amp;&amp;(r={type:void 0,texture:void 0},z[i]=r),r.type===e&amp;&amp;r.texture===n||(B!==i&amp;&amp;(t.activeTexture(i),B=i),t.bindTexture(e,n||X[e]),r.type=e,r.texture=n)},unbindTexture:function(){const e=z[B];void 0!==e&amp;&amp;void 0!==e.type&amp;&amp;(t.bindTexture(e.type,null),e.type=void 0,e.texture=void 0)},compressedTexImage2D:function(){try{t.compressedTexImage2D.apply(t,arguments)}catch(t){console.error(&quot;THREE.WebGLState:&quot;,t)}},compressedTexImage3D:function(){try{t.compressedTexImage3D.apply(t,arguments)}catch(t){console.error(&quot;THREE.WebGLState:&quot;,t)}},texImage2D:function(){try{t.texImage2D.apply(t,arguments)}catch(t){console.error(&quot;THREE.WebGLState:&quot;,t)}},texImage3D:function(){try{t.texImage3D.apply(t,arguments)}catch(t){console.error(&quot;THREE.WebGLState:&quot;,t)}},updateUBOMapping:function(e,n){let i=d.get(n);void 0===i&amp;&amp;(i=new WeakMap,d.set(n,i));let r=i.get(e);void 0===r&amp;&amp;(r=t.getUniformBlockIndex(n,e.name),i.set(e,r))},uniformBlockBinding:function(e,n){const i=d.get(n).get(e);u.get(n)!==i&amp;&amp;(t.uniformBlockBinding(n,i,e.__bindingPointIndex),u.set(n,i))},texStorage2D:function(){try{t.texStorage2D.apply(t,arguments)}catch(t){console.error(&quot;THREE.WebGLState:&quot;,t)}},texStorage3D:function(){try{t.texStorage3D.apply(t,arguments)}catch(t){console.error(&quot;THREE.WebGLState:&quot;,t)}},texSubImage2D:function(){try{t.texSubImage2D.apply(t,arguments)}catch(t){console.error(&quot;THREE.WebGLState:&quot;,t)}},texSubImage3D:function(){try{t.texSubImage3D.apply(t,arguments)}catch(t){console.error(&quot;THREE.WebGLState:&quot;,t)}},compressedTexSubImage2D:function(){try{t.compressedTexSubImage2D.apply(t,arguments)}catch(t){console.error(&quot;THREE.WebGLState:&quot;,t)}},compressedTexSubImage3D:function(){try{t.compressedTexSubImage3D.apply(t,arguments)}catch(t){console.error(&quot;THREE.WebGLState:&quot;,t)}},scissor:function(e){!1===V.equals(e)&amp;&amp;(t.scissor(e.x,e.y,e.z,e.w),V.copy(e))},viewport:function(e){!1===k.equals(e)&amp;&amp;(t.viewport(e.x,e.y,e.z,e.w),k.copy(e))},reset:function(){t.disable(t.BLEND),t.disable(t.CULL_FACE),t.disable(t.DEPTH_TEST),t.disable(t.POLYGON_OFFSET_FILL),t.disable(t.SCISSOR_TEST),t.disable(t.STENCIL_TEST),t.disable(t.SAMPLE_ALPHA_TO_COVERAGE),t.blendEquation(t.FUNC_ADD),t.blendFunc(t.ONE,t.ZERO),t.blendFuncSeparate(t.ONE,t.ZERO,t.ONE,t.ZERO),t.blendColor(0,0,0,0),t.colorMask(!0,!0,!0,!0),t.clearColor(0,0,0,0),t.depthMask(!0),t.depthFunc(t.LESS),t.clearDepth(1),t.stencilMask(4294967295),t.stencilFunc(t.ALWAYS,0,4294967295),t.stencilOp(t.KEEP,t.KEEP,t.KEEP),t.clearStencil(0),t.cullFace(t.BACK),t.frontFace(t.CCW),t.polygonOffset(0,0),t.activeTexture(t.TEXTURE0),t.bindFramebuffer(t.FRAMEBUFFER,null),!0===i&amp;&amp;(t.bindFramebuffer(t.DRAW_FRAMEBUFFER,null),t.bindFramebuffer(t.READ_FRAMEBUFFER,null)),t.useProgram(null),t.lineWidth(1),t.scissor(0,0,t.canvas.width,t.canvas.height),t.viewport(0,0,t.canvas.width,t.canvas.height),p={},B=null,z={},m={},f=new WeakMap,g=[],_=null,v=!1,x=null,y=null,M=null,S=null,b=null,T=null,E=null,w=new ci(0,0,0),A=0,R=!1,C=null,L=null,P=null,I=null,U=null,V.set(0,0,t.canvas.width,t.canvas.height),k.set(0,0,t.canvas.width,t.canvas.height),r.reset(),s.reset(),h.reset()}}}function Xa(t,e,n,i,r,s,a){const o=r.isWebGL2,l=e.has(&quot;WEBGL_multisampled_render_to_texture&quot;)?e.get(&quot;WEBGL_multisampled_render_to_texture&quot;):null,c=&quot;undefined&quot;!=typeof navigator&amp;&amp;/OculusBrowser/g.test(navigator.userAgent),h=new WeakMap;let u;const d=new WeakMap;let p=!1;try{p=&quot;undefined&quot;!=typeof OffscreenCanvas&amp;&amp;null!==new OffscreenCanvas(1,1).getContext(&quot;2d&quot;)}catch(t){}function m(t,e){return p?new OffscreenCanvas(t,e):ye(&quot;canvas&quot;)}function f(t,e,n,i){let r=1;if((t.width&gt;i||t.height&gt;i)&amp;&amp;(r=i/Math.max(t.width,t.height)),r&lt;1||!0===e){if(&quot;undefined&quot;!=typeof HTMLImageElement&amp;&amp;t instanceof HTMLImageElement||&quot;undefined&quot;!=typeof HTMLCanvasElement&amp;&amp;t instanceof HTMLCanvasElement||&quot;undefined&quot;!=typeof ImageBitmap&amp;&amp;t instanceof ImageBitmap){const i=e?he:Math.floor,s=i(r*t.width),a=i(r*t.height);void 0===u&amp;&amp;(u=m(s,a));const o=n?m(s,a):u;o.width=s,o.height=a;return o.getContext(&quot;2d&quot;).drawImage(t,0,0,s,a),console.warn(&quot;THREE.WebGLRenderer: Texture has been resized from (&quot;+t.width+&quot;x&quot;+t.height+&quot;) to (&quot;+s+&quot;x&quot;+a+&quot;).&quot;),o}return&quot;data&quot;in t&amp;&amp;console.warn(&quot;THREE.WebGLRenderer: Image in DataTexture is too big (&quot;+t.width+&quot;x&quot;+t.height+&quot;).&quot;),t}return t}function g(t){return ce(t.width)&amp;&amp;ce(t.height)}function _(t,e){return t.generateMipmaps&amp;&amp;e&amp;&amp;t.minFilter!==P&amp;&amp;t.minFilter!==D}function v(e){t.generateMipmap(e)}function x(n,i,r,s,a=!1){if(!1===o)return i;if(null!==n){if(void 0!==t[n])return t[n];console.warn(&quot;THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '&quot;+n+&quot;'&quot;)}let l=i;if(i===t.RED&amp;&amp;(r===t.FLOAT&amp;&amp;(l=t.R32F),r===t.HALF_FLOAT&amp;&amp;(l=t.R16F),r===t.UNSIGNED_BYTE&amp;&amp;(l=t.R8)),i===t.RED_INTEGER&amp;&amp;(r===t.UNSIGNED_BYTE&amp;&amp;(l=t.R8UI),r===t.UNSIGNED_SHORT&amp;&amp;(l=t.R16UI),r===t.UNSIGNED_INT&amp;&amp;(l=t.R32UI),r===t.BYTE&amp;&amp;(l=t.R8I),r===t.SHORT&amp;&amp;(l=t.R16I),r===t.INT&amp;&amp;(l=t.R32I)),i===t.RG&amp;&amp;(r===t.FLOAT&amp;&amp;(l=t.RG32F),r===t.HALF_FLOAT&amp;&amp;(l=t.RG16F),r===t.UNSIGNED_BYTE&amp;&amp;(l=t.RG8)),i===t.RGBA){const e=a?Wt:Re.getTransfer(s);r===t.FLOAT&amp;&amp;(l=t.RGBA32F),r===t.HALF_FLOAT&amp;&amp;(l=t.RGBA16F),r===t.UNSIGNED_BYTE&amp;&amp;(l=e===Xt?t.SRGB8_ALPHA8:t.RGBA8),r===t.UNSIGNED_SHORT_4_4_4_4&amp;&amp;(l=t.RGBA4),r===t.UNSIGNED_SHORT_5_5_5_1&amp;&amp;(l=t.RGB5_A1)}return l!==t.R16F&amp;&amp;l!==t.R32F&amp;&amp;l!==t.RG16F&amp;&amp;l!==t.RG32F&amp;&amp;l!==t.RGBA16F&amp;&amp;l!==t.RGBA32F||e.get(&quot;EXT_color_buffer_float&quot;),l}function y(t,e,n){return!0===_(t,n)||t.isFramebufferTexture&amp;&amp;t.minFilter!==P&amp;&amp;t.minFilter!==D?Math.log2(Math.max(e.width,e.height))+1:void 0!==t.mipmaps&amp;&amp;t.mipmaps.length&gt;0?t.mipmaps.length:t.isCompressedTexture&amp;&amp;Array.isArray(t.image)?e.mipmaps.length:1}function M(e){return e===P||e===I||e===U?t.NEAREST:t.LINEAR}function S(t){const e=t.target;e.removeEventListener(&quot;dispose&quot;,S),function(t){const e=i.get(t);if(void 0===e.__webglInit)return;const n=t.source,r=d.get(n);if(r){const i=r[e.__cacheKey];i.usedTimes--,0===i.usedTimes&amp;&amp;T(t),0===Object.keys(r).length&amp;&amp;d.delete(n)}i.remove(t)}(e),e.isVideoTexture&amp;&amp;h.delete(e)}function b(e){const n=e.target;n.removeEventListener(&quot;dispose&quot;,b),function(e){const n=e.texture,r=i.get(e),s=i.get(n);void 0!==s.__webglTexture&amp;&amp;(t.deleteTexture(s.__webglTexture),a.memory.textures--);e.depthTexture&amp;&amp;e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e&lt;6;e++){if(Array.isArray(r.__webglFramebuffer[e]))for(let n=0;n&lt;r.__webglFramebuffer[e].length;n++)t.deleteFramebuffer(r.__webglFramebuffer[e][n]);else t.deleteFramebuffer(r.__webglFramebuffer[e]);r.__webglDepthbuffer&amp;&amp;t.deleteRenderbuffer(r.__webglDepthbuffer[e])}else{if(Array.isArray(r.__webglFramebuffer))for(let e=0;e&lt;r.__webglFramebuffer.length;e++)t.deleteFramebuffer(r.__webglFramebuffer[e]);else t.deleteFramebuffer(r.__webglFramebuffer);if(r.__webglDepthbuffer&amp;&amp;t.deleteRenderbuffer(r.__webglDepthbuffer),r.__webglMultisampledFramebuffer&amp;&amp;t.deleteFramebuffer(r.__webglMultisampledFramebuffer),r.__webglColorRenderbuffer)for(let e=0;e&lt;r.__webglColorRenderbuffer.length;e++)r.__webglColorRenderbuffer[e]&amp;&amp;t.deleteRenderbuffer(r.__webglColorRenderbuffer[e]);r.__webglDepthRenderbuffer&amp;&amp;t.deleteRenderbuffer(r.__webglDepthRenderbuffer)}if(e.isWebGLMultipleRenderTargets)for(let e=0,r=n.length;e&lt;r;e++){const r=i.get(n[e]);r.__webglTexture&amp;&amp;(t.deleteTexture(r.__webglTexture),a.memory.textures--),i.remove(n[e])}i.remove(n),i.remove(e)}(n)}function T(e){const n=i.get(e);t.deleteTexture(n.__webglTexture);const r=e.source;delete d.get(r)[n.__cacheKey],a.memory.textures--}let E=0;function w(e,r){const s=i.get(e);if(e.isVideoTexture&amp;&amp;function(t){const e=a.render.frame;h.get(t)!==e&amp;&amp;(h.set(t,e),t.update())}(e),!1===e.isRenderTargetTexture&amp;&amp;e.version&gt;0&amp;&amp;s.__version!==e.version){const t=e.image;if(null===t)console.warn(&quot;THREE.WebGLRenderer: Texture marked for update but no image data found.&quot;);else{if(!1!==t.complete)return void J(s,e,r);console.warn(&quot;THREE.WebGLRenderer: Texture marked for update but image is incomplete&quot;)}}n.bindTexture(t.TEXTURE_2D,s.__webglTexture,t.TEXTURE0+r)}const A={[R]:t.REPEAT,[C]:t.CLAMP_TO_EDGE,[L]:t.MIRRORED_REPEAT},z={[P]:t.NEAREST,[I]:t.NEAREST_MIPMAP_NEAREST,[U]:t.NEAREST_MIPMAP_LINEAR,[D]:t.LINEAR,[N]:t.LINEAR_MIPMAP_NEAREST,[O]:t.LINEAR_MIPMAP_LINEAR},k={512:t.NEVER,519:t.ALWAYS,513:t.LESS,515:t.LEQUAL,514:t.EQUAL,518:t.GEQUAL,516:t.GREATER,517:t.NOTEQUAL};function W(n,s,a){if(a?(t.texParameteri(n,t.TEXTURE_WRAP_S,A[s.wrapS]),t.texParameteri(n,t.TEXTURE_WRAP_T,A[s.wrapT]),n!==t.TEXTURE_3D&amp;&amp;n!==t.TEXTURE_2D_ARRAY||t.texParameteri(n,t.TEXTURE_WRAP_R,A[s.wrapR]),t.texParameteri(n,t.TEXTURE_MAG_FILTER,z[s.magFilter]),t.texParameteri(n,t.TEXTURE_MIN_FILTER,z[s.minFilter])):(t.texParameteri(n,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(n,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),n!==t.TEXTURE_3D&amp;&amp;n!==t.TEXTURE_2D_ARRAY||t.texParameteri(n,t.TEXTURE_WRAP_R,t.CLAMP_TO_EDGE),s.wrapS===C&amp;&amp;s.wrapT===C||console.warn(&quot;THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.&quot;),t.texParameteri(n,t.TEXTURE_MAG_FILTER,M(s.magFilter)),t.texParameteri(n,t.TEXTURE_MIN_FILTER,M(s.minFilter)),s.minFilter!==P&amp;&amp;s.minFilter!==D&amp;&amp;console.warn(&quot;THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.&quot;)),s.compareFunction&amp;&amp;(t.texParameteri(n,t.TEXTURE_COMPARE_MODE,t.COMPARE_REF_TO_TEXTURE),t.texParameteri(n,t.TEXTURE_COMPARE_FUNC,k[s.compareFunction])),!0===e.has(&quot;EXT_texture_filter_anisotropic&quot;)){const a=e.get(&quot;EXT_texture_filter_anisotropic&quot;);if(s.magFilter===P)return;if(s.minFilter!==U&amp;&amp;s.minFilter!==O)return;if(s.type===H&amp;&amp;!1===e.has(&quot;OES_texture_float_linear&quot;))return;if(!1===o&amp;&amp;s.type===V&amp;&amp;!1===e.has(&quot;OES_texture_half_float_linear&quot;))return;(s.anisotropy&gt;1||i.get(s).__currentAnisotropy)&amp;&amp;(t.texParameterf(n,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),i.get(s).__currentAnisotropy=s.anisotropy)}}function Z(e,n){let i=!1;void 0===e.__webglInit&amp;&amp;(e.__webglInit=!0,n.addEventListener(&quot;dispose&quot;,S));const r=n.source;let s=d.get(r);void 0===s&amp;&amp;(s={},d.set(r,s));const o=function(t){const e=[];return e.push(t.wrapS),e.push(t.wrapT),e.push(t.wrapR||0),e.push(t.magFilter),e.push(t.minFilter),e.push(t.anisotropy),e.push(t.internalFormat),e.push(t.format),e.push(t.type),e.push(t.generateMipmaps),e.push(t.premultiplyAlpha),e.push(t.flipY),e.push(t.unpackAlignment),e.push(t.colorSpace),e.join()}(n);if(o!==e.__cacheKey){void 0===s[o]&amp;&amp;(s[o]={texture:t.createTexture(),usedTimes:0},a.memory.textures++,i=!0),s[o].usedTimes++;const r=s[e.__cacheKey];void 0!==r&amp;&amp;(s[e.__cacheKey].usedTimes--,0===r.usedTimes&amp;&amp;T(n)),e.__cacheKey=o,e.__webglTexture=s[o].texture}return i}function J(e,a,l){let c=t.TEXTURE_2D;(a.isDataArrayTexture||a.isCompressedArrayTexture)&amp;&amp;(c=t.TEXTURE_2D_ARRAY),a.isData3DTexture&amp;&amp;(c=t.TEXTURE_3D);const h=Z(e,a),u=a.source;n.bindTexture(c,e.__webglTexture,t.TEXTURE0+l);const d=i.get(u);if(u.version!==d.__version||!0===h){n.activeTexture(t.TEXTURE0+l);const e=Re.getPrimaries(Re.workingColorSpace),i=a.colorSpace===zt?null:Re.getPrimaries(a.colorSpace),p=a.colorSpace===zt||e===i?t.NONE:t.BROWSER_DEFAULT_WEBGL;t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,a.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,a.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,a.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,p);const m=function(t){return!o&amp;&amp;(t.wrapS!==C||t.wrapT!==C||t.minFilter!==P&amp;&amp;t.minFilter!==D)}(a)&amp;&amp;!1===g(a.image);let M=f(a.image,m,!1,r.maxTextureSize);M=nt(a,M);const S=g(M)||o,b=s.convert(a.format,a.colorSpace);let T,E=s.convert(a.type),w=x(a.internalFormat,b,E,a.colorSpace,a.isVideoTexture);W(c,a,S);const A=a.mipmaps,R=o&amp;&amp;!0!==a.isVideoTexture&amp;&amp;w!==at,L=void 0===d.__version||!0===h,I=y(a,M,S);if(a.isDepthTexture)w=t.DEPTH_COMPONENT,o?w=a.type===H?t.DEPTH_COMPONENT32F:a.type===G?t.DEPTH_COMPONENT24:a.type===X?t.DEPTH24_STENCIL8:t.DEPTH_COMPONENT16:a.type===H&amp;&amp;console.error(&quot;WebGLRenderer: Floating point depth texture requires WebGL2.&quot;),a.format===q&amp;&amp;w===t.DEPTH_COMPONENT&amp;&amp;a.type!==B&amp;&amp;a.type!==G&amp;&amp;(console.warn(&quot;THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.&quot;),a.type=G,E=s.convert(a.type)),a.format===Y&amp;&amp;w===t.DEPTH_COMPONENT&amp;&amp;(w=t.DEPTH_STENCIL,a.type!==X&amp;&amp;(console.warn(&quot;THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.&quot;),a.type=X,E=s.convert(a.type))),L&amp;&amp;(R?n.texStorage2D(t.TEXTURE_2D,1,w,M.width,M.height):n.texImage2D(t.TEXTURE_2D,0,w,M.width,M.height,0,b,E,null));else if(a.isDataTexture)if(A.length&gt;0&amp;&amp;S){R&amp;&amp;L&amp;&amp;n.texStorage2D(t.TEXTURE_2D,I,w,A[0].width,A[0].height);for(let e=0,i=A.length;e&lt;i;e++)T=A[e],R?n.texSubImage2D(t.TEXTURE_2D,e,0,0,T.width,T.height,b,E,T.data):n.texImage2D(t.TEXTURE_2D,e,w,T.width,T.height,0,b,E,T.data);a.generateMipmaps=!1}else R?(L&amp;&amp;n.texStorage2D(t.TEXTURE_2D,I,w,M.width,M.height),n.texSubImage2D(t.TEXTURE_2D,0,0,0,M.width,M.height,b,E,M.data)):n.texImage2D(t.TEXTURE_2D,0,w,M.width,M.height,0,b,E,M.data);else if(a.isCompressedTexture)if(a.isCompressedArrayTexture){R&amp;&amp;L&amp;&amp;n.texStorage3D(t.TEXTURE_2D_ARRAY,I,w,A[0].width,A[0].height,M.depth);for(let e=0,i=A.length;e&lt;i;e++)T=A[e],a.format!==j?null!==b?R?n.compressedTexSubImage3D(t.TEXTURE_2D_ARRAY,e,0,0,0,T.width,T.height,M.depth,b,T.data,0,0):n.compressedTexImage3D(t.TEXTURE_2D_ARRAY,e,w,T.width,T.height,M.depth,0,T.data,0,0):console.warn(&quot;THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()&quot;):R?n.texSubImage3D(t.TEXTURE_2D_ARRAY,e,0,0,0,T.width,T.height,M.depth,b,E,T.data):n.texImage3D(t.TEXTURE_2D_ARRAY,e,w,T.width,T.height,M.depth,0,b,E,T.data)}else{R&amp;&amp;L&amp;&amp;n.texStorage2D(t.TEXTURE_2D,I,w,A[0].width,A[0].height);for(let e=0,i=A.length;e&lt;i;e++)T=A[e],a.format!==j?null!==b?R?n.compressedTexSubImage2D(t.TEXTURE_2D,e,0,0,T.width,T.height,b,T.data):n.compressedTexImage2D(t.TEXTURE_2D,e,w,T.width,T.height,0,T.data):console.warn(&quot;THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()&quot;):R?n.texSubImage2D(t.TEXTURE_2D,e,0,0,T.width,T.height,b,E,T.data):n.texImage2D(t.TEXTURE_2D,e,w,T.width,T.height,0,b,E,T.data)}else if(a.isDataArrayTexture)R?(L&amp;&amp;n.texStorage3D(t.TEXTURE_2D_ARRAY,I,w,M.width,M.height,M.depth),n.texSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,0,M.width,M.height,M.depth,b,E,M.data)):n.texImage3D(t.TEXTURE_2D_ARRAY,0,w,M.width,M.height,M.depth,0,b,E,M.data);else if(a.isData3DTexture)R?(L&amp;&amp;n.texStorage3D(t.TEXTURE_3D,I,w,M.width,M.height,M.depth),n.texSubImage3D(t.TEXTURE_3D,0,0,0,0,M.width,M.height,M.depth,b,E,M.data)):n.texImage3D(t.TEXTURE_3D,0,w,M.width,M.height,M.depth,0,b,E,M.data);else if(a.isFramebufferTexture){if(L)if(R)n.texStorage2D(t.TEXTURE_2D,I,w,M.width,M.height);else{let e=M.width,i=M.height;for(let r=0;r&lt;I;r++)n.texImage2D(t.TEXTURE_2D,r,w,e,i,0,b,E,null),e&gt;&gt;=1,i&gt;&gt;=1}}else if(A.length&gt;0&amp;&amp;S){R&amp;&amp;L&amp;&amp;n.texStorage2D(t.TEXTURE_2D,I,w,A[0].width,A[0].height);for(let e=0,i=A.length;e&lt;i;e++)T=A[e],R?n.texSubImage2D(t.TEXTURE_2D,e,0,0,b,E,T):n.texImage2D(t.TEXTURE_2D,e,w,b,E,T);a.generateMipmaps=!1}else R?(L&amp;&amp;n.texStorage2D(t.TEXTURE_2D,I,w,M.width,M.height),n.texSubImage2D(t.TEXTURE_2D,0,0,0,b,E,M)):n.texImage2D(t.TEXTURE_2D,0,w,b,E,M);_(a,S)&amp;&amp;v(c),d.__version=u.version,a.onUpdate&amp;&amp;a.onUpdate(a)}e.__version=a.version}function K(e,r,a,o,c,h){const u=s.convert(a.format,a.colorSpace),d=s.convert(a.type),p=x(a.internalFormat,u,d,a.colorSpace);if(!i.get(r).__hasExternalTextures){const e=Math.max(1,r.width&gt;&gt;h),i=Math.max(1,r.height&gt;&gt;h);c===t.TEXTURE_3D||c===t.TEXTURE_2D_ARRAY?n.texImage3D(c,h,p,e,i,r.depth,0,u,d,null):n.texImage2D(c,h,p,e,i,0,u,d,null)}n.bindFramebuffer(t.FRAMEBUFFER,e),et(r)?l.framebufferTexture2DMultisampleEXT(t.FRAMEBUFFER,o,c,i.get(a).__webglTexture,0,tt(r)):(c===t.TEXTURE_2D||c&gt;=t.TEXTURE_CUBE_MAP_POSITIVE_X&amp;&amp;c&lt;=t.TEXTURE_CUBE_MAP_NEGATIVE_Z)&amp;&amp;t.framebufferTexture2D(t.FRAMEBUFFER,o,c,i.get(a).__webglTexture,h),n.bindFramebuffer(t.FRAMEBUFFER,null)}function $(e,n,i){if(t.bindRenderbuffer(t.RENDERBUFFER,e),n.depthBuffer&amp;&amp;!n.stencilBuffer){let r=!0===o?t.DEPTH_COMPONENT24:t.DEPTH_COMPONENT16;if(i||et(n)){const e=n.depthTexture;e&amp;&amp;e.isDepthTexture&amp;&amp;(e.type===H?r=t.DEPTH_COMPONENT32F:e.type===G&amp;&amp;(r=t.DEPTH_COMPONENT24));const i=tt(n);et(n)?l.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,i,r,n.width,n.height):t.renderbufferStorageMultisample(t.RENDERBUFFER,i,r,n.width,n.height)}else t.renderbufferStorage(t.RENDERBUFFER,r,n.width,n.height);t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.RENDERBUFFER,e)}else if(n.depthBuffer&amp;&amp;n.stencilBuffer){const r=tt(n);i&amp;&amp;!1===et(n)?t.renderbufferStorageMultisample(t.RENDERBUFFER,r,t.DEPTH24_STENCIL8,n.width,n.height):et(n)?l.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,r,t.DEPTH24_STENCIL8,n.width,n.height):t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_STENCIL,n.width,n.height),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.RENDERBUFFER,e)}else{const e=!0===n.isWebGLMultipleRenderTargets?n.texture:[n.texture];for(let r=0;r&lt;e.length;r++){const a=e[r],o=s.convert(a.format,a.colorSpace),c=s.convert(a.type),h=x(a.internalFormat,o,c,a.colorSpace),u=tt(n);i&amp;&amp;!1===et(n)?t.renderbufferStorageMultisample(t.RENDERBUFFER,u,h,n.width,n.height):et(n)?l.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,u,h,n.width,n.height):t.renderbufferStorage(t.RENDERBUFFER,h,n.width,n.height)}}t.bindRenderbuffer(t.RENDERBUFFER,null)}function Q(e){const r=i.get(e),s=!0===e.isWebGLCubeRenderTarget;if(e.depthTexture&amp;&amp;!r.__autoAllocateDepthBuffer){if(s)throw new Error(&quot;target.depthTexture not supported in Cube render targets&quot;);!function(e,r){if(r&amp;&amp;r.isWebGLCubeRenderTarget)throw new Error(&quot;Depth Texture with cube render targets is not supported&quot;);if(n.bindFramebuffer(t.FRAMEBUFFER,e),!r.depthTexture||!r.depthTexture.isDepthTexture)throw new Error(&quot;renderTarget.depthTexture must be an instance of THREE.DepthTexture&quot;);i.get(r.depthTexture).__webglTexture&amp;&amp;r.depthTexture.image.width===r.width&amp;&amp;r.depthTexture.image.height===r.height||(r.depthTexture.image.width=r.width,r.depthTexture.image.height=r.height,r.depthTexture.needsUpdate=!0),w(r.depthTexture,0);const s=i.get(r.depthTexture).__webglTexture,a=tt(r);if(r.depthTexture.format===q)et(r)?l.framebufferTexture2DMultisampleEXT(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.TEXTURE_2D,s,0,a):t.framebufferTexture2D(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.TEXTURE_2D,s,0);else{if(r.depthTexture.format!==Y)throw new Error(&quot;Unknown depthTexture format&quot;);et(r)?l.framebufferTexture2DMultisampleEXT(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.TEXTURE_2D,s,0,a):t.framebufferTexture2D(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.TEXTURE_2D,s,0)}}(r.__webglFramebuffer,e)}else if(s){r.__webglDepthbuffer=[];for(let i=0;i&lt;6;i++)n.bindFramebuffer(t.FRAMEBUFFER,r.__webglFramebuffer[i]),r.__webglDepthbuffer[i]=t.createRenderbuffer(),$(r.__webglDepthbuffer[i],e,!1)}else n.bindFramebuffer(t.FRAMEBUFFER,r.__webglFramebuffer),r.__webglDepthbuffer=t.createRenderbuffer(),$(r.__webglDepthbuffer,e,!1);n.bindFramebuffer(t.FRAMEBUFFER,null)}function tt(t){return Math.min(r.maxSamples,t.samples)}function et(t){const n=i.get(t);return o&amp;&amp;t.samples&gt;0&amp;&amp;!0===e.has(&quot;WEBGL_multisampled_render_to_texture&quot;)&amp;&amp;!1!==n.__useRenderToTexture}function nt(t,n){const i=t.colorSpace,r=t.format,s=t.type;return!0===t.isCompressedTexture||!0===t.isVideoTexture||t.format===Kt||i!==Ht&amp;&amp;i!==zt&amp;&amp;(Re.getTransfer(i)===Xt?!1===o?!0===e.has(&quot;EXT_sRGB&quot;)&amp;&amp;r===j?(t.format=Kt,t.minFilter=D,t.generateMipmaps=!1):n=Ie.sRGBToLinear(n):r===j&amp;&amp;s===F||console.warn(&quot;THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.&quot;):console.error(&quot;THREE.WebGLTextures: Unsupported texture color space:&quot;,i)),n}this.allocateTextureUnit=function(){const t=E;return t&gt;=r.maxTextures&amp;&amp;console.warn(&quot;THREE.WebGLTextures: Trying to use &quot;+t+&quot; texture units while this GPU supports only &quot;+r.maxTextures),E+=1,t},this.resetTextureUnits=function(){E=0},this.setTexture2D=w,this.setTexture2DArray=function(e,r){const s=i.get(e);e.version&gt;0&amp;&amp;s.__version!==e.version?J(s,e,r):n.bindTexture(t.TEXTURE_2D_ARRAY,s.__webglTexture,t.TEXTURE0+r)},this.setTexture3D=function(e,r){const s=i.get(e);e.version&gt;0&amp;&amp;s.__version!==e.version?J(s,e,r):n.bindTexture(t.TEXTURE_3D,s.__webglTexture,t.TEXTURE0+r)},this.setTextureCube=function(e,a){const l=i.get(e);e.version&gt;0&amp;&amp;l.__version!==e.version?function(e,a,l){if(6!==a.image.length)return;const c=Z(e,a),h=a.source;n.bindTexture(t.TEXTURE_CUBE_MAP,e.__webglTexture,t.TEXTURE0+l);const u=i.get(h);if(h.version!==u.__version||!0===c){n.activeTexture(t.TEXTURE0+l);const e=Re.getPrimaries(Re.workingColorSpace),i=a.colorSpace===zt?null:Re.getPrimaries(a.colorSpace),d=a.colorSpace===zt||e===i?t.NONE:t.BROWSER_DEFAULT_WEBGL;t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,a.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,a.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,a.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,d);const p=a.isCompressedTexture||a.image[0].isCompressedTexture,m=a.image[0]&amp;&amp;a.image[0].isDataTexture,M=[];for(let t=0;t&lt;6;t++)M[t]=p||m?m?a.image[t].image:a.image[t]:f(a.image[t],!1,!0,r.maxCubemapSize),M[t]=nt(a,M[t]);const S=M[0],b=g(S)||o,T=s.convert(a.format,a.colorSpace),E=s.convert(a.type),w=x(a.internalFormat,T,E,a.colorSpace),A=o&amp;&amp;!0!==a.isVideoTexture,R=void 0===u.__version||!0===c;let C,L=y(a,S,b);if(W(t.TEXTURE_CUBE_MAP,a,b),p){A&amp;&amp;R&amp;&amp;n.texStorage2D(t.TEXTURE_CUBE_MAP,L,w,S.width,S.height);for(let e=0;e&lt;6;e++){C=M[e].mipmaps;for(let i=0;i&lt;C.length;i++){const r=C[i];a.format!==j?null!==T?A?n.compressedTexSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,i,0,0,r.width,r.height,T,r.data):n.compressedTexImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,i,w,r.width,r.height,0,r.data):console.warn(&quot;THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()&quot;):A?n.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,i,0,0,r.width,r.height,T,E,r.data):n.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,i,w,r.width,r.height,0,T,E,r.data)}}}else{C=a.mipmaps,A&amp;&amp;R&amp;&amp;(C.length&gt;0&amp;&amp;L++,n.texStorage2D(t.TEXTURE_CUBE_MAP,L,w,M[0].width,M[0].height));for(let e=0;e&lt;6;e++)if(m){A?n.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,0,0,M[e].width,M[e].height,T,E,M[e].data):n.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,w,M[e].width,M[e].height,0,T,E,M[e].data);for(let i=0;i&lt;C.length;i++){const r=C[i].image[e].image;A?n.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,i+1,0,0,r.width,r.height,T,E,r.data):n.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,i+1,w,r.width,r.height,0,T,E,r.data)}}else{A?n.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,0,0,T,E,M[e]):n.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,w,T,E,M[e]);for(let i=0;i&lt;C.length;i++){const r=C[i];A?n.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,i+1,0,0,T,E,r.image[e]):n.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,i+1,w,T,E,r.image[e])}}}_(a,b)&amp;&amp;v(t.TEXTURE_CUBE_MAP),u.__version=h.version,a.onUpdate&amp;&amp;a.onUpdate(a)}e.__version=a.version}(l,e,a):n.bindTexture(t.TEXTURE_CUBE_MAP,l.__webglTexture,t.TEXTURE0+a)},this.rebindTextures=function(e,n,r){const s=i.get(e);void 0!==n&amp;&amp;K(s.__webglFramebuffer,e,e.texture,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,0),void 0!==r&amp;&amp;Q(e)},this.setupRenderTarget=function(e){const l=e.texture,c=i.get(e),h=i.get(l);e.addEventListener(&quot;dispose&quot;,b),!0!==e.isWebGLMultipleRenderTargets&amp;&amp;(void 0===h.__webglTexture&amp;&amp;(h.__webglTexture=t.createTexture()),h.__version=l.version,a.memory.textures++);const u=!0===e.isWebGLCubeRenderTarget,d=!0===e.isWebGLMultipleRenderTargets,p=g(e)||o;if(u){c.__webglFramebuffer=[];for(let e=0;e&lt;6;e++)if(o&amp;&amp;l.mipmaps&amp;&amp;l.mipmaps.length&gt;0){c.__webglFramebuffer[e]=[];for(let n=0;n&lt;l.mipmaps.length;n++)c.__webglFramebuffer[e][n]=t.createFramebuffer()}else c.__webglFramebuffer[e]=t.createFramebuffer()}else{if(o&amp;&amp;l.mipmaps&amp;&amp;l.mipmaps.length&gt;0){c.__webglFramebuffer=[];for(let e=0;e&lt;l.mipmaps.length;e++)c.__webglFramebuffer[e]=t.createFramebuffer()}else c.__webglFramebuffer=t.createFramebuffer();if(d)if(r.drawBuffers){const n=e.texture;for(let e=0,r=n.length;e&lt;r;e++){const r=i.get(n[e]);void 0===r.__webglTexture&amp;&amp;(r.__webglTexture=t.createTexture(),a.memory.textures++)}}else console.warn(&quot;THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension.&quot;);if(o&amp;&amp;e.samples&gt;0&amp;&amp;!1===et(e)){const i=d?l:[l];c.__webglMultisampledFramebuffer=t.createFramebuffer(),c.__webglColorRenderbuffer=[],n.bindFramebuffer(t.FRAMEBUFFER,c.__webglMultisampledFramebuffer);for(let n=0;n&lt;i.length;n++){const r=i[n];c.__webglColorRenderbuffer[n]=t.createRenderbuffer(),t.bindRenderbuffer(t.RENDERBUFFER,c.__webglColorRenderbuffer[n]);const a=s.convert(r.format,r.colorSpace),o=s.convert(r.type),l=x(r.internalFormat,a,o,r.colorSpace,!0===e.isXRRenderTarget),h=tt(e);t.renderbufferStorageMultisample(t.RENDERBUFFER,h,l,e.width,e.height),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0+n,t.RENDERBUFFER,c.__webglColorRenderbuffer[n])}t.bindRenderbuffer(t.RENDERBUFFER,null),e.depthBuffer&amp;&amp;(c.__webglDepthRenderbuffer=t.createRenderbuffer(),$(c.__webglDepthRenderbuffer,e,!0)),n.bindFramebuffer(t.FRAMEBUFFER,null)}}if(u){n.bindTexture(t.TEXTURE_CUBE_MAP,h.__webglTexture),W(t.TEXTURE_CUBE_MAP,l,p);for(let n=0;n&lt;6;n++)if(o&amp;&amp;l.mipmaps&amp;&amp;l.mipmaps.length&gt;0)for(let i=0;i&lt;l.mipmaps.length;i++)K(c.__webglFramebuffer[n][i],e,l,t.COLOR_ATTACHMENT0,t.TEXTURE_CUBE_MAP_POSITIVE_X+n,i);else K(c.__webglFramebuffer[n],e,l,t.COLOR_ATTACHMENT0,t.TEXTURE_CUBE_MAP_POSITIVE_X+n,0);_(l,p)&amp;&amp;v(t.TEXTURE_CUBE_MAP),n.unbindTexture()}else if(d){const r=e.texture;for(let s=0,a=r.length;s&lt;a;s++){const a=r[s],o=i.get(a);n.bindTexture(t.TEXTURE_2D,o.__webglTexture),W(t.TEXTURE_2D,a,p),K(c.__webglFramebuffer,e,a,t.COLOR_ATTACHMENT0+s,t.TEXTURE_2D,0),_(a,p)&amp;&amp;v(t.TEXTURE_2D)}n.unbindTexture()}else{let i=t.TEXTURE_2D;if((e.isWebGL3DRenderTarget||e.isWebGLArrayRenderTarget)&amp;&amp;(o?i=e.isWebGL3DRenderTarget?t.TEXTURE_3D:t.TEXTURE_2D_ARRAY:console.error(&quot;THREE.WebGLTextures: THREE.Data3DTexture and THREE.DataArrayTexture only supported with WebGL2.&quot;)),n.bindTexture(i,h.__webglTexture),W(i,l,p),o&amp;&amp;l.mipmaps&amp;&amp;l.mipmaps.length&gt;0)for(let n=0;n&lt;l.mipmaps.length;n++)K(c.__webglFramebuffer[n],e,l,t.COLOR_ATTACHMENT0,i,n);else K(c.__webglFramebuffer,e,l,t.COLOR_ATTACHMENT0,i,0);_(l,p)&amp;&amp;v(i),n.unbindTexture()}e.depthBuffer&amp;&amp;Q(e)},this.updateRenderTargetMipmap=function(e){const r=g(e)||o,s=!0===e.isWebGLMultipleRenderTargets?e.texture:[e.texture];for(let a=0,o=s.length;a&lt;o;a++){const o=s[a];if(_(o,r)){const r=e.isWebGLCubeRenderTarget?t.TEXTURE_CUBE_MAP:t.TEXTURE_2D,s=i.get(o).__webglTexture;n.bindTexture(r,s),v(r),n.unbindTexture()}}},this.updateMultisampleRenderTarget=function(e){if(o&amp;&amp;e.samples&gt;0&amp;&amp;!1===et(e)){const r=e.isWebGLMultipleRenderTargets?e.texture:[e.texture],s=e.width,a=e.height;let o=t.COLOR_BUFFER_BIT;const l=[],h=e.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,u=i.get(e),d=!0===e.isWebGLMultipleRenderTargets;if(d)for(let e=0;e&lt;r.length;e++)n.bindFramebuffer(t.FRAMEBUFFER,u.__webglMultisampledFramebuffer),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0+e,t.RENDERBUFFER,null),n.bindFramebuffer(t.FRAMEBUFFER,u.__webglFramebuffer),t.framebufferTexture2D(t.DRAW_FRAMEBUFFER,t.COLOR_ATTACHMENT0+e,t.TEXTURE_2D,null,0);n.bindFramebuffer(t.READ_FRAMEBUFFER,u.__webglMultisampledFramebuffer),n.bindFramebuffer(t.DRAW_FRAMEBUFFER,u.__webglFramebuffer);for(let n=0;n&lt;r.length;n++){l.push(t.COLOR_ATTACHMENT0+n),e.depthBuffer&amp;&amp;l.push(h);const p=void 0!==u.__ignoreDepthValues&amp;&amp;u.__ignoreDepthValues;if(!1===p&amp;&amp;(e.depthBuffer&amp;&amp;(o|=t.DEPTH_BUFFER_BIT),e.stencilBuffer&amp;&amp;(o|=t.STENCIL_BUFFER_BIT)),d&amp;&amp;t.framebufferRenderbuffer(t.READ_FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.RENDERBUFFER,u.__webglColorRenderbuffer[n]),!0===p&amp;&amp;(t.invalidateFramebuffer(t.READ_FRAMEBUFFER,[h]),t.invalidateFramebuffer(t.DRAW_FRAMEBUFFER,[h])),d){const e=i.get(r[n]).__webglTexture;t.framebufferTexture2D(t.DRAW_FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,e,0)}t.blitFramebuffer(0,0,s,a,0,0,s,a,o,t.NEAREST),c&amp;&amp;t.invalidateFramebuffer(t.READ_FRAMEBUFFER,l)}if(n.bindFramebuffer(t.READ_FRAMEBUFFER,null),n.bindFramebuffer(t.DRAW_FRAMEBUFFER,null),d)for(let e=0;e&lt;r.length;e++){n.bindFramebuffer(t.FRAMEBUFFER,u.__webglMultisampledFramebuffer),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0+e,t.RENDERBUFFER,u.__webglColorRenderbuffer[e]);const s=i.get(r[e]).__webglTexture;n.bindFramebuffer(t.FRAMEBUFFER,u.__webglFramebuffer),t.framebufferTexture2D(t.DRAW_FRAMEBUFFER,t.COLOR_ATTACHMENT0+e,t.TEXTURE_2D,s,0)}n.bindFramebuffer(t.DRAW_FRAMEBUFFER,u.__webglMultisampledFramebuffer)}},this.setupDepthRenderbuffer=Q,this.setupFrameBufferTexture=K,this.useMultisampledRTT=et}function ja(t,e,n){const i=n.isWebGL2;return{convert:function(n,r=&quot;&quot;){let s;const a=Re.getTransfer(r);if(n===F)return t.UNSIGNED_BYTE;if(n===k)return t.UNSIGNED_SHORT_4_4_4_4;if(n===W)return t.UNSIGNED_SHORT_5_5_5_1;if(1010===n)return t.BYTE;if(1011===n)return t.SHORT;if(n===B)return t.UNSIGNED_SHORT;if(n===z)return t.INT;if(n===G)return t.UNSIGNED_INT;if(n===H)return t.FLOAT;if(n===V)return i?t.HALF_FLOAT:(s=e.get(&quot;OES_texture_half_float&quot;),null!==s?s.HALF_FLOAT_OES:null);if(1021===n)return t.ALPHA;if(n===j)return t.RGBA;if(1024===n)return t.LUMINANCE;if(1025===n)return t.LUMINANCE_ALPHA;if(n===q)return t.DEPTH_COMPONENT;if(n===Y)return t.DEPTH_STENCIL;if(n===Kt)return s=e.get(&quot;EXT_sRGB&quot;),null!==s?s.SRGB_ALPHA_EXT:null;if(1028===n)return t.RED;if(n===Z)return t.RED_INTEGER;if(1030===n)return t.RG;if(n===J)return t.RG_INTEGER;if(n===K)return t.RGBA_INTEGER;if(n===$||n===Q||n===tt||n===et)if(a===Xt){if(s=e.get(&quot;WEBGL_compressed_texture_s3tc_srgb&quot;),null===s)return null;if(n===$)return s.COMPRESSED_SRGB_S3TC_DXT1_EXT;if(n===Q)return s.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;if(n===tt)return s.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;if(n===et)return s.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}else{if(s=e.get(&quot;WEBGL_compressed_texture_s3tc&quot;),null===s)return null;if(n===$)return s.COMPRESSED_RGB_S3TC_DXT1_EXT;if(n===Q)return s.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(n===tt)return s.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(n===et)return s.COMPRESSED_RGBA_S3TC_DXT5_EXT}if(n===nt||n===it||n===rt||n===st){if(s=e.get(&quot;WEBGL_compressed_texture_pvrtc&quot;),null===s)return null;if(n===nt)return s.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(n===it)return s.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(n===rt)return s.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(n===st)return s.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}if(n===at)return s=e.get(&quot;WEBGL_compressed_texture_etc1&quot;),null!==s?s.COMPRESSED_RGB_ETC1_WEBGL:null;if(n===ot||n===lt){if(s=e.get(&quot;WEBGL_compressed_texture_etc&quot;),null===s)return null;if(n===ot)return a===Xt?s.COMPRESSED_SRGB8_ETC2:s.COMPRESSED_RGB8_ETC2;if(n===lt)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:s.COMPRESSED_RGBA8_ETC2_EAC}if(n===ct||n===ht||n===ut||n===dt||n===pt||n===mt||n===ft||n===gt||n===_t||n===vt||n===xt||n===yt||n===Mt||n===St){if(s=e.get(&quot;WEBGL_compressed_texture_astc&quot;),null===s)return null;if(n===ct)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:s.COMPRESSED_RGBA_ASTC_4x4_KHR;if(n===ht)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:s.COMPRESSED_RGBA_ASTC_5x4_KHR;if(n===ut)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:s.COMPRESSED_RGBA_ASTC_5x5_KHR;if(n===dt)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:s.COMPRESSED_RGBA_ASTC_6x5_KHR;if(n===pt)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:s.COMPRESSED_RGBA_ASTC_6x6_KHR;if(n===mt)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:s.COMPRESSED_RGBA_ASTC_8x5_KHR;if(n===ft)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:s.COMPRESSED_RGBA_ASTC_8x6_KHR;if(n===gt)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:s.COMPRESSED_RGBA_ASTC_8x8_KHR;if(n===_t)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:s.COMPRESSED_RGBA_ASTC_10x5_KHR;if(n===vt)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:s.COMPRESSED_RGBA_ASTC_10x6_KHR;if(n===xt)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:s.COMPRESSED_RGBA_ASTC_10x8_KHR;if(n===yt)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:s.COMPRESSED_RGBA_ASTC_10x10_KHR;if(n===Mt)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:s.COMPRESSED_RGBA_ASTC_12x10_KHR;if(n===St)return a===Xt?s.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:s.COMPRESSED_RGBA_ASTC_12x12_KHR}if(n===bt||n===Tt||n===Et){if(s=e.get(&quot;EXT_texture_compression_bptc&quot;),null===s)return null;if(n===bt)return a===Xt?s.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:s.COMPRESSED_RGBA_BPTC_UNORM_EXT;if(n===Tt)return s.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;if(n===Et)return s.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT}if(36283===n||n===wt||n===At||n===Rt){if(s=e.get(&quot;EXT_texture_compression_rgtc&quot;),null===s)return null;if(n===bt)return s.COMPRESSED_RED_RGTC1_EXT;if(n===wt)return s.COMPRESSED_SIGNED_RED_RGTC1_EXT;if(n===At)return s.COMPRESSED_RED_GREEN_RGTC2_EXT;if(n===Rt)return s.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT}return n===X?i?t.UNSIGNED_INT_24_8:(s=e.get(&quot;WEBGL_depth_texture&quot;),null!==s?s.UNSIGNED_INT_24_8_WEBGL:null):void 0!==t[n]?t[n]:null}}}class qa extends sr{constructor(t=[]){super(),this.isArrayCamera=!0,this.cameras=t}}class Ya extends jn{constructor(){super(),this.isGroup=!0,this.type=&quot;Group&quot;}}const Za={type:&quot;move&quot;};class Ja{constructor(){this._targetRay=null,this._grip=null,this._hand=null}getHandSpace(){return null===this._hand&amp;&amp;(this._hand=new Ya,this._hand.matrixAutoUpdate=!1,this._hand.visible=!1,this._hand.joints={},this._hand.inputState={pinching:!1}),this._hand}getTargetRaySpace(){return null===this._targetRay&amp;&amp;(this._targetRay=new Ya,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1,this._targetRay.hasLinearVelocity=!1,this._targetRay.linearVelocity=new We,this._targetRay.hasAngularVelocity=!1,this._targetRay.angularVelocity=new We),this._targetRay}getGripSpace(){return null===this._grip&amp;&amp;(this._grip=new Ya,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1,this._grip.hasLinearVelocity=!1,this._grip.linearVelocity=new We,this._grip.hasAngularVelocity=!1,this._grip.angularVelocity=new We),this._grip}dispatchEvent(t){return null!==this._targetRay&amp;&amp;this._targetRay.dispatchEvent(t),null!==this._grip&amp;&amp;this._grip.dispatchEvent(t),null!==this._hand&amp;&amp;this._hand.dispatchEvent(t),this}connect(t){if(t&amp;&amp;t.hand){const e=this._hand;if(e)for(const n of t.hand.values())this._getHandJoint(e,n)}return this.dispatchEvent({type:&quot;connected&quot;,data:t}),this}disconnect(t){return this.dispatchEvent({type:&quot;disconnected&quot;,data:t}),null!==this._targetRay&amp;&amp;(this._targetRay.visible=!1),null!==this._grip&amp;&amp;(this._grip.visible=!1),null!==this._hand&amp;&amp;(this._hand.visible=!1),this}update(t,e,n){let i=null,r=null,s=null;const a=this._targetRay,o=this._grip,l=this._hand;if(t&amp;&amp;&quot;visible-blurred&quot;!==e.session.visibilityState){if(l&amp;&amp;t.hand){s=!0;for(const i of t.hand.values()){const t=e.getJointPose(i,n),r=this._getHandJoint(l,i);null!==t&amp;&amp;(r.matrix.fromArray(t.transform.matrix),r.matrix.decompose(r.position,r.rotation,r.scale),r.matrixWorldNeedsUpdate=!0,r.jointRadius=t.radius),r.visible=null!==t}const i=l.joints[&quot;index-finger-tip&quot;],r=l.joints[&quot;thumb-tip&quot;],a=i.position.distanceTo(r.position),o=.02,c=.005;l.inputState.pinching&amp;&amp;a&gt;o+c?(l.inputState.pinching=!1,this.dispatchEvent({type:&quot;pinchend&quot;,handedness:t.handedness,target:this})):!l.inputState.pinching&amp;&amp;a&lt;=o-c&amp;&amp;(l.inputState.pinching=!0,this.dispatchEvent({type:&quot;pinchstart&quot;,handedness:t.handedness,target:this}))}else null!==o&amp;&amp;t.gripSpace&amp;&amp;(r=e.getPose(t.gripSpace,n),null!==r&amp;&amp;(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));null!==a&amp;&amp;(i=e.getPose(t.targetRaySpace,n),null===i&amp;&amp;null!==r&amp;&amp;(i=r),null!==i&amp;&amp;(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),a.matrixWorldNeedsUpdate=!0,i.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(i.linearVelocity)):a.hasLinearVelocity=!1,i.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(i.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent(Za)))}return null!==a&amp;&amp;(a.visible=null!==i),null!==o&amp;&amp;(o.visible=null!==r),null!==l&amp;&amp;(l.visible=null!==s),this}_getHandJoint(t,e){if(void 0===t.joints[e.jointName]){const n=new Ya;n.matrixAutoUpdate=!1,n.visible=!1,t.joints[e.jointName]=n,t.add(n)}return t.joints[e.jointName]}}class Ka extends te{constructor(t,e){super();const n=this;let i=null,r=1,s=null,a=&quot;local-floor&quot;,o=1,l=null,c=null,h=null,u=null,d=null,p=null;const m=e.getContextAttributes();let f=null,g=null;const _=[],v=[],x=new me;let y=null;const M=new sr;M.layers.enable(1),M.viewport=new Be;const S=new sr;S.layers.enable(2),S.viewport=new Be;const b=[M,S],T=new qa;T.layers.enable(1),T.layers.enable(2);let E=null,w=null;function A(t){const e=v.indexOf(t.inputSource);if(-1===e)return;const n=_[e];void 0!==n&amp;&amp;(n.update(t.inputSource,t.frame,l||s),n.dispatchEvent({type:t.type,data:t.inputSource}))}function R(){i.removeEventListener(&quot;select&quot;,A),i.removeEventListener(&quot;selectstart&quot;,A),i.removeEventListener(&quot;selectend&quot;,A),i.removeEventListener(&quot;squeeze&quot;,A),i.removeEventListener(&quot;squeezestart&quot;,A),i.removeEventListener(&quot;squeezeend&quot;,A),i.removeEventListener(&quot;end&quot;,R),i.removeEventListener(&quot;inputsourceschange&quot;,C);for(let t=0;t&lt;_.length;t++){const e=v[t];null!==e&amp;&amp;(v[t]=null,_[t].disconnect(e))}E=null,w=null,t.setRenderTarget(f),d=null,u=null,h=null,i=null,g=null,D.stop(),n.isPresenting=!1,t.setPixelRatio(y),t.setSize(x.width,x.height,!1),n.dispatchEvent({type:&quot;sessionend&quot;})}function C(t){for(let e=0;e&lt;t.removed.length;e++){const n=t.removed[e],i=v.indexOf(n);i&gt;=0&amp;&amp;(v[i]=null,_[i].disconnect(n))}for(let e=0;e&lt;t.added.length;e++){const n=t.added[e];let i=v.indexOf(n);if(-1===i){for(let t=0;t&lt;_.length;t++){if(t&gt;=v.length){v.push(n),i=t;break}if(null===v[t]){v[t]=n,i=t;break}}if(-1===i)break}const r=_[i];r&amp;&amp;r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(t){let e=_[t];return void 0===e&amp;&amp;(e=new Ja,_[t]=e),e.getTargetRaySpace()},this.getControllerGrip=function(t){let e=_[t];return void 0===e&amp;&amp;(e=new Ja,_[t]=e),e.getGripSpace()},this.getHand=function(t){let e=_[t];return void 0===e&amp;&amp;(e=new Ja,_[t]=e),e.getHandSpace()},this.setFramebufferScaleFactor=function(t){r=t,!0===n.isPresenting&amp;&amp;console.warn(&quot;THREE.WebXRManager: Cannot change framebuffer scale while presenting.&quot;)},this.setReferenceSpaceType=function(t){a=t,!0===n.isPresenting&amp;&amp;console.warn(&quot;THREE.WebXRManager: Cannot change reference space type while presenting.&quot;)},this.getReferenceSpace=function(){return l||s},this.setReferenceSpace=function(t){l=t},this.getBaseLayer=function(){return null!==u?u:d},this.getBinding=function(){return h},this.getFrame=function(){return p},this.getSession=function(){return i},this.setSession=async function(c){if(i=c,null!==i){if(f=t.getRenderTarget(),i.addEventListener(&quot;select&quot;,A),i.addEventListener(&quot;selectstart&quot;,A),i.addEventListener(&quot;selectend&quot;,A),i.addEventListener(&quot;squeeze&quot;,A),i.addEventListener(&quot;squeezestart&quot;,A),i.addEventListener(&quot;squeezeend&quot;,A),i.addEventListener(&quot;end&quot;,R),i.addEventListener(&quot;inputsourceschange&quot;,C),!0!==m.xrCompatible&amp;&amp;await e.makeXRCompatible(),y=t.getPixelRatio(),t.getSize(x),void 0===i.renderState.layers||!1===t.capabilities.isWebGL2){const n={antialias:void 0!==i.renderState.layers||m.antialias,alpha:!0,depth:m.depth,stencil:m.stencil,framebufferScaleFactor:r};d=new XRWebGLLayer(i,e,n),i.updateRenderState({baseLayer:d}),t.setPixelRatio(1),t.setSize(d.framebufferWidth,d.framebufferHeight,!1),g=new Ge(d.framebufferWidth,d.framebufferHeight,{format:j,type:F,colorSpace:t.outputColorSpace,stencilBuffer:m.stencil})}else{let n=null,s=null,a=null;m.depth&amp;&amp;(a=m.stencil?e.DEPTH24_STENCIL8:e.DEPTH_COMPONENT24,n=m.stencil?Y:q,s=m.stencil?X:G);const o={colorFormat:e.RGBA8,depthFormat:a,scaleFactor:r};h=new XRWebGLBinding(i,e),u=h.createProjectionLayer(o),i.updateRenderState({layers:[u]}),t.setPixelRatio(1),t.setSize(u.textureWidth,u.textureHeight,!1),g=new Ge(u.textureWidth,u.textureHeight,{format:j,type:F,depthTexture:new ns(u.textureWidth,u.textureHeight,s,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:m.stencil,colorSpace:t.outputColorSpace,samples:m.antialias?4:0});t.properties.get(g).__ignoreDepthValues=u.ignoreDepthValues}g.isXRRenderTarget=!0,this.setFoveation(o),l=null,s=await i.requestReferenceSpace(a),D.setContext(i),D.start(),n.isPresenting=!0,n.dispatchEvent({type:&quot;sessionstart&quot;})}},this.getEnvironmentBlendMode=function(){if(null!==i)return i.environmentBlendMode};const L=new We,P=new We;function I(t,e){null===e?t.matrixWorld.copy(t.matrix):t.matrixWorld.multiplyMatrices(e.matrixWorld,t.matrix),t.matrixWorldInverse.copy(t.matrixWorld).invert()}this.updateCamera=function(t){if(null===i)return;T.near=S.near=M.near=t.near,T.far=S.far=M.far=t.far,E===T.near&amp;&amp;w===T.far||(i.updateRenderState({depthNear:T.near,depthFar:T.far}),E=T.near,w=T.far);const e=t.parent,n=T.cameras;I(T,e);for(let t=0;t&lt;n.length;t++)I(n[t],e);2===n.length?function(t,e,n){L.setFromMatrixPosition(e.matrixWorld),P.setFromMatrixPosition(n.matrixWorld);const i=L.distanceTo(P),r=e.projectionMatrix.elements,s=n.projectionMatrix.elements,a=r[14]/(r[10]-1),o=r[14]/(r[10]+1),l=(r[9]+1)/r[5],c=(r[9]-1)/r[5],h=(r[8]-1)/r[0],u=(s[8]+1)/s[0],d=a*h,p=a*u,m=i/(-h+u),f=m*-h;e.matrixWorld.decompose(t.position,t.quaternion,t.scale),t.translateX(f),t.translateZ(m),t.matrixWorld.compose(t.position,t.quaternion,t.scale),t.matrixWorldInverse.copy(t.matrixWorld).invert();const g=a+m,_=o+m,v=d-f,x=p+(i-f),y=l*o/_*g,M=c*o/_*g;t.projectionMatrix.makePerspective(v,x,y,M,g,_),t.projectionMatrixInverse.copy(t.projectionMatrix).invert()}(T,M,S):T.projectionMatrix.copy(M.projectionMatrix),function(t,e,n){null===n?t.matrix.copy(e.matrixWorld):(t.matrix.copy(n.matrixWorld),t.matrix.invert(),t.matrix.multiply(e.matrixWorld));t.matrix.decompose(t.position,t.quaternion,t.scale),t.updateMatrixWorld(!0),t.projectionMatrix.copy(e.projectionMatrix),t.projectionMatrixInverse.copy(e.projectionMatrixInverse),t.isPerspectiveCamera&amp;&amp;(t.fov=2*re*Math.atan(1/t.projectionMatrix.elements[5]),t.zoom=1)}(t,T,e)},this.getCamera=function(){return T},this.getFoveation=function(){if(null!==u||null!==d)return o},this.setFoveation=function(t){o=t,null!==u&amp;&amp;(u.fixedFoveation=t),null!==d&amp;&amp;void 0!==d.fixedFoveation&amp;&amp;(d.fixedFoveation=t)};let U=null;const D=new _r;D.setAnimationLoop((function(e,i){if(c=i.getViewerPose(l||s),p=i,null!==c){const e=c.views;null!==d&amp;&amp;(t.setRenderTargetFramebuffer(g,d.framebuffer),t.setRenderTarget(g));let n=!1;e.length!==T.cameras.length&amp;&amp;(T.cameras.length=0,n=!0);for(let i=0;i&lt;e.length;i++){const r=e[i];let s=null;if(null!==d)s=d.getViewport(r);else{const e=h.getViewSubImage(u,r);s=e.viewport,0===i&amp;&amp;(t.setRenderTargetTextures(g,e.colorTexture,u.ignoreDepthValues?void 0:e.depthStencilTexture),t.setRenderTarget(g))}let a=b[i];void 0===a&amp;&amp;(a=new sr,a.layers.enable(i),a.viewport=new Be,b[i]=a),a.matrix.fromArray(r.transform.matrix),a.matrix.decompose(a.position,a.quaternion,a.scale),a.projectionMatrix.fromArray(r.projectionMatrix),a.projectionMatrixInverse.copy(a.projectionMatrix).invert(),a.viewport.set(s.x,s.y,s.width,s.height),0===i&amp;&amp;(T.matrix.copy(a.matrix),T.matrix.decompose(T.position,T.quaternion,T.scale)),!0===n&amp;&amp;T.cameras.push(a)}}for(let t=0;t&lt;_.length;t++){const e=v[t],n=_[t];null!==e&amp;&amp;void 0!==n&amp;&amp;n.update(e,i,l||s)}U&amp;&amp;U(e,i),i.detectedPlanes&amp;&amp;n.dispatchEvent({type:&quot;planesdetected&quot;,data:i}),p=null})),this.setAnimationLoop=function(t){U=t},this.dispose=function(){}}}function $a(t,e){function n(t,e){!0===t.matrixAutoUpdate&amp;&amp;t.updateMatrix(),e.value.copy(t.matrix)}function i(i,r){i.opacity.value=r.opacity,r.color&amp;&amp;i.diffuse.value.copy(r.color),r.emissive&amp;&amp;i.emissive.value.copy(r.emissive).multiplyScalar(r.emissiveIntensity),r.map&amp;&amp;(i.map.value=r.map,n(r.map,i.mapTransform)),r.alphaMap&amp;&amp;(i.alphaMap.value=r.alphaMap,n(r.alphaMap,i.alphaMapTransform)),r.bumpMap&amp;&amp;(i.bumpMap.value=r.bumpMap,n(r.bumpMap,i.bumpMapTransform),i.bumpScale.value=r.bumpScale,r.side===a&amp;&amp;(i.bumpScale.value*=-1)),r.normalMap&amp;&amp;(i.normalMap.value=r.normalMap,n(r.normalMap,i.normalMapTransform),i.normalScale.value.copy(r.normalScale),r.side===a&amp;&amp;i.normalScale.value.negate()),r.displacementMap&amp;&amp;(i.displacementMap.value=r.displacementMap,n(r.displacementMap,i.displacementMapTransform),i.displacementScale.value=r.displacementScale,i.displacementBias.value=r.displacementBias),r.emissiveMap&amp;&amp;(i.emissiveMap.value=r.emissiveMap,n(r.emissiveMap,i.emissiveMapTransform)),r.specularMap&amp;&amp;(i.specularMap.value=r.specularMap,n(r.specularMap,i.specularMapTransform)),r.alphaTest&gt;0&amp;&amp;(i.alphaTest.value=r.alphaTest);const s=e.get(r).envMap;if(s&amp;&amp;(i.envMap.value=s,i.flipEnvMap.value=s.isCubeTexture&amp;&amp;!1===s.isRenderTargetTexture?-1:1,i.reflectivity.value=r.reflectivity,i.ior.value=r.ior,i.refractionRatio.value=r.refractionRatio),r.lightMap){i.lightMap.value=r.lightMap;const e=!0===t._useLegacyLights?Math.PI:1;i.lightMapIntensity.value=r.lightMapIntensity*e,n(r.lightMap,i.lightMapTransform)}r.aoMap&amp;&amp;(i.aoMap.value=r.aoMap,i.aoMapIntensity.value=r.aoMapIntensity,n(r.aoMap,i.aoMapTransform))}return{refreshFogUniforms:function(e,n){n.color.getRGB(e.fogColor.value,er(t)),n.isFog?(e.fogNear.value=n.near,e.fogFar.value=n.far):n.isFogExp2&amp;&amp;(e.fogDensity.value=n.density)},refreshMaterialUniforms:function(t,r,s,o,l){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(t,r):r.isMeshToonMaterial?(i(t,r),function(t,e){e.gradientMap&amp;&amp;(t.gradientMap.value=e.gradientMap)}(t,r)):r.isMeshPhongMaterial?(i(t,r),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4)}(t,r)):r.isMeshStandardMaterial?(i(t,r),function(t,i){t.metalness.value=i.metalness,i.metalnessMap&amp;&amp;(t.metalnessMap.value=i.metalnessMap,n(i.metalnessMap,t.metalnessMapTransform));t.roughness.value=i.roughness,i.roughnessMap&amp;&amp;(t.roughnessMap.value=i.roughnessMap,n(i.roughnessMap,t.roughnessMapTransform));const r=e.get(i).envMap;r&amp;&amp;(t.envMapIntensity.value=i.envMapIntensity)}(t,r),r.isMeshPhysicalMaterial&amp;&amp;function(t,e,i){t.ior.value=e.ior,e.sheen&gt;0&amp;&amp;(t.sheenColor.value.copy(e.sheenColor).multiplyScalar(e.sheen),t.sheenRoughness.value=e.sheenRoughness,e.sheenColorMap&amp;&amp;(t.sheenColorMap.value=e.sheenColorMap,n(e.sheenColorMap,t.sheenColorMapTransform)),e.sheenRoughnessMap&amp;&amp;(t.sheenRoughnessMap.value=e.sheenRoughnessMap,n(e.sheenRoughnessMap,t.sheenRoughnessMapTransform)));e.clearcoat&gt;0&amp;&amp;(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&amp;&amp;(t.clearcoatMap.value=e.clearcoatMap,n(e.clearcoatMap,t.clearcoatMapTransform)),e.clearcoatRoughnessMap&amp;&amp;(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap,n(e.clearcoatRoughnessMap,t.clearcoatRoughnessMapTransform)),e.clearcoatNormalMap&amp;&amp;(t.clearcoatNormalMap.value=e.clearcoatNormalMap,n(e.clearcoatNormalMap,t.clearcoatNormalMapTransform),t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),e.side===a&amp;&amp;t.clearcoatNormalScale.value.negate()));e.iridescence&gt;0&amp;&amp;(t.iridescence.value=e.iridescence,t.iridescenceIOR.value=e.iridescenceIOR,t.iridescenceThicknessMinimum.value=e.iridescenceThicknessRange[0],t.iridescenceThicknessMaximum.value=e.iridescenceThicknessRange[1],e.iridescenceMap&amp;&amp;(t.iridescenceMap.value=e.iridescenceMap,n(e.iridescenceMap,t.iridescenceMapTransform)),e.iridescenceThicknessMap&amp;&amp;(t.iridescenceThicknessMap.value=e.iridescenceThicknessMap,n(e.iridescenceThicknessMap,t.iridescenceThicknessMapTransform)));e.transmission&gt;0&amp;&amp;(t.transmission.value=e.transmission,t.transmissionSamplerMap.value=i.texture,t.transmissionSamplerSize.value.set(i.width,i.height),e.transmissionMap&amp;&amp;(t.transmissionMap.value=e.transmissionMap,n(e.transmissionMap,t.transmissionMapTransform)),t.thickness.value=e.thickness,e.thicknessMap&amp;&amp;(t.thicknessMap.value=e.thicknessMap,n(e.thicknessMap,t.thicknessMapTransform)),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));e.anisotropy&gt;0&amp;&amp;(t.anisotropyVector.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation)),e.anisotropyMap&amp;&amp;(t.anisotropyMap.value=e.anisotropyMap,n(e.anisotropyMap,t.anisotropyMapTransform)));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularColorMap&amp;&amp;(t.specularColorMap.value=e.specularColorMap,n(e.specularColorMap,t.specularColorMapTransform));e.specularIntensityMap&amp;&amp;(t.specularIntensityMap.value=e.specularIntensityMap,n(e.specularIntensityMap,t.specularIntensityMapTransform))}(t,r,l)):r.isMeshMatcapMaterial?(i(t,r),function(t,e){e.matcap&amp;&amp;(t.matcap.value=e.matcap)}(t,r)):r.isMeshDepthMaterial?i(t,r):r.isMeshDistanceMaterial?(i(t,r),function(t,n){const i=e.get(n).light;t.referencePosition.value.setFromMatrixPosition(i.matrixWorld),t.nearDistance.value=i.shadow.camera.near,t.farDistance.value=i.shadow.camera.far}(t,r)):r.isMeshNormalMaterial?i(t,r):r.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,e.map&amp;&amp;(t.map.value=e.map,n(e.map,t.mapTransform))}(t,r),r.isLineDashedMaterial&amp;&amp;function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,r)):r.isPointsMaterial?function(t,e,i,r){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*i,t.scale.value=.5*r,e.map&amp;&amp;(t.map.value=e.map,n(e.map,t.uvTransform));e.alphaMap&amp;&amp;(t.alphaMap.value=e.alphaMap,n(e.alphaMap,t.alphaMapTransform));e.alphaTest&gt;0&amp;&amp;(t.alphaTest.value=e.alphaTest)}(t,r,s,o):r.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,e.map&amp;&amp;(t.map.value=e.map,n(e.map,t.mapTransform));e.alphaMap&amp;&amp;(t.alphaMap.value=e.alphaMap,n(e.alphaMap,t.alphaMapTransform));e.alphaTest&gt;0&amp;&amp;(t.alphaTest.value=e.alphaTest)}(t,r):r.isShadowMaterial?(t.color.value.copy(r.color),t.opacity.value=r.opacity):r.isShaderMaterial&amp;&amp;(r.uniformsNeedUpdate=!1)}}}function Qa(t,e,n,i){let r={},s={},a=[];const o=n.isWebGL2?t.getParameter(t.MAX_UNIFORM_BUFFER_BINDINGS):0;function l(t,e,n,i){const r=t.value,s=e+&quot;_&quot;+n;if(void 0===i[s])return i[s]=&quot;number&quot;==typeof r||&quot;boolean&quot;==typeof r?r:r.clone(),!0;{const t=i[s];if(&quot;number&quot;==typeof r||&quot;boolean&quot;==typeof r){if(t!==r)return i[s]=r,!0}else if(!1===t.equals(r))return t.copy(r),!0}return!1}function c(t){const e={boundary:0,storage:0};return&quot;number&quot;==typeof t||&quot;boolean&quot;==typeof t?(e.boundary=4,e.storage=4):t.isVector2?(e.boundary=8,e.storage=8):t.isVector3||t.isColor?(e.boundary=16,e.storage=12):t.isVector4?(e.boundary=16,e.storage=16):t.isMatrix3?(e.boundary=48,e.storage=48):t.isMatrix4?(e.boundary=64,e.storage=64):t.isTexture?console.warn(&quot;THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.&quot;):console.warn(&quot;THREE.WebGLRenderer: Unsupported uniform value type.&quot;,t),e}function h(e){const n=e.target;n.removeEventListener(&quot;dispose&quot;,h);const i=a.indexOf(n.__bindingPointIndex);a.splice(i,1),t.deleteBuffer(r[n.id]),delete r[n.id],delete s[n.id]}return{bind:function(t,e){const n=e.program;i.uniformBlockBinding(t,n)},update:function(n,u){let d=r[n.id];void 0===d&amp;&amp;(!function(t){const e=t.uniforms;let n=0;const i=16;for(let t=0,r=e.length;t&lt;r;t++){const r=Array.isArray(e[t])?e[t]:[e[t]];for(let t=0,e=r.length;t&lt;e;t++){const e=r[t],s=Array.isArray(e.value)?e.value:[e.value];for(let t=0,r=s.length;t&lt;r;t++){const r=c(s[t]),a=n%i;0!==a&amp;&amp;i-a&lt;r.boundary&amp;&amp;(n+=i-a),e.__data=new Float32Array(r.storage/Float32Array.BYTES_PER_ELEMENT),e.__offset=n,n+=r.storage}}}const r=n%i;r&gt;0&amp;&amp;(n+=i-r);t.__size=n,t.__cache={}}(n),d=function(e){const n=function(){for(let t=0;t&lt;o;t++)if(-1===a.indexOf(t))return a.push(t),t;return console.error(&quot;THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.&quot;),0}();e.__bindingPointIndex=n;const i=t.createBuffer(),r=e.__size,s=e.usage;return t.bindBuffer(t.UNIFORM_BUFFER,i),t.bufferData(t.UNIFORM_BUFFER,r,s),t.bindBuffer(t.UNIFORM_BUFFER,null),t.bindBufferBase(t.UNIFORM_BUFFER,n,i),i}(n),r[n.id]=d,n.addEventListener(&quot;dispose&quot;,h));const p=u.program;i.updateUBOMapping(n,p);const m=e.render.frame;s[n.id]!==m&amp;&amp;(!function(e){const n=r[e.id],i=e.uniforms,s=e.__cache;t.bindBuffer(t.UNIFORM_BUFFER,n);for(let e=0,n=i.length;e&lt;n;e++){const n=Array.isArray(i[e])?i[e]:[i[e]];for(let i=0,r=n.length;i&lt;r;i++){const r=n[i];if(!0===l(r,e,i,s)){const e=r.__offset,n=Array.isArray(r.value)?r.value:[r.value];let i=0;for(let s=0;s&lt;n.length;s++){const a=n[s],o=c(a);&quot;number&quot;==typeof a||&quot;boolean&quot;==typeof a?(r.__data[0]=a,t.bufferSubData(t.UNIFORM_BUFFER,e+i,r.__data)):a.isMatrix3?(r.__data[0]=a.elements[0],r.__data[1]=a.elements[1],r.__data[2]=a.elements[2],r.__data[3]=0,r.__data[4]=a.elements[3],r.__data[5]=a.elements[4],r.__data[6]=a.elements[5],r.__data[7]=0,r.__data[8]=a.elements[6],r.__data[9]=a.elements[7],r.__data[10]=a.elements[8],r.__data[11]=0):(a.toArray(r.__data,i),i+=o.storage/Float32Array.BYTES_PER_ELEMENT)}t.bufferSubData(t.UNIFORM_BUFFER,e,r.__data)}}}t.bindBuffer(t.UNIFORM_BUFFER,null)}(n),s[n.id]=m)},dispose:function(){for(const e in r)t.deleteBuffer(r[e]);a=[],r={},s={}}}}class to{constructor(t={}){const{canvas:n=Me(),context:i=null,depth:r=!0,stencil:o=!0,alpha:l=!1,antialias:c=!1,premultipliedAlpha:h=!0,preserveDrawingBuffer:u=!1,powerPreference:d=&quot;default&quot;,failIfMajorPerformanceCaveat:m=!1}=t;let f;this.isWebGLRenderer=!0,f=null!==i?i.getContextAttributes().alpha:l;const g=new Uint32Array(4),_=new Int32Array(4);let v=null,x=null;const y=[],M=[];this.domElement=n,this.debug={checkShaderErrors:!0,onShaderError:null},this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.sortObjects=!0,this.clippingPlanes=[],this.localClippingEnabled=!1,this._outputColorSpace=Gt,this._useLegacyLights=!1,this.toneMapping=p,this.toneMappingExposure=1;const S=this;let b=!1,T=0,E=0,w=null,A=-1,R=null;const C=new Be,L=new Be;let P=null;const I=new ci(0);let U=0,D=n.width,N=n.height,z=1,q=null,Y=null;const $=new Be(0,0,D,N),Q=new Be(0,0,D,N);let tt=!1;const et=new gr;let nt=!1,it=!1,rt=null;const st=new Mn,at=new me,ot=new We,lt={background:null,fog:null,environment:null,overrideMaterial:null,isScene:!0};function ct(){return null===w?z:1}let ht,ut,dt,pt,mt,ft,gt,_t,vt,xt,yt,Mt,St,bt,Tt,Et,wt,At,Rt,Ct,Lt,Pt,It,Ut,Dt=i;function Nt(t,e){for(let i=0;i&lt;t.length;i++){const r=t[i],s=n.getContext(r,e);if(null!==s)return s}return null}try{const t={alpha:!0,depth:r,stencil:o,antialias:c,premultipliedAlpha:h,preserveDrawingBuffer:u,powerPreference:d,failIfMajorPerformanceCaveat:m};if(&quot;setAttribute&quot;in n&amp;&amp;n.setAttribute(&quot;data-engine&quot;,`three.js r${e}`),n.addEventListener(&quot;webglcontextlost&quot;,Bt,!1),n.addEventListener(&quot;webglcontextrestored&quot;,zt,!1),n.addEventListener(&quot;webglcontextcreationerror&quot;,Vt,!1),null===Dt){const e=[&quot;webgl2&quot;,&quot;webgl&quot;,&quot;experimental-webgl&quot;];if(!0===S.isWebGL1Renderer&amp;&amp;e.shift(),Dt=Nt(e,t),null===Dt)throw Nt(e)?new Error(&quot;Error creating WebGL context with your selected attributes.&quot;):new Error(&quot;Error creating WebGL context.&quot;)}&quot;undefined&quot;!=typeof WebGLRenderingContext&amp;&amp;Dt instanceof WebGLRenderingContext&amp;&amp;console.warn(&quot;THREE.WebGLRenderer: WebGL 1 support was deprecated in r153 and will be removed in r163.&quot;),void 0===Dt.getShaderPrecisionFormat&amp;&amp;(Dt.getShaderPrecisionFormat=function(){return{rangeMin:1,rangeMax:1,precision:1}})}catch(t){throw console.error(&quot;THREE.WebGLRenderer: &quot;+t.message),t}function Ot(){ht=new Yr(Dt),ut=new Ar(Dt,ht,t),ht.init(ut),Pt=new ja(Dt,ht,ut),dt=new Wa(Dt,ht,ut),pt=new Kr(Dt),mt=new La,ft=new Xa(Dt,ht,dt,mt,ut,Pt,pt),gt=new Cr(S),_t=new qr(S),vt=new vr(Dt,ut),It=new Er(Dt,ht,vt,ut),xt=new Zr(Dt,vt,pt,It),yt=new es(Dt,xt,vt,pt),Rt=new ts(Dt,ut,ft),Et=new Rr(mt),Mt=new Ca(S,gt,_t,ht,ut,It,Et),St=new $a(S,mt),bt=new Da,Tt=new Ga(ht,ut),At=new Tr(S,gt,_t,dt,yt,f,h),wt=new ka(S,yt,ut),Ut=new Qa(Dt,pt,ut,dt),Ct=new wr(Dt,ht,pt,ut),Lt=new Jr(Dt,ht,pt,ut),pt.programs=Mt.programs,S.capabilities=ut,S.extensions=ht,S.properties=mt,S.renderLists=bt,S.shadowMap=wt,S.state=dt,S.info=pt}Ot();const Ft=new Ka(S,Dt);function Bt(t){t.preventDefault(),console.log(&quot;THREE.WebGLRenderer: Context Lost.&quot;),b=!0}function zt(){console.log(&quot;THREE.WebGLRenderer: Context Restored.&quot;),b=!1;const t=pt.autoReset,e=wt.enabled,n=wt.autoUpdate,i=wt.needsUpdate,r=wt.type;Ot(),pt.autoReset=t,wt.enabled=e,wt.autoUpdate=n,wt.needsUpdate=i,wt.type=r}function Vt(t){console.error(&quot;THREE.WebGLRenderer: A WebGL context could not be created. Reason: &quot;,t.statusMessage)}function kt(t){const e=t.target;e.removeEventListener(&quot;dispose&quot;,kt),function(t){(function(t){const e=mt.get(t).programs;void 0!==e&amp;&amp;(e.forEach((function(t){Mt.releaseProgram(t)})),t.isShaderMaterial&amp;&amp;Mt.releaseShaderCache(t))})(t),mt.remove(t)}(e)}function Wt(t,e,n){!0===t.transparent&amp;&amp;2===t.side&amp;&amp;!1===t.forceSinglePass?(t.side=a,t.needsUpdate=!0,Qt(t,e,n),t.side=s,t.needsUpdate=!0,Qt(t,e,n),t.side=2):Qt(t,e,n)}this.xr=Ft,this.getContext=function(){return Dt},this.getContextAttributes=function(){return Dt.getContextAttributes()},this.forceContextLoss=function(){const t=ht.get(&quot;WEBGL_lose_context&quot;);t&amp;&amp;t.loseContext()},this.forceContextRestore=function(){const t=ht.get(&quot;WEBGL_lose_context&quot;);t&amp;&amp;t.restoreContext()},this.getPixelRatio=function(){return z},this.setPixelRatio=function(t){void 0!==t&amp;&amp;(z=t,this.setSize(D,N,!1))},this.getSize=function(t){return t.set(D,N)},this.setSize=function(t,e,i=!0){Ft.isPresenting?console.warn(&quot;THREE.WebGLRenderer: Can't change size while VR device is presenting.&quot;):(D=t,N=e,n.width=Math.floor(t*z),n.height=Math.floor(e*z),!0===i&amp;&amp;(n.style.width=t+&quot;px&quot;,n.style.height=e+&quot;px&quot;),this.setViewport(0,0,t,e))},this.getDrawingBufferSize=function(t){return t.set(D*z,N*z).floor()},this.setDrawingBufferSize=function(t,e,i){D=t,N=e,z=i,n.width=Math.floor(t*i),n.height=Math.floor(e*i),this.setViewport(0,0,t,e)},this.getCurrentViewport=function(t){return t.copy(C)},this.getViewport=function(t){return t.copy($)},this.setViewport=function(t,e,n,i){t.isVector4?$.set(t.x,t.y,t.z,t.w):$.set(t,e,n,i),dt.viewport(C.copy($).multiplyScalar(z).floor())},this.getScissor=function(t){return t.copy(Q)},this.setScissor=function(t,e,n,i){t.isVector4?Q.set(t.x,t.y,t.z,t.w):Q.set(t,e,n,i),dt.scissor(L.copy(Q).multiplyScalar(z).floor())},this.getScissorTest=function(){return tt},this.setScissorTest=function(t){dt.setScissorTest(tt=t)},this.setOpaqueSort=function(t){q=t},this.setTransparentSort=function(t){Y=t},this.getClearColor=function(t){return t.copy(At.getClearColor())},this.setClearColor=function(){At.setClearColor.apply(At,arguments)},this.getClearAlpha=function(){return At.getClearAlpha()},this.setClearAlpha=function(){At.setClearAlpha.apply(At,arguments)},this.clear=function(t=!0,e=!0,n=!0){let i=0;if(t){let t=!1;if(null!==w){const e=w.texture.format;t=e===K||e===J||e===Z}if(t){const t=w.texture.type,e=t===F||t===G||t===B||t===X||t===k||t===W,n=At.getClearColor(),i=At.getClearAlpha(),r=n.r,s=n.g,a=n.b;e?(g[0]=r,g[1]=s,g[2]=a,g[3]=i,Dt.clearBufferuiv(Dt.COLOR,0,g)):(_[0]=r,_[1]=s,_[2]=a,_[3]=i,Dt.clearBufferiv(Dt.COLOR,0,_))}else i|=Dt.COLOR_BUFFER_BIT}e&amp;&amp;(i|=Dt.DEPTH_BUFFER_BIT),n&amp;&amp;(i|=Dt.STENCIL_BUFFER_BIT,this.state.buffers.stencil.setMask(4294967295)),Dt.clear(i)},this.clearColor=function(){this.clear(!0,!1,!1)},this.clearDepth=function(){this.clear(!1,!0,!1)},this.clearStencil=function(){this.clear(!1,!1,!0)},this.dispose=function(){n.removeEventListener(&quot;webglcontextlost&quot;,Bt,!1),n.removeEventListener(&quot;webglcontextrestored&quot;,zt,!1),n.removeEventListener(&quot;webglcontextcreationerror&quot;,Vt,!1),bt.dispose(),Tt.dispose(),mt.dispose(),gt.dispose(),_t.dispose(),yt.dispose(),It.dispose(),Ut.dispose(),Mt.dispose(),Ft.dispose(),Ft.removeEventListener(&quot;sessionstart&quot;,jt),Ft.removeEventListener(&quot;sessionend&quot;,qt),rt&amp;&amp;(rt.dispose(),rt=null),Yt.stop()},this.renderBufferDirect=function(t,e,n,i,r,s){null===e&amp;&amp;(e=lt);const a=r.isMesh&amp;&amp;r.matrixWorld.determinant()&lt;0,o=function(t,e,n,i,r){!0!==e.isScene&amp;&amp;(e=lt);ft.resetTextureUnits();const s=e.fog,a=i.isMeshStandardMaterial?e.environment:null,o=null===w?S.outputColorSpace:!0===w.isXRRenderTarget?w.texture.colorSpace:Ht,l=(i.isMeshStandardMaterial?_t:gt).get(i.envMap||a),c=!0===i.vertexColors&amp;&amp;!!n.attributes.color&amp;&amp;4===n.attributes.color.itemSize,h=!!n.attributes.tangent&amp;&amp;(!!i.normalMap||i.anisotropy&gt;0),u=!!n.morphAttributes.position,d=!!n.morphAttributes.normal,m=!!n.morphAttributes.color;let f=p;i.toneMapped&amp;&amp;(null!==w&amp;&amp;!0!==w.isXRRenderTarget||(f=S.toneMapping));const g=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,_=void 0!==g?g.length:0,v=mt.get(i),y=x.state.lights;if(!0===nt&amp;&amp;(!0===it||t!==R)){const e=t===R&amp;&amp;i.id===A;Et.setState(i,t,e)}let M=!1;i.version===v.__version?v.needsLights&amp;&amp;v.lightsStateVersion!==y.state.version||v.outputColorSpace!==o||r.isBatchedMesh&amp;&amp;!1===v.batching?M=!0:r.isBatchedMesh||!0!==v.batching?r.isInstancedMesh&amp;&amp;!1===v.instancing?M=!0:r.isInstancedMesh||!0!==v.instancing?r.isSkinnedMesh&amp;&amp;!1===v.skinning?M=!0:r.isSkinnedMesh||!0!==v.skinning?r.isInstancedMesh&amp;&amp;!0===v.instancingColor&amp;&amp;null===r.instanceColor||r.isInstancedMesh&amp;&amp;!1===v.instancingColor&amp;&amp;null!==r.instanceColor||v.envMap!==l||!0===i.fog&amp;&amp;v.fog!==s?M=!0:void 0===v.numClippingPlanes||v.numClippingPlanes===Et.numPlanes&amp;&amp;v.numIntersection===Et.numIntersection?(v.vertexAlphas!==c||v.vertexTangents!==h||v.morphTargets!==u||v.morphNormals!==d||v.morphColors!==m||v.toneMapping!==f||!0===ut.isWebGL2&amp;&amp;v.morphTargetsCount!==_)&amp;&amp;(M=!0):M=!0:M=!0:M=!0:M=!0:(M=!0,v.__version=i.version);let b=v.currentProgram;!0===M&amp;&amp;(b=Qt(i,e,r));let T=!1,E=!1,C=!1;const L=b.getUniforms(),P=v.uniforms;dt.useProgram(b.program)&amp;&amp;(T=!0,E=!0,C=!0);i.id!==A&amp;&amp;(A=i.id,E=!0);if(T||R!==t){L.setValue(Dt,&quot;projectionMatrix&quot;,t.projectionMatrix),L.setValue(Dt,&quot;viewMatrix&quot;,t.matrixWorldInverse);const e=L.map.cameraPosition;void 0!==e&amp;&amp;e.setValue(Dt,ot.setFromMatrixPosition(t.matrixWorld)),ut.logarithmicDepthBuffer&amp;&amp;L.setValue(Dt,&quot;logDepthBufFC&quot;,2/(Math.log(t.far+1)/Math.LN2)),(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial)&amp;&amp;L.setValue(Dt,&quot;isOrthographic&quot;,!0===t.isOrthographicCamera),R!==t&amp;&amp;(R=t,E=!0,C=!0)}if(r.isSkinnedMesh){L.setOptional(Dt,r,&quot;bindMatrix&quot;),L.setOptional(Dt,r,&quot;bindMatrixInverse&quot;);const t=r.skeleton;t&amp;&amp;(ut.floatVertexTextures?(null===t.boneTexture&amp;&amp;t.computeBoneTexture(),L.setValue(Dt,&quot;boneTexture&quot;,t.boneTexture,ft)):console.warn(&quot;THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.&quot;))}r.isBatchedMesh&amp;&amp;(L.setOptional(Dt,r,&quot;batchingTexture&quot;),L.setValue(Dt,&quot;batchingTexture&quot;,r._matricesTexture,ft));const I=n.morphAttributes;(void 0!==I.position||void 0!==I.normal||void 0!==I.color&amp;&amp;!0===ut.isWebGL2)&amp;&amp;Rt.update(r,n,b);(E||v.receiveShadow!==r.receiveShadow)&amp;&amp;(v.receiveShadow=r.receiveShadow,L.setValue(Dt,&quot;receiveShadow&quot;,r.receiveShadow));i.isMeshGouraudMaterial&amp;&amp;null!==i.envMap&amp;&amp;(P.envMap.value=l,P.flipEnvMap.value=l.isCubeTexture&amp;&amp;!1===l.isRenderTargetTexture?-1:1);E&amp;&amp;(L.setValue(Dt,&quot;toneMappingExposure&quot;,S.toneMappingExposure),v.needsLights&amp;&amp;(D=C,(U=P).ambientLightColor.needsUpdate=D,U.lightProbe.needsUpdate=D,U.directionalLights.needsUpdate=D,U.directionalLightShadows.needsUpdate=D,U.pointLights.needsUpdate=D,U.pointLightShadows.needsUpdate=D,U.spotLights.needsUpdate=D,U.spotLightShadows.needsUpdate=D,U.rectAreaLights.needsUpdate=D,U.hemisphereLights.needsUpdate=D),s&amp;&amp;!0===i.fog&amp;&amp;St.refreshFogUniforms(P,s),St.refreshMaterialUniforms(P,i,z,N,rt),oa.upload(Dt,te(v),P,ft));var U,D;i.isShaderMaterial&amp;&amp;!0===i.uniformsNeedUpdate&amp;&amp;(oa.upload(Dt,te(v),P,ft),i.uniformsNeedUpdate=!1);i.isSpriteMaterial&amp;&amp;L.setValue(Dt,&quot;center&quot;,r.center);if(L.setValue(Dt,&quot;modelViewMatrix&quot;,r.modelViewMatrix),L.setValue(Dt,&quot;normalMatrix&quot;,r.normalMatrix),L.setValue(Dt,&quot;modelMatrix&quot;,r.matrixWorld),i.isShaderMaterial||i.isRawShaderMaterial){const t=i.uniformsGroups;for(let e=0,n=t.length;e&lt;n;e++)if(ut.isWebGL2){const n=t[e];Ut.update(n,b),Ut.bind(n,b)}else console.warn(&quot;THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.&quot;)}return b}(t,e,n,i,r);dt.setMaterial(i,a);let l=n.index,c=1;if(!0===i.wireframe){if(l=xt.getWireframeAttribute(n),void 0===l)return;c=2}const h=n.drawRange,u=n.attributes.position;let d=h.start*c,m=(h.start+h.count)*c;null!==s&amp;&amp;(d=Math.max(d,s.start*c),m=Math.min(m,(s.start+s.count)*c)),null!==l?(d=Math.max(d,0),m=Math.min(m,l.count)):null!=u&amp;&amp;(d=Math.max(d,0),m=Math.min(m,u.count));const f=m-d;if(f&lt;0||f===1/0)return;let g;It.setup(r,i,o,n,l);let _=Ct;if(null!==l&amp;&amp;(g=vt.get(l),_=Lt,_.setIndex(g)),r.isMesh)!0===i.wireframe?(dt.setLineWidth(i.wireframeLinewidth*ct()),_.setMode(Dt.LINES)):_.setMode(Dt.TRIANGLES);else if(r.isLine){let t=i.linewidth;void 0===t&amp;&amp;(t=1),dt.setLineWidth(t*ct()),r.isLineSegments?_.setMode(Dt.LINES):r.isLineLoop?_.setMode(Dt.LINE_LOOP):_.setMode(Dt.LINE_STRIP)}else r.isPoints?_.setMode(Dt.POINTS):r.isSprite&amp;&amp;_.setMode(Dt.TRIANGLES);if(r.isBatchedMesh)_.renderMultiDraw(r._multiDrawStarts,r._multiDrawCounts,r._multiDrawCount);else if(r.isInstancedMesh)_.renderInstances(d,f,r.count);else if(n.isInstancedBufferGeometry){const t=void 0!==n._maxInstanceCount?n._maxInstanceCount:1/0,e=Math.min(n.instanceCount,t);_.renderInstances(d,f,e)}else _.render(d,f)},this.compile=function(t,e,n=null){null===n&amp;&amp;(n=t),x=Tt.get(n),x.init(),M.push(x),n.traverseVisible((function(t){t.isLight&amp;&amp;t.layers.test(e.layers)&amp;&amp;(x.pushLight(t),t.castShadow&amp;&amp;x.pushShadow(t))})),t!==n&amp;&amp;t.traverseVisible((function(t){t.isLight&amp;&amp;t.layers.test(e.layers)&amp;&amp;(x.pushLight(t),t.castShadow&amp;&amp;x.pushShadow(t))})),x.setupLights(S._useLegacyLights);const i=new Set;return t.traverse((function(t){const e=t.material;if(e)if(Array.isArray(e))for(let r=0;r&lt;e.length;r++){const s=e[r];Wt(s,n,t),i.add(s)}else Wt(e,n,t),i.add(e)})),M.pop(),x=null,i},this.compileAsync=function(t,e,n=null){const i=this.compile(t,e,n);return new Promise((e=&gt;{function n(){i.forEach((function(t){mt.get(t).currentProgram.isReady()&amp;&amp;i.delete(t)})),0!==i.size?setTimeout(n,10):e(t)}null!==ht.get(&quot;KHR_parallel_shader_compile&quot;)?n():setTimeout(n,10)}))};let Xt=null;function jt(){Yt.stop()}function qt(){Yt.start()}const Yt=new _r;function Zt(t,e,n,i){if(!1===t.visible)return;if(t.layers.test(e.layers))if(t.isGroup)n=t.renderOrder;else if(t.isLOD)!0===t.autoUpdate&amp;&amp;t.update(e);else if(t.isLight)x.pushLight(t),t.castShadow&amp;&amp;x.pushShadow(t);else if(t.isSprite){if(!t.frustumCulled||et.intersectsSprite(t)){i&amp;&amp;ot.setFromMatrixPosition(t.matrixWorld).applyMatrix4(st);const e=yt.update(t),r=t.material;r.visible&amp;&amp;v.push(t,e,r,n,ot.z,null)}}else if((t.isMesh||t.isLine||t.isPoints)&amp;&amp;(!t.frustumCulled||et.intersectsObject(t))){const e=yt.update(t),r=t.material;if(i&amp;&amp;(void 0!==t.boundingSphere?(null===t.boundingSphere&amp;&amp;t.computeBoundingSphere(),ot.copy(t.boundingSphere.center)):(null===e.boundingSphere&amp;&amp;e.computeBoundingSphere(),ot.copy(e.boundingSphere.center)),ot.applyMatrix4(t.matrixWorld).applyMatrix4(st)),Array.isArray(r)){const i=e.groups;for(let s=0,a=i.length;s&lt;a;s++){const a=i[s],o=r[a.materialIndex];o&amp;&amp;o.visible&amp;&amp;v.push(t,e,o,n,ot.z,a)}}else r.visible&amp;&amp;v.push(t,e,r,n,ot.z,null)}const r=t.children;for(let t=0,s=r.length;t&lt;s;t++)Zt(r[t],e,n,i)}function Jt(t,e,n,i){const r=t.opaque,s=t.transmissive,o=t.transparent;x.setupLightsView(n),!0===nt&amp;&amp;Et.setGlobalState(S.clippingPlanes,n),s.length&gt;0&amp;&amp;function(t,e,n,i){const r=!0===n.isScene?n.overrideMaterial:null;if(null!==r)return;const s=ut.isWebGL2;null===rt&amp;&amp;(rt=new Ge(1,1,{generateMipmaps:!0,type:ht.has(&quot;EXT_color_buffer_half_float&quot;)?V:F,minFilter:O,samples:s?4:0}));S.getDrawingBufferSize(at),s?rt.setSize(at.x,at.y):rt.setSize(he(at.x),he(at.y));const o=S.getRenderTarget();S.setRenderTarget(rt),S.getClearColor(I),U=S.getClearAlpha(),U&lt;1&amp;&amp;S.setClearColor(16777215,.5);S.clear();const l=S.toneMapping;S.toneMapping=p,Kt(t,n,i),ft.updateMultisampleRenderTarget(rt),ft.updateRenderTargetMipmap(rt);let c=!1;for(let t=0,r=e.length;t&lt;r;t++){const r=e[t],s=r.object,o=r.geometry,l=r.material,h=r.group;if(2===l.side&amp;&amp;s.layers.test(i.layers)){const t=l.side;l.side=a,l.needsUpdate=!0,$t(s,n,i,o,l,h),l.side=t,l.needsUpdate=!0,c=!0}}!0===c&amp;&amp;(ft.updateMultisampleRenderTarget(rt),ft.updateRenderTargetMipmap(rt));S.setRenderTarget(o),S.setClearColor(I,U),S.toneMapping=l}(r,s,e,n),i&amp;&amp;dt.viewport(C.copy(i)),r.length&gt;0&amp;&amp;Kt(r,e,n),s.length&gt;0&amp;&amp;Kt(s,e,n),o.length&gt;0&amp;&amp;Kt(o,e,n),dt.buffers.depth.setTest(!0),dt.buffers.depth.setMask(!0),dt.buffers.color.setMask(!0),dt.setPolygonOffset(!1)}function Kt(t,e,n){const i=!0===e.isScene?e.overrideMaterial:null;for(let r=0,s=t.length;r&lt;s;r++){const s=t[r],a=s.object,o=s.geometry,l=null===i?s.material:i,c=s.group;a.layers.test(n.layers)&amp;&amp;$t(a,e,n,o,l,c)}}function $t(t,e,n,i,r,o){t.onBeforeRender(S,e,n,i,r,o),t.modelViewMatrix.multiplyMatrices(n.matrixWorldInverse,t.matrixWorld),t.normalMatrix.getNormalMatrix(t.modelViewMatrix),r.onBeforeRender(S,e,n,i,t,o),!0===r.transparent&amp;&amp;2===r.side&amp;&amp;!1===r.forceSinglePass?(r.side=a,r.needsUpdate=!0,S.renderBufferDirect(n,e,i,r,t,o),r.side=s,r.needsUpdate=!0,S.renderBufferDirect(n,e,i,r,t,o),r.side=2):S.renderBufferDirect(n,e,i,r,t,o),t.onAfterRender(S,e,n,i,r,o)}function Qt(t,e,n){!0!==e.isScene&amp;&amp;(e=lt);const i=mt.get(t),r=x.state.lights,s=x.state.shadowsArray,a=r.state.version,o=Mt.getParameters(t,r.state,s,e,n),l=Mt.getProgramCacheKey(o);let c=i.programs;i.environment=t.isMeshStandardMaterial?e.environment:null,i.fog=e.fog,i.envMap=(t.isMeshStandardMaterial?_t:gt).get(t.envMap||i.environment),void 0===c&amp;&amp;(t.addEventListener(&quot;dispose&quot;,kt),c=new Map,i.programs=c);let h=c.get(l);if(void 0!==h){if(i.currentProgram===h&amp;&amp;i.lightsStateVersion===a)return ee(t,o),h}else o.uniforms=Mt.getUniforms(t),t.onBuild(n,o,S),t.onBeforeCompile(o,S),h=Mt.acquireProgram(o,l),c.set(l,h),i.uniforms=o.uniforms;const u=i.uniforms;return(t.isShaderMaterial||t.isRawShaderMaterial)&amp;&amp;!0!==t.clipping||(u.clippingPlanes=Et.uniform),ee(t,o),i.needsLights=function(t){return t.isMeshLambertMaterial||t.isMeshToonMaterial||t.isMeshPhongMaterial||t.isMeshStandardMaterial||t.isShadowMaterial||t.isShaderMaterial&amp;&amp;!0===t.lights}(t),i.lightsStateVersion=a,i.needsLights&amp;&amp;(u.ambientLightColor.value=r.state.ambient,u.lightProbe.value=r.state.probe,u.directionalLights.value=r.state.directional,u.directionalLightShadows.value=r.state.directionalShadow,u.spotLights.value=r.state.spot,u.spotLightShadows.value=r.state.spotShadow,u.rectAreaLights.value=r.state.rectArea,u.ltc_1.value=r.state.rectAreaLTC1,u.ltc_2.value=r.state.rectAreaLTC2,u.pointLights.value=r.state.point,u.pointLightShadows.value=r.state.pointShadow,u.hemisphereLights.value=r.state.hemi,u.directionalShadowMap.value=r.state.directionalShadowMap,u.directionalShadowMatrix.value=r.state.directionalShadowMatrix,u.spotShadowMap.value=r.state.spotShadowMap,u.spotLightMatrix.value=r.state.spotLightMatrix,u.spotLightMap.value=r.state.spotLightMap,u.pointShadowMap.value=r.state.pointShadowMap,u.pointShadowMatrix.value=r.state.pointShadowMatrix),i.currentProgram=h,i.uniformsList=null,h}function te(t){if(null===t.uniformsList){const e=t.currentProgram.getUniforms();t.uniformsList=oa.seqWithValue(e.seq,t.uniforms)}return t.uniformsList}function ee(t,e){const n=mt.get(t);n.outputColorSpace=e.outputColorSpace,n.batching=e.batching,n.instancing=e.instancing,n.instancingColor=e.instancingColor,n.skinning=e.skinning,n.morphTargets=e.morphTargets,n.morphNormals=e.morphNormals,n.morphColors=e.morphColors,n.morphTargetsCount=e.morphTargetsCount,n.numClippingPlanes=e.numClippingPlanes,n.numIntersection=e.numClipIntersection,n.vertexAlphas=e.vertexAlphas,n.vertexTangents=e.vertexTangents,n.toneMapping=e.toneMapping}Yt.setAnimationLoop((function(t){Xt&amp;&amp;Xt(t)})),&quot;undefined&quot;!=typeof self&amp;&amp;Yt.setContext(self),this.setAnimationLoop=function(t){Xt=t,Ft.setAnimationLoop(t),null===t?Yt.stop():Yt.start()},Ft.addEventListener(&quot;sessionstart&quot;,jt),Ft.addEventListener(&quot;sessionend&quot;,qt),this.render=function(t,e){if(void 0!==e&amp;&amp;!0!==e.isCamera)return void console.error(&quot;THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.&quot;);if(!0===b)return;!0===t.matrixWorldAutoUpdate&amp;&amp;t.updateMatrixWorld(),null===e.parent&amp;&amp;!0===e.matrixWorldAutoUpdate&amp;&amp;e.updateMatrixWorld(),!0===Ft.enabled&amp;&amp;!0===Ft.isPresenting&amp;&amp;(!0===Ft.cameraAutoUpdate&amp;&amp;Ft.updateCamera(e),e=Ft.getCamera()),!0===t.isScene&amp;&amp;t.onBeforeRender(S,t,e,w),x=Tt.get(t,M.length),x.init(),M.push(x),st.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),et.setFromProjectionMatrix(st),it=this.localClippingEnabled,nt=Et.init(this.clippingPlanes,it),v=bt.get(t,y.length),v.init(),y.push(v),Zt(t,e,0,S.sortObjects),v.finish(),!0===S.sortObjects&amp;&amp;v.sort(q,Y),this.info.render.frame++,!0===nt&amp;&amp;Et.beginShadows();const n=x.state.shadowsArray;if(wt.render(n,t,e),!0===nt&amp;&amp;Et.endShadows(),!0===this.info.autoReset&amp;&amp;this.info.reset(),At.render(v,t),x.setupLights(S._useLegacyLights),e.isArrayCamera){const n=e.cameras;for(let e=0,i=n.length;e&lt;i;e++){const i=n[e];Jt(v,t,i,i.viewport)}}else Jt(v,t,e);null!==w&amp;&amp;(ft.updateMultisampleRenderTarget(w),ft.updateRenderTargetMipmap(w)),!0===t.isScene&amp;&amp;t.onAfterRender(S,t,e),It.resetDefaultState(),A=-1,R=null,M.pop(),x=M.length&gt;0?M[M.length-1]:null,y.pop(),v=y.length&gt;0?y[y.length-1]:null},this.getActiveCubeFace=function(){return T},this.getActiveMipmapLevel=function(){return E},this.getRenderTarget=function(){return w},this.setRenderTargetTextures=function(t,e,n){mt.get(t.texture).__webglTexture=e,mt.get(t.depthTexture).__webglTexture=n;const i=mt.get(t);i.__hasExternalTextures=!0,i.__hasExternalTextures&amp;&amp;(i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===ht.has(&quot;WEBGL_multisampled_render_to_texture&quot;)&amp;&amp;(console.warn(&quot;THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided&quot;),i.__useRenderToTexture=!1))},this.setRenderTargetFramebuffer=function(t,e){const n=mt.get(t);n.__webglFramebuffer=e,n.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,n=0){w=t,T=e,E=n;let i=!0,r=null,s=!1,a=!1;if(t){const o=mt.get(t);void 0!==o.__useDefaultFramebuffer?(dt.bindFramebuffer(Dt.FRAMEBUFFER,null),i=!1):void 0===o.__webglFramebuffer?ft.setupRenderTarget(t):o.__hasExternalTextures&amp;&amp;ft.rebindTextures(t,mt.get(t.texture).__webglTexture,mt.get(t.depthTexture).__webglTexture);const l=t.texture;(l.isData3DTexture||l.isDataArrayTexture||l.isCompressedArrayTexture)&amp;&amp;(a=!0);const c=mt.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=Array.isArray(c[e])?c[e][n]:c[e],s=!0):r=ut.isWebGL2&amp;&amp;t.samples&gt;0&amp;&amp;!1===ft.useMultisampledRTT(t)?mt.get(t).__webglMultisampledFramebuffer:Array.isArray(c)?c[n]:c,C.copy(t.viewport),L.copy(t.scissor),P=t.scissorTest}else C.copy($).multiplyScalar(z).floor(),L.copy(Q).multiplyScalar(z).floor(),P=tt;if(dt.bindFramebuffer(Dt.FRAMEBUFFER,r)&amp;&amp;ut.drawBuffers&amp;&amp;i&amp;&amp;dt.drawBuffers(t,r),dt.viewport(C),dt.scissor(L),dt.setScissorTest(P),s){const i=mt.get(t.texture);Dt.framebufferTexture2D(Dt.FRAMEBUFFER,Dt.COLOR_ATTACHMENT0,Dt.TEXTURE_CUBE_MAP_POSITIVE_X+e,i.__webglTexture,n)}else if(a){const i=mt.get(t.texture),r=e||0;Dt.framebufferTextureLayer(Dt.FRAMEBUFFER,Dt.COLOR_ATTACHMENT0,i.__webglTexture,n||0,r)}A=-1},this.readRenderTargetPixels=function(t,e,n,i,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error(&quot;THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.&quot;);let o=mt.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&amp;&amp;void 0!==a&amp;&amp;(o=o[a]),o){dt.bindFramebuffer(Dt.FRAMEBUFFER,o);try{const a=t.texture,o=a.format,l=a.type;if(o!==j&amp;&amp;Pt.convert(o)!==Dt.getParameter(Dt.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error(&quot;THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.&quot;);const c=l===V&amp;&amp;(ht.has(&quot;EXT_color_buffer_half_float&quot;)||ut.isWebGL2&amp;&amp;ht.has(&quot;EXT_color_buffer_float&quot;));if(!(l===F||Pt.convert(l)===Dt.getParameter(Dt.IMPLEMENTATION_COLOR_READ_TYPE)||l===H&amp;&amp;(ut.isWebGL2||ht.has(&quot;OES_texture_float&quot;)||ht.has(&quot;WEBGL_color_buffer_float&quot;))||c))return void console.error(&quot;THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.&quot;);e&gt;=0&amp;&amp;e&lt;=t.width-i&amp;&amp;n&gt;=0&amp;&amp;n&lt;=t.height-r&amp;&amp;Dt.readPixels(e,n,i,r,Pt.convert(o),Pt.convert(l),s)}finally{const t=null!==w?mt.get(w).__webglFramebuffer:null;dt.bindFramebuffer(Dt.FRAMEBUFFER,t)}}},this.copyFramebufferToTexture=function(t,e,n=0){const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),s=Math.floor(e.image.height*i);ft.setTexture2D(e,0),Dt.copyTexSubImage2D(Dt.TEXTURE_2D,n,0,0,t.x,t.y,r,s),dt.unbindTexture()},this.copyTextureToTexture=function(t,e,n,i=0){const r=e.image.width,s=e.image.height,a=Pt.convert(n.format),o=Pt.convert(n.type);ft.setTexture2D(n,0),Dt.pixelStorei(Dt.UNPACK_FLIP_Y_WEBGL,n.flipY),Dt.pixelStorei(Dt.UNPACK_PREMULTIPLY_ALPHA_WEBGL,n.premultiplyAlpha),Dt.pixelStorei(Dt.UNPACK_ALIGNMENT,n.unpackAlignment),e.isDataTexture?Dt.texSubImage2D(Dt.TEXTURE_2D,i,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?Dt.compressedTexSubImage2D(Dt.TEXTURE_2D,i,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):Dt.texSubImage2D(Dt.TEXTURE_2D,i,t.x,t.y,a,o,e.image),0===i&amp;&amp;n.generateMipmaps&amp;&amp;Dt.generateMipmap(Dt.TEXTURE_2D),dt.unbindTexture()},this.copyTextureToTexture3D=function(t,e,n,i,r=0){if(S.isWebGL1Renderer)return void console.warn(&quot;THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.&quot;);const s=t.max.x-t.min.x+1,a=t.max.y-t.min.y+1,o=t.max.z-t.min.z+1,l=Pt.convert(i.format),c=Pt.convert(i.type);let h;if(i.isData3DTexture)ft.setTexture3D(i,0),h=Dt.TEXTURE_3D;else{if(!i.isDataArrayTexture&amp;&amp;!i.isCompressedArrayTexture)return void console.warn(&quot;THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.&quot;);ft.setTexture2DArray(i,0),h=Dt.TEXTURE_2D_ARRAY}Dt.pixelStorei(Dt.UNPACK_FLIP_Y_WEBGL,i.flipY),Dt.pixelStorei(Dt.UNPACK_PREMULTIPLY_ALPHA_WEBGL,i.premultiplyAlpha),Dt.pixelStorei(Dt.UNPACK_ALIGNMENT,i.unpackAlignment);const u=Dt.getParameter(Dt.UNPACK_ROW_LENGTH),d=Dt.getParameter(Dt.UNPACK_IMAGE_HEIGHT),p=Dt.getParameter(Dt.UNPACK_SKIP_PIXELS),m=Dt.getParameter(Dt.UNPACK_SKIP_ROWS),f=Dt.getParameter(Dt.UNPACK_SKIP_IMAGES),g=n.isCompressedTexture?n.mipmaps[r]:n.image;Dt.pixelStorei(Dt.UNPACK_ROW_LENGTH,g.width),Dt.pixelStorei(Dt.UNPACK_IMAGE_HEIGHT,g.height),Dt.pixelStorei(Dt.UNPACK_SKIP_PIXELS,t.min.x),Dt.pixelStorei(Dt.UNPACK_SKIP_ROWS,t.min.y),Dt.pixelStorei(Dt.UNPACK_SKIP_IMAGES,t.min.z),n.isDataTexture||n.isData3DTexture?Dt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g.data):n.isCompressedArrayTexture?(console.warn(&quot;THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.&quot;),Dt.compressedTexSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,g.data)):Dt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g),Dt.pixelStorei(Dt.UNPACK_ROW_LENGTH,u),Dt.pixelStorei(Dt.UNPACK_IMAGE_HEIGHT,d),Dt.pixelStorei(Dt.UNPACK_SKIP_PIXELS,p),Dt.pixelStorei(Dt.UNPACK_SKIP_ROWS,m),Dt.pixelStorei(Dt.UNPACK_SKIP_IMAGES,f),0===r&amp;&amp;i.generateMipmaps&amp;&amp;Dt.generateMipmap(h),dt.unbindTexture()},this.initTexture=function(t){t.isCubeTexture?ft.setTextureCube(t,0):t.isData3DTexture?ft.setTexture3D(t,0):t.isDataArrayTexture||t.isCompressedArrayTexture?ft.setTexture2DArray(t,0):ft.setTexture2D(t,0),dt.unbindTexture()},this.resetState=function(){T=0,E=0,w=null,dt.reset(),It.reset()},&quot;undefined&quot;!=typeof __THREE_DEVTOOLS__&amp;&amp;__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent(&quot;observe&quot;,{detail:this}))}get coordinateSystem(){return $t}get outputColorSpace(){return this._outputColorSpace}set outputColorSpace(t){this._outputColorSpace=t;const e=this.getContext();e.drawingBufferColorSpace=t===Vt?&quot;display-p3&quot;:&quot;srgb&quot;,e.unpackColorSpace=Re.workingColorSpace===kt?&quot;display-p3&quot;:&quot;srgb&quot;}get outputEncoding(){return console.warn(&quot;THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.&quot;),this.outputColorSpace===Gt?Bt:Ft}set outputEncoding(t){console.warn(&quot;THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.&quot;),this.outputColorSpace=t===Bt?Gt:Ht}get useLegacyLights(){return console.warn(&quot;THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.&quot;),this._useLegacyLights}set useLegacyLights(t){console.warn(&quot;THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.&quot;),this._useLegacyLights=t}}class eo extends to{}eo.prototype.isWebGL1Renderer=!0;class no{constructor(t,e=25e-5){this.isFogExp2=!0,this.name=&quot;&quot;,this.color=new ci(t),this.density=e}clone(){return new no(this.color,this.density)}toJSON(){return{type:&quot;FogExp2&quot;,name:this.name,color:this.color.getHex(),density:this.density}}}class io{constructor(t,e=1,n=1e3){this.isFog=!0,this.name=&quot;&quot;,this.color=new ci(t),this.near=e,this.far=n}clone(){return new io(this.color,this.near,this.far)}toJSON(){return{type:&quot;Fog&quot;,name:this.name,color:this.color.getHex(),near:this.near,far:this.far}}}class ro extends jn{constructor(){super(),this.isScene=!0,this.type=&quot;Scene&quot;,this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.overrideMaterial=null,&quot;undefined&quot;!=typeof __THREE_DEVTOOLS__&amp;&amp;__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent(&quot;observe&quot;,{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&amp;&amp;(this.background=t.background.clone()),null!==t.environment&amp;&amp;(this.environment=t.environment.clone()),null!==t.fog&amp;&amp;(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,null!==t.overrideMaterial&amp;&amp;(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&amp;&amp;(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness&gt;0&amp;&amp;(e.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&amp;&amp;(e.object.backgroundIntensity=this.backgroundIntensity),e}}class so{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=Zt,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.version=0,this.uuid=se()}onUploadCallback(){}set needsUpdate(t){!0===t&amp;&amp;this.version++}get updateRange(){return console.warn(&quot;THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.&quot;),this._updateRange}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,n){t*=this.stride,n*=e.stride;for(let i=0,r=this.stride;i&lt;r;i++)this.array[t+i]=e.array[n+i];return this}set(t,e=0){return this.array.set(t,e),this}clone(t){void 0===t.arrayBuffers&amp;&amp;(t.arrayBuffers={}),void 0===this.array.buffer._uuid&amp;&amp;(this.array.buffer._uuid=se()),void 0===t.arrayBuffers[this.array.buffer._uuid]&amp;&amp;(t.arrayBuffers[this.array.buffer._uuid]=this.array.slice(0).buffer);const e=new this.array.constructor(t.arrayBuffers[this.array.buffer._uuid]),n=new this.constructor(e,this.stride);return n.setUsage(this.usage),n}onUpload(t){return this.onUploadCallback=t,this}toJSON(t){return void 0===t.arrayBuffers&amp;&amp;(t.arrayBuffers={}),void 0===this.array.buffer._uuid&amp;&amp;(this.array.buffer._uuid=se()),void 0===t.arrayBuffers[this.array.buffer._uuid]&amp;&amp;(t.arrayBuffers[this.array.buffer._uuid]=Array.from(new Uint32Array(this.array.buffer))),{uuid:this.uuid,buffer:this.array.buffer._uuid,type:this.array.constructor.name,stride:this.stride}}}const ao=new We;class oo{constructor(t,e,n,i=!1){this.isInterleavedBufferAttribute=!0,this.name=&quot;&quot;,this.data=t,this.itemSize=e,this.offset=n,this.normalized=i}get count(){return this.data.count}get array(){return this.data.array}set needsUpdate(t){this.data.needsUpdate=t}applyMatrix4(t){for(let e=0,n=this.data.count;e&lt;n;e++)ao.fromBufferAttribute(this,e),ao.applyMatrix4(t),this.setXYZ(e,ao.x,ao.y,ao.z);return this}applyNormalMatrix(t){for(let e=0,n=this.count;e&lt;n;e++)ao.fromBufferAttribute(this,e),ao.applyNormalMatrix(t),this.setXYZ(e,ao.x,ao.y,ao.z);return this}transformDirection(t){for(let e=0,n=this.count;e&lt;n;e++)ao.fromBufferAttribute(this,e),ao.transformDirection(t),this.setXYZ(e,ao.x,ao.y,ao.z);return this}setX(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.data.array[t*this.data.stride+this.offset]=e,this}setY(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.data.array[t*this.data.stride+this.offset+1]=e,this}setZ(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.data.array[t*this.data.stride+this.offset+2]=e,this}setW(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.data.array[t*this.data.stride+this.offset+3]=e,this}getX(t){let e=this.data.array[t*this.data.stride+this.offset];return this.normalized&amp;&amp;(e=ue(e,this.array)),e}getY(t){let e=this.data.array[t*this.data.stride+this.offset+1];return this.normalized&amp;&amp;(e=ue(e,this.array)),e}getZ(t){let e=this.data.array[t*this.data.stride+this.offset+2];return this.normalized&amp;&amp;(e=ue(e,this.array)),e}getW(t){let e=this.data.array[t*this.data.stride+this.offset+3];return this.normalized&amp;&amp;(e=ue(e,this.array)),e}setXY(t,e,n){return t=t*this.data.stride+this.offset,this.normalized&amp;&amp;(e=de(e,this.array),n=de(n,this.array)),this.data.array[t+0]=e,this.data.array[t+1]=n,this}setXYZ(t,e,n,i){return t=t*this.data.stride+this.offset,this.normalized&amp;&amp;(e=de(e,this.array),n=de(n,this.array),i=de(i,this.array)),this.data.array[t+0]=e,this.data.array[t+1]=n,this.data.array[t+2]=i,this}setXYZW(t,e,n,i,r){return t=t*this.data.stride+this.offset,this.normalized&amp;&amp;(e=de(e,this.array),n=de(n,this.array),i=de(i,this.array),r=de(r,this.array)),this.data.array[t+0]=e,this.data.array[t+1]=n,this.data.array[t+2]=i,this.data.array[t+3]=r,this}clone(t){if(void 0===t){console.log(&quot;THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.&quot;);const t=[];for(let e=0;e&lt;this.count;e++){const n=e*this.data.stride+this.offset;for(let e=0;e&lt;this.itemSize;e++)t.push(this.data.array[n+e])}return new Mi(new this.array.constructor(t),this.itemSize,this.normalized)}return void 0===t.interleavedBuffers&amp;&amp;(t.interleavedBuffers={}),void 0===t.interleavedBuffers[this.data.uuid]&amp;&amp;(t.interleavedBuffers[this.data.uuid]=this.data.clone(t)),new oo(t.interleavedBuffers[this.data.uuid],this.itemSize,this.offset,this.normalized)}toJSON(t){if(void 0===t){console.log(&quot;THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.&quot;);const t=[];for(let e=0;e&lt;this.count;e++){const n=e*this.data.stride+this.offset;for(let e=0;e&lt;this.itemSize;e++)t.push(this.data.array[n+e])}return{itemSize:this.itemSize,type:this.array.constructor.name,array:t,normalized:this.normalized}}return void 0===t.interleavedBuffers&amp;&amp;(t.interleavedBuffers={}),void 0===t.interleavedBuffers[this.data.uuid]&amp;&amp;(t.interleavedBuffers[this.data.uuid]=this.data.toJSON(t)),{isInterleavedBufferAttribute:!0,itemSize:this.itemSize,data:this.data.uuid,offset:this.offset,normalized:this.normalized}}}class lo extends di{constructor(t){super(),this.isSpriteMaterial=!0,this.type=&quot;SpriteMaterial&quot;,this.color=new ci(16777215),this.map=null,this.alphaMap=null,this.rotation=0,this.sizeAttenuation=!0,this.transparent=!0,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.alphaMap=t.alphaMap,this.rotation=t.rotation,this.sizeAttenuation=t.sizeAttenuation,this.fog=t.fog,this}}let co;const ho=new We,uo=new We,po=new We,mo=new me,fo=new me,go=new Mn,_o=new We,vo=new We,xo=new We,yo=new me,Mo=new me,So=new me;class bo extends jn{constructor(t=new lo){if(super(),this.isSprite=!0,this.type=&quot;Sprite&quot;,void 0===co){co=new Ii;const t=new Float32Array([-.5,-.5,0,0,0,.5,-.5,0,1,0,.5,.5,0,1,1,-.5,.5,0,0,1]),e=new so(t,5);co.setIndex([0,1,2,0,2,3]),co.setAttribute(&quot;position&quot;,new oo(e,3,0,!1)),co.setAttribute(&quot;uv&quot;,new oo(e,2,3,!1))}this.geometry=co,this.material=t,this.center=new me(.5,.5)}raycast(t,e){null===t.camera&amp;&amp;console.error('THREE.Sprite: &quot;Raycaster.camera&quot; needs to be set in order to raycast against sprites.'),uo.setFromMatrixScale(this.matrixWorld),go.copy(t.camera.matrixWorld),this.modelViewMatrix.multiplyMatrices(t.camera.matrixWorldInverse,this.matrixWorld),po.setFromMatrixPosition(this.modelViewMatrix),t.camera.isPerspectiveCamera&amp;&amp;!1===this.material.sizeAttenuation&amp;&amp;uo.multiplyScalar(-po.z);const n=this.material.rotation;let i,r;0!==n&amp;&amp;(r=Math.cos(n),i=Math.sin(n));const s=this.center;To(_o.set(-.5,-.5,0),po,s,uo,i,r),To(vo.set(.5,-.5,0),po,s,uo,i,r),To(xo.set(.5,.5,0),po,s,uo,i,r),yo.set(0,0),Mo.set(1,0),So.set(1,1);let a=t.ray.intersectTriangle(_o,vo,xo,!1,ho);if(null===a&amp;&amp;(To(vo.set(-.5,.5,0),po,s,uo,i,r),Mo.set(0,1),a=t.ray.intersectTriangle(_o,xo,vo,!1,ho),null===a))return;const o=t.ray.origin.distanceTo(ho);o&lt;t.near||o&gt;t.far||e.push({distance:o,point:ho.clone(),uv:ri.getInterpolation(ho,_o,vo,xo,yo,Mo,So,new me),face:null,object:this})}copy(t,e){return super.copy(t,e),void 0!==t.center&amp;&amp;this.center.copy(t.center),this.material=t.material,this}}function To(t,e,n,i,r,s){mo.subVectors(t,n).addScalar(.5).multiply(i),void 0!==r?(fo.x=s*mo.x-r*mo.y,fo.y=r*mo.x+s*mo.y):fo.copy(mo),t.copy(e),t.x+=fo.x,t.y+=fo.y,t.applyMatrix4(go)}const Eo=new We,wo=new We;class Ao extends jn{constructor(){super(),this._currentLevel=0,this.type=&quot;LOD&quot;,Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,n=e.length;t&lt;n;t++){const n=e[t];this.addLevel(n.object.clone(),n.distance,n.hysteresis)}return this.autoUpdate=t.autoUpdate,this}addLevel(t,e=0,n=0){e=Math.abs(e);const i=this.levels;let r;for(r=0;r&lt;i.length&amp;&amp;!(e&lt;i[r].distance);r++);return i.splice(r,0,{distance:e,hysteresis:n,object:t}),this.add(t),this}getCurrentLevel(){return this._currentLevel}getObjectForDistance(t){const e=this.levels;if(e.length&gt;0){let n,i;for(n=1,i=e.length;n&lt;i;n++){let i=e[n].distance;if(e[n].object.visible&amp;&amp;(i-=i*e[n].hysteresis),t&lt;i)break}return e[n-1].object}return null}raycast(t,e){if(this.levels.length&gt;0){Eo.setFromMatrixPosition(this.matrixWorld);const n=t.ray.origin.distanceTo(Eo);this.getObjectForDistance(n).raycast(t,e)}}update(t){const e=this.levels;if(e.length&gt;1){Eo.setFromMatrixPosition(t.matrixWorld),wo.setFromMatrixPosition(this.matrixWorld);const n=Eo.distanceTo(wo)/t.zoom;let i,r;for(e[0].object.visible=!0,i=1,r=e.length;i&lt;r;i++){let t=e[i].distance;if(e[i].object.visible&amp;&amp;(t-=t*e[i].hysteresis),!(n&gt;=t))break;e[i-1].object.visible=!1,e[i].object.visible=!0}for(this._currentLevel=i-1;i&lt;r;i++)e[i].object.visible=!1}}toJSON(t){const e=super.toJSON(t);!1===this.autoUpdate&amp;&amp;(e.object.autoUpdate=!1),e.object.levels=[];const n=this.levels;for(let t=0,i=n.length;t&lt;i;t++){const i=n[t];e.object.levels.push({object:i.object.uuid,distance:i.distance,hysteresis:i.hysteresis})}return e}}const Ro=new We,Co=new Be,Lo=new Be,Po=new We,Io=new Mn,Uo=new We,Do=new dn,No=new Mn,Oo=new yn;class Fo extends Ji{constructor(t,e){super(t,e),this.isSkinnedMesh=!0,this.type=&quot;SkinnedMesh&quot;,this.bindMode=y,this.bindMatrix=new Mn,this.bindMatrixInverse=new Mn,this.boundingBox=null,this.boundingSphere=null}computeBoundingBox(){const t=this.geometry;null===this.boundingBox&amp;&amp;(this.boundingBox=new qe),this.boundingBox.makeEmpty();const e=t.getAttribute(&quot;position&quot;);for(let t=0;t&lt;e.count;t++)this.getVertexPosition(t,Uo),this.boundingBox.expandByPoint(Uo)}computeBoundingSphere(){const t=this.geometry;null===this.boundingSphere&amp;&amp;(this.boundingSphere=new dn),this.boundingSphere.makeEmpty();const e=t.getAttribute(&quot;position&quot;);for(let t=0;t&lt;e.count;t++)this.getVertexPosition(t,Uo),this.boundingSphere.expandByPoint(Uo)}copy(t,e){return super.copy(t,e),this.bindMode=t.bindMode,this.bindMatrix.copy(t.bindMatrix),this.bindMatrixInverse.copy(t.bindMatrixInverse),this.skeleton=t.skeleton,null!==t.boundingBox&amp;&amp;(this.boundingBox=t.boundingBox.clone()),null!==t.boundingSphere&amp;&amp;(this.boundingSphere=t.boundingSphere.clone()),this}raycast(t,e){const n=this.material,i=this.matrixWorld;void 0!==n&amp;&amp;(null===this.boundingSphere&amp;&amp;this.computeBoundingSphere(),Do.copy(this.boundingSphere),Do.applyMatrix4(i),!1!==t.ray.intersectsSphere(Do)&amp;&amp;(No.copy(i).invert(),Oo.copy(t.ray).applyMatrix4(No),null!==this.boundingBox&amp;&amp;!1===Oo.intersectsBox(this.boundingBox)||this._computeIntersections(t,e,Oo)))}getVertexPosition(t,e){return super.getVertexPosition(t,e),this.applyBoneTransform(t,e),e}bind(t,e){this.skeleton=t,void 0===e&amp;&amp;(this.updateMatrixWorld(!0),this.skeleton.calculateInverses(),e=this.matrixWorld),this.bindMatrix.copy(e),this.bindMatrixInverse.copy(e).invert()}pose(){this.skeleton.pose()}normalizeSkinWeights(){const t=new Be,e=this.geometry.attributes.skinWeight;for(let n=0,i=e.count;n&lt;i;n++){t.fromBufferAttribute(e,n);const i=1/t.manhattanLength();i!==1/0?t.multiplyScalar(i):t.set(1,0,0,0),e.setXYZW(n,t.x,t.y,t.z,t.w)}}updateMatrixWorld(t){super.updateMatrixWorld(t),this.bindMode===y?this.bindMatrixInverse.copy(this.matrixWorld).invert():this.bindMode===M?this.bindMatrixInverse.copy(this.bindMatrix).invert():console.warn(&quot;THREE.SkinnedMesh: Unrecognized bindMode: &quot;+this.bindMode)}applyBoneTransform(t,e){const n=this.skeleton,i=this.geometry;Co.fromBufferAttribute(i.attributes.skinIndex,t),Lo.fromBufferAttribute(i.attributes.skinWeight,t),Ro.copy(e).applyMatrix4(this.bindMatrix),e.set(0,0,0);for(let t=0;t&lt;4;t++){const i=Lo.getComponent(t);if(0!==i){const r=Co.getComponent(t);Io.multiplyMatrices(n.bones[r].matrixWorld,n.boneInverses[r]),e.addScaledVector(Po.copy(Ro).applyMatrix4(Io),i)}}return e.applyMatrix4(this.bindMatrixInverse)}boneTransform(t,e){return console.warn(&quot;THREE.SkinnedMesh: .boneTransform() was renamed to .applyBoneTransform() in r151.&quot;),this.applyBoneTransform(t,e)}}class Bo extends jn{constructor(){super(),this.isBone=!0,this.type=&quot;Bone&quot;}}class zo extends Fe{constructor(t=null,e=1,n=1,i,r,s,a,o,l=1003,c=1003,h,u){super(null,s,a,o,l,c,i,r,h,u),this.isDataTexture=!0,this.image={data:t,width:e,height:n},this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}}const Go=new Mn,Ho=new Mn;class Vo{constructor(t=[],e=[]){this.uuid=se(),this.bones=t.slice(0),this.boneInverses=e,this.boneMatrices=null,this.boneTexture=null,this.init()}init(){const t=this.bones,e=this.boneInverses;if(this.boneMatrices=new Float32Array(16*t.length),0===e.length)this.calculateInverses();else if(t.length!==e.length){console.warn(&quot;THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.&quot;),this.boneInverses=[];for(let t=0,e=this.bones.length;t&lt;e;t++)this.boneInverses.push(new Mn)}}calculateInverses(){this.boneInverses.length=0;for(let t=0,e=this.bones.length;t&lt;e;t++){const e=new Mn;this.bones[t]&amp;&amp;e.copy(this.bones[t].matrixWorld).invert(),this.boneInverses.push(e)}}pose(){for(let t=0,e=this.bones.length;t&lt;e;t++){const e=this.bones[t];e&amp;&amp;e.matrixWorld.copy(this.boneInverses[t]).invert()}for(let t=0,e=this.bones.length;t&lt;e;t++){const e=this.bones[t];e&amp;&amp;(e.parent&amp;&amp;e.parent.isBone?(e.matrix.copy(e.parent.matrixWorld).invert(),e.matrix.multiply(e.matrixWorld)):e.matrix.copy(e.matrixWorld),e.matrix.decompose(e.position,e.quaternion,e.scale))}}update(){const t=this.bones,e=this.boneInverses,n=this.boneMatrices,i=this.boneTexture;for(let i=0,r=t.length;i&lt;r;i++){const r=t[i]?t[i].matrixWorld:Ho;Go.multiplyMatrices(r,e[i]),Go.toArray(n,16*i)}null!==i&amp;&amp;(i.needsUpdate=!0)}clone(){return new Vo(this.bones,this.boneInverses)}computeBoneTexture(){let t=Math.sqrt(4*this.bones.length);t=4*Math.ceil(t/4),t=Math.max(t,4);const e=new Float32Array(t*t*4);e.set(this.boneMatrices);const n=new zo(e,t,t,j,H);return n.needsUpdate=!0,this.boneMatrices=e,this.boneTexture=n,this}getBoneByName(t){for(let e=0,n=this.bones.length;e&lt;n;e++){const n=this.bones[e];if(n.name===t)return n}}dispose(){null!==this.boneTexture&amp;&amp;(this.boneTexture.dispose(),this.boneTexture=null)}fromJSON(t,e){this.uuid=t.uuid;for(let n=0,i=t.bones.length;n&lt;i;n++){const i=t.bones[n];let r=e[i];void 0===r&amp;&amp;(console.warn(&quot;THREE.Skeleton: No bone found with UUID:&quot;,i),r=new Bo),this.bones.push(r),this.boneInverses.push((new Mn).fromArray(t.boneInverses[n]))}return this.init(),this}toJSON(){const t={metadata:{version:4.6,type:&quot;Skeleton&quot;,generator:&quot;Skeleton.toJSON&quot;},bones:[],boneInverses:[]};t.uuid=this.uuid;const e=this.bones,n=this.boneInverses;for(let i=0,r=e.length;i&lt;r;i++){const r=e[i];t.bones.push(r.uuid);const s=n[i];t.boneInverses.push(s.toArray())}return t}}class ko extends Mi{constructor(t,e,n,i=1){super(t,e,n),this.isInstancedBufferAttribute=!0,this.meshPerAttribute=i}copy(t){return super.copy(t),this.meshPerAttribute=t.meshPerAttribute,this}toJSON(){const t=super.toJSON();return t.meshPerAttribute=this.meshPerAttribute,t.isInstancedBufferAttribute=!0,t}}const Wo=new Mn,Xo=new Mn,jo=[],qo=new qe,Yo=new Mn,Zo=new Ji,Jo=new dn;class Ko extends Ji{constructor(t,e,n){super(t,e),this.isInstancedMesh=!0,this.instanceMatrix=new ko(new Float32Array(16*n),16),this.instanceColor=null,this.count=n,this.boundingBox=null,this.boundingSphere=null;for(let t=0;t&lt;n;t++)this.setMatrixAt(t,Yo)}computeBoundingBox(){const t=this.geometry,e=this.count;null===this.boundingBox&amp;&amp;(this.boundingBox=new qe),null===t.boundingBox&amp;&amp;t.computeBoundingBox(),this.boundingBox.makeEmpty();for(let n=0;n&lt;e;n++)this.getMatrixAt(n,Wo),qo.copy(t.boundingBox).applyMatrix4(Wo),this.boundingBox.union(qo)}computeBoundingSphere(){const t=this.geometry,e=this.count;null===this.boundingSphere&amp;&amp;(this.boundingSphere=new dn),null===t.boundingSphere&amp;&amp;t.computeBoundingSphere(),this.boundingSphere.makeEmpty();for(let n=0;n&lt;e;n++)this.getMatrixAt(n,Wo),Jo.copy(t.boundingSphere).applyMatrix4(Wo),this.boundingSphere.union(Jo)}copy(t,e){return super.copy(t,e),this.instanceMatrix.copy(t.instanceMatrix),null!==t.instanceColor&amp;&amp;(this.instanceColor=t.instanceColor.clone()),this.count=t.count,null!==t.boundingBox&amp;&amp;(this.boundingBox=t.boundingBox.clone()),null!==t.boundingSphere&amp;&amp;(this.boundingSphere=t.boundingSphere.clone()),this}getColorAt(t,e){e.fromArray(this.instanceColor.array,3*t)}getMatrixAt(t,e){e.fromArray(this.instanceMatrix.array,16*t)}raycast(t,e){const n=this.matrixWorld,i=this.count;if(Zo.geometry=this.geometry,Zo.material=this.material,void 0!==Zo.material&amp;&amp;(null===this.boundingSphere&amp;&amp;this.computeBoundingSphere(),Jo.copy(this.boundingSphere),Jo.applyMatrix4(n),!1!==t.ray.intersectsSphere(Jo)))for(let r=0;r&lt;i;r++){this.getMatrixAt(r,Wo),Xo.multiplyMatrices(n,Wo),Zo.matrixWorld=Xo,Zo.raycast(t,jo);for(let t=0,n=jo.length;t&lt;n;t++){const n=jo[t];n.instanceId=r,n.object=this,e.push(n)}jo.length=0}}setColorAt(t,e){null===this.instanceColor&amp;&amp;(this.instanceColor=new ko(new Float32Array(3*this.instanceMatrix.count),3)),e.toArray(this.instanceColor.array,3*t)}setMatrixAt(t,e){e.toArray(this.instanceMatrix.array,16*t)}updateMorphTargets(){}dispose(){this.dispatchEvent({type:&quot;dispose&quot;})}}function $o(t,e){return t.z-e.z}function Qo(t,e){return e.z-t.z}class tl{constructor(){this.index=0,this.pool=[],this.list=[]}push(t,e){const n=this.pool,i=this.list;this.index&gt;=n.length&amp;&amp;n.push({start:-1,count:-1,z:-1});const r=n[this.index];i.push(r),this.index++,r.start=t.start,r.count=t.count,r.z=e}reset(){this.list.length=0,this.index=0}}const el=&quot;batchId&quot;,nl=new Mn,il=new Mn,rl=new Mn,sl=new Mn,al=new gr,ol=new qe,ll=new dn,cl=new We,hl=new tl,ul=new Ji,dl=[];function pl(t,e,n=0){const i=e.itemSize;if(t.isInterleavedBufferAttribute||t.array.constructor!==e.array.constructor){const r=t.count;for(let s=0;s&lt;r;s++)for(let r=0;r&lt;i;r++)e.setComponent(s+n,r,t.getComponent(s,r))}else e.array.set(t.array,n*i);e.needsUpdate=!0}class ml extends Ji{get maxGeometryCount(){return this._maxGeometryCount}constructor(t,e,n=2*e,i){super(new Ii,i),this.isBatchedMesh=!0,this.perObjectFrustumCulled=!0,this.sortObjects=!0,this.boundingBox=null,this.boundingSphere=null,this.customSort=null,this._drawRanges=[],this._reservedRanges=[],this._visibility=[],this._active=[],this._bounds=[],this._maxGeometryCount=t,this._maxVertexCount=e,this._maxIndexCount=n,this._geometryInitialized=!1,this._geometryCount=0,this._multiDrawCounts=new Int32Array(t),this._multiDrawStarts=new Int32Array(t),this._multiDrawCount=0,this._visibilityChanged=!0,this._matricesTexture=null,this._initMatricesTexture()}_initMatricesTexture(){let t=Math.sqrt(4*this._maxGeometryCount);t=4*Math.ceil(t/4),t=Math.max(t,4);const e=new Float32Array(t*t*4),n=new zo(e,t,t,j,H);this._matricesTexture=n}_initializeGeometry(t){const e=this.geometry,n=this._maxVertexCount,i=this._maxGeometryCount,r=this._maxIndexCount;if(!1===this._geometryInitialized){for(const i in t.attributes){const r=t.getAttribute(i),{array:s,itemSize:a,normalized:o}=r,l=new s.constructor(n*a),c=new r.constructor(l,a,o);c.setUsage(r.usage),e.setAttribute(i,c)}if(null!==t.getIndex()){const t=n&gt;65536?new Uint32Array(r):new Uint16Array(r);e.setIndex(new Mi(t,1))}const s=i&gt;65536?new Uint32Array(n):new Uint16Array(n);e.setAttribute(el,new Mi(s,1)),this._geometryInitialized=!0}}_validateGeometry(t){if(t.getAttribute(el))throw new Error(`BatchedMesh: Geometry cannot use attribute &quot;${el}&quot;`);const e=this.geometry;if(Boolean(t.getIndex())!==Boolean(e.getIndex()))throw new Error('BatchedMesh: All geometries must consistently have &quot;index&quot;.');for(const n in e.attributes){if(n===el)continue;if(!t.hasAttribute(n))throw new Error(`BatchedMesh: Added geometry missing &quot;${n}&quot;. All geometries must have consistent attributes.`);const i=t.getAttribute(n),r=e.getAttribute(n);if(i.itemSize!==r.itemSize||i.normalized!==r.normalized)throw new Error(&quot;BatchedMesh: All attributes must have a consistent itemSize and normalized value.&quot;)}}setCustomSort(t){return this.customSort=t,this}computeBoundingBox(){null===this.boundingBox&amp;&amp;(this.boundingBox=new qe);const t=this._geometryCount,e=this.boundingBox,n=this._active;e.makeEmpty();for(let i=0;i&lt;t;i++)!1!==n[i]&amp;&amp;(this.getMatrixAt(i,nl),this.getBoundingBoxAt(i,ol).applyMatrix4(nl),e.union(ol))}computeBoundingSphere(){null===this.boundingSphere&amp;&amp;(this.boundingSphere=new dn);const t=this._geometryCount,e=this.boundingSphere,n=this._active;e.makeEmpty();for(let i=0;i&lt;t;i++)!1!==n[i]&amp;&amp;(this.getMatrixAt(i,nl),this.getBoundingSphereAt(i,ll).applyMatrix4(nl),e.union(ll))}addGeometry(t,e=-1,n=-1){if(this._initializeGeometry(t),this._validateGeometry(t),this._geometryCount&gt;=this._maxGeometryCount)throw new Error(&quot;BatchedMesh: Maximum geometry count reached.&quot;);const i={vertexStart:-1,vertexCount:-1,indexStart:-1,indexCount:-1};let r=null;const s=this._reservedRanges,a=this._drawRanges,o=this._bounds;0!==this._geometryCount&amp;&amp;(r=s[s.length-1]),i.vertexCount=-1===e?t.getAttribute(&quot;position&quot;).count:e,i.vertexStart=null===r?0:r.vertexStart+r.vertexCount;const l=t.getIndex(),c=null!==l;if(c&amp;&amp;(i.indexCount=-1===n?l.count:n,i.indexStart=null===r?0:r.indexStart+r.indexCount),-1!==i.indexStart&amp;&amp;i.indexStart+i.indexCount&gt;this._maxIndexCount||i.vertexStart+i.vertexCount&gt;this._maxVertexCount)throw new Error(&quot;BatchedMesh: Reserved space request exceeds the maximum buffer size.&quot;);const h=this._visibility,u=this._active,d=this._matricesTexture,p=this._matricesTexture.image.data;h.push(!0),u.push(!0);const m=this._geometryCount;this._geometryCount++,rl.toArray(p,16*m),d.needsUpdate=!0,s.push(i),a.push({start:c?i.indexStart:i.vertexStart,count:-1}),o.push({boxInitialized:!1,box:new qe,sphereInitialized:!1,sphere:new dn});const f=this.geometry.getAttribute(el);for(let t=0;t&lt;i.vertexCount;t++)f.setX(i.vertexStart+t,m);return f.needsUpdate=!0,this.setGeometryAt(m,t),m}setGeometryAt(t,e){if(t&gt;=this._geometryCount)throw new Error(&quot;BatchedMesh: Maximum geometry count reached.&quot;);this._validateGeometry(e);const n=this.geometry,i=null!==n.getIndex(),r=n.getIndex(),s=e.getIndex(),a=this._reservedRanges[t];if(i&amp;&amp;s.count&gt;a.indexCount||e.attributes.position.count&gt;a.vertexCount)throw new Error(&quot;BatchedMesh: Reserved space not large enough for provided geometry.&quot;);const o=a.vertexStart,l=a.vertexCount;for(const t in n.attributes){if(t===el)continue;const i=e.getAttribute(t),r=n.getAttribute(t);pl(i,r,o);const s=i.itemSize;for(let t=i.count,e=l;t&lt;e;t++){const e=o+t;for(let t=0;t&lt;s;t++)r.setComponent(e,t,0)}r.needsUpdate=!0}if(i){const t=a.indexStart;for(let e=0;e&lt;s.count;e++)r.setX(t+e,o+s.getX(e));for(let e=s.count,n=a.indexCount;e&lt;n;e++)r.setX(t+e,o);r.needsUpdate=!0}const c=this._bounds[t];null!==e.boundingBox?(c.box.copy(e.boundingBox),c.boxInitialized=!0):c.boxInitialized=!1,null!==e.boundingSphere?(c.sphere.copy(e.boundingSphere),c.sphereInitialized=!0):c.sphereInitialized=!1;const h=this._drawRanges[t],u=e.getAttribute(&quot;position&quot;);return h.count=i?s.count:u.count,this._visibilityChanged=!0,t}deleteGeometry(t){const e=this._active;return t&gt;=e.length||!1===e[t]||(e[t]=!1,this._visibilityChanged=!0),this}getBoundingBoxAt(t,e){if(!1===this._active[t])return this;const n=this._bounds[t],i=n.box,r=this.geometry;if(!1===n.boxInitialized){i.makeEmpty();const e=r.index,s=r.attributes.position,a=this._drawRanges[t];for(let t=a.start,n=a.start+a.count;t&lt;n;t++){let n=t;e&amp;&amp;(n=e.getX(n)),i.expandByPoint(cl.fromBufferAttribute(s,n))}n.boxInitialized=!0}return e.copy(i),e}getBoundingSphereAt(t,e){if(!1===this._active[t])return this;const n=this._bounds[t],i=n.sphere,r=this.geometry;if(!1===n.sphereInitialized){i.makeEmpty(),this.getBoundingBoxAt(t,ol),ol.getCenter(i.center);const e=r.index,s=r.attributes.position,a=this._drawRanges[t];let o=0;for(let t=a.start,n=a.start+a.count;t&lt;n;t++){let n=t;e&amp;&amp;(n=e.getX(n)),cl.fromBufferAttribute(s,n),o=Math.max(o,i.center.distanceToSquared(cl))}i.radius=Math.sqrt(o),n.sphereInitialized=!0}return e.copy(i),e}setMatrixAt(t,e){const n=this._active,i=this._matricesTexture,r=this._matricesTexture.image.data;return t&gt;=this._geometryCount||!1===n[t]||(e.toArray(r,16*t),i.needsUpdate=!0),this}getMatrixAt(t,e){const n=this._active,i=this._matricesTexture.image.data;return t&gt;=this._geometryCount||!1===n[t]?null:e.fromArray(i,16*t)}setVisibleAt(t,e){const n=this._visibility,i=this._active;return t&gt;=this._geometryCount||!1===i[t]||n[t]===e||(n[t]=e,this._visibilityChanged=!0),this}getVisibleAt(t){const e=this._visibility,n=this._active;return!(t&gt;=this._geometryCount||!1===n[t])&amp;&amp;e[t]}raycast(t,e){const n=this._visibility,i=this._active,r=this._drawRanges,s=this._geometryCount,a=this.matrixWorld,o=this.geometry;ul.material=this.material,ul.geometry.index=o.index,ul.geometry.attributes=o.attributes,null===ul.geometry.boundingBox&amp;&amp;(ul.geometry.boundingBox=new qe),null===ul.geometry.boundingSphere&amp;&amp;(ul.geometry.boundingSphere=new dn);for(let o=0;o&lt;s;o++){if(!n[o]||!i[o])continue;const s=r[o];ul.geometry.setDrawRange(s.start,s.count),this.getMatrixAt(o,ul.matrixWorld).premultiply(a),this.getBoundingBoxAt(o,ul.geometry.boundingBox),this.getBoundingSphereAt(o,ul.geometry.boundingSphere),ul.raycast(t,dl);for(let t=0,n=dl.length;t&lt;n;t++){const n=dl[t];n.object=this,n.batchId=o,e.push(n)}dl.length=0}ul.material=null,ul.geometry.index=null,ul.geometry.attributes={},ul.geometry.setDrawRange(0,1/0)}copy(t){return super.copy(t),this.geometry=t.geometry.clone(),this.perObjectFrustumCulled=t.perObjectFrustumCulled,this.sortObjects=t.sortObjects,this.boundingBox=null!==t.boundingBox?t.boundingBox.clone():null,this.boundingSphere=null!==t.boundingSphere?t.boundingSphere.clone():null,this._drawRanges=t._drawRanges.map((t=&gt;({...t}))),this._reservedRanges=t._reservedRanges.map((t=&gt;({...t}))),this._visibility=t._visibility.slice(),this._active=t._active.slice(),this._bounds=t._bounds.map((t=&gt;({boxInitialized:t.boxInitialized,box:t.box.clone(),sphereInitialized:t.sphereInitialized,sphere:t.sphere.clone()}))),this._maxGeometryCount=t._maxGeometryCount,this._maxVertexCount=t._maxVertexCount,this._maxIndexCount=t._maxIndexCount,this._geometryInitialized=t._geometryInitialized,this._geometryCount=t._geometryCount,this._multiDrawCounts=t._multiDrawCounts.slice(),this._multiDrawStarts=t._multiDrawStarts.slice(),this._matricesTexture=t._matricesTexture.clone(),this._matricesTexture.image.data=this._matricesTexture.image.slice(),this}dispose(){return this.geometry.dispose(),this._matricesTexture.dispose(),this._matricesTexture=null,this}onBeforeRender(t,e,n,i,r){if(!this._visibilityChanged&amp;&amp;!this.perObjectFrustumCulled&amp;&amp;!this.sortObjects)return;const s=i.getIndex(),a=null===s?1:s.array.BYTES_PER_ELEMENT,o=this._visibility,l=this._multiDrawStarts,c=this._multiDrawCounts,h=this._drawRanges,u=this.perObjectFrustumCulled;u&amp;&amp;(sl.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse).multiply(this.matrixWorld),al.setFromProjectionMatrix(sl,t.isWebGPURenderer?Qt:$t));let d=0;if(this.sortObjects){il.copy(this.matrixWorld).invert(),cl.setFromMatrixPosition(n.matrixWorld).applyMatrix4(il);for(let t=0,e=o.length;t&lt;e;t++)if(o[t]){this.getMatrixAt(t,nl),this.getBoundingSphereAt(t,ll).applyMatrix4(nl);let e=!1;if(u&amp;&amp;(e=!al.intersectsSphere(ll)),!e){const e=cl.distanceTo(ll.center);hl.push(h[t],e)}}const t=hl.list,e=this.customSort;null===e?t.sort(r.transparent?Qo:$o):e.call(this,t,n);for(let e=0,n=t.length;e&lt;n;e++){const n=t[e];l[d]=n.start*a,c[d]=n.count,d++}hl.reset()}else for(let t=0,e=o.length;t&lt;e;t++)if(o[t]){let e=!1;if(u&amp;&amp;(this.getMatrixAt(t,nl),this.getBoundingSphereAt(t,ll).applyMatrix4(nl),e=!al.intersectsSphere(ll)),!e){const e=h[t];l[d]=e.start*a,c[d]=e.count,d++}}this._multiDrawCount=d,this._visibilityChanged=!1}onBeforeShadow(t,e,n,i,r,s){this.onBeforeRender(t,null,i,r,s)}}class fl extends di{constructor(t){super(),this.isLineBasicMaterial=!0,this.type=&quot;LineBasicMaterial&quot;,this.color=new ci(16777215),this.map=null,this.linewidth=1,this.linecap=&quot;round&quot;,this.linejoin=&quot;round&quot;,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.linewidth=t.linewidth,this.linecap=t.linecap,this.linejoin=t.linejoin,this.fog=t.fog,this}}const gl=new We,_l=new We,vl=new Mn,xl=new yn,yl=new dn;class Ml extends jn{constructor(t=new Ii,e=new fl){super(),this.isLine=!0,this.type=&quot;Line&quot;,this.geometry=t,this.material=e,this.updateMorphTargets()}copy(t,e){return super.copy(t,e),this.material=Array.isArray(t.material)?t.material.slice():t.material,this.geometry=t.geometry,this}computeLineDistances(){const t=this.geometry;if(null===t.index){const e=t.attributes.position,n=[0];for(let t=1,i=e.count;t&lt;i;t++)gl.fromBufferAttribute(e,t-1),_l.fromBufferAttribute(e,t),n[t]=n[t-1],n[t]+=gl.distanceTo(_l);t.setAttribute(&quot;lineDistance&quot;,new Ti(n,1))}else console.warn(&quot;THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.&quot;);return this}raycast(t,e){const n=this.geometry,i=this.matrixWorld,r=t.params.Line.threshold,s=n.drawRange;if(null===n.boundingSphere&amp;&amp;n.computeBoundingSphere(),yl.copy(n.boundingSphere),yl.applyMatrix4(i),yl.radius+=r,!1===t.ray.intersectsSphere(yl))return;vl.copy(i).invert(),xl.copy(t.ray).applyMatrix4(vl);const a=r/((this.scale.x+this.scale.y+this.scale.z)/3),o=a*a,l=new We,c=new We,h=new We,u=new We,d=this.isLineSegments?2:1,p=n.index,m=n.attributes.position;if(null!==p){for(let n=Math.max(0,s.start),i=Math.min(p.count,s.start+s.count)-1;n&lt;i;n+=d){const i=p.getX(n),r=p.getX(n+1);l.fromBufferAttribute(m,i),c.fromBufferAttribute(m,r);if(xl.distanceSqToSegment(l,c,u,h)&gt;o)continue;u.applyMatrix4(this.matrixWorld);const s=t.ray.origin.distanceTo(u);s&lt;t.near||s&gt;t.far||e.push({distance:s,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}else{for(let n=Math.max(0,s.start),i=Math.min(m.count,s.start+s.count)-1;n&lt;i;n+=d){l.fromBufferAttribute(m,n),c.fromBufferAttribute(m,n+1);if(xl.distanceSqToSegment(l,c,u,h)&gt;o)continue;u.applyMatrix4(this.matrixWorld);const i=t.ray.origin.distanceTo(u);i&lt;t.near||i&gt;t.far||e.push({distance:i,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}}updateMorphTargets(){const t=this.geometry.morphAttributes,e=Object.keys(t);if(e.length&gt;0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t&lt;e;t++){const e=n[t].name||String(t);this.morphTargetInfluences.push(0),this.morphTargetDictionary[e]=t}}}}}const Sl=new We,bl=new We;class Tl extends Ml{constructor(t,e){super(t,e),this.isLineSegments=!0,this.type=&quot;LineSegments&quot;}computeLineDistances(){const t=this.geometry;if(null===t.index){const e=t.attributes.position,n=[];for(let t=0,i=e.count;t&lt;i;t+=2)Sl.fromBufferAttribute(e,t),bl.fromBufferAttribute(e,t+1),n[t]=0===t?0:n[t-1],n[t+1]=n[t]+Sl.distanceTo(bl);t.setAttribute(&quot;lineDistance&quot;,new Ti(n,1))}else console.warn(&quot;THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.&quot;);return this}}class El extends Ml{constructor(t,e){super(t,e),this.isLineLoop=!0,this.type=&quot;LineLoop&quot;}}class wl extends di{constructor(t){super(),this.isPointsMaterial=!0,this.type=&quot;PointsMaterial&quot;,this.color=new ci(16777215),this.map=null,this.alphaMap=null,this.size=1,this.sizeAttenuation=!0,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.alphaMap=t.alphaMap,this.size=t.size,this.sizeAttenuation=t.sizeAttenuation,this.fog=t.fog,this}}const Al=new Mn,Rl=new yn,Cl=new dn,Ll=new We;class Pl extends jn{constructor(t=new Ii,e=new wl){super(),this.isPoints=!0,this.type=&quot;Points&quot;,this.geometry=t,this.material=e,this.updateMorphTargets()}copy(t,e){return super.copy(t,e),this.material=Array.isArray(t.material)?t.material.slice():t.material,this.geometry=t.geometry,this}raycast(t,e){const n=this.geometry,i=this.matrixWorld,r=t.params.Points.threshold,s=n.drawRange;if(null===n.boundingSphere&amp;&amp;n.computeBoundingSphere(),Cl.copy(n.boundingSphere),Cl.applyMatrix4(i),Cl.radius+=r,!1===t.ray.intersectsSphere(Cl))return;Al.copy(i).invert(),Rl.copy(t.ray).applyMatrix4(Al);const a=r/((this.scale.x+this.scale.y+this.scale.z)/3),o=a*a,l=n.index,c=n.attributes.position;if(null!==l){for(let n=Math.max(0,s.start),r=Math.min(l.count,s.start+s.count);n&lt;r;n++){const r=l.getX(n);Ll.fromBufferAttribute(c,r),Il(Ll,r,o,i,t,e,this)}}else{for(let n=Math.max(0,s.start),r=Math.min(c.count,s.start+s.count);n&lt;r;n++)Ll.fromBufferAttribute(c,n),Il(Ll,n,o,i,t,e,this)}}updateMorphTargets(){const t=this.geometry.morphAttributes,e=Object.keys(t);if(e.length&gt;0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t&lt;e;t++){const e=n[t].name||String(t);this.morphTargetInfluences.push(0),this.morphTargetDictionary[e]=t}}}}}function Il(t,e,n,i,r,s,a){const o=Rl.distanceSqToPoint(t);if(o&lt;n){const n=new We;Rl.closestPointToPoint(t,n),n.applyMatrix4(i);const l=r.ray.origin.distanceTo(n);if(l&lt;r.near||l&gt;r.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:e,face:null,object:a})}}class Ul extends Fe{constructor(t,e,n,i,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,i,r,h,u),this.isCompressedTexture=!0,this.image={width:e,height:n},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class Dl{constructor(){this.type=&quot;Curve&quot;,this.arcLengthDivisions=200}getPoint(){return console.warn(&quot;THREE.Curve: .getPoint() not implemented.&quot;),null}getPointAt(t,e){const n=this.getUtoTmapping(t);return this.getPoint(n,e)}getPoints(t=5){const e=[];for(let n=0;n&lt;=t;n++)e.push(this.getPoint(n/t));return e}getSpacedPoints(t=5){const e=[];for(let n=0;n&lt;=t;n++)e.push(this.getPointAt(n/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&amp;&amp;this.cacheArcLengths.length===t+1&amp;&amp;!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let n,i=this.getPoint(0),r=0;e.push(0);for(let s=1;s&lt;=t;s++)n=this.getPoint(s/t),r+=n.distanceTo(i),e.push(r),i=n;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const n=this.getLengths();let i=0;const r=n.length;let s;s=e||t*n[r-1];let a,o=0,l=r-1;for(;o&lt;=l;)if(i=Math.floor(o+(l-o)/2),a=n[i]-s,a&lt;0)o=i+1;else{if(!(a&gt;0)){l=i;break}l=i-1}if(i=l,n[i]===s)return i/(r-1);const c=n[i];return(i+(s-c)/(n[i+1]-c))/(r-1)}getTangent(t,e){const n=1e-4;let i=t-n,r=t+n;i&lt;0&amp;&amp;(i=0),r&gt;1&amp;&amp;(r=1);const s=this.getPoint(i),a=this.getPoint(r),o=e||(s.isVector2?new me:new We);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const n=this.getUtoTmapping(t);return this.getTangent(n,e)}computeFrenetFrames(t,e){const n=new We,i=[],r=[],s=[],a=new We,o=new Mn;for(let e=0;e&lt;=t;e++){const n=e/t;i[e]=this.getTangentAt(n,new We)}r[0]=new We,s[0]=new We;let l=Number.MAX_VALUE;const c=Math.abs(i[0].x),h=Math.abs(i[0].y),u=Math.abs(i[0].z);c&lt;=l&amp;&amp;(l=c,n.set(1,0,0)),h&lt;=l&amp;&amp;(l=h,n.set(0,1,0)),u&lt;=l&amp;&amp;n.set(0,0,1),a.crossVectors(i[0],n).normalize(),r[0].crossVectors(i[0],a),s[0].crossVectors(i[0],r[0]);for(let e=1;e&lt;=t;e++){if(r[e]=r[e-1].clone(),s[e]=s[e-1].clone(),a.crossVectors(i[e-1],i[e]),a.length()&gt;Number.EPSILON){a.normalize();const t=Math.acos(ae(i[e-1].dot(i[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(i[e],r[e])}if(!0===e){let e=Math.acos(ae(r[0].dot(r[t]),-1,1));e/=t,i[0].dot(a.crossVectors(r[0],r[t]))&gt;0&amp;&amp;(e=-e);for(let n=1;n&lt;=t;n++)r[n].applyMatrix4(o.makeRotationAxis(i[n],e*n)),s[n].crossVectors(i[n],r[n])}return{tangents:i,normals:r,binormals:s}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.6,type:&quot;Curve&quot;,generator:&quot;Curve.toJSON&quot;}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class Nl extends Dl{constructor(t=0,e=0,n=1,i=1,r=0,s=2*Math.PI,a=!1,o=0){super(),this.isEllipseCurve=!0,this.type=&quot;EllipseCurve&quot;,this.aX=t,this.aY=e,this.xRadius=n,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e){const n=e||new me,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)&lt;Number.EPSILON;for(;r&lt;0;)r+=i;for(;r&gt;i;)r-=i;r&lt;Number.EPSILON&amp;&amp;(r=s?0:i),!0!==this.aClockwise||s||(r===i?r=-i:r-=i);const a=this.aStartAngle+t*r;let o=this.aX+this.xRadius*Math.cos(a),l=this.aY+this.yRadius*Math.sin(a);if(0!==this.aRotation){const t=Math.cos(this.aRotation),e=Math.sin(this.aRotation),n=o-this.aX,i=l-this.aY;o=n*t-i*e+this.aX,l=n*e+i*t+this.aY}return n.set(o,l)}copy(t){return super.copy(t),this.aX=t.aX,this.aY=t.aY,this.xRadius=t.xRadius,this.yRadius=t.yRadius,this.aStartAngle=t.aStartAngle,this.aEndAngle=t.aEndAngle,this.aClockwise=t.aClockwise,this.aRotation=t.aRotation,this}toJSON(){const t=super.toJSON();return t.aX=this.aX,t.aY=this.aY,t.xRadius=this.xRadius,t.yRadius=this.yRadius,t.aStartAngle=this.aStartAngle,t.aEndAngle=this.aEndAngle,t.aClockwise=this.aClockwise,t.aRotation=this.aRotation,t}fromJSON(t){return super.fromJSON(t),this.aX=t.aX,this.aY=t.aY,this.xRadius=t.xRadius,this.yRadius=t.yRadius,this.aStartAngle=t.aStartAngle,this.aEndAngle=t.aEndAngle,this.aClockwise=t.aClockwise,this.aRotation=t.aRotation,this}}class Ol extends Nl{constructor(t,e,n,i,r,s){super(t,e,n,n,i,r,s),this.isArcCurve=!0,this.type=&quot;ArcCurve&quot;}}function Fl(){let t=0,e=0,n=0,i=0;function r(r,s,a,o){t=r,e=a,n=-3*r+3*s-2*a-o,i=2*r-2*s+a+o}return{initCatmullRom:function(t,e,n,i,s){r(e,n,s*(n-t),s*(i-e))},initNonuniformCatmullRom:function(t,e,n,i,s,a,o){let l=(e-t)/s-(n-t)/(s+a)+(n-e)/a,c=(n-e)/a-(i-e)/(a+o)+(i-n)/o;l*=a,c*=a,r(e,n,l,c)},calc:function(r){const s=r*r;return t+e*r+n*s+i*(s*r)}}}const Bl=new We,zl=new Fl,Gl=new Fl,Hl=new Fl;class Vl extends Dl{constructor(t=[],e=!1,n=&quot;centripetal&quot;,i=.5){super(),this.isCatmullRomCurve3=!0,this.type=&quot;CatmullRomCurve3&quot;,this.points=t,this.closed=e,this.curveType=n,this.tension=i}getPoint(t,e=new We){const n=e,i=this.points,r=i.length,s=(r-(this.closed?0:1))*t;let a,o,l=Math.floor(s),c=s-l;this.closed?l+=l&gt;0?0:(Math.floor(Math.abs(l)/r)+1)*r:0===c&amp;&amp;l===r-1&amp;&amp;(l=r-2,c=1),this.closed||l&gt;0?a=i[(l-1)%r]:(Bl.subVectors(i[0],i[1]).add(i[0]),a=Bl);const h=i[l%r],u=i[(l+1)%r];if(this.closed||l+2&lt;r?o=i[(l+2)%r]:(Bl.subVectors(i[r-1],i[r-2]).add(i[r-1]),o=Bl),&quot;centripetal&quot;===this.curveType||&quot;chordal&quot;===this.curveType){const t=&quot;chordal&quot;===this.curveType?.5:.25;let e=Math.pow(a.distanceToSquared(h),t),n=Math.pow(h.distanceToSquared(u),t),i=Math.pow(u.distanceToSquared(o),t);n&lt;1e-4&amp;&amp;(n=1),e&lt;1e-4&amp;&amp;(e=n),i&lt;1e-4&amp;&amp;(i=n),zl.initNonuniformCatmullRom(a.x,h.x,u.x,o.x,e,n,i),Gl.initNonuniformCatmullRom(a.y,h.y,u.y,o.y,e,n,i),Hl.initNonuniformCatmullRom(a.z,h.z,u.z,o.z,e,n,i)}else&quot;catmullrom&quot;===this.curveType&amp;&amp;(zl.initCatmullRom(a.x,h.x,u.x,o.x,this.tension),Gl.initCatmullRom(a.y,h.y,u.y,o.y,this.tension),Hl.initCatmullRom(a.z,h.z,u.z,o.z,this.tension));return n.set(zl.calc(c),Gl.calc(c),Hl.calc(c)),n}copy(t){super.copy(t),this.points=[];for(let e=0,n=t.points.length;e&lt;n;e++){const n=t.points[e];this.points.push(n.clone())}return this.closed=t.closed,this.curveType=t.curveType,this.tension=t.tension,this}toJSON(){const t=super.toJSON();t.points=[];for(let e=0,n=this.points.length;e&lt;n;e++){const n=this.points[e];t.points.push(n.toArray())}return t.closed=this.closed,t.curveType=this.curveType,t.tension=this.tension,t}fromJSON(t){super.fromJSON(t),this.points=[];for(let e=0,n=t.points.length;e&lt;n;e++){const n=t.points[e];this.points.push((new We).fromArray(n))}return this.closed=t.closed,this.curveType=t.curveType,this.tension=t.tension,this}}function kl(t,e,n,i,r){const s=.5*(i-e),a=.5*(r-n),o=t*t;return(2*n-2*i+s+a)*(t*o)+(-3*n+3*i-2*s-a)*o+s*t+n}function Wl(t,e,n,i){return function(t,e){const n=1-t;return n*n*e}(t,e)+function(t,e){return 2*(1-t)*t*e}(t,n)+function(t,e){return t*t*e}(t,i)}function Xl(t,e,n,i,r){return function(t,e){const n=1-t;return n*n*n*e}(t,e)+function(t,e){const n=1-t;return 3*n*n*t*e}(t,n)+function(t,e){return 3*(1-t)*t*t*e}(t,i)+function(t,e){return t*t*t*e}(t,r)}class jl extends Dl{constructor(t=new me,e=new me,n=new me,i=new me){super(),this.isCubicBezierCurve=!0,this.type=&quot;CubicBezierCurve&quot;,this.v0=t,this.v1=e,this.v2=n,this.v3=i}getPoint(t,e=new me){const n=e,i=this.v0,r=this.v1,s=this.v2,a=this.v3;return n.set(Xl(t,i.x,r.x,s.x,a.x),Xl(t,i.y,r.y,s.y,a.y)),n}copy(t){return super.copy(t),this.v0.copy(t.v0),this.v1.copy(t.v1),this.v2.copy(t.v2),this.v3.copy(t.v3),this}toJSON(){const t=super.toJSON();return t.v0=this.v0.toArray(),t.v1=this.v1.toArray(),t.v2=this.v2.toArray(),t.v3=this.v3.toArray(),t}fromJSON(t){return super.fromJSON(t),this.v0.fromArray(t.v0),this.v1.fromArray(t.v1),this.v2.fromArray(t.v2),this.v3.fromArray(t.v3),this}}class ql extends Dl{constructor(t=new We,e=new We,n=new We,i=new We){super(),this.isCubicBezierCurve3=!0,this.type=&quot;CubicBezierCurve3&quot;,this.v0=t,this.v1=e,this.v2=n,this.v3=i}getPoint(t,e=new We){const n=e,i=this.v0,r=this.v1,s=this.v2,a=this.v3;return n.set(Xl(t,i.x,r.x,s.x,a.x),Xl(t,i.y,r.y,s.y,a.y),Xl(t,i.z,r.z,s.z,a.z)),n}copy(t){return super.copy(t),this.v0.copy(t.v0),this.v1.copy(t.v1),this.v2.copy(t.v2),this.v3.copy(t.v3),this}toJSON(){const t=super.toJSON();return t.v0=this.v0.toArray(),t.v1=this.v1.toArray(),t.v2=this.v2.toArray(),t.v3=this.v3.toArray(),t}fromJSON(t){return super.fromJSON(t),this.v0.fromArray(t.v0),this.v1.fromArray(t.v1),this.v2.fromArray(t.v2),this.v3.fromArray(t.v3),this}}class Yl extends Dl{constructor(t=new me,e=new me){super(),this.isLineCurve=!0,this.type=&quot;LineCurve&quot;,this.v1=t,this.v2=e}getPoint(t,e=new me){const n=e;return 1===t?n.copy(this.v2):(n.copy(this.v2).sub(this.v1),n.multiplyScalar(t).add(this.v1)),n}getPointAt(t,e){return this.getPoint(t,e)}getTangent(t,e=new me){return e.subVectors(this.v2,this.v1).normalize()}getTangentAt(t,e){return this.getTangent(t,e)}copy(t){return super.copy(t),this.v1.copy(t.v1),this.v2.copy(t.v2),this}toJSON(){const t=super.toJSON();return t.v1=this.v1.toArray(),t.v2=this.v2.toArray(),t}fromJSON(t){return super.fromJSON(t),this.v1.fromArray(t.v1),this.v2.fromArray(t.v2),this}}class Zl extends Dl{constructor(t=new We,e=new We){super(),this.isLineCurve3=!0,this.type=&quot;LineCurve3&quot;,this.v1=t,this.v2=e}getPoint(t,e=new We){const n=e;return 1===t?n.copy(this.v2):(n.copy(this.v2).sub(this.v1),n.multiplyScalar(t).add(this.v1)),n}getPointAt(t,e){return this.getPoint(t,e)}getTangent(t,e=new We){return e.subVectors(this.v2,this.v1).normalize()}getTangentAt(t,e){return this.getTangent(t,e)}copy(t){return super.copy(t),this.v1.copy(t.v1),this.v2.copy(t.v2),this}toJSON(){const t=super.toJSON();return t.v1=this.v1.toArray(),t.v2=this.v2.toArray(),t}fromJSON(t){return super.fromJSON(t),this.v1.fromArray(t.v1),this.v2.fromArray(t.v2),this}}class Jl extends Dl{constructor(t=new me,e=new me,n=new me){super(),this.isQuadraticBezierCurve=!0,this.type=&quot;QuadraticBezierCurve&quot;,this.v0=t,this.v1=e,this.v2=n}getPoint(t,e=new me){const n=e,i=this.v0,r=this.v1,s=this.v2;return n.set(Wl(t,i.x,r.x,s.x),Wl(t,i.y,r.y,s.y)),n}copy(t){return super.copy(t),this.v0.copy(t.v0),this.v1.copy(t.v1),this.v2.copy(t.v2),this}toJSON(){const t=super.toJSON();return t.v0=this.v0.toArray(),t.v1=this.v1.toArray(),t.v2=this.v2.toArray(),t}fromJSON(t){return super.fromJSON(t),this.v0.fromArray(t.v0),this.v1.fromArray(t.v1),this.v2.fromArray(t.v2),this}}class Kl extends Dl{constructor(t=new We,e=new We,n=new We){super(),this.isQuadraticBezierCurve3=!0,this.type=&quot;QuadraticBezierCurve3&quot;,this.v0=t,this.v1=e,this.v2=n}getPoint(t,e=new We){const n=e,i=this.v0,r=this.v1,s=this.v2;return n.set(Wl(t,i.x,r.x,s.x),Wl(t,i.y,r.y,s.y),Wl(t,i.z,r.z,s.z)),n}copy(t){return super.copy(t),this.v0.copy(t.v0),this.v1.copy(t.v1),this.v2.copy(t.v2),this}toJSON(){const t=super.toJSON();return t.v0=this.v0.toArray(),t.v1=this.v1.toArray(),t.v2=this.v2.toArray(),t}fromJSON(t){return super.fromJSON(t),this.v0.fromArray(t.v0),this.v1.fromArray(t.v1),this.v2.fromArray(t.v2),this}}class $l extends Dl{constructor(t=[]){super(),this.isSplineCurve=!0,this.type=&quot;SplineCurve&quot;,this.points=t}getPoint(t,e=new me){const n=e,i=this.points,r=(i.length-1)*t,s=Math.floor(r),a=r-s,o=i[0===s?s:s-1],l=i[s],c=i[s&gt;i.length-2?i.length-1:s+1],h=i[s&gt;i.length-3?i.length-1:s+2];return n.set(kl(a,o.x,l.x,c.x,h.x),kl(a,o.y,l.y,c.y,h.y)),n}copy(t){super.copy(t),this.points=[];for(let e=0,n=t.points.length;e&lt;n;e++){const n=t.points[e];this.points.push(n.clone())}return this}toJSON(){const t=super.toJSON();t.points=[];for(let e=0,n=this.points.length;e&lt;n;e++){const n=this.points[e];t.points.push(n.toArray())}return t}fromJSON(t){super.fromJSON(t),this.points=[];for(let e=0,n=t.points.length;e&lt;n;e++){const n=t.points[e];this.points.push((new me).fromArray(n))}return this}}var Ql=Object.freeze({__proto__:null,ArcCurve:Ol,CatmullRomCurve3:Vl,CubicBezierCurve:jl,CubicBezierCurve3:ql,EllipseCurve:Nl,LineCurve:Yl,LineCurve3:Zl,QuadraticBezierCurve:Jl,QuadraticBezierCurve3:Kl,SplineCurve:$l});class tc extends Dl{constructor(){super(),this.type=&quot;CurvePath&quot;,this.curves=[],this.autoClose=!1}add(t){this.curves.push(t)}closePath(){const t=this.curves[0].getPoint(0),e=this.curves[this.curves.length-1].getPoint(1);if(!t.equals(e)){const n=!0===t.isVector2?&quot;LineCurve&quot;:&quot;LineCurve3&quot;;this.curves.push(new Ql[n](e,t))}return this}getPoint(t,e){const n=t*this.getLength(),i=this.getCurveLengths();let r=0;for(;r&lt;i.length;){if(i[r]&gt;=n){const t=i[r]-n,s=this.curves[r],a=s.getLength(),o=0===a?0:1-t/a;return s.getPointAt(o,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&amp;&amp;this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let n=0,i=this.curves.length;n&lt;i;n++)e+=this.curves[n].getLength(),t.push(e);return this.cacheLengths=t,t}getSpacedPoints(t=40){const e=[];for(let n=0;n&lt;=t;n++)e.push(this.getPoint(n/t));return this.autoClose&amp;&amp;e.push(e[0]),e}getPoints(t=12){const e=[];let n;for(let i=0,r=this.curves;i&lt;r.length;i++){const s=r[i],a=s.isEllipseCurve?2*t:s.isLineCurve||s.isLineCurve3?1:s.isSplineCurve?t*s.points.length:t,o=s.getPoints(a);for(let t=0;t&lt;o.length;t++){const i=o[t];n&amp;&amp;n.equals(i)||(e.push(i),n=i)}}return this.autoClose&amp;&amp;e.length&gt;1&amp;&amp;!e[e.length-1].equals(e[0])&amp;&amp;e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,n=t.curves.length;e&lt;n;e++){const n=t.curves[e];this.curves.push(n.clone())}return this.autoClose=t.autoClose,this}toJSON(){const t=super.toJSON();t.autoClose=this.autoClose,t.curves=[];for(let e=0,n=this.curves.length;e&lt;n;e++){const n=this.curves[e];t.curves.push(n.toJSON())}return t}fromJSON(t){super.fromJSON(t),this.autoClose=t.autoClose,this.curves=[];for(let e=0,n=t.curves.length;e&lt;n;e++){const n=t.curves[e];this.curves.push((new Ql[n.type]).fromJSON(n))}return this}}class ec extends tc{constructor(t){super(),this.type=&quot;Path&quot;,this.currentPoint=new me,t&amp;&amp;this.setFromPoints(t)}setFromPoints(t){this.moveTo(t[0].x,t[0].y);for(let e=1,n=t.length;e&lt;n;e++)this.lineTo(t[e].x,t[e].y);return this}moveTo(t,e){return this.currentPoint.set(t,e),this}lineTo(t,e){const n=new Yl(this.currentPoint.clone(),new me(t,e));return this.curves.push(n),this.currentPoint.set(t,e),this}quadraticCurveTo(t,e,n,i){const r=new Jl(this.currentPoint.clone(),new me(t,e),new me(n,i));return this.curves.push(r),this.currentPoint.set(n,i),this}bezierCurveTo(t,e,n,i,r,s){const a=new jl(this.currentPoint.clone(),new me(t,e),new me(n,i),new me(r,s));return this.curves.push(a),this.currentPoint.set(r,s),this}splineThru(t){const e=[this.currentPoint.clone()].concat(t),n=new $l(e);return this.curves.push(n),this.currentPoint.copy(t[t.length-1]),this}arc(t,e,n,i,r,s){const a=this.currentPoint.x,o=this.currentPoint.y;return this.absarc(t+a,e+o,n,i,r,s),this}absarc(t,e,n,i,r,s){return this.absellipse(t,e,n,n,i,r,s),this}ellipse(t,e,n,i,r,s,a,o){const l=this.currentPoint.x,c=this.currentPoint.y;return this.absellipse(t+l,e+c,n,i,r,s,a,o),this}absellipse(t,e,n,i,r,s,a,o){const l=new Nl(t,e,n,i,r,s,a,o);if(this.curves.length&gt;0){const t=l.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(l);const c=l.getPoint(1);return this.currentPoint.copy(c),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class nc extends Ii{constructor(t=[new me(0,-.5),new me(.5,0),new me(0,.5)],e=12,n=0,i=2*Math.PI){super(),this.type=&quot;LatheGeometry&quot;,this.parameters={points:t,segments:e,phiStart:n,phiLength:i},e=Math.floor(e),i=ae(i,0,2*Math.PI);const r=[],s=[],a=[],o=[],l=[],c=1/e,h=new We,u=new me,d=new We,p=new We,m=new We;let f=0,g=0;for(let e=0;e&lt;=t.length-1;e++)switch(e){case 0:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,m.copy(d),d.normalize(),o.push(d.x,d.y,d.z);break;case t.length-1:o.push(m.x,m.y,m.z);break;default:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),o.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r&lt;=e;r++){const d=n+r*c*i,p=Math.sin(d),m=Math.cos(d);for(let n=0;n&lt;=t.length-1;n++){h.x=t[n].x*p,h.y=t[n].y,h.z=t[n].x*m,s.push(h.x,h.y,h.z),u.x=r/e,u.y=n/(t.length-1),a.push(u.x,u.y);const i=o[3*n+0]*p,c=o[3*n+1],d=o[3*n+0]*m;l.push(i,c,d)}}for(let n=0;n&lt;e;n++)for(let e=0;e&lt;t.length-1;e++){const i=e+n*t.length,s=i,a=i+t.length,o=i+t.length+1,l=i+1;r.push(s,a,l),r.push(o,l,a)}this.setIndex(r),this.setAttribute(&quot;position&quot;,new Ti(s,3)),this.setAttribute(&quot;uv&quot;,new Ti(a,2)),this.setAttribute(&quot;normal&quot;,new Ti(l,3))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new nc(t.points,t.segments,t.phiStart,t.phiLength)}}class ic extends nc{constructor(t=1,e=1,n=4,i=8){const r=new ec;r.absarc(0,-e/2,t,1.5*Math.PI,0),r.absarc(0,e/2,t,0,.5*Math.PI),super(r.getPoints(n),i),this.type=&quot;CapsuleGeometry&quot;,this.parameters={radius:t,length:e,capSegments:n,radialSegments:i}}static fromJSON(t){return new ic(t.radius,t.length,t.capSegments,t.radialSegments)}}class rc extends Ii{constructor(t=1,e=32,n=0,i=2*Math.PI){super(),this.type=&quot;CircleGeometry&quot;,this.parameters={radius:t,segments:e,thetaStart:n,thetaLength:i},e=Math.max(3,e);const r=[],s=[],a=[],o=[],l=new We,c=new me;s.push(0,0,0),a.push(0,0,1),o.push(.5,.5);for(let r=0,h=3;r&lt;=e;r++,h+=3){const u=n+r/e*i;l.x=t*Math.cos(u),l.y=t*Math.sin(u),s.push(l.x,l.y,l.z),a.push(0,0,1),c.x=(s[h]/t+1)/2,c.y=(s[h+1]/t+1)/2,o.push(c.x,c.y)}for(let t=1;t&lt;=e;t++)r.push(t,t+1,0);this.setIndex(r),this.setAttribute(&quot;position&quot;,new Ti(s,3)),this.setAttribute(&quot;normal&quot;,new Ti(a,3)),this.setAttribute(&quot;uv&quot;,new Ti(o,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new rc(t.radius,t.segments,t.thetaStart,t.thetaLength)}}class sc extends Ii{constructor(t=1,e=1,n=1,i=32,r=1,s=!1,a=0,o=2*Math.PI){super(),this.type=&quot;CylinderGeometry&quot;,this.parameters={radiusTop:t,radiusBottom:e,height:n,radialSegments:i,heightSegments:r,openEnded:s,thetaStart:a,thetaLength:o};const l=this;i=Math.floor(i),r=Math.floor(r);const c=[],h=[],u=[],d=[];let p=0;const m=[],f=n/2;let g=0;function _(n){const r=p,s=new me,m=new We;let _=0;const v=!0===n?t:e,x=!0===n?1:-1;for(let t=1;t&lt;=i;t++)h.push(0,f*x,0),u.push(0,x,0),d.push(.5,.5),p++;const y=p;for(let t=0;t&lt;=i;t++){const e=t/i*o+a,n=Math.cos(e),r=Math.sin(e);m.x=v*r,m.y=f*x,m.z=v*n,h.push(m.x,m.y,m.z),u.push(0,x,0),s.x=.5*n+.5,s.y=.5*r*x+.5,d.push(s.x,s.y),p++}for(let t=0;t&lt;i;t++){const e=r+t,i=y+t;!0===n?c.push(i,i+1,e):c.push(i+1,i,e),_+=3}l.addGroup(g,_,!0===n?1:2),g+=_}!function(){const s=new We,_=new We;let v=0;const x=(e-t)/n;for(let l=0;l&lt;=r;l++){const c=[],g=l/r,v=g*(e-t)+t;for(let t=0;t&lt;=i;t++){const e=t/i,r=e*o+a,l=Math.sin(r),m=Math.cos(r);_.x=v*l,_.y=-g*n+f,_.z=v*m,h.push(_.x,_.y,_.z),s.set(l,x,m).normalize(),u.push(s.x,s.y,s.z),d.push(e,1-g),c.push(p++)}m.push(c)}for(let t=0;t&lt;i;t++)for(let e=0;e&lt;r;e++){const n=m[e][t],i=m[e+1][t],r=m[e+1][t+1],s=m[e][t+1];c.push(n,i,s),c.push(i,r,s),v+=6}l.addGroup(g,v,0),g+=v}(),!1===s&amp;&amp;(t&gt;0&amp;&amp;_(!0),e&gt;0&amp;&amp;_(!1)),this.setIndex(c),this.setAttribute(&quot;position&quot;,new Ti(h,3)),this.setAttribute(&quot;normal&quot;,new Ti(u,3)),this.setAttribute(&quot;uv&quot;,new Ti(d,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new sc(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class ac extends sc{constructor(t=1,e=1,n=32,i=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,n,i,r,s,a),this.type=&quot;ConeGeometry&quot;,this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new ac(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class oc extends Ii{constructor(t=[],e=[],n=1,i=0){super(),this.type=&quot;PolyhedronGeometry&quot;,this.parameters={vertices:t,indices:e,radius:n,detail:i};const r=[],s=[];function a(t,e,n,i){const r=i+1,s=[];for(let i=0;i&lt;=r;i++){s[i]=[];const a=t.clone().lerp(n,i/r),o=e.clone().lerp(n,i/r),l=r-i;for(let t=0;t&lt;=l;t++)s[i][t]=0===t&amp;&amp;i===r?a:a.clone().lerp(o,t/l)}for(let t=0;t&lt;r;t++)for(let e=0;e&lt;2*(r-t)-1;e++){const n=Math.floor(e/2);e%2==0?(o(s[t][n+1]),o(s[t+1][n]),o(s[t][n])):(o(s[t][n+1]),o(s[t+1][n+1]),o(s[t+1][n]))}}function o(t){r.push(t.x,t.y,t.z)}function l(e,n){const i=3*e;n.x=t[i+0],n.y=t[i+1],n.z=t[i+2]}function c(t,e,n,i){i&lt;0&amp;&amp;1===t.x&amp;&amp;(s[e]=t.x-1),0===n.x&amp;&amp;0===n.z&amp;&amp;(s[e]=i/2/Math.PI+.5)}function h(t){return Math.atan2(t.z,-t.x)}!function(t){const n=new We,i=new We,r=new We;for(let s=0;s&lt;e.length;s+=3)l(e[s+0],n),l(e[s+1],i),l(e[s+2],r),a(n,i,r,t)}(i),function(t){const e=new We;for(let n=0;n&lt;r.length;n+=3)e.x=r[n+0],e.y=r[n+1],e.z=r[n+2],e.normalize().multiplyScalar(t),r[n+0]=e.x,r[n+1]=e.y,r[n+2]=e.z}(n),function(){const t=new We;for(let n=0;n&lt;r.length;n+=3){t.x=r[n+0],t.y=r[n+1],t.z=r[n+2];const i=h(t)/2/Math.PI+.5,a=(e=t,Math.atan2(-e.y,Math.sqrt(e.x*e.x+e.z*e.z))/Math.PI+.5);s.push(i,1-a)}var e;(function(){const t=new We,e=new We,n=new We,i=new We,a=new me,o=new me,l=new me;for(let u=0,d=0;u&lt;r.length;u+=9,d+=6){t.set(r[u+0],r[u+1],r[u+2]),e.set(r[u+3],r[u+4],r[u+5]),n.set(r[u+6],r[u+7],r[u+8]),a.set(s[d+0],s[d+1]),o.set(s[d+2],s[d+3]),l.set(s[d+4],s[d+5]),i.copy(t).add(e).add(n).divideScalar(3);const p=h(i);c(a,d+0,t,p),c(o,d+2,e,p),c(l,d+4,n,p)}})(),function(){for(let t=0;t&lt;s.length;t+=6){const e=s[t+0],n=s[t+2],i=s[t+4],r=Math.max(e,n,i),a=Math.min(e,n,i);r&gt;.9&amp;&amp;a&lt;.1&amp;&amp;(e&lt;.2&amp;&amp;(s[t+0]+=1),n&lt;.2&amp;&amp;(s[t+2]+=1),i&lt;.2&amp;&amp;(s[t+4]+=1))}}()}(),this.setAttribute(&quot;position&quot;,new Ti(r,3)),this.setAttribute(&quot;normal&quot;,new Ti(r.slice(),3)),this.setAttribute(&quot;uv&quot;,new Ti(s,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new oc(t.vertices,t.indices,t.radius,t.details)}}class lc extends oc{constructor(t=1,e=0){const n=(1+Math.sqrt(5))/2,i=1/n;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-i,-n,0,-i,n,0,i,-n,0,i,n,-i,-n,0,-i,n,0,i,-n,0,i,n,0,-n,0,-i,n,0,-i,-n,0,i,n,0,i],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type=&quot;DodecahedronGeometry&quot;,this.parameters={radius:t,detail:e}}static fromJSON(t){return new lc(t.radius,t.detail)}}const cc=new We,hc=new We,uc=new We,dc=new ri;class pc extends Ii{constructor(t=null,e=1){if(super(),this.type=&quot;EdgesGeometry&quot;,this.parameters={geometry:t,thresholdAngle:e},null!==t){const n=4,i=Math.pow(10,n),r=Math.cos(ie*e),s=t.getIndex(),a=t.getAttribute(&quot;position&quot;),o=s?s.count:a.count,l=[0,0,0],c=[&quot;a&quot;,&quot;b&quot;,&quot;c&quot;],h=new Array(3),u={},d=[];for(let t=0;t&lt;o;t+=3){s?(l[0]=s.getX(t),l[1]=s.getX(t+1),l[2]=s.getX(t+2)):(l[0]=t,l[1]=t+1,l[2]=t+2);const{a:e,b:n,c:o}=dc;if(e.fromBufferAttribute(a,l[0]),n.fromBufferAttribute(a,l[1]),o.fromBufferAttribute(a,l[2]),dc.getNormal(uc),h[0]=`${Math.round(e.x*i)},${Math.round(e.y*i)},${Math.round(e.z*i)}`,h[1]=`${Math.round(n.x*i)},${Math.round(n.y*i)},${Math.round(n.z*i)}`,h[2]=`${Math.round(o.x*i)},${Math.round(o.y*i)},${Math.round(o.z*i)}`,h[0]!==h[1]&amp;&amp;h[1]!==h[2]&amp;&amp;h[2]!==h[0])for(let t=0;t&lt;3;t++){const e=(t+1)%3,n=h[t],i=h[e],s=dc[c[t]],a=dc[c[e]],o=`${n}_${i}`,p=`${i}_${n}`;p in u&amp;&amp;u[p]?(uc.dot(u[p].normal)&lt;=r&amp;&amp;(d.push(s.x,s.y,s.z),d.push(a.x,a.y,a.z)),u[p]=null):o in u||(u[o]={index0:l[t],index1:l[e],normal:uc.clone()})}}for(const t in u)if(u[t]){const{index0:e,index1:n}=u[t];cc.fromBufferAttribute(a,e),hc.fromBufferAttribute(a,n),d.push(cc.x,cc.y,cc.z),d.push(hc.x,hc.y,hc.z)}this.setAttribute(&quot;position&quot;,new Ti(d,3))}}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}}class mc extends ec{constructor(t){super(t),this.uuid=se(),this.type=&quot;Shape&quot;,this.holes=[]}getPointsHoles(t){const e=[];for(let n=0,i=this.holes.length;n&lt;i;n++)e[n]=this.holes[n].getPoints(t);return e}extractPoints(t){return{shape:this.getPoints(t),holes:this.getPointsHoles(t)}}copy(t){super.copy(t),this.holes=[];for(let e=0,n=t.holes.length;e&lt;n;e++){const n=t.holes[e];this.holes.push(n.clone())}return this}toJSON(){const t=super.toJSON();t.uuid=this.uuid,t.holes=[];for(let e=0,n=this.holes.length;e&lt;n;e++){const n=this.holes[e];t.holes.push(n.toJSON())}return t}fromJSON(t){super.fromJSON(t),this.uuid=t.uuid,this.holes=[];for(let e=0,n=t.holes.length;e&lt;n;e++){const n=t.holes[e];this.holes.push((new ec).fromJSON(n))}return this}}const fc=function(t,e,n=2){const i=e&amp;&amp;e.length,r=i?e[0]*n:t.length;let s=gc(t,0,r,n,!0);const a=[];if(!s||s.next===s.prev)return a;let o,l,c,h,u,d,p;if(i&amp;&amp;(s=function(t,e,n,i){const r=[];let s,a,o,l,c;for(s=0,a=e.length;s&lt;a;s++)o=e[s]*i,l=s&lt;a-1?e[s+1]*i:t.length,c=gc(t,o,l,i,!1),c===c.next&amp;&amp;(c.steiner=!0),r.push(Ac(c));for(r.sort(bc),s=0;s&lt;r.length;s++)n=Tc(r[s],n);return n}(t,e,s,n)),t.length&gt;80*n){o=c=t[0],l=h=t[1];for(let e=n;e&lt;r;e+=n)u=t[e],d=t[e+1],u&lt;o&amp;&amp;(o=u),d&lt;l&amp;&amp;(l=d),u&gt;c&amp;&amp;(c=u),d&gt;h&amp;&amp;(h=d);p=Math.max(c-o,h-l),p=0!==p?32767/p:0}return vc(s,a,n,o,l,p,0),a};function gc(t,e,n,i,r){let s,a;if(r===function(t,e,n,i){let r=0;for(let s=e,a=n-i;s&lt;n;s+=i)r+=(t[a]-t[s])*(t[s+1]+t[a+1]),a=s;return r}(t,e,n,i)&gt;0)for(s=e;s&lt;n;s+=i)a=Fc(s,t[s],t[s+1],a);else for(s=n-i;s&gt;=e;s-=i)a=Fc(s,t[s],t[s+1],a);return a&amp;&amp;Pc(a,a.next)&amp;&amp;(Bc(a),a=a.next),a}function _c(t,e){if(!t)return t;e||(e=t);let n,i=t;do{if(n=!1,i.steiner||!Pc(i,i.next)&amp;&amp;0!==Lc(i.prev,i,i.next))i=i.next;else{if(Bc(i),i=e=i.prev,i===i.next)break;n=!0}}while(n||i!==e);return e}function vc(t,e,n,i,r,s,a){if(!t)return;!a&amp;&amp;s&amp;&amp;function(t,e,n,i){let r=t;do{0===r.z&amp;&amp;(r.z=wc(r.x,r.y,e,n,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,n,i,r,s,a,o,l,c=1;do{for(n=t,t=null,s=null,a=0;n;){for(a++,i=n,o=0,e=0;e&lt;c&amp;&amp;(o++,i=i.nextZ,i);e++);for(l=c;o&gt;0||l&gt;0&amp;&amp;i;)0!==o&amp;&amp;(0===l||!i||n.z&lt;=i.z)?(r=n,n=n.nextZ,o--):(r=i,i=i.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;n=i}s.nextZ=null,c*=2}while(a&gt;1)}(r)}(t,i,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?yc(t,i,r,s):xc(t))e.push(o.i/n|0),e.push(t.i/n|0),e.push(l.i/n|0),Bc(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?vc(t=Mc(_c(t),e,n),e,n,i,r,s,2):2===a&amp;&amp;Sc(t,e,n,i,r,s):vc(_c(t),e,n,i,r,s,1);break}}function xc(t){const e=t.prev,n=t,i=t.next;if(Lc(e,n,i)&gt;=0)return!1;const r=e.x,s=n.x,a=i.x,o=e.y,l=n.y,c=i.y,h=r&lt;s?r&lt;a?r:a:s&lt;a?s:a,u=o&lt;l?o&lt;c?o:c:l&lt;c?l:c,d=r&gt;s?r&gt;a?r:a:s&gt;a?s:a,p=o&gt;l?o&gt;c?o:c:l&gt;c?l:c;let m=i.next;for(;m!==e;){if(m.x&gt;=h&amp;&amp;m.x&lt;=d&amp;&amp;m.y&gt;=u&amp;&amp;m.y&lt;=p&amp;&amp;Rc(r,o,s,l,a,c,m.x,m.y)&amp;&amp;Lc(m.prev,m,m.next)&gt;=0)return!1;m=m.next}return!0}function yc(t,e,n,i){const r=t.prev,s=t,a=t.next;if(Lc(r,s,a)&gt;=0)return!1;const o=r.x,l=s.x,c=a.x,h=r.y,u=s.y,d=a.y,p=o&lt;l?o&lt;c?o:c:l&lt;c?l:c,m=h&lt;u?h&lt;d?h:d:u&lt;d?u:d,f=o&gt;l?o&gt;c?o:c:l&gt;c?l:c,g=h&gt;u?h&gt;d?h:d:u&gt;d?u:d,_=wc(p,m,e,n,i),v=wc(f,g,e,n,i);let x=t.prevZ,y=t.nextZ;for(;x&amp;&amp;x.z&gt;=_&amp;&amp;y&amp;&amp;y.z&lt;=v;){if(x.x&gt;=p&amp;&amp;x.x&lt;=f&amp;&amp;x.y&gt;=m&amp;&amp;x.y&lt;=g&amp;&amp;x!==r&amp;&amp;x!==a&amp;&amp;Rc(o,h,l,u,c,d,x.x,x.y)&amp;&amp;Lc(x.prev,x,x.next)&gt;=0)return!1;if(x=x.prevZ,y.x&gt;=p&amp;&amp;y.x&lt;=f&amp;&amp;y.y&gt;=m&amp;&amp;y.y&lt;=g&amp;&amp;y!==r&amp;&amp;y!==a&amp;&amp;Rc(o,h,l,u,c,d,y.x,y.y)&amp;&amp;Lc(y.prev,y,y.next)&gt;=0)return!1;y=y.nextZ}for(;x&amp;&amp;x.z&gt;=_;){if(x.x&gt;=p&amp;&amp;x.x&lt;=f&amp;&amp;x.y&gt;=m&amp;&amp;x.y&lt;=g&amp;&amp;x!==r&amp;&amp;x!==a&amp;&amp;Rc(o,h,l,u,c,d,x.x,x.y)&amp;&amp;Lc(x.prev,x,x.next)&gt;=0)return!1;x=x.prevZ}for(;y&amp;&amp;y.z&lt;=v;){if(y.x&gt;=p&amp;&amp;y.x&lt;=f&amp;&amp;y.y&gt;=m&amp;&amp;y.y&lt;=g&amp;&amp;y!==r&amp;&amp;y!==a&amp;&amp;Rc(o,h,l,u,c,d,y.x,y.y)&amp;&amp;Lc(y.prev,y,y.next)&gt;=0)return!1;y=y.nextZ}return!0}function Mc(t,e,n){let i=t;do{const r=i.prev,s=i.next.next;!Pc(r,s)&amp;&amp;Ic(r,i,i.next,s)&amp;&amp;Nc(r,s)&amp;&amp;Nc(s,r)&amp;&amp;(e.push(r.i/n|0),e.push(i.i/n|0),e.push(s.i/n|0),Bc(i),Bc(i.next),i=t=s),i=i.next}while(i!==t);return _c(i)}function Sc(t,e,n,i,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&amp;&amp;Cc(a,t)){let o=Oc(a,t);return a=_c(a,a.next),o=_c(o,o.next),vc(a,e,n,i,r,s,0),void vc(o,e,n,i,r,s,0)}t=t.next}a=a.next}while(a!==t)}function bc(t,e){return t.x-e.x}function Tc(t,e){const n=function(t,e){let n,i=e,r=-1/0;const s=t.x,a=t.y;do{if(a&lt;=i.y&amp;&amp;a&gt;=i.next.y&amp;&amp;i.next.y!==i.y){const t=i.x+(a-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(t&lt;=s&amp;&amp;t&gt;r&amp;&amp;(r=t,n=i.x&lt;i.next.x?i:i.next,t===s))return n}i=i.next}while(i!==e);if(!n)return null;const o=n,l=n.x,c=n.y;let h,u=1/0;i=n;do{s&gt;=i.x&amp;&amp;i.x&gt;=l&amp;&amp;s!==i.x&amp;&amp;Rc(a&lt;c?s:r,a,l,c,a&lt;c?r:s,a,i.x,i.y)&amp;&amp;(h=Math.abs(a-i.y)/(s-i.x),Nc(i,t)&amp;&amp;(h&lt;u||h===u&amp;&amp;(i.x&gt;n.x||i.x===n.x&amp;&amp;Ec(n,i)))&amp;&amp;(n=i,u=h)),i=i.next}while(i!==o);return n}(t,e);if(!n)return e;const i=Oc(n,t);return _c(i,i.next),_c(n,n.next)}function Ec(t,e){return Lc(t.prev,t,e.prev)&lt;0&amp;&amp;Lc(e.next,t,t.next)&lt;0}function wc(t,e,n,i,r){return(t=1431655765&amp;((t=858993459&amp;((t=252645135&amp;((t=16711935&amp;((t=(t-n)*r|0)|t&lt;&lt;8))|t&lt;&lt;4))|t&lt;&lt;2))|t&lt;&lt;1))|(e=1431655765&amp;((e=858993459&amp;((e=252645135&amp;((e=16711935&amp;((e=(e-i)*r|0)|e&lt;&lt;8))|e&lt;&lt;4))|e&lt;&lt;2))|e&lt;&lt;1))&lt;&lt;1}function Ac(t){let e=t,n=t;do{(e.x&lt;n.x||e.x===n.x&amp;&amp;e.y&lt;n.y)&amp;&amp;(n=e),e=e.next}while(e!==t);return n}function Rc(t,e,n,i,r,s,a,o){return(r-a)*(e-o)&gt;=(t-a)*(s-o)&amp;&amp;(t-a)*(i-o)&gt;=(n-a)*(e-o)&amp;&amp;(n-a)*(s-o)&gt;=(r-a)*(i-o)}function Cc(t,e){return t.next.i!==e.i&amp;&amp;t.prev.i!==e.i&amp;&amp;!function(t,e){let n=t;do{if(n.i!==t.i&amp;&amp;n.next.i!==t.i&amp;&amp;n.i!==e.i&amp;&amp;n.next.i!==e.i&amp;&amp;Ic(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&amp;&amp;(Nc(t,e)&amp;&amp;Nc(e,t)&amp;&amp;function(t,e){let n=t,i=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{n.y&gt;s!=n.next.y&gt;s&amp;&amp;n.next.y!==n.y&amp;&amp;r&lt;(n.next.x-n.x)*(s-n.y)/(n.next.y-n.y)+n.x&amp;&amp;(i=!i),n=n.next}while(n!==t);return i}(t,e)&amp;&amp;(Lc(t.prev,t,e.prev)||Lc(t,e.prev,e))||Pc(t,e)&amp;&amp;Lc(t.prev,t,t.next)&gt;0&amp;&amp;Lc(e.prev,e,e.next)&gt;0)}function Lc(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function Pc(t,e){return t.x===e.x&amp;&amp;t.y===e.y}function Ic(t,e,n,i){const r=Dc(Lc(t,e,n)),s=Dc(Lc(t,e,i)),a=Dc(Lc(n,i,t)),o=Dc(Lc(n,i,e));return r!==s&amp;&amp;a!==o||(!(0!==r||!Uc(t,n,e))||(!(0!==s||!Uc(t,i,e))||(!(0!==a||!Uc(n,t,i))||!(0!==o||!Uc(n,e,i)))))}function Uc(t,e,n){return e.x&lt;=Math.max(t.x,n.x)&amp;&amp;e.x&gt;=Math.min(t.x,n.x)&amp;&amp;e.y&lt;=Math.max(t.y,n.y)&amp;&amp;e.y&gt;=Math.min(t.y,n.y)}function Dc(t){return t&gt;0?1:t&lt;0?-1:0}function Nc(t,e){return Lc(t.prev,t,t.next)&lt;0?Lc(t,e,t.next)&gt;=0&amp;&amp;Lc(t,t.prev,e)&gt;=0:Lc(t,e,t.prev)&lt;0||Lc(t,t.next,e)&lt;0}function Oc(t,e){const n=new zc(t.i,t.x,t.y),i=new zc(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,n.next=r,r.prev=n,i.next=n,n.prev=i,s.next=i,i.prev=s,i}function Fc(t,e,n,i){const r=new zc(t,e,n);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function Bc(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&amp;&amp;(t.prevZ.nextZ=t.nextZ),t.nextZ&amp;&amp;(t.nextZ.prevZ=t.prevZ)}function zc(t,e,n){this.i=t,this.x=e,this.y=n,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class Gc{static area(t){const e=t.length;let n=0;for(let i=e-1,r=0;r&lt;e;i=r++)n+=t[i].x*t[r].y-t[r].x*t[i].y;return.5*n}static isClockWise(t){return Gc.area(t)&lt;0}static triangulateShape(t,e){const n=[],i=[],r=[];Hc(t),Vc(n,t);let s=t.length;e.forEach(Hc);for(let t=0;t&lt;e.length;t++)i.push(s),s+=e[t].length,Vc(n,e[t]);const a=fc(n,i);for(let t=0;t&lt;a.length;t+=3)r.push(a.slice(t,t+3));return r}}function Hc(t){const e=t.length;e&gt;2&amp;&amp;t[e-1].equals(t[0])&amp;&amp;t.pop()}function Vc(t,e){for(let n=0;n&lt;e.length;n++)t.push(e[n].x),t.push(e[n].y)}class kc extends Ii{constructor(t=new mc([new me(.5,.5),new me(-.5,.5),new me(-.5,-.5),new me(.5,-.5)]),e={}){super(),this.type=&quot;ExtrudeGeometry&quot;,this.parameters={shapes:t,options:e},t=Array.isArray(t)?t:[t];const n=this,i=[],r=[];for(let e=0,n=t.length;e&lt;n;e++){s(t[e])}function s(t){const s=[],a=void 0!==e.curveSegments?e.curveSegments:12,o=void 0!==e.steps?e.steps:1,l=void 0!==e.depth?e.depth:1;let c=void 0===e.bevelEnabled||e.bevelEnabled,h=void 0!==e.bevelThickness?e.bevelThickness:.2,u=void 0!==e.bevelSize?e.bevelSize:h-.1,d=void 0!==e.bevelOffset?e.bevelOffset:0,p=void 0!==e.bevelSegments?e.bevelSegments:3;const m=e.extrudePath,f=void 0!==e.UVGenerator?e.UVGenerator:Wc;let g,_,v,x,y,M=!1;m&amp;&amp;(g=m.getSpacedPoints(o),M=!0,c=!1,_=m.computeFrenetFrames(o,!1),v=new We,x=new We,y=new We),c||(p=0,h=0,u=0,d=0);const S=t.extractPoints(a);let b=S.shape;const T=S.holes;if(!Gc.isClockWise(b)){b=b.reverse();for(let t=0,e=T.length;t&lt;e;t++){const e=T[t];Gc.isClockWise(e)&amp;&amp;(T[t]=e.reverse())}}const E=Gc.triangulateShape(b,T),w=b;for(let t=0,e=T.length;t&lt;e;t++){const e=T[t];b=b.concat(e)}function A(t,e,n){return e||console.error(&quot;THREE.ExtrudeGeometry: vec does not exist&quot;),t.clone().addScaledVector(e,n)}const R=b.length,C=E.length;function L(t,e,n){let i,r,s;const a=t.x-e.x,o=t.y-e.y,l=n.x-t.x,c=n.y-t.y,h=a*a+o*o,u=a*c-o*l;if(Math.abs(u)&gt;Number.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((n.x-c/d-p)*c-(n.y+l/d-m)*l)/(a*c-o*l);i=p+a*f-t.x,r=m+o*f-t.y;const g=i*i+r*r;if(g&lt;=2)return new me(i,r);s=Math.sqrt(g/2)}else{let t=!1;a&gt;Number.EPSILON?l&gt;Number.EPSILON&amp;&amp;(t=!0):a&lt;-Number.EPSILON?l&lt;-Number.EPSILON&amp;&amp;(t=!0):Math.sign(o)===Math.sign(c)&amp;&amp;(t=!0),t?(i=-o,r=a,s=Math.sqrt(h)):(i=a,r=o,s=Math.sqrt(h/2))}return new me(i/s,r/s)}const P=[];for(let t=0,e=w.length,n=e-1,i=t+1;t&lt;e;t++,n++,i++)n===e&amp;&amp;(n=0),i===e&amp;&amp;(i=0),P[t]=L(w[t],w[n],w[i]);const I=[];let U,D=P.concat();for(let t=0,e=T.length;t&lt;e;t++){const e=T[t];U=[];for(let t=0,n=e.length,i=n-1,r=t+1;t&lt;n;t++,i++,r++)i===n&amp;&amp;(i=0),r===n&amp;&amp;(r=0),U[t]=L(e[t],e[i],e[r]);I.push(U),D=D.concat(U)}for(let t=0;t&lt;p;t++){const e=t/p,n=h*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=w.length;t&lt;e;t++){const e=A(w[t],P[t],i);F(e.x,e.y,-n)}for(let t=0,e=T.length;t&lt;e;t++){const e=T[t];U=I[t];for(let t=0,r=e.length;t&lt;r;t++){const r=A(e[t],U[t],i);F(r.x,r.y,-n)}}}const N=u+d;for(let t=0;t&lt;R;t++){const e=c?A(b[t],D[t],N):b[t];M?(x.copy(_.normals[0]).multiplyScalar(e.x),v.copy(_.binormals[0]).multiplyScalar(e.y),y.copy(g[0]).add(x).add(v),F(y.x,y.y,y.z)):F(e.x,e.y,0)}for(let t=1;t&lt;=o;t++)for(let e=0;e&lt;R;e++){const n=c?A(b[e],D[e],N):b[e];M?(x.copy(_.normals[t]).multiplyScalar(n.x),v.copy(_.binormals[t]).multiplyScalar(n.y),y.copy(g[t]).add(x).add(v),F(y.x,y.y,y.z)):F(n.x,n.y,l/o*t)}for(let t=p-1;t&gt;=0;t--){const e=t/p,n=h*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=w.length;t&lt;e;t++){const e=A(w[t],P[t],i);F(e.x,e.y,l+n)}for(let t=0,e=T.length;t&lt;e;t++){const e=T[t];U=I[t];for(let t=0,r=e.length;t&lt;r;t++){const r=A(e[t],U[t],i);M?F(r.x,r.y+g[o-1].y,g[o-1].x+n):F(r.x,r.y,l+n)}}}function O(t,e){let n=t.length;for(;--n&gt;=0;){const i=n;let r=n-1;r&lt;0&amp;&amp;(r=t.length-1);for(let t=0,n=o+2*p;t&lt;n;t++){const n=R*t,s=R*(t+1);z(e+i+n,e+r+n,e+r+s,e+i+s)}}}function F(t,e,n){s.push(t),s.push(e),s.push(n)}function B(t,e,r){G(t),G(e),G(r);const s=i.length/3,a=f.generateTopUV(n,i,s-3,s-2,s-1);H(a[0]),H(a[1]),H(a[2])}function z(t,e,r,s){G(t),G(e),G(s),G(e),G(r),G(s);const a=i.length/3,o=f.generateSideWallUV(n,i,a-6,a-3,a-2,a-1);H(o[0]),H(o[1]),H(o[3]),H(o[1]),H(o[2]),H(o[3])}function G(t){i.push(s[3*t+0]),i.push(s[3*t+1]),i.push(s[3*t+2])}function H(t){r.push(t.x),r.push(t.y)}!function(){const t=i.length/3;if(c){let t=0,e=R*t;for(let t=0;t&lt;C;t++){const n=E[t];B(n[2]+e,n[1]+e,n[0]+e)}t=o+2*p,e=R*t;for(let t=0;t&lt;C;t++){const n=E[t];B(n[0]+e,n[1]+e,n[2]+e)}}else{for(let t=0;t&lt;C;t++){const e=E[t];B(e[2],e[1],e[0])}for(let t=0;t&lt;C;t++){const e=E[t];B(e[0]+R*o,e[1]+R*o,e[2]+R*o)}}n.addGroup(t,i.length/3-t,0)}(),function(){const t=i.length/3;let e=0;O(w,e),e+=w.length;for(let t=0,n=T.length;t&lt;n;t++){const n=T[t];O(n,e),e+=n.length}n.addGroup(t,i.length/3-t,1)}()}this.setAttribute(&quot;position&quot;,new Ti(i,3)),this.setAttribute(&quot;uv&quot;,new Ti(r,2)),this.computeVertexNormals()}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}toJSON(){const t=super.toJSON();return function(t,e,n){if(n.shapes=[],Array.isArray(t))for(let e=0,i=t.length;e&lt;i;e++){const i=t[e];n.shapes.push(i.uuid)}else n.shapes.push(t.uuid);n.options=Object.assign({},e),void 0!==e.extrudePath&amp;&amp;(n.options.extrudePath=e.extrudePath.toJSON());return n}(this.parameters.shapes,this.parameters.options,t)}static fromJSON(t,e){const n=[];for(let i=0,r=t.shapes.length;i&lt;r;i++){const r=e[t.shapes[i]];n.push(r)}const i=t.options.extrudePath;return void 0!==i&amp;&amp;(t.options.extrudePath=(new Ql[i.type]).fromJSON(i)),new kc(n,t.options)}}const Wc={generateTopUV:function(t,e,n,i,r){const s=e[3*n],a=e[3*n+1],o=e[3*i],l=e[3*i+1],c=e[3*r],h=e[3*r+1];return[new me(s,a),new me(o,l),new me(c,h)]},generateSideWallUV:function(t,e,n,i,r,s){const a=e[3*n],o=e[3*n+1],l=e[3*n+2],c=e[3*i],h=e[3*i+1],u=e[3*i+2],d=e[3*r],p=e[3*r+1],m=e[3*r+2],f=e[3*s],g=e[3*s+1],_=e[3*s+2];return Math.abs(o-h)&lt;Math.abs(a-c)?[new me(a,1-l),new me(c,1-u),new me(d,1-m),new me(f,1-_)]:[new me(o,1-l),new me(h,1-u),new me(p,1-m),new me(g,1-_)]}};class Xc extends oc{constructor(t=1,e=0){const n=(1+Math.sqrt(5))/2;super([-1,n,0,1,n,0,-1,-n,0,1,-n,0,0,-1,n,0,1,n,0,-1,-n,0,1,-n,n,0,-1,n,0,1,-n,0,-1,-n,0,1],[0,11,5,0,5,1,0,1,7,0,7,10,0,10,11,1,5,9,5,11,4,11,10,2,10,7,6,7,1,8,3,9,4,3,4,2,3,2,6,3,6,8,3,8,9,4,9,5,2,4,11,6,2,10,8,6,7,9,8,1],t,e),this.type=&quot;IcosahedronGeometry&quot;,this.parameters={radius:t,detail:e}}static fromJSON(t){return new Xc(t.radius,t.detail)}}class jc extends oc{constructor(t=1,e=0){super([1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],t,e),this.type=&quot;OctahedronGeometry&quot;,this.parameters={radius:t,detail:e}}static fromJSON(t){return new jc(t.radius,t.detail)}}class qc extends Ii{constructor(t=.5,e=1,n=32,i=1,r=0,s=2*Math.PI){super(),this.type=&quot;RingGeometry&quot;,this.parameters={innerRadius:t,outerRadius:e,thetaSegments:n,phiSegments:i,thetaStart:r,thetaLength:s},n=Math.max(3,n);const a=[],o=[],l=[],c=[];let h=t;const u=(e-t)/(i=Math.max(1,i)),d=new We,p=new me;for(let t=0;t&lt;=i;t++){for(let t=0;t&lt;=n;t++){const i=r+t/n*s;d.x=h*Math.cos(i),d.y=h*Math.sin(i),o.push(d.x,d.y,d.z),l.push(0,0,1),p.x=(d.x/e+1)/2,p.y=(d.y/e+1)/2,c.push(p.x,p.y)}h+=u}for(let t=0;t&lt;i;t++){const e=t*(n+1);for(let t=0;t&lt;n;t++){const i=t+e,r=i,s=i+n+1,o=i+n+2,l=i+1;a.push(r,s,l),a.push(s,o,l)}}this.setIndex(a),this.setAttribute(&quot;position&quot;,new Ti(o,3)),this.setAttribute(&quot;normal&quot;,new Ti(l,3)),this.setAttribute(&quot;uv&quot;,new Ti(c,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new qc(t.innerRadius,t.outerRadius,t.thetaSegments,t.phiSegments,t.thetaStart,t.thetaLength)}}class Yc extends Ii{constructor(t=new mc([new me(0,.5),new me(-.5,-.5),new me(.5,-.5)]),e=12){super(),this.type=&quot;ShapeGeometry&quot;,this.parameters={shapes:t,curveSegments:e};const n=[],i=[],r=[],s=[];let a=0,o=0;if(!1===Array.isArray(t))l(t);else for(let e=0;e&lt;t.length;e++)l(t[e]),this.addGroup(a,o,e),a+=o,o=0;function l(t){const a=i.length/3,l=t.extractPoints(e);let c=l.shape;const h=l.holes;!1===Gc.isClockWise(c)&amp;&amp;(c=c.reverse());for(let t=0,e=h.length;t&lt;e;t++){const e=h[t];!0===Gc.isClockWise(e)&amp;&amp;(h[t]=e.reverse())}const u=Gc.triangulateShape(c,h);for(let t=0,e=h.length;t&lt;e;t++){const e=h[t];c=c.concat(e)}for(let t=0,e=c.length;t&lt;e;t++){const e=c[t];i.push(e.x,e.y,0),r.push(0,0,1),s.push(e.x,e.y)}for(let t=0,e=u.length;t&lt;e;t++){const e=u[t],i=e[0]+a,r=e[1]+a,s=e[2]+a;n.push(i,r,s),o+=3}}this.setIndex(n),this.setAttribute(&quot;position&quot;,new Ti(i,3)),this.setAttribute(&quot;normal&quot;,new Ti(r,3)),this.setAttribute(&quot;uv&quot;,new Ti(s,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}toJSON(){const t=super.toJSON();return function(t,e){if(e.shapes=[],Array.isArray(t))for(let n=0,i=t.length;n&lt;i;n++){const i=t[n];e.shapes.push(i.uuid)}else e.shapes.push(t.uuid);return e}(this.parameters.shapes,t)}static fromJSON(t,e){const n=[];for(let i=0,r=t.shapes.length;i&lt;r;i++){const r=e[t.shapes[i]];n.push(r)}return new Yc(n,t.curveSegments)}}class Zc extends Ii{constructor(t=1,e=32,n=16,i=0,r=2*Math.PI,s=0,a=Math.PI){super(),this.type=&quot;SphereGeometry&quot;,this.parameters={radius:t,widthSegments:e,heightSegments:n,phiStart:i,phiLength:r,thetaStart:s,thetaLength:a},e=Math.max(3,Math.floor(e)),n=Math.max(2,Math.floor(n));const o=Math.min(s+a,Math.PI);let l=0;const c=[],h=new We,u=new We,d=[],p=[],m=[],f=[];for(let d=0;d&lt;=n;d++){const g=[],_=d/n;let v=0;0===d&amp;&amp;0===s?v=.5/e:d===n&amp;&amp;o===Math.PI&amp;&amp;(v=-.5/e);for(let n=0;n&lt;=e;n++){const o=n/e;h.x=-t*Math.cos(i+o*r)*Math.sin(s+_*a),h.y=t*Math.cos(s+_*a),h.z=t*Math.sin(i+o*r)*Math.sin(s+_*a),p.push(h.x,h.y,h.z),u.copy(h).normalize(),m.push(u.x,u.y,u.z),f.push(o+v,1-_),g.push(l++)}c.push(g)}for(let t=0;t&lt;n;t++)for(let i=0;i&lt;e;i++){const e=c[t][i+1],r=c[t][i],a=c[t+1][i],l=c[t+1][i+1];(0!==t||s&gt;0)&amp;&amp;d.push(e,r,l),(t!==n-1||o&lt;Math.PI)&amp;&amp;d.push(r,a,l)}this.setIndex(d),this.setAttribute(&quot;position&quot;,new Ti(p,3)),this.setAttribute(&quot;normal&quot;,new Ti(m,3)),this.setAttribute(&quot;uv&quot;,new Ti(f,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new Zc(t.radius,t.widthSegments,t.heightSegments,t.phiStart,t.phiLength,t.thetaStart,t.thetaLength)}}class Jc extends oc{constructor(t=1,e=0){super([1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],t,e),this.type=&quot;TetrahedronGeometry&quot;,this.parameters={radius:t,detail:e}}static fromJSON(t){return new Jc(t.radius,t.detail)}}class Kc extends Ii{constructor(t=1,e=.4,n=12,i=48,r=2*Math.PI){super(),this.type=&quot;TorusGeometry&quot;,this.parameters={radius:t,tube:e,radialSegments:n,tubularSegments:i,arc:r},n=Math.floor(n),i=Math.floor(i);const s=[],a=[],o=[],l=[],c=new We,h=new We,u=new We;for(let s=0;s&lt;=n;s++)for(let d=0;d&lt;=i;d++){const p=d/i*r,m=s/n*Math.PI*2;h.x=(t+e*Math.cos(m))*Math.cos(p),h.y=(t+e*Math.cos(m))*Math.sin(p),h.z=e*Math.sin(m),a.push(h.x,h.y,h.z),c.x=t*Math.cos(p),c.y=t*Math.sin(p),u.subVectors(h,c).normalize(),o.push(u.x,u.y,u.z),l.push(d/i),l.push(s/n)}for(let t=1;t&lt;=n;t++)for(let e=1;e&lt;=i;e++){const n=(i+1)*t+e-1,r=(i+1)*(t-1)+e-1,a=(i+1)*(t-1)+e,o=(i+1)*t+e;s.push(n,r,o),s.push(r,a,o)}this.setIndex(s),this.setAttribute(&quot;position&quot;,new Ti(a,3)),this.setAttribute(&quot;normal&quot;,new Ti(o,3)),this.setAttribute(&quot;uv&quot;,new Ti(l,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new Kc(t.radius,t.tube,t.radialSegments,t.tubularSegments,t.arc)}}class $c extends Ii{constructor(t=1,e=.4,n=64,i=8,r=2,s=3){super(),this.type=&quot;TorusKnotGeometry&quot;,this.parameters={radius:t,tube:e,tubularSegments:n,radialSegments:i,p:r,q:s},n=Math.floor(n),i=Math.floor(i);const a=[],o=[],l=[],c=[],h=new We,u=new We,d=new We,p=new We,m=new We,f=new We,g=new We;for(let a=0;a&lt;=n;++a){const v=a/n*r*Math.PI*2;_(v,r,s,t,d),_(v+.01,r,s,t,p),f.subVectors(p,d),g.addVectors(p,d),m.crossVectors(f,g),g.crossVectors(m,f),m.normalize(),g.normalize();for(let t=0;t&lt;=i;++t){const r=t/i*Math.PI*2,s=-e*Math.cos(r),p=e*Math.sin(r);h.x=d.x+(s*g.x+p*m.x),h.y=d.y+(s*g.y+p*m.y),h.z=d.z+(s*g.z+p*m.z),o.push(h.x,h.y,h.z),u.subVectors(h,d).normalize(),l.push(u.x,u.y,u.z),c.push(a/n),c.push(t/i)}}for(let t=1;t&lt;=n;t++)for(let e=1;e&lt;=i;e++){const n=(i+1)*(t-1)+(e-1),r=(i+1)*t+(e-1),s=(i+1)*t+e,o=(i+1)*(t-1)+e;a.push(n,r,o),a.push(r,s,o)}function _(t,e,n,i,r){const s=Math.cos(t),a=Math.sin(t),o=n/e*t,l=Math.cos(o);r.x=i*(2+l)*.5*s,r.y=i*(2+l)*a*.5,r.z=i*Math.sin(o)*.5}this.setIndex(a),this.setAttribute(&quot;position&quot;,new Ti(o,3)),this.setAttribute(&quot;normal&quot;,new Ti(l,3)),this.setAttribute(&quot;uv&quot;,new Ti(c,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new $c(t.radius,t.tube,t.tubularSegments,t.radialSegments,t.p,t.q)}}class Qc extends Ii{constructor(t=new Kl(new We(-1,-1,0),new We(-1,1,0),new We(1,1,0)),e=64,n=1,i=8,r=!1){super(),this.type=&quot;TubeGeometry&quot;,this.parameters={path:t,tubularSegments:e,radius:n,radialSegments:i,closed:r};const s=t.computeFrenetFrames(e,r);this.tangents=s.tangents,this.normals=s.normals,this.binormals=s.binormals;const a=new We,o=new We,l=new me;let c=new We;const h=[],u=[],d=[],p=[];function m(r){c=t.getPointAt(r/e,c);const l=s.normals[r],d=s.binormals[r];for(let t=0;t&lt;=i;t++){const e=t/i*Math.PI*2,r=Math.sin(e),s=-Math.cos(e);o.x=s*l.x+r*d.x,o.y=s*l.y+r*d.y,o.z=s*l.z+r*d.z,o.normalize(),u.push(o.x,o.y,o.z),a.x=c.x+n*o.x,a.y=c.y+n*o.y,a.z=c.z+n*o.z,h.push(a.x,a.y,a.z)}}!function(){for(let t=0;t&lt;e;t++)m(t);m(!1===r?e:0),function(){for(let t=0;t&lt;=e;t++)for(let n=0;n&lt;=i;n++)l.x=t/e,l.y=n/i,d.push(l.x,l.y)}(),function(){for(let t=1;t&lt;=e;t++)for(let e=1;e&lt;=i;e++){const n=(i+1)*(t-1)+(e-1),r=(i+1)*t+(e-1),s=(i+1)*t+e,a=(i+1)*(t-1)+e;p.push(n,r,a),p.push(r,s,a)}}()}(),this.setIndex(p),this.setAttribute(&quot;position&quot;,new Ti(h,3)),this.setAttribute(&quot;normal&quot;,new Ti(u,3)),this.setAttribute(&quot;uv&quot;,new Ti(d,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}toJSON(){const t=super.toJSON();return t.path=this.parameters.path.toJSON(),t}static fromJSON(t){return new Qc((new Ql[t.path.type]).fromJSON(t.path),t.tubularSegments,t.radius,t.radialSegments,t.closed)}}class th extends Ii{constructor(t=null){if(super(),this.type=&quot;WireframeGeometry&quot;,this.parameters={geometry:t},null!==t){const e=[],n=new Set,i=new We,r=new We;if(null!==t.index){const s=t.attributes.position,a=t.index;let o=t.groups;0===o.length&amp;&amp;(o=[{start:0,count:a.count,materialIndex:0}]);for(let t=0,l=o.length;t&lt;l;++t){const l=o[t],c=l.start;for(let t=c,o=c+l.count;t&lt;o;t+=3)for(let o=0;o&lt;3;o++){const l=a.getX(t+o),c=a.getX(t+(o+1)%3);i.fromBufferAttribute(s,l),r.fromBufferAttribute(s,c),!0===eh(i,r,n)&amp;&amp;(e.push(i.x,i.y,i.z),e.push(r.x,r.y,r.z))}}}else{const s=t.attributes.position;for(let t=0,a=s.count/3;t&lt;a;t++)for(let a=0;a&lt;3;a++){const o=3*t+a,l=3*t+(a+1)%3;i.fromBufferAttribute(s,o),r.fromBufferAttribute(s,l),!0===eh(i,r,n)&amp;&amp;(e.push(i.x,i.y,i.z),e.push(r.x,r.y,r.z))}}this.setAttribute(&quot;position&quot;,new Ti(e,3))}}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}}function eh(t,e,n){const i=`${t.x},${t.y},${t.z}-${e.x},${e.y},${e.z}`,r=`${e.x},${e.y},${e.z}-${t.x},${t.y},${t.z}`;return!0!==n.has(i)&amp;&amp;!0!==n.has(r)&amp;&amp;(n.add(i),n.add(r),!0)}var nh=Object.freeze({__proto__:null,BoxGeometry:$i,CapsuleGeometry:ic,CircleGeometry:rc,ConeGeometry:ac,CylinderGeometry:sc,DodecahedronGeometry:lc,EdgesGeometry:pc,ExtrudeGeometry:kc,IcosahedronGeometry:Xc,LatheGeometry:nc,OctahedronGeometry:jc,PlaneGeometry:xr,PolyhedronGeometry:oc,RingGeometry:qc,ShapeGeometry:Yc,SphereGeometry:Zc,TetrahedronGeometry:Jc,TorusGeometry:Kc,TorusKnotGeometry:$c,TubeGeometry:Qc,WireframeGeometry:th});class ih extends di{constructor(t){super(),this.isShadowMaterial=!0,this.type=&quot;ShadowMaterial&quot;,this.color=new ci(0),this.transparent=!0,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.fog=t.fog,this}}class rh extends ir{constructor(t){super(t),this.isRawShaderMaterial=!0,this.type=&quot;RawShaderMaterial&quot;}}class sh extends di{constructor(t){super(),this.isMeshStandardMaterial=!0,this.defines={STANDARD:&quot;&quot;},this.type=&quot;MeshStandardMaterial&quot;,this.color=new ci(16777215),this.roughness=1,this.metalness=0,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ci(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new me(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.roughnessMap=null,this.metalnessMap=null,this.alphaMap=null,this.envMap=null,this.envMapIntensity=1,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap=&quot;round&quot;,this.wireframeLinejoin=&quot;round&quot;,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={STANDARD:&quot;&quot;},this.color.copy(t.color),this.roughness=t.roughness,this.metalness=t.metalness,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.roughnessMap=t.roughnessMap,this.metalnessMap=t.metalnessMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapIntensity=t.envMapIntensity,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class ah extends sh{constructor(t){super(),this.isMeshPhysicalMaterial=!0,this.defines={STANDARD:&quot;&quot;,PHYSICAL:&quot;&quot;},this.type=&quot;MeshPhysicalMaterial&quot;,this.anisotropyRotation=0,this.anisotropyMap=null,this.clearcoatMap=null,this.clearcoatRoughness=0,this.clearcoatRoughnessMap=null,this.clearcoatNormalScale=new me(1,1),this.clearcoatNormalMap=null,this.ior=1.5,Object.defineProperty(this,&quot;reflectivity&quot;,{get:function(){return ae(2.5*(this.ior-1)/(this.ior+1),0,1)},set:function(t){this.ior=(1+.4*t)/(1-.4*t)}}),this.iridescenceMap=null,this.iridescenceIOR=1.3,this.iridescenceThicknessRange=[100,400],this.iridescenceThicknessMap=null,this.sheenColor=new ci(0),this.sheenColorMap=null,this.sheenRoughness=1,this.sheenRoughnessMap=null,this.transmissionMap=null,this.thickness=0,this.thicknessMap=null,this.attenuationDistance=1/0,this.attenuationColor=new ci(1,1,1),this.specularIntensity=1,this.specularIntensityMap=null,this.specularColor=new ci(1,1,1),this.specularColorMap=null,this._anisotropy=0,this._clearcoat=0,this._iridescence=0,this._sheen=0,this._transmission=0,this.setValues(t)}get anisotropy(){return this._anisotropy}set anisotropy(t){this._anisotropy&gt;0!=t&gt;0&amp;&amp;this.version++,this._anisotropy=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat&gt;0!=t&gt;0&amp;&amp;this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence&gt;0!=t&gt;0&amp;&amp;this.version++,this._iridescence=t}get sheen(){return this._sheen}set sheen(t){this._sheen&gt;0!=t&gt;0&amp;&amp;this.version++,this._sheen=t}get transmission(){return this._transmission}set transmission(t){this._transmission&gt;0!=t&gt;0&amp;&amp;this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:&quot;&quot;,PHYSICAL:&quot;&quot;},this.anisotropy=t.anisotropy,this.anisotropyRotation=t.anisotropyRotation,this.anisotropyMap=t.anisotropyMap,this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class oh extends di{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type=&quot;MeshPhongMaterial&quot;,this.color=new ci(16777215),this.specular=new ci(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ci(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new me(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=h,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap=&quot;round&quot;,this.wireframeLinejoin=&quot;round&quot;,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class lh extends di{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:&quot;&quot;},this.type=&quot;MeshToonMaterial&quot;,this.color=new ci(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ci(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new me(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap=&quot;round&quot;,this.wireframeLinejoin=&quot;round&quot;,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class ch extends di{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type=&quot;MeshNormalMaterial&quot;,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new me(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}class hh extends di{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type=&quot;MeshLambertMaterial&quot;,this.color=new ci(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ci(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new me(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=h,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap=&quot;round&quot;,this.wireframeLinejoin=&quot;round&quot;,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class uh extends di{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:&quot;&quot;},this.type=&quot;MeshMatcapMaterial&quot;,this.color=new ci(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new me(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:&quot;&quot;},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this.fog=t.fog,this}}class dh extends fl{constructor(t){super(),this.isLineDashedMaterial=!0,this.type=&quot;LineDashedMaterial&quot;,this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}function ph(t,e,n){return!t||!n&amp;&amp;t.constructor===e?t:&quot;number&quot;==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function mh(t){return ArrayBuffer.isView(t)&amp;&amp;!(t instanceof DataView)}function fh(t){const e=t.length,n=new Array(e);for(let t=0;t!==e;++t)n[t]=t;return n.sort((function(e,n){return t[e]-t[n]})),n}function gh(t,e,n){const i=t.length,r=new t.constructor(i);for(let s=0,a=0;a!==i;++s){const i=n[s]*e;for(let n=0;n!==e;++n)r[a++]=t[i+n]}return r}function _h(t,e,n,i){let r=1,s=t[0];for(;void 0!==s&amp;&amp;void 0===s[i];)s=t[r++];if(void 0===s)return;let a=s[i];if(void 0!==a)if(Array.isArray(a))do{a=s[i],void 0!==a&amp;&amp;(e.push(s.time),n.push.apply(n,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[i],void 0!==a&amp;&amp;(e.push(s.time),a.toArray(n,n.length)),s=t[r++]}while(void 0!==s);else do{a=s[i],void 0!==a&amp;&amp;(e.push(s.time),n.push(a)),s=t[r++]}while(void 0!==s)}const vh={convertArray:ph,isTypedArray:mh,getKeyframeOrder:fh,sortedArray:gh,flattenJSON:_h,subclip:function(t,e,n,i,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t&lt;s.tracks.length;++t){const e=s.tracks[t],o=e.getValueSize(),l=[],c=[];for(let t=0;t&lt;e.times.length;++t){const s=e.times[t]*r;if(!(s&lt;n||s&gt;=i)){l.push(e.times[t]);for(let n=0;n&lt;o;++n)c.push(e.values[t*o+n])}}0!==l.length&amp;&amp;(e.times=ph(l,e.times.constructor),e.values=ph(c,e.values.constructor),a.push(e))}s.tracks=a;let o=1/0;for(let t=0;t&lt;s.tracks.length;++t)o&gt;s.tracks[t].times[0]&amp;&amp;(o=s.tracks[t].times[0]);for(let t=0;t&lt;s.tracks.length;++t)s.tracks[t].shift(-1*o);return s.resetDuration(),s},makeClipAdditive:function(t,e=0,n=t,i=30){i&lt;=0&amp;&amp;(i=30);const r=n.tracks.length,s=e/i;for(let e=0;e&lt;r;++e){const i=n.tracks[e],r=i.ValueTypeName;if(&quot;bool&quot;===r||&quot;string&quot;===r)continue;const a=t.tracks.find((function(t){return t.name===i.name&amp;&amp;t.ValueTypeName===r}));if(void 0===a)continue;let o=0;const l=i.getValueSize();i.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline&amp;&amp;(o=l/3);let c=0;const h=a.getValueSize();a.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline&amp;&amp;(c=h/3);const u=i.times.length-1;let d;if(s&lt;=i.times[0]){const t=o,e=l-o;d=i.values.slice(t,e)}else if(s&gt;=i.times[u]){const t=u*l+o,e=t+l-o;d=i.values.slice(t,e)}else{const t=i.createInterpolant(),e=o,n=l-o;t.evaluate(s),d=t.resultBuffer.slice(e,n)}if(&quot;quaternion&quot;===r){(new ke).fromArray(d).normalize().conjugate().toArray(d)}const p=a.times.length;for(let t=0;t&lt;p;++t){const e=t*h+c;if(&quot;quaternion&quot;===r)ke.multiplyQuaternionsFlat(a.values,e,d,0,a.values,e);else{const t=h-2*c;for(let n=0;n&lt;t;++n)a.values[e+n]-=d[n]}}}return t.blendMode=Ot,t}};class xh{constructor(t,e,n,i){this.parameterPositions=t,this._cachedIndex=0,this.resultBuffer=void 0!==i?i:new e.constructor(n),this.sampleValues=e,this.valueSize=n,this.settings=null,this.DefaultSettings_={}}evaluate(t){const e=this.parameterPositions;let n=this._cachedIndex,i=e[n],r=e[n-1];t:{e:{let s;n:{i:if(!(t&lt;i)){for(let s=n+2;;){if(void 0===i){if(t&lt;r)break i;return n=e.length,this._cachedIndex=n,this.copySampleValue_(n-1)}if(n===s)break;if(r=i,i=e[++n],t&lt;i)break e}s=e.length;break n}if(t&gt;=r)break t;{const a=e[1];t&lt;a&amp;&amp;(n=2,r=a);for(let s=n-2;;){if(void 0===r)return this._cachedIndex=0,this.copySampleValue_(0);if(n===s)break;if(i=r,r=e[--n-1],t&gt;=r)break e}s=n,n=0}}for(;n&lt;s;){const i=n+s&gt;&gt;&gt;1;t&lt;e[i]?s=i:n=i+1}if(i=e[n],r=e[n-1],void 0===r)return this._cachedIndex=0,this.copySampleValue_(0);if(void 0===i)return n=e.length,this._cachedIndex=n,this.copySampleValue_(n-1)}this._cachedIndex=n,this.intervalChanged_(n,r,i)}return this.interpolate_(n,r,t,i)}getSettings_(){return this.settings||this.DefaultSettings_}copySampleValue_(t){const e=this.resultBuffer,n=this.sampleValues,i=this.valueSize,r=t*i;for(let t=0;t!==i;++t)e[t]=n[r+t];return e}interpolate_(){throw new Error(&quot;call to abstract method&quot;)}intervalChanged_(){}}class yh extends xh{constructor(t,e,n,i){super(t,e,n,i),this._weightPrev=-0,this._offsetPrev=-0,this._weightNext=-0,this._offsetNext=-0,this.DefaultSettings_={endingStart:It,endingEnd:It}}intervalChanged_(t,e,n){const i=this.parameterPositions;let r=t-2,s=t+1,a=i[r],o=i[s];if(void 0===a)switch(this.getSettings_().endingStart){case Ut:r=t,a=2*e-n;break;case Dt:r=i.length-2,a=e+i[r]-i[r+1];break;default:r=t,a=n}if(void 0===o)switch(this.getSettings_().endingEnd){case Ut:s=t,o=2*n-e;break;case Dt:s=1,o=n+i[1]-i[0];break;default:s=t-1,o=e}const l=.5*(n-e),c=this.valueSize;this._weightPrev=l/(e-a),this._weightNext=l/(o-n),this._offsetPrev=r*c,this._offsetNext=s*c}interpolate_(t,e,n,i){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=t*a,l=o-a,c=this._offsetPrev,h=this._offsetNext,u=this._weightPrev,d=this._weightNext,p=(n-e)/(i-e),m=p*p,f=m*p,g=-u*f+2*u*m-u*p,_=(1+u)*f+(-1.5-2*u)*m+(-.5+u)*p+1,v=(-1-d)*f+(1.5+d)*m+.5*p,x=d*f-d*m;for(let t=0;t!==a;++t)r[t]=g*s[c+t]+_*s[l+t]+v*s[o+t]+x*s[h+t];return r}}class Mh extends xh{constructor(t,e,n,i){super(t,e,n,i)}interpolate_(t,e,n,i){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=t*a,l=o-a,c=(n-e)/(i-e),h=1-c;for(let t=0;t!==a;++t)r[t]=s[l+t]*h+s[o+t]*c;return r}}class Sh extends xh{constructor(t,e,n,i){super(t,e,n,i)}interpolate_(t){return this.copySampleValue_(t-1)}}class bh{constructor(t,e,n,i){if(void 0===t)throw new Error(&quot;THREE.KeyframeTrack: track name is undefined&quot;);if(void 0===e||0===e.length)throw new Error(&quot;THREE.KeyframeTrack: no keyframes in track named &quot;+t);this.name=t,this.times=ph(e,this.TimeBufferType),this.values=ph(n,this.ValueBufferType),this.setInterpolation(i||this.DefaultInterpolation)}static toJSON(t){const e=t.constructor;let n;if(e.toJSON!==this.toJSON)n=e.toJSON(t);else{n={name:t.name,times:ph(t.times,Array),values:ph(t.values,Array)};const e=t.getInterpolation();e!==t.DefaultInterpolation&amp;&amp;(n.interpolation=e)}return n.type=t.ValueTypeName,n}InterpolantFactoryMethodDiscrete(t){return new Sh(this.times,this.values,this.getValueSize(),t)}InterpolantFactoryMethodLinear(t){return new Mh(this.times,this.values,this.getValueSize(),t)}InterpolantFactoryMethodSmooth(t){return new yh(this.times,this.values,this.getValueSize(),t)}setInterpolation(t){let e;switch(t){case Ct:e=this.InterpolantFactoryMethodDiscrete;break;case Lt:e=this.InterpolantFactoryMethodLinear;break;case Pt:e=this.InterpolantFactoryMethodSmooth}if(void 0===e){const e=&quot;unsupported interpolation for &quot;+this.ValueTypeName+&quot; keyframe track named &quot;+this.name;if(void 0===this.createInterpolant){if(t===this.DefaultInterpolation)throw new Error(e);this.setInterpolation(this.DefaultInterpolation)}return console.warn(&quot;THREE.KeyframeTrack:&quot;,e),this}return this.createInterpolant=e,this}getInterpolation(){switch(this.createInterpolant){case this.InterpolantFactoryMethodDiscrete:return Ct;case this.InterpolantFactoryMethodLinear:return Lt;case this.InterpolantFactoryMethodSmooth:return Pt}}getValueSize(){return this.values.length/this.times.length}shift(t){if(0!==t){const e=this.times;for(let n=0,i=e.length;n!==i;++n)e[n]+=t}return this}scale(t){if(1!==t){const e=this.times;for(let n=0,i=e.length;n!==i;++n)e[n]*=t}return this}trim(t,e){const n=this.times,i=n.length;let r=0,s=i-1;for(;r!==i&amp;&amp;n[r]&lt;t;)++r;for(;-1!==s&amp;&amp;n[s]&gt;e;)--s;if(++s,0!==r||s!==i){r&gt;=s&amp;&amp;(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=n.slice(r,s),this.values=this.values.slice(r*t,s*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&amp;&amp;(console.error(&quot;THREE.KeyframeTrack: Invalid value size in track.&quot;,this),t=!1);const n=this.times,i=this.values,r=n.length;0===r&amp;&amp;(console.error(&quot;THREE.KeyframeTrack: Track is empty.&quot;,this),t=!1);let s=null;for(let e=0;e!==r;e++){const i=n[e];if(&quot;number&quot;==typeof i&amp;&amp;isNaN(i)){console.error(&quot;THREE.KeyframeTrack: Time is not a valid number.&quot;,this,e,i),t=!1;break}if(null!==s&amp;&amp;s&gt;i){console.error(&quot;THREE.KeyframeTrack: Out of order keys.&quot;,this,e,i,s),t=!1;break}s=i}if(void 0!==i&amp;&amp;mh(i))for(let e=0,n=i.length;e!==n;++e){const n=i[e];if(isNaN(n)){console.error(&quot;THREE.KeyframeTrack: Value is not a valid number.&quot;,this,e,n),t=!1;break}}return t}optimize(){const t=this.times.slice(),e=this.values.slice(),n=this.getValueSize(),i=this.getInterpolation()===Pt,r=t.length-1;let s=1;for(let a=1;a&lt;r;++a){let r=!1;const o=t[a];if(o!==t[a+1]&amp;&amp;(1!==a||o!==t[0]))if(i)r=!0;else{const t=a*n,i=t-n,s=t+n;for(let a=0;a!==n;++a){const n=e[t+a];if(n!==e[i+a]||n!==e[s+a]){r=!0;break}}}if(r){if(a!==s){t[s]=t[a];const i=a*n,r=s*n;for(let t=0;t!==n;++t)e[r+t]=e[i+t]}++s}}if(r&gt;0){t[s]=t[r];for(let t=r*n,i=s*n,a=0;a!==n;++a)e[i+a]=e[t+a];++s}return s!==t.length?(this.times=t.slice(0,s),this.values=e.slice(0,s*n)):(this.times=t,this.values=e),this}clone(){const t=this.times.slice(),e=this.values.slice(),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}bh.prototype.TimeBufferType=Float32Array,bh.prototype.ValueBufferType=Float32Array,bh.prototype.DefaultInterpolation=Lt;class Th extends bh{}Th.prototype.ValueTypeName=&quot;bool&quot;,Th.prototype.ValueBufferType=Array,Th.prototype.DefaultInterpolation=Ct,Th.prototype.InterpolantFactoryMethodLinear=void 0,Th.prototype.InterpolantFactoryMethodSmooth=void 0;class Eh extends bh{}Eh.prototype.ValueTypeName=&quot;color&quot;;class wh extends bh{}wh.prototype.ValueTypeName=&quot;number&quot;;class Ah extends xh{constructor(t,e,n,i){super(t,e,n,i)}interpolate_(t,e,n,i){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(n-e)/(i-e);let l=t*a;for(let t=l+a;l!==t;l+=4)ke.slerpFlat(r,0,s,l-a,s,l,o);return r}}class Rh extends bh{InterpolantFactoryMethodLinear(t){return new Ah(this.times,this.values,this.getValueSize(),t)}}Rh.prototype.ValueTypeName=&quot;quaternion&quot;,Rh.prototype.DefaultInterpolation=Lt,Rh.prototype.InterpolantFactoryMethodSmooth=void 0;class Ch extends bh{}Ch.prototype.ValueTypeName=&quot;string&quot;,Ch.prototype.ValueBufferType=Array,Ch.prototype.DefaultInterpolation=Ct,Ch.prototype.InterpolantFactoryMethodLinear=void 0,Ch.prototype.InterpolantFactoryMethodSmooth=void 0;class Lh extends bh{}Lh.prototype.ValueTypeName=&quot;vector&quot;;class Ph{constructor(t,e=-1,n,i=2500){this.name=t,this.tracks=n,this.duration=e,this.blendMode=i,this.uuid=se(),this.duration&lt;0&amp;&amp;this.resetDuration()}static parse(t){const e=[],n=t.tracks,i=1/(t.fps||1);for(let t=0,r=n.length;t!==r;++t)e.push(Ih(n[t]).scale(i));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],n=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,i=n.length;t!==i;++t)e.push(bh.toJSON(n[t]));return i}static CreateFromMorphTargetSequence(t,e,n,i){const r=e.length,s=[];for(let t=0;t&lt;r;t++){let a=[],o=[];a.push((t+r-1)%r,t,(t+1)%r),o.push(0,1,0);const l=fh(a);a=gh(a,1,l),o=gh(o,1,l),i||0!==a[0]||(a.push(r),o.push(o[0])),s.push(new wh(&quot;.morphTargetInfluences[&quot;+e[t].name+&quot;]&quot;,a,o).scale(1/n))}return new this(t,-1,s)}static findByName(t,e){let n=t;if(!Array.isArray(t)){const e=t;n=e.geometry&amp;&amp;e.geometry.animations||e.animations}for(let t=0;t&lt;n.length;t++)if(n[t].name===e)return n[t];return null}static CreateClipsFromMorphTargetSequences(t,e,n){const i={},r=/^([\w-]*?)([\d]+)$/;for(let e=0,n=t.length;e&lt;n;e++){const n=t[e],s=n.name.match(r);if(s&amp;&amp;s.length&gt;1){const t=s[1];let e=i[t];e||(i[t]=e=[]),e.push(n)}}const s=[];for(const t in i)s.push(this.CreateFromMorphTargetSequence(t,i[t],e,n));return s}static parseAnimation(t,e){if(!t)return console.error(&quot;THREE.AnimationClip: No animation in JSONLoader data.&quot;),null;const n=function(t,e,n,i,r){if(0!==n.length){const s=[],a=[];_h(n,s,a,i),0!==s.length&amp;&amp;r.push(new t(e,s,a))}},i=[],r=t.name||&quot;default&quot;,s=t.fps||30,a=t.blendMode;let o=t.length||-1;const l=t.hierarchy||[];for(let t=0;t&lt;l.length;t++){const r=l[t].keys;if(r&amp;&amp;0!==r.length)if(r[0].morphTargets){const t={};let e;for(e=0;e&lt;r.length;e++)if(r[e].morphTargets)for(let n=0;n&lt;r[e].morphTargets.length;n++)t[r[e].morphTargets[n]]=-1;for(const n in t){const t=[],s=[];for(let i=0;i!==r[e].morphTargets.length;++i){const i=r[e];t.push(i.time),s.push(i.morphTarget===n?1:0)}i.push(new wh(&quot;.morphTargetInfluence[&quot;+n+&quot;]&quot;,t,s))}o=t.length*s}else{const s=&quot;.bones[&quot;+e[t].name+&quot;]&quot;;n(Lh,s+&quot;.position&quot;,r,&quot;pos&quot;,i),n(Rh,s+&quot;.quaternion&quot;,r,&quot;rot&quot;,i),n(Lh,s+&quot;.scale&quot;,r,&quot;scl&quot;,i)}}if(0===i.length)return null;return new this(r,o,i,a)}resetDuration(){let t=0;for(let e=0,n=this.tracks.length;e!==n;++e){const n=this.tracks[e];t=Math.max(t,n.times[n.times.length-1])}return this.duration=t,this}trim(){for(let t=0;t&lt;this.tracks.length;t++)this.tracks[t].trim(0,this.duration);return this}validate(){let t=!0;for(let e=0;e&lt;this.tracks.length;e++)t=t&amp;&amp;this.tracks[e].validate();return t}optimize(){for(let t=0;t&lt;this.tracks.length;t++)this.tracks[t].optimize();return this}clone(){const t=[];for(let e=0;e&lt;this.tracks.length;e++)t.push(this.tracks[e].clone());return new this.constructor(this.name,this.duration,t,this.blendMode)}toJSON(){return this.constructor.toJSON(this)}}function Ih(t){if(void 0===t.type)throw new Error(&quot;THREE.KeyframeTrack: track type undefined, can not parse&quot;);const e=function(t){switch(t.toLowerCase()){case&quot;scalar&quot;:case&quot;double&quot;:case&quot;float&quot;:case&quot;number&quot;:case&quot;integer&quot;:return wh;case&quot;vector&quot;:case&quot;vector2&quot;:case&quot;vector3&quot;:case&quot;vector4&quot;:return Lh;case&quot;color&quot;:return Eh;case&quot;quaternion&quot;:return Rh;case&quot;bool&quot;:case&quot;boolean&quot;:return Th;case&quot;string&quot;:return Ch}throw new Error(&quot;THREE.KeyframeTrack: Unsupported typeName: &quot;+t)}(t.type);if(void 0===t.times){const e=[],n=[];_h(t.keys,e,n,&quot;value&quot;),t.times=e,t.values=n}return void 0!==e.parse?e.parse(t):new e(t.name,t.times,t.values,t.interpolation)}const Uh={enabled:!1,files:{},add:function(t,e){!1!==this.enabled&amp;&amp;(this.files[t]=e)},get:function(t){if(!1!==this.enabled)return this.files[t]},remove:function(t){delete this.files[t]},clear:function(){this.files={}}};class Dh{constructor(t,e,n){const i=this;let r,s=!1,a=0,o=0;const l=[];this.onStart=void 0,this.onLoad=t,this.onProgress=e,this.onError=n,this.itemStart=function(t){o++,!1===s&amp;&amp;void 0!==i.onStart&amp;&amp;i.onStart(t,a,o),s=!0},this.itemEnd=function(t){a++,void 0!==i.onProgress&amp;&amp;i.onProgress(t,a,o),a===o&amp;&amp;(s=!1,void 0!==i.onLoad&amp;&amp;i.onLoad())},this.itemError=function(t){void 0!==i.onError&amp;&amp;i.onError(t)},this.resolveURL=function(t){return r?r(t):t},this.setURLModifier=function(t){return r=t,this},this.addHandler=function(t,e){return l.push(t,e),this},this.removeHandler=function(t){const e=l.indexOf(t);return-1!==e&amp;&amp;l.splice(e,2),this},this.getHandler=function(t){for(let e=0,n=l.length;e&lt;n;e+=2){const n=l[e],i=l[e+1];if(n.global&amp;&amp;(n.lastIndex=0),n.test(t))return i}return null}}}const Nh=new Dh;class Oh{constructor(t){this.manager=void 0!==t?t:Nh,this.crossOrigin=&quot;anonymous&quot;,this.withCredentials=!1,this.path=&quot;&quot;,this.resourcePath=&quot;&quot;,this.requestHeader={}}load(){}loadAsync(t,e){const n=this;return new Promise((function(i,r){n.load(t,i,e,r)}))}parse(){}setCrossOrigin(t){return this.crossOrigin=t,this}setWithCredentials(t){return this.withCredentials=t,this}setPath(t){return this.path=t,this}setResourcePath(t){return this.resourcePath=t,this}setRequestHeader(t){return this.requestHeader=t,this}}Oh.DEFAULT_MATERIAL_NAME=&quot;__DEFAULT&quot;;const Fh={};class Bh extends Error{constructor(t,e){super(t),this.response=e}}class zh extends Oh{constructor(t){super(t)}load(t,e,n,i){void 0===t&amp;&amp;(t=&quot;&quot;),void 0!==this.path&amp;&amp;(t=this.path+t),t=this.manager.resolveURL(t);const r=Uh.get(t);if(void 0!==r)return this.manager.itemStart(t),setTimeout((()=&gt;{e&amp;&amp;e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==Fh[t])return void Fh[t].push({onLoad:e,onProgress:n,onError:i});Fh[t]=[],Fh[t].push({onLoad:e,onProgress:n,onError:i});const s=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?&quot;include&quot;:&quot;same-origin&quot;}),a=this.mimeType,o=this.responseType;fetch(s).then((e=&gt;{if(200===e.status||0===e.status){if(0===e.status&amp;&amp;console.warn(&quot;THREE.FileLoader: HTTP Status 0 received.&quot;),&quot;undefined&quot;==typeof ReadableStream||void 0===e.body||void 0===e.body.getReader)return e;const n=Fh[t],i=e.body.getReader(),r=e.headers.get(&quot;Content-Length&quot;)||e.headers.get(&quot;X-File-Size&quot;),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){i.read().then((({done:i,value:r})=&gt;{if(i)t.close();else{o+=r.byteLength;const i=new ProgressEvent(&quot;progress&quot;,{lengthComputable:a,loaded:o,total:s});for(let t=0,e=n.length;t&lt;e;t++){const e=n[t];e.onProgress&amp;&amp;e.onProgress(i)}t.enqueue(r),e()}}))}()}});return new Response(l)}throw new Bh(`fetch for &quot;${e.url}&quot; responded with ${e.status}: ${e.statusText}`,e)})).then((t=&gt;{switch(o){case&quot;arraybuffer&quot;:return t.arrayBuffer();case&quot;blob&quot;:return t.blob();case&quot;document&quot;:return t.text().then((t=&gt;(new DOMParser).parseFromString(t,a)));case&quot;json&quot;:return t.json();default:if(void 0===a)return t.text();{const e=/charset=&quot;?([^;&quot;\s]*)&quot;?/i.exec(a),n=e&amp;&amp;e[1]?e[1].toLowerCase():void 0,i=new TextDecoder(n);return t.arrayBuffer().then((t=&gt;i.decode(t)))}}})).then((e=&gt;{Uh.add(t,e);const n=Fh[t];delete Fh[t];for(let t=0,i=n.length;t&lt;i;t++){const i=n[t];i.onLoad&amp;&amp;i.onLoad(e)}})).catch((e=&gt;{const n=Fh[t];if(void 0===n)throw this.manager.itemError(t),e;delete Fh[t];for(let t=0,i=n.length;t&lt;i;t++){const i=n[t];i.onError&amp;&amp;i.onError(e)}this.manager.itemError(t)})).finally((()=&gt;{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class Gh extends Oh{constructor(t){super(t)}load(t,e,n,i){void 0!==this.path&amp;&amp;(t=this.path+t),t=this.manager.resolveURL(t);const r=this,s=Uh.get(t);if(void 0!==s)return r.manager.itemStart(t),setTimeout((function(){e&amp;&amp;e(s),r.manager.itemEnd(t)}),0),s;const a=ye(&quot;img&quot;);function o(){c(),Uh.add(t,this),e&amp;&amp;e(this),r.manager.itemEnd(t)}function l(e){c(),i&amp;&amp;i(e),r.manager.itemError(t),r.manager.itemEnd(t)}function c(){a.removeEventListener(&quot;load&quot;,o,!1),a.removeEventListener(&quot;error&quot;,l,!1)}return a.addEventListener(&quot;load&quot;,o,!1),a.addEventListener(&quot;error&quot;,l,!1),&quot;data:&quot;!==t.slice(0,5)&amp;&amp;void 0!==this.crossOrigin&amp;&amp;(a.crossOrigin=this.crossOrigin),r.manager.itemStart(t),a.src=t,a}}class Hh extends jn{constructor(t,e=1){super(),this.isLight=!0,this.type=&quot;Light&quot;,this.color=new ci(t),this.intensity=e}dispose(){}copy(t,e){return super.copy(t,e),this.color.copy(t.color),this.intensity=t.intensity,this}toJSON(t){const e=super.toJSON(t);return e.object.color=this.color.getHex(),e.object.intensity=this.intensity,void 0!==this.groundColor&amp;&amp;(e.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&amp;&amp;(e.object.distance=this.distance),void 0!==this.angle&amp;&amp;(e.object.angle=this.angle),void 0!==this.decay&amp;&amp;(e.object.decay=this.decay),void 0!==this.penumbra&amp;&amp;(e.object.penumbra=this.penumbra),void 0!==this.shadow&amp;&amp;(e.object.shadow=this.shadow.toJSON()),e}}class Vh extends Hh{constructor(t,e,n){super(t,n),this.isHemisphereLight=!0,this.type=&quot;HemisphereLight&quot;,this.position.copy(jn.DEFAULT_UP),this.updateMatrix(),this.groundColor=new ci(e)}copy(t,e){return super.copy(t,e),this.groundColor.copy(t.groundColor),this}}const kh=new Mn,Wh=new We,Xh=new We;class jh{constructor(t){this.camera=t,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new me(512,512),this.map=null,this.mapPass=null,this.matrix=new Mn,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new gr,this._frameExtents=new me(1,1),this._viewportCount=1,this._viewports=[new Be(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(t){const e=this.camera,n=this.matrix;Wh.setFromMatrixPosition(t.matrixWorld),e.position.copy(Wh),Xh.setFromMatrixPosition(t.target.matrixWorld),e.lookAt(Xh),e.updateMatrixWorld(),kh.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this._frustum.setFromProjectionMatrix(kh),n.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),n.multiply(kh)}getViewport(t){return this._viewports[t]}getFrameExtents(){return this._frameExtents}dispose(){this.map&amp;&amp;this.map.dispose(),this.mapPass&amp;&amp;this.mapPass.dispose()}copy(t){return this.camera=t.camera.clone(),this.bias=t.bias,this.radius=t.radius,this.mapSize.copy(t.mapSize),this}clone(){return(new this.constructor).copy(this)}toJSON(){const t={};return 0!==this.bias&amp;&amp;(t.bias=this.bias),0!==this.normalBias&amp;&amp;(t.normalBias=this.normalBias),1!==this.radius&amp;&amp;(t.radius=this.radius),512===this.mapSize.x&amp;&amp;512===this.mapSize.y||(t.mapSize=this.mapSize.toArray()),t.camera=this.camera.toJSON(!1).object,delete t.camera.matrix,t}}class qh extends jh{constructor(){super(new sr(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(t){const e=this.camera,n=2*re*t.angle*this.focus,i=this.mapSize.width/this.mapSize.height,r=t.distance||e.far;n===e.fov&amp;&amp;i===e.aspect&amp;&amp;r===e.far||(e.fov=n,e.aspect=i,e.far=r,e.updateProjectionMatrix()),super.updateMatrices(t)}copy(t){return super.copy(t),this.focus=t.focus,this}}class Yh extends Hh{constructor(t,e,n=0,i=Math.PI/3,r=0,s=2){super(t,e),this.isSpotLight=!0,this.type=&quot;SpotLight&quot;,this.position.copy(jn.DEFAULT_UP),this.updateMatrix(),this.target=new jn,this.distance=n,this.angle=i,this.penumbra=r,this.decay=s,this.map=null,this.shadow=new qh}get power(){return this.intensity*Math.PI}set power(t){this.intensity=t/Math.PI}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.angle=t.angle,this.penumbra=t.penumbra,this.decay=t.decay,this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}const Zh=new Mn,Jh=new We,Kh=new We;class $h extends jh{constructor(){super(new sr(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new me(4,2),this._viewportCount=6,this._viewports=[new Be(2,1,1,1),new Be(0,1,1,1),new Be(3,1,1,1),new Be(1,1,1,1),new Be(3,0,1,1),new Be(1,0,1,1)],this._cubeDirections=[new We(1,0,0),new We(-1,0,0),new We(0,0,1),new We(0,0,-1),new We(0,1,0),new We(0,-1,0)],this._cubeUps=[new We(0,1,0),new We(0,1,0),new We(0,1,0),new We(0,1,0),new We(0,0,1),new We(0,0,-1)]}updateMatrices(t,e=0){const n=this.camera,i=this.matrix,r=t.distance||n.far;r!==n.far&amp;&amp;(n.far=r,n.updateProjectionMatrix()),Jh.setFromMatrixPosition(t.matrixWorld),n.position.copy(Jh),Kh.copy(n.position),Kh.add(this._cubeDirections[e]),n.up.copy(this._cubeUps[e]),n.lookAt(Kh),n.updateMatrixWorld(),i.makeTranslation(-Jh.x,-Jh.y,-Jh.z),Zh.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse),this._frustum.setFromProjectionMatrix(Zh)}}class Qh extends Hh{constructor(t,e,n=0,i=2){super(t,e),this.isPointLight=!0,this.type=&quot;PointLight&quot;,this.distance=n,this.decay=i,this.shadow=new $h}get power(){return 4*this.intensity*Math.PI}set power(t){this.intensity=t/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.decay=t.decay,this.shadow=t.shadow.clone(),this}}class tu extends jh{constructor(){super(new Lr(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class eu extends Hh{constructor(t,e){super(t,e),this.isDirectionalLight=!0,this.type=&quot;DirectionalLight&quot;,this.position.copy(jn.DEFAULT_UP),this.updateMatrix(),this.target=new jn,this.shadow=new tu}dispose(){this.shadow.dispose()}copy(t){return super.copy(t),this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}class nu extends Hh{constructor(t,e){super(t,e),this.isAmbientLight=!0,this.type=&quot;AmbientLight&quot;}}class iu extends Hh{constructor(t,e,n=10,i=10){super(t,e),this.isRectAreaLight=!0,this.type=&quot;RectAreaLight&quot;,this.width=n,this.height=i}get power(){return this.intensity*this.width*this.height*Math.PI}set power(t){this.intensity=t/(this.width*this.height*Math.PI)}copy(t){return super.copy(t),this.width=t.width,this.height=t.height,this}toJSON(t){const e=super.toJSON(t);return e.object.width=this.width,e.object.height=this.height,e}}class ru{constructor(){this.isSphericalHarmonics3=!0,this.coefficients=[];for(let t=0;t&lt;9;t++)this.coefficients.push(new We)}set(t){for(let e=0;e&lt;9;e++)this.coefficients[e].copy(t[e]);return this}zero(){for(let t=0;t&lt;9;t++)this.coefficients[t].set(0,0,0);return this}getAt(t,e){const n=t.x,i=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.282095),e.addScaledVector(s[1],.488603*i),e.addScaledVector(s[2],.488603*r),e.addScaledVector(s[3],.488603*n),e.addScaledVector(s[4],n*i*1.092548),e.addScaledVector(s[5],i*r*1.092548),e.addScaledVector(s[6],.315392*(3*r*r-1)),e.addScaledVector(s[7],n*r*1.092548),e.addScaledVector(s[8],.546274*(n*n-i*i)),e}getIrradianceAt(t,e){const n=t.x,i=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.886227),e.addScaledVector(s[1],1.023328*i),e.addScaledVector(s[2],1.023328*r),e.addScaledVector(s[3],1.023328*n),e.addScaledVector(s[4],.858086*n*i),e.addScaledVector(s[5],.858086*i*r),e.addScaledVector(s[6],.743125*r*r-.247708),e.addScaledVector(s[7],.858086*n*r),e.addScaledVector(s[8],.429043*(n*n-i*i)),e}add(t){for(let e=0;e&lt;9;e++)this.coefficients[e].add(t.coefficients[e]);return this}addScaledSH(t,e){for(let n=0;n&lt;9;n++)this.coefficients[n].addScaledVector(t.coefficients[n],e);return this}scale(t){for(let e=0;e&lt;9;e++)this.coefficients[e].multiplyScalar(t);return this}lerp(t,e){for(let n=0;n&lt;9;n++)this.coefficients[n].lerp(t.coefficients[n],e);return this}equals(t){for(let e=0;e&lt;9;e++)if(!this.coefficients[e].equals(t.coefficients[e]))return!1;return!0}copy(t){return this.set(t.coefficients)}clone(){return(new this.constructor).copy(this)}fromArray(t,e=0){const n=this.coefficients;for(let i=0;i&lt;9;i++)n[i].fromArray(t,e+3*i);return this}toArray(t=[],e=0){const n=this.coefficients;for(let i=0;i&lt;9;i++)n[i].toArray(t,e+3*i);return t}static getBasisAt(t,e){const n=t.x,i=t.y,r=t.z;e[0]=.282095,e[1]=.488603*i,e[2]=.488603*r,e[3]=.488603*n,e[4]=1.092548*n*i,e[5]=1.092548*i*r,e[6]=.315392*(3*r*r-1),e[7]=1.092548*n*r,e[8]=.546274*(n*n-i*i)}}class su extends Hh{constructor(t=new ru,e=1){super(void 0,e),this.isLightProbe=!0,this.sh=t}copy(t){return super.copy(t),this.sh.copy(t.sh),this}fromJSON(t){return this.intensity=t.intensity,this.sh.fromArray(t.sh),this}toJSON(t){const e=super.toJSON(t);return e.object.sh=this.sh.toArray(),e}}class au extends Oh{constructor(t){super(t),this.textures={}}load(t,e,n,i){const r=this,s=new zh(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(t,(function(n){try{e(r.parse(JSON.parse(n)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),n,i)}parse(t){const e=this.textures;function n(t){return void 0===e[t]&amp;&amp;console.warn(&quot;THREE.MaterialLoader: Undefined texture&quot;,t),e[t]}const i=au.createMaterialFromType(t.type);if(void 0!==t.uuid&amp;&amp;(i.uuid=t.uuid),void 0!==t.name&amp;&amp;(i.name=t.name),void 0!==t.color&amp;&amp;void 0!==i.color&amp;&amp;i.color.setHex(t.color),void 0!==t.roughness&amp;&amp;(i.roughness=t.roughness),void 0!==t.metalness&amp;&amp;(i.metalness=t.metalness),void 0!==t.sheen&amp;&amp;(i.sheen=t.sheen),void 0!==t.sheenColor&amp;&amp;(i.sheenColor=(new ci).setHex(t.sheenColor)),void 0!==t.sheenRoughness&amp;&amp;(i.sheenRoughness=t.sheenRoughness),void 0!==t.emissive&amp;&amp;void 0!==i.emissive&amp;&amp;i.emissive.setHex(t.emissive),void 0!==t.specular&amp;&amp;void 0!==i.specular&amp;&amp;i.specular.setHex(t.specular),void 0!==t.specularIntensity&amp;&amp;(i.specularIntensity=t.specularIntensity),void 0!==t.specularColor&amp;&amp;void 0!==i.specularColor&amp;&amp;i.specularColor.setHex(t.specularColor),void 0!==t.shininess&amp;&amp;(i.shininess=t.shininess),void 0!==t.clearcoat&amp;&amp;(i.clearcoat=t.clearcoat),void 0!==t.clearcoatRoughness&amp;&amp;(i.clearcoatRoughness=t.clearcoatRoughness),void 0!==t.iridescence&amp;&amp;(i.iridescence=t.iridescence),void 0!==t.iridescenceIOR&amp;&amp;(i.iridescenceIOR=t.iridescenceIOR),void 0!==t.iridescenceThicknessRange&amp;&amp;(i.iridescenceThicknessRange=t.iridescenceThicknessRange),void 0!==t.transmission&amp;&amp;(i.transmission=t.transmission),void 0!==t.thickness&amp;&amp;(i.thickness=t.thickness),void 0!==t.attenuationDistance&amp;&amp;(i.attenuationDistance=t.attenuationDistance),void 0!==t.attenuationColor&amp;&amp;void 0!==i.attenuationColor&amp;&amp;i.attenuationColor.setHex(t.attenuationColor),void 0!==t.anisotropy&amp;&amp;(i.anisotropy=t.anisotropy),void 0!==t.anisotropyRotation&amp;&amp;(i.anisotropyRotation=t.anisotropyRotation),void 0!==t.fog&amp;&amp;(i.fog=t.fog),void 0!==t.flatShading&amp;&amp;(i.flatShading=t.flatShading),void 0!==t.blending&amp;&amp;(i.blending=t.blending),void 0!==t.combine&amp;&amp;(i.combine=t.combine),void 0!==t.side&amp;&amp;(i.side=t.side),void 0!==t.shadowSide&amp;&amp;(i.shadowSide=t.shadowSide),void 0!==t.opacity&amp;&amp;(i.opacity=t.opacity),void 0!==t.transparent&amp;&amp;(i.transparent=t.transparent),void 0!==t.alphaTest&amp;&amp;(i.alphaTest=t.alphaTest),void 0!==t.alphaHash&amp;&amp;(i.alphaHash=t.alphaHash),void 0!==t.depthFunc&amp;&amp;(i.depthFunc=t.depthFunc),void 0!==t.depthTest&amp;&amp;(i.depthTest=t.depthTest),void 0!==t.depthWrite&amp;&amp;(i.depthWrite=t.depthWrite),void 0!==t.colorWrite&amp;&amp;(i.colorWrite=t.colorWrite),void 0!==t.blendSrc&amp;&amp;(i.blendSrc=t.blendSrc),void 0!==t.blendDst&amp;&amp;(i.blendDst=t.blendDst),void 0!==t.blendEquation&amp;&amp;(i.blendEquation=t.blendEquation),void 0!==t.blendSrcAlpha&amp;&amp;(i.blendSrcAlpha=t.blendSrcAlpha),void 0!==t.blendDstAlpha&amp;&amp;(i.blendDstAlpha=t.blendDstAlpha),void 0!==t.blendEquationAlpha&amp;&amp;(i.blendEquationAlpha=t.blendEquationAlpha),void 0!==t.blendColor&amp;&amp;void 0!==i.blendColor&amp;&amp;i.blendColor.setHex(t.blendColor),void 0!==t.blendAlpha&amp;&amp;(i.blendAlpha=t.blendAlpha),void 0!==t.stencilWriteMask&amp;&amp;(i.stencilWriteMask=t.stencilWriteMask),void 0!==t.stencilFunc&amp;&amp;(i.stencilFunc=t.stencilFunc),void 0!==t.stencilRef&amp;&amp;(i.stencilRef=t.stencilRef),void 0!==t.stencilFuncMask&amp;&amp;(i.stencilFuncMask=t.stencilFuncMask),void 0!==t.stencilFail&amp;&amp;(i.stencilFail=t.stencilFail),void 0!==t.stencilZFail&amp;&amp;(i.stencilZFail=t.stencilZFail),void 0!==t.stencilZPass&amp;&amp;(i.stencilZPass=t.stencilZPass),void 0!==t.stencilWrite&amp;&amp;(i.stencilWrite=t.stencilWrite),void 0!==t.wireframe&amp;&amp;(i.wireframe=t.wireframe),void 0!==t.wireframeLinewidth&amp;&amp;(i.wireframeLinewidth=t.wireframeLinewidth),void 0!==t.wireframeLinecap&amp;&amp;(i.wireframeLinecap=t.wireframeLinecap),void 0!==t.wireframeLinejoin&amp;&amp;(i.wireframeLinejoin=t.wireframeLinejoin),void 0!==t.rotation&amp;&amp;(i.rotation=t.rotation),void 0!==t.linewidth&amp;&amp;(i.linewidth=t.linewidth),void 0!==t.dashSize&amp;&amp;(i.dashSize=t.dashSize),void 0!==t.gapSize&amp;&amp;(i.gapSize=t.gapSize),void 0!==t.scale&amp;&amp;(i.scale=t.scale),void 0!==t.polygonOffset&amp;&amp;(i.polygonOffset=t.polygonOffset),void 0!==t.polygonOffsetFactor&amp;&amp;(i.polygonOffsetFactor=t.polygonOffsetFactor),void 0!==t.polygonOffsetUnits&amp;&amp;(i.polygonOffsetUnits=t.polygonOffsetUnits),void 0!==t.dithering&amp;&amp;(i.dithering=t.dithering),void 0!==t.alphaToCoverage&amp;&amp;(i.alphaToCoverage=t.alphaToCoverage),void 0!==t.premultipliedAlpha&amp;&amp;(i.premultipliedAlpha=t.premultipliedAlpha),void 0!==t.forceSinglePass&amp;&amp;(i.forceSinglePass=t.forceSinglePass),void 0!==t.visible&amp;&amp;(i.visible=t.visible),void 0!==t.toneMapped&amp;&amp;(i.toneMapped=t.toneMapped),void 0!==t.userData&amp;&amp;(i.userData=t.userData),void 0!==t.vertexColors&amp;&amp;(&quot;number&quot;==typeof t.vertexColors?i.vertexColors=t.vertexColors&gt;0:i.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(i.uniforms[e]={},r.type){case&quot;t&quot;:i.uniforms[e].value=n(r.value);break;case&quot;c&quot;:i.uniforms[e].value=(new ci).setHex(r.value);break;case&quot;v2&quot;:i.uniforms[e].value=(new me).fromArray(r.value);break;case&quot;v3&quot;:i.uniforms[e].value=(new We).fromArray(r.value);break;case&quot;v4&quot;:i.uniforms[e].value=(new Be).fromArray(r.value);break;case&quot;m3&quot;:i.uniforms[e].value=(new fe).fromArray(r.value);break;case&quot;m4&quot;:i.uniforms[e].value=(new Mn).fromArray(r.value);break;default:i.uniforms[e].value=r.value}}if(void 0!==t.defines&amp;&amp;(i.defines=t.defines),void 0!==t.vertexShader&amp;&amp;(i.vertexShader=t.vertexShader),void 0!==t.fragmentShader&amp;&amp;(i.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&amp;&amp;(i.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)i.extensions[e]=t.extensions[e];if(void 0!==t.lights&amp;&amp;(i.lights=t.lights),void 0!==t.clipping&amp;&amp;(i.clipping=t.clipping),void 0!==t.size&amp;&amp;(i.size=t.size),void 0!==t.sizeAttenuation&amp;&amp;(i.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&amp;&amp;(i.map=n(t.map)),void 0!==t.matcap&amp;&amp;(i.matcap=n(t.matcap)),void 0!==t.alphaMap&amp;&amp;(i.alphaMap=n(t.alphaMap)),void 0!==t.bumpMap&amp;&amp;(i.bumpMap=n(t.bumpMap)),void 0!==t.bumpScale&amp;&amp;(i.bumpScale=t.bumpScale),void 0!==t.normalMap&amp;&amp;(i.normalMap=n(t.normalMap)),void 0!==t.normalMapType&amp;&amp;(i.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&amp;&amp;(e=[e,e]),i.normalScale=(new me).fromArray(e)}return void 0!==t.displacementMap&amp;&amp;(i.displacementMap=n(t.displacementMap)),void 0!==t.displacementScale&amp;&amp;(i.displacementScale=t.displacementScale),void 0!==t.displacementBias&amp;&amp;(i.displacementBias=t.displacementBias),void 0!==t.roughnessMap&amp;&amp;(i.roughnessMap=n(t.roughnessMap)),void 0!==t.metalnessMap&amp;&amp;(i.metalnessMap=n(t.metalnessMap)),void 0!==t.emissiveMap&amp;&amp;(i.emissiveMap=n(t.emissiveMap)),void 0!==t.emissiveIntensity&amp;&amp;(i.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&amp;&amp;(i.specularMap=n(t.specularMap)),void 0!==t.specularIntensityMap&amp;&amp;(i.specularIntensityMap=n(t.specularIntensityMap)),void 0!==t.specularColorMap&amp;&amp;(i.specularColorMap=n(t.specularColorMap)),void 0!==t.envMap&amp;&amp;(i.envMap=n(t.envMap)),void 0!==t.envMapIntensity&amp;&amp;(i.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&amp;&amp;(i.reflectivity=t.reflectivity),void 0!==t.refractionRatio&amp;&amp;(i.refractionRatio=t.refractionRatio),void 0!==t.lightMap&amp;&amp;(i.lightMap=n(t.lightMap)),void 0!==t.lightMapIntensity&amp;&amp;(i.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&amp;&amp;(i.aoMap=n(t.aoMap)),void 0!==t.aoMapIntensity&amp;&amp;(i.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&amp;&amp;(i.gradientMap=n(t.gradientMap)),void 0!==t.clearcoatMap&amp;&amp;(i.clearcoatMap=n(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&amp;&amp;(i.clearcoatRoughnessMap=n(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&amp;&amp;(i.clearcoatNormalMap=n(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&amp;&amp;(i.clearcoatNormalScale=(new me).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&amp;&amp;(i.iridescenceMap=n(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&amp;&amp;(i.iridescenceThicknessMap=n(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&amp;&amp;(i.transmissionMap=n(t.transmissionMap)),void 0!==t.thicknessMap&amp;&amp;(i.thicknessMap=n(t.thicknessMap)),void 0!==t.anisotropyMap&amp;&amp;(i.anisotropyMap=n(t.anisotropyMap)),void 0!==t.sheenColorMap&amp;&amp;(i.sheenColorMap=n(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&amp;&amp;(i.sheenRoughnessMap=n(t.sheenRoughnessMap)),i}setTextures(t){return this.textures=t,this}static createMaterialFromType(t){return new{ShadowMaterial:ih,SpriteMaterial:lo,RawShaderMaterial:rh,ShaderMaterial:ir,PointsMaterial:wl,MeshPhysicalMaterial:ah,MeshStandardMaterial:sh,MeshPhongMaterial:oh,MeshToonMaterial:lh,MeshNormalMaterial:ch,MeshLambertMaterial:hh,MeshDepthMaterial:Ha,MeshDistanceMaterial:Va,MeshBasicMaterial:pi,MeshMatcapMaterial:uh,LineDashedMaterial:dh,LineBasicMaterial:fl,Material:di}[t]}}class ou{static decodeText(t){if(&quot;undefined&quot;!=typeof TextDecoder)return(new TextDecoder).decode(t);let e=&quot;&quot;;for(let n=0,i=t.length;n&lt;i;n++)e+=String.fromCharCode(t[n]);try{return decodeURIComponent(escape(e))}catch(t){return e}}static extractUrlBase(t){const e=t.lastIndexOf(&quot;/&quot;);return-1===e?&quot;./&quot;:t.slice(0,e+1)}static resolveURL(t,e){return&quot;string&quot;!=typeof t||&quot;&quot;===t?&quot;&quot;:(/^https?:\/\//i.test(e)&amp;&amp;/^\//.test(t)&amp;&amp;(e=e.replace(/(^https?:\/\/[^\/]+).*/i,&quot;$1&quot;)),/^(https?:)?\/\//i.test(t)||/^data:.*,.*$/i.test(t)||/^blob:.*$/i.test(t)?t:e+t)}}class lu extends Ii{constructor(){super(),this.isInstancedBufferGeometry=!0,this.type=&quot;InstancedBufferGeometry&quot;,this.instanceCount=1/0}copy(t){return super.copy(t),this.instanceCount=t.instanceCount,this}toJSON(){const t=super.toJSON();return t.instanceCount=this.instanceCount,t.isInstancedBufferGeometry=!0,t}}class cu extends Oh{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new zh(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(t,(function(n){try{e(r.parse(JSON.parse(n)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),n,i)}parse(t){const e={},n={};function i(t,i){if(void 0!==e[i])return e[i];const r=t.interleavedBuffers[i],s=function(t,e){if(void 0!==n[e])return n[e];const i=t.arrayBuffers,r=i[e],s=new Uint32Array(r).buffer;return n[e]=s,s}(t,r.buffer),a=xe(r.type,s),o=new so(a,r.stride);return o.uuid=r.uuid,e[i]=o,o}const r=t.isInstancedBufferGeometry?new lu:new Ii,s=t.data.index;if(void 0!==s){const t=xe(s.type,s.array);r.setIndex(new Mi(t,1))}const a=t.data.attributes;for(const e in a){const n=a[e];let s;if(n.isInterleavedBufferAttribute){const e=i(t.data,n.data);s=new oo(e,n.itemSize,n.offset,n.normalized)}else{const t=xe(n.type,n.array);s=new(n.isInstancedBufferAttribute?ko:Mi)(t,n.itemSize,n.normalized)}void 0!==n.name&amp;&amp;(s.name=n.name),void 0!==n.usage&amp;&amp;s.setUsage(n.usage),r.setAttribute(e,s)}const o=t.data.morphAttributes;if(o)for(const e in o){const n=o[e],s=[];for(let e=0,r=n.length;e&lt;r;e++){const r=n[e];let a;if(r.isInterleavedBufferAttribute){const e=i(t.data,r.data);a=new oo(e,r.itemSize,r.offset,r.normalized)}else{const t=xe(r.type,r.array);a=new Mi(t,r.itemSize,r.normalized)}void 0!==r.name&amp;&amp;(a.name=r.name),s.push(a)}r.morphAttributes[e]=s}t.data.morphTargetsRelative&amp;&amp;(r.morphTargetsRelative=!0);const l=t.data.groups||t.data.drawcalls||t.data.offsets;if(void 0!==l)for(let t=0,e=l.length;t!==e;++t){const e=l[t];r.addGroup(e.start,e.count,e.materialIndex)}const c=t.data.boundingSphere;if(void 0!==c){const t=new We;void 0!==c.center&amp;&amp;t.fromArray(c.center),r.boundingSphere=new dn(t,c.radius)}return t.name&amp;&amp;(r.name=t.name),t.userData&amp;&amp;(r.userData=t.userData),r}}const hu={UVMapping:S,CubeReflectionMapping:b,CubeRefractionMapping:T,EquirectangularReflectionMapping:E,EquirectangularRefractionMapping:w,CubeUVReflectionMapping:A},uu={RepeatWrapping:R,ClampToEdgeWrapping:C,MirroredRepeatWrapping:L},du={NearestFilter:P,NearestMipmapNearestFilter:I,NearestMipmapLinearFilter:U,LinearFilter:D,LinearMipmapNearestFilter:N,LinearMipmapLinearFilter:O};let pu;class mu{static getContext(){return void 0===pu&amp;&amp;(pu=new(window.AudioContext||window.webkitAudioContext)),pu}static setContext(t){pu=t}}const fu=new Mn,gu=new Mn,_u=new Mn;class vu{constructor(t=!0){this.autoStart=t,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}start(){this.startTime=xu(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0}stop(){this.getElapsedTime(),this.running=!1,this.autoStart=!1}getElapsedTime(){return this.getDelta(),this.elapsedTime}getDelta(){let t=0;if(this.autoStart&amp;&amp;!this.running)return this.start(),0;if(this.running){const e=xu();t=(e-this.oldTime)/1e3,this.oldTime=e,this.elapsedTime+=t}return t}}function xu(){return(&quot;undefined&quot;==typeof performance?Date:performance).now()}const yu=new We,Mu=new ke,Su=new We,bu=new We;class Tu extends jn{constructor(t){super(),this.type=&quot;Audio&quot;,this.listener=t,this.context=t.context,this.gain=this.context.createGain(),this.gain.connect(t.getInput()),this.autoplay=!1,this.buffer=null,this.detune=0,this.loop=!1,this.loopStart=0,this.loopEnd=0,this.offset=0,this.duration=void 0,this.playbackRate=1,this.isPlaying=!1,this.hasPlaybackControl=!0,this.source=null,this.sourceType=&quot;empty&quot;,this._startedAt=0,this._progress=0,this._connected=!1,this.filters=[]}getOutput(){return this.gain}setNodeSource(t){return this.hasPlaybackControl=!1,this.sourceType=&quot;audioNode&quot;,this.source=t,this.connect(),this}setMediaElementSource(t){return this.hasPlaybackControl=!1,this.sourceType=&quot;mediaNode&quot;,this.source=this.context.createMediaElementSource(t),this.connect(),this}setMediaStreamSource(t){return this.hasPlaybackControl=!1,this.sourceType=&quot;mediaStreamNode&quot;,this.source=this.context.createMediaStreamSource(t),this.connect(),this}setBuffer(t){return this.buffer=t,this.sourceType=&quot;buffer&quot;,this.autoplay&amp;&amp;this.play(),this}play(t=0){if(!0===this.isPlaying)return void console.warn(&quot;THREE.Audio: Audio is already playing.&quot;);if(!1===this.hasPlaybackControl)return void console.warn(&quot;THREE.Audio: this Audio has no playback control.&quot;);this._startedAt=this.context.currentTime+t;const e=this.context.createBufferSource();return e.buffer=this.buffer,e.loop=this.loop,e.loopStart=this.loopStart,e.loopEnd=this.loopEnd,e.onended=this.onEnded.bind(this),e.start(this._startedAt,this._progress+this.offset,this.duration),this.isPlaying=!0,this.source=e,this.setDetune(this.detune),this.setPlaybackRate(this.playbackRate),this.connect()}pause(){if(!1!==this.hasPlaybackControl)return!0===this.isPlaying&amp;&amp;(this._progress+=Math.max(this.context.currentTime-this._startedAt,0)*this.playbackRate,!0===this.loop&amp;&amp;(this._progress=this._progress%(this.duration||this.buffer.duration)),this.source.stop(),this.source.onended=null,this.isPlaying=!1),this;console.warn(&quot;THREE.Audio: this Audio has no playback control.&quot;)}stop(){if(!1!==this.hasPlaybackControl)return this._progress=0,null!==this.source&amp;&amp;(this.source.stop(),this.source.onended=null),this.isPlaying=!1,this;console.warn(&quot;THREE.Audio: this Audio has no playback control.&quot;)}connect(){if(this.filters.length&gt;0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t&lt;e;t++)this.filters[t-1].connect(this.filters[t]);this.filters[this.filters.length-1].connect(this.getOutput())}else this.source.connect(this.getOutput());return this._connected=!0,this}disconnect(){if(!1!==this._connected){if(this.filters.length&gt;0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t&lt;e;t++)this.filters[t-1].disconnect(this.filters[t]);this.filters[this.filters.length-1].disconnect(this.getOutput())}else this.source.disconnect(this.getOutput());return this._connected=!1,this}}getFilters(){return this.filters}setFilters(t){return t||(t=[]),!0===this._connected?(this.disconnect(),this.filters=t.slice(),this.connect()):this.filters=t.slice(),this}setDetune(t){if(this.detune=t,void 0!==this.source.detune)return!0===this.isPlaying&amp;&amp;this.source.detune.setTargetAtTime(this.detune,this.context.currentTime,.01),this}getDetune(){return this.detune}getFilter(){return this.getFilters()[0]}setFilter(t){return this.setFilters(t?[t]:[])}setPlaybackRate(t){if(!1!==this.hasPlaybackControl)return this.playbackRate=t,!0===this.isPlaying&amp;&amp;this.source.playbackRate.setTargetAtTime(this.playbackRate,this.context.currentTime,.01),this;console.warn(&quot;THREE.Audio: this Audio has no playback control.&quot;)}getPlaybackRate(){return this.playbackRate}onEnded(){this.isPlaying=!1}getLoop(){return!1===this.hasPlaybackControl?(console.warn(&quot;THREE.Audio: this Audio has no playback control.&quot;),!1):this.loop}setLoop(t){if(!1!==this.hasPlaybackControl)return this.loop=t,!0===this.isPlaying&amp;&amp;(this.source.loop=this.loop),this;console.warn(&quot;THREE.Audio: this Audio has no playback control.&quot;)}setLoopStart(t){return this.loopStart=t,this}setLoopEnd(t){return this.loopEnd=t,this}getVolume(){return this.gain.gain.value}setVolume(t){return this.gain.gain.setTargetAtTime(t,this.context.currentTime,.01),this}}const Eu=new We,wu=new ke,Au=new We,Ru=new We;class Cu{constructor(t,e,n){let i,r,s;switch(this.binding=t,this.valueSize=n,e){case&quot;quaternion&quot;:i=this._slerp,r=this._slerpAdditive,s=this._setAdditiveIdentityQuaternion,this.buffer=new Float64Array(6*n),this._workIndex=5;break;case&quot;string&quot;:case&quot;bool&quot;:i=this._select,r=this._select,s=this._setAdditiveIdentityOther,this.buffer=new Array(5*n);break;default:i=this._lerp,r=this._lerpAdditive,s=this._setAdditiveIdentityNumeric,this.buffer=new Float64Array(5*n)}this._mixBufferRegion=i,this._mixBufferRegionAdditive=r,this._setIdentity=s,this._origIndex=3,this._addIndex=4,this.cumulativeWeight=0,this.cumulativeWeightAdditive=0,this.useCount=0,this.referenceCount=0}accumulate(t,e){const n=this.buffer,i=this.valueSize,r=t*i+i;let s=this.cumulativeWeight;if(0===s){for(let t=0;t!==i;++t)n[r+t]=n[t];s=e}else{s+=e;const t=e/s;this._mixBufferRegion(n,r,0,t,i)}this.cumulativeWeight=s}accumulateAdditive(t){const e=this.buffer,n=this.valueSize,i=n*this._addIndex;0===this.cumulativeWeightAdditive&amp;&amp;this._setIdentity(),this._mixBufferRegionAdditive(e,i,0,t,n),this.cumulativeWeightAdditive+=t}apply(t){const e=this.valueSize,n=this.buffer,i=t*e+e,r=this.cumulativeWeight,s=this.cumulativeWeightAdditive,a=this.binding;if(this.cumulativeWeight=0,this.cumulativeWeightAdditive=0,r&lt;1){const t=e*this._origIndex;this._mixBufferRegion(n,i,t,1-r,e)}s&gt;0&amp;&amp;this._mixBufferRegionAdditive(n,i,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(n[t]!==n[t+e]){a.setValue(n,i);break}}saveOriginalState(){const t=this.binding,e=this.buffer,n=this.valueSize,i=n*this._origIndex;t.getValue(e,i);for(let t=n,r=i;t!==r;++t)e[t]=e[i+t%n];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let n=t;n&lt;e;n++)this.buffer[n]=0}_setAdditiveIdentityQuaternion(){this._setAdditiveIdentityNumeric(),this.buffer[this._addIndex*this.valueSize+3]=1}_setAdditiveIdentityOther(){const t=this._origIndex*this.valueSize,e=this._addIndex*this.valueSize;for(let n=0;n&lt;this.valueSize;n++)this.buffer[e+n]=this.buffer[t+n]}_select(t,e,n,i,r){if(i&gt;=.5)for(let i=0;i!==r;++i)t[e+i]=t[n+i]}_slerp(t,e,n,i){ke.slerpFlat(t,e,t,e,t,n,i)}_slerpAdditive(t,e,n,i,r){const s=this._workIndex*r;ke.multiplyQuaternionsFlat(t,s,t,e,t,n),ke.slerpFlat(t,e,t,e,t,s,i)}_lerp(t,e,n,i,r){const s=1-i;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[n+a]*i}}_lerpAdditive(t,e,n,i,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[n+s]*i}}}const Lu=&quot;\\[\\]\\.:\\/&quot;,Pu=new RegExp(&quot;[&quot;+Lu+&quot;]&quot;,&quot;g&quot;),Iu=&quot;[^&quot;+Lu+&quot;]&quot;,Uu=&quot;[^&quot;+Lu.replace(&quot;\\.&quot;,&quot;&quot;)+&quot;]&quot;,Du=new RegExp(&quot;^&quot;+/((?:WC+[\/:])*)/.source.replace(&quot;WC&quot;,Iu)+/(WCOD+)?/.source.replace(&quot;WCOD&quot;,Uu)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace(&quot;WC&quot;,Iu)+/\.(WC+)(?:\[(.+)\])?/.source.replace(&quot;WC&quot;,Iu)+&quot;$&quot;),Nu=[&quot;material&quot;,&quot;materials&quot;,&quot;bones&quot;,&quot;map&quot;];class Ou{constructor(t,e,n){this.path=e,this.parsedPath=n||Ou.parseTrackName(e),this.node=Ou.findNode(t,this.parsedPath.nodeName),this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,n){return t&amp;&amp;t.isAnimationObjectGroup?new Ou.Composite(t,e,n):new Ou(t,e,n)}static sanitizeNodeName(t){return t.replace(/\s/g,&quot;_&quot;).replace(Pu,&quot;&quot;)}static parseTrackName(t){const e=Du.exec(t);if(null===e)throw new Error(&quot;PropertyBinding: Cannot parse trackName: &quot;+t);const n={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},i=n.nodeName&amp;&amp;n.nodeName.lastIndexOf(&quot;.&quot;);if(void 0!==i&amp;&amp;-1!==i){const t=n.nodeName.substring(i+1);-1!==Nu.indexOf(t)&amp;&amp;(n.nodeName=n.nodeName.substring(0,i),n.objectName=t)}if(null===n.propertyName||0===n.propertyName.length)throw new Error(&quot;PropertyBinding: can not parse propertyName from trackName: &quot;+t);return n}static findNode(t,e){if(void 0===e||&quot;&quot;===e||&quot;.&quot;===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const n=t.skeleton.getBoneByName(e);if(void 0!==n)return n}if(t.children){const n=function(t){for(let i=0;i&lt;t.length;i++){const r=t[i];if(r.name===e||r.uuid===e)return r;const s=n(r.children);if(s)return s}return null},i=n(t.children);if(i)return i}return null}_getValue_unavailable(){}_setValue_unavailable(){}_getValue_direct(t,e){t[e]=this.targetObject[this.propertyName]}_getValue_array(t,e){const n=this.resolvedProperty;for(let i=0,r=n.length;i!==r;++i)t[e++]=n[i]}_getValue_arrayElement(t,e){t[e]=this.resolvedProperty[this.propertyIndex]}_getValue_toArray(t,e){this.resolvedProperty.toArray(t,e)}_setValue_direct(t,e){this.targetObject[this.propertyName]=t[e]}_setValue_direct_setNeedsUpdate(t,e){this.targetObject[this.propertyName]=t[e],this.targetObject.needsUpdate=!0}_setValue_direct_setMatrixWorldNeedsUpdate(t,e){this.targetObject[this.propertyName]=t[e],this.targetObject.matrixWorldNeedsUpdate=!0}_setValue_array(t,e){const n=this.resolvedProperty;for(let i=0,r=n.length;i!==r;++i)n[i]=t[e++]}_setValue_array_setNeedsUpdate(t,e){const n=this.resolvedProperty;for(let i=0,r=n.length;i!==r;++i)n[i]=t[e++];this.targetObject.needsUpdate=!0}_setValue_array_setMatrixWorldNeedsUpdate(t,e){const n=this.resolvedProperty;for(let i=0,r=n.length;i!==r;++i)n[i]=t[e++];this.targetObject.matrixWorldNeedsUpdate=!0}_setValue_arrayElement(t,e){this.resolvedProperty[this.propertyIndex]=t[e]}_setValue_arrayElement_setNeedsUpdate(t,e){this.resolvedProperty[this.propertyIndex]=t[e],this.targetObject.needsUpdate=!0}_setValue_arrayElement_setMatrixWorldNeedsUpdate(t,e){this.resolvedProperty[this.propertyIndex]=t[e],this.targetObject.matrixWorldNeedsUpdate=!0}_setValue_fromArray(t,e){this.resolvedProperty.fromArray(t,e)}_setValue_fromArray_setNeedsUpdate(t,e){this.resolvedProperty.fromArray(t,e),this.targetObject.needsUpdate=!0}_setValue_fromArray_setMatrixWorldNeedsUpdate(t,e){this.resolvedProperty.fromArray(t,e),this.targetObject.matrixWorldNeedsUpdate=!0}_getValue_unbound(t,e){this.bind(),this.getValue(t,e)}_setValue_unbound(t,e){this.bind(),this.setValue(t,e)}bind(){let t=this.node;const e=this.parsedPath,n=e.objectName,i=e.propertyName;let r=e.propertyIndex;if(t||(t=Ou.findNode(this.rootNode,e.nodeName),this.node=t),this.getValue=this._getValue_unavailable,this.setValue=this._setValue_unavailable,!t)return void console.warn(&quot;THREE.PropertyBinding: No target node found for track: &quot;+this.path+&quot;.&quot;);if(n){let i=e.objectIndex;switch(n){case&quot;materials&quot;:if(!t.material)return void console.error(&quot;THREE.PropertyBinding: Can not bind to material as node does not have a material.&quot;,this);if(!t.material.materials)return void console.error(&quot;THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.&quot;,this);t=t.material.materials;break;case&quot;bones&quot;:if(!t.skeleton)return void console.error(&quot;THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.&quot;,this);t=t.skeleton.bones;for(let e=0;e&lt;t.length;e++)if(t[e].name===i){i=e;break}break;case&quot;map&quot;:if(&quot;map&quot;in t){t=t.map;break}if(!t.material)return void console.error(&quot;THREE.PropertyBinding: Can not bind to material as node does not have a material.&quot;,this);if(!t.material.map)return void console.error(&quot;THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.&quot;,this);t=t.material.map;break;default:if(void 0===t[n])return void console.error(&quot;THREE.PropertyBinding: Can not bind to objectName of node undefined.&quot;,this);t=t[n]}if(void 0!==i){if(void 0===t[i])return void console.error(&quot;THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.&quot;,this,t);t=t[i]}}const s=t[i];if(void 0===s){const n=e.nodeName;return void console.error(&quot;THREE.PropertyBinding: Trying to update property for track: &quot;+n+&quot;.&quot;+i+&quot; but it wasn't found.&quot;,t)}let a=this.Versioning.None;this.targetObject=t,void 0!==t.needsUpdate?a=this.Versioning.NeedsUpdate:void 0!==t.matrixWorldNeedsUpdate&amp;&amp;(a=this.Versioning.MatrixWorldNeedsUpdate);let o=this.BindingType.Direct;if(void 0!==r){if(&quot;morphTargetInfluences&quot;===i){if(!t.geometry)return void console.error(&quot;THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.&quot;,this);if(!t.geometry.morphAttributes)return void console.error(&quot;THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.&quot;,this);void 0!==t.morphTargetDictionary[r]&amp;&amp;(r=t.morphTargetDictionary[r])}o=this.BindingType.ArrayElement,this.resolvedProperty=s,this.propertyIndex=r}else void 0!==s.fromArray&amp;&amp;void 0!==s.toArray?(o=this.BindingType.HasFromToArray,this.resolvedProperty=s):Array.isArray(s)?(o=this.BindingType.EntireArray,this.resolvedProperty=s):this.propertyName=i;this.getValue=this.GetterByBindingType[o],this.setValue=this.SetterByBindingTypeAndVersioning[o][a]}unbind(){this.node=null,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}}Ou.Composite=class{constructor(t,e,n){const i=n||Ou.parseTrackName(e);this._targetGroup=t,this._bindings=t.subscribe_(e,i)}getValue(t,e){this.bind();const n=this._targetGroup.nCachedObjects_,i=this._bindings[n];void 0!==i&amp;&amp;i.getValue(t,e)}setValue(t,e){const n=this._bindings;for(let i=this._targetGroup.nCachedObjects_,r=n.length;i!==r;++i)n[i].setValue(t,e)}bind(){const t=this._bindings;for(let e=this._targetGroup.nCachedObjects_,n=t.length;e!==n;++e)t[e].bind()}unbind(){const t=this._bindings;for(let e=this._targetGroup.nCachedObjects_,n=t.length;e!==n;++e)t[e].unbind()}},Ou.prototype.BindingType={Direct:0,EntireArray:1,ArrayElement:2,HasFromToArray:3},Ou.prototype.Versioning={None:0,NeedsUpdate:1,MatrixWorldNeedsUpdate:2},Ou.prototype.GetterByBindingType=[Ou.prototype._getValue_direct,Ou.prototype._getValue_array,Ou.prototype._getValue_arrayElement,Ou.prototype._getValue_toArray],Ou.prototype.SetterByBindingTypeAndVersioning=[[Ou.prototype._setValue_direct,Ou.prototype._setValue_direct_setNeedsUpdate,Ou.prototype._setValue_direct_setMatrixWorldNeedsUpdate],[Ou.prototype._setValue_array,Ou.prototype._setValue_array_setNeedsUpdate,Ou.prototype._setValue_array_setMatrixWorldNeedsUpdate],[Ou.prototype._setValue_arrayElement,Ou.prototype._setValue_arrayElement_setNeedsUpdate,Ou.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate],[Ou.prototype._setValue_fromArray,Ou.prototype._setValue_fromArray_setNeedsUpdate,Ou.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate]];class Fu{constructor(t,e,n=null,i=e.blendMode){this._mixer=t,this._clip=e,this._localRoot=n,this.blendMode=i;const r=e.tracks,s=r.length,a=new Array(s),o={endingStart:It,endingEnd:It};for(let t=0;t!==s;++t){const e=r[t].createInterpolant(null);a[t]=e,e.settings=o}this._interpolantSettings=o,this._interpolants=a,this._propertyBindings=new Array(s),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&amp;&amp;!this.paused&amp;&amp;0!==this.timeScale&amp;&amp;null===this._startTime&amp;&amp;this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(t){return this._startTime=t,this}setLoop(t,e){return this.loop=t,this.repetitions=e,this}setEffectiveWeight(t){return this.weight=t,this._effectiveWeight=this.enabled?t:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(t){return this._scheduleFading(t,0,1)}fadeOut(t){return this._scheduleFading(t,1,0)}crossFadeFrom(t,e,n){if(t.fadeOut(e),this.fadeIn(e),n){const n=this._clip.duration,i=t._clip.duration,r=i/n,s=n/i;t.warp(1,r,e),this.warp(s,1,e)}return this}crossFadeTo(t,e,n){return t.crossFadeFrom(this,e,n)}stopFading(){const t=this._weightInterpolant;return null!==t&amp;&amp;(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}setEffectiveTimeScale(t){return this.timeScale=t,this._effectiveTimeScale=this.paused?0:t,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(t){return this.timeScale=this._clip.duration/t,this.stopWarping()}syncWith(t){return this.time=t.time,this.timeScale=t.timeScale,this.stopWarping()}halt(t){return this.warp(this._effectiveTimeScale,0,t)}warp(t,e,n){const i=this._mixer,r=i.time,s=this.timeScale;let a=this._timeScaleInterpolant;null===a&amp;&amp;(a=i._lendControlInterpolant(),this._timeScaleInterpolant=a);const o=a.parameterPositions,l=a.sampleValues;return o[0]=r,o[1]=r+n,l[0]=t/s,l[1]=e/s,this}stopWarping(){const t=this._timeScaleInterpolant;return null!==t&amp;&amp;(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(t,e,n,i){if(!this.enabled)return void this._updateWeight(t);const r=this._startTime;if(null!==r){const i=(t-r)*n;i&lt;0||0===n?e=0:(this._startTime=null,e=n*i)}e*=this._updateTimeScale(t);const s=this._updateTime(e),a=this._updateWeight(t);if(a&gt;0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===Ot)for(let n=0,i=t.length;n!==i;++n)t[n].evaluate(s),e[n].accumulateAdditive(a);else for(let n=0,r=t.length;n!==r;++n)t[n].evaluate(s),e[n].accumulate(i,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const n=this._weightInterpolant;if(null!==n){const i=n.evaluate(t)[0];e*=i,t&gt;n.parameterPositions[1]&amp;&amp;(this.stopFading(),0===i&amp;&amp;(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const n=this._timeScaleInterpolant;if(null!==n){e*=n.evaluate(t)[0],t&gt;n.parameterPositions[1]&amp;&amp;(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,n=this.loop;let i=this.time+t,r=this._loopCount;const s=2202===n;if(0===t)return-1===r?i:s&amp;&amp;1==(1&amp;r)?e-i:i;if(2200===n){-1===r&amp;&amp;(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(i&gt;=e)i=e;else{if(!(i&lt;0)){this.time=i;break t}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:&quot;finished&quot;,action:this,direction:t&lt;0?-1:1})}}else{if(-1===r&amp;&amp;(t&gt;=0?(r=0,this._setEndings(!0,0===this.repetitions,s)):this._setEndings(0===this.repetitions,!0,s)),i&gt;=e||i&lt;0){const n=Math.floor(i/e);i-=e*n,r+=Math.abs(n);const a=this.repetitions-r;if(a&lt;=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=t&gt;0?e:0,this.time=i,this._mixer.dispatchEvent({type:&quot;finished&quot;,action:this,direction:t&gt;0?1:-1});else{if(1===a){const e=t&lt;0;this._setEndings(e,!e,s)}else this._setEndings(!1,!1,s);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:&quot;loop&quot;,action:this,loopDelta:n})}}else this.time=i;if(s&amp;&amp;1==(1&amp;r))return e-i}return i}_setEndings(t,e,n){const i=this._interpolantSettings;n?(i.endingStart=Ut,i.endingEnd=Ut):(i.endingStart=t?this.zeroSlopeAtStart?Ut:It:Dt,i.endingEnd=e?this.zeroSlopeAtEnd?Ut:It:Dt)}_scheduleFading(t,e,n){const i=this._mixer,r=i.time;let s=this._weightInterpolant;null===s&amp;&amp;(s=i._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=n,this}}const Bu=new Float32Array(1);class zu{constructor(t){this.value=t}clone(){return new zu(void 0===this.value.clone?this.value:this.value.clone())}}let Gu=0;function Hu(t,e){return t.distance-e.distance}function Vu(t,e,n,i){if(t.layers.test(e.layers)&amp;&amp;t.raycast(e,n),!0===i){const i=t.children;for(let t=0,r=i.length;t&lt;r;t++)Vu(i[t],e,n,!0)}}const ku=new me;const Wu=new We,Xu=new We;const ju=new We;const qu=new We,Yu=new Mn,Zu=new Mn;function Ju(t){const e=[];!0===t.isBone&amp;&amp;e.push(t);for(let n=0;n&lt;t.children.length;n++)e.push.apply(e,Ju(t.children[n]));return e}const Ku=new We,$u=new ci,Qu=new ci;const td=new We,ed=new We,nd=new We;const id=new We,rd=new rr;function sd(t,e,n,i,r,s,a){id.set(r,s,a).unproject(i);const o=e[t];if(void 0!==o){const t=n.getAttribute(&quot;position&quot;);for(let e=0,n=o.length;e&lt;n;e++)t.setXYZ(o[e],id.x,id.y,id.z)}}const ad=new qe;const od=new We;let ld,cd;&quot;undefined&quot;!=typeof __THREE_DEVTOOLS__&amp;&amp;__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent(&quot;register&quot;,{detail:{revision:e}})),&quot;undefined&quot;!=typeof window&amp;&amp;(window.__THREE__?console.warn(&quot;WARNING: Multiple instances of Three.js being imported.&quot;):window.__THREE__=e),t.ACESFilmicToneMapping=_,t.AddEquation=o,t.AddOperation=d,t.AdditiveAnimationBlendMode=Ot,t.AdditiveBlending=2,t.AgXToneMapping=x,t.AlphaFormat=1021,t.AlwaysCompare=519,t.AlwaysDepth=1,t.AlwaysStencilFunc=519,t.AmbientLight=nu,t.AnimationAction=Fu,t.AnimationClip=Ph,t.AnimationLoader=class extends Oh{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new zh(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(n){try{e(r.parse(JSON.parse(n)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),n,i)}parse(t){const e=[];for(let n=0;n&lt;t.length;n++){const i=Ph.parse(t[n]);e.push(i)}return e}},t.AnimationMixer=class extends te{constructor(t){super(),this._root=t,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(t,e){const n=t._localRoot||this._root,i=t._clip.tracks,r=i.length,s=t._propertyBindings,a=t._interpolants,o=n.uuid,l=this._bindingsByRootAndName;let c=l[o];void 0===c&amp;&amp;(c={},l[o]=c);for(let t=0;t!==r;++t){const r=i[t],l=r.name;let h=c[l];if(void 0!==h)++h.referenceCount,s[t]=h;else{if(h=s[t],void 0!==h){null===h._cacheIndex&amp;&amp;(++h.referenceCount,this._addInactiveBinding(h,o,l));continue}const i=e&amp;&amp;e._propertyBindings[t].binding.parsedPath;h=new Cu(Ou.create(n,l,i),r.ValueTypeName,r.getValueSize()),++h.referenceCount,this._addInactiveBinding(h,o,l),s[t]=h}a[t].resultBuffer=h.buffer}}_activateAction(t){if(!this._isActiveAction(t)){if(null===t._cacheIndex){const e=(t._localRoot||this._root).uuid,n=t._clip.uuid,i=this._actionsByClip[n];this._bindAction(t,i&amp;&amp;i.knownActions[0]),this._addInactiveAction(t,n,e)}const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==n.useCount++&amp;&amp;(this._lendBinding(n),n.saveOriginalState())}this._lendAction(t)}}_deactivateAction(t){if(this._isActiveAction(t)){const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==--n.useCount&amp;&amp;(n.restoreOriginalState(),this._takeBackBinding(n))}this._takeBackAction(t)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const t=this;this.stats={actions:{get total(){return t._actions.length},get inUse(){return t._nActiveActions}},bindings:{get total(){return t._bindings.length},get inUse(){return t._nActiveBindings}},controlInterpolants:{get total(){return t._controlInterpolants.length},get inUse(){return t._nActiveControlInterpolants}}}}_isActiveAction(t){const e=t._cacheIndex;return null!==e&amp;&amp;e&lt;this._nActiveActions}_addInactiveAction(t,e,n){const i=this._actions,r=this._actionsByClip;let s=r[e];if(void 0===s)s={knownActions:[t],actionByRoot:{}},t._byClipCacheIndex=0,r[e]=s;else{const e=s.knownActions;t._byClipCacheIndex=e.length,e.push(t)}t._cacheIndex=i.length,i.push(t),s.actionByRoot[n]=t}_removeInactiveAction(t){const e=this._actions,n=e[e.length-1],i=t._cacheIndex;n._cacheIndex=i,e[i]=n,e.pop(),t._cacheIndex=null;const r=t._clip.uuid,s=this._actionsByClip,a=s[r],o=a.knownActions,l=o[o.length-1],c=t._byClipCacheIndex;l._byClipCacheIndex=c,o[c]=l,o.pop(),t._byClipCacheIndex=null;delete a.actionByRoot[(t._localRoot||this._root).uuid],0===o.length&amp;&amp;delete s[r],this._removeInactiveBindingsForAction(t)}_removeInactiveBindingsForAction(t){const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==--n.referenceCount&amp;&amp;this._removeInactiveBinding(n)}}_lendAction(t){const e=this._actions,n=t._cacheIndex,i=this._nActiveActions++,r=e[i];t._cacheIndex=i,e[i]=t,r._cacheIndex=n,e[n]=r}_takeBackAction(t){const e=this._actions,n=t._cacheIndex,i=--this._nActiveActions,r=e[i];t._cacheIndex=i,e[i]=t,r._cacheIndex=n,e[n]=r}_addInactiveBinding(t,e,n){const i=this._bindingsByRootAndName,r=this._bindings;let s=i[e];void 0===s&amp;&amp;(s={},i[e]=s),s[n]=t,t._cacheIndex=r.length,r.push(t)}_removeInactiveBinding(t){const e=this._bindings,n=t.binding,i=n.rootNode.uuid,r=n.path,s=this._bindingsByRootAndName,a=s[i],o=e[e.length-1],l=t._cacheIndex;o._cacheIndex=l,e[l]=o,e.pop(),delete a[r],0===Object.keys(a).length&amp;&amp;delete s[i]}_lendBinding(t){const e=this._bindings,n=t._cacheIndex,i=this._nActiveBindings++,r=e[i];t._cacheIndex=i,e[i]=t,r._cacheIndex=n,e[n]=r}_takeBackBinding(t){const e=this._bindings,n=t._cacheIndex,i=--this._nActiveBindings,r=e[i];t._cacheIndex=i,e[i]=t,r._cacheIndex=n,e[n]=r}_lendControlInterpolant(){const t=this._controlInterpolants,e=this._nActiveControlInterpolants++;let n=t[e];return void 0===n&amp;&amp;(n=new Mh(new Float32Array(2),new Float32Array(2),1,Bu),n.__cacheIndex=e,t[e]=n),n}_takeBackControlInterpolant(t){const e=this._controlInterpolants,n=t.__cacheIndex,i=--this._nActiveControlInterpolants,r=e[i];t.__cacheIndex=i,e[i]=t,r.__cacheIndex=n,e[n]=r}clipAction(t,e,n){const i=e||this._root,r=i.uuid;let s=&quot;string&quot;==typeof t?Ph.findByName(i,t):t;const a=null!==s?s.uuid:t,o=this._actionsByClip[a];let l=null;if(void 0===n&amp;&amp;(n=null!==s?s.blendMode:Nt),void 0!==o){const t=o.actionByRoot[r];if(void 0!==t&amp;&amp;t.blendMode===n)return t;l=o.knownActions[0],null===s&amp;&amp;(s=l._clip)}if(null===s)return null;const c=new Fu(this,s,e,n);return this._bindAction(c,l),this._addInactiveAction(c,a,r),c}existingAction(t,e){const n=e||this._root,i=n.uuid,r=&quot;string&quot;==typeof t?Ph.findByName(n,t):t,s=r?r.uuid:t,a=this._actionsByClip[s];return void 0!==a&amp;&amp;a.actionByRoot[i]||null}stopAllAction(){const t=this._actions;for(let e=this._nActiveActions-1;e&gt;=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,n=this._nActiveActions,i=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==n;++a){e[a]._update(i,t,r,s)}const a=this._bindings,o=this._nActiveBindings;for(let t=0;t!==o;++t)a[t].apply(s);return this}setTime(t){this.time=0;for(let t=0;t&lt;this._actions.length;t++)this._actions[t].time=0;return this.update(t)}getRoot(){return this._root}uncacheClip(t){const e=this._actions,n=t.uuid,i=this._actionsByClip,r=i[n];if(void 0!==r){const t=r.knownActions;for(let n=0,i=t.length;n!==i;++n){const i=t[n];this._deactivateAction(i);const r=i._cacheIndex,s=e[e.length-1];i._cacheIndex=null,i._byClipCacheIndex=null,s._cacheIndex=r,e[r]=s,e.pop(),this._removeInactiveBindingsForAction(i)}delete i[n]}}uncacheRoot(t){const e=t.uuid,n=this._actionsByClip;for(const t in n){const i=n[t].actionByRoot[e];void 0!==i&amp;&amp;(this._deactivateAction(i),this._removeInactiveAction(i))}const i=this._bindingsByRootAndName[e];if(void 0!==i)for(const t in i){const e=i[t];e.restoreOriginalState(),this._removeInactiveBinding(e)}}uncacheAction(t,e){const n=this.existingAction(t,e);null!==n&amp;&amp;(this._deactivateAction(n),this._removeInactiveAction(n))}},t.AnimationObjectGroup=class{constructor(){this.isAnimationObjectGroup=!0,this.uuid=se(),this._objects=Array.prototype.slice.call(arguments),this.nCachedObjects_=0;const t={};this._indicesByUUID=t;for(let e=0,n=arguments.length;e!==n;++e)t[arguments[e].uuid]=e;this._paths=[],this._parsedPaths=[],this._bindings=[],this._bindingsIndicesByPath={};const e=this;this.stats={objects:{get total(){return e._objects.length},get inUse(){return this.total-e.nCachedObjects_}},get bindingsPerObject(){return e._bindings.length}}}add(){const t=this._objects,e=this._indicesByUUID,n=this._paths,i=this._parsedPaths,r=this._bindings,s=r.length;let a,o=t.length,l=this.nCachedObjects_;for(let c=0,h=arguments.length;c!==h;++c){const h=arguments[c],u=h.uuid;let d=e[u];if(void 0===d){d=o++,e[u]=d,t.push(h);for(let t=0,e=s;t!==e;++t)r[t].push(new Ou(h,n[t],i[t]))}else if(d&lt;l){a=t[d];const o=--l,c=t[o];e[c.uuid]=d,t[d]=c,e[u]=o,t[o]=h;for(let t=0,e=s;t!==e;++t){const e=r[t],s=e[o];let a=e[d];e[d]=s,void 0===a&amp;&amp;(a=new Ou(h,n[t],i[t])),e[o]=a}}else t[d]!==a&amp;&amp;console.error(&quot;THREE.AnimationObjectGroup: Different objects with the same UUID detected. Clean the caches or recreate your infrastructure when reloading scenes.&quot;)}this.nCachedObjects_=l}remove(){const t=this._objects,e=this._indicesByUUID,n=this._bindings,i=n.length;let r=this.nCachedObjects_;for(let s=0,a=arguments.length;s!==a;++s){const a=arguments[s],o=a.uuid,l=e[o];if(void 0!==l&amp;&amp;l&gt;=r){const s=r++,c=t[s];e[c.uuid]=l,t[l]=c,e[o]=s,t[s]=a;for(let t=0,e=i;t!==e;++t){const e=n[t],i=e[s],r=e[l];e[l]=i,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,n=this._bindings,i=n.length;let r=this.nCachedObjects_,s=t.length;for(let a=0,o=arguments.length;a!==o;++a){const o=arguments[a].uuid,l=e[o];if(void 0!==l)if(delete e[o],l&lt;r){const a=--r,o=t[a],c=--s,h=t[c];e[o.uuid]=l,t[l]=o,e[h.uuid]=a,t[a]=h,t.pop();for(let t=0,e=i;t!==e;++t){const e=n[t],i=e[a],r=e[c];e[l]=i,e[a]=r,e.pop()}}else{const r=--s,a=t[r];r&gt;0&amp;&amp;(e[a.uuid]=l),t[l]=a,t.pop();for(let t=0,e=i;t!==e;++t){const e=n[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const n=this._bindingsIndicesByPath;let i=n[t];const r=this._bindings;if(void 0!==i)return r[i];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);i=r.length,n[t]=i,s.push(t),a.push(e),r.push(h);for(let n=c,i=o.length;n!==i;++n){const i=o[n];h[n]=new Ou(i,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,n=e[t];if(void 0!==n){const i=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=n,s[n]=o,s.pop(),r[n]=r[a],r.pop(),i[n]=i[a],i.pop()}}},t.AnimationUtils=vh,t.ArcCurve=Ol,t.ArrayCamera=qa,t.ArrowHelper=class extends jn{constructor(t=new We(0,0,1),e=new We(0,0,0),n=1,i=16776960,r=.2*n,s=.2*r){super(),this.type=&quot;ArrowHelper&quot;,void 0===ld&amp;&amp;(ld=new Ii,ld.setAttribute(&quot;position&quot;,new Ti([0,0,0,0,1,0],3)),cd=new sc(0,.5,1,5,1),cd.translate(0,-.5,0)),this.position.copy(e),this.line=new Ml(ld,new fl({color:i,toneMapped:!1})),this.line.matrixAutoUpdate=!1,this.add(this.line),this.cone=new Ji(cd,new pi({color:i,toneMapped:!1})),this.cone.matrixAutoUpdate=!1,this.add(this.cone),this.setDirection(t),this.setLength(n,r,s)}setDirection(t){if(t.y&gt;.99999)this.quaternion.set(0,0,0,1);else if(t.y&lt;-.99999)this.quaternion.set(1,0,0,0);else{od.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(od,e)}}setLength(t,e=.2*t,n=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(n,e,n),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}},t.AttachedBindMode=y,t.Audio=Tu,t.AudioAnalyser=class{constructor(t,e=2048){this.analyser=t.context.createAnalyser(),this.analyser.fftSize=e,this.data=new Uint8Array(this.analyser.frequencyBinCount),t.getOutput().connect(this.analyser)}getFrequencyData(){return this.analyser.getByteFrequencyData(this.data),this.data}getAverageFrequency(){let t=0;const e=this.getFrequencyData();for(let n=0;n&lt;e.length;n++)t+=e[n];return t/e.length}},t.AudioContext=mu,t.AudioListener=class extends jn{constructor(){super(),this.type=&quot;AudioListener&quot;,this.context=mu.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new vu}getInput(){return this.gain}removeFilter(){return null!==this.filter&amp;&amp;(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(t){return null!==this.filter?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=t,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(t){return this.gain.gain.setTargetAtTime(t,this.context.currentTime,.01),this}updateMatrixWorld(t){super.updateMatrixWorld(t);const e=this.context.listener,n=this.up;if(this.timeDelta=this._clock.getDelta(),this.matrixWorld.decompose(yu,Mu,Su),bu.set(0,0,-1).applyQuaternion(Mu),e.positionX){const t=this.context.currentTime+this.timeDelta;e.positionX.linearRampToValueAtTime(yu.x,t),e.positionY.linearRampToValueAtTime(yu.y,t),e.positionZ.linearRampToValueAtTime(yu.z,t),e.forwardX.linearRampToValueAtTime(bu.x,t),e.forwardY.linearRampToValueAtTime(bu.y,t),e.forwardZ.linearRampToValueAtTime(bu.z,t),e.upX.linearRampToValueAtTime(n.x,t),e.upY.linearRampToValueAtTime(n.y,t),e.upZ.linearRampToValueAtTime(n.z,t)}else e.setPosition(yu.x,yu.y,yu.z),e.setOrientation(bu.x,bu.y,bu.z,n.x,n.y,n.z)}},t.AudioLoader=class extends Oh{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new zh(this.manager);function a(e){i?i(e):console.error(e),r.manager.itemError(t)}s.setResponseType(&quot;arraybuffer&quot;),s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(t){try{const n=t.slice(0);mu.getContext().decodeAudioData(n,(function(t){e(t)})).catch(a)}catch(t){a(t)}}),n,i)}},t.AxesHelper=class extends Tl{constructor(t=1){const e=[0,0,0,t,0,0,0,0,0,0,t,0,0,0,0,0,0,t],n=new Ii;n.setAttribute(&quot;position&quot;,new Ti(e,3)),n.setAttribute(&quot;color&quot;,new Ti([1,0,0,1,.6,0,0,1,0,.6,1,0,0,0,1,0,.6,1],3));super(n,new fl({vertexColors:!0,toneMapped:!1})),this.type=&quot;AxesHelper&quot;}setColors(t,e,n){const i=new ci,r=this.geometry.attributes.color.array;return i.set(t),i.toArray(r,0),i.toArray(r,3),i.set(e),i.toArray(r,6),i.toArray(r,9),i.set(n),i.toArray(r,12),i.toArray(r,15),this.geometry.attributes.color.needsUpdate=!0,this}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BackSide=a,t.BasicDepthPacking=3200,t.BasicShadowMap=0,t.BatchedMesh=ml,t.Bone=Bo,t.BooleanKeyframeTrack=Th,t.Box2=class{constructor(t=new me(1/0,1/0),e=new me(-1/0,-1/0)){this.isBox2=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromPoints(t){this.makeEmpty();for(let e=0,n=t.length;e&lt;n;e++)this.expandByPoint(t[e]);return this}setFromCenterAndSize(t,e){const n=ku.copy(e).multiplyScalar(.5);return this.min.copy(t).sub(n),this.max.copy(t).add(n),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.min.copy(t.min),this.max.copy(t.max),this}makeEmpty(){return this.min.x=this.min.y=1/0,this.max.x=this.max.y=-1/0,this}isEmpty(){return this.max.x&lt;this.min.x||this.max.y&lt;this.min.y}getCenter(t){return this.isEmpty()?t.set(0,0):t.addVectors(this.min,this.max).multiplyScalar(.5)}getSize(t){return this.isEmpty()?t.set(0,0):t.subVectors(this.max,this.min)}expandByPoint(t){return this.min.min(t),this.max.max(t),this}expandByVector(t){return this.min.sub(t),this.max.add(t),this}expandByScalar(t){return this.min.addScalar(-t),this.max.addScalar(t),this}containsPoint(t){return!(t.x&lt;this.min.x||t.x&gt;this.max.x||t.y&lt;this.min.y||t.y&gt;this.max.y)}containsBox(t){return this.min.x&lt;=t.min.x&amp;&amp;t.max.x&lt;=this.max.x&amp;&amp;this.min.y&lt;=t.min.y&amp;&amp;t.max.y&lt;=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return!(t.max.x&lt;this.min.x||t.min.x&gt;this.max.x||t.max.y&lt;this.min.y||t.min.y&gt;this.max.y)}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,ku).distanceTo(t)}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&amp;&amp;this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&amp;&amp;t.max.equals(this.max)}},t.Box3=qe,t.Box3Helper=class extends Tl{constructor(t,e=16776960){const n=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),i=new Ii;i.setIndex(new Mi(n,1)),i.setAttribute(&quot;position&quot;,new Ti([1,1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1],3)),super(i,new fl({color:e,toneMapped:!1})),this.box=t,this.type=&quot;Box3Helper&quot;,this.geometry.computeBoundingSphere()}updateMatrixWorld(t){const e=this.box;e.isEmpty()||(e.getCenter(this.position),e.getSize(this.scale),this.scale.multiplyScalar(.5),super.updateMatrixWorld(t))}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BoxGeometry=$i,t.BoxHelper=class extends Tl{constructor(t,e=16776960){const n=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),i=new Float32Array(24),r=new Ii;r.setIndex(new Mi(n,1)),r.setAttribute(&quot;position&quot;,new Mi(i,3)),super(r,new fl({color:e,toneMapped:!1})),this.object=t,this.type=&quot;BoxHelper&quot;,this.matrixAutoUpdate=!1,this.update()}update(t){if(void 0!==t&amp;&amp;console.warn(&quot;THREE.BoxHelper: .update() has no longer arguments.&quot;),void 0!==this.object&amp;&amp;ad.setFromObject(this.object),ad.isEmpty())return;const e=ad.min,n=ad.max,i=this.geometry.attributes.position,r=i.array;r[0]=n.x,r[1]=n.y,r[2]=n.z,r[3]=e.x,r[4]=n.y,r[5]=n.z,r[6]=e.x,r[7]=e.y,r[8]=n.z,r[9]=n.x,r[10]=e.y,r[11]=n.z,r[12]=n.x,r[13]=n.y,r[14]=e.z,r[15]=e.x,r[16]=n.y,r[17]=e.z,r[18]=e.x,r[19]=e.y,r[20]=e.z,r[21]=n.x,r[22]=e.y,r[23]=e.z,i.needsUpdate=!0,this.geometry.computeBoundingSphere()}setFromObject(t){return this.object=t,this.update(),this}copy(t,e){return super.copy(t,e),this.object=t.object,this}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BufferAttribute=Mi,t.BufferGeometry=Ii,t.BufferGeometryLoader=cu,t.ByteType=1010,t.Cache=Uh,t.Camera=rr,t.CameraHelper=class extends Tl{constructor(t){const e=new Ii,n=new fl({color:16777215,vertexColors:!0,toneMapped:!1}),i=[],r=[],s={};function a(t,e){o(t),o(e)}function o(t){i.push(0,0,0),r.push(0,0,0),void 0===s[t]&amp;&amp;(s[t]=[]),s[t].push(i.length/3-1)}a(&quot;n1&quot;,&quot;n2&quot;),a(&quot;n2&quot;,&quot;n4&quot;),a(&quot;n4&quot;,&quot;n3&quot;),a(&quot;n3&quot;,&quot;n1&quot;),a(&quot;f1&quot;,&quot;f2&quot;),a(&quot;f2&quot;,&quot;f4&quot;),a(&quot;f4&quot;,&quot;f3&quot;),a(&quot;f3&quot;,&quot;f1&quot;),a(&quot;n1&quot;,&quot;f1&quot;),a(&quot;n2&quot;,&quot;f2&quot;),a(&quot;n3&quot;,&quot;f3&quot;),a(&quot;n4&quot;,&quot;f4&quot;),a(&quot;p&quot;,&quot;n1&quot;),a(&quot;p&quot;,&quot;n2&quot;),a(&quot;p&quot;,&quot;n3&quot;),a(&quot;p&quot;,&quot;n4&quot;),a(&quot;u1&quot;,&quot;u2&quot;),a(&quot;u2&quot;,&quot;u3&quot;),a(&quot;u3&quot;,&quot;u1&quot;),a(&quot;c&quot;,&quot;t&quot;),a(&quot;p&quot;,&quot;c&quot;),a(&quot;cn1&quot;,&quot;cn2&quot;),a(&quot;cn3&quot;,&quot;cn4&quot;),a(&quot;cf1&quot;,&quot;cf2&quot;),a(&quot;cf3&quot;,&quot;cf4&quot;),e.setAttribute(&quot;position&quot;,new Ti(i,3)),e.setAttribute(&quot;color&quot;,new Ti(r,3)),super(e,n),this.type=&quot;CameraHelper&quot;,this.camera=t,this.camera.updateProjectionMatrix&amp;&amp;this.camera.updateProjectionMatrix(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.pointMap=s,this.update();const l=new ci(16755200),c=new ci(16711680),h=new ci(43775),u=new ci(16777215),d=new ci(3355443);this.setColors(l,c,h,u,d)}setColors(t,e,n,i,r){const s=this.geometry.getAttribute(&quot;color&quot;);s.setXYZ(0,t.r,t.g,t.b),s.setXYZ(1,t.r,t.g,t.b),s.setXYZ(2,t.r,t.g,t.b),s.setXYZ(3,t.r,t.g,t.b),s.setXYZ(4,t.r,t.g,t.b),s.setXYZ(5,t.r,t.g,t.b),s.setXYZ(6,t.r,t.g,t.b),s.setXYZ(7,t.r,t.g,t.b),s.setXYZ(8,t.r,t.g,t.b),s.setXYZ(9,t.r,t.g,t.b),s.setXYZ(10,t.r,t.g,t.b),s.setXYZ(11,t.r,t.g,t.b),s.setXYZ(12,t.r,t.g,t.b),s.setXYZ(13,t.r,t.g,t.b),s.setXYZ(14,t.r,t.g,t.b),s.setXYZ(15,t.r,t.g,t.b),s.setXYZ(16,t.r,t.g,t.b),s.setXYZ(17,t.r,t.g,t.b),s.setXYZ(18,t.r,t.g,t.b),s.setXYZ(19,t.r,t.g,t.b),s.setXYZ(20,t.r,t.g,t.b),s.setXYZ(21,t.r,t.g,t.b),s.setXYZ(22,t.r,t.g,t.b),s.setXYZ(23,t.r,t.g,t.b),s.setXYZ(24,e.r,e.g,e.b),s.setXYZ(25,e.r,e.g,e.b),s.setXYZ(26,e.r,e.g,e.b),s.setXYZ(27,e.r,e.g,e.b),s.setXYZ(28,e.r,e.g,e.b),s.setXYZ(29,e.r,e.g,e.b),s.setXYZ(30,e.r,e.g,e.b),s.setXYZ(31,e.r,e.g,e.b),s.setXYZ(32,n.r,n.g,n.b),s.setXYZ(33,n.r,n.g,n.b),s.setXYZ(34,n.r,n.g,n.b),s.setXYZ(35,n.r,n.g,n.b),s.setXYZ(36,n.r,n.g,n.b),s.setXYZ(37,n.r,n.g,n.b),s.setXYZ(38,i.r,i.g,i.b),s.setXYZ(39,i.r,i.g,i.b),s.setXYZ(40,r.r,r.g,r.b),s.setXYZ(41,r.r,r.g,r.b),s.setXYZ(42,r.r,r.g,r.b),s.setXYZ(43,r.r,r.g,r.b),s.setXYZ(44,r.r,r.g,r.b),s.setXYZ(45,r.r,r.g,r.b),s.setXYZ(46,r.r,r.g,r.b),s.setXYZ(47,r.r,r.g,r.b),s.setXYZ(48,r.r,r.g,r.b),s.setXYZ(49,r.r,r.g,r.b),s.needsUpdate=!0}update(){const t=this.geometry,e=this.pointMap;rd.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),sd(&quot;c&quot;,e,t,rd,0,0,-1),sd(&quot;t&quot;,e,t,rd,0,0,1),sd(&quot;n1&quot;,e,t,rd,-1,-1,-1),sd(&quot;n2&quot;,e,t,rd,1,-1,-1),sd(&quot;n3&quot;,e,t,rd,-1,1,-1),sd(&quot;n4&quot;,e,t,rd,1,1,-1),sd(&quot;f1&quot;,e,t,rd,-1,-1,1),sd(&quot;f2&quot;,e,t,rd,1,-1,1),sd(&quot;f3&quot;,e,t,rd,-1,1,1),sd(&quot;f4&quot;,e,t,rd,1,1,1),sd(&quot;u1&quot;,e,t,rd,.7,1.1,-1),sd(&quot;u2&quot;,e,t,rd,-.7,1.1,-1),sd(&quot;u3&quot;,e,t,rd,0,2,-1),sd(&quot;cf1&quot;,e,t,rd,-1,0,1),sd(&quot;cf2&quot;,e,t,rd,1,0,1),sd(&quot;cf3&quot;,e,t,rd,0,-1,1),sd(&quot;cf4&quot;,e,t,rd,0,1,1),sd(&quot;cn1&quot;,e,t,rd,-1,0,-1),sd(&quot;cn2&quot;,e,t,rd,1,0,-1),sd(&quot;cn3&quot;,e,t,rd,0,-1,-1),sd(&quot;cn4&quot;,e,t,rd,0,1,-1),t.getAttribute(&quot;position&quot;).needsUpdate=!0}dispose(){this.geometry.dispose(),this.material.dispose()}},t.CanvasTexture=class extends Fe{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}},t.CapsuleGeometry=ic,t.CatmullRomCurve3=Vl,t.CineonToneMapping=g,t.CircleGeometry=rc,t.ClampToEdgeWrapping=C,t.Clock=vu,t.Color=ci,t.ColorKeyframeTrack=Eh,t.ColorManagement=Re,t.CompressedArrayTexture=class extends Ul{constructor(t,e,n,i,r,s){super(t,e,n,r,s),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=C}},t.CompressedCubeTexture=class extends Ul{constructor(t,e,n){super(void 0,t[0].width,t[0].height,e,n,b),this.isCompressedCubeTexture=!0,this.isCubeTexture=!0,this.image=t}},t.CompressedTexture=Ul,t.CompressedTextureLoader=class extends Oh{constructor(t){super(t)}load(t,e,n,i){const r=this,s=[],a=new Ul,o=new zh(this.manager);o.setPath(this.path),o.setResponseType(&quot;arraybuffer&quot;),o.setRequestHeader(this.requestHeader),o.setWithCredentials(r.withCredentials);let l=0;function c(c){o.load(t[c],(function(t){const n=r.parse(t,!0);s[c]={width:n.width,height:n.height,format:n.format,mipmaps:n.mipmaps},l+=1,6===l&amp;&amp;(1===n.mipmapCount&amp;&amp;(a.minFilter=D),a.image=s,a.format=n.format,a.needsUpdate=!0,e&amp;&amp;e(a))}),n,i)}if(Array.isArray(t))for(let e=0,n=t.length;e&lt;n;++e)c(e);else o.load(t,(function(t){const n=r.parse(t,!0);if(n.isCubemap){const t=n.mipmaps.length/n.mipmapCount;for(let e=0;e&lt;t;e++){s[e]={mipmaps:[]};for(let t=0;t&lt;n.mipmapCount;t++)s[e].mipmaps.push(n.mipmaps[e*n.mipmapCount+t]),s[e].format=n.format,s[e].width=n.width,s[e].height=n.height}a.image=s}else a.image.width=n.width,a.image.height=n.height,a.mipmaps=n.mipmaps;1===n.mipmapCount&amp;&amp;(a.minFilter=D),a.format=n.format,a.needsUpdate=!0,e&amp;&amp;e(a)}),n,i);return a}},t.ConeGeometry=ac,t.ConstantAlphaFactor=213,t.ConstantColorFactor=211,t.CubeCamera=or,t.CubeReflectionMapping=b,t.CubeRefractionMapping=T,t.CubeTexture=lr,t.CubeTextureLoader=class extends Oh{constructor(t){super(t)}load(t,e,n,i){const r=new lr;r.colorSpace=Gt;const s=new Gh(this.manager);s.setCrossOrigin(this.crossOrigin),s.setPath(this.path);let a=0;function o(n){s.load(t[n],(function(t){r.images[n]=t,a++,6===a&amp;&amp;(r.needsUpdate=!0,e&amp;&amp;e(r))}),void 0,i)}for(let e=0;e&lt;t.length;++e)o(e);return r}},t.CubeUVReflectionMapping=A,t.CubicBezierCurve=jl,t.CubicBezierCurve3=ql,t.CubicInterpolant=yh,t.CullFaceBack=1,t.CullFaceFront=2,t.CullFaceFrontBack=3,t.CullFaceNone=0,t.Curve=Dl,t.CurvePath=tc,t.CustomBlending=5,t.CustomToneMapping=v,t.CylinderGeometry=sc,t.Cylindrical=class{constructor(t=1,e=0,n=0){return this.radius=t,this.theta=e,this.y=n,this}set(t,e,n){return this.radius=t,this.theta=e,this.y=n,this}copy(t){return this.radius=t.radius,this.theta=t.theta,this.y=t.y,this}setFromVector3(t){return this.setFromCartesianCoords(t.x,t.y,t.z)}setFromCartesianCoords(t,e,n){return this.radius=Math.sqrt(t*t+n*n),this.theta=Math.atan2(t,n),this.y=e,this}clone(){return(new this.constructor).copy(this)}},t.Data3DTexture=Ve,t.DataArrayTexture=He,t.DataTexture=zo,t.DataTextureLoader=class extends Oh{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new zo,a=new zh(this.manager);return a.setResponseType(&quot;arraybuffer&quot;),a.setRequestHeader(this.requestHeader),a.setPath(this.path),a.setWithCredentials(r.withCredentials),a.load(t,(function(t){let n;try{n=r.parse(t)}catch(t){if(void 0===i)return void console.error(t);i(t)}void 0!==n.image?s.image=n.image:void 0!==n.data&amp;&amp;(s.image.width=n.width,s.image.height=n.height,s.image.data=n.data),s.wrapS=void 0!==n.wrapS?n.wrapS:C,s.wrapT=void 0!==n.wrapT?n.wrapT:C,s.magFilter=void 0!==n.magFilter?n.magFilter:D,s.minFilter=void 0!==n.minFilter?n.minFilter:D,s.anisotropy=void 0!==n.anisotropy?n.anisotropy:1,void 0!==n.colorSpace?s.colorSpace=n.colorSpace:void 0!==n.encoding&amp;&amp;(s.encoding=n.encoding),void 0!==n.flipY&amp;&amp;(s.flipY=n.flipY),void 0!==n.format&amp;&amp;(s.format=n.format),void 0!==n.type&amp;&amp;(s.type=n.type),void 0!==n.mipmaps&amp;&amp;(s.mipmaps=n.mipmaps,s.minFilter=O),1===n.mipmapCount&amp;&amp;(s.minFilter=D),void 0!==n.generateMipmaps&amp;&amp;(s.generateMipmaps=n.generateMipmaps),s.needsUpdate=!0,e&amp;&amp;e(s,n)}),n,i),s}},t.DataUtils=vi,t.DecrementStencilOp=7683,t.DecrementWrapStencilOp=34056,t.DefaultLoadingManager=Nh,t.DepthFormat=q,t.DepthStencilFormat=Y,t.DepthTexture=ns,t.DetachedBindMode=M,t.DirectionalLight=eu,t.DirectionalLightHelper=class extends jn{constructor(t,e,n){super(),this.light=t,this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=n,this.type=&quot;DirectionalLightHelper&quot;,void 0===e&amp;&amp;(e=1);let i=new Ii;i.setAttribute(&quot;position&quot;,new Ti([-e,e,0,e,e,0,e,-e,0,-e,-e,0,-e,e,0],3));const r=new fl({fog:!1,toneMapped:!1});this.lightPlane=new Ml(i,r),this.add(this.lightPlane),i=new Ii,i.setAttribute(&quot;position&quot;,new Ti([0,0,0,0,0,1],3)),this.targetLine=new Ml(i,r),this.add(this.targetLine),this.update()}dispose(){this.lightPlane.geometry.dispose(),this.lightPlane.material.dispose(),this.targetLine.geometry.dispose(),this.targetLine.material.dispose()}update(){this.light.updateWorldMatrix(!0,!1),this.light.target.updateWorldMatrix(!0,!1),td.setFromMatrixPosition(this.light.matrixWorld),ed.setFromMatrixPosition(this.light.target.matrixWorld),nd.subVectors(ed,td),this.lightPlane.lookAt(ed),void 0!==this.color?(this.lightPlane.material.color.set(this.color),this.targetLine.material.color.set(this.color)):(this.lightPlane.material.color.copy(this.light.color),this.targetLine.material.color.copy(this.light.color)),this.targetLine.lookAt(ed),this.targetLine.scale.z=nd.length()}},t.DiscreteInterpolant=Sh,t.DisplayP3ColorSpace=Vt,t.DodecahedronGeometry=lc,t.DoubleSide=2,t.DstAlphaFactor=206,t.DstColorFactor=208,t.DynamicCopyUsage=35050,t.DynamicDrawUsage=35048,t.DynamicReadUsage=35049,t.EdgesGeometry=pc,t.EllipseCurve=Nl,t.EqualCompare=514,t.EqualDepth=4,t.EqualStencilFunc=514,t.EquirectangularReflectionMapping=E,t.EquirectangularRefractionMapping=w,t.Euler=Pn,t.EventDispatcher=te,t.ExtrudeGeometry=kc,t.FileLoader=zh,t.Float16BufferAttribute=class extends Mi{constructor(t,e,n){super(new Uint16Array(t),e,n),this.isFloat16BufferAttribute=!0}getX(t){let e=_i(this.array[t*this.itemSize]);return this.normalized&amp;&amp;(e=ue(e,this.array)),e}setX(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.array[t*this.itemSize]=gi(e),this}getY(t){let e=_i(this.array[t*this.itemSize+1]);return this.normalized&amp;&amp;(e=ue(e,this.array)),e}setY(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.array[t*this.itemSize+1]=gi(e),this}getZ(t){let e=_i(this.array[t*this.itemSize+2]);return this.normalized&amp;&amp;(e=ue(e,this.array)),e}setZ(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.array[t*this.itemSize+2]=gi(e),this}getW(t){let e=_i(this.array[t*this.itemSize+3]);return this.normalized&amp;&amp;(e=ue(e,this.array)),e}setW(t,e){return this.normalized&amp;&amp;(e=de(e,this.array)),this.array[t*this.itemSize+3]=gi(e),this}setXY(t,e,n){return t*=this.itemSize,this.normalized&amp;&amp;(e=de(e,this.array),n=de(n,this.array)),this.array[t+0]=gi(e),this.array[t+1]=gi(n),this}setXYZ(t,e,n,i){return t*=this.itemSize,this.normalized&amp;&amp;(e=de(e,this.array),n=de(n,this.array),i=de(i,this.array)),this.array[t+0]=gi(e),this.array[t+1]=gi(n),this.array[t+2]=gi(i),this}setXYZW(t,e,n,i,r){return t*=this.itemSize,this.normalized&amp;&amp;(e=de(e,this.array),n=de(n,this.array),i=de(i,this.array),r=de(r,this.array)),this.array[t+0]=gi(e),this.array[t+1]=gi(n),this.array[t+2]=gi(i),this.array[t+3]=gi(r),this}},t.Float32BufferAttribute=Ti,t.Float64BufferAttribute=class extends Mi{constructor(t,e,n){super(new Float64Array(t),e,n)}},t.FloatType=H,t.Fog=io,t.FogExp2=no,t.FramebufferTexture=class extends Fe{constructor(t,e){super({width:t,height:e}),this.isFramebufferTexture=!0,this.magFilter=P,this.minFilter=P,this.generateMipmaps=!1,this.needsUpdate=!0}},t.FrontSide=s,t.Frustum=gr,t.GLBufferAttribute=class{constructor(t,e,n,i,r){this.isGLBufferAttribute=!0,this.name=&quot;&quot;,this.buffer=t,this.type=e,this.itemSize=n,this.elementSize=i,this.count=r,this.version=0}set needsUpdate(t){!0===t&amp;&amp;this.version++}setBuffer(t){return this.buffer=t,this}setType(t,e){return this.type=t,this.elementSize=e,this}setItemSize(t){return this.itemSize=t,this}setCount(t){return this.count=t,this}},t.GLSL1=&quot;100&quot;,t.GLSL3=Jt,t.GreaterCompare=516,t.GreaterDepth=6,t.GreaterEqualCompare=518,t.GreaterEqualDepth=5,t.GreaterEqualStencilFunc=518,t.GreaterStencilFunc=516,t.GridHelper=class extends Tl{constructor(t=10,e=10,n=4473924,i=8947848){n=new ci(n),i=new ci(i);const r=e/2,s=t/e,a=t/2,o=[],l=[];for(let t=0,c=0,h=-a;t&lt;=e;t++,h+=s){o.push(-a,0,h,a,0,h),o.push(h,0,-a,h,0,a);const e=t===r?n:i;e.toArray(l,c),c+=3,e.toArray(l,c),c+=3,e.toArray(l,c),c+=3,e.toArray(l,c),c+=3}const c=new Ii;c.setAttribute(&quot;position&quot;,new Ti(o,3)),c.setAttribute(&quot;color&quot;,new Ti(l,3));super(c,new fl({vertexColors:!0,toneMapped:!1})),this.type=&quot;GridHelper&quot;}dispose(){this.geometry.dispose(),this.material.dispose()}},t.Group=Ya,t.HalfFloatType=V,t.HemisphereLight=Vh,t.HemisphereLightHelper=class extends jn{constructor(t,e,n){super(),this.light=t,this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=n,this.type=&quot;HemisphereLightHelper&quot;;const i=new jc(e);i.rotateY(.5*Math.PI),this.material=new pi({wireframe:!0,fog:!1,toneMapped:!1}),void 0===this.color&amp;&amp;(this.material.vertexColors=!0);const r=i.getAttribute(&quot;position&quot;),s=new Float32Array(3*r.count);i.setAttribute(&quot;color&quot;,new Mi(s,3)),this.add(new Ji(i,this.material)),this.update()}dispose(){this.children[0].geometry.dispose(),this.children[0].material.dispose()}update(){const t=this.children[0];if(void 0!==this.color)this.material.color.set(this.color);else{const e=t.geometry.getAttribute(&quot;color&quot;);$u.copy(this.light.color),Qu.copy(this.light.groundColor);for(let t=0,n=e.count;t&lt;n;t++){const i=t&lt;n/2?$u:Qu;e.setXYZ(t,i.r,i.g,i.b)}e.needsUpdate=!0}this.light.updateWorldMatrix(!0,!1),t.lookAt(Ku.setFromMatrixPosition(this.light.matrixWorld).negate())}},t.IcosahedronGeometry=Xc,t.ImageBitmapLoader=class extends Oh{constructor(t){super(t),this.isImageBitmapLoader=!0,&quot;undefined&quot;==typeof createImageBitmap&amp;&amp;console.warn(&quot;THREE.ImageBitmapLoader: createImageBitmap() not supported.&quot;),&quot;undefined&quot;==typeof fetch&amp;&amp;console.warn(&quot;THREE.ImageBitmapLoader: fetch() not supported.&quot;),this.options={premultiplyAlpha:&quot;none&quot;}}setOptions(t){return this.options=t,this}load(t,e,n,i){void 0===t&amp;&amp;(t=&quot;&quot;),void 0!==this.path&amp;&amp;(t=this.path+t),t=this.manager.resolveURL(t);const r=this,s=Uh.get(t);if(void 0!==s)return r.manager.itemStart(t),s.then?void s.then((n=&gt;{e&amp;&amp;e(n),r.manager.itemEnd(t)})).catch((t=&gt;{i&amp;&amp;i(t)})):(setTimeout((function(){e&amp;&amp;e(s),r.manager.itemEnd(t)}),0),s);const a={};a.credentials=&quot;anonymous&quot;===this.crossOrigin?&quot;same-origin&quot;:&quot;include&quot;,a.headers=this.requestHeader;const o=fetch(t,a).then((function(t){return t.blob()})).then((function(t){return createImageBitmap(t,Object.assign(r.options,{colorSpaceConversion:&quot;none&quot;}))})).then((function(n){return Uh.add(t,n),e&amp;&amp;e(n),r.manager.itemEnd(t),n})).catch((function(e){i&amp;&amp;i(e),Uh.remove(t),r.manager.itemError(t),r.manager.itemEnd(t)}));Uh.add(t,o),r.manager.itemStart(t)}},t.ImageLoader=Gh,t.ImageUtils=Ie,t.IncrementStencilOp=7682,t.IncrementWrapStencilOp=34055,t.InstancedBufferAttribute=ko,t.InstancedBufferGeometry=lu,t.InstancedInterleavedBuffer=class extends so{constructor(t,e,n=1){super(t,e),this.isInstancedInterleavedBuffer=!0,this.meshPerAttribute=n}copy(t){return super.copy(t),this.meshPerAttribute=t.meshPerAttribute,this}clone(t){const e=super.clone(t);return e.meshPerAttribute=this.meshPerAttribute,e}toJSON(t){const e=super.toJSON(t);return e.isInstancedInterleavedBuffer=!0,e.meshPerAttribute=this.meshPerAttribute,e}},t.InstancedMesh=Ko,t.Int16BufferAttribute=class extends Mi{constructor(t,e,n){super(new Int16Array(t),e,n)}},t.Int32BufferAttribute=class extends Mi{constructor(t,e,n){super(new Int32Array(t),e,n)}},t.Int8BufferAttribute=class extends Mi{constructor(t,e,n){super(new Int8Array(t),e,n)}},t.IntType=z,t.InterleavedBuffer=so,t.InterleavedBufferAttribute=oo,t.Interpolant=xh,t.InterpolateDiscrete=Ct,t.InterpolateLinear=Lt,t.InterpolateSmooth=Pt,t.InvertStencilOp=5386,t.KeepStencilOp=Yt,t.KeyframeTrack=bh,t.LOD=Ao,t.LatheGeometry=nc,t.Layers=In,t.LessCompare=513,t.LessDepth=2,t.LessEqualCompare=515,t.LessEqualDepth=3,t.LessEqualStencilFunc=515,t.LessStencilFunc=513,t.Light=Hh,t.LightProbe=su,t.Line=Ml,t.Line3=class{constructor(t=new We,e=new We){this.start=t,this.end=e}set(t,e){return this.start.copy(t),this.end.copy(e),this}copy(t){return this.start.copy(t.start),this.end.copy(t.end),this}getCenter(t){return t.addVectors(this.start,this.end).multiplyScalar(.5)}delta(t){return t.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(t,e){return this.delta(e).multiplyScalar(t).add(this.start)}closestPointToPointParameter(t,e){Wu.subVectors(t,this.start),Xu.subVectors(this.end,this.start);const n=Xu.dot(Xu);let i=Xu.dot(Wu)/n;return e&amp;&amp;(i=ae(i,0,1)),i}closestPointToPoint(t,e,n){const i=this.closestPointToPointParameter(t,e);return this.delta(n).multiplyScalar(i).add(this.start)}applyMatrix4(t){return this.start.applyMatrix4(t),this.end.applyMatrix4(t),this}equals(t){return t.start.equals(this.start)&amp;&amp;t.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}},t.LineBasicMaterial=fl,t.LineCurve=Yl,t.LineCurve3=Zl,t.LineDashedMaterial=dh,t.LineLoop=El,t.LineSegments=Tl,t.LinearDisplayP3ColorSpace=kt,t.LinearEncoding=Ft,t.LinearFilter=D,t.LinearInterpolant=Mh,t.LinearMipMapLinearFilter=1008,t.LinearMipMapNearestFilter=1007,t.LinearMipmapLinearFilter=O,t.LinearMipmapNearestFilter=N,t.LinearSRGBColorSpace=Ht,t.LinearToneMapping=m,t.LinearTransfer=Wt,t.Loader=Oh,t.LoaderUtils=ou,t.LoadingManager=Dh,t.LoopOnce=2200,t.LoopPingPong=2202,t.LoopRepeat=2201,t.LuminanceAlphaFormat=1025,t.LuminanceFormat=1024,t.MOUSE={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2},t.Material=di,t.MaterialLoader=au,t.MathUtils=pe,t.Matrix3=fe,t.Matrix4=Mn,t.MaxEquation=104,t.Mesh=Ji,t.MeshBasicMaterial=pi,t.MeshDepthMaterial=Ha,t.MeshDistanceMaterial=Va,t.MeshLambertMaterial=hh,t.MeshMatcapMaterial=uh,t.MeshNormalMaterial=ch,t.MeshPhongMaterial=oh,t.MeshPhysicalMaterial=ah,t.MeshStandardMaterial=sh,t.MeshToonMaterial=lh,t.MinEquation=103,t.MirroredRepeatWrapping=L,t.MixOperation=u,t.MultiplyBlending=4,t.MultiplyOperation=h,t.NearestFilter=P,t.NearestMipMapLinearFilter=1005,t.NearestMipMapNearestFilter=1004,t.NearestMipmapLinearFilter=U,t.NearestMipmapNearestFilter=I,t.NeverCompare=512,t.NeverDepth=0,t.NeverStencilFunc=512,t.NoBlending=0,t.NoColorSpace=zt,t.NoToneMapping=p,t.NormalAnimationBlendMode=Nt,t.NormalBlending=1,t.NotEqualCompare=517,t.NotEqualDepth=7,t.NotEqualStencilFunc=517,t.NumberKeyframeTrack=wh,t.Object3D=jn,t.ObjectLoader=class extends Oh{constructor(t){super(t)}load(t,e,n,i){const r=this,s=&quot;&quot;===this.path?ou.extractUrlBase(t):this.path;this.resourcePath=this.resourcePath||s;const a=new zh(this.manager);a.setPath(this.path),a.setRequestHeader(this.requestHeader),a.setWithCredentials(this.withCredentials),a.load(t,(function(n){let s=null;try{s=JSON.parse(n)}catch(e){return void 0!==i&amp;&amp;i(e),void console.error(&quot;THREE:ObjectLoader: Can't parse &quot;+t+&quot;.&quot;,e.message)}const a=s.metadata;if(void 0===a||void 0===a.type||&quot;geometry&quot;===a.type.toLowerCase())return void 0!==i&amp;&amp;i(new Error(&quot;THREE.ObjectLoader: Can't load &quot;+t)),void console.error(&quot;THREE.ObjectLoader: Can't load &quot;+t);r.parse(s,e)}),n,i)}async loadAsync(t,e){const n=&quot;&quot;===this.path?ou.extractUrlBase(t):this.path;this.resourcePath=this.resourcePath||n;const i=new zh(this.manager);i.setPath(this.path),i.setRequestHeader(this.requestHeader),i.setWithCredentials(this.withCredentials);const r=await i.loadAsync(t,e),s=JSON.parse(r),a=s.metadata;if(void 0===a||void 0===a.type||&quot;geometry&quot;===a.type.toLowerCase())throw new Error(&quot;THREE.ObjectLoader: Can't load &quot;+t);return await this.parseAsync(s)}parse(t,e){const n=this.parseAnimations(t.animations),i=this.parseShapes(t.shapes),r=this.parseGeometries(t.geometries,i),s=this.parseImages(t.images,(function(){void 0!==e&amp;&amp;e(l)})),a=this.parseTextures(t.textures,s),o=this.parseMaterials(t.materials,a),l=this.parseObject(t.object,r,o,a,n),c=this.parseSkeletons(t.skeletons,l);if(this.bindSkeletons(l,c),void 0!==e){let t=!1;for(const e in s)if(s[e].data instanceof HTMLImageElement){t=!0;break}!1===t&amp;&amp;e(l)}return l}async parseAsync(t){const e=this.parseAnimations(t.animations),n=this.parseShapes(t.shapes),i=this.parseGeometries(t.geometries,n),r=await this.parseImagesAsync(t.images),s=this.parseTextures(t.textures,r),a=this.parseMaterials(t.materials,s),o=this.parseObject(t.object,i,a,s,e),l=this.parseSkeletons(t.skeletons,o);return this.bindSkeletons(o,l),o}parseShapes(t){const e={};if(void 0!==t)for(let n=0,i=t.length;n&lt;i;n++){const i=(new mc).fromJSON(t[n]);e[i.uuid]=i}return e}parseSkeletons(t,e){const n={},i={};if(e.traverse((function(t){t.isBone&amp;&amp;(i[t.uuid]=t)})),void 0!==t)for(let e=0,r=t.length;e&lt;r;e++){const r=(new Vo).fromJSON(t[e],i);n[r.uuid]=r}return n}parseGeometries(t,e){const n={};if(void 0!==t){const i=new cu;for(let r=0,s=t.length;r&lt;s;r++){let s;const a=t[r];switch(a.type){case&quot;BufferGeometry&quot;:case&quot;InstancedBufferGeometry&quot;:s=i.parse(a);break;default:a.type in nh?s=nh[a.type].fromJSON(a,e):console.warn(`THREE.ObjectLoader: Unsupported geometry type &quot;${a.type}&quot;`)}s.uuid=a.uuid,void 0!==a.name&amp;&amp;(s.name=a.name),void 0!==a.userData&amp;&amp;(s.userData=a.userData),n[a.uuid]=s}}return n}parseMaterials(t,e){const n={},i={};if(void 0!==t){const r=new au;r.setTextures(e);for(let e=0,s=t.length;e&lt;s;e++){const s=t[e];void 0===n[s.uuid]&amp;&amp;(n[s.uuid]=r.parse(s)),i[s.uuid]=n[s.uuid]}}return i}parseAnimations(t){const e={};if(void 0!==t)for(let n=0;n&lt;t.length;n++){const i=t[n],r=Ph.parse(i);e[r.uuid]=r}return e}parseImages(t,e){const n=this,i={};let r;function s(t){if(&quot;string&quot;==typeof t){const e=t;return function(t){return n.manager.itemStart(t),r.load(t,(function(){n.manager.itemEnd(t)}),void 0,(function(){n.manager.itemError(t),n.manager.itemEnd(t)}))}(/^(\/\/)|([a-z]+:(\/\/)?)/i.test(e)?e:n.resourcePath+e)}return t.data?{data:xe(t.type,t.data),width:t.width,height:t.height}:null}if(void 0!==t&amp;&amp;t.length&gt;0){const n=new Dh(e);r=new Gh(n),r.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e&lt;n;e++){const n=t[e],r=n.url;if(Array.isArray(r)){const t=[];for(let e=0,n=r.length;e&lt;n;e++){const n=s(r[e]);null!==n&amp;&amp;(n instanceof HTMLImageElement?t.push(n):t.push(new zo(n.data,n.width,n.height)))}i[n.uuid]=new De(t)}else{const t=s(n.url);i[n.uuid]=new De(t)}}}return i}async parseImagesAsync(t){const e=this,n={};let i;async function r(t){if(&quot;string&quot;==typeof t){const n=t,r=/^(\/\/)|([a-z]+:(\/\/)?)/i.test(n)?n:e.resourcePath+n;return await i.loadAsync(r)}return t.data?{data:xe(t.type,t.data),width:t.width,height:t.height}:null}if(void 0!==t&amp;&amp;t.length&gt;0){i=new Gh(this.manager),i.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e&lt;i;e++){const i=t[e],s=i.url;if(Array.isArray(s)){const t=[];for(let e=0,n=s.length;e&lt;n;e++){const n=s[e],i=await r(n);null!==i&amp;&amp;(i instanceof HTMLImageElement?t.push(i):t.push(new zo(i.data,i.width,i.height)))}n[i.uuid]=new De(t)}else{const t=await r(i.url);n[i.uuid]=new De(t)}}}return n}parseTextures(t,e){function n(t,e){return&quot;number&quot;==typeof t?t:(console.warn(&quot;THREE.ObjectLoader.parseTexture: Constant should be in numeric form.&quot;,t),e[t])}const i={};if(void 0!==t)for(let r=0,s=t.length;r&lt;s;r++){const s=t[r];void 0===s.image&amp;&amp;console.warn('THREE.ObjectLoader: No &quot;image&quot; specified for',s.uuid),void 0===e[s.image]&amp;&amp;console.warn(&quot;THREE.ObjectLoader: Undefined image&quot;,s.image);const a=e[s.image],o=a.data;let l;Array.isArray(o)?(l=new lr,6===o.length&amp;&amp;(l.needsUpdate=!0)):(l=o&amp;&amp;o.data?new zo:new Fe,o&amp;&amp;(l.needsUpdate=!0)),l.source=a,l.uuid=s.uuid,void 0!==s.name&amp;&amp;(l.name=s.name),void 0!==s.mapping&amp;&amp;(l.mapping=n(s.mapping,hu)),void 0!==s.channel&amp;&amp;(l.channel=s.channel),void 0!==s.offset&amp;&amp;l.offset.fromArray(s.offset),void 0!==s.repeat&amp;&amp;l.repeat.fromArray(s.repeat),void 0!==s.center&amp;&amp;l.center.fromArray(s.center),void 0!==s.rotation&amp;&amp;(l.rotation=s.rotation),void 0!==s.wrap&amp;&amp;(l.wrapS=n(s.wrap[0],uu),l.wrapT=n(s.wrap[1],uu)),void 0!==s.format&amp;&amp;(l.format=s.format),void 0!==s.internalFormat&amp;&amp;(l.internalFormat=s.internalFormat),void 0!==s.type&amp;&amp;(l.type=s.type),void 0!==s.colorSpace&amp;&amp;(l.colorSpace=s.colorSpace),void 0!==s.encoding&amp;&amp;(l.encoding=s.encoding),void 0!==s.minFilter&amp;&amp;(l.minFilter=n(s.minFilter,du)),void 0!==s.magFilter&amp;&amp;(l.magFilter=n(s.magFilter,du)),void 0!==s.anisotropy&amp;&amp;(l.anisotropy=s.anisotropy),void 0!==s.flipY&amp;&amp;(l.flipY=s.flipY),void 0!==s.generateMipmaps&amp;&amp;(l.generateMipmaps=s.generateMipmaps),void 0!==s.premultiplyAlpha&amp;&amp;(l.premultiplyAlpha=s.premultiplyAlpha),void 0!==s.unpackAlignment&amp;&amp;(l.unpackAlignment=s.unpackAlignment),void 0!==s.compareFunction&amp;&amp;(l.compareFunction=s.compareFunction),void 0!==s.userData&amp;&amp;(l.userData=s.userData),i[s.uuid]=l}return i}parseObject(t,e,n,i,r){let s,a,o;function l(t){return void 0===e[t]&amp;&amp;console.warn(&quot;THREE.ObjectLoader: Undefined geometry&quot;,t),e[t]}function c(t){if(void 0!==t){if(Array.isArray(t)){const e=[];for(let i=0,r=t.length;i&lt;r;i++){const r=t[i];void 0===n[r]&amp;&amp;console.warn(&quot;THREE.ObjectLoader: Undefined material&quot;,r),e.push(n[r])}return e}return void 0===n[t]&amp;&amp;console.warn(&quot;THREE.ObjectLoader: Undefined material&quot;,t),n[t]}}function h(t){return void 0===i[t]&amp;&amp;console.warn(&quot;THREE.ObjectLoader: Undefined texture&quot;,t),i[t]}switch(t.type){case&quot;Scene&quot;:s=new ro,void 0!==t.background&amp;&amp;(Number.isInteger(t.background)?s.background=new ci(t.background):s.background=h(t.background)),void 0!==t.environment&amp;&amp;(s.environment=h(t.environment)),void 0!==t.fog&amp;&amp;(&quot;Fog&quot;===t.fog.type?s.fog=new io(t.fog.color,t.fog.near,t.fog.far):&quot;FogExp2&quot;===t.fog.type&amp;&amp;(s.fog=new no(t.fog.color,t.fog.density)),&quot;&quot;!==t.fog.name&amp;&amp;(s.fog.name=t.fog.name)),void 0!==t.backgroundBlurriness&amp;&amp;(s.backgroundBlurriness=t.backgroundBlurriness),void 0!==t.backgroundIntensity&amp;&amp;(s.backgroundIntensity=t.backgroundIntensity);break;case&quot;PerspectiveCamera&quot;:s=new sr(t.fov,t.aspect,t.near,t.far),void 0!==t.focus&amp;&amp;(s.focus=t.focus),void 0!==t.zoom&amp;&amp;(s.zoom=t.zoom),void 0!==t.filmGauge&amp;&amp;(s.filmGauge=t.filmGauge),void 0!==t.filmOffset&amp;&amp;(s.filmOffset=t.filmOffset),void 0!==t.view&amp;&amp;(s.view=Object.assign({},t.view));break;case&quot;OrthographicCamera&quot;:s=new Lr(t.left,t.right,t.top,t.bottom,t.near,t.far),void 0!==t.zoom&amp;&amp;(s.zoom=t.zoom),void 0!==t.view&amp;&amp;(s.view=Object.assign({},t.view));break;case&quot;AmbientLight&quot;:s=new nu(t.color,t.intensity);break;case&quot;DirectionalLight&quot;:s=new eu(t.color,t.intensity);break;case&quot;PointLight&quot;:s=new Qh(t.color,t.intensity,t.distance,t.decay);break;case&quot;RectAreaLight&quot;:s=new iu(t.color,t.intensity,t.width,t.height);break;case&quot;SpotLight&quot;:s=new Yh(t.color,t.intensity,t.distance,t.angle,t.penumbra,t.decay);break;case&quot;HemisphereLight&quot;:s=new Vh(t.color,t.groundColor,t.intensity);break;case&quot;LightProbe&quot;:s=(new su).fromJSON(t);break;case&quot;SkinnedMesh&quot;:a=l(t.geometry),o=c(t.material),s=new Fo(a,o),void 0!==t.bindMode&amp;&amp;(s.bindMode=t.bindMode),void 0!==t.bindMatrix&amp;&amp;s.bindMatrix.fromArray(t.bindMatrix),void 0!==t.skeleton&amp;&amp;(s.skeleton=t.skeleton);break;case&quot;Mesh&quot;:a=l(t.geometry),o=c(t.material),s=new Ji(a,o);break;case&quot;InstancedMesh&quot;:a=l(t.geometry),o=c(t.material);const e=t.count,n=t.instanceMatrix,i=t.instanceColor;s=new Ko(a,o,e),s.instanceMatrix=new ko(new Float32Array(n.array),16),void 0!==i&amp;&amp;(s.instanceColor=new ko(new Float32Array(i.array),i.itemSize));break;case&quot;BatchedMesh&quot;:a=l(t.geometry),o=c(t.material),s=new ml(t.maxGeometryCount,t.maxVertexCount,t.maxIndexCount,o),s.geometry=a,s.perObjectFrustumCulled=t.perObjectFrustumCulled,s.sortObjects=t.sortObjects,s._drawRanges=t.drawRanges,s._reservedRanges=t.reservedRanges,s._visibility=t.visibility,s._active=t.active,s._bounds=t.bounds.map((t=&gt;{const e=new qe;e.min.fromArray(t.boxMin),e.max.fromArray(t.boxMax);const n=new dn;return n.radius=t.sphereRadius,n.center.fromArray(t.sphereCenter),{boxInitialized:t.boxInitialized,box:e,sphereInitialized:t.sphereInitialized,sphere:n}})),s._maxGeometryCount=t.maxGeometryCount,s._maxVertexCount=t.maxVertexCount,s._maxIndexCount=t.maxIndexCount,s._geometryInitialized=t.geometryInitialized,s._geometryCount=t.geometryCount,s._matricesTexture=h(t.matricesTexture.uuid);break;case&quot;LOD&quot;:s=new Ao;break;case&quot;Line&quot;:s=new Ml(l(t.geometry),c(t.material));break;case&quot;LineLoop&quot;:s=new El(l(t.geometry),c(t.material));break;case&quot;LineSegments&quot;:s=new Tl(l(t.geometry),c(t.material));break;case&quot;PointCloud&quot;:case&quot;Points&quot;:s=new Pl(l(t.geometry),c(t.material));break;case&quot;Sprite&quot;:s=new bo(c(t.material));break;case&quot;Group&quot;:s=new Ya;break;case&quot;Bone&quot;:s=new Bo;break;default:s=new jn}if(s.uuid=t.uuid,void 0!==t.name&amp;&amp;(s.name=t.name),void 0!==t.matrix?(s.matrix.fromArray(t.matrix),void 0!==t.matrixAutoUpdate&amp;&amp;(s.matrixAutoUpdate=t.matrixAutoUpdate),s.matrixAutoUpdate&amp;&amp;s.matrix.decompose(s.position,s.quaternion,s.scale)):(void 0!==t.position&amp;&amp;s.position.fromArray(t.position),void 0!==t.rotation&amp;&amp;s.rotation.fromArray(t.rotation),void 0!==t.quaternion&amp;&amp;s.quaternion.fromArray(t.quaternion),void 0!==t.scale&amp;&amp;s.scale.fromArray(t.scale)),void 0!==t.up&amp;&amp;s.up.fromArray(t.up),void 0!==t.castShadow&amp;&amp;(s.castShadow=t.castShadow),void 0!==t.receiveShadow&amp;&amp;(s.receiveShadow=t.receiveShadow),t.shadow&amp;&amp;(void 0!==t.shadow.bias&amp;&amp;(s.shadow.bias=t.shadow.bias),void 0!==t.shadow.normalBias&amp;&amp;(s.shadow.normalBias=t.shadow.normalBias),void 0!==t.shadow.radius&amp;&amp;(s.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&amp;&amp;s.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&amp;&amp;(s.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&amp;&amp;(s.visible=t.visible),void 0!==t.frustumCulled&amp;&amp;(s.frustumCulled=t.frustumCulled),void 0!==t.renderOrder&amp;&amp;(s.renderOrder=t.renderOrder),void 0!==t.userData&amp;&amp;(s.userData=t.userData),void 0!==t.layers&amp;&amp;(s.layers.mask=t.layers),void 0!==t.children){const a=t.children;for(let t=0;t&lt;a.length;t++)s.add(this.parseObject(a[t],e,n,i,r))}if(void 0!==t.animations){const e=t.animations;for(let t=0;t&lt;e.length;t++){const n=e[t];s.animations.push(r[n])}}if(&quot;LOD&quot;===t.type){void 0!==t.autoUpdate&amp;&amp;(s.autoUpdate=t.autoUpdate);const e=t.levels;for(let t=0;t&lt;e.length;t++){const n=e[t],i=s.getObjectByProperty(&quot;uuid&quot;,n.object);void 0!==i&amp;&amp;s.addLevel(i,n.distance,n.hysteresis)}}return s}bindSkeletons(t,e){0!==Object.keys(e).length&amp;&amp;t.traverse((function(t){if(!0===t.isSkinnedMesh&amp;&amp;void 0!==t.skeleton){const n=e[t.skeleton];void 0===n?console.warn(&quot;THREE.ObjectLoader: No skeleton found with UUID:&quot;,t.skeleton):t.bind(n,t.bindMatrix)}}))}},t.ObjectSpaceNormalMap=1,t.OctahedronGeometry=jc,t.OneFactor=201,t.OneMinusConstantAlphaFactor=214,t.OneMinusConstantColorFactor=212,t.OneMinusDstAlphaFactor=207,t.OneMinusDstColorFactor=209,t.OneMinusSrcAlphaFactor=c,t.OneMinusSrcColorFactor=203,t.OrthographicCamera=Lr,t.P3Primaries=qt,t.PCFShadowMap=n,t.PCFSoftShadowMap=i,t.PMREMGenerator=Hr,t.Path=ec,t.PerspectiveCamera=sr,t.Plane=pr,t.PlaneGeometry=xr,t.PlaneHelper=class extends Ml{constructor(t,e=1,n=16776960){const i=n,r=new Ii;r.setAttribute(&quot;position&quot;,new Ti([1,-1,0,-1,1,0,-1,-1,0,1,1,0,-1,1,0,-1,-1,0,1,-1,0,1,1,0],3)),r.computeBoundingSphere(),super(r,new fl({color:i,toneMapped:!1})),this.type=&quot;PlaneHelper&quot;,this.plane=t,this.size=e;const s=new Ii;s.setAttribute(&quot;position&quot;,new Ti([1,1,0,-1,1,0,-1,-1,0,1,1,0,-1,-1,0,1,-1,0],3)),s.computeBoundingSphere(),this.add(new Ji(s,new pi({color:i,opacity:.2,transparent:!0,depthWrite:!1,toneMapped:!1})))}updateMatrixWorld(t){this.position.set(0,0,0),this.scale.set(.5*this.size,.5*this.size,1),this.lookAt(this.plane.normal),this.translateZ(-this.plane.constant),super.updateMatrixWorld(t)}dispose(){this.geometry.dispose(),this.material.dispose(),this.children[0].geometry.dispose(),this.children[0].material.dispose()}},t.PointLight=Qh,t.PointLightHelper=class extends Ji{constructor(t,e,n){super(new Zc(e,4,2),new pi({wireframe:!0,fog:!1,toneMapped:!1})),this.light=t,this.color=n,this.type=&quot;PointLightHelper&quot;,this.matrix=this.light.matrixWorld,this.matrixAutoUpdate=!1,this.update()}dispose(){this.geometry.dispose(),this.material.dispose()}update(){this.light.updateWorldMatrix(!0,!1),void 0!==this.color?this.material.color.set(this.color):this.material.color.copy(this.light.color)}},t.Points=Pl,t.PointsMaterial=wl,t.PolarGridHelper=class extends Tl{constructor(t=10,e=16,n=8,i=64,r=4473924,s=8947848){r=new ci(r),s=new ci(s);const a=[],o=[];if(e&gt;1)for(let n=0;n&lt;e;n++){const i=n/e*(2*Math.PI),l=Math.sin(i)*t,c=Math.cos(i)*t;a.push(0,0,0),a.push(l,0,c);const h=1&amp;n?r:s;o.push(h.r,h.g,h.b),o.push(h.r,h.g,h.b)}for(let e=0;e&lt;n;e++){const l=1&amp;e?r:s,c=t-t/n*e;for(let t=0;t&lt;i;t++){let e=t/i*(2*Math.PI),n=Math.sin(e)*c,r=Math.cos(e)*c;a.push(n,0,r),o.push(l.r,l.g,l.b),e=(t+1)/i*(2*Math.PI),n=Math.sin(e)*c,r=Math.cos(e)*c,a.push(n,0,r),o.push(l.r,l.g,l.b)}}const l=new Ii;l.setAttribute(&quot;position&quot;,new Ti(a,3)),l.setAttribute(&quot;color&quot;,new Ti(o,3));super(l,new fl({vertexColors:!0,toneMapped:!1})),this.type=&quot;PolarGridHelper&quot;}dispose(){this.geometry.dispose(),this.material.dispose()}},t.PolyhedronGeometry=oc,t.PositionalAudio=class extends Tu{constructor(t){super(t),this.panner=this.context.createPanner(),this.panner.panningModel=&quot;HRTF&quot;,this.panner.connect(this.gain)}connect(){super.connect(),this.panner.connect(this.gain)}disconnect(){super.disconnect(),this.panner.disconnect(this.gain)}getOutput(){return this.panner}getRefDistance(){return this.panner.refDistance}setRefDistance(t){return this.panner.refDistance=t,this}getRolloffFactor(){return this.panner.rolloffFactor}setRolloffFactor(t){return this.panner.rolloffFactor=t,this}getDistanceModel(){return this.panner.distanceModel}setDistanceModel(t){return this.panner.distanceModel=t,this}getMaxDistance(){return this.panner.maxDistance}setMaxDistance(t){return this.panner.maxDistance=t,this}setDirectionalCone(t,e,n){return this.panner.coneInnerAngle=t,this.panner.coneOuterAngle=e,this.panner.coneOuterGain=n,this}updateMatrixWorld(t){if(super.updateMatrixWorld(t),!0===this.hasPlaybackControl&amp;&amp;!1===this.isPlaying)return;this.matrixWorld.decompose(Eu,wu,Au),Ru.set(0,0,1).applyQuaternion(wu);const e=this.panner;if(e.positionX){const t=this.context.currentTime+this.listener.timeDelta;e.positionX.linearRampToValueAtTime(Eu.x,t),e.positionY.linearRampToValueAtTime(Eu.y,t),e.positionZ.linearRampToValueAtTime(Eu.z,t),e.orientationX.linearRampToValueAtTime(Ru.x,t),e.orientationY.linearRampToValueAtTime(Ru.y,t),e.orientationZ.linearRampToValueAtTime(Ru.z,t)}else e.setPosition(Eu.x,Eu.y,Eu.z),e.setOrientation(Ru.x,Ru.y,Ru.z)}},t.PropertyBinding=Ou,t.PropertyMixer=Cu,t.QuadraticBezierCurve=Jl,t.QuadraticBezierCurve3=Kl,t.Quaternion=ke,t.QuaternionKeyframeTrack=Rh,t.QuaternionLinearInterpolant=Ah,t.RED_GREEN_RGTC2_Format=At,t.RED_RGTC1_Format=36283,t.REVISION=e,t.RGBADepthPacking=3201,t.RGBAFormat=j,t.RGBAIntegerFormat=K,t.RGBA_ASTC_10x10_Format=yt,t.RGBA_ASTC_10x5_Format=_t,t.RGBA_ASTC_10x6_Format=vt,t.RGBA_ASTC_10x8_Format=xt,t.RGBA_ASTC_12x10_Format=Mt,t.RGBA_ASTC_12x12_Format=St,t.RGBA_ASTC_4x4_Format=ct,t.RGBA_ASTC_5x4_Format=ht,t.RGBA_ASTC_5x5_Format=ut,t.RGBA_ASTC_6x5_Format=dt,t.RGBA_ASTC_6x6_Format=pt,t.RGBA_ASTC_8x5_Format=mt,t.RGBA_ASTC_8x6_Format=ft,t.RGBA_ASTC_8x8_Format=gt,t.RGBA_BPTC_Format=bt,t.RGBA_ETC2_EAC_Format=lt,t.RGBA_PVRTC_2BPPV1_Format=st,t.RGBA_PVRTC_4BPPV1_Format=rt,t.RGBA_S3TC_DXT1_Format=Q,t.RGBA_S3TC_DXT3_Format=tt,t.RGBA_S3TC_DXT5_Format=et,t.RGB_BPTC_SIGNED_Format=Tt,t.RGB_BPTC_UNSIGNED_Format=Et,t.RGB_ETC1_Format=at,t.RGB_ETC2_Format=ot,t.RGB_PVRTC_2BPPV1_Format=it,t.RGB_PVRTC_4BPPV1_Format=nt,t.RGB_S3TC_DXT1_Format=$,t.RGFormat=1030,t.RGIntegerFormat=J,t.RawShaderMaterial=rh,t.Ray=yn,t.Raycaster=class{constructor(t,e,n=0,i=1/0){this.ray=new yn(t,e),this.near=n,this.far=i,this.camera=null,this.layers=new In,this.params={Mesh:{},Line:{threshold:1},LOD:{},Points:{threshold:1},Sprite:{}}}set(t,e){this.ray.set(t,e)}setFromCamera(t,e){e.isPerspectiveCamera?(this.ray.origin.setFromMatrixPosition(e.matrixWorld),this.ray.direction.set(t.x,t.y,.5).unproject(e).sub(this.ray.origin).normalize(),this.camera=e):e.isOrthographicCamera?(this.ray.origin.set(t.x,t.y,(e.near+e.far)/(e.near-e.far)).unproject(e),this.ray.direction.set(0,0,-1).transformDirection(e.matrixWorld),this.camera=e):console.error(&quot;THREE.Raycaster: Unsupported camera type: &quot;+e.type)}intersectObject(t,e=!0,n=[]){return Vu(t,this,n,e),n.sort(Hu),n}intersectObjects(t,e=!0,n=[]){for(let i=0,r=t.length;i&lt;r;i++)Vu(t[i],this,n,e);return n.sort(Hu),n}},t.Rec709Primaries=jt,t.RectAreaLight=iu,t.RedFormat=1028,t.RedIntegerFormat=Z,t.ReinhardToneMapping=f,t.RenderTarget=ze,t.RepeatWrapping=R,t.ReplaceStencilOp=7681,t.ReverseSubtractEquation=102,t.RingGeometry=qc,t.SIGNED_RED_GREEN_RGTC2_Format=Rt,t.SIGNED_RED_RGTC1_Format=wt,t.SRGBColorSpace=Gt,t.SRGBTransfer=Xt,t.Scene=ro,t.ShaderChunk=yr,t.ShaderLib=Sr,t.ShaderMaterial=ir,t.ShadowMaterial=ih,t.Shape=mc,t.ShapeGeometry=Yc,t.ShapePath=class{constructor(){this.type=&quot;ShapePath&quot;,this.color=new ci,this.subPaths=[],this.currentPath=null}moveTo(t,e){return this.currentPath=new ec,this.subPaths.push(this.currentPath),this.currentPath.moveTo(t,e),this}lineTo(t,e){return this.currentPath.lineTo(t,e),this}quadraticCurveTo(t,e,n,i){return this.currentPath.quadraticCurveTo(t,e,n,i),this}bezierCurveTo(t,e,n,i,r,s){return this.currentPath.bezierCurveTo(t,e,n,i,r,s),this}splineThru(t){return this.currentPath.splineThru(t),this}toShapes(t){function e(t,e){const n=e.length;let i=!1;for(let r=n-1,s=0;s&lt;n;r=s++){let n=e[r],a=e[s],o=a.x-n.x,l=a.y-n.y;if(Math.abs(l)&gt;Number.EPSILON){if(l&lt;0&amp;&amp;(n=e[s],o=-o,a=e[r],l=-l),t.y&lt;n.y||t.y&gt;a.y)continue;if(t.y===n.y){if(t.x===n.x)return!0}else{const e=l*(t.x-n.x)-o*(t.y-n.y);if(0===e)return!0;if(e&lt;0)continue;i=!i}}else{if(t.y!==n.y)continue;if(a.x&lt;=t.x&amp;&amp;t.x&lt;=n.x||n.x&lt;=t.x&amp;&amp;t.x&lt;=a.x)return!0}}return i}const n=Gc.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,s,a;const o=[];if(1===i.length)return s=i[0],a=new mc,a.curves=s.curves,o.push(a),o;let l=!n(i[0].getPoints());l=t?!l:l;const c=[],h=[];let u,d,p=[],m=0;h[m]=void 0,p[m]=[];for(let e=0,a=i.length;e&lt;a;e++)s=i[e],u=s.getPoints(),r=n(u),r=t?!r:r,r?(!l&amp;&amp;h[m]&amp;&amp;m++,h[m]={s:new mc,p:u},h[m].s.curves=s.curves,l&amp;&amp;m++,p[m]=[]):p[m].push({h:s,p:u[0]});if(!h[0])return function(t){const e=[];for(let n=0,i=t.length;n&lt;i;n++){const i=t[n],r=new mc;r.curves=i.curves,e.push(r)}return e}(i);if(h.length&gt;1){let t=!1,n=0;for(let t=0,e=h.length;t&lt;e;t++)c[t]=[];for(let i=0,r=h.length;i&lt;r;i++){const r=p[i];for(let s=0;s&lt;r.length;s++){const a=r[s];let o=!0;for(let r=0;r&lt;h.length;r++)e(a.p,h[r].p)&amp;&amp;(i!==r&amp;&amp;n++,o?(o=!1,c[r].push(a)):t=!0);o&amp;&amp;c[i].push(a)}}n&gt;0&amp;&amp;!1===t&amp;&amp;(p=c)}for(let t=0,e=h.length;t&lt;e;t++){a=h[t].s,o.push(a),d=p[t];for(let t=0,e=d.length;t&lt;e;t++)a.holes.push(d[t].h)}return o}},t.ShapeUtils=Gc,t.ShortType=1011,t.Skeleton=Vo,t.SkeletonHelper=class extends Tl{constructor(t){const e=Ju(t),n=new Ii,i=[],r=[],s=new ci(0,0,1),a=new ci(0,1,0);for(let t=0;t&lt;e.length;t++){const n=e[t];n.parent&amp;&amp;n.parent.isBone&amp;&amp;(i.push(0,0,0),i.push(0,0,0),r.push(s.r,s.g,s.b),r.push(a.r,a.g,a.b))}n.setAttribute(&quot;position&quot;,new Ti(i,3)),n.setAttribute(&quot;color&quot;,new Ti(r,3));super(n,new fl({vertexColors:!0,depthTest:!1,depthWrite:!1,toneMapped:!1,transparent:!0})),this.isSkeletonHelper=!0,this.type=&quot;SkeletonHelper&quot;,this.root=t,this.bones=e,this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1}updateMatrixWorld(t){const e=this.bones,n=this.geometry,i=n.getAttribute(&quot;position&quot;);Zu.copy(this.root.matrixWorld).invert();for(let t=0,n=0;t&lt;e.length;t++){const r=e[t];r.parent&amp;&amp;r.parent.isBone&amp;&amp;(Yu.multiplyMatrices(Zu,r.matrixWorld),qu.setFromMatrixPosition(Yu),i.setXYZ(n,qu.x,qu.y,qu.z),Yu.multiplyMatrices(Zu,r.parent.matrixWorld),qu.setFromMatrixPosition(Yu),i.setXYZ(n+1,qu.x,qu.y,qu.z),n+=2)}n.getAttribute(&quot;position&quot;).needsUpdate=!0,super.updateMatrixWorld(t)}dispose(){this.geometry.dispose(),this.material.dispose()}},t.SkinnedMesh=Fo,t.Source=De,t.Sphere=dn,t.SphereGeometry=Zc,t.Spherical=class{constructor(t=1,e=0,n=0){return this.radius=t,this.phi=e,this.theta=n,this}set(t,e,n){return this.radius=t,this.phi=e,this.theta=n,this}copy(t){return this.radius=t.radius,this.phi=t.phi,this.theta=t.theta,this}makeSafe(){const t=1e-6;return this.phi=Math.max(t,Math.min(Math.PI-t,this.phi)),this}setFromVector3(t){return this.setFromCartesianCoords(t.x,t.y,t.z)}setFromCartesianCoords(t,e,n){return this.radius=Math.sqrt(t*t+e*e+n*n),0===this.radius?(this.theta=0,this.phi=0):(this.theta=Math.atan2(t,n),this.phi=Math.acos(ae(e/this.radius,-1,1))),this}clone(){return(new this.constructor).copy(this)}},t.SphericalHarmonics3=ru,t.SplineCurve=$l,t.SpotLight=Yh,t.SpotLightHelper=class extends jn{constructor(t,e){super(),this.light=t,this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=e,this.type=&quot;SpotLightHelper&quot;;const n=new Ii,i=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(let t=0,e=1,n=32;t&lt;n;t++,e++){const r=t/n*Math.PI*2,s=e/n*Math.PI*2;i.push(Math.cos(r),Math.sin(r),1,Math.cos(s),Math.sin(s),1)}n.setAttribute(&quot;position&quot;,new Ti(i,3));const r=new fl({fog:!1,toneMapped:!1});this.cone=new Tl(n,r),this.add(this.cone),this.update()}dispose(){this.cone.geometry.dispose(),this.cone.material.dispose()}update(){this.light.updateWorldMatrix(!0,!1),this.light.target.updateWorldMatrix(!0,!1);const t=this.light.distance?this.light.distance:1e3,e=t*Math.tan(this.light.angle);this.cone.scale.set(e,e,t),ju.setFromMatrixPosition(this.light.target.matrixWorld),this.cone.lookAt(ju),void 0!==this.color?this.cone.material.color.set(this.color):this.cone.material.color.copy(this.light.color)}},t.Sprite=bo,t.SpriteMaterial=lo,t.SrcAlphaFactor=l,t.SrcAlphaSaturateFactor=210,t.SrcColorFactor=202,t.StaticCopyUsage=35046,t.StaticDrawUsage=Zt,t.StaticReadUsage=35045,t.StereoCamera=class{constructor(){this.type=&quot;StereoCamera&quot;,this.aspect=1,this.eyeSep=.064,this.cameraL=new sr,this.cameraL.layers.enable(1),this.cameraL.matrixAutoUpdate=!1,this.cameraR=new sr,this.cameraR.layers.enable(2),this.cameraR.matrixAutoUpdate=!1,this._cache={focus:null,fov:null,aspect:null,near:null,far:null,zoom:null,eyeSep:null}}update(t){const e=this._cache;if(e.focus!==t.focus||e.fov!==t.fov||e.aspect!==t.aspect*this.aspect||e.near!==t.near||e.far!==t.far||e.zoom!==t.zoom||e.eyeSep!==this.eyeSep){e.focus=t.focus,e.fov=t.fov,e.aspect=t.aspect*this.aspect,e.near=t.near,e.far=t.far,e.zoom=t.zoom,e.eyeSep=this.eyeSep,_u.copy(t.projectionMatrix);const n=e.eyeSep/2,i=n*e.near/e.focus,r=e.near*Math.tan(ie*e.fov*.5)/e.zoom;let s,a;gu.elements[12]=-n,fu.elements[12]=n,s=-r*e.aspect+i,a=r*e.aspect+i,_u.elements[0]=2*e.near/(a-s),_u.elements[8]=(a+s)/(a-s),this.cameraL.projectionMatrix.copy(_u),s=-r*e.aspect-i,a=r*e.aspect-i,_u.elements[0]=2*e.near/(a-s),_u.elements[8]=(a+s)/(a-s),this.cameraR.projectionMatrix.copy(_u)}this.cameraL.matrixWorld.copy(t.matrixWorld).multiply(gu),this.cameraR.matrixWorld.copy(t.matrixWorld).multiply(fu)}},t.StreamCopyUsage=35042,t.StreamDrawUsage=35040,t.StreamReadUsage=35041,t.StringKeyframeTrack=Ch,t.SubtractEquation=101,t.SubtractiveBlending=3,t.TOUCH={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},t.TangentSpaceNormalMap=0,t.TetrahedronGeometry=Jc,t.Texture=Fe,t.TextureLoader=class extends Oh{constructor(t){super(t)}load(t,e,n,i){const r=new Fe,s=new Gh(this.manager);return s.setCrossOrigin(this.crossOrigin),s.setPath(this.path),s.load(t,(function(t){r.image=t,r.needsUpdate=!0,void 0!==e&amp;&amp;e(r)}),n,i),r}},t.TorusGeometry=Kc,t.TorusKnotGeometry=$c,t.Triangle=ri,t.TriangleFanDrawMode=2,t.TriangleStripDrawMode=1,t.TrianglesDrawMode=0,t.TubeGeometry=Qc,t.TwoPassDoubleSide=2,t.UVMapping=S,t.Uint16BufferAttribute=Si,t.Uint32BufferAttribute=bi,t.Uint8BufferAttribute=class extends Mi{constructor(t,e,n){super(new Uint8Array(t),e,n)}},t.Uint8ClampedBufferAttribute=class extends Mi{constructor(t,e,n){super(new Uint8ClampedArray(t),e,n)}},t.Uniform=zu,t.UniformsGroup=class extends te{constructor(){super(),this.isUniformsGroup=!0,Object.defineProperty(this,&quot;id&quot;,{value:Gu++}),this.name=&quot;&quot;,this.usage=Zt,this.uniforms=[]}add(t){return this.uniforms.push(t),this}remove(t){const e=this.uniforms.indexOf(t);return-1!==e&amp;&amp;this.uniforms.splice(e,1),this}setName(t){return this.name=t,this}setUsage(t){return this.usage=t,this}dispose(){return this.dispatchEvent({type:&quot;dispose&quot;}),this}copy(t){this.name=t.name,this.usage=t.usage;const e=t.uniforms;this.uniforms.length=0;for(let t=0,n=e.length;t&lt;n;t++){const n=Array.isArray(e[t])?e[t]:[e[t]];for(let t=0;t&lt;n.length;t++)this.uniforms.push(n[t].clone())}return this}clone(){return(new this.constructor).copy(this)}},t.UniformsLib=Mr,t.UniformsUtils=nr,t.UnsignedByteType=F,t.UnsignedInt248Type=X,t.UnsignedIntType=G,t.UnsignedShort4444Type=k,t.UnsignedShort5551Type=W,t.UnsignedShortType=B,t.VSMShadowMap=r,t.Vector2=me,t.Vector3=We,t.Vector4=Be,t.VectorKeyframeTrack=Lh,t.VideoTexture=class extends Fe{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.isVideoTexture=!0,this.minFilter=void 0!==s?s:D,this.magFilter=void 0!==r?r:D,this.generateMipmaps=!1;const c=this;&quot;requestVideoFrameCallback&quot;in t&amp;&amp;t.requestVideoFrameCallback((function e(){c.needsUpdate=!0,t.requestVideoFrameCallback(e)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const t=this.image;!1===&quot;requestVideoFrameCallback&quot;in t&amp;&amp;t.readyState&gt;=t.HAVE_CURRENT_DATA&amp;&amp;(this.needsUpdate=!0)}},t.WebGL1Renderer=eo,t.WebGL3DRenderTarget=class extends Ge{constructor(t=1,e=1,n=1,i={}){super(t,e,i),this.isWebGL3DRenderTarget=!0,this.depth=n,this.texture=new Ve(null,t,e,n),this.texture.isRenderTargetTexture=!0}},t.WebGLArrayRenderTarget=class extends Ge{constructor(t=1,e=1,n=1,i={}){super(t,e,i),this.isWebGLArrayRenderTarget=!0,this.depth=n,this.texture=new He(null,t,e,n),this.texture.isRenderTargetTexture=!0}},t.WebGLCoordinateSystem=$t,t.WebGLCubeRenderTarget=cr,t.WebGLMultipleRenderTargets=class extends Ge{constructor(t=1,e=1,n=1,i={}){super(t,e,i),this.isWebGLMultipleRenderTargets=!0;const r=this.texture;this.texture=[];for(let t=0;t&lt;n;t++)this.texture[t]=r.clone(),this.texture[t].isRenderTargetTexture=!0}setSize(t,e,n=1){if(this.width!==t||this.height!==e||this.depth!==n){this.width=t,this.height=e,this.depth=n;for(let i=0,r=this.texture.length;i&lt;r;i++)this.texture[i].image.width=t,this.texture[i].image.height=e,this.texture[i].image.depth=n;this.dispose()}this.viewport.set(0,0,t,e),this.scissor.set(0,0,t,e)}copy(t){this.dispose(),this.width=t.width,this.height=t.height,this.depth=t.depth,this.scissor.copy(t.scissor),this.scissorTest=t.scissorTest,this.viewport.copy(t.viewport),this.depthBuffer=t.depthBuffer,this.stencilBuffer=t.stencilBuffer,null!==t.depthTexture&amp;&amp;(this.depthTexture=t.depthTexture.clone()),this.texture.length=0;for(let e=0,n=t.texture.length;e&lt;n;e++)this.texture[e]=t.texture[e].clone(),this.texture[e].isRenderTargetTexture=!0;return this}},t.WebGLRenderTarget=Ge,t.WebGLRenderer=to,t.WebGLUtils=ja,t.WebGPUCoordinateSystem=Qt,t.WireframeGeometry=th,t.WrapAroundEnding=Dt,t.ZeroCurvatureEnding=It,t.ZeroFactor=200,t.ZeroSlopeEnding=Ut,t.ZeroStencilOp=0,t._SRGBAFormat=Kt,t.createCanvasElement=Me,t.sRGBEncoding=Bt}));

&lt;/script&gt;
&lt;script&gt;
const { EventDispatcher, MOUSE, Quaternion, Spherical, TOUCH, Vector2, Vector3, Plane, Ray, MathUtils } = THREE;

// OrbitControls performs orbiting, dollying (zooming), and panning.
// Unlike TrackballControls, it maintains the &quot;up&quot; direction object.up (+Y by default).
//
//    Orbit - left mouse / touch: one-finger move
//    Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
//    Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move

const _changeEvent = { type: 'change' };
const _startEvent = { type: 'start' };
const _endEvent = { type: 'end' };
const _ray = new Ray();
const _plane = new Plane();
const TILT_LIMIT = Math.cos( 70 * MathUtils.DEG2RAD );

class OrbitControls extends EventDispatcher {

	constructor( object, domElement ) {

		super();

		this.object = object;
		this.domElement = domElement;
		this.domElement.style.touchAction = 'none'; // disable touch scroll

		// Set to false to disable this control
		this.enabled = true;

		// &quot;target&quot; sets the location of focus, where the object orbits around
		this.target = new Vector3();

		// Sets the 3D cursor (similar to Blender), from which the maxTargetRadius takes effect
		this.cursor = new Vector3();

		// How far you can dolly in and out ( PerspectiveCamera only )
		this.minDistance = 0;
		this.maxDistance = Infinity;

		// How far you can zoom in and out ( OrthographicCamera only )
		this.minZoom = 0;
		this.maxZoom = Infinity;

		// Limit camera target within a spherical area around the cursor
		this.minTargetRadius = 0;
		this.maxTargetRadius = Infinity;

		// How far you can orbit vertically, upper and lower limits.
		// Range is 0 to Math.PI radians.
		this.minPolarAngle = 0; // radians
		this.maxPolarAngle = Math.PI; // radians

		// How far you can orbit horizontally, upper and lower limits.
		// If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min &lt; 2 PI )
		this.minAzimuthAngle = - Infinity; // radians
		this.maxAzimuthAngle = Infinity; // radians

		// Set to true to enable damping (inertia)
		// If damping is enabled, you must call controls.update() in your animation loop
		this.enableDamping = false;
		this.dampingFactor = 0.05;

		// This option actually enables dollying in and out; left as &quot;zoom&quot; for backwards compatibility.
		// Set to false to disable zooming
		this.enableZoom = true;
		this.zoomSpeed = 1.0;

		// Set to false to disable rotating
		this.enableRotate = true;
		this.rotateSpeed = 1.0;

		// Set to false to disable panning
		this.enablePan = true;
		this.panSpeed = 1.0;
		this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up
		this.keyPanSpeed = 7.0;	// pixels moved per arrow key push
		this.zoomToCursor = false;

		// Set to true to automatically rotate around the target
		// If auto-rotate is enabled, you must call controls.update() in your animation loop
		this.autoRotate = false;
		this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60

		// The four arrow keys
		this.keys = { LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' };

		// Mouse buttons
		this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };

		// Touch fingers
		this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };

		// for reset
		this.target0 = this.target.clone();
		this.position0 = this.object.position.clone();
		this.zoom0 = this.object.zoom;

		// the target DOM element for key events
		this._domElementKeyEvents = null;

		//
		// public methods
		//

		this.getPolarAngle = function () {

			return spherical.phi;

		};

		this.getAzimuthalAngle = function () {

			return spherical.theta;

		};

		this.getDistance = function () {

			return this.object.position.distanceTo( this.target );

		};

		this.listenToKeyEvents = function ( domElement ) {

			domElement.addEventListener( 'keydown', onKeyDown );
			this._domElementKeyEvents = domElement;

		};

		this.stopListenToKeyEvents = function () {

			this._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
			this._domElementKeyEvents = null;

		};

		this.saveState = function () {

			scope.target0.copy( scope.target );
			scope.position0.copy( scope.object.position );
			scope.zoom0 = scope.object.zoom;

		};

		this.reset = function () {

			scope.target.copy( scope.target0 );
			scope.object.position.copy( scope.position0 );
			scope.object.zoom = scope.zoom0;

			scope.object.updateProjectionMatrix();
			scope.dispatchEvent( _changeEvent );

			scope.update();

			state = STATE.NONE;

		};

		// this method is exposed, but perhaps it would be better if we can make it private...
		this.update = function () {

			const offset = new Vector3();

			// so camera.up is the orbit axis
			const quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );
			const quatInverse = quat.clone().invert();

			const lastPosition = new Vector3();
			const lastQuaternion = new Quaternion();
			const lastTargetPosition = new Vector3();

			const twoPI = 2 * Math.PI;

			return function update( deltaTime = null ) {

				const position = scope.object.position;

				offset.copy( position ).sub( scope.target );

				// rotate offset to &quot;y-axis-is-up&quot; space
				offset.applyQuaternion( quat );

				// angle from z-axis around y-axis
				spherical.setFromVector3( offset );

				if ( scope.autoRotate &amp;&amp; state === STATE.NONE ) {

					rotateLeft( getAutoRotationAngle( deltaTime ) );

				}

				if ( scope.enableDamping ) {

					spherical.theta += sphericalDelta.theta * scope.dampingFactor;
					spherical.phi += sphericalDelta.phi * scope.dampingFactor;

				} else {

					spherical.theta += sphericalDelta.theta;
					spherical.phi += sphericalDelta.phi;

				}

				// restrict theta to be between desired limits

				let min = scope.minAzimuthAngle;
				let max = scope.maxAzimuthAngle;

				if ( isFinite( min ) &amp;&amp; isFinite( max ) ) {

					if ( min &lt; - Math.PI ) min += twoPI; else if ( min &gt; Math.PI ) min -= twoPI;

					if ( max &lt; - Math.PI ) max += twoPI; else if ( max &gt; Math.PI ) max -= twoPI;

					if ( min &lt;= max ) {

						spherical.theta = Math.max( min, Math.min( max, spherical.theta ) );

					} else {

						spherical.theta = ( spherical.theta &gt; ( min + max ) / 2 ) ?
							Math.max( min, spherical.theta ) :
							Math.min( max, spherical.theta );

					}

				}

				// restrict phi to be between desired limits
				spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );

				spherical.makeSafe();


				// move target to panned location

				if ( scope.enableDamping === true ) {

					scope.target.addScaledVector( panOffset, scope.dampingFactor );

				} else {

					scope.target.add( panOffset );

				}

				// Limit the target distance from the cursor to create a sphere around the center of interest
				scope.target.sub( scope.cursor );
				scope.target.clampLength( scope.minTargetRadius, scope.maxTargetRadius );
				scope.target.add( scope.cursor );

				// adjust the camera position based on zoom only if we're not zooming to the cursor or if it's an ortho camera
				// we adjust zoom later in these cases
				if ( scope.zoomToCursor &amp;&amp; performCursorZoom || scope.object.isOrthographicCamera ) {

					spherical.radius = clampDistance( spherical.radius );

				} else {

					spherical.radius = clampDistance( spherical.radius * scale );

				}

				offset.setFromSpherical( spherical );

				// rotate offset back to &quot;camera-up-vector-is-up&quot; space
				offset.applyQuaternion( quatInverse );

				position.copy( scope.target ).add( offset );

				scope.object.lookAt( scope.target );

				if ( scope.enableDamping === true ) {

					sphericalDelta.theta *= ( 1 - scope.dampingFactor );
					sphericalDelta.phi *= ( 1 - scope.dampingFactor );

					panOffset.multiplyScalar( 1 - scope.dampingFactor );

				} else {

					sphericalDelta.set( 0, 0, 0 );

					panOffset.set( 0, 0, 0 );

				}

				// adjust camera position
				let zoomChanged = false;
				if ( scope.zoomToCursor &amp;&amp; performCursorZoom ) {

					let newRadius = null;
					if ( scope.object.isPerspectiveCamera ) {

						// move the camera down the pointer ray
						// this method avoids floating point error
						const prevRadius = offset.length();
						newRadius = clampDistance( prevRadius * scale );

						const radiusDelta = prevRadius - newRadius;
						scope.object.position.addScaledVector( dollyDirection, radiusDelta );
						scope.object.updateMatrixWorld();

					} else if ( scope.object.isOrthographicCamera ) {

						// adjust the ortho camera position based on zoom changes
						const mouseBefore = new Vector3( mouse.x, mouse.y, 0 );
						mouseBefore.unproject( scope.object );

						scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / scale ) );
						scope.object.updateProjectionMatrix();
						zoomChanged = true;

						const mouseAfter = new Vector3( mouse.x, mouse.y, 0 );
						mouseAfter.unproject( scope.object );

						scope.object.position.sub( mouseAfter ).add( mouseBefore );
						scope.object.updateMatrixWorld();

						newRadius = offset.length();

					} else {

						console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled.' );
						scope.zoomToCursor = false;

					}

					// handle the placement of the target
					if ( newRadius !== null ) {

						if ( this.screenSpacePanning ) {

							// position the orbit target in front of the new camera position
							scope.target.set( 0, 0, - 1 )
								.transformDirection( scope.object.matrix )
								.multiplyScalar( newRadius )
								.add( scope.object.position );

						} else {

							// get the ray and translation plane to compute target
							_ray.origin.copy( scope.object.position );
							_ray.direction.set( 0, 0, - 1 ).transformDirection( scope.object.matrix );

							// if the camera is 20 degrees above the horizon then don't adjust the focus target to avoid
							// extremely large values
							if ( Math.abs( scope.object.up.dot( _ray.direction ) ) &lt; TILT_LIMIT ) {

								object.lookAt( scope.target );

							} else {

								_plane.setFromNormalAndCoplanarPoint( scope.object.up, scope.target );
								_ray.intersectPlane( _plane, scope.target );

							}

						}

					}

				} else if ( scope.object.isOrthographicCamera ) {

					scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / scale ) );
					scope.object.updateProjectionMatrix();
					zoomChanged = true;

				}

				scale = 1;
				performCursorZoom = false;

				// update condition is:
				// min(camera displacement, camera rotation in radians)^2 &gt; EPS
				// using small-angle approximation cos(x/2) = 1 - x^2 / 8

				if ( zoomChanged ||
					lastPosition.distanceToSquared( scope.object.position ) &gt; EPS ||
					8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) &gt; EPS ||
					lastTargetPosition.distanceToSquared( scope.target ) &gt; 0 ) {

					scope.dispatchEvent( _changeEvent );

					lastPosition.copy( scope.object.position );
					lastQuaternion.copy( scope.object.quaternion );
					lastTargetPosition.copy( scope.target );

					return true;

				}

				return false;

			};

		}();

		this.dispose = function () {

			scope.domElement.removeEventListener( 'contextmenu', onContextMenu );

			scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
			scope.domElement.removeEventListener( 'pointercancel', onPointerUp );
			scope.domElement.removeEventListener( 'wheel', onMouseWheel );

			scope.domElement.removeEventListener( 'pointermove', onPointerMove );
			scope.domElement.removeEventListener( 'pointerup', onPointerUp );


			if ( scope._domElementKeyEvents !== null ) {

				scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
				scope._domElementKeyEvents = null;

			}

			//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?

		};

		//
		// internals
		//

		const scope = this;

		const STATE = {
			NONE: - 1,
			ROTATE: 0,
			DOLLY: 1,
			PAN: 2,
			TOUCH_ROTATE: 3,
			TOUCH_PAN: 4,
			TOUCH_DOLLY_PAN: 5,
			TOUCH_DOLLY_ROTATE: 6
		};

		let state = STATE.NONE;

		const EPS = 0.000001;

		// current position in spherical coordinates
		const spherical = new Spherical();
		const sphericalDelta = new Spherical();

		let scale = 1;
		const panOffset = new Vector3();

		const rotateStart = new Vector2();
		const rotateEnd = new Vector2();
		const rotateDelta = new Vector2();

		const panStart = new Vector2();
		const panEnd = new Vector2();
		const panDelta = new Vector2();

		const dollyStart = new Vector2();
		const dollyEnd = new Vector2();
		const dollyDelta = new Vector2();

		const dollyDirection = new Vector3();
		const mouse = new Vector2();
		let performCursorZoom = false;

		const pointers = [];
		const pointerPositions = {};

		function getAutoRotationAngle( deltaTime ) {

			if ( deltaTime !== null ) {

				return ( 2 * Math.PI / 60 * scope.autoRotateSpeed ) * deltaTime;

			} else {

				return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;

			}

		}

		function getZoomScale( delta ) {

			const normalized_delta = Math.abs( delta ) / ( 100 * ( window.devicePixelRatio | 0 ) );
			return Math.pow( 0.95, scope.zoomSpeed * normalized_delta );

		}

		function rotateLeft( angle ) {

			sphericalDelta.theta -= angle;

		}

		function rotateUp( angle ) {

			sphericalDelta.phi -= angle;

		}

		const panLeft = function () {

			const v = new Vector3();

			return function panLeft( distance, objectMatrix ) {

				v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
				v.multiplyScalar( - distance );

				panOffset.add( v );

			};

		}();

		const panUp = function () {

			const v = new Vector3();

			return function panUp( distance, objectMatrix ) {

				if ( scope.screenSpacePanning === true ) {

					v.setFromMatrixColumn( objectMatrix, 1 );

				} else {

					v.setFromMatrixColumn( objectMatrix, 0 );
					v.crossVectors( scope.object.up, v );

				}

				v.multiplyScalar( distance );

				panOffset.add( v );

			};

		}();

		// deltaX and deltaY are in pixels; right and down are positive
		const pan = function () {

			const offset = new Vector3();

			return function pan( deltaX, deltaY ) {

				const element = scope.domElement;

				if ( scope.object.isPerspectiveCamera ) {

					// perspective
					const position = scope.object.position;
					offset.copy( position ).sub( scope.target );
					let targetDistance = offset.length();

					// half of the fov is center to top of screen
					targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );

					// we use only clientHeight here so aspect ratio does not distort speed
					panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
					panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );

				} else if ( scope.object.isOrthographicCamera ) {

					// orthographic
					panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );
					panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );

				} else {

					// camera neither orthographic nor perspective
					console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
					scope.enablePan = false;

				}

			};

		}();

		function dollyOut( dollyScale ) {

			if ( scope.object.isPerspectiveCamera || scope.object.isOrthographicCamera ) {

				scale /= dollyScale;

			} else {

				console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
				scope.enableZoom = false;

			}

		}

		function dollyIn( dollyScale ) {

			if ( scope.object.isPerspectiveCamera || scope.object.isOrthographicCamera ) {

				scale *= dollyScale;

			} else {

				console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
				scope.enableZoom = false;

			}

		}

		function updateZoomParameters( x, y ) {

			if ( ! scope.zoomToCursor ) {

				return;

			}

			performCursorZoom = true;

			const rect = scope.domElement.getBoundingClientRect();
			const dx = x - rect.left;
			const dy = y - rect.top;
			const w = rect.width;
			const h = rect.height;

			mouse.x = ( dx / w ) * 2 - 1;
			mouse.y = - ( dy / h ) * 2 + 1;

			dollyDirection.set( mouse.x, mouse.y, 1 ).unproject( scope.object ).sub( scope.object.position ).normalize();

		}

		function clampDistance( dist ) {

			return Math.max( scope.minDistance, Math.min( scope.maxDistance, dist ) );

		}

		//
		// event callbacks - update the object state
		//

		function handleMouseDownRotate( event ) {

			rotateStart.set( event.clientX, event.clientY );

		}

		function handleMouseDownDolly( event ) {

			updateZoomParameters( event.clientX, event.clientX );
			dollyStart.set( event.clientX, event.clientY );

		}

		function handleMouseDownPan( event ) {

			panStart.set( event.clientX, event.clientY );

		}

		function handleMouseMoveRotate( event ) {

			rotateEnd.set( event.clientX, event.clientY );

			rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );

			const element = scope.domElement;

			rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height

			rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );

			rotateStart.copy( rotateEnd );

			scope.update();

		}

		function handleMouseMoveDolly( event ) {

			dollyEnd.set( event.clientX, event.clientY );

			dollyDelta.subVectors( dollyEnd, dollyStart );

			if ( dollyDelta.y &gt; 0 ) {

				dollyOut( getZoomScale( dollyDelta.y ) );

			} else if ( dollyDelta.y &lt; 0 ) {

				dollyIn( getZoomScale( dollyDelta.y ) );

			}

			dollyStart.copy( dollyEnd );

			scope.update();

		}

		function handleMouseMovePan( event ) {

			panEnd.set( event.clientX, event.clientY );

			panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );

			pan( panDelta.x, panDelta.y );

			panStart.copy( panEnd );

			scope.update();

		}

		function handleMouseWheel( event ) {

			updateZoomParameters( event.clientX, event.clientY );

			if ( event.deltaY &lt; 0 ) {

				dollyIn( getZoomScale( event.deltaY ) );

			} else if ( event.deltaY &gt; 0 ) {

				dollyOut( getZoomScale( event.deltaY ) );

			}

			scope.update();

		}

		function handleKeyDown( event ) {

			let needsUpdate = false;

			switch ( event.code ) {

				case scope.keys.UP:

					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {

						rotateUp( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );

					} else {

						pan( 0, scope.keyPanSpeed );

					}

					needsUpdate = true;
					break;

				case scope.keys.BOTTOM:

					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {

						rotateUp( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );

					} else {

						pan( 0, - scope.keyPanSpeed );

					}

					needsUpdate = true;
					break;

				case scope.keys.LEFT:

					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {

						rotateLeft( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );

					} else {

						pan( scope.keyPanSpeed, 0 );

					}

					needsUpdate = true;
					break;

				case scope.keys.RIGHT:

					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {

						rotateLeft( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );

					} else {

						pan( - scope.keyPanSpeed, 0 );

					}

					needsUpdate = true;
					break;

			}

			if ( needsUpdate ) {

				// prevent the browser from scrolling on cursor keys
				event.preventDefault();

				scope.update();

			}


		}

		function handleTouchStartRotate( event ) {

			if ( pointers.length === 1 ) {

				rotateStart.set( event.pageX, event.pageY );

			} else {

				const position = getSecondPointerPosition( event );

				const x = 0.5 * ( event.pageX + position.x );
				const y = 0.5 * ( event.pageY + position.y );

				rotateStart.set( x, y );

			}

		}

		function handleTouchStartPan( event ) {

			if ( pointers.length === 1 ) {

				panStart.set( event.pageX, event.pageY );

			} else {

				const position = getSecondPointerPosition( event );

				const x = 0.5 * ( event.pageX + position.x );
				const y = 0.5 * ( event.pageY + position.y );

				panStart.set( x, y );

			}

		}

		function handleTouchStartDolly( event ) {

			const position = getSecondPointerPosition( event );

			const dx = event.pageX - position.x;
			const dy = event.pageY - position.y;

			const distance = Math.sqrt( dx * dx + dy * dy );

			dollyStart.set( 0, distance );

		}

		function handleTouchStartDollyPan( event ) {

			if ( scope.enableZoom ) handleTouchStartDolly( event );

			if ( scope.enablePan ) handleTouchStartPan( event );

		}

		function handleTouchStartDollyRotate( event ) {

			if ( scope.enableZoom ) handleTouchStartDolly( event );

			if ( scope.enableRotate ) handleTouchStartRotate( event );

		}

		function handleTouchMoveRotate( event ) {

			if ( pointers.length == 1 ) {

				rotateEnd.set( event.pageX, event.pageY );

			} else {

				const position = getSecondPointerPosition( event );

				const x = 0.5 * ( event.pageX + position.x );
				const y = 0.5 * ( event.pageY + position.y );

				rotateEnd.set( x, y );

			}

			rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );

			const element = scope.domElement;

			rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height

			rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );

			rotateStart.copy( rotateEnd );

		}

		function handleTouchMovePan( event ) {

			if ( pointers.length === 1 ) {

				panEnd.set( event.pageX, event.pageY );

			} else {

				const position = getSecondPointerPosition( event );

				const x = 0.5 * ( event.pageX + position.x );
				const y = 0.5 * ( event.pageY + position.y );

				panEnd.set( x, y );

			}

			panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );

			pan( panDelta.x, panDelta.y );

			panStart.copy( panEnd );

		}

		function handleTouchMoveDolly( event ) {

			const position = getSecondPointerPosition( event );

			const dx = event.pageX - position.x;
			const dy = event.pageY - position.y;

			const distance = Math.sqrt( dx * dx + dy * dy );

			dollyEnd.set( 0, distance );

			dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );

			dollyOut( dollyDelta.y );

			dollyStart.copy( dollyEnd );

			const centerX = ( event.pageX + position.x ) * 0.5;
			const centerY = ( event.pageY + position.y ) * 0.5;

			updateZoomParameters( centerX, centerY );

		}

		function handleTouchMoveDollyPan( event ) {

			if ( scope.enableZoom ) handleTouchMoveDolly( event );

			if ( scope.enablePan ) handleTouchMovePan( event );

		}

		function handleTouchMoveDollyRotate( event ) {

			if ( scope.enableZoom ) handleTouchMoveDolly( event );

			if ( scope.enableRotate ) handleTouchMoveRotate( event );

		}

		//
		// event handlers - FSM: listen for events and reset state
		//

		function onPointerDown( event ) {

			if ( scope.enabled === false ) return;

			if ( pointers.length === 0 ) {

				scope.domElement.setPointerCapture( event.pointerId );

				scope.domElement.addEventListener( 'pointermove', onPointerMove );
				scope.domElement.addEventListener( 'pointerup', onPointerUp );

			}

			//

			addPointer( event );

			if ( event.pointerType === 'touch' ) {

				onTouchStart( event );

			} else {

				onMouseDown( event );

			}

		}

		function onPointerMove( event ) {

			if ( scope.enabled === false ) return;

			if ( event.pointerType === 'touch' ) {

				onTouchMove( event );

			} else {

				onMouseMove( event );

			}

		}

		function onPointerUp( event ) {

			removePointer( event );

			if ( pointers.length === 0 ) {

				scope.domElement.releasePointerCapture( event.pointerId );

				scope.domElement.removeEventListener( 'pointermove', onPointerMove );
				scope.domElement.removeEventListener( 'pointerup', onPointerUp );

			}

			scope.dispatchEvent( _endEvent );

			state = STATE.NONE;

		}

		function onMouseDown( event ) {

			let mouseAction;

			switch ( event.button ) {

				case 0:

					mouseAction = scope.mouseButtons.LEFT;
					break;

				case 1:

					mouseAction = scope.mouseButtons.MIDDLE;
					break;

				case 2:

					mouseAction = scope.mouseButtons.RIGHT;
					break;

				default:

					mouseAction = - 1;

			}

			switch ( mouseAction ) {

				case MOUSE.DOLLY:

					if ( scope.enableZoom === false ) return;

					handleMouseDownDolly( event );

					state = STATE.DOLLY;

					break;

				case MOUSE.ROTATE:

					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {

						if ( scope.enablePan === false ) return;

						handleMouseDownPan( event );

						state = STATE.PAN;

					} else {

						if ( scope.enableRotate === false ) return;

						handleMouseDownRotate( event );

						state = STATE.ROTATE;

					}

					break;

				case MOUSE.PAN:

					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {

						if ( scope.enableRotate === false ) return;

						handleMouseDownRotate( event );

						state = STATE.ROTATE;

					} else {

						if ( scope.enablePan === false ) return;

						handleMouseDownPan( event );

						state = STATE.PAN;

					}

					break;

				default:

					state = STATE.NONE;

			}

			if ( state !== STATE.NONE ) {

				scope.dispatchEvent( _startEvent );

			}

		}

		function onMouseMove( event ) {

			switch ( state ) {

				case STATE.ROTATE:

					if ( scope.enableRotate === false ) return;

					handleMouseMoveRotate( event );

					break;

				case STATE.DOLLY:

					if ( scope.enableZoom === false ) return;

					handleMouseMoveDolly( event );

					break;

				case STATE.PAN:

					if ( scope.enablePan === false ) return;

					handleMouseMovePan( event );

					break;

			}

		}

		function onMouseWheel( event ) {

			if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE ) return;

			event.preventDefault();

			scope.dispatchEvent( _startEvent );

			handleMouseWheel( event );

			scope.dispatchEvent( _endEvent );

		}

		function onKeyDown( event ) {

			if ( scope.enabled === false || scope.enablePan === false ) return;

			handleKeyDown( event );

		}

		function onTouchStart( event ) {

			trackPointer( event );

			switch ( pointers.length ) {

				case 1:

					switch ( scope.touches.ONE ) {

						case TOUCH.ROTATE:

							if ( scope.enableRotate === false ) return;

							handleTouchStartRotate( event );

							state = STATE.TOUCH_ROTATE;

							break;

						case TOUCH.PAN:

							if ( scope.enablePan === false ) return;

							handleTouchStartPan( event );

							state = STATE.TOUCH_PAN;

							break;

						default:

							state = STATE.NONE;

					}

					break;

				case 2:

					switch ( scope.touches.TWO ) {

						case TOUCH.DOLLY_PAN:

							if ( scope.enableZoom === false &amp;&amp; scope.enablePan === false ) return;

							handleTouchStartDollyPan( event );

							state = STATE.TOUCH_DOLLY_PAN;

							break;

						case TOUCH.DOLLY_ROTATE:

							if ( scope.enableZoom === false &amp;&amp; scope.enableRotate === false ) return;

							handleTouchStartDollyRotate( event );

							state = STATE.TOUCH_DOLLY_ROTATE;

							break;

						default:

							state = STATE.NONE;

					}

					break;

				default:

					state = STATE.NONE;

			}

			if ( state !== STATE.NONE ) {

				scope.dispatchEvent( _startEvent );

			}

		}

		function onTouchMove( event ) {

			trackPointer( event );

			switch ( state ) {

				case STATE.TOUCH_ROTATE:

					if ( scope.enableRotate === false ) return;

					handleTouchMoveRotate( event );

					scope.update();

					break;

				case STATE.TOUCH_PAN:

					if ( scope.enablePan === false ) return;

					handleTouchMovePan( event );

					scope.update();

					break;

				case STATE.TOUCH_DOLLY_PAN:

					if ( scope.enableZoom === false &amp;&amp; scope.enablePan === false ) return;

					handleTouchMoveDollyPan( event );

					scope.update();

					break;

				case STATE.TOUCH_DOLLY_ROTATE:

					if ( scope.enableZoom === false &amp;&amp; scope.enableRotate === false ) return;

					handleTouchMoveDollyRotate( event );

					scope.update();

					break;

				default:

					state = STATE.NONE;

			}

		}

		function onContextMenu( event ) {

			if ( scope.enabled === false ) return;

			event.preventDefault();

		}

		function addPointer( event ) {

			pointers.push( event.pointerId );

		}

		function removePointer( event ) {

			delete pointerPositions[ event.pointerId ];

			for ( let i = 0; i &lt; pointers.length; i ++ ) {

				if ( pointers[ i ] == event.pointerId ) {

					pointers.splice( i, 1 );
					return;

				}

			}

		}

		function trackPointer( event ) {

			let position = pointerPositions[ event.pointerId ];

			if ( position === undefined ) {

				position = new Vector2();
				pointerPositions[ event.pointerId ] = position;

			}

			position.set( event.pageX, event.pageY );

		}

		function getSecondPointerPosition( event ) {

			const pointerId = ( event.pointerId === pointers[ 0 ] ) ? pointers[ 1 ] : pointers[ 0 ];

			return pointerPositions[ pointerId ];

		}

		//

		scope.domElement.addEventListener( 'contextmenu', onContextMenu );

		scope.domElement.addEventListener( 'pointerdown', onPointerDown );
		scope.domElement.addEventListener( 'pointercancel', onPointerUp );
		scope.domElement.addEventListener( 'wheel', onMouseWheel, { passive: false } );

		// force an update at start

		this.update();

	}

}

&lt;/script&gt;
&lt;script&gt;
(function () {

// ─── SCENE ──────────────────────────────────────────────────────────────────
var scene = new THREE.Scene();
scene.background = new THREE.Color(0x0d0d0d);
scene.fog = new THREE.FogExp2(0x0d0d0d, 0.013);

var _cw = document.getElementById('booth-container').getBoundingClientRect().width || document.getElementById('booth-container').offsetWidth || window.innerWidth;
var _ch = 800;
var camera = new THREE.PerspectiveCamera(45, _cw / _ch, 0.1, 200);
camera.position.set(22, 17, 22);

var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setSize(_cw, _ch);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.getElementById('booth-container').appendChild(renderer.domElement);

var controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.06;
controls.minDistance = 5;
controls.maxDistance = 65;
controls.maxPolarAngle = Math.PI * 0.47;
controls.target.set(0, 0, 0);

// ─── LIGHTING ───────────────────────────────────────────────────────────────
scene.add(new THREE.AmbientLight(0xffffff, 0.55));
var sun = new THREE.DirectionalLight(0xfff8e0, 0.9);
sun.position.set(14, 22, 10);
sun.castShadow = true;
sun.shadow.mapSize.width = sun.shadow.mapSize.height = 2048;
sun.shadow.camera.left = sun.shadow.camera.bottom = -22;
sun.shadow.camera.right = sun.shadow.camera.top = 22;
sun.shadow.camera.near = 1; sun.shadow.camera.far = 60;
scene.add(sun);
var fillLight = new THREE.DirectionalLight(0x4466cc, 0.22);
fillLight.position.set(-10, 12, -10);
scene.add(fillLight);

// ─── CONSTANTS ──────────────────────────────────────────────────────────────
var BW = 9, BD = 12, BH = 4, GAP = 2, NBW = 3;
var CELL_W = BW / 4;    // 2.25m per column
var CELL_D = BD / 5;    // 2.4m per row
var COLS = 4;
var ROWS = 5;
var WALL_HEIGHTS = [0, 1, 2, 4];  // 4 states: 0=없음, 1=1m, 2=2m, 3=4m

// ─── NODE POSITIONS (deformable grid) ────────────────────────────────────────
// nodePos[ci][ri] = {x, z}  — world-space position of each grid intersection
var nodePos = [];
(function initNodePos(){
  for(var ci=0;ci&lt;=COLS;ci++){
    nodePos[ci]=[];
    for(var ri=0;ri&lt;=ROWS;ri++){
      nodePos[ci][ri]={x:-BW/2+ci*CELL_W, z:-BD/2+ri*CELL_D};
    }
  }
})();

// ─── HELPERS ────────────────────────────────────────────────────────────────
var CELL_COLORS = [0x484848, 0x2ecc71, 0x9b59b6, 0x01579b];

function brighten(hex, pct) {
  var r = Math.min(255, Math.round(((hex &gt;&gt; 16) &amp; 0xff) * (1 + pct)));
  var g = Math.min(255, Math.round(((hex &gt;&gt;  8) &amp; 0xff) * (1 + pct)));
  var b = Math.min(255, Math.round(( hex        &amp; 0xff) * (1 + pct)));
  return (r &lt;&lt; 16) | (g &lt;&lt; 8) | b;
}

// Segment transform: unit-length BoxGeometry scaled by actual node distance
function updateSegTransform(seg){
  var A=nodePos[seg.userData.nodeA.ci][seg.userData.nodeA.ri];
  var B=nodePos[seg.userData.nodeB.ci][seg.userData.nodeB.ri];
  var dx=B.x-A.x, dz=B.z-A.z;
  var len=Math.sqrt(dx*dx+dz*dz);
  seg.position.set((A.x+B.x)/2, 0.012, (A.z+B.z)/2);
  seg.rotation.y = -Math.atan2(dz, dx);
  seg.scale.set(len, 1, 1);
}

// Cell floor as deformable quad (BufferGeometry)
function makeCellBuf(){
  var geo=new THREE.BufferGeometry();
  geo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(12), 3));
  geo.setAttribute('normal',   new THREE.BufferAttribute(new Float32Array([0,1,0,0,1,0,0,1,0,0,1,0]), 3));
  geo.setIndex(new THREE.BufferAttribute(new Uint16Array([0,2,1,0,3,2]), 1));
  return geo;
}
function updateCellGeo(m){
  var cc=m.userData.col, cr=m.userData.row;
  var f=0.015;
  var n00=nodePos[cc][cr], n10=nodePos[cc+1][cr];
  var n11=nodePos[cc+1][cr+1], n01=nodePos[cc][cr+1];
  var cx=(n00.x+n10.x+n11.x+n01.x)/4;
  var cz=(n00.z+n10.z+n11.z+n01.z)/4;
  function ins(p){return{x:cx+(p.x-cx)*(1-f),z:cz+(p.z-cz)*(1-f)};}
  var s00=ins(n00),s10=ins(n10),s11=ins(n11),s01=ins(n01);
  var v=m.geometry.attributes.position.array;
  v[0]=s00.x; v[1]=0.001; v[2]=s00.z;
  v[3]=s10.x; v[4]=0.001; v[5]=s10.z;
  v[6]=s11.x; v[7]=0.001; v[8]=s11.z;
  v[9]=s01.x; v[10]=0.001; v[11]=s01.z;
  m.geometry.attributes.position.needsUpdate=true;
  m.geometry.computeBoundingSphere();
}

// 2D geometry helpers for deformed-grid hover detection
function distPtSeg2D(px,pz,ax,az,bx,bz){
  var dx=bx-ax,dz=bz-az,l2=dx*dx+dz*dz;
  if(l2===0)return Math.hypot(px-ax,pz-az);
  var t=Math.max(0,Math.min(1,((px-ax)*dx+(pz-az)*dz)/l2));
  return Math.hypot(px-(ax+t*dx),pz-(az+t*dz));
}
function cross2D(ox,oz,ax,az,bx,bz){return(ax-ox)*(bz-oz)-(az-oz)*(bx-ox);}
function ptInQuad2D(px,pz,n00,n10,n11,n01){
  var s1=cross2D(n00.x,n00.z,n10.x,n10.z,px,pz);
  var s2=cross2D(n10.x,n10.z,n11.x,n11.z,px,pz);
  var s3=cross2D(n11.x,n11.z,n01.x,n01.z,px,pz);
  var s4=cross2D(n01.x,n01.z,n00.x,n00.z,px,pz);
  return(s1&gt;0&amp;&amp;s2&gt;0&amp;&amp;s3&gt;0&amp;&amp;s4&gt;0)||(s1&lt;0&amp;&amp;s2&lt;0&amp;&amp;s3&lt;0&amp;&amp;s4&lt;0);
}

// Area of a quad (two triangles, XZ plane)
function quadArea(n00,n10,n11,n01){
  function tri(a,b,c){return Math.abs((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z))*0.5;}
  return tri(n00,n10,n11)+tri(n00,n11,n01);
}

// Mouse pixel position for tooltip placement
var mouseXY = {x:0, y:0};

function makePlane(w, d, color, y, x, z) {
  y=y||0; x=x||0; z=z||0;
  var m = new THREE.Mesh(new THREE.PlaneGeometry(w, d),
    new THREE.MeshLambertMaterial({ color: color }));
  m.rotation.x = -Math.PI/2; m.position.set(x, y, z);
  m.receiveShadow = true; scene.add(m); return m;
}
function makeOutline(w, d, color, x, z) {
  var yo = 0.005;
  var pts = [new THREE.Vector3(-w/2,yo,-d/2), new THREE.Vector3(w/2,yo,-d/2),
             new THREE.Vector3(w/2,yo,d/2),   new THREE.Vector3(-w/2,yo,d/2),
             new THREE.Vector3(-w/2,yo,-d/2)];
  var ln = new THREE.Line(new THREE.BufferGeometry().setFromPoints(pts),
    new THREE.LineBasicMaterial({ color: color }));
  ln.position.set(x, 0, z); scene.add(ln);
}
function makeSprite(text, x, y, z, color, sx) {
  color=color||'#fff'; sx=sx||3;
  var c=document.createElement('canvas'); c.width=256; c.height=80;
  var ctx=c.getContext('2d');
  ctx.font='bold 44px Arial'; ctx.fillStyle=color;
  ctx.textAlign='center'; ctx.textBaseline='middle';
  ctx.fillText(text,128,40);
  var sp=new THREE.Sprite(new THREE.SpriteMaterial({
    map:new THREE.CanvasTexture(c), transparent:true, depthWrite:false}));
  sp.position.set(x,y,z); sp.scale.set(sx,sx*80/256,1); scene.add(sp);
}

// ─── HALL FLOOR ─────────────────────────────────────────────────────────────
makePlane(70, 70, 0x191919, -0.01);
var hg = new THREE.GridHelper(60, 60, 0x222222, 0x1e1e1e);
hg.position.y = -0.009; scene.add(hg);

// ─── BOOTH CELL FLOORS (4×5, deformable quads) ───────────────────────────────
var cellMeshes = [];
for(var ci=0; ci&lt;COLS; ci++){
  for(var cj=0; cj&lt;ROWS; cj++){
    var mat = new THREE.MeshLambertMaterial({ color: CELL_COLORS[0], side: THREE.DoubleSide });
    var m = new THREE.Mesh(makeCellBuf(), mat);
    m.receiveShadow = true;
    m.userData = { isCell:true, col:ci, row:cj, colorState:0 };
    scene.add(m); cellMeshes.push(m);
    updateCellGeo(m);
  }
}

// ─── NEIGHBOR BOOTHS ────────────────────────────────────────────────────────
function nbBooth(x, z, w, d, label) {
  makePlane(w,d,0x2c2c2c,0.002,x,z);
  makeOutline(w,d,0x484848,x,z);
  makeSprite(label,x,0.4,z,'rgba(255,255,255,0.55)',2.8);
}
nbBooth(0,-(BD/2+GAP+NBW/2),BW,NBW,'MIL');
nbBooth(0, (BD/2+GAP+NBW/2),BW,NBW,'KYS');
nbBooth(-(BW/2+GAP+NBW/2),0,NBW,BD,'MIN');
nbBooth( (BW/2+GAP+NBW/2),0,NBW,BD,'LIB');
var cnx=BW/2+GAP+NBW/2, cnz=BD/2+GAP+NBW/2;
[[-1,-1],[1,-1],[-1,1],[1,1]].forEach(function(s){
  makePlane(NBW,NBW,0x252525,0.002,s[0]*cnx,s[1]*cnz);
  makeOutline(NBW,NBW,0x3a3a3a,s[0]*cnx,s[1]*cnz);
});

// ─── BOOTH WALLS ────────────────────────────────────────────────────────────
var wMat = new THREE.MeshLambertMaterial({
  color:0xdddddd, transparent:true, opacity:0.09,
  side:THREE.DoubleSide, depthWrite:false});
var eMat = new THREE.LineBasicMaterial({ color:0x404040 });
function addWall(w,h,px,py,pz,ry){
  var m=new THREE.Mesh(new THREE.PlaneGeometry(w,h),wMat);
  m.position.set(px,py,pz); m.rotation.y=ry; scene.add(m);
  var el=new THREE.LineSegments(
    new THREE.EdgesGeometry(new THREE.BoxGeometry(w,h,0.001)),eMat);
  el.position.set(px,py,pz); el.rotation.y=ry; scene.add(el);
}
addWall(BW,BH,   0,  BH/2,-BD/2,       0);
addWall(BW,BH,   0,  BH/2, BD/2,       0);
addWall(BD,BH,-BW/2,BH/2,    0,Math.PI/2);
addWall(BD,BH, BW/2,BH/2,    0,Math.PI/2);
var rp=[new THREE.Vector3(-BW/2,BH,-BD/2),new THREE.Vector3(BW/2,BH,-BD/2),
        new THREE.Vector3(BW/2,BH,BD/2),  new THREE.Vector3(-BW/2,BH,BD/2),
        new THREE.Vector3(-BW/2,BH,-BD/2)];
scene.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(rp),
  new THREE.LineBasicMaterial({color:0x555555})));
[-BW/2,BW/2].forEach(function(px){[-BD/2,BD/2].forEach(function(pz){
  scene.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(
    [new THREE.Vector3(px,0,pz),new THREE.Vector3(px,BH,pz)]),
    new THREE.LineBasicMaterial({color:0x505050})));
});});

// ─── GRID SEGMENTS (per-cell) ────────────────────────────────────────────────
var gridSegments = [];
var COL_NORMAL = 0x999999, COL_HOVER = 0xffff00;

var hitPlane = new THREE.Mesh(new THREE.PlaneGeometry(BW,BD),
  new THREE.MeshBasicMaterial({visible:false,side:THREE.DoubleSide}));
hitPlane.rotation.x = -Math.PI/2; hitPlane.position.y = 0.013; scene.add(hitPlane);

// addSeg uses node indices; a unit BoxGeometry scaled by updateSegTransform
function addSeg(ciA,riA,ciB,riB,ud){
  var geo=new THREE.BoxGeometry(1, 0.022, 0.07);
  var mat=new THREE.MeshBasicMaterial({color:COL_NORMAL});
  var m=new THREE.Mesh(geo,mat);
  m.userData=Object.assign({},ud,{nodeA:{ci:ciA,ri:riA},nodeB:{ci:ciB,ri:riB}});
  scene.add(m); gridSegments.push(m);
  updateSegTransform(m);
}
// H segments: j=0..ROWS boundaries, col=0..COLS-1
for(var j=0;j&lt;=ROWS;j++){
  for(var col=0;col&lt;COLS;col++){
    addSeg(col,j,col+1,j,{
      type:'H', col:col, row:j,
      label:'수평 선분 ('+(j===0?'남쪽 경계':j===ROWS?'북쪽 경계':'내부')+') 열 '+(col+1)
    });
  }
}
// V segments: i=0..COLS boundaries, row=0..ROWS-1
for(var i=0;i&lt;=COLS;i++){
  for(var row=0;row&lt;ROWS;row++){
    addSeg(i,row,i,row+1,{
      type:'V', col:i, row:row,
      label:'수직 선분 ('+(i===0?'서쪽 경계':i===COLS?'동쪽 경계':'내부')+') 행 '+(row+1)
    });
  }
}


// ─── CORNER NODES (v3) ───────────────────────────────────────────────────────
var COL_CORNER     = 0xe8e8e8;
var COL_CORNER_HOV = 0xffee33;
var COL_CORNER_DRG = 0xff9900;
var cornerNodes    = [];
var hovCorner      = null;
var dragCorner     = null;
var dragFloorPlane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
var dragPt         = new THREE.Vector3();

(function buildCorners(){
  var geoDisc = new THREE.CylinderGeometry(0.22, 0.22, 0.08, 32);
  for(var ci=0; ci&lt;=COLS; ci++){
    for(var ri=0; ri&lt;=ROWS; ri++){
      var mat = new THREE.MeshLambertMaterial({ color: COL_CORNER });
      var disc = new THREE.Mesh(geoDisc, mat);
      disc.position.set(-BW/2 + ci*CELL_W, 0.065, -BD/2 + ri*CELL_D);
      disc.userData = { type:'corner', ci:ci, ri:ri };
      scene.add(disc);
      cornerNodes.push(disc);
    }
  }
})();

// ─── DIMENSION LABELS ───────────────────────────────────────────────────────
makeSprite('9 m',  0,          0.3, BD/2+0.6,'rgba(255,255,100,0.55)',1.8);
makeSprite('12 m', BW/2+0.7,  0.3, 0,        'rgba(255,255,100,0.55)',1.8);
makeSprite('4 m',  BW/2+0.6,  BH/2,-BD/2,    'rgba(255,255,100,0.45)',1.5);

// ─── YELLOW PARTITION WALLS ──────────────────────────────────────────────────
var segWalls = {};   // segUUID → { grp: THREE.Group, state: 1|2|3 }

function buildWallGroup(seg, h) {
  var A=nodePos[seg.userData.nodeA.ci][seg.userData.nodeA.ri];
  var B=nodePos[seg.userData.nodeB.ci][seg.userData.nodeB.ri];
  var dx=B.x-A.x, dz=B.z-A.z;
  var len=Math.sqrt(dx*dx+dz*dz);
  var cx=(A.x+B.x)/2, cz=(A.z+B.z)/2;
  var ry=-Math.atan2(dz,dx);
  var grp = new THREE.Group();
  var faceMat = new THREE.MeshBasicMaterial({
    color: 0xffdd00, transparent: true, opacity: 0.45,
    side: THREE.DoubleSide, depthWrite: false
  });
  var face = new THREE.Mesh(new THREE.PlaneGeometry(len, h), faceMat);
  grp.add(face);
  var edgeLine = new THREE.LineSegments(
    new THREE.EdgesGeometry(new THREE.BoxGeometry(len, h, 0.02)),
    new THREE.LineBasicMaterial({ color: 0xffff00, linewidth: 2 }));
  grp.add(edgeLine);
  grp.position.set(cx, h/2, cz);
  grp.rotation.y = ry;
  return grp;
}

function cycleWall(seg) {
  var key = seg.uuid;
  var entry = segWalls[key];
  var curState = entry ? entry.state : 0;
  var nextState = (curState + 1) % WALL_HEIGHTS.length;

  if (entry) {
    scene.remove(entry.grp);
    delete segWalls[key];
  }

  if (nextState &gt; 0) {
    var h = WALL_HEIGHTS[nextState];
    var grp = buildWallGroup(seg, h);
    scene.add(grp);
    segWalls[key] = { grp: grp, state: nextState };
  }
}

// ─── LOOKUP HELPERS ──────────────────────────────────────────────────────────
function findHSeg(lz, col) {
  for(var k=0;k&lt;gridSegments.length;k++){
    var s=gridSegments[k];
    if(s.userData.type==='H'&amp;&amp;Math.abs(s.userData.lineZ-lz)&lt;0.01&amp;&amp;s.userData.col===col)return s;
  }
  return null;
}
function findVSeg(lx, row) {
  for(var k=0;k&lt;gridSegments.length;k++){
    var s=gridSegments[k];
    if(s.userData.type==='V'&amp;&amp;Math.abs(s.userData.lineX-lx)&lt;0.01&amp;&amp;s.userData.row===row)return s;
  }
  return null;
}
function findCell(col, row) {
  for(var k=0;k&lt;cellMeshes.length;k++){
    var c=cellMeshes[k];
    if(c.userData.col===col&amp;&amp;c.userData.row===row)return c;
  }
  return null;
}

// ─── INTERACTION ─────────────────────────────────────────────────────────────
var raycaster    = new THREE.Raycaster();
var pointer      = new THREE.Vector2(-9999,-9999);
var hovSeg       = null, hovCell = null;
var hoverTag     = document.getElementById('hover-tag');
var mouseDownXY  = null;   // {x,y} at mousedown — used to detect drag vs click

// pointerdown — capture phase (runs before OrbitControls)
var dragStartXY = null;   // pointerdown position — drag activates after 6px move
renderer.domElement.addEventListener('pointerdown', function(e){
  var _rd=renderer.domElement.getBoundingClientRect();
  var cMouse = new THREE.Vector2(
    _rd.width&gt;0?(e.clientX-_rd.left)/_rd.width*2-1:0,
    _rd.height&gt;0?-((e.clientY-_rd.top)/_rd.height)*2+1:0
  );
  raycaster.setFromCamera(cMouse, camera);
  var cHits = raycaster.intersectObjects(cornerNodes);
  if(cHits.length &gt; 0){
    dragCorner  = cHits[0].object;
    dragStartXY = { x: e.clientX, y: e.clientY };
    controls.enabled = false;
    mouseDownXY = null;   // block cell/seg click
    e.stopPropagation();
    return;
  }
  mouseDownXY = { x: e.clientX, y: e.clientY };
}, true);

renderer.domElement.addEventListener('pointermove', function(e){
  var _r2=renderer.domElement.getBoundingClientRect();
  pointer.x = _r2.width&gt;0?(e.clientX-_r2.left)/_r2.width*2-1:0;
  pointer.y = _r2.height&gt;0?-((e.clientY-_r2.top)/_r2.height)*2+1:0;
  var _cr=renderer.domElement.getBoundingClientRect();
  mouseXY.x = e.clientX - _cr.left; mouseXY.y = e.clientY - _cr.top;
  if(dragCorner){
    // Require at least 6px movement before actually moving the node
    if(dragStartXY){
      var dx=e.clientX-dragStartXY.x, dy=e.clientY-dragStartXY.y;
      if(dx*dx+dy*dy &lt; 36) return;
      dragStartXY = null;   // threshold crossed — start real drag
      dragCorner.material.color.setHex(COL_CORNER_DRG);
      dragCorner.scale.set(1.3, 1.3, 1.3);
    }
    raycaster.setFromCamera(pointer, camera);
    if(raycaster.ray.intersectPlane(dragFloorPlane, dragPt)){
      var _nx=Math.max(-BW/2,Math.min(BW/2,dragPt.x));
      var _nz=Math.max(-BD/2,Math.min(BD/2,dragPt.z));
      var _ci=dragCorner.userData.ci, _ri=dragCorner.userData.ri;
      nodePos[_ci][_ri]={x:_nx,z:_nz};
      dragCorner.position.x=_nx; dragCorner.position.z=_nz;
      // Update adjacent segments
      for(var _si=0;_si&lt;gridSegments.length;_si++){
        var _s=gridSegments[_si];
        var _ua=_s.userData.nodeA,_ub=_s.userData.nodeB;
        if((_ua.ci===_ci&amp;&amp;_ua.ri===_ri)||(_ub.ci===_ci&amp;&amp;_ub.ri===_ri)){
          updateSegTransform(_s);
          if(segWalls[_s.uuid]){
            var _we=segWalls[_s.uuid];
            scene.remove(_we.grp);
            var _wg=buildWallGroup(_s,WALL_HEIGHTS[_we.state]);
            scene.add(_wg);
            segWalls[_s.uuid]={grp:_wg,state:_we.state};
          }
        }
      }
      // Update adjacent cell floors
      for(var _ci2=0;_ci2&lt;cellMeshes.length;_ci2++){
        var _cm=cellMeshes[_ci2];
        var _cc=_cm.userData.col,_cr=_cm.userData.row;
        if(_ci&gt;=_cc&amp;&amp;_ci&lt;=_cc+1&amp;&amp;_ri&gt;=_cr&amp;&amp;_ri&lt;=_cr+1) updateCellGeo(_cm);
      }
    }
  }
});
renderer.domElement.addEventListener('pointerup', function(){
  if(dragCorner){
    dragCorner.material.color.setHex(hovCorner===dragCorner ? COL_CORNER_HOV : COL_CORNER);
    dragCorner.scale.set(1, 1, 1);
    dragCorner  = null;
    dragStartXY = null;
    controls.enabled = true;
  }
});
renderer.domElement.addEventListener('pointerleave', function(){
  pointer.set(-9999,-9999);
  if(dragCorner){
    dragCorner.material.color.setHex(COL_CORNER);
    dragCorner.scale.set(1,1,1);
    dragCorner  = null;
    dragStartXY = null;
    controls.enabled = true;
  }
});

renderer.domElement.addEventListener('click', function(e){
  // Ignore if mouse moved more than 5px since pointerdown (= it was a drag/orbit)
  if(mouseDownXY){
    var dx = e.clientX - mouseDownXY.x, dy = e.clientY - mouseDownXY.y;
    mouseDownXY = null;
    if(Math.sqrt(dx*dx+dy*dy) &gt; 5) return;
  }

  if(hovSeg) {
    cycleWall(hovSeg);
  } else if(hovCell) {
    hovCell.userData.colorState = (hovCell.userData.colorState+1) % CELL_COLORS.length;
    hovCell.material.color.setHex(brighten(CELL_COLORS[hovCell.userData.colorState], 0.10));
  }
});

// ─── KEYBOARD ────────────────────────────────────────────────────────────────
var keys={};
window.addEventListener('keydown',function(e){
  keys[e.key]=true;
  if(['ArrowLeft','ArrowRight','ArrowUp','ArrowDown'].indexOf(e.key)!==-1)e.preventDefault();
});
window.addEventListener('keyup',function(e){ keys[e.key]=false; });
function applyKeys(){
  var any=false; for(var k in keys){if(keys[k]){any=true;break;}} if(!any)return;
  var sph=new THREE.Spherical().setFromVector3(camera.position.clone().sub(controls.target));
  var s=0.028;
  if(keys['ArrowLeft'])  sph.theta-=s;
  if(keys['ArrowRight']) sph.theta+=s;
  if(keys['ArrowUp'])    sph.phi=Math.max(0.06,sph.phi-s);
  if(keys['ArrowDown'])  sph.phi=Math.min(Math.PI*0.47,sph.phi+s);
  camera.position.setFromSpherical(sph).add(controls.target);
}

// ─── RENDER LOOP ─────────────────────────────────────────────────────────────
var THRESH = 0.26;

function animate(){
  requestAnimationFrame(animate);
  applyKeys();
  controls.update();

  raycaster.setFromCamera(pointer, camera);

  // Corner node hover (highest priority — skip seg/cell when dragging or hovering corner)
  var newCorner = null;
  if(!dragCorner){
    var cHits = raycaster.intersectObjects(cornerNodes);
    newCorner = cHits.length &gt; 0 ? cHits[0].object : null;
  } else {
    newCorner = dragCorner;
  }
  if(newCorner !== hovCorner){
    if(hovCorner &amp;&amp; hovCorner !== dragCorner){
      hovCorner.material.color.setHex(COL_CORNER);
      hovCorner.scale.set(1,1,1);
    }
    hovCorner = newCorner;
    if(hovCorner &amp;&amp; !dragCorner){
      hovCorner.material.color.setHex(COL_CORNER_HOV);
      hovCorner.scale.set(1.25, 1.25, 1.25);
    }
  }

  var hit = raycaster.intersectObject(hitPlane);
  var newSeg=null, newCell=null;
  if(!newCorner &amp;&amp; hit.length){
    var px=hit[0].point.x, pz=hit[0].point.z;
    // Find nearest segment using actual node positions
    var bestSegDist=THRESH, bestSeg=null;
    for(var _k=0;_k&lt;gridSegments.length;_k++){
      var _s=gridSegments[_k];
      var _nA=nodePos[_s.userData.nodeA.ci][_s.userData.nodeA.ri];
      var _nB=nodePos[_s.userData.nodeB.ci][_s.userData.nodeB.ri];
      var _d=distPtSeg2D(px,pz,_nA.x,_nA.z,_nB.x,_nB.z);
      if(_d&lt;bestSegDist){bestSegDist=_d;bestSeg=_s;}
    }
    if(bestSeg){
      newSeg=bestSeg;
    } else {
      // Find cell using quad containment test
      for(var _k2=0;_k2&lt;cellMeshes.length;_k2++){
        var _cm=cellMeshes[_k2];
        var _cc=_cm.userData.col,_cr=_cm.userData.row;
        if(ptInQuad2D(px,pz,nodePos[_cc][_cr],nodePos[_cc+1][_cr],nodePos[_cc+1][_cr+1],nodePos[_cc][_cr+1])){
          newCell=_cm; break;
        }
      }
    }
  }

  // Segment hover
  if(newSeg!==hovSeg){
    if(hovSeg) hovSeg.material.color.setHex(COL_NORMAL);
    hovSeg=newSeg;
    if(hovSeg) hovSeg.material.color.setHex(COL_HOVER);
  }

  // Cell hover
  if(newCell!==hovCell){
    if(hovCell) hovCell.material.color.setHex(CELL_COLORS[hovCell.userData.colorState]);
    hovCell=newCell;
    if(hovCell) hovCell.material.color.setHex(brighten(CELL_COLORS[hovCell.userData.colorState],0.10));
  }

  // Tooltip: position near cursor and show measurement
  if(hovSeg){
    var _nA=nodePos[hovSeg.userData.nodeA.ci][hovSeg.userData.nodeA.ri];
    var _nB=nodePos[hovSeg.userData.nodeB.ci][hovSeg.userData.nodeB.ri];
    var _len=Math.sqrt(Math.pow(_nB.x-_nA.x,2)+Math.pow(_nB.z-_nA.z,2));
    var _wEntry=segWalls[hovSeg.uuid];
    var _wState=_wEntry?_wEntry.state:0;
    var _wLabels=['클릭: 1m 벽 생성','클릭: 2m 벽으로','클릭: 4m 벽으로','클릭: 벽 제거'];
    hoverTag.innerHTML='&lt;span style=&quot;color:#aaddff&quot;&gt;길이&lt;/span&gt; '+_len.toFixed(2)+' m'
      +'&lt;span style=&quot;color:rgba(255,255,100,.45);font-weight:400;font-size:10.5px&quot;&gt; &amp;nbsp;│&amp;nbsp; '+_wLabels[_wState]+'&lt;/span&gt;';
    hoverTag.classList.add('on');
  } else if(hovCell){
    var _cc=hovCell.userData.col,_cr=hovCell.userData.row;
    var _area=quadArea(nodePos[_cc][_cr],nodePos[_cc+1][_cr],nodePos[_cc+1][_cr+1],nodePos[_cc][_cr+1]);
    hoverTag.innerHTML='&lt;span style=&quot;color:#aaddff&quot;&gt;면적&lt;/span&gt; '+_area.toFixed(2)+' m²'
      +'&lt;span style=&quot;color:rgba(255,255,100,.45);font-weight:400;font-size:10.5px&quot;&gt; &amp;nbsp;│&amp;nbsp; 클릭: 색상 변경&lt;/span&gt;';
    hoverTag.classList.add('on');
  } else {
    hoverTag.classList.remove('on');
  }

  // Move tooltip 16px right and 8px below cursor, keep inside viewport
  if(hovSeg||hovCell){
    var _tx=mouseXY.x+16, _ty=mouseXY.y+8;
    var _tw=hoverTag.offsetWidth, _th=hoverTag.offsetHeight;
    if(_tx+_tw&gt;_cw-8)  _tx=mouseXY.x-_tw-8;
    if(_ty+_th&gt;_ch-8) _ty=mouseXY.y-_th-8;
    hoverTag.style.left=_tx+'px'; hoverTag.style.top=_ty+'px';
  }

  renderer.domElement.style.cursor = dragCorner ? 'grabbing' : (hovCorner ? 'grab' : (hovCell||hovSeg) ? 'pointer' : 'default');
  renderer.render(scene, camera);
}
animate();

// ─── RESIZE ──────────────────────────────────────────────────────────────────
window.addEventListener('resize',function(){
  var _c=document.getElementById('booth-container');
  var _nw=_c.getBoundingClientRect().width||_c.offsetWidth, _nh=800;
  camera.aspect=_nw/_nh;
  camera.updateProjectionMatrix();
  renderer.setSize(_nw,_nh);
});

})();

&lt;/script&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9m x 12m 의 박람회&amp;nbsp; 부스 공간. 서른 평이 약간 넘는 공간을 세 자회사가 어떻게 나눌 수 있을까를 각 회사에서 입장에서 구상해 볼 수 있도록 툴을 제공하기로 했어. 클로드와 대화하면서 &lt;b&gt;&quot;말로만&quot;&lt;/b&gt; 원하는 걸 이야기 했더니 금방 파일을 만들어주네. 첫 안은 매우 단순했고, 지금은 여섯 번 정도 revise 한 결과물이야.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 9x12x4미터의 공간을 n개로 나누고, 그 사이에 벽을 세울 수 있음&lt;br /&gt;&amp;bull; 각 셀을 롤오버하면 색이 밝아지는데, 클릭하면 녹색-보라색-파란색-회색으로 순환하게 함 &lt;br /&gt;&amp;nbsp; (각각 자회사를 상징하는 색상이며 회색은 공용공간&amp;nbsp;&lt;br /&gt;&amp;bull; 벽은 노란색으로 하되, 노란색 선분을 클릭하면 1m-2m-4m-없어짐으로 순환하게 함.&lt;br /&gt;&amp;bull; 각 모서리와 꼭지점에 원형 핸들을 두고, 영역 내에서 드래그하게 하되, 움직임에 따라 핸들에 붙어있는 선이 변형됨&lt;br /&gt;&amp;bull; 선이나 셀에 롤오버하면 길이 또는 너비값을 알 수 있음&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;&amp;bull; (MIL, KYS, LIB등은 주변 부스의 약칭임. 보안상 AI에게 구체적 사명은 넣지 않음)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;824&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PDECo/dJMcab4IL0l/uzdbCwooeZ2cml739Uw0E1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PDECo/dJMcab4IL0l/uzdbCwooeZ2cml739Uw0E1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PDECo/dJMcab4IL0l/uzdbCwooeZ2cml739Uw0E1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPDECo%2FdJMcab4IL0l%2FuzdbCwooeZ2cml739Uw0E1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;824&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;824&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로는 약간 더 복잡한 대화를 했지만, 거의 저 정도의 지시문 만으로 만든 html을 공유하는 건 즐거운 경험이었어.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 개발자에게 요청하면 얼마나 걸릴까?&lt;br /&gt;개성이 없는 좌표 조정 탬플릿은 약간의 서칭으로도 찾을 수 있겠지만, &lt;b&gt;그 서칭하는 노력의 절반 정도만 시간을 써서&lt;/b&gt; 내게 딱 맞춘 툴을 만드는 건 참 대단한 것 같아.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ps.&lt;br /&gt;이미지 만드는 건 이미 나는 뒤떨어져 가고 있는 것 같고 코딩 역시 늦깎이 진입인데... 재밌어^^&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/Of737/dJMcafTBOep/rkf51b2kuj7aQBGCgKDPE0/booth.html?attach=1&amp;amp;knm=tfile.html&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;booth.html&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.69MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IMG/COD</category>
      <author>ARTBRAIN</author>
      <guid isPermaLink="true">https://pnpt.tistory.com/204</guid>
      <comments>https://pnpt.tistory.com/204#entry204comment</comments>
      <pubDate>Mon, 30 Mar 2026 17:55:49 +0900</pubDate>
    </item>
    <item>
      <title>Work Louder의 Framer Micro v2 - 내돈내산</title>
      <link>https://pnpt.tistory.com/202</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3446&quot; data-origin-height=&quot;2902&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8MXtz/dJMcaiIGnMb/dnuzwqjIeWfyOqswuMLmNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8MXtz/dJMcaiIGnMb/dnuzwqjIeWfyOqswuMLmNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8MXtz/dJMcaiIGnMb/dnuzwqjIeWfyOqswuMLmNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8MXtz%2FdJMcaiIGnMb%2FdnuzwqjIeWfyOqswuMLmNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3446&quot; height=&quot;2902&quot; data-origin-width=&quot;3446&quot; data-origin-height=&quot;2902&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;꽤 오래 기다려 받았어. 1년은 된 것 같아.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작년에 피그마 에디션을 놓친 아쉬움이 있었어서, 올해 초에 나온 &lt;a href=&quot;https://worklouder.cc/framer-creator-micro&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;프레이머 에디션&lt;/b&gt;&lt;/a&gt;은 큰 고민하지 않고 질렀지. 배송비까지 포함해서 20만 원 초반대. 만듦새 이쁘고, GUI도 이쁘고, 좋아 보여서 오랫동안 눈팅중이었거든. &lt;a href=&quot;https://worklouder.cc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;Work Louder&lt;/b&gt;&lt;/a&gt;라는 회사에 대한 그동안의 관심도 있었기 때문에 처음 받았을 때는 정말 기분이 좋았어. 유선 모델은 30불 정도 더 싼데, 기계식 키보드를 쓴 이후로 가장 아쉬웠던 게 유선의 불편함이었기 때문에, 이번에는 약간 돈이 더 들더라도 블루투스 모델을 샀지.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완제품 키보드와 40개 정도의 아이콘이 그려진 키캡을 따로 줘. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(본체에는 민무늬 키캡이 기본으로 꽂혀있음)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2756&quot; data-origin-height=&quot;1810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FUQWV/dJMcac2LRBo/ABxk8zi9auty8mkFVpYHp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FUQWV/dJMcac2LRBo/ABxk8zi9auty8mkFVpYHp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FUQWV/dJMcac2LRBo/ABxk8zi9auty8mkFVpYHp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFUQWV%2FdJMcac2LRBo%2FABxk8zi9auty8mkFVpYHp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2756&quot; height=&quot;1810&quot; data-origin-width=&quot;2756&quot; data-origin-height=&quot;1810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Input 이라는 자체 앱을 통해서 세팅을 하는데, 처음엔 유선으로 연결해서 동기화하고, 그 뒤로는 무선으로도 매핑 업데이트를 할 수 있어. VIA나 QMK 만큼은 아니지만 자율도는 꽤 좋은 편이고, &lt;b&gt;사용 중인 프로그램(앱)을 자동 인식해서 다른 매핑으로 바꿔주는 AppSense&lt;/b&gt;도 편리한 것 같아. VIA나 QMK에서는 LED 조정 기능이나 마우스 기능을 쓸 수 있도록 하는 옵션이 있는데, Input 앱에는 아직 그런 게 없어서 조금 아쉽지만, 조만간에 업데이트 할 것 같아.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어제 받아서 많이 써보지는 않았지만, 평소에 관심이 있었던, 다이얼 노브&lt;span style=&quot;color: #7e98b1;&quot;&gt;(왼쪽 위)&lt;/span&gt;와 조이스틱&lt;span style=&quot;color: #7e98b1;&quot;&gt;(오른쪽 위)&lt;/span&gt;을 쓰는 건 참 재밌어. 직관적이기도 하고. &lt;b&gt;'그동안 이걸 왜 키를 눌러 써 왔을까'&lt;/b&gt; 싶을 정도였지, 특히 볼륨 조절이나 undo/redo를 다이얼로 하는 건 '이게 맞는 방법'이라는 확신이 들어. 왼쪽 아래의 프레이머 로고는 눌림 없는 터치 버튼인데, 굳이 그래야 했을까는 싶지만... 뭐 참신하긴 해.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만듦새 깔끔하고 앱 직관적이고, 잘만 쓰면 작업 능률이 너무 좋을 것 같아. UIUX 하는 사람으로서 이정도로 완결적인 프로덕트를 구현하기는 쉽지 않거든. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(쓰기 불편한 건 하드웨어의 능력 부족이고, 한계가 있는 기기의 범위 내에서는 최선을 다했다고 봐.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자.&lt;br /&gt;이 정도 칭찬했으면 됐겠지.&lt;br /&gt;이제 본론.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;웬만한 고인물 아니면 사지 말길. ^^&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째로, 아직 불안정성이 엄청나. &lt;br /&gt;펌웨어가 0.2.2인데 여전히 끊기고 먹통이 되기도 해. 제품을 받고 30분 정도 탐색하고 나서 &lt;b&gt;아 이제 알겠네, 이제 제대로 세팅을 해볼까!&lt;/b&gt; 라던 순간, 갑자기 기기를 인식 못하는 앱, 작동 안 되는 키보드.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;Update. 2026. 01. 04 - 펌웨어 0.2.3, 인풋버전 0.12.6 이 되면서 안정성은 눈에 띄게 좋아짐. &lt;br /&gt;하지만 위에서 말한 기능 개선까지는 아직임. 이전보다 배터리 드레인은 많이 좋아졌으나, 일반적인 블루투스 기기에 비해서는 아직 모자람. 간신히 이틀 정도 씀.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 시간 정도 씨름하다가 다이소에서 렌치 사다가 해체하고 수동 리셋을 했음. 제품을 받은 지 반나절도 안 돼서 말이지. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(다행히 해체는 극히 단순하고 리셋도 어렵지 않았지만, 다른 키보드는 그냥 작은 구멍을 펜으로 꾹 눌러 리셋하는 것에 비하면 엄청 번잡한 일이야.)&lt;/span&gt; 이후로 두세 번의 리셋과 벽돌이 반복. 지금은 불안한 상태로 정상작동 중. ㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사지 마. &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;아니, 만듦새는 좋으니까 다른 &quot;유선&quot; 키보드를 골라봐.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;Work Louder의 다른 제품은 모르겠는데, 이건 베타버전을 돈 받고 사는 상황이야.&lt;br /&gt;버전 0.5쯤 되면 괜찮아질지도? ^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>LOG/SHP</category>
      <category>WorkLouder</category>
      <category>내돈내산</category>
      <category>사지마</category>
      <category>예쁘긴해</category>
      <author>ARTBRAIN</author>
      <guid isPermaLink="true">https://pnpt.tistory.com/202</guid>
      <comments>https://pnpt.tistory.com/202#entry202comment</comments>
      <pubDate>Sun, 28 Dec 2025 16:40:44 +0900</pubDate>
    </item>
    <item>
      <title>CMF 헤드폰 프로 : 사도 돼</title>
      <link>https://pnpt.tistory.com/201</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;CMF는 Nothing의 서브 브랜드야. Nothing 자체가 충분히 작은 회사인데 무슨 서브 브랜드인가 싶긴 한데, CMF라는 이름답게 만듦새는 괜찮은 것 같아. 이미 Nothing의 제품을 두 개&lt;span style=&quot;color: #009a87;&quot;&gt; (&lt;a style=&quot;color: #009a87;&quot; href=&quot;https://www.panopt.net/177&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;폰 하나&lt;/a&gt;, &lt;a style=&quot;color: #009a87;&quot; href=&quot;https://pnpt.tistory.com/196&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이어폰 하나&lt;/a&gt;)&lt;/span&gt; 쓰고 있는 중인데, 이 브랜드의 언더독 성향이 - 오늘 소개하는 이 헤드폰에도 그대로 적용된 것 같아.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;가격 대비 훌륭함&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;522&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sAmd0/dJMcacuBQBm/xAjelNrTZJ2MopRfVU9uk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sAmd0/dJMcacuBQBm/xAjelNrTZJ2MopRfVU9uk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sAmd0/dJMcacuBQBm/xAjelNrTZJ2MopRfVU9uk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsAmd0%2FdJMcacuBQBm%2FxAjelNrTZJ2MopRfVU9uk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;522&quot; height=&quot;313&quot; data-origin-width=&quot;522&quot; data-origin-height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크게 봐도 굴욕 없는 외모, 만듦새는 가격대비 최고야. 다크 그레이만 캡 부분이 무광이라는데, 밝은 색상은 유광이래. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(그것도 예쁘더라)&lt;/span&gt; 사진보다 실제로 보면 더 어두운 색이지만, 조금만 더 진했으면 어땠을까 싶어. 검은색 머리카락 위에 얹어지면 밝게 보이는, 실제로는 #444444 정도의 느낌이야.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;대두 샷. 설계 실수?&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rlml7/dJMcaj1zvzi/zEt5cTnsQjo7QJmkIwjkb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rlml7/dJMcaj1zvzi/zEt5cTnsQjo7QJmkIwjkb0/img.png&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;708&quot; data-is-animation=&quot;false&quot; style=&quot;width: 45.5358%; margin-right: 10px;&quot; data-widthpercent=&quot;46.07&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rlml7/dJMcaj1zvzi/zEt5cTnsQjo7QJmkIwjkb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frlml7%2FdJMcaj1zvzi%2FzEt5cTnsQjo7QJmkIwjkb0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;664&quot; height=&quot;708&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bccf1Y/dJMcaj1zvzg/9UDcXWHD3PA0jft7aq8XzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bccf1Y/dJMcaj1zvzg/9UDcXWHD3PA0jft7aq8XzK/img.png&quot; data-origin-width=&quot;2290&quot; data-origin-height=&quot;2086&quot; data-is-animation=&quot;false&quot; style=&quot;width: 53.3014%;&quot; data-widthpercent=&quot;53.93&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bccf1Y/dJMcaj1zvzg/9UDcXWHD3PA0jft7aq8XzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbccf1Y%2FdJMcaj1zvzg%2F9UDcXWHD3PA0jft7aq8XzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2290&quot; height=&quot;2086&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게... 설계가 좀 잘못됐어. &lt;b&gt;이어컵 부분이 너무 두꺼워.&lt;/b&gt; 때문에 암이 너무 이상하게 벌어져. 가격을 낮추는 대신 공간을 두껍게 만든 셈인데, 이것 때문에 암은 &lt;span style=&quot;color: #7e98b1;&quot;&gt;(반원으로 예쁘게 떨어지지 않고)&lt;/span&gt; 거의 'ㄷ'자로 벌어지게 돼. 당신의 머리가 저 콜라보다 크다면&lt;b&gt; 무조건 대두처럼 보일 거야.&lt;/b&gt; 저 모델들이 쓴 헤드폰은 그나마 부드러운 곡선을 그리는데, 실제로는 맨 아래 오른쪽 여성의 룩이 나와. 그런데 'ㄷ'자 형태로 벌어지는 구조 덕분인지 착용감은 웬만한 헤드폰들보다 좋아. 좌우 이어컵이 무겁지도 않거니와 무게 분산이 좋아서 &lt;b&gt;오래 쓰고 있어도 부담이 적어. &lt;/b&gt;즉, 이 헤드폰은 패션 소품으로 쓸 때는 목에 걸어두는 걸 추천^^&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2786&quot; data-origin-height=&quot;1514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N5Pmk/dJMcaesqr4A/0IkxS6rbwm9AQ3rqnjBHk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N5Pmk/dJMcaesqr4A/0IkxS6rbwm9AQ3rqnjBHk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N5Pmk/dJMcaesqr4A/0IkxS6rbwm9AQ3rqnjBHk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN5Pmk%2FdJMcaesqr4A%2F0IkxS6rbwm9AQ3rqnjBHk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2786&quot; height=&quot;1514&quot; data-origin-width=&quot;2786&quot; data-origin-height=&quot;1514&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오른쪽 이미지는 이전에 나온 플래그십 헤드폰인 Nothing headphone 1인데, 실물이 참 별로였던 기억. 과장된 디자인에는 그만큼 소재나 디테일도 살아줘야 하는데 실제로는 플라스틱 덩어리에 투광성도 좋지 않아서, 실물을 본 뒤 살 마음을 접었더랬지. 그런데 이번 것은 디자인과 퀄리티가 유사하게 align 되어서, 헤드폰 1보다는 훨씬 나은 디자인이라고 생각해.&lt;span style=&quot;color: #7e98b1;&quot;&gt; (지금 보니 왼쪽 이미지도 포샵이 많이 들어갔네, 위의 콜라 사진이 내가 찍은 것이니 암의 두께나 곡률을 보려면 그 사진을 참고해) &lt;/span&gt;오른쪽 헤드폰은 컵의 두께를 줄이려고 노력한 흔적이 역력하지만, CMF에는 그런 것 없음. 엄청난 두께 차이. 이렇게 비교하고 보니, 정말 암의 엔지니어링 디테일은 차이가 크네.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;다양한 기능인데, 쓸 건 딱히&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1468&quot; data-origin-height=&quot;944&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpeadw/dJMcaaKkow8/mg7bkY2iMQ0SfPICiKqSK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpeadw/dJMcaaKkow8/mg7bkY2iMQ0SfPICiKqSK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpeadw/dJMcaaKkow8/mg7bkY2iMQ0SfPICiKqSK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbpeadw%2FdJMcaaKkow8%2Fmg7bkY2iMQ0SfPICiKqSK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1468&quot; height=&quot;944&quot; data-origin-width=&quot;1468&quot; data-origin-height=&quot;944&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nothing 브랜드의 특징답게 독창성이고 위트 있는 구성이야. 에너지 슬라이더는 설정에 따라 베이스나 트레블을 아날로그로 조절할 수 있게 만든 건데, 그다지 성능이 좋지는 않아. 인위적인 베이스 강화. 차라리 트레블 조절로 설정을 바꿔 쓰면 나은 것 같아. 왼쪽에는 에너지 슬라이더와 전원, 이어폰잭이 있고, 오른쪽에는 볼륨, 액션버튼(핫 키), USB 포트가 있는데 - 조작 밀도를 나누어야 하므로 양쪽으로 나눠 둔 것은 그럴 수 있다 쳐도, 배분이 이게 맞나 싶어. &lt;b&gt;두 손을 고르게 사용하는 게 맞는 걸까?&lt;/b&gt; 사용 빈도가 높은 걸 한쪽에 모아두어야 하는 것 아닐까?&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;가장 큰 장점은 배터리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 일주일 정도밖에 써보지 않았으니, 나중에 배터리 성능이 얼마나 낮아질지는 모르겠지만, 지금까지는 너무 만족하는 부분이 바로 재생시간이야. 배터리의 총량도 중요하지만, 소모속도도 중요한 법인데, 이 헤드폰은 &lt;b&gt;배터리가 매우 천천히 줄어들어.&lt;/b&gt; 웬만한 사람들은 매일 쓰더라도 2~3일에 한 번만 충전해도 될 것 같아. 하루에 한두 시간씩 들으면 일주일은 넘기지 싶어. 완충은 느리지만, 몇 분 충전하면 한 시간 분량은 충전되는 것도 큰 장점인 것 같아.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;듀얼 커넥션&lt;/b&gt;(multi point)&lt;b&gt;의 편리함&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플 제품을 제외하고는 멀티포인트 연결이 부드러운 기기는 흔치 않아. 핸드폰에서 아이패드, 혹은 맥북으로 자연스럽게&amp;nbsp;연결을 전환해 주는 기기는 많지 않고, 있다고 하더라도 개운하지 않은데, 낫싱 제품은 그게 꽤 괜찮아. 물론 애플보단 떨어지지만 거의 즉각적으로 소리 내는 기기를 잡아줘.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;그래도, 헤드폰의 본질은 음질이지.&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;낫싱 Ear(a)를 소개할 때도 한 말이긴 한데, 이 제품도 음질 자체는 매우 좋아. 하지만 매우 허약? 한 게 단점이야. 매우 조용한 환경에서 중간 볼륨으로 음악을 들으면, 이 헤드폰은 매우 훌륭한 음향을 들려줘. &lt;b&gt;밸런스도 좋고, 모나지 않은 고른 퍼포먼스를 내.&lt;/b&gt; 심지어 애플처럼 정 없는 무미건조한 소리도 아니고 적절히 안아주는 안정감 있는 소리를 내. 잔음이 좀 날아가는 느낌이 없지는 않으나 그렇다고 뭉뚱거리는 소리는 아니야. 어디에 무슨 소리가 얼마만큼 나는지는 명확하게 들려.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 체력이 문제.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평범한 40mm 드라이버라서 전체적인 파워는 낮은 편이야. 마샬로 듣다가 이걸로 들으면 무스탕 몰다가 현대차 모는 느낌이랄까. 음악의 절반은 실재성인데, 실제 음원의 수준까지 음량이 못미치니 아쉽긴 해. 심지어 아이폰과 연결하면 최대 음량이 안드로이드보다 80% 정도로 낮게 나오는 것 같아. 낫싱 폰에 연결할 때의 최대 볼륨은 그나마 괜찮은데, 아이폰과 연결했을 때는 50% 정도 볼륨을 더 올리고 싶은 마음이 생겨. 그래도 찌그러뜨리는 소리로 억지로 음량을 키우지는 않는 건 참 좋은 선택인 것 같아. 자기 체력에 맞는 퍼포먼스를 보이는 건 좋은 거라고 봐.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ANC&lt;/b&gt;와 &lt;b&gt;공간음향&lt;/b&gt;은 낫배드한 수준. '어 된다' 수준인데, 아쉽지는 않아. 음악을 들을 때 잡소리를 막아주는 정도는 충분히 하는 수준이라서 불만은 없어. 하지만 공간음향은... 요즘 다른 기기들이 워낙 잘하니까. 이건 딱 흉내 내는 수준이야.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;낫싱 헤드폰이 그럼에도 좋은 것은 &lt;b&gt;LDAC&lt;/b&gt; 지원. 게다가 아이튠즈의 lossless 음원도 꽤 잘 지원해 주는 것 같아. &lt;b&gt;체력만 좋으면 크게 될 놈인데 워낙 기초체력이 약해놔서.&lt;/b&gt; 하하 ^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음악은 두루두루 잘 받쳐주는 느낌인데, 궁합이 좋은 장르는 딱히 없는 거 같아. 굳이 말하자면 피아노 건반음이나 타악기의 잔향을 잘 잡아주는 느낌이라서 &lt;b&gt;실내악 클래식&lt;/b&gt;이 꽤 맞는 것 같은데, 또 에스파 같은 K-Pop의 &lt;b&gt;가공된 소리&lt;/b&gt;도 제법 잘 살려주기도 해. 반대로 라이브 음원이나 오케스트라와는 조금 결이 안 맞는 느낌. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(지금 히사이시 죠의 음악을 듣고 있는데, 이건 아닌 것 같아^^ 차라리 에스파의 Whiplash를 추천)&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;결론 : 사라 사&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점을 잔뜩 적어두고서 사라고 하는 게 이상할 수는 있는데, 이건 12만 9천 원이라는 가격에 기반한 주장이야. 만일 네가 50만 원 정도의 여윳돈이 있다면 다른 걸 권하겠지. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(20만원 더 보태서 소니ANC 되는 거 사라)&lt;/span&gt; 또는 네가 진심으로 음악 마니아라면 애초에 이런 헤드폰을 기웃거리지도 않겠지. ㅎㅎ. &lt;b&gt;겨울에 귀 따숩게 다니고 음악도 나오는 예쁜 귀마개 하나 어디 없을까 하며&lt;/b&gt; 찾다가 여길 방문한 사람이라면, 이 헤드폰은 정말 나무랄 데가 하나도 없어.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;착용샷이 조금 찐따같이 보일 수는 있어도, 네 외모가 출중하면 '그깟 헤드폰 따위'일 테고, 헤드폰 자체로만 보면 또 나름 예쁘긴 하거든, 싸 보이지도 않고 말이지. 그냥 평범하게 자신의 폰 브랜드에 맞춰서 에어팟이나 갤럭시 버즈 쓰던 사람에게도 괜찮은 선택일 것 같아. 최소한 이 헤드폰의 &lt;b&gt;음질이 떨어져서 못 듣겠네 하는 경우는 없을걸?&lt;/b&gt; &lt;span style=&quot;color: #7e98b1;&quot;&gt;(노이즈 캔슬링이나 공간음향의 아쉬움은 있겠지만)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가격, 만듦새, 배터리, 음질 등 장점이 단점을 상쇄할 정도라고 보고, 마지막 팁을 주자면... &lt;br /&gt;&lt;b&gt;머리 큰 사람은 밝은 걸로 사라! ^^&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>LOG/SHP</category>
      <author>ARTBRAIN</author>
      <guid isPermaLink="true">https://pnpt.tistory.com/201</guid>
      <comments>https://pnpt.tistory.com/201#entry201comment</comments>
      <pubDate>Tue, 28 Oct 2025 14:17:25 +0900</pubDate>
    </item>
    <item>
      <title>AI 이미지 생성용 '효과' 단어들 모음</title>
      <link>https://pnpt.tistory.com/200</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;AI 잘들 쓰고 있어? ^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지만 만들기에는 너무 아까운 기술이지만, 그래도 제일 재밌는 게 이미지 만들기잖아. 그래서 나도 여러가지를 심심할때마다 만들고 있는데, 기술이 너무 빨리 발전해서 이제는 전문적인 지식이 없어도 쉽게 원하는 걸 만들 수 있는 것 같아.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 약간의 기술적인 용어를 프롬프트에 섞어주면 대화가 잘 통하더라구. 그래서 3D 분야나 사진 분야에서 쓰는 용어를 좀 모아봤어. 디테일을 살리는 데 쉽고 직관적으로 사용하기 좋아.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkunYm/dJMb9LKLi0r/ceY541eMTMZZscLSycpku0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkunYm/dJMb9LKLi0r/ceY541eMTMZZscLSycpku0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkunYm/dJMb9LKLi0r/ceY541eMTMZZscLSycpku0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkunYm%2FdJMb9LKLi0r%2FceY541eMTMZZscLSycpku0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;924&quot; height=&quot;374&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제일 많이 쓰는 것 중에 하나가 &lt;b&gt;specular highlight&lt;/b&gt;. 소위 물광 피부를 만드는 느낌인데, 콘트라스트가 강한 '빛의 점'을 만들어 주기 때문에 디테일이 높아 보이는 장점이 있어. 두번째는 3D에서 SSS라고 부르는, &lt;b&gt;subsurface scattering&lt;/b&gt;. 피부 속에서 빛이 반사되는 느낌인데, 볼이나 귀 끝을 잘 봐봐. 인물의 경우 이게 적용되면 약간 클래식한 느낌으로 이미지 톤이 잡히는 것 같아. &lt;b&gt;rim light&lt;/b&gt;는 역광과는 다르게, 테두리에 떨어지는 광선이라서 'back light'라고 말하는 것보다 인물의 외모를 잘 살릴 수 있어.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/divSWZ/dJMb9i2Og33/XmaWpVv6YivV09YM1FwSyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/divSWZ/dJMb9i2Og33/XmaWpVv6YivV09YM1FwSyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/divSWZ/dJMb9i2Og33/XmaWpVv6YivV09YM1FwSyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdivSWZ%2FdJMb9i2Og33%2FXmaWpVv6YivV09YM1FwSyK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;924&quot; height=&quot;374&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;fresnel effect&lt;/b&gt;는 설명하기 조금 어려운데... 카메라에 대해서 비스듬하게 배치된 오브젝트의 반사가 강해지는 현상이야. 이 이미지에서는 눈동자 테두리와 머리카락 가장자리, 볼과 턱의 경계 부분에서 미묘하게 볼 수 있어. &lt;b&gt;ambient occlusion&lt;/b&gt;은 SSAO라고도 불리는데, 틈이나 음영의 디테일을 잡는데 좋아. 이미지를 크게 쓰면 좋겠지만... 콧망울 아래, 입술 아래의 그림자들을 관찰해봐. &lt;b&gt;depth of field&lt;/b&gt;는 말 그대로 망원렌즈 촬영에서 배경을 날리는 효과야.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMOqKy/dJMb9V0PDO6/E5Ca4psNr2nluCKtMK6rV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMOqKy/dJMb9V0PDO6/E5Ca4psNr2nluCKtMK6rV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMOqKy/dJMb9V0PDO6/E5Ca4psNr2nluCKtMK6rV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMOqKy%2FdJMb9V0PDO6%2FE5Ca4psNr2nluCKtMK6rV1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;924&quot; height=&quot;374&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;bloom&lt;/b&gt;은 빛 확산이야. 하이라이트 광선이 대상에만 맺히지 않고 주변의 공기에도 묻어 번지는 효과야. &lt;b&gt;vignette&lt;/b&gt;는 많이들 알겠지만, 비네팅, 화면 주위를눌러서 가운데가 돋보이게 하는 효과이고, &lt;b&gt;volume light&lt;/b&gt;, 흔히 god rays는, 먼지가 많은 곳에서 빛줄기가 나타나는 것을 말해.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2pB1n/dJMb9fLMCmj/4rH3jjCLMqgBplK8aPpOv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2pB1n/dJMb9fLMCmj/4rH3jjCLMqgBplK8aPpOv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2pB1n/dJMb9fLMCmj/4rH3jjCLMqgBplK8aPpOv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2pB1n%2FdJMb9fLMCmj%2F4rH3jjCLMqgBplK8aPpOv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;924&quot; height=&quot;374&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;anisotropy&lt;/b&gt;는, 방향성을 갖는 빛의 흐름이야. 원래는 예시를 금속이나 물체로 해야 했겠지만, 모두 '붉은 머리의 여자'로 예시를 통일하는 바람에. ㅋ. 광택의 질감을 주거나, 광택에서 색상이 살짝 변하게 해주는 데 쓰면 좋아. &lt;b&gt;chromatic aberration&lt;/b&gt;은 소위 색수차로 말하는, 색상이 빨녹파로 분리되는 현상으로 물체의 테두리에서 발생해. 주황색 머리카락 주변에서 녹색이 보이는 것이나, 앞쪽 어깨에 서툴게 적용되어 있어. &lt;b&gt;sheen&lt;/b&gt;은 특정 오브젝트를 지칭하며 사용하면 좋은데, 직물이나 장식물들의 디테일을 올리는데 좋아. 그 부분의 빛을 평평하게 펴주면서도 디테일을 살려주거든.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7e71r/dJMb9QrLFTa/oPT7dRQEzFq6kMln3XHskK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7e71r/dJMb9QrLFTa/oPT7dRQEzFq6kMln3XHskK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7e71r/dJMb9QrLFTa/oPT7dRQEzFq6kMln3XHskK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7e71r%2FdJMb9QrLFTa%2FoPT7dRQEzFq6kMln3XHskK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;924&quot; height=&quot;374&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;caustics&lt;/b&gt;는 광집효과라고 해서, 물에서 반사되는 빛들이 만드는 무늬, 또는 빛이 투명 재질을 통과할 때 만들어지는 패턴 등을 말해. 이미지에서는 두 팔에 나타나 있어.&lt;b&gt; diffuse reflection&lt;/b&gt;은 확산되는 반사, 다양한 빛이 화면을 두루 튕겨다니면서 고르게 풍부하게 만드는 효과야. &lt;b&gt;backlight&lt;/b&gt;는 역광. 말 안해도 알지. 백라이트는 위에서 설명한 rim light나 fresnel effect와 구별해서 쓰면 좋아.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqVcov/dJMb9P0Hsvh/zTfmrw3mKRRcoqfbpIPO9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqVcov/dJMb9P0Hsvh/zTfmrw3mKRRcoqfbpIPO9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqVcov/dJMb9P0Hsvh/zTfmrw3mKRRcoqfbpIPO9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqVcov%2FdJMb9P0Hsvh%2FzTfmrw3mKRRcoqfbpIPO9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;924&quot; height=&quot;374&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ambient light&lt;/b&gt;는 광선 방향이 불분명한 확산광이야. 그래서 화면 전체를 부드럽게 만들어. 여기에 색상을 섞어주는 표현을 쓰면 또 그것 나름 독특한 느낌을 만들 수 있어. &lt;b&gt;bump mapping&lt;/b&gt;은 정말 3D 용어이긴 한데, 3D 매핑을 하지 않고, 단순한 큐브에 이미지로 패턴을 주는 트릭같은 방식이야. 실제로 AI가 이 프롬프트를 어떻게 해석하는지는 모르지만, 복잡한 것이 반복될 때 쓰면 그 쪽을 '덜 중요하게' 판단하는 것 같아. 이 이미지의 경우에는 벽돌 벽에 그 프롬프트를 적용했어. 마지막으로 &lt;b&gt;global illumination&lt;/b&gt;은, 전체적으로 균형있게 광선을 조절하는 효과가 있는 것 같아. 전역조명이라고 번역하는데, 이론적으로는 다양한 반사광이나 간접조명의 효과를 극대화하는 데 사용돼.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 한국말도 제법 잘 알아듣는 AI이지만, 여전히 영어가 잘 먹히는 상황이라서 이런 프롬프트 하나씩만 넣어줘도 목적하는 표현을 잘 구현할 수 있어. 시간 나면 더 추가할게. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(썸네일 이미지는 여러가지 효과를 다 때려박아서 무서워진 이미지^^)&lt;/span&gt;&lt;/p&gt;</description>
      <category>IMG</category>
      <category>ai</category>
      <category>GPT</category>
      <category>midjourney</category>
      <author>ARTBRAIN</author>
      <guid isPermaLink="true">https://pnpt.tistory.com/200</guid>
      <comments>https://pnpt.tistory.com/200#entry200comment</comments>
      <pubDate>Thu, 23 Oct 2025 10:56:45 +0900</pubDate>
    </item>
    <item>
      <title>AI가 너희를 자유롭게 해줄 것 같은가? (*이미지)</title>
      <link>https://pnpt.tistory.com/199</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ke3fp/btsP24S7hNB/b7Gn72Mi6gOk6hXRuQqUHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ke3fp/btsP24S7hNB/b7Gn72Mi6gOk6hXRuQqUHk/img.png&quot; width=&quot;320&quot; height=&quot;480&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;1442&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.7393%; margin-right: 10px;&quot; data-widthpercent=&quot;33.52&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ke3fp/btsP24S7hNB/b7Gn72Mi6gOk6hXRuQqUHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKe3fp%2FbtsP24S7hNB%2Fb7Gn72Mi6gOk6hXRuQqUHk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;962&quot; height=&quot;1442&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N98pS/btsP4zEMd60/PXu5t0SKf5mrlobQBw1x70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N98pS/btsP4zEMd60/PXu5t0SKf5mrlobQBw1x70/img.png&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;1440&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.8529%; margin-right: 10px;&quot; data-widthpercent=&quot;33.64&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N98pS/btsP4zEMd60/PXu5t0SKf5mrlobQBw1x70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN98pS%2FbtsP4zEMd60%2FPXu5t0SKf5mrlobQBw1x70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;964&quot; height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9PkAv/btsP4ZwrbZL/xlapIOxKJLSPSaB4RH4TQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9PkAv/btsP4ZwrbZL/xlapIOxKJLSPSaB4RH4TQk/img.png&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;1444&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.0822%;&quot; data-widthpercent=&quot;32.84&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9PkAv/btsP4ZwrbZL/xlapIOxKJLSPSaB4RH4TQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9PkAv%2FbtsP4ZwrbZL%2FxlapIOxKJLSPSaB4RH4TQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;944&quot; height=&quot;1444&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI를 두 방향에서 공부하고 있어. &lt;br /&gt;하나는 시각적인 구현이고, 다른 하나는 논리적인 협업자 생성이야.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, 전자가 난 더 재밌지.&amp;nbsp;&lt;br /&gt;평생 해 온 게 &lt;b&gt;'예쁜 것, 좋은 것, 이치에 맞는 것을 시각적으로 구현해 내는 일'&lt;/b&gt;이었으니, 요즘 AI들로 만들어 내는 그림이나 영상을 보면 참 만시지탄이자 감개무량이야. &lt;b&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;그림을 배우지 않고도 자신이 원하는 이미지를 만들어 낼 수 있다는 아이디어&lt;/span&gt;&lt;/b&gt;는 참 매혹적이야.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데... 그래, 아이디어. &lt;br /&gt;사실이 아니거나 일부에게만 사실인 구상일 뿐이야.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오래된 아티스트이자 디자이너 입장에서 보면, 말꼬리를 잡지 않을 수 없어. &lt;span style=&quot;color: #ef6f53;&quot;&gt;&lt;b&gt;&quot;그림을 배우지 않고도 원하는 이미지를 만들어 낸다&quot;&lt;/b&gt;&lt;/span&gt;는 이 환상적인 문장은 일견 멋져 보이지만, 사실은 처음부터 끝까지 맞는 부분이 없거든. ^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 그림을 배우지 않은 이에게 '환각'을 줄 수는 있어. 그 환각이 정말 실재와 물리적으로, 해부학적으로, 기능적으로 완전히 동일하다고 하더라도 &lt;b&gt;'네가 원하는 이미지를 구현'&lt;/b&gt;하는 게 아니야. 애초에 미술을 배우지 않은 일반인은 &lt;b&gt;'원하는 이미지'&lt;/b&gt;가 뭔지도 모르기 때문이지. 이는 훈련받은 시각 관련 전문인들도 쉽게 빠지는 환상이야. &lt;span style=&quot;color: #0593d3;&quot;&gt;(카탈로그를 보며 &lt;b&gt;'어머 이거 사야 해. 항상 갖고 싶었던 그것이야'&lt;/b&gt;라고 느끼는 순간을 생각해 보면 조금 이해가 쉬울지도?)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;픽사의 에드 캣멀은 '창의성을 지휘하라'라는 책에서 다음과 같은 말을 하기도 했어 : &lt;b&gt;예술가는 성급하게 결론을 내리려는 두뇌의 심성모형에 방해받지 않는 법을 배운 덕분에 다른 사람들보다 더 잘 본다. 예술가는 다른 사람들이 갖지 못한 몇 가지 관찰 기술을 도구함에 넣어놓고 필요할 때 꺼내 쓸 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로는 우리나라의 교육기관이나 예술 및 디자인 현장에서 너무나 &lt;b&gt;'하는 것'&lt;/b&gt;에만 집중하고 &lt;b&gt;'보는 것'&lt;/b&gt;에 대한 담론을 적게 가르치는 것에 불만이 있고, 실제로 학생이나 전문 디자이너들이나 이 '본다'는 것의 가치를 대충 생각하는 경향이 있다고 생각해. 그래서 '보는 방법을 모르더라도 자신이 잘 보고 있다고 생각하는' 필부에게 이 AI 이미지 생성이 주는 모호함은 참 위험하다고 느껴져.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알아. 이거 되게 특권의식이고, 일방적인 판단일 수 있어. 심지어 일반인들의 기준에서는 차별적인 언사일 수도 있어. 그런데, AI를 파고드는 여러분들에게 꼭 하고 싶은 말을 아주 짧게 하고 싶어서 조금 격하게 비약적으로 말하건대 ;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;&lt;b&gt;함정에 빠지지 않길 바라.&lt;/b&gt;&lt;/span&gt; &lt;br /&gt;&lt;b&gt;'대중들이 생각하는 대로 생각하는 걸 자신의 생각이라고 착각하게 되는 상황'&lt;/b&gt;만큼은, 당신이 피했으면 좋겠어.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, 이건 어제 오늘 일은 아니지.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDSUPN/btsP38nmEgK/MDxbflAbMNUU8s7lQvBKOk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDSUPN/btsP38nmEgK/MDxbflAbMNUU8s7lQvBKOk/img.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;480&quot; data-is-animation=&quot;false&quot; style=&quot;width: 43.1019%; margin-right: 10px;&quot; data-widthpercent=&quot;43.61&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDSUPN/btsP38nmEgK/MDxbflAbMNUU8s7lQvBKOk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDSUPN%2FbtsP38nmEgK%2FMDxbflAbMNUU8s7lQvBKOk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJuuFX/btsP6ezFgOT/BuEP5tbdVPQpBwvSVlxqQ0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJuuFX/btsP6ezFgOT/BuEP5tbdVPQpBwvSVlxqQ0/img.jpg&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;261&quot; data-is-animation=&quot;false&quot; style=&quot;width: 55.7353%;&quot; data-widthpercent=&quot;56.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJuuFX/btsP6ezFgOT/BuEP5tbdVPQpBwvSVlxqQ0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJuuFX%2FbtsP6ezFgOT%2FBuEP5tbdVPQpBwvSVlxqQ0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;261&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 AI 시대에는 &lt;b&gt;'남들도 입으니까'&lt;/b&gt; 수준의 인식이 아니라, &lt;b&gt;&quot;이건 내 아이디어이고, 내 취향이고, 내 선택이고, 내 미감이야&quot;&lt;/b&gt;라고 주장하는 리플리 증후군 환자들이 범람할 것 같아서 걱정돼.&lt;span style=&quot;color: #8cb3be;&quot;&gt; (뭐 요즘도 흔하게 보긴 하지.)&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐... 잔소리야. 나한테도 해당하는 내용이긴 하지만, 그래도 나는 좀 닳고 닳았으니^^ 내 인생에 큰 문제는 안 줄 것 같은데, &lt;b&gt;디자인을 10년도 안해 본 젊은이들&lt;/b&gt;은 앞으로의 커리어에 AI의 영향이 클 거잖아. 미래가 창창하잖아. 그러니까 걱정이 많이 되더라구. 실제로 그런 현상이 여기저기서 보이기도 해.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;물론!&lt;/b&gt; 그림을 한 번도 배우지 않은 사람이 AI를 통해서 온전히 자신의 뜻을 시각적으로 구현해낼 수도 있어. 하지만 그 확률은 매우 낮아. 초심자의 행운도 있을 테지만. 대개의 경우, 그 천재가 너는 아닐 거야. ^^&lt;/p&gt;</description>
      <category>LOG/OPN</category>
      <category>궁시렁</category>
      <category>사실은나도몰라</category>
      <category>푸념</category>
      <author>ARTBRAIN</author>
      <guid isPermaLink="true">https://pnpt.tistory.com/199</guid>
      <comments>https://pnpt.tistory.com/199#entry199comment</comments>
      <pubDate>Sun, 24 Aug 2025 23:14:36 +0900</pubDate>
    </item>
    <item>
      <title>더블 다이아몬드 모델 ( 오브 마이 라이프 )</title>
      <link>https://pnpt.tistory.com/198</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;'더블 다이아몬드 프로세스'&lt;/b&gt;는 업무 과정을 분할하여 각 시기에 맞는 업무의 방향을 제시하는 유용한 방법론인데, 이는 비단 UX 디자인뿐만 아니라 우리의 삶 전반에 걸쳐 적용될 만한 일반론에 가까워.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qDJcf/btsPOkPzNof/M2dRLtFarkidrAcHkXu05K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qDJcf/btsPOkPzNof/M2dRLtFarkidrAcHkXu05K/img.png&quot; data-alt=&quot;https://www.hi-interactive.com/blog/ux-process-the-double-diamond&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qDJcf/btsPOkPzNof/M2dRLtFarkidrAcHkXu05K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqDJcf%2FbtsPOkPzNof%2FM2dRLtFarkidrAcHkXu05K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;520&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.hi-interactive.com/blog/ux-process-the-double-diamond&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Discover&lt;/b&gt;&lt;br /&gt;일단 일을 맡으면 천천히 탐색의 범위를 넓히며 고민하지. 이 일의 의미는 무엇일까, 이 일에서 핵심인 부분은 어디이고, 영향을 받는 곳은 어디일까. 소외되어 보이지만 챙겨야 하는 일은 무엇일까. 놓친 곳은 없는가. 도대체 이건 왜 존재해야 하는 문제인가.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Define&lt;/b&gt;&lt;br /&gt;그리고 이 논의를 더 펼쳐서 주름진 곳 없이 펼친 후에는 펼친 논의들을 어떻게 수렴할 것인지를 살펴 봐. 이런 방향으로 이 일을 몰고 가볼까? 이 의미의 정수는 이런 단어이니 고정해야 오해가 없겠군. 이런 특성이 생길 수 있지만 일단은 묻어둘까. 이 일의 진정한 의미는 이런 거였구나! 이제 알겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Develop&lt;/b&gt;&lt;br /&gt;조금은 자신감이 생기지. &lt;span style=&quot;color: #7e98b1;&quot;&gt;내가 이해한 바에 따르면&lt;/span&gt; 여긴 이렇게 해야 해. 저건 저렇게, 그건 그렇게. 처음 펼쳐 둔 곳을 구석구석 밟아가며 내 이해와 원칙을 적용해 보는 거지. 나름의 변화가 느껴지고, 그만큼 미지의 것들도 눈에 띄게 돼. 무가치했던 곳에서 꽃이 피어나기도 하고, 우연들처럼 보이지만 사실은 내가 정리한 방향이고 내 관점의 실체적 재현이라고 느껴지면 마음이 뿌듯하지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Deliver&lt;/b&gt;&lt;br /&gt;그렇게 모든 곳을 밟아 놓고 나면, 나는 이것으로, 비로소, 세상과 마주하게 돼. 이제 유저도 받고, 테스트도 하며 실전 속에서 내가 맞았는지 틀린 지를 검증하면서 내가 걸어온 지점들을 둘러보며 단단히 다지는 일. 지난한 작업이고 변수도 많지만 어쨌든 세계에 영향을 끼치는 보람.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실, 나는 이 과정을 몇 백번, &lt;span style=&quot;color: #8cb3be;&quot;&gt;세는 방법에 따라서는&lt;/span&gt; 몇 천 번도 거쳐 왔어. 일에서든 삶에서든.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크게 보면 나는, 라이프 사이클의 Deliver 초입에 도착한 게 아닐까. 사춘기 시절까지, 길게 보면 군 시절 직후까지 나는 Discover 했고 방황했고 인생에 대해서 고민해 왔지. 나는 누구인가 왜 태어났나. 직업을 찾아보면서는 내가 스스로 만들어 둔 정체성을 사회에 적용해 보면서 스스로를 Define 하려 노력했어. 이건 내가 해야 하는 일인가. 이 활동은 나와 사회에 어떤 의미를 주고 있는가. 이 일을 시작하면서부터는 내 삶의 철학과 내 디자이너로서의 철학을 녹여서 나름의 여러 이야기들을 Develop 했고, 이제는 이 과정들을 돌아보며 삶의 외부에 여러 흔적을 남기며 대를 잇는 거지. 일에서든 삶에서든.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실은 실패에 가까워. 사춘기나 청년기에 끝냈어야 할 Discover를 여전히 하고 있고, 불혹의 나이를 지나면서도 삶을 Define 하지 못했거든. 여러 가지 이유로 내 자산을 Develop 하지도 못한 상태로 성긴 Deliver를 하느라 시간을 보내고 있지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 잘게 볼 수록 더블 다이아몬드는 무한한 중첩 구조라는 걸 알게 되었어. 마치 프랙탈 도형처럼 - 한 곳의 discover가 이루어질 때, 삶의 어딘가에서는 deliver도 일어나고 define도 생겨. 계속 희망 속에서 수렴이 일어나고 절망 안에서 새로운 대안을 찾지.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삶은, 굳이 UX 용어로써가 아니더라도 매우 Agile해야 해.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>LOG/OPN</category>
      <category>나중에 정리할게 그냥 끄적임</category>
      <author>ARTBRAIN</author>
      <guid isPermaLink="true">https://pnpt.tistory.com/198</guid>
      <comments>https://pnpt.tistory.com/198#entry198comment</comments>
      <pubDate>Wed, 13 Aug 2025 12:32:34 +0900</pubDate>
    </item>
    <item>
      <title>키치와 버내큘러의 차이</title>
      <link>https://pnpt.tistory.com/197</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;언젠가는 한 번 쓰고 싶은 내용이었어. 오랜만에 시간이 나서 간단히 적어볼까 해.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람들이 키치&lt;span style=&quot;color: #7e98b1;&quot;&gt;(Kitsch)&lt;/span&gt;와 버내큘러&lt;span style=&quot;color: #7e98b1;&quot;&gt;(Vernacular)&lt;/span&gt;를 혼동하는 경우를 많이 보는데, 이게 적잖이 성가시거든. 상대가 잘못 이해하고 있는 걸 바로잡아 주어야 더 나은 대화가 될 것 같다가도, 뭐 나만 제대로 알아들으면 된 거 아닌가, 걍 저렇게 평생 살라고 하자 싶기도 하고. ^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더욱더 심각한 것은, 맞춤법처럼 정답이 있는 게 아니라서, &lt;b&gt;&quot;아닌데요, 그거 그런 뜻이 아닌데요&quot;&lt;/b&gt; 하기에도 좀 애매하단 말이지. &lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;s&gt;(불분명한 정의를 갖더라도 네 말은 틀림)&lt;/s&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼, 내가 알고 있는 범주 내에서 간단히 정리하려 해.&lt;br /&gt;이렇게 구분하자 ;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kitsch : 업자들의 모조품&lt;br /&gt;Vernacular : 비전문가의 오리지널&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐... 개운하진 않은데, 이게 제일 외우기 쉬운 것 같아.&lt;br /&gt;키치는 &lt;b&gt;업자들이 만든 B급 제품&lt;/b&gt;이고, 버내큘러는 &lt;b&gt;일반인이 만든 오리지널 손맛&lt;/b&gt;.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/66Yd8/btsPlgTjyT0/uxnhjgvCWulJWWYGvAhGuK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/66Yd8/btsPlgTjyT0/uxnhjgvCWulJWWYGvAhGuK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/66Yd8/btsPlgTjyT0/uxnhjgvCWulJWWYGvAhGuK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F66Yd8%2FbtsPlgTjyT0%2FuxnhjgvCWulJWWYGvAhGuK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;442&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;442&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 키치의 대표 작품(?)으로 여기는 게 왼쪽 이미지야. 아마 나이가 제법 있는 사람들은 택시나 버스 운전석 한구석에, 또는 룸미러에 대롱대롱 매달린 이 그림을 본 적이 있을 거야. 원본은 영국 화가 조슈아 레이놀즈의 '어린 사무엘'이라는 그림인데, 이건 사실 안전과는 전혀 관계가 없는 그림이고.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'어린 사무엘'이라는 그림을 본 누군가 &lt;span style=&quot;color: #7e98b1;&quot;&gt;(아마도 그림을 그려서 먹고사는 사람이었겠지)가&lt;/span&gt; 이걸 '아버지의 무사 귀환을 빌며 기도하는 자녀의 이미지'로 번안하여 그렸고, 우리나라에서는 직업 운전수들의 부적처럼 전파되었어.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오리지널리티를 누구도 묻지 않고, 생산과정의 특성상 B급 가치&lt;span style=&quot;color: #7e98b1;&quot;&gt;(상대적으로 저급한 퀄리티)&lt;/span&gt;를 띄는 생산물이 &lt;b&gt;키치&lt;/b&gt;를 정의하는 가장 큰 개념이라고 생각해. 그래서 kitsch는 기본적으로 오리지널리티의 담론과 항상 밀접하게 연결되어 있고, 현대로 오면서 그 개념&lt;span style=&quot;color: #7e98b1;&quot;&gt;(오리지널은 무엇인가)&lt;/span&gt;은 많이 퇴색되었지만, 여전히 '오리지널은 무엇인지 묻지 않겠다'는 전제는 유지하고 있어.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 너무 성장해서 더 이상 '키치 예술가'라고 말하긴 애매하지만, 이 분야의 가장 유명한 예술가는 아무래도 제프쿤스.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/das2tW/btsPj6Efxgn/zag71TKQf0Z6yKkwXatCH0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/das2tW/btsPj6Efxgn/zag71TKQf0Z6yKkwXatCH0/img.jpg&quot; data-origin-width=&quot;616&quot; data-origin-height=&quot;488&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;45.7&quot; style=&quot;width: 45.166%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/das2tW/btsPj6Efxgn/zag71TKQf0Z6yKkwXatCH0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdas2tW%2FbtsPj6Efxgn%2Fzag71TKQf0Z6yKkwXatCH0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;616&quot; height=&quot;488&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caD40o/btsPlhLvFrm/dBu6fsbsUw68KJQz4xPIT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caD40o/btsPlhLvFrm/dBu6fsbsUw68KJQz4xPIT1/img.png&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;1120&quot; data-is-animation=&quot;false&quot; style=&quot;width: 53.6712%;&quot; data-widthpercent=&quot;54.3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caD40o/btsPlhLvFrm/dBu6fsbsUw68KJQz4xPIT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaD40o%2FbtsPlhLvFrm%2FdBu6fsbsUw68KJQz4xPIT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1680&quot; height=&quot;1120&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;&amp;copy;jeffkoons&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 흔히 '이발소 그림'이라고 부르는 스타일. 제프쿤스는 그런 '업자'들의 작업을 모방해서 성공한 사람인데 요즘 작업은 그런 Kitsch 한 맛은 없어도, 여전히 '오리지널은 중요하지 않다'는 걸 여러 작업에서 보여주고 있지.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMw2T2/btsPkI3Y94q/8F6dnluaCtXoXpOzwEnh41/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMw2T2/btsPkI3Y94q/8F6dnluaCtXoXpOzwEnh41/img.jpg&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;324&quot; data-is-animation=&quot;false&quot; style=&quot;width: 57.4635%; margin-right: 10px;&quot; data-widthpercent=&quot;58.14&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMw2T2/btsPkI3Y94q/8F6dnluaCtXoXpOzwEnh41/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMw2T2%2FbtsPkI3Y94q%2F8F6dnluaCtXoXpOzwEnh41%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cV3m8M/btsPmcJjxus/xYLhfpLCGcCpkNkmPk8GyK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cV3m8M/btsPmcJjxus/xYLhfpLCGcCpkNkmPk8GyK/img.jpg&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;800&quot; data-is-animation=&quot;false&quot; style=&quot;width: 41.3737%;&quot; data-widthpercent=&quot;41.86&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cV3m8M/btsPmcJjxus/xYLhfpLCGcCpkNkmPk8GyK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcV3m8M%2FbtsPmcJjxus%2FxYLhfpLCGcCpkNkmPk8GyK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;출처미상&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 버내큘러는, 찾으려고 맘만 먹으면 원작자를 찾을 수 있겠지만 굳이 원작자를 찾지 않아. 그 원작자의 '비전문성'이 버내큘러 디자인을 특징짓는 가장 중요한 요소이기 때문에, 원작자를 몰라야 오히려 속이 편해. 그래서 버내큘러의 담론은 &lt;b&gt;'아트&lt;span style=&quot;color: #7e98b1;&quot;&gt;(또는 디자인)&lt;/span&gt;는 자생적인가'&lt;/b&gt;, 또는 &lt;b&gt;'예술가&lt;span style=&quot;color: #7e98b1;&quot;&gt;(디자이너)&lt;/span&gt;는 누구인가'&lt;/b&gt; 등과 연결되어 있어. 라따뚜이에서 말하는 'Anyone can cook'과 연결된 내용이지.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예술가나 디자이너 등 전문가가 없는 상황에서, 동네에서 글씨 좀 쓴다는 사람이나, 당장의 필요로 인해서 급하게 만들어지는 생산물을 버내큘러하다고 말할 수 있는데, 이는 키치와는 다르게 '훈련된 사람들과는 &lt;b&gt;미감 자체가 다르기 때문에 생기는&lt;/b&gt;' 결과물이야. &lt;b&gt;키치는 오리지널을 따라가려는 과정에서 생기는 부산물이고, 버내큘러는&lt;span style=&quot;color: #ee2323;&quot;&gt; 내가 오리지널인데 내 눈엔 이게 좋아&lt;/span&gt;&lt;/b&gt;&amp;nbsp;라는 거지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버내큘러는 필연적으로 기업에선 나오기 힘든 결과물이야. 디자이너를 뽑으면 안되거든. 아래 광고들을 봐. 서투름을 흉내 냈지만 몸에 밴 기본기는 드러날 수밖에 없지.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b07Fqa/btsPmef6wdO/IAkn7CNPWrkKLlAJ8hzsx0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b07Fqa/btsPmef6wdO/IAkn7CNPWrkKLlAJ8hzsx0/img.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;480&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.8643%; margin-right: 10px;&quot; data-widthpercent=&quot;48.43&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b07Fqa/btsPmef6wdO/IAkn7CNPWrkKLlAJ8hzsx0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb07Fqa%2FbtsPmef6wdO%2FIAkn7CNPWrkKLlAJ8hzsx0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o0oFK/btsPjQhpqaa/kLGDPjpQBfrp5o17zSmvm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o0oFK/btsPjQhpqaa/kLGDPjpQBfrp5o17zSmvm1/img.png&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;562&quot; data-is-animation=&quot;false&quot; style=&quot;width: 50.9729%;&quot; data-widthpercent=&quot;51.57&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o0oFK/btsPjQhpqaa/kLGDPjpQBfrp5o17zSmvm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo0oFK%2FbtsPjQhpqaa%2FkLGDPjpQBfrp5o17zSmvm1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;798&quot; height=&quot;562&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;&amp;copy;배달의민족&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 설명도 정확하다고 주장하긴 어렵지만, 적어도 '틀리지는 않은' 내용이라고 자부하니까 - 헷갈리는 사람은 이 키워드만 기억해줘. &lt;br /&gt;&lt;b&gt;키치는 모조품, 버내큘러는 비전문가&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소한 이것만 알고 있으면, 어디가서 뻘소리로 디자이너들 뒷목 잡게 하진 않을 거야. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(너 말이야 너!)&lt;/span&gt;&lt;/p&gt;</description>
      <category>IMG</category>
      <author>ARTBRAIN</author>
      <guid isPermaLink="true">https://pnpt.tistory.com/197</guid>
      <comments>https://pnpt.tistory.com/197#entry197comment</comments>
      <pubDate>Wed, 16 Jul 2025 15:03:32 +0900</pubDate>
    </item>
    <item>
      <title>Nothing ear(a) : 처음엔 칭찬할 생각이었는데</title>
      <link>https://pnpt.tistory.com/196</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;1881&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XYBpD/btsOKzE5a90/3EoIPKmxZzwk3JptyLfYlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XYBpD/btsOKzE5a90/3EoIPKmxZzwk3JptyLfYlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XYBpD/btsOKzE5a90/3EoIPKmxZzwk3JptyLfYlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXYBpD%2FbtsOKzE5a90%2F3EoIPKmxZzwk3JptyLfYlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1915&quot; height=&quot;1881&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;1881&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nothing 2(a) 폰에 이어서 ear(a)를 샀어. &lt;br /&gt;Nothing 2(a) 폰은 산 지 2년 정도 되었고, ear(a)는 산 지 일주일 정도 됐어.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직업이 직업인지라, 폰을 두 개 쓰는데, 이 Nothing 2(a)는 안드로이드앱 테스트용이고 메인 폰은 아이폰이야. 당연히 에어팟도 사용하고 있고. 오늘은 에어팟&lt;span style=&quot;color: #7e98b1;&quot;&gt;(pro2)&lt;/span&gt;과 ear(a)를 비교하는 방식으로 구매 후기를 써볼까 해. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(이하 nothing ear(a)는 '낫싱'으로 표기)&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫인상은, &lt;b&gt;작고 귀엽다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사진으로 보면 에어팟과 크기 차이가 없고, 재는 방식에 따라서는 더 크기도 한데, 눈으로 보기엔 매우 작아. 디자인 차이겠지. 쥐는 맛도 좋지만, 여는 건 조금 불편해. 일부러 연약하게 만든 느낌도 있어. 애플 제품처럼 뭔가 씌우고 꾸미게 만들게 하겠다는 전략인 것 같은데, 여는 방향을 헷갈리게 만든 건 좀 심했다 싶어.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcei8n/btsOJsty5mv/ortWCVv0FvIxdnrT7RCveK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcei8n/btsOJsty5mv/ortWCVv0FvIxdnrT7RCveK/img.png&quot; data-alt=&quot;두께도 살짝 두꺼움&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcei8n/btsOJsty5mv/ortWCVv0FvIxdnrT7RCveK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbcei8n%2FbtsOJsty5mv%2FortWCVv0FvIxdnrT7RCveK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;936&quot; height=&quot;446&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;446&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;두께도 살짝 두꺼움&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연약해 보이고, 흠집도 잘 나게 생겼지만, 플라스틱 자체의 품질은 나쁘지 않아. 생각보다는 내구성이 있을 것 같은데, 힌지 등의 연결부위가 충격에 잘 버틸지는 미지수야. 케이스의 방수방진등급이 IPx2라고 해서 깜짝 놀랐는데 &lt;span style=&quot;color: #7e98b1;&quot;&gt;(요즘에도 방수방진 안 되는 케이스가 있어?)&lt;/span&gt; 알고보니 내 에어팟&lt;span style=&quot;color: #7e98b1;&quot;&gt;(라이트닝 충전 버전)&lt;/span&gt;은 아예 케이스의 방수방진 등급이 없더라고. ㅋㅋ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NrPeq/btsOKpCSB3M/Tb1TYbVuLOkEoY9ptZaSKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NrPeq/btsOKpCSB3M/Tb1TYbVuLOkEoY9ptZaSKk/img.png&quot; data-origin-width=&quot;1754&quot; data-origin-height=&quot;1154&quot; data-is-animation=&quot;false&quot; style=&quot;width: 63.7628%; margin-right: 10px;&quot; data-widthpercent=&quot;64.51&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NrPeq/btsOKpCSB3M/Tb1TYbVuLOkEoY9ptZaSKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNrPeq%2FbtsOKpCSB3M%2FTb1TYbVuLOkEoY9ptZaSKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1754&quot; height=&quot;1154&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9cniQ/btsOJrg8v7M/WnZ4xIugKNXCtiGSuAHDY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9cniQ/btsOJrg8v7M/WnZ4xIugKNXCtiGSuAHDY0/img.png&quot; data-origin-width=&quot;2030&quot; data-origin-height=&quot;2428&quot; data-is-animation=&quot;false&quot; style=&quot;width: 35.0744%;&quot; data-widthpercent=&quot;35.49&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9cniQ/btsOJrg8v7M/WnZ4xIugKNXCtiGSuAHDY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9cniQ%2FbtsOJrg8v7M%2FWnZ4xIugKNXCtiGSuAHDY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2030&quot; height=&quot;2428&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이어팁의 사이즈는 에어팟과 낫싱 모두 '미디엄'인데, 에어팟의 '라지'가 낫싱의 '미디엄'정도로 보여. 그런데 이건 재는 방식의 차이가 아닐까. 이어팁의 &lt;b&gt;단단한 입구 부분의 직경&lt;/b&gt;은 비슷한 것 같아. 낫싱 이어팁의 유연한 부분이 더 넓게 펼쳐진 느낌. 실제로 착용해 보면 낫싱 쪽이 &lt;b&gt;차폐력&lt;/b&gt;이 더 좋은 것 같아. 사람에 따라 호불호가 나뉠 듯. 낫싱이 조금 크긴 한데, 무게나 밀도는 에어팟이 미묘하게 더 큰 거 같아. 그래서 착용한 상태로 보면 낫싱의 존재감이 더 강한데, 착용감은 조금 더 가볍고 단단하게 물리는 느낌이야.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이어폰의 가장 큰 점은 아무래도 음질. &lt;br /&gt;낫싱의 내 평가는 &lt;b&gt;'낫배드'&lt;/b&gt; 정도. 장단점이 분명해.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까도 말했지만, 구조적 특성으로 인해서 강한 차폐력이 있어. 이어폰이 완전 방전된 상태에서 귀에 끼고만 있어도 어느 정도 외부 소음을 막아주는 정도. 사람에 따라서 이 '압박감'이 피로감으로 느껴질 수도 있겠다 싶어. 내 경우에는 음악을 '분명히' 듣고 싶어 하는 터라 압박감을 좋아하는 편인데, 대중적으로는 불편해하는 사람들이 더 많을 것 같아.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전반적인 음질은 이 가격대에서 훌륭한 편이라고 생각하는데, 개성이 꽤 강해.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단적으로 말하자면, &lt;b&gt;'조용한 환경에서 비틀즈를 들을 때 가장 좋은 이어폰'&lt;/b&gt;이라고 말할 수 있어. 음 분리도 좋고 treble이나 음의 입체감도 좋은데, 전체적으로 &lt;b&gt;Bass의 인공미&lt;/b&gt;가 강해. 전용 앱에서도 bass를 여러 방식으로 보강하고 있는데, 자신들도 알고 있는 게지. 근데, 그 인공적인 Bass가 꼭 나쁘냐고 하면 또 그렇지도 않아. 다른 음을 누르거나 소리 왜곡을 하지 않고 딱 bass 영역만 강하게 해주는 느낌인데, 드라이버와 하우징이 좀 안 맞는 건지, 아니면 덩치에 비해 강한 드라이버를 넣은 건지 - 소리를 약간만 올려도 음압이 강해지더라고. 그래서 음악을 크게 듣는 사람들은 인공 bass를 빼고 듣는 걸 추천해...... 근데 또 그거 좋아하는 사람도 있으니까. 귀 쪽에서 공기가 팡팡 솟아나는 느낌이랄까. 그리고 뚜렷한 음 분리가 장점이라고 말하긴 했는데, 이게 약간 &lt;b&gt;레트로한 맛&lt;/b&gt;이 있어. 약간의 LP같은 치찰음이 있는데 불편할 정도는 아니고 재밌는 정도. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(이 이어폰의 상위 버전인 Nothing 2024는 하우징이 세라믹이라던데, 그건 좀 다를듯도?)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸로 &lt;b&gt;가장 듣기 좋은 음악은 60년대 영미권 음악, 리마스터하지 않은 음원&lt;/b&gt;을 듣는 게 최고인 것 같아. 반면 소리를 맥스로 놓고 듣는 사람들에게는 적합하지 않은 것 같아. 소리를 키울수록 개방감과 확장감이 있어야 하는데, 낫싱은 조금 막아 세우는 느낌이 있어. 빵 하고 터지는 걸 애써 막는 느낌이라 스래시 메탈 듣는 사람은 - 걍 마샬 쓰는 게 좋을 것 같아. 게다가 낫싱은 &lt;b&gt;소리가 외부로 새는 편&lt;/b&gt;이야.&amp;nbsp;볼륨을 맥스로 놓고 들으니 주변에서 크다고 하더라구. 에어팟을 쓸 땐 그런 피드백이 없었는데 말이지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나 듣기 좋은 장르는 &lt;b&gt;한국 아이돌 음악&lt;/b&gt;이야. &lt;b&gt;에스파&lt;/b&gt;나 &lt;b&gt;블랙핑크&lt;/b&gt;같은 조금 하드한 비트를 인공적으로 조절한 음색과 또 궁합이 좋더라구. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(특히 에스파의 &lt;b&gt;savage&lt;/b&gt;)&lt;/span&gt; 한국 특유의 뭉개는 듯한 매끄러운 음색이 인공적인 튜닝을 만나니 원래 곡의 의도를 잘 살리는 느낌이야. 마이클 잭슨과 자넷 잭슨이 함께 부른 &lt;b&gt;Scream&lt;/b&gt;도 매우 좋아. 같은 맥락에서 독일 클럽 음악, EDM 등도 듣기 좋은 편이야. &lt;span style=&quot;color: #7e98b1;&quot;&gt;(주변에 뭐라는 사람이 없다면 이 경우는 크게 들어도 좋을 듯.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/0P4A1K4lXDo?si=AHv0rwPuYd2uVvro&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/0P4A1K4lXDo?si=AHv0rwPuYd2uVvro&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=0P4A1K4lXDo&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/eW5eE/hyY8VscY7g/BYalL7BolZHg8jkUuvxnH0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=288_218_940_522,https://scrap.kakaocdn.net/dn/cv1nbr/hyY79YpiyD/7SNm5Vc4QLG3rOjb3gEmk0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=288_218_940_522&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Michael Jackson, Janet Jackson - Scream (Official Video)&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/0P4A1K4lXDo&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/WPdWvnAAurg?si=06wpOeLrV1T2Yhuz&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/WPdWvnAAurg?si=06wpOeLrV1T2Yhuz&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=WPdWvnAAurg&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/las1S/hyY8apvlsm/ZywhxDliinVSOz0USkcvCK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=284_148_1008_454,https://scrap.kakaocdn.net/dn/c4uIjI/hyZcnHl72W/GyxgR5kbS4BaBxdAgreqn0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=284_148_1008_454&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;aespa 에스파 &quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/WPdWvnAAurg&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/90M60PzmxEE?si=Eopo--4HaxwwgEeN&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/90M60PzmxEE?si=Eopo--4HaxwwgEeN&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=90M60PzmxEE&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/hr1Fe/hyZcjybBHF/iUHzVuoWp6MnA149jdqfg0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=408_162_858_542,https://scrap.kakaocdn.net/dn/Gayun/hyZcjEXiuF/jvQEHb3GdfU0AHV4IuEkkK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=408_162_858_542&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Across The Universe (Remastered 2009)&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/90M60PzmxEE&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 낫싱은,&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비활동적인 사람이 (주변 환경이) 적당히 조용한 곳에서&lt;/li&gt;
&lt;li&gt;레트로한 음악을 듣거나 인공적인 음색, 과장된 비트의 음악을 들을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최적화된 이어폰이라고 생각해.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;귀여운 디자인&lt;/li&gt;
&lt;li&gt;경쟁력 있는 가격&lt;/li&gt;
&lt;li&gt;충전 속도 개빠름&lt;/li&gt;
&lt;li&gt;두 기기 간의 전환이 &lt;b&gt;에어팟보다 빠르고 부드러움&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;가격대비 훌륭한 노이즈캔슬링 &lt;span style=&quot;color: #7e98b1;&quot;&gt;(그런데 배터리 소모가 큰 편, OFF도 나쁘지 않음)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;버튼 커스텀 가능, 별도 앱 지원, 맥 친화적&lt;/li&gt;
&lt;li&gt;개성 있는 음색, 음 분리 탁월&lt;/li&gt;
&lt;li&gt;(에어팟에 비해서) 청소가 쉬운 구조. 자석으로 착 붙는 느낌 좋음.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LDAC 코덱 지원!&lt;/b&gt; &lt;b&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;(음악 좋아하는 유저들에게는 매력적인 일이지)&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;스트랩을 꽂을 곳이 없음&lt;/li&gt;
&lt;li&gt;QCY 등 요즘은 싼 것도 좋은 게 많아서.&lt;/li&gt;
&lt;li&gt;에어팟에 비해서 지속 시간이 짧음&lt;/li&gt;
&lt;li&gt;여러 기기를 등록할 수 있으나 전환은 두 개로 한정&lt;/li&gt;
&lt;li&gt;노이즈캔슬링이 기기의 차폐력에 기대는 편&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;쓸어서 볼륨조절이 안됨!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;인공적인 음색을 기술로 커버하려다가...&lt;/li&gt;
&lt;li&gt;뭔가 불안한 이어폰의 케이스 내 고정방법&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;그래서 추천하나?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9만 원에서 10만 원 초반까지의 블루투스 기준으로 보면, 정말 &lt;b&gt;탁월하게 좋은 수준&lt;/b&gt;이야. QCY의 가성비를 넘을 수는 없겠지만, 걔는... 못생겼잖아. ㅎㅎ. 노이즈 캔슬링은 그다지 눈에 띄는 수준은 아닌데, 확실히 작동되기는 해. 이어캡이 워낙 소릴 잘 막아주니까 낀 후에 뭔가 달라졌다고 느끼기 어려운 탓이지. 사운드에 대해 부정적인 얘기를 많이 했지만, 요즘은 워낙 좋은 이어폰들이 대중화되어 있어서 사람들의 청음 수준이 높아졌기 때문이지 이 이어폰의 수준이 낮다는 뜻은 아니야.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이 이어폰은 스스로 의도치 않게 매우 날카로운 유저군을 대상으로 해. 스타일에 맞는 사람들에게는 열광할 만한 물건이지만, 많은 사람들은 각자의 불만사항이 있을 것 같아. 사용시간이 긴 사람은 이어폰 배터리에 아쉬움이 있을 수 있고, 음량을 크게 듣는 사람들은 개방성에 아쉬울 수 있어. 파인 리스너&lt;span style=&quot;color: #7e98b1;&quot;&gt;(민감한 분들)&lt;/span&gt;들에게는 참 근본 없는 구성이라고 생각할 수도 있어.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 개성 있는 거 좋아하고, 낫싱 폰을 사용하거나, 이어폰을 계속 꽂고 사는 사람이 아닌 캐주얼한 유저들에게는 꽤 괜찮은 선택이라고 생각해. 그래서? 나는 추천.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>LOG/SHP</category>
      <category>ear(a)</category>
      <category>낫싱</category>
      <category>내돈내산</category>
      <author>ARTBRAIN</author>
      <guid isPermaLink="true">https://pnpt.tistory.com/196</guid>
      <comments>https://pnpt.tistory.com/196#entry196comment</comments>
      <pubDate>Fri, 20 Jun 2025 12:49:12 +0900</pubDate>
    </item>
  </channel>
</rss>