MikaFil commited on
Commit
6c26003
·
verified ·
1 Parent(s): 92bb0d2

Update orbit-camera.js

Browse files
Files changed (1) hide show
  1. orbit-camera.js +52 -34
orbit-camera.js CHANGED
@@ -34,9 +34,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 +54,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 +64,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 +74,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 +84,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 +96,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,7 +137,6 @@ OrbitCamera.prototype.resetToPosition = function (position, lookAtPoint) {
148
  this._updatePosition();
149
  };
150
 
151
-
152
  ////////////////////////////////////////////////////////////////////////////////
153
  // Private Methods //
154
  ////////////////////////////////////////////////////////////////////////////////
@@ -168,7 +156,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 +216,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,12 +279,27 @@ 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
  };
302
 
303
  OrbitCamera.prototype._clampYawAngle = function (yaw) {
@@ -308,9 +310,6 @@ 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 +317,11 @@ 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
  ////////////////////////////////////////////////////////////////////////////////
@@ -342,6 +339,7 @@ OrbitCameraInputMouse.attributes.add('distanceSensitivity', {
342
  title: 'Distance Sensitivity',
343
  description: 'How fast the camera moves in and out. Higher is faster'
344
  });
 
345
  OrbitCameraInputMouse.prototype.initialize = function () {
346
  this.orbitCamera = this.entity.script.orbitCamera;
347
  if (this.orbitCamera) {
@@ -365,9 +363,11 @@ OrbitCameraInputMouse.prototype.initialize = function () {
365
  this.panButtonDown = false;
366
  this.lastPoint = new pc.Vec2();
367
  };
 
368
  OrbitCameraInputMouse.fromWorldPoint = new pc.Vec3();
369
  OrbitCameraInputMouse.toWorldPoint = new pc.Vec3();
370
  OrbitCameraInputMouse.worldDiff = new pc.Vec3();
 
371
  OrbitCameraInputMouse.prototype.pan = function (screenPoint) {
372
  var fromWorldPoint = OrbitCameraInputMouse.fromWorldPoint;
373
  var toWorldPoint = OrbitCameraInputMouse.toWorldPoint;
@@ -384,6 +384,7 @@ OrbitCameraInputMouse.prototype.pan = function (screenPoint) {
384
  this.orbitCamera.pivotPoint.y = minPivotY;
385
  }
386
  };
 
387
  OrbitCameraInputMouse.prototype.onMouseDown = function (event) {
388
  switch (event.button) {
389
  case pc.MOUSEBUTTON_LEFT:
@@ -406,15 +407,21 @@ 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);
@@ -423,6 +430,7 @@ OrbitCameraInputMouse.prototype.onMouseWheel = function (event) {
423
  }
424
  event.event.preventDefault();
425
  };
 
426
  OrbitCameraInputMouse.prototype.onMouseOut = function (event) {
427
  this.lookButtonDown = false;
428
  this.panButtonDown = false;
@@ -446,6 +454,7 @@ OrbitCameraInputTouch.attributes.add('distanceSensitivity', {
446
  title: 'Distance Sensitivity',
447
  description: 'How fast the camera moves in and out. Higher is faster'
448
  });
 
449
  OrbitCameraInputTouch.prototype.initialize = function () {
450
  this.orbitCamera = this.entity.script.orbitCamera;
451
  this.lastTouchPoint = new pc.Vec2();
@@ -464,6 +473,7 @@ OrbitCameraInputTouch.prototype.initialize = function () {
464
  });
465
  }
466
  };
 
467
  OrbitCameraInputTouch.prototype.getPinchDistance = function (pointA, pointB) {
468
  var dx = pointA.x - pointB.x;
469
  var dy = pointA.y - pointB.y;
@@ -484,9 +494,11 @@ OrbitCameraInputTouch.prototype.onTouchStartEndCancel = function (event) {
484
  this.calcMidPoint(touches[0], touches[1], this.lastPinchMidPoint);
485
  }
486
  };
 
487
  OrbitCameraInputTouch.fromWorldPoint = new pc.Vec3();
488
  OrbitCameraInputTouch.toWorldPoint = new pc.Vec3();
489
  OrbitCameraInputTouch.worldDiff = new pc.Vec3();
 
490
  OrbitCameraInputTouch.prototype.pan = function (midPoint) {
491
  var fromWorldPoint = OrbitCameraInputTouch.fromWorldPoint;
492
  var toWorldPoint = OrbitCameraInputTouch.toWorldPoint;
@@ -503,22 +515,28 @@ OrbitCameraInputTouch.prototype.pan = function (midPoint) {
503
  this.orbitCamera.pivotPoint.y = minPivotY;
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]);
517
  var diffInPinchDistance = currentPinchDistance - this.lastPinchDistance;
518
  this.lastPinchDistance = currentPinchDistance;
519
  this.orbitCamera.distance -= (diffInPinchDistance * this.distanceSensitivity * 0.1) * (this.orbitCamera.distance * 0.1);
520
- this.calcMidPoint(touches[0], touches[1], pinchMidPoint);
521
- this.pan(pinchMidPoint);
522
- this.lastPinchMidPoint.copy(pinchMidPoint);
523
  }
524
- };
 
