@mml-io/3d-web-client-core 0.12.0 → 0.12.2

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/build/index.js CHANGED
@@ -100,8 +100,8 @@ var CameraManager = class {
100
100
  this.maxDistance = 8;
101
101
  this.initialFOV = 60;
102
102
  this.fov = this.initialFOV;
103
- this.minFOV = 50;
104
- this.maxFOV = 70;
103
+ this.minFOV = 85;
104
+ this.maxFOV = 60;
105
105
  this.targetFOV = this.initialFOV;
106
106
  this.minPolarAngle = Math.PI * 0.25;
107
107
  this.maxPolarAngle = Math.PI * 0.95;
@@ -199,10 +199,12 @@ var CameraManager = class {
199
199
  this.fov = this.targetFOV;
200
200
  }
201
201
  adjustCameraPosition() {
202
- this.rayCaster.set(
203
- this.camera.position,
204
- this.target.clone().sub(this.camera.position).normalize()
205
- );
202
+ const offsetDistance = 0.5;
203
+ const offset = new Vector32(0, 0, offsetDistance);
204
+ offset.applyEuler(this.camera.rotation);
205
+ const rayOrigin = this.camera.position.clone().add(offset);
206
+ const rayDirection = this.target.clone().sub(rayOrigin).normalize();
207
+ this.rayCaster.set(rayOrigin, rayDirection);
206
208
  const firstRaycastHit = this.collisionsManager.raycastFirst(this.rayCaster.ray);
207
209
  const cameraToPlayerDistance = this.camera.position.distanceTo(this.target);
208
210
  if (firstRaycastHit !== null && firstRaycastHit[0] <= cameraToPlayerDistance) {
@@ -260,7 +262,7 @@ import { Color as Color3, Group, Vector3 as Vector34 } from "three";
260
262
 
261
263
  // src/character/CharacterModel.ts
262
264
  import {
263
- Character as MMLCharacter,
265
+ MMLCharacter,
264
266
  ModelLoader,
265
267
  parseMMLDescription
266
268
  } from "@mml-io/3d-web-avatar";
@@ -271,7 +273,7 @@ import {
271
273
  } from "three";
272
274
 
273
275
  // src/character/CharacterMaterial.ts
274
- import { Color, MeshPhysicalMaterial, UniformsUtils } from "three";
276
+ import { Color, MeshStandardMaterial, UniformsUtils } from "three";
275
277
 
276
278
  // src/rendering/shaders/bayer-dither.ts
277
279
  var bayerDither = (
@@ -365,50 +367,23 @@ ${before}
365
367
 
366
368
  // src/tweakpane/blades/characterFolder.ts
367
369
  var characterValues = {
368
- transmission: 0.01,
369
370
  metalness: 0.2,
370
371
  roughness: 0.8,
371
- ior: 1,
372
- thickness: 0.1,
373
- specularColor: { r: 1, g: 1, b: 1 },
374
- specularIntensity: 0.1,
375
372
  emissive: { r: 1, g: 1, b: 1 },
376
373
  emissiveIntensity: 0.01,
377
- envMapIntensity: 0.12,
378
- sheenColor: { r: 1, g: 1, b: 1 },
379
- sheen: 0.5,
380
- clearcoat: 0,
381
- clearcoatRoughness: 0
374
+ envMapIntensity: 0.12
382
375
  };
383
376
  var characterOptions = {
384
- transmission: { min: 0.01, max: 3, step: 0.01 },
385
377
  metalness: { min: 0, max: 1, step: 0.01 },
386
378
  roughness: { min: 0, max: 1, step: 0.01 },
387
- ior: { min: 1, max: 5, step: 0.01 },
388
- thickness: { min: 0, max: 1, step: 0.01 },
389
- specularIntensity: { min: 0, max: 1, step: 0.01 },
390
379
  emissiveIntensity: { min: 0, max: 1, step: 0.01 },
391
- envMapIntensity: { min: 0, max: 1, step: 0.01 },
392
- sheen: { min: 0, max: 1, step: 0.01 },
393
- clearcoat: { min: 0, max: 1, step: 0.01 },
394
- clearcoatRoughness: { min: 0, max: 1, step: 0.01 }
380
+ envMapIntensity: { min: 0, max: 1, step: 0.01 }
395
381
  };
396
382
  var CharacterFolder = class {
397
383
  constructor(parentFolder, expand = false) {
398
384
  this.folder = parentFolder.addFolder({ title: "characterMaterial", expanded: expand });
399
- this.folder.addBinding(characterValues, "transmission", characterOptions.transmission);
400
385
  this.folder.addBinding(characterValues, "metalness", characterOptions.metalness);
401
386
  this.folder.addBinding(characterValues, "roughness", characterOptions.roughness);
402
- this.folder.addBinding(characterValues, "ior", characterOptions.ior);
403
- this.folder.addBinding(characterValues, "thickness", characterOptions.thickness);
404
- this.folder.addBinding(characterValues, "specularColor", {
405
- color: { type: "float" }
406
- });
407
- this.folder.addBinding(
408
- characterValues,
409
- "specularIntensity",
410
- characterOptions.specularIntensity
411
- );
412
387
  this.folder.addBinding(characterValues, "emissive", {
413
388
  color: { type: "float" }
414
389
  });
@@ -418,16 +393,6 @@ var CharacterFolder = class {
418
393
  characterOptions.emissiveIntensity
419
394
  );
420
395
  this.folder.addBinding(characterValues, "envMapIntensity", characterOptions.envMapIntensity);
421
- this.folder.addBinding(characterValues, "sheenColor", {
422
- color: { type: "float" }
423
- });
424
- this.folder.addBinding(characterValues, "sheen", characterOptions.sheen);
425
- this.folder.addBinding(characterValues, "clearcoat", characterOptions.clearcoat);
426
- this.folder.addBinding(
427
- characterValues,
428
- "clearcoatRoughness",
429
- characterOptions.clearcoatRoughness
430
- );
431
396
  }
432
397
  setupChangeEvent() {
433
398
  this.folder.on("change", (e) => {
@@ -435,15 +400,6 @@ var CharacterFolder = class {
435
400
  if (!target)
436
401
  return;
437
402
  switch (target) {
438
- case "specularColor": {
439
- const value = e.value;
440
- characterValues.specularColor = {
441
- r: value.r,
442
- g: value.g,
443
- b: value.b
444
- };
445
- break;
446
- }
447
403
  case "emissive": {
448
404
  const value = e.value;
449
405
  characterValues.emissive = {
@@ -453,15 +409,6 @@ var CharacterFolder = class {
453
409
  };
454
410
  break;
455
411
  }
456
- case "sheenColor": {
457
- const value = e.value;
458
- characterValues.sheenColor = {
459
- r: value.r,
460
- g: value.g,
461
- b: value.b
462
- };
463
- break;
464
- }
465
412
  default: {
466
413
  break;
467
414
  }
@@ -471,83 +418,59 @@ var CharacterFolder = class {
471
418
  };
472
419
 
473
420
  // src/character/CharacterMaterial.ts
474
- var CharacterMaterial = class extends MeshPhysicalMaterial {
475
- constructor(color) {
421
+ var CharacterMaterial = class extends MeshStandardMaterial {
422
+ constructor(isLocal, cameraManager, characterId, originalMaterial, colorOverride) {
476
423
  super();
477
- this.uniforms = {};
424
+ this.isLocal = isLocal;
425
+ this.cameraManager = cameraManager;
426
+ this.characterId = characterId;
427
+ this.originalMaterial = originalMaterial;
428
+ this.colorOverride = colorOverride;
429
+ this.uniforms = {
430
+ discardAll: { value: 1 },
431
+ diffuseColor: { value: new Color() },
432
+ map: { value: null }
433
+ };
478
434
  this.colorsCube216 = [];
479
- if (color) {
480
- this.color = color;
481
- }
482
- this.transmission = characterValues.transmission;
483
- this.metalness = characterValues.metalness;
484
- this.roughness = characterValues.roughness;
485
- this.ior = characterValues.ior;
486
- this.thickness = characterValues.thickness;
487
- this.specularColor = new Color().setRGB(
488
- characterValues.specularColor.r,
489
- characterValues.specularColor.g,
490
- characterValues.specularColor.b
491
- );
492
- this.specularIntensity = characterValues.specularIntensity;
493
- this.emissive = new Color().setRGB(
494
- characterValues.emissive.r,
495
- characterValues.emissive.g,
496
- characterValues.emissive.b
497
- );
498
- this.emissiveIntensity = characterValues.emissiveIntensity;
435
+ this.targetAlpha = 1;
436
+ this.currentAlpha = 1;
437
+ this.copy(this.originalMaterial);
438
+ this.generateColorCube();
439
+ this.color = this.colorOverride || this.colorsCube216[this.characterId];
499
440
  this.envMapIntensity = characterValues.envMapIntensity;
500
- this.sheenColor = new Color().setRGB(
501
- characterValues.sheenColor.r,
502
- characterValues.sheenColor.g,
503
- characterValues.sheenColor.b
504
- );
505
- this.sheen = characterValues.sheen;
506
- this.clearcoat = characterValues.clearcoat;
507
- this.clearcoatRoughness = characterValues.clearcoatRoughness;
441
+ this.transparent = true;
442
+ this.side = this.originalMaterial.side;
508
443
  this.onBeforeCompile = (shader) => {
509
444
  this.uniforms = UniformsUtils.clone(shader.uniforms);
510
445
  this.uniforms.nearClip = { value: 0.01 };
511
446
  this.uniforms.farClip = { value: 1e3 };
512
- this.uniforms.ditheringNear = { value: 0.25 };
447
+ this.uniforms.ditheringNear = { value: 0.3 };
513
448
  this.uniforms.ditheringRange = { value: 0.5 };
514
449
  this.uniforms.time = { value: 0 };
515
450
  this.uniforms.diffuseRandomColor = { value: new Color() };
451
+ this.uniforms.discardAll = { value: 0 };
516
452
  shader.uniforms = this.uniforms;
453
+ shader.vertexShader = "varying vec3 vWorldPosition;\n" + shader.vertexShader;
454
+ shader.vertexShader = shader.vertexShader.replace(
455
+ "#include <worldpos_vertex>",
456
+ "vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\nvWorldPosition = worldPosition.xyz;"
457
+ );
517
458
  shader.vertexShader = injectBeforeMain(shader.vertexShader, "varying vec2 vUv;");
518
459
  shader.vertexShader = injectInsideMain(shader.vertexShader, "vUv = uv;");
519
460
  shader.fragmentShader = injectBeforeMain(
520
461
  shader.fragmentShader,
521
462
  /* glsl */
522
463
  `
523
- //#define showPattern
524
464
  varying vec2 vUv;
465
+ varying vec3 vWorldPosition;
525
466
  uniform float nearClip;
526
467
  uniform float farClip;
527
468
  uniform float ditheringNear;
528
469
  uniform float ditheringRange;
529
470
  uniform float time;
530
471
  uniform vec3 diffuseRandomColor;
472
+ uniform int discardAll;
531
473
  ${bayerDither}
532
-
533
- #ifdef showPattern
534
- vec2 rand2(vec2 p) {
535
- return fract(vec2(sin(p.x * 591.32 + p.y * 154.077), cos(p.x * 391.32 + p.y * 49.077)));
536
- }
537
- float voronoi(in vec2 x) {
538
- vec2 p = floor(x);
539
- vec2 f = fract(x);
540
- float minDistance = 1.0;
541
- for(int j = -1; j <= 1; j ++)
542
- for(int i = -1; i <= 1; i ++) {
543
- vec2 b = vec2(i, j);
544
- vec2 rand = 0.5 + 0.5 * sin(time * 1.5 + 12.0 * rand2(p + b));
545
- vec2 r = vec2(b) - f + rand;
546
- minDistance = min(minDistance, length(r));
547
- }
548
- return minDistance;
549
- }
550
- #endif
551
474
  `
552
475
  );
553
476
  shader.fragmentShader = injectBefore(
@@ -555,42 +478,32 @@ var CharacterMaterial = class extends MeshPhysicalMaterial {
555
478
  "#include <output_fragment>",
556
479
  /* glsl */
557
480
  `
558
- float distance = length(vWorldPosition - cameraPosition);
559
- float normalizedDistance = (distance - nearClip) / (farClip - nearClip);
560
- ivec2 p = ivec2(mod(gl_FragCoord.xy, 8.0));
561
- float d = 0.0;
562
- if (p.x <= 3 && p.y <= 3) {
563
- d = bayerDither(bayertl, p);
564
- } else if (p.x > 3 && p.y <= 3) {
565
- d = bayerDither(bayertr, p - ivec2(4, 0));
566
- } else if (p.x <= 3 && p.y > 3) {
567
- d = bayerDither(bayerbl, p - ivec2(0, 4));
568
- } else if (p.x > 3 && p.y > 3) {
569
- d = bayerDither(bayerbr, p - ivec2(4, 4));
481
+ if (discardAll == 1) {
482
+ discard;
483
+ } else {
484
+ float distance = length(vWorldPosition - cameraPosition);
485
+ float normalizedDistance = (distance - nearClip) / (farClip - nearClip);
486
+ ivec2 p = ivec2(mod(gl_FragCoord.xy, 8.0));
487
+ float d = 0.0;
488
+ if (p.x <= 3 && p.y <= 3) {
489
+ d = bayerDither(bayertl, p);
490
+ } else if (p.x > 3 && p.y <= 3) {
491
+ d = bayerDither(bayertr, p - ivec2(4, 0));
492
+ } else if (p.x <= 3 && p.y > 3) {
493
+ d = bayerDither(bayerbl, p - ivec2(0, 4));
494
+ } else if (p.x > 3 && p.y > 3) {
495
+ d = bayerDither(bayerbr, p - ivec2(4, 4));
496
+ }
497
+ if (distance <= ditheringNear + d * ditheringRange) discard;
498
+ outgoingLight *= diffuseRandomColor;
570
499
  }
571
- if (distance <= ditheringNear + d * ditheringRange) discard;
572
-
573
- vec2 uv = vUv;
574
- float s = clamp(0.35 + 0.35 * sin(5.0 * -time + vUv.y * 600.0), 0.0, 1.0);
575
- float scanLines = pow(s, 1.33);
576
-
577
- outgoingLight *= diffuseRandomColor;
578
-
579
- #ifdef showPattern
580
- float val = pow(voronoi(uv * 8.0) * 1.2, 0.5);
581
- float thickness = 1.0 / 500.0;
582
- vec2 g = step(mod(uv, 0.015), vec2(thickness));
583
- float a = 1.0 - clamp(val * (g.x + g.y), 0.0, 1.0);
584
- vec3 grid = vec3(smoothstep(0.01, 0.0, a) * 1.15) * diffuseRandomColor;
585
- outgoingLight += grid;
586
- #endif
587
500
  `
588
501
  );
589
502
  };
590
- this.generateColorCube();
503
+ this.needsUpdate = true;
591
504
  }
592
505
  generateColorCube() {
593
- const saturation = 0.5;
506
+ const saturation = 1;
594
507
  const lightness = 0.9;
595
508
  const goldenRatioConjugate = 0.618033988749895;
596
509
  let hue = 0;
@@ -602,17 +515,24 @@ var CharacterMaterial = class extends MeshPhysicalMaterial {
602
515
  }
603
516
  }
604
517
  update() {
605
- this.transmission = characterValues.transmission;
518
+ if (this.isLocal) {
519
+ this.targetAlpha = this.cameraManager.targetDistance < 0.4 ? 0 : 1;
520
+ this.currentAlpha += ease(this.targetAlpha, this.currentAlpha, 0.07);
521
+ if (this.currentAlpha > 0.999) {
522
+ this.currentAlpha = 1;
523
+ this.cameraManager.minPolarAngle = Math.PI * 0.25;
524
+ }
525
+ if (this.currentAlpha < 1e-3) {
526
+ this.currentAlpha = 0;
527
+ this.cameraManager.minPolarAngle = Math.PI * 0.35;
528
+ }
529
+ this.uniforms.discardAll.value = this.currentAlpha === 0 ? 1 : 0;
530
+ if (this.currentAlpha !== this.opacity) {
531
+ this.opacity = this.currentAlpha;
532
+ }
533
+ }
606
534
  this.metalness = characterValues.metalness;
607
535
  this.roughness = characterValues.roughness;
608
- this.ior = characterValues.ior;
609
- this.thickness = characterValues.thickness;
610
- this.specularColor = new Color().setRGB(
611
- characterValues.specularColor.r,
612
- characterValues.specularColor.g,
613
- characterValues.specularColor.b
614
- );
615
- this.specularIntensity = characterValues.specularIntensity;
616
536
  this.emissive = new Color().setRGB(
617
537
  characterValues.emissive.r,
618
538
  characterValues.emissive.g,
@@ -620,14 +540,6 @@ var CharacterMaterial = class extends MeshPhysicalMaterial {
620
540
  );
621
541
  this.emissiveIntensity = characterValues.emissiveIntensity;
622
542
  this.envMapIntensity = characterValues.envMapIntensity;
623
- this.sheenColor = new Color().setRGB(
624
- characterValues.sheenColor.r,
625
- characterValues.sheenColor.g,
626
- characterValues.sheenColor.b
627
- );
628
- this.sheen = characterValues.sheen;
629
- this.clearcoat = characterValues.clearcoat;
630
- this.clearcoatRoughness = characterValues.clearcoatRoughness;
631
543
  }
632
544
  };
633
545
 
@@ -644,13 +556,16 @@ var AnimationState = /* @__PURE__ */ ((AnimationState2) => {
644
556
 
645
557
  // src/character/CharacterModel.ts
646
558
  var CharacterModel = class {
647
- constructor(characterDescription, animationConfig, characterModelLoader) {
559
+ constructor(characterDescription, animationConfig, characterModelLoader, cameraManager, characterId, isLocal) {
648
560
  this.characterDescription = characterDescription;
649
561
  this.animationConfig = animationConfig;
650
562
  this.characterModelLoader = characterModelLoader;
563
+ this.cameraManager = cameraManager;
564
+ this.characterId = characterId;
565
+ this.isLocal = isLocal;
651
566
  this.mesh = null;
652
- this.material = new CharacterMaterial();
653
567
  this.headBone = null;
568
+ this.materials = /* @__PURE__ */ new Map();
654
569
  this.animations = {};
655
570
  this.animationMixer = null;
656
571
  this.currentAnimation = 0 /* idle */;
@@ -667,22 +582,32 @@ var CharacterModel = class {
667
582
  2 /* running */
668
583
  );
669
584
  await this.setAnimationFromFile(this.animationConfig.airAnimationFileUrl, 4 /* air */);
670
- if (this.characterDescription.meshFileUrl) {
671
- this.applyCustomMaterial(this.material);
672
- }
585
+ this.applyCustomMaterials();
673
586
  }
674
- applyCustomMaterial(material) {
587
+ applyCustomMaterials() {
675
588
  if (!this.mesh)
676
589
  return;
677
590
  this.mesh.traverse((child) => {
678
- const asSkinnedMesh = child;
679
- if (asSkinnedMesh.isSkinnedMesh) {
680
- const mat = asSkinnedMesh.material;
681
- if (!mat.name.includes("joints")) {
682
- asSkinnedMesh.material = material;
591
+ if (child.isMesh || child.isSkinnedMesh) {
592
+ const asMesh = child;
593
+ const originalMaterial = asMesh.material;
594
+ if (this.materials.has(originalMaterial.name)) {
595
+ asMesh.material = this.materials.get(originalMaterial.name);
683
596
  } else {
684
- const color = mat.color;
685
- asSkinnedMesh.material = new CharacterMaterial(color);
597
+ const material = originalMaterial.name === "body_replaceable_color" ? new CharacterMaterial(
598
+ this.isLocal,
599
+ this.cameraManager,
600
+ this.characterId,
601
+ originalMaterial
602
+ ) : new CharacterMaterial(
603
+ this.isLocal,
604
+ this.cameraManager,
605
+ this.characterId,
606
+ originalMaterial,
607
+ originalMaterial.color
608
+ );
609
+ this.materials.set(originalMaterial.name, material);
610
+ asMesh.material = material;
686
611
  }
687
612
  }
688
613
  });
@@ -704,7 +629,7 @@ var CharacterModel = class {
704
629
  this.animationMixer = new AnimationMixer(this.mesh);
705
630
  }
706
631
  async composeMMLCharacter(mmlCharacterDescription) {
707
- var _a, _b, _c;
632
+ var _a, _b;
708
633
  if (((_a = mmlCharacterDescription.base) == null ? void 0 : _a.url.length) === 0) {
709
634
  throw new Error(
710
635
  "ERROR: An MML Character Description was provided but it's not a valid <m-character> string, or a valid URL"
@@ -713,14 +638,13 @@ var CharacterModel = class {
713
638
  let mergedCharacter = null;
714
639
  if (mmlCharacterDescription) {
715
640
  const characterBase = ((_b = mmlCharacterDescription.base) == null ? void 0 : _b.url) || null;
716
- const parts = [];
717
- (_c = mmlCharacterDescription.parts) == null ? void 0 : _c.forEach((part) => {
718
- if (part.url)
719
- parts.push(part.url);
720
- });
721
641
  if (characterBase) {
642
+ this.mmlCharacterDescription = mmlCharacterDescription;
722
643
  const mmlCharacter = new MMLCharacter(new ModelLoader());
723
- mergedCharacter = await mmlCharacter.mergeBodyParts(characterBase, parts);
644
+ mergedCharacter = await mmlCharacter.mergeBodyParts(
645
+ characterBase,
646
+ mmlCharacterDescription.parts
647
+ );
724
648
  if (mergedCharacter) {
725
649
  return mergedCharacter.children[0].children[0];
726
650
  }
@@ -812,6 +736,7 @@ var CharacterModel = class {
812
736
  update(time) {
813
737
  if (this.animationMixer) {
814
738
  this.animationMixer.update(time);
739
+ this.materials.forEach((material) => material.update());
815
740
  }
816
741
  }
817
742
  };
@@ -820,7 +745,7 @@ var CharacterModel = class {
820
745
  import {
821
746
  CircleGeometry,
822
747
  GLSL3,
823
- Mesh,
748
+ Mesh as Mesh2,
824
749
  RawShaderMaterial
825
750
  } from "three";
826
751
  var CharacterSpeakingIndicator = class {
@@ -884,7 +809,7 @@ var CharacterSpeakingIndicator = class {
884
809
  transparent: true,
885
810
  glslVersion: GLSL3
886
811
  });
887
- this.mesh = new Mesh(this.geometry, this.material);
812
+ this.mesh = new Mesh2(this.geometry, this.material);
888
813
  this.currentAlpha = 0;
889
814
  this.targetAlpha = 0;
890
815
  this.scene.add(this.mesh);
@@ -913,13 +838,13 @@ import {
913
838
  Color as Color2,
914
839
  FrontSide,
915
840
  LinearFilter as LinearFilter2,
916
- Mesh as Mesh2,
841
+ Mesh as Mesh3,
917
842
  MeshBasicMaterial as MeshBasicMaterial2,
918
843
  PlaneGeometry
919
844
  } from "three";
920
845
 
921
846
  // src/character/CanvasText.ts
922
- import { Texture, LinearFilter, RGBAFormat, MeshBasicMaterial } from "three";
847
+ import { Texture as Texture2, LinearFilter, RGBAFormat, MeshBasicMaterial } from "three";
923
848
  function getTextAlignOffset(textAlign, width) {
924
849
  switch (textAlign) {
925
850
  case "center":
@@ -1020,7 +945,7 @@ function CanvasText(message, options) {
1020
945
  }
1021
946
  function THREECanvasTextTexture(text, options) {
1022
947
  const canvas = CanvasText(text, options);
1023
- const texture = new Texture(canvas);
948
+ const texture = new Texture2(canvas);
1024
949
  texture.minFilter = LinearFilter;
1025
950
  texture.magFilter = LinearFilter;
1026
951
  texture.format = RGBAFormat;
@@ -1039,7 +964,7 @@ var defaultLabelWidth = 0.25;
1039
964
  var defaultLabelHeight = 0.125;
1040
965
  var defaultLabelCastShadows = true;
1041
966
  var tooltipGeometry = new PlaneGeometry(1, 1, 1, 1);
1042
- var CharacterTooltip = class extends Mesh2 {
967
+ var CharacterTooltip = class extends Mesh3 {
1043
968
  constructor() {
1044
969
  super(tooltipGeometry);
1045
970
  this.visibleOpacity = 0.85;
@@ -1146,7 +1071,7 @@ var CharacterTooltip = class extends Mesh2 {
1146
1071
 
1147
1072
  // src/character/Character.ts
1148
1073
  var Character = class extends Group {
1149
- constructor(characterDescription, animationConfig, characterModelLoader, characterId, modelLoadedCallback, cameraManager, composer) {
1074
+ constructor(characterDescription, animationConfig, characterModelLoader, characterId, modelLoadedCallback, cameraManager, composer, isLocal) {
1150
1075
  super();
1151
1076
  this.characterDescription = characterDescription;
1152
1077
  this.animationConfig = animationConfig;
@@ -1155,6 +1080,7 @@ var Character = class extends Group {
1155
1080
  this.modelLoadedCallback = modelLoadedCallback;
1156
1081
  this.cameraManager = cameraManager;
1157
1082
  this.composer = composer;
1083
+ this.isLocal = isLocal;
1158
1084
  this.model = null;
1159
1085
  this.color = new Color3();
1160
1086
  this.tooltip = null;
@@ -1167,14 +1093,16 @@ var Character = class extends Group {
1167
1093
  this.model = new CharacterModel(
1168
1094
  this.characterDescription,
1169
1095
  this.animationConfig,
1170
- this.characterModelLoader
1096
+ this.characterModelLoader,
1097
+ this.cameraManager,
1098
+ this.characterId,
1099
+ this.isLocal
1171
1100
  );
1172
1101
  await this.model.init();
1173
1102
  this.add(this.model.mesh);
1174
1103
  if (this.speakingIndicator === null) {
1175
1104
  this.speakingIndicator = new CharacterSpeakingIndicator(this.composer.postPostScene);
1176
1105
  }
1177
- this.color = this.model.material.colorsCube216[this.characterId];
1178
1106
  this.modelLoadedCallback();
1179
1107
  }
1180
1108
  updateAnimation(targetAnimation) {
@@ -1197,11 +1125,6 @@ var Character = class extends Group {
1197
1125
  );
1198
1126
  }
1199
1127
  }
1200
- if (typeof this.model.material.uniforms.time !== "undefined") {
1201
- this.model.material.uniforms.time.value = time;
1202
- this.model.material.uniforms.diffuseRandomColor.value = this.color;
1203
- this.model.material.update();
1204
- }
1205
1128
  this.model.update(deltaTime);
1206
1129
  }
1207
1130
  getCurrentAnimation() {
@@ -1611,8 +1534,6 @@ var CharacterManager = class {
1611
1534
  this.remoteCharacterControllers = /* @__PURE__ */ new Map();
1612
1535
  this.localCharacterSpawned = false;
1613
1536
  this.localCharacter = null;
1614
- this.cameraOffsetTarget = 0;
1615
- this.cameraOffset = 0;
1616
1537
  this.speakingCharacters = /* @__PURE__ */ new Map();
1617
1538
  this.group = new Group2();
1618
1539
  }
@@ -1626,7 +1547,8 @@ var CharacterManager = class {
1626
1547
  () => {
1627
1548
  },
1628
1549
  this.cameraManager,
1629
- this.composer
1550
+ this.composer,
1551
+ true
1630
1552
  );
1631
1553
  const quaternion = new Quaternion5().setFromEuler(character.rotation);
1632
1554
  this.sendUpdate({
@@ -1665,7 +1587,8 @@ var CharacterManager = class {
1665
1587
  () => {
1666
1588
  },
1667
1589
  this.cameraManager,
1668
- this.composer
1590
+ this.composer,
1591
+ false
1669
1592
  );
1670
1593
  this.remoteCharacters.set(id, character);
1671
1594
  const remoteController = new RemoteController(character, id);
@@ -1712,12 +1635,9 @@ var CharacterManager = class {
1712
1635
  if (this.timeManager.frame % 2 === 0) {
1713
1636
  this.sendUpdate(this.localController.networkState);
1714
1637
  }
1715
- this.cameraOffsetTarget = this.cameraManager.targetDistance <= 0.4 ? 0.13 : 0;
1716
- this.cameraOffset += ease(this.cameraOffsetTarget, this.cameraOffset, 0.1);
1717
- const targetOffset = new Vector38(0, 0, this.cameraOffset);
1718
- targetOffset.add(this.headTargetOffset);
1719
- targetOffset.applyQuaternion(this.localCharacter.quaternion);
1720
- this.cameraManager.setTarget(targetOffset.add(this.localCharacter.position));
1638
+ const targetOffset = new Vector38();
1639
+ targetOffset.add(this.headTargetOffset).applyQuaternion(this.localCharacter.quaternion).add(this.localCharacter.position);
1640
+ this.cameraManager.setTarget(targetOffset);
1721
1641
  for (const [id, update] of this.clientStates) {
1722
1642
  if (this.remoteCharacters.has(id) && this.speakingCharacters.has(id)) {
1723
1643
  const character = this.remoteCharacters.get(id);
@@ -2067,8 +1987,8 @@ var BrightnessContrastSaturationFolder = class {
2067
1987
  // src/tweakpane/blades/environmentFolder.ts
2068
1988
  var sunValues = {
2069
1989
  sunPosition: {
2070
- sunAzimuthalAngle: 215,
2071
- sunPolarAngle: -39
1990
+ sunAzimuthalAngle: 214.5,
1991
+ sunPolarAngle: -41.5
2072
1992
  },
2073
1993
  sunIntensity: 1,
2074
1994
  sunColor: { r: 1, g: 1, b: 1 }
@@ -2222,14 +2142,14 @@ var EnvironmentFolder = class {
2222
2142
  // src/tweakpane/blades/postExtrasFolder.ts
2223
2143
  var extrasValues = {
2224
2144
  grain: 0.055,
2225
- bloom: 0.25
2145
+ bloom: 3
2226
2146
  };
2227
2147
  var extrasOptions = {
2228
2148
  grain: {
2229
2149
  amount: { min: 0, max: 0.2, step: 2e-3 }
2230
2150
  },
2231
2151
  bloom: {
2232
- amount: { min: 0, max: 2, step: 0.05 }
2152
+ amount: { min: 0, max: 5, step: 0.05 }
2233
2153
  }
2234
2154
  };
2235
2155
  var PostExtrasFolder = class {
@@ -2262,7 +2182,7 @@ var rendererValues = {
2262
2182
  shadowMap: 2,
2263
2183
  toneMapping: 5,
2264
2184
  exposure: 1,
2265
- bgIntensity: 0.45,
2185
+ bgIntensity: 1,
2266
2186
  bgBlurriness: 0
2267
2187
  };
2268
2188
  var rendererOptions = {
@@ -2358,18 +2278,15 @@ var RendererStatsFolder = class {
2358
2278
  FPS: "0"
2359
2279
  };
2360
2280
  this.folder = parentFolder.addFolder({ title: "renderStats", expanded });
2361
- this.performance = this.folder.addFolder({ title: "performance", expanded: true });
2362
- this.defails = this.folder.addFolder({ title: "pipeline details", expanded: false });
2363
- this.folder.addBlade({ view: "separator" });
2364
- this.performance.addBinding(this.statsData, "FPS", { readonly: true });
2365
- this.performance.addBinding(this.statsData, "deltaTime", { readonly: true });
2366
- this.performance.addBinding(this.statsData, "rawDeltaTime", { readonly: true });
2367
- this.defails.addBinding(this.statsData, "triangles", { readonly: true });
2368
- this.defails.addBinding(this.statsData, "geometries", { readonly: true });
2369
- this.defails.addBinding(this.statsData, "textures", { readonly: true });
2370
- this.defails.addBinding(this.statsData, "shaders", { readonly: true });
2371
- this.defails.addBinding(this.statsData, "postPasses", { readonly: true });
2372
- this.defails.addBinding(this.statsData, "drawCalls", { readonly: true });
2281
+ this.folder.addBinding(this.statsData, "FPS", { readonly: true });
2282
+ this.folder.addBinding(this.statsData, "deltaTime", { readonly: true });
2283
+ this.folder.addBinding(this.statsData, "rawDeltaTime", { readonly: true });
2284
+ this.folder.addBinding(this.statsData, "triangles", { readonly: true });
2285
+ this.folder.addBinding(this.statsData, "geometries", { readonly: true });
2286
+ this.folder.addBinding(this.statsData, "textures", { readonly: true });
2287
+ this.folder.addBinding(this.statsData, "shaders", { readonly: true });
2288
+ this.folder.addBinding(this.statsData, "postPasses", { readonly: true });
2289
+ this.folder.addBinding(this.statsData, "drawCalls", { readonly: true });
2373
2290
  }
2374
2291
  update(renderer, composer, timeManager) {
2375
2292
  const { geometries, textures } = renderer.info.memory;
@@ -2716,7 +2633,7 @@ var ToneMappingFolder = class {
2716
2633
  // src/tweakpane/tweakPaneStyle.ts
2717
2634
  var tweakPaneStyle = `
2718
2635
  :root {
2719
- --tp-base-background-color: rgba(0, 0, 0, 0.6);
2636
+ --tp-base-background-color: rgba(12, 12, 12, 0.6);
2720
2637
  --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
2721
2638
  --tp-button-background-color: hsla(0, 0%, 80%, 1);
2722
2639
  --tp-button-background-color-active: hsla(0, 0%, 100%, 1);
@@ -2737,6 +2654,9 @@ var tweakPaneStyle = `
2737
2654
  --tp-label-foreground-color: hsla(0, 0%, 100%, 0.6);
2738
2655
  --tp-monitor-background-color: hsla(0, 0%, 0%, 0.3);
2739
2656
  --tp-monitor-foreground-color: hsla(0, 0%, 100%, 0.3);
2657
+ -webkit-user-select: none;
2658
+ -ms-user-select: none;
2659
+ user-select: none;
2740
2660
  }
2741
2661
 
2742
2662
  .tp-brkv {
@@ -2746,28 +2666,40 @@ var tweakPaneStyle = `
2746
2666
  }
2747
2667
 
2748
2668
  .tp-dfwv {
2669
+ z-index: 100;
2749
2670
  color: white;
2750
- backdrop-filter: blur(12px);
2751
- width: 360px !important;
2671
+ width: 600px !important;
2752
2672
  display: none;
2753
2673
  -webkit-user-select: none;
2754
2674
  -ms-user-select: none;
2755
2675
  user-select: none;
2756
2676
  }
2757
2677
 
2678
+ .tp-fldv {
2679
+ margin: 1px 0px 0px 0px !important;
2680
+ }
2681
+
2682
+ .tp-fldv_b {
2683
+ overflow: visible !important;
2684
+ }
2685
+
2758
2686
  .tp-fldv_t {
2759
- font-size: 11px;
2760
- background-color: rgba(0, 0, 0, 0.1);
2687
+ font-size: 13px;
2688
+ font-weight: 900;
2689
+ color: #ffffff;
2690
+ background-color: rgba(70, 70, 70, 0.3);
2691
+ border-top: 1px solid rgba(210, 210, 210, 0.1);
2692
+ border-radius: 3px;
2761
2693
  }
2762
2694
 
2763
2695
  .tp-lblv_l {
2764
- font-size: 11px;
2696
+ font-size: 12px;
2765
2697
  padding-left: 0px !important;
2766
2698
  padding-right: 0px !important;
2767
2699
  }
2768
2700
 
2769
2701
  .tp-lblv_v {
2770
- width: 180px;
2702
+ width: 150px;
2771
2703
  }
2772
2704
 
2773
2705
  .tp-sldtxtv_t {
@@ -2775,9 +2707,13 @@ var tweakPaneStyle = `
2775
2707
  }
2776
2708
 
2777
2709
  .tp-sglv_i {
2778
- font-size: 11px;
2710
+ font-size: 12px;
2779
2711
  color: rgba(255, 255, 255, 0.7);
2780
2712
  }
2713
+
2714
+ .tp-ckbv_w {
2715
+ border: 1px solid rgba(200, 200, 250, 0.2);
2716
+ }
2781
2717
  `;
2782
2718
 
2783
2719
  // src/tweakpane/TweakPane.ts
@@ -2786,9 +2722,13 @@ var TweakPane = class {
2786
2722
  this.renderer = renderer;
2787
2723
  this.scene = scene;
2788
2724
  this.composer = composer;
2789
- this.gui = new Pane();
2790
2725
  this.saveVisibilityInLocalStorage = true;
2791
2726
  this.guiVisible = false;
2727
+ const appWrapper = document.getElementById("app");
2728
+ const tweakPaneWrapper = document.createElement("div");
2729
+ tweakPaneWrapper.id = "tweakpane-panel";
2730
+ appWrapper.appendChild(tweakPaneWrapper);
2731
+ this.gui = new Pane({ container: tweakPaneWrapper });
2792
2732
  this.gui.registerPlugin(EssentialsPlugin);
2793
2733
  if (this.saveVisibilityInLocalStorage) {
2794
2734
  const localStorageGuiVisible = localStorage.getItem("guiVisible");
@@ -2815,21 +2755,22 @@ var TweakPane = class {
2815
2755
  this.toneMappingFolder.folder.hidden = rendererValues.toneMapping === 5 ? false : true;
2816
2756
  this.export = this.gui.addFolder({ title: "import / export", expanded: false });
2817
2757
  window.addEventListener("keydown", this.processKey.bind(this));
2818
- this.setupGUIListeners.bind(this)();
2819
2758
  this.setupRenderPane = this.setupRenderPane.bind(this);
2820
- }
2821
- processKey(e) {
2822
- if (e.key === "p")
2823
- this.toggleGUI();
2759
+ this.setupGUIListeners.bind(this)();
2824
2760
  }
2825
2761
  setupGUIListeners() {
2826
2762
  const gui = this.gui;
2827
2763
  const paneElement = gui.containerElem_;
2828
- paneElement.style.display = this.guiVisible ? "unset" : "none";
2764
+ paneElement.style.right = this.guiVisible ? "0px" : "-450px";
2765
+ this.gui.element.addEventListener("mouseenter", () => setTweakpaneActive(true));
2829
2766
  this.gui.element.addEventListener("mousedown", () => setTweakpaneActive(true));
2830
2767
  this.gui.element.addEventListener("mouseup", () => setTweakpaneActive(false));
2831
2768
  this.gui.element.addEventListener("mouseleave", () => setTweakpaneActive(false));
2832
2769
  }
2770
+ processKey(e) {
2771
+ if (e.key === "p")
2772
+ this.toggleGUI();
2773
+ }
2833
2774
  setupRenderPane(composer, normalPass, ppssaoEffect, ppssaoPass, n8aopass, toneMappingEffect, toneMappingPass, brightnessContrastSaturation, bloomEffect, gaussGrainEffect, hasLighting, sun, setHDR, setAmbientLight, setFog) {
2834
2775
  this.rendererFolder.setupChangeEvent(
2835
2776
  this.scene,
@@ -2901,10 +2842,10 @@ var TweakPane = class {
2901
2842
  input.click();
2902
2843
  }
2903
2844
  toggleGUI() {
2845
+ this.guiVisible = !this.guiVisible;
2904
2846
  const gui = this.gui;
2905
2847
  const paneElement = gui.containerElem_;
2906
- paneElement.style.display = this.guiVisible ? "none" : "unset";
2907
- this.guiVisible = !this.guiVisible;
2848
+ paneElement.style.right = this.guiVisible ? "0px" : "-450px";
2908
2849
  if (this.saveVisibilityInLocalStorage) {
2909
2850
  localStorage.setItem("guiVisible", this.guiVisible === true ? "true" : "false");
2910
2851
  }
@@ -2972,8 +2913,8 @@ var Sun = class extends Group4 {
2972
2913
  }
2973
2914
  this.directionalLight = new DirectionalLight(16777215, 0.5);
2974
2915
  this.directionalLight.intensity = sunValues.sunIntensity;
2975
- this.directionalLight.shadow.normalBias = 0.05;
2976
- this.directionalLight.shadow.radius = 1.5;
2916
+ this.directionalLight.shadow.normalBias = 0.01;
2917
+ this.directionalLight.shadow.radius = 0.02;
2977
2918
  this.directionalLight.shadow.camera = this.shadowCamera;
2978
2919
  this.directionalLight.shadow.mapSize.set(this.shadowResolution, this.shadowResolution);
2979
2920
  this.directionalLight.castShadow = true;
@@ -3822,7 +3763,7 @@ var EffectShader = {
3822
3763
  import {
3823
3764
  BufferAttribute,
3824
3765
  BufferGeometry,
3825
- Mesh as Mesh3,
3766
+ Mesh as Mesh4,
3826
3767
  OrthographicCamera as OrthographicCamera2,
3827
3768
  Sphere
3828
3769
  } from "three";
@@ -3838,7 +3779,7 @@ var FullScreenTriangle = class {
3838
3779
  this.geometry.boundingSphere = new Sphere();
3839
3780
  this.geometry.computeBoundingSphere = function() {
3840
3781
  };
3841
- this.mesh = new Mesh3(this.geometry, material);
3782
+ this.mesh = new Mesh4(this.geometry, material);
3842
3783
  this.mesh.frustumCulled = false;
3843
3784
  }
3844
3785
  get material() {
@@ -4686,7 +4627,6 @@ var Composer = class {
4686
4627
  if (envMap) {
4687
4628
  envMap.colorSpace = LinearSRGBColorSpace;
4688
4629
  envMap.needsUpdate = true;
4689
- this.scene.environment = envMap;
4690
4630
  this.scene.background = envMap;
4691
4631
  this.scene.backgroundIntensity = rendererValues.bgIntensity;
4692
4632
  this.isEnvHDRI = true;
@@ -4809,7 +4749,7 @@ import {
4809
4749
  Group as Group5,
4810
4750
  Line3 as Line32,
4811
4751
  Matrix4 as Matrix46,
4812
- Mesh as Mesh4,
4752
+ Mesh as Mesh5,
4813
4753
  MeshBasicMaterial as MeshBasicMaterial3,
4814
4754
  Quaternion as Quaternion6,
4815
4755
  Ray as Ray2,
@@ -4897,7 +4837,7 @@ var CollisionsManager = class {
4897
4837
  };
4898
4838
  if (this.debug) {
4899
4839
  newBufferGeometry.boundsTree = meshBVH;
4900
- const wireframeMesh = new Mesh4(newBufferGeometry, new MeshBasicMaterial3({ wireframe: true }));
4840
+ const wireframeMesh = new Mesh5(newBufferGeometry, new MeshBasicMaterial3({ wireframe: true }));
4901
4841
  const normalsHelper = new VertexNormalsHelper(wireframeMesh, 0.25, 65280);
4902
4842
  const visualizer = new MeshBVHHelper(wireframeMesh, 4);
4903
4843
  visualizer.edgeMaterial.color = new Color8("blue");
@@ -5003,13 +4943,10 @@ var CollisionsManager = class {
5003
4943
  return collisionPosition;
5004
4944
  }
5005
4945
  applyColliders(tempSegment, radius) {
5006
- let collidedElements = null;
4946
+ const collidedElements = /* @__PURE__ */ new Map();
5007
4947
  for (const meshState of this.collisionMeshState.values()) {
5008
4948
  const collisionPosition = this.applyCollider(tempSegment, radius, meshState);
5009
4949
  if (collisionPosition && meshState.trackCollisions) {
5010
- if (collidedElements === null) {
5011
- collidedElements = /* @__PURE__ */ new Map();
5012
- }
5013
4950
  const relativePosition = getRelativePositionAndRotationRelativeToObject(
5014
4951
  {
5015
4952
  position: collisionPosition,
@@ -5022,7 +4959,16 @@ var CollisionsManager = class {
5022
4959
  });
5023
4960
  }
5024
4961
  }
5025
- this.collisionTrigger.setCurrentCollisions(collidedElements);
4962
+ const reportedCollidingElements = new Map(collidedElements);
4963
+ if (this.previouslyCollidingElements) {
4964
+ for (const [element, position] of this.previouslyCollidingElements) {
4965
+ if (!reportedCollidingElements.has(element)) {
4966
+ reportedCollidingElements.set(element, position);
4967
+ }
4968
+ }
4969
+ }
4970
+ this.previouslyCollidingElements = collidedElements;
4971
+ this.collisionTrigger.setCurrentCollisions(reportedCollidingElements);
5026
4972
  }
5027
4973
  };
5028
4974
  export {