123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573 |
- using System;
- using System.Runtime.InteropServices;
- #if REAL_T_IS_DOUBLE
- using real_t = System.Double;
- #else
- using real_t = System.Single;
- #endif
- namespace Godot
- {
- [StructLayout(LayoutKind.Sequential)]
- public struct Basis : IEquatable<Basis>
- {
- private static readonly Basis identity = new Basis
- (
- new Vector3(1f, 0f, 0f),
- new Vector3(0f, 1f, 0f),
- new Vector3(0f, 0f, 1f)
- );
- private static readonly Basis[] orthoBases = {
- new Basis(1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f),
- new Basis(0f, -1f, 0f, 1f, 0f, 0f, 0f, 0f, 1f),
- new Basis(-1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f),
- new Basis(0f, 1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f),
- new Basis(1f, 0f, 0f, 0f, 0f, -1f, 0f, 1f, 0f),
- new Basis(0f, 0f, 1f, 1f, 0f, 0f, 0f, 1f, 0f),
- new Basis(-1f, 0f, 0f, 0f, 0f, 1f, 0f, 1f, 0f),
- new Basis(0f, 0f, -1f, -1f, 0f, 0f, 0f, 1f, 0f),
- new Basis(1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, -1f),
- new Basis(0f, 1f, 0f, 1f, 0f, 0f, 0f, 0f, -1f),
- new Basis(-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, -1f),
- new Basis(0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, -1f),
- new Basis(1f, 0f, 0f, 0f, 0f, 1f, 0f, -1f, 0f),
- new Basis(0f, 0f, -1f, 1f, 0f, 0f, 0f, -1f, 0f),
- new Basis(-1f, 0f, 0f, 0f, 0f, -1f, 0f, -1f, 0f),
- new Basis(0f, 0f, 1f, -1f, 0f, 0f, 0f, -1f, 0f),
- new Basis(0f, 0f, 1f, 0f, 1f, 0f, -1f, 0f, 0f),
- new Basis(0f, -1f, 0f, 0f, 0f, 1f, -1f, 0f, 0f),
- new Basis(0f, 0f, -1f, 0f, -1f, 0f, -1f, 0f, 0f),
- new Basis(0f, 1f, 0f, 0f, 0f, -1f, -1f, 0f, 0f),
- new Basis(0f, 0f, 1f, 0f, -1f, 0f, 1f, 0f, 0f),
- new Basis(0f, 1f, 0f, 0f, 0f, 1f, 1f, 0f, 0f),
- new Basis(0f, 0f, -1f, 0f, 1f, 0f, 1f, 0f, 0f),
- new Basis(0f, -1f, 0f, 0f, 0f, -1f, 1f, 0f, 0f)
- };
- public Vector3 x
- {
- get { return GetAxis(0); }
- set { SetAxis(0, value); }
- }
- public Vector3 y
- {
- get { return GetAxis(1); }
- set { SetAxis(1, value); }
- }
- public Vector3 z
- {
- get { return GetAxis(2); }
- set { SetAxis(2, value); }
- }
- private Vector3 _x;
- private Vector3 _y;
- private Vector3 _z;
- public static Basis Identity
- {
- get { return identity; }
- }
- public Vector3 Scale
- {
- get
- {
- return new Vector3
- (
- new Vector3(this[0, 0], this[1, 0], this[2, 0]).Length(),
- new Vector3(this[0, 1], this[1, 1], this[2, 1]).Length(),
- new Vector3(this[0, 2], this[1, 2], this[2, 2]).Length()
- );
- }
- }
- public Vector3 this[int index]
- {
- get
- {
- switch (index)
- {
- case 0:
- return _x;
- case 1:
- return _y;
- case 2:
- return _z;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- set
- {
- switch (index)
- {
- case 0:
- _x = value;
- return;
- case 1:
- _y = value;
- return;
- case 2:
- _z = value;
- return;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- }
- public real_t this[int index, int axis]
- {
- get
- {
- switch (index)
- {
- case 0:
- return _x[axis];
- case 1:
- return _y[axis];
- case 2:
- return _z[axis];
- default:
- throw new IndexOutOfRangeException();
- }
- }
- set
- {
- switch (index)
- {
- case 0:
- _x[axis] = value;
- return;
- case 1:
- _y[axis] = value;
- return;
- case 2:
- _z[axis] = value;
- return;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- }
- internal static Basis CreateFromAxes(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis)
- {
- return new Basis
- (
- new Vector3(xAxis.x, yAxis.x, zAxis.x),
- new Vector3(xAxis.y, yAxis.y, zAxis.y),
- new Vector3(xAxis.z, yAxis.z, zAxis.z)
- );
- }
- public real_t Determinant()
- {
- return this[0, 0] * (this[1, 1] * this[2, 2] - this[2, 1] * this[1, 2]) -
- this[1, 0] * (this[0, 1] * this[2, 2] - this[2, 1] * this[0, 2]) +
- this[2, 0] * (this[0, 1] * this[1, 2] - this[1, 1] * this[0, 2]);
- }
- public Vector3 GetAxis(int axis)
- {
- return new Vector3(this[0, axis], this[1, axis], this[2, axis]);
- }
- public void SetAxis(int axis, Vector3 value)
- {
- this[0, axis] = value.x;
- this[1, axis] = value.y;
- this[2, axis] = value.z;
- }
- public Vector3 GetEuler()
- {
- Basis m = Orthonormalized();
- Vector3 euler;
- euler.z = 0.0f;
- real_t mxy = m[1, 2];
- if (mxy < 1.0f)
- {
- if (mxy > -1.0f)
- {
- euler.x = Mathf.Asin(-mxy);
- euler.y = Mathf.Atan2(m[0, 2], m[2, 2]);
- euler.z = Mathf.Atan2(m[1, 0], m[1, 1]);
- }
- else
- {
- euler.x = Mathf.Pi * 0.5f;
- euler.y = -Mathf.Atan2(-m[0, 1], m[0, 0]);
- }
- }
- else
- {
- euler.x = -Mathf.Pi * 0.5f;
- euler.y = -Mathf.Atan2(-m[0, 1], m[0, 0]);
- }
- return euler;
- }
- public int GetOrthogonalIndex()
- {
- var orth = this;
- for (int i = 0; i < 3; i++)
- {
- for (int j = 0; j < 3; j++)
- {
- real_t v = orth[i, j];
- if (v > 0.5f)
- v = 1.0f;
- else if (v < -0.5f)
- v = -1.0f;
- else
- v = 0f;
- orth[i, j] = v;
- }
- }
- for (int i = 0; i < 24; i++)
- {
- if (orthoBases[i] == orth)
- return i;
- }
- return 0;
- }
- public Basis Inverse()
- {
- var inv = this;
- real_t[] co = {
- inv[1, 1] * inv[2, 2] - inv[1, 2] * inv[2, 1],
- inv[1, 2] * inv[2, 0] - inv[1, 0] * inv[2, 2],
- inv[1, 0] * inv[2, 1] - inv[1, 1] * inv[2, 0]
- };
- real_t det = inv[0, 0] * co[0] + inv[0, 1] * co[1] + inv[0, 2] * co[2];
- if (det == 0)
- {
- return new Basis
- (
- real_t.NaN, real_t.NaN, real_t.NaN,
- real_t.NaN, real_t.NaN, real_t.NaN,
- real_t.NaN, real_t.NaN, real_t.NaN
- );
- }
- real_t s = 1.0f / det;
- inv = new Basis
- (
- co[0] * s,
- inv[0, 2] * inv[2, 1] - inv[0, 1] * inv[2, 2] * s,
- inv[0, 1] * inv[1, 2] - inv[0, 2] * inv[1, 1] * s,
- co[1] * s,
- inv[0, 0] * inv[2, 2] - inv[0, 2] * inv[2, 0] * s,
- inv[0, 2] * inv[1, 0] - inv[0, 0] * inv[1, 2] * s,
- co[2] * s,
- inv[0, 1] * inv[2, 0] - inv[0, 0] * inv[2, 1] * s,
- inv[0, 0] * inv[1, 1] - inv[0, 1] * inv[1, 0] * s
- );
- return inv;
- }
- public Basis Orthonormalized()
- {
- Vector3 xAxis = GetAxis(0);
- Vector3 yAxis = GetAxis(1);
- Vector3 zAxis = GetAxis(2);
- xAxis.Normalize();
- yAxis = yAxis - xAxis * xAxis.Dot(yAxis);
- yAxis.Normalize();
- zAxis = zAxis - xAxis * xAxis.Dot(zAxis) - yAxis * yAxis.Dot(zAxis);
- zAxis.Normalize();
- return CreateFromAxes(xAxis, yAxis, zAxis);
- }
- public Basis Rotated(Vector3 axis, real_t phi)
- {
- return new Basis(axis, phi) * this;
- }
- public Basis Scaled(Vector3 scale)
- {
- var m = this;
- m[0, 0] *= scale.x;
- m[0, 1] *= scale.x;
- m[0, 2] *= scale.x;
- m[1, 0] *= scale.y;
- m[1, 1] *= scale.y;
- m[1, 2] *= scale.y;
- m[2, 0] *= scale.z;
- m[2, 1] *= scale.z;
- m[2, 2] *= scale.z;
- return m;
- }
- public real_t Tdotx(Vector3 with)
- {
- return this[0, 0] * with[0] + this[1, 0] * with[1] + this[2, 0] * with[2];
- }
- public real_t Tdoty(Vector3 with)
- {
- return this[0, 1] * with[0] + this[1, 1] * with[1] + this[2, 1] * with[2];
- }
- public real_t Tdotz(Vector3 with)
- {
- return this[0, 2] * with[0] + this[1, 2] * with[1] + this[2, 2] * with[2];
- }
- public Basis Transposed()
- {
- var tr = this;
- real_t temp = tr[0, 1];
- tr[0, 1] = tr[1, 0];
- tr[1, 0] = temp;
- temp = tr[0, 2];
- tr[0, 2] = tr[2, 0];
- tr[2, 0] = temp;
- temp = tr[1, 2];
- tr[1, 2] = tr[2, 1];
- tr[2, 1] = temp;
- return tr;
- }
- public Vector3 Xform(Vector3 v)
- {
- return new Vector3
- (
- this[0].Dot(v),
- this[1].Dot(v),
- this[2].Dot(v)
- );
- }
- public Vector3 XformInv(Vector3 v)
- {
- return new Vector3
- (
- this[0, 0] * v.x + this[1, 0] * v.y + this[2, 0] * v.z,
- this[0, 1] * v.x + this[1, 1] * v.y + this[2, 1] * v.z,
- this[0, 2] * v.x + this[1, 2] * v.y + this[2, 2] * v.z
- );
- }
- public Quat Quat() {
- real_t trace = _x[0] + _y[1] + _z[2];
- if (trace > 0.0f) {
- real_t s = Mathf.Sqrt(trace + 1.0f) * 2f;
- real_t inv_s = 1f / s;
- return new Quat(
- (_z[1] - _y[2]) * inv_s,
- (_x[2] - _z[0]) * inv_s,
- (_y[0] - _x[1]) * inv_s,
- s * 0.25f
- );
- }
- if (_x[0] > _y[1] && _x[0] > _z[2]) {
- real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f;
- real_t inv_s = 1f / s;
- return new Quat(
- s * 0.25f,
- (_x[1] + _y[0]) * inv_s,
- (_x[2] + _z[0]) * inv_s,
- (_z[1] - _y[2]) * inv_s
- );
- }
- if (_y[1] > _z[2]) {
- real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f;
- real_t inv_s = 1f / s;
- return new Quat(
- (_x[1] + _y[0]) * inv_s,
- s * 0.25f,
- (_y[2] + _z[1]) * inv_s,
- (_x[2] - _z[0]) * inv_s
- );
- } else {
- real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f;
- real_t inv_s = 1f / s;
- return new Quat(
- (_x[2] + _z[0]) * inv_s,
- (_y[2] + _z[1]) * inv_s,
- s * 0.25f,
- (_y[0] - _x[1]) * inv_s
- );
- }
- }
- public Basis(Quat quat)
- {
- real_t s = 2.0f / quat.LengthSquared();
- real_t xs = quat.x * s;
- real_t ys = quat.y * s;
- real_t zs = quat.z * s;
- real_t wx = quat.w * xs;
- real_t wy = quat.w * ys;
- real_t wz = quat.w * zs;
- real_t xx = quat.x * xs;
- real_t xy = quat.x * ys;
- real_t xz = quat.x * zs;
- real_t yy = quat.y * ys;
- real_t yz = quat.y * zs;
- real_t zz = quat.z * zs;
- _x = new Vector3(1.0f - (yy + zz), xy - wz, xz + wy);
- _y = new Vector3(xy + wz, 1.0f - (xx + zz), yz - wx);
- _z = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy));
- }
- public Basis(Vector3 euler)
- {
- real_t c;
- real_t s;
- c = Mathf.Cos(euler.x);
- s = Mathf.Sin(euler.x);
- var xmat = new Basis(1, 0, 0, 0, c, -s, 0, s, c);
- c = Mathf.Cos(euler.y);
- s = Mathf.Sin(euler.y);
- var ymat = new Basis(c, 0, s, 0, 1, 0, -s, 0, c);
- c = Mathf.Cos(euler.z);
- s = Mathf.Sin(euler.z);
- var zmat = new Basis(c, -s, 0, s, c, 0, 0, 0, 1);
- this = ymat * xmat * zmat;
- }
- public Basis(Vector3 axis, real_t phi)
- {
- var axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
- real_t cosine = Mathf.Cos( phi);
- real_t sine = Mathf.Sin( phi);
- _x = new Vector3
- (
- axis_sq.x + cosine * (1.0f - axis_sq.x),
- axis.x * axis.y * (1.0f - cosine) - axis.z * sine,
- axis.z * axis.x * (1.0f - cosine) + axis.y * sine
- );
- _y = new Vector3
- (
- axis.x * axis.y * (1.0f - cosine) + axis.z * sine,
- axis_sq.y + cosine * (1.0f - axis_sq.y),
- axis.y * axis.z * (1.0f - cosine) - axis.x * sine
- );
- _z = new Vector3
- (
- axis.z * axis.x * (1.0f - cosine) - axis.y * sine,
- axis.y * axis.z * (1.0f - cosine) + axis.x * sine,
- axis_sq.z + cosine * (1.0f - axis_sq.z)
- );
- }
- public Basis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis)
- {
- _x = xAxis;
- _y = yAxis;
- _z = zAxis;
- }
- public Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz)
- {
- _x = new Vector3(xx, xy, xz);
- _y = new Vector3(yx, yy, yz);
- _z = new Vector3(zx, zy, zz);
- }
- public static Basis operator *(Basis left, Basis right)
- {
- return new Basis
- (
- right.Tdotx(left[0]), right.Tdoty(left[0]), right.Tdotz(left[0]),
- right.Tdotx(left[1]), right.Tdoty(left[1]), right.Tdotz(left[1]),
- right.Tdotx(left[2]), right.Tdoty(left[2]), right.Tdotz(left[2])
- );
- }
- public static bool operator ==(Basis left, Basis right)
- {
- return left.Equals(right);
- }
- public static bool operator !=(Basis left, Basis right)
- {
- return !left.Equals(right);
- }
- public override bool Equals(object obj)
- {
- if (obj is Basis)
- {
- return Equals((Basis)obj);
- }
- return false;
- }
- public bool Equals(Basis other)
- {
- return _x.Equals(other[0]) && _y.Equals(other[1]) && _z.Equals(other[2]);
- }
- public override int GetHashCode()
- {
- return _x.GetHashCode() ^ _y.GetHashCode() ^ _z.GetHashCode();
- }
- public override string ToString()
- {
- return String.Format("({0}, {1}, {2})", new object[]
- {
- _x.ToString(),
- _y.ToString(),
- _z.ToString()
- });
- }
- public string ToString(string format)
- {
- return String.Format("({0}, {1}, {2})", new object[]
- {
- _x.ToString(format),
- _y.ToString(format),
- _z.ToString(format)
- });
- }
- }
- }
|