34
  description: 'Frames the entity or scene at the start of the application."'
35
  });
36
 
 
37
  // Property to get and set the distance between the pivot point and camera
 
38
  Object.defineProperty(OrbitCamera.prototype, 'distance', {
39
  get: function () {
40
  return this._targetDistance;
 
54
  }
55
  });
56
 
 
57
  // Property to get and set the pitch (in degrees) of the camera around the pivot.
 
 
 
58
  Object.defineProperty(OrbitCamera.prototype, 'pitch', {
59
  get: function () {
60
  return this._targetPitch;
 
64
  }
65
  });
66
 
 
67
  // Property to get and set the yaw (in degrees) of the camera around the pivot.
68
  Object.defineProperty(OrbitCamera.prototype, 'yaw', {
69
  get: function () {
 
74
  }
75
  });
76
 
 
77
  // Property to get and set the world position of the pivot point that the camera orbits around.
78
  Object.defineProperty(OrbitCamera.prototype, 'pivotPoint', {
79
  get: function () {
 
84
  }
85
  });
86
 
 
87
  // Moves the camera to look at an entity and all its children so they are all in view.
88
  OrbitCamera.prototype.focus = function (focusEntity) {
 
89
  this._buildAabb(focusEntity);
90
  var halfExtents = this._modelsAabb.halfExtents;
91
  var radius = Math.max(halfExtents.x, Math.max(halfExtents.y, halfExtents.z));
 
96
 
97
  OrbitCamera.distanceBetween = new pc.Vec3();
98
 
 
99
  OrbitCamera.prototype.resetAndLookAtPoint = function (resetPoint, lookAtPoint) {
100
  this.pivotPoint.copy(lookAtPoint);
101
  this.entity.setPosition(resetPoint);
 
137
  this._updatePosition();
138
  };
139
 
 
140
  ////////////////////////////////////////////////////////////////////////////////
141
  // Private Methods //
142
  ////////////////////////////////////////////////////////////////////////////////
 
156
  this._pivotPoint.copy(this._modelsAabb.center);
157
  var cameraQuat = this.entity.getRotation();
158
  this._yaw = this._calcYaw(cameraQuat);
 
159
  this._pitch = this._clampPitchAngle(this._calcPitch(cameraQuat, this._yaw));
160
  this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);
161
  this._distance = 0;
 
216
  position.copy(this.entity.forward);
217
  position.mulScalar(-this._distance);
218
  position.add(this.pivotPoint);
219
+ // Clamp the camera's Y position so it never goes below minY.
220
  position.y = Math.max(position.y, this.minY);
221
  this.entity.setPosition(position);
222
  };
 
279
  return Math.max(distance, this.distanceMin);
280
  };
281
 
282
+ // ----- FIXED PITCH CLAMPING WITH minY RESPECT -----
 
 
 
283
  OrbitCamera.prototype._clampPitchAngle = function (pitch) {
284
+ // Clamp between configured pitchAngleMin/Max first
285
+ var clamped = pc.math.clamp(pitch, this.pitchAngleMin, this.pitchAngleMax);
286
+
287
+ // Then ensure resulting world-space Y >= minY
288
+ // simulate forward vector
289
+ var yaw = this._targetYaw;
290
+ var quat = new pc.Quat().setFromEulerAngles(clamped, yaw, 0);
291
+ var forward = new pc.Vec3();
292
+ quat.transformVector(pc.Vec3.FORWARD, forward);
293
+ var simulatedY = this._pivotPoint.y - forward.y * this._targetDistance;
294
+ if (simulatedY < this.minY) {
295
+ // compute max pitch that just reaches minY: asin((pivotY-minY)/distance)
296
+ var ratio = (this._pivotPoint.y - this.minY) / this._targetDistance;
297
+ ratio = pc.math.clamp(ratio, -1, 1);
298
+ var angle = Math.asin(ratio) * pc.math.RAD_TO_DEG;
299
+ return pc.math.clamp(angle, this.pitchAngleMin, this.pitchAngleMax);
300
+ }
301
+
302
+ return clamped;
303
  };
304
 
305
  OrbitCamera.prototype._clampYawAngle = function (yaw) {
 
310
  OrbitCamera.yawOffset = new pc.Quat();
311
 
312
  // ----- REVISED PITCH CALCULATION -----
 
 
 
313
  OrbitCamera.prototype._calcPitch = function (quat, yaw) {
314
  var quatWithoutYaw = OrbitCamera.quatWithoutYaw;
315
  var yawOffset = OrbitCamera.yawOffset;
 
317
  quatWithoutYaw.mul2(yawOffset, quat);
318
  var transformedForward = new pc.Vec3();
319
  quatWithoutYaw.transformVector(pc.Vec3.FORWARD, transformedForward);
 
 
 
320
  return Math.atan2(-transformedForward.y, -transformedForward.z) * pc.math.RAD_TO_DEG;
321
  };
322
 
323
 
324
+
325
  ////////////////////////////////////////////////////////////////////////////////
326
  // Orbit Camera Mouse Input Script //
327
  ////////////////////////////////////////////////////////////////////////////////
 
339
  title: 'Distance Sensitivity',
340
  description: 'How fast the camera moves in and out. Higher is faster'
341
  });
342
+
343
  OrbitCameraInputMouse.prototype.initialize = function () {
344
  this.orbitCamera = this.entity.script.orbitCamera;
345
  if (this.orbitCamera) {
 
363
  this.panButtonDown = false;
364
  this.lastPoint = new pc.Vec2();
365
  };
366
+
367
  OrbitCameraInputMouse.fromWorldPoint = new pc.Vec3();
368
  OrbitCameraInputMouse.toWorldPoint = new pc.Vec3();
369
  OrbitCameraInputMouse.worldDiff = new pc.Vec3();
370
+
371
  OrbitCameraInputMouse.prototype.pan = function (screenPoint) {
372
  var fromWorldPoint = OrbitCameraInputMouse.fromWorldPoint;
373
  var toWorldPoint = OrbitCameraInputMouse.toWorldPoint;
 
384
  this.orbitCamera.pivotPoint.y = minPivotY;
385
  }
386
  };
387
+
388
  OrbitCameraInputMouse.prototype.onMouseDown = function (event) {
389
  switch (event.button) {
390
  case pc.MOUSEBUTTON_LEFT:
 
407
  break;
408
  }
409
  };
410
+
411
  OrbitCameraInputMouse.prototype.onMouseMove = function (event) {
412
  if (this.lookButtonDown) {
413
+ var delta = -event.dy * this.orbitSensitivity;
414
+ var camY = this.entity.getPosition().y;
415
+ // block further downward orbit when at minY
416
+ if (!(delta < 0 && camY <= this.orbitCamera.minY)) {
417
+ this.orbitCamera.pitch += delta;
418
+ }
419
  } else if (this.panButtonDown) {
420
  this.pan(new pc.Vec2(event.x, event.y));
421
  }
422
  this.lastPoint.set(event.x, event.y);
423
  };
424
+
425
  OrbitCameraInputMouse.prototype.onMouseWheel = function (event) {
426
  if (this.entity.camera.projection === pc.PROJECTION_PERSPECTIVE) {
427
  this.orbitCamera.distance -= event.wheelDelta * this.distanceSensitivity * (this.orbitCamera.distance * 0.1);
 
430
  }
431
  event.event.preventDefault();
432
  };
433
+
434
  OrbitCameraInputMouse.prototype.onMouseOut = function (event) {
435
  this.lookButtonDown = false;
436
  this.panButtonDown = false;
 
454
  title: 'Distance Sensitivity',
455
  description: 'How fast the camera moves in and out. Higher is faster'
456
  });
457
+
458
  OrbitCameraInputTouch.prototype.initialize = function () {
459
  this.orbitCamera = this.entity.script.orbitCamera;
460
  this.lastTouchPoint = new pc.Vec2();
 
473
  });
474
  }
475
  };
476
+
477
  OrbitCameraInputTouch.prototype.getPinchDistance = function (pointA, pointB) {
478
  var dx = pointA.x - pointB.x;
479
  var dy = pointA.y - pointB.y;
 
494
  this.calcMidPoint(touches[0], touches[1], this.lastPinchMidPoint);
495
  }
496
  };
497
+
498
  OrbitCameraInputTouch.fromWorldPoint = new pc.Vec3();
499
  OrbitCameraInputTouch.toWorldPoint = new pc.Vec3();
500
  OrbitCameraInputTouch.worldDiff = new pc.Vec3();
501
+
502
  OrbitCameraInputTouch.prototype.pan = function (midPoint) {
503
  var fromWorldPoint = OrbitCameraInputTouch.fromWorldPoint;
504
  var toWorldPoint = OrbitCameraInputTouch.toWorldPoint;
 
515
  this.orbitCamera.pivotPoint.y = minPivotY;
516
  }
517
  };
518
+
519
  OrbitCameraInputTouch.pinchMidPoint = new pc.Vec2();
520
+
521
  OrbitCameraInputTouch.prototype.onTouchMove = function (event) {
 
522
  var touches = event.touches;
523
  if (touches.length === 1) {
524
  var touch = touches[0];
525
+ var dy = touch.y - this.lastTouchPoint.y;
526
+ var delta = -dy * this.orbitSensitivity;
527
+ var camY = this.entity.getPosition().y;
528
+ // block further downward orbit when at minY
529
+ if (!(delta < 0 && camY <= this.orbitCamera.minY)) {
530
+ this.orbitCamera.pitch += delta;
531
+ }
532
  this.lastTouchPoint.set(touch.x, touch.y);
533
  } else if (touches.length === 2) {
534
  var currentPinchDistance = this.getPinchDistance(touches[0], touches[1]);
535
  var diffInPinchDistance = currentPinchDistance - this.lastPinchDistance;
536
  this.lastPinchDistance = currentPinchDistance;
537
  this.orbitCamera.distance -= (diffInPinchDistance * this.distanceSensitivity * 0.1) * (this.orbitCamera.distance * 0.1);
538
+ this.calcMidPoint(touches[0], touches[1], OrbitCameraInputTouch.pinchMidPoint);
539
+ this.pan(OrbitCameraInputTouch.pinchMidPoint);
540
+ this.lastPinchMidPoint.copy(OrbitCameraInputTouch.pinchMidPoint);
541
  }
542
+ };