MikaFil commited on
Commit
8a56f2f
·
verified ·
1 Parent(s): 86b7939

Update orbit-camera.js

Browse files
Files changed (1) hide show
  1. orbit-camera.js +108 -36
orbit-camera.js CHANGED
@@ -1,6 +1,8 @@
 
 
 
 
1
  ///////////////////////////////////////////////////////////////////////////////
2
- // Orbit Camera Script qui marche presque //
3
- ////////////////////////////////////////////////////////////////////////////////
4
 
5
  var OrbitCamera = pc.createScript('orbitCamera');
6
 
@@ -11,7 +13,6 @@ OrbitCamera.attributes.add('pitchAngleMax', { type: 'number', default: 90, title
11
  OrbitCamera.attributes.add('pitchAngleMin', { type: 'number', default: 0, title: 'Pitch Angle Min (degrees)' });
12
  OrbitCamera.attributes.add('yawAngleMax', { type: 'number', default: 360, title: 'Yaw Angle Max (degrees)' });
13
  OrbitCamera.attributes.add('yawAngleMin', { type: 'number', default: -360, title: 'Yaw Angle Min (degrees)' });
14
- // NEW: Added minY attribute to define the minimum allowed Y value for the camera.
15
  OrbitCamera.attributes.add('minY', { type: 'number', default: 0, title: 'Minimum Y', description: 'Minimum Y value for the camera during orbiting or translation' });
16
 
17
  OrbitCamera.attributes.add('inertiaFactor', {
@@ -34,9 +35,7 @@ OrbitCamera.attributes.add('frameOnStart', {
34
  description: 'Frames the entity or scene at the start of the application."'
35
  });
36
 
37
-
38
  // Property to get and set the distance between the pivot point and camera
39
- // Clamped between this.distanceMin and this.distanceMax
40
  Object.defineProperty(OrbitCamera.prototype, 'distance', {
41
  get: function () {
42
  return this._targetDistance;
@@ -56,11 +55,7 @@ Object.defineProperty(OrbitCamera.prototype, 'orthoHeight', {
56
  }
57
  });
58
 
59
-
60
  // Property to get and set the pitch (in degrees) of the camera around the pivot.
61
- // The pitch value is clamped between pitchAngleMin and pitchAngleMax.
62
- // With your JSON (minAngle: -90, maxAngle: 0), the allowed pitch will be from -90 (overhead)
63
- // to 0 (horizontal).
64
  Object.defineProperty(OrbitCamera.prototype, 'pitch', {
65
  get: function () {
66
  return this._targetPitch;
@@ -70,7 +65,6 @@ Object.defineProperty(OrbitCamera.prototype, 'pitch', {
70
  }
71
  });
72
 
73
-
74
  // Property to get and set the yaw (in degrees) of the camera around the pivot.
75
  Object.defineProperty(OrbitCamera.prototype, 'yaw', {
76
  get: function () {
@@ -81,7 +75,6 @@ Object.defineProperty(OrbitCamera.prototype, 'yaw', {
81
  }
82
  });
83
 
84
-
85
  // Property to get and set the world position of the pivot point that the camera orbits around.
86
  Object.defineProperty(OrbitCamera.prototype, 'pivotPoint', {
87
  get: function () {
@@ -92,10 +85,8 @@ Object.defineProperty(OrbitCamera.prototype, 'pivotPoint', {
92
  }
93
  });
94
 
95
-
96
  // Moves the camera to look at an entity and all its children so they are all in view.
97
  OrbitCamera.prototype.focus = function (focusEntity) {
98
- // Calculate a bounding box that encompasses all models to frame in the camera view.
99
  this._buildAabb(focusEntity);
100
  var halfExtents = this._modelsAabb.halfExtents;
101
  var radius = Math.max(halfExtents.x, Math.max(halfExtents.y, halfExtents.z));
@@ -106,7 +97,6 @@ OrbitCamera.prototype.focus = function (focusEntity) {
106
 
107
  OrbitCamera.distanceBetween = new pc.Vec3();
108
 
109
- // Set the camera position to a world position and look at a world position.
110
  OrbitCamera.prototype.resetAndLookAtPoint = function (resetPoint, lookAtPoint) {
111
  this.pivotPoint.copy(lookAtPoint);
112
  this.entity.setPosition(resetPoint);
@@ -148,9 +138,8 @@ OrbitCamera.prototype.resetToPosition = function (position, lookAtPoint) {
148
  this._updatePosition();
149
  };
150
 
151
-
152
  ////////////////////////////////////////////////////////////////////////////////
153
- // Private Methods //
154
  ////////////////////////////////////////////////////////////////////////////////
155
 
156
  OrbitCamera.prototype.initialize = function () {
@@ -168,7 +157,6 @@ OrbitCamera.prototype.initialize = function () {
168
  this._pivotPoint.copy(this._modelsAabb.center);
169
  var cameraQuat = this.entity.getRotation();
170
  this._yaw = this._calcYaw(cameraQuat);
171
- // Compute pitch and clamp it immediately.
172
  this._pitch = this._clampPitchAngle(this._calcPitch(cameraQuat, this._yaw));
173
  this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);
174
  this._distance = 0;
@@ -229,7 +217,7 @@ OrbitCamera.prototype._updatePosition = function () {
229
  position.copy(this.entity.forward);
230
  position.mulScalar(-this._distance);
231
  position.add(this.pivotPoint);
232
- // NEW: Clamp the camera's Y position so it never goes below the specified minY value.
233
  position.y = Math.max(position.y, this.minY);
234
  this.entity.setPosition(position);
235
  };
@@ -292,10 +280,6 @@ OrbitCamera.prototype._clampDistance = function (distance) {
292
  return Math.max(distance, this.distanceMin);
293
  };
294
 
295
-
296
- // ----- FIXED PITCH CLAMPING -----
297
- // Clamp the pitch between pitchAngleMin and pitchAngleMax so that with your JSON values
298
- // (minAngle: -90, maxAngle: 0) the allowed pitch is between -90 (overhead) and 0 (horizontal).
299
  OrbitCamera.prototype._clampPitchAngle = function (pitch) {
300
  return pc.math.clamp(pitch, this.pitchAngleMin, this.pitchAngleMax);
301
  };
@@ -307,10 +291,6 @@ OrbitCamera.prototype._clampYawAngle = function (yaw) {
307
  OrbitCamera.quatWithoutYaw = new pc.Quat();
308
  OrbitCamera.yawOffset = new pc.Quat();
309
 
310
- // ----- REVISED PITCH CALCULATION -----
311
- // Modify _calcPitch so that horizontal (looking straight ahead) returns 0,
312
- // and looking overhead returns -90.
313
- // This change ensures that with JSON (minAngle: -90, maxAngle: 0) the allowed pitch is strictly between -90 and 0.
314
  OrbitCamera.prototype._calcPitch = function (quat, yaw) {
315
  var quatWithoutYaw = OrbitCamera.quatWithoutYaw;
316
  var yawOffset = OrbitCamera.yawOffset;
@@ -318,13 +298,9 @@ OrbitCamera.prototype._calcPitch = function (quat, yaw) {
318
  quatWithoutYaw.mul2(yawOffset, quat);
319
  var transformedForward = new pc.Vec3();
320
  quatWithoutYaw.transformVector(pc.Vec3.FORWARD, transformedForward);
321
- // Here we swap the sign of the computed angle so that:
322
- // - When the camera is horizontal, transformedForward.y is 0 and the result is 0.
323
- // - When the camera is overhead, transformedForward.y is negative and the result is -90.
324
  return Math.atan2(-transformedForward.y, -transformedForward.z) * pc.math.RAD_TO_DEG;
325
  };
326
 
327
-
328
  ////////////////////////////////////////////////////////////////////////////////
329
  // Orbit Camera Mouse Input Script //
330
  ////////////////////////////////////////////////////////////////////////////////
@@ -406,15 +382,65 @@ OrbitCameraInputMouse.prototype.onMouseUp = function (event) {
406
  break;
407
  }
408
  };
 
 
409
  OrbitCameraInputMouse.prototype.onMouseMove = function (event) {
410
  if (this.lookButtonDown) {
411
- this.orbitCamera.pitch -= event.dy * this.orbitSensitivity;
412
- this.orbitCamera.yaw -= event.dx * this.orbitSensitivity;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413
  } else if (this.panButtonDown) {
414
  this.pan(new pc.Vec2(event.x, event.y));
415
  }
416
  this.lastPoint.set(event.x, event.y);
417
  };
 
 
418
  OrbitCameraInputMouse.prototype.onMouseWheel = function (event) {
419
  if (this.entity.camera.projection === pc.PROJECTION_PERSPECTIVE) {
420
  this.orbitCamera.distance -= event.wheelDelta * this.distanceSensitivity * (this.orbitCamera.distance * 0.1);
@@ -428,7 +454,6 @@ OrbitCameraInputMouse.prototype.onMouseOut = function (event) {
428
  this.panButtonDown = false;
429
  };
430
 
431
-
432
  ////////////////////////////////////////////////////////////////////////////////
433
  // Orbit Camera Touch Input Script //
434
  ////////////////////////////////////////////////////////////////////////////////
@@ -504,13 +529,59 @@ OrbitCameraInputTouch.prototype.pan = function (midPoint) {
504
  }
505
  };
506
  OrbitCameraInputTouch.pinchMidPoint = new pc.Vec2();
 
 
507
  OrbitCameraInputTouch.prototype.onTouchMove = function (event) {
508
  var pinchMidPoint = OrbitCameraInputTouch.pinchMidPoint;
509
  var touches = event.touches;
510
  if (touches.length === 1) {
511
  var touch = touches[0];
512
- this.orbitCamera.pitch -= (touch.y - this.lastTouchPoint.y) * this.orbitSensitivity;
513
- this.orbitCamera.yaw -= (touch.x - this.lastTouchPoint.x) * this.orbitSensitivity;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
514
  this.lastTouchPoint.set(touch.x, touch.y);
515
  } else if (touches.length === 2) {
516
  var currentPinchDistance = this.getPinchDistance(touches[0], touches[1]);
@@ -521,4 +592,5 @@ OrbitCameraInputTouch.prototype.onTouchMove = function (event) {
521
  this.pan(pinchMidPoint);
522
  this.lastPinchMidPoint.copy(pinchMidPoint);
523
  }
524
- };
 
 
1
+ // orbit-camera.js (fixed to clamp world Y at minY, with debug logs)
2
+
3
+ ///////////////////////////////////////////////////////////////////////////////
4
+ // Orbit Camera Script //
5
  ///////////////////////////////////////////////////////////////////////////////
 
 
6
 
7
  var OrbitCamera = pc.createScript('orbitCamera');
8
 
 
13
  OrbitCamera.attributes.add('pitchAngleMin', { type: 'number', default: 0, title: 'Pitch Angle Min (degrees)' });
14
  OrbitCamera.attributes.add('yawAngleMax', { type: 'number', default: 360, title: 'Yaw Angle Max (degrees)' });
15
  OrbitCamera.attributes.add('yawAngleMin', { type: 'number', default: -360, title: 'Yaw Angle Min (degrees)' });
 
16
  OrbitCamera.attributes.add('minY', { type: 'number', default: 0, title: 'Minimum Y', description: 'Minimum Y value for the camera during orbiting or translation' });
17
 
18
  OrbitCamera.attributes.add('inertiaFactor', {
 
35
  description: 'Frames the entity or scene at the start of the application."'
36
  });
37
 
 
38
  // Property to get and set the distance between the pivot point and camera
 
39
  Object.defineProperty(OrbitCamera.prototype, 'distance', {
40
  get: function () {
41
  return this._targetDistance;
 
55
  }
56
  });
57
 
 
58
  // Property to get and set the pitch (in degrees) of the camera around the pivot.
 
 
 
59
  Object.defineProperty(OrbitCamera.prototype, 'pitch', {
60
  get: function () {
61
  return this._targetPitch;
 
65
  }
66
  });
67
 
 
68
  // Property to get and set the yaw (in degrees) of the camera around the pivot.
69
  Object.defineProperty(OrbitCamera.prototype, 'yaw', {
70
  get: function () {
 
75
  }
76
  });
77
 
 
78
  // Property to get and set the world position of the pivot point that the camera orbits around.
79
  Object.defineProperty(OrbitCamera.prototype, 'pivotPoint', {
80
  get: function () {
 
85
  }
86
  });
87
 
 
88
  // Moves the camera to look at an entity and all its children so they are all in view.
89
  OrbitCamera.prototype.focus = function (focusEntity) {
 
90
  this._buildAabb(focusEntity);
91
  var halfExtents = this._modelsAabb.halfExtents;
92
  var radius = Math.max(halfExtents.x, Math.max(halfExtents.y, halfExtents.z));
 
97
 
98
  OrbitCamera.distanceBetween = new pc.Vec3();
99
 
 
100
  OrbitCamera.prototype.resetAndLookAtPoint = function (resetPoint, lookAtPoint) {
101
  this.pivotPoint.copy(lookAtPoint);
102
  this.entity.setPosition(resetPoint);
 
138
  this._updatePosition();
139
  };
140
 
 
141
  ////////////////////////////////////////////////////////////////////////////////
142
+ // Private Methods //
143
  ////////////////////////////////////////////////////////////////////////////////
144
 
145
  OrbitCamera.prototype.initialize = function () {
 
157
  this._pivotPoint.copy(this._modelsAabb.center);
158
  var cameraQuat = this.entity.getRotation();
159
  this._yaw = this._calcYaw(cameraQuat);
 
160
  this._pitch = this._clampPitchAngle(this._calcPitch(cameraQuat, this._yaw));
161
  this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);
162
  this._distance = 0;
 
217
  position.copy(this.entity.forward);
218
  position.mulScalar(-this._distance);
219
  position.add(this.pivotPoint);
220
+ // Clamp camera's Y position so it never goes below minY (after all rotations)
221
  position.y = Math.max(position.y, this.minY);
222
  this.entity.setPosition(position);
223
  };
 
280
  return Math.max(distance, this.distanceMin);
281
  };
282
 
 
 
 
 
283
  OrbitCamera.prototype._clampPitchAngle = function (pitch) {
284
  return pc.math.clamp(pitch, this.pitchAngleMin, this.pitchAngleMax);
285
  };
 
291
  OrbitCamera.quatWithoutYaw = new pc.Quat();
292
  OrbitCamera.yawOffset = new pc.Quat();
293
 
 
 
 
 
294
  OrbitCamera.prototype._calcPitch = function (quat, yaw) {
295
  var quatWithoutYaw = OrbitCamera.quatWithoutYaw;
296
  var yawOffset = OrbitCamera.yawOffset;
 
298
  quatWithoutYaw.mul2(yawOffset, quat);
299
  var transformedForward = new pc.Vec3();
300
  quatWithoutYaw.transformVector(pc.Vec3.FORWARD, transformedForward);
 
 
 
301
  return Math.atan2(-transformedForward.y, -transformedForward.z) * pc.math.RAD_TO_DEG;
302
  };
303
 
 
304
  ////////////////////////////////////////////////////////////////////////////////
305
  // Orbit Camera Mouse Input Script //
306
  ////////////////////////////////////////////////////////////////////////////////
 
382
  break;
383
  }
384
  };
385
+
386
+ // ---------- PATCHED: orbit suppression at minY (mouse) ---------------
387
  OrbitCameraInputMouse.prototype.onMouseMove = function (event) {
388
  if (this.lookButtonDown) {
389
+ var sens = this.orbitSensitivity;
390
+ var deltaPitch = event.dy * sens;
391
+ var deltaYaw = event.dx * sens;
392
+
393
+ var currPitch = this.orbitCamera.pitch;
394
+ var currYaw = this.orbitCamera.yaw;
395
+ var currDist = this.orbitCamera.distance;
396
+ var currPivot = this.orbitCamera.pivotPoint.clone();
397
+
398
+ // Compute the world position before the change
399
+ var camQuat = new pc.Quat();
400
+ camQuat.setFromEulerAngles(currPitch, currYaw, 0);
401
+ var forward = new pc.Vec3();
402
+ camQuat.transformVector(pc.Vec3.FORWARD, forward);
403
+ var preY = currPivot.y + (-forward.y) * currDist;
404
+
405
+ // Compute the world position after applying the vertical delta
406
+ var proposedPitch = currPitch - deltaPitch;
407
+ var testQuat = new pc.Quat();
408
+ testQuat.setFromEulerAngles(proposedPitch, currYaw, 0);
409
+ var testForward = new pc.Vec3();
410
+ testQuat.transformVector(pc.Vec3.FORWARD, testForward);
411
+ var proposedY = currPivot.y + (-testForward.y) * currDist;
412
+
413
+ var minY = this.orbitCamera.minY;
414
+ var isAtMinY = preY <= minY + 1e-4;
415
+ var wouldGoBelow = proposedY < minY - 1e-4;
416
+ var suppressed = false;
417
+
418
+ // Only suppress if going *further* below minY (upward)
419
+ if (wouldGoBelow && (proposedY < preY)) {
420
+ // Suppress vertical, allow horizontal (yaw)
421
+ this.orbitCamera.yaw = currYaw - deltaYaw;
422
+ suppressed = true;
423
+ } else {
424
+ this.orbitCamera.pitch = proposedPitch;
425
+ this.orbitCamera.yaw = currYaw - deltaYaw;
426
+ }
427
+
428
+ console.log(
429
+ '[Mouse] currentY=', preY.toFixed(3),
430
+ 'proposedY=', proposedY.toFixed(3),
431
+ 'minY=', minY,
432
+ 'deltaX=', event.dx,
433
+ 'deltaY=', event.dy,
434
+ 'isAtMinY=', isAtMinY,
435
+ 'suppressedVertical=', suppressed
436
+ );
437
  } else if (this.panButtonDown) {
438
  this.pan(new pc.Vec2(event.x, event.y));
439
  }
440
  this.lastPoint.set(event.x, event.y);
441
  };
442
+ // ---------------------------------------------------------------------
443
+
444
  OrbitCameraInputMouse.prototype.onMouseWheel = function (event) {
445
  if (this.entity.camera.projection === pc.PROJECTION_PERSPECTIVE) {
446
  this.orbitCamera.distance -= event.wheelDelta * this.distanceSensitivity * (this.orbitCamera.distance * 0.1);
 
454
  this.panButtonDown = false;
455
  };
456
 
 
457
  ////////////////////////////////////////////////////////////////////////////////
458
  // Orbit Camera Touch Input Script //
459
  ////////////////////////////////////////////////////////////////////////////////
 
529
  }
530
  };
531
  OrbitCameraInputTouch.pinchMidPoint = new pc.Vec2();
532
+
533
+ // ---------- PATCHED: orbit suppression at minY (touch) ---------------
534
  OrbitCameraInputTouch.prototype.onTouchMove = function (event) {
535
  var pinchMidPoint = OrbitCameraInputTouch.pinchMidPoint;
536
  var touches = event.touches;
537
  if (touches.length === 1) {
538
  var touch = touches[0];
539
+ var sens = this.orbitSensitivity;
540
+ var deltaPitch = (touch.y - this.lastTouchPoint.y) * sens;
541
+ var deltaYaw = (touch.x - this.lastTouchPoint.x) * sens;
542
+
543
+ var currPitch = this.orbitCamera.pitch;
544
+ var currYaw = this.orbitCamera.yaw;
545
+ var currDist = this.orbitCamera.distance;
546
+ var currPivot = this.orbitCamera.pivotPoint.clone();
547
+
548
+ // Compute the world position before the change
549
+ var camQuat = new pc.Quat();
550
+ camQuat.setFromEulerAngles(currPitch, currYaw, 0);
551
+ var forward = new pc.Vec3();
552
+ camQuat.transformVector(pc.Vec3.FORWARD, forward);
553
+ var preY = currPivot.y + (-forward.y) * currDist;
554
+
555
+ // Compute the world position after applying the vertical delta
556
+ var proposedPitch = currPitch - deltaPitch;
557
+ var testQuat = new pc.Quat();
558
+ testQuat.setFromEulerAngles(proposedPitch, currYaw, 0);
559
+ var testForward = new pc.Vec3();
560
+ testQuat.transformVector(pc.Vec3.FORWARD, testForward);
561
+ var proposedY = currPivot.y + (-testForward.y) * currDist;
562
+
563
+ var minY = this.orbitCamera.minY;
564
+ var isAtMinY = preY <= minY + 1e-4;
565
+ var wouldGoBelow = proposedY < minY - 1e-4;
566
+ var suppressed = false;
567
+
568
+ if (wouldGoBelow && (proposedY < preY)) {
569
+ // Suppress vertical, allow horizontal (yaw)
570
+ this.orbitCamera.yaw = currYaw - deltaYaw;
571
+ suppressed = true;
572
+ } else {
573
+ this.orbitCamera.pitch = proposedPitch;
574
+ this.orbitCamera.yaw = currYaw - deltaYaw;
575
+ }
576
+ console.log(
577
+ '[Touch] currentY=', preY.toFixed(3),
578
+ 'proposedY=', proposedY.toFixed(3),
579
+ 'minY=', minY,
580
+ 'deltaX=', (touch.x - this.lastTouchPoint.x),
581
+ 'deltaY=', (touch.y - this.lastTouchPoint.y),
582
+ 'isAtMinY=', isAtMinY,
583
+ 'suppressedVertical=', suppressed
584
+ );
585
  this.lastTouchPoint.set(touch.x, touch.y);
586
  } else if (touches.length === 2) {
587
  var currentPinchDistance = this.getPinchDistance(touches[0], touches[1]);
 
592
  this.pan(pinchMidPoint);
593
  this.lastPinchMidPoint.copy(pinchMidPoint);
594
  }
595
+ };
596
+ // ---------------------------------------------------------------------