@opsydyn/effect-three 0.2.0 → 0.3.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/README.md +2 -1
  3. package/dist/{index-01kwfekm.js → index-8cf8t6by.js} +327 -24
  4. package/dist/index-8cf8t6by.js.map +41 -0
  5. package/dist/index.js +61 -8
  6. package/dist/index.js.map +3 -3
  7. package/dist/kernel/behaviours.d.ts.map +1 -1
  8. package/dist/kernel/build.d.ts +56 -1
  9. package/dist/kernel/build.d.ts.map +1 -1
  10. package/dist/kernel/cameraMotion.d.ts +3 -1
  11. package/dist/kernel/cameraMotion.d.ts.map +1 -1
  12. package/dist/kernel/cameraShake.d.ts +33 -0
  13. package/dist/kernel/cameraShake.d.ts.map +1 -0
  14. package/dist/kernel/description.d.ts +85 -1
  15. package/dist/kernel/description.d.ts.map +1 -1
  16. package/dist/kernel/diff.d.ts +3 -1
  17. package/dist/kernel/diff.d.ts.map +1 -1
  18. package/dist/kernel/equality.d.ts +5 -1
  19. package/dist/kernel/equality.d.ts.map +1 -1
  20. package/dist/kernel/index.d.ts +1 -1
  21. package/dist/kernel/index.d.ts.map +1 -1
  22. package/dist/kernel/index.js +12 -2
  23. package/dist/kernel/index.js.map +1 -1
  24. package/dist/kernel/pointer.d.ts.map +1 -1
  25. package/dist/kernel/resources.d.ts.map +1 -1
  26. package/dist/kernel/sceneGraph.d.ts +0 -1
  27. package/dist/kernel/sceneGraph.d.ts.map +1 -1
  28. package/dist/runtime/SceneSchema.d.ts +296 -5
  29. package/dist/runtime/SceneSchema.d.ts.map +1 -1
  30. package/package.json +1 -1
  31. package/src/kernel/behaviours.ts +5 -0
  32. package/src/kernel/bodySources.ts +1 -1
  33. package/src/kernel/build.ts +98 -0
  34. package/src/kernel/cameraMotion.ts +3 -0
  35. package/src/kernel/cameraShake.ts +97 -0
  36. package/src/kernel/description.ts +91 -1
  37. package/src/kernel/diff.ts +7 -1
  38. package/src/kernel/equality.ts +47 -0
  39. package/src/kernel/index.ts +5 -0
  40. package/src/kernel/pointer.ts +8 -0
  41. package/src/kernel/resources.ts +69 -0
  42. package/src/kernel/sceneGraph.ts +142 -1
  43. package/src/runtime/SceneSchema.ts +58 -4
  44. package/dist/index-01kwfekm.js.map +0 -40
@@ -67,6 +67,10 @@ var writeRotation2 = (target, rotation, elapsedSeconds) => {
67
67
  target.set(rotation.euler[0], rotation.euler[1], rotation.euler[2]);
68
68
  return;
69
69
  }
70
+ if (rotation._tag === "Billboard") {
71
+ target.set(0, 0, 0);
72
+ return;
73
+ }
70
74
  const angle = spinAngle2(rotation, elapsedSeconds);
