func (v1 Vec3) OuterProd3(v2 Vec3) Mat3 {
	return Mat3{v1[0] * v2[0], v1[1] * v2[0], v1[2] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[2] * v2[1], v1[0] * v2[2], v1[1] * v2[2], v1[2] * v2[2]}
}
OuterProd3 does the vector outer product
of two vectors. The outer product produces an
3x3 matrix. E.G. a Vec3 * Vec3 = Mat3.

The outer product can be thought of as the "opposite"
of the Dot product. The Dot product treats both vectors like matrices
oriented such that the left one has N columns and the right has N rows.
So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.

The outer product orients it so they're facing "outward": Vec2*Vec3
= Mat2x1*Mat1x3 = Mat2x3.
package mgl32
import (
	"golang.org/x/image/math/f32"
	"math"
)
type Vec2 f32.Vec2
type Vec3 f32.Vec3
type Vec4 f32.Vec4
func (v Vec2) Vec3(z float32) Vec3 {
	return Vec3{v[0], v[1], z}
}
func (v Vec2) Vec4(z, w float32) Vec4 {
	return Vec4{v[0], v[1], z, w}
}
func (v Vec3) Vec4(w float32) Vec4 {
	return Vec4{v[0], v[1], v[2], w}
}
func (v Vec3) Vec2() Vec2 {
	return Vec2{v[0], v[1]}
}
func (v Vec4) Vec2() Vec2 {
	return Vec2{v[0], v[1]}
}
func (v Vec4) Vec3() Vec3 {
	return Vec3{v[0], v[1], v[2]}
}
func (v Vec2) Elem() (x, y float32) {
	return v[0], v[1]
}
func (v Vec3) Elem() (x, y, z float32) {
	return v[0], v[1], v[2]
}
func (v Vec4) Elem() (x, y, z, w float32) {
	return v[0], v[1], v[2], v[3]
}
func (v1 Vec3) Cross(v2 Vec3) Vec3 {
	return Vec3{v1[1]*v2[2] - v1[2]*v2[1], v1[2]*v2[0] - v1[0]*v2[2], v1[0]*v2[1] - v1[1]*v2[0]}
}
func (v Vec4) Quat() Quat {
	return Quat{v[3], Vec3{v[0], v[1], v[2]}}
}
func (v1 Vec2) Add(v2 Vec2) Vec2 {
	return Vec2{v1[0] + v2[0], v1[1] + v2[1]}
}
func (v1 Vec2) Sub(v2 Vec2) Vec2 {
	return Vec2{v1[0] - v2[0], v1[1] - v2[1]}
}
func (v1 Vec2) Mul(c float32) Vec2 {
	return Vec2{v1[0] * c, v1[1] * c}
}
func (v1 Vec2) Dot(v2 Vec2) float32 {
	return v1[0]*v2[0] + v1[1]*v2[1]
}
func (v1 Vec2) Len() float32 {
	return float32(math.Hypot(float64(v1[0]), float64(v1[1])))
}
func (v1 Vec2) LenSqr() float32 {
	return v1[0]*v1[0] + v1[1]*v1[1]
}
func (v1 Vec2) Normalize() Vec2 {
	l := 1.0 / v1.Len()
	return Vec2{v1[0] * l, v1[1] * l}
}
func (v1 Vec2) ApproxEqual(v2 Vec2) bool {
	for i := range v1 {
		if !FloatEqual(v1[i], v2[i]) {
			return false
		}
	}
	return true
}
func (v1 Vec2) ApproxEqualThreshold(v2 Vec2, threshold float32) bool {
	for i := range v1 {
		if !FloatEqualThreshold(v1[i], v2[i], threshold) {
			return false
		}
	}
	return true
}
func (v1 Vec2) ApproxFuncEqual(v2 Vec2, eq func(float32, float32) bool) bool {
	for i := range v1 {
		if !eq(v1[i], v2[i]) {
			return false
		}
	}
	return true
}
func (v Vec2) X() float32 {
	return v[0]
}
func (v Vec2) Y() float32 {
	return v[1]
}
func (v1 Vec2) OuterProd2(v2 Vec2) Mat2 {
	return Mat2{v1[0] * v2[0], v1[1] * v2[0], v1[0] * v2[1], v1[1] * v2[1]}
}
func (v1 Vec2) OuterProd3(v2 Vec3) Mat2x3 {
	return Mat2x3{v1[0] * v2[0], v1[1] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[0] * v2[2], v1[1] * v2[2]}
}
func (v1 Vec2) OuterProd4(v2 Vec4) Mat2x4 {
	return Mat2x4{v1[0] * v2[0], v1[1] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[0] * v2[2], v1[1] * v2[2], v1[0] * v2[3], v1[1] * v2[3]}
}
func (v1 Vec3) Add(v2 Vec3) Vec3 {
	return Vec3{v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]}
}
func (v1 Vec3) Sub(v2 Vec3) Vec3 {
	return Vec3{v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]}
}
func (v1 Vec3) Mul(c float32) Vec3 {
	return Vec3{v1[0] * c, v1[1] * c, v1[2] * c}
}
func (v1 Vec3) Dot(v2 Vec3) float32 {
	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]
}
func (v1 Vec3) Len() float32 {
	return float32(math.Sqrt(float64(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2])))
}
func (v1 Vec3) LenSqr() float32 {
	return v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]
}
func (v1 Vec3) Normalize() Vec3 {
	l := 1.0 / v1.Len()
	return Vec3{v1[0] * l, v1[1] * l, v1[2] * l}
}
func (v1 Vec3) ApproxEqual(v2 Vec3) bool {
	for i := range v1 {
		if !FloatEqual(v1[i], v2[i]) {
			return false
		}
	}
	return true
}
func (v1 Vec3) ApproxEqualThreshold(v2 Vec3, threshold float32) bool {
	for i := range v1 {
		if !FloatEqualThreshold(v1[i], v2[i], threshold) {
			return false
		}
	}
	return true
}
func (v1 Vec3) ApproxFuncEqual(v2 Vec3, eq func(float32, float32) bool) bool {
	for i := range v1 {
		if !eq(v1[i], v2[i]) {
			return false
		}
	}
	return true
}
func (v Vec3) X() float32 {
	return v[0]
}
func (v Vec3) Y() float32 {
	return v[1]
}
func (v Vec3) Z() float32 {
	return v[2]
}
func (v1 Vec3) OuterProd2(v2 Vec2) Mat3x2 {
	return Mat3x2{v1[0] * v2[0], v1[1] * v2[0], v1[2] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[2] * v2[1]}
}