MikaFil commited on
Commit
8d41429
·
verified ·
1 Parent(s): 911707b

Update orbit-camera.js

Browse files
Files changed (1) hide show
  1. orbit-camera.js +6 -575
orbit-camera.js CHANGED
@@ -1,5 +1,6 @@
1
  // orbit-camera.js
2
  // ==============================
 
3
 
4
  /*
5
  * PlayCanvas Orbit Camera for GSplat/SOGS/GLB viewers.
@@ -60,11 +61,9 @@ OrbitCamera.prototype.resetAndLookAtPoint = function (resetPoint, lookAtPoint) {
60
  distance.sub2(lookAtPoint, resetPoint);
61
  this.distance = distance.length();
62
  this.pivotPoint.copy(lookAtPoint);
63
-
64
  var cameraQuat = this.entity.getRotation();
65
  this.yaw = this._calcYaw(cameraQuat);
66
  this.pitch = this._calcPitch(cameraQuat, this.yaw);
67
-
68
  this._removeInertia();
69
  this._updatePosition();
70
  };
@@ -85,15 +84,12 @@ OrbitCamera.prototype.resetToPosition = function (position, lookAtPoint) {
85
  this.entity.setPosition(position);
86
  this.entity.lookAt(lookAtPoint);
87
  this._pivotPoint.copy(lookAtPoint);
88
-
89
  var distanceVec = new pc.Vec3();
90
  distanceVec.sub2(position, lookAtPoint);
91
  this._targetDistance = this._distance = distanceVec.length();
92
-
93
  var cameraQuat = this.entity.getRotation();
94
  this._targetYaw = this._yaw = this._calcYaw(cameraQuat);
95
  this._targetPitch = this._pitch = this._calcPitch(cameraQuat, this._yaw);
96
-
97
  this._removeInertia();
98
  this._updatePosition();
99
  };
@@ -110,21 +106,19 @@ OrbitCamera.prototype.worldCameraYForPivot = function(pivot) {
110
 
111
  OrbitCamera.prototype.initialize = function () {
112
  var self = this;
113
-
114
  var onWindowResize = function () { self._checkAspectRatio(); };
115
  window.addEventListener('resize', onWindowResize, false);
116
  this._checkAspectRatio();
117
 
118
  this._modelsAabb = new pc.BoundingBox();
119
  this._buildAabb(this.focusEntity || this.app.root);
120
-
121
  this.entity.lookAt(this._modelsAabb.center);
122
 
123
  this._pivotPoint = new pc.Vec3();
124
  this._pivotPoint.copy(this._modelsAabb.center);
125
 
126
  var cameraQuat = this.entity.getRotation();
127
- this._yaw = this._calcYaw(cameraQuat); // degrees
128
  this._pitch = this._clampPitchAngle(this._calcPitch(cameraQuat, this._yaw));
129
  this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);
130
 
@@ -153,12 +147,10 @@ OrbitCamera.prototype.initialize = function () {
153
  if (value) { this.focus(this.focusEntity || this.app.root); }
154
  });
155
 
156
- this.on('destroy', function () {
157
- window.removeEventListener('resize', onWindowResize, false);
158
- });
159
 
160
- // --- Logs init ---
161
- console.log('[OrbitCam] init yaw=%s° pitch=%s° dist=%s', this._yaw.toFixed(2), this._pitch.toFixed(2), this._distance.toFixed(3));
162
  };
163
 
164
  OrbitCamera.prototype.update = function (dt) {
@@ -172,15 +164,11 @@ OrbitCamera.prototype.update = function (dt) {
172
  OrbitCamera.prototype._updatePosition = function () {
173
  this.entity.setLocalPosition(0, 0, 0);
174
  this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);
175
-
176
  var position = this.entity.getPosition();
177
  position.copy(this.entity.forward);
178
  position.mulScalar(-this._distance);
179
  position.add(this.pivotPoint);
180
-
181
- // Clamp camera's Y position so it never goes below minY
182
  position.y = Math.max(position.y, this.minY);
183
-
184
  this.entity.setPosition(position);
185
  };
186
 
@@ -197,561 +185,4 @@ OrbitCamera.prototype._checkAspectRatio = function () {
197
  };
198
 
199
  OrbitCamera.prototype._buildAabb = function (entity) {
200
- var i, m, meshInstances = [];
201
-
202
- var renders = entity.findComponents('render');
203
- for (i = 0; i < renders.length; i++) {
204
- var render = renders[i];
205
- for (m = 0; m < render.meshInstances.length; m++) {
206
- meshInstances.push(render.meshInstances[m]);
207
- }
208
- }
209
-
210
- var models = entity.findComponents('model');
211
- for (i = 0; i < models.length; i++) {
212
- var model = models[i];
213
- for (m = 0; m < model.meshInstances.length; m++) {
214
- meshInstances.push(model.meshInstances[m]);
215
- }
216
- }
217
-
218
- var gsplats = entity.findComponents('gsplat');
219
- for (i = 0; i < gsplats.length; i++) {
220
- var gsplat = gsplats[i];
221
- var instance = gsplat.instance;
222
- if (instance && instance.meshInstance) {
223
- meshInstances.push(instance.meshInstance);
224
- }
225
- }
226
-
227
- for (i = 0; i < meshInstances.length; i++) {
228
- if (i === 0) {
229
- this._modelsAabb.copy(meshInstances[i].aabb);
230
- } else {
231
- this._modelsAabb.add(meshInstances[i].aabb);
232
- }
233
- }
234
- };
235
-
236
- OrbitCamera.prototype._calcYaw = function (quat) {
237
- // CORRECTION: renvoyer des DEGRÉS (pas des radians)
238
- var f = new pc.Vec3();
239
- quat.transformVector(pc.Vec3.FORWARD, f);
240
- return Math.atan2(-f.x, -f.z) * pc.math.RAD_TO_DEG;
241
- };
242
-
243
- OrbitCamera.prototype._clampDistance = function (distance) {
244
- if (this.distanceMax > 0) {
245
- return pc.math.clamp(distance, this.distanceMin, this.distanceMax);
246
- }
247
- return Math.max(distance, this.distanceMin);
248
- };
249
-
250
- OrbitCamera.prototype._clampPitchAngle = function (pitch) {
251
- return pc.math.clamp(pitch, this.pitchAngleMin, this.pitchAngleMax);
252
- };
253
-
254
- OrbitCamera.prototype._clampYawAngle = function (yaw) {
255
- return pc.math.clamp(yaw, this.yawAngleMin, this.yawAngleMax);
256
- };
257
-
258
- OrbitCamera.quatWithoutYaw = new pc.Quat();
259
- OrbitCamera.yawOffset = new pc.Quat();
260
-
261
- OrbitCamera.prototype._calcPitch = function (quat, yaw) {
262
- var quatWithoutYaw = OrbitCamera.quatWithoutYaw;
263
- var yawOffset = OrbitCamera.yawOffset;
264
-
265
- yawOffset.setFromEulerAngles(0, -yaw, 0);
266
- quatWithoutYaw.mul2(yawOffset, quat);
267
-
268
- var transformedForward = new pc.Vec3();
269
- quatWithoutYaw.transformVector(pc.Vec3.FORWARD, transformedForward);
270
-
271
- return Math.atan2(-transformedForward.y, -transformedForward.z) * pc.math.RAD_TO_DEG;
272
- };
273
-
274
- // =================== Orbit Camera Input Mouse Script ========================
275
-
276
- var OrbitCameraInputMouse = pc.createScript('orbitCameraInputMouse');
277
- OrbitCameraInputMouse.attributes.add('orbitSensitivity', { type: 'number', default: 0.3, title: 'Orbit Sensitivity' });
278
- OrbitCameraInputMouse.attributes.add('distanceSensitivity',{ type: 'number', default: 0.4, title: 'Distance Sensitivity' });
279
-
280
- OrbitCameraInputMouse.prototype.initialize = function () {
281
- this.orbitCamera = this.entity.script.orbitCamera;
282
-
283
- if (this.orbitCamera) {
284
- var self = this;
285
- var onMouseOut = function (e) { self.onMouseOut(e); };
286
-
287
- this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
288
- this.app.mouse.on(pc.EVENT_MOUSEUP, this.onMouseUp, this);
289
- this.app.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
290
- this.app.mouse.on(pc.EVENT_MOUSEWHEEL, this.onMouseWheel, this);
291
-
292
- window.addEventListener('mouseout', onMouseOut, false);
293
-
294
- this.on('destroy', function () {
295
- this.app.mouse.off(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
296
- this.app.mouse.off(pc.EVENT_MOUSEUP, this.onMouseUp, this);
297
- this.app.mouse.off(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
298
- this.app.mouse.off(pc.EVENT_MOUSEWHEEL, this.onMouseWheel, this);
299
- window.removeEventListener('mouseout', onMouseOut, false);
300
- });
301
- }
302
-
303
- this.app.mouse.disableContextMenu();
304
-
305
- this.lookButtonDown = false;
306
- this.panButtonDown = false;
307
-
308
- this.lastPoint = new pc.Vec2();
309
- };
310
- OrbitCameraInputMouse.fromWorldPoint = new pc.Vec3();
311
- OrbitCameraInputMouse.toWorldPoint = new pc.Vec3();
312
- OrbitCameraInputMouse.worldDiff = new pc.Vec3();
313
-
314
- OrbitCameraInputMouse.prototype.pan = function (screenPoint) {
315
- var fromWorldPoint = OrbitCameraInputMouse.fromWorldPoint;
316
- var toWorldPoint = OrbitCameraInputMouse.toWorldPoint;
317
- var worldDiff = OrbitCameraInputMouse.worldDiff;
318
-
319
- var camera = this.entity.camera;
320
- var distance = this.orbitCamera.distance;
321
-
322
- camera.screenToWorld(screenPoint.x, screenPoint.y, distance, fromWorldPoint);
323
- camera.screenToWorld(this.lastPoint.x, this.lastPoint.y, distance, toWorldPoint);
324
-
325
- worldDiff.sub2(toWorldPoint, fromWorldPoint);
326
-
327
- // Clamp so camera never goes below minY
328
- var proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
329
- var minY = this.orbitCamera.minY;
330
- var resultingY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
331
-
332
- if (resultingY >= minY - 1e-4) {
333
- this.orbitCamera.pivotPoint.add(worldDiff);
334
- } else {
335
- // Only allow horizontal pan if it would help
336
- worldDiff.y = 0;
337
- proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
338
- resultingY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
339
- if (resultingY >= minY - 1e-4) {
340
- this.orbitCamera.pivotPoint.add(worldDiff);
341
- }
342
- // Otherwise, suppress pan
343
- }
344
- };
345
-
346
- OrbitCameraInputMouse.prototype.onMouseDown = function (event) {
347
- switch (event.button) {
348
- case pc.MOUSEBUTTON_LEFT: this.panButtonDown = true; break;
349
- case pc.MOUSEBUTTON_MIDDLE:
350
- case pc.MOUSEBUTTON_RIGHT: this.lookButtonDown = true; break;
351
- }
352
- };
353
- OrbitCameraInputMouse.prototype.onMouseUp = function (event) {
354
- switch (event.button) {
355
- case pc.MOUSEBUTTON_LEFT: this.panButtonDown = false; break;
356
- case pc.MOUSEBUTTON_MIDDLE:
357
- case pc.MOUSEBUTTON_RIGHT: this.lookButtonDown = false; break;
358
- }
359
- };
360
- OrbitCameraInputMouse.prototype.onMouseMove = function (event) {
361
- if (this.lookButtonDown) {
362
- var sens = this.orbitSensitivity;
363
- var deltaPitch = event.dy * sens;
364
- var deltaYaw = event.dx * sens;
365
-
366
- var currPitch = this.orbitCamera.pitch;
367
- var currYaw = this.orbitCamera.yaw;
368
- var currDist = this.orbitCamera.distance;
369
- var currPivot = this.orbitCamera.pivotPoint.clone();
370
-
371
- var camQuat = new pc.Quat();
372
- camQuat.setFromEulerAngles(currPitch, currYaw, 0);
373
- var forward = new pc.Vec3();
374
- camQuat.transformVector(pc.Vec3.FORWARD, forward);
375
- var preY = currPivot.y + (-forward.y) * currDist;
376
-
377
- var proposedPitch = currPitch - deltaPitch;
378
- var testQuat = new pc.Quat();
379
- testQuat.setFromEulerAngles(proposedPitch, currYaw, 0);
380
- var testForward = new pc.Vec3();
381
- testQuat.transformVector(pc.Vec3.FORWARD, testForward);
382
- var proposedY = currPivot.y + (-testForward.y) * currDist;
383
-
384
- var minY = this.orbitCamera.minY;
385
- var wouldGoBelow = proposedY < minY - 1e-4;
386
-
387
- if (wouldGoBelow && (proposedY < preY)) {
388
- this.orbitCamera.yaw = currYaw - deltaYaw;
389
- } else {
390
- this.orbitCamera.pitch = proposedPitch;
391
- this.orbitCamera.yaw = currYaw - deltaYaw;
392
- }
393
- } else if (this.panButtonDown) {
394
- this.pan(new pc.Vec2(event.x, event.y));
395
- }
396
-
397
- this.lastPoint.set(event.x, event.y);
398
- };
399
-
400
- OrbitCameraInputMouse.prototype.onMouseWheel = function (event) {
401
- if (this.entity.camera.projection === pc.PROJECTION_PERSPECTIVE) {
402
- this.orbitCamera.distance -= event.wheelDelta * this.distanceSensitivity * (this.orbitCamera.distance * 0.1);
403
- } else {
404
- this.orbitCamera.orthoHeight -= event.wheelDelta * this.distanceSensitivity * (this.orbitCamera.orthoHeight * 0.1);
405
- }
406
- event.event.preventDefault();
407
- };
408
- OrbitCameraInputMouse.prototype.onMouseOut = function () {
409
- this.lookButtonDown = false;
410
- this.panButtonDown = false;
411
- };
412
-
413
- // =================== Orbit Camera Input Touch Script ========================
414
- var OrbitCameraInputTouch = pc.createScript('orbitCameraInputTouch');
415
- OrbitCameraInputTouch.attributes.add('orbitSensitivity', { type: 'number', default: 0.6, title: 'Orbit Sensitivity' });
416
- OrbitCameraInputTouch.attributes.add('distanceSensitivity', { type: 'number', default: 0.5, title: 'Distance Sensitivity' });
417
-
418
- OrbitCameraInputTouch.prototype.initialize = function () {
419
- this.orbitCamera = this.entity.script.orbitCamera;
420
-
421
- this.lastTouchPoint = new pc.Vec2();
422
- this.lastPinchMidPoint = new pc.Vec2();
423
- this.lastPinchDistance = 0;
424
-
425
- if (this.orbitCamera && this.app.touch) {
426
- this.app.touch.on(pc.EVENT_TOUCHSTART, this.onTouchStartEndCancel, this);
427
- this.app.touch.on(pc.EVENT_TOUCHEND, this.onTouchStartEndCancel, this);
428
- this.app.touch.on(pc.EVENT_TOUCHCANCEL, this.onTouchStartEndCancel, this);
429
- this.app.touch.on(pc.EVENT_TOUCHMOVE, this.onTouchMove, this);
430
-
431
- this.on('destroy', function () {
432
- this.app.touch.off(pc.EVENT_TOUCHSTART, this.onTouchStartEndCancel, this);
433
- this.app.touch.off(pc.EVENT_TOUCHEND, this.onTouchStartEndCancel, this);
434
- this.app.touch.off(pc.EVENT_TOUCHCANCEL, this.onTouchStartEndCancel, this);
435
- this.app.touch.off(pc.EVENT_TOUCHMOVE, this.onTouchMove, this);
436
- });
437
- }
438
- };
439
- OrbitCameraInputTouch.prototype.getPinchDistance = function (pointA, pointB) {
440
- var dx = pointA.x - pointB.x;
441
- var dy = pointA.y - pointB.y;
442
- return Math.sqrt((dx * dx) + (dy * dy));
443
- };
444
- OrbitCameraInputTouch.prototype.calcMidPoint = function (pointA, pointB, result) {
445
- result.set(pointB.x - pointA.x, pointB.y - pointA.y);
446
- result.mulScalar(0.5);
447
- result.x += pointA.x;
448
- result.y += pointA.y;
449
- };
450
- OrbitCameraInputTouch.prototype.onTouchStartEndCancel = function (event) {
451
- var touches = event.touches;
452
- if (touches.length === 1) {
453
- this.lastTouchPoint.set(touches[0].x, touches[0].y);
454
- } else if (touches.length === 2) {
455
- this.lastPinchDistance = this.getPinchDistance(touches[0], touches[1]);
456
- this.calcMidPoint(touches[0], touches[1], this.lastPinchMidPoint);
457
- }
458
- };
459
- OrbitCameraInputTouch.fromWorldPoint = new pc.Vec3();
460
- OrbitCameraInputTouch.toWorldPoint = new pc.Vec3();
461
- OrbitCameraInputTouch.worldDiff = new pc.Vec3();
462
-
463
- OrbitCameraInputTouch.prototype.pan = function (midPoint) {
464
- var fromWorldPoint = OrbitCameraInputTouch.fromWorldPoint;
465
- var toWorldPoint = OrbitCameraInputTouch.toWorldPoint;
466
- var worldDiff = OrbitCameraInputTouch.worldDiff;
467
-
468
- var camera = this.entity.camera;
469
- var distance = this.orbitCamera.distance;
470
-
471
- camera.screenToWorld(midPoint.x, midPoint.y, distance, fromWorldPoint);
472
- camera.screenToWorld(this.lastPinchMidPoint.x, this.lastPinchMidPoint.y, distance, toWorldPoint);
473
-
474
- worldDiff.sub2(toWorldPoint, fromWorldPoint);
475
-
476
- var proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
477
- var minY = this.orbitCamera.minY;
478
- var resultingY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
479
-
480
- if (resultingY >= minY - 1e-4) {
481
- this.orbitCamera.pivotPoint.add(worldDiff);
482
- } else {
483
- worldDiff.y = 0;
484
- proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
485
- resultingY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
486
- if (resultingY >= minY - 1e-4) {
487
- this.orbitCamera.pivotPoint.add(worldDiff);
488
- }
489
- }
490
- };
491
-
492
- OrbitCameraInputTouch.pinchMidPoint = new pc.Vec2();
493
-
494
- OrbitCameraInputTouch.prototype.onTouchMove = function (event) {
495
- var pinchMidPoint = OrbitCameraInputTouch.pinchMidPoint;
496
- var touches = event.touches;
497
-
498
- if (touches.length === 1) {
499
- var touch = touches[0];
500
-
501
- var sens = this.orbitSensitivity;
502
- var deltaPitch = (touch.y - this.lastTouchPoint.y) * sens;
503
- var deltaYaw = (touch.x - this.lastTouchPoint.x) * sens;
504
-
505
- var currPitch = this.orbitCamera.pitch;
506
- var currYaw = this.orbitCamera.yaw;
507
- var currDist = this.orbitCamera.distance;
508
- var currPivot = this.orbitCamera.pivotPoint.clone();
509
-
510
- var camQuat = new pc.Quat();
511
- camQuat.setFromEulerAngles(currPitch, currYaw, 0);
512
- var forward = new pc.Vec3();
513
- camQuat.transformVector(pc.Vec3.FORWARD, forward);
514
- var preY = currPivot.y + (-forward.y) * currDist;
515
-
516
- var proposedPitch = currPitch - deltaPitch;
517
- var testQuat = new pc.Quat();
518
- testQuat.setFromEulerAngles(proposedPitch, currYaw, 0);
519
- var testForward = new pc.Vec3();
520
- testQuat.transformVector(pc.Vec3.FORWARD, testForward);
521
- var proposedY = currPivot.y + (-testForward.y) * currDist;
522
-
523
- var minY = this.orbitCamera.minY;
524
- var wouldGoBelow = proposedY < minY - 1e-4;
525
-
526
- if (wouldGoBelow && (proposedY < preY)) {
527
- this.orbitCamera.yaw = currYaw - deltaYaw;
528
- } else {
529
- this.orbitCamera.pitch = proposedPitch;
530
- this.orbitCamera.yaw = currYaw - deltaYaw;
531
- }
532
-
533
- this.lastTouchPoint.set(touch.x, touch.y);
534
- } else if (touches.length === 2) {
535
- var currentPinchDistance = this.getPinchDistance(touches[0], touches[1]);
536
- var diffInPinchDistance = currentPinchDistance - this.lastPinchDistance;
537
- this.lastPinchDistance = currentPinchDistance;
538
-
539
- this.orbitCamera.distance -= (diffInPinchDistance * this.distanceSensitivity * 0.1) * (this.orbitCamera.distance * 0.1);
540
-
541
- this.calcMidPoint(touches[0], touches[1], pinchMidPoint);
542
- this.pan(pinchMidPoint);
543
- this.lastPinchMidPoint.copy(pinchMidPoint);
544
- }
545
- };
546
-
547
- // =================== Orbit Camera Input Keyboard Script ========================
548
- var OrbitCameraInputKeyboard = pc.createScript('orbitCameraInputKeyboard');
549
-
550
- /**
551
- * Réglages clavier :
552
- * - orbitDegreesPerSecond : vitesse d’orbite (deg/s) pour yaw/pitch
553
- * - zoomFactorPerSecond : facteur de zoom (proportionnel à la distance) par seconde
554
- * - panUnitsPerSecond : vitesse de pan (en unités monde = distance * facteur) par seconde
555
- * - debugLogs : activer les console.log de diagnostic
556
- */
557
- OrbitCameraInputKeyboard.attributes.add('orbitDegreesPerSecond', { type: 'number', default: 180, title: 'Orbit Degrees / s' });
558
- OrbitCameraInputKeyboard.attributes.add('zoomFactorPerSecond', { type: 'number', default: 2.0, title: 'Zoom Factor / s' });
559
- OrbitCameraInputKeyboard.attributes.add('panUnitsPerSecond', { type: 'number', default: 1.0, title: 'Pan (distance frac) / s' });
560
- OrbitCameraInputKeyboard.attributes.add('debugLogs', { type: 'boolean', default: true, title: 'Enable Debug Logs' });
561
-
562
- OrbitCameraInputKeyboard.prototype._log = function () {
563
- if (!this.debugLogs) return;
564
- // eslint-disable-next-line no-console
565
- console.log.apply(console, arguments);
566
- };
567
-
568
- OrbitCameraInputKeyboard.prototype.initialize = function () {
569
- this.orbitCamera = this.entity.script.orbitCamera;
570
-
571
- // S’assure que le clavier est bien initialisé
572
- if (!this.app.keyboard) {
573
- this.app.keyboard = new pc.Keyboard(window);
574
- this._log('[OrbitKB] app.keyboard was null -> created new pc.Keyboard(window)');
575
- } else {
576
- this._log('[OrbitKB] app.keyboard OK (already present)');
577
- }
578
-
579
- // Empêche le scroll de la page avec les flèches quand la scène a le focus
580
- var self = this;
581
- this._preventDefault = function (e) {
582
- var tag = (e.target && e.target.tagName) ? e.target.tagName.toUpperCase() : '';
583
- if (tag === 'INPUT' || tag === 'TEXTAREA' || e.isContentEditable) return;
584
- var key = e.key || '';
585
- if (key === 'ArrowUp' || key === 'ArrowDown' || key === 'ArrowLeft' || key === 'ArrowRight') {
586
- e.preventDefault();
587
- if (self.debugLogs) console.log('[OrbitKB] preventDefault on', key);
588
- }
589
- };
590
- window.addEventListener('keydown', this._preventDefault, { passive: false });
591
-
592
- // Petits logs sur keydown/keyup pour vérifier la réception des flèches
593
- this._onKeyDown = function (e) {
594
- if (!self.debugLogs) return;
595
- console.log('[OrbitKB] keydown', e.key, 'code=', e.keyCode);
596
- };
597
- this._onKeyUp = function (e) {
598
- if (!self.debugLogs) return;
599
- console.log('[OrbitKB] keyup ', e.key, 'code=', e.keyCode);
600
- };
601
- window.addEventListener('keydown', this._onKeyDown);
602
- window.addEventListener('keyup', this._onKeyUp);
603
-
604
- this.on('destroy', function () {
605
- window.removeEventListener('keydown', self._preventDefault, { passive: false });
606
- window.removeEventListener('keydown', self._onKeyDown);
607
- window.removeEventListener('keyup', self._onKeyUp);
608
- });
609
-
610
- this._log('[OrbitKB] init done. Camera start yaw=%s pitch=%s dist=%s',
611
- this.orbitCamera ? this.orbitCamera.yaw : 'n/a',
612
- this.orbitCamera ? this.orbitCamera.pitch : 'n/a',
613
- this.orbitCamera ? this.orbitCamera.distance : 'n/a'
614
- );
615
- };
616
-
617
- // Teste si un pitch proposé ferait passer la caméra sous minY (même logique que la souris)
618
- OrbitCameraInputKeyboard.prototype._wouldGoBelowMinYWithPitch = function (proposedPitch) {
619
- var cam = this.orbitCamera;
620
-
621
- var currPitch = cam.pitch;
622
- var currYaw = cam.yaw;
623
- var currDist = cam.distance;
624
- var pivot = cam.pivotPoint.clone();
625
-
626
- var camQuat = new pc.Quat();
627
- camQuat.setFromEulerAngles(currPitch, currYaw, 0);
628
- var forward = new pc.Vec3();
629
- camQuat.transformVector(pc.Vec3.FORWARD, forward);
630
- var preY = pivot.y + (-forward.y) * currDist;
631
-
632
- var testQuat = new pc.Quat();
633
- testQuat.setFromEulerAngles(proposedPitch, currYaw, 0);
634
- var testForward = new pc.Vec3();
635
- testQuat.transformVector(pc.Vec3.FORWARD, testForward);
636
- var proposedY = pivot.y + (-testForward.y) * currDist;
637
-
638
- var minY = cam.minY;
639
- return { wouldGoBelow: proposedY < minY - 1e-4, preY: preY, proposedY: proposedY };
640
- };
641
-
642
- // Pan latéral (⇧ + ←/→) avec respect de minY
643
- OrbitCameraInputKeyboard.prototype._panSideways = function (delta) {
644
- var cam = this.orbitCamera;
645
-
646
- var quat = new pc.Quat();
647
- quat.setFromEulerAngles(cam.pitch, cam.yaw, 0);
648
-
649
- var right = new pc.Vec3();
650
- quat.transformVector(pc.Vec3.RIGHT, right);
651
-
652
- var worldDiff = right.scale(delta);
653
-
654
- var minY = cam.minY;
655
- var proposedPivot = cam.pivotPoint.clone().add(worldDiff);
656
- var resultingY = cam.worldCameraYForPivot(proposedPivot);
657
-
658
- if (resultingY >= minY - 1e-4) {
659
- cam.pivotPoint.add(worldDiff);
660
- this._log('[OrbitKB] panSideways OK delta=%s -> pivot=(%s,%s,%s)',
661
- delta.toFixed(3),
662
- cam.pivotPoint.x.toFixed(3),
663
- cam.pivotPoint.y.toFixed(3),
664
- cam.pivotPoint.z.toFixed(3)
665
- );
666
- } else {
667
- worldDiff.y = 0;
668
- proposedPivot = cam.pivotPoint.clone().add(worldDiff);
669
- resultingY = cam.worldCameraYForPivot(proposedPivot);
670
- if (resultingY >= minY - 1e-4) {
671
- cam.pivotPoint.add(worldDiff);
672
- this._log('[OrbitKB] panSideways horizontal-only delta=%s -> pivot=(%s,%s,%s)',
673
- delta.toFixed(3),
674
- cam.pivotPoint.x.toFixed(3),
675
- cam.pivotPoint.y.toFixed(3),
676
- cam.pivotPoint.z.toFixed(3)
677
- );
678
- } else {
679
- this._log('[OrbitKB] panSideways blocked by minY (delta=%s)', delta.toFixed(3));
680
- }
681
- }
682
- };
683
-
684
- OrbitCameraInputKeyboard.prototype.update = function (dt) {
685
- if (!this.orbitCamera || !this.app.keyboard) return;
686
-
687
- var kb = this.app.keyboard;
688
- var shift = kb.isPressed(pc.KEY_SHIFT);
689
- var cam = this.orbitCamera;
690
-
691
- // log des états de touches quand quelque chose d'intéressant est enfoncé
692
- if (this.debugLogs && (kb.isPressed(pc.KEY_UP) || kb.isPressed(pc.KEY_DOWN) || kb.isPressed(pc.KEY_LEFT) || kb.isPressed(pc.KEY_RIGHT))) {
693
- console.log('[OrbitKB] pressed states: shift=%s up=%s down=%s left=%s right=%s',
694
- !!shift, !!kb.isPressed(pc.KEY_UP), !!kb.isPressed(pc.KEY_DOWN), !!kb.isPressed(pc.KEY_LEFT), !!kb.isPressed(pc.KEY_RIGHT));
695
- }
696
-
697
- // --------- Avec SHIFT : zoom & pan latéral ----------
698
- if (shift) {
699
- // Zoom (⇧+↑ / ⇧+↓) — proportionnel à la distance / orthoHeight
700
- if (kb.isPressed(pc.KEY_UP) || kb.isPressed(pc.KEY_DOWN)) {
701
- var k = this.zoomFactorPerSecond;
702
-
703
- if (this.entity.camera.projection === pc.PROJECTION_PERSPECTIVE) {
704
- var dz = k * dt * (cam.distance * 0.8);
705
- var before = cam.distance;
706
- if (kb.isPressed(pc.KEY_UP)) cam.distance = cam.distance - dz;
707
- if (kb.isPressed(pc.KEY_DOWN)) cam.distance = cam.distance + dz;
708
- this._log('[OrbitKB] SHIFT Zoom persp d:%s -> %s (dz=%s)',
709
- before.toFixed(3), cam.distance.toFixed(3), dz.toFixed(3));
710
- } else {
711
- var dh = k * dt * (this.entity.camera.orthoHeight * 0.8);
712
- var beforeH = this.entity.camera.orthoHeight;
713
- if (kb.isPressed(pc.KEY_UP)) this.entity.camera.orthoHeight -= dh;
714
- if (kb.isPressed(pc.KEY_DOWN)) this.entity.camera.orthoHeight += dh;
715
- this._log('[OrbitKB] SHIFT Zoom ortho h:%s -> %s (dh=%s)',
716
- beforeH.toFixed(3), this.entity.camera.orthoHeight.toFixed(3), dh.toFixed(3));
717
- }
718
- }
719
-
720
- // Pan latéral (⇧+← / ⇧+→)
721
- if (kb.isPressed(pc.KEY_LEFT) || kb.isPressed(pc.KEY_RIGHT)) {
722
- var speed = this.panUnitsPerSecond * cam.distance; // unités/s
723
- var delta = speed * dt * (kb.isPressed(pc.KEY_LEFT) ? -1 : 1);
724
- this._log('[OrbitKB] SHIFT Pan request delta=%s (speed=%s, dist=%s)',
725
- delta.toFixed(3), speed.toFixed(3), cam.distance.toFixed(3));
726
- this._panSideways(delta);
727
- }
728
-
729
- return; // pas d’orbite quand SHIFT est enfoncé
730
- }
731
-
732
- // --------- Sans SHIFT : orbite yaw/pitch ----------
733
- var orbitRate = this.orbitDegreesPerSecond * dt;
734
-
735
- // Pitch (↑/↓) — protège minY exactement comme la souris
736
- if (kb.isPressed(pc.KEY_UP) || kb.isPressed(pc.KEY_DOWN)) {
737
- var dir = kb.isPressed(pc.KEY_UP) ? -1 : 1; // ↑ = réduire le pitch (orbiter vers le nord)
738
- var beforePitch = cam.pitch;
739
- var proposedPitch = beforePitch + dir * orbitRate;
740
-
741
- var test = this._wouldGoBelowMinYWithPitch(proposedPitch);
742
- if (!(test.wouldGoBelow && (test.proposedY < test.preY))) {
743
- cam.pitch = proposedPitch;
744
- this._log('[OrbitKB] Orbit PITCH %s -> %s (rate=%s)', beforePitch.toFixed(3), cam.pitch.toFixed(3), orbitRate.toFixed(3));
745
- } else {
746
- this._log('[OrbitKB] Orbit PITCH blocked by minY (before=%s proposed=%s)', beforePitch.toFixed(3), proposedPitch.toFixed(3));
747
- }
748
- }
749
-
750
- // Yaw (←/→) — orbite horizontale
751
- if (kb.isPressed(pc.KEY_LEFT) || kb.isPressed(pc.KEY_RIGHT)) {
752
- var beforeYaw = cam.yaw;
753
- if (kb.isPressed(pc.KEY_LEFT)) cam.yaw = cam.yaw + orbitRate; // vers la gauche
754
- if (kb.isPressed(pc.KEY_RIGHT)) cam.yaw = cam.yaw - orbitRate; // vers la droite
755
- this._log('[OrbitKB] Orbit YAW %s -> %s (rate=%s)', beforeYaw.toFixed(3), cam.yaw.toFixed(3), orbitRate.toFixed(3));
756
- }
757
- };
 
