MikaFil commited on
Commit
f0e1251
·
verified ·
1 Parent(s): 5777589

Update deplacement_dans_env/ctrl_camera_pr_env.js

Browse files
deplacement_dans_env/ctrl_camera_pr_env.js CHANGED
@@ -1,8 +1,11 @@
1
  // ctrl_camera_pr_env.js
2
  // ============================================================================
3
- // ORBIT CAMERA + INPUTS (PlayCanvas) — version bbox + sans maxZoom
4
- // - Contraintes : minY (altitude min caméra), Bounding Box (X/Y/Z min/max)
5
- // - Zoom : seul un minimum est imposé (plus de maxZoom)
 
 
 
6
  // ============================================================================
7
 
8
  var OrbitCamera = pc.createScript('orbitCamera');
@@ -61,20 +64,16 @@ OrbitCamera.prototype.focus = function (focusEntity) {
61
  this._buildAabb(focusEntity);
62
  var halfExtents = this._modelsAabb.halfExtents;
63
  var radius = Math.max(halfExtents.x, Math.max(halfExtents.y, halfExtents.z));
64
-
65
- // calcule distance initiale (pas de maxZoom à respecter)
66
  this.distance = (radius * 1.5) / Math.sin(0.5 * this.entity.camera.fov * pc.math.DEG_TO_RAD);
67
-
68
  this._removeInertia();
69
  this._pivotPoint.copy(this._modelsAabb.center);
70
- this._clampPivotToBBox(this._pivotPoint);
71
  };
72
 
73
  OrbitCamera.distanceBetween = new pc.Vec3();
74
 
