github.com/coming-chat/gomobile@v0.0.0-20220601074111-56995f7d7aba/exp/f32/mat4.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package f32 6 7 import "fmt" 8 9 // A Mat4 is a 4x4 matrix of float32 values. 10 // Elements are indexed first by row then column, i.e. m[row][column]. 11 type Mat4 [4]Vec4 12 13 func (m Mat4) String() string { 14 return fmt.Sprintf(`Mat4[% 0.3f, % 0.3f, % 0.3f, % 0.3f, 15 % 0.3f, % 0.3f, % 0.3f, % 0.3f, 16 % 0.3f, % 0.3f, % 0.3f, % 0.3f, 17 % 0.3f, % 0.3f, % 0.3f, % 0.3f]`, 18 m[0][0], m[0][1], m[0][2], m[0][3], 19 m[1][0], m[1][1], m[1][2], m[1][3], 20 m[2][0], m[2][1], m[2][2], m[2][3], 21 m[3][0], m[3][1], m[3][2], m[3][3]) 22 } 23 24 func (m *Mat4) Identity() { 25 *m = Mat4{ 26 {1, 0, 0, 0}, 27 {0, 1, 0, 0}, 28 {0, 0, 1, 0}, 29 {0, 0, 0, 1}, 30 } 31 } 32 33 func (m *Mat4) Eq(n *Mat4, epsilon float32) bool { 34 for i := range m { 35 for j := range m[i] { 36 diff := m[i][j] - n[i][j] 37 if diff < -epsilon || +epsilon < diff { 38 return false 39 } 40 } 41 } 42 return true 43 } 44 45 // Mul stores a × b in m. 46 func (m *Mat4) Mul(a, b *Mat4) { 47 // Store the result in local variables, in case m == a || m == b. 48 m00 := a[0][0]*b[0][0] + a[0][1]*b[1][0] + a[0][2]*b[2][0] + a[0][3]*b[3][0] 49 m01 := a[0][0]*b[0][1] + a[0][1]*b[1][1] + a[0][2]*b[2][1] + a[0][3]*b[3][1] 50 m02 := a[0][0]*b[0][2] + a[0][1]*b[1][2] + a[0][2]*b[2][2] + a[0][3]*b[3][2] 51 m03 := a[0][0]*b[0][3] + a[0][1]*b[1][3] + a[0][2]*b[2][3] + a[0][3]*b[3][3] 52 m10 := a[1][0]*b[0][0] + a[1][1]*b[1][0] + a[1][2]*b[2][0] + a[1][3]*b[3][0] 53 m11 := a[1][0]*b[0][1] + a[1][1]*b[1][1] + a[1][2]*b[2][1] + a[1][3]*b[3][1] 54 m12 := a[1][0]*b[0][2] + a[1][1]*b[1][2] + a[1][2]*b[2][2] + a[1][3]*b[3][2] 55 m13 := a[1][0]*b[0][3] + a[1][1]*b[1][3] + a[1][2]*b[2][3] + a[1][3]*b[3][3] 56 m20 := a[2][0]*b[0][0] + a[2][1]*b[1][0] + a[2][2]*b[2][0] + a[2][3]*b[3][0] 57 m21 := a[2][0]*b[0][1] + a[2][1]*b[1][1] + a[2][2]*b[2][1] + a[2][3]*b[3][1] 58 m22 := a[2][0]*b[0][2] + a[2][1]*b[1][2] + a[2][2]*b[2][2] + a[2][3]*b[3][2] 59 m23 := a[2][0]*b[0][3] + a[2][1]*b[1][3] + a[2][2]*b[2][3] + a[2][3]*b[3][3] 60 m30 := a[3][0]*b[0][0] + a[3][1]*b[1][0] + a[3][2]*b[2][0] + a[3][3]*b[3][0] 61 m31 := a[3][0]*b[0][1] + a[3][1]*b[1][1] + a[3][2]*b[2][1] + a[3][3]*b[3][1] 62 m32 := a[3][0]*b[0][2] + a[3][1]*b[1][2] + a[3][2]*b[2][2] + a[3][3]*b[3][2] 63 m33 := a[3][0]*b[0][3] + a[3][1]*b[1][3] + a[3][2]*b[2][3] + a[3][3]*b[3][3] 64 m[0][0] = m00 65 m[0][1] = m01 66 m[0][2] = m02 67 m[0][3] = m03 68 m[1][0] = m10 69 m[1][1] = m11 70 m[1][2] = m12 71 m[1][3] = m13 72 m[2][0] = m20 73 m[2][1] = m21 74 m[2][2] = m22 75 m[2][3] = m23 76 m[3][0] = m30 77 m[3][1] = m31 78 m[3][2] = m32 79 m[3][3] = m33 80 } 81 82 // Perspective sets m to be the GL perspective matrix. 83 func (m *Mat4) Perspective(fov Radian, aspect, near, far float32) { 84 t := Tan(float32(fov) / 2) 85 86 m[0][0] = 1 / (aspect * t) 87 m[1][1] = 1 / t 88 m[2][2] = -(far + near) / (far - near) 89 m[2][3] = -1 90 m[3][2] = -2 * far * near / (far - near) 91 } 92 93 // Scale sets m to be a scale followed by p. 94 // It is equivalent to 95 // 96 // m.Mul(p, &Mat4{ 97 // {x, 0, 0, 0}, 98 // {0, y, 0, 0}, 99 // {0, 0, z, 0}, 100 // {0, 0, 0, 1}, 101 // }). 102 func (m *Mat4) Scale(p *Mat4, x, y, z float32) { 103 m[0][0] = p[0][0] * x 104 m[0][1] = p[0][1] * y 105 m[0][2] = p[0][2] * z 106 m[0][3] = p[0][3] 107 m[1][0] = p[1][0] * x 108 m[1][1] = p[1][1] * y 109 m[1][2] = p[1][2] * z 110 m[1][3] = p[1][3] 111 m[2][0] = p[2][0] * x 112 m[2][1] = p[2][1] * y 113 m[2][2] = p[2][2] * z 114 m[2][3] = p[2][3] 115 m[3][0] = p[3][0] * x 116 m[3][1] = p[3][1] * y 117 m[3][2] = p[3][2] * z 118 m[3][3] = p[3][3] 119 } 120 121 // Translate sets m to be a translation followed by p. 122 // It is equivalent to 123 // 124 // m.Mul(p, &Mat4{ 125 // {1, 0, 0, x}, 126 // {0, 1, 0, y}, 127 // {0, 0, 1, z}, 128 // {0, 0, 0, 1}, 129 // }). 130 func (m *Mat4) Translate(p *Mat4, x, y, z float32) { 131 m[0][0] = p[0][0] 132 m[0][1] = p[0][1] 133 m[0][2] = p[0][2] 134 m[0][3] = p[0][0]*x + p[0][1]*y + p[0][2]*z + p[0][3] 135 m[1][0] = p[1][0] 136 m[1][1] = p[1][1] 137 m[1][2] = p[1][2] 138 m[1][3] = p[1][0]*x + p[1][1]*y + p[1][2]*z + p[1][3] 139 m[2][0] = p[2][0] 140 m[2][1] = p[2][1] 141 m[2][2] = p[2][2] 142 m[2][3] = p[2][0]*x + p[2][1]*y + p[2][2]*z + p[2][3] 143 m[3][0] = p[3][0] 144 m[3][1] = p[3][1] 145 m[3][2] = p[3][2] 146 m[3][3] = p[3][0]*x + p[3][1]*y + p[3][2]*z + p[3][3] 147 } 148 149 // Rotate sets m to a rotation in radians around a specified axis, followed by p. 150 // It is equivalent to m.Mul(p, affineRotation). 151 func (m *Mat4) Rotate(p *Mat4, angle Radian, axis *Vec3) { 152 a := *axis 153 a.Normalize() 154 155 c, s := Cos(float32(angle)), Sin(float32(angle)) 156 d := 1 - c 157 158 m.Mul(p, &Mat4{{ 159 c + d*a[0]*a[1], 160 0 + d*a[0]*a[1] + s*a[2], 161 0 + d*a[0]*a[1] - s*a[1], 162 0, 163 }, { 164 0 + d*a[1]*a[0] - s*a[2], 165 c + d*a[1]*a[1], 166 0 + d*a[1]*a[2] + s*a[0], 167 0, 168 }, { 169 0 + d*a[2]*a[0] + s*a[1], 170 0 + d*a[2]*a[1] - s*a[0], 171 c + d*a[2]*a[2], 172 0, 173 }, { 174 0, 0, 0, 1, 175 }}) 176 } 177 178 func (m *Mat4) LookAt(eye, center, up *Vec3) { 179 f, s, u := new(Vec3), new(Vec3), new(Vec3) 180 181 *f = *center 182 f.Sub(f, eye) 183 f.Normalize() 184 185 s.Cross(f, up) 186 s.Normalize() 187 u.Cross(s, f) 188 189 *m = Mat4{ 190 {s[0], u[0], -f[0], 0}, 191 {s[1], u[1], -f[1], 0}, 192 {s[2], u[2], -f[2], 0}, 193 {-s.Dot(eye), -u.Dot(eye), +f.Dot(eye), 1}, 194 } 195 }