@mml-io/3d-web-client-core 0.7.0 → 0.8.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.
package/build/index.js CHANGED
@@ -2,7 +2,21 @@
2
2
  import { PerspectiveCamera, Raycaster, Vector3 as Vector32 } from "three";
3
3
 
4
4
  // src/helpers/math-helpers.ts
5
- import { Vector3 } from "three";
5
+ import { Quaternion, Vector3, Vector4 } from "three";
6
+ var roundToDecimalPlaces = (value, decimalPlaces) => {
7
+ const mult = 10 ** decimalPlaces;
8
+ return Math.round(value * mult) / mult;
9
+ };
10
+ var toArray = (origin, precision = 3) => {
11
+ const array = [];
12
+ array[0] = roundToDecimalPlaces(origin.x, precision);
13
+ array[1] = roundToDecimalPlaces(origin.y, precision);
14
+ array[2] = roundToDecimalPlaces(origin.z, precision);
15
+ if (origin instanceof Vector4 || origin instanceof Quaternion) {
16
+ array[3] = roundToDecimalPlaces(origin.w, precision);
17
+ }
18
+ return array;
19
+ };
6
20
  var getSpawnPositionInsideCircle = (radius, positions, id, yPos = 0) => {
7
21
  if (id > 0)
8
22
  id += 3;
@@ -53,6 +67,7 @@ var CameraManager = class {
53
67
  this.dampingFactor = 0.091;
54
68
  this.targetDistance = this.initialDistance;
55
69
  this.distance = this.initialDistance;
70
+ this.desiredDistance = this.initialDistance;
56
71
  this.targetPhi = Math.PI / 2;
57
72
  this.phi = Math.PI / 2;
58
73
  this.targetTheta = -Math.PI / 2;
@@ -97,6 +112,7 @@ var CameraManager = class {
97
112
  this.minDistance,
98
113
  Math.min(this.maxDistance, this.targetDistance)
99
114
  );
115
+ this.desiredDistance = this.targetDistance;
100
116
  }
101
117
  setTarget(target) {
102
118
  this.target.copy(target);
@@ -128,6 +144,8 @@ var CameraManager = class {
128
144
  if (minimumDistance !== null && minimumDistance <= cameraToPlayerDistance) {
129
145
  this.targetDistance = cameraToPlayerDistance - minimumDistance;
130
146
  this.distance = this.targetDistance;
147
+ } else {
148
+ this.targetDistance += (this.desiredDistance - this.targetDistance) * this.dampingFactor * 4;
131
149
  }
132
150
  }
133
151
  update() {
@@ -159,7 +177,7 @@ var CameraManager = class {
159
177
  };
160
178
 
161
179
  // src/character/Character.ts
162
- import { Color as Color3, Vector3 as Vector34 } from "three";
180
+ import { Color as Color3, Vector3 as Vector35 } from "three";
163
181
 
164
182
  // src/character/CharacterModel.ts
165
183
  import {
@@ -664,6 +682,7 @@ var CharacterModel = class {
664
682
  this.modelLoader = ModelLoader_default;
665
683
  this.mesh = null;
666
684
  this.material = new CharacterMaterial();
685
+ this.headBone = null;
667
686
  this.animations = {};
668
687
  this.animationMixer = null;
669
688
  this.currentAnimation = 0 /* idle */;
@@ -699,6 +718,9 @@ var CharacterModel = class {
699
718
  if (!this.mesh)
700
719
  return;
701
720
  this.mesh.traverse((child) => {
721
+ if (child.type === "Bone" && child.name === "mixamorigHeadTop_End") {
722
+ this.headBone = child;
723
+ }
702
724
  if (child.type === "SkinnedMesh" && child.name === meshName) {
703
725
  child.material = new MeshStandardMaterial({
704
726
  color: 16711680,
@@ -782,12 +804,104 @@ var CharacterModel = class {
782
804
  }
783
805
  };
784
806
 
807
+ // src/character/CharacterSpeakingIndicator.ts
808
+ import {
809
+ CircleGeometry,
810
+ GLSL3,
811
+ Mesh as Mesh2,
812
+ RawShaderMaterial
813
+ } from "three";
814
+ var CharacterSpeakingIndicator = class {
815
+ constructor(scene) {
816
+ this.scene = scene;
817
+ this.vertexShader = /* glsl */
818
+ `
819
+ in vec3 position;
820
+ in vec2 uv;
821
+ uniform mat4 modelViewMatrix;
822
+ uniform mat4 projectionMatrix;
823
+ out vec2 vUv;
824
+ void main() {
825
+ vUv = uv;
826
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
827
+ }`;
828
+ this.fragmentShader = /* glsl */
829
+ `
830
+ precision highp float;
831
+
832
+ uniform float time;
833
+ uniform float alpha;
834
+ in vec2 vUv;
835
+ out vec4 fragColor;
836
+
837
+ const float size = 1.7;
838
+ const float distribution = 0.03;
839
+ const float speed = 0.2;
840
+ const float overdraw = 3.5;
841
+ const float shapeK = 0.25;
842
+
843
+ float sdHyperbola(vec2 p, float k, float wi) {
844
+ p = abs(p);
845
+ float k2 = k * k;
846
+ float a = p.x + p.y;
847
+ float i = 0.5 * (a - k2 / a) > wi ? -1.0 : 1.0;
848
+ float x = clamp(0.5 * (a - k2 / a), 0.0, wi);
849
+ vec2 q = vec2(x, sqrt(x * x + k2));
850
+ float s = sign(p.x * p.x - p.y * p.y + k2);
851
+ return s * length(p - q);
852
+ }
853
+
854
+ void main(void) {
855
+ vec2 uv = (vUv * 2.0 - 1.0);
856
+ float r = -(uv.x * uv.x + uv.y * uv.y);
857
+ float z = 0.5 + 0.5 * sin((r + time * speed) / distribution);
858
+ float a = clamp(smoothstep(-0.1, 0.2, size - length(uv * 2.0)), 0.0, 0.5);
859
+ float h = clamp(sdHyperbola(uv, shapeK, 1.0), 0.0, 1.0) * overdraw;
860
+ float fragAlpha = clamp(a * h, 0.0, 0.7);
861
+ fragColor = vec4(z * fragAlpha) * alpha;
862
+ }`;
863
+ this.uniforms = {
864
+ time: { value: 0 },
865
+ alpha: { value: 0 }
866
+ };
867
+ this.geometry = new CircleGeometry(0.35, 21);
868
+ this.material = new RawShaderMaterial({
869
+ vertexShader: this.vertexShader,
870
+ fragmentShader: this.fragmentShader,
871
+ uniforms: this.uniforms,
872
+ transparent: true,
873
+ glslVersion: GLSL3
874
+ });
875
+ this.mesh = new Mesh2(this.geometry, this.material);
876
+ this.currentAlpha = 0;
877
+ this.targetAlpha = 0;
878
+ this.scene.add(this.mesh);
879
+ }
880
+ setBillboarding(position, camera) {
881
+ this.mesh.position.set(position.x, position.y - 0.15, position.z);
882
+ this.mesh.lookAt(camera.position);
883
+ }
884
+ setTime(value) {
885
+ this.currentAlpha += ease(this.targetAlpha, this.currentAlpha, 0.06);
886
+ this.uniforms.time.value = value;
887
+ this.uniforms.alpha.value = this.currentAlpha;
888
+ }
889
+ setSpeaking(value) {
890
+ this.targetAlpha = value === true ? 1 : 0;
891
+ }
892
+ dispose() {
893
+ this.scene.remove(this.mesh);
894
+ this.mesh.material.dispose();
895
+ this.mesh.geometry.dispose();
896
+ }
897
+ };
898
+
785
899
  // src/character/CharacterTooltip.ts
786
900
  import {
787
901
  Color as Color2,
788
902
  FrontSide,
789
903
  LinearFilter as LinearFilter2,
790
- Mesh as Mesh2,
904
+ Mesh as Mesh3,
791
905
  MeshBasicMaterial as MeshBasicMaterial2,
792
906
  PlaneGeometry
793
907
  } from "three";
@@ -937,7 +1051,7 @@ var CharacterTooltip = class {
937
1051
  });
938
1052
  this.material.side = FrontSide;
939
1053
  this.geometry = new PlaneGeometry(1, 1, 1, 1);
940
- this.mesh = new Mesh2(this.geometry, this.material);
1054
+ this.mesh = new Mesh3(this.geometry, this.material);
941
1055
  this.mesh.position.set(0, 1.6, 0);
942
1056
  this.mesh.visible = false;
943
1057
  parentModel.add(this.mesh);
@@ -1020,7 +1134,7 @@ var CharacterTooltip = class {
1020
1134
  };
1021
1135
 
1022
1136
  // src/character/LocalController.ts
1023
- import { Line3, Matrix4, Quaternion, Raycaster as Raycaster2, Vector3 as Vector33 } from "three";
1137
+ import { Line3, Matrix4, Quaternion as Quaternion2, Raycaster as Raycaster2, Vector3 as Vector34 } from "three";
1024
1138
  var LocalController = class {
1025
1139
  constructor(model, id, collisionsManager, keyInputManager, cameraManager, timeManager) {
1026
1140
  this.model = model;
@@ -1032,7 +1146,7 @@ var LocalController = class {
1032
1146
  this.collisionDetectionSteps = 15;
1033
1147
  this.capsuleInfo = {
1034
1148
  radius: 0.4,
1035
- segment: new Line3(new Vector33(), new Vector33(0, 1.05, 0))
1149
+ segment: new Line3(new Vector34(), new Vector34(0, 1.05, 0))
1036
1150
  };
1037
1151
  this.maxWalkSpeed = 6;
1038
1152
  this.maxRunSpeed = 8.5;
@@ -1045,15 +1159,15 @@ var LocalController = class {
1045
1159
  this.characterWasOnGround = false;
1046
1160
  this.characterAirborneSince = 0;
1047
1161
  this.currentHeight = 0;
1048
- this.characterVelocity = new Vector33();
1049
- this.vectorUp = new Vector33(0, 1, 0);
1050
- this.vectorDown = new Vector33(0, -1, 0);
1162
+ this.characterVelocity = new Vector34();
1163
+ this.vectorUp = new Vector34(0, 1, 0);
1164
+ this.vectorDown = new Vector34(0, -1, 0);
1051
1165
  this.rotationOffset = 0;
1052
1166
  this.azimuthalAngle = 0;
1053
1167
  this.tempMatrix = new Matrix4();
1054
1168
  this.tempSegment = new Line3();
1055
- this.tempVector = new Vector33();
1056
- this.tempVector2 = new Vector33();
1169
+ this.tempVector = new Vector34();
1170
+ this.tempVector2 = new Vector34();
1057
1171
  this.rayCaster = new Raycaster2();
1058
1172
  this.thirdPersonCamera = null;
1059
1173
  this.speed = 0;
@@ -1141,7 +1255,7 @@ var LocalController = class {
1141
1255
  const camToModelDistance = this.thirdPersonCamera.position.distanceTo(this.model.mesh.position);
1142
1256
  const isCameraFirstPerson = camToModelDistance < 2;
1143
1257
  if (isCameraFirstPerson) {
1144
- const cameraForward = new Vector33(0, 0, 1).applyQuaternion(this.thirdPersonCamera.quaternion);
1258
+ const cameraForward = new Vector34(0, 0, 1).applyQuaternion(this.thirdPersonCamera.quaternion);
1145
1259
  this.azimuthalAngle = Math.atan2(cameraForward.x, cameraForward.z);
1146
1260
  } else {
1147
1261
  this.azimuthalAngle = Math.atan2(
@@ -1162,7 +1276,7 @@ var LocalController = class {
1162
1276
  return;
1163
1277
  this.updateRotationOffset();
1164
1278
  this.updateAzimuthalAngle();
1165
- const rotationQuaternion = new Quaternion();
1279
+ const rotationQuaternion = new Quaternion2();
1166
1280
  rotationQuaternion.setFromAxisAngle(this.vectorUp, this.azimuthalAngle + this.rotationOffset);
1167
1281
  const angularDifference = this.computeAngularDifference(rotationQuaternion);
1168
1282
  const desiredTime = 0.07;
@@ -1200,19 +1314,19 @@ var LocalController = class {
1200
1314
  this.model.mesh.position.addScaledVector(this.characterVelocity, deltaTime);
1201
1315
  this.tempVector.set(0, 0, 0);
1202
1316
  if (this.forward) {
1203
- const forward = new Vector33(0, 0, -1).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1317
+ const forward = new Vector34(0, 0, -1).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1204
1318
  this.tempVector.add(forward);
1205
1319
  }
1206
1320
  if (this.backward) {
1207
- const backward = new Vector33(0, 0, 1).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1321
+ const backward = new Vector34(0, 0, 1).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1208
1322
  this.tempVector.add(backward);
1209
1323
  }
1210
1324
  if (this.left) {
1211
- const left = new Vector33(-1, 0, 0).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1325
+ const left = new Vector34(-1, 0, 0).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1212
1326
  this.tempVector.add(left);
1213
1327
  }
1214
1328
  if (this.right) {
1215
- const right = new Vector33(1, 0, 0).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1329
+ const right = new Vector34(1, 0, 0).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1216
1330
  this.tempVector.add(right);
1217
1331
  }
1218
1332
  if (this.tempVector.length() > 0) {
@@ -1249,13 +1363,13 @@ var LocalController = class {
1249
1363
  if (!((_a = this.model) == null ? void 0 : _a.mesh)) {
1250
1364
  this.networkState = {
1251
1365
  id: this.id,
1252
- position: new Vector33(),
1366
+ position: new Vector34(),
1253
1367
  rotation: { quaternionY: 0, quaternionW: 1 },
1254
1368
  state: 0 /* idle */
1255
1369
  };
1256
1370
  } else {
1257
- const characterQuaternion = this.model.mesh.getWorldQuaternion(new Quaternion());
1258
- const positionUpdate = new Vector33(
1371
+ const characterQuaternion = this.model.mesh.getWorldQuaternion(new Quaternion2());
1372
+ const positionUpdate = new Vector34(
1259
1373
  this.model.mesh.position.x,
1260
1374
  this.model.mesh.position.y,
1261
1375
  this.model.mesh.position.z
@@ -1280,7 +1394,7 @@ var LocalController = class {
1280
1394
 
1281
1395
  // src/character/Character.ts
1282
1396
  var Character = class {
1283
- constructor(characterDescription, id, isLocal, modelLoadedCallback, collisionsManager, keyInputManager, cameraManager, timeManager) {
1397
+ constructor(characterDescription, id, isLocal, modelLoadedCallback, collisionsManager, keyInputManager, cameraManager, timeManager, composer) {
1284
1398
  this.characterDescription = characterDescription;
1285
1399
  this.id = id;
1286
1400
  this.isLocal = isLocal;
@@ -1289,12 +1403,14 @@ var Character = class {
1289
1403
  this.keyInputManager = keyInputManager;
1290
1404
  this.cameraManager = cameraManager;
1291
1405
  this.timeManager = timeManager;
1406
+ this.composer = composer;
1292
1407
  this.controller = null;
1293
1408
  this.name = null;
1294
1409
  this.model = null;
1295
1410
  this.color = new Color3();
1296
- this.position = new Vector34();
1411
+ this.position = new Vector35();
1297
1412
  this.tooltip = null;
1413
+ this.speakingIndicator = null;
1298
1414
  this.load();
1299
1415
  }
1300
1416
  async load() {
@@ -1303,6 +1419,9 @@ var Character = class {
1303
1419
  if (this.tooltip === null) {
1304
1420
  this.tooltip = new CharacterTooltip(this.model.mesh);
1305
1421
  }
1422
+ if (this.speakingIndicator === null) {
1423
+ this.speakingIndicator = new CharacterSpeakingIndicator(this.composer.postPostScene);
1424
+ }
1306
1425
  this.color = this.model.material.colorsCube216[this.id];
1307
1426
  if (this.isLocal) {
1308
1427
  this.controller = new LocalController(
@@ -1317,11 +1436,21 @@ var Character = class {
1317
1436
  this.modelLoadedCallback();
1318
1437
  }
1319
1438
  update(time) {
1439
+ var _a;
1320
1440
  if (!this.model)
1321
1441
  return;
1322
1442
  if (this.tooltip) {
1323
1443
  this.tooltip.update(this.cameraManager.camera);
1324
1444
  }
1445
+ if (this.speakingIndicator) {
1446
+ this.speakingIndicator.setTime(time);
1447
+ if (this.model.mesh && this.model.headBone) {
1448
+ this.speakingIndicator.setBillboarding(
1449
+ (_a = this.model.headBone) == null ? void 0 : _a.getWorldPosition(new Vector35()),
1450
+ this.cameraManager.camera
1451
+ );
1452
+ }
1453
+ }
1325
1454
  this.model.mesh.getWorldPosition(this.position);
1326
1455
  if (typeof this.model.material.uniforms.time !== "undefined") {
1327
1456
  this.model.material.uniforms.time.value = time;
@@ -1332,14 +1461,14 @@ var Character = class {
1332
1461
  };
1333
1462
 
1334
1463
  // src/character/CharacterManager.ts
1335
- import { Group, Vector3 as Vector36 } from "three";
1464
+ import { Group, Vector3 as Vector37 } from "three";
1336
1465
 
1337
1466
  // src/character/RemoteController.ts
1338
1467
  import {
1339
1468
  AnimationMixer as AnimationMixer2,
1340
- Object3D as Object3D4,
1341
- Quaternion as Quaternion2,
1342
- Vector3 as Vector35
1469
+ Object3D as Object3D5,
1470
+ Quaternion as Quaternion3,
1471
+ Vector3 as Vector36
1343
1472
  } from "three";
1344
1473
  var RemoteController = class {
1345
1474
  constructor(character, id) {
@@ -1347,7 +1476,7 @@ var RemoteController = class {
1347
1476
  this.id = id;
1348
1477
  this.modelLoader = ModelLoader_default;
1349
1478
  this.characterModel = null;
1350
- this.animationMixer = new AnimationMixer2(new Object3D4());
1479
+ this.animationMixer = new AnimationMixer2(new Object3D5());
1351
1480
  this.animations = /* @__PURE__ */ new Map();
1352
1481
  this.currentAnimation = 0 /* idle */;
1353
1482
  this.characterModel = this.character.model.mesh;
@@ -1395,8 +1524,8 @@ var RemoteController = class {
1395
1524
  if (!this.characterModel)
1396
1525
  return;
1397
1526
  const { position, rotation, state } = clientUpdate;
1398
- this.characterModel.position.lerp(new Vector35(position.x, position.y, position.z), 0.15);
1399
- const rotationQuaternion = new Quaternion2(0, rotation.quaternionY, 0, rotation.quaternionW);
1527
+ this.characterModel.position.lerp(new Vector36(position.x, position.y, position.z), 0.15);
1528
+ const rotationQuaternion = new Quaternion3(0, rotation.quaternionY, 0, rotation.quaternionW);
1400
1529
  this.characterModel.quaternion.slerp(rotationQuaternion, 0.6);
1401
1530
  if (state !== this.currentAnimation) {
1402
1531
  this.transitionToAnimation(state);
@@ -1407,10 +1536,10 @@ var RemoteController = class {
1407
1536
  // src/character/CharacterManager.ts
1408
1537
  function encodeCharacterAndCamera(character, camera) {
1409
1538
  return [
1410
- ...character.position.toArray(),
1411
- ...character.quaternion.toArray(),
1412
- ...camera.position.toArray(),
1413
- ...camera.quaternion.toArray()
1539
+ ...toArray(character.position),
1540
+ ...toArray(character.quaternion),
1541
+ ...toArray(camera.position),
1542
+ ...toArray(camera.quaternion)
1414
1543
  ].join(",");
1415
1544
  }
1416
1545
  function decodeCharacterAndCamera(hash, character, camera) {
@@ -1421,7 +1550,8 @@ function decodeCharacterAndCamera(hash, character, camera) {
1421
1550
  camera.quaternion.fromArray(values.slice(10, 14));
1422
1551
  }
1423
1552
  var CharacterManager = class {
1424
- constructor(collisionsManager, cameraManager, timeManager, inputManager, clientStates, sendUpdate) {
1553
+ constructor(composer, collisionsManager, cameraManager, timeManager, inputManager, clientStates, sendUpdate) {
1554
+ this.composer = composer;
1425
1555
  this.collisionsManager = collisionsManager;
1426
1556
  this.cameraManager = cameraManager;
1427
1557
  this.timeManager = timeManager;
@@ -1434,6 +1564,7 @@ var CharacterManager = class {
1434
1564
  can be trapped).
1435
1565
  */
1436
1566
  this.updateLocationHash = false;
1567
+ this.id = 0;
1437
1568
  this.loadingCharacters = /* @__PURE__ */ new Map();
1438
1569
  this.remoteCharacters = /* @__PURE__ */ new Map();
1439
1570
  this.remoteCharacterControllers = /* @__PURE__ */ new Map();
@@ -1441,6 +1572,7 @@ var CharacterManager = class {
1441
1572
  this.character = null;
1442
1573
  this.cameraOffsetTarget = 0;
1443
1574
  this.cameraOffset = 0;
1575
+ this.speakingCharacters = /* @__PURE__ */ new Map();
1444
1576
  this.group = new Group();
1445
1577
  }
1446
1578
  /* TODO:
@@ -1449,7 +1581,7 @@ var CharacterManager = class {
1449
1581
  the mesh loading async (would allow us to show a nameplate where a remote
1450
1582
  user is before the asset loads).
1451
1583
  */
1452
- spawnCharacter(characterDescription, id, isLocal = false, spawnPosition = new Vector36()) {
1584
+ spawnCharacter(characterDescription, id, isLocal = false, spawnPosition = new Vector37()) {
1453
1585
  this.characterDescription = characterDescription;
1454
1586
  const characterLoadingPromise = new Promise((resolve) => {
1455
1587
  const character = new Character(
@@ -1487,6 +1619,7 @@ var CharacterManager = class {
1487
1619
  }
1488
1620
  this.group.add(character.model.mesh);
1489
1621
  if (isLocal) {
1622
+ this.id = id;
1490
1623
  this.character = character;
1491
1624
  (_e = this.character.tooltip) == null ? void 0 : _e.setText(`${id}`);
1492
1625
  } else {
@@ -1521,7 +1654,8 @@ var CharacterManager = class {
1521
1654
  this.collisionsManager,
1522
1655
  this.inputManager,
1523
1656
  this.cameraManager,
1524
- this.timeManager
1657
+ this.timeManager,
1658
+ this.composer
1525
1659
  );
1526
1660
  });
1527
1661
  this.loadingCharacters.set(id, characterLoadingPromise);
@@ -1551,14 +1685,20 @@ var CharacterManager = class {
1551
1685
  }
1552
1686
  this.loadingCharacters.clear();
1553
1687
  }
1688
+ setSpeakingCharacter(id, value) {
1689
+ this.speakingCharacters.set(id, value);
1690
+ }
1554
1691
  update() {
1555
- var _a;
1692
+ var _a, _b, _c, _d;
1556
1693
  if (this.character) {
1557
1694
  this.character.update(this.timeManager.time);
1558
- if ((_a = this.character.model) == null ? void 0 : _a.mesh) {
1559
- this.cameraOffsetTarget = this.cameraManager.targetDistance <= 0.4 ? 0.6 : 0;
1695
+ if (this.speakingCharacters.has(this.id)) {
1696
+ (_a = this.character.speakingIndicator) == null ? void 0 : _a.setSpeaking(this.speakingCharacters.get(this.id));
1697
+ }
1698
+ if ((_b = this.character.model) == null ? void 0 : _b.mesh) {
1699
+ this.cameraOffsetTarget = this.cameraManager.targetDistance <= 0.4 ? 0.13 : 0;
1560
1700
  this.cameraOffset += ease(this.cameraOffsetTarget, this.cameraOffset, 0.1);
1561
- const targetOffset = new Vector36(0, 1.3, this.cameraOffset);
1701
+ const targetOffset = new Vector37(0, 1.3, this.cameraOffset);
1562
1702
  targetOffset.applyQuaternion(this.character.model.mesh.quaternion);
1563
1703
  this.cameraManager.setTarget(this.character.position.add(targetOffset));
1564
1704
  }
@@ -1569,13 +1709,17 @@ var CharacterManager = class {
1569
1709
  }
1570
1710
  }
1571
1711
  for (const [id, update] of this.clientStates) {
1712
+ if (this.remoteCharacters.has(id) && this.speakingCharacters.has(id)) {
1713
+ const character = this.remoteCharacters.get(id);
1714
+ (_c = character == null ? void 0 : character.speakingIndicator) == null ? void 0 : _c.setSpeaking(this.speakingCharacters.get(id));
1715
+ }
1572
1716
  const { position } = update;
1573
1717
  if (!this.remoteCharacters.has(id) && !this.loadingCharacters.has(id)) {
1574
1718
  this.spawnCharacter(
1575
1719
  this.characterDescription,
1576
1720
  id,
1577
1721
  false,
1578
- new Vector36(position.x, position.y, position.z)
1722
+ new Vector37(position.x, position.y, position.z)
1579
1723
  ).then((_character) => {
1580
1724
  this.loadingCharacters.delete(id);
1581
1725
  });
@@ -1587,6 +1731,7 @@ var CharacterManager = class {
1587
1731
  }
1588
1732
  for (const [id, character] of this.remoteCharacters) {
1589
1733
  if (!this.clientStates.has(id)) {
1734
+ (_d = character.speakingIndicator) == null ? void 0 : _d.dispose();
1590
1735
  this.group.remove(character.model.mesh);
1591
1736
  this.remoteCharacters.delete(id);
1592
1737
  this.remoteCharacterControllers.delete(id);
@@ -1748,13 +1893,14 @@ import {
1748
1893
  LinearSRGBColorSpace,
1749
1894
  LoadingManager as LoadingManager2,
1750
1895
  PMREMGenerator,
1896
+ Scene as Scene3,
1751
1897
  Vector2 as Vector22,
1752
1898
  WebGLRenderer as WebGLRenderer2
1753
1899
  } from "three";
1754
1900
  import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
1755
1901
 
1756
1902
  // src/sun/Sun.ts
1757
- import { CameraHelper, Color as Color4, DirectionalLight, Group as Group3, OrthographicCamera, Vector3 as Vector37 } from "three";
1903
+ import { CameraHelper, Color as Color4, DirectionalLight, Group as Group3, OrthographicCamera, Vector3 as Vector38 } from "three";
1758
1904
 
1759
1905
  // src/tweakpane/blades/environmentFolder.ts
1760
1906
  var sunValues = {
@@ -1916,7 +2062,7 @@ var Sun = class extends Group3 {
1916
2062
  constructor() {
1917
2063
  super();
1918
2064
  this.debug = false;
1919
- this.sunOffset = new Vector37(
2065
+ this.sunOffset = new Vector38(
1920
2066
  39 * (Math.PI / 180),
1921
2067
  50 * (Math.PI / 180),
1922
2068
  100
@@ -1943,7 +2089,7 @@ var Sun = class extends Group3 {
1943
2089
  this.directionalLight.shadow.mapSize.set(this.shadowResolution, this.shadowResolution);
1944
2090
  this.directionalLight.castShadow = true;
1945
2091
  this.setColor();
1946
- this.updateCharacterPosition(new Vector37(0, 0, 0));
2092
+ this.updateCharacterPosition(new Vector38(0, 0, 0));
1947
2093
  this.add(this.directionalLight);
1948
2094
  if (this.debug === true && this.camHelper instanceof CameraHelper) {
1949
2095
  this.add(this.camHelper);
@@ -1981,7 +2127,7 @@ var Sun = class extends Group3 {
1981
2127
  if (!this.target)
1982
2128
  return;
1983
2129
  const distance = this.sunOffset.z;
1984
- const sphericalPosition = new Vector37(
2130
+ const sphericalPosition = new Vector38(
1985
2131
  distance * Math.sin(polarAngle) * Math.cos(azimuthalAngle),
1986
2132
  distance * Math.cos(polarAngle),
1987
2133
  distance * Math.sin(polarAngle) * Math.sin(azimuthalAngle)
@@ -2892,6 +3038,7 @@ var Composer = class {
2892
3038
  this.ambientLight = null;
2893
3039
  this.sun = null;
2894
3040
  this.scene = scene;
3041
+ this.postPostScene = new Scene3();
2895
3042
  this.camera = camera;
2896
3043
  this.spawnSun = spawnSun;
2897
3044
  this.renderer = new WebGLRenderer2({
@@ -3050,6 +3197,7 @@ var Composer = class {
3050
3197
  this.gaussGrainEffect.uniforms.time.value = timeManager.time;
3051
3198
  this.gaussGrainEffect.uniforms.alpha.value = 1;
3052
3199
  this.composer.render();
3200
+ this.renderer.render(this.postPostScene, this.camera);
3053
3201
  if (this.tweakPane.guiVisible) {
3054
3202
  this.tweakPane.updateStats(timeManager);
3055
3203
  }
@@ -3181,17 +3329,17 @@ import {
3181
3329
  MMLCollisionTrigger
3182
3330
  } from "mml-web";
3183
3331
  import {
3184
- Box3 as Box32,
3332
+ Box3,
3185
3333
  Color as Color7,
3186
3334
  DoubleSide,
3187
3335
  Euler,
3188
3336
  Group as Group4,
3189
3337
  Line3 as Line32,
3190
3338
  Matrix4 as Matrix42,
3191
- Mesh as Mesh3,
3339
+ Mesh as Mesh4,
3192
3340
  MeshBasicMaterial as MeshBasicMaterial3,
3193
3341
  Ray,
3194
- Vector3 as Vector38
3342
+ Vector3 as Vector39
3195
3343
  } from "three";
3196
3344
  import { VertexNormalsHelper } from "three/examples/jsm/helpers/VertexNormalsHelper.js";
3197
3345
  import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUtils.js";
@@ -3199,13 +3347,13 @@ import { MeshBVH, MeshBVHVisualizer } from "three-mesh-bvh";
3199
3347
  var CollisionsManager = class {
3200
3348
  constructor(scene) {
3201
3349
  this.debug = false;
3202
- this.tempVector = new Vector38();
3203
- this.tempVector2 = new Vector38();
3204
- this.tempVector3 = new Vector38();
3350
+ this.tempVector = new Vector39();
3351
+ this.tempVector2 = new Vector39();
3352
+ this.tempVector3 = new Vector39();
3205
3353
  this.tempRay = new Ray();
3206
3354
  this.tempMatrix = new Matrix42();
3207
3355
  this.tempMatrix2 = new Matrix42();
3208
- this.tempBox = new Box32();
3356
+ this.tempBox = new Box3();
3209
3357
  this.tempEuler = new Euler();
3210
3358
  this.tempSegment = new Line32();
3211
3359
  this.tempSegment2 = new Line32();
@@ -3267,7 +3415,7 @@ var CollisionsManager = class {
3267
3415
  };
3268
3416
  if (this.debug) {
3269
3417
  newBufferGeometry.boundsTree = meshBVH;
3270
- const wireframeMesh = new Mesh3(newBufferGeometry, new MeshBasicMaterial3({ wireframe: true }));
3418
+ const wireframeMesh = new Mesh4(newBufferGeometry, new MeshBasicMaterial3({ wireframe: true }));
3271
3419
  const normalsHelper = new VertexNormalsHelper(wireframeMesh, 0.25, 65280);
3272
3420
  const visualizer = new MeshBVHVisualizer(wireframeMesh, 4);
3273
3421
  visualizer.edgeMaterial.color = new Color7("blue");
@@ -3350,7 +3498,7 @@ var CollisionsManager = class {
3350
3498
  const realDistance = intersectionSegment.distance();
3351
3499
  if (realDistance < capsuleRadius) {
3352
3500
  if (!collisionPosition) {
3353
- collisionPosition = new Vector38().copy(closestPointOnSegment);
3501
+ collisionPosition = new Vector39().copy(closestPointOnSegment).applyMatrix4(meshState.matrix);
3354
3502
  }
3355
3503
  const ratio = realDistance / modelReferenceDistance;
3356
3504
  const realDepth = capsuleRadius - realDistance;