Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions src/as/cameras/OrthographicCamera.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* global QUnit */

import { OrthographicCamera } from './OrthographicCamera'

describe('Cameras', () => {
describe('OrthographicCamera', () => {
// INHERITANCE
// Not needed, we can delete this, we don't need to test that `class Foo extends Bar` works, we assume the language works.
// todo('Extending')

// INSTANCING
// Not needed, we can delete this, we don't need to test that `new Foo` works, this will be required in all other tests anyway.
// todo('Instancing')

// ^ NOTE, the Extending and Instancing tests were a thing of long ago,
// when JS has only functions, Three.js was sometimes testing that
// inheritance was done properly. Nowadays, we trust `class` syntax.

// PUBLIC STUFF
todo('isOrthographicCamera')
todo('copy')

// TODO this needs to be done or we won't know if it works
todo('setViewOffset')

// TODO this needs to be done or we won't know if it works
todo('clearViewOffset')

test('updateProjectionMatrix', () => {
const left: f32 = -1
const right: f32 = 1
const top: f32 = 1
const bottom: f32 = -1
const near: f32 = 1
const far: f32 = 3
const cam = new OrthographicCamera(left, right, top, bottom, near, far)

// updateProjectionMatrix is called in constructor
const pMatrix = cam.projectionMatrix.elements

// orthographic projection is given my the 4x4 Matrix
// 2/r-l 0 0 -(l+r/r-l)
// 0 2/t-b 0 -(t+b/t-b)
// 0 0 -2/f-n -(f+n/f-n)
// 0 0 0 1

expect(pMatrix[0]).toBe(2 / (right - left), 'm[0,0] === 2 / (r - l)')
expect(pMatrix[5]).toBe(2 / (top - bottom), 'm[1,1] === 2 / (t - b)')
expect(pMatrix[10]).toBe(-2 / (far - near), 'm[2,2] === -2 / (f - n)')
expect(pMatrix[12]).toBe(-((right + left) / (right - left)), 'm[3,0] === -(r+l/r-l)')
expect(pMatrix[13]).toBe(-((top + bottom) / (top - bottom)), 'm[3,1] === -(t+b/b-t)')
expect(pMatrix[14]).toBe(-((far + near) / (far - near)), 'm[3,2] === -(f+n/f-n)')
})

todo('toJSON')

// v TODO

// OTHERS
// TODO: no no no clone is a camera methods that relied to copy method
// QUnit.test('clone', assert => {
// var left = -1.5,
// right = 1.5,
// top = 1,
// bottom = -1,
// near = 0.1,
// far = 42
// var cam = new OrthographicCamera(left, right, top, bottom, near, far)

// var clonedCam = cam.clone()

// assert.ok(cam.left === clonedCam.left, 'left is equal')
// assert.ok(cam.right === clonedCam.right, 'right is equal')
// assert.ok(cam.top === clonedCam.top, 'top is equal')
// assert.ok(cam.bottom === clonedCam.bottom, 'bottom is equal')
// assert.ok(cam.near === clonedCam.near, 'near is equal')
// assert.ok(cam.far === clonedCam.far, 'far is equal')
// assert.ok(cam.zoom === clonedCam.zoom, 'zoom is equal')
// })
})
})
142 changes: 142 additions & 0 deletions src/as/cameras/OrthographicCamera.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { Camera } from './Camera'
import { Object3D } from '../core'

// @unmanaged
@final
class OrthographicView {
enabled: boolean
fullWidth: f32
fullHeight: f32
offsetX: f32
offsetY: f32
width: f32
height: f32
}

/**
* Camera with orthographic projection
*
* @example
* var camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
* scene.add( camera );
*
* @see <a href="https://github.com/mrdoob/three.js/blob/master/src/cameras/OrthographicCamera.js">src/cameras/OrthographicCamera.js</a>
*/
export class OrthographicCamera extends Camera {
readonly isOrthographicCamera: boolean = true

type: string = 'OrthographicCamera'

zoom: f32 = 1
view: OrthographicView | null = null

/**
* @param left `f32` - Camera frustum left plane.
* @param right `f32` - Camera frustum right plane.
* @param top `f32` - Camera frustum top plane.
* @param bottom `f32` - Camera frustum bottom plane.
* @param near `f32` - Camera frustum near plane.
* @param far `f32` - Camera frustum far plane.
*/
constructor(
public left: f32 = -1,
public right: f32 = 1,
public top: f32 = 1,
public bottom: f32 = -1,
public near: f32 = 0.1,
public far: f32 = 2000
) {
super()
this.updateProjectionMatrix()
}

setViewOffset(fullWidth: f32, fullHeight: f32, offsetX: f32, offsetY: f32, width: f32, height: f32): void {
let view = this.view

if (!view) {
this.view = view = {
enabled: true,
fullWidth: 1,
fullHeight: 1,
offsetX: 0,
offsetY: 0,
width: 1,
height: 1,
}
}

view.enabled = true
view.fullWidth = fullWidth
view.fullHeight = fullHeight
view.offsetX = offsetX
view.offsetY = offsetY
view.width = width
view.height = height

this.updateProjectionMatrix()
}

clearViewOffset(): void {
const view = this.view

if (view) {
view.enabled = false
}

this.updateProjectionMatrix()
}

/**
* Updates the camera projection matrix. Must be called after change of parameters.
*/
updateProjectionMatrix(): void {
const dx = (this.right - this.left) / (2 * this.zoom)
const dy = (this.top - this.bottom) / (2 * this.zoom)
const cx = (this.right + this.left) / 2
const cy = (this.top + this.bottom) / 2

let left = cx - dx
let right = cx + dx
let top = cy + dy
let bottom = cy - dy

const view = this.view

if (view && view.enabled) {
const zoomW = this.zoom / (view.width / view.fullWidth)
const zoomH = this.zoom / (view.height / view.fullHeight)
const scaleW = (this.right - this.left) / view.width
const scaleH = (this.top - this.bottom) / view.height

left += scaleW * (view.offsetX / zoomW)
right = left + scaleW * (view.width / zoomW)
top -= scaleH * (view.offsetY / zoomH)
bottom = top - scaleH * (view.height / zoomH)
}

this.projectionMatrix.makeOrthographic(left, right, top, bottom, this.near, this.far)

this.projectionMatrixInverse.getInverse(this.projectionMatrix)
}

// TODO copy method in Camera class
// clone(): OrthographicCamera {
// return new OrthographicCamera().copy(this)
// }

// toJSON(meta) {
// const data = Object3D.prototype.toJSON.call(this, meta)

// data.object.zoom = this.zoom
// data.object.left = this.left
// data.object.right = this.right
// data.object.top = this.top
// data.object.bottom = this.bottom
// data.object.near = this.near
// data.object.far = this.far

// if (this.view !== null) data.object.view = Object.assign({}, this.view)

// return data
// }
}
1 change: 1 addition & 0 deletions src/as/cameras/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import './ArrayCamera.spec'
import './Camera.spec'
import './OrthographicCamera.spec'
import './PerspectiveCamera.spec'