75
  OrbitCamera.prototype.resetAndLookAtPoint = function (resetPoint, lookAtPoint) {
76
  this.pivotPoint.copy(lookAtPoint);
77
- this._clampPivotToBBox(this._pivotPoint);
78
 
79
  this.entity.setPosition(resetPoint);
80
  this.entity.lookAt(lookAtPoint);
@@ -107,7 +106,6 @@ OrbitCamera.prototype.resetToPosition = function (position, lookAtPoint) {
107
  this.entity.setPosition(position);
108
  this.entity.lookAt(lookAtPoint);
109
  this._pivotPoint.copy(lookAtPoint);
110
- this._clampPivotToBBox(this._pivotPoint);
111
 
112
  var distanceVec = new pc.Vec3();
113
  distanceVec.sub2(position, lookAtPoint);
@@ -121,7 +119,7 @@ OrbitCamera.prototype.resetToPosition = function (position, lookAtPoint) {
121
  this._updatePosition();
122
  };
123
 
124
- // ==== Helper: calc cam Y if pivot became 'pivot' (used to enforce minY) ====
125
  OrbitCamera.prototype.worldCameraYForPivot = function(pivot) {
126
  var quat = new pc.Quat();
127
  quat.setFromEulerAngles(this._pitch, this._yaw, 0);
@@ -145,7 +143,6 @@ OrbitCamera.prototype.initialize = function () {
145
  this.entity.lookAt(this._modelsAabb.center);
146
  this._pivotPoint = new pc.Vec3();
147
  this._pivotPoint.copy(this._modelsAabb.center);
148
- this._clampPivotToBBox(this._pivotPoint);
149
 
150
  var cameraQuat = this.entity.getRotation();
151
  this._yaw = this._calcYaw(cameraQuat);
@@ -165,7 +162,7 @@ OrbitCamera.prototype.initialize = function () {
165
  }
166
  this._targetDistance = this._distance;
167
 
168
- // Listeners d’attributs (note: pas de distanceMax)
169
  this.on('attr:distanceMin', function () { this._distance = this._clampDistance(this._distance); });
170
  this.on('attr:pitchAngleMin', function () { this._pitch = this._clampPitchAngle(this._pitch); });
171
  this.on('attr:pitchAngleMax', function () { this._pitch = this._clampPitchAngle(this._pitch); });
@@ -179,10 +176,6 @@ OrbitCamera.prototype.initialize = function () {
179
  if (value) { this.focus(this.focusEntity || this.app.root); }
180
  });
181
 
182
- // Clamp bbox dynamique
183
- var bboxAttrs = ['Xmin','Xmax','Ymin','Ymax','Zmin','Zmax'];
184
- bboxAttrs.forEach((a)=> this.on('attr:'+a, function(){ this._clampPivotToBBox(this._pivotPoint); this._updatePosition(); }));
185
-
186
  this.on('destroy', function () { window.removeEventListener('resize', onWindowResize, false); });
187
  };
188
 
@@ -195,24 +188,33 @@ OrbitCamera.prototype.update = function (dt) {
195
  };
196
 
197
  OrbitCamera.prototype._updatePosition = function () {
 
198
  this.entity.setLocalPosition(0, 0, 0);
199
  this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);
200
 
201
- var position = this.entity.getPosition();
202
- position.copy(this.entity.forward);
203
- position.mulScalar(-this._distance);
204
- position.add(this.pivotPoint);
205
 
206
- // 1) altitude mini
207
- position.y = Math.max(position.y, this.minY);
 
 
208
 
209
- // 2) clamp BBox caméra
210
- this._applyBoundingBox(position);
 
211
 
212
- this.entity.setPosition(position);
 
213
 
214
- // 3) assure que le pivot reste dans la bbox
215
- this._clampPivotToBBox(this._pivotPoint);
 
 
 
 
 
216
  };
217
 
218
  OrbitCamera.prototype._removeInertia = function () {
@@ -268,7 +270,6 @@ OrbitCamera.prototype._calcYaw = function (quat) {
268
  };
269
 
270
  OrbitCamera.prototype._clampDistance = function (distance) {
271
- // Plus de distanceMax : uniquement un minimum
272
  return Math.max(distance, this.distanceMin);
273
  };
274
 
@@ -298,18 +299,22 @@ OrbitCamera.prototype._bboxEnabled = function () {
298
  return (this.Xmin < this.Xmax) && (this.Ymin < this.Ymax) && (this.Zmin < this.Zmax);
299
  };
300
 
 
 
 
 
301
  OrbitCamera.prototype._applyBoundingBox = function (v3 /* camera position */) {
302
- if (!this._bboxEnabled()) return;
303
- v3.x = pc.math.clamp(v3.x, this.Xmin, this.Xmax);
304
- v3.y = pc.math.clamp(v3.y, this.Ymin, this.Ymax);
305
- v3.z = pc.math.clamp(v3.z, this.Zmin, this.Zmax);
306
- };
 
307
 
308
- OrbitCamera.prototype._clampPivotToBBox = function (v3 /* pivot */) {
309
- if (!this._bboxEnabled()) return;
310
- v3.x = pc.math.clamp(v3.x, this.Xmin, this.Xmax);
311
- v3.y = pc.math.clamp(v3.y, this.Ymin, this.Ymax);
312
- v3.z = pc.math.clamp(v3.z, this.Zmin, this.Zmax);
313
  };
314
 
315
  // ===================== Orbit Camera Input Mouse ========================
@@ -358,26 +363,24 @@ OrbitCameraInputMouse.prototype.pan = function (screenPoint) {
358
  var camera = this.entity.camera;
359
  var distance = this.orbitCamera.distance;
360
 
361
- camera.screenToWorld(screenPoint.x, this.lastPoint.y, distance, fromWorldPoint);
362
  camera.screenToWorld(this.lastPoint.x, this.lastPoint.y, distance, toWorldPoint);
363
 
364
  worldDiff.sub2(toWorldPoint, fromWorldPoint);
365
 
366
- // Enforce minY + bbox via pivot
367
  var proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
368
- var minY = this.orbitCamera.minY;
369
- var resultingY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
370
 
371
- if (resultingY >= minY - 1e-4) {
372
- this.orbitCamera._clampPivotToBBox(proposedPivot);
 
373
  this.orbitCamera.pivotPoint.copy(proposedPivot);
374
  } else {
375
- // Horizontal-only si nécessaire
376
  worldDiff.y = 0;
377
  proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
378
- resultingY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
379
- if (resultingY >= minY - 1e-4) {
380
- this.orbitCamera._clampPivotToBBox(proposedPivot);
381
  this.orbitCamera.pivotPoint.copy(proposedPivot);
382
  }
383
  }
@@ -525,14 +528,12 @@ OrbitCameraInputTouch.prototype.pan = function (midPoint) {
525
  var resultingY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
526
 
527
  if (resultingY >= minY - 1e-4) {
528
- this.orbitCamera._clampPivotToBBox(proposedPivot);
529
  this.orbitCamera.pivotPoint.copy(proposedPivot);
530
  } else {
531
  worldDiff.y = 0;
532
  proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
533
  resultingY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
534
  if (resultingY >= minY - 1e-4) {
535
- this.orbitCamera._clampPivotToBBox(proposedPivot);
536
  this.orbitCamera.pivotPoint.copy(proposedPivot);
537
  }
538
  }
@@ -595,7 +596,7 @@ OrbitCameraInputTouch.prototype.onTouchMove = function (event) {
595
 
596
  // =================== Orbit Camera Input Keyboard ========================
597
  // Flèches : déplacement avant/arrière & droite/gauche (repère caméra, 3D)
598
- // Ctrl+flèches : orbiter autour du pivot
599
  // Maj+flèches : rotation libre sur place (pas de limites yaw/pitch)
600
  var OrbitCameraInputKeyboard = pc.createScript('orbitCameraInputKeyboard');
601
 
@@ -677,7 +678,6 @@ OrbitCameraInputKeyboard.prototype.update = function (dt) {
677
  var q = new pc.Quat().setFromEulerAngles(this.orbitCamera._pitch, this.orbitCamera._yaw, 0);
678
  var forward = new pc.Vec3(); q.transformVector(pc.Vec3.FORWARD, forward);
679
  var newPivot = camPos.clone().add(forward.clone().mulScalar(dist));
680
- this.orbitCamera._clampPivotToBBox(newPivot);
681
  this.orbitCamera._pivotPoint.copy(newPivot);
682
 
683
  this.orbitCamera._removeInertia();
@@ -712,8 +712,6 @@ OrbitCameraInputKeyboard.prototype.update = function (dt) {
712
  if (currCamY + delta.y < minY) {
713
  delta.y = minY - currCamY;
714
  }
715
- var newPivot = this.orbitCamera._pivotPoint.clone().add(delta);
716
- this.orbitCamera._clampPivotToBBox(newPivot);
717
- this.orbitCamera._pivotPoint.copy(newPivot);
718
  }
719
  };
 
1
  // ctrl_camera_pr_env.js
2
  // ============================================================================
3
+ // ORBIT CAMERA + INPUTS (PlayCanvas) — version bbox "rotation-libre"
4
+ // - Zoom : uniquement un minimum (pas de maxZoom)
5
+ // - Bounding Box : on contraint UNIQUEMENT la position caméra
6
+ // -> si la position sort, on la clampe puis on décale le pivot
7
+ // pour conserver l'orientation ET la distance (orbite fluide).
8
+ // - minY : altitude mini de la caméra (appliquée comme une "box" horizontale)
9
  // ============================================================================
10
 
11
  var OrbitCamera = pc.createScript('orbitCamera');
 
64
  this._buildAabb(focusEntity);
65
  var halfExtents = this._modelsAabb.halfExtents;
66
  var radius = Math.max(halfExtents.x, Math.max(halfExtents.y, halfExtents.z));
67
+ // Distance initiale (pas de maxZoom)
 
68
  this.distance = (radius * 1.5) / Math.sin(0.5 * this.entity.camera.fov * pc.math.DEG_TO_RAD);
 
69
  this._removeInertia();
70
  this._pivotPoint.copy(this._modelsAabb.center);
 
71
  };
72
 
73
  OrbitCamera.distanceBetween = new pc.Vec3();
74
 
75
  OrbitCamera.prototype.resetAndLookAtPoint = function (resetPoint, lookAtPoint) {
76
  this.pivotPoint.copy(lookAtPoint);
 
77
 
78
  this.entity.setPosition(resetPoint);
79
  this.entity.lookAt(lookAtPoint);
 
106
  this.entity.setPosition(position);
107
  this.entity.lookAt(lookAtPoint);
108
  this._pivotPoint.copy(lookAtPoint);
 
109
 
110
  var distanceVec = new pc.Vec3();
111
  distanceVec.sub2(position, lookAtPoint);
 
119
  this._updatePosition();
120
  };
121
 
122
+ // ==== Helper: cam Y si le pivot = 'pivot' (sert pour minY) ====
123
  OrbitCamera.prototype.worldCameraYForPivot = function(pivot) {
124
  var quat = new pc.Quat();
125
  quat.setFromEulerAngles(this._pitch, this._yaw, 0);
 
143
  this.entity.lookAt(this._modelsAabb.center);
144
  this._pivotPoint = new pc.Vec3();
145
  this._pivotPoint.copy(this._modelsAabb.center);
 
146
 
147
  var cameraQuat = this.entity.getRotation();
148
  this._yaw = this._calcYaw(cameraQuat);
 
162
  }
163
  this._targetDistance = this._distance;
164
 
165
+ // Listeners d’attributs
166
  this.on('attr:distanceMin', function () { this._distance = this._clampDistance(this._distance); });
167
  this.on('attr:pitchAngleMin', function () { this._pitch = this._clampPitchAngle(this._pitch); });
168
  this.on('attr:pitchAngleMax', function () { this._pitch = this._clampPitchAngle(this._pitch); });
 
176
  if (value) { this.focus(this.focusEntity || this.app.root); }
177
  });
178
 
 
 
 
 
179
  this.on('destroy', function () { window.removeEventListener('resize', onWindowResize, false); });
180
  };
181
 
 
188
  };
