Skip to content

Instantly share code, notes, and snippets.

@scan
Created May 20, 2011 22:00
Show Gist options
  • Save scan/983906 to your computer and use it in GitHub Desktop.
Save scan/983906 to your computer and use it in GitHub Desktop.
Scala Matrices
case class Matrix(_1: (Double, Double, Double, Double), _2: (Double, Double, Double, Double),
_3: (Double, Double, Double, Double), _4: (Double, Double, Double, Double)) extends Immutable {
def transpose = Matrix(
(_1._1, _2._1, _3._1, _4._1),
(_1._2, _2._2, _3._2, _4._2),
(_1._3, _2._3, _3._3, _4._3),
(_1._4, _2._4, _3._4, _4._4)
)
def invert = {
val _11 = _2._2 * _3._3 * _4._4 - _2._2 * _3._4 * _4._3 - _3._2 * _2._3 * _4._4
+_3._2 * _2._4 * _4._3 + _4._2 * _2._3 * _3._4 - _4._2 * _2._4 * _3._3;
val _21 = -_2._1 * _3._3 * _4._4 + _2._1 * _3._4 * _4._3 + _3._1 * _2._3 * _4._4
-_3._1 * _2._4 * _4._3 - _4._1 * _2._3 * _3._4 + _4._1 * _2._4 * _3._3;
val _31 = _2._1 * _3._2 * _4._4 - _2._1 * _3._4 * _4._2 - _3._1 * _2._2 * _4._4
+_3._1 * _2._4 * _4._2 + _4._1 * _2._2 * _3._4 - _4._1 * _2._4 * _3._2;
val _41 = -_2._1 * _3._2 * _4._3 + _2._1 * _3._3 * _4._2 + _3._1 * _2._2 * _4._3
-_3._1 * _2._3 * _4._2 - _4._1 * _2._2 * _3._3 + _4._1 * _2._3 * _3._2;
val _12 = -_1._2 * _3._3 * _4._4 + _1._2 * _3._4 * _4._3 + _3._2 * _1._3 * _4._4
-_3._2 * _1._4 * _4._3 - _4._2 * _1._3 * _3._4 + _4._2 * _1._4 * _3._3;
val _22 = _1._1 * _3._3 * _4._4 - _1._1 * _3._4 * _4._3 - _3._1 * _1._3 * _4._4
+_3._1 * _1._4 * _4._3 + _4._1 * _1._3 * _3._4 - _4._1 * _1._4 * _3._3;
val _32 = -_1._1 * _3._2 * _4._4 + _1._1 * _3._4 * _4._2 + _3._1 * _1._2 * _4._4
-_3._1 * _1._4 * _4._2 - _4._1 * _1._2 * _3._4 + _4._1 * _1._4 * _3._2;
val _42 = _1._1 * _3._2 * _4._3 - _1._1 * _3._3 * _4._2 - _3._1 * _1._2 * _4._3
+_3._1 * _1._3 * _4._2 + _4._1 * _1._2 * _3._3 - _4._1 * _1._3 * _3._2;
val _13 = _1._2 * _2._3 * _4._4 - _1._2 * _2._4 * _4._3 - _2._2 * _1._3 * _4._4
+_2._2 * _1._4 * _4._3 + _4._2 * _1._3 * _2._4 - _4._2 * _1._4 * _2._3;
val _23 = -_1._1 * _2._3 * _4._4 + _1._1 * _2._4 * _4._3 + _2._1 * _1._3 * _4._4
-_2._1 * _1._4 * _4._3 - _4._1 * _1._3 * _2._4 + _4._1 * _1._4 * _2._3;
val _33 = _1._1 * _2._2 * _4._4 - _1._1 * _2._4 * _4._2 - _2._1 * _1._2 * _4._4
+_2._1 * _1._4 * _4._2 + _4._1 * _1._2 * _2._4 - _4._1 * _1._4 * _2._2;
val _43 = -_1._1 * _2._2 * _4._3 + _1._1 * _2._3 * _4._2 + _2._1 * _1._2 * _4._3
-_2._1 * _1._3 * _4._2 - _4._1 * _1._2 * _2._3 + _4._1 * _1._3 * _2._2;
val _14 = -_1._2 * _2._3 * _3._4 + _1._2 * _2._4 * _3._3 + _2._2 * _1._3 * _3._4
-_2._2 * _1._4 * _3._3 - _3._2 * _1._3 * _2._4 + _3._2 * _1._4 * _2._3;
val _24 = _1._1 * _2._3 * _3._4 - _1._1 * _2._4 * _3._3 - _2._1 * _1._3 * _3._4
+_2._1 * _1._4 * _3._3 + _3._1 * _1._3 * _2._4 - _3._1 * _1._4 * _2._3;
val _34 = -_1._1 * _2._2 * _3._4 + _1._1 * _2._4 * _3._2 + _2._1 * _1._2 * _3._4
-_2._1 * _1._4 * _3._2 - _3._1 * _1._2 * _2._4 + _3._1 * _1._4 * _2._2;
val _44 = _1._1 * _2._2 * _3._3 - _1._1 * _2._3 * _3._2 - _2._1 * _1._2 * _3._3
+_2._1 * _1._3 * _3._2 + _3._1 * _1._2 * _2._3 - _3._1 * _1._3 * _2._2;
val det = _1._1 * _11 + _1._2 * _21 + _1._3 * _31 + _1._4 * _41
if (det == 0) this
else Matrix(
(_11, _12, _13, _14),
(_21, _22, _23, _24),
(_31, _32, _33, _34),
(_41, _42, _43, _44)
) * (1 / det)
}
def *(m: Matrix) = {
val _11 = (_1._1 * m._1._1) + (_1._2 * m._2._1) + (_1._3 * m._3._1) + (_1._4 * m._4._1)
val _12 = (_1._1 * m._1._2) + (_1._2 * m._2._2) + (_1._3 * m._3._2) + (_1._4 * m._4._2)
val _13 = (_1._1 * m._1._3) + (_1._2 * m._2._3) + (_1._3 * m._3._3) + (_1._4 * m._4._3)
val _14 = (_1._1 * m._1._4) + (_1._2 * m._2._4) + (_1._3 * m._3._4) + (_1._4 * m._4._4)
val _21 = (_2._1 * m._1._1) + (_2._2 * m._2._1) + (_2._3 * m._3._1) + (_2._4 * m._4._1)
val _22 = (_2._1 * m._1._2) + (_2._2 * m._2._2) + (_2._3 * m._3._2) + (_2._4 * m._4._2)
val _23 = (_2._1 * m._1._3) + (_2._2 * m._2._3) + (_2._3 * m._3._3) + (_2._4 * m._4._3)
val _24 = (_2._1 * m._1._4) + (_2._2 * m._2._4) + (_2._3 * m._3._4) + (_2._4 * m._4._4)
val _31 = (_3._1 * m._1._1) + (_3._2 * m._2._1) + (_3._3 * m._3._1) + (_3._4 * m._4._1)
val _32 = (_3._1 * m._1._2) + (_3._2 * m._2._2) + (_3._3 * m._3._2) + (_3._4 * m._4._2)
val _33 = (_3._1 * m._1._3) + (_3._2 * m._2._3) + (_3._3 * m._3._3) + (_3._4 * m._4._3)
val _34 = (_3._1 * m._1._4) + (_3._2 * m._2._4) + (_3._3 * m._3._4) + (_3._4 * m._4._4)
val _41 = (_4._1 * m._1._1) + (_4._2 * m._2._1) + (_4._3 * m._3._1) + (_4._4 * m._4._1)
val _42 = (_4._1 * m._1._2) + (_4._2 * m._2._2) + (_4._3 * m._3._2) + (_4._4 * m._4._2)
val _43 = (_4._1 * m._1._3) + (_4._2 * m._2._3) + (_4._3 * m._3._3) + (_4._4 * m._4._3)
val _44 = (_4._1 * m._1._4) + (_4._2 * m._2._4) + (_4._3 * m._3._4) + (_4._4 * m._4._4)
Matrix(
(_11, _12, _13, _14),
(_21, _22, _23, _24),
(_31, _32, _33, _34),
(_41, _42, _43, _44)
)
}
def *(v: Vector) = {
val x = v.x * _1._1 + v.y * _2._1 + v.z * _3._1 + v.w * _4._1
val y = v.x * _1._2 + v.y * _2._2 + v.z * _3._2 + v.w * _4._2
val z = v.x * _1._3 + v.y * _2._3 + v.z * _3._3 + v.w * _4._3
val w = v.x * _1._4 + v.y * _2._4 + v.z * _3._4 + v.w * _4._4
if (w != 1) Vector(x / w, y / w, z / w, 1)
else Vector(x, y, z, w)
}
def *(f: Double) = Matrix(
(_1._1 * f, _1._2 * f, _1._3 * f, _1._4 * f),
(_2._1 * f, _2._2 * f, _2._3 * f, _2._4 * f),
(_3._1 * f, _3._2 * f, _3._3 * f, _3._4 * f),
(_4._1 * f, _4._2 * f, _4._3 * f, _4._4 * f)
)
}
object Matrix {
implicit def asTuple(m: Matrix):
((Double, Double, Double, Double),
(Double, Double, Double, Double),
(Double, Double, Double, Double),
(Double, Double, Double, Double)) = (m._1, m._2, m._3, m._4)
implicit def asArray(m: Matrix): Array[Double] = Array(m._1._1, m._1._2, m._1._3, m._1._4,
m._2._1, m._2._2, m._2._3, m._2._4,
m._3._1, m._3._2, m._3._3, m._3._4,
m._4._1, m._4._2, m._4._3, m._4._4)
object identity extends Matrix((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1))
def projection(fov: Double, aspect: Double, near: Double, far: Double) = Matrix(
(1 / math.tan(fov / 2), 0, 0, 0),
(0, (1 / math.tan(fov / 2)) / aspect, 0, 0),
(0, 0, far / (near - far), -1),
(0, 0, near * far / (near - far), 0)
)
def ortho(w: Double, h: Double, near: Double, far: Double) = Matrix(
(2 / w, 0, 0, 0),
(0, 2 / h, 0, 0),
(0, 0, 1 / (near - far), 0),
(0, 0, near / (near - far), 1)
)
def translation(x: Double, y: Double, z: Double) = Matrix(
(1, 0, 0, 0),
(0, 1, 0, 0),
(0, 0, 1, 0),
(x, y, z, 1)
)
def scale(sx: Double, sy: Double, sz: Double) = Matrix(
(sx, 0, 0, 0),
(0, sy, 0, 0),
(0, 0, sz, 0),
(0, 0, 0, 1)
)
def rotateX(a: Double) = {
val c = math.cos(a)
val s = math.sin(a)
Matrix(
(1, 0, 0, 0),
(0, c, s, 0),
(0, -c, s, 0),
(0, 0, 0, 1)
)
}
def rotateY(a: Double) = {
val c = math.cos(a)
val s = math.sin(a)
Matrix(
(c, 0, -s, 0),
(0, 1, 0, 0),
(s, 0, c, 0),
(0, 0, 0, 1)
)
}
def rotateZ(a: Double) = {
val c = math.cos(a)
val s = math.sin(a)
Matrix(
(c, s, 0, 0),
(-s, c, 0, 0),
(0, 0, 1, 0),
(0, 0, 0, 1)
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment