MikaFil commited on
Commit
a230471
·
verified ·
1 Parent(s): f21a297

Update orbit-camera.js

Browse files
Files changed (1) hide show
  1. orbit-camera.js +240 -32
orbit-camera.js CHANGED
@@ -34,6 +34,7 @@ OrbitCamera.attributes.add('frameOnStart', {
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
  // Clamped between this.distanceMin and this.distanceMax
39
  Object.defineProperty(OrbitCamera.prototype, 'distance', {
@@ -55,33 +56,21 @@ Object.defineProperty(OrbitCamera.prototype, 'orthoHeight', {
55
  }
56
  });
57
 
 
58
  // Property to get and set the pitch (in degrees) of the camera around the pivot.
59
- // The pitch value is clamped between pitchAngleMin and pitchAngleMax,
60
- // and also clamped so world-space Y never falls below minY.
 
61
  Object.defineProperty(OrbitCamera.prototype, 'pitch', {
62
  get: function () {
63
  return this._targetPitch;
64
  },
65
  set: function (value) {
66
- // First clamp to configured angle limits
67
- var clamped = this._clampPitchAngle(value);
68
-
69
- // Then ensure world Y >= minY: pivotY + sin(pitch)*distance >= minY
70
- if (this._pivotPoint && this._targetDistance !== undefined) {
71
- var pivotY = this._pivotPoint.y;
72
- var dist = this._targetDistance;
73
- // maximum downward (negative) pitch (in radians) allowed by minY
74
- var maxDownRad = Math.asin(Math.max(0, Math.min(1, (pivotY - this.minY) / dist)));
75
- var maxDownDeg = -maxDownRad * pc.math.RAD_TO_DEG;
76
- if (clamped < maxDownDeg) {
77
- clamped = maxDownDeg;
78
- }
79
- }
80
-
81
- this._targetPitch = clamped;
82
  }
83
  });
84
 
 
85
  // Property to get and set the yaw (in degrees) of the camera around the pivot.
86
  Object.defineProperty(OrbitCamera.prototype, 'yaw', {
87
  get: function () {
@@ -92,6 +81,7 @@ Object.defineProperty(OrbitCamera.prototype, 'yaw', {
92
  }
93
  });
94
 
 
95
  // Property to get and set the world position of the pivot point that the camera orbits around.
96
  Object.defineProperty(OrbitCamera.prototype, 'pivotPoint', {
97
  get: function () {
@@ -102,8 +92,10 @@ Object.defineProperty(OrbitCamera.prototype, 'pivotPoint', {
102
  }
103
  });
104
 
 
105
  // Moves the camera to look at an entity and all its children so they are all in view.
106
  OrbitCamera.prototype.focus = function (focusEntity) {
 
107
  this._buildAabb(focusEntity);
108
  var halfExtents = this._modelsAabb.halfExtents;
109
  var radius = Math.max(halfExtents.x, Math.max(halfExtents.y, halfExtents.z));
@@ -114,6 +106,7 @@ OrbitCamera.prototype.focus = function (focusEntity) {
114
 
115
  OrbitCamera.distanceBetween = new pc.Vec3();
116
 
 
117
  OrbitCamera.prototype.resetAndLookAtPoint = function (resetPoint, lookAtPoint) {
118
  this.pivotPoint.copy(lookAtPoint);
119
  this.entity.setPosition(resetPoint);
@@ -155,6 +148,11 @@ OrbitCamera.prototype.resetToPosition = function (position, lookAtPoint) {
155
  this._updatePosition();
156
  };
157
 
 
 
 
 
 
158
  OrbitCamera.prototype.initialize = function () {
159
  var self = this;
160
  var onWindowResize = function () {
@@ -170,6 +168,7 @@ OrbitCamera.prototype.initialize = function () {
170
  this._pivotPoint.copy(this._modelsAabb.center);
171
  var cameraQuat = this.entity.getRotation();
172
  this._yaw = this._calcYaw(cameraQuat);
 
173
  this._pitch = this._clampPitchAngle(this._calcPitch(cameraQuat, this._yaw));
174
  this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);
175
  this._distance = 0;
@@ -186,26 +185,26 @@ OrbitCamera.prototype.initialize = function () {
186
 
187
  this._targetDistance = this._distance;
188
 
189
- this.on('attr:distanceMin', function () {
190
  this._distance = this._clampDistance(this._distance);
191
  });
192
- this.on('attr:distanceMax', function () {
193
  this._distance = this._clampDistance(this._distance);
194
  });
195
- this.on('attr:pitchAngleMin', function () {
196
  this._pitch = this._clampPitchAngle(this._pitch);
197
  });
198
- this.on('attr:pitchAngleMax', function () {
199
  this._pitch = this._clampPitchAngle(this._pitch);
200
  });
201
- this.on('attr:focusEntity', function (value) {
202
  if (this.frameOnStart) {
203
  this.focus(value || this.app.root);
204
  } else {
205
  this.resetAndLookAtEntity(this.entity.getPosition(), value || this.app.root);
206
  }
207
  });
208
- this.on('attr:frameOnStart', function (value) {
209
  if (value) {
210
  this.focus(this.focusEntity || this.app.root);
211
  }
@@ -230,7 +229,7 @@ OrbitCamera.prototype._updatePosition = function () {
230
  position.copy(this.entity.forward);
231
  position.mulScalar(-this._distance);
232
  position.add(this.pivotPoint);
233
- // Clamp world-space Y at minY
234
  position.y = Math.max(position.y, this.minY);
235
  this.entity.setPosition(position);
236
  };
@@ -248,11 +247,11 @@ OrbitCamera.prototype._checkAspectRatio = function () {
248
  };
249
 
250
  OrbitCamera.prototype._buildAabb = function (entity) {
251
- var meshInstances = [];
252
  var renders = entity.findComponents('render');
253
- for (var i = 0; i < renders.length; i++) {
254
  var render = renders[i];
255
- for (var m = 0; m < render.meshInstances.length; m++) {
256
  meshInstances.push(render.meshInstances[m]);
257
  }
258
  }
@@ -265,8 +264,9 @@ OrbitCamera.prototype._buildAabb = function (entity) {
265
  }
266
  var gsplats = entity.findComponents('gsplat');
267
  for (i = 0; i < gsplats.length; i++) {
268
- var instance = gsplats[i].instance;
269
- if (instance && instance.meshInstance) {
 
270
  meshInstances.push(instance.meshInstance);
271
  }
272
  }
@@ -292,7 +292,10 @@ OrbitCamera.prototype._clampDistance = function (distance) {
292
  return Math.max(distance, this.distanceMin);
293
  };
294
 
295
- // Clamp the pitch between pitchAngleMin and pitchAngleMax
 
 
 
296
  OrbitCamera.prototype._clampPitchAngle = function (pitch) {
297
  return pc.math.clamp(pitch, this.pitchAngleMin, this.pitchAngleMax);
298
  };
@@ -304,7 +307,10 @@ OrbitCamera.prototype._clampYawAngle = function (yaw) {
304
  OrbitCamera.quatWithoutYaw = new pc.Quat();
305
  OrbitCamera.yawOffset = new pc.Quat();
306
 
307
- // Calculate pitch from quaternion and yaw
 
 
 
308
  OrbitCamera.prototype._calcPitch = function (quat, yaw) {
309
  var quatWithoutYaw = OrbitCamera.quatWithoutYaw;
310
  var yawOffset = OrbitCamera.yawOffset;
@@ -312,5 +318,207 @@ OrbitCamera.prototype._calcPitch = function (quat, yaw) {
312
  quatWithoutYaw.mul2(yawOffset, quat);
313
  var transformedForward = new pc.Vec3();
314
  quatWithoutYaw.transformVector(pc.Vec3.FORWARD, transformedForward);
 
 
 
315
  return Math.atan2(-transformedForward.y, -transformedForward.z) * pc.math.RAD_TO_DEG;
316
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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', {
 
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;
67
  },
68
  set: function (value) {
69
+ this._targetPitch = this._clampPitchAngle(value);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
  }
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
  }
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
 
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
  this._updatePosition();
149
  };
150
 
151
+
152
+ ////////////////////////////////////////////////////////////////////////////////
153
+ // Private Methods //
154
+ ////////////////////////////////////////////////////////////////////////////////
155
+
156
  OrbitCamera.prototype.initialize = function () {
157
  var self = this;
158
  var onWindowResize = 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;
 
185
 
186
  this._targetDistance = this._distance;
187
 
188
+ this.on('attr:distanceMin', function (value, prev) {
189
  this._distance = this._clampDistance(this._distance);
190
  });
191
+ this.on('attr:distanceMax', function (value, prev) {
192
  this._distance = this._clampDistance(this._distance);
193
  });
194
+ this.on('attr:pitchAngleMin', function (value, prev) {
195
  this._pitch = this._clampPitchAngle(this._pitch);
196
  });
197
+ this.on('attr:pitchAngleMax', function (value, prev) {
198
  this._pitch = this._clampPitchAngle(this._pitch);
199
  });
200
+ this.on('attr:focusEntity', function (value, prev) {
201
  if (this.frameOnStart) {
202
  this.focus(value || this.app.root);
203
  } else {
204
  this.resetAndLookAtEntity(this.entity.getPosition(), value || this.app.root);
205
  }
206
  });
207
+ this.on('attr:frameOnStart', function (value, prev) {
208
  if (value) {
209
  this.focus(this.focusEntity || this.app.root);
210
  }
 
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
  };
 
247
  };
248
 
249
  OrbitCamera.prototype._buildAabb = function (entity) {
250
+ var i, m, meshInstances = [];
251
  var renders = entity.findComponents('render');
252
+ for (i = 0; i < renders.length; i++) {
253
  var render = renders[i];
254
+ for (m = 0; m < render.meshInstances.length; m++) {
255
  meshInstances.push(render.meshInstances[m]);
256
  }
257
  }
 
264
  }
265
  var gsplats = entity.findComponents('gsplat');
266
  for (i = 0; i < gsplats.length; i++) {
267
+ var gsplat = gsplats[i];
268
+ var instance = gsplat.instance;
269
+ if (instance?.meshInstance) {
270
  meshInstances.push(instance.meshInstance);
271
  }
272
  }
 
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
  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
  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
+ ////////////////////////////////////////////////////////////////////////////////
331
+ var OrbitCameraInputMouse = pc.createScript('orbitCameraInputMouse');
332
+
333
+ OrbitCameraInputMouse.attributes.add('orbitSensitivity', {
334
+ type: 'number',
335
+ default: 0.3,
336
+ title: 'Orbit Sensitivity',
337
+ description: 'How fast the camera moves around the orbit. Higher is faster'
338
+ });
339
+ OrbitCameraInputMouse.attributes.add('distanceSensitivity', {
340
+ type: 'number',
341
+ default: 0.4,
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) {
348
+ var self = this;
349
+ var onMouseOut = function (e) { self.onMouseOut(e); };
350
+ this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
351
+ this.app.mouse.on(pc.EVENT_MOUSEUP, this.onMouseUp, this);
352
+ this.app.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
353
+ this.app.mouse.on(pc.EVENT_MOUSEWHEEL, this.onMouseWheel, this);
354
+ window.addEventListener('mouseout', onMouseOut, false);
355
+ this.on('destroy', function () {
356
+ this.app.mouse.off(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
357
+ this.app.mouse.off(pc.EVENT_MOUSEUP, this.onMouseUp, this);
358
+ this.app.mouse.off(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
359
+ this.app.mouse.off(pc.EVENT_MOUSEWHEEL, this.onMouseWheel, this);
360
+ window.removeEventListener('mouseout', onMouseOut, false);
361
+ });
362
+ }
363
+ this.app.mouse.disableContextMenu();
364
+ this.lookButtonDown = false;
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;
374
+ var worldDiff = OrbitCameraInputMouse.worldDiff;
375
+ var camera = this.entity.camera;
376
+ var distance = this.orbitCamera.distance;
377
+ camera.screenToWorld(screenPoint.x, screenPoint.y, distance, fromWorldPoint);
378
+ camera.screenToWorld(this.lastPoint.x, this.lastPoint.y, distance, toWorldPoint);
379
+ worldDiff.sub2(toWorldPoint, fromWorldPoint);
380
+ this.orbitCamera.pivotPoint.add(worldDiff);
381
+ var pitchRadians = this.orbitCamera.pitch * pc.math.DEG_TO_RAD;
382
+ var minPivotY = this.orbitCamera.distance * Math.sin(pitchRadians);
383
+ if (this.orbitCamera.pivotPoint.y < minPivotY) {
384
+ this.orbitCamera.pivotPoint.y = minPivotY;
385
+ }
386
+ };
387
+ OrbitCameraInputMouse.prototype.onMouseDown = function (event) {
388
+ switch (event.button) {
389
+ case pc.MOUSEBUTTON_LEFT:
390
+ this.panButtonDown = true;
391
+ break;
392
+ case pc.MOUSEBUTTON_MIDDLE:
393
+ case pc.MOUSEBUTTON_RIGHT:
394
+ this.lookButtonDown = true;
395
+ break;
396
+ }
397
+ };
398
+ OrbitCameraInputMouse.prototype.onMouseUp = function (event) {
399
+ switch (event.button) {
400
+ case pc.MOUSEBUTTON_LEFT:
401
+ this.panButtonDown = false;
402
+ break;
403
+ case pc.MOUSEBUTTON_MIDDLE:
404
+ case pc.MOUSEBUTTON_RIGHT:
405
+ this.lookButtonDown = false;
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);
421
+ } else {
422
+ this.orbitCamera.orthoHeight -= event.wheelDelta * this.distanceSensitivity * (this.orbitCamera.orthoHeight * 0.1);
423
+ }
424
+ event.event.preventDefault();
425
+ };
426
+ OrbitCameraInputMouse.prototype.onMouseOut = function (event) {
427
+ this.lookButtonDown = false;
428
+ this.panButtonDown = false;
429
+ };
430
+
431
+
432
+ ////////////////////////////////////////////////////////////////////////////////
433
+ // Orbit Camera Touch Input Script //
434
+ ////////////////////////////////////////////////////////////////////////////////
435
+ var OrbitCameraInputTouch = pc.createScript('orbitCameraInputTouch');
436
+
437
+ OrbitCameraInputTouch.attributes.add('orbitSensitivity', {
438
+ type: 'number',
439
+ default: 0.6,
440
+ title: 'Orbit Sensitivity',
441
+ description: 'How fast the camera moves around the orbit. Higher is faster'
442
+ });
443
+ OrbitCameraInputTouch.attributes.add('distanceSensitivity', {
444
+ type: 'number',
445
+ default: 0.5,
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();
452
+ this.lastPinchMidPoint = new pc.Vec2();
453
+ this.lastPinchDistance = 0;
454
+ if (this.orbitCamera && this.app.touch) {
455
+ this.app.touch.on(pc.EVENT_TOUCHSTART, this.onTouchStartEndCancel, this);
456
+ this.app.touch.on(pc.EVENT_TOUCHEND, this.onTouchStartEndCancel, this);
457
+ this.app.touch.on(pc.EVENT_TOUCHCANCEL, this.onTouchStartEndCancel, this);
458
+ this.app.touch.on(pc.EVENT_TOUCHMOVE, this.onTouchMove, this);
459
+ this.on('destroy', function () {
460
+ this.app.touch.off(pc.EVENT_TOUCHSTART, this.onTouchStartEndCancel, this);
461
+ this.app.touch.off(pc.EVENT_TOUCHEND, this.onTouchStartEndCancel, this);
462
+ this.app.touch.off(pc.EVENT_TOUCHCANCEL, this.onTouchStartEndCancel, this);
463
+ this.app.touch.off(pc.EVENT_TOUCHMOVE, this.onTouchMove, this);
464
+ });
465
+ }
466
+ };
467
+ OrbitCameraInputTouch.prototype.getPinchDistance = function (pointA, pointB) {
468
+ var dx = pointA.x - pointB.x;
469
+ var dy = pointA.y - pointB.y;
470
+ return Math.sqrt((dx * dx) + (dy * dy));
471
+ };
472
+ OrbitCameraInputTouch.prototype.calcMidPoint = function (pointA, pointB, result) {
473
+ result.set(pointB.x - pointA.x, pointB.y - pointA.y);
474
+ result.mulScalar(0.5);
475
+ result.x += pointA.x;
476
+ result.y += pointA.y;
477
+ };
478
+ OrbitCameraInputTouch.prototype.onTouchStartEndCancel = function (event) {
479
+ var touches = event.touches;
480
+ if (touches.length === 1) {
481
+ this.lastTouchPoint.set(touches[0].x, touches[0].y);
482
+ } else if (touches.length === 2) {
483
+ this.lastPinchDistance = this.getPinchDistance(touches[0], touches[1]);
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;
493
+ var worldDiff = OrbitCameraInputTouch.worldDiff;
494
+ var camera = this.entity.camera;
495
+ var distance = this.orbitCamera.distance;
496
+ camera.screenToWorld(midPoint.x, midPoint.y, distance, fromWorldPoint);
497
+ camera.screenToWorld(this.lastPinchMidPoint.x, this.lastPinchMidPoint.y, distance, toWorldPoint);
498
+ worldDiff.sub2(toWorldPoint, fromWorldPoint);
499
+ this.orbitCamera.pivotPoint.add(worldDiff);
500
+ var pitchRadians = this.orbitCamera.pitch * pc.math.DEG_TO_RAD;
501
+ var minPivotY = this.orbitCamera.distance * Math.sin(pitchRadians);
502
+ if (this.orbitCamera.pivotPoint.y < minPivotY) {
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
+ };