189
 
190
  OrbitCamera.prototype._updatePosition = function () {
191
+ // 1) oriente la caméra
192
  this.entity.setLocalPosition(0, 0, 0);
193
  this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);
194
 
195
+ // 2) calcule la position théorique en fonction du pivot et de la distance
196
+ var forward = this.entity.forward.clone(); // direction de visée
197
+ var desired = this._pivotPoint.clone().add(forward.clone().mulScalar(-this._distance));
 
198
 
199
+ // 3) applique minY (comme un plan horizontal)
200
+ if (desired.y < this.minY) {
201
+ desired.y = this.minY;
202
+ }
203
 
204
+ // 4) contraint UNIQUEMENT la position caméra à la bbox
205
+ var clamped = desired.clone();
206
+ var wasClamped = this._applyBoundingBox(clamped); // retourne true si clamp effectué
207
 
208
+ // 5) positionne la caméra
209
+ this.entity.setPosition(clamped);
210
 
211
+ // 6) si clamp (bbox ou minY), on recalcule un pivot cohérent sur le même rayon
212
+ // (préserve orientation + distance => rotation reste fluide au contact)
213
+ if (wasClamped || clamped.y !== desired.y) {
214
+ // forward pointe de la caméra vers la scène
215
+ // pos = pivot - forward * distance => pivot = pos + forward * distance
216
+ this._pivotPoint.copy(clamped.clone().add(forward.mulScalar(this._distance)));
217
+ }
218
  };
