Spaces:
Running
Running
Update deplacement_dans_env/ctrl_camera_pr_env.js
Browse files
deplacement_dans_env/ctrl_camera_pr_env.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
| 1 |
// ctrl_camera_pr_env.js
|
| 2 |
// ============================================================================
|
| 3 |
-
// ORBIT CAMERA + INPUTS (PlayCanvas) —
|
| 4 |
// - Zoom : uniquement un minimum (pas de maxZoom)
|
| 5 |
-
// - Bounding Box :
|
| 6 |
-
//
|
| 7 |
-
//
|
| 8 |
-
// - minY : altitude mini de la caméra (appliquée comme une "box" horizontale)
|
| 9 |
// ============================================================================
|
| 10 |
|
| 11 |
var OrbitCamera = pc.createScript('orbitCamera');
|
|
@@ -16,8 +15,9 @@ OrbitCamera.attributes.add('distanceMin', { type: 'number', default: 1, titl
|
|
| 16 |
OrbitCamera.attributes.add('pitchAngleMax', { type: 'number', default: 90, title: 'Pitch Angle Max (degrees)' });
|
| 17 |
OrbitCamera.attributes.add('pitchAngleMin', { type: 'number', default: 0, title: 'Pitch Angle Min (degrees)' });
|
| 18 |
|
| 19 |
-
|
| 20 |
-
OrbitCamera.attributes.add('
|
|
|
|
| 21 |
|
| 22 |
OrbitCamera.attributes.add('minY', { type: 'number', default: 0, title: 'Minimum Y (camera world Y)' });
|
| 23 |
|
|
@@ -51,7 +51,10 @@ Object.defineProperty(OrbitCamera.prototype, 'pitch', {
|
|
| 51 |
|
| 52 |
Object.defineProperty(OrbitCamera.prototype, 'yaw', {
|
| 53 |
get: function () { return this._targetYaw; },
|
| 54 |
-
set: function (value) {
|
|
|
|
|
|
|
|
|
|
| 55 |
});
|
| 56 |
|
| 57 |
Object.defineProperty(OrbitCamera.prototype, 'pivotPoint', {
|
|
@@ -196,22 +199,20 @@ OrbitCamera.prototype._updatePosition = function () {
|
|
| 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 (
|
| 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); //
|
| 207 |
|
| 208 |
-
// 5)
|
| 209 |
this.entity.setPosition(clamped);
|
| 210 |
|
| 211 |
-
// 6) si clamp (bbox
|
| 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 |
}
|
|
@@ -266,7 +267,8 @@ OrbitCamera.prototype._buildAabb = function (entity) {
|
|
| 266 |
OrbitCamera.prototype._calcYaw = function (quat) {
|
| 267 |
var transformedForward = new pc.Vec3();
|
| 268 |
quat.transformVector(pc.Vec3.FORWARD, transformedForward);
|
| 269 |
-
|
|
|
|
| 270 |
};
|
| 271 |
|
| 272 |
OrbitCamera.prototype._clampDistance = function (distance) {
|
|
@@ -277,9 +279,8 @@ OrbitCamera.prototype._clampPitchAngle = function (pitch) {
|
|
| 277 |
return pc.math.clamp(pitch, this.pitchAngleMin, this.pitchAngleMax);
|
| 278 |
};
|
| 279 |
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
};
|
| 283 |
|
| 284 |
OrbitCamera.quatWithoutYaw = new pc.Quat();
|
| 285 |
OrbitCamera.yawOffset = new pc.Quat();
|
|
@@ -299,20 +300,14 @@ OrbitCamera.prototype._bboxEnabled = function () {
|
|
| 299 |
return (this.Xmin < this.Xmax) && (this.Ymin < this.Ymax) && (this.Zmin < this.Zmax);
|
| 300 |
};
|
| 301 |
|
| 302 |
-
/**
|
| 303 |
-
|
| 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 |
};
|
|
@@ -368,15 +363,13 @@ OrbitCameraInputMouse.prototype.pan = function (screenPoint) {
|
|
| 368 |
|
| 369 |
worldDiff.sub2(toWorldPoint, fromWorldPoint);
|
| 370 |
|
| 371 |
-
//
|
| 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);
|
|
@@ -406,8 +399,10 @@ OrbitCameraInputMouse.prototype.onMouseMove = function (event) {
|
|
| 406 |
if (this.lookButtonDown) {
|
| 407 |
var sens = this.orbitSensitivity;
|
| 408 |
|
| 409 |
-
|
| 410 |
var deltaYaw = event.dx * sens;
|
|
|
|
|
|
|
| 411 |
|
| 412 |
var currPitch = this.orbitCamera.pitch;
|
| 413 |
var currYaw = this.orbitCamera.yaw;
|
|
@@ -420,22 +415,26 @@ OrbitCameraInputMouse.prototype.onMouseMove = function (event) {
|
|
| 420 |
camQuat.transformVector(pc.Vec3.FORWARD, forward);
|
| 421 |
var preY = currPivot.y + (-forward.y) * currDist;
|
| 422 |
|
|
|
|
|
|
|
|
|
|
| 423 |
var proposedPitch = currPitch - deltaPitch;
|
| 424 |
-
var
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
testQuat.
|
|
|
|
| 428 |
var proposedY = currPivot.y + (-testForward.y) * currDist;
|
| 429 |
|
| 430 |
var minY = this.orbitCamera.minY;
|
| 431 |
var wouldGoBelow = proposedY < minY - 1e-4;
|
| 432 |
|
| 433 |
-
if (wouldGoBelow && (proposedY < preY)) {
|
| 434 |
-
this.orbitCamera.yaw = currYaw - deltaYaw;
|
| 435 |
-
} else {
|
| 436 |
this.orbitCamera.pitch = proposedPitch;
|
| 437 |
-
this.orbitCamera.yaw = currYaw - deltaYaw;
|
| 438 |
}
|
|
|
|
|
|
|
|
|
|
| 439 |
} else if (this.panButtonDown) {
|
| 440 |
this.pan(new pc.Vec2(event.x, event.y));
|
| 441 |
}
|
|
@@ -549,36 +548,33 @@ OrbitCameraInputTouch.prototype.onTouchMove = function (event) {
|
|
| 549 |
var touch = touches[0];
|
| 550 |
var sens = this.orbitSensitivity;
|
| 551 |
|
| 552 |
-
var deltaPitch = (touch.y - this.lastTouchPoint.y) * sens;
|
| 553 |
var deltaYaw = (touch.x - this.lastTouchPoint.x) * sens;
|
|
|
|
| 554 |
|
| 555 |
var currPitch = this.orbitCamera.pitch;
|
| 556 |
var currYaw = this.orbitCamera.yaw;
|
| 557 |
var currDist = this.orbitCamera.distance;
|
| 558 |
var currPivot = this.orbitCamera.pivotPoint.clone();
|
| 559 |
|
| 560 |
-
var camQuat = new pc.Quat();
|
| 561 |
-
camQuat.
|
| 562 |
-
var forward = new pc.Vec3();
|
| 563 |
-
camQuat.transformVector(pc.Vec3.FORWARD, forward);
|
| 564 |
var preY = currPivot.y + (-forward.y) * currDist;
|
| 565 |
|
|
|
|
| 566 |
var proposedPitch = currPitch - deltaPitch;
|
| 567 |
-
var
|
| 568 |
-
|
| 569 |
-
var
|
| 570 |
-
testQuat.transformVector(pc.Vec3.FORWARD, testForward);
|
| 571 |
var proposedY = currPivot.y + (-testForward.y) * currDist;
|
| 572 |
|
| 573 |
var minY = this.orbitCamera.minY;
|
| 574 |
var wouldGoBelow = proposedY < minY - 1e-4;
|
| 575 |
|
| 576 |
-
if (wouldGoBelow && (proposedY < preY)) {
|
| 577 |
-
this.orbitCamera.yaw = currYaw - deltaYaw;
|
| 578 |
-
} else {
|
| 579 |
this.orbitCamera.pitch = proposedPitch;
|
| 580 |
-
this.orbitCamera.yaw = currYaw - deltaYaw;
|
| 581 |
}
|
|
|
|
| 582 |
|
| 583 |
this.lastTouchPoint.set(touch.x, touch.y);
|
| 584 |
} else if (touches.length === 2) {
|
|
@@ -596,7 +592,7 @@ OrbitCameraInputTouch.prototype.onTouchMove = function (event) {
|
|
| 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 (
|
| 600 |
// Maj+flèches : rotation libre sur place (pas de limites yaw/pitch)
|
| 601 |
var OrbitCameraInputKeyboard = pc.createScript('orbitCameraInputKeyboard');
|
| 602 |
|
|
@@ -628,14 +624,15 @@ OrbitCameraInputKeyboard.prototype.update = function (dt) {
|
|
| 628 |
|
| 629 |
// -------- Ctrl + flèches : ORBIT autour du pivot --------
|
| 630 |
if (ctrl && (up || dn || lt || rt)) {
|
| 631 |
-
|
| 632 |
-
var
|
|
|
|
| 633 |
|
| 634 |
-
if (
|
| 635 |
-
this.orbitCamera.yaw = this.orbitCamera.yaw +
|
| 636 |
}
|
| 637 |
|
| 638 |
-
if (
|
| 639 |
var currPitch = this.orbitCamera.pitch;
|
| 640 |
var currYaw = this.orbitCamera.yaw;
|
| 641 |
var currDist = this.orbitCamera.distance;
|
|
@@ -645,7 +642,7 @@ OrbitCameraInputKeyboard.prototype.update = function (dt) {
|
|
| 645 |
var forward = new pc.Vec3(); camQuat.transformVector(pc.Vec3.FORWARD, forward);
|
| 646 |
var preY = currPivot.y + (-forward.y) * currDist;
|
| 647 |
|
| 648 |
-
var testPitch = currPitch +
|
| 649 |
var testQuat = new pc.Quat().setFromEulerAngles(testPitch, currYaw, 0);
|
| 650 |
var testForward = new pc.Vec3(); testQuat.transformVector(pc.Vec3.FORWARD, testForward);
|
| 651 |
var proposedY = currPivot.y + (-testForward.y) * currDist;
|
|
@@ -662,8 +659,8 @@ OrbitCameraInputKeyboard.prototype.update = function (dt) {
|
|
| 662 |
|
| 663 |
// -------- Maj + flèches : ROTATION SUR PLACE --------
|
| 664 |
if (shift && (up || dn || lt || rt)) {
|
| 665 |
-
var yawDirR = (
|
| 666 |
-
var pitchDirR = (up ? 1 : 0) - (dn ? 1 : 0);
|
| 667 |
|
| 668 |
var camPos = this.entity.getPosition().clone();
|
| 669 |
var dist = this.orbitCamera._distance;
|
|
|
|
| 1 |
// ctrl_camera_pr_env.js
|
| 2 |
// ============================================================================
|
| 3 |
+
// ORBIT CAMERA + INPUTS (PlayCanvas) — bbox + rotation libre & sens corrigés
|
| 4 |
// - Zoom : uniquement un minimum (pas de maxZoom)
|
| 5 |
+
// - Bounding Box : clamp SEULEMENT la position caméra, jamais l'orientation
|
| 6 |
+
// - Yaw : pas de clamp -> rotations illimitées (±2000° etc.)
|
| 7 |
+
// - Pitch : clamp via min/max (configurable), minY préservé
|
|
|
|
| 8 |
// ============================================================================
|
| 9 |
|
| 10 |
var OrbitCamera = pc.createScript('orbitCamera');
|
|
|
|
| 15 |
OrbitCamera.attributes.add('pitchAngleMax', { type: 'number', default: 90, title: 'Pitch Angle Max (degrees)' });
|
| 16 |
OrbitCamera.attributes.add('pitchAngleMin', { type: 'number', default: 0, title: 'Pitch Angle Min (degrees)' });
|
| 17 |
|
| 18 |
+
// NB: gardés pour compat, mais non utilisés pour brider le yaw (rotation libre)
|
| 19 |
+
OrbitCamera.attributes.add('yawAngleMax', { type: 'number', default: 360, title: 'Yaw Angle Max (unused clamp)' });
|
| 20 |
+
OrbitCamera.attributes.add('yawAngleMin', { type: 'number', default: -360, title: 'Yaw Angle Min (unused clamp)' });
|
| 21 |
|
| 22 |
OrbitCamera.attributes.add('minY', { type: 'number', default: 0, title: 'Minimum Y (camera world Y)' });
|
| 23 |
|
|
|
|
| 51 |
|
| 52 |
Object.defineProperty(OrbitCamera.prototype, 'yaw', {
|
| 53 |
get: function () { return this._targetYaw; },
|
| 54 |
+
set: function (value) {
|
| 55 |
+
// Yaw LIBRE : pas de clamp pour permettre ±2000°, etc.
|
| 56 |
+
this._targetYaw = value;
|
| 57 |
+
}
|
| 58 |
});
|
| 59 |
|
| 60 |
Object.defineProperty(OrbitCamera.prototype, 'pivotPoint', {
|
|
|
|
| 199 |
var forward = this.entity.forward.clone(); // direction de visée
|
| 200 |
var desired = this._pivotPoint.clone().add(forward.clone().mulScalar(-this._distance));
|
| 201 |
|
| 202 |
+
// 3) applique minY (plan horizontal)
|
| 203 |
if (desired.y < this.minY) {
|
| 204 |
desired.y = this.minY;
|
| 205 |
}
|
| 206 |
|
| 207 |
// 4) contraint UNIQUEMENT la position caméra à la bbox
|
| 208 |
var clamped = desired.clone();
|
| 209 |
+
var wasClamped = this._applyBoundingBox(clamped); // true si clamp
|
| 210 |
|
| 211 |
+
// 5) place la caméra
|
| 212 |
this.entity.setPosition(clamped);
|
| 213 |
|
| 214 |
+
// 6) si clamp (bbox/minY), recalcule un pivot cohérent sur le même rayon
|
|
|
|
| 215 |
if (wasClamped || clamped.y !== desired.y) {
|
|
|
|
| 216 |
// pos = pivot - forward * distance => pivot = pos + forward * distance
|
| 217 |
this._pivotPoint.copy(clamped.clone().add(forward.mulScalar(this._distance)));
|
| 218 |
}
|
|
|
|
| 267 |
OrbitCamera.prototype._calcYaw = function (quat) {
|
| 268 |
var transformedForward = new pc.Vec3();
|
| 269 |
quat.transformVector(pc.Vec3.FORWARD, transformedForward);
|
| 270 |
+
// Convention: yaw croissant = rotation CCW vue de dessus
|
| 271 |
+
return Math.atan2(transformedForward.x, transformedForward.z) * pc.math.RAD_TO_DEG;
|
| 272 |
};
|
| 273 |
|
| 274 |
OrbitCamera.prototype._clampDistance = function (distance) {
|
|
|
|
| 279 |
return pc.math.clamp(pitch, this.pitchAngleMin, this.pitchAngleMax);
|
| 280 |
};
|
| 281 |
|
| 282 |
+
// Yaw: pas de clamp (rotation libre)
|
| 283 |
+
OrbitCamera.prototype._clampYawAngle = function (yaw) { return yaw; };
|
|
|
|
| 284 |
|
| 285 |
OrbitCamera.quatWithoutYaw = new pc.Quat();
|
| 286 |
OrbitCamera.yawOffset = new pc.Quat();
|
|
|
|
| 300 |
return (this.Xmin < this.Xmax) && (this.Ymin < this.Ymax) && (this.Zmin < this.Zmax);
|
| 301 |
};
|
| 302 |
|
| 303 |
+
/** Clamp position caméra à la bbox. @returns {boolean} true si clamp appliqué */
|
| 304 |
+
OrbitCamera.prototype._applyBoundingBox = function (v3) {
|
|
|
|
|
|
|
|
|
|
| 305 |
if (!this._bboxEnabled()) return false;
|
|
|
|
| 306 |
var clamped = false;
|
| 307 |
var nx = pc.math.clamp(v3.x, this.Xmin, this.Xmax);
|
| 308 |
var ny = pc.math.clamp(v3.y, this.Ymin, this.Ymax);
|
| 309 |
var nz = pc.math.clamp(v3.z, this.Zmin, this.Zmax);
|
|
|
|
| 310 |
if (nx !== v3.x || ny !== v3.y || nz !== v3.z) clamped = true;
|
|
|
|
| 311 |
v3.x = nx; v3.y = ny; v3.z = nz;
|
| 312 |
return clamped;
|
| 313 |
};
|
|
|
|
| 363 |
|
| 364 |
worldDiff.sub2(toWorldPoint, fromWorldPoint);
|
| 365 |
|
| 366 |
+
// minY via test sur la position caméra résultante
|
| 367 |
var proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
|
|
|
|
|
|
|
| 368 |
var camY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
|
| 369 |
+
|
| 370 |
if (camY >= this.orbitCamera.minY - 1e-4) {
|
| 371 |
this.orbitCamera.pivotPoint.copy(proposedPivot);
|
| 372 |
} else {
|
|
|
|
| 373 |
worldDiff.y = 0;
|
| 374 |
proposedPivot = this.orbitCamera.pivotPoint.clone().add(worldDiff);
|
| 375 |
camY = this.orbitCamera.worldCameraYForPivot(proposedPivot);
|
|
|
|
| 399 |
if (this.lookButtonDown) {
|
| 400 |
var sens = this.orbitSensitivity;
|
| 401 |
|
| 402 |
+
// Souris : droite => orbite à droite ; gauche => orbite à gauche
|
| 403 |
var deltaYaw = event.dx * sens;
|
| 404 |
+
// Pitch : dy<0 (monte) => pitch augmente (look up)
|
| 405 |
+
var deltaPitch = event.dy * sens;
|
| 406 |
|
| 407 |
var currPitch = this.orbitCamera.pitch;
|
| 408 |
var currYaw = this.orbitCamera.yaw;
|
|
|
|
| 415 |
camQuat.transformVector(pc.Vec3.FORWARD, forward);
|
| 416 |
var preY = currPivot.y + (-forward.y) * currDist;
|
| 417 |
|
| 418 |
+
// Conventions:
|
| 419 |
+
// - Yaw: +deltaYaw = tourner gauche (CCW). On veut "drag droite => tourner droite (CW)" -> yaw -= deltaYaw
|
| 420 |
+
// - Pitch: "drag haut (dy<0) => look up" -> pitch -= deltaPitch (car deltaPitch<0)
|
| 421 |
var proposedPitch = currPitch - deltaPitch;
|
| 422 |
+
var proposedYaw = currYaw - deltaYaw;
|
| 423 |
+
|
| 424 |
+
// Vérif minY pour pitch uniquement (comme avant)
|
| 425 |
+
var testQuat = new pc.Quat().setFromEulerAngles(proposedPitch, currYaw, 0);
|
| 426 |
+
var testForward = new pc.Vec3(); testQuat.transformVector(pc.Vec3.FORWARD, testForward);
|
| 427 |
var proposedY = currPivot.y + (-testForward.y) * currDist;
|
| 428 |
|
| 429 |
var minY = this.orbitCamera.minY;
|
| 430 |
var wouldGoBelow = proposedY < minY - 1e-4;
|
| 431 |
|
| 432 |
+
if (!(wouldGoBelow && (proposedY < preY))) {
|
|
|
|
|
|
|
| 433 |
this.orbitCamera.pitch = proposedPitch;
|
|
|
|
| 434 |
}
|
| 435 |
+
// Yaw toujours libre
|
| 436 |
+
this.orbitCamera.yaw = proposedYaw;
|
| 437 |
+
|
| 438 |
} else if (this.panButtonDown) {
|
| 439 |
this.pan(new pc.Vec2(event.x, event.y));
|
| 440 |
}
|
|
|
|
| 548 |
var touch = touches[0];
|
| 549 |
var sens = this.orbitSensitivity;
|
| 550 |
|
|
|
|
| 551 |
var deltaYaw = (touch.x - this.lastTouchPoint.x) * sens;
|
| 552 |
+
var deltaPitch = (touch.y - this.lastTouchPoint.y) * sens;
|
| 553 |
|
| 554 |
var currPitch = this.orbitCamera.pitch;
|
| 555 |
var currYaw = this.orbitCamera.yaw;
|
| 556 |
var currDist = this.orbitCamera.distance;
|
| 557 |
var currPivot = this.orbitCamera.pivotPoint.clone();
|
| 558 |
|
| 559 |
+
var camQuat = new pc.Quat().setFromEulerAngles(currPitch, currYaw, 0);
|
| 560 |
+
var forward = new pc.Vec3(); camQuat.transformVector(pc.Vec3.FORWARD, forward);
|
|
|
|
|
|
|
| 561 |
var preY = currPivot.y + (-forward.y) * currDist;
|
| 562 |
|
| 563 |
+
// mêmes conventions que souris
|
| 564 |
var proposedPitch = currPitch - deltaPitch;
|
| 565 |
+
var proposedYaw = currYaw - deltaYaw;
|
| 566 |
+
|
| 567 |
+
var testQuat = new pc.Quat().setFromEulerAngles(proposedPitch, currYaw, 0);
|
| 568 |
+
var testForward = new pc.Vec3(); testQuat.transformVector(pc.Vec3.FORWARD, testForward);
|
| 569 |
var proposedY = currPivot.y + (-testForward.y) * currDist;
|
| 570 |
|
| 571 |
var minY = this.orbitCamera.minY;
|
| 572 |
var wouldGoBelow = proposedY < minY - 1e-4;
|
| 573 |
|
| 574 |
+
if (!(wouldGoBelow && (proposedY < preY))) {
|
|
|
|
|
|
|
| 575 |
this.orbitCamera.pitch = proposedPitch;
|
|
|
|
| 576 |
}
|
| 577 |
+
this.orbitCamera.yaw = proposedYaw;
|
| 578 |
|
| 579 |
this.lastTouchPoint.set(touch.x, touch.y);
|
| 580 |
} else if (touches.length === 2) {
|
|
|
|
| 592 |
|
| 593 |
// =================== Orbit Camera Input Keyboard ========================
|
| 594 |
// Flèches : déplacement avant/arrière & droite/gauche (repère caméra, 3D)
|
| 595 |
+
// Ctrl+flèches : orbiter autour du pivot (sens conforme ← CCW / → CW)
|
| 596 |
// Maj+flèches : rotation libre sur place (pas de limites yaw/pitch)
|
| 597 |
var OrbitCameraInputKeyboard = pc.createScript('orbitCameraInputKeyboard');
|
| 598 |
|
|
|
|
| 624 |
|
| 625 |
// -------- Ctrl + flèches : ORBIT autour du pivot --------
|
| 626 |
if (ctrl && (up || dn || lt || rt)) {
|
| 627 |
+
// Convention : ← = CCW => yaw augmente ; → = CW => yaw diminue
|
| 628 |
+
var yawDirLeftRight = (lt ? 1 : 0) - (rt ? 1 : 0); // ← +1, → -1
|
| 629 |
+
var pitchDirUpDown = (up ? 1 : 0) - (dn ? 1 : 0); // ↑ +1, ↓ -1
|
| 630 |
|
| 631 |
+
if (yawDirLeftRight !== 0) {
|
| 632 |
+
this.orbitCamera.yaw = this.orbitCamera.yaw + yawDirLeftRight * this.orbitYawSpeedDeg * dt;
|
| 633 |
}
|
| 634 |
|
| 635 |
+
if (pitchDirUpDown !== 0) {
|
| 636 |
var currPitch = this.orbitCamera.pitch;
|
| 637 |
var currYaw = this.orbitCamera.yaw;
|
| 638 |
var currDist = this.orbitCamera.distance;
|
|
|
|
| 642 |
var forward = new pc.Vec3(); camQuat.transformVector(pc.Vec3.FORWARD, forward);
|
| 643 |
var preY = currPivot.y + (-forward.y) * currDist;
|
| 644 |
|
| 645 |
+
var testPitch = currPitch + pitchDirUpDown * this.orbitPitchSpeedDeg * dt;
|
| 646 |
var testQuat = new pc.Quat().setFromEulerAngles(testPitch, currYaw, 0);
|
| 647 |
var testForward = new pc.Vec3(); testQuat.transformVector(pc.Vec3.FORWARD, testForward);
|
| 648 |
var proposedY = currPivot.y + (-testForward.y) * currDist;
|
|
|
|
| 659 |
|
| 660 |
// -------- Maj + flèches : ROTATION SUR PLACE --------
|
| 661 |
if (shift && (up || dn || lt || rt)) {
|
| 662 |
+
var yawDirR = (lt ? 1 : 0) - (rt ? 1 : 0); // ← +1 (CCW), → -1 (CW)
|
| 663 |
+
var pitchDirR = (up ? 1 : 0) - (dn ? 1 : 0); // ↑ +1, ↓ -1
|
| 664 |
|
| 665 |
var camPos = this.entity.getPosition().clone();
|
| 666 |
var dist = this.orbitCamera._distance;
|