-
Notifications
You must be signed in to change notification settings - Fork 0
/
matrix.go
98 lines (90 loc) · 3.23 KB
/
matrix.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package pathtracer
import "math"
// IdentityMatrix represents a transformation matrix that makes no
// changes when applied to a vector.
func IdentityMatrix() Matrix {
return Matrix{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
}
}
// Matrix represents transformations that can be applied to Vectors.
//
// https://github.com/fogleman/pt/blob/master/pt/matrix.go
type Matrix struct {
x00, x01, x02, x03 float64
x10, x11, x12, x13 float64
x20, x21, x22, x23 float64
x30, x31, x32, x33 float64
}
// Multiply produces a matrix that represents the transformations of
// both matrices. Order matters.
//
// https://github.com/fogleman/pt/blob/master/pt/matrix.go
// https://www.mathsisfun.com/algebra/matrix-multiplying.html
func (m Matrix) Multiply(b Matrix) Matrix {
output := Matrix{}
output.x00 = m.x00*b.x00 + m.x01*b.x10 + m.x02*b.x20 + m.x03*b.x30
output.x10 = m.x10*b.x00 + m.x11*b.x10 + m.x12*b.x20 + m.x13*b.x30
output.x20 = m.x20*b.x00 + m.x21*b.x10 + m.x22*b.x20 + m.x23*b.x30
output.x30 = m.x30*b.x00 + m.x31*b.x10 + m.x32*b.x20 + m.x33*b.x30
output.x01 = m.x00*b.x01 + m.x01*b.x11 + m.x02*b.x21 + m.x03*b.x31
output.x11 = m.x10*b.x01 + m.x11*b.x11 + m.x12*b.x21 + m.x13*b.x31
output.x21 = m.x20*b.x01 + m.x21*b.x11 + m.x22*b.x21 + m.x23*b.x31
output.x31 = m.x30*b.x01 + m.x31*b.x11 + m.x32*b.x21 + m.x33*b.x31
output.x02 = m.x00*b.x02 + m.x01*b.x12 + m.x02*b.x22 + m.x03*b.x32
output.x12 = m.x10*b.x02 + m.x11*b.x12 + m.x12*b.x22 + m.x13*b.x32
output.x22 = m.x20*b.x02 + m.x21*b.x12 + m.x22*b.x22 + m.x23*b.x32
output.x32 = m.x30*b.x02 + m.x31*b.x12 + m.x32*b.x22 + m.x33*b.x32
output.x03 = m.x00*b.x03 + m.x01*b.x13 + m.x02*b.x23 + m.x03*b.x33
output.x13 = m.x10*b.x03 + m.x11*b.x13 + m.x12*b.x23 + m.x13*b.x33
output.x23 = m.x20*b.x03 + m.x21*b.x13 + m.x22*b.x23 + m.x23*b.x33
output.x33 = m.x30*b.x03 + m.x31*b.x13 + m.x32*b.x23 + m.x33*b.x33
return output
}
// Rotate creates a transformation matrix that rotates vectors around an
// arbitrary axis. For example, to rotate around the X axis, the input
// vector would be [1, 0, 0].
//
// https://github.com/fogleman/pt/blob/master/pt/matrix.go
// http://ksuweb.kennesaw.edu/~plaval/math4490/rotgen.pdf
func (m Matrix) Rotate(v Vector, radians float64) Matrix {
v = v.Normalize()
s := math.Sin(radians)
c := math.Cos(radians)
t := 1 - c
r := Matrix{
t*v.X*v.X + c, t*v.X*v.Y + v.Z*s, t*v.Z*v.X - v.Y*s, 0,
t*v.X*v.Y - v.Z*s, t*v.Y*v.Y + c, t*v.Y*v.Z + v.X*s, 0,
t*v.Z*v.X + v.Y*s, t*v.Y*v.Z - v.X*s, t*v.Z*v.Z + c, 0,
0, 0, 0, 1}
return m.Multiply(r)
}
// Scale uniformly changes the size of a transformation matrix.
func (m Matrix) Scale(s float64) Matrix {
return Matrix{
m.x00 * s, m.x01, m.x02, m.x03,
m.x10, m.x11 * s, m.x12, m.x13,
m.x20, m.x21, m.x22 * s, m.x23,
m.x30, m.x31, m.x32, m.x33,
}
}
// SetTranslation overrides the current translation of the matrix.
func (m Matrix) SetTranslation(v Vector) Matrix {
mStripped := m
mStripped.x03 = v.X
mStripped.x13 = v.Y
mStripped.x23 = v.Z
return mStripped
}
// Translate adds a vector to a transformation matrix.
func (m Matrix) Translate(v Vector) Matrix {
return Matrix{
m.x00, m.x01, m.x02, m.x03 + v.X,
m.x10, m.x11, m.x12, m.x13 + v.Y,
m.x20, m.x21, m.x22, m.x23 + v.Z,
m.x30, m.x31, m.x32, m.x33,
}
}