71
75
  switch (rotation.axis) {
72
76
  case "x":
@@ -251,6 +255,13 @@ import {
251
255
 
252
256
  // src/kernel/equality.ts
253
257
  var vec3Equals2 = (a, b) => a === b || Object.is(a[0], b[0]) && Object.is(a[1], b[1]) && Object.is(a[2], b[2]);
258
+ var detailEquals = (a, b) => {
259
+ if (a === b)
260
+ return true;
261
+ if (a === null || b === null)
262
+ return false;
263
+ return Object.is(a.hysteresis, b.hysteresis) && a.distances.length === b.distances.length && a.distances.every((distance, index) => Object.is(distance, b.distances[index]));
264
+ };
254
265
  var rotationEquals2 = (a, b) => {
255
266
  if (a === b)
256
267
  return true;
@@ -259,6 +270,9 @@ var rotationEquals2 = (a, b) => {
259
270
  if (a._tag === "Spin" && b._tag === "Spin") {
260
271
  return a.axis === b.axis && Object.is(a.radiansPerSecond, b.radiansPerSecond) && Object.is(a.phase, b.phase);
261
272
  }
273
+ if (a._tag === "Billboard" && b._tag === "Billboard") {
274
+ return a.lockX === b.lockX && a.lockY === b.lockY && a.lockZ === b.lockZ;
275
+ }
262
276
  return false;
263
277
  };
264
278
  var shapeEquals2 = (a, b) => {
@@ -283,6 +297,10 @@ var shapeEquals2 = (a, b) => {
283
297
  return b._tag === "Ring" && Object.is(a.innerRadius, b.innerRadius) && Object.is(a.outerRadius, b.outerRadius) && a.thetaSegments === b.thetaSegments;
284
298
  case "Circle":
285
299
  return b._tag === "Circle" && Object.is(a.radius, b.radius) && a.segments === b.segments;
300
+ case "RoundedBox":
301
+ return b._tag === "RoundedBox" && Object.is(a.width, b.width) && Object.is(a.height, b.height) && Object.is(a.depth, b.depth) && Object.is(a.radius, b.radius) && a.smoothness === b.smoothness && a.bevelSegments === b.bevelSegments && a.steps === b.steps && Object.is(a.creaseAngle, b.creaseAngle);
302
+ case "Backdrop":
303
+ return b._tag === "Backdrop" && Object.is(a.floor, b.floor) && a.segments === b.segments;
286
304
  case "Text":
287
305
  return b._tag === "Text" && a.text === b.text && a.font === b.font && Object.is(a.size, b.size) && Object.is(a.depth, b.depth) && a.curveSegments === b.curveSegments && a.center === b.center && Object.is(a.letterSpacing, b.letterSpacing) && Object.is(a.lineHeight, b.lineHeight) && a.align === b.align && bevelEquals(a.bevel, b.bevel);
288
306
  }
@@ -340,11 +358,12 @@ var materialRefEquals2 = (a, b) => {
340
358
  }
341
359
  return sameFlatRecord(a, b);
342
360
  };
361
+ var cameraShakeEquals = (a, b) => a === b || a !== null && b !== null && Object.is(a.intensity, b.intensity) && a.decay === b.decay && Object.is(a.decayRate, b.decayRate) && Object.is(a.maxYaw, b.maxYaw) && Object.is(a.maxPitch, b.maxPitch) && Object.is(a.maxRoll, b.maxRoll) && Object.is(a.yawFrequency, b.yawFrequency) && Object.is(a.pitchFrequency, b.pitchFrequency) && Object.is(a.rollFrequency, b.rollFrequency) && Object.is(a.trigger, b.trigger);
343
362
  var cameraEquals2 = (a, b) => {
344
363
  if (a === b)
345
364
  return true;
346
365
  const sameLens = a._tag === "Perspective" && b._tag === "Perspective" && Object.is(a.fov, b.fov) || a._tag === "Orthographic" && b._tag === "Orthographic" && Object.is(a.zoom, b.zoom);
347
- return sameLens && Object.is(a.near, b.near) && Object.is(a.far, b.far) && Object.is(a.damping, b.damping) && Object.is(a.autoRotate, b.autoRotate) && vec3Equals2(a.position, b.position) && vec3Equals2(a.lookAt, b.lookAt);
366
+ return sameLens && Object.is(a.near, b.near) && Object.is(a.far, b.far) && Object.is(a.damping, b.damping) && Object.is(a.autoRotate, b.autoRotate) && cameraShakeEquals(a.shake, b.shake) && vec3Equals2(a.position, b.position) && vec3Equals2(a.lookAt, b.lookAt);
348
367
  };
349
368
  var renderSettingsEquals2 = (a, b) => a === b || a.frames === b.frames && Object.is(a.resolution, b.resolution) && a.shadows === b.shadows && a.toneMapping === b.toneMapping && Object.is(a.exposure, b.exposure) && a.colorSpace === b.colorSpace && effectsEqual2(a.effects, b.effects);
350
369
  var effectsEqual2 = (a, b) => {
@@ -651,6 +670,12 @@ var spin2 = (options) => ({
651
670
  radiansPerSecond: options.radiansPerSecond,
652
671
  phase: options.phase ?? 0
653
672
  });
673
+ var billboard2 = (options = {}) => ({
674
+ _tag: "Billboard",
675
+ lockX: options.lockX ?? false,
676
+ lockY: options.lockY ?? false,
677
+ lockZ: options.lockZ ?? false
678
+ });
654
679
  var box2 = (size = {}) => ({
655
680
  _tag: "Box",
656
681
  width: size.width ?? 1,
@@ -691,6 +716,22 @@ var capsule2 = (options = {}) => ({
691
716
  capSegments: options.capSegments ?? 4,
692
717
  radialSegments: options.radialSegments ?? 8
693
718
  });
719
+ var roundedBox2 = (options = {}) => ({
720
+ _tag: "RoundedBox",
721
+ width: options.width ?? 1,
722
+ height: options.height ?? 1,
723
+ depth: options.depth ?? 1,
724
+ radius: options.radius ?? 0.05,
725
+ smoothness: options.smoothness ?? 4,
726
+ bevelSegments: options.bevelSegments ?? 4,
727
+ steps: options.steps ?? 1,
728
+ creaseAngle: options.creaseAngle ?? 0.4
729
+ });
730
+ var backdrop2 = (options = {}) => ({
731
+ _tag: "Backdrop",
732
+ floor: options.floor ?? 0.25,
733
+ segments: options.segments ?? 20
734
+ });
694
735
  var ring2 = (options = {}) => ({
695
736
  _tag: "Ring",
696
737
  innerRadius: options.innerRadius ?? 0.5,
@@ -846,8 +887,10 @@ var group2 = (options) => ({
846
887
  interactive: options.interactive ?? false,
847
888
  children: options.children ?? [],
848
889
  body: options.body ?? null,
849
- follow: options.follow ?? null
890
+ follow: options.follow ?? null,
891
+ detail: options.detail ?? null
850
892
  });
893
+ var detailed2 = (options) => ({ distances: options.distances, hysteresis: options.hysteresis ?? 0 });
851
894
  var headSpace2 = () => ({ _tag: "Head" });
852
895
  var jointSpace2 = (hand, joint) => ({
853
896
  _tag: "Joint",
@@ -1032,7 +1075,9 @@ var borrowed2 = (options) => ({
1032
1075
  transition: options.transition ?? instantTransition,
1033
1076
  behaviour: options.behaviour ?? null,
1034
1077
  interactive: options.interactive ?? false,
1035
- body: options.body ?? null
1078
+ body: options.body ?? null,
1079
+ castShadow: options.castShadow ?? false,
1080
+ receiveShadow: options.receiveShadow ?? false
1036
1081
  });
1037
1082
  var noColorRanges = [];
1038
1083
  var label2 = (options) => ({
@@ -1124,7 +1169,8 @@ var perspectiveCamera2 = (options = {}) => ({
1124
1169
  position: options.position ?? [0, 0, 5],
1125
1170
  lookAt: options.lookAt ?? origin,
1126
1171
  damping: options.damping ?? 0,
1127
- autoRotate: options.autoRotate ?? 0
1172
+ autoRotate: options.autoRotate ?? 0,
1173
+ shake: options.shake ?? null
1128
1174
  });
1129
1175
  var orthographicCamera2 = (options = {}) => ({
1130
1176
  _tag: "Orthographic",
@@ -1134,7 +1180,20 @@ var orthographicCamera2 = (options = {}) => ({
1134
1180
  position: options.position ?? [0, 0, 5],
1135
1181
  lookAt: options.lookAt ?? origin,
1136
1182
  damping: options.damping ?? 0,
1137
- autoRotate: options.autoRotate ?? 0
1183
+ autoRotate: options.autoRotate ?? 0,
1184
+ shake: options.shake ?? null
1185
+ });
1186
+ var cameraShake2 = (options = {}) => ({
1187
+ intensity: options.intensity ?? 1,
1188
+ decay: options.decay ?? false,
1189
+ decayRate: options.decayRate ?? 0.65,
1190
+ maxYaw: options.maxYaw ?? 0.1,
1191
+ maxPitch: options.maxPitch ?? 0.1,
1192
+ maxRoll: options.maxRoll ?? 0.1,
1193
+ yawFrequency: options.yawFrequency ?? 0.1,
1194
+ pitchFrequency: options.pitchFrequency ?? 0.1,
1195
+ rollFrequency: options.rollFrequency ?? 0.1,
1196
+ trigger: options.trigger ?? 0
1138
1197
  });
1139
1198
  var noEffects = [];
1140
1199
  var bloom2 = (options = {}) => ({
@@ -1419,6 +1478,8 @@ var changedFields2 = (prev, next) => {
1419
1478
  fields.push("body");
1420
1479
  if (!xrSpaceEquals(prev.follow, next.follow))
1421
1480
  fields.push("follow");
1481
+ if (!detailEquals(prev.detail, next.detail))
1482
+ fields.push("detail");
1422
1483
  return fields;
1423
1484
  }
1424
1485
  case "Mesh": {
@@ -1498,6 +1559,10 @@ var changedFields2 = (prev, next) => {
1498
1559
  fields.push("interactive");
1499
1560
  if (!bodyEquals2(prev.body, next.body))
1500
1561
  fields.push("body");
1562
+ if (prev.castShadow !== next.castShadow)
1563
+ fields.push("castShadow");
1564
+ if (prev.receiveShadow !== next.receiveShadow)
1565
+ fields.push("receiveShadow");
1501
1566
  return fields;
1502
1567
  }
1503
1568
  case "Label": {
@@ -1744,14 +1809,18 @@ import {
1744
1809
  CircleGeometry,
1745
1810
  ConeGeometry,
1746
1811
  CylinderGeometry,
1812
+ Euler as Euler2,
1747
1813
  ExtrudeGeometry,
1748
1814
  Material,
1749
1815
  PlaneGeometry,
1816
+ Quaternion as Quaternion2,
1750
1817
  RingGeometry,
1818
+ Shape,
1751
1819
  ShapeGeometry as ShapeGeometry3,
1752
1820
  SphereGeometry,
1753
1821
  TorusGeometry
1754
1822
  } from "three";
1823
+ import { toCreasedNormals } from "three/addons/utils/BufferGeometryUtils.js";
1755
1824
 
1756
1825
  // src/kernel/textLayout.ts
1757
1826
  import { Vector2 } from "three";
@@ -1846,6 +1915,45 @@ var buildText = (shape, font) => {
1846
1915
  geometry.center();
1847
1916
  return geometry;
1848
1917
  };
1918
+ var roundedEpsilon = 0.00001;
1919
+ var buildRoundedBox = (shape) => {
1920
+ const { width, height, depth, radius } = shape;
1921
+ const outline = new Shape;
1922
+ const inset = radius - roundedEpsilon;
1923
+ const e = roundedEpsilon;
1924
+ outline.absarc(e, e, e, -Math.PI / 2, -Math.PI, true);
1925
+ outline.absarc(e, height - inset * 2, e, Math.PI, Math.PI / 2, true);
1926
+ outline.absarc(width - inset * 2, height - inset * 2, e, Math.PI / 2, 0, true);
1927
+ outline.absarc(width - inset * 2, e, e, 0, -Math.PI / 2, true);
1928
+ const geometry = new ExtrudeGeometry(outline, {
1929
+ depth: depth - radius * 2,
1930
+ bevelEnabled: true,
1931
+ bevelSegments: shape.bevelSegments * 2,
1932
+ steps: shape.steps,
1933
+ bevelSize: radius - roundedEpsilon,
1934
+ bevelThickness: radius,
1935
+ curveSegments: shape.smoothness
1936
+ });
1937
+ geometry.center();
1938
+ return toCreasedNormals(geometry, shape.creaseAngle);
1939
+ };
1940
+ var backdropTurn = new Quaternion2().setFromEuler(new Euler2(-Math.PI / 2, 0, Math.PI / 2));
1941
+ var easeInExpo = (x) => x === 0 ? 0 : 2 ** (10 * x - 10);
1942
+ var buildBackdrop = (shape) => {
1943
+ const { segments, floor } = shape;
1944
+ const geometry = new PlaneGeometry(1, 1, segments, segments);
1945
+ const position = geometry.getAttribute("position");
1946
+ const offset = 0.5;
1947
+ let vertex = 0;
1948
+ for (let x = 0;x < segments + 1; x++) {
1949
+ for (let y = 0;y < segments + 1; y++) {
1950
+ position.setXYZ(vertex++, x / segments - offset + (x === 0 ? -floor : 0), y / segments - offset, easeInExpo(x / segments));
1951
+ }
1952
+ }
1953
+ position.needsUpdate = true;
1954
+ geometry.computeVertexNormals();
1955
+ return geometry.applyQuaternion(backdropTurn);
1956
+ };
1849
1957
  var buildShape = (shape, fontOf) => {
1850
1958
  switch (shape._tag) {
1851
1959
  case "Text":
@@ -1868,6 +1976,10 @@ var buildShape = (shape, fontOf) => {
1868
1976
  return new RingGeometry(shape.innerRadius, shape.outerRadius, shape.thetaSegments);
1869
1977
  case "Circle":
1870
1978
  return new CircleGeometry(shape.radius, shape.segments);
1979
+ case "RoundedBox":
1980
+ return buildRoundedBox(shape);
1981
+ case "Backdrop":
1982
+ return buildBackdrop(shape);
1871
1983
  }
1872
1984
  };
1873
1985
  var notLent = new BufferGeometry;
@@ -2586,9 +2698,9 @@ var placeOverlays2 = (graph) => {
2586
2698
  };
2587
2699
  // src/kernel/physics.ts
2588
2700
  import {
2589
- Euler as Euler2,
2701
+ Euler as Euler3,
2590
2702
  Matrix4 as Matrix43,
2591
- Quaternion as Quaternion2,
2703
+ Quaternion as Quaternion3,
2592
2704
  Vector3 as Vector35
2593
2705
  } from "three";
2594
2706
  var interactionBits2 = (groups) => {
@@ -2666,8 +2778,8 @@ var colliderFor2 = (geometry, collider, scale) => {
2666
2778
  const { shape, offset } = shapeFor(geometry, collider, scale);
2667
2779
  return { shape, translation: toVec32(offset), rotation: [0, 0, 0, 1] };
2668
2780
  };
2669
- var turn3 = new Quaternion2;
2670
- var turnEuler = new Euler2;
2781
+ var turn3 = new Quaternion3;
2782
+ var turnEuler = new Euler3;
2671
2783
  var largest = (a, b) => Math.max(Math.abs(a), Math.abs(b));
2672
2784
  var scaledShape = (shape, scale) => {
2673
2785
  switch (shape._tag) {
@@ -2704,11 +2816,11 @@ function describedCollider(collider, scale) {
2704
2816
  var relative = new Matrix43;
2705
2817
  var bodyInverse = new Matrix43;
2706
2818
  var where = new Vector35;
2707
- var turn = new Quaternion2;
2819
+ var turn = new Quaternion3;
2708
2820
  var relativeScale = new Vector35;
2709
2821
  var worldScale = new Vector35;
2710
2822
  var worldPosition = new Vector35;
2711
- var worldTurn = new Quaternion2;
2823
+ var worldTurn = new Quaternion3;
2712
2824
  var isMesh = (object) => ("isMesh" in object) && object.isMesh === true;
2713
2825
  function placedCollider2(child, collider, body) {
2714
2826
  child.matrixWorld.decompose(worldPosition, worldTurn, worldScale);
@@ -2995,6 +3107,12 @@ var pathOf = (graph, object) => {
2995
3107
  }
2996
3108
  return path;
2997
3109
  };
3110
+ var shown = (object) => {
3111
+ for (let at = object;at !== null; at = at.parent)
3112
+ if (!at.visible)
3113
+ return false;
3114
+ return true;
3115
+ };
2998
3116
  var createPicker2 = (graph) => {
2999
3117
  const raycaster = new Raycaster2;
3000
3118
  const ndc = new Vector23;
@@ -3030,6 +3148,8 @@ var createPicker2 = (graph) => {
3030
3148
  const rayDirection = new Vector36;
3031
3149
  const nearestHit = (view) => {
3032
3150
  for (const intersection of raycaster.intersectObjects(graph.interactiveObjects(), true)) {
3151
+ if (!shown(intersection.object))
3152
+ continue;
3033
3153
  const owner = keyedOwner(graph, intersection.object);
3034
3154
  const key = owner === undefined ? undefined : graph.keyOf(owner);
3035
3155
  if (owner !== undefined && key !== undefined) {
@@ -3569,24 +3689,26 @@ import {
3569
3689
  OrthographicCamera as OrthographicCamera4,
3570
3690
  PerspectiveCamera as PerspectiveCamera3,
3571
3691
  PointLight,
3692
+ Quaternion as Quaternion6,
3572
3693
  Scene,
3573
3694
  SpotLight,
3574
3695
  Vector3 as Vector39
3575
3696
  } from "three";
3697
+ import { clone as cloneSkinned } from "three/addons/utils/SkeletonUtils.js";
3576
3698
 
3577
3699
  // src/kernel/bodies.ts
3578
- import { Euler as Euler4, Quaternion as Quaternion4 } from "three";
3700
+ import { Euler as Euler5, Quaternion as Quaternion5 } from "three";
3579
3701
 
3580
3702
  // src/kernel/bodySources.ts
3581
- import { Euler as Euler3, Matrix4 as Matrix44, Quaternion as Quaternion3, Vector3 as Vector37 } from "three";
3703
+ import { Euler as Euler4, Matrix4 as Matrix44, Quaternion as Quaternion4, Vector3 as Vector37 } from "three";
3582
3704
  var bodyId = (key, instance) => instance === null ? key : `${key}\x00${instance}`;
3583
3705
  var position3 = new Vector37;
3584
- var quaternion2 = new Quaternion3;
3706
+ var quaternion2 = new Quaternion4;
3585
3707
  var scale2 = new Vector37;
3586
3708
  var matrix2 = new Matrix44;
3587
3709
  var local = new Matrix44;
3588
3710
  var inverse = new Matrix44;
3589
- var euler2 = new Euler3;
3711
+ var euler2 = new Euler4;
3590
3712
  var ownScale = new Vector37;
3591
3713
  var toPose = (from) => {
3592
3714
  from.decompose(position3, quaternion2, scale2);
@@ -3600,7 +3722,7 @@ var worldScale2 = (from) => {
3600
3722
  return ownScale;
3601
3723
  };
3602
3724
  var scaleText = (from) => worldScale2(from).toArray().map((value) => (Math.round(value * 1e5) / 1e5 || 0).toString()).join(",");
3603
- var rotationText = (rotation) => rotation._tag === "Fixed" ? rotation.euler.join(",") : "spin";
3725
+ var rotationText = (rotation) => rotation._tag === "Fixed" ? rotation.euler.join(",") : rotation._tag;
3604
3726
  var placeObject = (object, pose) => {
3605
3727
  object.matrixWorld.decompose(position3, quaternion2, scale2);
3606
3728
  matrix2.compose(position3.fromArray(pose.position), quaternion2.fromArray(pose.quaternion), scale2);
@@ -3717,9 +3839,9 @@ var createPhysicsDebug = (scene) => {
3717
3839
  };
3718
3840
 
3719
3841
  // src/kernel/bodies.ts
3720
- var from = new Quaternion4;
3721
- var to = new Quaternion4;
3722
- var euler3 = new Euler4;
3842
+ var from = new Quaternion5;
3843
+ var to = new Quaternion5;
3844
+ var euler3 = new Euler5;
3723
3845
  var quatOf = (angles) => {
3724
3846
  from.setFromEuler(euler3.fromArray([...angles]));
3725
3847
  return [from.x, from.y, from.z, from.w];
@@ -4075,9 +4197,58 @@ var createCameraMotion = () => {
4075
4197
  return;
4076
4198
  position4.setFromSpherical(goal.spherical).add(goal.target);
4077
4199
  return [position4.x, position4.y, position4.z];
4200
+ },
4201
+ target: () => current.target
4202
+ };
4203
+ };
4204
+
4205
+ // src/kernel/cameraShake.ts
4206
+ import { SimplexNoise } from "three/addons/math/SimplexNoise.js";
4207
+ var seeded = (seed) => {
4208
+ let state = seed >>> 0;
4209
+ return {
4210
+ random: () => {
4211
+ state = state + 1831565813 >>> 0;
4212
+ let t = state;
4213
+ t = Math.imul(t ^ t >>> 15, t | 1);
4214
+ t ^= t + Math.imul(t ^ t >>> 7, t | 61);
4215
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
4078
4216
  }
4079
4217
  };
4080
4218
  };
4219
+ var yawNoise = new SimplexNoise(seeded(1));
4220
+ var pitchNoise = new SimplexNoise(seeded(2));
4221
+ var rollNoise = new SimplexNoise(seeded(3));
4222
+ var shakeIntensity = (shake, seconds) => {
4223
+ const decayed = shake.decay ? shake.intensity - shake.decayRate * seconds : shake.intensity;
4224
+ return Math.min(1, Math.max(0, decayed));
4225
+ };
4226
+ var createCameraShaker = () => {
4227
+ let current = null;
4228
+ let since = 0;
4229
+ let offset = false;
4230
+ return {
4231
+ describe: (shake, now) => {
4232
+ if (shake !== null && (current === null || !cameraShakeEquals(current, shake)))
4233
+ since = now;
4234
+ current = shake;
4235
+ },
4236
+ apply: (camera, target, now, animating) => {
4237
+ const shake = current;
4238
+ const strength = shake === null || !animating ? 0 : shakeIntensity(shake, Math.max(0, now - since)) ** 2;
4239
+ if (shake === null || strength === 0) {
4240
+ if (offset)
4241
+ camera.lookAt(target);
4242
+ offset = false;
4243
+ return;
4244
+ }
4245
+ camera.lookAt(target);
4246
+ camera.rotation.set(camera.rotation.x + shake.maxPitch * strength * pitchNoise.noise(now * shake.pitchFrequency, 1), camera.rotation.y + shake.maxYaw * strength * yawNoise.noise(now * shake.yawFrequency, 1), camera.rotation.z + shake.maxRoll * strength * rollNoise.noise(now * shake.rollFrequency, 1));
4247
+ offset = true;
4248
+ },
4249
+ shaking: (now) => offset || current !== null && shakeIntensity(current, Math.max(0, now - since)) > 0
4250
+ };
4251
+ };
4081
4252
 
4082
4253
  // src/kernel/sceneGraph.ts
4083
4254
  var isPlaced = (entry) => entry._tag === "Group" || entry._tag === "Mesh" || entry._tag === "Instances" || entry._tag === "Borrowed" || entry._tag === "Label";
@@ -4165,6 +4336,7 @@ var applyLens = (camera, description) => {
4165
4336
  };
4166
4337
  var noInstances = [];
4167
4338
  var emptyScene = scene2({});
4339
+ var cloneLoan = (lent) => lent.getObjectByProperty("isSkinnedMesh", true) === undefined ? lent.clone() : cloneSkinned(lent);
4168
4340
  var createSceneGraph2 = (options = {}) => {
4169
4341
  const store = options.store ?? createResourceStore2();
4170
4342
  const ownsStore = options.store === undefined;
@@ -4202,7 +4374,23 @@ var createSceneGraph2 = (options = {}) => {
4202
4374
  hostedSky = undefined;
4203
4375
  }
4204
4376
  const cameraMotion = createCameraMotion();
4377
+ const cameraShaker = createCameraShaker();
4205
4378
  const viewMotions = new Map;
4379
+ const viewShakers = new Map;
4380
+ const shaking = () => {
4381
+ if (cameraShaker.shaking(elapsed))
4382
+ return true;
4383
+ for (const shaker of viewShakers.values())
4384
+ if (shaker.shaking(elapsed))
4385
+ return true;
4386
+ return false;
4387
+ };
4388
+ const shakeView = (view) => {
4389
+ const motion = viewMotions.get(view.key);
4390
+ if (motion === undefined)
4391
+ return;
4392
+ viewShakers.get(view.key)?.apply(view.camera, motion.target(), elapsed, animating);
4393
+ };
4206
4394
  const viewsMoving = () => {
4207
4395
  for (const motion of viewMotions.values())
4208
4396
  if (motion.moving())
@@ -4233,6 +4421,9 @@ var createSceneGraph2 = (options = {}) => {
4233
4421
  applyLens(hostedCamera, description.camera);
4234
4422
  const motion = viewMotions.get(description.key) ?? createCameraMotion();
4235
4423
  viewMotions.set(description.key, motion);
4424
+ const shaker = viewShakers.get(description.key) ?? createCameraShaker();
4425
+ viewShakers.set(description.key, shaker);
4426
+ shaker.describe(description.camera.shake, elapsed);
4236
4427
  motion.aim(hostedCamera, description.camera, elapsed, hostedCamera !== previous || !animating);
4237
4428
  const area = areaOf(description.rect);
4238
4429
  fitCamera(hostedCamera, area);
@@ -4246,10 +4437,20 @@ var createSceneGraph2 = (options = {}) => {
4246
4437
  if (!described.some((description) => description.key === key))
4247
4438
  viewMotions.delete(key);
4248
4439
  }
4440
+ for (const key of viewShakers.keys()) {
4441
+ if (!described.some((description) => description.key === key))
4442
+ viewShakers.delete(key);
4443
+ }
4249
4444
  };
4250
4445
  const entries = new Map;
4251
4446
  const keys = new WeakMap;
4252
4447
  const spinning = new Set;
4448
+ const facing = new Set;
4449
+ const cameraTurn = new Quaternion6;
4450
+ const parentTurn = new Quaternion6;
4451
+ const detailing = new Set;
4452
+ const cameraPlace = new Vector39;
4453
+ const groupPlace = new Vector39;
4253
4454
  const playing = new Set;
4254
4455
  const registry = {
4255
4456
  ...builtinBehaviours2,
@@ -4307,6 +4508,77 @@ var createSceneGraph2 = (options = {}) => {
4307
4508
  spinning.add(entry);
4308
4509
  else
4309
4510
  spinning.delete(entry);
4511
+ if (node.rotation._tag === "Billboard")
4512
+ facing.add(entry);
4513
+ else
4514
+ facing.delete(entry);
4515
+ };
4516
+ const faceCamera = (entry) => {
4517
+ if (!isPlaced(entry) || entry.node.rotation._tag !== "Billboard")
4518
+ return;
4519
+ const { lockX, lockY, lockZ } = entry.node.rotation;
4520
+ const object = entry.object;
4521
+ parentTurn.identity();
4522
+ object.parent?.getWorldQuaternion(parentTurn);
4523
+ object.quaternion.copy(cameraTurn).premultiply(parentTurn.invert());
4524
+ if (lockX)
4525
+ object.rotation.x = 0;
4526
+ if (lockY)
4527
+ object.rotation.y = 0;
4528
+ if (lockZ)
4529
+ object.rotation.z = 0;
4530
+ };
4531
+ const childObject = (node, index) => {
4532
+ const child = node.children[index];
4533
+ return child === undefined ? undefined : entries.get(child.key)?.object;
4534
+ };
4535
+ const showLevel = (entry) => {
4536
+ if (entry._tag !== "Group")
4537
+ return;
4538
+ const { node } = entry;
4539
+ const { detail } = node;
4540
+ if (detail === null)
4541
+ return;
4542
+ const { distances, hysteresis } = detail;
4543
+ const count = node.children.length;
4544
+ if (count < 2)
4545
+ return;
4546
+ entry.object.getWorldPosition(groupPlace);
4547
+ const distance = cameraPlace.distanceTo(groupPlace) / camera.zoom;
4548
+ const first = childObject(node, 0);
4549
+ if (first !== undefined)
4550
+ first.visible = true;
4551
+ let level = 1;
4552
+ for (;level < count; level++) {
4553
+ const object = childObject(node, level);
4554
+ const from = distances[level] ?? Number.NaN;
4555
+ const reach = object?.visible === true ? from - from * hysteresis : from;
4556
+ if (!(distance >= reach))
4557
+ break;
4558
+ const previous = childObject(node, level - 1);
4559
+ if (previous !== undefined)
4560
+ previous.visible = false;
4561
+ if (object !== undefined)
4562
+ object.visible = true;
4563
+ }
4564
+ for (;level < count; level++) {
4565
+ const object = childObject(node, level);
4566
+ if (object !== undefined)
4567
+ object.visible = false;
4568
+ }
4569
+ };
4570
+ const trackDetail = (entry, node) => {
4571
+ if (node.detail !== null) {
4572
+ detailing.add(entry);
4573
+ return;
4574
+ }
4575
+ if (detailing.delete(entry)) {
4576
+ for (let index = 0;index < node.children.length; index++) {
4577
+ const object = childObject(node, index);
4578
+ if (object !== undefined)
4579
+ object.visible = true;
4580
+ }
4581
+ }
4310
4582
  };
4311
4583
  const build = (node) => {
4312
4584
  switch (node._tag) {
@@ -4319,6 +4591,7 @@ var createSceneGraph2 = (options = {}) => {
4319
4591
  trackInteractive(entry.object, node.interactive);
4320
4592
  if (node.follow !== null)
4321
4593
  entry.object.visible = false;
4594
+ trackDetail(entry, node);
4322
4595
  return entry;
4323
4596
  }
4324
4597
  case "Mesh": {
@@ -4418,11 +4691,22 @@ var createSceneGraph2 = (options = {}) => {
4418
4691
  const lent = store.lent(entry.node.id);
4419
4692
  if (lent === undefined)
4420
4693
  return;
4421
- const shown = lent.parent === null ? lent : lent.clone();
4694
+ const shown = lent.parent === null ? lent : cloneLoan(lent);
4422
4695
  entry.object.add(shown);
4423
4696
  entry.shown = shown;
4697
+ castShadows(shown, entry.node);
4424
4698
  startPlayer(entry);
4425
4699
  };
4700
+ const castShadows = (shown, node) => {
4701
+ if (!node.castShadow && !node.receiveShadow)
4702
+ return;
4703
+ shown.traverse((part) => {
4704
+ if (part instanceof Mesh && node.castShadow)
4705
+ part.castShadow = true;
4706
+ if (part instanceof Mesh && node.receiveShadow)
4707
+ part.receiveShadow = true;
4708
+ });
4709
+ };
4426
4710
  const stopPlayer = (entry) => {
4427
4711
  if (entry.player === undefined)
4428
4712
  return;
@@ -4556,6 +4840,8 @@ var createSceneGraph2 = (options = {}) => {
4556
4840
  if (isPlaced(entry))
4557
4841
  behaving.delete(entry);
4558
4842
  spinning.delete(entry);
4843
+ facing.delete(entry);
4844
+ detailing.delete(entry);
4559
4845
  moving.delete(entry);
4560
4846
  reparented.delete(entry);
4561
4847
  trackInteractive(entry.object, false);
@@ -4685,6 +4971,10 @@ var createSceneGraph2 = (options = {}) => {
4685
4971
  showLoan(entry);
4686
4972
  else if (fields.includes("animation"))
4687
4973
  startPlayer(entry);
4974
+ if (fields.includes("castShadow") || fields.includes("receiveShadow")) {
4975
+ if (entry.shown !== undefined)
4976
+ castShadows(entry.shown, next);
4977
+ }
4688
4978
  return;
4689
4979
  }
4690
4980
  if (entry._tag === "Label" && next._tag === "Label") {
@@ -4713,6 +5003,8 @@ var createSceneGraph2 = (options = {}) => {
4713
5003
  trackBehaviour(entry, next);
4714
5004
  if (fields.includes("interactive"))
4715
5005
  trackInteractive(entry.object, next.interactive);
5006
+ if (fields.includes("detail"))
5007
+ trackDetail(entry, next);
4716
5008
  if (fields.includes("follow")) {
4717
5009
  entry.object.visible = next.follow === null;
4718
5010
  if (next.follow === null) {
@@ -4785,6 +5077,7 @@ var createSceneGraph2 = (options = {}) => {
4785
5077
  camera = cameraFor(camera, op.camera);
4786
5078
  applyLens(camera, op.camera);
4787
5079
  cameraMotion.aim(camera, op.camera, elapsed, camera !== previous || !animating);
5080
+ cameraShaker.describe(op.camera.shake, elapsed);
4788
5081
  fitCamera(camera, viewport);
4789
5082
  return;
4790
5083
  }
@@ -4994,7 +5287,17 @@ var createSceneGraph2 = (options = {}) => {
4994
5287
  cameraMotion.step(camera, elapsed);
4995
5288
  for (const view of views)
4996
5289
  viewMotions.get(view.key)?.step(view.camera, elapsed);
5290
+ cameraShaker.apply(camera, cameraMotion.target(), elapsed, animating);
5291
+ views.forEach(shakeView);
4997
5292
  bodyHost.tick(elapsed, animating);
5293
+ if (facing.size > 0) {
5294
+ camera.getWorldQuaternion(cameraTurn);
5295
+ facing.forEach(faceCamera);
5296
+ }
5297
+ if (detailing.size > 0) {
5298
+ camera.getWorldPosition(cameraPlace);
5299
+ detailing.forEach(showLevel);
5300
+ }
4998
5301
  };
4999
5302
  const finishTween = (tween, entry) => {
5000
5303
  applyTween2(entry.object, tween, Number.POSITIVE_INFINITY);
@@ -5080,7 +5383,7 @@ var createSceneGraph2 = (options = {}) => {
5080
5383
  tick,
5081
5384
  elapsedSeconds: () => elapsed,
5082
5385
  renderSettings: () => settings,
5083
- needsFrame: () => dirty || textureList.some((texture) => texture.graph.needsFrame()) || animating && (spinning.size > 0 || moving.size > 0 || behaving.size > 0 || clipsRunning() || cameraMotion.moving() || viewsMoving() || bodyHost.needsFrame()),
5386
+ needsFrame: () => dirty || textureList.some((texture) => texture.graph.needsFrame()) || animating && (spinning.size > 0 || moving.size > 0 || behaving.size > 0 || clipsRunning() || cameraMotion.moving() || viewsMoving() || shaking() || bodyHost.needsFrame()),
5084
5387
  drawn: () => {
5085
5388
  dirty = false;
5086
5389
  },
@@ -5112,7 +5415,7 @@ var createSceneGraph2 = (options = {}) => {
5112
5415
  dispose
5113
5416
  };
5114
5417
  };
5115
- export { handJoints2, clipTime2, clipRunning2, createPose2, resetPose2, float2, builtinBehaviours2, spinAngle2, writeRotation2, buildMaterial2, updateMaterial2, vec3Equals2, rotationEquals2, shapeEquals2, geometryRefEquals2, instanceEquals2, instancesEqual2, behaviourEquals2, animationEquals2, transitionEquals2, materialRefEquals2, cameraEquals2, renderSettingsEquals2, effectsEqual2, viewsEqual2, resourcesEqual2, overlaysEqual2, environmentEquals2, skyEquals2, contactShadowsEquals2, bodyEquals2, physicsEquals2, xrEquals2, capacityFor2, createPerformanceMonitor2, easeProgress2, startTween2, applyTween2, fixed2, spin2, box2, sphere2, plane2, cylinder2, torus2, cone2, capsule2, ring2, circle2, text2, instant2, ease2, basic2, lambert2, phong2, standard2, physical2, normalMaterial2, shadowMaterial2, grid2, shaderGrid2, sharedGeometry2, lentGeometry2, sharedMaterial2, group2, headSpace2, jointSpace2, controllerSpace2, anchorSpace2, planeSpace2, meshSpace2, xrMeshGeometryId2, xrMesh2, xrAnchor2, mesh2, body2, interactionGroups2, cuboidCollider2, ballCollider2, capsuleCollider2, cylinderCollider2, coneCollider2, velocityMotor2, positionMotor2, physics2, bodyRef2, joint2, fixedJoint2, sphericalJoint2, revoluteJoint2, prismaticJoint2, ropeJoint2, springJoint2, glide2, xr2, instance2, instances2, behave2, play2, borrowed2, label2, colorRange2, ambientLight2, directionalLight2, pointLight2, spotLight2, hemisphereLight2, perspectiveCamera2, orthographicCamera2, bloom2, vignette2, film2, renderSettings2, view2, renderTexture2, environment2, sunPositionFromAngles2, sky2, contactShadows2, overlay2, scene2, emptyIndex2, indexScene2, changedFields2, diff2, createResourceStore2, createSceneClock2, createManualFrames2, createGatedFrames2, createFramePacer2, defaultOrbit2, orbitOptions2, rotateCamera2, dollyCamera2, panCamera2, dollyCameraToward2, orbit2, orbitKey2, autoRotated2, fitCamera2, clipCamera2, placeOverlays2, interactionBits2, colliderFor2, describedColliders2, collidersFor2, colliderSignature2, locomote2, teleport2, glided2, createXrTracker2, environmentPresets2, environmentPresetUrl2, stagePresets2, stage2, centerOffset2, stageBounds2, noModifiers2, pointOnPlane2, createPicker2, createPointerTracker2, createSceneLoop2, recordingRendererFactory2, createSceneGraph2 };
5418
+ export { handJoints2, clipTime2, clipRunning2, createPose2, resetPose2, float2, builtinBehaviours2, spinAngle2, writeRotation2, buildMaterial2, updateMaterial2, vec3Equals2, rotationEquals2, shapeEquals2, geometryRefEquals2, instanceEquals2, instancesEqual2, behaviourEquals2, animationEquals2, transitionEquals2, materialRefEquals2, cameraEquals2, renderSettingsEquals2, effectsEqual2, viewsEqual2, resourcesEqual2, overlaysEqual2, environmentEquals2, skyEquals2, contactShadowsEquals2, bodyEquals2, physicsEquals2, xrEquals2, capacityFor2, createPerformanceMonitor2, easeProgress2, startTween2, applyTween2, fixed2, spin2, billboard2, box2, sphere2, plane2, cylinder2, torus2, cone2, capsule2, roundedBox2, backdrop2, ring2, circle2, text2, instant2, ease2, basic2, lambert2, phong2, standard2, physical2, normalMaterial2, shadowMaterial2, grid2, shaderGrid2, sharedGeometry2, lentGeometry2, sharedMaterial2, group2, detailed2, headSpace2, jointSpace2, controllerSpace2, anchorSpace2, planeSpace2, meshSpace2, xrMeshGeometryId2, xrMesh2, xrAnchor2, mesh2, body2, interactionGroups2, cuboidCollider2, ballCollider2, capsuleCollider2, cylinderCollider2, coneCollider2, velocityMotor2, positionMotor2, physics2, bodyRef2, joint2, fixedJoint2, sphericalJoint2, revoluteJoint2, prismaticJoint2, ropeJoint2, springJoint2, glide2, xr2, instance2, instances2, behave2, play2, borrowed2, label2, colorRange2, ambientLight2, directionalLight2, pointLight2, spotLight2, hemisphereLight2, perspectiveCamera2, orthographicCamera2, cameraShake2, bloom2, vignette2, film2, renderSettings2, view2, renderTexture2, environment2, sunPositionFromAngles2, sky2, contactShadows2, overlay2, scene2, emptyIndex2, indexScene2, changedFields2, diff2, createResourceStore2, createSceneClock2, createManualFrames2, createGatedFrames2, createFramePacer2, defaultOrbit2, orbitOptions2, rotateCamera2, dollyCamera2, panCamera2, dollyCameraToward2, orbit2, orbitKey2, autoRotated2, fitCamera2, clipCamera2, placeOverlays2, interactionBits2, colliderFor2, describedColliders2, collidersFor2, colliderSignature2, locomote2, teleport2, glided2, createXrTracker2, environmentPresets2, environmentPresetUrl2, stagePresets2, stage2, centerOffset2, stageBounds2, noModifiers2, pointOnPlane2, createPicker2, createPointerTracker2, createSceneLoop2, recordingRendererFactory2, createSceneGraph2 };
5116
5419
 
5117
- //# debugId=C47554518AE363C364756E2164756E21
5118
- //# sourceMappingURL=index-01kwfekm.js.map
5420
+ //# debugId=DD15A712F87B1C4C64756E2164756E21
5421
+ //# sourceMappingURL=index-8cf8t6by.js.map