three-live 0.0.0-stage → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +58 -2
  3. package/dist/index.d.ts +224 -0
  4. package/dist/three-author-engine.js +292 -0
  5. package/dist/three-author.cjs +292 -0
  6. package/dist/three-author.d.ts +224 -0
  7. package/dist/three-author.js +292 -0
  8. package/dist/three-convert.cjs +286 -0
  9. package/dist/three-convert.d.ts +224 -0
  10. package/dist/three-convert.js +286 -0
  11. package/dist/three-live-animation.cjs +36 -0
  12. package/dist/three-live-animation.d.ts +224 -0
  13. package/dist/three-live-animation.js +36 -0
  14. package/dist/three-live-animation.min.js +36 -0
  15. package/dist/three-live-element.cjs +217 -0
  16. package/dist/three-live-element.d.ts +224 -0
  17. package/dist/three-live-element.js +217 -0
  18. package/dist/three-live-extras.cjs +42 -0
  19. package/dist/three-live-extras.d.ts +224 -0
  20. package/dist/three-live-extras.js +42 -0
  21. package/dist/three-live-extras.min.js +42 -0
  22. package/dist/three-live-full.cjs +336 -0
  23. package/dist/three-live-full.js +336 -0
  24. package/dist/three-live-full.min.js +336 -0
  25. package/dist/three-live-sandbox.html +157 -0
  26. package/dist/three-live-viewer.cjs +217 -0
  27. package/dist/three-live-viewer.d.ts +224 -0
  28. package/dist/three-live-viewer.js +217 -0
  29. package/dist/three-live-viewer.min.js +217 -0
  30. package/dist/three-live.cjs +294 -0
  31. package/dist/three-live.js +294 -0
  32. package/dist/three-live.min.js +294 -0
  33. package/dist/three-view.cjs +217 -0
  34. package/dist/three-view.d.ts +224 -0
  35. package/dist/three-view.js +217 -0
  36. package/dist/three-xr.cjs +286 -0
  37. package/dist/three-xr.d.ts +224 -0
  38. package/dist/three-xr.js +286 -0
  39. package/package.json +81 -4
