UNPKG

itowns

Version:

A JS/WebGL framework for 3D geospatial data visualization

118 lines (115 loc) 4.72 kB
import * as THREE from 'three'; class Distortion { constructor(size) { this.size = size; this.pps = null; this.polynom = null; this.l1l2 = null; } setFromMicmacCalibration(distortion) { let imageYDown = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; this.pps = new THREE.Vector2().fromArray(distortion.pps); this.polynom = new THREE.Vector4().fromArray(distortion.poly357); this.l1l2 = new THREE.Vector3(); // inverse Y pps convention image micmac this.pps.y = imageYDown ? this.size.y - this.pps.y : this.pps.y; this.polynom.w = distortion.limit ** 2; if (distortion.l1l2) { this.l1l2.fromArray(distortion.l1l2); this.l1l2.z = distortion.etats; } } clone() { const dest = new Distortion(this.size.clone()); dest.pps = this.pps.clone(); dest.polynom = this.polynom.clone(); dest.l1l2 = this.l1l2.clone(); return dest; } } const zoom = new THREE.Vector3(); /** * OrientedImageCamera is a ThreeJs camera adapted to photogrammetric description. * So we can build a ThreeJs perspective camera from size and focal information. */ class OrientedImageCamera extends THREE.PerspectiveCamera { /** * @param {number|Vector2} size - image size in pixels (default: x=1024, y=x) * @param {number|Vector2} focal - focal length in pixels (default: x=1024, y=x) * @param {Vector2} center - principal point in pixels (default: size/2) * @param {number} near - Camera frustum near plane (default: see THREE.PerspectiveCamera). * @param {number} far - Camera frustum far plane (default: see THREE.PerspectiveCamera). * @param {number} skew - shear transform parameter (default: 0) * @param {number} aspect - aspect ratio of the camera (default: size.x/size.y). */ constructor() { let size = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1024; let focal = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1024; let center = arguments.length > 2 ? arguments[2] : undefined; let near = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0.1; let far = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 10000; let skew = arguments.length > 5 ? arguments[5] : undefined; let aspect = arguments.length > 6 ? arguments[6] : undefined; size = size.isVector2 ? size : new THREE.Vector2(size, size); aspect = aspect || size.x / size.y; super(undefined, aspect, near, far); this.size = size; this.focal = focal.isVector2 ? focal : new THREE.Vector2(focal, focal); this.center = center || size.clone().multiplyScalar(0.5); this.skew = skew || 0; this.textureMatrixWorldInverse = new THREE.Matrix4(); Object.defineProperty(this, 'fov', { get: () => 2 * THREE.MathUtils.radToDeg(Math.atan2(this.size.y, 2 * this.focal.y)), // setting the fov overwrites focal.x and focal.y set: fov => { const focal = 0.5 * this.size.y / Math.tan(THREE.MathUtils.degToRad(fov * 0.5)); this.focal.x = focal; this.focal.y = focal; } }); this.distortion = new Distortion(this.size); this.maskPath = undefined; this.mask = undefined; this.updateProjectionMatrix(); } // we override PerspectiveCamera.updateProjectionMatrix to // update the projection matrix depending on other variables // focal, center and size... updateProjectionMatrix() { if (!this.focal) { return; } const near = this.near; const sx = near / this.focal.x; const sy = near / this.focal.y; const left = -sx * this.center.x; const bottom = -sy * this.center.y; const right = left + sx * this.size.x; const top = bottom + sy * this.size.y; this.projectionMatrix.makePerspective(left, right, top, bottom, near, this.far); this.projectionMatrix.elements[4] = 2 * this.skew / this.size.x; // take zoom and aspect into account const textureAspect = this.size.x / this.size.y; const aspectRatio = this.aspect / textureAspect; zoom.set(this.zoom, this.zoom, 1); if (aspectRatio > 1) { zoom.x /= aspectRatio; } else { zoom.y *= aspectRatio; } this.projectionMatrix.scale(zoom); } copy(source, recursive) { super.copy(source, recursive); this.size = source.size.clone(); this.focal = source.focal.clone(); this.center = source.center.clone(); this.distortion = source.distortion.clone(); this.textureMatrixWorldInverse = source.textureMatrixWorldInverse.clone(); this.skew = source.skew; this.maskPath = source.maskPath; this.mask = source.mask; return this; } } export default OrientedImageCamera;