github.com/F4RD1N/gomobile@v1.0.1/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  //	m.Mul(p, &Mat4{
    96  //		{x, 0, 0, 0},
    97  //		{0, y, 0, 0},
    98  //		{0, 0, z, 0},
    99  //		{0, 0, 0, 1},
   100  //	}).
   101  func (m *Mat4) Scale(p *Mat4, x, y, z float32) {
   102  	m[0][0] = p[0][0] * x
   103  	m[0][1] = p[0][1] * y
   104  	m[0][2] = p[0][2] * z
   105  	m[0][3] = p[0][3]
   106  	m[1][0] = p[1][0] * x
   107  	m[1][1] = p[1][1] * y
   108  	m[1][2] = p[1][2] * z
   109  	m[1][3] = p[1][3]
   110  	m[2][0] = p[2][0] * x
   111  	m[2][1] = p[2][1] * y
   112  	m[2][2] = p[2][2] * z
   113  	m[2][3] = p[2][3]
   114  	m[3][0] = p[3][0] * x
   115  	m[3][1] = p[3][1] * y
   116  	m[3][2] = p[3][2] * z
   117  	m[3][3] = p[3][3]
   118  }
   119  
   120  // Translate sets m to be a translation followed by p.
   121  // It is equivalent to
   122  //	m.Mul(p, &Mat4{
   123  //		{1, 0, 0, x},
   124  //		{0, 1, 0, y},
   125  //		{0, 0, 1, z},
   126  //		{0, 0, 0, 1},
   127  //	}).
   128  func (m *Mat4) Translate(p *Mat4, x, y, z float32) {
   129  	m[0][0] = p[0][0]
   130  	m[0][1] = p[0][1]
   131  	m[0][2] = p[0][2]
   132  	m[0][3] = p[0][0]*x + p[0][1]*y + p[0][2]*z + p[0][3]
   133  	m[1][0] = p[1][0]
   134  	m[1][1] = p[1][1]
   135  	m[1][2] = p[1][2]
   136  	m[1][3] = p[1][0]*x + p[1][1]*y + p[1][2]*z + p[1][3]
   137  	m[2][0] = p[2][0]
   138  	m[2][1] = p[2][1]
   139  	m[2][2] = p[2][2]
   140  	m[2][3] = p[2][0]*x + p[2][1]*y + p[2][2]*z + p[2][3]
   141  	m[3][0] = p[3][0]
   142  	m[3][1] = p[3][1]
   143  	m[3][2] = p[3][2]
   144  	m[3][3] = p[3][0]*x + p[3][1]*y + p[3][2]*z + p[3][3]
   145  }
   146  
   147  // Rotate sets m to a rotation in radians around a specified axis, followed by p.
   148  // It is equivalent to m.Mul(p, affineRotation).
   149  func (m *Mat4) Rotate(p *Mat4, angle Radian, axis *Vec3) {
   150  	a := *axis
   151  	a.Normalize()
   152  
   153  	c, s := Cos(float32(angle)), Sin(float32(angle))
   154  	d := 1 - c
   155  
   156  	m.Mul(p, &Mat4{{
   157  		c + d*a[0]*a[1],
   158  		0 + d*a[0]*a[1] + s*a[2],
   159  		0 + d*a[0]*a[1] - s*a[1],
   160  		0,
   161  	}, {
   162  		0 + d*a[1]*a[0] - s*a[2],
   163  		c + d*a[1]*a[1],
   164  		0 + d*a[1]*a[2] + s*a[0],
   165  		0,
   166  	}, {
   167  		0 + d*a[2]*a[0] + s*a[1],
   168  		0 + d*a[2]*a[1] - s*a[0],
   169  		c + d*a[2]*a[2],
   170  		0,
   171  	}, {
   172  		0, 0, 0, 1,
   173  	}})
   174  }
   175  
   176  func (m *Mat4) LookAt(eye, center, up *Vec3) {
   177  	f, s, u := new(Vec3), new(Vec3), new(Vec3)
   178  
   179  	*f = *center
   180  	f.Sub(f, eye)
   181  	f.Normalize()
   182  
   183  	s.Cross(f, up)
   184  	s.Normalize()
   185  	u.Cross(s, f)
   186  
   187  	*m = Mat4{
   188  		{s[0], u[0], -f[0], 0},
   189  		{s[1], u[1], -f[1], 0},
   190  		{s[2], u[2], -f[2], 0},
   191  		{-s.Dot(eye), -u.Dot(eye), +f.Dot(eye), 1},
   192  	}
   193  }