219
 
220
  OrbitCamera.prototype._removeInertia = function () {
 
270
  };
271
 
272
  OrbitCamera.prototype._clampDistance = function (distance) {
 
273
  return Math.max(distance, this.distanceMin);
274
  };
275
 
 
299
  return (this.Xmin < this.Xmax) && (this.Ymin < this.Ymax) && (this.Zmin < this.Zmax);
300
  };
301
 
302
+ /**
303
+ * Contrainte position caméra à la bbox.
304
+ * @returns {boolean} true si un clamp a été appliqué
305
+ */
306
  OrbitCamera.prototype._applyBoundingBox = function (v3 /* camera position */) {
307
+ if (!this._bboxEnabled()) return false;
308
+
309
+ var clamped = false;
310
+ var nx = pc.math.clamp(v3.x, this.Xmin, this.Xmax);
311
+ var ny = pc.math.clamp(v3.y, this.Ymin, this.Ymax);
312
+ var nz = pc.math.clamp(v3.z, this.Zmin, this.Zmax);
313
 
314
+ if (nx !== v3.x || ny !== v3.y || nz !== v3.z) clamped = true;
315
+
316
+ v3.x = nx; v3.y = ny; v3.z = nz;
317
+ return clamped;
 
318
  };
319
 
320
  // ===================== Orbit Camera Input Mouse ========================
 
