@xviewer.js/core 1.0.4-alpha.1 → 1.0.4-alpha.11

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.
package/dist/module.js CHANGED
@@ -4,10 +4,10 @@ import { GLTFLoader as GLTFLoader$1 } from 'three/examples/jsm/loaders/GLTFLoade
4
4
  import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
5
5
  import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
6
6
  import * as THREE from 'three';
7
- import { EquirectangularReflectionMapping, FileLoader, TextureLoader as TextureLoader$1, SRGBColorSpace, CubeUVReflectionMapping, Mesh, BoxGeometry, SphereGeometry, PlaneGeometry, MathUtils, Vector3, Vector2, LinearInterpolant, Object3D, Plane as Plane$1, Matrix4, Vector4, PerspectiveCamera, WebGLRenderTarget, LinearMipMapLinearFilter, LinearFilter, HalfFloatType, AnimationMixer, Color, OrthographicCamera, MeshDepthMaterial, ShaderMaterial, Euler, Group, REVISION, Box3, Sphere as Sphere$1, Raycaster, Quaternion, Spherical, UniformsUtils, NoBlending, AdditiveBlending, FloatType, UnsignedByteType, LinearSRGBColorSpace, NearestFilter, ClampToEdgeWrapping, WebGLCubeRenderTarget, DataTexture, RGBAFormat, UVMapping, BufferGeometry, Float32BufferAttribute, Scene, WebGLRenderer, LinearToneMapping, PCFSoftShadowMap, LoadingManager, PMREMGenerator, CubeCamera, ShaderLib, ShaderChunk } from 'three';
7
+ import { EquirectangularReflectionMapping, FileLoader, TextureLoader as TextureLoader$1, SRGBColorSpace, CubeUVReflectionMapping, Mesh, BoxGeometry, SphereGeometry, PlaneGeometry, MathUtils, Vector3, Vector2, LinearInterpolant, Object3D, Plane as Plane$1, Matrix4, Vector4, PerspectiveCamera, WebGLRenderTarget, LinearMipMapLinearFilter, LinearFilter, HalfFloatType, AnimationMixer, Color, OrthographicCamera, MeshDepthMaterial, ShaderMaterial, Euler, Group, REVISION, Box3, Sphere as Sphere$1, Raycaster, Quaternion, Spherical, UniformsUtils, NoBlending, AdditiveBlending, FloatType, UnsignedByteType, LinearSRGBColorSpace, NearestFilter, ClampToEdgeWrapping, WebGLCubeRenderTarget, DataTexture, RGBAFormat, UVMapping, BufferGeometry, Float32BufferAttribute, Scene, WebGLRenderer, LinearToneMapping, PCFSoftShadowMap, LoadingManager, PMREMGenerator, CubeCamera, ShaderLib, ShaderChunk, BufferAttribute, NormalBlending } from 'three';
8
8
  import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
9
9
  import { SVGLoader as SVGLoader$1 } from 'three/examples/jsm/loaders/SVGLoader.js';
10
- import { KTX2Loader as KTX2Loader$1 } from 'three/examples/jsm/loaders/KTX2Loader';
10
+ import { KTX2Loader as KTX2Loader$1 } from 'three/examples/jsm/loaders/KTX2Loader.js';
11
11
  import { HorizontalBlurShader, VerticalBlurShader } from 'three/examples/jsm/Addons.js';
12
12
 