1
  // orbit-camera.js
2
  // ==============================
3
+ console.log('[OrbitFILE] loaded orbit-camera.js'); // preuve que le fichier est bien chargé
4
 
5
  /*
6
  * PlayCanvas Orbit Camera for GSplat/SOGS/GLB viewers.
 
61
  distance.sub2(lookAtPoint, resetPoint);
62
  this.distance = distance.length();
63
  this.pivotPoint.copy(lookAtPoint);
 
64
  var cameraQuat = this.entity.getRotation();
65
  this.yaw = this._calcYaw(cameraQuat);
66
  this.pitch = this._calcPitch(cameraQuat, this.yaw);
 
67
  this._removeInertia();
68
  this._updatePosition();
69
  };
 
84
  this.entity.setPosition(position);
85
  this.entity.lookAt(lookAtPoint);
86
  this._pivotPoint.copy(lookAtPoint);
 
87
  var distanceVec = new pc.Vec3();
88
  distanceVec.sub2(position, lookAtPoint);
89
  this._targetDistance = this._distance = distanceVec.length();
 
90
  var cameraQuat = this.entity.getRotation();
91
  this._targetYaw = this._yaw = this._calcYaw(cameraQuat);
92
  this._targetPitch = this._pitch = this._calcPitch(cameraQuat, this._yaw);
 
93
  this._removeInertia();
94
  this._updatePosition();
95
  };
 
106
 
107
  OrbitCamera.prototype.initialize = function () {
108
  var self = this;
 
109
  var onWindowResize = function () { self._checkAspectRatio(); };
110
  window.addEventListener('resize', onWindowResize, false);
111
  this._checkAspectRatio();
112
 
113
  this._modelsAabb = new pc.BoundingBox();
114
  this._buildAabb(this.focusEntity || this.app.root);
 
115
  this.entity.lookAt(this._modelsAabb.center);
116
 
117
  this._pivotPoint = new pc.Vec3();
118
  this._pivotPoint.copy(this._modelsAabb.center);
119
 
120
  var cameraQuat = this.entity.getRotation();
121
+ this._yaw = this._calcYaw(cameraQuat); // DEGRÉS
122
  this._pitch = this._clampPitchAngle(this._calcPitch(cameraQuat, this._yaw));
123
  this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);
124
 
 
147
  if (value) { this.focus(this.focusEntity || this.app.root); }
148
  });
149
 
150
+ this.on('destroy', function () { window.removeEventListener('resize', onWindowResize, false); });
 
 
151
 
152
+ console.log('[OrbitCam] init yaw=%s° pitch=%s° dist=%s',
153
+ this._yaw.toFixed(2), this._pitch.toFixed(2), this._distance.toFixed(3));
154
  };
155
 
156
  OrbitCamera.prototype.update = function (dt) {
 
164
  OrbitCamera.prototype._updatePosition = function () {
165
  this.entity.setLocalPosition(0, 0, 0);
166
  this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);
 
167
  var position = this.entity.getPosition();
168
  position.copy(this.entity.forward);
169
  position.mulScalar(-this._distance);
170
  position.add(this.pivotPoint);
 
 
171
  position.y = Math.max(position.y, this.minY);
 
172
  this.entity.setPosition(position);
173
  };
174
 
 
185
  };
186
 
187
  OrbitCamera.prototype._buildAabb = function (entity) {
188
+ var i, m, mes