summaryrefslogtreecommitdiff
path: root/modules/mono/glue/Managed/Files/Transform2D.cs
diff options
context:
space:
mode:
authorIgnacio Etcheverry <neikeq@users.noreply.github.com>2018-09-12 22:08:54 +0200
committerGitHub <noreply@github.com>2018-09-12 22:08:54 +0200
commit8704b7787624da98cece35c1b8b8e51bde709488 (patch)
tree398ab2ee1e88e3b853c6157458362dced14d64da /modules/mono/glue/Managed/Files/Transform2D.cs
parent4cd3dd821932660a7d89d90da7626fa46c07ac39 (diff)
parent995a40e8efa9f7a868a6706e30c476305e16180b (diff)
Merge pull request #22007 from neikeq/<name_of_your_new_branch>
Move modules/mono/glue/cs_files to modules/mono/glue/Managed/Files
Diffstat (limited to 'modules/mono/glue/Managed/Files/Transform2D.cs')
-rw-r--r--modules/mono/glue/Managed/Files/Transform2D.cs360
1 files changed, 360 insertions, 0 deletions
diff --git a/modules/mono/glue/Managed/Files/Transform2D.cs b/modules/mono/glue/Managed/Files/Transform2D.cs
new file mode 100644
index 0000000000..8d30833066
--- /dev/null
+++ b/modules/mono/glue/Managed/Files/Transform2D.cs
@@ -0,0 +1,360 @@
+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 Transform2D : IEquatable<Transform2D>
+ {
+ public Vector2 x;
+ public Vector2 y;
+ public Vector2 o;
+
+ public Vector2 Origin
+ {
+ get { return o; }
+ }
+
+ public real_t Rotation
+ {
+ get { return Mathf.Atan2(y.x, o.y); }
+ }
+
+ public Vector2 Scale
+ {
+ get { return new Vector2(x.Length(), y.Length()); }
+ }
+
+ public Vector2 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return o;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x = value;
+ return;
+ case 1:
+ y = value;
+ return;
+ case 2:
+ o = 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];
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x[axis] = value;
+ return;
+ case 1:
+ y[axis] = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ public Transform2D AffineInverse()
+ {
+ var inv = this;
+
+ real_t det = this[0, 0] * this[1, 1] - this[1, 0] * this[0, 1];
+
+ if (det == 0)
+ {
+ return new Transform2D
+ (
+ float.NaN, float.NaN,
+ float.NaN, float.NaN,
+ float.NaN, float.NaN
+ );
+ }
+
+ real_t idet = 1.0f / det;
+
+ real_t temp = this[0, 0];
+ this[0, 0] = this[1, 1];
+ this[1, 1] = temp;
+
+ this[0] *= new Vector2(idet, -idet);
+ this[1] *= new Vector2(-idet, idet);
+
+ this[2] = BasisXform(-this[2]);
+
+ return inv;
+ }
+
+ public Vector2 BasisXform(Vector2 v)
+ {
+ return new Vector2(Tdotx(v), Tdoty(v));
+ }
+
+ public Vector2 BasisXformInv(Vector2 v)
+ {
+ return new Vector2(x.Dot(v), y.Dot(v));
+ }
+
+ public Transform2D InterpolateWith(Transform2D m, real_t c)
+ {
+ real_t r1 = Rotation;
+ real_t r2 = m.Rotation;
+
+ Vector2 s1 = Scale;
+ Vector2 s2 = m.Scale;
+
+ // Slerp rotation
+ var v1 = new Vector2(Mathf.Cos(r1), Mathf.Sin(r1));
+ var v2 = new Vector2(Mathf.Cos(r2), Mathf.Sin(r2));
+
+ real_t dot = v1.Dot(v2);
+
+ // Clamp dot to [-1, 1]
+ dot = dot < -1.0f ? -1.0f : (dot > 1.0f ? 1.0f : dot);
+
+ Vector2 v;
+
+ if (dot > 0.9995f)
+ {
+ // Linearly interpolate to avoid numerical precision issues
+ v = v1.LinearInterpolate(v2, c).Normalized();
+ }
+ else
+ {
+ real_t angle = c * Mathf.Acos(dot);
+ Vector2 v3 = (v2 - v1 * dot).Normalized();
+ v = v1 * Mathf.Cos(angle) + v3 * Mathf.Sin(angle);
+ }
+
+ // Extract parameters
+ Vector2 p1 = Origin;
+ Vector2 p2 = m.Origin;
+
+ // Construct matrix
+ var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.LinearInterpolate(p2, c));
+ Vector2 scale = s1.LinearInterpolate(s2, c);
+ res.x *= scale;
+ res.y *= scale;
+
+ return res;
+ }
+
+ public Transform2D Inverse()
+ {
+ var inv = this;
+
+ // Swap
+ real_t temp = inv.x.y;
+ inv.x.y = inv.y.x;
+ inv.y.x = temp;
+
+ inv.o = inv.BasisXform(-inv.o);
+
+ return inv;
+ }
+
+ public Transform2D Orthonormalized()
+ {
+ var on = this;
+
+ Vector2 onX = on.x;
+ Vector2 onY = on.y;
+
+ onX.Normalize();
+ onY = onY - onX * onX.Dot(onY);
+ onY.Normalize();
+
+ on.x = onX;
+ on.y = onY;
+
+ return on;
+ }
+
+ public Transform2D Rotated(real_t phi)
+ {
+ return this * new Transform2D(phi, new Vector2());
+ }
+
+ public Transform2D Scaled(Vector2 scale)
+ {
+ var copy = this;
+ copy.x *= scale;
+ copy.y *= scale;
+ copy.o *= scale;
+ return copy;
+ }
+
+ private real_t Tdotx(Vector2 with)
+ {
+ return this[0, 0] * with[0] + this[1, 0] * with[1];
+ }
+
+ private real_t Tdoty(Vector2 with)
+ {
+ return this[0, 1] * with[0] + this[1, 1] * with[1];
+ }
+
+ public Transform2D Translated(Vector2 offset)
+ {
+ var copy = this;
+ copy.o += copy.BasisXform(offset);
+ return copy;
+ }
+
+ public Vector2 Xform(Vector2 v)
+ {
+ return new Vector2(Tdotx(v), Tdoty(v)) + o;
+ }
+
+ public Vector2 XformInv(Vector2 v)
+ {
+ Vector2 vInv = v - o;
+ return new Vector2(x.Dot(vInv), y.Dot(vInv));
+ }
+
+ // Constants
+ private static readonly Transform2D _identity = new Transform2D(new Vector2(1f, 0f), new Vector2(0f, 1f), Vector2.Zero);
+ private static readonly Transform2D _flipX = new Transform2D(new Vector2(-1f, 0f), new Vector2(0f, 1f), Vector2.Zero);
+ private static readonly Transform2D _flipY = new Transform2D(new Vector2(1f, 0f), new Vector2(0f, -1f), Vector2.Zero);
+
+ public static Transform2D Identity { get { return _identity; } }
+ public static Transform2D FlipX { get { return _flipX; } }
+ public static Transform2D FlipY { get { return _flipY; } }
+
+ // Constructors
+ public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 origin)
+ {
+ x = xAxis;
+ y = yAxis;
+ o = origin;
+ }
+
+ public Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy)
+ {
+ x = new Vector2(xx, xy);
+ y = new Vector2(yx, yy);
+ o = new Vector2(ox, oy);
+ }
+
+ public Transform2D(real_t rot, Vector2 pos)
+ {
+ real_t cr = Mathf.Cos(rot);
+ real_t sr = Mathf.Sin(rot);
+ x.x = cr;
+ y.y = cr;
+ x.y = -sr;
+ y.x = sr;
+ o = pos;
+ }
+
+ public static Transform2D operator *(Transform2D left, Transform2D right)
+ {
+ left.o = left.Xform(right.o);
+
+ real_t x0, x1, y0, y1;
+
+ x0 = left.Tdotx(right.x);
+ x1 = left.Tdoty(right.x);
+ y0 = left.Tdotx(right.y);
+ y1 = left.Tdoty(right.y);
+
+ left.x.x = x0;
+ left.x.y = x1;
+ left.y.x = y0;
+ left.y.y = y1;
+
+ return left;
+ }
+
+ public static bool operator ==(Transform2D left, Transform2D right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Transform2D left, Transform2D right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Transform2D)
+ {
+ return Equals((Transform2D)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Transform2D other)
+ {
+ return x.Equals(other.x) && y.Equals(other.y) && o.Equals(other.o);
+ }
+
+ public override int GetHashCode()
+ {
+ return x.GetHashCode() ^ y.GetHashCode() ^ o.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("({0}, {1}, {2})", new object[]
+ {
+ x.ToString(),
+ y.ToString(),
+ o.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("({0}, {1}, {2})", new object[]
+ {
+ x.ToString(format),
+ y.ToString(format),
+ o.ToString(format)
+ });
+ }
+ }
+}