Spaces:
Running
Running
| // 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 | |