// orbit-camera.js // ============================== console.log('[OrbitFILE] loaded orbit-camera.js'); // preuve que le fichier est bien chargé /* * PlayCanvas Orbit Camera for GSplat/SOGS/GLB viewers. * - Handles min/max zoom, pitch, yaw, minY (don't go below ground) * - Mouse, touch & keyboard controls (orbit, pan, zoom) * - Attributes are auto-injected by viewer.js */ var OrbitCamera = pc.createScript('orbitCamera'); OrbitCamera.attributes.add('distanceMax', { type: 'number', default: 20, title: 'Distance Max' }); OrbitCamera.attributes.add('distanceMin', { type: 'number', default: 1, title: 'Distance Min' }); OrbitCamera.attributes.add('pitchAngleMax', { type: 'number', default: 90, title: 'Pitch Angle Max (degrees)' }); OrbitCamera.attributes.add('pitchAngleMin', { type: 'number', default: 0, title: 'Pitch Angle Min (degrees)' }); OrbitCamera.attributes.add('yawAngleMax', { type: 'number', default: 360, title: 'Yaw Angle Max (degrees)' }); OrbitCamera.attributes.add('yawAngleMin', { type: 'number', default: -360,title: 'Yaw Angle Min (degrees)' }); OrbitCamera.attributes.add('minY', { type: 'number', default: 0, title: 'Minimum Y' }); OrbitCamera.attributes.add('inertiaFactor', { type: 'number', default: 0.2, title: 'Inertia Factor' }); OrbitCamera.attributes.add('focusEntity', { type: 'entity', title: 'Focus Entity' }); OrbitCamera.attributes.add('frameOnStart', { type: 'boolean', default: true, title: 'Frame on Start' }); Object.defineProperty(OrbitCamera.prototype, 'distance', { get: function () { return this._targetDistance; }, set: function (value) { this._targetDistance = this._clampDistance(value); } }); Object.defineProperty(OrbitCamera.prototype, 'pitch', { get: function () { return this._targetPitch; }, set: function (value) { this._targetPitch = this._clampPitchAngle(value); } }); Object.defineProperty(OrbitCamera.prototype, 'yaw', { get: function () { return this._targetYaw; }, set: function (value) { this._targetYaw = this._clampYawAngle(value); } }); Object.defineProperty(OrbitCamera.prototype, 'pivotPoint', { get: function () { return this._pivotPoint; }, set: function (value) { this._pivotPoint.copy(value); } }); OrbitCamera.prototype.focus = function (focusEntity) { this._buildAabb(focusEntity); var halfExtents = this._modelsAabb.halfExtents; var radius = Math.max(halfExtents.x, Math.max(halfExtents.y, halfExtents.z)); this.distance = (radius * 1.5) / Math.sin(0.5 * this.entity.camera.fov * pc.math.DEG_TO_RAD); this._removeInertia(); this._pivotPoint.copy(this._modelsAabb.center); }; OrbitCamera.distanceBetween = new pc.Vec3(); OrbitCamera.prototype.resetAndLookAtPoint = function (resetPoint, lookAtPoint) { this.pivotPoint.copy(lookAtPoint); this.entity.setPosition(resetPoint); this.entity.lookAt(lookAtPoint); var distance = OrbitCamera.distanceBetween; distance.sub2(lookAtPoint, resetPoint); this.distance = distance.length(); this.pivotPoint.copy(lookAtPoint); var cameraQuat = this.entity.getRotation(); this.yaw = this._calcYaw(cameraQuat); this.pitch = this._calcPitch(cameraQuat, this.yaw); this._removeInertia(); this._updatePosition(); }; OrbitCamera.prototype.resetAndLookAtEntity = function (resetPoint, entity) { this._buildAabb(entity); this.resetAndLookAtPoint(resetPoint, this._modelsAabb.center); }; OrbitCamera.prototype.reset = function (yaw, pitch, distance) { this.pitch = pitch; this.yaw = yaw; this.distance = distance; this._removeInertia(); }; OrbitCamera.prototype.resetToPosition = function (position, lookAtPoint) { this.entity.setPosition(position); this.entity.lookAt(lookAtPoint); this._pivotPoint.copy(lookAtPoint); var distanceVec = new pc.Vec3(); distanceVec.sub2(position, lookAtPoint); this._targetDistance = this._distance = distanceVec.length(); var cameraQuat = this.entity.getRotation(); this._targetYaw = this._yaw = this._calcYaw(cameraQuat); this._targetPitch = this._pitch = this._calcPitch(cameraQuat, this._yaw); this._removeInertia(); this._updatePosition(); }; OrbitCamera.prototype.worldCameraYForPivot = function(pivot) { var quat = new pc.Quat(); quat.setFromEulerAngles(this._pitch, this._yaw, 0); var forward = new pc.Vec3(); quat.transformVector(pc.Vec3.FORWARD, forward); var camPos = pivot.clone(); camPos.add(forward.clone().scale(-this._distance)); return camPos.y; }; OrbitCamera.prototype.initialize = function () { var self = this; var onWindowResize = function () { self._checkAspectRatio(); }; window.addEventListener('resize', onWindowResize, false); this._checkAspectRatio(); this._modelsAabb = new pc.BoundingBox(); this._buildAabb(this.focusEntity || this.app.root); this.entity.lookAt(this._modelsAabb.center); this._pivotPoint = new pc.Vec3(); this._pivotPoint.copy(this._modelsAabb.center); var cameraQuat = this.entity.getRotation(); this._yaw = this._calcYaw(cameraQuat); // DEGRÉS this._pitch = this._clampPitchAngle(this._calcPitch(cameraQuat, this._yaw)); this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0); this._distance = 0; this._targetYaw = this._yaw; this._targetPitch = this._pitch; if (this.frameOnStart) { this.focus(this.focusEntity || this.app.root); } else { var distanceBetween = new pc.Vec3(); distanceBetween.sub2(this.entity.getPosition(), this._pivotPoint); this._distance = this._clampDistance(distanceBetween.length()); } this._targetDistance = this._distance; this.on('attr:distanceMin', function () { this._distance = this._clampDistance(this._distance); }); this.on('attr:distanceMax', function () { this._distance = this._clampDistance(this._distance); }); this.on('attr:pitchAngleMin', function () { this._pitch = this._clampPitchAngle(this._pitch); }); this.on('attr:pitchAngleMax', function () { this._pitch = this._clampPitchAngle(this._pitch); }); this.on('attr:focusEntity', function (value) { if (this.frameOnStart) { this.focus(value || this.app.root); } else { this.resetAndLookAtEntity(this.entity.getPosition(), value || this.app.root); } }); this.on('attr:frameOnStart', function (value) { if (value) { this.focus(this.focusEntity || this.app.root); } }); this.on('destroy', function () { window.removeEventListener('resize', onWindowResize, false); }); console.log('[OrbitCam] init yaw=%s° pitch=%s° dist=%s', this._yaw.toFixed(2), this._pitch.toFixed(2), this._distance.toFixed(3)); }; OrbitCamera.prototype.update = function (dt) { var t = this.inertiaFactor === 0 ? 1 : Math.min(dt / this.inertiaFactor, 1); this._distance = pc.math.lerp(this._distance, this._targetDistance, t); this._yaw = pc.math.lerp(this._yaw, this._targetYaw, t); this._pitch = pc.math.lerp(this._pitch, this._targetPitch, t); this._updatePosition(); }; OrbitCamera.prototype._updatePosition = function () { this.entity.setLocalPosition(0, 0, 0); this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0); var position = this.entity.getPosition(); position.copy(this.entity.forward); position.mulScalar(-this._distance); position.add(this.pivotPoint); position.y = Math.max(position.y, this.minY); this.entity.setPosition(position); }; OrbitCamera.prototype._removeInertia = function () { this._yaw = this._targetYaw; this._pitch = this._targetPitch; this._distance = this._targetDistance; }; OrbitCamera.prototype._checkAspectRatio = function () { var height = this.app.graphicsDevice.height; var width = this.app.graphicsDevice.width; this.entity.camera.horizontalFov = (height > width); }; OrbitCamera.prototype._buildAabb = function (entity) { var i, m, mes