# Packages
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
# README
Vector
Collection of generic, immutable vector math functions I've written overtime for different hobby projects.
API
Function | Vector2 | Vector3 | Vector4 | Description |
---|---|---|---|---|
Abs | ✅ | ✅ | ✅ | Returns a vector with each component's absolute value |
Add | ✅ | ✅ | ✅ | Component Wise Addition |
Angle | ✅ | ✅ | Returns the angle between two vectors | |
ToArr | ✅ | ✅ | ✅ | Returns a slice containing the vector component data |
ToFixedArr | ✅ | ✅ | ✅ | Returns a array containing the vector component data |
Ceil | ✅ | ✅ | ✅ | Ceils each vectors component to the nearest integer |
Clamp | ✅ | ✅ | ✅ | Clamps each component between two values |
ContainsNaN | ✅ | ✅ | ✅ | Returns true if any component of the vector is NaN |
Cross | ✅ | Returns the cross product between two vectors | ||
Dot | ✅ | ✅ | ✅ | Returns the dot product between two vectors |
DivByVector | ✅ | ✅ | ✅ | Component wise division |
Flip | ✅ | ✅ | ✅ | Scales the vector by -1 |
FlipX | ✅ | ✅ | ✅ | Returns a vector with the X component multiplied by -1 |
FlipY | ✅ | ✅ | ✅ | Returns a vector with the Y component multiplied by -1 |
FlipZ | ✅ | ✅ | Returns a vector with the Z component multiplied by -1 | |
FlipW | ✅ | Returns a vector with the W component multiplied by -1 | ||
Floor | ✅ | ✅ | ✅ | Floors each vectors component |
Format | ✅ | ✅ | ✅ | Build a string with vector data |
Length | ✅ | ✅ | ✅ | Returns the length of the vector |
LengthSquared | ✅ | ✅ | ✅ | Returns the squared length of the vector |
Max | ✅ | ✅ | ✅ | Returns a new vector where each component is the largest value between the two vectors |
MaxX | ✅ | ✅ | ✅ | Returns the largest X component between the two vectors |
MaxY | ✅ | ✅ | ✅ | Returns the largest Y component between the two vectors |
MaxZ | ✅ | ✅ | Returns the largest Z component between the two vectors | |
MaxW | ✅ | Returns the largest W component between the two vectors | ||
MaxComponent | ✅ | ✅ | ✅ | Returns the vectors largest component |
Midpoint | ✅ | ✅ | ✅ | Finds the mid point between two vectors |
Min | ✅ | ✅ | ✅ | Returns a new vector where each component is the smallest value between the two vectors |
MinX | ✅ | ✅ | ✅ | Returns the smallest X component between the two vectors |
MinY | ✅ | ✅ | ✅ | Returns the smallest Y component between the two vectors |
MinZ | ✅ | ✅ | Returns the smallest Z component between the two vectors | |
MinW | ✅ | Returns the smallest W component between the two vectors | ||
MinComponent | ✅ | ✅ | ✅ | Returns the vectors smallest component |
MultByVector | ✅ | ✅ | ✅ | component wise multiplication, also known as Hadamard product |
Normalized | ✅ | ✅ | ✅ | Returns the normalized vector |
NearZero | ✅ | ✅ | ✅ | Returns true if all of the components are near 0 |
Round | ✅ | ✅ | ✅ | Rounds each vectors component to the nearest integer |
Scale | ✅ | ✅ | ✅ | Scales the vector by some constant |
Sqrt | ✅ | ✅ | ✅ | Returns a vector with each component's square root |
Sub | ✅ | ✅ | ✅ | Component Wise Subtraction |
Values | ✅ | ✅ | ✅ | Returns all components of the vector |
X | ✅ | ✅ | ✅ | Returns the x component of the vector |
Y | ✅ | ✅ | ✅ | Returns the y component of the vector |
Z | ✅ | ✅ | Returns the z component of the vector | |
W | ✅ | Returns the w component of the vector | ||
XY | ✅ | ✅ | Equivalent to vector2.New[T](v.x, v.y) | |
YZ | ✅ | ✅ | Equivalent to vector2.New[T](v.y, v.z) | |
XZ | ✅ | ✅ | Equivalent to vector2.New[T](v.x, v.z) | |
YX | ✅ | ✅ | ✅ | Equivalent to vector2.New[T](v.y, v.x) |
ZX | ✅ | ✅ | Equivalent to vector2.New[T](v.z, v.x) | |
ZY | ✅ | ✅ | Equivalent to vector2.New[T](v.z, v.y) | |
Lerp | ✅ | ✅ | ✅ | Interpolates between two vectors by t. |
LerpClamped | ✅ | ✅ | ✅ | Interpolates between two vectors by t. T is clamped 0 to 1 |
Log | ✅ | ✅ | ✅ | Returns the natural logarithm for each component |
Log2 | ✅ | ✅ | ✅ | Returns the binary logarithm for each component |
Log10 | ✅ | ✅ | ✅ | Returns the decimal logarithm for each component |
Exp | ✅ | ✅ | ✅ | Returns e**x, the base-e exponential for each component |
Exp2 | ✅ | ✅ | ✅ | Returns 2**x, the base-2 exponential for each component |
Expm1 | ✅ | ✅ | ✅ | Returns e**x - 1, the base-e exponential for each component minus 1. It is more accurate than Exp(x) - 1 when the component is near zero |
Write | ✅ | ✅ | ✅ | Write vector component data as binary to io.Writer |
Example
Below is an example on how to implement the different sign distance field functions in a generic fashion to work for both int8
, int16
, int32
int
, int64
, float32
, and float64
.
The code below produces this output:
package main
import (
"fmt"
"image"
"image/color"
"image/png"
"math"
"os"
"github.com/EliCDavis/vector"
"github.com/EliCDavis/vector/vector2"
"github.com/EliCDavis/vector/vector3"
)
type Field[T vector.Number] func(v vector3.Vector[T]) float64
func Sphere[T vector.Number](pos vector3.Vector[T], radius float64) Field[T] {
return func(v vector3.Vector[T]) float64 {
return v.Distance(pos) - radius
}
}
func Box[T vector.Number](pos vector3.Vector[T], bounds vector3.Vector[T]) Field[T] {
halfBounds := bounds.Scale(0.5)
// It's best to watch the video to understand
// https://www.youtube.com/watch?v=62-pRVZuS5c
return func(v vector3.Vector[T]) float64 {
q := v.Sub(pos).Abs().Sub(halfBounds)
inside := math.Min(float64(q.MaxComponent()), 0)
return vector3.Max(q, vector3.Zero[T]()).Length() + inside
}
}
func Union[T vector.Number](fields ...Field[T]) Field[T] {
return func(v vector3.Vector[T]) float64 {
min := math.MaxFloat64
for _, f := range fields {
fv := f(v)
if fv < min {
min = fv
}
}
return min
}
}
func Intersect[T vector.Number](fields ...Field[T]) Field[T] {
return func(v vector3.Vector[T]) float64 {
max := -math.MaxFloat64
for _, f := range fields {
fv := f(v)
if fv > max {
max = fv
}
}
return max
}
}
func Subtract[T vector.Number](minuend, subtrahend Field[T]) Field[T] {
return func(f vector3.Vector[T]) float64 {
return math.Max(minuend(f), -subtrahend(f))
}
}
func Translate[T vector.Number](field Field[T], translation vector3.Vector[T]) Field[T] {
return func(v vector3.Vector[T]) float64 {
return field(v.Sub(translation))
}
}
func evaluateAtDepth[T vector.Number](dimension int, field Field[T], depth T, i int) {
img := image.NewRGBA(image.Rectangle{
image.Point{0, 0},
image.Point{dimension, dimension},
})
for x := 0; x < dimension; x++ {
for y := 0; y < dimension; y++ {
v := field(vector3.New[T](T(x), T(y), depth))
byteVal := (v / float64(dimension/20)) * 255
var c color.Color
if v > 0 {
c = color.RGBA{R: 0, G: 0, B: byte(byteVal), A: 255}
} else {
c = color.RGBA{R: 0, G: byte(-byteVal), B: 0, A: 255}
}
img.Set(x, y, c)
}
}
f, err := os.Create(fmt.Sprintf("field_%04d.png", i))
if err != nil {
panic(err)
}
defer f.Close()
err = png.Encode(f, img)
if err != nil {
panic(err)
}
}
func main() {
dimension := 512
quarterDim := float64(dimension) / 4.
middleCoord := vector2.
Fill(dimension).
Scale(0.5).
ToFloat64()
middleCord3D := vector3.New(middleCoord.X(), middleCoord.Y(), 0)
smallRing := Subtract(
Sphere(middleCord3D, 100),
Sphere(middleCord3D, 50),
)
field := Intersect(
Subtract(
Sphere(middleCord3D, 200),
Sphere(middleCord3D, 100),
),
Union(
Translate(smallRing, vector3.New(1., 1., 0.).Scale(quarterDim)),
Translate(smallRing, vector3.New(1., -1., 0.).Scale(quarterDim)),
Translate(smallRing, vector3.New(-1., 1., 0.).Scale(quarterDim)),
Translate(smallRing, vector3.New(-1., -1., 0.).Scale(quarterDim)),
Box(middleCord3D, middleCord3D),
),
)
for i := 0; i < 100; i++ {
evaluateAtDepth(dimension, field, float64(-dimension/2)+(float64(i*dimension)*0.01), i)
}
}