363
  var camera = this.entity.camera;
364
  var distance = this.orbitCamera.distance;
365
 
366
+ camera.screenToWorld(screenPoint.x, screenPoint.y, distance, fromWorldPoint);
367
  camera.screenToWorld(this.lastPoint.x, this.lastPoint.y, distance, toWorldPoint);
368
 
369
  worldDiff.sub2(toWorldPoint, fromWorldPoint);
370
 
371
+ // Enforce minY via test sur la position caméra résultante
372
  var proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
 
 
373
 
374
+ // calcule Y caméra si on acceptait ce pivot (sans bbox ici)
375
+ var camY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
376
+ if (camY >= this.orbitCamera.minY - 1e-4) {
377
  this.orbitCamera.pivotPoint.copy(proposedPivot);
378
  } else {
379
+ // Essai horizontal-only
380
  worldDiff.y = 0;
381
  proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
382
+ camY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
383
+ if (camY >= this.orbitCamera.minY - 1e-4) {
 
384
  this.orbitCamera.pivotPoint.copy(proposedPivot);
385
  }
386
  }
 
528
  var resultingY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
529
 
530
  if (resultingY >= minY - 1e-4) {
 
531
  this.orbitCamera.pivotPoint.copy(proposedPivot);
532
  } else {
533
  worldDiff.y = 0;
534
  proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
535
  resultingY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
536
  if (resultingY >= minY - 1e-4) {
 
537
  this.orbitCamera.pivotPoint.copy(proposedPivot);
538
  }
539
  }
 
596
 
597
  // =================== Orbit Camera Input Keyboard ========================
598
  // Flèches : déplacement avant/arrière & droite/gauche (repère caméra, 3D)
599
+ // Ctrl+flèches : orbiter autour du pivot (avec test minY)
600
  // Maj+flèches : rotation libre sur place (pas de limites yaw/pitch)
601
  var OrbitCameraInputKeyboard = pc.createScript('orbitCameraInputKeyboard');
602
 
 
678
  var q = new pc.Quat().setFromEulerAngles(this.orbitCamera._pitch, this.orbitCamera._yaw, 0);
679
  var forward = new pc.Vec3(); q.transformVector(pc.Vec3.FORWARD, forward);
680
  var newPivot = camPos.clone().add(forward.clone().mulScalar(dist));
 
681
  this.orbitCamera._pivotPoint.copy(newPivot);
682
 
683
  this.orbitCamera._removeInertia();
 
712
  if (currCamY + delta.y < minY) {
713
  delta.y = minY - currCamY;
714
  }
715
+ this.orbitCamera._pivotPoint.add(delta);
 
 
716
  }
717
  };