tofu

Making something with OpenGL in Go
Log | Files | Refs

math.go (2649B)


      1 package tofu
      2 
      3 import "math"
      4 
      5 type Vec2 [2]float32
      6 type Vec3 [3]float32
      7 
      8 func (v Vec3) Normalize() Vec3 {
      9 	r := float32(math.Sqrt(float64(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])))
     10 	return Vec3{v[0] / r, v[1] / r, v[2] / r}
     11 }
     12 
     13 func (v Vec3) Add(w Vec3) Vec3 {
     14 	return Vec3{v[0] + w[0], v[1] + w[1], v[2] + w[2]}
     15 }
     16 
     17 func (v Vec3) Sub(w Vec3) Vec3 {
     18 	return Vec3{v[0] - w[0], v[1] - w[1], v[2] - w[2]}
     19 }
     20 
     21 func (v Vec3) Inverse() Vec3 {
     22 	return Vec3{-v[0], -v[1], -v[2]}
     23 }
     24 
     25 func (v Vec3) Cross(w Vec3) Vec3 {
     26 	return Vec3{
     27 		v[1]*w[2] - v[2]*w[1],
     28 		v[2]*w[0] - v[0]*w[2],
     29 		v[0]*w[1] - v[1]*w[0],
     30 	}
     31 }
     32 
     33 func (v Vec3) MulF(x float32) Vec3 {
     34 	return Vec3{v[0] * x, v[1] * x, v[2] * x}
     35 }
     36 
     37 type Vec4 [4]float32
     38 
     39 func (v Vec4) Vec3() Vec3 {
     40 	return Vec3{v[0], v[1], v[2]}
     41 }
     42 
     43 type Mat3 [9]float32
     44 
     45 func Rotate3(rad float32, axis Vec3) Mat3 {
     46 	x, y, z := axis[0], axis[1], axis[2]
     47 	c := float32(math.Cos(float64(rad)))
     48 	d := 1 - c
     49 	s := float32(math.Sin(float64(rad)))
     50 	return Mat3{c + x*x*d, y*x*d + z*s, z*x*d - y*s,
     51 		x*y*d - z*s, c + y*y*d, z*y*d + x*s,
     52 		x*z*d + y*s, y*z*d - x*s, c + z*z*d}
     53 }
     54 
     55 func (m Mat3) MulV(v Vec3) Vec3 {
     56 	return Vec3{
     57 		m[0]*v[0] + m[3]*v[1] + m[6]*v[2],
     58 		m[1]*v[0] + m[4]*v[1] + m[7]*v[2],
     59 		m[2]*v[0] + m[5]*v[1] + m[8]*v[2]}
     60 }
     61 
     62 // column major
     63 type Mat4 [16]float32
     64 
     65 // Mul multiplies m by n and returns newly allocated result.
     66 func (m Mat4) Mul(n Mat4) Mat4 {
     67 	var dst Mat4
     68 	for i := 0; i < 4; i++ {
     69 		for j := 0; j < 4; j++ {
     70 			for k := 0; k < 4; k++ {
     71 				dst[i+4*j] += m[i+4*k] * n[k+4*j]
     72 			}
     73 		}
     74 	}
     75 	return dst
     76 }
     77 
     78 func (m Mat4) MulVec(v Vec4) Vec4 {
     79 	return Vec4{
     80 		m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3],
     81 		m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3],
     82 		m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3],
     83 		m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3],
     84 	}
     85 }
     86 
     87 func Scale(r float32) Mat4 {
     88 	return Mat4{
     89 		r, 0, 0, 0,
     90 		0, r, 0, 0,
     91 		0, 0, r, 0,
     92 		0, 0, 0, 1,
     93 	}
     94 }
     95 
     96 func Translate(v Vec3) Mat4 {
     97 	var n Mat4
     98 	n[0] = 1
     99 	n[5] = 1
    100 	n[10] = 1
    101 	n[12] = v[0]
    102 	n[13] = v[1]
    103 	n[14] = v[2]
    104 	n[15] = 1
    105 	return n
    106 }
    107 
    108 func Rotate(rad float32, axis Vec3) Mat4 {
    109 	x, y, z := axis[0], axis[1], axis[2]
    110 	c := float32(math.Cos(float64(rad)))
    111 	d := 1 - c
    112 	s := float32(math.Sin(float64(rad)))
    113 	return Mat4{c + x*x*d, y*x*d + z*s, z*x*d - y*s, 0,
    114 		x*y*d - z*s, c + y*y*d, z*y*d + x*s, 0,
    115 		x*z*d + y*s, y*z*d - x*s, c + z*z*d, 0,
    116 		0, 0, 0, 1}
    117 }
    118 
    119 func Perspective(fov, asp, min, max float32) Mat4 {
    120 	tan := float32(math.Tan(float64(fov / 2)))
    121 	w := min * tan
    122 	h := w / asp
    123 
    124 	var mat Mat4
    125 	mat[0] = min / w
    126 	mat[5] = min / h
    127 	mat[10] = -(max + min) / (max - min)
    128 	mat[11] = -1
    129 	mat[14] = -(2 * min * max) / (max - min)
    130 	return mat
    131 }