13
13
  class EventEmitter {
@@ -145,7 +145,6 @@ function getClassInstance(constructor, args = []) {
145
145
 
146
146
  class Loader {
147
147
  static _setUserData(node) {
148
- const keys = Loader._texKeys;
149
148
  const meshes = [];
150
149
  const textures = {};
151
150
  const materials = {};
@@ -163,7 +162,7 @@ class Loader {
163
162
  queue.push(...object.children);
164
163
  }
165
164
  Object.values(materials).forEach((mat)=>{
166
- keys.forEach((k)=>{
165
+ Loader._texKeys.forEach((k)=>{
167
166
  let tex = mat[k];
168
167
  if (tex) {
169
168
  textures[tex.uuid] = tex;
@@ -224,13 +223,10 @@ class FBXLoader extends Loader {
224
223
  loader.manager = manager;
225
224
  loader.setPath(path);
226
225
  loader.setResourcePath(resourcePath);
227
- const loadCallback = (node)=>{
228
- onLoad(Loader._setUserData(node));
229
- };
230
226
  if (buffer) {
231
- loadCallback(loader.parse(buffer, resourcePath));
227
+ onLoad(loader.parse(buffer, resourcePath));
232
228
  } else {
233
- loader.load(url, loadCallback, onProgress, onError);
229
+ loader.load(url, onLoad, onProgress, onError);
234
230
  }
235
231
  }
236
232
  constructor(...args){
@@ -257,15 +253,10 @@ class GLTFLoader extends Loader {
257
253
  loader.manager = manager;
258
254
  loader.setPath(path);
259
255
  loader.setResourcePath(resourcePath);
260
- const loadCallback = (gltf)=>{
261
- const node = gltf.scene;
262
- node.animations.push(...gltf.animations);
263
- onLoad(Loader._setUserData(node));
264
- };
265
256
  if (buffer) {
266
- loader.parse(buffer, resourcePath, loadCallback, onError);
257
+ loader.parse(buffer, resourcePath, onLoad, onError);
267
258
  } else {
268
- loader.load(url, loadCallback, onProgress, onError);
259
+ loader.load(url, onLoad, onProgress, onError);
269
260
  }
270
261
  }
271
262
  constructor(...args){
@@ -359,15 +350,10 @@ class BINLoader extends Loader {
359
350
  loader.manager = manager;
360
351
  loader.setPath(path);
361
352
  loader.setResourcePath(resourcePath);
362
- const loadCallback = (gltf)=>{
363
- const node = gltf.scene;
364
- node.animations.push(...gltf.animations);
365
- onLoad(Loader._setUserData(node));
366
- };
367
353
  if (buffer) {
368
- loader.parse(buffer, resourcePath, loadCallback, onError);
354
+ loader.parse(buffer, resourcePath, onLoad, onError);
369
355
  } else {
370
- loader.load(url, loadCallback, onProgress, onError);
356
+ loader.load(url, onLoad, onProgress, onError);
371
357
  }
372
358
  }
373
359
  constructor(...args){
@@ -439,11 +425,11 @@ class SVGLoader extends Loader {
439
425
  SVGLoader.Primitive = SVGLoader$1;
440
426
 
441
427
  class KTX2Loader extends Loader {
442
- load({ url, path, resourcePath, manager, texSettings, onLoad, onProgress, onError }) {
428
+ load({ url, path, resourcePath, transcoderPath, manager, texSettings, onLoad, onProgress, onError }) {
443
429
  let loader = this._loader;
444
430
  if (loader === undefined) {
445
431
  loader = this._loader = new KTX2Loader$1();
446
- loader.setTranscoderPath("three/examples/js/libs/basis/");
432
+ loader.setTranscoderPath(transcoderPath);
447
433
  loader.detectSupport(this.viewer.renderer);
448
434
  }
449
435
  loader.manager = manager;
@@ -2225,8 +2211,7 @@ class ComponentScheduler {
2225
2211
  if (comp.onEnable) {
2226
2212
  comp.onEnable();
2227
2213
  }
2228
- if (typeof comp.start === "function" && !comp.flags.isStartCalled) {
2229
- comp.flags.isStartCalled = true;
2214
+ if (typeof comp.start === "function") {
2230
2215
  this.startInvoker.add(comp);
2231
2216
  }
2232
2217
  if (typeof comp.update === "function") {
@@ -2456,12 +2441,12 @@ ComponentManager._infoMap = new Map();
2456
2441
 
2457
2442
  class Renderer extends Component {
2458
2443
  render(dt) {
2459
- const { renderer, scene, camera } = this.context;
2444
+ const { renderer, scene, camera } = this.viewer;
2460
2445
  renderer.setRenderTarget(null);
2461
2446
  renderer.render(scene, camera);
2462
2447
  }
2463
2448
  resize(width, height) {
2464
- const { renderer } = this.context;
2449
+ const { renderer } = this.viewer;
2465
2450
  renderer.setSize(width, height);
2466
2451
  }
2467
2452
  constructor(...args){
@@ -2581,6 +2566,60 @@ class Pressability {
2581
2566
  }
2582
2567
  }
2583
2568
 
2569
+ const PIXEL_STEP = 10;
2570
+ const LINE_HEIGHT = 40;
2571
+ const PAGE_HEIGHT = 800;
2572
+ function normalizeWheel(/*object*/ event) /*object*/ {
2573
+ let sX = 0, sY = 0, pX = 0, pY = 0; // pixelX, pixelY
2574
+ // Legacy
2575
+ if ('detail' in event) {
2576
+ sY = event.detail;
2577
+ }
2578
+ if ('wheelDelta' in event) {
2579
+ sY = -event.wheelDelta / 120;
2580
+ }
2581
+ if ('wheelDeltaY' in event) {
2582
+ sY = -event.wheelDeltaY / 120;
2583
+ }
2584
+ if ('wheelDeltaX' in event) {
2585
+ sX = -event.wheelDeltaX / 120;
2586
+ }
2587
+ // side scrolling on FF with DOMMouseScroll
2588
+ if ('axis' in event && event.axis === event.HORIZONTAL_AXIS) {
2589
+ sX = sY;
2590
+ sY = 0;
2591
+ }
2592
+ pX = sX * PIXEL_STEP;
2593
+ pY = sY * PIXEL_STEP;
2594
+ if ('deltaY' in event) {
2595
+ pY = event.deltaY;
2596
+ }
2597
+ if ('deltaX' in event) {
2598
+ pX = event.deltaX;
2599
+ }
2600
+ if ((pX || pY) && event.deltaMode) {
2601
+ if (event.deltaMode == 1) {
2602
+ pX *= LINE_HEIGHT;
2603
+ pY *= LINE_HEIGHT;
2604
+ } else {
2605
+ pX *= PAGE_HEIGHT;
2606
+ pY *= PAGE_HEIGHT;
2607
+ }
2608
+ }
2609
+ // Fall-back if spin cannot be determined
2610
+ if (pX && !sX) {
2611
+ sX = pX < 1 ? -1 : 1;
2612
+ }
2613
+ if (pY && !sY) {
2614
+ sY = pY < 1 ? -1 : 1;
2615
+ }
2616
+ return {
2617
+ spinX: sX,
2618
+ spinY: sY,
2619
+ pixelX: pX,
2620
+ pixelY: pY
2621
+ };
2622
+ }
2584
2623
  class DeviceInput extends Component {
2585
2624
  get pointer() {
2586
2625
  return this._pointer;
@@ -2597,9 +2636,18 @@ class DeviceInput extends Component {
2597
2636
  get prePointerPixel() {
2598
2637
  return this._prePointerPixel;
2599
2638
  }
2639
+ get preTouches() {
2640
+ return this._preTouches;
2641
+ }
2600
2642
  get mouseWheel() {
2601
2643
  return this._mouseWheel;
2602
2644
  }
2645
+ get touchStart() {
2646
+ return this._touchStart;
2647
+ }
2648
+ get touchMoving() {
2649
+ return this._touchMoving;
2650
+ }
2603
2651
  get touchCount() {
2604
2652
  return this._touchCount;
2605
2653
  }
@@ -2663,7 +2711,12 @@ class DeviceInput extends Component {
2663
2711
  lastUpdate(dt) {
2664
2712
  this._prePointer.copy(this._pointer);
2665
2713
  this._prePointerPixel.copy(this._pointerPixel);
2714
+ for(let i = this._touchCount; i--;){
2715
+ this._preTouches[i].id = this._touches[i].id;
2716
+ this._preTouches[i].position.copy(this._touches[i].position);
2717
+ }
2666
2718
  this._mouseWheel = 0;
2719
+ this._touchStart = false;
2667
2720
  }
2668
2721
  connect(target, event) {
2669
2722
  switch(event){
@@ -2734,14 +2787,16 @@ class DeviceInput extends Component {
2734
2787
  const isDocument = target instanceof Document;
2735
2788
  const width = isDocument ? window.innerWidth : target.offsetWidth;
2736
2789
  const height = isDocument ? window.innerHeight : target.offsetHeight;
2737
- this._pointer.x = e.clientX / width * 2 - 1;
2738
- this._pointer.y = 1 - e.clientY / height * 2;
2739
- this._pointerPixel.set(e.clientX, e.clientY);
2790
+ this._pointer.x = e.pageX / width * 2 - 1;
2791
+ this._pointer.y = 1 - e.pageY / height * 2;
2792
+ this._pointerPixel.set(e.pageX, e.pageY);
2740
2793
  }
2741
2794
  _onPointerDown(e) {
2742
2795
  e = this._remapPointer(e);
2743
2796
  this._pointerButton = e.button;
2744
2797
  this._computePointer(e);
2798
+ this._prePointer.copy(this._pointer);
2799
+ this._prePointerPixel.copy(this._pointerPixel);
2745
2800
  this._pressability.pointerDown(this._pointer, this.viewer.camera);
2746
2801
  this.viewer.emit(DeviceInput.POINTER_DOWN, e);
2747
2802
  }
@@ -2759,33 +2814,54 @@ class DeviceInput extends Component {
2759
2814
  this.viewer.emit(DeviceInput.POINTER_MOVE, e);
2760
2815
  }
2761
2816
  _onMouseWheel(e) {
2762
- this._mouseWheel = e.deltaY || e.wheelDelta;
2817
+ this._mouseWheel = this._normalizeWheel(e).pixelY;
2763
2818
  this.viewer.emit(DeviceInput.MOUSE_WHEEL, e);
2764
2819
  }
2765
2820
  _onTouchStart(e) {
2821
+ this._touchStart = true;
2766
2822
  e = this._remapTouch(e);
2823
+ const curr = e.touches;
2824
+ const touches = this._touches;
2825
+ const preTouches = this._preTouches;
2826
+ for(let i = curr.length; i--;){
2827
+ if (touches[i] === undefined) {
2828
+ touches[i] = {
2829
+ id: -1,
2830
+ position: new Vector2()
2831
+ };
2832
+ }
2833
+ const touch = curr[i];
2834
+ touches[i].id = touch.identifier;
2835
+ touches[i].position.set(touch.pageX, touch.pageY);
2836
+ if (preTouches[i] === undefined) {
2837
+ preTouches[i] = {
2838
+ id: touches[i].id,
2839
+ position: touches[i].position.clone()
2840
+ };
2841
+ } else {
2842
+ preTouches[i].id = touches[i].id;
2843
+ preTouches[i].position.copy(touches[i].position);
2844
+ }
2845
+ }
2846
+ this._touchCount = curr.length;
2767
2847
  this.viewer.emit(DeviceInput.TOUCH_START, e);
2768
2848
  }
2769
2849
  _onTouchEnd(e) {
2850
+ this._touchMoving = false;
2770
2851
  e = this._remapTouch(e);
2771
2852
  this.viewer.emit(DeviceInput.TOUCH_END, e);
2772
2853
  }
2773
2854
  _onTouchMove(e) {
2855
+ this._touchMoving = true;
2774
2856
  e = this._remapTouch(e);
2775
- const touches = e.touches;
2776
- const touchesTo = this._touches;
2777
- for(let i = touches.length; i--;){
2778
- if (touchesTo[i] == undefined) {
2779
- touchesTo[i] = {
2780
- id: -1,
2781
- position: new Vector2()
2782
- };
2783
- }
2784
- const touch = touches[i];
2785
- touchesTo[i].id = touch.identifier;
2786
- touchesTo[i].position.set(touch.pageX, touch.pageY);
2787
- }
2788
- this._touchCount = touches.length;
2857
+ const curr = e.touches;
2858
+ const touches = this._touches;
2859
+ for(let i = curr.length; i--;){
2860
+ const touch = curr[i];
2861
+ touches[i].id = touch.identifier;
2862
+ touches[i].position.set(touch.pageX, touch.pageY);
2863
+ }
2864
+ this._touchCount = curr.length;
2789
2865
  this.viewer.emit(DeviceInput.TOUCH_MOVE, e);
2790
2866
  }
2791
2867
  _onKeyDown(e) {
@@ -2800,9 +2876,10 @@ class DeviceInput extends Component {
2800
2876
  this._keys[e.key] = false;
2801
2877
  this.viewer.emit(DeviceInput.KEYUP, e);
2802
2878
  }
2803
- constructor(target){
2804
- super(), this._listeners = [], this._touches = [], this._touchCount = 0, this._pointer = new Vector2(), this._pointerPixel = new Vector2(), this._pointerButton = -1, this._prePointer = new Vector2(), this._prePointerPixel = new Vector2(), this._mouseWheel = 0, this._keys = {}, this._pressability = new Pressability();
2805
- this._target = target;
2879
+ constructor(option){
2880
+ super(), this._listeners = [], this._touches = [], this._touchCount = 0, this._touchStart = false, this._touchMoving = false, this._pointer = new Vector2(), this._pointerPixel = new Vector2(), this._pointerButton = -1, this._prePointer = new Vector2(), this._prePointerPixel = new Vector2(), this._preTouches = [], this._mouseWheel = 0, this._keys = {}, this._pressability = new Pressability();
2881
+ this._target = option.source;
2882
+ this._normalizeWheel = option.normalizeWheel || normalizeWheel;
2806
2883
  }
2807
2884
  }
2808
2885
  DeviceInput.CLICK = "click";
@@ -3646,7 +3723,9 @@ uniform float roughness;
3646
3723
  uniform float metalness;
3647
3724
  uniform sampler2D map;
3648
3725
  uniform sampler2D normalMap;
3726
+ uniform vec4 normalScaleBias;
3649
3727
  uniform sampler2D roughnessMap;
3728
+ uniform vec4 roughnessScaleBias;
3650
3729
  uniform sampler2D aoMap;
3651
3730
  uniform float aoMapIntensity;
3652
3731
  uniform sampler2D lightMap;
@@ -3684,7 +3763,7 @@ void main() {
3684
3763
  vec2 reflectUv = coord.xy;
3685
3764
 
3686
3765
  #ifdef USE_NORMALMAP
3687
- vec4 texelNormal = texture2D(normalMap, UV_NORMAL);
3766
+ vec4 texelNormal = texture2D(normalMap, UV_NORMAL * normalScaleBias.xy + normalScaleBias.zw);
3688
3767
  vec3 normal = normalize(vec3(texelNormal.r * 2.0 - 1.0, texelNormal.b, texelNormal.g * 2.0 - 1.0));
3689
3768
  reflectUv += coord.z * normal.xz * 0.05;
3690
3769
  #endif
@@ -3711,7 +3790,7 @@ void main() {
3711
3790
  float roughnessFactor = roughness;
3712
3791
 
3713
3792
  #ifdef USE_ROUGHNESSMAP
3714
- roughnessFactor *= texture2D(roughnessMap, UV_ROUGHNESS).g * roughness;
3793
+ roughnessFactor *= texture2D(roughnessMap, UV_ROUGHNESS * roughnessScaleBias.xy + roughnessScaleBias.zw).g * roughness;
3715
3794
  #endif
3716
3795
 
3717
3796
  computeMultiscattering( geometryNormal, geometryViewDir, specularColor, specularF90, roughnessFactor, singleScattering, multiScattering );
@@ -3723,6 +3802,8 @@ void main() {
3723
3802
 
3724
3803
  #ifdef USE_LIGHTMAP
3725
3804
  irradiance += texture2D(lightMap, UV_LIGHTMAP).rgb * lightMapIntensity;
3805
+ #else
3806
+ irradiance += vec3(1.);
3726
3807
  #endif
3727
3808
 
3728
3809
  float lod = roughnessFactor * (1.7 - 0.7 * roughnessFactor) * 6.;
@@ -3809,12 +3890,24 @@ class ReflectorMaterial extends ShaderMaterial {
3809
3890
  set roughnessMap(v) {
3810
3891
  this.uniforms.roughnessMap.value = v;
3811
3892
  }
3893
+ get roughnessScaleBias() {
3894
+ return this.uniforms.roughnessScaleBias.value;
3895
+ }
3896
+ set roughnessScaleBias(v) {
3897
+ this.uniforms.roughnessScaleBias.value.copy(v);
3898
+ }
3812
3899
  get normalMap() {
3813
3900
  return this.uniforms.normalMap.value;
3814
3901
  }
3815
3902
  set normalMap(v) {
3816
3903
  this.uniforms.normalMap.value = v;
3817
3904
  }
3905
+ get normalScaleBias() {
3906
+ return this.uniforms.normalScaleBias.value;
3907
+ }
3908
+ set normalScaleBias(v) {
3909
+ this.uniforms.normalScaleBias.value.copy(v);
3910
+ }
3818
3911
  get aoMap() {
3819
3912
  return this.uniforms.aoMap.value;
3820
3913
  }
@@ -3879,9 +3972,15 @@ class ReflectorMaterial extends ShaderMaterial {
3879
3972
  roughnessMap: {
3880
3973
  value: null
3881
3974
  },
3975
+ roughnessScaleBias: {
3976
+ value: new Vector4(1, 1, 0, 0)
3977
+ },
3882
3978
  normalMap: {
3883
3979
  value: null
3884
3980
  },
3981
+ normalScaleBias: {
3982
+ value: new Vector4(1, 1, 0, 0)
3983
+ },
3885
3984
  aoMap: {
3886
3985
  value: null
3887
3986
  },
@@ -3927,9 +4026,15 @@ __decorate([
3927
4026
  __decorate([
3928
4027
  property
3929
4028
  ], ReflectorMaterial.prototype, "roughnessMap", null);
4029
+ __decorate([
4030
+ property
4031
+ ], ReflectorMaterial.prototype, "roughnessScaleBias", null);
3930
4032
  __decorate([
3931
4033
  property
3932
4034
  ], ReflectorMaterial.prototype, "normalMap", null);
4035
+ __decorate([
4036
+ property
4037
+ ], ReflectorMaterial.prototype, "normalScaleBias", null);
3933
4038
  __decorate([
3934
4039
  property
3935
4040
  ], ReflectorMaterial.prototype, "aoMap", null);
@@ -4391,19 +4496,15 @@ class ResourceManager {
4391
4496
  }
4392
4497
  return loader;
4393
4498
  }
4394
- loadAsset({ url, buffer, ext, path, resourcePath, dracoPath, manager, onProgress, ...props }) {
4499
+ loadAsset({ url, ext, onProgress, ...props }) {
4395
4500
  return new Promise((resolve, reject)=>{
4396
4501
  const sel = ext || url && ResourceManager.extension(url) || "";
4397
4502
  const texSettings = ResourceManager._splitTextureSettings(props);
4398
4503
  if (this._loaders.has(sel)) {
4399
4504
  this._loaders.get(sel).load({
4400
4505
  url,
4401
- buffer,
4402
4506
  texSettings,
4403
- path,
4404
- resourcePath,
4405
- dracoPath,
4406
- manager,
4507
+ ...props,
4407
4508
  onProgress,
4408
4509
  onLoad: resolve,
4409
4510
  onError: (err)=>{
@@ -4860,6 +4961,9 @@ class Viewer extends EventEmitter {
4860
4961
  clearColor(renderTarget, color, alpha) {
4861
4962
  Viewer.ClearColor(this._renderer, renderTarget, color, alpha);
4862
4963
  }
4964
+ stash(renderTarget, callback, clearColor, clearAlpha) {
4965
+ Viewer.Stash(this._renderer, renderTarget, callback, clearColor, clearAlpha);
4966
+ }
4863
4967
  blur(blurLevel, shadingScale, inputBuffer, tempBuffer, outputBuffer, fixedOutput) {
4864
4968
  Viewer.Blur(this._renderer, blurLevel, shadingScale, inputBuffer, tempBuffer, outputBuffer, fixedOutput);
4865
4969
  }
@@ -4955,7 +5059,7 @@ class Viewer extends EventEmitter {
4955
5059
  renderer.autoClear = true;
4956
5060
  renderer.setRenderTarget(renderTarget);
4957
5061
  clearColor !== undefined && renderer.setClearColor(clearColor, clearAlpha);
4958
- callback && callback();
5062
+ callback && callback(renderer);
4959
5063
  renderer.autoClear = autoClear;
4960
5064
  renderer.setRenderTarget(RT);
4961
5065
  clearColor !== undefined && renderer.setClearColor(color, alpha);
@@ -4991,7 +5095,7 @@ class Viewer extends EventEmitter {
4991
5095
  near: 0.1,
4992
5096
  far: 1000,
4993
5097
  position: new Vector3(0, 0, 4)
4994
- }, targetFrameRate = -1, fixedFrameTime = false, colorSpace = SRGBColorSpace, toneMapping = LinearToneMapping, toneMappingExposure = 1, maxDPR = 1.5, path = "", resourcePath = "", dracoPath = "https://www.gstatic.com/draco/v1/decoders/", orientation = Orientation.AUTO, loader = {}, tasker = {}, ...webglOpts } = {}){
5098
+ }, targetFrameRate = -1, fixedFrameTime = false, colorSpace = SRGBColorSpace, toneMapping = LinearToneMapping, toneMappingExposure = 1, maxDPR = 1.5, path = "", resourcePath = "", dracoPath = "https://www.gstatic.com/draco/v1/decoders/", transcoderPath = "three/examples/js/libs/basis/", orientation = Orientation.AUTO, loader = {}, tasker = {}, ...webglOpts } = {}){
4995
5099
  super(), this._instanceId = Viewer.instanceCount++, this._dpr = 1, this._width = 1, this._height = 1, this._viewport = {
4996
5100
  width: 1,
4997
5101
  height: 1,
@@ -5049,12 +5153,15 @@ class Viewer extends EventEmitter {
5049
5153
  path,
5050
5154
  resourcePath,
5051
5155
  dracoPath,
5156
+ transcoderPath,
5052
5157
  manager: this._loadingManager
5053
5158
  };
5054
5159
  this._mount = applyProps(new Object3D(), {
5055
5160
  name: "Mount"
5056
5161
  });
5057
- this._input = this.add(new DeviceInput(input || this._canvas));
5162
+ this._input = this.add(new DeviceInput(input || {
5163
+ source: this._canvas
5164
+ }));
5058
5165
  this.add(Renderer);
5059
5166
  this.addLoader(GLTFLoader);
5060
5167
  this.addLoader(HDRLoader);
@@ -5790,5 +5897,690 @@ function getFilesFromItemList(items, onDone) {
5790
5897
  }
5791
5898
  }
5792
5899
 
5793
- export { AccumulativeShadows, Animation, AnimationCurve, BINLoader, Box, BoxProjection, Center, Component, ContactShadows, DependentMode, DeviceInput, DropFile, EXRLoader, Easing, Environment, EventEmitter, FBXLoader, FInterpConstantTo, FInterpTo, FreelookVirtualCamera, GLTFLoader, HDRLoader, JSONLoader, KTX2Loader, Loader, Logger, ObjectInstance, Orientation, PerformanceMonitor, Perlin, Plane, PropertyManager, QInterpConstantTo, QInterpTo, Quat_AngularDistance, Quat_Equals, Quat_exponentialDamp, Quat_quarticDamp, Quat_smoothDamp, RandomizedLight, Reflector, ReflectorMaterial, RenderTexture, Renderer, ResizeMode, ResourceManager, SVGLoader, ShadowMaterial, Sphere, SystemInfo, Task, TextureLoader, VInterpConstantTo, VInterpTo, Vec3_smoothDamp, Vector3_NEG_ONE, Vector3_ONE, Vector3_RIGHT, Vector3_UNIT_X, Vector3_UNIT_Y, Vector3_UNIT_Z, Vector3_UP, Vector3_ZERO, Viewer, applyProps, dependencies, exponentialDamp, find, frag_BoxfilterBlur, frag_cubeMapToPanorama, frag_panoramaToCubeMap, getChildByName, getChildren, getClassInstance, getShaderMaterial, mixin, property, quarticDamp, queryValues, smoothDamp, vert_fullscreen };
5900
+ const newline = /\n/;
5901
+ const newlineChar = '\n';
5902
+ const whitespace = /\s/;
5903
+ function wordwrap(text, opt) {
5904
+ opt = opt || {};
5905
+ //zero width results in nothing visible
5906
+ if (opt.width === 0 && opt.mode !== 'nowrap') return [];
5907
+ text = text || '';
5908
+ const width = typeof opt.width === 'number' ? opt.width : Number.MAX_VALUE;
5909
+ const start = Math.max(0, opt.start || 0);
5910
+ const end = typeof opt.end === 'number' ? opt.end : text.length;
5911
+ const mode = opt.mode;
5912
+ const letterSpacing = opt.letterSpacing || 0;
5913
+ const measure = opt.measure || monospace;
5914
+ if (mode === 'pre') return pre(measure, text, start, end, width, letterSpacing);
5915
+ else return greedy(measure, text, start, end, width, mode, letterSpacing);
5916
+ }
5917
+ function idxOf(text, chr, start, end) {
5918
+ var idx = text.indexOf(chr, start);
5919
+ if (idx === -1 || idx > end) return end;
5920
+ return idx;
5921
+ }
5922
+ function isWhitespace(chr) {
5923
+ return whitespace.test(chr);
5924
+ }
5925
+ function pre(measure, text, start, end, width, letterSpacing) {
5926
+ var lines = [];
5927
+ var lineStart = start;
5928
+ for(var i = start; i < end && i < text.length; i++){
5929
+ var chr = text.charAt(i);
5930
+ var isNewline = newline.test(chr);
5931
+ //If we've reached a newline, then step down a line
5932
+ //Or if we've reached the EOF
5933
+ if (isNewline || i === end - 1) {
5934
+ var lineEnd = isNewline ? i : i + 1;
5935
+ var measured = measure(text, lineStart, lineEnd, width, letterSpacing);
5936
+ lines.push(measured);
5937
+ lineStart = i + 1;
5938
+ }
5939
+ }
5940
+ return lines;
5941
+ }
5942
+ function greedy(measure, text, start, end, width, mode, letterSpacing) {
5943
+ //A greedy word wrapper based on LibGDX algorithm
5944
+ //https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/BitmapFontCache.java
5945
+ var lines = [];
5946
+ var testWidth = width;
5947
+ //if 'nowrap' is specified, we only wrap on newline chars
5948
+ if (mode === 'nowrap') testWidth = Number.MAX_VALUE;
5949
+ while(start < end && start < text.length){
5950
+ //get next newline position
5951
+ var newLine = idxOf(text, newlineChar, start, end);
5952
+ //eat whitespace at start of line
5953
+ while(start < newLine){
5954
+ if (!isWhitespace(text.charAt(start))) break;
5955
+ start++;
5956
+ }
5957
+ //determine visible # of glyphs for the available width
5958
+ var measured = measure(text, start, newLine, testWidth, letterSpacing);
5959
+ var lineEnd = start + (measured.end - measured.start);
5960
+ var nextStart = lineEnd + newlineChar.length;
5961
+ //if we had to cut the line before the next newline...
5962
+ if (lineEnd < newLine) {
5963
+ //find char to break on
5964
+ while(lineEnd > start){
5965
+ if (isWhitespace(text.charAt(lineEnd))) break;
5966
+ lineEnd--;
5967
+ }
5968
+ if (lineEnd === start) {
5969
+ if (nextStart > start + newlineChar.length) nextStart--;
5970
+ lineEnd = nextStart; // If no characters to break, show all.
5971
+ } else {
5972
+ nextStart = lineEnd;
5973
+ //eat whitespace at end of line
5974
+ while(lineEnd > start){
5975
+ if (!isWhitespace(text.charAt(lineEnd - newlineChar.length))) break;
5976
+ lineEnd--;
5977
+ }
5978
+ }
5979
+ }
5980
+ if (lineEnd >= start) {
5981
+ var result = measure(text, start, lineEnd, testWidth);
5982
+ lines.push(result);
5983
+ }
5984
+ start = nextStart;
5985
+ }
5986
+ return lines;
5987
+ }
5988
+ //determines the visible number of glyphs within a given width
5989
+ function monospace(text, start, end, width) {
5990
+ var glyphs = Math.min(width, end - start);
5991
+ return {
5992
+ start: start,
5993
+ end: start + glyphs
5994
+ };
5995
+ }
5996
+
5997
+ const X_HEIGHTS = [
5998
+ 'x',
5999
+ 'e',
6000
+ 'a',
6001
+ 'o',
6002
+ 'n',
6003
+ 's',
6004
+ 'r',
6005
+ 'c',
6006
+ 'u',
6007
+ 'm',
6008
+ 'v',
6009
+ 'w',
6010
+ 'z'
6011
+ ];
6012
+ const M_WIDTHS = [
6013
+ 'm',
6014
+ 'w'
6015
+ ];
6016
+ const CAP_HEIGHTS = [
6017
+ 'H',
6018
+ 'I',
6019
+ 'N',
6020
+ 'E',
6021
+ 'F',
6022
+ 'K',
6023
+ 'L',
6024
+ 'T',
6025
+ 'U',
6026
+ 'V',
6027
+ 'W',
6028
+ 'X',
6029
+ 'Y',
6030
+ 'Z'
6031
+ ];
6032
+ const TAB_ID = '\t'.charCodeAt(0);
6033
+ const SPACE_ID = ' '.charCodeAt(0);
6034
+ const ALIGN_LEFT = 0, ALIGN_CENTER = 1, ALIGN_RIGHT = 2;
6035
+ function findChar(array, value, start) {
6036
+ start = start || 0;
6037
+ for(let i = start; i < array.length; i++){
6038
+ if (array[i].id === value) {
6039
+ return i;
6040
+ }
6041
+ }
6042
+ return -1;
6043
+ }
6044
+ function getGlyphById(font, id) {
6045
+ if (!font.chars || font.chars.length === 0) return null;
6046
+ let glyphIdx = findChar(font.chars, id);
6047
+ if (glyphIdx >= 0) return font.chars[glyphIdx];
6048
+ return null;
6049
+ }
6050
+ function getXHeight(font) {
6051
+ for(let i = 0; i < X_HEIGHTS.length; i++){
6052
+ let id = X_HEIGHTS[i].charCodeAt(0);
6053
+ let idx = findChar(font.chars, id);
6054
+ if (idx >= 0) return font.chars[idx].height;
6055
+ }
6056
+ return 0;
6057
+ }
6058
+ function getMGlyph(font) {
6059
+ for(let i = 0; i < M_WIDTHS.length; i++){
6060
+ let id = M_WIDTHS[i].charCodeAt(0);
6061
+ let idx = findChar(font.chars, id);
6062
+ if (idx >= 0) return font.chars[idx];
6063
+ }
6064
+ return 0;
6065
+ }
6066
+ function getCapHeight(font) {
6067
+ for(let i = 0; i < CAP_HEIGHTS.length; i++){
6068
+ let id = CAP_HEIGHTS[i].charCodeAt(0);
6069
+ let idx = findChar(font.chars, id);
6070
+ if (idx >= 0) return font.chars[idx].height;
6071
+ }
6072
+ return 0;
6073
+ }
6074
+ function getKerning(font, left, right) {
6075
+ if (!font.kernings || font.kernings.length === 0) return 0;
6076
+ let table = font.kernings;
6077
+ for(let i = 0; i < table.length; i++){
6078
+ let kern = table[i];
6079
+ if (kern.first === left && kern.second === right) return kern.amount;
6080
+ }
6081
+ return 0;
6082
+ }
6083
+ function getAlignType(align) {
6084
+ if (align === 'center') return ALIGN_CENTER;
6085
+ else if (align === 'right') return ALIGN_RIGHT;
6086
+ return ALIGN_LEFT;
6087
+ }
6088
+ class BMFontTextLayout {
6089
+ get width() {
6090
+ return this._width;
6091
+ }
6092
+ get height() {
6093
+ return this._height;
6094
+ }
6095
+ get descender() {
6096
+ return this._descender;
6097
+ }
6098
+ get ascender() {
6099
+ return this._ascender;
6100
+ }
6101
+ get xHeight() {
6102
+ return this._xHeight;
6103
+ }
6104
+ get baseline() {
6105
+ return this._baseline;
6106
+ }
6107
+ get capHeight() {
6108
+ return this._capHeight;
6109
+ }
6110
+ get lineHeight() {
6111
+ return this._lineHeight;
6112
+ }
6113
+ get glyphs() {
6114
+ return this._glyphs;
6115
+ }
6116
+ get linesTotal() {
6117
+ return this._linesTotal;
6118
+ }
6119
+ update(font, text, setting) {
6120
+ setting = Object.assign({
6121
+ tabSize: 4,
6122
+ width: 0,
6123
+ letterSpacing: 0,
6124
+ mode: "nowrap",
6125
+ align: "left"
6126
+ }, setting);
6127
+ this._font = font;
6128
+ const measure = this._computeMetrics.bind(this);
6129
+ const lines = wordwrap(text, {
6130
+ measure,
6131
+ ...setting
6132
+ });
6133
+ const minWidth = setting.width || 0;
6134
+ const glyphs = this._glyphs;
6135
+ const maxLineWidth = lines.reduce((prev, line)=>Math.max(prev, line.width, minWidth), 0);
6136
+ var _setting_lineHeight;
6137
+ //the pen position
6138
+ const lineHeight = (_setting_lineHeight = setting.lineHeight) != null ? _setting_lineHeight : font.common.lineHeight;
6139
+ const baseline = font.common.base;
6140
+ const descender = lineHeight - baseline;
6141
+ const letterSpacing = setting.letterSpacing || 0;
6142
+ const height = lineHeight * lines.length - descender;
6143
+ const align = getAlignType(setting.align);
6144
+ var _setting_anchor;
6145
+ const anchor = (_setting_anchor = setting.anchor) != null ? _setting_anchor : [
6146
+ 0.5,
6147
+ 0.5
6148
+ ];
6149
+ this._setupSpaceGlyphs(font, setting);
6150
+ //the metrics for this text layout
6151
+ this._width = maxLineWidth;
6152
+ this._height = height;
6153
+ this._descender = descender;
6154
+ this._baseline = baseline;
6155
+ this._xHeight = getXHeight(font);
6156
+ this._capHeight = getCapHeight(font);
6157
+ this._lineHeight = lineHeight;
6158
+ this._ascender = baseline - this._xHeight; //lineHeight - descender - this._xHeight
6159
+ const anchorOffset = [
6160
+ -maxLineWidth * anchor[0],
6161
+ 2 * lineHeight * anchor[1] - baseline
6162
+ ];
6163
+ let x = 0, y = 0;
6164
+ //draw text along baseline
6165
+ y -= height;
6166
+ glyphs.length = 0;
6167
+ for(let k = 0; k < lines.length; k++){
6168
+ const line = lines[k];
6169
+ let start = line.start;
6170
+ let end = line.end;
6171
+ let lineWidth = line.width;
6172
+ let lastGlyph;
6173
+ //for each glyph in that line...
6174
+ for(let i = start; i < end; i++){
6175
+ let id = text.charCodeAt(i);
6176
+ let glyph = this._getGlyph(font, id);
6177
+ if (glyph) {
6178
+ if (lastGlyph) x += getKerning(font, lastGlyph.id, glyph.id);
6179
+ let tx = x;
6180
+ if (align === ALIGN_CENTER) tx += (maxLineWidth - lineWidth) / 2;
6181
+ else if (align === ALIGN_RIGHT) tx += maxLineWidth - lineWidth;
6182
+ glyphs.push({
6183
+ position: [
6184
+ tx + anchorOffset[0],
6185
+ y + anchorOffset[1]
6186
+ ],
6187
+ data: glyph,
6188
+ index: i,
6189
+ line: k
6190
+ });
6191
+ //move pen forward
6192
+ x += glyph.xadvance + letterSpacing;
6193
+ lastGlyph = glyph;
6194
+ }
6195
+ }
6196
+ //next line down
6197
+ y += lineHeight;
6198
+ x = 0;
6199
+ }
6200
+ this._linesTotal = lines.length;
6201
+ }
6202
+ _setupSpaceGlyphs(font, setting) {
6203
+ //These are fallbacks, when the font doesn't include
6204
+ //' ' or '\t' glyphs
6205
+ if (!font.chars || font.chars.length === 0) return;
6206
+ //try to get space glyph
6207
+ //then fall back to the 'm' or 'w' glyphs
6208
+ //then fall back to the first glyph available
6209
+ const space = Object.assign({}, getGlyphById(font, SPACE_ID) || getMGlyph(font) || font.chars[0]);
6210
+ //and create a fallback for tab
6211
+ const tabWidth = setting.tabSize * space.xadvance;
6212
+ this._fallbackSpaceGlyph = space;
6213
+ this._fallbackTabGlyph = Object.assign(space, {
6214
+ x: 0,
6215
+ y: 0,
6216
+ xadvance: tabWidth,
6217
+ id: TAB_ID,
6218
+ xoffset: 0,
6219
+ yoffset: 0,
6220
+ width: 0,
6221
+ height: 0
6222
+ });
6223
+ }
6224
+ _getGlyph(font, id) {
6225
+ let glyph = getGlyphById(font, id);
6226
+ if (glyph) return glyph;
6227
+ else if (id === TAB_ID) return this._fallbackTabGlyph;
6228
+ else if (id === SPACE_ID) return this._fallbackSpaceGlyph;
6229
+ return null;
6230
+ }
6231
+ _computeMetrics(text, start, end, width, letterSpacing = 0) {
6232
+ let font = this._font;
6233
+ let curPen = 0;
6234
+ let curWidth = 0;
6235
+ let count = 0;
6236
+ let lastGlyph;
6237
+ if (!font.chars || font.chars.length === 0) {
6238
+ return {
6239
+ start: start,
6240
+ end: start,
6241
+ width: 0
6242
+ };
6243
+ }
6244
+ end = Math.min(text.length, end);
6245
+ for(let i = start; i < end; i++){
6246
+ let id = text.charCodeAt(i);
6247
+ let glyph = this._getGlyph(font, id);
6248
+ if (glyph) {
6249
+ //move pen forward
6250
+ glyph.xoffset;
6251
+ let kern = lastGlyph ? getKerning(font, lastGlyph.id, glyph.id) : 0;
6252
+ curPen += kern;
6253
+ let nextPen = curPen + glyph.xadvance + letterSpacing;
6254
+ let nextWidth = curPen + glyph.width;
6255
+ //we've hit our limit; we can't move onto the next glyph
6256
+ if (nextWidth >= width || nextPen >= width) break;
6257
+ //otherwise continue along our line
6258
+ curPen = nextPen;
6259
+ curWidth = nextWidth;
6260
+ lastGlyph = glyph;
6261
+ }
6262
+ count++;
6263
+ }
6264
+ //make sure rightmost edge lines up with rendered glyphs
6265
+ if (lastGlyph) curWidth += lastGlyph.xoffset;
6266
+ return {
6267
+ start: start,
6268
+ end: start + count,
6269
+ width: curWidth
6270
+ };
6271
+ }
6272
+ constructor(){
6273
+ this._width = 0;
6274
+ this._height = 0;
6275
+ this._descender = 0;
6276
+ this._ascender = 0;
6277
+ this._xHeight = 0;
6278
+ this._baseline = 0;
6279
+ this._capHeight = 0;
6280
+ this._lineHeight = 0;
6281
+ this._linesTotal = 0;
6282
+ this._glyphs = [];
6283
+ this._fallbackSpaceGlyph = null;
6284
+ this._fallbackTabGlyph = null;
6285
+ this._font = null;
6286
+ }
6287
+ }
6288
+
6289
+ const itemSize = 2;
6290
+ const box = {
6291
+ min: [
6292
+ 0,
6293
+ 0
6294
+ ],
6295
+ max: [
6296
+ 0,
6297
+ 0
6298
+ ]
6299
+ };
6300
+ function bounds(positions) {
6301
+ const count = positions.length / itemSize;
6302
+ box.min[0] = positions[0];
6303
+ box.min[1] = positions[1];
6304
+ box.max[0] = positions[0];
6305
+ box.max[1] = positions[1];
6306
+ for(let i = 0; i < count; i++){
6307
+ const x = positions[i * itemSize + 0];
6308
+ const y = positions[i * itemSize + 1];
6309
+ box.min[0] = Math.min(x, box.min[0]);
6310
+ box.min[1] = Math.min(y, box.min[1]);
6311
+ box.max[0] = Math.max(x, box.max[0]);
6312
+ box.max[1] = Math.max(y, box.max[1]);
6313
+ }
6314
+ }
6315
+ function computeBox(positions, output) {
6316
+ bounds(positions);
6317
+ output.min.set(box.min[0], box.min[1], 0);
6318
+ output.max.set(box.max[0], box.max[1], 0);
6319
+ }
6320
+ function computeSphere(positions, output) {
6321
+ bounds(positions);
6322
+ const minX = box.min[0];
6323
+ const minY = box.min[1];
6324
+ const maxX = box.max[0];
6325
+ const maxY = box.max[1];
6326
+ const width = maxX - minX;
6327
+ const height = maxY - minY;
6328
+ const length = Math.sqrt(width * width + height * height);
6329
+ output.center.set(minX + width / 2, minY + height / 2, 0);
6330
+ output.radius = length / 2;
6331
+ }
6332
+
6333
+ class BMFontTextGeometry extends BufferGeometry {
6334
+ update(fontAtlas, text, setting) {
6335
+ this.layout.update(fontAtlas.info, text, setting);
6336
+ const { indice, position, uv } = fontAtlas.build(this.layout, setting);
6337
+ this.setIndex(new BufferAttribute(indice, 1));
6338
+ this.setAttribute("position", new BufferAttribute(position, 2));
6339
+ this.setAttribute("uv", new BufferAttribute(uv, 2));
6340
+ }
6341
+ computeBoundingSphere() {
6342
+ if (this.boundingSphere === null) {
6343
+ this.boundingSphere = new Sphere$1();
6344
+ }
6345
+ const positions = this.attributes.position.array;
6346
+ const itemSize = this.attributes.position.itemSize;
6347
+ if (!positions || !itemSize || positions.length < 2) {
6348
+ this.boundingSphere.radius = 0;
6349
+ this.boundingSphere.center.set(0, 0, 0);
6350
+ return;
6351
+ }
6352
+ computeSphere(positions, this.boundingSphere);
6353
+ if (isNaN(this.boundingSphere.radius)) {
6354
+ console.error('THREE.BufferGeometry.computeBoundingSphere(): ' + 'Computed radius is NaN. The ' + '"position" attribute is likely to have NaN values.');
6355
+ }
6356
+ }
6357
+ computeBoundingBox() {
6358
+ if (this.boundingBox === null) {
6359
+ this.boundingBox = new Box3();
6360
+ }
6361
+ const bbox = this.boundingBox;
6362
+ const positions = this.attributes.position["array"];
6363
+ const itemSize = this.attributes.position.itemSize;
6364
+ if (!positions || !itemSize || positions.length < 2) {
6365
+ bbox.makeEmpty();
6366
+ return;
6367
+ }
6368
+ computeBox(positions, bbox);
6369
+ }
6370
+ constructor(...args){
6371
+ super(...args), this.layout = new BMFontTextLayout();
6372
+ }
6373
+ }
6374
+
6375
+ class Label extends Component {
6376
+ get text() {
6377
+ return this._text;
6378
+ }
6379
+ set text(v) {
6380
+ if (this._text !== v) {
6381
+ this._text = v;
6382
+ this.needsUpdate = true;
6383
+ }
6384
+ }
6385
+ get font() {
6386
+ return this._font;
6387
+ }
6388
+ set font(v) {
6389
+ if (this._font !== v) {
6390
+ this._font = v;
6391
+ this.needsUpdate = true;
6392
+ }
6393
+ }
6394
+ get setting() {
6395
+ return this._setting;
6396
+ }
6397
+ set setting(v) {
6398
+ if (JSON.stringify(this._setting) !== JSON.stringify(v)) {
6399
+ this._setting = v;
6400
+ this.needsUpdate = true;
6401
+ }
6402
+ }
6403
+ get layout() {
6404
+ return this.node.geometry.layout;
6405
+ }
6406
+ forceUpdate() {
6407
+ this.node.geometry.update(this.font, this.text, this.setting);
6408
+ }
6409
+ update(dt) {
6410
+ if (this.needsUpdate) {
6411
+ this.needsUpdate = false;
6412
+ this.forceUpdate();
6413
+ }
6414
+ }
6415
+ constructor({ text = "", font, material, ...setting }){
6416
+ super(), this.needsUpdate = false, this._text = "", this._font = null, this._setting = null;
6417
+ this.text = text;
6418
+ this.font = font;
6419
+ this.setting = setting;
6420
+ this.node = new Mesh(new BMFontTextGeometry(), material || font.material);
6421
+ this.node.geometry.update(this.font, this.text, this.setting);
6422
+ }
6423
+ }
6424
+
6425
+ const vert_MSDF = `
6426
+ varying vec2 v_uv;
6427
+
6428
+ void main() {
6429
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
6430
+ v_uv = uv;
6431
+ }
6432
+ `;
6433
+ const frag_MSDF = `
6434
+ uniform sampler2D u_fontTexture;
6435
+ varying vec2 v_uv;
6436
+
6437
+ uniform vec3 u_color;
6438
+ uniform float u_opacity;
6439
+ uniform vec3 u_strokeColor;
6440
+ uniform float u_strokeWidth;
6441
+ uniform vec3 u_shadowColor;
6442
+ uniform float u_shadowBlur;
6443
+ uniform vec2 u_shadowOffset;
6444
+ uniform float u_weight;
6445
+
6446
+ float median(in float r, in float g, in float b) {
6447
+ return max(min(r, g), min(max(r, g), b));
6448
+ }
6449
+
6450
+ float signedDistance(in vec2 uv) {
6451
+ vec4 texel = texture2D(u_fontTexture, uv);
6452
+ return median(texel.r, texel.g, texel.b) - 0.5;
6453
+ }
6454
+
6455
+ void main() {
6456
+ vec4 color = vec4(u_color, 1.);
6457
+ float d = signedDistance(v_uv) + u_weight;
6458
+ float w = fwidth(d);
6459
+
6460
+ vec4 stroke = vec4(u_strokeColor, smoothstep(-w, w, d));
6461
+ color.a *= smoothstep(-w, w, d - u_strokeWidth);
6462
+ color = mix(stroke, color, color.a);
6463
+
6464
+ float sd = signedDistance(v_uv + u_shadowOffset) + u_weight;
6465
+ vec4 shadow = vec4(u_shadowColor, smoothstep(-w - u_shadowBlur, w + u_shadowBlur, sd));
6466
+ color = mix(shadow, color, color.a);
6467
+
6468
+ color.a *= u_opacity;
6469
+ gl_FragColor = color;
6470
+ }
6471
+ `;
6472
+ class BMFontAtlas {
6473
+ build(layout, setting) {
6474
+ const info = this.info;
6475
+ const texWidth = info.common.scaleW;
6476
+ const texHeight = info.common.scaleH;
6477
+ const glyphs = layout.glyphs.filter((glyph)=>glyph.data.width * glyph.data.height > 0);
6478
+ const flipY = setting.flipY !== false;
6479
+ const position = new Float32Array(glyphs.length * 8);
6480
+ const uv = new Float32Array(glyphs.length * 8);
6481
+ const indice = new Uint16Array(glyphs.length * 6);
6482
+ for(let k = 0, i0 = 0, i1 = 0, i2 = 0, i = 0; i < glyphs.length; i++, k += 4){
6483
+ const glyph = glyphs[i];
6484
+ const bitmap = glyph.data;
6485
+ // bottom left position
6486
+ let x = glyph.position[0] + bitmap.xoffset;
6487
+ let y = glyph.position[1] + bitmap.yoffset;
6488
+ // quad size
6489
+ let w = bitmap.width;
6490
+ let h = bitmap.height;
6491
+ // BL
6492
+ position[i0++] = x;
6493
+ position[i0++] = y;
6494
+ // BR
6495
+ position[i0++] = x + w;
6496
+ position[i0++] = y;
6497
+ // TR
6498
+ position[i0++] = x + w;
6499
+ position[i0++] = y + h;
6500
+ // TL
6501
+ position[i0++] = x;
6502
+ position[i0++] = y + h;
6503
+ let bw = bitmap.x + bitmap.width;
6504
+ let bh = bitmap.y + bitmap.height;
6505
+ // top left position
6506
+ let u0 = bitmap.x / texWidth;
6507
+ let v0 = bitmap.y / texHeight;
6508
+ let u1 = bw / texWidth;
6509
+ let v1 = bh / texHeight;
6510
+ if (flipY) {
6511
+ v0 = 1 - v0;
6512
+ v1 = 1 - v1;
6513
+ }
6514
+ // BL
6515
+ uv[i1++] = u0;
6516
+ uv[i1++] = v0;
6517
+ // BR
6518
+ uv[i1++] = u1;
6519
+ uv[i1++] = v0;
6520
+ // TR
6521
+ uv[i1++] = u1;
6522
+ uv[i1++] = v1;
6523
+ // TL
6524
+ uv[i1++] = u0;
6525
+ uv[i1++] = v1;
6526
+ indice[i2++] = k + 0;
6527
+ indice[i2++] = k + 1;
6528
+ indice[i2++] = k + 2;
6529
+ indice[i2++] = k + 0;
6530
+ indice[i2++] = k + 2;
6531
+ indice[i2++] = k + 3;
6532
+ }
6533
+ return {
6534
+ position,
6535
+ uv,
6536
+ indice
6537
+ };
6538
+ }
6539
+ constructor({ info, texture, uniforms, ...props }){
6540
+ this.uniforms = {
6541
+ u_color: {
6542
+ value: new Color(0xffffff)
6543
+ },
6544
+ u_opacity: {
6545
+ value: 1
6546
+ },
6547
+ u_weight: {
6548
+ value: 0.2
6549
+ },
6550
+ u_strokeColor: {
6551
+ value: new Color(0xff0000)
6552
+ },
6553
+ u_strokeWidth: {
6554
+ value: 0
6555
+ },
6556
+ u_shadowColor: {
6557
+ value: new Color(0xff0000)
6558
+ },
6559
+ u_shadowBlur: {
6560
+ value: 0
6561
+ },
6562
+ u_shadowOffset: {
6563
+ value: new Vector2()
6564
+ },
6565
+ u_fontTexture: {
6566
+ value: null
6567
+ }
6568
+ };
6569
+ this.info = info;
6570
+ this.uniforms.u_fontTexture.value = texture;
6571
+ this.material = new ShaderMaterial(Object.assign({
6572
+ vertexShader: vert_MSDF,
6573
+ fragmentShader: frag_MSDF,
6574
+ transparent: true,
6575
+ depthWrite: false,
6576
+ blending: NormalBlending,
6577
+ uniforms: {
6578
+ ...this.uniforms,
6579
+ ...uniforms
6580
+ }
6581
+ }, props));
6582
+ }
6583
+ }
6584
+
6585
+ export { AccumulativeShadows, Animation, AnimationCurve, BINLoader, BMFontAtlas, BMFontTextGeometry, BMFontTextLayout, Box, BoxProjection, Center, Component, ContactShadows, DependentMode, DeviceInput, DropFile, EXRLoader, Easing, Environment, EventEmitter, FBXLoader, FInterpConstantTo, FInterpTo, FreelookVirtualCamera, GLTFLoader, HDRLoader, JSONLoader, KTX2Loader, Label, Loader, Logger, ObjectInstance, Orientation, PerformanceMonitor, Perlin, Plane, PropertyManager, QInterpConstantTo, QInterpTo, Quat_AngularDistance, Quat_Equals, Quat_exponentialDamp, Quat_quarticDamp, Quat_smoothDamp, RandomizedLight, Reflector, ReflectorMaterial, RenderTexture, Renderer, ResizeMode, ResourceManager, SVGLoader, ShadowMaterial, Sphere, SystemInfo, Task, TextureLoader, VInterpConstantTo, VInterpTo, Vec3_smoothDamp, Vector3_NEG_ONE, Vector3_ONE, Vector3_RIGHT, Vector3_UNIT_X, Vector3_UNIT_Y, Vector3_UNIT_Z, Vector3_UP, Vector3_ZERO, Viewer, applyProps, dependencies, exponentialDamp, find, frag_BoxfilterBlur, frag_cubeMapToPanorama, frag_panoramaToCubeMap, getChildByName, getChildren, getClassInstance, getShaderMaterial, mixin, property, quarticDamp, queryValues, smoothDamp, vert_fullscreen };
5794
6586
  //# sourceMappingURL=module.js.map