2018-03-01 08:51:35 +01:00
|
|
|
|
#if REAL_T_IS_DOUBLE
|
|
|
|
|
using real_t = System.Double;
|
|
|
|
|
#else
|
|
|
|
|
using real_t = System.Single;
|
|
|
|
|
#endif
|
2021-07-23 01:56:37 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.Runtime.InteropServices;
|
2018-03-01 08:51:35 +01:00
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
|
namespace Godot
|
|
|
|
|
{
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 3×4 matrix (3 rows, 4 columns) used for 3D linear transformations.
|
|
|
|
|
/// It can represent transformations such as translation, rotation, or scaling.
|
|
|
|
|
/// It consists of a <see cref="Basis"/> (first 3 columns) and a
|
|
|
|
|
/// <see cref="Vector3"/> for the origin (last column).
|
|
|
|
|
///
|
|
|
|
|
/// For more information, read this documentation article:
|
|
|
|
|
/// https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html
|
|
|
|
|
/// </summary>
|
2019-08-08 03:29:40 +02:00
|
|
|
|
[Serializable]
|
2017-10-02 23:24:00 +02:00
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public struct Transform3D : IEquatable<Transform3D>
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The <see cref="Basis"/> of this transform. Contains the X, Y, and Z basis
|
|
|
|
|
/// vectors (columns 0 to 2) and is responsible for rotation and scale.
|
|
|
|
|
/// </summary>
|
2017-10-02 23:24:00 +02:00
|
|
|
|
public Basis basis;
|
2020-07-07 23:29:35 +02:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The origin vector (column 3, the fourth column). Equivalent to array index `[3]`.
|
|
|
|
|
/// </summary>
|
2017-10-02 23:24:00 +02:00
|
|
|
|
public Vector3 origin;
|
|
|
|
|
|
2019-11-29 08:20:31 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Access whole columns in the form of Vector3. The fourth column is the origin vector.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="column">Which column vector.</param>
|
|
|
|
|
public Vector3 this[int column]
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
switch (column)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
return basis.Column0;
|
|
|
|
|
case 1:
|
|
|
|
|
return basis.Column1;
|
|
|
|
|
case 2:
|
|
|
|
|
return basis.Column2;
|
|
|
|
|
case 3:
|
|
|
|
|
return origin;
|
|
|
|
|
default:
|
|
|
|
|
throw new IndexOutOfRangeException();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
switch (column)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
basis.Column0 = value;
|
|
|
|
|
return;
|
|
|
|
|
case 1:
|
|
|
|
|
basis.Column1 = value;
|
|
|
|
|
return;
|
|
|
|
|
case 2:
|
|
|
|
|
basis.Column2 = value;
|
|
|
|
|
return;
|
|
|
|
|
case 3:
|
|
|
|
|
origin = value;
|
|
|
|
|
return;
|
|
|
|
|
default:
|
|
|
|
|
throw new IndexOutOfRangeException();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Access matrix elements in column-major order. The fourth column is the origin vector.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="column">Which column, the matrix horizontal position.</param>
|
|
|
|
|
/// <param name="row">Which row, the matrix vertical position.</param>
|
|
|
|
|
public real_t this[int column, int row]
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (column == 3)
|
|
|
|
|
{
|
|
|
|
|
return origin[row];
|
|
|
|
|
}
|
|
|
|
|
return basis[column, row];
|
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (column == 3)
|
|
|
|
|
{
|
|
|
|
|
origin[row] = value;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
basis[column, row] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns the inverse of the transform, under the assumption that
|
|
|
|
|
/// the transformation is composed of rotation, scaling, and translation.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The inverse transformation matrix.</returns>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public Transform3D AffineInverse()
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2017-11-21 23:32:19 +01:00
|
|
|
|
Basis basisInv = basis.Inverse();
|
2020-10-17 07:08:21 +02:00
|
|
|
|
return new Transform3D(basisInv, basisInv.Xform(-origin));
|
2017-10-02 23:24:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Interpolates this transform to the other `transform` by `weight`.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="transform">The other transform.</param>
|
|
|
|
|
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
|
|
|
|
/// <returns>The interpolated transform.</returns>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public Transform3D InterpolateWith(Transform3D transform, real_t weight)
|
2018-09-15 04:26:11 +02:00
|
|
|
|
{
|
|
|
|
|
/* not sure if very "efficient" but good enough? */
|
|
|
|
|
|
|
|
|
|
Vector3 sourceScale = basis.Scale;
|
2021-01-20 08:02:02 +01:00
|
|
|
|
Quaternion sourceRotation = basis.RotationQuaternion();
|
2018-09-15 04:26:11 +02:00
|
|
|
|
Vector3 sourceLocation = origin;
|
|
|
|
|
|
|
|
|
|
Vector3 destinationScale = transform.basis.Scale;
|
2021-01-20 08:02:02 +01:00
|
|
|
|
Quaternion destinationRotation = transform.basis.RotationQuaternion();
|
2018-09-15 04:26:11 +02:00
|
|
|
|
Vector3 destinationLocation = transform.origin;
|
|
|
|
|
|
2020-10-17 07:08:21 +02:00
|
|
|
|
var interpolated = new Transform3D();
|
2021-01-20 08:02:02 +01:00
|
|
|
|
interpolated.basis.SetQuaternionScale(sourceRotation.Slerp(destinationRotation, weight).Normalized(), sourceScale.Lerp(destinationScale, weight));
|
2020-07-07 23:29:35 +02:00
|
|
|
|
interpolated.origin = sourceLocation.Lerp(destinationLocation, weight);
|
2018-09-15 04:26:11 +02:00
|
|
|
|
|
|
|
|
|
return interpolated;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns the inverse of the transform, under the assumption that
|
|
|
|
|
/// the transformation is composed of rotation and translation
|
|
|
|
|
/// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling).
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The inverse matrix.</returns>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public Transform3D Inverse()
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2017-11-21 23:32:19 +01:00
|
|
|
|
Basis basisTr = basis.Transposed();
|
2020-10-17 07:08:21 +02:00
|
|
|
|
return new Transform3D(basisTr, basisTr.Xform(-origin));
|
2017-10-02 23:24:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns a copy of the transform rotated such that its
|
|
|
|
|
/// -Z axis (forward) points towards the target position.
|
|
|
|
|
///
|
|
|
|
|
/// The transform will first be rotated around the given up vector,
|
|
|
|
|
/// and then fully aligned to the target by a further rotation around
|
|
|
|
|
/// an axis perpendicular to both the target and up vectors.
|
|
|
|
|
///
|
|
|
|
|
/// Operations take place in global space.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="target">The object to look at.</param>
|
|
|
|
|
/// <param name="up">The relative up direction</param>
|
|
|
|
|
/// <returns>The resulting transform.</returns>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public Transform3D LookingAt(Vector3 target, Vector3 up)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2018-04-08 05:30:43 +02:00
|
|
|
|
var t = this;
|
2018-03-03 18:30:53 +01:00
|
|
|
|
t.SetLookAt(origin, target, up);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns the transform with the basis orthogonal (90 degrees),
|
|
|
|
|
/// and normalized axis vectors (scale of 1 or -1).
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The orthonormalized transform.</returns>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public Transform3D Orthonormalized()
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2020-10-17 07:08:21 +02:00
|
|
|
|
return new Transform3D(basis.Orthonormalized(), origin);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Rotates the transform around the given `axis` by `phi` (in radians),
|
|
|
|
|
/// using matrix multiplication. The axis must be a normalized vector.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
|
|
|
|
|
/// <param name="phi">The angle to rotate, in radians.</param>
|
|
|
|
|
/// <returns>The rotated transformation matrix.</returns>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public Transform3D Rotated(Vector3 axis, real_t phi)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2020-10-17 07:08:21 +02:00
|
|
|
|
return new Transform3D(new Basis(axis, phi), new Vector3()) * this;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Scales the transform by the given 3D scaling factor, using matrix multiplication.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="scale">The scale to introduce.</param>
|
|
|
|
|
/// <returns>The scaled transformation matrix.</returns>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public Transform3D Scaled(Vector3 scale)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2020-10-17 07:08:21 +02:00
|
|
|
|
return new Transform3D(basis.Scaled(scale), origin * scale);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
|
|
|
|
// Make rotation matrix
|
|
|
|
|
// Z vector
|
2019-02-23 18:22:27 +01:00
|
|
|
|
Vector3 column2 = eye - target;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
2019-02-23 18:22:27 +01:00
|
|
|
|
column2.Normalize();
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
2019-02-23 18:22:27 +01:00
|
|
|
|
Vector3 column1 = up;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
2019-02-23 18:22:27 +01:00
|
|
|
|
Vector3 column0 = column1.Cross(column2);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
|
|
// Recompute Y = Z cross X
|
2019-02-23 18:22:27 +01:00
|
|
|
|
column1 = column2.Cross(column0);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
2019-02-23 18:22:27 +01:00
|
|
|
|
column0.Normalize();
|
|
|
|
|
column1.Normalize();
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
2019-02-23 18:22:27 +01:00
|
|
|
|
basis = new Basis(column0, column1, column2);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
|
|
|
|
|
origin = eye;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Translates the transform by the given `offset`,
|
|
|
|
|
/// relative to the transform's basis vectors.
|
|
|
|
|
///
|
|
|
|
|
/// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>,
|
|
|
|
|
/// this does not use matrix multiplication.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="offset">The offset to translate by.</param>
|
|
|
|
|
/// <returns>The translated matrix.</returns>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public Transform3D Translated(Vector3 offset)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2020-10-17 07:08:21 +02:00
|
|
|
|
return new Transform3D(basis, new Vector3
|
2017-10-02 23:24:00 +02:00
|
|
|
|
(
|
2020-07-07 23:29:35 +02:00
|
|
|
|
origin[0] += basis.Row0.Dot(offset),
|
|
|
|
|
origin[1] += basis.Row1.Dot(offset),
|
|
|
|
|
origin[2] += basis.Row2.Dot(offset)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns a vector transformed (multiplied) by this transformation matrix.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="v">A vector to transform.</param>
|
2020-07-22 22:46:04 +02:00
|
|
|
|
/// <returns>The transformed vector.</returns>
|
2017-11-21 23:32:19 +01:00
|
|
|
|
public Vector3 Xform(Vector3 v)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
|
|
|
|
return new Vector3
|
|
|
|
|
(
|
2019-02-23 18:22:27 +01:00
|
|
|
|
basis.Row0.Dot(v) + origin.x,
|
|
|
|
|
basis.Row1.Dot(v) + origin.y,
|
|
|
|
|
basis.Row2.Dot(v) + origin.z
|
2017-10-02 23:24:00 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns a vector transformed (multiplied) by the transposed transformation matrix.
|
|
|
|
|
///
|
|
|
|
|
/// Note: This results in a multiplication by the inverse of the
|
|
|
|
|
/// transformation matrix only if it represents a rotation-reflection.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="v">A vector to inversely transform.</param>
|
2020-07-22 22:46:04 +02:00
|
|
|
|
/// <returns>The inversely transformed vector.</returns>
|
2017-11-21 23:32:19 +01:00
|
|
|
|
public Vector3 XformInv(Vector3 v)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
|
|
|
|
Vector3 vInv = v - origin;
|
|
|
|
|
|
|
|
|
|
return new Vector3
|
|
|
|
|
(
|
2019-02-23 18:22:27 +01:00
|
|
|
|
basis.Row0[0] * vInv.x + basis.Row1[0] * vInv.y + basis.Row2[0] * vInv.z,
|
|
|
|
|
basis.Row0[1] * vInv.x + basis.Row1[1] * vInv.y + basis.Row2[1] * vInv.z,
|
|
|
|
|
basis.Row0[2] * vInv.x + basis.Row1[2] * vInv.y + basis.Row2[2] * vInv.z
|
2017-10-02 23:24:00 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
2018-08-10 20:46:03 +02:00
|
|
|
|
|
|
|
|
|
// Constants
|
2020-10-17 07:08:21 +02:00
|
|
|
|
private static readonly Transform3D _identity = new Transform3D(Basis.Identity, Vector3.Zero);
|
|
|
|
|
private static readonly Transform3D _flipX = new Transform3D(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero);
|
|
|
|
|
private static readonly Transform3D _flipY = new Transform3D(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero);
|
|
|
|
|
private static readonly Transform3D _flipZ = new Transform3D(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero);
|
2018-08-10 20:46:03 +02:00
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The identity transform, with no translation, rotation, or scaling applied.
|
|
|
|
|
/// This is used as a replacement for `Transform()` in GDScript.
|
|
|
|
|
/// Do not use `new Transform()` with no arguments in C#, because it sets all values to zero.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Back, Vector3.Zero)`.</value>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public static Transform3D Identity { get { return _identity; } }
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The transform that will flip something along the X axis.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>Equivalent to `new Transform(Vector3.Left, Vector3.Up, Vector3.Back, Vector3.Zero)`.</value>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public static Transform3D FlipX { get { return _flipX; } }
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The transform that will flip something along the Y axis.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Down, Vector3.Back, Vector3.Zero)`.</value>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public static Transform3D FlipY { get { return _flipY; } }
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The transform that will flip something along the Z axis.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Forward, Vector3.Zero)`.</value>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public static Transform3D FlipZ { get { return _flipZ; } }
|
2018-08-10 20:46:03 +02:00
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Constructs a transformation matrix from 4 vectors (matrix columns).
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="column0">The X vector, or column index 0.</param>
|
|
|
|
|
/// <param name="column1">The Y vector, or column index 1.</param>
|
|
|
|
|
/// <param name="column2">The Z vector, or column index 2.</param>
|
|
|
|
|
/// <param name="origin">The origin vector, or column index 3.</param>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public Transform3D(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2019-02-23 18:22:27 +01:00
|
|
|
|
basis = new Basis(column0, column1, column2);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
this.origin = origin;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Constructs a transformation matrix from the given quaternion and origin vector.
|
|
|
|
|
/// </summary>
|
2021-01-20 08:02:02 +01:00
|
|
|
|
/// <param name="quaternion">The <see cref="Godot.Quaternion"/> to create the basis from.</param>
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <param name="origin">The origin vector, or column index 3.</param>
|
2021-01-20 08:02:02 +01:00
|
|
|
|
public Transform3D(Quaternion quaternion, Vector3 origin)
|
2017-10-09 14:49:53 +02:00
|
|
|
|
{
|
2021-01-20 08:02:02 +01:00
|
|
|
|
basis = new Basis(quaternion);
|
2017-10-09 14:49:53 +02:00
|
|
|
|
this.origin = origin;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Constructs a transformation matrix from the given basis and origin vector.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="basis">The <see cref="Godot.Basis"/> to create the basis from.</param>
|
|
|
|
|
/// <param name="origin">The origin vector, or column index 3.</param>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public Transform3D(Basis basis, Vector3 origin)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
|
|
|
|
this.basis = basis;
|
|
|
|
|
this.origin = origin;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public static Transform3D operator *(Transform3D left, Transform3D right)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2017-11-21 23:32:19 +01:00
|
|
|
|
left.origin = left.Xform(right.origin);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
left.basis *= right.basis;
|
|
|
|
|
return left;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public static bool operator ==(Transform3D left, Transform3D right)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
|
|
|
|
return left.Equals(right);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public static bool operator !=(Transform3D left, Transform3D right)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
|
|
|
|
return !left.Equals(right);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool Equals(object obj)
|
|
|
|
|
{
|
2020-10-17 07:08:21 +02:00
|
|
|
|
if (obj is Transform3D)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
2020-10-17 07:08:21 +02:00
|
|
|
|
return Equals((Transform3D)obj);
|
2017-10-02 23:24:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public bool Equals(Transform3D other)
|
2017-10-02 23:24:00 +02:00
|
|
|
|
{
|
|
|
|
|
return basis.Equals(other.basis) && origin.Equals(other.origin);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 23:29:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns true if this transform and `other` are approximately equal, by running
|
|
|
|
|
/// <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="other">The other transform to compare.</param>
|
|
|
|
|
/// <returns>Whether or not the matrices are approximately equal.</returns>
|
2020-10-17 07:08:21 +02:00
|
|
|
|
public bool IsEqualApprox(Transform3D other)
|
2019-10-14 22:33:45 +02:00
|
|
|
|
{
|
|
|
|
|
return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
|
public override int GetHashCode()
|
|
|
|
|
{
|
|
|
|
|
return basis.GetHashCode() ^ origin.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2021-02-25 15:54:50 +01:00
|
|
|
|
return "[X: " + basis.x.ToString() +
|
|
|
|
|
", Y: " + basis.y.ToString() +
|
|
|
|
|
", Z: " + basis.z.ToString() +
|
|
|
|
|
", O: " + origin.ToString() + "]";
|
2017-10-02 23:24:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ToString(string format)
|
|
|
|
|
{
|
2021-02-25 15:54:50 +01:00
|
|
|
|
return "[X: " + basis.x.ToString(format) +
|
|
|
|
|
", Y: " + basis.y.ToString(format) +
|
|
|
|
|
", Z: " + basis.z.ToString(format) +
|
|
|
|
|
", O: " + origin.ToString(format) + "]";
|
2017-10-02 23:24:00 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|