@navaramap/three-plugins 0.0.5 → 0.0.6

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/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { EventHandler as e, MAPBOX_ELEVATION_DECODER as t, Plugin as n, TERRARIUM_ELEVATION_DECODER as r, convertWorldToScreen as i, degreeToRadian as a, eastNorthUpToFixedFrame as o, geodeticToVector3 as s, radianToDegree as c, vector3ToGeodetic as l } from "@navaramap/three";
2
- import { Matrix4 as u, Vector3 as d } from "three";
2
+ import { MathUtils as u, Matrix4 as d, Vector3 as f } from "three";
3
3
  //#region src/PersonViewPlugin.ts
4
- var f = {
4
+ var p = {
5
5
  x: 0,
6
6
  y: 0,
7
7
  z: 0
8
- }, p = {
8
+ }, m = {
9
9
  forward: ["KeyW"],
10
10
  backward: ["KeyS"],
11
11
  turnLeft: ["KeyA"],
@@ -19,12 +19,35 @@ var f = {
19
19
  dash: ["ShiftLeft", "ShiftRight"],
20
20
  orbitCamera: ["AltLeft", "AltRight"],
21
21
  toggleView: ["KeyV"]
22
- }, m = {
22
+ }, h = {
23
+ mode: "off",
24
+ groundOffset: 0,
25
+ alignToSlope: !0,
26
+ slopeSampleDistance: 4,
27
+ maxSlopeTilt: Math.PI / 4,
28
+ cameraSlopeFollow: 1
29
+ }, g = 10, _ = 6, v = Math.PI / 4, y = [
30
+ 0,
31
+ 1,
32
+ 2,
33
+ 3,
34
+ 4,
35
+ 5,
36
+ 6,
37
+ 7
38
+ ].map((e) => {
39
+ let t = e * Math.PI / 4;
40
+ return {
41
+ sin: Math.sin(t),
42
+ cos: Math.cos(t)
43
+ };
44
+ }), b = (e, t) => e > 0 && t > 0 ? 1 - Math.exp(-e * t) : 1, x = {
23
45
  allowCameraControl: !1,
24
46
  initialView: "tpv",
25
47
  moveSpeed: 50,
26
48
  rotationSpeed: 3,
27
49
  altSpeed: 30,
50
+ dashSpeedMultiplier: 2.5,
28
51
  minAlt: 50,
29
52
  maxAlt: 5e3,
30
53
  cameraDistance: 50,
@@ -37,20 +60,23 @@ var f = {
37
60
  startLng: 139.7671,
38
61
  startHeight: 500,
39
62
  startHeading: Math.PI * 1.3
40
- }, h = 3, g = 1e3, _ = class extends n {
63
+ }, S = 3, C = 1e3, w = class extends n {
41
64
  view;
42
65
  config;
66
+ collision;
43
67
  character;
44
68
  keys;
45
69
  keyToAction;
46
70
  handle = null;
47
71
  modelRef = null;
48
72
  animId = null;
73
+ placed = !1;
49
74
  lastTime = 0;
50
75
  state;
51
76
  listeners = /* @__PURE__ */ new Set();
77
+ actionListeners = /* @__PURE__ */ new Set();
52
78
  heldActions = /* @__PURE__ */ new Set();
53
- dashMultiplier = 1;
79
+ dashHeld = !1;
54
80
  orbitKeyHeld = !1;
55
81
  orbitLatched = !1;
56
82
  currentAnimState;
@@ -60,21 +86,33 @@ var f = {
60
86
  movementSuppressed = !1;
61
87
  boundKeyDown;
62
88
  boundKeyUp;
63
- _curPos = new d();
64
- _east = new d();
65
- _north = new d();
66
- _worldForward = new d();
67
- _offset = new d();
68
- _headingMatrix = new u();
69
- _characterFrame = new u();
89
+ _curPos = new f();
90
+ _east = new f();
91
+ _north = new f();
92
+ _worldForward = new f();
93
+ _offset = new f();
94
+ _probePos = new f();
95
+ _headingMatrix = new d();
96
+ _tiltMatrix = new d();
97
+ _characterFrame = new d();
98
+ cameraSlopePitch = 0;
99
+ slopeGradEast = 0;
100
+ slopeGradNorth = 0;
101
+ lastGroundSample;
102
+ unabsorbedGroundShift = 0;
103
+ settleVelocity = 0;
104
+ groundSurfaceHeight;
70
105
  constructor(e = {}) {
71
106
  super();
72
- let { character: t, keys: n, ...r } = e;
107
+ let { character: t, keys: n, collision: r, ...i } = e;
73
108
  this.config = {
74
- ...m,
109
+ ...x,
110
+ ...i
111
+ }, this.collision = {
112
+ ...h,
75
113
  ...r
76
114
  }, this.character = t ? this.resolveCharacter(t) : null, this.keys = {
77
- ...p,
115
+ ...m,
78
116
  ...n
79
117
  }, this.keyToAction = this.buildKeyMap(this.keys), this.modelHeading = this.config.startHeading, this.cameraHeading = this.config.startHeading, this.viewMode = this.config.initialView, this.currentAnimState = this.character ? this.character.animation.idleClip : null, this.boundKeyDown = this.onKeyDown.bind(this), this.boundKeyUp = this.onKeyUp.bind(this);
80
118
  }
@@ -91,7 +129,11 @@ var f = {
91
129
  }
92
130
  start() {
93
131
  if (!this.view || this.animId != null) return;
94
- this.animId = -1;
132
+ if (this.animId = -1, document.addEventListener("keydown", this.boundKeyDown), document.addEventListener("keyup", this.boundKeyUp), this.placed) {
133
+ this.resumeLoop(), this.placeChaseCamera(this.state.lat, this.state.lng, this.state.alt, this.cameraHeading), this.applyModelVisibility();
134
+ return;
135
+ }
136
+ this.placed = !0;
95
137
  let { startLat: e, startLng: t, startHeight: n, startHeading: r } = this.config, i = s({
96
138
  lat: a(e),
97
139
  lng: a(t),
@@ -107,7 +149,7 @@ var f = {
107
149
  animationEnabled: !0,
108
150
  animationAutoPlay: !0,
109
151
  animationActiveClip: e.idleClip,
110
- animationSpeed: e.speed,
152
+ animationSpeed: this.clipSpeed(e.idleClip),
111
153
  animationLoop: !0,
112
154
  animationCrossfadeDuration: e.crossfadeDuration
113
155
  },
@@ -123,27 +165,46 @@ var f = {
123
165
  z: n
124
166
  }
125
167
  }), this.modelRef = this.handle.ref, this.modelRef.on("load", () => {
126
- this.view && (this.lastTime = performance.now(), this.animId = requestAnimationFrame(this.tick));
168
+ !this.view || this.animId == null || this.resumeLoop();
127
169
  });
128
- } else this.lastTime = performance.now(), this.animId = requestAnimationFrame(this.tick);
129
- this.applyInitialCamera(), this.applyModelVisibility(), document.addEventListener("keydown", this.boundKeyDown), document.addEventListener("keyup", this.boundKeyUp);
170
+ } else this.resumeLoop();
171
+ this.applyInitialCamera(), this.applyModelVisibility();
172
+ }
173
+ stop() {
174
+ if (this.animId == null) return;
175
+ this.releaseControl(), this.view?.cameraFollow(!1), this.view?.cameraFreeLook(!1), this.playAnimation(this.character?.animation.idleClip);
176
+ let e = {
177
+ ...this.state,
178
+ speed: 0,
179
+ animationState: this.currentAnimState
180
+ };
181
+ this.hasStateChanged(this.state, e) && (this.state = e, this.notify());
182
+ }
183
+ releaseControl() {
184
+ this.animId != null && this.animId >= 0 && cancelAnimationFrame(this.animId), this.animId = null, document.removeEventListener("keydown", this.boundKeyDown), document.removeEventListener("keyup", this.boundKeyUp), this.heldActions.clear(), this.orbitKeyHeld = !1, this.orbitLatched = !1, this.dashHeld = !1;
185
+ }
186
+ resumeLoop() {
187
+ this.lastTime = performance.now(), this.animId = requestAnimationFrame(this.tick);
130
188
  }
131
189
  teleport(e) {
132
190
  if (!this.view) return;
133
- let { lng: t, lat: n, alt: r } = e, i = e.heading == null ? this.cameraHeading : e.heading;
134
- if (this.handle && this.character) {
191
+ let { lng: t, lat: n } = e, r = e.heading == null ? this.cameraHeading : e.heading, i = {
192
+ lat: a(n),
193
+ lng: a(t)
194
+ }, o = this.resolveGroundHeight(i, i, e.alt, 0);
195
+ if (this.updateSlopeTilt(i.lat, i.lng, o, 0), this.handle && this.character) {
135
196
  let e = s({
136
- lat: a(n),
137
- lng: a(t),
138
- height: r
197
+ lat: i.lat,
198
+ lng: i.lng,
199
+ height: o
139
200
  });
140
- this.handle.update({ matrixWorld: this.composeCharacterFrame(e, i) });
201
+ this.handle.update({ matrixWorld: this.composeCharacterFrame(e, r) });
141
202
  }
142
- this.modelHeading = i, this.cameraHeading = i, this.placeChaseCamera(n, t, r, i), this.state = {
203
+ this.modelHeading = r, this.cameraHeading = r, this.placeChaseCamera(n, t, o, r), this.state = {
143
204
  lng: t,
144
205
  lat: n,
145
- alt: r,
146
- heading: i,
206
+ alt: o,
207
+ heading: r,
147
208
  speed: 0,
148
209
  animationState: this.currentAnimState,
149
210
  mode: this.viewMode
@@ -155,6 +216,9 @@ var f = {
155
216
  onStateChange(e) {
156
217
  return this.listeners.add(e), () => this.listeners.delete(e);
157
218
  }
219
+ onAction(e) {
220
+ return this.actionListeners.add(e), () => this.actionListeners.delete(e);
221
+ }
158
222
  setViewMode(e) {
159
223
  this.viewMode !== e && (this.viewMode = e, this.state = {
160
224
  ...this.state,
@@ -167,6 +231,15 @@ var f = {
167
231
  setAllowCameraControl(e) {
168
232
  this.config.allowCameraControl = e;
169
233
  }
234
+ setCollision(e) {
235
+ this.collision = {
236
+ ...this.collision,
237
+ ...e
238
+ };
239
+ }
240
+ getCollision() {
241
+ return this.collision;
242
+ }
170
243
  setHeading(e) {
171
244
  if (!this.view) return;
172
245
  let { lat: t, lng: n, alt: r } = this.state;
@@ -204,18 +277,34 @@ var f = {
204
277
  getFpvHeightOffset() {
205
278
  return this.config.fpvHeightOffset;
206
279
  }
280
+ setAnimationSpeed(e) {
281
+ this.character && (this.character.animation.speed = e), this.modelRef?.setAnimationSpeed(this.clipSpeed(this.currentAnimState));
282
+ }
283
+ getAnimationSpeed() {
284
+ return this.character?.animation.speed ?? 1;
285
+ }
286
+ get model() {
287
+ return this.handle;
288
+ }
289
+ clipSpeed(e) {
290
+ let t = this.character?.animation;
291
+ return t ? e === t.dashClip ? t.dashSpeed ?? t.speed ?? 1 : t.walkClip != null && e === t.walkClip ? t.walkSpeed ?? t.speed ?? 1 : t.idleSpeed ?? t.speed ?? 1 : 1;
292
+ }
207
293
  dispose() {
208
- this.animId != null && cancelAnimationFrame(this.animId), this.animId = null, document.removeEventListener("keydown", this.boundKeyDown), document.removeEventListener("keyup", this.boundKeyUp), this.handle &&= (this.handle.delete(), null), this.modelRef = null, this.heldActions.clear(), this.listeners.clear(), this.orbitKeyHeld = !1, this.orbitLatched = !1, this.dashMultiplier = 1, this.view = void 0;
294
+ this.releaseControl(), this.handle &&= (this.handle.delete(), null), this.modelRef = null, this.placed = !1, this.listeners.clear(), this.actionListeners.clear(), this.view = void 0;
295
+ }
296
+ playAnimation(e) {
297
+ !e || !this.character || !this.modelRef || e !== this.currentAnimState && (this.modelRef.crossFadeAnimation(this.currentAnimState ?? "", e, this.character.animation.crossfadeDuration), this.modelRef.setAnimationSpeed(this.clipSpeed(e)), this.currentAnimState = e);
209
298
  }
210
299
  resolveCharacter(e) {
211
300
  return {
212
301
  modelUrl: e.modelUrl,
213
302
  animation: e.animation,
214
303
  modelRotationOffset: e.modelRotationOffset ? {
215
- ...f,
304
+ ...p,
216
305
  ...e.modelRotationOffset
217
- } : f,
218
- modelScale: e.modelScale ?? h,
306
+ } : p,
307
+ modelScale: e.modelScale ?? S,
219
308
  hideModelInFpv: e.hideModelInFpv ?? !0,
220
309
  castShadow: e.castShadow ?? !1,
221
310
  receiveShadow: e.receiveShadow ?? !1
@@ -242,28 +331,119 @@ var f = {
242
331
  let { startLat: e, startLng: t, startHeight: n, startHeading: r } = this.config;
243
332
  this.placeChaseCamera(e, t, n, r);
244
333
  }
245
- placeChaseCamera(e, t, n, r) {
334
+ placeChaseCamera(e, t, n, r, i = 0) {
246
335
  if (!this.view) return;
247
- let { cameraDistance: i, cameraPitch: a, fpvPitch: o, fpvHeightOffset: s, fpvForwardOffset: c } = this.config, l = this.viewMode === "fpv", u = n + s;
248
- if (l) {
249
- let n = g, i = c + g, a = Math.tan(o) * n, s = this.advanceLatLng(e, t, r, i);
250
- this._offset.set(-Math.sin(r) * n, -Math.cos(r) * n, a), this.view.cameraFollow(!0, {
251
- lat: s.lat,
252
- lng: s.lng,
253
- height: u - a
336
+ let { cameraDistance: a, fpvPitch: o, fpvForwardOffset: s } = this.config, c = this.viewMode === "fpv", l = this.eyeHeightAt(n);
337
+ if (c) {
338
+ let a = C, c = s + C, u = this.followSlopeWithPitch(o, e, t, n, r, i), d = Math.tan(u) * a, f = this.advanceLatLng(e, t, r, c);
339
+ this._offset.set(-Math.sin(r) * a, -Math.cos(r) * a, d), this.view.cameraFollow(!0, {
340
+ lat: f.lat,
341
+ lng: f.lng,
342
+ height: l - d
254
343
  }, this._offset);
255
344
  return;
256
345
  }
257
- let d = i * Math.cos(a), f = i * Math.sin(a);
346
+ let u = this.followSlopeWithPitch(this.config.cameraPitch, e, t, n, r, i), d = a * Math.cos(u), f = a * Math.sin(u);
258
347
  this._offset.set(-Math.sin(r) * d, -Math.cos(r) * d, f), this.view.cameraFollow(!0, {
259
348
  lat: e,
260
349
  lng: t,
261
- height: u
350
+ height: l
262
351
  }, this._offset);
263
352
  }
353
+ followSlopeWithPitch(e, t, n, r, i, a) {
354
+ let { cameraDistance: o, cameraLerpSpeed: s } = this.config, { mode: c, cameraSlopeFollow: l } = this.collision, d = 0;
355
+ if (c !== "off" && l > 0) {
356
+ let e = this.terrainAlong(t, n, i, o), a = this.terrainAlong(t, n, i + Math.PI, o);
357
+ e !== void 0 && a !== void 0 && (d = u.clamp(Math.atan2(e - a, 2 * o) * l * this.groundedFactor(r, o), -v, v));
358
+ }
359
+ return this.cameraSlopePitch += (d - this.cameraSlopePitch) * b(s, a), e - this.cameraSlopePitch;
360
+ }
361
+ groundedFactor(e, t) {
362
+ let n = this.groundSurfaceHeight;
363
+ return n === void 0 ? 0 : u.clamp(1 - (e - n) / t, 0, 1);
364
+ }
365
+ terrainAlong(e, t, n, r) {
366
+ let i = this.advanceLatLng(e, t, n, r);
367
+ return this.sampleTerrain(a(i.lat), a(i.lng));
368
+ }
264
369
  composeCharacterFrame(e, t) {
265
370
  let n = o(e);
266
- return this._headingMatrix.makeRotationZ(-t), this._characterFrame.multiplyMatrices(n, this._headingMatrix);
371
+ this._headingMatrix.makeRotationZ(-t), this._characterFrame.multiplyMatrices(n, this._headingMatrix);
372
+ let r = this.slopeGradEast, i = this.slopeGradNorth;
373
+ if (r !== 0 || i !== 0) {
374
+ let e = Math.sin(t), n = Math.cos(t), a = this.collision.maxSlopeTilt, o = u.clamp(Math.atan(r * e + i * n), -a, a), s = u.clamp(-Math.atan(r * n - i * e), -a, a);
375
+ this._tiltMatrix.makeRotationX(o), this._characterFrame.multiply(this._tiltMatrix), this._tiltMatrix.makeRotationY(s), this._characterFrame.multiply(this._tiltMatrix);
376
+ }
377
+ return this._characterFrame;
378
+ }
379
+ eyeHeightAt(e) {
380
+ return e + this.config.fpvHeightOffset;
381
+ }
382
+ sampleTerrain(e, t) {
383
+ return this.view?.sampleTerrainHeight({
384
+ lat: e,
385
+ lng: t,
386
+ height: 0
387
+ });
388
+ }
389
+ resolveGroundHeight(e, t, n, r) {
390
+ let { mode: i, groundOffset: a } = this.collision;
391
+ if (i === "off") return this.forgetGroundSamples(), n;
392
+ let o = this.sampleTerrain(e.lat, e.lng);
393
+ if (o === void 0) return this.forgetGroundSamples(), n;
394
+ this.groundSurfaceHeight = o + a;
395
+ let s = this.groundSurfaceHeight - this.absorbGroundDataShift(e, t, o, n, r);
396
+ return i === "ground" ? s : Math.max(n, s);
397
+ }
398
+ absorbGroundDataShift(e, t, n, r, i) {
399
+ let a = this.lastGroundSample, o;
400
+ if (a === void 0) o = (this.sampleTerrain(t.lat, t.lng) ?? n) + this.collision.groundOffset - r;
401
+ else {
402
+ let e = this.sampleTerrain(a.lat, a.lng);
403
+ o = e === void 0 ? 0 : e - a.height;
404
+ }
405
+ let s = this.unabsorbedGroundShift + o, c = Math.sign(s);
406
+ i > 0 && (c !== Math.sign(this.settleVelocity) && (this.settleVelocity = 0), this.settleVelocity += c * g * i);
407
+ let l = i > 0 ? Math.abs(this.settleVelocity) * i : Math.abs(s);
408
+ return this.unabsorbedGroundShift = c * Math.max(0, Math.abs(s) - l), this.unabsorbedGroundShift === 0 && (this.settleVelocity = 0), this.lastGroundSample = {
409
+ lat: e.lat,
410
+ lng: e.lng,
411
+ height: n
412
+ }, this.unabsorbedGroundShift;
413
+ }
414
+ forgetGroundSamples() {
415
+ this.lastGroundSample = void 0, this.unabsorbedGroundShift = 0, this.settleVelocity = 0, this.groundSurfaceHeight = void 0;
416
+ }
417
+ updateSlopeTilt(e, t, n, r) {
418
+ let { mode: i, alignToSlope: a, slopeSampleDistance: o } = this.collision, s = 0, c = 0;
419
+ if (i !== "off" && a) {
420
+ let r = this.measureSlopeGradient(e, t);
421
+ if (!r) return;
422
+ let i = this.groundedFactor(n, o);
423
+ s = r.east * i, c = r.north * i;
424
+ } else if (this.slopeGradEast === 0 && this.slopeGradNorth === 0) return;
425
+ let l = b(_, r);
426
+ this.slopeGradEast += (s - this.slopeGradEast) * l, this.slopeGradNorth += (c - this.slopeGradNorth) * l;
427
+ }
428
+ measureSlopeGradient(e, t) {
429
+ let n = this.collision.slopeSampleDistance, r = s({
430
+ lat: e,
431
+ lng: t,
432
+ height: 0
433
+ }), i = o(r);
434
+ this._east.setFromMatrixColumn(i, 0).normalize(), this._north.setFromMatrixColumn(i, 1).normalize();
435
+ let a = 0, c = 0;
436
+ for (let { sin: e, cos: t } of y) {
437
+ this._probePos.copy(r).addScaledVector(this._east, e * n).addScaledVector(this._north, t * n);
438
+ let i = l(this._probePos), o = this.sampleTerrain(i.lat, i.lng);
439
+ if (o === void 0) return;
440
+ a += o * e, c += o * t;
441
+ }
442
+ let u = 2 / (y.length * n);
443
+ return {
444
+ east: a * u,
445
+ north: c * u
446
+ };
267
447
  }
268
448
  advanceLatLng(e, t, n, r) {
269
449
  let i = s({
@@ -281,12 +461,15 @@ var f = {
281
461
  notify() {
282
462
  for (let e of this.listeners) e(this.state);
283
463
  }
464
+ emitAction(e) {
465
+ for (let t of this.actionListeners) t(e);
466
+ }
284
467
  onKeyDown(e) {
285
468
  let t = e.target;
286
469
  if (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable) return;
287
470
  let n = this.keyToAction.get(e.code);
288
471
  if (n !== void 0) {
289
- if (n === "toggleView") {
472
+ if (e.repeat || this.emitAction(n), n === "toggleView") {
290
473
  if (e.repeat) return;
291
474
  this.toggleViewMode();
292
475
  return;
@@ -297,7 +480,7 @@ var f = {
297
480
  }
298
481
  if (!this.movementSuppressed) {
299
482
  if (n === "dash") {
300
- this.dashMultiplier = 2.5;
483
+ this.dashHeld = !0;
301
484
  return;
302
485
  }
303
486
  this.isMovementAction(n) && (this.orbitLatched = !1), this.heldActions.add(n);
@@ -312,73 +495,73 @@ var f = {
312
495
  return;
313
496
  }
314
497
  if (t === "dash") {
315
- this.dashMultiplier = 1;
498
+ this.dashHeld = !1;
316
499
  return;
317
500
  }
318
501
  this.heldActions.delete(t);
319
502
  }
320
503
  }
321
504
  tick = (e) => {
322
- if (!this.view) return;
505
+ if (!this.view || this.animId == null) return;
323
506
  this.animId = requestAnimationFrame(this.tick);
324
507
  let t = Math.min((e - this.lastTime) / 1e3, .1);
325
508
  this.lastTime = e;
326
509
  let n = 0, r = 0, i = 0;
327
510
  this.heldActions.has("forward") && (r += 1), this.heldActions.has("backward") && --r, this.heldActions.has("turnLeft") && --n, this.heldActions.has("turnRight") && (n += 1), this.heldActions.has("ascend") && (i += 1), this.heldActions.has("descend") && --i;
328
- let { moveSpeed: u, rotationSpeed: d, altSpeed: f, minAlt: p, maxAlt: m, cameraLerpSpeed: h } = this.config;
329
- n !== 0 && (this.modelHeading += a(d * n));
330
- let g = this._curPos;
511
+ let { moveSpeed: d, rotationSpeed: f, altSpeed: p, minAlt: m, maxAlt: h, cameraLerpSpeed: g } = this.config, _ = this.dashHeld ? this.config.dashSpeedMultiplier : 1;
512
+ n !== 0 && (this.modelHeading += a(f * n));
513
+ let v = this._curPos;
331
514
  if (this.handle && this.modelRef) {
332
515
  let e = this.modelRef.getWorldPosition();
333
516
  if (!e) return;
334
- g.copy(e);
335
- } else g.copy(s({
517
+ v.copy(e);
518
+ } else v.copy(s({
336
519
  lat: a(this.state.lat),
337
520
  lng: a(this.state.lng),
338
521
  height: this.state.alt
339
522
  }));
340
- let _ = o(g);
341
- this._east.setFromMatrixColumn(_, 0).normalize(), this._north.setFromMatrixColumn(_, 1).normalize();
342
- let v = l(g);
343
- this._worldForward.copy(this._east).multiplyScalar(Math.sin(this.modelHeading)).addScaledVector(this._north, Math.cos(this.modelHeading)), r !== 0 && g.addScaledVector(this._worldForward, u * this.dashMultiplier * t * r);
344
- let y = l(g), b = v.height + i * f * t, x = Math.max(p, Math.min(m, b)), S = c(y.lat), C = c(y.lng), w = x;
345
- if (this.handle && this.character) {
523
+ let y = o(v);
524
+ this._east.setFromMatrixColumn(y, 0).normalize(), this._north.setFromMatrixColumn(y, 1).normalize();
525
+ let x = l(v);
526
+ this._worldForward.copy(this._east).multiplyScalar(Math.sin(this.modelHeading)).addScaledVector(this._north, Math.cos(this.modelHeading)), r !== 0 && v.addScaledVector(this._worldForward, d * _ * t * r);
527
+ let S = l(v), C = this.collision.mode === "ground" ? x.height : u.clamp(x.height + i * p * t, m, h), w = this.resolveGroundHeight(S, x, C, t), T = c(S.lat), E = c(S.lng), D = w;
528
+ if (this.updateSlopeTilt(S.lat, S.lng, w, t), this.handle && this.character) {
346
529
  let e = s({
347
- lat: y.lat,
348
- lng: y.lng,
349
- height: x
530
+ lat: S.lat,
531
+ lng: S.lng,
532
+ height: w
350
533
  });
351
534
  this.handle.update({ matrixWorld: this.composeCharacterFrame(e, this.modelHeading) });
352
535
  }
353
- let T = this.modelHeading - this.cameraHeading;
354
- if (T -= Math.round(T / (Math.PI * 2)) * (Math.PI * 2), this.cameraHeading += T * Math.min(t * h, 1), this.isFreeCamera()) if (this.viewMode === "fpv") {
355
- let e = this.advanceLatLng(S, C, this.cameraHeading, this.config.fpvForwardOffset);
536
+ let O = this.modelHeading - this.cameraHeading;
537
+ if (O -= Math.round(O / (Math.PI * 2)) * (Math.PI * 2), this.cameraHeading += O * b(g, t), this.isFreeCamera()) if (this.viewMode === "fpv") {
538
+ let e = this.advanceLatLng(T, E, this.cameraHeading, this.config.fpvForwardOffset);
356
539
  this.view.cameraFreeLook(!0, {
357
540
  lat: e.lat,
358
541
  lng: e.lng,
359
- height: w + this.config.fpvHeightOffset
542
+ height: this.eyeHeightAt(D)
360
543
  });
361
544
  } else this.view.cameraFollow(!0, {
362
- lat: S,
363
- lng: C,
364
- height: w + this.config.fpvHeightOffset
545
+ lat: T,
546
+ lng: E,
547
+ height: this.eyeHeightAt(D)
365
548
  });
366
- else this.placeChaseCamera(S, C, w, this.cameraHeading);
367
- let E = r !== 0 || n !== 0 || i !== 0, D = E && this.dashMultiplier > 1, O = this.currentAnimState;
368
- if (this.character && this.modelRef) {
369
- let { animation: e } = this.character, t = e.walkClip ?? e.idleClip, n;
370
- n = D ? e.dashClip : E ? t : e.idleClip, n !== this.currentAnimState && (this.modelRef.crossFadeAnimation(this.currentAnimState ?? "", n, e.crossfadeDuration), this.currentAnimState = n), O = n;
549
+ else this.placeChaseCamera(T, E, D, this.cameraHeading, t);
550
+ let k = r !== 0 || n !== 0 || i !== 0, A = k && this.dashHeld, j = this.currentAnimState;
551
+ if (this.character) {
552
+ let { animation: e } = this.character, t = e.walkClip ?? e.idleClip;
553
+ j = A ? e.dashClip : k ? t : e.idleClip, this.playAnimation(j);
371
554
  }
372
- let k = {
373
- lng: C,
374
- lat: S,
375
- alt: w,
555
+ let M = {
556
+ lng: E,
557
+ lat: T,
558
+ alt: D,
376
559
  heading: this.modelHeading,
377
- speed: u * this.dashMultiplier,
378
- animationState: O,
560
+ speed: d * _,
561
+ animationState: j,
379
562
  mode: this.viewMode
380
563
  };
381
- this.hasStateChanged(this.state, k) && (this.state = k, this.notify());
564
+ this.hasStateChanged(this.state, M) && (this.state = M, this.notify());
382
565
  };
383
566
  hasStateChanged(e, t) {
384
567
  return e.lng !== t.lng || e.lat !== t.lat || e.alt !== t.alt || e.heading !== t.heading || e.speed !== t.speed || e.animationState !== t.animationState || e.mode !== t.mode;
@@ -386,10 +569,10 @@ var f = {
386
569
  };
387
570
  //#endregion
388
571
  //#region src/OverlayPlugin.ts
389
- function v(e, t, n) {
572
+ function T(e, t, n) {
390
573
  e.style.transform = `translate(${t}px, ${n}px)`, e.style.willChange = "transform";
391
574
  }
392
- var y = 1e5, b = class extends n {
575
+ var E = 1e5, D = class extends n {
393
576
  view;
394
577
  maxDistance;
395
578
  positions = [];
@@ -397,7 +580,7 @@ var y = 1e5, b = class extends n {
397
580
  listeners = /* @__PURE__ */ new Set();
398
581
  boundHandler;
399
582
  constructor(e) {
400
- super(), this.maxDistance = e?.maxDistance ?? y, this.boundHandler = this.handlePreRender.bind(this);
583
+ super(), this.maxDistance = e?.maxDistance ?? E, this.boundHandler = this.handlePreRender.bind(this);
401
584
  }
402
585
  async init(e, t) {
403
586
  this.view = e, e.on("preRender", this.boundHandler);
@@ -451,7 +634,7 @@ var y = 1e5, b = class extends n {
451
634
  let r = { projected: this.projected };
452
635
  for (let e of this.listeners) e(r);
453
636
  }
454
- }, x = "https://api.cesium.com/v1/assets", S = class extends n {
637
+ }, O = "https://api.cesium.com/v1/assets", k = class extends n {
455
638
  view;
456
639
  config;
457
640
  endpoint;
@@ -460,7 +643,7 @@ var y = 1e5, b = class extends n {
460
643
  }
461
644
  async init(e, t) {
462
645
  this.view = e;
463
- let { assetId: n, accessToken: r, endpoint: i = x } = this.config, a = `${i}/${encodeURIComponent(String(n))}/endpoint?access_token=${encodeURIComponent(r)}`, o = await fetch(a);
646
+ let { assetId: n, accessToken: r, endpoint: i = O } = this.config, a = `${i}/${encodeURIComponent(String(n))}/endpoint?access_token=${encodeURIComponent(r)}`, o = await fetch(a);
464
647
  if (!o.ok) throw Error(`CesiumIonPlugin: failed to fetch asset ${n} endpoint (${o.status} ${o.statusText})`);
465
648
  let s = await o.json();
466
649
  this.endpoint = {
@@ -489,19 +672,19 @@ var y = 1e5, b = class extends n {
489
672
  });
490
673
  return l.once("deleted", () => c.delete()), l;
491
674
  }
492
- }, C = /^3\.\d+\.\d+$/, w = 512, T = "mapbox";
493
- function E(e) {
494
- if (typeof e.tilejson != "string" || !C.test(e.tilejson)) throw Error(`TileJsonPlugin: invalid or missing "tilejson" version field (got ${JSON.stringify(e.tilejson)}).`);
675
+ }, A = /^3\.\d+\.\d+$/, j = 512, M = "mapbox";
676
+ function N(e) {
677
+ if (typeof e.tilejson != "string" || !A.test(e.tilejson)) throw Error(`TileJsonPlugin: invalid or missing "tilejson" version field (got ${JSON.stringify(e.tilejson)}).`);
495
678
  if (!Array.isArray(e.tiles) || e.tiles.length === 0) throw Error("TileJsonPlugin: \"tiles\" must be a non-empty array of URL templates.");
496
679
  }
497
- function D(e) {
680
+ function P(e) {
498
681
  switch (e) {
499
682
  case "mapbox": return t();
500
683
  case "terrarium": return r();
501
684
  default: throw Error(`TileJsonPlugin: unsupported raster-dem encoding ${JSON.stringify(e)}. Supported encodings: "mapbox", "terrarium".`);
502
685
  }
503
686
  }
504
- var O = class extends n {
687
+ var F = class extends n {
505
688
  view;
506
689
  events = new e();
507
690
  credits = [];
@@ -521,7 +704,7 @@ var O = class extends n {
521
704
  let t = this.view;
522
705
  if (!t) throw Error("TileJsonPlugin: addSource() must be called after view.init().");
523
706
  let n = await this.fetchTileJson(e.url);
524
- E(n);
707
+ N(n);
525
708
  let [r, ...i] = n.tiles;
526
709
  i.length > 0 && console.warn(`TileJsonPlugin: TileJSON at ${e.url} lists ${n.tiles.length} mirror tile endpoints; Navara sources use a single URL, so only the first is used.`);
527
710
  let a = e.minzoom ?? n.minzoom, o = e.maxzoom ?? n.maxzoom, s = e.scheme ?? n.scheme, c = e.id, l = {
@@ -539,8 +722,8 @@ var O = class extends n {
539
722
  }) : e.type === "raster-dem" ? t.addSource({
540
723
  type: "raster-dem",
541
724
  ...u,
542
- tileSize: e.tileSize ?? n.tileSize ?? w,
543
- elevationDecoder: D(e.encoding ?? n.encoding ?? T)
725
+ tileSize: e.tileSize ?? n.tileSize ?? j,
726
+ elevationDecoder: P(e.encoding ?? n.encoding ?? M)
544
727
  }) : t.addSource({
545
728
  type: "vector-tile",
546
729
  ...l
@@ -564,4 +747,4 @@ var O = class extends n {
564
747
  }
565
748
  };
566
749
  //#endregion
567
- export { S as CesiumIonPlugin, b as OverlayPlugin, _ as PersonViewPlugin, O as TileJsonPlugin, v as moveOverlayElement };
750
+ export { k as CesiumIonPlugin, D as OverlayPlugin, w as PersonViewPlugin, F as TileJsonPlugin, T as moveOverlayElement };