1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2026-05-13 16:49:10 -04:00
Files
OpenDiablo2/d2common/d2math/vector4.go
Ian 0dee6518b4 WIP: Add checkboxes, de-lint ecs branch (#1017)
* Add checkboxes, checkbox test scene

* De-lint ecs branch
2021-01-04 00:43:56 -08:00

191 lines
4.6 KiB
Go

package d2math
import "math"
// Vector4Like is a generic interface for things like are like a Vector4
type Vector4Like interface {
Vector2Like
Vector3Like
XYZW() (x, y, z, w float64)
}
// static check that Vector4 is Vector4Like
var _ Vector4Like = &Vector4{}
// NewVector4 creates a new Vector4
func NewVector4(x, y, z, w float64) *Vector4 {
return &Vector4{
X: x,
Y: y,
Z: z,
W: w,
}
}
// Vector4 is a representation of a vector in 4D space.
type Vector4 struct {
X, Y, Z, W float64
}
// XY returns the x and y components of the vector
func (v *Vector4) XY() (x, y float64) {
return v.X, v.Y
}
// XYZ returns the x, y, and z components of the vector
func (v *Vector4) XYZ() (x, y, z float64) {
return v.X, v.Y, v.Z
}
// XYZW returns the x, y, z, and w components of the vector
func (v *Vector4) XYZW() (x, y, z, w float64) {
return v.X, v.Y, v.Z, v.W
}
// Clone makes a clone of this vector
func (v *Vector4) Clone() *Vector4 {
return NewVector4(v.XYZW())
}
// Copy the components of a given Vector into this Vector.
func (v *Vector4) Copy(other *Vector4) *Vector4 {
return v.Set(other.XYZW())
}
// Equals checks if this vector is equal to the given vector
func (v *Vector4) Equals(other *Vector4) bool {
return math.Abs(v.X-other.X) < Epsilon &&
math.Abs(v.Y-other.Y) < Epsilon &&
math.Abs(v.Z-other.Z) < Epsilon &&
math.Abs(v.W-other.W) < Epsilon
}
// Set the x, y, z, and w components of this vector
func (v *Vector4) Set(x, y, z, w float64) *Vector4 {
v.X, v.Y, v.Z, v.W = x, y, z, w
return v
}
// Add the given vector to this vector
func (v *Vector4) Add(other *Vector4) *Vector4 {
return v.Set(v.X+other.X, v.Y+other.Y, v.Z+other.Z, v.W+other.W)
}
// Subtract the given vector from this vector
func (v *Vector4) Subtract(other *Vector4) *Vector4 {
return v.Set(v.X-other.X, v.Y-other.Y, v.Z-other.Z, v.W-other.W)
}
// Scale this vector by a scalar value
func (v *Vector4) Scale(s float64) *Vector4 {
return v.Set(v.X*s, v.Y*s, v.Z*s, v.W*s)
}
// Length returns the length (magnitude) of this vector
func (v *Vector4) Length() float64 {
return math.Sqrt(v.LengthSquared())
}
// LengthSquared returns the length of this vector, squared
func (v *Vector4) LengthSquared() float64 {
return v.X*v.X + v.Y*v.Y + v.Z*v.Z + v.W*v.W
}
// Normalize this vector to unit length of 1 in the same direction
func (v *Vector4) Normalize() *Vector4 {
l := v.LengthSquared()
if l > 0 {
v.Scale(1 / math.Sqrt(l))
}
return v
}
// Dot calculates the dot product with the given vector
func (v *Vector4) Dot(other *Vector4) float64 {
return v.X*other.X + v.Y*other.Y + v.Z*other.Z + v.W*other.W
}
// Lerp linearly interpolates with the given vector using position `t`
func (v *Vector4) Lerp(other *Vector4, t float64) *Vector4 {
return v.Set(
v.X+t*(other.X-v.X),
v.Y+t*(other.Y-v.Y),
v.Z+t*(other.Z-v.Z),
v.W+t*(other.W-v.W),
)
}
// Multiply this vector by the given vector
func (v *Vector4) Multiply(other *Vector4) *Vector4 {
return v.Set(
v.X*other.X,
v.Y*other.Y,
v.Z*other.Z,
v.W*other.W,
)
}
// Divide this vector by the given vector
func (v *Vector4) Divide(other *Vector4) *Vector4 {
return v.Set(
v.X/other.X,
v.Y/other.Y,
v.Z/other.Z,
v.W/other.W,
)
}
// Distance calculates the distance between this vector and the given vector
func (v *Vector4) Distance(other *Vector4) float64 {
return math.Sqrt(v.DistanceSquared(other))
}
// DistanceSquared calculates the distance between this vector and the given vector, squared
func (v *Vector4) DistanceSquared(other *Vector4) float64 {
dx := other.X - v.X
dy := other.Y - v.Y
dz := other.Z - v.Z
dw := other.W - v.W
return dx*dx + dy*dy + dz*dz + dw*dw
}
// Negate the signs of the components of this vector
func (v *Vector4) Negate() *Vector4 {
return v.Scale(-1)
}
// TransformMatrix4 transforms this vector with the given Matrix4
func (v *Vector4) TransformMatrix4(m4 *Matrix4) *Vector4 {
m := m4.Values
return v.Set(
m[0]*v.X+m[4]*v.Y+m[8]*v.Z+m[12]*v.W,
m[1]*v.X+m[5]*v.Y+m[9]*v.Z+m[13]*v.W,
m[2]*v.X+m[6]*v.Y+m[10]*v.Z+m[14]*v.W,
m[3]*v.X+m[7]*v.Y+m[11]*v.Z+m[15]*v.W,
)
}
// TransformQuaternion transforms this vector with the given Quaternion
func (v *Vector4) TransformQuaternion(q *Quaternion) *Vector4 {
ix := q.W*v.X + q.Y*v.Z - q.Z*v.Y
iy := q.W*v.Y + q.Z*v.X - q.X*v.Z
iz := q.W*v.Z + q.X*v.Y - q.Y*v.X
iw := -q.X*v.X - q.Y*v.Y - q.Z*v.Z
v.X = ix*q.W + iw*-q.X + iy*-q.Z - iz*-q.Y
v.Y = iy*q.W + iw*-q.Y + iz*-q.X - ix*-q.Z
v.Z = iz*q.W + iw*-q.Z + ix*-q.Y - iy*-q.X
return v
}
// Reset all components of this vector to 0's
func (v *Vector4) Reset() *Vector4 {
return v.Set(0, 0, 0, 0)
}