mirror of https://github.com/liamg/aminal.git
208 lines
7.5 KiB
Cheetah
208 lines
7.5 KiB
Cheetah
// Copyright 2014 The go-gl/mathgl Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// <<.Comment>>
|
|
// Edit <<.TemplateName>> and run "go generate" to make changes.
|
|
|
|
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) Vec2() Vec2 {
|
|
return Vec2{v[0], v[1]}
|
|
}
|
|
|
|
func (v Vec3) Vec4(w float32) Vec4 {
|
|
return Vec4{v[0], v[1], v[2], w}
|
|
}
|
|
|
|
func (v Vec4) Vec2() Vec2 {
|
|
return Vec2{v[0], v[1]}
|
|
}
|
|
|
|
func (v Vec4) Vec3() Vec3 {
|
|
return Vec3{v[0], v[1], v[2]}
|
|
}
|
|
|
|
// Elem extracts the elements of the vector for direct value assignment.
|
|
func (v Vec2) Elem() (x, y float32) {
|
|
return v[0], v[1]
|
|
}
|
|
|
|
// Elem extracts the elements of the vector for direct value assignment.
|
|
func (v Vec3) Elem() (x, y, z float32) {
|
|
return v[0], v[1], v[2]
|
|
}
|
|
|
|
// Elem extracts the elements of the vector for direct value assignment.
|
|
func (v Vec4) Elem() (x, y, z, w float32) {
|
|
return v[0], v[1], v[2], v[3]
|
|
}
|
|
|
|
// The vector cross product is an operation only defined on 3D vectors. It is equivalent to
|
|
// 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]}.
|
|
// Another interpretation is that it's the vector whose magnitude is |v1||v2|sin(theta)
|
|
// where theta is the angle between v1 and v2.
|
|
//
|
|
// The cross product is most often used for finding surface normals. The cross product of vectors
|
|
// will generate a vector that is perpendicular to the plane they form.
|
|
//
|
|
// Technically, a generalized cross product exists as an "(N-1)ary" operation
|
|
// (that is, the 4D cross product requires 3 4D vectors). But the binary
|
|
// 3D (and 7D) cross product is the most important. It can be considered
|
|
// the area of a parallelogram with sides v1 and v2.
|
|
//
|
|
// Like the dot product, the cross product is roughly a measure of directionality.
|
|
// Two normalized perpendicular vectors will return a vector with a magnitude of
|
|
// 1.0 or -1.0 and two parallel vectors will return a vector with magnitude 0.0.
|
|
// The cross product is "anticommutative" meaning v1.Cross(v2) = -v2.Cross(v1),
|
|
// this property can be useful to know when finding normals,
|
|
// as taking the wrong cross product can lead to the opposite normal of the one you want.
|
|
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]}
|
|
}
|
|
|
|
|
|
<</* Common functions for all vectors */>>
|
|
<<range $m := enum 2 3 4>>
|
|
<<$type := typename $m 1>>
|
|
|
|
// Add performs element-wise addition between two vectors. It is equivalent to iterating
|
|
// over every element of v1 and adding the corresponding element of v2 to it.
|
|
func (v1 <<$type>>) Add(v2 <<$type>>) <<$type>> {
|
|
return <<$type>>{<<range $i := iter 0 $m>> v1[<<$i>>] + v2[<<$i>>], <<end>>}
|
|
}
|
|
|
|
// Sub performs element-wise subtraction between two vectors. It is equivalent to iterating
|
|
// over every element of v1 and subtracting the corresponding element of v2 from it.
|
|
func (v1 <<$type>>) Sub(v2 <<$type>>) <<$type>> {
|
|
return <<$type>>{<<range $i := iter 0 $m>> v1[<<$i>>] - v2[<<$i>>], <<end>>}
|
|
}
|
|
|
|
// Mul performs a scalar multiplication between the vector and some constant value
|
|
// c. This is equivalent to iterating over every vector element and multiplying by c.
|
|
func (v1 <<$type>>) Mul(c float32) <<$type>> {
|
|
return <<$type>>{<<range $i := iter 0 $m>> v1[<<$i>>] * c, <<end>>}
|
|
}
|
|
|
|
// Dot returns the dot product of this vector with another. There are multiple ways
|
|
// to describe this value. One is the multiplication of their lengths and cos(theta) where
|
|
// theta is the angle between the vectors: v1.v2 = |v1||v2|cos(theta).
|
|
//
|
|
// The other (and what is actually done) is the sum of the element-wise multiplication of all
|
|
// elements. So for instance, two Vec3s would yield v1.x * v2.x + v1.y * v2.y + v1.z * v2.z.
|
|
//
|
|
// This means that the dot product of a vector and itself is the square of its Len (within
|
|
// the bounds of floating points error).
|
|
//
|
|
// The dot product is roughly a measure of how closely two vectors are to pointing in the same
|
|
// direction. If both vectors are normalized, the value will be -1 for opposite pointing,
|
|
// one for same pointing, and 0 for perpendicular vectors.
|
|
func (v1 <<$type>>) Dot(v2 <<$type>>) float32 {
|
|
return <<range $i := iter 0 $m>><<sep "+" $i>> v1[<<$i>>]*v2[<<$i>>] <<end>>
|
|
}
|
|
|
|
// Len returns the vector's length. Note that this is NOT the dimension of
|
|
// the vector (len(v)), but the mathematical length. This is equivalent to the square
|
|
// root of the sum of the squares of all elements. E.G. for a Vec2 it's
|
|
// math.Hypot(v[0], v[1]).
|
|
func (v1 <<$type>>) Len() float32 {
|
|
<<if eq $m 2 >>
|
|
return float32(math.Hypot(float64(v1[0]), float64(v1[1])))
|
|
<<else>>
|
|
return float32(math.Sqrt(float64(<<repeat $m "v1[%d]*v1[%d]" "+">>)))
|
|
<<end>>
|
|
}
|
|
|
|
// Normalize normalizes the vector. Normalization is (1/|v|)*v,
|
|
// making this equivalent to v.Scale(1/v.Len()). If the len is 0.0,
|
|
// this function will return an infinite value for all elements due
|
|
// to how floating point division works in Go (n/0.0 = math.Inf(Sign(n))).
|
|
//
|
|
// Normalization makes a vector's Len become 1.0 (within the margin of floating point error),
|
|
// while maintaining its directionality.
|
|
//
|
|
// (Can be seen here: http://play.golang.org/p/Aaj7SnbqIp )
|
|
func (v1 <<$type>>) Normalize() <<$type>> {
|
|
l := 1.0 / v1.Len()
|
|
return <<$type>>{<<range $i := iter 0 $m>>v1[<<$i>>] * l,<<end>>}
|
|
}
|
|
|
|
// ApproxEqual takes in a vector and does an element-wise
|
|
// approximate float comparison as if FloatEqual had been used
|
|
func (v1 <<$type>>) ApproxEqual(v2 <<$type>>) bool {
|
|
for i := range v1 {
|
|
if !FloatEqual(v1[i], v2[i]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// ApproxThresholdEq takes in a threshold for comparing two floats, and uses it to do an
|
|
// element-wise comparison of the vector to another.
|
|
func (v1 <<$type>>) ApproxEqualThreshold(v2 <<$type>>, threshold float32) bool {
|
|
for i := range v1 {
|
|
if !FloatEqualThreshold(v1[i], v2[i], threshold) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// ApproxFuncEq takes in a func that compares two floats, and uses it to do an element-wise
|
|
// comparison of the vector to another. This is intended to be used with FloatEqualFunc
|
|
func (v1 <<$type>>) ApproxFuncEqual(v2 <<$type>>, eq func(float32, float32) bool) bool {
|
|
for i := range v1 {
|
|
if !eq(v1[i], v2[i]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
<<range $i := iter 0 $m>>
|
|
// This is an element access func, it is equivalent to v[n] where
|
|
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
|
// show that this is more or less as fast as direct acces, probably due to
|
|
// inlining, so use v[0] or v.X() depending on personal preference.
|
|
func (v <<$type>>) <<elementname $i>>() float32 {
|
|
return v[<<$i>>]
|
|
}
|
|
<<end>>
|
|
|
|
<<range $n := enum 2 3 4>>
|
|
// Does the vector outer product
|
|
// of two vectors. The outer product produces an
|
|
// <<$m>>x<<$n>> matrix. E.G. a Vec<<$m>> * Vec<<$n>> = <<typename $m $n>>.
|
|
//
|
|
// 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.
|
|
func (v1 <<$type>>) OuterProd<<$n>>(v2 <<typename $n 1>>) <<typename $m $n>> {
|
|
return <<typename $m $n>>{<<range $i := matiter $m $n>>v1[<<$i.M>>] * v2[<<$i.N>>], <<end>>}
|
|
}
|
|
<<end>>
|
|
|
|
<<end>> <</* range $m */>>
|