Skip to content

Instantly share code, notes, and snippets.

@525c1e21-bd67-4735-ac99-b4b0e5262290
Created September 25, 2011 06:36
Show Gist options
  • Save 525c1e21-bd67-4735-ac99-b4b0e5262290/1240310 to your computer and use it in GitHub Desktop.
Save 525c1e21-bd67-4735-ac99-b4b0e5262290/1240310 to your computer and use it in GitHub Desktop.
Vector3 = require './vector3'
module.exports = class Matrix4
constructor: ->
@m11 = @m12 = @m13 = @m14 = @m21 = @m22 = @m23 = @m24 = @m31 = @m32 = @m33 = @m34 = @m41 = @m42 = @m43 = @m44 = 0
set: (@m11, @m12, @m13, @m14, @m21, @m22, @m23, @m24, @m31, @m32, @m33, @m34, @m41, @m42, @m43, @m44) -> this
copy: ({@m11, @m12, @m13, @m14, @m21, @m22, @m23, @m24, @m31, @m32, @m33, @m34, @m41, @m42, @m43, @m44}) -> this
identity: ->
@set 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
zero: ->
@set 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
frustum: (left, right, bottom, top, near, far) ->
a = (right + left) / (right - left)
b = (top + bottom) / (top - bottom)
c = -(far + near) / (far - near)
d = -(2 * far * near) / (far - near)
x = (2 * near) / (right - left)
y = (2 * near) / (top - bottom)
@set x, 0, a, 0, 0, y, b, 0, 0, 0, c, d, 0, 0, -1, 0
perspective: (fov, aspect, near, far) ->
maxY = near * (Math.tan fov * Math.PI / 360)
minY = -maxY
minX = minY * aspect
maxX = maxY * aspect
@frustum minX, maxX, minY, maxY, near, far
setTranslationFromVector: ({x, y, z}) ->
@m14 += x
@m24 += y
@m34 += z
this
scaleByVector: (vector) ->
{x, y, z} = vector
@m11 *= x ; @m12 *= y ; @m13 *= z
@m21 *= x ; @m22 *= y ; @m23 *= z
@m31 *= x ; @m32 *= y ; @m33 *= z
@m41 *= x ; @m42 *= y ; @m43 *= z
this
scaleByScalar: (scalar) ->
@m11 *= scalar ; @m12 *= scalar ; @m13 *= scalar
@m21 *= scalar ; @m22 *= scalar ; @m23 *= scalar
@m31 *= scalar ; @m32 *= scalar ; @m33 *= scalar
@m41 *= scalar ; @m42 *= scalar ; @m43 *= scalar
this
setRotationFromVector: (vector) ->
{x, y, z} = vector
cosX = Math.cos x ; sinX = Math.sin x
cosY = Math.cos y ; sinY = Math.sin y
cosZ = Math.cos z ; sinZ = Math.sin z
cosZsinX = cosZ * sinX
sinXsinZ = sinX * sinZ
cosXcosZ = cosX * cosZ
@m11 = cosY * cosZ ; @m12 = cosY * -sinZ ; @m13 = sinY
@m21 = cosZsinX * sinY + sinZ * cosX ; @m22 = sinXsinZ * -sinY + cosXcosZ ; @m23 = -sinX * cosY
@m31 = cosXcosZ * -sinY + sinXsinZ ; @m32 = cosX * sinY * sinZ + cosZsinX ; @m33 = cosX * cosY
this
multiply: (matrix) ->
m1_m11 = @m11 ; m1_m12 = @m12 ; m1_m13 = @m13 ; m1_m14 = @m14
m1_m21 = @m21 ; m1_m22 = @m22 ; m1_m23 = @m23 ; m1_m24 = @m24
m1_m31 = @m31 ; m1_m32 = @m32 ; m1_m33 = @m33 ; m1_m34 = @m34
m1_m41 = @m41 ; m1_m42 = @m42 ; m1_m43 = @m43 ; m1_m44 = @m44
m2_m11 = matrix.m11 ; m2_m12 = matrix.m12 ; m2_m13 = matrix.m13 ; m2_m14 = matrix.m14
m2_m21 = matrix.m21 ; m2_m22 = matrix.m22 ; m2_m23 = matrix.m23 ; m2_m24 = matrix.m24
m2_m31 = matrix.m31 ; m2_m32 = matrix.m32 ; m2_m33 = matrix.m33 ; m2_m34 = matrix.m34
m2_m41 = matrix.m41 ; m2_m42 = matrix.m42 ; m2_m43 = matrix.m43 ; m2_m44 = matrix.m44
@m11 = m1_m11 * m2_m11 + m1_m12 * m2_m21 + m1_m13 * m2_m31 + m1_m14 * m2_m41
@m12 = m1_m11 * m2_m12 + m1_m12 * m2_m22 + m1_m13 * m2_m32 + m1_m14 * m2_m42
@m13 = m1_m11 * m2_m13 + m1_m12 * m2_m23 + m1_m13 * m2_m33 + m1_m14 * m2_m43
@m14 = m1_m11 * m2_m14 + m1_m12 * m2_m24 + m1_m13 * m2_m34 + m1_m14 * m2_m44
@m21 = m1_m21 * m2_m11 + m1_m22 * m2_m21 + m1_m23 * m2_m31 + m1_m24 * m2_m41
@m22 = m1_m21 * m2_m12 + m1_m22 * m2_m22 + m1_m23 * m2_m32 + m1_m24 * m2_m42
@m23 = m1_m21 * m2_m13 + m1_m22 * m2_m23 + m1_m23 * m2_m33 + m1_m24 * m2_m43
@m24 = m1_m21 * m2_m14 + m1_m22 * m2_m24 + m1_m23 * m2_m34 + m1_m24 * m2_m44
@m31 = m1_m31 * m2_m11 + m1_m32 * m2_m21 + m1_m33 * m2_m31 + m1_m34 * m2_m41
@m32 = m1_m31 * m2_m12 + m1_m32 * m2_m22 + m1_m33 * m2_m32 + m1_m34 * m2_m42
@m33 = m1_m31 * m2_m13 + m1_m32 * m2_m23 + m1_m33 * m2_m33 + m1_m34 * m2_m43
@m34 = m1_m31 * m2_m14 + m1_m32 * m2_m24 + m1_m33 * m2_m34 + m1_m34 * m2_m44
@m41 = m1_m41 * m2_m11 + m1_m42 * m2_m21 + m1_m43 * m2_m31 + m1_m44 * m2_m41
@m42 = m1_m41 * m2_m12 + m1_m42 * m2_m22 + m1_m43 * m2_m32 + m1_m44 * m2_m42
@m43 = m1_m41 * m2_m13 + m1_m42 * m2_m23 + m1_m43 * m2_m33 + m1_m44 * m2_m43
@m44 = m1_m41 * m2_m14 + m1_m42 * m2_m24 + m1_m43 * m2_m34 + m1_m44 * m2_m44
this
multiplyVector3: (vector) ->
{x, y, z} = vector
w = 1 / (@m41 * x * @m42 * y + @m43 * z + @m44)
vector.x = @m11 * x + @m12 * y + @m13 * z + @m14
vector.y = @m21 * x + @m22 * y + @m23 * z + @m24
vector.z = @m31 * x + @m32 * y + @m33 * z + @m34
vector.multiplyByScalar w
vector
determinant: ->
@m14 * @m23 * @m32 * @m41 - @m13 * @m24 * @m32 * @m41 - @m14 * @m22 * @m33 * @m41 + @m12 * @m24 * @m33 * @m41 +
@m13 * @m22 * @m34 * @m41 - @m12 * @m23 * @m34 * @m41 - @m14 * @m23 * @m31 * @m42 + @m13 * @m24 * @m31 * @m42 +
@m14 * @m21 * @m33 * @m42 - @m11 * @m24 * @m33 * @m42 - @m13 * @m21 * @m34 * @m42 + @m11 * @m23 * @m34 * @m42 +
@m14 * @m22 * @m31 * @m43 - @m12 * @m24 * @m31 * @m43 - @m14 * @m21 * @m32 * @m43 + @m11 * @m24 * @m32 * @m43 +
@m12 * @m21 * @m34 * @m43 - @m11 * @m22 * @m34 * @m43 - @m13 * @m22 * @m31 * @m44 + @m12 * @m23 * @m31 * @m44 +
@m13 * @m21 * @m32 * @m44 - @m11 * @m23 * @m32 * @m44 - @m12 * @m21 * @m33 * @m44 + @m11 * @m22 * @m33 * @m44
invert: ->
{m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44} = @
determinant = @determinant()
throw 'determinant is 0' if determinant is 0
@m11 = m23 * m34 * m42 - m24 * m33 * m42 + m24 * m32 * m43 - m22 * m34 * m43 - m23 * m32 * m44 + m22 * m33 * m44
@m12 = m14 * m33 * m42 - m13 * m34 * m42 - m14 * m32 * m43 + m12 * m34 * m43 + m13 * m32 * m44 - m12 * m33 * m44
@m13 = m13 * m24 * m42 - m14 * m23 * m42 + m14 * m22 * m43 - m12 * m24 * m43 - m13 * m22 * m44 + m12 * m23 * m44
@m14 = m14 * m23 * m32 - m13 * m24 * m32 - m14 * m22 * m33 + m12 * m24 * m33 + m13 * m22 * m34 - m12 * m23 * m34
@m21 = m24 * m33 * m41 - m23 * m34 * m41 - m24 * m31 * m43 + m21 * m34 * m43 + m23 * m31 * m44 - m21 * m33 * m44
@m22 = m13 * m34 * m41 - m14 * m33 * m41 + m14 * m31 * m43 - m11 * m34 * m43 - m13 * m31 * m44 + m11 * m33 * m44
@m23 = m14 * m23 * m41 - m13 * m24 * m41 - m14 * m21 * m43 + m11 * m24 * m43 + m13 * m21 * m44 - m11 * m23 * m44
@m24 = m13 * m24 * m31 - m14 * m23 * m31 + m14 * m21 * m33 - m11 * m24 * m33 - m13 * m21 * m34 + m11 * m23 * m34
@m31 = m22 * m34 * m41 - m24 * m32 * m41 + m24 * m31 * m42 - m21 * m34 * m42 - m22 * m31 * m44 + m21 * m32 * m44
@m32 = m14 * m32 * m41 - m12 * m34 * m41 - m14 * m31 * m42 + m11 * m34 * m42 + m12 * m31 * m44 - m11 * m32 * m44
@m33 = m12 * m24 * m41 - m14 * m22 * m41 + m14 * m21 * m42 - m11 * m24 * m42 - m12 * m21 * m44 + m11 * m22 * m44
@m34 = m14 * m22 * m31 - m12 * m24 * m31 - m14 * m21 * m32 + m11 * m24 * m32 + m12 * m21 * m32 - m11 * m22 * m34
@m41 = m23 * m32 * m41 - m22 * m33 * m41 - m23 * m31 * m42 + m21 * m33 * m42 + m22 * m31 * m43 - m21 * m32 * m43
@m42 = m12 * m33 * m41 - m13 * m32 * m41 + m13 * m31 * m42 - m11 * m33 * m42 - m12 * m31 * m43 + m11 * m32 * m43
@m43 = m13 * m22 * m41 - m12 * m23 * m41 - m13 * m21 * m42 + m11 * m23 * m42 + m12 * m21 * m43 - m11 * m22 * m43
@m44 = m12 * m23 * m31 - m13 * m22 * m31 + m13 * m21 * m32 - m11 * m23 * m32 - m12 * m21 * m33 + m11 * m22 * m33
@scaleByScalar 1 / determinant
this
lookAt: (eye, target, up) ->
direction = new Vector3
right = new Vector3
up = new Vector3
direction.copy(eye).subtract(target).normalize()
direction.z = 1 if direction.length() is 0
right.copy(up).cross(direction).normalize()
if right.length() is 0
direction.z += 0.1
right.copy(up).cross(direction).normalize()
up.copy(direction).cross(right).normalize()
@m11 = right.x ; @m12 = up.x ; @m13 = direction.x
@m21 = right.y ; @m22 = up.y ; @m23 = direction.y
@m31 = right.z ; @m32 = up.z ; @m33 = direction.z
this
toArray: (out) ->
out[0] = @m11 ; out[1] = @m21 ; out[2] = @m31 ; out[3] = @m41
out[4] = @m12 ; out[5] = @m22 ; out[6] = @m32 ; out[7] = @m42
out[8] = @m13 ; out[9] = @m23 ; out[10] = @m33 ; out[11] = @m43
out[12] = @m14 ; out[13] = @m24 ; out[14] = @m34 ; out[15] = @m44
out
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment