@mml-io/3d-web-client-core 0.4.0 → 0.6.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
@@ -48,13 +48,13 @@ var CameraManager = class {
48
48
  constructor(collisionsManager) {
49
49
  this.collisionsManager = collisionsManager;
50
50
  __publicField(this, "camera");
51
- __publicField(this, "initialDistance", 2.5);
51
+ __publicField(this, "initialDistance", 3.3);
52
52
  __publicField(this, "minDistance", 0.1);
53
- __publicField(this, "maxDistance", 6);
54
- __publicField(this, "initialFOV", 80);
53
+ __publicField(this, "maxDistance", 8);
54
+ __publicField(this, "initialFOV", 60);
55
55
  __publicField(this, "fov", this.initialFOV);
56
- __publicField(this, "minFOV", 63);
57
- __publicField(this, "maxFOV", 85);
56
+ __publicField(this, "minFOV", 50);
57
+ __publicField(this, "maxFOV", 70);
58
58
  __publicField(this, "targetFOV", this.initialFOV);
59
59
  __publicField(this, "minPolarAngle", Math.PI * 0.25);
60
60
  __publicField(this, "maxPolarAngle", Math.PI * 0.95);
@@ -168,7 +168,7 @@ var CameraManager = class {
168
168
  };
169
169
 
170
170
  // src/character/Character.ts
171
- import { Color as Color2, Vector3 as Vector34 } from "three";
171
+ import { Color as Color3, Vector3 as Vector34 } from "three";
172
172
 
173
173
  // src/character/CharacterModel.ts
174
174
  import {
@@ -724,6 +724,246 @@ var CharacterModel = class {
724
724
  }
725
725
  };
726
726
 
727
+ // src/character/CharacterTooltip.ts
728
+ import {
729
+ Color as Color2,
730
+ FrontSide,
731
+ LinearFilter as LinearFilter2,
732
+ Mesh as Mesh2,
733
+ MeshBasicMaterial as MeshBasicMaterial2,
734
+ PlaneGeometry
735
+ } from "three";
736
+
737
+ // src/character/CanvasText.ts
738
+ import * as THREE from "three";
739
+ function getTextAlignOffset(textAlign, width) {
740
+ switch (textAlign) {
741
+ case "center":
742
+ return width / 2;
743
+ case "right":
744
+ return width;
745
+ default:
746
+ return 0;
747
+ }
748
+ }
749
+ function printAtWordWrap(context, fullText, x, y, lineHeight, fitWidth, padding, alignment) {
750
+ const lines = fullText.split("\n");
751
+ let currentLine = 0;
752
+ for (const text of lines) {
753
+ fitWidth = fitWidth || 0;
754
+ if (fitWidth <= 0) {
755
+ context.fillText(text, x, y + lineHeight * currentLine);
756
+ currentLine++;
757
+ continue;
758
+ }
759
+ let words = text.split(" ");
760
+ let lastWordIndex = 1;
761
+ while (words.length > 0 && lastWordIndex <= words.length) {
762
+ const str = words.slice(0, lastWordIndex).join(" ");
763
+ const textWidth = context.measureText(str).width;
764
+ if (textWidth + padding * 2 > fitWidth) {
765
+ if (lastWordIndex === 1) {
766
+ lastWordIndex = 2;
767
+ }
768
+ context.fillText(
769
+ words.slice(0, lastWordIndex - 1).join(" "),
770
+ x + padding,
771
+ y + lineHeight * currentLine + padding
772
+ );
773
+ currentLine++;
774
+ words = words.splice(lastWordIndex - 1);
775
+ lastWordIndex = 1;
776
+ } else {
777
+ lastWordIndex++;
778
+ }
779
+ }
780
+ if (lastWordIndex > 0 && words.length > 0) {
781
+ const xOffset = alignment === "center" ? 0 : padding;
782
+ context.fillText(words.join(" "), x + xOffset, y + lineHeight * currentLine + padding);
783
+ currentLine++;
784
+ }
785
+ }
786
+ }
787
+ function CanvasText(message, options) {
788
+ const fontsize = options.fontSize;
789
+ const textColor = options.textColorRGB255A1;
790
+ const backgroundColor = options.backgroundColorRGB255A1 || { r: 255, g: 255, b: 255, a: 1 };
791
+ const padding = options.paddingPx || 0;
792
+ const font = options.font || "Arial";
793
+ const fontString = (options.bold ? "bold " : "") + fontsize + "px " + font;
794
+ const canvas = document.createElement("canvas");
795
+ const ct = canvas.getContext("2d");
796
+ const textAlign = options.alignment ?? "left";
797
+ if (options.dimensions) {
798
+ canvas.width = options.dimensions.width;
799
+ canvas.height = options.dimensions.height;
800
+ ct.clearRect(0, 0, canvas.width, canvas.height);
801
+ ct.font = fontString;
802
+ ct.textAlign = textAlign;
803
+ ct.fillStyle = `rgba(${backgroundColor.r}, ${backgroundColor.g}, ${backgroundColor.b}, ${backgroundColor.a})`;
804
+ ct.lineWidth = 0;
805
+ ct.fillRect(0, 0, canvas.width, canvas.height);
806
+ ct.fillStyle = `rgba(${textColor.r}, ${textColor.g}, ${textColor.b}, ${textColor.a})`;
807
+ ct.font = fontString;
808
+ printAtWordWrap(
809
+ ct,
810
+ message,
811
+ getTextAlignOffset(textAlign, canvas.width),
812
+ fontsize,
813
+ fontsize,
814
+ canvas.width,
815
+ padding,
816
+ textAlign
817
+ );
818
+ } else {
819
+ ct.font = fontString;
820
+ const metrics = ct.measureText(message);
821
+ const textWidth = metrics.width;
822
+ const textHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
823
+ canvas.width = textWidth + padding * 2;
824
+ canvas.height = textHeight + padding;
825
+ ct.clearRect(0, 0, canvas.width, canvas.height);
826
+ ct.font = fontString;
827
+ ct.textAlign = textAlign;
828
+ ct.fillStyle = `rgba(${backgroundColor.r}, ${backgroundColor.g}, ${backgroundColor.b}, ${backgroundColor.a})`;
829
+ ct.lineWidth = 0;
830
+ ct.fillRect(0, 0, canvas.width, canvas.height);
831
+ ct.fillStyle = `rgba(${textColor.r}, ${textColor.g}, ${textColor.b}, ${textColor.a})`;
832
+ ct.font = fontString;
833
+ ct.fillText(message, padding + getTextAlignOffset(textAlign, textWidth), textHeight);
834
+ }
835
+ return canvas;
836
+ }
837
+ function THREECanvasTextTexture(text, options) {
838
+ const canvas = CanvasText(text, options);
839
+ const texture = new THREE.Texture(canvas);
840
+ texture.minFilter = THREE.LinearFilter;
841
+ texture.magFilter = THREE.LinearFilter;
842
+ texture.format = THREE.RGBAFormat;
843
+ texture.needsUpdate = true;
844
+ return { texture, width: canvas.width, height: canvas.height };
845
+ }
846
+
847
+ // src/character/CharacterTooltip.ts
848
+ var fontScale = 5;
849
+ var defaultLabelColor = new Color2(0);
850
+ var defaultFontColor = new Color2(16777215);
851
+ var defaultLabelAlignment = "center" /* center */;
852
+ var defaultLabelFontSize = 9;
853
+ var defaultLabelPadding = 0;
854
+ var defaultLabelWidth = 0.25;
855
+ var defaultLabelHeight = 0.125;
856
+ var defaultLabelCastShadows = true;
857
+ var CharacterTooltip = class {
858
+ constructor(parentModel) {
859
+ __publicField(this, "geometry");
860
+ __publicField(this, "material");
861
+ __publicField(this, "mesh");
862
+ __publicField(this, "visibleOpacity", 0.85);
863
+ __publicField(this, "targetOpacity", 0);
864
+ __publicField(this, "fadingSpeed", 0.02);
865
+ __publicField(this, "secondsToFadeOut", 15);
866
+ __publicField(this, "props", {
867
+ content: "",
868
+ alignment: defaultLabelAlignment,
869
+ width: defaultLabelWidth,
870
+ height: defaultLabelHeight,
871
+ fontSize: defaultLabelFontSize,
872
+ padding: defaultLabelPadding,
873
+ color: defaultLabelColor,
874
+ fontColor: defaultFontColor,
875
+ castShadows: defaultLabelCastShadows
876
+ });
877
+ this.setText = this.setText.bind(this);
878
+ this.material = new MeshBasicMaterial2({
879
+ map: null,
880
+ transparent: true,
881
+ opacity: 0
882
+ });
883
+ this.material.side = FrontSide;
884
+ this.geometry = new PlaneGeometry(1, 1, 1, 1);
885
+ this.mesh = new Mesh2(this.geometry, this.material);
886
+ this.mesh.position.set(0, 1.6, 0);
887
+ this.mesh.visible = false;
888
+ parentModel.add(this.mesh);
889
+ }
890
+ redrawText(content) {
891
+ if (!this.material) {
892
+ return;
893
+ }
894
+ if (this.material.map) {
895
+ this.material.map.dispose();
896
+ }
897
+ const { texture, width, height } = THREECanvasTextTexture(content, {
898
+ bold: true,
899
+ fontSize: this.props.fontSize * fontScale,
900
+ paddingPx: this.props.padding,
901
+ textColorRGB255A1: {
902
+ r: this.props.fontColor.r * 255,
903
+ g: this.props.fontColor.g * 255,
904
+ b: this.props.fontColor.b * 255,
905
+ a: 1
906
+ },
907
+ backgroundColorRGB255A1: {
908
+ r: this.props.color.r * 255,
909
+ g: this.props.color.g * 255,
910
+ b: this.props.color.b * 255,
911
+ a: 1
912
+ },
913
+ dimensions: {
914
+ width: this.props.width * (100 * fontScale),
915
+ height: this.props.height * (100 * fontScale)
916
+ },
917
+ alignment: this.props.alignment
918
+ });
919
+ this.material.map = texture;
920
+ this.material.map.magFilter = LinearFilter2;
921
+ this.material.map.minFilter = LinearFilter2;
922
+ this.material.needsUpdate = true;
923
+ this.mesh.scale.x = width / (100 * fontScale);
924
+ this.mesh.scale.y = height / (100 * fontScale);
925
+ this.mesh.position.y = 1.6;
926
+ }
927
+ setText(text, temporary = false) {
928
+ this.redrawText(text);
929
+ this.mesh.visible = true;
930
+ this.targetOpacity = this.visibleOpacity;
931
+ if (temporary) {
932
+ setTimeout(() => {
933
+ this.hide();
934
+ }, this.secondsToFadeOut * 1e3);
935
+ }
936
+ }
937
+ hide() {
938
+ this.targetOpacity = 0;
939
+ }
940
+ update(camera) {
941
+ this.mesh.lookAt(camera.position);
942
+ const opacity = this.mesh.material.opacity;
943
+ if (opacity < this.targetOpacity) {
944
+ this.mesh.material.opacity = Math.min(
945
+ this.mesh.material.opacity + this.fadingSpeed,
946
+ this.targetOpacity
947
+ );
948
+ } else if (opacity > this.targetOpacity) {
949
+ this.mesh.material.opacity = Math.max(
950
+ this.mesh.material.opacity - this.fadingSpeed,
951
+ this.targetOpacity
952
+ );
953
+ if (opacity >= 1 && this.mesh.material.transparent === true) {
954
+ this.mesh.material.transparent = false;
955
+ this.mesh.material.needsUpdate = true;
956
+ } else if (opacity > 0 && opacity < 1 && this.mesh.material.transparent === false) {
957
+ this.mesh.material.transparent = true;
958
+ this.mesh.material.needsUpdate = true;
959
+ }
960
+ if (this.mesh.material.opacity <= 0) {
961
+ this.mesh.visible = false;
962
+ }
963
+ }
964
+ }
965
+ };
966
+
727
967
  // src/character/LocalController.ts
728
968
  import { Box3, Line3, Matrix4, Quaternion, Raycaster as Raycaster2, Vector3 as Vector33 } from "three";
729
969
  var LocalController = class {
@@ -743,7 +983,7 @@ var LocalController = class {
743
983
  __publicField(this, "maxRunSpeed", 8.5);
744
984
  __publicField(this, "gravity", -42);
745
985
  __publicField(this, "jumpForce", 16);
746
- __publicField(this, "coyoteTimeThreshold", 290);
986
+ __publicField(this, "coyoteTimeThreshold", 70);
747
987
  __publicField(this, "coyoteTime", false);
748
988
  __publicField(this, "canJump", true);
749
989
  __publicField(this, "characterOnGround", false);
@@ -772,13 +1012,13 @@ var LocalController = class {
772
1012
  __publicField(this, "thirdPersonCamera", null);
773
1013
  __publicField(this, "speed", 0);
774
1014
  __publicField(this, "targetSpeed", 0);
775
- __publicField(this, "networkState", {
776
- id: 0,
1015
+ __publicField(this, "networkState");
1016
+ this.networkState = {
1017
+ id: this.id,
777
1018
  position: { x: 0, y: 0, z: 0 },
778
- rotation: { quaternionY: 0, quaternionW: 0 },
1019
+ rotation: { quaternionY: 0, quaternionW: 1 },
779
1020
  state: 0 /* idle */
780
- });
781
- setInterval(() => this.update.bind(this), 3e3);
1021
+ };
782
1022
  }
783
1023
  update() {
784
1024
  if (!this.model?.mesh || !this.model?.animationMixer)
@@ -863,6 +1103,11 @@ var LocalController = class {
863
1103
  );
864
1104
  }
865
1105
  }
1106
+ computeAngularDifference(rotationQuaternion) {
1107
+ if (!this.model?.mesh)
1108
+ return 0;
1109
+ return 2 * Math.acos(Math.abs(this.model.mesh.quaternion.dot(rotationQuaternion)));
1110
+ }
866
1111
  updateRotation() {
867
1112
  if (!this.thirdPersonCamera || !this.model?.mesh)
868
1113
  return;
@@ -870,7 +1115,11 @@ var LocalController = class {
870
1115
  this.updateAzimuthalAngle();
871
1116
  const rotationQuaternion = new Quaternion();
872
1117
  rotationQuaternion.setFromAxisAngle(this.vectorUp, this.azimuthalAngle + this.rotationOffset);
873
- this.model.mesh.quaternion.rotateTowards(rotationQuaternion, 0.07);
1118
+ const angularDifference = this.computeAngularDifference(rotationQuaternion);
1119
+ const desiredTime = 0.07;
1120
+ const angularSpeed = angularDifference / desiredTime;
1121
+ const frameRotation = angularSpeed * this.timeManager.deltaTime;
1122
+ this.model.mesh.quaternion.rotateTowards(rotationQuaternion, frameRotation);
874
1123
  }
875
1124
  addScaledVectorToCharacter(deltaTime) {
876
1125
  if (!this.model?.mesh)
@@ -950,20 +1199,27 @@ var LocalController = class {
950
1199
  }
951
1200
  }
952
1201
  updateNetworkState() {
953
- if (!this.model?.mesh)
954
- return;
955
- const characterQuaternion = this.model.mesh.getWorldQuaternion(new Quaternion());
956
- const positionUpdate = new Vector33(
957
- this.model.mesh.position.x,
958
- this.model.mesh.position.y,
959
- this.model.mesh.position.z
960
- );
961
- this.networkState = {
962
- id: this.id,
963
- position: positionUpdate,
964
- rotation: { quaternionY: characterQuaternion?.y, quaternionW: characterQuaternion?.w },
965
- state: this.model.currentAnimation
966
- };
1202
+ if (!this.model?.mesh) {
1203
+ this.networkState = {
1204
+ id: this.id,
1205
+ position: new Vector33(),
1206
+ rotation: { quaternionY: 0, quaternionW: 1 },
1207
+ state: 0 /* idle */
1208
+ };
1209
+ } else {
1210
+ const characterQuaternion = this.model.mesh.getWorldQuaternion(new Quaternion());
1211
+ const positionUpdate = new Vector33(
1212
+ this.model.mesh.position.x,
1213
+ this.model.mesh.position.y,
1214
+ this.model.mesh.position.z
1215
+ );
1216
+ this.networkState = {
1217
+ id: this.id,
1218
+ position: positionUpdate,
1219
+ rotation: { quaternionY: characterQuaternion.y, quaternionW: characterQuaternion.w },
1220
+ state: this.model.currentAnimation
1221
+ };
1222
+ }
967
1223
  }
968
1224
  resetPosition() {
969
1225
  if (!this.model?.mesh)
@@ -988,13 +1244,17 @@ var Character = class {
988
1244
  __publicField(this, "controller", null);
989
1245
  __publicField(this, "name", null);
990
1246
  __publicField(this, "model", null);
991
- __publicField(this, "color", new Color2());
1247
+ __publicField(this, "color", new Color3());
992
1248
  __publicField(this, "position", new Vector34());
1249
+ __publicField(this, "tooltip", null);
993
1250
  this.load();
994
1251
  }
995
1252
  async load() {
996
1253
  this.model = new CharacterModel(this.characterDescription);
997
1254
  await this.model.init();
1255
+ if (this.tooltip === null) {
1256
+ this.tooltip = new CharacterTooltip(this.model.mesh);
1257
+ }
998
1258
  this.color = this.model.material.colorsCube216[this.id];
999
1259
  if (this.isLocal) {
1000
1260
  this.controller = new LocalController(
@@ -1011,6 +1271,9 @@ var Character = class {
1011
1271
  update(time) {
1012
1272
  if (!this.model)
1013
1273
  return;
1274
+ if (this.tooltip) {
1275
+ this.tooltip.update(this.cameraManager.camera);
1276
+ }
1014
1277
  this.model.mesh.getWorldPosition(this.position);
1015
1278
  if (typeof this.model.material.uniforms.time !== "undefined") {
1016
1279
  this.model.material.uniforms.time.value = time;
@@ -1026,7 +1289,7 @@ import { Group, Vector3 as Vector36 } from "three";
1026
1289
  // src/character/RemoteController.ts
1027
1290
  import {
1028
1291
  AnimationMixer as AnimationMixer2,
1029
- Object3D as Object3D3,
1292
+ Object3D as Object3D4,
1030
1293
  Quaternion as Quaternion2,
1031
1294
  Vector3 as Vector35
1032
1295
  } from "three";
@@ -1036,18 +1299,19 @@ var RemoteController = class {
1036
1299
  this.id = id;
1037
1300
  __publicField(this, "modelLoader", ModelLoader_default);
1038
1301
  __publicField(this, "characterModel", null);
1039
- __publicField(this, "animationMixer", new AnimationMixer2(new Object3D3()));
1302
+ __publicField(this, "animationMixer", new AnimationMixer2(new Object3D4()));
1040
1303
  __publicField(this, "animations", /* @__PURE__ */ new Map());
1041
1304
  __publicField(this, "currentAnimation", 0 /* idle */);
1042
- __publicField(this, "networkState", {
1043
- id: 0,
1044
- position: { x: 0, y: 0, z: 0 },
1045
- rotation: { quaternionY: 0, quaternionW: 0 },
1046
- state: this.currentAnimation
1047
- });
1305
+ __publicField(this, "networkState");
1048
1306
  this.characterModel = this.character.model.mesh;
1049
1307
  this.characterModel.updateMatrixWorld();
1050
1308
  this.animationMixer = new AnimationMixer2(this.characterModel);
1309
+ this.networkState = {
1310
+ id: this.id,
1311
+ position: { x: 0, y: 0, z: 0 },
1312
+ rotation: { quaternionY: 0, quaternionW: 1 },
1313
+ state: this.currentAnimation
1314
+ };
1051
1315
  }
1052
1316
  update(clientUpdate, time, deltaTime) {
1053
1317
  if (!this.character)
@@ -1132,7 +1396,6 @@ var CharacterManager = class {
1132
1396
  __publicField(this, "cameraOffset", 0);
1133
1397
  __publicField(this, "group");
1134
1398
  this.group = new Group();
1135
- setInterval(() => this.update.bind(this), 3e3);
1136
1399
  }
1137
1400
  /* TODO:
1138
1401
  1) Separate this method into spawnLocalCharacter and spawnRemoteCharacter
@@ -1165,7 +1428,7 @@ var CharacterManager = class {
1165
1428
  y: spawnPosition.y,
1166
1429
  z: spawnPosition.z
1167
1430
  },
1168
- rotation: { quaternionY: 0, quaternionW: 0 },
1431
+ rotation: { quaternionY: 0, quaternionW: 1 },
1169
1432
  state: 0 /* idle */
1170
1433
  });
1171
1434
  }
@@ -1178,6 +1441,7 @@ var CharacterManager = class {
1178
1441
  this.group.add(character.model.mesh);
1179
1442
  if (isLocal) {
1180
1443
  this.character = character;
1444
+ this.character.tooltip?.setText(`${id}`);
1181
1445
  } else {
1182
1446
  this.remoteCharacters.set(id, character);
1183
1447
  const remoteController = new RemoteController(character, id);
@@ -1203,6 +1467,7 @@ var CharacterManager = class {
1203
1467
  spawnPosition.z
1204
1468
  );
1205
1469
  this.remoteCharacterControllers.set(id, remoteController);
1470
+ character.tooltip?.setText(`${id}`);
1206
1471
  }
1207
1472
  resolve(character);
1208
1473
  },
@@ -1432,7 +1697,9 @@ import {
1432
1697
  NormalPass
1433
1698
  } from "postprocessing";
1434
1699
  import {
1435
- Color as Color4,
1700
+ AmbientLight,
1701
+ Color as Color6,
1702
+ Fog,
1436
1703
  HalfFloatType,
1437
1704
  LinearSRGBColorSpace,
1438
1705
  LoadingManager as LoadingManager2,
@@ -1442,14 +1709,117 @@ import {
1442
1709
  } from "three";
1443
1710
  import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
1444
1711
 
1712
+ // src/sun/Sun.ts
1713
+ import { CameraHelper, Color as Color4, DirectionalLight, Group as Group3, OrthographicCamera, Vector3 as Vector37 } from "three";
1714
+
1715
+ // src/tweakpane/sunSettings.ts
1716
+ var sunValues = {
1717
+ sunPosition: {
1718
+ sunAzimuthalAngle: 39,
1719
+ sunPolarAngle: 50
1720
+ },
1721
+ sunIntensity: 0.5,
1722
+ sunColor: { r: 1, g: 1, b: 1 }
1723
+ };
1724
+ var sunOptions = {
1725
+ sunPosition: {
1726
+ sunAzimuthalAngle: { min: 0, max: 360, step: 1 },
1727
+ sunPolarAngle: { min: -90, max: 90, step: 1 }
1728
+ },
1729
+ sunIntensity: { min: 0, max: 1, step: 0.05 }
1730
+ };
1731
+
1732
+ // src/sun/Sun.ts
1733
+ var Sun = class extends Group3 {
1734
+ constructor() {
1735
+ super();
1736
+ __publicField(this, "debug", false);
1737
+ __publicField(this, "sunOffset", new Vector37(
1738
+ 39 * (Math.PI / 180),
1739
+ 50 * (Math.PI / 180),
1740
+ 100
1741
+ ));
1742
+ __publicField(this, "shadowResolution", 8192);
1743
+ __publicField(this, "shadowCamFrustum", 50);
1744
+ __publicField(this, "camHelper", null);
1745
+ __publicField(this, "shadowCamera");
1746
+ __publicField(this, "directionalLight");
1747
+ __publicField(this, "target", null);
1748
+ this.shadowCamera = new OrthographicCamera(
1749
+ -this.shadowCamFrustum,
1750
+ this.shadowCamFrustum,
1751
+ this.shadowCamFrustum,
1752
+ -this.shadowCamFrustum,
1753
+ 0.1,
1754
+ 200
1755
+ );
1756
+ if (this.debug === true) {
1757
+ this.camHelper = new CameraHelper(this.shadowCamera);
1758
+ }
1759
+ this.directionalLight = new DirectionalLight(16777215, 0.5);
1760
+ this.directionalLight.shadow.normalBias = 0.05;
1761
+ this.directionalLight.shadow.radius = 1.5;
1762
+ this.directionalLight.shadow.camera = this.shadowCamera;
1763
+ this.directionalLight.shadow.mapSize.set(this.shadowResolution, this.shadowResolution);
1764
+ this.directionalLight.castShadow = true;
1765
+ this.updateCharacterPosition(new Vector37(0, 0, 0));
1766
+ this.add(this.directionalLight);
1767
+ if (this.debug === true && this.camHelper instanceof CameraHelper) {
1768
+ this.add(this.camHelper);
1769
+ }
1770
+ }
1771
+ updateCharacterPosition(position) {
1772
+ if (!position)
1773
+ return;
1774
+ this.target = position;
1775
+ this.setSunPosition(this.sunOffset.x, this.sunOffset.y);
1776
+ }
1777
+ setAzimuthalAngle(angle) {
1778
+ if (this.sunOffset)
1779
+ this.sunOffset.x = angle;
1780
+ if (this.target)
1781
+ this.updateCharacterPosition(this.target);
1782
+ }
1783
+ setPolarAngle(angle) {
1784
+ if (this.sunOffset)
1785
+ this.sunOffset.y = angle;
1786
+ if (this.target)
1787
+ this.updateCharacterPosition(this.target);
1788
+ }
1789
+ setIntensity(intensity) {
1790
+ this.directionalLight.intensity = intensity;
1791
+ }
1792
+ setColor() {
1793
+ this.directionalLight.color = new Color4().setRGB(
1794
+ sunValues.sunColor.r,
1795
+ sunValues.sunColor.g,
1796
+ sunValues.sunColor.b
1797
+ );
1798
+ }
1799
+ setSunPosition(azimuthalAngle, polarAngle) {
1800
+ if (!this.target)
1801
+ return;
1802
+ const distance = this.sunOffset.z;
1803
+ const sphericalPosition = new Vector37(
1804
+ distance * Math.sin(polarAngle) * Math.cos(azimuthalAngle),
1805
+ distance * Math.cos(polarAngle),
1806
+ distance * Math.sin(polarAngle) * Math.sin(azimuthalAngle)
1807
+ );
1808
+ const newSunPosition = this.target.clone().add(sphericalPosition);
1809
+ this.directionalLight.position.set(newSunPosition.x, newSunPosition.y, newSunPosition.z);
1810
+ this.directionalLight.target.position.copy(this.target.clone());
1811
+ this.directionalLight.target.updateMatrixWorld();
1812
+ }
1813
+ };
1814
+
1445
1815
  // src/tweakpane/composerSettings.ts
1446
1816
  import { BlendFunction } from "postprocessing";
1447
1817
  var composerValues = {
1448
1818
  renderer: {
1449
1819
  shadowMap: 2,
1450
- toneMapping: 4,
1820
+ toneMapping: 5,
1451
1821
  exposure: 1,
1452
- bgIntensity: 0.6,
1822
+ bgIntensity: 0.5,
1453
1823
  bgBlurriness: 0
1454
1824
  },
1455
1825
  ssao: {
@@ -1480,17 +1850,17 @@ var composerValues = {
1480
1850
  adaptationRate: 2
1481
1851
  },
1482
1852
  brightness: -0.03,
1483
- contrast: 1.3,
1484
- saturation: 0.95,
1485
- grain: 0.055,
1486
- bloom: 0.4
1853
+ contrast: 1.21,
1854
+ saturation: 0.91,
1855
+ grain: 0.061,
1856
+ bloom: 0.25
1487
1857
  };
1488
1858
  var composerOptions = {
1489
1859
  renderer: {
1490
1860
  shadowMap: { min: 0, max: 2, step: 1 },
1491
1861
  toneMapping: { min: 0, max: 5, step: 1 },
1492
1862
  exposure: { min: 0, max: 3, step: 0.01 },
1493
- bgIntensity: { min: 0, max: 1, step: 0.01 },
1863
+ bgIntensity: { min: 0, max: 1.3, step: 0.01 },
1494
1864
  bgBlurriness: { min: 0, max: 0.1, step: 1e-3 }
1495
1865
  },
1496
1866
  ssao: {
@@ -1529,7 +1899,7 @@ var composerOptions = {
1529
1899
  amount: { min: 0, max: 0.2, step: 2e-3 }
1530
1900
  },
1531
1901
  bloom: {
1532
- amount: { min: 0, max: 4, step: 0.1 }
1902
+ amount: { min: 0, max: 2, step: 0.05 }
1533
1903
  }
1534
1904
  };
1535
1905
  var shadowMapTypes = {
@@ -1589,17 +1959,81 @@ var statsData = {
1589
1959
  FPS: "0"
1590
1960
  };
1591
1961
 
1962
+ // src/tweakpane/envSettings.ts
1963
+ var envValues = {
1964
+ ambientLight: {
1965
+ ambientLightIntensity: 0,
1966
+ ambientLightColor: { r: 1, g: 1, b: 1 }
1967
+ },
1968
+ fog: {
1969
+ fogNear: 30,
1970
+ fogFar: 210,
1971
+ fogColor: { r: 0.42, g: 0.48, b: 0.59 }
1972
+ }
1973
+ };
1974
+ var envOptions = {
1975
+ ambientLight: {
1976
+ ambientLightIntensity: { min: 0, max: 1, step: 0.01 }
1977
+ },
1978
+ fog: {
1979
+ fogNear: { min: 0, max: 80, step: 1 },
1980
+ fogFar: { min: 81, max: 300, step: 1 }
1981
+ }
1982
+ };
1983
+
1592
1984
  // src/tweakpane/TweakPane.ts
1593
1985
  import {
1594
1986
  BlendFunction as BlendFunction2
1595
1987
  } from "postprocessing";
1596
- import { Color as Color3 } from "three";
1988
+ import { Color as Color5 } from "three";
1597
1989
  import { Pane } from "tweakpane";
1598
1990
  var TweakPane = class {
1599
1991
  constructor(renderer, scene, composer) {
1600
1992
  __publicField(this, "renderer");
1601
1993
  __publicField(this, "scene");
1602
1994
  __publicField(this, "composer");
1995
+ __publicField(this, "guiStyle", `
1996
+ :root {
1997
+ --tp-base-background-color: hsla(0, 0%, 10%, 0.8);
1998
+ --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
1999
+ --tp-button-background-color: hsla(0, 0%, 80%, 1);
2000
+ --tp-button-background-color-active: hsla(0, 0%, 100%, 1);
2001
+ --tp-button-background-color-focus: hsla(0, 0%, 95%, 1);
2002
+ --tp-button-background-color-hover: hsla(0, 0%, 85%, 1);
2003
+ --tp-button-foreground-color: hsla(0, 0%, 0%, 0.8);
2004
+ --tp-container-background-color: hsla(0, 0%, 0%, 0.3);
2005
+ --tp-container-background-color-active: hsla(0, 0%, 0%, 0.6);
2006
+ --tp-container-background-color-focus: hsla(0, 0%, 0%, 0.5);
2007
+ --tp-container-background-color-hover: hsla(0, 0%, 0%, 0.4);
2008
+ --tp-container-foreground-color: hsla(0, 0%, 100%, 0.5);
2009
+ --tp-groove-foreground-color: hsla(0, 0%, 0%, 0.2);
2010
+ --tp-input-background-color: hsla(0, 0%, 0%, 0.3);
2011
+ --tp-input-background-color-active: hsla(0, 0%, 0%, 0.6);
2012
+ --tp-input-background-color-focus: hsla(0, 0%, 0%, 0.5);
2013
+ --tp-input-background-color-hover: hsla(0, 0%, 0%, 0.4);
2014
+ --tp-input-foreground-color: hsla(0, 0%, 100%, 0.5);
2015
+ --tp-label-foreground-color: hsla(0, 0%, 100%, 0.5);
2016
+ --tp-monitor-background-color: hsla(0, 0%, 0%, 0.3);
2017
+ --tp-monitor-foreground-color: hsla(0, 0%, 100%, 0.3);
2018
+ }
2019
+
2020
+ .tp-brkv {
2021
+ -webkit-user-select: none;
2022
+ -ms-user-select: none;
2023
+ user-select: none;
2024
+ }
2025
+
2026
+ .tp-dfwv {
2027
+ width: 333px !important;
2028
+ display: none;
2029
+ }
2030
+
2031
+ .tp-lblv_l {
2032
+ font-size: 10px;
2033
+ padding-left: 0px !important;
2034
+ padding-right: 0px !important;
2035
+ }
2036
+ `);
1603
2037
  __publicField(this, "gui", new Pane());
1604
2038
  __publicField(this, "render");
1605
2039
  __publicField(this, "stats");
@@ -1609,6 +2043,10 @@ var TweakPane = class {
1609
2043
  __publicField(this, "post");
1610
2044
  __publicField(this, "export");
1611
2045
  __publicField(this, "characterMaterial");
2046
+ __publicField(this, "environment");
2047
+ __publicField(this, "sun");
2048
+ __publicField(this, "sunButton");
2049
+ __publicField(this, "ambient");
1612
2050
  __publicField(this, "saveVisibilityInLocalStorage", true);
1613
2051
  __publicField(this, "guiVisible", false);
1614
2052
  if (this.saveVisibilityInLocalStorage) {
@@ -1624,6 +2062,10 @@ var TweakPane = class {
1624
2062
  this.renderer = renderer;
1625
2063
  this.scene = scene;
1626
2064
  this.composer = composer;
2065
+ const styleElement = document.createElement("style");
2066
+ styleElement.type = "text/css";
2067
+ styleElement.appendChild(document.createTextNode(this.guiStyle));
2068
+ document.head.appendChild(styleElement);
1627
2069
  this.render = this.gui.addFolder({ title: "rendering", expanded: true });
1628
2070
  this.stats = this.render.addFolder({ title: "stats", expanded: true });
1629
2071
  this.renderOptions = this.render.addFolder({ title: "renderOptions", expanded: false });
@@ -1631,96 +2073,105 @@ var TweakPane = class {
1631
2073
  this.ssao = this.render.addFolder({ title: "ambientOcclusion", expanded: false });
1632
2074
  this.post = this.render.addFolder({ title: "post", expanded: false });
1633
2075
  this.toneMapping.hidden = composerValues.renderer.toneMapping === 5 ? false : true;
1634
- this.characterMaterial = this.gui.addFolder({ title: "characterMaterial", expanded: false });
1635
- this.characterMaterial.addInput(
1636
- characterValues.material,
1637
- "transmission",
1638
- characterOptions.material.transmission
1639
- );
1640
- this.characterMaterial.addInput(
1641
- characterValues.material,
1642
- "metalness",
1643
- characterOptions.material.metalness
1644
- );
1645
- this.characterMaterial.addInput(
1646
- characterValues.material,
1647
- "roughness",
1648
- characterOptions.material.roughness
1649
- );
1650
- this.characterMaterial.addInput(characterValues.material, "ior", characterOptions.material.ior);
1651
- this.characterMaterial.addInput(
1652
- characterValues.material,
1653
- "thickness",
1654
- characterOptions.material.thickness
1655
- );
1656
- this.characterMaterial.addInput(characterValues.material, "specularColor", {
1657
- color: { type: "float" }
1658
- });
1659
- this.characterMaterial.addInput(
1660
- characterValues.material,
1661
- "specularIntensity",
1662
- characterOptions.material.specularIntensity
1663
- );
1664
- this.characterMaterial.addInput(characterValues.material, "emissive", {
1665
- color: { type: "float" }
1666
- });
1667
- this.characterMaterial.addInput(
1668
- characterValues.material,
1669
- "emissiveIntensity",
1670
- characterOptions.material.emissiveIntensity
1671
- );
1672
- this.characterMaterial.addInput(
1673
- characterValues.material,
1674
- "envMapIntensity",
1675
- characterOptions.material.envMapIntensity
1676
- );
1677
- this.characterMaterial.addInput(characterValues.material, "sheenColor", {
1678
- color: { type: "float" }
1679
- });
1680
- this.characterMaterial.addInput(
1681
- characterValues.material,
1682
- "sheen",
1683
- characterOptions.material.sheen
1684
- );
1685
- this.characterMaterial.addInput(
1686
- characterValues.material,
1687
- "clearcoat",
1688
- characterOptions.material.clearcoat
1689
- );
1690
- this.characterMaterial.addInput(
1691
- characterValues.material,
1692
- "clearcoatRoughness",
1693
- characterOptions.material.clearcoatRoughness
1694
- );
1695
- this.characterMaterial.on("change", (e) => {
1696
- if (!e.presetKey) {
1697
- return;
1698
- }
1699
- if (e.presetKey === "specularColor") {
1700
- characterValues.material.specularColor = {
1701
- r: e.value.r,
1702
- g: e.value.g,
1703
- b: e.value.b
1704
- };
1705
- return;
1706
- }
1707
- if (e.presetKey === "emissive") {
1708
- characterValues.material.emissive = {
1709
- r: e.value.r,
1710
- g: e.value.g,
1711
- b: e.value.b
1712
- };
1713
- return;
1714
- }
1715
- if (e.presetKey === "sheenColor") {
1716
- characterValues.material.sheenColor = {
1717
- r: e.value.r,
1718
- g: e.value.g,
1719
- b: e.value.b
1720
- };
1721
- return;
1722
- }
1723
- });
2076
+ {
2077
+ this.characterMaterial = this.gui.addFolder({ title: "characterMaterial", expanded: false });
2078
+ this.characterMaterial.addInput(
2079
+ characterValues.material,
2080
+ "transmission",
2081
+ characterOptions.material.transmission
2082
+ );
2083
+ this.characterMaterial.addInput(
2084
+ characterValues.material,
2085
+ "metalness",
2086
+ characterOptions.material.metalness
2087
+ );
2088
+ this.characterMaterial.addInput(
2089
+ characterValues.material,
2090
+ "roughness",
2091
+ characterOptions.material.roughness
2092
+ );
2093
+ this.characterMaterial.addInput(
2094
+ characterValues.material,
2095
+ "ior",
2096
+ characterOptions.material.ior
2097
+ );
2098
+ this.characterMaterial.addInput(
2099
+ characterValues.material,
2100
+ "thickness",
2101
+ characterOptions.material.thickness
2102
+ );
2103
+ this.characterMaterial.addInput(characterValues.material, "specularColor", {
2104
+ color: { type: "float" }
2105
+ });
2106
+ this.characterMaterial.addInput(
2107
+ characterValues.material,
2108
+ "specularIntensity",
2109
+ characterOptions.material.specularIntensity
2110
+ );
2111
+ this.characterMaterial.addInput(characterValues.material, "emissive", {
2112
+ color: { type: "float" }
2113
+ });
2114
+ this.characterMaterial.addInput(
2115
+ characterValues.material,
2116
+ "emissiveIntensity",
2117
+ characterOptions.material.emissiveIntensity
2118
+ );
2119
+ this.characterMaterial.addInput(
2120
+ characterValues.material,
2121
+ "envMapIntensity",
2122
+ characterOptions.material.envMapIntensity
2123
+ );
2124
+ this.characterMaterial.addInput(characterValues.material, "sheenColor", {
2125
+ color: { type: "float" }
2126
+ });
2127
+ this.characterMaterial.addInput(
2128
+ characterValues.material,
2129
+ "sheen",
2130
+ characterOptions.material.sheen
2131
+ );
2132
+ this.characterMaterial.addInput(
2133
+ characterValues.material,
2134
+ "clearcoat",
2135
+ characterOptions.material.clearcoat
2136
+ );
2137
+ this.characterMaterial.addInput(
2138
+ characterValues.material,
2139
+ "clearcoatRoughness",
2140
+ characterOptions.material.clearcoatRoughness
2141
+ );
2142
+ this.characterMaterial.on("change", (e) => {
2143
+ if (!e.presetKey) {
2144
+ return;
2145
+ }
2146
+ if (e.presetKey === "specularColor") {
2147
+ characterValues.material.specularColor = {
2148
+ r: e.value.r,
2149
+ g: e.value.g,
2150
+ b: e.value.b
2151
+ };
2152
+ return;
2153
+ }
2154
+ if (e.presetKey === "emissive") {
2155
+ characterValues.material.emissive = {
2156
+ r: e.value.r,
2157
+ g: e.value.g,
2158
+ b: e.value.b
2159
+ };
2160
+ return;
2161
+ }
2162
+ if (e.presetKey === "sheenColor") {
2163
+ characterValues.material.sheenColor = {
2164
+ r: e.value.r,
2165
+ g: e.value.g,
2166
+ b: e.value.b
2167
+ };
2168
+ return;
2169
+ }
2170
+ });
2171
+ }
2172
+ this.environment = this.gui.addFolder({ title: "environment", expanded: false });
2173
+ this.sun = this.environment.addFolder({ title: "sun", expanded: true });
2174
+ this.ambient = this.environment.addFolder({ title: "ambient", expanded: true });
1724
2175
  this.export = this.gui.addFolder({ title: "import/export", expanded: false });
1725
2176
  window.addEventListener("keydown", this.processKey.bind(this));
1726
2177
  this.setupGUIListeners.bind(this)();
@@ -1738,205 +2189,308 @@ var TweakPane = class {
1738
2189
  this.gui.element.addEventListener("mouseup", () => setTweakpaneActive(false));
1739
2190
  this.gui.element.addEventListener("mouseleave", () => setTweakpaneActive(false));
1740
2191
  }
1741
- setupRenderPane(ssaoEffect, toneMappingEffect, toneMappingPass, brightnessContrastSaturation, bloomEffect, gaussGrainEffect) {
1742
- this.stats.addMonitor(statsData, "triangles");
1743
- this.stats.addMonitor(statsData, "geometries");
1744
- this.stats.addMonitor(statsData, "textures");
1745
- this.stats.addMonitor(statsData, "shaders");
1746
- this.stats.addMonitor(statsData, "postPasses");
1747
- this.stats.addMonitor(statsData, "drawCalls");
1748
- this.stats.addMonitor(statsData, "rawDeltaTime");
1749
- this.stats.addMonitor(statsData, "deltaTime");
1750
- this.stats.addMonitor(statsData, "FPS");
1751
- this.renderOptions.addInput(
1752
- composerValues.renderer,
1753
- "shadowMap",
1754
- composerOptions.renderer.shadowMap
1755
- );
1756
- this.renderOptions.addMonitor(rendererBlades, "shadowMapType");
1757
- this.renderOptions.addInput(
1758
- composerValues.renderer,
1759
- "toneMapping",
1760
- composerOptions.renderer.toneMapping
1761
- );
1762
- this.renderOptions.addMonitor(rendererBlades, "toneMappingType");
1763
- this.renderOptions.addInput(
1764
- composerValues.renderer,
1765
- "exposure",
1766
- composerOptions.renderer.exposure
1767
- );
1768
- this.renderOptions.addInput(
1769
- composerValues.renderer,
1770
- "bgIntensity",
1771
- composerOptions.renderer.bgIntensity
1772
- );
1773
- this.renderOptions.addInput(
1774
- composerValues.renderer,
1775
- "bgBlurriness",
1776
- composerOptions.renderer.bgBlurriness
1777
- );
1778
- this.renderOptions.on("change", (e) => {
1779
- const target = e.target;
1780
- switch (target.label) {
1781
- case "shadowMap":
1782
- this.renderer.shadowMap.type = e.value;
1783
- setShadowMapType(e.value);
1784
- break;
1785
- case "toneMapping":
1786
- this.renderer.toneMapping = e.value;
1787
- if (e.value !== 5 && e.value !== 0) {
1788
- this.toneMapping.hidden = true;
1789
- } else {
1790
- this.toneMapping.hidden = false;
1791
- }
1792
- toneMappingPass.enabled = e.value === 5 || e.value === 0 ? true : false;
1793
- setToneMappingType(e.value);
1794
- break;
1795
- case "exposure":
1796
- this.renderer.toneMappingExposure = e.value;
1797
- break;
1798
- case "bgIntensity":
1799
- this.scene.backgroundIntensity = e.value;
1800
- break;
1801
- case "bgBlurriness":
1802
- this.scene.backgroundBlurriness = e.value;
1803
- break;
1804
- default:
1805
- break;
1806
- }
1807
- });
1808
- this.ssao.addInput({ showEffectOnly: false }, "showEffectOnly");
1809
- this.ssao.addInput(composerValues.ssao, "samples", composerOptions.ssao.samples);
1810
- this.ssao.addInput(composerValues.ssao, "rings", composerOptions.ssao.rings);
1811
- this.ssao.addInput(
1812
- composerValues.ssao,
1813
- "luminanceInfluence",
1814
- composerOptions.ssao.luminanceInfluence
1815
- );
1816
- this.ssao.addInput(composerValues.ssao, "radius", composerOptions.ssao.radius);
1817
- this.ssao.addInput(composerValues.ssao, "intensity", composerOptions.ssao.intensity);
1818
- this.ssao.addInput(composerValues.ssao, "bias", composerOptions.ssao.bias);
1819
- this.ssao.addInput(composerValues.ssao, "fade", composerOptions.ssao.fade);
1820
- this.ssao.addInput(
1821
- composerValues.ssao,
1822
- "resolutionScale",
1823
- composerOptions.ssao.resolutionScale
1824
- );
1825
- this.ssao.addInput(
1826
- composerValues.ssao,
1827
- "worldDistanceThreshold",
1828
- composerOptions.ssao.worldDistanceThreshold
1829
- );
1830
- this.ssao.addInput(
1831
- composerValues.ssao,
1832
- "worldDistanceFalloff",
1833
- composerOptions.ssao.worldDistanceFalloff
1834
- );
1835
- this.ssao.addInput(
1836
- composerValues.ssao,
1837
- "worldProximityThreshold",
1838
- composerOptions.ssao.worldProximityThreshold
1839
- );
1840
- this.ssao.addInput(
1841
- composerValues.ssao,
1842
- "worldProximityFalloff",
1843
- composerOptions.ssao.worldProximityFalloff
1844
- );
1845
- this.ssao.addInput(composerValues.ssao, "color", {
1846
- color: { alpha: false, type: "float" }
1847
- });
1848
- this.ssao.on("change", (e) => {
1849
- if (!e.presetKey) {
1850
- return;
1851
- }
1852
- const preset = e.presetKey;
1853
- if (preset === "showEffectOnly") {
1854
- ssaoEffect.blendMode.blendFunction = e.value === true ? BlendFunction2.NORMAL : BlendFunction2.MULTIPLY;
1855
- return;
1856
- }
1857
- if (preset === "resolutionScale") {
1858
- ssaoEffect.resolution.scale = e.value;
1859
- return;
1860
- }
1861
- if (ssaoMaterialParams.includes(e.presetKey)) {
1862
- ssaoEffect.ssaoMaterial[preset] = e.value;
1863
- return;
1864
- }
1865
- if (e.presetKey === "color") {
1866
- ssaoEffect.color = new Color3().setRGB(e.value.r, e.value.g, e.value.b);
1867
- return;
1868
- }
1869
- ssaoEffect[preset] = e.value;
1870
- });
1871
- this.toneMapping.addInput(composerValues.toneMapping, "mode", composerOptions.toneMapping.mode);
1872
- this.toneMapping.addMonitor(customToneMappingBlade, "customToneMappingType");
1873
- this.toneMapping.addInput(
1874
- composerValues.toneMapping,
1875
- "whitePoint",
1876
- composerOptions.toneMapping.whitePoint
1877
- );
1878
- this.toneMapping.addInput(
1879
- composerValues.toneMapping,
1880
- "middleGrey",
1881
- composerOptions.toneMapping.middleGrey
1882
- );
1883
- const minLuminance = this.toneMapping.addInput(
1884
- composerValues.toneMapping,
1885
- "minLuminance",
1886
- composerOptions.toneMapping.minLuminance
1887
- );
1888
- minLuminance.hidden = composerValues.toneMapping.mode === 2 ? true : false;
1889
- const averageLuminance = this.toneMapping.addInput(
1890
- composerValues.toneMapping,
1891
- "averageLuminance",
1892
- composerOptions.toneMapping.averageLuminance
1893
- );
1894
- averageLuminance.hidden = composerValues.toneMapping.mode === 2 ? true : false;
1895
- this.toneMapping.addInput(
1896
- composerValues.toneMapping,
1897
- "adaptationRate",
1898
- composerOptions.toneMapping.adaptationRate
1899
- );
1900
- this.toneMapping.on("change", (e) => {
1901
- if (!e.presetKey) {
2192
+ setupRenderPane(ssaoEffect, toneMappingEffect, toneMappingPass, brightnessContrastSaturation, bloomEffect, gaussGrainEffect, hasLighting, sun, setHDR, setAmbientLight, setFog) {
2193
+ {
2194
+ this.stats.addMonitor(statsData, "triangles");
2195
+ this.stats.addMonitor(statsData, "geometries");
2196
+ this.stats.addMonitor(statsData, "textures");
2197
+ this.stats.addMonitor(statsData, "shaders");
2198
+ this.stats.addMonitor(statsData, "postPasses");
2199
+ this.stats.addMonitor(statsData, "drawCalls");
2200
+ this.stats.addMonitor(statsData, "rawDeltaTime");
2201
+ this.stats.addMonitor(statsData, "deltaTime");
2202
+ this.stats.addMonitor(statsData, "FPS");
2203
+ }
2204
+ {
2205
+ this.renderOptions.addInput(
2206
+ composerValues.renderer,
2207
+ "shadowMap",
2208
+ composerOptions.renderer.shadowMap
2209
+ );
2210
+ this.renderOptions.addMonitor(rendererBlades, "shadowMapType");
2211
+ this.renderOptions.addInput(
2212
+ composerValues.renderer,
2213
+ "toneMapping",
2214
+ composerOptions.renderer.toneMapping
2215
+ );
2216
+ this.renderOptions.addMonitor(rendererBlades, "toneMappingType");
2217
+ this.renderOptions.addInput(
2218
+ composerValues.renderer,
2219
+ "exposure",
2220
+ composerOptions.renderer.exposure
2221
+ );
2222
+ this.renderOptions.addInput(
2223
+ composerValues.renderer,
2224
+ "bgIntensity",
2225
+ composerOptions.renderer.bgIntensity
2226
+ );
2227
+ this.renderOptions.addInput(
2228
+ composerValues.renderer,
2229
+ "bgBlurriness",
2230
+ composerOptions.renderer.bgBlurriness
2231
+ );
2232
+ this.renderOptions.on("change", (e) => {
2233
+ const target = e.target;
2234
+ switch (target.label) {
2235
+ case "shadowMap":
2236
+ this.renderer.shadowMap.type = e.value;
2237
+ setShadowMapType(e.value);
2238
+ break;
2239
+ case "toneMapping":
2240
+ this.renderer.toneMapping = e.value;
2241
+ this.toneMapping.hidden = e.value !== 5;
2242
+ toneMappingPass.enabled = e.value === 5 ? true : false;
2243
+ setToneMappingType(e.value);
2244
+ break;
2245
+ case "exposure":
2246
+ this.renderer.toneMappingExposure = e.value;
2247
+ break;
2248
+ case "bgIntensity":
2249
+ this.scene.backgroundIntensity = e.value;
2250
+ break;
2251
+ case "bgBlurriness":
2252
+ this.scene.backgroundBlurriness = e.value;
2253
+ break;
2254
+ default:
2255
+ break;
2256
+ }
2257
+ });
2258
+ }
2259
+ {
2260
+ this.ssao.addInput({ showEffectOnly: false }, "showEffectOnly");
2261
+ this.ssao.addInput(composerValues.ssao, "samples", composerOptions.ssao.samples);
2262
+ this.ssao.addInput(composerValues.ssao, "rings", composerOptions.ssao.rings);
2263
+ this.ssao.addInput(
2264
+ composerValues.ssao,
2265
+ "luminanceInfluence",
2266
+ composerOptions.ssao.luminanceInfluence
2267
+ );
2268
+ this.ssao.addInput(composerValues.ssao, "radius", composerOptions.ssao.radius);
2269
+ this.ssao.addInput(composerValues.ssao, "intensity", composerOptions.ssao.intensity);
2270
+ this.ssao.addInput(composerValues.ssao, "bias", composerOptions.ssao.bias);
2271
+ this.ssao.addInput(composerValues.ssao, "fade", composerOptions.ssao.fade);
2272
+ this.ssao.addInput(
2273
+ composerValues.ssao,
2274
+ "resolutionScale",
2275
+ composerOptions.ssao.resolutionScale
2276
+ );
2277
+ this.ssao.addInput(
2278
+ composerValues.ssao,
2279
+ "worldDistanceThreshold",
2280
+ composerOptions.ssao.worldDistanceThreshold
2281
+ );
2282
+ this.ssao.addInput(
2283
+ composerValues.ssao,
2284
+ "worldDistanceFalloff",
2285
+ composerOptions.ssao.worldDistanceFalloff
2286
+ );
2287
+ this.ssao.addInput(
2288
+ composerValues.ssao,
2289
+ "worldProximityThreshold",
2290
+ composerOptions.ssao.worldProximityThreshold
2291
+ );
2292
+ this.ssao.addInput(
2293
+ composerValues.ssao,
2294
+ "worldProximityFalloff",
2295
+ composerOptions.ssao.worldProximityFalloff
2296
+ );
2297
+ this.ssao.addInput(composerValues.ssao, "color", {
2298
+ color: { alpha: false, type: "float" }
2299
+ });
2300
+ this.ssao.on("change", (e) => {
2301
+ if (!e.presetKey) {
2302
+ return;
2303
+ }
2304
+ const preset = e.presetKey;
2305
+ if (preset === "showEffectOnly") {
2306
+ ssaoEffect.blendMode.blendFunction = e.value === true ? BlendFunction2.NORMAL : BlendFunction2.MULTIPLY;
2307
+ return;
2308
+ }
2309
+ if (preset === "resolutionScale") {
2310
+ ssaoEffect.resolution.scale = e.value;
2311
+ return;
2312
+ }
2313
+ if (ssaoMaterialParams.includes(e.presetKey)) {
2314
+ ssaoEffect.ssaoMaterial[preset] = e.value;
2315
+ return;
2316
+ }
2317
+ if (e.presetKey === "color") {
2318
+ ssaoEffect.color = new Color5().setRGB(e.value.r, e.value.g, e.value.b);
2319
+ return;
2320
+ }
2321
+ ssaoEffect[preset] = e.value;
2322
+ });
2323
+ }
2324
+ {
2325
+ this.toneMapping.addInput(
2326
+ composerValues.toneMapping,
2327
+ "mode",
2328
+ composerOptions.toneMapping.mode
2329
+ );
2330
+ this.toneMapping.addMonitor(customToneMappingBlade, "customToneMappingType");
2331
+ this.toneMapping.addInput(
2332
+ composerValues.toneMapping,
2333
+ "whitePoint",
2334
+ composerOptions.toneMapping.whitePoint
2335
+ );
2336
+ this.toneMapping.addInput(
2337
+ composerValues.toneMapping,
2338
+ "middleGrey",
2339
+ composerOptions.toneMapping.middleGrey
2340
+ );
2341
+ const minLuminance = this.toneMapping.addInput(
2342
+ composerValues.toneMapping,
2343
+ "minLuminance",
2344
+ composerOptions.toneMapping.minLuminance
2345
+ );
2346
+ minLuminance.hidden = composerValues.toneMapping.mode === 2 ? true : false;
2347
+ const averageLuminance = this.toneMapping.addInput(
2348
+ composerValues.toneMapping,
2349
+ "averageLuminance",
2350
+ composerOptions.toneMapping.averageLuminance
2351
+ );
2352
+ averageLuminance.hidden = composerValues.toneMapping.mode === 2 ? true : false;
2353
+ this.toneMapping.addInput(
2354
+ composerValues.toneMapping,
2355
+ "adaptationRate",
2356
+ composerOptions.toneMapping.adaptationRate
2357
+ );
2358
+ this.toneMapping.on("change", (e) => {
2359
+ if (!e.presetKey) {
2360
+ return;
2361
+ }
2362
+ const preset = e.presetKey;
2363
+ if (preset === "mode") {
2364
+ minLuminance.hidden = composerValues.toneMapping.mode === 2 ? true : false;
2365
+ averageLuminance.hidden = composerValues.toneMapping.mode === 2 ? true : false;
2366
+ setCustomToneMappingType(e.value);
2367
+ }
2368
+ toneMappingEffect[preset] = e.value;
1902
2369
  return;
1903
- }
1904
- const preset = e.presetKey;
1905
- if (preset === "mode") {
1906
- minLuminance.hidden = composerValues.toneMapping.mode === 2 ? true : false;
1907
- averageLuminance.hidden = composerValues.toneMapping.mode === 2 ? true : false;
1908
- setCustomToneMappingType(e.value);
1909
- }
1910
- toneMappingEffect[preset] = e.value;
1911
- return;
1912
- });
1913
- this.post.addInput(composerValues, "brightness", composerOptions.brightness.amount);
1914
- this.post.addInput(composerValues, "contrast", composerOptions.contrast.amount);
1915
- this.post.addInput(composerValues, "saturation", composerOptions.saturation.amount);
1916
- this.post.addInput(composerValues, "bloom", composerOptions.bloom.amount);
1917
- this.post.addInput(composerValues, "grain", composerOptions.grain.amount);
1918
- this.post.on("change", (e) => {
1919
- const target = e.presetKey;
1920
- switch (target) {
1921
- case "brightness":
1922
- brightnessContrastSaturation.uniforms.brightness.value = e.value;
1923
- break;
1924
- case "contrast":
1925
- brightnessContrastSaturation.uniforms.contrast.value = e.value;
1926
- break;
1927
- case "saturation":
1928
- brightnessContrastSaturation.uniforms.saturation.value = e.value;
1929
- break;
1930
- case "bloom":
1931
- bloomEffect.intensity = e.value;
1932
- break;
1933
- case "grain":
1934
- gaussGrainEffect.uniforms.amount.value = e.value;
1935
- break;
1936
- default:
1937
- break;
1938
- }
1939
- });
2370
+ });
2371
+ }
2372
+ {
2373
+ this.post.addInput(composerValues, "brightness", composerOptions.brightness.amount);
2374
+ this.post.addInput(composerValues, "contrast", composerOptions.contrast.amount);
2375
+ this.post.addInput(composerValues, "saturation", composerOptions.saturation.amount);
2376
+ this.post.addInput(composerValues, "bloom", composerOptions.bloom.amount);
2377
+ this.post.addInput(composerValues, "grain", composerOptions.grain.amount);
2378
+ this.post.on("change", (e) => {
2379
+ const target = e.presetKey;
2380
+ switch (target) {
2381
+ case "brightness":
2382
+ brightnessContrastSaturation.uniforms.brightness.value = e.value;
2383
+ break;
2384
+ case "contrast":
2385
+ brightnessContrastSaturation.uniforms.contrast.value = e.value;
2386
+ break;
2387
+ case "saturation":
2388
+ brightnessContrastSaturation.uniforms.saturation.value = e.value;
2389
+ break;
2390
+ case "bloom":
2391
+ bloomEffect.intensity = e.value;
2392
+ break;
2393
+ case "grain":
2394
+ gaussGrainEffect.uniforms.amount.value = e.value;
2395
+ break;
2396
+ default:
2397
+ break;
2398
+ }
2399
+ });
2400
+ }
2401
+ {
2402
+ this.environment.hidden = hasLighting === false || sun === null;
2403
+ this.sun.addInput(
2404
+ sunValues.sunPosition,
2405
+ "sunAzimuthalAngle",
2406
+ sunOptions.sunPosition.sunAzimuthalAngle
2407
+ );
2408
+ this.sun.addInput(
2409
+ sunValues.sunPosition,
2410
+ "sunPolarAngle",
2411
+ sunOptions.sunPosition.sunPolarAngle
2412
+ );
2413
+ this.sun.addInput(sunValues, "sunIntensity", sunOptions.sunIntensity);
2414
+ this.sun.addInput(sunValues, "sunColor", {
2415
+ color: { type: "float" }
2416
+ });
2417
+ this.sunButton = this.sun.addButton({ title: "Set HDRI" });
2418
+ this.sunButton.on("click", () => {
2419
+ setHDR();
2420
+ });
2421
+ this.sun.on("change", (e) => {
2422
+ const target = e.presetKey;
2423
+ switch (target) {
2424
+ case "sunAzimuthalAngle":
2425
+ sun?.setAzimuthalAngle(e.value * (Math.PI / 180));
2426
+ break;
2427
+ case "sunPolarAngle":
2428
+ sun?.setPolarAngle(e.value * (Math.PI / 180));
2429
+ break;
2430
+ case "sunIntensity":
2431
+ sun?.setIntensity(e.value);
2432
+ break;
2433
+ case "sunColor":
2434
+ sunValues.sunColor = {
2435
+ r: e.value.r,
2436
+ g: e.value.g,
2437
+ b: e.value.b
2438
+ };
2439
+ sun?.setColor();
2440
+ break;
2441
+ default:
2442
+ break;
2443
+ }
2444
+ });
2445
+ this.ambient.addInput(
2446
+ envValues.ambientLight,
2447
+ "ambientLightIntensity",
2448
+ envOptions.ambientLight.ambientLightIntensity
2449
+ );
2450
+ this.ambient.addInput(envValues.ambientLight, "ambientLightColor", {
2451
+ color: { type: "float" }
2452
+ });
2453
+ this.ambient.addInput(envValues.fog, "fogNear", envOptions.fog.fogNear);
2454
+ this.ambient.addInput(envValues.fog, "fogFar", envOptions.fog.fogFar);
2455
+ this.ambient.addInput(envValues.fog, "fogColor", {
2456
+ color: { type: "float" }
2457
+ });
2458
+ this.ambient.on("change", (e) => {
2459
+ const target = e.presetKey;
2460
+ switch (target) {
2461
+ case "ambientLightIntensity":
2462
+ envValues.ambientLight.ambientLightIntensity = e.value;
2463
+ setAmbientLight();
2464
+ break;
2465
+ case "ambientLightColor":
2466
+ envValues.ambientLight.ambientLightColor = {
2467
+ r: e.value.r,
2468
+ g: e.value.g,
2469
+ b: e.value.b
2470
+ };
2471
+ setAmbientLight();
2472
+ break;
2473
+ case "fogNear":
2474
+ envValues.fog.fogNear = e.value;
2475
+ setFog();
2476
+ break;
2477
+ case "fogFar":
2478
+ envValues.fog.fogFar = e.value;
2479
+ setFog();
2480
+ break;
2481
+ case "fogColor":
2482
+ envValues.fog.fogColor = {
2483
+ r: e.value.r,
2484
+ g: e.value.g,
2485
+ b: e.value.b
2486
+ };
2487
+ setFog();
2488
+ break;
2489
+ default:
2490
+ break;
2491
+ }
2492
+ });
2493
+ }
1940
2494
  const exportButton = this.export.addButton({ title: "export" });
1941
2495
  exportButton.on("click", () => {
1942
2496
  this.downloadSettingsAsJSON(this.gui.exportPreset());
@@ -2159,7 +2713,7 @@ var GaussGrainEffect = new ShaderMaterial2({
2159
2713
 
2160
2714
  // src/rendering/composer.ts
2161
2715
  var Composer = class {
2162
- constructor(scene, camera) {
2716
+ constructor(scene, camera, spawnSun = false) {
2163
2717
  __publicField(this, "width", window.innerWidth);
2164
2718
  __publicField(this, "height", window.innerHeight);
2165
2719
  __publicField(this, "resolution", new Vector22(this.width, this.height));
@@ -2185,9 +2739,13 @@ var Composer = class {
2185
2739
  __publicField(this, "bcsPass");
2186
2740
  __publicField(this, "gaussGrainEffect", GaussGrainEffect);
2187
2741
  __publicField(this, "gaussGrainPass");
2742
+ __publicField(this, "ambientLight", null);
2743
+ __publicField(this, "sun", null);
2744
+ __publicField(this, "spawnSun");
2188
2745
  __publicField(this, "tweakPane");
2189
2746
  this.scene = scene;
2190
2747
  this.camera = camera;
2748
+ this.spawnSun = spawnSun;
2191
2749
  this.renderer = new WebGLRenderer3({
2192
2750
  powerPreference: "high-performance",
2193
2751
  antialias: false,
@@ -2200,6 +2758,8 @@ var Composer = class {
2200
2758
  this.renderer.shadowMap.type = composerValues.renderer.shadowMap;
2201
2759
  this.renderer.toneMapping = composerValues.renderer.toneMapping;
2202
2760
  this.renderer.toneMappingExposure = composerValues.renderer.exposure;
2761
+ this.setAmbientLight();
2762
+ this.setFog();
2203
2763
  document.body.appendChild(this.renderer.domElement);
2204
2764
  this.composer = new EffectComposer2(this.renderer, {
2205
2765
  frameBufferType: HalfFloatType
@@ -2227,7 +2787,7 @@ var Composer = class {
2227
2787
  bias: composerValues.ssao.bias,
2228
2788
  fade: composerValues.ssao.fade,
2229
2789
  resolutionScale: composerValues.ssao.resolutionScale,
2230
- color: new Color4().setRGB(composerValues.ssao.color.r, composerValues.ssao.color.g, composerValues.ssao.color.b),
2790
+ color: new Color6().setRGB(composerValues.ssao.color.r, composerValues.ssao.color.g, composerValues.ssao.color.b),
2231
2791
  worldDistanceThreshold: composerValues.ssao.worldDistanceThreshold,
2232
2792
  worldDistanceFalloff: composerValues.ssao.worldDistanceFalloff,
2233
2793
  worldProximityThreshold: composerValues.ssao.worldProximityThreshold,
@@ -2267,13 +2827,22 @@ var Composer = class {
2267
2827
  this.composer.addPass(this.toneMappingPass);
2268
2828
  this.composer.addPass(this.bcsPass);
2269
2829
  this.composer.addPass(this.gaussGrainPass);
2830
+ if (this.spawnSun === true) {
2831
+ this.sun = new Sun();
2832
+ this.scene.add(this.sun);
2833
+ }
2270
2834
  this.tweakPane.setupRenderPane(
2271
2835
  this.ssaoEffect,
2272
2836
  this.toneMappingEffect,
2273
2837
  this.toneMappingPass,
2274
2838
  this.bcs,
2275
2839
  this.bloomEffect,
2276
- this.gaussGrainEffect
2840
+ this.gaussGrainEffect,
2841
+ this.spawnSun,
2842
+ this.sun,
2843
+ this.setHDRIFromFile.bind(this),
2844
+ this.setAmbientLight.bind(this),
2845
+ this.setFog.bind(this)
2277
2846
  );
2278
2847
  window.addEventListener("resize", () => this.updateProjection());
2279
2848
  this.updateProjection();
@@ -2307,8 +2876,8 @@ var Composer = class {
2307
2876
  this.tweakPane.updateStats(timeManager);
2308
2877
  }
2309
2878
  }
2310
- useHDRI(url) {
2311
- if (this.isEnvHDRI || !this.renderer)
2879
+ useHDRI(url, fromFile = false) {
2880
+ if (this.isEnvHDRI && fromFile === false || !this.renderer)
2312
2881
  return;
2313
2882
  const pmremGenerator = new PMREMGenerator(this.renderer);
2314
2883
  new RGBELoader(new LoadingManager2()).load(
@@ -2333,6 +2902,52 @@ var Composer = class {
2333
2902
  }
2334
2903
  );
2335
2904
  }
2905
+ setHDRIFromFile() {
2906
+ if (!this.renderer)
2907
+ return;
2908
+ const fileInput = document.createElement("input");
2909
+ fileInput.type = "file";
2910
+ fileInput.accept = ".hdr";
2911
+ fileInput.addEventListener("change", () => {
2912
+ const file = fileInput.files?.[0];
2913
+ if (!file) {
2914
+ console.log("no file");
2915
+ return;
2916
+ }
2917
+ const fileURL = URL.createObjectURL(file);
2918
+ if (fileURL) {
2919
+ this.useHDRI(fileURL, true);
2920
+ URL.revokeObjectURL(fileURL);
2921
+ document.body.removeChild(fileInput);
2922
+ }
2923
+ });
2924
+ document.body.appendChild(fileInput);
2925
+ fileInput.click();
2926
+ }
2927
+ setFog() {
2928
+ const fogColor = new Color6().setRGB(
2929
+ envValues.fog.fogColor.r,
2930
+ envValues.fog.fogColor.g,
2931
+ envValues.fog.fogColor.b
2932
+ );
2933
+ this.scene.fog = new Fog(fogColor, envValues.fog.fogNear, envValues.fog.fogFar);
2934
+ }
2935
+ setAmbientLight() {
2936
+ if (this.ambientLight) {
2937
+ this.scene.remove(this.ambientLight);
2938
+ this.ambientLight.dispose();
2939
+ }
2940
+ const ambientLightColor = new Color6().setRGB(
2941
+ envValues.ambientLight.ambientLightColor.r,
2942
+ envValues.ambientLight.ambientLightColor.g,
2943
+ envValues.ambientLight.ambientLightColor.b
2944
+ );
2945
+ this.ambientLight = new AmbientLight(
2946
+ ambientLightColor,
2947
+ envValues.ambientLight.ambientLightIntensity
2948
+ );
2949
+ this.scene.add(this.ambientLight);
2950
+ }
2336
2951
  };
2337
2952
 
2338
2953
  // src/time/TimeManager.ts
@@ -2387,13 +3002,13 @@ import {
2387
3002
  getRelativePositionAndRotationRelativeToObject
2388
3003
  } from "mml-web";
2389
3004
  import {
2390
- Color as Color5,
3005
+ Color as Color7,
2391
3006
  DoubleSide,
2392
3007
  Euler,
2393
- FrontSide,
2394
- Mesh as Mesh2,
3008
+ FrontSide as FrontSide2,
3009
+ Mesh as Mesh3,
2395
3010
  MeshStandardMaterial as MeshStandardMaterial2,
2396
- Vector3 as Vector37
3011
+ Vector3 as Vector38
2397
3012
  } from "three";
2398
3013
  import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUtils.js";
2399
3014
  import { MeshBVH, MeshBVHVisualizer } from "three-mesh-bvh";
@@ -2401,20 +3016,20 @@ var CollisionsManager = class {
2401
3016
  constructor(scene) {
2402
3017
  __publicField(this, "debug", false);
2403
3018
  __publicField(this, "scene");
2404
- __publicField(this, "tempVector", new Vector37());
2405
- __publicField(this, "tempVector2", new Vector37());
3019
+ __publicField(this, "tempVector", new Vector38());
3020
+ __publicField(this, "tempVector2", new Vector38());
2406
3021
  __publicField(this, "collisionMeshState", /* @__PURE__ */ new Map());
2407
3022
  __publicField(this, "collisionTrigger");
2408
3023
  this.scene = scene;
2409
3024
  this.collisionTrigger = MMLCollisionTrigger.init();
2410
3025
  }
2411
3026
  raycastFirstDistance(ray) {
2412
- let minimumDistance = Infinity;
3027
+ let minimumDistance = null;
2413
3028
  for (const [, value] of this.collisionMeshState) {
2414
- const hit = value.meshBVH.raycast(ray, DoubleSide);
2415
- if (hit.length > 0) {
2416
- if (hit[0].distance < minimumDistance) {
2417
- minimumDistance = hit[0].distance;
3029
+ const hit = value.meshBVH.raycastFirst(ray, DoubleSide);
3030
+ if (hit) {
3031
+ if (minimumDistance === null || hit.distance < minimumDistance) {
3032
+ minimumDistance = hit.distance;
2418
3033
  }
2419
3034
  }
2420
3035
  }
@@ -2425,7 +3040,7 @@ var CollisionsManager = class {
2425
3040
  group.traverse((child) => {
2426
3041
  if (child.type === "Mesh") {
2427
3042
  const mesh = child;
2428
- mesh.localToWorld(new Vector37());
3043
+ mesh.localToWorld(new Vector38());
2429
3044
  mesh.updateMatrixWorld();
2430
3045
  const clonedGeometry = mesh.geometry.clone();
2431
3046
  clonedGeometry.applyMatrix4(mesh.matrixWorld);
@@ -2446,13 +3061,13 @@ var CollisionsManager = class {
2446
3061
  if (!this.debug) {
2447
3062
  return { source: group, visualizer: null, meshBVH };
2448
3063
  }
2449
- const mergedMesh = new Mesh2(
3064
+ const mergedMesh = new Mesh3(
2450
3065
  newBufferGeometry,
2451
- new MeshStandardMaterial2({ color: 16711680, side: FrontSide, wireframe: true })
3066
+ new MeshStandardMaterial2({ color: 16711680, side: FrontSide2, wireframe: true })
2452
3067
  );
2453
3068
  mergedMesh.geometry.boundsTree = meshBVH;
2454
3069
  const visualizer = new MeshBVHVisualizer(mergedMesh, 3);
2455
- visualizer.edgeMaterial.color = new Color5(255);
3070
+ visualizer.edgeMaterial.color = new Color7(255);
2456
3071
  visualizer.update();
2457
3072
  return { source: group, visualizer, meshBVH };
2458
3073
  }
@@ -2499,7 +3114,7 @@ var CollisionsManager = class {
2499
3114
  const distance = tri.closestPointToSegment(tempSegment, triPoint, capsulePoint);
2500
3115
  if (distance < radius) {
2501
3116
  const depth = radius - distance;
2502
- collisionPosition = new Vector37().copy(capsulePoint);
3117
+ collisionPosition = new Vector38().copy(capsulePoint);
2503
3118
  const direction = capsulePoint.sub(triPoint).normalize();
2504
3119
  tempSegment.start.addScaledVector(direction, depth);
2505
3120
  tempSegment.end.addScaledVector(direction, depth);
@@ -2539,6 +3154,7 @@ export {
2539
3154
  Composer,
2540
3155
  KeyInputManager,
2541
3156
  MMLCompositionScene,
3157
+ Sun,
2542
3158
  TimeManager
2543
3159
  };
2544
3160
  //# sourceMappingURL=index.js.map