| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624 |
- // Copyright 2016 The G3N Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package math32
- // Vector3 is a 3D vector/point with X, Y and Z components.
- type Vector3 struct {
- X float32
- Y float32
- Z float32
- }
- // NewVector3 creates and returns a pointer to a new Vector3 with
- // the specified x, y and y components
- func NewVector3(x, y, z float32) *Vector3 {
- return &Vector3{X: x, Y: y, Z: z}
- }
- // Set sets this vector X, Y and Z components.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Set(x, y, z float32) *Vector3 {
- v.X = x
- v.Y = y
- v.Z = z
- return v
- }
- // SetX sets this vector X component.
- // Returns the pointer to this updated Vector.
- func (v *Vector3) SetX(x float32) *Vector3 {
- v.X = x
- return v
- }
- // SetY sets this vector Y component.
- // Returns the pointer to this updated vector.
- func (v *Vector3) SetY(y float32) *Vector3 {
- v.Y = y
- return v
- }
- // SetZ sets this vector Z component.
- // Returns the pointer to this updated vector.
- func (v *Vector3) SetZ(z float32) *Vector3 {
- v.Z = z
- return v
- }
- // SetComponent sets this vector component value by its index: 0 for X, 1 for Y, 2 for Z.
- // Returns the pointer to this updated vector
- func (v *Vector3) SetComponent(index int, value float32) {
- switch index {
- case 0:
- v.X = value
- case 1:
- v.Y = value
- case 2:
- v.Z = value
- default:
- panic("index is out of range: ")
- }
- }
- // Component returns this vector component by its index: 0 for X, 1 for Y, 2 for Z.
- func (v *Vector3) Component(index int) float32 {
- switch index {
- case 0:
- return v.X
- case 1:
- return v.Y
- case 2:
- return v.Z
- default:
- panic("index is out of range")
- }
- }
- // SetByName sets this vector component value by its case insensitive name: "x", "y", or "z".
- func (v *Vector3) SetByName(name string, value float32) {
- switch name {
- case "x", "X":
- v.X = value
- case "y", "Y":
- v.Y = value
- case "z", "Z":
- v.Z = value
- default:
- panic("Invalid Vector3 component name: " + name)
- }
- }
- // Copy copies other vector to this one.
- // It is equivalent to: *v = *other.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Copy(other *Vector3) *Vector3 {
- *v = *other
- return v
- }
- // Add adds other vector to this one.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Add(other *Vector3) *Vector3 {
- v.X += other.X
- v.Y += other.Y
- v.Z += other.Z
- return v
- }
- // AddScalar adds scalar s to each component of this vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) AddScalar(s float32) *Vector3 {
- v.X += s
- v.Y += s
- v.Z += s
- return v
- }
- // AddVectors adds vectors a and b to this one.
- // Returns the pointer to this updated vector.
- func (v *Vector3) AddVectors(a, b *Vector3) *Vector3 {
- v.X = a.X + b.X
- v.Y = a.Y + b.Y
- v.Z = a.Z + b.Z
- return v
- }
- // Sub subtracts other vector from this one.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Sub(other *Vector3) *Vector3 {
- v.X -= other.X
- v.Y -= other.Y
- v.Z -= other.Z
- return v
- }
- // SubScalar subtracts scalar s from each component of this vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) SubScalar(s float32) *Vector3 {
- v.X -= s
- v.Y -= s
- v.Z -= s
- return v
- }
- // SubVectors subtracts vectors a and b from this vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) SubVectors(a, b *Vector3) *Vector3 {
- v.X = a.X - b.X
- v.Y = a.Y - b.Y
- v.Z = a.Z - b.Z
- return v
- }
- // Multiply multiplies each component of this vector by the corresponding one from other vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Multiply(other *Vector3) *Vector3 {
- v.X *= other.X
- v.Y *= other.Y
- v.Z *= other.Z
- return v
- }
- // MultiplyScalar multiplies each component of this vector by the scalar s.
- // Returns the pointer to this updated vector.
- func (v *Vector3) MultiplyScalar(s float32) *Vector3 {
- v.X *= s
- v.Y *= s
- v.Z *= s
- return v
- }
- // Divide divides each component of this vector by the corresponding one from other vector.
- // Returns the pointer to this updated vector
- func (v *Vector3) Divide(other *Vector3) *Vector3 {
- v.X /= other.X
- v.Y /= other.Y
- v.Z /= other.Z
- return v
- }
- // DivideScalar divides each component of this vector by the scalar s.
- // If scalar is zero, sets this vector to zero.
- // Returns the pointer to this updated vector.
- func (v *Vector3) DivideScalar(scalar float32) *Vector3 {
- if scalar != 0 {
- invScalar := 1 / scalar
- v.X *= invScalar
- v.Y *= invScalar
- v.Z *= invScalar
- } else {
- v.X = 0
- v.Y = 0
- v.Z = 0
- }
- return v
- }
- // Min sets this vector components to the minimum values of itself and other vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Min(other *Vector3) *Vector3 {
- if v.X > other.X {
- v.X = other.X
- }
- if v.Y > other.Y {
- v.Y = other.Y
- }
- if v.Z > other.Z {
- v.Z = other.Z
- }
- return v
- }
- // Max sets this vector components to the maximum value of itself and other vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Max(other *Vector3) *Vector3 {
- if v.X < other.X {
- v.X = other.X
- }
- if v.Y < other.Y {
- v.Y = other.Y
- }
- if v.Z < other.Z {
- v.Z = other.Z
- }
- return v
- }
- // Clamp sets this vector components to be no less than the corresponding components of min
- // and not greater than the corresponding component of max.
- // Assumes min < max, if this assumption isn't true it will not operate correctly.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Clamp(min, max *Vector3) *Vector3 {
- if v.X < min.X {
- v.X = min.X
- } else if v.X > max.X {
- v.X = max.X
- }
- if v.Y < min.Y {
- v.Y = min.Y
- } else if v.Y > max.Y {
- v.Y = max.Y
- }
- if v.Z < min.Z {
- v.Z = min.Z
- } else if v.Z > max.Z {
- v.Z = max.Z
- }
- return v
- }
- // ClampScalar sets this vector components to be no less than minVal and not greater than maxVal.
- // Returns the pointer to this updated vector.
- func (v *Vector3) ClampScalar(minVal, maxVal float32) *Vector3 {
- min := NewVector3(minVal, minVal, minVal)
- max := NewVector3(maxVal, maxVal, maxVal)
- return v.Clamp(min, max)
- }
- // Floor applies math32.Floor() to each of this vector's components.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Floor() *Vector3 {
- v.X = Floor(v.X)
- v.Y = Floor(v.Y)
- v.Z = Floor(v.Z)
- return v
- }
- // Ceil applies math32.Ceil() to each of this vector's components.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Ceil() *Vector3 {
- v.X = Ceil(v.X)
- v.Y = Ceil(v.Y)
- v.Z = Ceil(v.Z)
- return v
- }
- // Round rounds each of this vector's components.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Round() *Vector3 {
- v.X = Floor(v.X + 0.5)
- v.Y = Floor(v.Y + 0.5)
- v.Z = Floor(v.Z + 0.5)
- return v
- }
- // Negate negates each of this vector's components.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Negate() *Vector3 {
- v.X = -v.X
- v.Y = -v.Y
- v.Z = -v.Z
- return v
- }
- // Dot returns the dot product of this vector with other.
- // None of the vectors are changed.
- func (v *Vector3) Dot(other *Vector3) float32 {
- return v.X*other.X + v.Y*other.Y + v.Z*other.Z
- }
- // LengthSq returns the length squared of this vector.
- // LengthSq can be used to compare vectors' lengths without the need to perform a square root.
- func (v *Vector3) LengthSq() float32 {
- return v.X*v.X + v.Y*v.Y + v.Z*v.Z
- }
- // Length returns the length of this vector.
- func (v *Vector3) Length() float32 {
- return Sqrt(v.X*v.X + v.Y*v.Y + v.Z*v.Z)
- }
- // Normalize normalizes this vector so its length will be 1.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Normalize() *Vector3 {
- return v.DivideScalar(v.Length())
- }
- // DistanceTo returns the distance of this point to other.
- func (v *Vector3) DistanceTo(other *Vector3) float32 {
- return Sqrt(v.DistanceToSquared(other))
- }
- // DistanceToSquared returns the distance squared of this point to other.
- func (v *Vector3) DistanceToSquared(other *Vector3) float32 {
- dx := v.X - other.X
- dy := v.Y - other.Y
- dz := v.Z - other.Z
- return dx*dx + dy*dy + dz*dz
- }
- // SetLength sets this vector to have the specified length.
- // If the current length is zero, does nothing.
- // Returns the pointer to this updated vector.
- func (v *Vector3) SetLength(l float32) *Vector3 {
- oldLength := v.Length()
- if oldLength != 0 && l != oldLength {
- v.MultiplyScalar(l / oldLength)
- }
- return v
- }
- // Lerp sets each of this vector's components to the linear interpolated value of
- // alpha between ifself and the corresponding other component.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Lerp(other *Vector3, alpha float32) *Vector3 {
- v.X += (other.X - v.X) * alpha
- v.Y += (other.Y - v.Y) * alpha
- v.Z += (other.Z - v.Z) * alpha
- return v
- }
- // Equals returns if this vector is equal to other.
- func (v *Vector3) Equals(other *Vector3) bool {
- return (other.X == v.X) && (other.Y == v.Y) && (other.Z == v.Z)
- }
- // FromArray sets this vector's components from the specified array and offset
- // Returns the pointer to this updated vector.
- func (v *Vector3) FromArray(array []float32, offset int) *Vector3 {
- v.X = array[offset]
- v.Y = array[offset+1]
- v.Z = array[offset+2]
- return v
- }
- // ToArray copies this vector's components to array starting at offset.
- // Returns the array.
- func (v *Vector3) ToArray(array []float32, offset int) []float32 {
- array[offset] = v.X
- array[offset+1] = v.Y
- array[offset+2] = v.Z
- return array
- }
- // MultiplyVectors multiply vectors a and b storing the result in this vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) MultiplyVectors(a, b *Vector3) *Vector3 {
- v.X = a.X * b.X
- v.Y = a.Y * b.Y
- v.Z = a.Z * b.Z
- return v
- }
- // ApplyAxisAngle rotates the vector around axis by angle.
- // Returns the pointer to this updated vector.
- func (v *Vector3) ApplyAxisAngle(axis *Vector3, angle float32) *Vector3 {
- var quaternion Quaternion
- v.ApplyQuaternion(quaternion.SetFromAxisAngle(axis, angle))
- return v
- }
- // ApplyMatrix3 multiplies the specified 3x3 matrix by this vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) ApplyMatrix3(m *Matrix3) *Vector3 {
- x := v.X
- y := v.Y
- z := v.Z
- v.X = m[0]*x + m[3]*y + m[6]*z
- v.Y = m[1]*x + m[4]*y + m[7]*z
- v.Z = m[2]*x + m[5]*y + m[8]*z
- return v
- }
- // ApplyMatrix4 multiplies the specified 4x4 matrix by this vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) ApplyMatrix4(m *Matrix4) *Vector3 {
- x := v.X
- y := v.Y
- z := v.Z
- v.X = m[0]*x + m[4]*y + m[8]*z + m[12]
- v.Y = m[1]*x + m[5]*y + m[9]*z + m[13]
- v.Z = m[2]*x + m[6]*y + m[10]*z + m[14]
- return v
- }
- // ApplyProjection applies the projection matrix m to this vector
- // Returns the pointer to this updated vector.
- func (v *Vector3) ApplyProjection(m *Matrix4) *Vector3 {
- x := v.X
- y := v.Y
- z := v.Z
- d := 1 / (m[3]*x + m[7]*y + m[11]*z + m[15]) // perspective divide
- v.X = (m[0]*x + m[4]*y + m[8]*z + m[12]) * d
- v.Y = (m[1]*x + m[5]*y + m[9]*z + m[13]) * d
- v.Z = (m[2]*x + m[6]*y + m[10]*z + m[14]) * d
- return v
- }
- // ApplyQuaternion transforms this vector by multiplying it by
- // the specified quaternion and then by the quaternion inverse.
- // It basically applies the rotation encoded in the quaternion to this vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) ApplyQuaternion(q *Quaternion) *Vector3 {
- x := v.X
- y := v.Y
- z := v.Z
- qx := q.x
- qy := q.y
- qz := q.z
- qw := q.w
- // calculate quat * vector
- ix := qw*x + qy*z - qz*y
- iy := qw*y + qz*x - qx*z
- iz := qw*z + qx*y - qy*x
- iw := -qx*x - qy*y - qz*z
- // calculate result * inverse quat
- v.X = ix*qw + iw*-qx + iy*-qz - iz*-qy
- v.Y = iy*qw + iw*-qy + iz*-qx - ix*-qz
- v.Z = iz*qw + iw*-qz + ix*-qy - iy*-qx
- return v
- }
- // Cross calculates the cross product of this vector with other and returns the result vector.
- func (v *Vector3) Cross(other *Vector3) *Vector3 {
- cx := v.Y*other.Z - v.Z*other.Y
- cy := v.Z*other.X - v.X*other.Z
- cz := v.X*other.Y - v.Y*other.X
- v.X = cx
- v.Y = cy
- v.Z = cz
- return v
- }
- // CrossVectors calculates the cross product of a and b storing the result in this vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) CrossVectors(a, b *Vector3) *Vector3 {
- cx := a.Y*b.Z - a.Z*b.Y
- cy := a.Z*b.X - a.X*b.Z
- cz := a.X*b.Y - a.Y*b.X
- v.X = cx
- v.Y = cy
- v.Z = cz
- return v
- }
- // ProjectOnVector sets this vector to its projection on other vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) ProjectOnVector(other *Vector3) *Vector3 {
- var on Vector3
- on.Copy(other).Normalize()
- dot := v.Dot(&on)
- return v.Copy(&on).MultiplyScalar(dot)
- }
- // ProjectOnPlane sets this vector to its projection on the plane
- // specified by its normal vector.
- // Returns the pointer to this updated vector.
- func (v *Vector3) ProjectOnPlane(planeNormal *Vector3) *Vector3 {
- var tmp Vector3
- tmp.Copy(v).ProjectOnVector(planeNormal)
- return v.Sub(&tmp)
- }
- // Reflect sets this vector to its reflection relative to the normal vector.
- // The normal vector is assumed to be normalized.
- // Returns the pointer to this updated vector.
- func (v *Vector3) Reflect(normal *Vector3) *Vector3 {
- var tmp Vector3
- return v.Sub(tmp.Copy(normal).MultiplyScalar(2 * v.Dot(normal)))
- }
- // AngleTo returns the angle between this vector and other
- func (v *Vector3) AngleTo(other *Vector3) float32 {
- theta := v.Dot(other) / (v.Length() * other.Length())
- // clamp, to handle numerical problems
- return Acos(Clamp(theta, -1, 1))
- }
- // SetFromMatrixPosition set this vector from the translation coordinates
- // in the specified transformation matrix.
- func (v *Vector3) SetFromMatrixPosition(m *Matrix4) *Vector3 {
- v.X = m[12]
- v.Y = m[13]
- v.Z = m[14]
- return v
- }
- // SetFromMatrixColumn set this vector with the column at index of the m matrix.
- // Returns the pointer to this updated vector.
- func (v *Vector3) SetFromMatrixColumn(index int, m *Matrix4) *Vector3 {
- offset := index * 4
- v.X = m[offset]
- v.Y = m[offset+1]
- v.Z = m[offset+2]
- return v
- }
- // Clone returns a copy of this vector
- func (v *Vector3) Clone() *Vector3 {
- return NewVector3(v.X, v.Y, v.Z)
- }
- // SetFromRotationMatrix sets this vector components to the Euler angles
- // from the specified pure rotation matrix.
- // Returns the pointer to this updated vector.
- func (v *Vector3) SetFromRotationMatrix(m *Matrix4) *Vector3 {
- m11 := m[0]
- m12 := m[4]
- m13 := m[8]
- m22 := m[5]
- m23 := m[9]
- m32 := m[6]
- m33 := m[10]
- v.Y = Asin(Clamp(m13, -1, 1))
- if Abs(m13) < 0.99999 {
- v.X = Atan2(-m23, m33)
- v.Z = Atan2(-m12, m11)
- } else {
- v.X = Atan2(m32, m22)
- v.Z = 0
- }
- return v
- }
- // SetFromQuaternion sets this vector components to the Euler angles
- // from the specified quaternion
- // Returns the pointer to this updated vector.
- func (v *Vector3) SetFromQuaternion(q *Quaternion) *Vector3 {
- matrix := NewMatrix4()
- matrix.MakeRotationFromQuaternion(q)
- v.SetFromRotationMatrix(matrix)
- return v
- }
|