diff --git a/src/mol-canvas3d/camera.ts b/src/mol-canvas3d/camera.ts index bde9504bc6f39ddfe795d53e54b097aa6ae19fa4..5e3cbbabbf3b0402659fac398ed9723a37d56083 100644 --- a/src/mol-canvas3d/camera.ts +++ b/src/mol-canvas3d/camera.ts @@ -233,25 +233,36 @@ namespace Camera { const _center = Vec3.zero(); function updateOrtho(camera: Camera) { - const { viewport, state: { zoom, near, far } } = camera; + const { viewport, state: { zoom, near, far }, viewOffset } = camera - const fullLeft = (viewport.width - viewport.x) / -2 + const fullLeft = -(viewport.width - viewport.x) / 2 const fullRight = (viewport.width - viewport.x) / 2 const fullTop = (viewport.height - viewport.y) / 2 - const fullBottom = (viewport.height - viewport.y) / -2 + const fullBottom = -(viewport.height - viewport.y) / 2 const dx = (fullRight - fullLeft) / (2 * zoom) const dy = (fullTop - fullBottom) / (2 * zoom) const cx = (fullRight + fullLeft) / 2 const cy = (fullTop + fullBottom) / 2 - const left = cx - dx - const right = cx + dx - const top = cy + dy - const bottom = cy - dy + let left = cx - dx + let right = cx + dx + let top = cy + dy + let bottom = cy - dy + + if (viewOffset && viewOffset.enabled) { + const zoomW = zoom / (viewOffset.width / viewOffset.fullWidth) + const zoomH = zoom / (viewOffset.height / viewOffset.fullHeight) + const scaleW = (fullRight - fullLeft) / viewOffset.width + const scaleH = (fullTop - fullBottom) / viewOffset.height + left += scaleW * (viewOffset.offsetX / zoomW) + right = left + scaleW * (viewOffset.width / zoomW) + top -= scaleH * (viewOffset.offsetY / zoomH) + bottom = top - scaleH * (viewOffset.height / zoomH) + } // build projection matrix - Mat4.ortho(camera.projection, left, right, bottom, top, Math.abs(near), Math.abs(far)) + Mat4.ortho(camera.projection, left, right, top, bottom, near, far) // build view matrix Vec3.add(_center, camera.position, camera.direction) @@ -261,7 +272,7 @@ function updateOrtho(camera: Camera) { function updatePers(camera: Camera) { const aspect = camera.viewport.width / camera.viewport.height - const { state: { fov, near, far }, viewOffset } = camera; + const { state: { fov, near, far }, viewOffset } = camera let top = near * Math.tan(0.5 * fov) let height = 2 * top diff --git a/src/mol-math/linear-algebra/3d/mat4.ts b/src/mol-math/linear-algebra/3d/mat4.ts index ff0167e3f255fe1d1465e6991cf468aff1fa6d02..313de7f7b336a2bd2fd3787f79bdeae51583eb86 100644 --- a/src/mol-math/linear-algebra/3d/mat4.ts +++ b/src/mol-math/linear-algebra/3d/mat4.ts @@ -778,33 +778,7 @@ namespace Mat4 { } /** - * Generates a frustum matrix with the given bounds - */ - export function frustum(out: Mat4, left: number, right: number, bottom: number, top: number, near: number, far: number) { - const rl = 1 / (right - left); - const tb = 1 / (top - bottom); - const nf = 1 / (near - far); - out[0] = (near * 2) * rl; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = (near * 2) * tb; - out[6] = 0; - out[7] = 0; - out[8] = (right + left) * rl; - out[9] = (top + bottom) * tb; - out[10] = (far + near) * nf; - out[11] = -1; - out[12] = 0; - out[13] = 0; - out[14] = (far * near * 2) * nf; - out[15] = 0; - return out; - } - - /** - * Generates a perspective projection matrix with the given bounds + * Generates a perspective projection (frustum) matrix with the given bounds */ export function perspective(out: Mat4, left: number, right: number, top: number, bottom: number, near: number, far: number) { const x = 2 * near / (right - left); @@ -812,8 +786,8 @@ namespace Mat4 { const a = (right + left) / (right - left); const b = (top + bottom) / (top - bottom); - const c = - (far + near) / (far - near); - const d = - 2 * far * near / (far - near); + const c = -(far + near) / (far - near); + const d = -2 * far * near / (far - near); out[0] = x; out[1] = 0; @@ -827,17 +801,17 @@ namespace Mat4 { out[9] = b; out[10] = c; out[11] = -1; - out[ 12 ] = 0; - out[ 13 ] = 0; - out[ 14 ] = d; - out[ 15 ] = 0; + out[12] = 0; + out[13] = 0; + out[14] = d; + out[15] = 0; return out; } /** * Generates a orthogonal projection matrix with the given bounds */ - export function ortho(out: Mat4, left: number, right: number, bottom: number, top: number, near: number, far: number) { + export function ortho(out: Mat4, left: number, right: number, top: number, bottom: number, near: number, far: number) { const w = 1.0 / (right - left); const h = 1.0 / (top - bottom); const p = 1.0 / (far - near); @@ -846,22 +820,22 @@ namespace Mat4 { const y = (top + bottom) * h; const z = (far + near) * p; - out[ 0 ] = 2 * w; - out[ 1 ] = 0; - out[ 2 ] = 0; - out[ 3 ] = 0; - out[ 4 ] = 0; - out[ 5 ] = 2 * h; - out[ 6 ] = 0; - out[ 7 ] = 0; - out[ 8 ] = 0; - out[ 9 ] = 0; - out[ 10 ] = - 2 * p; - out[ 11 ] = 0; - out[ 12 ] = - x; - out[ 13 ] = - y; - out[ 14 ] = - z; - out[ 15 ] = 1; + out[0] = 2 * w; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 2 * h; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = -2 * p; + out[11] = 0; + out[12] = -x; + out[13] = -y; + out[14] = -z; + out[15] = 1; return out; }