2020-06-13 21:40:56 +08:00

278 lines
5.2 KiB
Go

// Copyright 2017-2020 The ShadowEditor Authors. All rights reserved.
// Use of e source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//
// For more information, please visit: https://github.com/tengge1/ShadowEditor
// You can also visit: https://gitee.com/tengge1/ShadowEditor
//
// e package is translated from three.js, visit `https://github.com/mrdoob/three.js`
// for more information.
package three
import (
"math"
)
const (
// DefaultOrder :
DefaultOrder = "xyz"
)
// RotationOrders :
var RotationOrders = []string{"XYZ", "YZX", "ZXY", "XZY", "YXZ", "ZYX"}
var _matrix = NewMatrix4()
var _quaternion = NewQuaternion(0, 0, 0, 1)
// NewEuler :
func NewEuler(x, y, z float64, order string) *Euler {
if order == "" {
order = DefaultOrder
}
return &Euler{x, y, z, order, nil}
}
// Euler :
type Euler struct {
_x float64
_y float64
_z float64
_order string
_onChangeCallback onChangeCallback
}
// X :
func (e Euler) X() float64 {
return e._x
}
// SetX :
func (e Euler) SetX(value float64) {
e._x = value
e._onChangeCallback()
}
// Y :
func (e Euler) Y() float64 {
return e._y
}
// SetY :
func (e Euler) SetY(value float64) {
e._y = value
e._onChangeCallback()
}
// Z :
func (e Euler) Z() float64 {
return e._z
}
// SetZ :
func (e Euler) SetZ(value float64) {
e._z = value
e._onChangeCallback()
}
// Order :
func (e Euler) Order() string {
return e._order
}
// SetOrder :
func (e Euler) SetOrder(value string) {
e._order = value
e._onChangeCallback()
}
// Set :
func (e Euler) Set(x, y, z float64, order string) *Euler {
e._x = x
e._y = y
e._z = z
if order != "" {
e._order = order
}
e._onChangeCallback()
return &e
}
// Clone :
func (e Euler) Clone() *Euler {
return NewEuler(e._x, e._y, e._z, e._order)
}
// Copy :
func (e Euler) Copy(euler Euler) *Euler {
e._x = euler._x
e._y = euler._y
e._z = euler._z
e._order = euler._order
e._onChangeCallback()
return &e
}
// SetFromRotationMatrix :
func (e Euler) SetFromRotationMatrix(m Matrix4, order string, update bool) *Euler {
clamp := Clamp
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
te := m.Elements
m11, m12, m13 := te[0], te[4], te[8]
m21, m22, m23 := te[1], te[5], te[9]
m31, m32, m33 := te[2], te[6], te[10]
if order == "" {
order = e._order
}
switch order {
default:
panic("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: " + order)
case "XYZ":
e._y = math.Asin(clamp(m13, -1, 1))
if math.Abs(m13) < 0.9999999 {
e._x = math.Atan2(-m23, m33)
e._z = math.Atan2(-m12, m11)
} else {
e._x = math.Atan2(m32, m22)
e._z = 0
}
case "YXZ":
e._x = math.Asin(-clamp(m23, -1, 1))
if math.Abs(m23) < 0.9999999 {
e._y = math.Atan2(m13, m33)
e._z = math.Atan2(m21, m22)
} else {
e._y = math.Atan2(-m31, m11)
e._z = 0
}
case "ZXY":
e._x = math.Asin(clamp(m32, -1, 1))
if math.Abs(m32) < 0.9999999 {
e._y = math.Atan2(-m31, m33)
e._z = math.Atan2(-m12, m22)
} else {
e._y = 0
e._z = math.Atan2(m21, m11)
}
case "ZYX":
e._y = math.Asin(-clamp(m31, -1, 1))
if math.Abs(m31) < 0.9999999 {
e._x = math.Atan2(m32, m33)
e._z = math.Atan2(m21, m11)
} else {
e._x = 0
e._z = math.Atan2(-m12, m22)
}
case "YZX":
e._z = math.Asin(clamp(m21, -1, 1))
if math.Abs(m21) < 0.9999999 {
e._x = math.Atan2(-m23, m22)
e._y = math.Atan2(-m31, m11)
} else {
e._x = 0
e._y = math.Atan2(m13, m33)
}
case "XZY":
e._z = math.Asin(-clamp(m12, -1, 1))
if math.Abs(m12) < 0.9999999 {
e._x = math.Atan2(m32, m22)
e._y = math.Atan2(m13, m11)
} else {
e._x = math.Atan2(-m23, m33)
e._y = 0
}
}
e._order = order
if update {
e._onChangeCallback()
}
return &e
}
// SetFromQuaternion :
func (e Euler) SetFromQuaternion(q Quaternion, order string, update bool) *Euler {
_matrix.MakeRotationFromQuaternion(q)
return e.SetFromRotationMatrix(*_matrix, order, update)
}
// SetFromVector3 :
func (e Euler) SetFromVector3(v Vector3, order string) *Euler {
if order == "" {
order = e._order
}
return e.Set(v.X, v.Y, v.Z, order)
}
// Reorder :
func (e Euler) Reorder(newOrder string) *Euler {
// WARNING: e discards revolution information -bhouston
_quaternion.SetFromEuler(e, false)
return e.SetFromQuaternion(*_quaternion, newOrder, true)
}
// Equals :
func (e Euler) Equals(euler Euler) bool {
return (euler._x == e._x) &&
(euler._y == e._y) &&
(euler._z == e._z) &&
(euler._order == e._order)
}
// FromArray :
func (e Euler) FromArray(array []float64, order string) *Euler {
if len(array) < 3 {
panic("array length should be greater than 3")
}
e._x = array[0]
e._y = array[1]
e._z = array[2]
if order != "" {
e._order = order
}
e._onChangeCallback()
return &e
}
// ToArray :
func (e Euler) ToArray(array []float64, offset int) ([]float64, string) {
if len(array) < offset+3 {
panic("array length should be greater than offset+3")
}
array[offset] = e._x
array[offset+1] = e._y
array[offset+2] = e._z
return array, e._order
}
// ToVector3 :
func (e Euler) ToVector3(optionalResult Vector3) *Vector3 {
return optionalResult.Set(e._x, e._y, e._z)
}
func (e Euler) _onChange(callback onChangeCallback) *Euler {
e._onChangeCallback = callback
return &e
}