@@ -0,0 +1,286 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ "use strict";var we=Object.defineProperty;var ht=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames;var ft=Object.prototype.hasOwnProperty;var dt=(n,e)=>{for(var t in e)we(n,t,{get:e[t],enumerable:!0})},pt=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of mt(e))!ft.call(n,r)&&r!==t&&we(n,r,{get:()=>e[r],enumerable:!(i=ht(e,r))||i.enumerable});return n};var bt=n=>pt(we({},"__esModule",{value:!0}),n);var Ft={};dt(Ft,{WebXRSessionManager:()=>Me,activateAR:()=>Lt,buildUSDZZip:()=>ve,calculateCRC32:()=>Ce,createSceneViewerIntent:()=>rt,createUSDZBlob:()=>Ie,generateUSDA:()=>Fe,generateUSDZ:()=>it,getARCapabilities:()=>Ne,getAvailableARModes:()=>Et,getBestARMode:()=>Pt,glbToUSDZ:()=>xe,isQuickLookSupported:()=>_e,isSceneViewerSupported:()=>Be,isWebXRSupported:()=>ke,launchQuickLook:()=>Ue,launchSceneViewer:()=>st});module.exports=bt(Ft);var pe="__THREE_LIVE_REGISTRY__";function ce(){let n=typeof globalThis<"u"?globalThis:{};if(!n[pe]){let e={plugins:[],decoders:new Map};try{Object.defineProperty(n,pe,{value:e,writable:!1,configurable:!1,enumerable:!1})}catch{n[pe]=e}}return n[pe]}var z=ce().plugins;function Ve(n){let e=ce().plugins;e.some(t=>t.name===n.name)||e.push(n)}function Oe(){return ce().plugins}function $(){let n=new Float32Array(16);return n[0]=1,n[5]=1,n[10]=1,n[15]=1,n}function Ge(n,e,t,i,r){let s=1/Math.tan(e/2);n.fill(0),n[0]=s/t,n[5]=s,n[11]=-1;let u=1/(i-r);return n[10]=(r+i)*u,n[14]=2*r*i*u,n}function He(n,e,t,i){let[r,s,u]=e,[l,o,c]=i,[a,f,m]=t,b=r-a,h=s-f,T=u-m,y=Math.hypot(b,h,T);y<=1e-5?(b=0,h=0,T=1):(b/=y,h/=y,T/=y);let R=o*T-c*h,w=c*b-l*T,M=l*h-o*b;y=Math.hypot(R,w,M),y<=1e-5?(R=0,w=0,M=0):(R/=y,w/=y,M/=y);let A=h*M-T*w,x=T*R-b*M,D=b*w-h*R;return y=Math.hypot(A,x,D),y<=1e-5?(A=0,x=0,D=0):(A/=y,x/=y,D/=y),n[0]=R,n[1]=A,n[2]=b,n[3]=0,n[4]=w,n[5]=x,n[6]=h,n[7]=0,n[8]=M,n[9]=D,n[10]=T,n[11]=0,n[12]=-(R*r+w*s+M*u),n[13]=-(A*r+x*s+D*u),n[14]=-(b*r+h*s+T*u),n[15]=1,n}function Q(n,e,t){let i=e[0],r=e[1],s=e[2],u=e[3],l=e[4],o=e[5],c=e[6],a=e[7],f=e[8],m=e[9],b=e[10],h=e[11],T=e[12],y=e[13],R=e[14],w=e[15],M=t[0],A=t[1],x=t[2],D=t[3];return n[0]=M*i+A*l+x*f+D*T,n[1]=M*r+A*o+x*m+D*y,n[2]=M*s+A*c+x*b+D*R,n[3]=M*u+A*a+x*h+D*w,M=t[4],A=t[5],x=t[6],D=t[7],n[4]=M*i+A*l+x*f+D*T,n[5]=M*r+A*o+x*m+D*y,n[6]=M*s+A*c+x*b+D*R,n[7]=M*u+A*a+x*h+D*w,M=t[8],A=t[9],x=t[10],D=t[11],n[8]=M*i+A*l+x*f+D*T,n[9]=M*r+A*o+x*m+D*y,n[10]=M*s+A*c+x*b+D*R,n[11]=M*u+A*a+x*h+D*w,M=t[12],A=t[13],x=t[14],D=t[15],n[12]=M*i+A*l+x*f+D*T,n[13]=M*r+A*o+x*m+D*y,n[14]=M*s+A*c+x*b+D*R,n[15]=M*u+A*a+x*h+D*w,n}function Xe(n,e,t,i){let r=e[0],s=e[1],u=e[2],l=e[3],o=r+r,c=s+s,a=u+u,f=r*o,m=r*c,b=r*a,h=s*c,T=s*a,y=u*a,R=l*o,w=l*c,M=l*a,A=i[0],x=i[1],D=i[2];return n[0]=(1-(h+y))*A,n[1]=(m+M)*A,n[2]=(b-w)*A,n[3]=0,n[4]=(m-M)*x,n[5]=(1-(f+y))*x,n[6]=(T+R)*x,n[7]=0,n[8]=(b+w)*D,n[9]=(T-R)*D,n[10]=(1-(f+h))*D,n[11]=0,n[12]=t[0],n[13]=t[1],n[14]=t[2],n[15]=1,n}function ne(n,e){let t=e[0],i=e[1],r=e[2],s=e[4],u=e[5],l=e[6],o=e[8],c=e[9],a=e[10],f=a*u-l*c,m=-a*s+l*o,b=c*s-u*o,h=t*f+i*m+r*b;return h&&(h=1/h,n[0]=f*h,n[1]=(-a*i+r*c)*h,n[2]=(l*i-r*u)*h,n[3]=m*h,n[4]=(a*t-r*o)*h,n[5]=(-l*t+r*s)*h,n[6]=b*h,n[7]=(-c*t+i*o)*h,n[8]=(u*t-i*s)*h),n}function ze(n,e){let t=e[0],i=e[1],r=e[2],s=e[3],u=e[4],l=e[5],o=e[6],c=e[7],a=e[8],f=e[9],m=e[10],b=e[11],h=e[12],T=e[13],y=e[14],R=e[15],w=t*l-i*u,M=t*o-r*u,A=t*c-s*u,x=i*o-r*l,D=i*c-s*l,d=r*c-s*o,v=a*T-f*h,p=a*y-m*h,E=a*R-b*h,L=f*y-m*T,g=f*R-b*T,S=m*R-b*y,P=w*S-M*g+A*L+x*E-D*p+d*v;return P?(P=1/P,n[0]=(l*S-o*g+c*L)*P,n[1]=(r*g-i*S-s*L)*P,n[2]=(T*d-y*D+R*x)*P,n[3]=(m*D-f*d-b*x)*P,n[4]=(o*E-u*S-c*p)*P,n[5]=(t*S-r*E+s*p)*P,n[6]=(y*A-h*d-R*M)*P,n[7]=(a*d-m*A+b*M)*P,n[8]=(u*g-l*E+c*v)*P,n[9]=(i*E-t*g-s*v)*P,n[10]=(h*D-T*A+R*w)*P,n[11]=(f*A-a*D-b*w)*P,n[12]=(l*p-u*L-o*v)*P,n[13]=(t*L-i*p+r*v)*P,n[14]=(T*M-h*x-y*w)*P,n[15]=(a*x-f*M+m*w)*P,n):null}function Re(n,e,t,i,r){let s=r[0]*e+r[4]*t+r[8]*i+r[12],u=r[1]*e+r[5]*t+r[9]*i+r[13],l=r[2]*e+r[6]*t+r[10]*i+r[14],o=r[3]*e+r[7]*t+r[11]*i+r[15],c=o!==0?1/o:1;n[0]=s*c,n[1]=u*c,n[2]=l*c}function We(n,e,t,i,r,s,u,l,o,c,a,f,m,b,h,T,y=0){let R=c-u,w=a-l,M=f-o,A=m-u,x=b-l,D=h-o,d=r*D-s*x,v=s*A-i*D,p=i*x-r*A,E=R*d+w*v+M*p;if(E>-1e-7&&E<1e-7)return!1;let L=1/E,g=n-u,S=e-l,P=t-o,B=L*(g*d+S*v+P*p);if(B<-y||B>1+y)return!1;let X=S*M-P*w,W=P*R-g*M,G=g*w-S*R,j=L*(i*X+r*W+s*G);if(j<-y||B+j>1+y)return!1;let V=L*(A*X+x*W+D*G);if(V>1e-4&&V<T.distance){T.distance=V,T.point=[n+i*V,e+r*V,t+s*V];let q=w*D-M*x,N=M*A-R*D,_=R*x-w*A,H=Math.hypot(q,N,_)||1;return T.normal=[q/H,N/H,_/H],!0}return!1}function be(n,e){let t=Array.isArray(n?.nodes)?n.nodes.length:0,i=[];for(let a=0;a<t;a++)i.push($());if(t===0)return i;let r=new Set;for(let a of n.nodes)if(Array.isArray(a.children))for(let f of a.children)r.add(f);let s=new Set,u=128,l=(a,f,m=0)=>{if(m>u||a<0||a>=t||s.has(a))return;s.add(a);let b=n.nodes[a];if(!b)return;let h=$();if(e&&e[a])h.set(e[a]);else if(b.matrix&&b.matrix.length===16)h.set(b.matrix);else{let y=b.translation||[0,0,0],R=b.rotation||[0,0,0,1],w=b.scale||[1,1,1];Xe(h,R,y,w)}let T=i[a];if(f?Q(T,f,h):T.set(h),Array.isArray(b.children))for(let y of b.children)typeof y=="number"&&l(y,T,m+1)},o=[],c=n.scenes&&n.scenes[n.scene!==void 0?n.scene:0];if(c&&Array.isArray(c.nodes))o.push(...c.nodes);else for(let a=0;a<t;a++)r.has(a)||o.push(a);for(let a of o)l(a,null);for(let a=0;a<t;a++)!r.has(a)&&!o.includes(a)&&l(a,null);return i}function gt(n){return new TextDecoder().decode(n)}var Ke=ce().decoders;function yt(n,e){Ke.set(n.toLowerCase(),e)}function he(n){return Ke.get(n.toLowerCase())}function Ye(n){let e=ArrayBuffer.isView(n)?n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength):n,t=new DataView(e);if(e.byteLength<12)throw new Error(`Invalid GLB buffer size: ${e.byteLength} bytes`);let i=t.getUint32(0,!0);if(i!==1179937895){let m=t.getUint8(0);throw m===123||m===32||m===10||m===13?new Error("[three-live] Multi-file JSON .gltf is not supported for performance reasons. Please pack your asset into a single binary .glb file."):new Error(`Invalid GLB magic: 0x${i.toString(16)}`)}let r=t.getUint32(4,!0);if(r!==2)throw new Error(`Unsupported GLB version: ${r}`);let s=t.getUint32(8,!0),u=12,l=null,o=null;for(;u+8<=s&&u+8<=e.byteLength;){let m=t.getUint32(u,!0),b=t.getUint32(u+4,!0),h=u+8;if(h+m>e.byteLength)throw new Error(`Truncated GLB chunk: required ${h+m} bytes, buffer has ${e.byteLength}`);if(b===1313821514){let T=new Uint8Array(e,h,m),y=gt(T);l=JSON.parse(y,(R,w)=>R==="__proto__"||R==="constructor"||R==="prototype"?void 0:w)}else b===5130562&&(o=e.slice(h,h+m));u=h+m}if(!l)throw new Error("Missing JSON chunk in GLB");let c=l.extensionsRequired||[];if(c.includes("KHR_draco_mesh_compression")&&!he("draco"))throw new Error("Model requires KHR_draco_mesh_compression. Register a decoder via ThreeLiveElement.registerDecoder('draco', decoder).");if(c.includes("EXT_meshopt_compression")&&!he("meshopt"))throw new Error("Model requires EXT_meshopt_compression. Register a decoder via ThreeLiveElement.registerDecoder('meshopt', decoder).");if(c.includes("KHR_texture_basisu")&&!he("ktx2"))throw new Error("Model requires KHR_texture_basisu. Register a decoder via ThreeLiveElement.registerDecoder('ktx2', decoder).");let a=o||new ArrayBuffer(0),f={gltf:l,bin:a,animations:[]};for(let m of z)m.onParseGLB?.(f);return f}function vt(n){return typeof n=="object"&&n!==null&&"gltf"in n&&typeof n.gltf=="object"&&n.gltf!==null&&"bin"in n&&(n.bin instanceof ArrayBuffer||ArrayBuffer.isView(n.bin))}function me(n){if(vt(n))return n;if(n instanceof ArrayBuffer||ArrayBuffer.isView(n))return Ye(n);throw new TypeError("Invalid 3D model input: expected GLBData ({ gltf, bin }) or binary GLB (ArrayBuffer / ArrayBufferView).")}var Ze=`#version 300 es
18
+ layout(location=0) in vec3 aPosition;
19
+ layout(location=1) in vec3 aNormal;
20
+ layout(location=2) in vec2 aUV;
21
+ uniform mat4 uMVP,uModel;
22
+ uniform mat3 uNormalMatrix;
23
+ uniform vec4 uUvTransform;
24
+ out vec3 vNormal,vWorldPos;
25
+ out vec2 vUV;
26
+ void main(){
27
+ vec3 rawN=uNormalMatrix*aNormal;
28
+ vNormal=length(rawN)>1e-5?normalize(rawN):vec3(0.0);
29
+ vec4 world=uModel*vec4(aPosition,1.0);
30
+ vWorldPos=world.xyz;
31
+ vec2 scaleUV=uUvTransform.zw;
32
+ if(scaleUV.x==0.0&&scaleUV.y==0.0)scaleUV=vec2(1.0);
33
+ vUV=aUV*scaleUV+uUvTransform.xy;
34
+ gl_Position=uMVP*vec4(aPosition,1.0);
35
+ }`,Qe=`#version 300 es
36
+ precision highp float;
37
+ in vec3 vNormal,vWorldPos;
38
+ in vec2 vUV;
39
+ uniform vec4 uBaseColor;
40
+ uniform float uMetallic,uRoughness,uEmissive,uEnvIntensity;
41
+ uniform vec2 uClearcoat;
42
+ uniform vec3 uCameraPos,uAmbientColor;
43
+ uniform sampler2D uBaseColorTexture,uMetallicRoughnessTexture,uNormalTexture,uOcclusionTexture,uEnvironmentMap,uXrDepthTex;
44
+ uniform int uHasTexture,uHasMetallicRoughnessTexture,uHasNormalTexture,uHasOcclusionTexture,uHasEnvironmentMap,uXrDepthEnabled,uXrDepthFormat;
45
+ uniform float uNormalScale,uOcclusionStrength,uXrRawValueToMeters;
46
+ uniform mat4 uXrDepthUVTransform;
47
+ uniform vec2 uViewportSize;
48
+ uniform int uToneMapping,uNumDirLights,uNumPointLights;
49
+ uniform vec3 uDirLightDir[2],uDirLightColor[2],uPointLightPos[2],uPointLightColor[2];
50
+ out vec4 fragColor;
51
+
52
+ vec2 envBRDF(float r,float n){
53
+ vec4 c0=vec4(-1.0,-0.0275,-0.572,0.022),c1=vec4(1.0,0.0425,1.04,-0.04);
54
+ vec4 rv=r*c0+c1;
55
+ float a=min(rv.x*rv.x,exp2(-9.28*n))*rv.x+rv.y;
56
+ return vec2(-1.04,1.04)*a+rv.zw;
57
+ }
58
+
59
+ vec3 F_SchlickRoughness(vec3 F0,float r,float n){
60
+ return F0+(max(vec3(1.0-r),F0)-F0)*pow(clamp(1.0-n,0.0,1.0),5.0);
61
+ }
62
+
63
+ vec3 getStudioRadiance(vec3 R,float r){
64
+ vec3 kd=normalize(vec3(0.0,1.0,0.35));
65
+ float ki=pow(max(dot(R,kd),0.0),mix(96.0,1.5,r))*mix(2.4,0.5,r);
66
+ vec3 fd=normalize(vec3(-0.85,0.45,-0.35));
67
+ float fi=pow(max(dot(R,fd),0.0),mix(36.0,1.2,r))*mix(1.3,0.35,r);
68
+ float ri=pow(clamp(1.0-abs(R.y),0.0,1.0),3.5)*mix(0.55,0.22,r);
69
+ vec3 ag=mix(vec3(0.06,0.06,0.08),vec3(0.48,0.50,0.55),R.y*0.5+0.5);
70
+ return ag+vec3(1.0,0.98,0.94)*ki+vec3(0.85,0.92,1.0)*fi+vec3(0.65,0.72,0.85)*ri;
71
+ }
72
+
73
+ vec3 perturbNormal(vec3 N,vec3 V,vec2 uv,sampler2D normalMap,float scale){
74
+ vec3 mapNormal=texture(normalMap,uv).xyz*2.0-1.0;
75
+ mapNormal.xy*=scale;
76
+ vec3 dp1=dFdx(vWorldPos);
77
+ vec3 dp2=dFdy(vWorldPos);
78
+ vec2 duv1=dFdx(uv);
79
+ vec2 duv2=dFdy(uv);
80
+ vec3 dp2perp=cross(dp2,N);
81
+ vec3 dp1perp=cross(N,dp1);
82
+ vec3 T=dp2perp*duv1.x+dp1perp*duv2.x;
83
+ vec3 B=dp2perp*duv1.y+dp1perp*duv2.y;
84
+ float invmax=inversesqrt(max(dot(T,T),dot(B,B)));
85
+ return normalize(mat3(T*invmax,B*invmax,N)*normalize(mapNormal));
86
+ }
87
+
88
+ vec2 equirectangularUV(vec3 dir){
89
+ vec3 d=normalize(dir);
90
+ float u=atan(d.z,d.x)*0.15915494309+0.5;
91
+ float v=asin(clamp(d.y,-1.0,1.0))*0.31830988618+0.5;
92
+ return vec2(u,1.0-v);
93
+ }
94
+
95
+ vec3 neutralToneMapping(vec3 color){
96
+ const float startCompression=0.76;
97
+ const float desaturation=0.15;
98
+ float x=min(color.r,min(color.g,color.b));
99
+ float offset=x<0.08?x-6.25*x*x:0.04;
100
+ color-=offset;
101
+ float peak=max(color.r,max(color.g,color.b));
102
+ if(peak<startCompression)return color;
103
+ const float d=1.0-startCompression;
104
+ float newPeak=1.0-d*d/(peak+d-startCompression);
105
+ color*=newPeak/peak;
106
+ float g=1.0-1.0/(desaturation*(peak-newPeak)+1.0);
107
+ return mix(color,newPeak*vec3(1.0),g);
108
+ }
109
+
110
+ vec3 applyToneMapping(vec3 color,int mode){
111
+ if(mode==0)return neutralToneMapping(color);
112
+ if(mode==1)return color/(color+vec3(1.0));
113
+ return color;
114
+ }
115
+
116
+ void main(){
117
+ vec4 base=uBaseColor;
118
+ if(uHasTexture==1)base*=texture(uBaseColorTexture,vUV);
119
+ if(length(vNormal)<1e-4&&uHasTexture==1){
120
+ vec3 unlit=base.rgb+vec3(uEmissive*0.35,uEmissive*0.5,uEmissive*0.7);
121
+ fragColor=vec4(unlit,base.a);
122
+ return;
123
+ }
124
+ vec3 N=length(vNormal)<1e-4?normalize(cross(dFdx(vWorldPos),dFdy(vWorldPos))):normalize(vNormal);
125
+ if(!gl_FrontFacing)N=-N;
126
+ vec3 V=normalize(uCameraPos-vWorldPos);
127
+ if(uHasNormalTexture==1){
128
+ N=perturbNormal(N,V,vUV,uNormalTexture,uNormalScale);
129
+ }
130
+
131
+ float metallic=uMetallic;
132
+ float roughness=uRoughness;
133
+ if(uHasMetallicRoughnessTexture==1){
134
+ vec4 mr=texture(uMetallicRoughnessTexture,vUV);
135
+ roughness*=mr.g;
136
+ metallic*=mr.b;
137
+ }
138
+ roughness=clamp(roughness,0.04,1.0);
139
+ metallic=clamp(metallic,0.0,1.0);
140
+
141
+ float occ=1.0;
142
+ if(uHasOcclusionTexture==1){
143
+ occ=mix(1.0,texture(uOcclusionTexture,vUV).r,uOcclusionStrength);
144
+ }
145
+
146
+ float gloss=1.0-roughness;
147
+ float specExp=mix(16.0,256.0,gloss*gloss);
148
+ float specWeight=mix(0.22*gloss,1.0,metallic);
149
+ vec3 directLight=vec3(0.0);
150
+ for(int i=0;i<2;i++){
151
+ if(i>=uNumDirLights)break;
152
+ vec3 L=normalize(uDirLightDir[i]);
153
+ float NdotL=max(dot(N,L),0.0);
154
+ vec3 H=normalize(L+V);
155
+ float NoH=max(dot(N,H),0.0);
156
+ float spec=pow(NoH,specExp)*specWeight+uClearcoat.x*pow(NoH,mix(64.0,512.0,1.0-uClearcoat.y))*0.35;
157
+ directLight+=(base.rgb*NdotL*0.75+vec3(spec))*uDirLightColor[i];
158
+ }
159
+ for(int i=0;i<2;i++){
160
+ if(i>=uNumPointLights)break;
161
+ vec3 toLight=uPointLightPos[i]-vWorldPos;
162
+ float dist=length(toLight);
163
+ vec3 L=toLight/max(dist,0.0001);
164
+ float atten=1.0/(1.0+0.09*dist+0.032*dist*dist);
165
+ float NdotL=max(dot(N,L),0.0);
166
+ vec3 H=normalize(L+V);
167
+ float NoH=max(dot(N,H),0.0);
168
+ float spec=pow(NoH,specExp)*specWeight+uClearcoat.x*pow(NoH,mix(64.0,512.0,1.0-uClearcoat.y))*0.35;
169
+ directLight+=(base.rgb*NdotL*0.75+vec3(spec))*uPointLightColor[i]*atten;
170
+ }
171
+
172
+ vec3 R=reflect(-V,N);
173
+ float NoV=clamp(dot(N,V),0.001,1.0);
174
+ vec3 F0=mix(vec3(0.04),base.rgb,metallic);
175
+ vec3 F=F_SchlickRoughness(F0,roughness,NoV);
176
+ vec2 brdf=envBRDF(roughness,NoV);
177
+
178
+ vec3 specularIBL;
179
+ vec3 envDiffuse;
180
+ if(uHasEnvironmentMap==1){
181
+ specularIBL=texture(uEnvironmentMap,equirectangularUV(R)).rgb*(F*brdf.x+brdf.y);
182
+ envDiffuse=texture(uEnvironmentMap,equirectangularUV(N)).rgb;
183
+ }else{
184
+ specularIBL=getStudioRadiance(R,roughness)*(F*brdf.x+brdf.y);
185
+ envDiffuse=mix(vec3(0.10,0.10,0.12),vec3(0.52,0.54,0.58),N.y*0.5+0.5);
186
+ }
187
+
188
+ vec3 kD=(vec3(1.0)-F)*(1.0-metallic);
189
+ vec3 diffuseIBL=kD*base.rgb*(uAmbientColor+envDiffuse*0.5)*occ;
190
+ vec3 color=directLight+(diffuseIBL+specularIBL)*uEnvIntensity+vec3(uEmissive*0.35,uEmissive*0.5,uEmissive*0.7);
191
+ if(uClearcoat.x>0.0){
192
+ vec3 ccF=F_SchlickRoughness(vec3(0.04),uClearcoat.y,NoV)*uClearcoat.x;
193
+ color=color*(vec3(1.0)-ccF)+getStudioRadiance(R,uClearcoat.y)*ccF*uEnvIntensity;
194
+ }
195
+ color=applyToneMapping(color,uToneMapping);
196
+ float outAlpha=base.a;
197
+ if(uXrDepthEnabled==1){
198
+ vec2 normViewUV=gl_FragCoord.xy/max(uViewportSize,vec2(1.0));
199
+ vec2 depthUV=(uXrDepthUVTransform*vec4(normViewUV,0.0,1.0)).xy;
200
+ vec4 depthSample=texture(uXrDepthTex,depthUV);
201
+ float realDepth=(uXrDepthFormat==1?depthSample.r:(depthSample.r+depthSample.a*256.0))*uXrRawValueToMeters;
202
+ float virtDepth=length(uCameraPos-vWorldPos);
203
+ if(realDepth>0.05&&virtDepth>realDepth){
204
+ float occAlpha=1.0-smoothstep(0.0,0.025,virtDepth-realDepth);
205
+ outAlpha*=occAlpha;
206
+ if(outAlpha<0.01)discard;
207
+ }
208
+ }
209
+ fragColor=vec4(color,outAlpha);
210
+ }`,xt=`#version 300 es
211
+ layout(location=0) in vec3 aPosition;
212
+ uniform mat4 uMVP;
213
+ void main(){gl_Position=uMVP*vec4(aPosition,1.0);}`,Tt=`#version 300 es
214
+ precision highp float;
215
+ uniform vec4 uColorId;
216
+ out vec4 fragColor;
217
+ void main(){fragColor=uColorId;}`;function $e(n,e,t){let i=n.createShader(e);if(n.shaderSource(i,t),n.compileShader(i),!n.getShaderParameter(i,35713)){let r=n.getShaderInfoLog(i);throw n.deleteShader(i),new Error(`Shader compile error: ${r}`)}return i}function De(n,e,t){let i=$e(n,35633,e),r=$e(n,35632,t),s=n.createProgram();if(n.attachShader(s,i),n.attachShader(s,r),n.linkProgram(s),!n.getProgramParameter(s,35714)){let u=n.getProgramInfoLog(s);throw n.deleteProgram(s),new Error(`Program link error: ${u}`)}return s}function Ee(n,e,t){let i={};for(let r of t)i[r]=n.getUniformLocation(e,r);return i}var je=["uMVP","uModel","uNormalMatrix","uUvTransform","uBaseColor","uMetallic","uRoughness","uClearcoat","uEmissive","uCameraPos","uBaseColorTexture","uHasTexture","uMetallicRoughnessTexture","uHasMetallicRoughnessTexture","uNormalTexture","uHasNormalTexture","uNormalScale","uOcclusionTexture","uHasOcclusionTexture","uOcclusionStrength","uToneMapping","uEnvironmentMap","uHasEnvironmentMap","uAmbientColor","uNumDirLights","uDirLightDir","uDirLightColor","uNumPointLights","uPointLightPos","uPointLightColor","uEnvIntensity","uXrDepthTex","uXrDepthEnabled","uXrDepthFormat","uXrRawValueToMeters","uXrDepthUVTransform","uViewportSize"];function Mt(n){if(typeof n!="string")return null;let e=n.trim();if(!e||/[\x00-\x1f\x7f]/.test(e))return null;let t=e.toLowerCase();return t.startsWith("data:")?/^data:image\/(png|jpeg|jpg|webp|ktx2|avif)(;|,)/i.test(e)?e:null:t.startsWith("https://")||t.startsWith("blob:")?e:t.startsWith("//")||/^[a-z][a-z0-9+.-]*:/i.test(e)||/(^|[\\/])\.\.([\\/]|$)/.test(e)?null:e}function Ae(n,e,t,i,r,s,u){if(i===void 0||!e.accessors?.[i])return null;let l=e.accessors[i],o=e.bufferViews[l.bufferView],c=(o.byteOffset||0)+(l.byteOffset||0),a=o.byteStride&&o.byteStride>s*4?o.byteStride>>2:s,f;if(a===s)f=new Float32Array(t,c,l.count*s);else{f=new Float32Array(l.count*s);let b=new Float32Array(t,o.byteOffset||0,Math.floor(o.byteLength/4)),h=(l.byteOffset||0)>>2;for(let T=0;T<l.count;T++){let y=h+T*a;for(let R=0;R<s;R++)f[T*s+R]=b[y+R]}}let m=n.createBuffer();return u.push(m),n.bindBuffer(34962,m),n.bufferData(34962,f,35044),n.enableVertexAttribArray(r),n.vertexAttribPointer(r,s,5126,!1,0,0),f}var kt=Object.freeze({maxMeshes:1e3,maxTextures:64,maxVertices:1e6,maxIndices:3e6}),Je=Object.freeze({maxMeshes:1/0,maxTextures:1/0,maxVertices:1/0,maxIndices:1/0});function qe(n,e,t=Je,i){if(!e||!e.gltf)throw new Error("Invalid GLBData passed to buildGpuScene: missing gltf object.");let{gltf:r,bin:s}=e,u=[],l=be(r),o=[];if(Array.isArray(r.nodes))for(let v=0;v<r.nodes.length;v++){let p=r.nodes[v];p.mesh!==void 0&&r.meshes&&r.meshes[p.mesh]&&o.push({node:p,nodeIdx:v,meshIdx:p.mesh})}let c=o.length>0?o:(r.meshes||[]).map((v,p)=>({node:v,nodeIdx:-1,meshIdx:p})),a=[];if(Array.isArray(e.lights)&&e.lights.length>0)a.push(...e.lights);else if(r.extensions?.KHR_lights_punctual?.lights){let v=r.extensions.KHR_lights_punctual.lights;for(let p of v){let E=p.type==="directional"?"directional":p.type==="point"?"point":"ambient";a.push({type:E,color:p.color||[1,1,1],intensity:p.intensity!==void 0?p.intensity:1})}}if(a.length===0&&(a.push({type:"ambient",color:[1,1,1],intensity:.35}),a.push({type:"directional",color:[1,1,1],intensity:.85,direction:[.5,1,.8]})),c.length>t.maxMeshes)throw new Error(`SecurityError: GLB scene exceeds host mesh limit (${t.maxMeshes}). Found: ${c.length}`);let f=[];if(r.textures&&r.images){if(r.textures.length>t.maxTextures)throw new Error(`SecurityError: GLB scene exceeds host texture limit (${t.maxTextures}). Found: ${r.textures.length}`);for(let v=0;v<r.textures.length;v++){let p=r.textures[v],E=r.images[p.source];if(E){let L=n.createTexture();if(n.bindTexture(3553,L),n.texImage2D(3553,0,6408,1,1,0,6408,5121,new Uint8Array([255,255,255,255])),n.texParameteri(3553,10242,10497),n.texParameteri(3553,10243,10497),n.texParameteri(3553,10241,9729),n.texParameteri(3553,10240,9729),E.bufferView!==void 0){let g=r.bufferViews[E.bufferView],S=s.slice(g.byteOffset||0,(g.byteOffset||0)+g.byteLength),P=new Blob([S],{type:E.mimeType||"image/png"});typeof createImageBitmap=="function"&&createImageBitmap(P).then(B=>{n.bindTexture(3553,L),n.texImage2D(3553,0,6408,6408,5121,B),n.generateMipmap(3553),i?.()}).catch(()=>{})}else if(E.uri){let g=Mt(E.uri);if(g){let S=new Image;S.crossOrigin="anonymous",S.referrerPolicy="no-referrer",S.onload=()=>{n.bindTexture(3553,L),n.texImage2D(3553,0,6408,6408,5121,S),n.generateMipmap(3553),i?.()},S.src=g}else console.warn("[Three-Live Security] Blocked unsafe glTF image URI:",E.uri)}f.push(L)}else f.push(null)}}let m=[1/0,1/0,1/0],b=[-1/0,-1/0,-1/0],h=0,T=0;for(let v=0;v<c.length;v++){let p=c[v],E=r.meshes[p.meshIdx],L=p.nodeIdx>=0?l[p.nodeIdx]:$(),g=new Float32Array(9);ne(g,L);let S={name:p.node.name||E.name||`Mesh_${p.meshIdx}`,nodeIndex:p.nodeIdx,transform:L,normalMatrix:g,primitives:[],extras:p.node.extras||E.extras};for(let P of E.primitives||[]){if(P.extensions?.KHR_draco_mesh_compression){let k=he("draco");k&&k.decodePrimitive(r,P,s)}let B=[],X=n.createVertexArray();n.bindVertexArray(X);let W=r.accessors[P.attributes.POSITION],G=Number(W?.count??0);if(!Number.isFinite(G)||G<0||h+G>t.maxVertices)throw new Error(`SecurityError: GLB scene exceeds host vertex limit (${t.maxVertices}).`);if(h+=G,W?.min&&W?.max)for(let k=0;k<3;k++){let J=L[12+k],ue=L[12+k];for(let ie=0;ie<3;ie++){let fe=L[ie*4+k]*W.min[ie],de=L[ie*4+k]*W.max[ie];J+=fe<de?fe:de,ue+=fe>de?fe:de}J<m[k]&&(m[k]=J),ue>b[k]&&(b[k]=ue)}let j=Ae(n,r,s,P.attributes.POSITION,0,3,B);Ae(n,r,s,P.attributes.NORMAL,1,3,B),Ae(n,r,s,P.attributes.TEXCOORD_0,2,2,B);let V=0,q=5123,N=null;if(P.indices!==void 0){let k=r.accessors[P.indices],ue=(r.bufferViews[k.bufferView].byteOffset||0)+(k.byteOffset||0);if(V=Number(k.count??0),!Number.isFinite(V)||V<0||T+V>t.maxIndices)throw new Error(`SecurityError: GLB scene exceeds host index limit (${t.maxIndices}).`);T+=V,q=k.componentType===5125?5125||5125:5123||5123;let ie=n.createBuffer();B.push(ie),n.bindBuffer(34963,ie),k.componentType===5125?(N=new Uint32Array(s,ue,k.count),n.bufferData(34963,N,35044)):(N=new Uint16Array(s,ue,k.count),n.bufferData(34963,N,35044))}else V=W.count;let _={};for(let k of z)if(k.onBuildPrimitiveVAO){let J=k.onBuildPrimitiveVAO(n,X,P,r,s);J&&(_[k.name]=J)}n.bindVertexArray(null);let H=r.materials&&P.material!==void 0?r.materials[P.material]:null,F=Ze,C=Qe,O=!1;for(let k of z)if(k.onResolveShader){let J=k.onResolveShader(P,H,F,C);J&&(F=J.vs,C=J.fs,O=!0)}let U=O?De(n,F,C):null,ee=U?Ee(n,U,je):null,K=H?.pbrMetallicRoughness,Y=K?.baseColorFactor||[.8,.8,.8,1],re=K?.metallicFactor??.1,se=K?.roughnessFactor??.5,te=H?.extensions?.KHR_materials_clearcoat,Z=te?te.clearcoatFactor??1:0,ae=Math.max(.04,te?.clearcoatRoughnessFactor??.04),oe=K?.baseColorTexture!==void 0&&f[K.baseColorTexture.index]?f[K.baseColorTexture.index]:null,le=K?.metallicRoughnessTexture!==void 0&&f[K.metallicRoughnessTexture.index]?f[K.metallicRoughnessTexture.index]:null,at=H?.normalTexture!==void 0&&f[H.normalTexture.index]?f[H.normalTexture.index]:null,ot=H?.normalTexture?.scale??1,ct=H?.occlusionTexture!==void 0&&f[H.occlusionTexture.index]?f[H.occlusionTexture.index]:null,ut=H?.occlusionTexture?.strength??1,lt=!!(H?.extensions?.KHR_materials_transmission||_.materials?.isTransmissive);S.primitives.push({vao:X,indexCount:V,indexType:q,baseColor:Y,metallic:re,roughness:se,clearcoat:Z,clearcoatRoughness:ae,positions:j,indices:N,texture:oe,metallicRoughnessTexture:le,normalTexture:at,occlusionTexture:ct,normalScale:ot,occlusionStrength:ut,buffers:B,materialIndex:P.material,pluginData:_,customProgram:U,customUniforms:ee,isTransmissive:lt})}u.push(S)}isFinite(m[0])||(m=[-1,-1,-1]),isFinite(b[0])||(b=[1,1,1]);let y=[(m[0]+b[0])/2,(m[1]+b[1])/2,(m[2]+b[2])/2],R=b[0]-m[0],w=b[1]-m[1],M=b[2]-m[2],A=Math.max(Math.hypot(R,w,M)/2,.5),x=[m[0],m[1],m[2]],D=[b[0],b[1],b[2]],d=e.animations;if(!d){for(let v of z)if(v.onParseGLB?.(e),e.animations){d=e.animations;break}}return d||(d=[]),{meshes:u,bounds:{center:y,radius:A,min:x,max:D},lights:a,animations:d,worldMatrices:l}}var ge=class{constructor(e,t,i){this.meshes=[];this.backdropMeshes=[];this.bounds={center:[0,0,0],radius:1,min:[-1,-1,-1],max:[1,1,1]};this.lights=[];this.modelRootMatrix=$();this.clearColor=[0,0,0,0];this.envIntensity=1;this.shadowIntensity=0;this.shadowSoftness=.5;this.toneMapping="neutral";this.environmentTexture=null;this.animations=[];this.currentClip=null;this.animationTime=0;this.isPlayingAnimation=!1;this.autoplay=!1;this.animationName="";this.gltf=null;this.worldMatrices=[];this.initialNodeTransforms=[];this.projMatrix=$();this.viewMatrix=$();this.modelMatrix=$();this.mvpMatrix=$();this.normalMatrix=new Float32Array(9);this.initialTheta=.6;this.initialPhi=.35;this.initialDistance=null;this.customDistance=!1;this.distanceMode="auto";this.initialCustomTarget=null;this.customTarget=null;this.fov=Math.PI/4;this.minTheta=-1/0;this.maxTheta=1/0;this.minPhi=-Math.PI*.48;this.maxPhi=Math.PI*.48;this.minDistanceLimit=null;this.maxDistanceLimit=null;this.activePointers=new Map;this.isPanning=!1;this.targetTheta=.6;this.currTheta=.6;this.targetPhi=.35;this.currPhi=.35;this.targetDistance=3;this.currDistance=3;this.autoRotate=!1;this.autoRotateSpeed=Math.PI/6;this.autoRotateDelay=3e3;this.lastInteractionTime=-1/0;this.turntableRotation=0;this.isPointerDown=!1;this.interactive=!0;this.skyboxTexture=null;this.lastPointerX=0;this.lastPointerY=0;this.totalDragDist=0;this.selectedMeshName="";this.pickFbo=null;this.pickTexture=null;this.pickDepth=null;this.pickFboWidth=0;this.pickFboHeight=0;this.animFrameId=null;this.isVisible=!0;this.lastTime=0;this.lastReportedTheta=-999;this.lastReportedPhi=-999;this.lastReportedZoom=-999;this.boundPointerDown=null;this.boundPointerMove=null;this.boundPointerUp=null;this.boundWheel=null;this.boundKeyDown=null;this.boundContextMenu=null;this.boundSetCamera=null;this.boundResetCamera=null;this.xrDepthState={enabled:!1,texture:null,uvTransform:$(),rawValueToMeters:.001,format:0};this.container=e;let r,s;if(t&&typeof t.getContext=="function"?(r=t,s=i):(s=t,r=s?.canvas),!r){let o=e.querySelector("canvas");o||(o=document.createElement("canvas"),o.style.width="100%",o.style.height="100%",o.style.display="block",o.style.touchAction="none",e.prepend(o)),r=o}this.canvas=r,this.opts=s||{},this.opts.clearColor&&(this.clearColor=this.opts.clearColor);let u=typeof window<"u"&&typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches;this.opts.autoRotate!==void 0?this.autoRotate=this.opts.autoRotate&&!u:u&&(this.autoRotate=!1),this.opts.autoRotateSpeed!==void 0&&(this.autoRotateSpeed=this.opts.autoRotateSpeed),this.opts.autoRotateDelay!==void 0&&(this.autoRotateDelay=Math.max(0,Number(this.opts.autoRotateDelay)||0)),this.opts.exposure!==void 0&&(this.envIntensity=Math.max(0,Number(this.opts.exposure))),this.opts.camera&&this.setInitialCamera(this.opts.camera.theta,this.opts.camera.phi,this.opts.camera.distance,this.opts.camera.zoom),this.opts.shadowIntensity!==void 0&&(this.shadowIntensity=Math.max(0,Math.min(1,Number(this.opts.shadowIntensity)||0))),this.opts.shadowSoftness!==void 0&&(this.shadowSoftness=Math.max(0,Math.min(1,Number(this.opts.shadowSoftness)||0))),this.opts.toneMapping!==void 0&&(this.toneMapping=this.opts.toneMapping),this.opts.autoplay!==void 0&&(this.autoplay=this.opts.autoplay),this.opts.animationName!==void 0&&(this.animationName=this.opts.animationName),this.opts.fieldOfView!==void 0&&(this.fov=this.opts.fieldOfView*Math.PI/180),this.opts.distanceMode!==void 0&&(this.distanceMode=this.opts.distanceMode),this.opts.cameraTarget!==void 0&&(this.setTarget(this.opts.cameraTarget[0],this.opts.cameraTarget[1],this.opts.cameraTarget[2]),this.initialCustomTarget=[...this.opts.cameraTarget]),(this.opts.minCameraOrbit||this.opts.maxCameraOrbit)&&this.setOrbitLimits({minTheta:this.opts.minCameraOrbit?.theta,maxTheta:this.opts.maxCameraOrbit?.theta,minPhi:this.opts.minCameraOrbit?.phi,maxPhi:this.opts.maxCameraOrbit?.phi,minDistance:this.opts.minCameraOrbit?.distance,maxDistance:this.opts.maxCameraOrbit?.distance});let l=r.getContext("webgl2",{antialias:!0,alpha:!0,xrCompatible:!0});if(!l)throw new Error("WebGL2 not supported");this.gl=l,this.renderProg=De(l,Ze,Qe),this.pickProg=De(l,xt,Tt),this.uRender=Ee(l,this.renderProg,je),this.uPick=Ee(l,this.pickProg,["uMVP","uColorId"]),this.setupPickingFbo(),this.setupEvents(),this.opts.environmentImage&&this.setEnvironmentImage(this.opts.environmentImage).catch(()=>{}),typeof requestAnimationFrame<"u"&&this.opts.autoStart!==!1&&this.start()}static registerDecoder(e,t){yt(e,t)}static getDecoder(e){return he(e)}setupPickingFbo(){let e=this.gl;if(typeof e.createFramebuffer!="function")return;this.pickFbo=e.createFramebuffer(),this.pickTexture=e.createTexture(),this.pickDepth=e.createRenderbuffer();let t=Math.max(1,this.canvas.width),i=Math.max(1,this.canvas.height);this.pickFboWidth=t,this.pickFboHeight=i,e.bindTexture(3553,this.pickTexture),e.texImage2D(3553,0,6408,t,i,0,6408,5121,null),e.texParameteri(3553,10241,9728),e.texParameteri(3553,10240,9728),e.bindRenderbuffer(36161,this.pickDepth),e.renderbufferStorage(36161,33189,t,i),e.bindFramebuffer(36160,this.pickFbo),e.framebufferTexture2D(36160,36064,3553,this.pickTexture,0),e.framebufferRenderbuffer(36160,36096,36161,this.pickDepth),e.bindFramebuffer(36160,null)}resizePickingFbo(e,t){if(!this.pickFbo)return;let i=this.gl,r=Math.max(1,e),s=Math.max(1,t);this.pickFboWidth=r,this.pickFboHeight=s,i.bindTexture(3553,this.pickTexture),i.texImage2D(3553,0,6408,r,s,0,6408,5121,null),i.bindRenderbuffer(36161,this.pickDepth),i.renderbufferStorage(36161,33189,r,s)}loadGLBData(e,t){let{meshes:i,bounds:r,lights:s,animations:u,worldMatrices:l}=qe(this.gl,e,t,()=>this.render());if(this.disposeMeshGpuResources(),this.meshes=i,this.bounds=r,this.turntableRotation=0,this.updateTurntableMatrix(),this.lights=s,this.animations=u||[],this.worldMatrices=l||[],this.gltf=e.gltf,this.initialNodeTransforms=[],Array.isArray(e.gltf?.nodes))for(let c of e.gltf.nodes)this.initialNodeTransforms.push({t:c.translation?[c.translation[0],c.translation[1],c.translation[2]]:[0,0,0],r:c.rotation?[c.rotation[0],c.rotation[1],c.rotation[2],c.rotation[3]]:[0,0,0,1],s:c.scale?[c.scale[0],c.scale[1],c.scale[2]]:[1,1,1]});this.autoplay&&this.animations.length>0&&this.playAnimation(this.animationName||void 0);for(let c of z)c.onLoadModel?.(this,this.gltf);this.customDistance||(this.initialDistance=this.distanceMode==="absolute"?3:r.radius*2.5,this.targetDistance=this.initialDistance,this.currDistance=this.initialDistance);let o=e.exposure??e.environmentIntensity??e.gltf?.extras?.exposure??e.gltf?.extras?.environmentIntensity??e.gltf?.asset?.extras?.exposure??e.gltf?.asset?.extras?.environmentIntensity;o!==void 0&&(this.envIntensity=Math.max(0,Number(o))),this.container&&typeof this.container.hasAttribute=="function"&&this.container.hasAttribute("poster")&&this.container.removeAttribute("poster"),this.resize(),this.update(0),this.render(),this.animFrameId===null&&typeof requestAnimationFrame<"u"&&this.opts.autoStart!==!1&&this.start()}loadGLB(e){this.loadGLBData(Ye(e))}loadModel(e){this.loadGLBData(me(e))}setBackdropGLB(e,t){if(this.disposeMeshListGpuResources(this.backdropMeshes),this.backdropMeshes=[],!e){this.update(0),this.render();return}let i=me(e),{meshes:r}=qe(this.gl,i,Je,()=>this.render());if(t)for(let s of r)s.transform[12]+=t[0],s.transform[13]+=t[1],s.transform[14]+=t[2],ne(s.normalMatrix,s.transform);this.backdropMeshes=r,this.update(0),this.render()}setClearColor(e,t,i,r=1){this.clearColor=[e,t,i,r]}updateMeshTransforms(e){for(let t=0;t<this.meshes.length;t++){let i=this.meshes[t],r;e instanceof Map?r=e.get(i.name)??e.get(t):Array.isArray(e)?r=e[t]:e&&typeof e=="object"&&(Object.prototype.hasOwnProperty.call(e,i.name)?r=e[i.name]:Object.prototype.hasOwnProperty.call(e,t)&&(r=e[t])),r&&r.length===16&&(i.transform.set(r),ne(i.normalMatrix,i.transform))}}bindLights(e=this.uRender){let t=this.gl,i=[.28,.28,.28],r=[],s=[],u=[],l=[];for(let o of this.lights){let c=o.color||[1,1,1],a=o.intensity!==void 0?o.intensity:1;if(o.type==="ambient")i=[c[0]*a,c[1]*a,c[2]*a];else if(o.type==="directional"&&r.length<6){let f=o.direction||[.5,1,.8];r.push(f[0],f[1],f[2]),s.push(c[0]*a,c[1]*a,c[2]*a)}else if(o.type==="point"&&u.length<6){let f=o.position||[0,0,0];u.push(f[0],f[1],f[2]),l.push(c[0]*a,c[1]*a,c[2]*a)}}r.length===0&&(r.push(.5,1,.8),s.push(1,1,1)),t.uniform3fv(e.uAmbientColor,i),t.uniform1i(e.uNumDirLights,r.length/3),r.length>0&&(t.uniform3fv(e.uDirLightDir,r),t.uniform3fv(e.uDirLightColor,s)),t.uniform1i(e.uNumPointLights,u.length/3),u.length>0&&(t.uniform3fv(e.uPointLightPos,u),t.uniform3fv(e.uPointLightColor,l)),t.uniform1f(e.uEnvIntensity,this.envIntensity)}setExposure(e){this.envIntensity=Math.max(0,Number(e))}getExposure(){return this.envIntensity}setShadow(e,t){this.shadowIntensity=Math.max(0,Math.min(1,Number(e)||0)),t!==void 0&&(this.shadowSoftness=Math.max(0,Math.min(1,Number(t)||0)))}getShadowIntensity(){return this.shadowIntensity}getShadowSoftness(){return this.shadowSoftness}setToneMapping(e){this.toneMapping=e}getToneMapping(){return this.toneMapping}async setEnvironmentImage(e){for(let t of z)if(t.setEnvironmentImage){await t.setEnvironmentImage(this,e);return}}async setSkyboxImage(e){for(let t of z)if(t.setSkyboxImage){await t.setSkyboxImage(this,e);return}}setInteractive(e){this.interactive=e}isInteractive(){return this.interactive}getCameraOrbit(){let e=this.currTheta,t=this.currPhi,i=this.currDistance;return{theta:e,phi:t,radius:i,toString(){return`${e.toFixed(4)}rad ${t.toFixed(4)}rad ${i.toFixed(4)}m`}}}getCameraTarget(){let e=this.customTarget||this.bounds.center;return{x:e[0],y:e[1],z:e[2],toString(){return`${e[0].toFixed(4)}m ${e[1].toFixed(4)}m ${e[2].toFixed(4)}m`}}}jumpCameraToGoal(){this.currTheta=this.targetTheta,this.currPhi=this.targetPhi,this.currDistance=this.targetDistance,this.update(0),this.render()}getModelMaterials(){let e=this.gltf?.materials?.length?this.gltf.materials:[{name:"DefaultMaterial",pbrMetallicRoughness:{}}];return e.map((t,i)=>{let r=this.meshes.flatMap(a=>a.primitives.filter(f=>f.materialIndex===i||e.length===1&&f.materialIndex===void 0)),s=r[0],u=s?[...s.baseColor]:t.pbrMetallicRoughness?.baseColorFactor||[.8,.8,.8,1],l=s?s.metallic:t.pbrMetallicRoughness?.metallicFactor??.1,o=s?s.roughness:t.pbrMetallicRoughness?.roughnessFactor??.5,c={baseColorFactor:u,metallicFactor:l,roughnessFactor:o,setBaseColorFactor:a=>{let f=[a[0],a[1],a[2],a[3]??1];c.baseColorFactor=f,t.pbrMetallicRoughness&&(t.pbrMetallicRoughness.baseColorFactor=f);for(let m of r)m.baseColor=f;this.render()},setMetallicFactor:a=>{c.metallicFactor=a,t.pbrMetallicRoughness&&(t.pbrMetallicRoughness.metallicFactor=a);for(let f of r)f.metallic=a;this.render()},setRoughnessFactor:a=>{c.roughnessFactor=a,t.pbrMetallicRoughness&&(t.pbrMetallicRoughness.roughnessFactor=a);for(let f of r)f.roughness=a;this.render()}};return{name:t.name||`Material_${i}`,pbrMetallicRoughness:c}})}playAnimation(e){if(this.animations.length!==0){if(e){let t=this.animations.find(i=>i.name===e);t&&(this.currentClip=t)}else this.currentClip||(this.currentClip=this.animations[0]);this.isPlayingAnimation=!0}}pauseAnimation(){this.isPlayingAnimation=!1}getAvailableAnimations(){return this.animations.map(e=>e.name)}setAutoplay(e){this.autoplay=e,e?this.playAnimation(this.animationName||void 0):this.pauseAnimation()}setAnimationName(e){this.animationName=e,(this.isPlayingAnimation||this.autoplay)&&this.playAnimation(e)}evaluateAnimation(e){for(let t of z)if(t.evaluateAnimation){t.evaluateAnimation(this,e);return}}setTarget(e,t,i){this.customTarget=[e,t,i],this.gl&&(this.meshes.length>0||this.backdropMeshes.length>0)&&(this.update(0),this.render())}getTarget(){return this.customTarget?[...this.customTarget]:null}setFieldOfView(e){let t=Math.max(10,Math.min(90,e));this.fov=t*Math.PI/180}getFieldOfView(){return this.fov*180/Math.PI}setDistanceMode(e){if(this.distanceMode=e,!this.customDistance){let t=this.clampDistance(this.distanceMode==="absolute"?3:this.bounds.radius*2.5);this.initialDistance=t,this.targetDistance=t,this.currDistance=t,this.gl&&(this.meshes.length>0||this.backdropMeshes.length>0)&&(this.update(0),this.render())}}getDistanceMode(){return this.distanceMode}setOrbitLimits(e){e.minTheta!==void 0&&(this.minTheta=e.minTheta*Math.PI/180),e.maxTheta!==void 0&&(this.maxTheta=e.maxTheta*Math.PI/180),e.minPhi!==void 0&&(this.minPhi=Math.max(-Math.PI*.48,e.minPhi*Math.PI/180)),e.maxPhi!==void 0&&(this.maxPhi=Math.min(Math.PI*.48,e.maxPhi*Math.PI/180)),e.minDistance!==void 0&&(this.minDistanceLimit=e.minDistance),e.maxDistance!==void 0&&(this.maxDistanceLimit=e.maxDistance),this.targetTheta=this.clampTheta(this.targetTheta),this.targetPhi=this.clampPhi(this.targetPhi),this.targetDistance=this.clampDistance(this.targetDistance)}getOrbitLimits(){return{minTheta:isFinite(this.minTheta)?this.minTheta*180/Math.PI:void 0,maxTheta:isFinite(this.maxTheta)?this.maxTheta*180/Math.PI:void 0,minPhi:this.minPhi*180/Math.PI,maxPhi:this.maxPhi*180/Math.PI,minDistance:this.minDistanceLimit!==null?this.minDistanceLimit:void 0,maxDistance:this.maxDistanceLimit!==null?this.maxDistanceLimit:void 0}}clampTheta(e){return Math.max(this.minTheta,Math.min(this.maxTheta,e))}clampPhi(e){return Math.max(this.minPhi,Math.min(this.maxPhi,e))}clampDistance(e){let t=this.minDistanceLimit!==null?this.minDistanceLimit:this.bounds?this.bounds.radius*.5:.1,i=this.maxDistanceLimit!==null?this.maxDistanceLimit:this.bounds?this.bounds.radius*8:100;return Math.max(t,Math.min(i,e))}setCamera(e,t,i,r){e!==void 0&&(this.targetTheta=this.clampTheta(e*Math.PI/180)),t!==void 0&&(this.targetPhi=this.clampPhi(t*Math.PI/180)),i!==void 0&&i>0&&(this.targetDistance=this.clampDistance(i)),r!==void 0&&r>0&&(this.targetDistance=this.clampDistance(this.bounds.radius*2.5/r))}setInitialCamera(e,t,i,r){if(e!==void 0&&(this.initialTheta=this.clampTheta(e*Math.PI/180),this.targetTheta=this.initialTheta,this.currTheta=this.initialTheta),t!==void 0&&(this.initialPhi=this.clampPhi(t*Math.PI/180),this.targetPhi=this.initialPhi,this.currPhi=this.initialPhi),i!==void 0&&i>0){let s=this.clampDistance(i);this.initialDistance=s,this.customDistance=!0,this.targetDistance=s,this.currDistance=s}else if(r!==void 0&&r>0){let s=this.clampDistance(this.bounds.radius*2.5/r);this.initialDistance=s,this.customDistance=!0,this.targetDistance=s,this.currDistance=s}else{this.customDistance=!1;let s=this.clampDistance(this.distanceMode==="absolute"?3:this.bounds.radius*2.5);this.initialDistance=s,this.targetDistance=s,this.currDistance=s}this.gl&&(this.meshes.length>0||this.backdropMeshes.length>0)&&(this.update(0),this.render())}resetCamera(){this.targetTheta=this.clampTheta(this.initialTheta),this.targetPhi=this.clampPhi(this.initialPhi),this.initialDistance!==null?this.targetDistance=this.clampDistance(this.initialDistance):this.targetDistance=this.clampDistance(this.bounds.radius*2.5),this.initialCustomTarget?this.customTarget=[...this.initialCustomTarget]:this.customTarget=null,this.turntableRotation=0,this.updateTurntableMatrix()}projectPointToScreen(e,t){let i=$();Q(i,this.projMatrix,this.viewMatrix);let[r,s,u]=e,l=t?t[0]:0,o=t?t[1]:0,c=t?t[2]:0,a=this.modelRootMatrix;a&&(r=a[0]*e[0]+a[4]*e[1]+a[8]*e[2]+a[12],s=a[1]*e[0]+a[5]*e[1]+a[9]*e[2]+a[13],u=a[2]*e[0]+a[6]*e[1]+a[10]*e[2]+a[14],t&&(l=a[0]*t[0]+a[4]*t[1]+a[8]*t[2],o=a[1]*t[0]+a[5]*t[1]+a[9]*t[2],c=a[2]*t[0]+a[6]*t[1]+a[10]*t[2]));let f=i[0]*r+i[4]*s+i[8]*u+i[12],m=i[1]*r+i[5]*s+i[9]*u+i[13],b=i[2]*r+i[6]*s+i[10]*u+i[14],h=i[3]*r+i[7]*s+i[11]*u+i[15];if(h<=1e-4)return{x:0,y:0,z:1,visible:!1};let T=f/h,y=m/h,R=b/h,w=this.canvas.getBoundingClientRect(),M=w.width||this.canvas.clientWidth||this.canvas.width||300,A=w.height||this.canvas.clientHeight||this.canvas.height||150,x=(T*.5+.5)*M,D=(-y*.5+.5)*A,d=T>=-1.1&&T<=1.1&&y>=-1.1&&y<=1.1&&R>=-1&&R<=1;if(d&&t){let v=this.customTarget||this.bounds.center,p=v[0]+this.currDistance*Math.cos(this.currPhi)*Math.sin(this.currTheta),E=v[1]+this.currDistance*Math.sin(this.currPhi),L=v[2]+this.currDistance*Math.cos(this.currPhi)*Math.cos(this.currTheta),g=[r-p,s-E,u-L];l*g[0]+o*g[1]+c*g[2]>.05&&(d=!1)}return{x,y:D,z:R,visible:d}}setSelectedMesh(e){this.selectedMeshName=e||""}setupEvents(){let e=this.canvas;this.boundContextMenu=t=>{t.preventDefault()},e.addEventListener("contextmenu",this.boundContextMenu),this.boundPointerDown=t=>{this.interactive&&(this.isPointerDown=!0,this.lastInteractionTime=typeof performance<"u"?performance.now():Date.now(),this.lastPointerX=t.clientX,this.lastPointerY=t.clientY,this.totalDragDist=0,this.activePointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this.isPanning=t.button===2||t.shiftKey||this.activePointers.size===2,e.setPointerCapture(t.pointerId))},e.addEventListener("pointerdown",this.boundPointerDown),this.boundPointerMove=t=>{if(!this.isPointerDown||!this.interactive)return;this.lastInteractionTime=typeof performance<"u"?performance.now():Date.now();let i=this.activePointers.get(t.pointerId)||{x:this.lastPointerX,y:this.lastPointerY},r=t.clientX-i.x,s=t.clientY-i.y;if(this.activePointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this.lastPointerX=t.clientX,this.lastPointerY=t.clientY,this.totalDragDist+=Math.hypot(r,s),this.isPanning||t.button===2||t.shiftKey||this.activePointers.size===2){let u=[this.viewMatrix[0],this.viewMatrix[4],this.viewMatrix[8]],l=[this.viewMatrix[1],this.viewMatrix[5],this.viewMatrix[9]],o=this.customTarget?[...this.customTarget]:[...this.bounds.center],c=this.currDistance/Math.max(e.clientHeight||300,1)*1.5;o[0]+=(-r*u[0]+s*l[0])*c,o[1]+=(-r*u[1]+s*l[1])*c,o[2]+=(-r*u[2]+s*l[2])*c,this.customTarget=o}else this.targetTheta=this.clampTheta(this.targetTheta-r*.008),this.targetPhi=this.clampPhi(this.targetPhi+s*.008)},e.addEventListener("pointermove",this.boundPointerMove),this.boundPointerUp=t=>{this.lastInteractionTime=typeof performance<"u"?performance.now():Date.now(),this.activePointers.delete(t.pointerId),this.activePointers.size===0?(this.isPointerDown=!1,this.isPanning=!1):this.activePointers.size===1&&(this.isPanning=!1);try{e.releasePointerCapture(t.pointerId)}catch{}if(this.totalDragDist<5&&t.button===0){let i=e.getBoundingClientRect(),r=Math.floor((t.clientX-i.left)*(e.width/Math.max(i.width,1))),s=Math.floor((t.clientY-i.top)*(e.height/Math.max(i.height,1)));this.performMeshPick(r,s,!0)}},e.addEventListener("pointerup",this.boundPointerUp),this.boundWheel=t=>{if(!this.interactive)return;t.preventDefault(),this.lastInteractionTime=typeof performance<"u"?performance.now():Date.now();let i=Math.exp(t.deltaY*.001);this.targetDistance=this.clampDistance(this.targetDistance*i)},e.addEventListener("wheel",this.boundWheel,{passive:!1}),this.boundSetCamera=t=>{let i=t.detail||{};i.reset?this.resetCamera():this.setCamera(i.theta,i.phi,i.distance,i.zoom)},this.container.addEventListener("setCamera",this.boundSetCamera),this.boundResetCamera=()=>{this.resetCamera()},this.container.addEventListener("resetCamera",this.boundResetCamera),e.tabIndex!==void 0&&e.tabIndex<0&&(e.tabIndex=0),e.getAttribute?.("role")||e.setAttribute?.("role","region"),e.getAttribute?.("aria-label")||e.setAttribute?.("aria-label","Interactive 3D model viewport"),this.boundKeyDown=t=>{if(!this.interactive)return;let i=typeof performance<"u"?performance.now():Date.now();switch(t.key){case"ArrowLeft":this.lastInteractionTime=i,this.targetTheta=this.clampTheta(this.targetTheta-.1),t.preventDefault();break;case"ArrowRight":this.lastInteractionTime=i,this.targetTheta=this.clampTheta(this.targetTheta+.1),t.preventDefault();break;case"ArrowUp":this.lastInteractionTime=i,this.targetPhi=this.clampPhi(this.targetPhi+.08),t.preventDefault();break;case"ArrowDown":this.lastInteractionTime=i,this.targetPhi=this.clampPhi(this.targetPhi-.08),t.preventDefault();break;case"+":case"=":{this.lastInteractionTime=i,this.targetDistance=this.clampDistance(this.targetDistance*.9),t.preventDefault();break}case"-":case"_":{this.lastInteractionTime=i,this.targetDistance=this.clampDistance(this.targetDistance*1.1),t.preventDefault();break}case"Home":this.lastInteractionTime=i,this.resetCamera(),t.preventDefault();break}},e.addEventListener("keydown",this.boundKeyDown)}teardownEvents(){let e=this.canvas;this.boundContextMenu&&(e.removeEventListener("contextmenu",this.boundContextMenu),this.boundContextMenu=null),this.boundPointerDown&&(e.removeEventListener("pointerdown",this.boundPointerDown),this.boundPointerDown=null),this.boundPointerMove&&(e.removeEventListener("pointermove",this.boundPointerMove),this.boundPointerMove=null),this.boundPointerUp&&(e.removeEventListener("pointerup",this.boundPointerUp),this.boundPointerUp=null),this.boundWheel&&(e.removeEventListener("wheel",this.boundWheel),this.boundWheel=null),this.boundKeyDown&&(e.removeEventListener("keydown",this.boundKeyDown),this.boundKeyDown=null),this.boundSetCamera&&(this.container.removeEventListener("setCamera",this.boundSetCamera),this.boundSetCamera=null),this.boundResetCamera&&(this.container.removeEventListener("resetCamera",this.boundResetCamera),this.boundResetCamera=null)}raycastFromScreenPoint(e,t){let i=this.canvas,r=i.getBoundingClientRect(),s=i.width||300,u=i.height||300,l=r.width>0?Math.floor((e-r.left)*(s/r.width)):Math.floor(e),o=r.height>0?Math.floor((t-r.top)*(u/r.height)):Math.floor(t);return this.performMeshPick(l,o,!1)}performMeshPick(e,t,i=!0){if(this.meshes.length===0)return null;let r=this.gl,s=Math.max(1,this.canvas.width||300),u=Math.max(1,this.canvas.height||300),l=$();Q(l,this.projMatrix,this.viewMatrix);let o=[],c=Math.max(0,Math.min(s-1,e)),a=Math.max(0,Math.min(u-1,u-1-t));if(this.pickFbo&&r){(this.pickFboWidth!==s||this.pickFboHeight!==u)&&this.resizePickingFbo(s,u),r.bindFramebuffer(36160,this.pickFbo),r.viewport(0,0,s,u),r.enable(2929),r.clearColor(0,0,0,0),r.clear(16384|256),r.useProgram(this.pickProg);for(let d=0;d<this.meshes.length;d++){let v=this.meshes[d];if(v.visible===!1||v.isPluginMesh)continue;let p=d+1,E=(p&255)/255,L=(p>>8&255)/255,g=(p>>16&255)/255;r.uniform4f(this.uPick.uColorId,E,L,g,1),Q(this.modelMatrix,this.modelRootMatrix,v.transform),Q(this.mvpMatrix,l,this.modelMatrix),r.uniformMatrix4fv(this.uPick.uMVP,!1,this.mvpMatrix);for(let S of v.primitives)r.bindVertexArray(S.vao),r.drawElements(4,S.indexCount,S.indexType,0)}let x=new Uint8Array(4);r.readPixels(c,a,1,1,6408,5121,x),r.bindFramebuffer(36160,null);let D=x[0]+(x[1]<<8)+(x[2]<<16);D>0&&D<=this.meshes.length&&(o=[this.meshes[D-1]])}o.length===0&&(o=this.meshes.filter(x=>x.visible!==!1));let f=null,m=1/0,b=[0,0,0],h=[0,1,0],T=this.customTarget||this.bounds.center,y=T[0]+this.currDistance*Math.cos(this.currPhi)*Math.sin(this.currTheta),R=T[1]+this.currDistance*Math.sin(this.currPhi),w=T[2]+this.currDistance*Math.cos(this.currPhi)*Math.cos(this.currTheta);for(let x of o){Q(this.modelMatrix,this.modelRootMatrix,x.transform),Q(this.mvpMatrix,l,this.modelMatrix);let D=$();if(!ze(D,this.mvpMatrix))continue;let d=(c+.5)/s*2-1,v=(a+.5)/u*2-1,p=[0,0,0],E=[0,0,0];Re(p,d,v,-1,D),Re(E,d,v,1,D);let L=E[0]-p[0],g=E[1]-p[1],S=E[2]-p[2],P=Math.hypot(L,g,S)||1,B=L/P,X=g/P,W=S/P,G={distance:1/0,point:[0,0,0],normal:[0,1,0]};if((V=>{for(let q of x.primitives){if(!q.positions)continue;let N=q.positions,_=q.indices,H=Math.floor(_?_.length/3:N.length/9);for(let F=0;F<H;F++){let C=_?_[F*3]:F*3,O=_?_[F*3+1]:F*3+1,U=_?_[F*3+2]:F*3+2;We(p[0],p[1],p[2],B,X,W,N[C*3],N[C*3+1],N[C*3+2],N[O*3],N[O*3+1],N[O*3+2],N[U*3],N[U*3+1],N[U*3+2],G,V)}}})(1e-4),isFinite(G.distance)){let V=G.point[0],q=G.point[1],N=G.point[2],_=this.modelMatrix,H=_[0]*V+_[4]*q+_[8]*N+_[12],F=_[1]*V+_[5]*q+_[9]*N+_[13],C=_[2]*V+_[6]*q+_[10]*N+_[14],O=H-y,U=F-R,ee=C-w,K=Math.hypot(O,U,ee);if(K<m){ne(this.normalMatrix,this.modelMatrix);let Y=this.normalMatrix,re=G.normal[0],se=G.normal[1],te=G.normal[2],Z=Y[0]*re+Y[3]*se+Y[6]*te,ae=Y[1]*re+Y[4]*se+Y[7]*te,oe=Y[2]*re+Y[5]*se+Y[8]*te,le=Math.hypot(Z,ae,oe)||1;Z/=le,ae/=le,oe/=le,Z*O+ae*U+oe*ee>0&&(Z=-Z,ae=-ae,oe=-oe),f=x,m=Math.round(K*1e3)/1e3,b=[Math.round(H*1e3)/1e3,Math.round(F*1e3)/1e3,Math.round(C*1e3)/1e3],h=[Math.round(Z*1e3)/1e3,Math.round(ae*1e3)/1e3,Math.round(oe*1e3)/1e3]}}}if(!f)return null;let A={meshIndex:this.meshes.indexOf(f),meshName:f.name,nodeIndex:f.nodeIndex,distance:m,hitPoint:b,normal:h,screenX:e,screenY:t};if(i){for(let x of z)x.onMeshSelect?.(this,A);this.opts.onMeshClick&&this.opts.onMeshClick(A),typeof CustomEvent<"u"&&typeof this.container.dispatchEvent=="function"&&this.container.dispatchEvent(new CustomEvent("meshClick",{bubbles:!0,detail:A}))}return A}resize(){let e=Math.min((typeof window<"u"?window.devicePixelRatio:1)||1,2),t=this.canvas.getBoundingClientRect(),i=Math.max(1,Math.floor(t.width*e)),r=Math.max(1,Math.floor(t.height*e));(this.canvas.width!==i||this.canvas.height!==r)&&(this.canvas.width=i,this.canvas.height=r,this.resizePickingFbo(i,r))}start(){if(this.animFrameId!==null)return;this.lastTime=performance.now();let e=t=>{let i=Math.min((t-this.lastTime)/1e3,.1);this.lastTime=t,this.isVisible&&(this.resize(),this.update(i),this.render()),this.animFrameId=requestAnimationFrame(e)};this.animFrameId=requestAnimationFrame(e)}stop(){this.animFrameId!==null&&(cancelAnimationFrame(this.animFrameId),this.animFrameId=null)}setAutoRotate(e){this.autoRotate=e}getAutoRotate(){return this.autoRotate}setAutoRotateSpeed(e){this.autoRotateSpeed=e}getAutoRotateSpeed(){return this.autoRotateSpeed}setAutoRotateDelay(e){this.autoRotateDelay=Math.max(0,Number(e)||0)}getAutoRotateDelay(){return this.autoRotateDelay}resetTurntableRotation(e=0){this.turntableRotation=Number(e)||0,this.updateTurntableMatrix(),this.render()}updateTurntableMatrix(){let e=Math.cos(this.turntableRotation),t=Math.sin(this.turntableRotation),i=this.bounds.center[0],r=this.bounds.center[2],s=this.modelRootMatrix;s[0]=e,s[1]=0,s[2]=-t,s[3]=0,s[4]=0,s[5]=1,s[6]=0,s[7]=0,s[8]=t,s[9]=0,s[10]=e,s[11]=0,s[12]=i-(e*i+t*r),s[13]=0,s[14]=r-(-t*i+e*r),s[15]=1}setVisible(e){this.isVisible=e}update(e){for(let m of z)m.onUpdate?.(this,e);let t=typeof performance<"u"?performance.now():Date.now();if(!this.isPointerDown&&this.autoRotate&&t-this.lastInteractionTime>=this.autoRotateDelay){this.turntableRotation+=this.autoRotateSpeed*e,this.updateTurntableMatrix();for(let m of z)m.onCameraChange?.(this,this.container)}this.currTheta+=(this.targetTheta-this.currTheta)*.12,this.currPhi+=(this.targetPhi-this.currPhi)*.12,this.currDistance+=(this.targetDistance-this.currDistance)*.12;let i=(this.canvas.width||1)/(this.canvas.height||1),r=this.backdropMeshes.length>0?Math.max(this.bounds.radius*20,120):this.bounds.radius*20;Ge(this.projMatrix,this.fov,i,.1,r);let s=this.customTarget||this.bounds.center,u=s[0]+this.currDistance*Math.cos(this.currPhi)*Math.sin(this.currTheta),l=s[1]+this.currDistance*Math.sin(this.currPhi),o=s[2]+this.currDistance*Math.cos(this.currPhi)*Math.cos(this.currTheta);He(this.viewMatrix,[u,l,o],s,[0,1,0]),Q(this.mvpMatrix,this.projMatrix,this.viewMatrix),ne(this.normalMatrix,this.modelMatrix);let c=Math.round((this.currTheta*180/Math.PI%360+360)%360),a=Math.round(this.currPhi*180/Math.PI),f=Math.round(this.bounds.radius*2.5/this.currDistance*100)/100;if(Math.abs(c-this.lastReportedTheta)>=1||Math.abs(a-this.lastReportedPhi)>=1||Math.abs(f-this.lastReportedZoom)>=.02){this.lastReportedTheta=c,this.lastReportedPhi=a,this.lastReportedZoom=f;let m={theta:c,phi:a,zoom:f,distance:Math.round(this.currDistance*100)/100};this.opts.onCameraChange&&this.opts.onCameraChange(m),typeof CustomEvent<"u"&&typeof this.container.dispatchEvent=="function"&&this.container.dispatchEvent(new CustomEvent("cameraChange",{bubbles:!0,detail:m}))}}renderXRView(e,t,i,r){this.onBeforeRenderXRView&&this.onBeforeRenderXRView(e);let s=e?.transform?.inverse?.matrix||this.viewMatrix,u=e?.projectionMatrix||this.projMatrix,l=e?.transform?.position,o=l?[l.x,l.y,l.z]:[0,1.6,0];i&&t&&this.modelRootMatrix.set(t),this.render({viewMatrix:s,projMatrix:u,eyePos:o,viewport:r,eye:e?.eye||"none",clear:e?.eye!=="right"})}render(e){let t=this.gl,i=this.canvas.width,r=this.canvas.height;e?.viewport?(t.viewport(e.viewport[0],e.viewport[1],e.viewport[2],e.viewport[3]),i=e.viewport[2],r=e.viewport[3]):t.viewport(0,0,this.canvas.width,this.canvas.height),t.enable(2929),(!e||e.clear!==!1)&&(t.clearColor(this.clearColor[0],this.clearColor[1],this.clearColor[2],this.clearColor[3]),t.clear(16384|256));let s=$();Q(s,e?.projMatrix??this.projMatrix,e?.viewMatrix??this.viewMatrix);let u=this.toneMapping==="reinhard"?1:this.toneMapping==="none"?2:0,l=this.customTarget||this.bounds.center,o=e?e.eyePos[0]:l[0]+this.currDistance*Math.cos(this.currPhi)*Math.sin(this.currTheta),c=e?e.eyePos[1]:l[1]+this.currDistance*Math.sin(this.currPhi),a=e?e.eyePos[2]:l[2]+this.currDistance*Math.cos(this.currPhi)*Math.cos(this.currTheta);for(let y of z)y.onBeforeDrawScene?.(this,t,s,[o,c,a],u);if(this.meshes.length===0&&this.backdropMeshes.length===0)return;let f=e?.eye||"none",m=!1,b=this.backdropMeshes.length,h=b>0?[...this.backdropMeshes,...this.meshes]:this.meshes,T=y=>{for(let R=0;R<h.length;R++){let w=h[R];if(w.visible===!1)continue;let M=this.selectedMeshName!==""&&w.name===this.selectedMeshName;R<b?this.modelMatrix.set(w.transform):Q(this.modelMatrix,this.modelRootMatrix,w.transform),Q(this.mvpMatrix,s,this.modelMatrix),ne(w.normalMatrix,this.modelMatrix);let A=w.extras?.xr?.stereo||w.userData?.xr?.stereo,x=0,D=0,d=1,v=1;A==="sbs"?(d=.5,x=f==="right"?.5:0):A==="ou"&&(v=.5,D=f==="right"?.5:0);for(let p of w.primitives){let E=!!p.isTransmissive;if(!y&&E){m=!0;continue}if(y&&!E)continue;let L=p.customProgram||this.renderProg,g=p.customUniforms||this.uRender;t.useProgram(L),t.uniform1i(g.uToneMapping,u),t.uniform1f(g.uEnvIntensity,this.envIntensity),t.uniform3f(g.uCameraPos,o,c,a),t.uniform1f(g.uEmissive,M?1:0),t.uniformMatrix4fv(g.uMVP,!1,this.mvpMatrix),t.uniformMatrix4fv(g.uModel,!1,this.modelMatrix),t.uniformMatrix3fv(g.uNormalMatrix,!1,w.normalMatrix),g.uUvTransform&&t.uniform4f(g.uUvTransform,x,D,d,v),g.uViewportSize&&t.uniform2f(g.uViewportSize,Math.max(1,i),Math.max(1,r)),this.xrDepthState.enabled&&this.xrDepthState.texture?(t.activeTexture(33989),t.bindTexture(3553,this.xrDepthState.texture),g.uXrDepthTex&&t.uniform1i(g.uXrDepthTex,5),g.uXrDepthEnabled&&t.uniform1i(g.uXrDepthEnabled,1),g.uXrDepthFormat&&t.uniform1i(g.uXrDepthFormat,this.xrDepthState.format||0),g.uXrRawValueToMeters&&t.uniform1f(g.uXrRawValueToMeters,this.xrDepthState.rawValueToMeters),g.uXrDepthUVTransform&&t.uniformMatrix4fv(g.uXrDepthUVTransform,!1,this.xrDepthState.uvTransform)):g.uXrDepthEnabled&&t.uniform1i(g.uXrDepthEnabled,0),this.environmentTexture?(t.activeTexture(33988),t.bindTexture(3553,this.environmentTexture),t.uniform1i(g.uEnvironmentMap,4),t.uniform1i(g.uHasEnvironmentMap,1)):t.uniform1i(g.uHasEnvironmentMap,0),this.bindLights(g);for(let S of z)S.onBeforeDrawPrimitive?.(t,L,p,w,this.worldMatrices||[],this.gltf);t.uniform4fv(g.uBaseColor,p.baseColor),t.uniform1f(g.uMetallic,p.metallic),t.uniform1f(g.uRoughness,p.roughness),g.uClearcoat&&t.uniform2f(g.uClearcoat,p.clearcoat??0,p.clearcoatRoughness??.04),p.texture?(t.activeTexture(33984),t.bindTexture(3553,p.texture),t.uniform1i(g.uBaseColorTexture,0),t.uniform1i(g.uHasTexture,1)):t.uniform1i(g.uHasTexture,0),p.metallicRoughnessTexture?(t.activeTexture(33985),t.bindTexture(3553,p.metallicRoughnessTexture),t.uniform1i(g.uMetallicRoughnessTexture,1),t.uniform1i(g.uHasMetallicRoughnessTexture,1)):t.uniform1i(g.uHasMetallicRoughnessTexture,0),p.normalTexture?(t.activeTexture(33986),t.bindTexture(3553,p.normalTexture),t.uniform1i(g.uNormalTexture,2),t.uniform1i(g.uHasNormalTexture,1),t.uniform1f(g.uNormalScale,p.normalScale)):t.uniform1i(g.uHasNormalTexture,0),p.occlusionTexture?(t.activeTexture(33987),t.bindTexture(3553,p.occlusionTexture),t.uniform1i(g.uOcclusionTexture,3),t.uniform1i(g.uHasOcclusionTexture,1),t.uniform1f(g.uOcclusionStrength,p.occlusionStrength)):t.uniform1i(g.uHasOcclusionTexture,0),t.bindVertexArray(p.vao),t.drawElements(4,p.indexCount,p.indexType,0)}}};if(T(!1),m){for(let y of z)y.onBeforeTransmissivePass?.(t,this);T(!0)}for(let y of z)y.onAfterRender?.(t,this,s)}disposeMeshListGpuResources(e){let t=this.gl;for(let i of e)for(let r of i.primitives){if(r.vao&&t.deleteVertexArray(r.vao),r.buffers)for(let s of r.buffers)t.deleteBuffer(s);r.texture&&t.deleteTexture(r.texture),r.metallicRoughnessTexture&&t.deleteTexture(r.metallicRoughnessTexture),r.normalTexture&&t.deleteTexture(r.normalTexture),r.occlusionTexture&&t.deleteTexture(r.occlusionTexture),r.customProgram&&t.deleteProgram(r.customProgram)}}disposeMeshGpuResources(){this.disposeMeshListGpuResources(this.meshes),this.meshes=[]}disposeGpuResources(){let e=this.gl;this.disposeMeshGpuResources(),this.disposeMeshListGpuResources(this.backdropMeshes),this.backdropMeshes=[];for(let t of z)t.onDestroy?.(e,this);this.environmentTexture&&(e.deleteTexture(this.environmentTexture),this.environmentTexture=null),this.renderProg&&e.deleteProgram(this.renderProg),this.pickProg&&e.deleteProgram(this.pickProg),this.pickFbo&&e.deleteFramebuffer(this.pickFbo),this.pickTexture&&e.deleteTexture(this.pickTexture),this.pickDepth&&e.deleteRenderbuffer(this.pickDepth),this.pickFbo=null,this.pickTexture=null,this.pickDepth=null}dispose(){this.stop(),this.teardownEvents(),this.disposeGpuResources()}destroy(){this.dispose()}};ge.registerPlugin=Ve,ge.getRegisteredPlugins=Oe;function Le(n){return new TextEncoder().encode(n)}function wt(n,e){n.updateMatrixWorld(!0);let t=[];return n.traverse(i=>{if(i.geometry){let r=i.geometry,s=r.attributes.position;if(!s||s.count===0)return;let u=s.count,l=new Float32Array(u*3),o=i.matrixWorld.elements;for(let d=0;d<u;d++){let v=s.getX(d),p=s.getY(d),E=s.getZ(d);l[d*3]=o[0]*v+o[4]*p+o[8]*E+o[12],l[d*3+1]=o[1]*v+o[5]*p+o[9]*E+o[13],l[d*3+2]=o[2]*v+o[6]*p+o[10]*E+o[14]}let c;if(r.attributes.normal){let d=r.attributes.normal;c=new Float32Array(u*3);let v=new Float32Array(9);ne(v,o);for(let p=0;p<u;p++){let E=d.getX(p),L=d.getY(p),g=d.getZ(p),S=v[0]*E+v[3]*L+v[6]*g,P=v[1]*E+v[4]*L+v[7]*g,B=v[2]*E+v[5]*L+v[8]*g,X=Math.hypot(S,P,B)||1;c[p*3]=S/X,c[p*3+1]=P/X,c[p*3+2]=B/X}}let a;if(r.attributes.uv){let d=r.attributes.uv;a=new Float32Array(u*2);for(let v=0;v<u;v++)a[v*2]=d.getX(v),a[v*2+1]=d.getY(v)}let f;if(r.index)f=r.index.array;else{f=u>65535?new Uint32Array(u):new Uint16Array(u);for(let d=0;d<u;d++)f[d]=d}let m="DefaultMaterial",b=[.8,.8,.8],h=.5,T=.1,y=0,R=0,w=1.5,M=1,A=[0,0,0];if(i.material){let d=i.material;m=d.name||`Material_${t.length}`,d.color&&(b=[d.color.r,d.color.g,d.color.b]),typeof d.roughness=="number"&&(h=d.roughness),typeof d.metalness=="number"&&(T=d.metalness),typeof d.clearcoat=="number"&&(y=d.clearcoat),typeof d.clearcoatRoughness=="number"&&(R=d.clearcoatRoughness),typeof d.ior=="number"&&(w=d.ior);let v=typeof d.opacity=="number"?d.opacity:1,p=typeof d.transmission=="number"?d.transmission:0;if(M=v*(1-p),d.emissive&&(d.emissive.r>0||d.emissive.g>0||d.emissive.b>0)){let E=d.emissiveIntensity??1;A=[d.emissive.r*E,d.emissive.g*E,d.emissive.b*E]}}let x,D=e?.animateCallback||e?.animateFn||(typeof n.userData?.animate=="function"?n.userData.animate:typeof n.__animateFn=="function"?n.__animateFn:typeof globalThis.animate=="function"?globalThis.animate:void 0);if(typeof D=="function"){let d=e?.duration??4,v=e?.fps??4,p=Math.max(2,Math.round(d*v)+1),E=[],L=[],g=[],S=[],P=[i.position.x,i.position.y,i.position.z],B=[i.quaternion.x,i.quaternion.y,i.quaternion.z,i.quaternion.w],X=[i.scale.x,i.scale.y,i.scale.z],W=!1;for(let G=0;G<p;G++){let j=G/(p-1)*d;E.push(j);try{D(j)}catch{}L.push([i.position.x,i.position.y,i.position.z]),g.push([i.quaternion.x,i.quaternion.y,i.quaternion.z,i.quaternion.w]),S.push([i.scale.x,i.scale.y,i.scale.z]),(Math.abs(i.position.x-P[0])>1e-4||Math.abs(i.position.y-P[1])>1e-4||Math.abs(i.position.z-P[2])>1e-4||Math.abs(i.quaternion.x-B[0])>1e-4||Math.abs(i.quaternion.y-B[1])>1e-4||Math.abs(i.quaternion.z-B[2])>1e-4||Math.abs(i.quaternion.w-B[3])>1e-4||Math.abs(i.scale.x-X[0])>1e-4)&&(W=!0)}i.position.set(P[0],P[1],P[2]),i.quaternion.set(B[0],B[1],B[2],B[3]),i.scale.set(X[0],X[1],X[2]),W&&(x={times:E,translations:L,rotations:g,scales:S})}t.push({name:i.name||`Mesh_${t.length}`,positions:l,indices:f,normals:c,uvs:a,materialName:m,color:b,roughness:h,metallic:T,clearcoat:y,clearcoatRoughness:R,ior:w,opacity:M,emissiveColor:A,xrTraits:i.userData?.xr,timeSamples:x})}}),t}function nt(n){let e=[],t=n.gltf,i=n.bin,r=i instanceof ArrayBuffer?i:i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength),s=t.accessors||[],u=t.bufferViews||[],l=t.materials||[],o=t.meshes||[],c=t.nodes||[];function a(b){let h=s[b];if(!h)throw new Error(`Accessor ${b} not found`);let T=u[h.bufferView||0],y=(T.byteOffset||0)+(h.byteOffset||0),R=T.byteLength||0,w=r.slice(y,y+R);return{acc:h,buffer:w}}let f=new Map;if(c.length>0){let b=be(t);for(let h=0;h<b.length;h++)f.set(h,b[h])}function m(b,h,T,y){let R=o[b];if(!R)return;let w=new Float32Array(9);ne(w,h);for(let M=0;M<(R.primitives||[]).length;M++){let A=R.primitives[M],x=A.attributes?.POSITION;if(x===void 0)continue;let{acc:D,buffer:d}=a(x),v=new Float32Array(d,0,D.count*3),p=new Float32Array(v.length);for(let F=0;F<D.count;F++){let C=v[F*3],O=v[F*3+1],U=v[F*3+2];p[F*3]=h[0]*C+h[4]*O+h[8]*U+h[12],p[F*3+1]=h[1]*C+h[5]*O+h[9]*U+h[13],p[F*3+2]=h[2]*C+h[6]*O+h[10]*U+h[14]}let E,L=A.attributes?.NORMAL;if(L!==void 0){let{acc:F,buffer:C}=a(L),O=new Float32Array(C,0,F.count*3);E=new Float32Array(O.length);for(let U=0;U<F.count;U++){let ee=O[U*3],K=O[U*3+1],Y=O[U*3+2],re=w[0]*ee+w[3]*K+w[6]*Y,se=w[1]*ee+w[4]*K+w[7]*Y,te=w[2]*ee+w[5]*K+w[8]*Y,Z=Math.hypot(re,se,te)||1;E[U*3]=re/Z,E[U*3+1]=se/Z,E[U*3+2]=te/Z}}let g,S=A.attributes?.TEXCOORD_0;if(S!==void 0){let{acc:F,buffer:C}=a(S);g=new Float32Array(C,0,F.count*2)}let P;if(A.indices!==void 0){let{acc:F,buffer:C}=a(A.indices);F.componentType===5125?P=new Uint32Array(C,0,F.count):P=new Uint16Array(C,0,F.count);let O=D.count;for(let U of P)if(U>=O)throw new Error(`SecurityError: Index buffer value (${U}) out of vertex bounds [0, ${O}).`)}else{let F=D.count;P=F>65535?new Uint32Array(F):new Uint16Array(F);for(let C=0;C<F;C++)P[C]=C}let B="DefaultMaterial",X=[.8,.8,.8],W=.5,G=.1,j=0,V=0,q=1.5,N=1,_=[0,0,0];if(A.material!==void 0&&l[A.material]){let F=l[A.material];B=F.name||`Material_${A.material}`;let C=F.pbrMetallicRoughness||{},O=1;Array.isArray(C.baseColorFactor)&&(X=[C.baseColorFactor[0],C.baseColorFactor[1],C.baseColorFactor[2]],typeof C.baseColorFactor[3]=="number"&&(O=C.baseColorFactor[3])),typeof C.roughnessFactor=="number"&&(W=C.roughnessFactor),typeof C.metallicFactor=="number"&&(G=C.metallicFactor),Array.isArray(F.emissiveFactor)&&F.emissiveFactor.length>=3&&(_=[F.emissiveFactor[0],F.emissiveFactor[1],F.emissiveFactor[2]]);let U=F.extensions||{};U.KHR_materials_clearcoat&&(j=U.KHR_materials_clearcoat.clearcoatFactor??0,V=U.KHR_materials_clearcoat.clearcoatRoughnessFactor??0),U.KHR_materials_ior&&typeof U.KHR_materials_ior.ior=="number"&&(q=U.KHR_materials_ior.ior);let ee=U.KHR_materials_transmission?.transmissionFactor??0;N=O*(1-ee)}let H=(R.primitives||[]).length>1?`${T}_p${M}`:T;e.push({name:H,positions:p,indices:P,normals:E,uvs:g,materialName:B,color:X,roughness:W,metallic:G,clearcoat:j,clearcoatRoughness:V,ior:q,opacity:N,emissiveColor:_,xrTraits:y?.xr||R.extras?.xr})}}if(c.length>0)for(let b=0;b<c.length;b++){let h=c[b];if(h.mesh!==void 0&&h.mesh<o.length){let T=f.get(b)||$(),y=h.name||o[h.mesh].name||`Node_${b}`;m(h.mesh,T,y,h.extras)}}else{let b=$();for(let h=0;h<o.length;h++){let T=o[h].name||`Mesh_${h}`;m(h,b,T,o[h].extras)}}return e}function Pe(n,e){if(!n||typeof n!="string")return e;let t=n.replace(/[^A-Za-z0-9_]/g,"_");return/^[0-9]/.test(t)&&(t="_"+t),t||e}function et(n){return String(n??"").replace(/[\x00-\x1f\x7f]/g,"").replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function I(n){if(!Number.isFinite(n)||Math.abs(n)<1e-7)return"0";let e=Number(n.toFixed(5)).toString();return e.indexOf(".")===-1?`${e}.0`:e}function tt(n){let e=n.length/3,t=new Array(e);for(let i=0;i<e;i++)t[i]=`(${I(n[i*3])}, ${I(n[i*3+1])}, ${I(n[i*3+2])})`;return t.join(", ")}function Rt(n,e){let t=new Array(e);for(let i=0;i<e;i++)t[i]=`(${I(n[i*2])}, ${I(1-n[i*2+1])})`;return t.join(", ")}function At(n){return Array.from(n).join(", ")}function Se(n){let e=new Map;for(let o of n){let c=Pe(o.materialName,"DefaultMaterial");e.has(c)||e.set(c,{color:o.color||[.8,.8,.8],roughness:o.roughness??.5,metallic:o.metallic??0,clearcoat:o.clearcoat??0,clearcoatRoughness:o.clearcoatRoughness??0,ior:o.ior??1.5,opacity:o.opacity??1,emissiveColor:o.emissiveColor||[0,0,0]})}let t=0,i=null;for(let o of n){if(o.timeSamples&&o.timeSamples.times.length>0){let c=o.timeSamples.times[o.timeSamples.times.length-1];c>t&&(t=c)}o.xrTraits?.anchor&&!i&&(i=o.xrTraits.anchor==="vertical"||o.xrTraits.anchor==="wall"?"vertical":"horizontal")}let r="";t>0&&(r=`startTimeCode = 0
218
+ endTimeCode = ${I(t)}
219
+ timeCodesPerSecond = 1.0
220
+ `);let s="";i&&(s=`uniform token preliminary:anchoring:type = "plane"
221
+ uniform token preliminary:planeAnchoring:alignment = "${i}"
222
+ `);let u=`#usda 1.0
223
+ (
224
+ defaultPrim = "Root"
225
+ metersPerUnit = 1.0
226
+ upAxis = "Y"
227
+ ${r})
228
+
229
+ def Xform "Root" (
230
+ kind = "component"
231
+ )
232
+ {
233
+ ${s}def Scope "Materials"
234
+ {
235
+ `;for(let[o,c]of e.entries()){let[a,f,m]=c.color,[b,h,T]=c.emissiveColor,y="";c.clearcoat>0&&(y+=`float inputs:clearcoat = ${I(c.clearcoat)}
236
+ `,y+=`float inputs:clearcoatRoughness = ${I(c.clearcoatRoughness)}
237
+ `),c.ior!==1.5&&(y+=`float inputs:ior = ${I(c.ior)}
238
+ `),c.opacity<1&&(y+=`float inputs:opacity = ${I(c.opacity)}
239
+ `),(b>0||h>0||T>0)&&(y+=`color3f inputs:emissiveColor = (${I(b)}, ${I(h)}, ${I(T)})
240
+ `),u+=`def Material "${o}"
241
+ {
242
+ def Shader "PBRShader"
243
+ {
244
+ uniform token info:id = "UsdPreviewSurface"
245
+ color3f inputs:diffuseColor = (${I(a)}, ${I(f)}, ${I(m)})
246
+ float inputs:metallic = ${I(c.metallic)}
247
+ float inputs:roughness = ${I(c.roughness)}
248
+ ${y}token outputs:surface
249
+ }
250
+ token outputs:surface.connect = </Root/Materials/${o}/PBRShader.outputs:surface>
251
+ }
252
+ `}u+=`}
253
+ def Scope "Meshes"
254
+ {
255
+ `;let l=new Set;for(let o=0;o<n.length;o++){let c=n[o],a=c.positions.length/3,f=1/0,m=1/0,b=1/0,h=-1/0,T=-1/0,y=-1/0;for(let d=0;d<a;d++){let v=c.positions[d*3],p=c.positions[d*3+1],E=c.positions[d*3+2];v<f&&(f=v),v>h&&(h=v),p<m&&(m=p),p>T&&(T=p),E<b&&(b=E),E>y&&(y=E)}isFinite(f)||(f=m=b=-1,h=T=y=1);let R=Math.floor(c.indices.length/3),w=Pe(c.materialName,"DefaultMaterial"),M=Pe(c.name,`Mesh_${o}`);l.has(M)&&(M=`${M}_${o}`),l.add(M);let A=R>0?R===1?"3":"3, ".repeat(R-1)+"3":"",x=c.xrTraits,D="";if(x){let d=[];x.physics&&x.physics!=="none"&&d.push('prepend apiSchemas = ["PhysicsBodyAPI", "PhysicsCollisionAPI"]');let v=ce().xrTraitSerializer?.usdLines(x,et)??[];if(!v.length)for(let p of["grab","billboard","follow","anchor","physics"]){let E=p==="follow"&&typeof x.follow=="object"?x.follow.mode??"head":x[p];E!==void 0&&v.push(`string ${p} = "${et(E)}"`)}v.length>0&&d.push(`customData = {
256
+ dictionary xr = {
257
+ ${v.join(`
258
+ `)}
259
+ }
260
+ }`),d.length>0&&(D=` (
261
+ ${d.join(`
262
+ `)}
263
+ )`)}if(u+=`def Mesh "${M}"${D}
264
+ {
265
+ `,x?.physics&&x.physics!=="none"){let d=x.physics==="static"?"true":"false";u+=`bool physics:rigidBodyEnabled = true
266
+ bool physics:kinematicEnabled = ${d}
267
+ bool physics:collisionEnabled = true
268
+ `}if(c.timeSamples&&c.timeSamples.times.length>0){let d=c.timeSamples,v=d.times.map((L,g)=>{let S=d.translations?.[g]||[0,0,0];return`${I(L)}: (${I(S[0])}, ${I(S[1])}, ${I(S[2])})`}).join(", "),p=d.times.map((L,g)=>{let S=d.rotations?.[g]||[0,0,0,1];return`${I(L)}: (${I(S[3])}, ${I(S[0])}, ${I(S[1])}, ${I(S[2])})`}).join(", "),E=d.times.map((L,g)=>{let S=d.scales?.[g]||[1,1,1];return`${I(L)}: (${I(S[0])}, ${I(S[1])}, ${I(S[2])})`}).join(", ");u+=`double3 xformOp:translate.timeSamples = { ${v} }
269
+ quatf xformOp:orient.timeSamples = { ${p} }
270
+ double3 xformOp:scale.timeSamples = { ${E} }
271
+ uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
272
+ `}u+=`float3[] extent = [(${I(f)}, ${I(m)}, ${I(b)}), (${I(h)}, ${I(T)}, ${I(y)})]
273
+ int[] faceVertexCounts = [${A}]
274
+ int[] faceVertexIndices = [${At(c.indices)}]
275
+ point3f[] points = [${tt(c.positions)}]
276
+ `,c.normals&&c.normals.length===c.positions.length&&(u+=`normal3f[] normals = [${tt(c.normals)}] (
277
+ interpolation = "vertex"
278
+ )
279
+ `),c.uvs&&c.uvs.length===a*2&&(u+=`texCoord2f[] primvars:st = [${Rt(c.uvs,a)}] (
280
+ interpolation = "vertex"
281
+ )
282
+ `),u+=`rel material:binding = </Root/Materials/${w}>
283
+ }
284
+ `}return u+=`}
285
+ }
286
+ `,u}function Fe(n,e){if(n&&typeof n.traverse=="function"){let r=wt(n,e);return Se(r)}let t=me(n),i=nt(t);return Se(i)}var ye=null;function Ce(n){if(!ye){ye=new Uint32Array(256);for(let t=0;t<256;t++){let i=t;for(let r=0;r<8;r++)i=i&1?3988292384^i>>>1:i>>>1;ye[t]=i}}let e=4294967295;for(let t=0;t<n.length;t++)e=ye[(e^n[t])&255]^e>>>8;return(e^4294967295)>>>0}function ve(n){let e=[],t=0,i=[];for(let a of n){let f=Le(a.filename),m=Ce(a.data),b=a.data.length,h=30+f.length,T=t+h,y=0,R=T%64;R!==0&&(y=64-R);let w=new Uint8Array(h+y),M=new DataView(w.buffer);M.setUint32(0,67324752,!0),M.setUint16(4,20,!0),M.setUint16(6,0,!0),M.setUint16(8,0,!0),M.setUint16(10,0,!0),M.setUint16(12,0,!0),M.setUint32(14,m,!0),M.setUint32(18,b,!0),M.setUint32(22,b,!0),M.setUint16(26,f.length,!0),M.setUint16(28,y,!0),w.set(f,30),y>0&&w.fill(0,30+f.length),e.push({offset:t,size:b,crc:m,filenameBytes:f,entry:a}),i.push(w),i.push(a.data),t+=w.length+a.data.length}let r=t;for(let a of e){let f=new Uint8Array(46+a.filenameBytes.length),m=new DataView(f.buffer);m.setUint32(0,33639248,!0),m.setUint16(4,20,!0),m.setUint16(6,20,!0),m.setUint16(8,0,!0),m.setUint16(10,0,!0),m.setUint16(12,0,!0),m.setUint16(14,0,!0),m.setUint32(16,a.crc,!0),m.setUint32(20,a.size,!0),m.setUint32(24,a.size,!0),m.setUint16(28,a.filenameBytes.length,!0),m.setUint16(30,0,!0),m.setUint16(32,0,!0),m.setUint16(34,0,!0),m.setUint16(36,0,!0),m.setUint32(38,0,!0),m.setUint32(42,a.offset,!0),f.set(a.filenameBytes,46),i.push(f),t+=f.length}let s=t-r,u=new Uint8Array(22),l=new DataView(u.buffer);l.setUint32(0,101010256,!0),l.setUint16(4,0,!0),l.setUint16(6,0,!0),l.setUint16(8,e.length,!0),l.setUint16(10,e.length,!0),l.setUint32(12,s,!0),l.setUint32(16,r,!0),l.setUint16(20,0,!0),i.push(u),t+=22;let o=new Uint8Array(t),c=0;for(let a of i)o.set(a,c),c+=a.length;return o}function Dt(n){let e=Fe(n),t=Le(e);return ve([{filename:"model.usda",data:t}])}function xe(n){let e=me(n),t=nt(e),i=Se(t),r=Le(i);return ve([{filename:"model.usda",data:r}])}function it(n){return n&&typeof n.toUSDZ=="function"?n.toUSDZ():n&&typeof n.traverse=="function"?Dt(n):xe(n)}function Ie(n){let e=n&&typeof n.toUSDZ=="function"?n.toUSDZ():xe(n);return new Blob([e],{type:"model/vnd.usdz+zip"})}function _e(){if(typeof window>"u"||typeof navigator>"u")return!1;let n=navigator.userAgent||"";if(!(/iPad|iPhone|iPod/.test(n)||navigator.platform==="MacIntel"&&navigator.maxTouchPoints>1))return!1;let t=document.createElement("a");return t.relList!==void 0&&t.relList.supports!==void 0&&t.relList.supports("ar")}function Be(){if(typeof navigator>"u")return!1;let n=navigator.userAgent||"";return/android/i.test(n)}async function ke(){if(typeof navigator>"u")return!1;let n=navigator;if(!n.xr||typeof n.xr.isSessionSupported!="function")return!1;try{return await n.xr.isSessionSupported("immersive-ar")?!0:await n.xr.isSessionSupported("immersive-vr")}catch{return!1}}async function Et(){let n=[];return await ke()&&n.push("webxr"),_e()&&n.push("quick-look"),Be()&&n.push("scene-viewer"),n}async function Pt(){return(await Ne()).bestMode}async function Ne(){let[n,e,t]=await Promise.all([ke(),Promise.resolve(_e()),Promise.resolve(Be())]),i=[];e&&i.push("quick-look"),n&&i.push("webxr"),t&&i.push("scene-viewer");let r=null;return e?r="quick-look":n?r="webxr":t&&(r="scene-viewer"),{webxr:n,quickLook:e,sceneViewer:t,availableModes:i,bestMode:r}}function Ue(n,e={}){if(typeof document>"u")throw new Error("launchQuickLook requires a browser DOM environment");let t,i=!1;if(typeof n=="string"){if(t=St(n),!t)throw new Error("[XR-Live Security] Quick Look URL is empty.")}else t=URL.createObjectURL(n),i=!0;let r=[];if(e.allowScale===!1&&r.push("allowsContentScaling=0"),e.canonicalWebPageUrl){let l=Te(e.canonicalWebPageUrl,!1);l&&r.push(`canonicalWebPageURL=${encodeURIComponent(l)}`)}e.checkoutTitle&&r.push(`checkoutTitle=${encodeURIComponent(e.checkoutTitle)}`),e.checkoutSubtitle&&r.push(`checkoutSubtitle=${encodeURIComponent(e.checkoutSubtitle)}`),e.price&&r.push(`price=${encodeURIComponent(e.price)}`),r.length>0&&(t+=`#${r.join("&")}`);let s=document.createElement("a");s.setAttribute("rel","ar"),s.setAttribute("href",t);let u=document.createElement("img");u.setAttribute("src","data:image/svg+xml;utf8,<svg/>"),u.style.display="none",s.appendChild(u),document.body.appendChild(s),s.click(),setTimeout(()=>{document.body.removeChild(s),i&&URL.revokeObjectURL(t.split("#")[0])},3e3)}function Te(n,e=!1){if(typeof n!="string")return"";let t=n.replace(/[\x00-\x1f\x7f]+/g,"").trim();if(!t)return"";if(/^[\\/]{2}/.test(t))throw new Error(`[XR-Live Security] Rejected protocol-relative URL in Scene Viewer intent: ${t.slice(0,32)}`);let i=t.toLowerCase();if(i.startsWith("https://")||i.startsWith("http://")||e&&i.startsWith("blob:")||!/^[a-z][a-z0-9+.-]*:/i.test(t))return t;throw new Error(`[XR-Live Security] Rejected unsafe URL scheme in Scene Viewer intent: ${t.slice(0,32)}`)}function St(n){try{return Te(n,!0)}catch{throw new Error(`[XR-Live Security] Rejected unsafe URL scheme in Quick Look launch: ${(n||"").trim().slice(0,32)}`)}}function rt(n,e={}){let t=Te(n,!0),i=e.mode||"ar_preferred",r=new URLSearchParams({file:t,mode:i,resizable:e.resizable!==!1?"true":"false",enable_vertical_placement:e.enableVerticalPlacement?"true":"false"});return e.title&&r.set("title",e.title),e.link&&r.set("link",Te(e.link,!1)),`intent://arvr.google.com/scene-viewer/1.0?${r.toString()}#Intent;scheme=https;package=com.google.ar.core;action=android.intent.action.VIEW;end;`}function st(n,e={}){if(typeof window>"u")throw new Error("launchSceneViewer requires a browser environment");let t=rt(n,e);window.location.href=t}var Me=class{constructor(e={}){this.session=null;this.refSpace=null;this.viewerSpace=null;this.hitTestSource=null;this.isPlaced=!1;this.placedMatrix=new Float32Array(16);this.currentHitMatrix=null;this.view=null;this.options=e}isSessionActive(){return this.session!==null}hasPlacedModel(){return this.isPlaced}getPlacedMatrix(){return this.placedMatrix}async start(e,t){if(typeof navigator>"u"||!navigator.xr)throw new Error("WebXR is not supported on this browser.");let i=navigator.xr;this.view=e;let r={requiredFeatures:this.options.requiredFeatures||[],optionalFeatures:this.options.optionalFeatures||["local","hit-test","dom-overlay","light-estimation"]},s=t||e?.container;for(let o of z)o.onConfigureXRSessionInit?.(s,r);let u="immersive-ar";try{await i.isSessionSupported("immersive-ar")||(u="immersive-vr")}catch{u="immersive-vr"}try{this.session=await i.requestSession(u,r)}catch(o){throw this.options.onError?.(o),o}this.session.addEventListener("end",()=>{this.cleanup(),this.options.onExit?.()}),this.session.addEventListener("select",()=>{this.handleSelect()});let l=e.getGLContext?.();if(l&&l.makeXRCompatible&&await l.makeXRCompatible(),l&&typeof window<"u"&&typeof window.XRWebGLLayer=="function"&&typeof this.session.updateRenderState=="function"){let o=new window.XRWebGLLayer(this.session,l);this.session.updateRenderState({baseLayer:o})}if(this.refSpace=await this.session.requestReferenceSpace("local"),this.viewerSpace=await this.session.requestReferenceSpace("viewer"),this.session.requestHitTestSource)try{this.hitTestSource=await this.session.requestHitTestSource({space:this.viewerSpace})}catch{}this.session.requestAnimationFrame(this.onXRFrame.bind(this))}async stop(){this.session&&(await this.session.end(),this.cleanup())}handleSelect(){this.currentHitMatrix&&!this.isPlaced&&(this.placedMatrix.set(this.currentHitMatrix),this.isPlaced=!0,this.options.onPlaced?.(this.placedMatrix))}onXRFrame(e,t){if(!this.session)return;this.session.requestAnimationFrame(this.onXRFrame.bind(this));let i=t.getViewerPose(this.refSpace);if(!i)return;let r=this.view?.getGLContext?.(),s=this.session.renderState?.baseLayer;if(r&&s&&s.framebuffer&&r.bindFramebuffer(36160,s.framebuffer),this.hitTestSource&&!this.isPlaced){let u=t.getHitTestResults(this.hitTestSource);for(let l of u){let o=l.getPose(this.refSpace);if(o){let c=o.transform.matrix,a=c[5];if(this.options.arPlacement==="wall"&&Math.abs(a)>.35||this.options.arPlacement==="floor"&&Math.abs(a)<.65)continue;this.currentHitMatrix=c,this.options.onHit?.(this.currentHitMatrix);break}}}for(let u of z)u.onXRFrame?.(this.view,this.session,t,this.refSpace);for(let u of i.views)this.view&&typeof this.view.renderXRView=="function"&&this.view.renderXRView(u,this.isPlaced?this.placedMatrix:this.currentHitMatrix,this.isPlaced);r&&s&&s.framebuffer&&r.bindFramebuffer(36160,null)}cleanup(){this.hitTestSource&&(this.hitTestSource.cancel?.(),this.hitTestSource=null),this.session=null,this.refSpace=null,this.viewerSpace=null,this.currentHitMatrix=null,this.isPlaced=!1,this.view=null}};async function Lt(n){let e=await Ne(),t=n.preferredModes||["quick-look","webxr","scene-viewer"],i=null;for(let l of t)if(e.availableModes.includes(l)){i=l;break}if(i||(i=e.bestMode),!i)return{mode:"quick-look",success:!1,error:new Error("No augmented reality viewing mode is supported on this device.")};let r={...n.quickLookOptions,allowScale:n.arScale==="fixed"?!1:n.quickLookOptions?.allowScale},s={...n.sceneViewerOptions,resizable:n.arScale==="fixed"?!1:n.sceneViewerOptions?.resizable,enableVerticalPlacement:n.arPlacement==="wall"?!0:n.sceneViewerOptions?.enableVerticalPlacement},u={...n.webXROptions,arPlacement:n.arPlacement||n.webXROptions?.arPlacement};try{if(i==="quick-look"){let l;if(n.model instanceof Blob&&n.model.type==="model/vnd.usdz+zip")l=n.model;else{if(typeof n.model=="string")return Ue(n.model,r),{mode:"quick-look",success:!0};l=Ie(n.model)}return Ue(l,r),{mode:"quick-look",success:!0}}if(i==="scene-viewer"){let l=n.glbUrl||(typeof n.model=="string"?n.model:null);if(!l)throw new Error("Scene Viewer requires a hosted GLB URL (glbUrl option).");return st(l,s),{mode:"scene-viewer",success:!0}}if(i==="webxr"){if(!n.view)throw new Error("WebXR AR mode requires an active ThreeView instance.");let l=new Me(u);return await l.start(n.view),{mode:"webxr",success:!0,session:l}}}catch(l){return{mode:i,success:!1,error:l}}return{mode:i,success:!1,error:new Error(`Unhandled AR mode: ${i}`)}}