@mml-io/3d-web-client-core 0.11.0 → 0.12.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
@@ -203,10 +203,10 @@ var CameraManager = class {
203
203
  this.camera.position,
204
204
  this.target.clone().sub(this.camera.position).normalize()
205
205
  );
206
- const minimumDistance = this.collisionsManager.raycastFirstDistance(this.rayCaster.ray);
206
+ const firstRaycastHit = this.collisionsManager.raycastFirst(this.rayCaster.ray);
207
207
  const cameraToPlayerDistance = this.camera.position.distanceTo(this.target);
208
- if (minimumDistance !== null && minimumDistance <= cameraToPlayerDistance) {
209
- this.targetDistance = cameraToPlayerDistance - minimumDistance;
208
+ if (firstRaycastHit !== null && firstRaycastHit[0] <= cameraToPlayerDistance) {
209
+ this.targetDistance = cameraToPlayerDistance - firstRaycastHit[0];
210
210
  this.distance = this.targetDistance;
211
211
  } else {
212
212
  this.targetDistance += (this.desiredDistance - this.targetDistance) * this.dampingFactor * 4;
@@ -259,11 +259,15 @@ var CameraManager = class {
259
259
  import { Color as Color3, Group, Vector3 as Vector34 } from "three";
260
260
 
261
261
  // src/character/CharacterModel.ts
262
+ import {
263
+ Character as MMLCharacter,
264
+ ModelLoader,
265
+ parseMMLDescription
266
+ } from "@mml-io/3d-web-avatar";
262
267
  import {
263
268
  AnimationClip,
264
269
  AnimationMixer,
265
- LoopRepeat,
266
- Object3D
270
+ LoopRepeat
267
271
  } from "three";
268
272
 
269
273
  // src/character/CharacterMaterial.ts
@@ -362,15 +366,15 @@ ${before}
362
366
  // src/tweakpane/blades/characterFolder.ts
363
367
  var characterValues = {
364
368
  transmission: 0.01,
365
- metalness: 0.8,
366
- roughness: 0.05,
369
+ metalness: 0.2,
370
+ roughness: 0.8,
367
371
  ior: 1,
368
372
  thickness: 0.1,
369
373
  specularColor: { r: 1, g: 1, b: 1 },
370
374
  specularIntensity: 0.1,
371
375
  emissive: { r: 1, g: 1, b: 1 },
372
- emissiveIntensity: 0.1,
373
- envMapIntensity: 0.8,
376
+ emissiveIntensity: 0.01,
377
+ envMapIntensity: 0.12,
374
378
  sheenColor: { r: 1, g: 1, b: 1 },
375
379
  sheen: 0.5,
376
380
  clearcoat: 0,
@@ -468,11 +472,13 @@ var CharacterFolder = class {
468
472
 
469
473
  // src/character/CharacterMaterial.ts
470
474
  var CharacterMaterial = class extends MeshPhysicalMaterial {
471
- constructor() {
475
+ constructor(color) {
472
476
  super();
473
477
  this.uniforms = {};
474
478
  this.colorsCube216 = [];
475
- this.color = new Color(16777215);
479
+ if (color) {
480
+ this.color = color;
481
+ }
476
482
  this.transmission = characterValues.transmission;
477
483
  this.metalness = characterValues.metalness;
478
484
  this.roughness = characterValues.roughness;
@@ -578,16 +584,14 @@ var CharacterMaterial = class extends MeshPhysicalMaterial {
578
584
  vec3 grid = vec3(smoothstep(0.01, 0.0, a) * 1.15) * diffuseRandomColor;
579
585
  outgoingLight += grid;
580
586
  #endif
581
-
582
- outgoingLight += smoothstep(0.1, 0.0, scanLines) * 0.1;
583
587
  `
584
588
  );
585
589
  };
586
590
  this.generateColorCube();
587
591
  }
588
592
  generateColorCube() {
589
- const saturation = 0.4;
590
- const lightness = 0.7;
593
+ const saturation = 0.5;
594
+ const lightness = 0.9;
591
595
  const goldenRatioConjugate = 0.618033988749895;
592
596
  let hue = 0;
593
597
  for (let i = 0; i < 216; i++) {
@@ -640,8 +644,9 @@ var AnimationState = /* @__PURE__ */ ((AnimationState2) => {
640
644
 
641
645
  // src/character/CharacterModel.ts
642
646
  var CharacterModel = class {
643
- constructor(characterDescription, characterModelLoader) {
647
+ constructor(characterDescription, animationConfig, characterModelLoader) {
644
648
  this.characterDescription = characterDescription;
649
+ this.animationConfig = animationConfig;
645
650
  this.characterModelLoader = characterModelLoader;
646
651
  this.mesh = null;
647
652
  this.material = new CharacterMaterial();
@@ -652,65 +657,130 @@ var CharacterModel = class {
652
657
  }
653
658
  async init() {
654
659
  await this.loadMainMesh();
660
+ await this.setAnimationFromFile(this.animationConfig.idleAnimationFileUrl, 0 /* idle */);
655
661
  await this.setAnimationFromFile(
656
- this.characterDescription.idleAnimationFileUrl,
657
- 0 /* idle */
658
- );
659
- await this.setAnimationFromFile(
660
- this.characterDescription.jogAnimationFileUrl,
662
+ this.animationConfig.jogAnimationFileUrl,
661
663
  1 /* walking */
662
664
  );
663
665
  await this.setAnimationFromFile(
664
- this.characterDescription.sprintAnimationFileUrl,
666
+ this.animationConfig.sprintAnimationFileUrl,
665
667
  2 /* running */
666
668
  );
667
- await this.setAnimationFromFile(
668
- this.characterDescription.airAnimationFileUrl,
669
- 4 /* air */
670
- );
671
- this.applyMaterialToAllSkinnedMeshes(this.material);
669
+ await this.setAnimationFromFile(this.animationConfig.airAnimationFileUrl, 4 /* air */);
670
+ if (this.characterDescription.meshFileUrl) {
671
+ this.applyCustomMaterial(this.material);
672
+ }
673
+ }
674
+ applyCustomMaterial(material) {
675
+ if (!this.mesh)
676
+ return;
677
+ 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;
683
+ } else {
684
+ const color = mat.color;
685
+ asSkinnedMesh.material = new CharacterMaterial(color);
686
+ }
687
+ }
688
+ });
672
689
  }
673
690
  updateAnimation(targetAnimation) {
674
691
  if (this.currentAnimation !== targetAnimation) {
675
692
  this.transitionToAnimation(targetAnimation);
676
693
  }
677
694
  }
678
- applyMaterialToAllSkinnedMeshes(material) {
679
- if (!this.mesh)
680
- return;
695
+ setMainMesh(mainMesh) {
696
+ this.mesh = mainMesh;
697
+ this.mesh.position.set(0, -0.4, 0);
681
698
  this.mesh.traverse((child) => {
682
699
  if (child.type === "SkinnedMesh") {
683
- child.material = material;
700
+ child.castShadow = true;
701
+ child.receiveShadow = true;
684
702
  }
685
703
  });
704
+ this.animationMixer = new AnimationMixer(this.mesh);
705
+ }
706
+ async composeMMLCharacter(mmlCharacterDescription) {
707
+ var _a, _b, _c;
708
+ if (((_a = mmlCharacterDescription.base) == null ? void 0 : _a.url.length) === 0) {
709
+ throw new Error(
710
+ "ERROR: An MML Character Description was provided but it's not a valid <m-character> string, or a valid URL"
711
+ );
712
+ }
713
+ let mergedCharacter = null;
714
+ if (mmlCharacterDescription) {
715
+ 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
+ if (characterBase) {
722
+ const mmlCharacter = new MMLCharacter(new ModelLoader());
723
+ mergedCharacter = await mmlCharacter.mergeBodyParts(characterBase, parts);
724
+ if (mergedCharacter) {
725
+ return mergedCharacter.children[0].children[0];
726
+ }
727
+ }
728
+ }
729
+ }
730
+ async loadCharacterFromDescription() {
731
+ if (this.characterDescription.meshFileUrl) {
732
+ return await this.characterModelLoader.load(this.characterDescription.meshFileUrl, "model") || null;
733
+ }
734
+ let mmlCharacterSource;
735
+ if (this.characterDescription.mmlCharacterUrl) {
736
+ const res = await fetch(this.characterDescription.mmlCharacterUrl);
737
+ mmlCharacterSource = await res.text();
738
+ } else if (this.characterDescription.mmlCharacterString) {
739
+ mmlCharacterSource = this.characterDescription.mmlCharacterString;
740
+ } else {
741
+ throw new Error(
742
+ "ERROR: No Character Description was provided. Specify one of meshFileUrl, mmlCharacterUrl or mmlCharacterString"
743
+ );
744
+ }
745
+ const parsedMMLDescription = parseMMLDescription(mmlCharacterSource);
746
+ const mmlCharacterDescription = parsedMMLDescription[0];
747
+ if (parsedMMLDescription[1].length > 0) {
748
+ console.warn("Errors parsing MML Character Description: ", parsedMMLDescription[1]);
749
+ }
750
+ const mmlCharacterBody = await this.composeMMLCharacter(mmlCharacterDescription);
751
+ if (mmlCharacterBody) {
752
+ return mmlCharacterBody;
753
+ }
754
+ return null;
686
755
  }
687
756
  async loadMainMesh() {
688
- const mainMeshUrl = this.characterDescription.meshFileUrl;
689
- const scale = this.characterDescription.modelScale;
690
- const extension = mainMeshUrl.split(".").pop();
691
- const name = mainMeshUrl.split("/").pop().replace(`.${extension}`, "");
692
- const mainMesh = await this.characterModelLoader.load(mainMeshUrl, "model");
757
+ const mainMesh = await this.loadCharacterFromDescription();
693
758
  if (typeof mainMesh !== "undefined") {
694
- this.mesh = new Object3D();
695
- const model = mainMesh;
696
- model.position.set(0, -0.4, 0);
697
- this.mesh.add(model);
698
- this.mesh.name = name;
699
- this.mesh.scale.set(scale, scale, scale);
700
- this.mesh.traverse((child) => {
701
- if (child.type === "SkinnedMesh") {
702
- child.castShadow = true;
703
- child.receiveShadow = true;
704
- }
705
- });
706
- this.animationMixer = new AnimationMixer(this.mesh);
759
+ this.setMainMesh(mainMesh);
760
+ } else {
761
+ throw new Error("ERROR: No Character Model was loaded");
707
762
  }
708
763
  }
764
+ cleanAnimationClips(skeletalMesh, animationClip) {
765
+ const availableBones = /* @__PURE__ */ new Set();
766
+ skeletalMesh.traverse((child) => {
767
+ const asBone = child;
768
+ if (asBone.isBone) {
769
+ availableBones.add(child.name);
770
+ }
771
+ });
772
+ animationClip.tracks = animationClip.tracks.filter((track) => {
773
+ const trackName = track.name.split(".")[0];
774
+ return availableBones.has(trackName);
775
+ });
776
+ return animationClip;
777
+ }
709
778
  async setAnimationFromFile(animationFileUrl, animationType) {
710
779
  return new Promise(async (resolve, reject) => {
711
780
  const animation = await this.characterModelLoader.load(animationFileUrl, "animation");
712
- if (typeof animation !== "undefined" && animation instanceof AnimationClip) {
713
- this.animations[animationType] = this.animationMixer.clipAction(animation);
781
+ const cleanAnimation = this.cleanAnimationClips(this.mesh, animation);
782
+ if (typeof animation !== "undefined" && cleanAnimation instanceof AnimationClip) {
783
+ this.animations[animationType] = this.animationMixer.clipAction(cleanAnimation);
714
784
  this.animations[animationType].stop();
715
785
  if (animationType === 0 /* idle */) {
716
786
  this.animations[animationType].play();
@@ -750,7 +820,7 @@ var CharacterModel = class {
750
820
  import {
751
821
  CircleGeometry,
752
822
  GLSL3,
753
- Mesh as Mesh2,
823
+ Mesh,
754
824
  RawShaderMaterial
755
825
  } from "three";
756
826
  var CharacterSpeakingIndicator = class {
@@ -814,7 +884,7 @@ var CharacterSpeakingIndicator = class {
814
884
  transparent: true,
815
885
  glslVersion: GLSL3
816
886
  });
817
- this.mesh = new Mesh2(this.geometry, this.material);
887
+ this.mesh = new Mesh(this.geometry, this.material);
818
888
  this.currentAlpha = 0;
819
889
  this.targetAlpha = 0;
820
890
  this.scene.add(this.mesh);
@@ -843,7 +913,7 @@ import {
843
913
  Color as Color2,
844
914
  FrontSide,
845
915
  LinearFilter as LinearFilter2,
846
- Mesh as Mesh3,
916
+ Mesh as Mesh2,
847
917
  MeshBasicMaterial as MeshBasicMaterial2,
848
918
  PlaneGeometry
849
919
  } from "three";
@@ -969,7 +1039,7 @@ var defaultLabelWidth = 0.25;
969
1039
  var defaultLabelHeight = 0.125;
970
1040
  var defaultLabelCastShadows = true;
971
1041
  var tooltipGeometry = new PlaneGeometry(1, 1, 1, 1);
972
- var CharacterTooltip = class extends Mesh3 {
1042
+ var CharacterTooltip = class extends Mesh2 {
973
1043
  constructor() {
974
1044
  super(tooltipGeometry);
975
1045
  this.visibleOpacity = 0.85;
@@ -1076,9 +1146,10 @@ var CharacterTooltip = class extends Mesh3 {
1076
1146
 
1077
1147
  // src/character/Character.ts
1078
1148
  var Character = class extends Group {
1079
- constructor(characterDescription, characterModelLoader, characterId, modelLoadedCallback, cameraManager, composer) {
1149
+ constructor(characterDescription, animationConfig, characterModelLoader, characterId, modelLoadedCallback, cameraManager, composer) {
1080
1150
  super();
1081
1151
  this.characterDescription = characterDescription;
1152
+ this.animationConfig = animationConfig;
1082
1153
  this.characterModelLoader = characterModelLoader;
1083
1154
  this.characterId = characterId;
1084
1155
  this.modelLoadedCallback = modelLoadedCallback;
@@ -1093,7 +1164,11 @@ var Character = class extends Group {
1093
1164
  this.load();
1094
1165
  }
1095
1166
  async load() {
1096
- this.model = new CharacterModel(this.characterDescription, this.characterModelLoader);
1167
+ this.model = new CharacterModel(
1168
+ this.characterDescription,
1169
+ this.animationConfig,
1170
+ this.characterModelLoader
1171
+ );
1097
1172
  await this.model.init();
1098
1173
  this.add(this.model.mesh);
1099
1174
  if (this.speakingIndicator === null) {
@@ -1136,10 +1211,19 @@ var Character = class extends Group {
1136
1211
  };
1137
1212
 
1138
1213
  // src/character/CharacterManager.ts
1139
- import { Euler, Group as Group2, Quaternion as Quaternion5, Vector3 as Vector38 } from "three";
1214
+ import { Euler as Euler2, Group as Group2, Quaternion as Quaternion5, Vector3 as Vector38 } from "three";
1140
1215
 
1141
1216
  // src/character/LocalController.ts
1142
- import { Line3, Matrix4, Quaternion as Quaternion2, Raycaster as Raycaster2, Vector3 as Vector35 } from "three";
1217
+ import { Euler, Line3, Matrix4, Quaternion as Quaternion2, Ray, Raycaster as Raycaster2, Vector3 as Vector35 } from "three";
1218
+ var downVector = new Vector35(0, -1, 0);
1219
+ var airResistance = 0.5;
1220
+ var groundResistance = 0.99999999;
1221
+ var airControlModifier = 0.05;
1222
+ var groundWalkControl = 0.75;
1223
+ var groundRunControl = 1;
1224
+ var baseControl = 200;
1225
+ var collisionDetectionSteps = 15;
1226
+ var minimumSurfaceAngle = 0.9;
1143
1227
  var LocalController = class {
1144
1228
  constructor(character, id, collisionsManager, keyInputManager, cameraManager, timeManager) {
1145
1229
  this.character = character;
@@ -1148,15 +1232,12 @@ var LocalController = class {
1148
1232
  this.keyInputManager = keyInputManager;
1149
1233
  this.cameraManager = cameraManager;
1150
1234
  this.timeManager = timeManager;
1151
- this.collisionDetectionSteps = 15;
1152
1235
  this.capsuleInfo = {
1153
1236
  radius: 0.4,
1154
1237
  segment: new Line3(new Vector35(), new Vector35(0, 1.05, 0))
1155
1238
  };
1156
- this.maxWalkSpeed = 6;
1157
- this.maxRunSpeed = 8.5;
1158
1239
  this.gravity = -42;
1159
- this.jumpForce = 16;
1240
+ this.jumpForce = 20;
1160
1241
  this.coyoteTimeThreshold = 70;
1161
1242
  this.coyoteTime = false;
1162
1243
  this.canJump = true;
@@ -1164,6 +1245,7 @@ var LocalController = class {
1164
1245
  this.characterWasOnGround = false;
1165
1246
  this.characterAirborneSince = 0;
1166
1247
  this.currentHeight = 0;
1248
+ this.currentSurfaceAngle = new Vector35();
1167
1249
  this.characterVelocity = new Vector35();
1168
1250
  this.vectorUp = new Vector35(0, 1, 0);
1169
1251
  this.vectorDown = new Vector35(0, -1, 0);
@@ -1171,11 +1253,21 @@ var LocalController = class {
1171
1253
  this.azimuthalAngle = 0;
1172
1254
  this.tempMatrix = new Matrix4();
1173
1255
  this.tempSegment = new Line3();
1256
+ this.tempQuaternion = new Quaternion2();
1257
+ this.tempEuler = new Euler();
1174
1258
  this.tempVector = new Vector35();
1175
1259
  this.tempVector2 = new Vector35();
1260
+ this.tempVector3 = new Vector35();
1176
1261
  this.rayCaster = new Raycaster2();
1177
- this.speed = 0;
1178
- this.targetSpeed = 0;
1262
+ this.surfaceTempQuaternion = new Quaternion2();
1263
+ this.surfaceTempQuaternion2 = new Quaternion2();
1264
+ this.surfaceTempVector1 = new Vector35();
1265
+ this.surfaceTempVector2 = new Vector35();
1266
+ this.surfaceTempVector3 = new Vector35();
1267
+ this.surfaceTempVector4 = new Vector35();
1268
+ this.surfaceTempVector5 = new Vector35();
1269
+ this.surfaceTempRay = new Ray();
1270
+ this.lastFrameSurfaceState = null;
1179
1271
  this.networkState = {
1180
1272
  id: this.id,
1181
1273
  position: { x: 0, y: 0, z: 0 },
@@ -1183,47 +1275,55 @@ var LocalController = class {
1183
1275
  state: 0 /* idle */
1184
1276
  };
1185
1277
  }
1278
+ updateControllerState() {
1279
+ this.forward = this.keyInputManager.forward;
1280
+ this.backward = this.keyInputManager.backward;
1281
+ this.left = this.keyInputManager.left;
1282
+ this.right = this.keyInputManager.right;
1283
+ this.run = this.keyInputManager.run;
1284
+ this.jump = this.keyInputManager.jump;
1285
+ this.anyDirection = this.keyInputManager.anyDirection;
1286
+ this.conflictingDirections = this.keyInputManager.conflictingDirection;
1287
+ }
1186
1288
  update() {
1187
- const { forward, backward, left, right, run, jump, anyDirection, conflictingDirection } = this.keyInputManager;
1188
- this.forward = forward;
1189
- this.backward = backward;
1190
- this.left = left;
1191
- this.right = right;
1192
- this.run = run;
1193
- this.jump = jump;
1194
- this.anyDirection = anyDirection;
1195
- this.conflictingDirections = conflictingDirection;
1196
- this.targetSpeed = this.run ? this.maxRunSpeed : this.maxWalkSpeed;
1197
- this.speed += ease(this.targetSpeed, this.speed, 0.07);
1289
+ this.updateControllerState();
1198
1290
  this.rayCaster.set(this.character.position, this.vectorDown);
1199
- const minimumDistance = this.collisionsManager.raycastFirstDistance(this.rayCaster.ray);
1200
- if (minimumDistance !== null) {
1201
- this.currentHeight = minimumDistance;
1291
+ const firstRaycastHit = this.collisionsManager.raycastFirst(this.rayCaster.ray);
1292
+ if (firstRaycastHit !== null) {
1293
+ this.currentHeight = firstRaycastHit[0];
1294
+ this.currentSurfaceAngle.copy(firstRaycastHit[1]);
1202
1295
  }
1203
- if (anyDirection || !this.characterOnGround) {
1296
+ if (this.anyDirection || !this.characterOnGround) {
1204
1297
  const targetAnimation = this.getTargetAnimation();
1205
1298
  this.character.updateAnimation(targetAnimation);
1206
1299
  } else {
1207
1300
  this.character.updateAnimation(0 /* idle */);
1208
1301
  }
1209
- if (this.anyDirection)
1302
+ if (this.anyDirection) {
1210
1303
  this.updateRotation();
1211
- for (let i = 0; i < this.collisionDetectionSteps; i++) {
1212
- this.updatePosition(this.timeManager.deltaTime / this.collisionDetectionSteps, i);
1213
1304
  }
1214
- if (this.character.position.y < 0)
1305
+ for (let i = 0; i < collisionDetectionSteps; i++) {
1306
+ this.updatePosition(
1307
+ this.timeManager.deltaTime,
1308
+ this.timeManager.deltaTime / collisionDetectionSteps,
1309
+ i
1310
+ );
1311
+ }
1312
+ if (this.character.position.y < 0) {
1215
1313
  this.resetPosition();
1314
+ }
1216
1315
  this.updateNetworkState();
1217
1316
  }
1218
1317
  getTargetAnimation() {
1219
1318
  if (!this.character)
1220
1319
  return 0 /* idle */;
1221
- if (this.conflictingDirections)
1222
- return 0 /* idle */;
1223
1320
  const jumpHeight = this.characterVelocity.y > 0 ? 0.2 : 1.8;
1224
1321
  if (this.currentHeight > jumpHeight && !this.characterOnGround) {
1225
1322
  return 4 /* air */;
1226
1323
  }
1324
+ if (this.conflictingDirections) {
1325
+ return 0 /* idle */;
1326
+ }
1227
1327
  return this.run && this.anyDirection ? 2 /* running */ : this.anyDirection ? 1 /* walking */ : 0 /* idle */;
1228
1328
  }
1229
1329
  updateRotationOffset() {
@@ -1253,9 +1353,7 @@ var LocalController = class {
1253
1353
  );
1254
1354
  const isCameraFirstPerson = camToModelDistance < 2;
1255
1355
  if (isCameraFirstPerson) {
1256
- const cameraForward = new Vector35(0, 0, 1).applyQuaternion(
1257
- this.cameraManager.camera.quaternion
1258
- );
1356
+ const cameraForward = this.tempVector.set(0, 0, 1).applyQuaternion(this.cameraManager.camera.quaternion);
1259
1357
  this.azimuthalAngle = Math.atan2(cameraForward.x, cameraForward.z);
1260
1358
  } else {
1261
1359
  this.azimuthalAngle = Math.atan2(
@@ -1270,91 +1368,162 @@ var LocalController = class {
1270
1368
  updateRotation() {
1271
1369
  this.updateRotationOffset();
1272
1370
  this.updateAzimuthalAngle();
1273
- const rotationQuaternion = new Quaternion2();
1274
- rotationQuaternion.setFromAxisAngle(this.vectorUp, this.azimuthalAngle + this.rotationOffset);
1371
+ const rotationQuaternion = this.tempQuaternion.setFromAxisAngle(
1372
+ this.vectorUp,
1373
+ this.azimuthalAngle + this.rotationOffset
1374
+ );
1275
1375
  const angularDifference = this.computeAngularDifference(rotationQuaternion);
1276
1376
  const desiredTime = 0.07;
1277
1377
  const angularSpeed = angularDifference / desiredTime;
1278
1378
  const frameRotation = angularSpeed * this.timeManager.deltaTime;
1279
1379
  this.character.quaternion.rotateTowards(rotationQuaternion, frameRotation);
1280
1380
  }
1281
- addScaledVectorToCharacter(deltaTime) {
1282
- this.character.position.addScaledVector(this.tempVector, this.speed * deltaTime);
1283
- }
1284
- updatePosition(deltaTime, _iter) {
1381
+ applyControls(deltaTime) {
1382
+ const resistance = this.characterOnGround ? groundResistance : airResistance;
1383
+ const speedFactor = Math.pow(1 - resistance, deltaTime);
1384
+ this.characterVelocity.multiplyScalar(speedFactor);
1385
+ const acceleration = this.tempVector.set(0, 0, 0);
1285
1386
  if (this.characterOnGround) {
1286
- if (!this.jump)
1387
+ if (!this.jump) {
1287
1388
  this.canJump = true;
1389
+ }
1288
1390
  if (this.jump && this.canJump) {
1289
- this.characterVelocity.y += this.jumpForce;
1391
+ acceleration.y += this.jumpForce / deltaTime;
1290
1392
  this.canJump = false;
1291
1393
  } else {
1292
- this.characterVelocity.y = deltaTime * this.gravity;
1394
+ if (this.currentSurfaceAngle.y < minimumSurfaceAngle) {
1395
+ acceleration.y += this.gravity;
1396
+ }
1293
1397
  }
1294
1398
  } else if (this.jump && this.coyoteTime) {
1295
- this.characterVelocity.y = this.jumpForce;
1399
+ acceleration.y += this.jumpForce / deltaTime;
1296
1400
  this.canJump = false;
1297
1401
  } else {
1298
- this.characterVelocity.y += deltaTime * this.gravity;
1402
+ acceleration.y += this.gravity;
1299
1403
  this.canJump = false;
1300
1404
  }
1301
- this.character.position.addScaledVector(this.characterVelocity, deltaTime);
1302
- this.tempVector.set(0, 0, 0);
1303
- if (this.forward) {
1304
- const forward = new Vector35(0, 0, -1).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1305
- this.tempVector.add(forward);
1306
- }
1307
- if (this.backward) {
1308
- const backward = new Vector35(0, 0, 1).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1309
- this.tempVector.add(backward);
1310
- }
1311
- if (this.left) {
1312
- const left = new Vector35(-1, 0, 0).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1313
- this.tempVector.add(left);
1405
+ const control = (this.characterOnGround ? this.run ? groundRunControl : groundWalkControl : airControlModifier) * baseControl;
1406
+ const controlAcceleration = this.tempVector2.set(0, 0, 0);
1407
+ if (!this.conflictingDirections) {
1408
+ if (this.forward) {
1409
+ const forward = this.tempVector3.set(0, 0, -1).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1410
+ controlAcceleration.add(forward);
1411
+ }
1412
+ if (this.backward) {
1413
+ const backward = this.tempVector3.set(0, 0, 1).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1414
+ controlAcceleration.add(backward);
1415
+ }
1416
+ if (this.left) {
1417
+ const left = this.tempVector3.set(-1, 0, 0).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1418
+ controlAcceleration.add(left);
1419
+ }
1420
+ if (this.right) {
1421
+ const right = this.tempVector3.set(1, 0, 0).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1422
+ controlAcceleration.add(right);
1423
+ }
1314
1424
  }
1315
- if (this.right) {
1316
- const right = new Vector35(1, 0, 0).applyAxisAngle(this.vectorUp, this.azimuthalAngle);
1317
- this.tempVector.add(right);
1425
+ if (controlAcceleration.length() > 0) {
1426
+ controlAcceleration.normalize();
1427
+ controlAcceleration.multiplyScalar(control);
1318
1428
  }
1319
- if (this.tempVector.length() > 0) {
1320
- this.tempVector.normalize();
1321
- this.addScaledVectorToCharacter(deltaTime);
1429
+ acceleration.add(controlAcceleration);
1430
+ this.characterVelocity.addScaledVector(acceleration, deltaTime);
1431
+ this.character.position.addScaledVector(this.characterVelocity, deltaTime);
1432
+ }
1433
+ updatePosition(deltaTime, stepDeltaTime, iter) {
1434
+ this.applyControls(stepDeltaTime);
1435
+ if (iter === 0) {
1436
+ const lastMovement = this.getMovementFromSurfaces(this.character.position, deltaTime);
1437
+ if (lastMovement) {
1438
+ this.character.position.add(lastMovement.position);
1439
+ const asQuaternion = this.tempQuaternion.setFromEuler(this.character.rotation);
1440
+ const lastMovementEuler = this.tempEuler.setFromQuaternion(lastMovement.rotation);
1441
+ lastMovementEuler.x = 0;
1442
+ lastMovementEuler.z = 0;
1443
+ lastMovement.rotation.setFromEuler(lastMovementEuler);
1444
+ asQuaternion.multiply(lastMovement.rotation);
1445
+ this.character.rotation.setFromQuaternion(asQuaternion);
1446
+ }
1322
1447
  }
1323
1448
  this.character.updateMatrixWorld();
1324
- this.tempSegment.copy(this.capsuleInfo.segment);
1325
- this.tempSegment.start.applyMatrix4(this.character.matrixWorld).applyMatrix4(this.tempMatrix);
1326
- this.tempSegment.end.applyMatrix4(this.character.matrixWorld).applyMatrix4(this.tempMatrix);
1327
- this.collisionsManager.applyColliders(this.tempSegment, this.capsuleInfo.radius);
1328
- const newPosition = this.tempVector;
1329
- newPosition.copy(this.tempSegment.start);
1330
- const deltaVector = this.tempVector2;
1331
- deltaVector.subVectors(newPosition, this.character.position);
1332
- const offset = Math.max(0, deltaVector.length() - 1e-5);
1333
- deltaVector.normalize().multiplyScalar(offset);
1334
- this.character.position.add(deltaVector);
1335
- this.characterOnGround = deltaVector.y > Math.abs(deltaTime * this.characterVelocity.y * 0.25);
1449
+ const avatarSegment = this.tempSegment;
1450
+ avatarSegment.copy(this.capsuleInfo.segment);
1451
+ avatarSegment.start.applyMatrix4(this.character.matrixWorld).applyMatrix4(this.tempMatrix);
1452
+ avatarSegment.end.applyMatrix4(this.character.matrixWorld).applyMatrix4(this.tempMatrix);
1453
+ const positionBeforeCollisions = this.tempVector.copy(avatarSegment.start);
1454
+ this.collisionsManager.applyColliders(avatarSegment, this.capsuleInfo.radius);
1455
+ this.character.position.copy(avatarSegment.start);
1456
+ const deltaCollisionPosition = avatarSegment.start.sub(positionBeforeCollisions);
1457
+ this.characterOnGround = deltaCollisionPosition.y > 0;
1336
1458
  if (this.characterWasOnGround && !this.characterOnGround) {
1337
1459
  this.characterAirborneSince = Date.now();
1338
1460
  }
1339
1461
  this.coyoteTime = this.characterVelocity.y < 0 && !this.characterOnGround && Date.now() - this.characterAirborneSince < this.coyoteTimeThreshold;
1340
1462
  this.characterWasOnGround = this.characterOnGround;
1341
- if (this.characterOnGround) {
1342
- this.characterVelocity.set(0, 0, 0);
1463
+ }
1464
+ getMovementFromSurfaces(userPosition, deltaTime) {
1465
+ let lastMovement = null;
1466
+ if (this.lastFrameSurfaceState !== null) {
1467
+ const meshState = this.lastFrameSurfaceState[0];
1468
+ const currentFrameMatrix = meshState.matrix;
1469
+ const lastFrameMatrix = this.lastFrameSurfaceState[1].lastMatrix;
1470
+ if (lastFrameMatrix.equals(currentFrameMatrix)) {
1471
+ } else {
1472
+ const lastMeshPosition = this.surfaceTempVector1;
1473
+ const lastMeshRotation = this.surfaceTempQuaternion;
1474
+ lastFrameMatrix.decompose(lastMeshPosition, lastMeshRotation, this.surfaceTempVector3);
1475
+ const currentMeshPosition = this.surfaceTempVector2;
1476
+ const currentMeshRotation = this.surfaceTempQuaternion2;
1477
+ currentFrameMatrix.decompose(
1478
+ currentMeshPosition,
1479
+ currentMeshRotation,
1480
+ this.surfaceTempVector3
1481
+ );
1482
+ const meshTranslationDelta = this.surfaceTempVector5.copy(currentMeshPosition).sub(lastMeshPosition);
1483
+ const lastFrameRelativeUserPosition = this.surfaceTempVector3.copy(userPosition).sub(lastMeshPosition);
1484
+ const meshRotationDelta = lastMeshRotation.invert().multiply(currentMeshRotation);
1485
+ const translationDueToRotation = this.surfaceTempVector4.copy(lastFrameRelativeUserPosition).applyQuaternion(meshRotationDelta).sub(lastFrameRelativeUserPosition);
1486
+ const translationAndRotationPositionDelta = this.surfaceTempVector1.copy(meshTranslationDelta).add(translationDueToRotation);
1487
+ lastMovement = {
1488
+ position: translationAndRotationPositionDelta,
1489
+ rotation: meshRotationDelta
1490
+ };
1491
+ lastFrameMatrix.copy(currentFrameMatrix);
1492
+ }
1493
+ }
1494
+ const newPosition = this.surfaceTempVector3.copy(userPosition);
1495
+ if (lastMovement) {
1496
+ newPosition.add(lastMovement.position);
1497
+ }
1498
+ newPosition.setY(newPosition.y + 0.05);
1499
+ const ray = this.surfaceTempRay.set(newPosition, downVector);
1500
+ const hit = this.collisionsManager.raycastFirst(ray);
1501
+ if (hit && hit[0] < 0.8) {
1502
+ const currentCollisionMeshState = hit[2];
1503
+ this.lastFrameSurfaceState = [
1504
+ currentCollisionMeshState,
1505
+ { lastMatrix: currentCollisionMeshState.matrix.clone() }
1506
+ ];
1343
1507
  } else {
1344
- deltaVector.normalize();
1345
- this.characterVelocity.addScaledVector(deltaVector, -deltaVector.dot(this.characterVelocity));
1508
+ if (this.lastFrameSurfaceState !== null && lastMovement) {
1509
+ this.characterVelocity.add(
1510
+ lastMovement.position.clone().divideScalar(deltaTime)
1511
+ // The position delta is the result of one tick which is deltaTime seconds, so we need to divide by deltaTime to get the velocity per second
1512
+ );
1513
+ }
1514
+ this.lastFrameSurfaceState = null;
1346
1515
  }
1516
+ return lastMovement;
1347
1517
  }
1348
1518
  updateNetworkState() {
1349
- const characterQuaternion = this.character.getWorldQuaternion(new Quaternion2());
1350
- const positionUpdate = new Vector35(
1351
- this.character.position.x,
1352
- this.character.position.y,
1353
- this.character.position.z
1354
- );
1519
+ const characterQuaternion = this.character.getWorldQuaternion(this.tempQuaternion);
1355
1520
  this.networkState = {
1356
1521
  id: this.id,
1357
- position: positionUpdate,
1522
+ position: {
1523
+ x: this.character.position.x,
1524
+ y: this.character.position.y,
1525
+ z: this.character.position.z
1526
+ },
1358
1527
  rotation: { quaternionY: characterQuaternion.y, quaternionW: characterQuaternion.w },
1359
1528
  state: this.character.getCurrentAnimation()
1360
1529
  };
@@ -1424,7 +1593,7 @@ function decodeCharacterAndCamera(hash) {
1424
1593
 
1425
1594
  // src/character/CharacterManager.ts
1426
1595
  var CharacterManager = class {
1427
- constructor(composer, characterModelLoader, collisionsManager, cameraManager, timeManager, keyInputManager, clientStates, sendUpdate) {
1596
+ constructor(composer, characterModelLoader, collisionsManager, cameraManager, timeManager, keyInputManager, clientStates, sendUpdate, animationConfig, characterDescription) {
1428
1597
  this.composer = composer;
1429
1598
  this.characterModelLoader = characterModelLoader;
1430
1599
  this.collisionsManager = collisionsManager;
@@ -1433,23 +1602,25 @@ var CharacterManager = class {
1433
1602
  this.keyInputManager = keyInputManager;
1434
1603
  this.clientStates = clientStates;
1435
1604
  this.sendUpdate = sendUpdate;
1605
+ this.animationConfig = animationConfig;
1606
+ this.characterDescription = characterDescription;
1436
1607
  this.updateLocationHash = true;
1437
1608
  this.headTargetOffset = new Vector38(0, 1.3, 0);
1438
1609
  this.id = 0;
1439
1610
  this.remoteCharacters = /* @__PURE__ */ new Map();
1440
1611
  this.remoteCharacterControllers = /* @__PURE__ */ new Map();
1441
- this.characterDescription = null;
1612
+ this.localCharacterSpawned = false;
1442
1613
  this.localCharacter = null;
1443
1614
  this.cameraOffsetTarget = 0;
1444
1615
  this.cameraOffset = 0;
1445
1616
  this.speakingCharacters = /* @__PURE__ */ new Map();
1446
1617
  this.group = new Group2();
1447
1618
  }
1448
- spawnCharacter(characterDescription, id, isLocal = false, spawnPosition = new Vector38(), spawnRotation = new Euler()) {
1619
+ spawnLocalCharacter(characterDescription, id, spawnPosition = new Vector38(), spawnRotation = new Euler2()) {
1449
1620
  var _a;
1450
- this.characterDescription = characterDescription;
1451
1621
  const character = new Character(
1452
1622
  characterDescription,
1623
+ this.animationConfig,
1453
1624
  this.characterModelLoader,
1454
1625
  id,
1455
1626
  () => {
@@ -1457,39 +1628,50 @@ var CharacterManager = class {
1457
1628
  this.cameraManager,
1458
1629
  this.composer
1459
1630
  );
1460
- if (isLocal) {
1461
- const quaternion = new Quaternion5().setFromEuler(character.rotation);
1462
- this.sendUpdate({
1463
- id,
1464
- position: {
1465
- x: spawnPosition.x,
1466
- y: spawnPosition.y,
1467
- z: spawnPosition.z
1468
- },
1469
- rotation: { quaternionY: quaternion.y, quaternionW: quaternion.w },
1470
- state: 0 /* idle */
1471
- });
1472
- }
1473
- if (isLocal) {
1474
- this.id = id;
1475
- this.localCharacter = character;
1476
- this.localController = new LocalController(
1477
- this.localCharacter,
1478
- this.id,
1479
- this.collisionsManager,
1480
- this.keyInputManager,
1481
- this.cameraManager,
1482
- this.timeManager
1483
- );
1484
- this.localCharacter.position.set(spawnPosition.x, spawnPosition.y, spawnPosition.z);
1485
- this.localCharacter.rotation.set(spawnRotation.x, spawnRotation.y, spawnRotation.z);
1486
- } else {
1487
- this.remoteCharacters.set(id, character);
1488
- const remoteController = new RemoteController(character, id);
1489
- remoteController.character.position.set(spawnPosition.x, spawnPosition.y, spawnPosition.z);
1490
- remoteController.character.rotation.set(spawnRotation.x, spawnRotation.y, spawnRotation.z);
1491
- this.remoteCharacterControllers.set(id, remoteController);
1492
- }
1631
+ const quaternion = new Quaternion5().setFromEuler(character.rotation);
1632
+ this.sendUpdate({
1633
+ id,
1634
+ position: {
1635
+ x: spawnPosition.x,
1636
+ y: spawnPosition.y,
1637
+ z: spawnPosition.z
1638
+ },
1639
+ rotation: { quaternionY: quaternion.y, quaternionW: quaternion.w },
1640
+ state: 0 /* idle */
1641
+ });
1642
+ this.id = id;
1643
+ this.localCharacter = character;
1644
+ this.localController = new LocalController(
1645
+ this.localCharacter,
1646
+ this.id,
1647
+ this.collisionsManager,
1648
+ this.keyInputManager,
1649
+ this.cameraManager,
1650
+ this.timeManager
1651
+ );
1652
+ this.localCharacter.position.set(spawnPosition.x, spawnPosition.y, spawnPosition.z);
1653
+ this.localCharacter.rotation.set(spawnRotation.x, spawnRotation.y, spawnRotation.z);
1654
+ (_a = character.tooltip) == null ? void 0 : _a.setText(`${id}`);
1655
+ this.group.add(character);
1656
+ this.localCharacterSpawned = true;
1657
+ }
1658
+ spawnRemoteCharacter(characterDescription, id, spawnPosition = new Vector38(), spawnRotation = new Euler2()) {
1659
+ var _a;
1660
+ const character = new Character(
1661
+ characterDescription,
1662
+ this.animationConfig,
1663
+ this.characterModelLoader,
1664
+ id,
1665
+ () => {
1666
+ },
1667
+ this.cameraManager,
1668
+ this.composer
1669
+ );
1670
+ this.remoteCharacters.set(id, character);
1671
+ const remoteController = new RemoteController(character, id);
1672
+ remoteController.character.position.set(spawnPosition.x, spawnPosition.y, spawnPosition.z);
1673
+ remoteController.character.rotation.set(spawnRotation.x, spawnRotation.y, spawnRotation.z);
1674
+ this.remoteCharacterControllers.set(id, remoteController);
1493
1675
  (_a = character.tooltip) == null ? void 0 : _a.setText(`${id}`);
1494
1676
  this.group.add(character);
1495
1677
  }
@@ -1526,27 +1708,26 @@ var CharacterManager = class {
1526
1708
  if (this.speakingCharacters.has(this.id)) {
1527
1709
  (_a = this.localCharacter.speakingIndicator) == null ? void 0 : _a.setSpeaking(this.speakingCharacters.get(this.id));
1528
1710
  }
1711
+ this.localController.update();
1712
+ if (this.timeManager.frame % 2 === 0) {
1713
+ this.sendUpdate(this.localController.networkState);
1714
+ }
1529
1715
  this.cameraOffsetTarget = this.cameraManager.targetDistance <= 0.4 ? 0.13 : 0;
1530
1716
  this.cameraOffset += ease(this.cameraOffsetTarget, this.cameraOffset, 0.1);
1531
1717
  const targetOffset = new Vector38(0, 0, this.cameraOffset);
1532
1718
  targetOffset.add(this.headTargetOffset);
1533
1719
  targetOffset.applyQuaternion(this.localCharacter.quaternion);
1534
1720
  this.cameraManager.setTarget(targetOffset.add(this.localCharacter.position));
1535
- this.localController.update();
1536
- if (this.timeManager.frame % 2 === 0) {
1537
- this.sendUpdate(this.localController.networkState);
1538
- }
1539
1721
  for (const [id, update] of this.clientStates) {
1540
1722
  if (this.remoteCharacters.has(id) && this.speakingCharacters.has(id)) {
1541
1723
  const character = this.remoteCharacters.get(id);
1542
1724
  (_b = character == null ? void 0 : character.speakingIndicator) == null ? void 0 : _b.setSpeaking(this.speakingCharacters.get(id));
1543
1725
  }
1544
1726
  const { position } = update;
1545
- if (!this.remoteCharacters.has(id)) {
1546
- this.spawnCharacter(
1727
+ if (!this.remoteCharacters.has(id) && this.localCharacterSpawned === true) {
1728
+ this.spawnRemoteCharacter(
1547
1729
  this.characterDescription,
1548
1730
  id,
1549
- false,
1550
1731
  new Vector38(position.x, position.y, position.z)
1551
1732
  );
1552
1733
  }
@@ -1839,7 +2020,7 @@ import { Pane } from "tweakpane";
1839
2020
  // src/tweakpane/blades/bcsFolder.ts
1840
2021
  var bcsValues = {
1841
2022
  brightness: 0,
1842
- contrast: 1.25,
2023
+ contrast: 1,
1843
2024
  saturation: 1
1844
2025
  };
1845
2026
  var bcsOptions = {
@@ -1886,22 +2067,22 @@ var BrightnessContrastSaturationFolder = class {
1886
2067
  // src/tweakpane/blades/environmentFolder.ts
1887
2068
  var sunValues = {
1888
2069
  sunPosition: {
1889
- sunAzimuthalAngle: 39,
1890
- sunPolarAngle: 50
2070
+ sunAzimuthalAngle: 215,
2071
+ sunPolarAngle: -39
1891
2072
  },
1892
- sunIntensity: 0.5,
1893
- sunColor: { r: 1, g: 0.74, b: 0.5 }
2073
+ sunIntensity: 1,
2074
+ sunColor: { r: 1, g: 1, b: 1 }
1894
2075
  };
1895
2076
  var sunOptions = {
1896
2077
  sunPosition: {
1897
2078
  sunAzimuthalAngle: { min: 0, max: 360, step: 1 },
1898
2079
  sunPolarAngle: { min: -90, max: 90, step: 1 }
1899
2080
  },
1900
- sunIntensity: { min: 0, max: 1, step: 0.05 }
2081
+ sunIntensity: { min: 0, max: 3, step: 0.05 }
1901
2082
  };
1902
2083
  var envValues = {
1903
2084
  ambientLight: {
1904
- ambientLightIntensity: 0,
2085
+ ambientLightIntensity: 0.05,
1905
2086
  ambientLightColor: { r: 1, g: 1, b: 1 }
1906
2087
  },
1907
2088
  fog: {
@@ -2756,6 +2937,7 @@ import {
2756
2937
  LinearSRGBColorSpace,
2757
2938
  LoadingManager as LoadingManager2,
2758
2939
  PMREMGenerator,
2940
+ SRGBColorSpace,
2759
2941
  Scene as Scene4,
2760
2942
  Vector2 as Vector27,
2761
2943
  WebGLRenderer as WebGLRenderer4
@@ -2769,8 +2951,8 @@ var Sun = class extends Group4 {
2769
2951
  super();
2770
2952
  this.debug = false;
2771
2953
  this.sunOffset = new Vector39(
2772
- 39 * (Math.PI / 180),
2773
- 50 * (Math.PI / 180),
2954
+ sunValues.sunPosition.sunAzimuthalAngle * (Math.PI / 180),
2955
+ sunValues.sunPosition.sunPolarAngle * (Math.PI / 180),
2774
2956
  100
2775
2957
  );
2776
2958
  this.shadowResolution = 8192;
@@ -2789,6 +2971,7 @@ var Sun = class extends Group4 {
2789
2971
  this.camHelper = new CameraHelper(this.shadowCamera);
2790
2972
  }
2791
2973
  this.directionalLight = new DirectionalLight(16777215, 0.5);
2974
+ this.directionalLight.intensity = sunValues.sunIntensity;
2792
2975
  this.directionalLight.shadow.normalBias = 0.05;
2793
2976
  this.directionalLight.shadow.radius = 1.5;
2794
2977
  this.directionalLight.shadow.camera = this.shadowCamera;
@@ -3639,7 +3822,7 @@ var EffectShader = {
3639
3822
  import {
3640
3823
  BufferAttribute,
3641
3824
  BufferGeometry,
3642
- Mesh as Mesh4,
3825
+ Mesh as Mesh3,
3643
3826
  OrthographicCamera as OrthographicCamera2,
3644
3827
  Sphere
3645
3828
  } from "three";
@@ -3655,7 +3838,7 @@ var FullScreenTriangle = class {
3655
3838
  this.geometry.boundingSphere = new Sphere();
3656
3839
  this.geometry.computeBoundingSphere = function() {
3657
3840
  };
3658
- this.mesh = new Mesh4(this.geometry, material);
3841
+ this.mesh = new Mesh3(this.geometry, material);
3659
3842
  this.mesh.frustumCulled = false;
3660
3843
  }
3661
3844
  get material() {
@@ -4319,6 +4502,7 @@ var Composer = class {
4319
4502
  stencil: false,
4320
4503
  depth: false
4321
4504
  });
4505
+ this.renderer.outputColorSpace = SRGBColorSpace;
4322
4506
  this.renderer.info.autoReset = false;
4323
4507
  this.renderer.setSize(this.width, this.height);
4324
4508
  this.renderer.shadowMap.enabled = true;
@@ -4621,51 +4805,60 @@ import {
4621
4805
  Box3,
4622
4806
  Color as Color8,
4623
4807
  DoubleSide,
4624
- Euler as Euler2,
4808
+ Euler as Euler3,
4625
4809
  Group as Group5,
4626
4810
  Line3 as Line32,
4627
4811
  Matrix4 as Matrix46,
4628
- Mesh as Mesh5,
4812
+ Mesh as Mesh4,
4629
4813
  MeshBasicMaterial as MeshBasicMaterial3,
4630
- Ray,
4814
+ Quaternion as Quaternion6,
4815
+ Ray as Ray2,
4631
4816
  Vector3 as Vector314
4632
4817
  } from "three";
4633
4818
  import { VertexNormalsHelper } from "three/examples/jsm/helpers/VertexNormalsHelper.js";
4634
4819
  import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUtils.js";
4635
- import { MeshBVH, MeshBVHVisualizer } from "three-mesh-bvh";
4820
+ import { MeshBVH, MeshBVHHelper } from "three-mesh-bvh";
4636
4821
  var CollisionsManager = class {
4637
4822
  constructor(scene) {
4638
4823
  this.debug = false;
4639
4824
  this.tempVector = new Vector314();
4640
4825
  this.tempVector2 = new Vector314();
4641
4826
  this.tempVector3 = new Vector314();
4642
- this.tempRay = new Ray();
4827
+ this.tempQuaternion = new Quaternion6();
4828
+ this.tempRay = new Ray2();
4643
4829
  this.tempMatrix = new Matrix46();
4644
4830
  this.tempMatrix2 = new Matrix46();
4645
4831
  this.tempBox = new Box3();
4646
- this.tempEuler = new Euler2();
4832
+ this.tempEuler = new Euler3();
4647
4833
  this.tempSegment = new Line32();
4648
4834
  this.tempSegment2 = new Line32();
4649
4835
  this.collisionMeshState = /* @__PURE__ */ new Map();
4650
4836
  this.scene = scene;
4651
4837
  this.collisionTrigger = MMLCollisionTrigger.init();
4652
4838
  }
4653
- raycastFirstDistance(ray) {
4839
+ raycastFirst(ray) {
4654
4840
  let minimumDistance = null;
4655
- for (const [, value] of this.collisionMeshState) {
4656
- this.tempRay.copy(ray).applyMatrix4(this.tempMatrix.copy(value.matrix).invert());
4657
- const hit = value.meshBVH.raycastFirst(this.tempRay, DoubleSide);
4841
+ let minimumHit = null;
4842
+ let minimumNormal = new Vector314();
4843
+ for (const [, collisionMeshState] of this.collisionMeshState) {
4844
+ this.tempRay.copy(ray).applyMatrix4(this.tempMatrix.copy(collisionMeshState.matrix).invert());
4845
+ const hit = collisionMeshState.meshBVH.raycastFirst(this.tempRay, DoubleSide);
4658
4846
  if (hit) {
4659
4847
  this.tempSegment.start.copy(this.tempRay.origin);
4660
4848
  this.tempSegment.end.copy(hit.point);
4661
- this.tempSegment.applyMatrix4(value.matrix);
4849
+ this.tempSegment.applyMatrix4(collisionMeshState.matrix);
4662
4850
  const dist = this.tempSegment.distance();
4663
4851
  if (minimumDistance === null || dist < minimumDistance) {
4664
4852
  minimumDistance = dist;
4853
+ minimumHit = collisionMeshState;
4854
+ minimumNormal = (hit.normal ? minimumNormal.copy(hit.normal) : minimumNormal).applyQuaternion(this.tempQuaternion.setFromRotationMatrix(collisionMeshState.matrix)).normalize();
4665
4855
  }
4666
4856
  }
4667
4857
  }
4668
- return minimumDistance;
4858
+ if (minimumDistance === null || minimumNormal === null || minimumHit === null) {
4859
+ return null;
4860
+ }
4861
+ return [minimumDistance, minimumNormal, minimumHit];
4669
4862
  }
4670
4863
  createCollisionMeshState(group, trackCollisions) {
4671
4864
  const geometries = [];
@@ -4704,9 +4897,9 @@ var CollisionsManager = class {
4704
4897
  };
4705
4898
  if (this.debug) {
4706
4899
  newBufferGeometry.boundsTree = meshBVH;
4707
- const wireframeMesh = new Mesh5(newBufferGeometry, new MeshBasicMaterial3({ wireframe: true }));
4900
+ const wireframeMesh = new Mesh4(newBufferGeometry, new MeshBasicMaterial3({ wireframe: true }));
4708
4901
  const normalsHelper = new VertexNormalsHelper(wireframeMesh, 0.25, 65280);
4709
- const visualizer = new MeshBVHVisualizer(wireframeMesh, 4);
4902
+ const visualizer = new MeshBVHHelper(wireframeMesh, 4);
4710
4903
  visualizer.edgeMaterial.color = new Color8("blue");
4711
4904
  const debugGroup = new Group5();
4712
4905
  debugGroup.add(wireframeMesh, normalsHelper, visualizer);