Add C# XML documentation to core C# math types
This commit is contained in:
parent
9678a41b19
commit
5fd4fa0b73
16 changed files with 3235 additions and 552 deletions
|
@ -14,6 +14,10 @@ using real_t = System.Single;
|
|||
|
||||
namespace Godot
|
||||
{
|
||||
/// <summary>
|
||||
/// Axis-Aligned Bounding Box. AABB consists of a position, a size, and
|
||||
/// several utility functions. It is typically used for fast overlap tests.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct AABB : IEquatable<AABB>
|
||||
|
@ -21,24 +25,55 @@ namespace Godot
|
|||
private Vector3 _position;
|
||||
private Vector3 _size;
|
||||
|
||||
/// <summary>
|
||||
/// Beginning corner. Typically has values lower than End.
|
||||
/// </summary>
|
||||
/// <value>Directly uses a private field.</value>
|
||||
public Vector3 Position
|
||||
{
|
||||
get { return _position; }
|
||||
set { _position = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Size from Position to End. Typically all components are positive.
|
||||
/// If the size is negative, you can use <see cref="Abs"/> to fix it.
|
||||
/// </summary>
|
||||
/// <value>Directly uses a private field.</value>
|
||||
public Vector3 Size
|
||||
{
|
||||
get { return _size; }
|
||||
set { _size = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ending corner. This is calculated as <see cref="Position"/> plus
|
||||
/// <see cref="Size"/>. Setting this value will change the size.
|
||||
/// </summary>
|
||||
/// <value>Getting is equivalent to `value = Position + Size`, setting is equivalent to `Size = value - Position`.</value>
|
||||
public Vector3 End
|
||||
{
|
||||
get { return _position + _size; }
|
||||
set { _size = value - _position; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an AABB with equivalent position and size, modified so that
|
||||
/// the most-negative corner is the origin and the size is positive.
|
||||
/// </summary>
|
||||
/// <returns>The modified AABB.</returns>
|
||||
public AABB Abs()
|
||||
{
|
||||
Vector3 end = End;
|
||||
Vector3 topLeft = new Vector3(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y), Mathf.Min(_position.z, end.z));
|
||||
return new AABB(topLeft, _size.Abs());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this AABB completely encloses another one.
|
||||
/// </summary>
|
||||
/// <param name="with">The other AABB that may be enclosed.</param>
|
||||
/// <returns>A bool for whether or not this AABB encloses `b`.</returns>
|
||||
public bool Encloses(AABB with)
|
||||
{
|
||||
Vector3 src_min = _position;
|
||||
|
@ -54,33 +89,59 @@ namespace Godot
|
|||
src_max.z > dst_max.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this AABB expanded to include a given point.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to include.</param>
|
||||
/// <returns>The expanded AABB.</returns>
|
||||
public AABB Expand(Vector3 point)
|
||||
{
|
||||
Vector3 begin = _position;
|
||||
Vector3 end = _position + _size;
|
||||
|
||||
if (point.x < begin.x)
|
||||
{
|
||||
begin.x = point.x;
|
||||
}
|
||||
if (point.y < begin.y)
|
||||
{
|
||||
begin.y = point.y;
|
||||
}
|
||||
if (point.z < begin.z)
|
||||
{
|
||||
begin.z = point.z;
|
||||
}
|
||||
|
||||
if (point.x > end.x)
|
||||
{
|
||||
end.x = point.x;
|
||||
}
|
||||
if (point.y > end.y)
|
||||
{
|
||||
end.y = point.y;
|
||||
}
|
||||
if (point.z > end.z)
|
||||
{
|
||||
end.z = point.z;
|
||||
}
|
||||
|
||||
return new AABB(begin, end - begin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the area of the AABB.
|
||||
/// </summary>
|
||||
/// <returns>The area.</returns>
|
||||
public real_t GetArea()
|
||||
{
|
||||
return _size.x * _size.y * _size.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of one of the 8 endpoints of the AABB.
|
||||
/// </summary>
|
||||
/// <param name="idx">Which endpoint to get.</param>
|
||||
/// <returns>An endpoint of the AABB.</returns>
|
||||
public Vector3 GetEndpoint(int idx)
|
||||
{
|
||||
switch (idx)
|
||||
|
@ -106,6 +167,10 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the normalized longest axis of the AABB.
|
||||
/// </summary>
|
||||
/// <returns>A vector representing the normalized longest axis of the AABB.</returns>
|
||||
public Vector3 GetLongestAxis()
|
||||
{
|
||||
var axis = new Vector3(1f, 0f, 0f);
|
||||
|
@ -125,6 +190,10 @@ namespace Godot
|
|||
return axis;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="Vector3.Axis"/> index of the longest axis of the AABB.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Vector3.Axis"/> index for which axis is longest.</returns>
|
||||
public Vector3.Axis GetLongestAxisIndex()
|
||||
{
|
||||
var axis = Vector3.Axis.X;
|
||||
|
@ -144,6 +213,10 @@ namespace Godot
|
|||
return axis;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scalar length of the longest axis of the AABB.
|
||||
/// </summary>
|
||||
/// <returns>The scalar length of the longest axis of the AABB.</returns>
|
||||
public real_t GetLongestAxisSize()
|
||||
{
|
||||
real_t max_size = _size.x;
|
||||
|
@ -157,6 +230,10 @@ namespace Godot
|
|||
return max_size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the normalized shortest axis of the AABB.
|
||||
/// </summary>
|
||||
/// <returns>A vector representing the normalized shortest axis of the AABB.</returns>
|
||||
public Vector3 GetShortestAxis()
|
||||
{
|
||||
var axis = new Vector3(1f, 0f, 0f);
|
||||
|
@ -176,6 +253,10 @@ namespace Godot
|
|||
return axis;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="Vector3.Axis"/> index of the shortest axis of the AABB.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Vector3.Axis"/> index for which axis is shortest.</returns>
|
||||
public Vector3.Axis GetShortestAxisIndex()
|
||||
{
|
||||
var axis = Vector3.Axis.X;
|
||||
|
@ -195,6 +276,10 @@ namespace Godot
|
|||
return axis;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scalar length of the shortest axis of the AABB.
|
||||
/// </summary>
|
||||
/// <returns>The scalar length of the shortest axis of the AABB.</returns>
|
||||
public real_t GetShortestAxisSize()
|
||||
{
|
||||
real_t max_size = _size.x;
|
||||
|
@ -208,6 +293,12 @@ namespace Godot
|
|||
return max_size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the support point in a given direction.
|
||||
/// This is useful for collision detection algorithms.
|
||||
/// </summary>
|
||||
/// <param name="dir">The direction to find support for.</param>
|
||||
/// <returns>A vector representing the support.</returns>
|
||||
public Vector3 GetSupport(Vector3 dir)
|
||||
{
|
||||
Vector3 half_extents = _size * 0.5f;
|
||||
|
@ -219,6 +310,11 @@ namespace Godot
|
|||
dir.z > 0f ? -half_extents.z : half_extents.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the AABB grown a given amount of units towards all the sides.
|
||||
/// </summary>
|
||||
/// <param name="by">The amount to grow by.</param>
|
||||
/// <returns>The grown AABB.</returns>
|
||||
public AABB Grow(real_t by)
|
||||
{
|
||||
var res = this;
|
||||
|
@ -233,16 +329,29 @@ namespace Godot
|
|||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the AABB is flat or empty, or false otherwise.
|
||||
/// </summary>
|
||||
/// <returns>A bool for whether or not the AABB has area.</returns>
|
||||
public bool HasNoArea()
|
||||
{
|
||||
return _size.x <= 0f || _size.y <= 0f || _size.z <= 0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the AABB has no surface (no size), or false otherwise.
|
||||
/// </summary>
|
||||
/// <returns>A bool for whether or not the AABB has area.</returns>
|
||||
public bool HasNoSurface()
|
||||
{
|
||||
return _size.x <= 0f && _size.y <= 0f && _size.z <= 0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the AABB contains a point, or false otherwise.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to check.</param>
|
||||
/// <returns>A bool for whether or not the AABB contains `point`.</returns>
|
||||
public bool HasPoint(Vector3 point)
|
||||
{
|
||||
if (point.x < _position.x)
|
||||
|
@ -261,6 +370,11 @@ namespace Godot
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the intersection of this AABB and `b`.
|
||||
/// </summary>
|
||||
/// <param name="with">The other AABB.</param>
|
||||
/// <returns>The clipped AABB.</returns>
|
||||
public AABB Intersection(AABB with)
|
||||
{
|
||||
Vector3 src_min = _position;
|
||||
|
@ -297,24 +411,57 @@ namespace Godot
|
|||
return new AABB(min, max - min);
|
||||
}
|
||||
|
||||
public bool Intersects(AABB with)
|
||||
/// <summary>
|
||||
/// Returns true if the AABB overlaps with `b`
|
||||
/// (i.e. they have at least one point in common).
|
||||
///
|
||||
/// If `includeBorders` is true, they will also be considered overlapping
|
||||
/// if their borders touch, even without intersection.
|
||||
/// </summary>
|
||||
/// <param name="with">The other AABB to check for intersections with.</param>
|
||||
/// <param name="includeBorders">Whether or not to consider borders.</param>
|
||||
/// <returns>A bool for whether or not they are intersecting.</returns>
|
||||
public bool Intersects(AABB with, bool includeBorders = false)
|
||||
{
|
||||
if (_position.x >= with._position.x + with._size.x)
|
||||
return false;
|
||||
if (_position.x + _size.x <= with._position.x)
|
||||
return false;
|
||||
if (_position.y >= with._position.y + with._size.y)
|
||||
return false;
|
||||
if (_position.y + _size.y <= with._position.y)
|
||||
return false;
|
||||
if (_position.z >= with._position.z + with._size.z)
|
||||
return false;
|
||||
if (_position.z + _size.z <= with._position.z)
|
||||
return false;
|
||||
if (includeBorders)
|
||||
{
|
||||
if (_position.x > with._position.x + with._size.x)
|
||||
return false;
|
||||
if (_position.x + _size.x < with._position.x)
|
||||
return false;
|
||||
if (_position.y > with._position.y + with._size.y)
|
||||
return false;
|
||||
if (_position.y + _size.y < with._position.y)
|
||||
return false;
|
||||
if (_position.z > with._position.z + with._size.z)
|
||||
return false;
|
||||
if (_position.z + _size.z < with._position.z)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_position.x >= with._position.x + with._size.x)
|
||||
return false;
|
||||
if (_position.x + _size.x <= with._position.x)
|
||||
return false;
|
||||
if (_position.y >= with._position.y + with._size.y)
|
||||
return false;
|
||||
if (_position.y + _size.y <= with._position.y)
|
||||
return false;
|
||||
if (_position.z >= with._position.z + with._size.z)
|
||||
return false;
|
||||
if (_position.z + _size.z <= with._position.z)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the AABB is on both sides of `plane`.
|
||||
/// </summary>
|
||||
/// <param name="plane">The plane to check for intersection.</param>
|
||||
/// <returns>A bool for whether or not the AABB intersects the plane.</returns>
|
||||
public bool IntersectsPlane(Plane plane)
|
||||
{
|
||||
Vector3[] points =
|
||||
|
@ -335,14 +482,24 @@ namespace Godot
|
|||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (plane.DistanceTo(points[i]) > 0)
|
||||
{
|
||||
over = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
under = true;
|
||||
}
|
||||
}
|
||||
|
||||
return under && over;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the AABB intersects the line segment between `from` and `to`.
|
||||
/// </summary>
|
||||
/// <param name="from">The start of the line segment.</param>
|
||||
/// <param name="to">The end of the line segment.</param>
|
||||
/// <returns>A bool for whether or not the AABB intersects the line segment.</returns>
|
||||
public bool IntersectsSegment(Vector3 from, Vector3 to)
|
||||
{
|
||||
real_t min = 0f;
|
||||
|
@ -359,7 +516,9 @@ namespace Godot
|
|||
if (segFrom < segTo)
|
||||
{
|
||||
if (segFrom > boxEnd || segTo < boxBegin)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
real_t length = segTo - segFrom;
|
||||
cmin = segFrom < boxBegin ? (boxBegin - segFrom) / length : 0f;
|
||||
|
@ -368,7 +527,9 @@ namespace Godot
|
|||
else
|
||||
{
|
||||
if (segTo > boxEnd || segFrom < boxBegin)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
real_t length = segTo - segFrom;
|
||||
cmin = segFrom > boxEnd ? (boxEnd - segFrom) / length : 0f;
|
||||
|
@ -381,14 +542,23 @@ namespace Godot
|
|||
}
|
||||
|
||||
if (cmax < max)
|
||||
{
|
||||
max = cmax;
|
||||
}
|
||||
if (max < min)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a larger AABB that contains this AABB and `b`.
|
||||
/// </summary>
|
||||
/// <param name="with">The other AABB.</param>
|
||||
/// <returns>The merged AABB.</returns>
|
||||
public AABB Merge(AABB with)
|
||||
{
|
||||
Vector3 beg1 = _position;
|
||||
|
@ -411,22 +581,52 @@ namespace Godot
|
|||
return new AABB(min, max - min);
|
||||
}
|
||||
|
||||
// Constructors
|
||||
/// <summary>
|
||||
/// Constructs an AABB from a position and size.
|
||||
/// </summary>
|
||||
/// <param name="position">The position.</param>
|
||||
/// <param name="size">The size, typically positive.</param>
|
||||
public AABB(Vector3 position, Vector3 size)
|
||||
{
|
||||
_position = position;
|
||||
_size = size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an AABB from a position, width, height, and depth.
|
||||
/// </summary>
|
||||
/// <param name="position">The position.</param>
|
||||
/// <param name="width">The width, typically positive.</param>
|
||||
/// <param name="height">The height, typically positive.</param>
|
||||
/// <param name="depth">The depth, typically positive.</param>
|
||||
public AABB(Vector3 position, real_t width, real_t height, real_t depth)
|
||||
{
|
||||
_position = position;
|
||||
_size = new Vector3(width, height, depth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an AABB from x, y, z, and size.
|
||||
/// </summary>
|
||||
/// <param name="x">The position's X coordinate.</param>
|
||||
/// <param name="y">The position's Y coordinate.</param>
|
||||
/// <param name="z">The position's Z coordinate.</param>
|
||||
/// <param name="size">The size, typically positive.</param>
|
||||
public AABB(real_t x, real_t y, real_t z, Vector3 size)
|
||||
{
|
||||
_position = new Vector3(x, y, z);
|
||||
_size = size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an AABB from x, y, z, width, height, and depth.
|
||||
/// </summary>
|
||||
/// <param name="x">The position's X coordinate.</param>
|
||||
/// <param name="y">The position's Y coordinate.</param>
|
||||
/// <param name="z">The position's Z coordinate.</param>
|
||||
/// <param name="width">The width, typically positive.</param>
|
||||
/// <param name="height">The height, typically positive.</param>
|
||||
/// <param name="depth">The depth, typically positive.</param>
|
||||
public AABB(real_t x, real_t y, real_t z, real_t width, real_t height, real_t depth)
|
||||
{
|
||||
_position = new Vector3(x, y, z);
|
||||
|
@ -458,6 +658,12 @@ namespace Godot
|
|||
return _position == other._position && _size == other._size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this AABB and `other` are approximately equal, by running
|
||||
/// <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
|
||||
/// </summary>
|
||||
/// <param name="other">The other AABB to compare.</param>
|
||||
/// <returns>Whether or not the AABBs are approximately equal.</returns>
|
||||
public bool IsEqualApprox(AABB other)
|
||||
{
|
||||
return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other._size);
|
||||
|
|
|
@ -8,6 +8,20 @@ using real_t = System.Single;
|
|||
|
||||
namespace Godot
|
||||
{
|
||||
/// <summary>
|
||||
/// 3×3 matrix used for 3D rotation and scale.
|
||||
/// Almost always used as an orthogonal basis for a Transform.
|
||||
///
|
||||
/// Contains 3 vector fields X, Y and Z as its columns, which are typically
|
||||
/// interpreted as the local basis vectors of a 3D transformation. For such use,
|
||||
/// it is composed of a scaling and a rotation matrix, in that order (M = R.S).
|
||||
///
|
||||
/// Can also be accessed as array of 3D vectors. These vectors are normally
|
||||
/// orthogonal to each other, but are not necessarily normalized (due to scaling).
|
||||
///
|
||||
/// For more information, read this documentation article:
|
||||
/// https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Basis : IEquatable<Basis>
|
||||
|
@ -15,9 +29,9 @@ namespace Godot
|
|||
// NOTE: x, y and z are public-only. Use Column0, Column1 and Column2 internally.
|
||||
|
||||
/// <summary>
|
||||
/// Returns the basis matrix’s x vector.
|
||||
/// This is equivalent to <see cref="Column0"/>.
|
||||
/// The basis matrix's X vector (column 0).
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="Column0"/> and array index `[0]`.</value>
|
||||
public Vector3 x
|
||||
{
|
||||
get => Column0;
|
||||
|
@ -25,9 +39,9 @@ namespace Godot
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the basis matrix’s y vector.
|
||||
/// This is equivalent to <see cref="Column1"/>.
|
||||
/// The basis matrix's Y vector (column 1).
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="Column1"/> and array index `[1]`.</value>
|
||||
public Vector3 y
|
||||
{
|
||||
get => Column1;
|
||||
|
@ -35,19 +49,40 @@ namespace Godot
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the basis matrix’s z vector.
|
||||
/// This is equivalent to <see cref="Column2"/>.
|
||||
/// The basis matrix's Z vector (column 2).
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="Column2"/> and array index `[2]`.</value>
|
||||
public Vector3 z
|
||||
{
|
||||
get => Column2;
|
||||
set => Column2 = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Row 0 of the basis matrix. Shows which vectors contribute
|
||||
/// to the X direction. Rows are not very useful for user code,
|
||||
/// but are more efficient for some internal calculations.
|
||||
/// </summary>
|
||||
public Vector3 Row0;
|
||||
|
||||
/// <summary>
|
||||
/// Row 1 of the basis matrix. Shows which vectors contribute
|
||||
/// to the Y direction. Rows are not very useful for user code,
|
||||
/// but are more efficient for some internal calculations.
|
||||
/// </summary>
|
||||
public Vector3 Row1;
|
||||
|
||||
/// <summary>
|
||||
/// Row 2 of the basis matrix. Shows which vectors contribute
|
||||
/// to the Z direction. Rows are not very useful for user code,
|
||||
/// but are more efficient for some internal calculations.
|
||||
/// </summary>
|
||||
public Vector3 Row2;
|
||||
|
||||
/// <summary>
|
||||
/// Column 0 of the basis matrix (the X vector).
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="x"/> and array index `[0]`.</value>
|
||||
public Vector3 Column0
|
||||
{
|
||||
get => new Vector3(Row0.x, Row1.x, Row2.x);
|
||||
|
@ -58,6 +93,11 @@ namespace Godot
|
|||
this.Row2.x = value.z;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Column 1 of the basis matrix (the Y vector).
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="y"/> and array index `[1]`.</value>
|
||||
public Vector3 Column1
|
||||
{
|
||||
get => new Vector3(Row0.y, Row1.y, Row2.y);
|
||||
|
@ -68,6 +108,11 @@ namespace Godot
|
|||
this.Row2.y = value.z;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Column 2 of the basis matrix (the Z vector).
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="z"/> and array index `[2]`.</value>
|
||||
public Vector3 Column2
|
||||
{
|
||||
get => new Vector3(Row0.z, Row1.z, Row2.z);
|
||||
|
@ -79,6 +124,10 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The scale of this basis.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to the lengths of each column vector, but negative if the determinant is negative.</value>
|
||||
public Vector3 Scale
|
||||
{
|
||||
get
|
||||
|
@ -86,11 +135,18 @@ namespace Godot
|
|||
real_t detSign = Mathf.Sign(Determinant());
|
||||
return detSign * new Vector3
|
||||
(
|
||||
new Vector3(this.Row0[0], this.Row1[0], this.Row2[0]).Length(),
|
||||
new Vector3(this.Row0[1], this.Row1[1], this.Row2[1]).Length(),
|
||||
new Vector3(this.Row0[2], this.Row1[2], this.Row2[2]).Length()
|
||||
Column0.Length(),
|
||||
Column1.Length(),
|
||||
Column2.Length()
|
||||
);
|
||||
}
|
||||
set
|
||||
{
|
||||
value /= Scale; // Value becomes what's called "delta_scale" in core.
|
||||
Column0 *= value.x;
|
||||
Column1 *= value.y;
|
||||
Column2 *= value.z;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -157,8 +213,9 @@ namespace Godot
|
|||
real_t det = orthonormalizedBasis.Determinant();
|
||||
if (det < 0)
|
||||
{
|
||||
// Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
|
||||
orthonormalizedBasis = orthonormalizedBasis.Scaled(Vector3.NegOne);
|
||||
// Ensure that the determinant is 1, such that result is a proper
|
||||
// rotation matrix which can be represented by Euler angles.
|
||||
orthonormalizedBasis = orthonormalizedBasis.Scaled(-Vector3.One);
|
||||
}
|
||||
|
||||
return orthonormalizedBasis.Quat();
|
||||
|
@ -182,6 +239,15 @@ namespace Godot
|
|||
Row2 = new Vector3(0, 0, diagonal.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the determinant of the basis matrix. If the basis is
|
||||
/// uniformly scaled, its determinant is the square of the scale.
|
||||
///
|
||||
/// A negative determinant means the basis has a negative scale.
|
||||
/// A zero determinant means the basis isn't invertible,
|
||||
/// and is usually considered invalid.
|
||||
/// </summary>
|
||||
/// <returns>The determinant of the basis matrix.</returns>
|
||||
public real_t Determinant()
|
||||
{
|
||||
real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1];
|
||||
|
@ -191,6 +257,16 @@ namespace Godot
|
|||
return Row0[0] * cofac00 + Row0[1] * cofac10 + Row0[2] * cofac20;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the basis's rotation in the form of Euler angles
|
||||
/// (in the YXZ convention: when *decomposing*, first Z, then X, and Y last).
|
||||
/// The returned vector contains the rotation angles in
|
||||
/// the format (X angle, Y angle, Z angle).
|
||||
///
|
||||
/// Consider using the <see cref="Basis.Quat()"/> method instead, which
|
||||
/// returns a <see cref="Godot.Quat"/> quaternion instead of Euler angles.
|
||||
/// </summary>
|
||||
/// <returns>A Vector3 representing the basis rotation in Euler angles.</returns>
|
||||
public Vector3 GetEuler()
|
||||
{
|
||||
Basis m = Orthonormalized();
|
||||
|
@ -223,6 +299,12 @@ namespace Godot
|
|||
return euler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get rows by index. Rows are not very useful for user code,
|
||||
/// but are more efficient for some internal calculations.
|
||||
/// </summary>
|
||||
/// <param name="index">Which row.</param>
|
||||
/// <returns>One of `Row0`, `Row1`, or `Row2`.</returns>
|
||||
public Vector3 GetRow(int index)
|
||||
{
|
||||
switch (index)
|
||||
|
@ -238,6 +320,12 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets rows by index. Rows are not very useful for user code,
|
||||
/// but are more efficient for some internal calculations.
|
||||
/// </summary>
|
||||
/// <param name="index">Which row.</param>
|
||||
/// <param name="value">The vector to set the row to.</param>
|
||||
public void SetRow(int index, Vector3 value)
|
||||
{
|
||||
switch (index)
|
||||
|
@ -256,16 +344,16 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
public Vector3 GetColumn(int index)
|
||||
{
|
||||
return this[index];
|
||||
}
|
||||
|
||||
public void SetColumn(int index, Vector3 value)
|
||||
{
|
||||
this[index] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function considers a discretization of rotations into
|
||||
/// 24 points on unit sphere, lying along the vectors (x, y, z) with
|
||||
/// each component being either -1, 0, or 1, and returns the index
|
||||
/// of the point best representing the orientation of the object.
|
||||
/// It is mainly used by the <see cref="GridMap"/> editor.
|
||||
///
|
||||
/// For further details, refer to the Godot source code.
|
||||
/// </summary>
|
||||
/// <returns>The orthogonal index.</returns>
|
||||
public int GetOrthogonalIndex()
|
||||
{
|
||||
var orth = this;
|
||||
|
@ -279,11 +367,17 @@ namespace Godot
|
|||
real_t v = row[j];
|
||||
|
||||
if (v > 0.5f)
|
||||
{
|
||||
v = 1.0f;
|
||||
}
|
||||
else if (v < -0.5f)
|
||||
{
|
||||
v = -1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = 0f;
|
||||
}
|
||||
|
||||
row[j] = v;
|
||||
|
||||
|
@ -294,12 +388,18 @@ namespace Godot
|
|||
for (int i = 0; i < 24; i++)
|
||||
{
|
||||
if (orth == _orthoBases[i])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the inverse of the matrix.
|
||||
/// </summary>
|
||||
/// <returns>The inverse matrix.</returns>
|
||||
public Basis Inverse()
|
||||
{
|
||||
real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1];
|
||||
|
@ -309,7 +409,9 @@ namespace Godot
|
|||
real_t det = Row0[0] * cofac00 + Row0[1] * cofac10 + Row0[2] * cofac20;
|
||||
|
||||
if (det == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Matrix determinant is zero and cannot be inverted.");
|
||||
}
|
||||
|
||||
real_t detInv = 1.0f / det;
|
||||
|
||||
|
@ -328,11 +430,17 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the orthonormalized version of the basis matrix (useful to
|
||||
/// call occasionally to avoid rounding errors for orthogonal matrices).
|
||||
/// This performs a Gram-Schmidt orthonormalization on the basis of the matrix.
|
||||
/// </summary>
|
||||
/// <returns>An orthonormalized basis matrix.</returns>
|
||||
public Basis Orthonormalized()
|
||||
{
|
||||
Vector3 column0 = GetColumn(0);
|
||||
Vector3 column1 = GetColumn(1);
|
||||
Vector3 column2 = GetColumn(2);
|
||||
Vector3 column0 = this[0];
|
||||
Vector3 column1 = this[1];
|
||||
Vector3 column2 = this[2];
|
||||
|
||||
column0.Normalize();
|
||||
column1 = column1 - column0 * column0.Dot(column1);
|
||||
|
@ -343,48 +451,86 @@ namespace Godot
|
|||
return new Basis(column0, column1, column2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Introduce an additional rotation around the given `axis`
|
||||
/// by `phi` (in radians). 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 basis matrix.</returns>
|
||||
public Basis Rotated(Vector3 axis, real_t phi)
|
||||
{
|
||||
return new Basis(axis, phi) * this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Introduce an additional scaling specified by the given 3D scaling factor.
|
||||
/// </summary>
|
||||
/// <param name="scale">The scale to introduce.</param>
|
||||
/// <returns>The scaled basis matrix.</returns>
|
||||
public Basis Scaled(Vector3 scale)
|
||||
{
|
||||
var b = this;
|
||||
Basis b = this;
|
||||
b.Row0 *= scale.x;
|
||||
b.Row1 *= scale.y;
|
||||
b.Row2 *= scale.z;
|
||||
return b;
|
||||
}
|
||||
|
||||
public Basis Slerp(Basis target, real_t t)
|
||||
/// <summary>
|
||||
/// Assuming that the matrix is a proper rotation matrix, slerp performs
|
||||
/// a spherical-linear interpolation with another rotation matrix.
|
||||
/// </summary>
|
||||
/// <param name="target">The destination basis for interpolation.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting basis matrix of the interpolation.</returns>
|
||||
public Basis Slerp(Basis target, real_t weight)
|
||||
{
|
||||
var from = new Quat(this);
|
||||
var to = new Quat(target);
|
||||
Quat from = new Quat(this);
|
||||
Quat to = new Quat(target);
|
||||
|
||||
var b = new Basis(from.Slerp(to, t));
|
||||
b.Row0 *= Mathf.Lerp(Row0.Length(), target.Row0.Length(), t);
|
||||
b.Row1 *= Mathf.Lerp(Row1.Length(), target.Row1.Length(), t);
|
||||
b.Row2 *= Mathf.Lerp(Row2.Length(), target.Row2.Length(), t);
|
||||
Basis b = new Basis(from.Slerp(to, weight));
|
||||
b.Row0 *= Mathf.Lerp(Row0.Length(), target.Row0.Length(), weight);
|
||||
b.Row1 *= Mathf.Lerp(Row1.Length(), target.Row1.Length(), weight);
|
||||
b.Row2 *= Mathf.Lerp(Row2.Length(), target.Row2.Length(), weight);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transposed dot product with the X axis of the matrix.
|
||||
/// </summary>
|
||||
/// <param name="with">A vector to calculate the dot product with.</param>
|
||||
/// <returns>The resulting dot product.</returns>
|
||||
public real_t Tdotx(Vector3 with)
|
||||
{
|
||||
return this.Row0[0] * with[0] + this.Row1[0] * with[1] + this.Row2[0] * with[2];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transposed dot product with the Y axis of the matrix.
|
||||
/// </summary>
|
||||
/// <param name="with">A vector to calculate the dot product with.</param>
|
||||
/// <returns>The resulting dot product.</returns>
|
||||
public real_t Tdoty(Vector3 with)
|
||||
{
|
||||
return this.Row0[1] * with[0] + this.Row1[1] * with[1] + this.Row2[1] * with[2];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transposed dot product with the Z axis of the matrix.
|
||||
/// </summary>
|
||||
/// <param name="with">A vector to calculate the dot product with.</param>
|
||||
/// <returns>The resulting dot product.</returns>
|
||||
public real_t Tdotz(Vector3 with)
|
||||
{
|
||||
return this.Row0[2] * with[0] + this.Row1[2] * with[1] + this.Row2[2] * with[2];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the transposed version of the basis matrix.
|
||||
/// </summary>
|
||||
/// <returns>The transposed basis matrix.</returns>
|
||||
public Basis Transposed()
|
||||
{
|
||||
var tr = this;
|
||||
|
@ -404,6 +550,11 @@ namespace Godot
|
|||
return tr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector transformed (multiplied) by the basis matrix.
|
||||
/// </summary>
|
||||
/// <param name="v">A vector to transform.</param>
|
||||
/// <returns>The transfomed vector.</returns>
|
||||
public Vector3 Xform(Vector3 v)
|
||||
{
|
||||
return new Vector3
|
||||
|
@ -414,6 +565,14 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector transformed (multiplied) by the transposed basis matrix.
|
||||
///
|
||||
/// Note: This results in a multiplication by the inverse of the
|
||||
/// basis matrix only if it represents a rotation-reflection.
|
||||
/// </summary>
|
||||
/// <param name="v">A vector to inversely transform.</param>
|
||||
/// <returns>The inversely transfomed vector.</returns>
|
||||
public Vector3 XformInv(Vector3 v)
|
||||
{
|
||||
return new Vector3
|
||||
|
@ -424,6 +583,12 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the basis's rotation in the form of a quaternion.
|
||||
/// See <see cref="GetEuler()"/> if you need Euler angles, but keep in
|
||||
/// mind that quaternions should generally be preferred to Euler angles.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Godot.Quat"/> representing the basis's rotation.</returns>
|
||||
public Quat Quat()
|
||||
{
|
||||
real_t trace = Row0[0] + Row1[1] + Row2[2];
|
||||
|
@ -508,11 +673,33 @@ namespace Godot
|
|||
private static readonly Basis _flipY = new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1);
|
||||
private static readonly Basis _flipZ = new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1);
|
||||
|
||||
/// <summary>
|
||||
/// The identity basis, with no rotation or scaling applied.
|
||||
/// This is used as a replacement for `Basis()` in GDScript.
|
||||
/// Do not use `new Basis()` with no arguments in C#, because it sets all values to zero.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Basis(Vector3.Right, Vector3.Up, Vector3.Back)`.</value>
|
||||
public static Basis Identity { get { return _identity; } }
|
||||
/// <summary>
|
||||
/// The basis that will flip something along the X axis when used in a transformation.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Basis(Vector3.Left, Vector3.Up, Vector3.Back)`.</value>
|
||||
public static Basis FlipX { get { return _flipX; } }
|
||||
/// <summary>
|
||||
/// The basis that will flip something along the Y axis when used in a transformation.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Basis(Vector3.Right, Vector3.Down, Vector3.Back)`.</value>
|
||||
public static Basis FlipY { get { return _flipY; } }
|
||||
/// <summary>
|
||||
/// The basis that will flip something along the Z axis when used in a transformation.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Basis(Vector3.Right, Vector3.Up, Vector3.Forward)`.</value>
|
||||
public static Basis FlipZ { get { return _flipZ; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a pure rotation basis matrix from the given quaternion.
|
||||
/// </summary>
|
||||
/// <param name="quat">The quaternion to create the basis from.</param>
|
||||
public Basis(Quat quat)
|
||||
{
|
||||
real_t s = 2.0f / quat.LengthSquared;
|
||||
|
@ -535,26 +722,41 @@ namespace Godot
|
|||
Row2 = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy));
|
||||
}
|
||||
|
||||
public Basis(Vector3 euler)
|
||||
/// <summary>
|
||||
/// Constructs a pure rotation basis matrix from the given Euler angles
|
||||
/// (in the YXZ convention: when *composing*, first Y, then X, and Z last),
|
||||
/// given in the vector format as (X angle, Y angle, Z angle).
|
||||
///
|
||||
/// Consider using the <see cref="Basis(Quat)"/> constructor instead, which
|
||||
/// uses a <see cref="Godot.Quat"/> quaternion instead of Euler angles.
|
||||
/// </summary>
|
||||
/// <param name="eulerYXZ">The Euler angles to create the basis from.</param>
|
||||
public Basis(Vector3 eulerYXZ)
|
||||
{
|
||||
real_t c;
|
||||
real_t s;
|
||||
|
||||
c = Mathf.Cos(euler.x);
|
||||
s = Mathf.Sin(euler.x);
|
||||
c = Mathf.Cos(eulerYXZ.x);
|
||||
s = Mathf.Sin(eulerYXZ.x);
|
||||
var xmat = new Basis(1, 0, 0, 0, c, -s, 0, s, c);
|
||||
|
||||
c = Mathf.Cos(euler.y);
|
||||
s = Mathf.Sin(euler.y);
|
||||
c = Mathf.Cos(eulerYXZ.y);
|
||||
s = Mathf.Sin(eulerYXZ.y);
|
||||
var ymat = new Basis(c, 0, s, 0, 1, 0, -s, 0, c);
|
||||
|
||||
c = Mathf.Cos(euler.z);
|
||||
s = Mathf.Sin(euler.z);
|
||||
c = Mathf.Cos(eulerYXZ.z);
|
||||
s = Mathf.Sin(eulerYXZ.z);
|
||||
var zmat = new Basis(c, -s, 0, s, c, 0, 0, 0, 1);
|
||||
|
||||
this = ymat * xmat * zmat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a pure rotation basis matrix, rotated around the given `axis`
|
||||
/// by `phi` (in radians). 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>
|
||||
public Basis(Vector3 axis, real_t phi)
|
||||
{
|
||||
Vector3 axisSq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
|
||||
|
@ -582,6 +784,12 @@ namespace Godot
|
|||
Row2.y = xyzt + zyxs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a basis matrix from 3 axis vectors (matrix columns).
|
||||
/// </summary>
|
||||
/// <param name="column0">The X vector, or Column0.</param>
|
||||
/// <param name="column1">The Y vector, or Column1.</param>
|
||||
/// <param name="column2">The Z vector, or Column2.</param>
|
||||
public Basis(Vector3 column0, Vector3 column1, Vector3 column2)
|
||||
{
|
||||
Row0 = new Vector3(column0.x, column1.x, column2.x);
|
||||
|
@ -637,6 +845,12 @@ namespace Godot
|
|||
return Row0.Equals(other.Row0) && Row1.Equals(other.Row1) && Row2.Equals(other.Row2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this basis and `other` are approximately equal, by running
|
||||
/// <see cref="Vector3.IsEqualApprox(Vector3)"/> on each component.
|
||||
/// </summary>
|
||||
/// <param name="other">The other basis to compare.</param>
|
||||
/// <returns>Whether or not the matrices are approximately equal.</returns>
|
||||
public bool IsEqualApprox(Basis other)
|
||||
{
|
||||
return Row0.IsEqualApprox(other.Row0) && Row1.IsEqualApprox(other.Row1) && Row2.IsEqualApprox(other.Row2);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,10 @@ using System.Collections.Generic;
|
|||
|
||||
namespace Godot
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains color constants created from standardized color names.
|
||||
/// The standardized color set is based on the X11 and .NET color names.
|
||||
/// </summary>
|
||||
public static class Colors
|
||||
{
|
||||
// Color names and values are derived from core/color_names.inc
|
||||
|
|
|
@ -11,79 +11,185 @@ namespace Godot
|
|||
{
|
||||
// Define constants with Decimal precision and cast down to double or float.
|
||||
|
||||
/// <summary>
|
||||
/// The circle constant, the circumference of the unit circle in radians.
|
||||
/// </summary>
|
||||
public const real_t Tau = (real_t) 6.2831853071795864769252867666M; // 6.2831855f and 6.28318530717959
|
||||
|
||||
/// <summary>
|
||||
/// Constant that represents how many times the diameter of a circle
|
||||
/// fits around its perimeter. This is equivalent to `Mathf.Tau / 2`.
|
||||
/// </summary>
|
||||
public const real_t Pi = (real_t) 3.1415926535897932384626433833M; // 3.1415927f and 3.14159265358979
|
||||
|
||||
/// <summary>
|
||||
/// Positive infinity. For negative infinity, use `-Mathf.Inf`.
|
||||
/// </summary>
|
||||
public const real_t Inf = real_t.PositiveInfinity;
|
||||
|
||||
/// <summary>
|
||||
/// "Not a Number", an invalid value. `NaN` has special properties, including
|
||||
/// that it is not equal to itself. It is output by some invalid operations,
|
||||
/// such as dividing zero by zero.
|
||||
/// </summary>
|
||||
public const real_t NaN = real_t.NaN;
|
||||
|
||||
private const real_t Deg2RadConst = (real_t) 0.0174532925199432957692369077M; // 0.0174532924f and 0.0174532925199433
|
||||
private const real_t Rad2DegConst = (real_t) 57.295779513082320876798154814M; // 57.29578f and 57.2957795130823
|
||||
|
||||
/// <summary>
|
||||
/// Returns the absolute value of `s` (i.e. positive value).
|
||||
/// </summary>
|
||||
/// <param name="s">The input number.</param>
|
||||
/// <returns>The absolute value of `s`.</returns>
|
||||
public static int Abs(int s)
|
||||
{
|
||||
return Math.Abs(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the absolute value of `s` (i.e. positive value).
|
||||
/// </summary>
|
||||
/// <param name="s">The input number.</param>
|
||||
/// <returns>The absolute value of `s`.</returns>
|
||||
public static real_t Abs(real_t s)
|
||||
{
|
||||
return Math.Abs(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the arc cosine of `s` in radians. Use to get the angle of cosine s.
|
||||
/// </summary>
|
||||
/// <param name="s">The input cosine value. Must be on the range of -1.0 to 1.0.</param>
|
||||
/// <returns>An angle that would result in the given cosine value. On the range `0` to `Tau/2`.</returns>
|
||||
public static real_t Acos(real_t s)
|
||||
{
|
||||
return (real_t)Math.Acos(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the arc sine of `s` in radians. Use to get the angle of sine s.
|
||||
/// </summary>
|
||||
/// <param name="s">The input sine value. Must be on the range of -1.0 to 1.0.</param>
|
||||
/// <returns>An angle that would result in the given sine value. On the range `-Tau/4` to `Tau/4`.</returns>
|
||||
public static real_t Asin(real_t s)
|
||||
{
|
||||
return (real_t)Math.Asin(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the arc tangent of `s` in radians. Use to get the angle of tangent s.
|
||||
///
|
||||
/// The method cannot know in which quadrant the angle should fall.
|
||||
/// See <see cref="Atan2(real_t, real_t)"/> if you have both `y` and `x`.
|
||||
/// </summary>
|
||||
/// <param name="s">The input tangent value.</param>
|
||||
/// <returns>An angle that would result in the given tangent value. On the range `-Tau/4` to `Tau/4`.</returns>
|
||||
public static real_t Atan(real_t s)
|
||||
{
|
||||
return (real_t)Math.Atan(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the arc tangent of `y` and `x` in radians. Use to get the angle
|
||||
/// of the tangent of `y/x`. To compute the value, the method takes into
|
||||
/// account the sign of both arguments in order to determine the quadrant.
|
||||
///
|
||||
/// Important note: The Y coordinate comes first, by convention.
|
||||
/// </summary>
|
||||
/// <param name="y">The Y coordinate of the point to find the angle to.</param>
|
||||
/// <param name="x">The X coordinate of the point to find the angle to.</param>
|
||||
/// <returns>An angle that would result in the given tangent value. On the range `-Tau/2` to `Tau/2`.</returns>
|
||||
public static real_t Atan2(real_t y, real_t x)
|
||||
{
|
||||
return (real_t)Math.Atan2(y, x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a 2D point expressed in the cartesian coordinate
|
||||
/// system (X and Y axis) to the polar coordinate system
|
||||
/// (a distance from the origin and an angle).
|
||||
/// </summary>
|
||||
/// <param name="x">The input X coordinate.</param>
|
||||
/// <param name="y">The input Y coordinate.</param>
|
||||
/// <returns>A <see cref="Vector2"/> with X representing the distance and Y representing the angle.</returns>
|
||||
public static Vector2 Cartesian2Polar(real_t x, real_t y)
|
||||
{
|
||||
return new Vector2(Sqrt(x * x + y * y), Atan2(y, x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rounds `s` upward (towards positive infinity).
|
||||
/// </summary>
|
||||
/// <param name="s">The number to ceil.</param>
|
||||
/// <returns>The smallest whole number that is not less than `s`.</returns>
|
||||
public static real_t Ceil(real_t s)
|
||||
{
|
||||
return (real_t)Math.Ceiling(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps a `value` so that it is not less than `min` and not more than `max`.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to clamp.</param>
|
||||
/// <param name="min">The minimum allowed value.</param>
|
||||
/// <param name="max">The maximum allowed value.</param>
|
||||
/// <returns>The clamped value.</returns>
|
||||
public static int Clamp(int value, int min, int max)
|
||||
{
|
||||
return value < min ? min : value > max ? max : value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps a `value` so that it is not less than `min` and not more than `max`.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to clamp.</param>
|
||||
/// <param name="min">The minimum allowed value.</param>
|
||||
/// <param name="max">The maximum allowed value.</param>
|
||||
/// <returns>The clamped value.</returns>
|
||||
public static real_t Clamp(real_t value, real_t min, real_t max)
|
||||
{
|
||||
return value < min ? min : value > max ? max : value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cosine of angle `s` in radians.
|
||||
/// </summary>
|
||||
/// <param name="s">The angle in radians.</param>
|
||||
/// <returns>The cosine of that angle.</returns>
|
||||
public static real_t Cos(real_t s)
|
||||
{
|
||||
return (real_t)Math.Cos(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hyperbolic cosine of angle `s` in radians.
|
||||
/// </summary>
|
||||
/// <param name="s">The angle in radians.</param>
|
||||
/// <returns>The hyperbolic cosine of that angle.</returns>
|
||||
public static real_t Cosh(real_t s)
|
||||
{
|
||||
return (real_t)Math.Cosh(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an angle expressed in degrees to radians.
|
||||
/// </summary>
|
||||
/// <param name="deg">An angle expressed in degrees.</param>
|
||||
/// <returns>The same angle expressed in radians.</returns>
|
||||
public static real_t Deg2Rad(real_t deg)
|
||||
{
|
||||
return deg * Deg2RadConst;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Easing function, based on exponent. The curve values are:
|
||||
/// `0` is constant, `1` is linear, `0` to `1` is ease-in, `1` or more is ease-out.
|
||||
/// Negative values are in-out/out-in.
|
||||
/// </summary>
|
||||
/// <param name="s">The value to ease.</param>
|
||||
/// <param name="curve">`0` is constant, `1` is linear, `0` to `1` is ease-in, `1` or more is ease-out.</param>
|
||||
/// <returns>The eased value.</returns>
|
||||
public static real_t Ease(real_t s, real_t curve)
|
||||
{
|
||||
if (s < 0f)
|
||||
|
@ -118,21 +224,47 @@ namespace Godot
|
|||
return 0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The natural exponential function. It raises the mathematical
|
||||
/// constant `e` to the power of `s` and returns it.
|
||||
/// </summary>
|
||||
/// <param name="s">The exponent to raise `e` to.</param>
|
||||
/// <returns>`e` raised to the power of `s`.</returns>
|
||||
public static real_t Exp(real_t s)
|
||||
{
|
||||
return (real_t)Math.Exp(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rounds `s` downward (towards negative infinity).
|
||||
/// </summary>
|
||||
/// <param name="s">The number to floor.</param>
|
||||
/// <returns>The largest whole number that is not more than `s`.</returns>
|
||||
public static real_t Floor(real_t s)
|
||||
{
|
||||
return (real_t)Math.Floor(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a normalized value considering the given range.
|
||||
/// This is the opposite of <see cref="Lerp(real_t, real_t, real_t)"/>.
|
||||
/// </summary>
|
||||
/// <param name="from">The interpolated value.</param>
|
||||
/// <param name="to">The destination value for interpolation.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting value of the inverse interpolation.</returns>
|
||||
public static real_t InverseLerp(real_t from, real_t to, real_t weight)
|
||||
{
|
||||
return (weight - from) / (to - from);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if `a` and `b` are approximately equal to each other.
|
||||
/// The comparison is done using a tolerance calculation with <see cref="Epsilon"/>.
|
||||
/// </summary>
|
||||
/// <param name="a">One of the values.</param>
|
||||
/// <param name="b">The other value.</param>
|
||||
/// <returns>A bool for whether or not the two values are approximately equal.</returns>
|
||||
public static bool IsEqualApprox(real_t a, real_t b)
|
||||
{
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
|
@ -149,26 +281,62 @@ namespace Godot
|
|||
return Abs(a - b) < tolerance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether `s` is an infinity value (either positive infinity or negative infinity).
|
||||
/// </summary>
|
||||
/// <param name="s">The value to check.</param>
|
||||
/// <returns>A bool for whether or not the value is an infinity value.</returns>
|
||||
public static bool IsInf(real_t s)
|
||||
{
|
||||
return real_t.IsInfinity(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether `s` is a `NaN` ("Not a Number" or invalid) value.
|
||||
/// </summary>
|
||||
/// <param name="s">The value to check.</param>
|
||||
/// <returns>A bool for whether or not the value is a `NaN` value.</returns>
|
||||
public static bool IsNaN(real_t s)
|
||||
{
|
||||
return real_t.IsNaN(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if `s` is approximately zero.
|
||||
/// The comparison is done using a tolerance calculation with <see cref="Epsilon"/>.
|
||||
///
|
||||
/// This method is faster than using <see cref="IsEqualApprox(real_t, real_t)"/> with one value as zero.
|
||||
/// </summary>
|
||||
/// <param name="s">The value to check.</param>
|
||||
/// <returns>A bool for whether or not the value is nearly zero.</returns>
|
||||
public static bool IsZeroApprox(real_t s)
|
||||
{
|
||||
return Abs(s) < Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolates between two values by a normalized value.
|
||||
/// This is the opposite <see cref="InverseLerp(real_t, real_t, real_t)"/>.
|
||||
/// </summary>
|
||||
/// <param name="from">The start value for interpolation.</param>
|
||||
/// <param name="to">The destination value for interpolation.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting value of the interpolation.</returns>
|
||||
public static real_t Lerp(real_t from, real_t to, real_t weight)
|
||||
{
|
||||
return from + (to - from) * weight;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolates between two angles (in radians) by a normalized value.
|
||||
///
|
||||
/// Similar to <see cref="Lerp(real_t, real_t, real_t)"/>,
|
||||
/// but interpolates correctly when the angles wrap around <see cref="Tau"/>.
|
||||
/// </summary>
|
||||
/// <param name="from">The start angle for interpolation.</param>
|
||||
/// <param name="to">The destination angle for interpolation.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting angle of the interpolation.</returns>
|
||||
public static real_t LerpAngle(real_t from, real_t to, real_t weight)
|
||||
{
|
||||
real_t difference = (to - from) % Mathf.Tau;
|
||||
|
@ -176,36 +344,81 @@ namespace Godot
|
|||
return from + distance * weight;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Natural logarithm. The amount of time needed to reach a certain level of continuous growth.
|
||||
///
|
||||
/// Note: This is not the same as the "log" function on most calculators, which uses a base 10 logarithm.
|
||||
/// </summary>
|
||||
/// <param name="s">The input value.</param>
|
||||
/// <returns>The natural log of `s`.</returns>
|
||||
public static real_t Log(real_t s)
|
||||
{
|
||||
return (real_t)Math.Log(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum of two values.
|
||||
/// </summary>
|
||||
/// <param name="a">One of the values.</param>
|
||||
/// <param name="b">The other value.</param>
|
||||
/// <returns>Whichever of the two values is higher.</returns>
|
||||
public static int Max(int a, int b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum of two values.
|
||||
/// </summary>
|
||||
/// <param name="a">One of the values.</param>
|
||||
/// <param name="b">The other value.</param>
|
||||
/// <returns>Whichever of the two values is higher.</returns>
|
||||
public static real_t Max(real_t a, real_t b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum of two values.
|
||||
/// </summary>
|
||||
/// <param name="a">One of the values.</param>
|
||||
/// <param name="b">The other value.</param>
|
||||
/// <returns>Whichever of the two values is lower.</returns>
|
||||
public static int Min(int a, int b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum of two values.
|
||||
/// </summary>
|
||||
/// <param name="a">One of the values.</param>
|
||||
/// <param name="b">The other value.</param>
|
||||
/// <returns>Whichever of the two values is lower.</returns>
|
||||
public static real_t Min(real_t a, real_t b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves `from` toward `to` by the `delta` value.
|
||||
///
|
||||
/// Use a negative delta value to move away.
|
||||
/// </summary>
|
||||
/// <param name="from">The start value.</param>
|
||||
/// <param name="to">The value to move towards.</param>
|
||||
/// <param name="delta">The amount to move by.</param>
|
||||
/// <returns>The value after moving.</returns>
|
||||
public static real_t MoveToward(real_t from, real_t to, real_t delta)
|
||||
{
|
||||
return Abs(to - from) <= delta ? to : from + Sign(to - from) * delta;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the nearest larger power of 2 for the integer `value`.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>The nearest larger power of 2.</returns>
|
||||
public static int NearestPo2(int value)
|
||||
{
|
||||
value--;
|
||||
|
@ -218,14 +431,25 @@ namespace Godot
|
|||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a 2D point expressed in the polar coordinate
|
||||
/// system (a distance from the origin `r` and an angle `th`)
|
||||
/// to the cartesian coordinate system (X and Y axis).
|
||||
/// </summary>
|
||||
/// <param name="r">The distance from the origin.</param>
|
||||
/// <param name="th">The angle of the point.</param>
|
||||
/// <returns>A <see cref="Vector2"/> representing the cartesian coordinate.</returns>
|
||||
public static Vector2 Polar2Cartesian(real_t r, real_t th)
|
||||
{
|
||||
return new Vector2(r * Cos(th), r * Sin(th));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a canonical Modulus operation, where the output is on the range [0, b).
|
||||
/// Performs a canonical Modulus operation, where the output is on the range `[0, b)`.
|
||||
/// </summary>
|
||||
/// <param name="a">The dividend, the primary input.</param>
|
||||
/// <param name="b">The divisor. The output is on the range `[0, b)`.</param>
|
||||
/// <returns>The resulting output.</returns>
|
||||
public static int PosMod(int a, int b)
|
||||
{
|
||||
int c = a % b;
|
||||
|
@ -237,8 +461,11 @@ namespace Godot
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a canonical Modulus operation, where the output is on the range [0, b).
|
||||
/// Performs a canonical Modulus operation, where the output is on the range `[0, b)`.
|
||||
/// </summary>
|
||||
/// <param name="a">The dividend, the primary input.</param>
|
||||
/// <param name="b">The divisor. The output is on the range `[0, b)`.</param>
|
||||
/// <returns>The resulting output.</returns>
|
||||
public static real_t PosMod(real_t a, real_t b)
|
||||
{
|
||||
real_t c = a % b;
|
||||
|
@ -249,43 +476,89 @@ namespace Godot
|
|||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of `x` raised to the power of `y`.
|
||||
/// </summary>
|
||||
/// <param name="x">The base.</param>
|
||||
/// <param name="y">The exponent.</param>
|
||||
/// <returns>`x` raised to the power of `y`.</returns>
|
||||
public static real_t Pow(real_t x, real_t y)
|
||||
{
|
||||
return (real_t)Math.Pow(x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an angle expressed in radians to degrees.
|
||||
/// </summary>
|
||||
/// <param name="rad">An angle expressed in radians.</param>
|
||||
/// <returns>The same angle expressed in degrees.</returns>
|
||||
public static real_t Rad2Deg(real_t rad)
|
||||
{
|
||||
return rad * Rad2DegConst;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rounds `s` to the nearest whole number,
|
||||
/// with halfway cases rounded towards the nearest multiple of two.
|
||||
/// </summary>
|
||||
/// <param name="s">The number to round.</param>
|
||||
/// <returns>The rounded number.</returns>
|
||||
public static real_t Round(real_t s)
|
||||
{
|
||||
return (real_t)Math.Round(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the sign of `s`: `-1` or `1`. Returns `0` if `s` is `0`.
|
||||
/// </summary>
|
||||
/// <param name="s">The input number.</param>
|
||||
/// <returns>One of three possible values: `1`, `-1`, or `0`.</returns>
|
||||
public static int Sign(int s)
|
||||
{
|
||||
if (s == 0) return 0;
|
||||
return s < 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the sign of `s`: `-1` or `1`. Returns `0` if `s` is `0`.
|
||||
/// </summary>
|
||||
/// <param name="s">The input number.</param>
|
||||
/// <returns>One of three possible values: `1`, `-1`, or `0`.</returns>
|
||||
public static int Sign(real_t s)
|
||||
{
|
||||
if (s == 0) return 0;
|
||||
return s < 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the sine of angle `s` in radians.
|
||||
/// </summary>
|
||||
/// <param name="s">The angle in radians.</param>
|
||||
/// <returns>The sine of that angle.</returns>
|
||||
public static real_t Sin(real_t s)
|
||||
{
|
||||
return (real_t)Math.Sin(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hyperbolic sine of angle `s` in radians.
|
||||
/// </summary>
|
||||
/// <param name="s">The angle in radians.</param>
|
||||
/// <returns>The hyperbolic sine of that angle.</returns>
|
||||
public static real_t Sinh(real_t s)
|
||||
{
|
||||
return (real_t)Math.Sinh(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a number smoothly interpolated between `from` and `to`,
|
||||
/// based on the `weight`. Similar to <see cref="Lerp(real_t, real_t, real_t)"/>,
|
||||
/// but interpolates faster at the beginning and slower at the end.
|
||||
/// </summary>
|
||||
/// <param name="from">The start value for interpolation.</param>
|
||||
/// <param name="to">The destination value for interpolation.</param>
|
||||
/// <param name="weight">A value representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting value of the interpolation.</returns>
|
||||
public static real_t SmoothStep(real_t from, real_t to, real_t weight)
|
||||
{
|
||||
if (IsEqualApprox(from, to))
|
||||
|
@ -296,11 +569,25 @@ namespace Godot
|
|||
return x * x * (3 - 2 * x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the square root of `s`, where `s` is a non-negative number.
|
||||
///
|
||||
/// If you need negative inputs, use `System.Numerics.Complex`.
|
||||
/// </summary>
|
||||
/// <param name="s">The input number. Must not be negative.</param>
|
||||
/// <returns>The square root of `s`.</returns>
|
||||
public static real_t Sqrt(real_t s)
|
||||
{
|
||||
return (real_t)Math.Sqrt(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the position of the first non-zero digit, after the
|
||||
/// decimal point. Note that the maximum return value is 10,
|
||||
/// which is a design decision in the implementation.
|
||||
/// </summary>
|
||||
/// <param name="step">The input value.</param>
|
||||
/// <returns>The position of the first non-zero digit.</returns>
|
||||
public static int StepDecimals(real_t step)
|
||||
{
|
||||
double[] sd = new double[] {
|
||||
|
@ -326,32 +613,68 @@ namespace Godot
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Snaps float value `s` to a given `step`.
|
||||
/// This can also be used to round a floating point
|
||||
/// number to an arbitrary number of decimals.
|
||||
/// </summary>
|
||||
/// <param name="s">The value to stepify.</param>
|
||||
/// <param name="step">The step size to snap to.</param>
|
||||
/// <returns></returns>
|
||||
public static real_t Stepify(real_t s, real_t step)
|
||||
{
|
||||
if (step != 0f)
|
||||
{
|
||||
s = Floor(s / step + 0.5f) * step;
|
||||
return Floor(s / step + 0.5f) * step;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the tangent of angle `s` in radians.
|
||||
/// </summary>
|
||||
/// <param name="s">The angle in radians.</param>
|
||||
/// <returns>The tangent of that angle.</returns>
|
||||
public static real_t Tan(real_t s)
|
||||
{
|
||||
return (real_t)Math.Tan(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hyperbolic tangent of angle `s` in radians.
|
||||
/// </summary>
|
||||
/// <param name="s">The angle in radians.</param>
|
||||
/// <returns>The hyperbolic tangent of that angle.</returns>
|
||||
public static real_t Tanh(real_t s)
|
||||
{
|
||||
return (real_t)Math.Tanh(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps `value` between `min` and `max`. Usable for creating loop-alike
|
||||
/// behavior or infinite surfaces. If `min` is `0`, this is equivalent
|
||||
/// to <see cref="PosMod(int, int)"/>, so prefer using that instead.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to wrap.</param>
|
||||
/// <param name="min">The minimum allowed value and lower bound of the range.</param>
|
||||
/// <param name="max">The maximum allowed value and upper bound of the range.</param>
|
||||
/// <returns>The wrapped value.</returns>
|
||||
public static int Wrap(int value, int min, int max)
|
||||
{
|
||||
int range = max - min;
|
||||
return range == 0 ? min : min + ((value - min) % range + range) % range;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps `value` between `min` and `max`. Usable for creating loop-alike
|
||||
/// behavior or infinite surfaces. If `min` is `0`, this is equivalent
|
||||
/// to <see cref="PosMod(real_t, real_t)"/>, so prefer using that instead.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to wrap.</param>
|
||||
/// <param name="min">The minimum allowed value and lower bound of the range.</param>
|
||||
/// <param name="max">The maximum allowed value and upper bound of the range.</param>
|
||||
/// <returns>The wrapped value.</returns>
|
||||
public static real_t Wrap(real_t value, real_t min, real_t max)
|
||||
{
|
||||
real_t range = max - min;
|
||||
|
|
|
@ -12,40 +12,89 @@ namespace Godot
|
|||
{
|
||||
// Define constants with Decimal precision and cast down to double or float.
|
||||
|
||||
/// <summary>
|
||||
/// The natural number `e`.
|
||||
/// </summary>
|
||||
public const real_t E = (real_t) 2.7182818284590452353602874714M; // 2.7182817f and 2.718281828459045
|
||||
|
||||
/// <summary>
|
||||
/// The square root of 2.
|
||||
/// </summary>
|
||||
public const real_t Sqrt2 = (real_t) 1.4142135623730950488016887242M; // 1.4142136f and 1.414213562373095
|
||||
|
||||
/// <summary>
|
||||
/// A very small number used for float comparison with error tolerance.
|
||||
/// 1e-06 with single-precision floats, but 1e-14 if `REAL_T_IS_DOUBLE`.
|
||||
/// </summary>
|
||||
#if REAL_T_IS_DOUBLE
|
||||
public const real_t Epsilon = 1e-14; // Epsilon size should depend on the precision used.
|
||||
#else
|
||||
public const real_t Epsilon = 1e-06f;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the amount of digits after the decimal place.
|
||||
/// </summary>
|
||||
/// <param name="s">The input value.</param>
|
||||
/// <returns>The amount of digits.</returns>
|
||||
public static int DecimalCount(real_t s)
|
||||
{
|
||||
return DecimalCount((decimal)s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the amount of digits after the decimal place.
|
||||
/// </summary>
|
||||
/// <param name="s">The input <see cref="System.Decimal"/> value.</param>
|
||||
/// <returns>The amount of digits.</returns>
|
||||
public static int DecimalCount(decimal s)
|
||||
{
|
||||
return BitConverter.GetBytes(decimal.GetBits(s)[3])[2];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rounds `s` upward (towards positive infinity).
|
||||
///
|
||||
/// This is the same as <see cref="Ceil(real_t)"/>, but returns an `int`.
|
||||
/// </summary>
|
||||
/// <param name="s">The number to ceil.</param>
|
||||
/// <returns>The smallest whole number that is not less than `s`.</returns>
|
||||
public static int CeilToInt(real_t s)
|
||||
{
|
||||
return (int)Math.Ceiling(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rounds `s` downward (towards negative infinity).
|
||||
///
|
||||
/// This is the same as <see cref="Floor(real_t)"/>, but returns an `int`.
|
||||
/// </summary>
|
||||
/// <param name="s">The number to floor.</param>
|
||||
/// <returns>The largest whole number that is not more than `s`.</returns>
|
||||
public static int FloorToInt(real_t s)
|
||||
{
|
||||
return (int)Math.Floor(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static int RoundToInt(real_t s)
|
||||
{
|
||||
return (int)Math.Round(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if `a` and `b` are approximately equal to each other.
|
||||
/// The comparison is done using the provided tolerance value.
|
||||
/// If you want the tolerance to be calculated for you, use <see cref="IsEqualApprox(real_t, real_t)"/>.
|
||||
/// </summary>
|
||||
/// <param name="a">One of the values.</param>
|
||||
/// <param name="b">The other value.</param>
|
||||
/// <param name="tolerance">The pre-calculated tolerance value.</param>
|
||||
/// <returns>A bool for whether or not the two values are equal.</returns>
|
||||
public static bool IsEqualApprox(real_t a, real_t b, real_t tolerance)
|
||||
{
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
|
|
|
@ -8,18 +8,32 @@ using real_t = System.Single;
|
|||
|
||||
namespace Godot
|
||||
{
|
||||
/// <summary>
|
||||
/// Plane represents a normalized plane equation.
|
||||
/// "Over" or "Above" the plane is considered the side of
|
||||
/// the plane towards where the normal is pointing.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Plane : IEquatable<Plane>
|
||||
{
|
||||
private Vector3 _normal;
|
||||
|
||||
/// <summary>
|
||||
/// The normal of the plane (in the plane equation: a, b, and c).
|
||||
/// The normal vector must be normalized.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `x`, `y`, and `z`.</value>
|
||||
public Vector3 Normal
|
||||
{
|
||||
get { return _normal; }
|
||||
set { _normal = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The X component of the plane's normal vector.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="Normal"/>'s X value.</value>
|
||||
public real_t x
|
||||
{
|
||||
get
|
||||
|
@ -32,6 +46,10 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Y component of the plane's normal vector.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="Normal"/>'s Y value.</value>
|
||||
public real_t y
|
||||
{
|
||||
get
|
||||
|
@ -44,6 +62,10 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Z component of the plane's normal vector.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="Normal"/>'s Z value.</value>
|
||||
public real_t z
|
||||
{
|
||||
get
|
||||
|
@ -56,38 +78,68 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The distance from the origin to the plane (in the direction of
|
||||
/// <see cref="Normal"/>). This value is typically non-negative.
|
||||
/// </summary>
|
||||
/// <value>The plane's distance from the origin.</value>
|
||||
public real_t D { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The center of the plane, the point where the normal line intersects the plane.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="Normal"/> multiplied by `D`.</value>
|
||||
public Vector3 Center
|
||||
{
|
||||
get
|
||||
{
|
||||
return _normal * D;
|
||||
}
|
||||
set
|
||||
{
|
||||
_normal = value.Normalized();
|
||||
D = value.Length();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the shortest distance from this plane to the position `point`.
|
||||
/// </summary>
|
||||
/// <param name="point">The position to use for the calcualtion.</param>
|
||||
/// <returns>The shortest distance.</returns>
|
||||
public real_t DistanceTo(Vector3 point)
|
||||
{
|
||||
return _normal.Dot(point) - D;
|
||||
}
|
||||
|
||||
public Vector3 GetAnyPoint()
|
||||
{
|
||||
return _normal * D;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if point is inside the plane.
|
||||
/// Comparison uses a custom minimum epsilon threshold.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to check.</param>
|
||||
/// <param name="epsilon">The tolerance threshold.</param>
|
||||
/// <returns>A bool for whether or not the plane has the point.</returns>
|
||||
public bool HasPoint(Vector3 point, real_t epsilon = Mathf.Epsilon)
|
||||
{
|
||||
real_t dist = _normal.Dot(point) - D;
|
||||
return Mathf.Abs(dist) <= epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the intersection point of the three planes: `b`, `c`,
|
||||
/// and this plane. If no intersection is found, `null` is returned.
|
||||
/// </summary>
|
||||
/// <param name="b">One of the three planes to use in the calculation.</param>
|
||||
/// <param name="c">One of the three planes to use in the calculation.</param>
|
||||
/// <returns>The intersection, or `null` if none is found.</returns>
|
||||
public Vector3? Intersect3(Plane b, Plane c)
|
||||
{
|
||||
real_t denom = _normal.Cross(b._normal).Dot(c._normal);
|
||||
|
||||
if (Mathf.IsZeroApprox(denom))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Vector3 result = b._normal.Cross(c._normal) * D +
|
||||
c._normal.Cross(_normal) * b.D +
|
||||
|
@ -96,54 +148,94 @@ namespace Godot
|
|||
return result / denom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the intersection point of a ray consisting of the
|
||||
/// position `from` and the direction normal `dir` with this plane.
|
||||
/// If no intersection is found, `null` is returned.
|
||||
/// </summary>
|
||||
/// <param name="from">The start of the ray.</param>
|
||||
/// <param name="dir">The direction of the ray, normalized.</param>
|
||||
/// <returns>The intersection, or `null` if none is found.</returns>
|
||||
public Vector3? IntersectRay(Vector3 from, Vector3 dir)
|
||||
{
|
||||
real_t den = _normal.Dot(dir);
|
||||
|
||||
if (Mathf.IsZeroApprox(den))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
real_t dist = (_normal.Dot(from) - D) / den;
|
||||
|
||||
// This is a ray, before the emitting pos (from) does not exist
|
||||
if (dist > Mathf.Epsilon)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return from + dir * -dist;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the intersection point of a line segment from
|
||||
/// position `begin` to position `end` with this plane.
|
||||
/// If no intersection is found, `null` is returned.
|
||||
/// </summary>
|
||||
/// <param name="begin">The start of the line segment.</param>
|
||||
/// <param name="end">The end of the line segment.</param>
|
||||
/// <returns>The intersection, or `null` if none is found.</returns>
|
||||
public Vector3? IntersectSegment(Vector3 begin, Vector3 end)
|
||||
{
|
||||
Vector3 segment = begin - end;
|
||||
real_t den = _normal.Dot(segment);
|
||||
|
||||
if (Mathf.IsZeroApprox(den))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
real_t dist = (_normal.Dot(begin) - D) / den;
|
||||
|
||||
// Only allow dist to be in the range of 0 to 1, with tolerance.
|
||||
if (dist < -Mathf.Epsilon || dist > 1.0f + Mathf.Epsilon)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return begin + segment * -dist;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if `point` is located above the plane.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to check.</param>
|
||||
/// <returns>A bool for whether or not the point is above the plane.</returns>
|
||||
public bool IsPointOver(Vector3 point)
|
||||
{
|
||||
return _normal.Dot(point) > D;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the plane scaled to unit length.
|
||||
/// </summary>
|
||||
/// <returns>A normalized version of the plane.</returns>
|
||||
public Plane Normalized()
|
||||
{
|
||||
real_t len = _normal.Length();
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
return new Plane(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return new Plane(_normal / len, D / len);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the orthogonal projection of `point` into the plane.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to project.</param>
|
||||
/// <returns>The projected point.</returns>
|
||||
public Vector3 Project(Vector3 point)
|
||||
{
|
||||
return point - _normal * DistanceTo(point);
|
||||
|
@ -154,22 +246,56 @@ namespace Godot
|
|||
private static readonly Plane _planeXZ = new Plane(0, 1, 0, 0);
|
||||
private static readonly Plane _planeXY = new Plane(0, 0, 1, 0);
|
||||
|
||||
/// <summary>
|
||||
/// A plane that extends in the Y and Z axes (normal vector points +X).
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Plane(1, 0, 0, 0)`.</value>
|
||||
public static Plane PlaneYZ { get { return _planeYZ; } }
|
||||
|
||||
/// <summary>
|
||||
/// A plane that extends in the X and Z axes (normal vector points +Y).
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Plane(0, 1, 0, 0)`.</value>
|
||||
public static Plane PlaneXZ { get { return _planeXZ; } }
|
||||
|
||||
/// <summary>
|
||||
/// A plane that extends in the X and Y axes (normal vector points +Z).
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Plane(0, 0, 1, 0)`.</value>
|
||||
public static Plane PlaneXY { get { return _planeXY; } }
|
||||
|
||||
// Constructors
|
||||
/// <summary>
|
||||
/// Constructs a plane from four values. `a`, `b` and `c` become the
|
||||
/// components of the resulting plane's <see cref="Normal"/> vector.
|
||||
/// `d` becomes the plane's distance from the origin.
|
||||
/// </summary>
|
||||
/// <param name="a">The X component of the plane's normal vector.</param>
|
||||
/// <param name="b">The Y component of the plane's normal vector.</param>
|
||||
/// <param name="c">The Z component of the plane's normal vector.</param>
|
||||
/// <param name="d">The plane's distance from the origin. This value is typically non-negative.</param>
|
||||
public Plane(real_t a, real_t b, real_t c, real_t d)
|
||||
{
|
||||
_normal = new Vector3(a, b, c);
|
||||
this.D = d;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a plane from a normal vector and the plane's distance to the origin.
|
||||
/// </summary>
|
||||
/// <param name="normal">The normal of the plane, must be normalized.</param>
|
||||
/// <param name="d">The plane's distance from the origin. This value is typically non-negative.</param>
|
||||
public Plane(Vector3 normal, real_t d)
|
||||
{
|
||||
this._normal = normal;
|
||||
this.D = d;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a plane from the three points, given in clockwise order.
|
||||
/// </summary>
|
||||
/// <param name="v1">The first point.</param>
|
||||
/// <param name="v2">The second point.</param>
|
||||
/// <param name="v3">The third point.</param>
|
||||
public Plane(Vector3 v1, Vector3 v2, Vector3 v3)
|
||||
{
|
||||
_normal = (v1 - v3).Cross(v1 - v2);
|
||||
|
@ -207,6 +333,12 @@ namespace Godot
|
|||
return _normal == other._normal && D == other.D;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this plane and `other` are approximately equal, by running
|
||||
/// <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
|
||||
/// </summary>
|
||||
/// <param name="other">The other plane to compare.</param>
|
||||
/// <returns>Whether or not the planes are approximately equal.</returns>
|
||||
public bool IsEqualApprox(Plane other)
|
||||
{
|
||||
return _normal.IsEqualApprox(other._normal) && Mathf.IsEqualApprox(D, other.D);
|
||||
|
|
|
@ -8,15 +8,51 @@ using real_t = System.Single;
|
|||
|
||||
namespace Godot
|
||||
{
|
||||
/// <summary>
|
||||
/// A unit quaternion used for representing 3D rotations.
|
||||
/// Quaternions need to be normalized to be used for rotation.
|
||||
///
|
||||
/// It is similar to Basis, which implements matrix representation of
|
||||
/// rotations, and can be parametrized using both an axis-angle pair
|
||||
/// or Euler angles. Basis stores rotation, scale, and shearing,
|
||||
/// while Quat only stores rotation.
|
||||
///
|
||||
/// Due to its compactness and the way it is stored in memory, certain
|
||||
/// operations (obtaining axis-angle and performing SLERP, in particular)
|
||||
/// are more efficient and robust against floating-point errors.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Quat : IEquatable<Quat>
|
||||
{
|
||||
/// <summary>
|
||||
/// X component of the quaternion (imaginary `i` axis part).
|
||||
/// Quaternion components should usually not be manipulated directly.
|
||||
/// </summary>
|
||||
public real_t x;
|
||||
|
||||
/// <summary>
|
||||
/// Y component of the quaternion (imaginary `j` axis part).
|
||||
/// Quaternion components should usually not be manipulated directly.
|
||||
/// </summary>
|
||||
public real_t y;
|
||||
|
||||
/// <summary>
|
||||
/// Z component of the quaternion (imaginary `k` axis part).
|
||||
/// Quaternion components should usually not be manipulated directly.
|
||||
/// </summary>
|
||||
public real_t z;
|
||||
|
||||
/// <summary>
|
||||
/// W component of the quaternion (real part).
|
||||
/// Quaternion components should usually not be manipulated directly.
|
||||
/// </summary>
|
||||
public real_t w;
|
||||
|
||||
/// <summary>
|
||||
/// Access quaternion components using their index.
|
||||
/// </summary>
|
||||
/// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`, `[2]` is equivalent to `.z`, `[3]` is equivalent to `.w`.</value>
|
||||
public real_t this[int index]
|
||||
{
|
||||
get
|
||||
|
@ -57,16 +93,35 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length (magnitude) of the quaternion.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `Mathf.Sqrt(LengthSquared)`.</value>
|
||||
public real_t Length
|
||||
{
|
||||
get { return Mathf.Sqrt(LengthSquared); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the squared length (squared magnitude) of the quaternion.
|
||||
/// This method runs faster than <see cref="Length"/>, so prefer it if
|
||||
/// you need to compare quaternions or need the squared length for some formula.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `Dot(this)`.</value>
|
||||
public real_t LengthSquared
|
||||
{
|
||||
get { return Dot(this); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a cubic spherical interpolation between quaternions `preA`,
|
||||
/// this vector, `b`, and `postB`, by the given amount `t`.
|
||||
/// </summary>
|
||||
/// <param name="b">The destination quaternion.</param>
|
||||
/// <param name="preA">A quaternion before this quaternion.</param>
|
||||
/// <param name="postB">A quaternion after `b`.</param>
|
||||
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The interpolated quaternion.</returns>
|
||||
public Quat CubicSlerp(Quat b, Quat preA, Quat postB, real_t t)
|
||||
{
|
||||
real_t t2 = (1.0f - t) * t * 2f;
|
||||
|
@ -75,85 +130,131 @@ namespace Godot
|
|||
return sp.Slerpni(sq, t2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dot product of two quaternions.
|
||||
/// </summary>
|
||||
/// <param name="b">The other quaternion.</param>
|
||||
/// <returns>The dot product.</returns>
|
||||
public real_t Dot(Quat b)
|
||||
{
|
||||
return x * b.x + y * b.y + z * b.z + w * b.w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Euler angles (in the YXZ convention: when decomposing,
|
||||
/// first Z, then X, and Y last) corresponding to the rotation
|
||||
/// represented by the unit quaternion. Returned vector contains
|
||||
/// the rotation angles in the format (X angle, Y angle, Z angle).
|
||||
/// </summary>
|
||||
/// <returns>The Euler angle representation of this quaternion.</returns>
|
||||
public Vector3 GetEuler()
|
||||
{
|
||||
#if DEBUG
|
||||
if (!IsNormalized())
|
||||
{
|
||||
throw new InvalidOperationException("Quat is not normalized");
|
||||
}
|
||||
#endif
|
||||
var basis = new Basis(this);
|
||||
return basis.GetEuler();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the inverse of the quaternion.
|
||||
/// </summary>
|
||||
/// <returns>The inverse quaternion.</returns>
|
||||
public Quat Inverse()
|
||||
{
|
||||
#if DEBUG
|
||||
if (!IsNormalized())
|
||||
{
|
||||
throw new InvalidOperationException("Quat is not normalized");
|
||||
}
|
||||
#endif
|
||||
return new Quat(-x, -y, -z, w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the quaternion is normalized or not.
|
||||
/// </summary>
|
||||
/// <returns>A bool for whether the quaternion is normalized or not.</returns>
|
||||
public bool IsNormalized()
|
||||
{
|
||||
return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the quaternion, normalized to unit length.
|
||||
/// </summary>
|
||||
/// <returns>The normalized quaternion.</returns>
|
||||
public Quat Normalized()
|
||||
{
|
||||
return this / Length;
|
||||
}
|
||||
|
||||
public Quat Slerp(Quat b, real_t t)
|
||||
/// <summary>
|
||||
/// Returns the result of the spherical linear interpolation between
|
||||
/// this quaternion and `to` by amount `weight`.
|
||||
///
|
||||
/// Note: Both quaternions must be normalized.
|
||||
/// </summary>
|
||||
/// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting quaternion of the interpolation.</returns>
|
||||
public Quat Slerp(Quat to, real_t weight)
|
||||
{
|
||||
#if DEBUG
|
||||
if (!IsNormalized())
|
||||
{
|
||||
throw new InvalidOperationException("Quat is not normalized");
|
||||
if (!b.IsNormalized())
|
||||
throw new ArgumentException("Argument is not normalized", nameof(b));
|
||||
}
|
||||
if (!to.IsNormalized())
|
||||
{
|
||||
throw new ArgumentException("Argument is not normalized", nameof(to));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Calculate cosine
|
||||
real_t cosom = x * b.x + y * b.y + z * b.z + w * b.w;
|
||||
// Calculate cosine.
|
||||
real_t cosom = x * to.x + y * to.y + z * to.z + w * to.w;
|
||||
|
||||
var to1 = new Quat();
|
||||
|
||||
// Adjust signs if necessary
|
||||
// Adjust signs if necessary.
|
||||
if (cosom < 0.0)
|
||||
{
|
||||
cosom = -cosom;
|
||||
to1.x = -b.x;
|
||||
to1.y = -b.y;
|
||||
to1.z = -b.z;
|
||||
to1.w = -b.w;
|
||||
to1.x = -to.x;
|
||||
to1.y = -to.y;
|
||||
to1.z = -to.z;
|
||||
to1.w = -to.w;
|
||||
}
|
||||
else
|
||||
{
|
||||
to1.x = b.x;
|
||||
to1.y = b.y;
|
||||
to1.z = b.z;
|
||||
to1.w = b.w;
|
||||
to1.x = to.x;
|
||||
to1.y = to.y;
|
||||
to1.z = to.z;
|
||||
to1.w = to.w;
|
||||
}
|
||||
|
||||
real_t sinom, scale0, scale1;
|
||||
|
||||
// Calculate coefficients
|
||||
// Calculate coefficients.
|
||||
if (1.0 - cosom > Mathf.Epsilon)
|
||||
{
|
||||
// Standard case (Slerp)
|
||||
// Standard case (Slerp).
|
||||
real_t omega = Mathf.Acos(cosom);
|
||||
sinom = Mathf.Sin(omega);
|
||||
scale0 = Mathf.Sin((1.0f - t) * omega) / sinom;
|
||||
scale1 = Mathf.Sin(t * omega) / sinom;
|
||||
scale0 = Mathf.Sin((1.0f - weight) * omega) / sinom;
|
||||
scale1 = Mathf.Sin(weight * omega) / sinom;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Quaternions are very close so we can do a linear interpolation
|
||||
scale0 = 1.0f - t;
|
||||
scale1 = t;
|
||||
// Quaternions are very close so we can do a linear interpolation.
|
||||
scale0 = 1.0f - weight;
|
||||
scale1 = weight;
|
||||
}
|
||||
|
||||
// Calculate final values
|
||||
// Calculate final values.
|
||||
return new Quat
|
||||
(
|
||||
scale0 * x + scale1 * to1.x,
|
||||
|
@ -163,9 +264,17 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
public Quat Slerpni(Quat b, real_t t)
|
||||
/// <summary>
|
||||
/// Returns the result of the spherical linear interpolation between
|
||||
/// this quaternion and `to` by amount `weight`, but without
|
||||
/// checking if the rotation path is not bigger than 90 degrees.
|
||||
/// </summary>
|
||||
/// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting quaternion of the interpolation.</returns>
|
||||
public Quat Slerpni(Quat to, real_t weight)
|
||||
{
|
||||
real_t dot = Dot(b);
|
||||
real_t dot = Dot(to);
|
||||
|
||||
if (Mathf.Abs(dot) > 0.9999f)
|
||||
{
|
||||
|
@ -174,33 +283,54 @@ namespace Godot
|
|||
|
||||
real_t theta = Mathf.Acos(dot);
|
||||
real_t sinT = 1.0f / Mathf.Sin(theta);
|
||||
real_t newFactor = Mathf.Sin(t * theta) * sinT;
|
||||
real_t invFactor = Mathf.Sin((1.0f - t) * theta) * sinT;
|
||||
real_t newFactor = Mathf.Sin(weight * theta) * sinT;
|
||||
real_t invFactor = Mathf.Sin((1.0f - weight) * theta) * sinT;
|
||||
|
||||
return new Quat
|
||||
(
|
||||
invFactor * x + newFactor * b.x,
|
||||
invFactor * y + newFactor * b.y,
|
||||
invFactor * z + newFactor * b.z,
|
||||
invFactor * w + newFactor * b.w
|
||||
invFactor * x + newFactor * to.x,
|
||||
invFactor * y + newFactor * to.y,
|
||||
invFactor * z + newFactor * to.z,
|
||||
invFactor * w + newFactor * to.w
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector transformed (multiplied) by this quaternion.
|
||||
/// </summary>
|
||||
/// <param name="v">A vector to transform.</param>
|
||||
/// <returns>The transfomed vector.</returns>
|
||||
public Vector3 Xform(Vector3 v)
|
||||
{
|
||||
#if DEBUG
|
||||
if (!IsNormalized())
|
||||
{
|
||||
throw new InvalidOperationException("Quat is not normalized");
|
||||
}
|
||||
#endif
|
||||
var u = new Vector3(x, y, z);
|
||||
Vector3 uv = u.Cross(v);
|
||||
return v + ((uv * w) + u.Cross(uv)) * 2;
|
||||
}
|
||||
|
||||
// Static Readonly Properties
|
||||
public static Quat Identity { get; } = new Quat(0f, 0f, 0f, 1f);
|
||||
// Constants
|
||||
private static readonly Quat _identity = new Quat(0, 0, 0, 1);
|
||||
|
||||
// Constructors
|
||||
/// <summary>
|
||||
/// The identity quaternion, representing no rotation.
|
||||
/// Equivalent to an identity <see cref="Basis"/> matrix. If a vector is transformed by
|
||||
/// an identity quaternion, it will not change.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Quat(0, 0, 0, 1)`.</value>
|
||||
public static Quat Identity { get { return _identity; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a quaternion defined by the given values.
|
||||
/// </summary>
|
||||
/// <param name="x">X component of the quaternion (imaginary `i` axis part).</param>
|
||||
/// <param name="y">Y component of the quaternion (imaginary `j` axis part).</param>
|
||||
/// <param name="z">Z component of the quaternion (imaginary `k` axis part).</param>
|
||||
/// <param name="w">W component of the quaternion (real part).</param>
|
||||
public Quat(real_t x, real_t y, real_t z, real_t w)
|
||||
{
|
||||
this.x = x;
|
||||
|
@ -209,21 +339,31 @@ namespace Godot
|
|||
this.w = w;
|
||||
}
|
||||
|
||||
public bool IsNormalized()
|
||||
{
|
||||
return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a quaternion from the given quaternion.
|
||||
/// </summary>
|
||||
/// <param name="q">The existing quaternion.</param>
|
||||
public Quat(Quat q)
|
||||
{
|
||||
this = q;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a quaternion from the given <see cref="Basis"/>.
|
||||
/// </summary>
|
||||
/// <param name="basis">The basis to construct from.</param>
|
||||
public Quat(Basis basis)
|
||||
{
|
||||
this = basis.Quat();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a quaternion that will perform a rotation specified by
|
||||
/// Euler angles (in the YXZ convention: when decomposing,
|
||||
/// first Z, then X, and Y last),
|
||||
/// given in the vector format as (X angle, Y angle, Z angle).
|
||||
/// </summary>
|
||||
/// <param name="eulerYXZ"></param>
|
||||
public Quat(Vector3 eulerYXZ)
|
||||
{
|
||||
real_t half_a1 = eulerYXZ.y * 0.5f;
|
||||
|
@ -247,11 +387,19 @@ namespace Godot
|
|||
w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a quaternion that will rotate around the given axis
|
||||
/// by the specified angle. The axis must be a normalized vector.
|
||||
/// </summary>
|
||||
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
|
||||
/// <param name="angle">The angle to rotate, in radians.</param>
|
||||
public Quat(Vector3 axis, real_t angle)
|
||||
{
|
||||
#if DEBUG
|
||||
if (!axis.IsNormalized())
|
||||
{
|
||||
throw new ArgumentException("Argument is not normalized", nameof(axis));
|
||||
}
|
||||
#endif
|
||||
|
||||
real_t d = axis.Length();
|
||||
|
@ -364,6 +512,12 @@ namespace Godot
|
|||
return x == other.x && y == other.y && z == other.z && w == other.w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this quaternion and `other` are approximately equal, by running
|
||||
/// <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
|
||||
/// </summary>
|
||||
/// <param name="other">The other quaternion to compare.</param>
|
||||
/// <returns>Whether or not the quaternions are approximately equal.</returns>
|
||||
public bool IsEqualApprox(Quat other)
|
||||
{
|
||||
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
|
||||
|
|
|
@ -8,6 +8,10 @@ using real_t = System.Single;
|
|||
|
||||
namespace Godot
|
||||
{
|
||||
/// <summary>
|
||||
/// 2D axis-aligned bounding box. Rect2 consists of a position, a size, and
|
||||
/// several utility functions. It is typically used for fast overlap tests.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Rect2 : IEquatable<Rect2>
|
||||
|
@ -15,29 +19,52 @@ namespace Godot
|
|||
private Vector2 _position;
|
||||
private Vector2 _size;
|
||||
|
||||
/// <summary>
|
||||
/// Beginning corner. Typically has values lower than End.
|
||||
/// </summary>
|
||||
/// <value>Directly uses a private field.</value>
|
||||
public Vector2 Position
|
||||
{
|
||||
get { return _position; }
|
||||
set { _position = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Size from Position to End. Typically all components are positive.
|
||||
/// If the size is negative, you can use <see cref="Abs"/> to fix it.
|
||||
/// </summary>
|
||||
/// <value>Directly uses a private field.</value>
|
||||
public Vector2 Size
|
||||
{
|
||||
get { return _size; }
|
||||
set { _size = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ending corner. This is calculated as <see cref="Position"/> plus
|
||||
/// <see cref="Size"/>. Setting this value will change the size.
|
||||
/// </summary>
|
||||
/// <value>Getting is equivalent to `value = Position + Size`, setting is equivalent to `Size = value - Position`.</value>
|
||||
public Vector2 End
|
||||
{
|
||||
get { return _position + _size; }
|
||||
set { _size = value - _position; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The area of this rect.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="GetArea()"/>.</value>
|
||||
public real_t Area
|
||||
{
|
||||
get { return GetArea(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Rect2 with equivalent position and size, modified so that
|
||||
/// the top-left corner is the origin and width and height are positive.
|
||||
/// </summary>
|
||||
/// <returns>The modified rect.</returns>
|
||||
public Rect2 Abs()
|
||||
{
|
||||
Vector2 end = End;
|
||||
|
@ -45,12 +72,19 @@ namespace Godot
|
|||
return new Rect2(topLeft, _size.Abs());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the intersection of this Rect2 and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other rect.</param>
|
||||
/// <returns>The clipped rect.</returns>
|
||||
public Rect2 Clip(Rect2 b)
|
||||
{
|
||||
var newRect = b;
|
||||
|
||||
if (!Intersects(newRect))
|
||||
{
|
||||
return new Rect2();
|
||||
}
|
||||
|
||||
newRect._position.x = Mathf.Max(b._position.x, _position.x);
|
||||
newRect._position.y = Mathf.Max(b._position.y, _position.y);
|
||||
|
@ -64,6 +98,11 @@ namespace Godot
|
|||
return newRect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this Rect2 completely encloses another one.
|
||||
/// </summary>
|
||||
/// <param name="b">The other rect that may be enclosed.</param>
|
||||
/// <returns>A bool for whether or not this rect encloses `b`.</returns>
|
||||
public bool Encloses(Rect2 b)
|
||||
{
|
||||
return b._position.x >= _position.x && b._position.y >= _position.y &&
|
||||
|
@ -71,6 +110,11 @@ namespace Godot
|
|||
b._position.y + b._size.y < _position.y + _size.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this Rect2 expanded to include a given point.
|
||||
/// </summary>
|
||||
/// <param name="to">The point to include.</param>
|
||||
/// <returns>The expanded rect.</returns>
|
||||
public Rect2 Expand(Vector2 to)
|
||||
{
|
||||
var expanded = this;
|
||||
|
@ -79,14 +123,22 @@ namespace Godot
|
|||
Vector2 end = expanded._position + expanded._size;
|
||||
|
||||
if (to.x < begin.x)
|
||||
{
|
||||
begin.x = to.x;
|
||||
}
|
||||
if (to.y < begin.y)
|
||||
{
|
||||
begin.y = to.y;
|
||||
}
|
||||
|
||||
if (to.x > end.x)
|
||||
{
|
||||
end.x = to.x;
|
||||
}
|
||||
if (to.y > end.y)
|
||||
{
|
||||
end.y = to.y;
|
||||
}
|
||||
|
||||
expanded._position = begin;
|
||||
expanded._size = end - begin;
|
||||
|
@ -94,11 +146,20 @@ namespace Godot
|
|||
return expanded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the area of the Rect2.
|
||||
/// </summary>
|
||||
/// <returns>The area.</returns>
|
||||
public real_t GetArea()
|
||||
{
|
||||
return _size.x * _size.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the Rect2 grown a given amount of units towards all the sides.
|
||||
/// </summary>
|
||||
/// <param name="by">The amount to grow by.</param>
|
||||
/// <returns>The grown rect.</returns>
|
||||
public Rect2 Grow(real_t by)
|
||||
{
|
||||
var g = this;
|
||||
|
@ -111,6 +172,14 @@ namespace Godot
|
|||
return g;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the Rect2 grown a given amount of units towards each direction individually.
|
||||
/// </summary>
|
||||
/// <param name="left">The amount to grow by on the left.</param>
|
||||
/// <param name="top">The amount to grow by on the top.</param>
|
||||
/// <param name="right">The amount to grow by on the right.</param>
|
||||
/// <param name="bottom">The amount to grow by on the bottom.</param>
|
||||
/// <returns>The grown rect.</returns>
|
||||
public Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom)
|
||||
{
|
||||
var g = this;
|
||||
|
@ -123,6 +192,12 @@ namespace Godot
|
|||
return g;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the Rect2 grown a given amount of units towards the <see cref="Margin"/> direction.
|
||||
/// </summary>
|
||||
/// <param name="margin">The direction to grow in.</param>
|
||||
/// <param name="by">The amount to grow by.</param>
|
||||
/// <returns>The grown rect.</returns>
|
||||
public Rect2 GrowMargin(Margin margin, real_t by)
|
||||
{
|
||||
var g = this;
|
||||
|
@ -135,11 +210,20 @@ namespace Godot
|
|||
return g;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the Rect2 is flat or empty, or false otherwise.
|
||||
/// </summary>
|
||||
/// <returns>A bool for whether or not the rect has area.</returns>
|
||||
public bool HasNoArea()
|
||||
{
|
||||
return _size.x <= 0 || _size.y <= 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the Rect2 contains a point, or false otherwise.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to check.</param>
|
||||
/// <returns>A bool for whether or not the rect contains `point`.</returns>
|
||||
public bool HasPoint(Vector2 point)
|
||||
{
|
||||
if (point.x < _position.x)
|
||||
|
@ -155,20 +239,65 @@ namespace Godot
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool Intersects(Rect2 b)
|
||||
/// <summary>
|
||||
/// Returns true if the Rect2 overlaps with `b`
|
||||
/// (i.e. they have at least one point in common).
|
||||
///
|
||||
/// If `includeBorders` is true, they will also be considered overlapping
|
||||
/// if their borders touch, even without intersection.
|
||||
/// </summary>
|
||||
/// <param name="b">The other rect to check for intersections with.</param>
|
||||
/// <param name="includeBorders">Whether or not to consider borders.</param>
|
||||
/// <returns>A bool for whether or not they are intersecting.</returns>
|
||||
public bool Intersects(Rect2 b, bool includeBorders = false)
|
||||
{
|
||||
if (_position.x >= b._position.x + b._size.x)
|
||||
return false;
|
||||
if (_position.x + _size.x <= b._position.x)
|
||||
return false;
|
||||
if (_position.y >= b._position.y + b._size.y)
|
||||
return false;
|
||||
if (_position.y + _size.y <= b._position.y)
|
||||
return false;
|
||||
if (includeBorders)
|
||||
{
|
||||
if (_position.x > b._position.x + b._size.x)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_position.x + _size.x < b._position.x)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_position.y > b._position.y + b._size.y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_position.y + _size.y < b._position.y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_position.x >= b._position.x + b._size.x)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_position.x + _size.x <= b._position.x)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_position.y >= b._position.y + b._size.y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_position.y + _size.y <= b._position.y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a larger Rect2 that contains this Rect2 and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other rect.</param>
|
||||
/// <returns>The merged rect.</returns>
|
||||
public Rect2 Merge(Rect2 b)
|
||||
{
|
||||
Rect2 newRect;
|
||||
|
@ -179,27 +308,53 @@ namespace Godot
|
|||
newRect._size.x = Mathf.Max(b._position.x + b._size.x, _position.x + _size.x);
|
||||
newRect._size.y = Mathf.Max(b._position.y + b._size.y, _position.y + _size.y);
|
||||
|
||||
newRect._size = newRect._size - newRect._position; // Make relative again
|
||||
newRect._size -= newRect._position; // Make relative again
|
||||
|
||||
return newRect;
|
||||
}
|
||||
|
||||
// Constructors
|
||||
/// <summary>
|
||||
/// Constructs a Rect2 from a position and size.
|
||||
/// </summary>
|
||||
/// <param name="position">The position.</param>
|
||||
/// <param name="size">The size.</param>
|
||||
public Rect2(Vector2 position, Vector2 size)
|
||||
{
|
||||
_position = position;
|
||||
_size = size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a Rect2 from a position, width, and height.
|
||||
/// </summary>
|
||||
/// <param name="position">The position.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
public Rect2(Vector2 position, real_t width, real_t height)
|
||||
{
|
||||
_position = position;
|
||||
_size = new Vector2(width, height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a Rect2 from x, y, and size.
|
||||
/// </summary>
|
||||
/// <param name="x">The position's X coordinate.</param>
|
||||
/// <param name="y">The position's Y coordinate.</param>
|
||||
/// <param name="size">The size.</param>
|
||||
public Rect2(real_t x, real_t y, Vector2 size)
|
||||
{
|
||||
_position = new Vector2(x, y);
|
||||
_size = size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a Rect2 from x, y, width, and height.
|
||||
/// </summary>
|
||||
/// <param name="x">The position's X coordinate.</param>
|
||||
/// <param name="y">The position's Y coordinate.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
public Rect2(real_t x, real_t y, real_t width, real_t height)
|
||||
{
|
||||
_position = new Vector2(x, y);
|
||||
|
@ -231,6 +386,12 @@ namespace Godot
|
|||
return _position.Equals(other._position) && _size.Equals(other._size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this rect and `other` are approximately equal, by running
|
||||
/// <see cref="Vector2.IsEqualApprox(Vector2)"/> on each component.
|
||||
/// </summary>
|
||||
/// <param name="other">The other rect to compare.</param>
|
||||
/// <returns>Whether or not the rects are approximately equal.</returns>
|
||||
public bool IsEqualApprox(Rect2 other)
|
||||
{
|
||||
return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other.Size);
|
||||
|
|
|
@ -3,6 +3,10 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace Godot
|
||||
{
|
||||
/// <summary>
|
||||
/// 2D axis-aligned bounding box using integers. Rect2i consists of a position, a size, and
|
||||
/// several utility functions. It is typically used for fast overlap tests.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Rect2i : IEquatable<Rect2i>
|
||||
|
@ -10,29 +14,52 @@ namespace Godot
|
|||
private Vector2i _position;
|
||||
private Vector2i _size;
|
||||
|
||||
/// <summary>
|
||||
/// Beginning corner. Typically has values lower than End.
|
||||
/// </summary>
|
||||
/// <value>Directly uses a private field.</value>
|
||||
public Vector2i Position
|
||||
{
|
||||
get { return _position; }
|
||||
set { _position = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Size from Position to End. Typically all components are positive.
|
||||
/// If the size is negative, you can use <see cref="Abs"/> to fix it.
|
||||
/// </summary>
|
||||
/// <value>Directly uses a private field.</value>
|
||||
public Vector2i Size
|
||||
{
|
||||
get { return _size; }
|
||||
set { _size = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ending corner. This is calculated as <see cref="Position"/> plus
|
||||
/// <see cref="Size"/>. Setting this value will change the size.
|
||||
/// </summary>
|
||||
/// <value>Getting is equivalent to `value = Position + Size`, setting is equivalent to `Size = value - Position`.</value>
|
||||
public Vector2i End
|
||||
{
|
||||
get { return _position + _size; }
|
||||
set { _size = value - _position; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The area of this rect.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to <see cref="GetArea()"/>.</value>
|
||||
public int Area
|
||||
{
|
||||
get { return GetArea(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Rect2i with equivalent position and size, modified so that
|
||||
/// the top-left corner is the origin and width and height are positive.
|
||||
/// </summary>
|
||||
/// <returns>The modified rect.</returns>
|
||||
public Rect2i Abs()
|
||||
{
|
||||
Vector2i end = End;
|
||||
|
@ -40,12 +67,19 @@ namespace Godot
|
|||
return new Rect2i(topLeft, _size.Abs());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the intersection of this Rect2i and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other rect.</param>
|
||||
/// <returns>The clipped rect.</returns>
|
||||
public Rect2i Clip(Rect2i b)
|
||||
{
|
||||
var newRect = b;
|
||||
|
||||
if (!Intersects(newRect))
|
||||
{
|
||||
return new Rect2i();
|
||||
}
|
||||
|
||||
newRect._position.x = Mathf.Max(b._position.x, _position.x);
|
||||
newRect._position.y = Mathf.Max(b._position.y, _position.y);
|
||||
|
@ -59,6 +93,11 @@ namespace Godot
|
|||
return newRect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this Rect2i completely encloses another one.
|
||||
/// </summary>
|
||||
/// <param name="b">The other rect that may be enclosed.</param>
|
||||
/// <returns>A bool for whether or not this rect encloses `b`.</returns>
|
||||
public bool Encloses(Rect2i b)
|
||||
{
|
||||
return b._position.x >= _position.x && b._position.y >= _position.y &&
|
||||
|
@ -66,6 +105,11 @@ namespace Godot
|
|||
b._position.y + b._size.y < _position.y + _size.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this Rect2i expanded to include a given point.
|
||||
/// </summary>
|
||||
/// <param name="to">The point to include.</param>
|
||||
/// <returns>The expanded rect.</returns>
|
||||
public Rect2i Expand(Vector2i to)
|
||||
{
|
||||
var expanded = this;
|
||||
|
@ -74,14 +118,22 @@ namespace Godot
|
|||
Vector2i end = expanded._position + expanded._size;
|
||||
|
||||
if (to.x < begin.x)
|
||||
{
|
||||
begin.x = to.x;
|
||||
}
|
||||
if (to.y < begin.y)
|
||||
{
|
||||
begin.y = to.y;
|
||||
}
|
||||
|
||||
if (to.x > end.x)
|
||||
{
|
||||
end.x = to.x;
|
||||
}
|
||||
if (to.y > end.y)
|
||||
{
|
||||
end.y = to.y;
|
||||
}
|
||||
|
||||
expanded._position = begin;
|
||||
expanded._size = end - begin;
|
||||
|
@ -89,11 +141,20 @@ namespace Godot
|
|||
return expanded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the area of the Rect2.
|
||||
/// </summary>
|
||||
/// <returns>The area.</returns>
|
||||
public int GetArea()
|
||||
{
|
||||
return _size.x * _size.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the Rect2i grown a given amount of units towards all the sides.
|
||||
/// </summary>
|
||||
/// <param name="by">The amount to grow by.</param>
|
||||
/// <returns>The grown rect.</returns>
|
||||
public Rect2i Grow(int by)
|
||||
{
|
||||
var g = this;
|
||||
|
@ -106,6 +167,14 @@ namespace Godot
|
|||
return g;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the Rect2i grown a given amount of units towards each direction individually.
|
||||
/// </summary>
|
||||
/// <param name="left">The amount to grow by on the left.</param>
|
||||
/// <param name="top">The amount to grow by on the top.</param>
|
||||
/// <param name="right">The amount to grow by on the right.</param>
|
||||
/// <param name="bottom">The amount to grow by on the bottom.</param>
|
||||
/// <returns>The grown rect.</returns>
|
||||
public Rect2i GrowIndividual(int left, int top, int right, int bottom)
|
||||
{
|
||||
var g = this;
|
||||
|
@ -118,6 +187,12 @@ namespace Godot
|
|||
return g;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the Rect2i grown a given amount of units towards the <see cref="Margin"/> direction.
|
||||
/// </summary>
|
||||
/// <param name="margin">The direction to grow in.</param>
|
||||
/// <param name="by">The amount to grow by.</param>
|
||||
/// <returns>The grown rect.</returns>
|
||||
public Rect2i GrowMargin(Margin margin, int by)
|
||||
{
|
||||
var g = this;
|
||||
|
@ -130,11 +205,20 @@ namespace Godot
|
|||
return g;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the Rect2 is flat or empty, or false otherwise.
|
||||
/// </summary>
|
||||
/// <returns>A bool for whether or not the rect has area.</returns>
|
||||
public bool HasNoArea()
|
||||
{
|
||||
return _size.x <= 0 || _size.y <= 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the Rect2 contains a point, or false otherwise.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to check.</param>
|
||||
/// <returns>A bool for whether or not the rect contains `point`.</returns>
|
||||
public bool HasPoint(Vector2i point)
|
||||
{
|
||||
if (point.x < _position.x)
|
||||
|
@ -150,20 +234,49 @@ namespace Godot
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool Intersects(Rect2i b)
|
||||
/// <summary>
|
||||
/// Returns true if the Rect2i overlaps with `b`
|
||||
/// (i.e. they have at least one point in common).
|
||||
///
|
||||
/// If `includeBorders` is true, they will also be considered overlapping
|
||||
/// if their borders touch, even without intersection.
|
||||
/// </summary>
|
||||
/// <param name="b">The other rect to check for intersections with.</param>
|
||||
/// <param name="includeBorders">Whether or not to consider borders.</param>
|
||||
/// <returns>A bool for whether or not they are intersecting.</returns>
|
||||
public bool Intersects(Rect2i b, bool includeBorders = false)
|
||||
{
|
||||
if (_position.x >= b._position.x + b._size.x)
|
||||
return false;
|
||||
if (_position.x + _size.x <= b._position.x)
|
||||
return false;
|
||||
if (_position.y >= b._position.y + b._size.y)
|
||||
return false;
|
||||
if (_position.y + _size.y <= b._position.y)
|
||||
return false;
|
||||
if (includeBorders)
|
||||
{
|
||||
if (_position.x > b._position.x + b._size.x)
|
||||
return false;
|
||||
if (_position.x + _size.x < b._position.x)
|
||||
return false;
|
||||
if (_position.y > b._position.y + b._size.y)
|
||||
return false;
|
||||
if (_position.y + _size.y < b._position.y)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_position.x >= b._position.x + b._size.x)
|
||||
return false;
|
||||
if (_position.x + _size.x <= b._position.x)
|
||||
return false;
|
||||
if (_position.y >= b._position.y + b._size.y)
|
||||
return false;
|
||||
if (_position.y + _size.y <= b._position.y)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a larger Rect2i that contains this Rect2 and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other rect.</param>
|
||||
/// <returns>The merged rect.</returns>
|
||||
public Rect2i Merge(Rect2i b)
|
||||
{
|
||||
Rect2i newRect;
|
||||
|
@ -174,27 +287,53 @@ namespace Godot
|
|||
newRect._size.x = Mathf.Max(b._position.x + b._size.x, _position.x + _size.x);
|
||||
newRect._size.y = Mathf.Max(b._position.y + b._size.y, _position.y + _size.y);
|
||||
|
||||
newRect._size = newRect._size - newRect._position; // Make relative again
|
||||
newRect._size -= newRect._position; // Make relative again
|
||||
|
||||
return newRect;
|
||||
}
|
||||
|
||||
// Constructors
|
||||
/// <summary>
|
||||
/// Constructs a Rect2i from a position and size.
|
||||
/// </summary>
|
||||
/// <param name="position">The position.</param>
|
||||
/// <param name="size">The size.</param>
|
||||
public Rect2i(Vector2i position, Vector2i size)
|
||||
{
|
||||
_position = position;
|
||||
_size = size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a Rect2i from a position, width, and height.
|
||||
/// </summary>
|
||||
/// <param name="position">The position.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
public Rect2i(Vector2i position, int width, int height)
|
||||
{
|
||||
_position = position;
|
||||
_size = new Vector2i(width, height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a Rect2i from x, y, and size.
|
||||
/// </summary>
|
||||
/// <param name="x">The position's X coordinate.</param>
|
||||
/// <param name="y">The position's Y coordinate.</param>
|
||||
/// <param name="size">The size.</param>
|
||||
public Rect2i(int x, int y, Vector2i size)
|
||||
{
|
||||
_position = new Vector2i(x, y);
|
||||
_size = size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a Rect2i from x, y, width, and height.
|
||||
/// </summary>
|
||||
/// <param name="x">The position's X coordinate.</param>
|
||||
/// <param name="y">The position's Y coordinate.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
public Rect2i(int x, int y, int width, int height)
|
||||
{
|
||||
_position = new Vector2i(x, y);
|
||||
|
|
|
@ -8,11 +8,28 @@ using real_t = System.Single;
|
|||
|
||||
namespace Godot
|
||||
{
|
||||
/// <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>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Transform : IEquatable<Transform>
|
||||
{
|
||||
/// <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>
|
||||
public Basis basis;
|
||||
|
||||
/// <summary>
|
||||
/// The origin vector (column 3, the fourth column). Equivalent to array index `[3]`.
|
||||
/// </summary>
|
||||
public Vector3 origin;
|
||||
|
||||
/// <summary>
|
||||
|
@ -85,13 +102,24 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform AffineInverse()
|
||||
{
|
||||
Basis basisInv = basis.Inverse();
|
||||
return new Transform(basisInv, basisInv.Xform(-origin));
|
||||
}
|
||||
|
||||
public Transform InterpolateWith(Transform transform, real_t c)
|
||||
/// <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>
|
||||
public Transform InterpolateWith(Transform transform, real_t weight)
|
||||
{
|
||||
/* not sure if very "efficient" but good enough? */
|
||||
|
||||
|
@ -104,18 +132,37 @@ namespace Godot
|
|||
Vector3 destinationLocation = transform.origin;
|
||||
|
||||
var interpolated = new Transform();
|
||||
interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, c).Normalized(), sourceScale.Lerp(destinationScale, c));
|
||||
interpolated.origin = sourceLocation.Lerp(destinationLocation, c);
|
||||
interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, weight).Normalized(), sourceScale.Lerp(destinationScale, weight));
|
||||
interpolated.origin = sourceLocation.Lerp(destinationLocation, weight);
|
||||
|
||||
return interpolated;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform Inverse()
|
||||
{
|
||||
Basis basisTr = basis.Transposed();
|
||||
return new Transform(basisTr, basisTr.Xform(-origin));
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform LookingAt(Vector3 target, Vector3 up)
|
||||
{
|
||||
var t = this;
|
||||
|
@ -123,22 +170,39 @@ namespace Godot
|
|||
return t;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform Orthonormalized()
|
||||
{
|
||||
return new Transform(basis.Orthonormalized(), origin);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform Rotated(Vector3 axis, real_t phi)
|
||||
{
|
||||
return new Transform(new Basis(axis, phi), new Vector3()) * this;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform Scaled(Vector3 scale)
|
||||
{
|
||||
return new Transform(basis.Scaled(scale), origin * scale);
|
||||
}
|
||||
|
||||
public void SetLookAt(Vector3 eye, Vector3 target, Vector3 up)
|
||||
private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up)
|
||||
{
|
||||
// Make rotation matrix
|
||||
// Z vector
|
||||
|
@ -161,16 +225,30 @@ namespace Godot
|
|||
origin = eye;
|
||||
}
|
||||
|
||||
public Transform Translated(Vector3 ofs)
|
||||
/// <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>
|
||||
public Transform Translated(Vector3 offset)
|
||||
{
|
||||
return new Transform(basis, new Vector3
|
||||
(
|
||||
origin[0] += basis.Row0.Dot(ofs),
|
||||
origin[1] += basis.Row1.Dot(ofs),
|
||||
origin[2] += basis.Row2.Dot(ofs)
|
||||
origin[0] += basis.Row0.Dot(offset),
|
||||
origin[1] += basis.Row1.Dot(offset),
|
||||
origin[2] += basis.Row2.Dot(offset)
|
||||
));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector transformed (multiplied) by this transformation matrix.
|
||||
/// </summary>
|
||||
/// <param name="v">A vector to transform.</param>
|
||||
/// <returns>The transfomed vector.</returns>
|
||||
public Vector3 Xform(Vector3 v)
|
||||
{
|
||||
return new Vector3
|
||||
|
@ -181,6 +259,14 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <returns>The inversely transfomed vector.</returns>
|
||||
public Vector3 XformInv(Vector3 v)
|
||||
{
|
||||
Vector3 vInv = v - origin;
|
||||
|
@ -199,24 +285,58 @@ namespace Godot
|
|||
private static readonly Transform _flipY = new Transform(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero);
|
||||
private static readonly Transform _flipZ = new Transform(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero);
|
||||
|
||||
/// <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>
|
||||
public static Transform Identity { get { return _identity; } }
|
||||
/// <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>
|
||||
public static Transform FlipX { get { return _flipX; } }
|
||||
/// <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>
|
||||
public static Transform FlipY { get { return _flipY; } }
|
||||
/// <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>
|
||||
public static Transform FlipZ { get { return _flipZ; } }
|
||||
|
||||
// Constructors
|
||||
/// <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>
|
||||
public Transform(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin)
|
||||
{
|
||||
basis = new Basis(column0, column1, column2);
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a transformation matrix from the given quaternion and origin vector.
|
||||
/// </summary>
|
||||
/// <param name="quat">The <see cref="Godot.Quat"/> to create the basis from.</param>
|
||||
/// <param name="origin">The origin vector, or column index 3.</param>
|
||||
public Transform(Quat quat, Vector3 origin)
|
||||
{
|
||||
basis = new Basis(quat);
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform(Basis basis, Vector3 origin)
|
||||
{
|
||||
this.basis = basis;
|
||||
|
@ -255,6 +375,12 @@ namespace Godot
|
|||
return basis.Equals(other.basis) && origin.Equals(other.origin);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public bool IsEqualApprox(Transform other)
|
||||
{
|
||||
return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin);
|
||||
|
|
|
@ -8,25 +8,44 @@ using real_t = System.Single;
|
|||
|
||||
namespace Godot
|
||||
{
|
||||
/// <summary>
|
||||
/// 2×3 matrix (2 rows, 3 columns) used for 2D linear transformations.
|
||||
/// It can represent transformations such as translation, rotation, or scaling.
|
||||
/// It consists of a three <see cref="Vector2"/> values: x, y, and the origin.
|
||||
///
|
||||
/// For more information, read this documentation article:
|
||||
/// https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Transform2D : IEquatable<Transform2D>
|
||||
{
|
||||
/// <summary>
|
||||
/// The basis matrix's X vector (column 0). Equivalent to array index `[0]`.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public Vector2 x;
|
||||
|
||||
/// <summary>
|
||||
/// The basis matrix's Y vector (column 1). Equivalent to array index `[1]`.
|
||||
/// </summary>
|
||||
public Vector2 y;
|
||||
|
||||
/// <summary>
|
||||
/// The origin vector (column 2, the third column). Equivalent to array index `[2]`.
|
||||
/// The origin vector represents translation.
|
||||
/// </summary>
|
||||
public Vector2 origin;
|
||||
|
||||
/// <summary>
|
||||
/// The rotation of this transformation matrix.
|
||||
/// </summary>
|
||||
/// <value>Getting is equivalent to calling <see cref="Mathf.Atan2(real_t, real_t)"/> with the values of <see cref="x"/>.</value>
|
||||
public real_t Rotation
|
||||
{
|
||||
get
|
||||
{
|
||||
real_t det = BasisDeterminant();
|
||||
Transform2D t = Orthonormalized();
|
||||
if (det < 0)
|
||||
{
|
||||
t.ScaleBasis(new Vector2(1, -1));
|
||||
}
|
||||
return Mathf.Atan2(t.x.y, t.x.x);
|
||||
return Mathf.Atan2(x.y, x.x);
|
||||
}
|
||||
set
|
||||
{
|
||||
|
@ -38,6 +57,10 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The scale of this transformation matrix.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to the lengths of each column vector, but Y is negative if the determinant is negative.</value>
|
||||
public Vector2 Scale
|
||||
{
|
||||
get
|
||||
|
@ -47,8 +70,7 @@ namespace Godot
|
|||
}
|
||||
set
|
||||
{
|
||||
x = x.Normalized();
|
||||
y = y.Normalized();
|
||||
value /= Scale; // Value becomes what's called "delta_scale" in core.
|
||||
x *= value.x;
|
||||
y *= value.y;
|
||||
}
|
||||
|
@ -112,6 +134,11 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform2D AffineInverse()
|
||||
{
|
||||
real_t det = BasisDeterminant();
|
||||
|
@ -135,28 +162,58 @@ namespace Godot
|
|||
return inv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the determinant of the basis matrix. If the basis is
|
||||
/// uniformly scaled, its determinant is the square of the scale.
|
||||
///
|
||||
/// A negative determinant means the Y scale is negative.
|
||||
/// A zero determinant means the basis isn't invertible,
|
||||
/// and is usually considered invalid.
|
||||
/// </summary>
|
||||
/// <returns>The determinant of the basis matrix.</returns>
|
||||
private real_t BasisDeterminant()
|
||||
{
|
||||
return x.x * y.y - x.y * y.x;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector transformed (multiplied) by the basis matrix.
|
||||
/// This method does not account for translation (the origin vector).
|
||||
/// </summary>
|
||||
/// <param name="v">A vector to transform.</param>
|
||||
/// <returns>The transfomed vector.</returns>
|
||||
public Vector2 BasisXform(Vector2 v)
|
||||
{
|
||||
return new Vector2(Tdotx(v), Tdoty(v));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector transformed (multiplied) by the inverse basis matrix.
|
||||
/// This method does not account for translation (the origin vector).
|
||||
///
|
||||
/// Note: This results in a multiplication by the inverse of the
|
||||
/// basis matrix only if it represents a rotation-reflection.
|
||||
/// </summary>
|
||||
/// <param name="v">A vector to inversely transform.</param>
|
||||
/// <returns>The inversely transfomed vector.</returns>
|
||||
public Vector2 BasisXformInv(Vector2 v)
|
||||
{
|
||||
return new Vector2(x.Dot(v), y.Dot(v));
|
||||
}
|
||||
|
||||
public Transform2D InterpolateWith(Transform2D m, real_t c)
|
||||
/// <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>
|
||||
public Transform2D InterpolateWith(Transform2D transform, real_t weight)
|
||||
{
|
||||
real_t r1 = Rotation;
|
||||
real_t r2 = m.Rotation;
|
||||
real_t r2 = transform.Rotation;
|
||||
|
||||
Vector2 s1 = Scale;
|
||||
Vector2 s2 = m.Scale;
|
||||
Vector2 s2 = transform.Scale;
|
||||
|
||||
// Slerp rotation
|
||||
var v1 = new Vector2(Mathf.Cos(r1), Mathf.Sin(r1));
|
||||
|
@ -172,28 +229,34 @@ namespace Godot
|
|||
if (dot > 0.9995f)
|
||||
{
|
||||
// Linearly interpolate to avoid numerical precision issues
|
||||
v = v1.Lerp(v2, c).Normalized();
|
||||
v = v1.Lerp(v2, weight).Normalized();
|
||||
}
|
||||
else
|
||||
{
|
||||
real_t angle = c * Mathf.Acos(dot);
|
||||
real_t angle = weight * 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;
|
||||
Vector2 p2 = transform.origin;
|
||||
|
||||
// Construct matrix
|
||||
var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.Lerp(p2, c));
|
||||
Vector2 scale = s1.Lerp(s2, c);
|
||||
var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.Lerp(p2, weight));
|
||||
Vector2 scale = s1.Lerp(s2, weight);
|
||||
res.x *= scale;
|
||||
res.y *= scale;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform2D Inverse()
|
||||
{
|
||||
var inv = this;
|
||||
|
@ -208,6 +271,11 @@ namespace Godot
|
|||
return inv;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform2D Orthonormalized()
|
||||
{
|
||||
var on = this;
|
||||
|
@ -225,11 +293,21 @@ namespace Godot
|
|||
return on;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the transform by `phi` (in radians), using matrix multiplication.
|
||||
/// </summary>
|
||||
/// <param name="phi">The angle to rotate, in radians.</param>
|
||||
/// <returns>The rotated transformation matrix.</returns>
|
||||
public Transform2D Rotated(real_t phi)
|
||||
{
|
||||
return this * new Transform2D(phi, new Vector2());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the transform by the given scaling factor, using matrix multiplication.
|
||||
/// </summary>
|
||||
/// <param name="scale">The scale to introduce.</param>
|
||||
/// <returns>The scaled transformation matrix.</returns>
|
||||
public Transform2D Scaled(Vector2 scale)
|
||||
{
|
||||
var copy = this;
|
||||
|
@ -257,6 +335,15 @@ namespace Godot
|
|||
return this[0, 1] * with[0] + this[1, 1] * with[1];
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Transform2D Translated(Vector2 offset)
|
||||
{
|
||||
var copy = this;
|
||||
|
@ -264,11 +351,21 @@ namespace Godot
|
|||
return copy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector transformed (multiplied) by this transformation matrix.
|
||||
/// </summary>
|
||||
/// <param name="v">A vector to transform.</param>
|
||||
/// <returns>The transfomed vector.</returns>
|
||||
public Vector2 Xform(Vector2 v)
|
||||
{
|
||||
return new Vector2(Tdotx(v), Tdoty(v)) + origin;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector transformed (multiplied) by the inverse transformation matrix.
|
||||
/// </summary>
|
||||
/// <param name="v">A vector to inversely transform.</param>
|
||||
/// <returns>The inversely transfomed vector.</returns>
|
||||
public Vector2 XformInv(Vector2 v)
|
||||
{
|
||||
Vector2 vInv = v - origin;
|
||||
|
@ -280,11 +377,30 @@ namespace Godot
|
|||
private static readonly Transform2D _flipX = new Transform2D(-1, 0, 0, 1, 0, 0);
|
||||
private static readonly Transform2D _flipY = new Transform2D(1, 0, 0, -1, 0, 0);
|
||||
|
||||
public static Transform2D Identity => _identity;
|
||||
public static Transform2D FlipX => _flipX;
|
||||
public static Transform2D FlipY => _flipY;
|
||||
/// <summary>
|
||||
/// The identity transform, with no translation, rotation, or scaling applied.
|
||||
/// This is used as a replacement for `Transform2D()` in GDScript.
|
||||
/// Do not use `new Transform2D()` with no arguments in C#, because it sets all values to zero.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Transform2D(Vector2.Right, Vector2.Down, Vector2.Zero)`.</value>
|
||||
public static Transform2D Identity { get { return _identity; } }
|
||||
/// <summary>
|
||||
/// The transform that will flip something along the X axis.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Transform2D(Vector2.Left, Vector2.Down, Vector2.Zero)`.</value>
|
||||
public static Transform2D FlipX { get { return _flipX; } }
|
||||
/// <summary>
|
||||
/// The transform that will flip something along the Y axis.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Transform2D(Vector2.Right, Vector2.Up, Vector2.Zero)`.</value>
|
||||
public static Transform2D FlipY { get { return _flipY; } }
|
||||
|
||||
// Constructors
|
||||
/// <summary>
|
||||
/// Constructs a transformation matrix from 3 vectors (matrix columns).
|
||||
/// </summary>
|
||||
/// <param name="xAxis">The X vector, or column index 0.</param>
|
||||
/// <param name="yAxis">The Y vector, or column index 1.</param>
|
||||
/// <param name="originPos">The origin vector, or column index 2.</param>
|
||||
public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 originPos)
|
||||
{
|
||||
x = xAxis;
|
||||
|
@ -292,7 +408,16 @@ namespace Godot
|
|||
origin = originPos;
|
||||
}
|
||||
|
||||
// Arguments are named such that xy is equal to calling x.y
|
||||
/// <summary>
|
||||
/// Constructs a transformation matrix from the given components.
|
||||
/// Arguments are named such that xy is equal to calling x.y
|
||||
/// </summary>
|
||||
/// <param name="xx">The X component of the X column vector, accessed via `t.x.x` or `[0][0]`</param>
|
||||
/// <param name="xy">The Y component of the X column vector, accessed via `t.x.y` or `[0][1]`</param>
|
||||
/// <param name="yx">The X component of the Y column vector, accessed via `t.y.x` or `[1][0]`</param>
|
||||
/// <param name="yy">The Y component of the Y column vector, accessed via `t.y.y` or `[1][1]`</param>
|
||||
/// <param name="ox">The X component of the origin vector, accessed via `t.origin.x` or `[2][0]`</param>
|
||||
/// <param name="oy">The Y component of the origin vector, accessed via `t.origin.y` or `[2][1]`</param>
|
||||
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);
|
||||
|
@ -300,6 +425,11 @@ namespace Godot
|
|||
origin = new Vector2(ox, oy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a transformation matrix from a rotation value and origin vector.
|
||||
/// </summary>
|
||||
/// <param name="rot">The rotation of the new transform, in radians.</param>
|
||||
/// <param name="pos">The origin vector, or column index 2.</param>
|
||||
public Transform2D(real_t rot, Vector2 pos)
|
||||
{
|
||||
x.x = y.y = Mathf.Cos(rot);
|
||||
|
@ -345,6 +475,12 @@ namespace Godot
|
|||
return x.Equals(other.x) && y.Equals(other.y) && origin.Equals(other.origin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this transform and `other` are approximately equal, by running
|
||||
/// <see cref="Vector2.IsEqualApprox(Vector2)"/> on each component.
|
||||
/// </summary>
|
||||
/// <param name="other">The other transform to compare.</param>
|
||||
/// <returns>Whether or not the matrices are approximately equal.</returns>
|
||||
public bool IsEqualApprox(Transform2D other)
|
||||
{
|
||||
return x.IsEqualApprox(other.x) && y.IsEqualApprox(other.y) && origin.IsEqualApprox(other.origin);
|
||||
|
|
|
@ -21,15 +21,29 @@ namespace Godot
|
|||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Vector2 : IEquatable<Vector2>
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerated index values for the axes.
|
||||
/// Returned by <see cref="MaxAxis"/> and <see cref="MinAxis"/>.
|
||||
/// </summary>
|
||||
public enum Axis
|
||||
{
|
||||
X = 0,
|
||||
Y
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The vector's X component. Also accessible by using the index position `[0]`.
|
||||
/// </summary>
|
||||
public real_t x;
|
||||
/// <summary>
|
||||
/// The vector's Y component. Also accessible by using the index position `[1]`.
|
||||
/// </summary>
|
||||
public real_t y;
|
||||
|
||||
/// <summary>
|
||||
/// Access vector components using their index.
|
||||
/// </summary>
|
||||
/// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`.</value>
|
||||
public real_t this[int index]
|
||||
{
|
||||
get
|
||||
|
@ -76,41 +90,80 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new vector with all components in absolute values (i.e. positive).
|
||||
/// </summary>
|
||||
/// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns>
|
||||
public Vector2 Abs()
|
||||
{
|
||||
return new Vector2(Mathf.Abs(x), Mathf.Abs(y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this vector's angle with respect to the X axis, or (1, 0) vector, in radians.
|
||||
///
|
||||
/// Equivalent to the result of <see cref="Mathf.Atan2(real_t, real_t)"/> when
|
||||
/// called with the vector's `y` and `x` as parameters: `Mathf.Atan2(v.y, v.x)`.
|
||||
/// </summary>
|
||||
/// <returns>The angle of this vector, in radians.</returns>
|
||||
public real_t Angle()
|
||||
{
|
||||
return Mathf.Atan2(y, x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the angle to the given vector, in radians.
|
||||
/// </summary>
|
||||
/// <param name="to">The other vector to compare this vector to.</param>
|
||||
/// <returns>The angle between the two vectors, in radians.</returns>
|
||||
public real_t AngleTo(Vector2 to)
|
||||
{
|
||||
return Mathf.Atan2(Cross(to), Dot(to));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the angle between the line connecting the two points and the X axis, in radians.
|
||||
/// </summary>
|
||||
/// <param name="to">The other vector to compare this vector to.</param>
|
||||
/// <returns>The angle between the two vectors, in radians.</returns>
|
||||
public real_t AngleToPoint(Vector2 to)
|
||||
{
|
||||
return Mathf.Atan2(y - to.y, x - to.x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the aspect ratio of this vector, the ratio of `x` to `y`.
|
||||
/// </summary>
|
||||
/// <returns>The `x` component divided by the `y` component.</returns>
|
||||
public real_t Aspect()
|
||||
{
|
||||
return x / y;
|
||||
}
|
||||
|
||||
public Vector2 Bounce(Vector2 n)
|
||||
/// <summary>
|
||||
/// Returns the vector "bounced off" from a plane defined by the given normal.
|
||||
/// </summary>
|
||||
/// <param name="normal">The normal vector defining the plane to bounce off. Must be normalized.</param>
|
||||
/// <returns>The bounced vector.</returns>
|
||||
public Vector2 Bounce(Vector2 normal)
|
||||
{
|
||||
return -Reflect(n);
|
||||
return -Reflect(normal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new vector with all components rounded up (towards positive infinity).
|
||||
/// </summary>
|
||||
/// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns>
|
||||
public Vector2 Ceil()
|
||||
{
|
||||
return new Vector2(Mathf.Ceil(x), Mathf.Ceil(y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the vector with a maximum length by limiting its length to `length`.
|
||||
/// </summary>
|
||||
/// <param name="length">The length to limit to.</param>
|
||||
/// <returns>The vector with its length limited.</returns>
|
||||
public Vector2 Clamped(real_t length)
|
||||
{
|
||||
var v = this;
|
||||
|
@ -125,17 +178,30 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cross product of this vector and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector.</param>
|
||||
/// <returns>The cross product value.</returns>
|
||||
public real_t Cross(Vector2 b)
|
||||
{
|
||||
return x * b.y - y * b.x;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a cubic interpolation between vectors `preA`, this vector, `b`, and `postB`, by the given amount `t`.
|
||||
/// </summary>
|
||||
/// <param name="b">The destination vector.</param>
|
||||
/// <param name="preA">A vector before this vector.</param>
|
||||
/// <param name="postB">A vector after `b`.</param>
|
||||
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The interpolated vector.</returns>
|
||||
public Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t t)
|
||||
{
|
||||
var p0 = preA;
|
||||
var p1 = this;
|
||||
var p2 = b;
|
||||
var p3 = postB;
|
||||
Vector2 p0 = preA;
|
||||
Vector2 p1 = this;
|
||||
Vector2 p2 = b;
|
||||
Vector2 p3 = postB;
|
||||
|
||||
real_t t2 = t * t;
|
||||
real_t t3 = t2 * t;
|
||||
|
@ -146,46 +212,102 @@ namespace Godot
|
|||
(-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the normalized vector pointing from this vector to `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to point towards.</param>
|
||||
/// <returns>The direction from this vector to `b`.</returns>
|
||||
public Vector2 DirectionTo(Vector2 b)
|
||||
{
|
||||
return new Vector2(b.x - x, b.y - y).Normalized();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the squared distance between this vector and `to`.
|
||||
/// This method runs faster than <see cref="DistanceTo"/>, so prefer it if
|
||||
/// you need to compare vectors or need the squared distance for some formula.
|
||||
/// </summary>
|
||||
/// <param name="to">The other vector to use.</param>
|
||||
/// <returns>The squared distance between the two vectors.</returns>
|
||||
public real_t DistanceSquaredTo(Vector2 to)
|
||||
{
|
||||
return (x - to.x) * (x - to.x) + (y - to.y) * (y - to.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the distance between this vector and `to`.
|
||||
/// </summary>
|
||||
/// <param name="to">The other vector to use.</param>
|
||||
/// <returns>The distance between the two vectors.</returns>
|
||||
public real_t DistanceTo(Vector2 to)
|
||||
{
|
||||
return Mathf.Sqrt((x - to.x) * (x - to.x) + (y - to.y) * (y - to.y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dot product of this vector and `with`.
|
||||
/// </summary>
|
||||
/// <param name="with">The other vector to use.</param>
|
||||
/// <returns>The dot product of the two vectors.</returns>
|
||||
public real_t Dot(Vector2 with)
|
||||
{
|
||||
return x * with.x + y * with.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new vector with all components rounded down (towards negative infinity).
|
||||
/// </summary>
|
||||
/// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns>
|
||||
public Vector2 Floor()
|
||||
{
|
||||
return new Vector2(Mathf.Floor(x), Mathf.Floor(y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the inverse of this vector. This is the same as `new Vector2(1 / v.x, 1 / v.y)`.
|
||||
/// </summary>
|
||||
/// <returns>The inverse of this vector.</returns>
|
||||
public Vector2 Inverse()
|
||||
{
|
||||
return new Vector2(1 / x, 1 / y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the vector is normalized, and false otherwise.
|
||||
/// </summary>
|
||||
/// <returns>A bool indicating whether or not the vector is normalized.</returns>
|
||||
public bool IsNormalized()
|
||||
{
|
||||
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length (magnitude) of this vector.
|
||||
/// </summary>
|
||||
/// <returns>The length of this vector.</returns>
|
||||
public real_t Length()
|
||||
{
|
||||
return Mathf.Sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the squared length (squared magnitude) of this vector.
|
||||
/// This method runs faster than <see cref="Length"/>, so prefer it if
|
||||
/// you need to compare vectors or need the squared length for some formula.
|
||||
/// </summary>
|
||||
/// <returns>The squared length of this vector.</returns>
|
||||
public real_t LengthSquared()
|
||||
{
|
||||
return x * x + y * y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of the linear interpolation between
|
||||
/// this vector and `to` by amount `weight`.
|
||||
/// </summary>
|
||||
/// <param name="to">The destination vector for interpolation.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting vector of the interpolation.</returns>
|
||||
public Vector2 Lerp(Vector2 to, real_t weight)
|
||||
{
|
||||
return new Vector2
|
||||
|
@ -195,6 +317,13 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of the linear interpolation between
|
||||
/// this vector and `to` by the vector amount `weight`.
|
||||
/// </summary>
|
||||
/// <param name="to">The destination vector for interpolation.</param>
|
||||
/// <param name="weight">A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting vector of the interpolation.</returns>
|
||||
public Vector2 Lerp(Vector2 to, Vector2 weight)
|
||||
{
|
||||
return new Vector2
|
||||
|
@ -204,6 +333,32 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the axis of the vector's largest value. See <see cref="Axis"/>.
|
||||
/// If both components are equal, this method returns <see cref="Axis.X"/>.
|
||||
/// </summary>
|
||||
/// <returns>The index of the largest axis.</returns>
|
||||
public Axis MaxAxis()
|
||||
{
|
||||
return x < y ? Axis.Y : Axis.X;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the axis of the vector's smallest value. See <see cref="Axis"/>.
|
||||
/// If both components are equal, this method returns <see cref="Axis.Y"/>.
|
||||
/// </summary>
|
||||
/// <returns>The index of the smallest axis.</returns>
|
||||
public Axis MinAxis()
|
||||
{
|
||||
return x < y ? Axis.X : Axis.Y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves this vector toward `to` by the fixed `delta` amount.
|
||||
/// </summary>
|
||||
/// <param name="to">The vector to move towards.</param>
|
||||
/// <param name="delta">The amount to move towards by.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public Vector2 MoveToward(Vector2 to, real_t delta)
|
||||
{
|
||||
var v = this;
|
||||
|
@ -212,6 +367,10 @@ namespace Godot
|
|||
return len <= delta || len < Mathf.Epsilon ? to : v + vd / len * delta;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the vector scaled to unit length. Equivalent to `v / v.Length()`.
|
||||
/// </summary>
|
||||
/// <returns>A normalized version of the vector.</returns>
|
||||
public Vector2 Normalized()
|
||||
{
|
||||
var v = this;
|
||||
|
@ -219,6 +378,11 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> of this vector's components and `mod`.
|
||||
/// </summary>
|
||||
/// <param name="mod">A value representing the divisor of the operation.</param>
|
||||
/// <returns>A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by `mod`.</returns>
|
||||
public Vector2 PosMod(real_t mod)
|
||||
{
|
||||
Vector2 v;
|
||||
|
@ -227,6 +391,11 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> of this vector's components and `modv`'s components.
|
||||
/// </summary>
|
||||
/// <param name="modv">A vector representing the divisors of the operation.</param>
|
||||
/// <returns>A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by `modv`'s components.</returns>
|
||||
public Vector2 PosMod(Vector2 modv)
|
||||
{
|
||||
Vector2 v;
|
||||
|
@ -235,27 +404,59 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this vector projected onto another vector `b`.
|
||||
/// </summary>
|
||||
/// <param name="onNormal">The vector to project onto.</param>
|
||||
/// <returns>The projected vector.</returns>
|
||||
public Vector2 Project(Vector2 onNormal)
|
||||
{
|
||||
return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
|
||||
}
|
||||
|
||||
public Vector2 Reflect(Vector2 n)
|
||||
/// <summary>
|
||||
/// Returns this vector reflected from a plane defined by the given `normal`.
|
||||
/// </summary>
|
||||
/// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param>
|
||||
/// <returns>The reflected vector.</returns>
|
||||
public Vector2 Reflect(Vector2 normal)
|
||||
{
|
||||
return 2 * Dot(n) * n - this;
|
||||
#if DEBUG
|
||||
if (!normal.IsNormalized())
|
||||
{
|
||||
throw new ArgumentException("Argument is not normalized", nameof(normal));
|
||||
}
|
||||
#endif
|
||||
return 2 * Dot(normal) * normal - this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates this vector by `phi` radians.
|
||||
/// </summary>
|
||||
/// <param name="phi">The angle to rotate by, in radians.</param>
|
||||
/// <returns>The rotated vector.</returns>
|
||||
public Vector2 Rotated(real_t phi)
|
||||
{
|
||||
real_t rads = Angle() + phi;
|
||||
return new Vector2(Mathf.Cos(rads), Mathf.Sin(rads)) * Length();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this vector with all components rounded to the nearest integer,
|
||||
/// with halfway cases rounded towards the nearest multiple of two.
|
||||
/// </summary>
|
||||
/// <returns>The rounded vector.</returns>
|
||||
public Vector2 Round()
|
||||
{
|
||||
return new Vector2(Mathf.Round(x), Mathf.Round(y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector with each component set to one or negative one, depending
|
||||
/// on the signs of this vector's components, or zero if the component is zero,
|
||||
/// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
|
||||
/// </summary>
|
||||
/// <returns>A vector with all components as either `1`, `-1`, or `0`.</returns>
|
||||
public Vector2 Sign()
|
||||
{
|
||||
Vector2 v;
|
||||
|
@ -264,23 +465,57 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
public Vector2 Slerp(Vector2 b, real_t t)
|
||||
/// <summary>
|
||||
/// Returns the result of the spherical linear interpolation between
|
||||
/// this vector and `to` by amount `weight`.
|
||||
///
|
||||
/// Note: Both vectors must be normalized.
|
||||
/// </summary>
|
||||
/// <param name="to">The destination vector for interpolation. Must be normalized.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting vector of the interpolation.</returns>
|
||||
public Vector2 Slerp(Vector2 to, real_t weight)
|
||||
{
|
||||
real_t theta = AngleTo(b);
|
||||
return Rotated(theta * t);
|
||||
#if DEBUG
|
||||
if (!IsNormalized())
|
||||
{
|
||||
throw new InvalidOperationException("Vector2.Slerp: From vector is not normalized.");
|
||||
}
|
||||
if (!to.IsNormalized())
|
||||
{
|
||||
throw new InvalidOperationException("Vector2.Slerp: `to` is not normalized.");
|
||||
}
|
||||
#endif
|
||||
return Rotated(AngleTo(to) * weight);
|
||||
}
|
||||
|
||||
public Vector2 Slide(Vector2 n)
|
||||
/// <summary>
|
||||
/// Returns this vector slid along a plane defined by the given normal.
|
||||
/// </summary>
|
||||
/// <param name="normal">The normal vector defining the plane to slide on.</param>
|
||||
/// <returns>The slid vector.</returns>
|
||||
public Vector2 Slide(Vector2 normal)
|
||||
{
|
||||
return this - n * Dot(n);
|
||||
return this - normal * Dot(normal);
|
||||
}
|
||||
|
||||
public Vector2 Snapped(Vector2 by)
|
||||
/// <summary>
|
||||
/// Returns this vector with each component snapped to the nearest multiple of `step`.
|
||||
/// This can also be used to round to an arbitrary number of decimals.
|
||||
/// </summary>
|
||||
/// <param name="step">A vector value representing the step size to snap to.</param>
|
||||
/// <returns>The snapped vector.</returns>
|
||||
public Vector2 Snapped(Vector2 step)
|
||||
{
|
||||
return new Vector2(Mathf.Stepify(x, by.x), Mathf.Stepify(y, by.y));
|
||||
return new Vector2(Mathf.Stepify(x, step.x), Mathf.Stepify(y, step.y));
|
||||
}
|
||||
|
||||
public Vector2 Tangent()
|
||||
/// <summary>
|
||||
/// Returns a perpendicular vector rotated 90 degrees counter-clockwise
|
||||
/// compared to the original, with the same length.
|
||||
/// </summary>
|
||||
/// <returns>The perpendicular vector.</returns>
|
||||
public Vector2 Perpendicular()
|
||||
{
|
||||
return new Vector2(y, -x);
|
||||
}
|
||||
|
@ -288,7 +523,6 @@ namespace Godot
|
|||
// Constants
|
||||
private static readonly Vector2 _zero = new Vector2(0, 0);
|
||||
private static readonly Vector2 _one = new Vector2(1, 1);
|
||||
private static readonly Vector2 _negOne = new Vector2(-1, -1);
|
||||
private static readonly Vector2 _inf = new Vector2(Mathf.Inf, Mathf.Inf);
|
||||
|
||||
private static readonly Vector2 _up = new Vector2(0, -1);
|
||||
|
@ -296,22 +530,58 @@ namespace Godot
|
|||
private static readonly Vector2 _right = new Vector2(1, 0);
|
||||
private static readonly Vector2 _left = new Vector2(-1, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Zero vector, a vector with all components set to `0`.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2(0, 0)`</value>
|
||||
public static Vector2 Zero { get { return _zero; } }
|
||||
public static Vector2 NegOne { get { return _negOne; } }
|
||||
/// <summary>
|
||||
/// One vector, a vector with all components set to `1`.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2(1, 1)`</value>
|
||||
public static Vector2 One { get { return _one; } }
|
||||
/// <summary>
|
||||
/// Infinity vector, a vector with all components set to `Mathf.Inf`.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2(Mathf.Inf, Mathf.Inf)`</value>
|
||||
public static Vector2 Inf { get { return _inf; } }
|
||||
|
||||
/// <summary>
|
||||
/// Up unit vector. Y is down in 2D, so this vector points -Y.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2(0, -1)`</value>
|
||||
public static Vector2 Up { get { return _up; } }
|
||||
/// <summary>
|
||||
/// Down unit vector. Y is down in 2D, so this vector points +Y.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2(0, 1)`</value>
|
||||
public static Vector2 Down { get { return _down; } }
|
||||
/// <summary>
|
||||
/// Right unit vector. Represents the direction of right.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2(1, 0)`</value>
|
||||
public static Vector2 Right { get { return _right; } }
|
||||
/// <summary>
|
||||
/// Left unit vector. Represents the direction of left.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2(-1, 0)`</value>
|
||||
public static Vector2 Left { get { return _left; } }
|
||||
|
||||
// Constructors
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Vector2"/> with the given components.
|
||||
/// </summary>
|
||||
/// <param name="x">The vector's X component.</param>
|
||||
/// <param name="y">The vector's Y component.</param>
|
||||
public Vector2(real_t x, real_t y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Vector2"/> from an existing <see cref="Vector2"/>.
|
||||
/// </summary>
|
||||
/// <param name="v">The existing <see cref="Vector2"/>.</param>
|
||||
public Vector2(Vector2 v)
|
||||
{
|
||||
x = v.x;
|
||||
|
@ -453,6 +723,12 @@ namespace Godot
|
|||
return x == other.x && y == other.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this vector and `other` are approximately equal, by running
|
||||
/// <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare.</param>
|
||||
/// <returns>Whether or not the vectors are approximately equal.</returns>
|
||||
public bool IsEqualApprox(Vector2 other)
|
||||
{
|
||||
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y);
|
||||
|
|
|
@ -16,15 +16,29 @@ namespace Godot
|
|||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Vector2i : IEquatable<Vector2i>
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerated index values for the axes.
|
||||
/// Returned by <see cref="MaxAxis"/> and <see cref="MinAxis"/>.
|
||||
/// </summary>
|
||||
public enum Axis
|
||||
{
|
||||
X = 0,
|
||||
Y
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The vector's X component. Also accessible by using the index position `[0]`.
|
||||
/// </summary>
|
||||
public int x;
|
||||
/// <summary>
|
||||
/// The vector's Y component. Also accessible by using the index position `[1]`.
|
||||
/// </summary>
|
||||
public int y;
|
||||
|
||||
/// <summary>
|
||||
/// Access vector components using their index.
|
||||
/// </summary>
|
||||
/// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`.</value>
|
||||
public int this[int index]
|
||||
{
|
||||
get
|
||||
|
@ -55,56 +69,102 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new vector with all components in absolute values (i.e. positive).
|
||||
/// </summary>
|
||||
/// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns>
|
||||
public Vector2i Abs()
|
||||
{
|
||||
return new Vector2i(Mathf.Abs(x), Mathf.Abs(y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this vector's angle with respect to the X axis, or (1, 0) vector, in radians.
|
||||
///
|
||||
/// Equivalent to the result of <see cref="Mathf.Atan2(real_t, real_t)"/> when
|
||||
/// called with the vector's `y` and `x` as parameters: `Mathf.Atan2(v.y, v.x)`.
|
||||
/// </summary>
|
||||
/// <returns>The angle of this vector, in radians.</returns>
|
||||
public real_t Angle()
|
||||
{
|
||||
return Mathf.Atan2(y, x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the angle to the given vector, in radians.
|
||||
/// </summary>
|
||||
/// <param name="to">The other vector to compare this vector to.</param>
|
||||
/// <returns>The angle between the two vectors, in radians.</returns>
|
||||
public real_t AngleTo(Vector2i to)
|
||||
{
|
||||
return Mathf.Atan2(Cross(to), Dot(to));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the angle between the line connecting the two points and the X axis, in radians.
|
||||
/// </summary>
|
||||
/// <param name="to">The other vector to compare this vector to.</param>
|
||||
/// <returns>The angle between the two vectors, in radians.</returns>
|
||||
public real_t AngleToPoint(Vector2i to)
|
||||
{
|
||||
return Mathf.Atan2(y - to.y, x - to.x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the aspect ratio of this vector, the ratio of `x` to `y`.
|
||||
/// </summary>
|
||||
/// <returns>The `x` component divided by the `y` component.</returns>
|
||||
public real_t Aspect()
|
||||
{
|
||||
return x / (real_t)y;
|
||||
}
|
||||
|
||||
public Vector2i Bounce(Vector2i n)
|
||||
{
|
||||
return -Reflect(n);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cross product of this vector and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector.</param>
|
||||
/// <returns>The cross product vector.</returns>
|
||||
public int Cross(Vector2i b)
|
||||
{
|
||||
return x * b.y - y * b.x;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the squared distance between this vector and `b`.
|
||||
/// This method runs faster than <see cref="DistanceTo"/>, so prefer it if
|
||||
/// you need to compare vectors or need the squared distance for some formula.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to use.</param>
|
||||
/// <returns>The squared distance between the two vectors.</returns>
|
||||
public int DistanceSquaredTo(Vector2i b)
|
||||
{
|
||||
return (b - this).LengthSquared();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the distance between this vector and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to use.</param>
|
||||
/// <returns>The distance between the two vectors.</returns>
|
||||
public real_t DistanceTo(Vector2i b)
|
||||
{
|
||||
return (b - this).Length();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dot product of this vector and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to use.</param>
|
||||
/// <returns>The dot product of the two vectors.</returns>
|
||||
public int Dot(Vector2i b)
|
||||
{
|
||||
return x * b.x + y * b.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length (magnitude) of this vector.
|
||||
/// </summary>
|
||||
/// <returns>The length of this vector.</returns>
|
||||
public real_t Length()
|
||||
{
|
||||
int x2 = x * x;
|
||||
|
@ -113,6 +173,12 @@ namespace Godot
|
|||
return Mathf.Sqrt(x2 + y2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the squared length (squared magnitude) of this vector.
|
||||
/// This method runs faster than <see cref="Length"/>, so prefer it if
|
||||
/// you need to compare vectors or need the squared length for some formula.
|
||||
/// </summary>
|
||||
/// <returns>The squared length of this vector.</returns>
|
||||
public int LengthSquared()
|
||||
{
|
||||
int x2 = x * x;
|
||||
|
@ -121,16 +187,31 @@ namespace Godot
|
|||
return x2 + y2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the axis of the vector's largest value. See <see cref="Axis"/>.
|
||||
/// If both components are equal, this method returns <see cref="Axis.X"/>.
|
||||
/// </summary>
|
||||
/// <returns>The index of the largest axis.</returns>
|
||||
public Axis MaxAxis()
|
||||
{
|
||||
return x < y ? Axis.Y : Axis.X;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the axis of the vector's smallest value. See <see cref="Axis"/>.
|
||||
/// If both components are equal, this method returns <see cref="Axis.Y"/>.
|
||||
/// </summary>
|
||||
/// <returns>The index of the smallest axis.</returns>
|
||||
public Axis MinAxis()
|
||||
{
|
||||
return x > y ? Axis.Y : Axis.X;
|
||||
return x < y ? Axis.X : Axis.Y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components and `mod`.
|
||||
/// </summary>
|
||||
/// <param name="mod">A value representing the divisor of the operation.</param>
|
||||
/// <returns>A vector with each component <see cref="Mathf.PosMod(int, int)"/> by `mod`.</returns>
|
||||
public Vector2i PosMod(int mod)
|
||||
{
|
||||
Vector2i v = this;
|
||||
|
@ -139,6 +220,11 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components and `modv`'s components.
|
||||
/// </summary>
|
||||
/// <param name="modv">A vector representing the divisors of the operation.</param>
|
||||
/// <returns>A vector with each component <see cref="Mathf.PosMod(int, int)"/> by `modv`'s components.</returns>
|
||||
public Vector2i PosMod(Vector2i modv)
|
||||
{
|
||||
Vector2i v = this;
|
||||
|
@ -147,11 +233,12 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
public Vector2i Reflect(Vector2i n)
|
||||
{
|
||||
return 2 * Dot(n) * n - this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector with each component set to one or negative one, depending
|
||||
/// on the signs of this vector's components, or zero if the component is zero,
|
||||
/// by calling <see cref="Mathf.Sign(int)"/> on each component.
|
||||
/// </summary>
|
||||
/// <returns>A vector with all components as either `1`, `-1`, or `0`.</returns>
|
||||
public Vector2i Sign()
|
||||
{
|
||||
Vector2i v = this;
|
||||
|
@ -160,9 +247,14 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
public Vector2i Tangent()
|
||||
/// <summary>
|
||||
/// Returns a vector rotated 90 degrees counter-clockwise
|
||||
/// compared to the original, with the same length.
|
||||
/// </summary>
|
||||
/// <returns>The perpendicular vector.</returns>
|
||||
public Vector2 Perpendicular()
|
||||
{
|
||||
return new Vector2i(y, -x);
|
||||
return new Vector2(y, -x);
|
||||
}
|
||||
|
||||
// Constants
|
||||
|
@ -174,25 +266,64 @@ namespace Godot
|
|||
private static readonly Vector2i _right = new Vector2i(1, 0);
|
||||
private static readonly Vector2i _left = new Vector2i(-1, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Zero vector, a vector with all components set to `0`.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2i(0, 0)`</value>
|
||||
public static Vector2i Zero { get { return _zero; } }
|
||||
/// <summary>
|
||||
/// One vector, a vector with all components set to `1`.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2i(1, 1)`</value>
|
||||
public static Vector2i One { get { return _one; } }
|
||||
|
||||
/// <summary>
|
||||
/// Up unit vector. Y is down in 2D, so this vector points -Y.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2i(0, -1)`</value>
|
||||
public static Vector2i Up { get { return _up; } }
|
||||
/// <summary>
|
||||
/// Down unit vector. Y is down in 2D, so this vector points +Y.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2i(0, 1)`</value>
|
||||
public static Vector2i Down { get { return _down; } }
|
||||
/// <summary>
|
||||
/// Right unit vector. Represents the direction of right.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2i(1, 0)`</value>
|
||||
public static Vector2i Right { get { return _right; } }
|
||||
/// <summary>
|
||||
/// Left unit vector. Represents the direction of left.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector2i(-1, 0)`</value>
|
||||
public static Vector2i Left { get { return _left; } }
|
||||
|
||||
// Constructors
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Vector2i"/> with the given components.
|
||||
/// </summary>
|
||||
/// <param name="x">The vector's X component.</param>
|
||||
/// <param name="y">The vector's Y component.</param>
|
||||
public Vector2i(int x, int y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Vector2i"/> from an existing <see cref="Vector2i"/>.
|
||||
/// </summary>
|
||||
/// <param name="vi">The existing <see cref="Vector2i"/>.</param>
|
||||
public Vector2i(Vector2i vi)
|
||||
{
|
||||
this.x = vi.x;
|
||||
this.y = vi.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Vector2i"/> from an existing <see cref="Vector2"/>
|
||||
/// by rounding the components via <see cref="Mathf.RoundToInt(real_t)"/>.
|
||||
/// </summary>
|
||||
/// <param name="v">The <see cref="Vector2"/> to convert.</param>
|
||||
public Vector2i(Vector2 v)
|
||||
{
|
||||
this.x = Mathf.RoundToInt(v.x);
|
||||
|
|
|
@ -21,6 +21,10 @@ namespace Godot
|
|||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Vector3 : IEquatable<Vector3>
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerated index values for the axes.
|
||||
/// Returned by <see cref="MaxAxis"/> and <see cref="MinAxis"/>.
|
||||
/// </summary>
|
||||
public enum Axis
|
||||
{
|
||||
X = 0,
|
||||
|
@ -28,10 +32,23 @@ namespace Godot
|
|||
Z
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The vector's X component. Also accessible by using the index position `[0]`.
|
||||
/// </summary>
|
||||
public real_t x;
|
||||
/// <summary>
|
||||
/// The vector's Y component. Also accessible by using the index position `[1]`.
|
||||
/// </summary>
|
||||
public real_t y;
|
||||
/// <summary>
|
||||
/// The vector's Z component. Also accessible by using the index position `[2]`.
|
||||
/// </summary>
|
||||
public real_t z;
|
||||
|
||||
/// <summary>
|
||||
/// Access vector components using their index.
|
||||
/// </summary>
|
||||
/// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`, `[2]` is equivalent to `.z`.</value>
|
||||
public real_t this[int index]
|
||||
{
|
||||
get
|
||||
|
@ -84,26 +101,49 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new vector with all components in absolute values (i.e. positive).
|
||||
/// </summary>
|
||||
/// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns>
|
||||
public Vector3 Abs()
|
||||
{
|
||||
return new Vector3(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum angle to the given vector, in radians.
|
||||
/// </summary>
|
||||
/// <param name="to">The other vector to compare this vector to.</param>
|
||||
/// <returns>The angle between the two vectors, in radians.</returns>
|
||||
public real_t AngleTo(Vector3 to)
|
||||
{
|
||||
return Mathf.Atan2(Cross(to).Length(), Dot(to));
|
||||
}
|
||||
|
||||
public Vector3 Bounce(Vector3 n)
|
||||
/// <summary>
|
||||
/// Returns this vector "bounced off" from a plane defined by the given normal.
|
||||
/// </summary>
|
||||
/// <param name="normal">The normal vector defining the plane to bounce off. Must be normalized.</param>
|
||||
/// <returns>The bounced vector.</returns>
|
||||
public Vector3 Bounce(Vector3 normal)
|
||||
{
|
||||
return -Reflect(n);
|
||||
return -Reflect(normal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new vector with all components rounded up (towards positive infinity).
|
||||
/// </summary>
|
||||
/// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns>
|
||||
public Vector3 Ceil()
|
||||
{
|
||||
return new Vector3(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cross product of this vector and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector.</param>
|
||||
/// <returns>The cross product vector.</returns>
|
||||
public Vector3 Cross(Vector3 b)
|
||||
{
|
||||
return new Vector3
|
||||
|
@ -114,12 +154,21 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a cubic interpolation between vectors `preA`, this vector,
|
||||
/// `b`, and `postB`, by the given amount `t`.
|
||||
/// </summary>
|
||||
/// <param name="b">The destination vector.</param>
|
||||
/// <param name="preA">A vector before this vector.</param>
|
||||
/// <param name="postB">A vector after `b`.</param>
|
||||
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The interpolated vector.</returns>
|
||||
public Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t t)
|
||||
{
|
||||
var p0 = preA;
|
||||
var p1 = this;
|
||||
var p2 = b;
|
||||
var p3 = postB;
|
||||
Vector3 p0 = preA;
|
||||
Vector3 p1 = this;
|
||||
Vector3 p2 = b;
|
||||
Vector3 p3 = postB;
|
||||
|
||||
real_t t2 = t * t;
|
||||
real_t t3 = t2 * t;
|
||||
|
@ -131,41 +180,79 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the normalized vector pointing from this vector to `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to point towards.</param>
|
||||
/// <returns>The direction from this vector to `b`.</returns>
|
||||
public Vector3 DirectionTo(Vector3 b)
|
||||
{
|
||||
return new Vector3(b.x - x, b.y - y, b.z - z).Normalized();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the squared distance between this vector and `b`.
|
||||
/// This method runs faster than <see cref="DistanceTo"/>, so prefer it if
|
||||
/// you need to compare vectors or need the squared distance for some formula.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to use.</param>
|
||||
/// <returns>The squared distance between the two vectors.</returns>
|
||||
public real_t DistanceSquaredTo(Vector3 b)
|
||||
{
|
||||
return (b - this).LengthSquared();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the distance between this vector and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to use.</param>
|
||||
/// <returns>The distance between the two vectors.</returns>
|
||||
public real_t DistanceTo(Vector3 b)
|
||||
{
|
||||
return (b - this).Length();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dot product of this vector and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to use.</param>
|
||||
/// <returns>The dot product of the two vectors.</returns>
|
||||
public real_t Dot(Vector3 b)
|
||||
{
|
||||
return x * b.x + y * b.y + z * b.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new vector with all components rounded down (towards negative infinity).
|
||||
/// </summary>
|
||||
/// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns>
|
||||
public Vector3 Floor()
|
||||
{
|
||||
return new Vector3(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the inverse of this vector. This is the same as `new Vector3(1 / v.x, 1 / v.y, 1 / v.z)`.
|
||||
/// </summary>
|
||||
/// <returns>The inverse of this vector.</returns>
|
||||
public Vector3 Inverse()
|
||||
{
|
||||
return new Vector3(1.0f / x, 1.0f / y, 1.0f / z);
|
||||
return new Vector3(1 / x, 1 / y, 1 / z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the vector is normalized, and false otherwise.
|
||||
/// </summary>
|
||||
/// <returns>A bool indicating whether or not the vector is normalized.</returns>
|
||||
public bool IsNormalized()
|
||||
{
|
||||
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length (magnitude) of this vector.
|
||||
/// </summary>
|
||||
/// <returns>The length of this vector.</returns>
|
||||
public real_t Length()
|
||||
{
|
||||
real_t x2 = x * x;
|
||||
|
@ -175,6 +262,12 @@ namespace Godot
|
|||
return Mathf.Sqrt(x2 + y2 + z2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the squared length (squared magnitude) of this vector.
|
||||
/// This method runs faster than <see cref="Length"/>, so prefer it if
|
||||
/// you need to compare vectors or need the squared length for some formula.
|
||||
/// </summary>
|
||||
/// <returns>The squared length of this vector.</returns>
|
||||
public real_t LengthSquared()
|
||||
{
|
||||
real_t x2 = x * x;
|
||||
|
@ -184,6 +277,13 @@ namespace Godot
|
|||
return x2 + y2 + z2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of the linear interpolation between
|
||||
/// this vector and `to` by amount `weight`.
|
||||
/// </summary>
|
||||
/// <param name="to">The destination vector for interpolation.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting vector of the interpolation.</returns>
|
||||
public Vector3 Lerp(Vector3 to, real_t weight)
|
||||
{
|
||||
return new Vector3
|
||||
|
@ -194,6 +294,13 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the result of the linear interpolation between
|
||||
/// this vector and `to` by the vector amount `weight`.
|
||||
/// </summary>
|
||||
/// <param name="to">The destination vector for interpolation.</param>
|
||||
/// <param name="weight">A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting vector of the interpolation.</returns>
|
||||
public Vector3 Lerp(Vector3 to, Vector3 weight)
|
||||
{
|
||||
return new Vector3
|
||||
|
@ -204,6 +311,32 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the axis of the vector's largest value. See <see cref="Axis"/>.
|
||||
/// If all components are equal, this method returns <see cref="Axis.X"/>.
|
||||
/// </summary>
|
||||
/// <returns>The index of the largest axis.</returns>
|
||||
public Axis MaxAxis()
|
||||
{
|
||||
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the axis of the vector's smallest value. See <see cref="Axis"/>.
|
||||
/// If all components are equal, this method returns <see cref="Axis.Z"/>.
|
||||
/// </summary>
|
||||
/// <returns>The index of the smallest axis.</returns>
|
||||
public Axis MinAxis()
|
||||
{
|
||||
return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves this vector toward `to` by the fixed `delta` amount.
|
||||
/// </summary>
|
||||
/// <param name="to">The vector to move towards.</param>
|
||||
/// <param name="delta">The amount to move towards by.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public Vector3 MoveToward(Vector3 to, real_t delta)
|
||||
{
|
||||
var v = this;
|
||||
|
@ -212,16 +345,10 @@ namespace Godot
|
|||
return len <= delta || len < Mathf.Epsilon ? to : v + vd / len * delta;
|
||||
}
|
||||
|
||||
public Axis MaxAxis()
|
||||
{
|
||||
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
|
||||
}
|
||||
|
||||
public Axis MinAxis()
|
||||
{
|
||||
return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the vector scaled to unit length. Equivalent to `v / v.Length()`.
|
||||
/// </summary>
|
||||
/// <returns>A normalized version of the vector.</returns>
|
||||
public Vector3 Normalized()
|
||||
{
|
||||
var v = this;
|
||||
|
@ -229,6 +356,11 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the outer product with `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector.</param>
|
||||
/// <returns>A <see cref="Basis"/> representing the outer product matrix.</returns>
|
||||
public Basis Outer(Vector3 b)
|
||||
{
|
||||
return new Basis(
|
||||
|
@ -238,6 +370,11 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> of this vector's components and `mod`.
|
||||
/// </summary>
|
||||
/// <param name="mod">A value representing the divisor of the operation.</param>
|
||||
/// <returns>A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by `mod`.</returns>
|
||||
public Vector3 PosMod(real_t mod)
|
||||
{
|
||||
Vector3 v;
|
||||
|
@ -247,6 +384,11 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> of this vector's components and `modv`'s components.
|
||||
/// </summary>
|
||||
/// <param name="modv">A vector representing the divisors of the operation.</param>
|
||||
/// <returns>A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by `modv`'s components.</returns>
|
||||
public Vector3 PosMod(Vector3 modv)
|
||||
{
|
||||
Vector3 v;
|
||||
|
@ -256,30 +398,66 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this vector projected onto another vector `b`.
|
||||
/// </summary>
|
||||
/// <param name="onNormal">The vector to project onto.</param>
|
||||
/// <returns>The projected vector.</returns>
|
||||
public Vector3 Project(Vector3 onNormal)
|
||||
{
|
||||
return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
|
||||
}
|
||||
|
||||
public Vector3 Reflect(Vector3 n)
|
||||
/// <summary>
|
||||
/// Returns this vector reflected from a plane defined by the given `normal`.
|
||||
/// </summary>
|
||||
/// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param>
|
||||
/// <returns>The reflected vector.</returns>
|
||||
public Vector3 Reflect(Vector3 normal)
|
||||
{
|
||||
#if DEBUG
|
||||
if (!n.IsNormalized())
|
||||
throw new ArgumentException("Argument is not normalized", nameof(n));
|
||||
if (!normal.IsNormalized())
|
||||
{
|
||||
throw new ArgumentException("Argument is not normalized", nameof(normal));
|
||||
}
|
||||
#endif
|
||||
return 2.0f * n * Dot(n) - this;
|
||||
return 2.0f * Dot(normal) * normal - this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates this vector around a given `axis` vector by `phi` radians.
|
||||
/// The `axis` vector must be a normalized vector.
|
||||
/// </summary>
|
||||
/// <param name="axis">The vector to rotate around. Must be normalized.</param>
|
||||
/// <param name="phi">The angle to rotate by, in radians.</param>
|
||||
/// <returns>The rotated vector.</returns>
|
||||
public Vector3 Rotated(Vector3 axis, real_t phi)
|
||||
{
|
||||
#if DEBUG
|
||||
if (!axis.IsNormalized())
|
||||
{
|
||||
throw new ArgumentException("Argument is not normalized", nameof(axis));
|
||||
}
|
||||
#endif
|
||||
return new Basis(axis, phi).Xform(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this vector with all components rounded to the nearest integer,
|
||||
/// with halfway cases rounded towards the nearest multiple of two.
|
||||
/// </summary>
|
||||
/// <returns>The rounded vector.</returns>
|
||||
public Vector3 Round()
|
||||
{
|
||||
return new Vector3(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z));
|
||||
}
|
||||
|
||||
public Vector3 Rotated(Vector3 axis, real_t phi)
|
||||
{
|
||||
return new Basis(axis, phi).Xform(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector with each component set to one or negative one, depending
|
||||
/// on the signs of this vector's components, or zero if the component is zero,
|
||||
/// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
|
||||
/// </summary>
|
||||
/// <returns>A vector with all components as either `1`, `-1`, or `0`.</returns>
|
||||
public Vector3 Sign()
|
||||
{
|
||||
Vector3 v;
|
||||
|
@ -289,44 +467,76 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
public Vector3 Slerp(Vector3 b, real_t t)
|
||||
/// <summary>
|
||||
/// Returns the result of the spherical linear interpolation between
|
||||
/// this vector and `to` by amount `weight`.
|
||||
///
|
||||
/// Note: Both vectors must be normalized.
|
||||
/// </summary>
|
||||
/// <param name="to">The destination vector for interpolation. Must be normalized.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <returns>The resulting vector of the interpolation.</returns>
|
||||
public Vector3 Slerp(Vector3 to, real_t weight)
|
||||
{
|
||||
#if DEBUG
|
||||
if (!IsNormalized())
|
||||
throw new InvalidOperationException("Vector3 is not normalized");
|
||||
{
|
||||
throw new InvalidOperationException("Vector3.Slerp: From vector is not normalized.");
|
||||
}
|
||||
if (!to.IsNormalized())
|
||||
{
|
||||
throw new InvalidOperationException("Vector3.Slerp: `to` is not normalized.");
|
||||
}
|
||||
#endif
|
||||
real_t theta = AngleTo(b);
|
||||
return Rotated(Cross(b), theta * t);
|
||||
real_t theta = AngleTo(to);
|
||||
return Rotated(Cross(to), theta * weight);
|
||||
}
|
||||
|
||||
public Vector3 Slide(Vector3 n)
|
||||
/// <summary>
|
||||
/// Returns this vector slid along a plane defined by the given normal.
|
||||
/// </summary>
|
||||
/// <param name="normal">The normal vector defining the plane to slide on.</param>
|
||||
/// <returns>The slid vector.</returns>
|
||||
public Vector3 Slide(Vector3 normal)
|
||||
{
|
||||
return this - n * Dot(n);
|
||||
return this - normal * Dot(normal);
|
||||
}
|
||||
|
||||
public Vector3 Snapped(Vector3 by)
|
||||
/// <summary>
|
||||
/// Returns this vector with each component snapped to the nearest multiple of `step`.
|
||||
/// This can also be used to round to an arbitrary number of decimals.
|
||||
/// </summary>
|
||||
/// <param name="step">A vector value representing the step size to snap to.</param>
|
||||
/// <returns>The snapped vector.</returns>
|
||||
public Vector3 Snapped(Vector3 step)
|
||||
{
|
||||
return new Vector3
|
||||
(
|
||||
Mathf.Stepify(x, by.x),
|
||||
Mathf.Stepify(y, by.y),
|
||||
Mathf.Stepify(z, by.z)
|
||||
Mathf.Stepify(x, step.x),
|
||||
Mathf.Stepify(y, step.y),
|
||||
Mathf.Stepify(z, step.z)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a diagonal matrix with the vector as main diagonal.
|
||||
///
|
||||
/// This is equivalent to a Basis with no rotation or shearing and
|
||||
/// this vector's components set as the scale.
|
||||
/// </summary>
|
||||
/// <returns>A Basis with the vector as its main diagonal.</returns>
|
||||
public Basis ToDiagonalMatrix()
|
||||
{
|
||||
return new Basis(
|
||||
x, 0f, 0f,
|
||||
0f, y, 0f,
|
||||
0f, 0f, z
|
||||
x, 0, 0,
|
||||
0, y, 0,
|
||||
0, 0, z
|
||||
);
|
||||
}
|
||||
|
||||
// Constants
|
||||
private static readonly Vector3 _zero = new Vector3(0, 0, 0);
|
||||
private static readonly Vector3 _one = new Vector3(1, 1, 1);
|
||||
private static readonly Vector3 _negOne = new Vector3(-1, -1, -1);
|
||||
private static readonly Vector3 _inf = new Vector3(Mathf.Inf, Mathf.Inf, Mathf.Inf);
|
||||
|
||||
private static readonly Vector3 _up = new Vector3(0, 1, 0);
|
||||
|
@ -336,25 +546,74 @@ namespace Godot
|
|||
private static readonly Vector3 _forward = new Vector3(0, 0, -1);
|
||||
private static readonly Vector3 _back = new Vector3(0, 0, 1);
|
||||
|
||||
/// <summary>
|
||||
/// Zero vector, a vector with all components set to `0`.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3(0, 0, 0)`</value>
|
||||
public static Vector3 Zero { get { return _zero; } }
|
||||
/// <summary>
|
||||
/// One vector, a vector with all components set to `1`.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3(1, 1, 1)`</value>
|
||||
public static Vector3 One { get { return _one; } }
|
||||
public static Vector3 NegOne { get { return _negOne; } }
|
||||
/// <summary>
|
||||
/// Infinity vector, a vector with all components set to `Mathf.Inf`.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3(Mathf.Inf, Mathf.Inf, Mathf.Inf)`</value>
|
||||
public static Vector3 Inf { get { return _inf; } }
|
||||
|
||||
/// <summary>
|
||||
/// Up unit vector.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3(0, 1, 0)`</value>
|
||||
public static Vector3 Up { get { return _up; } }
|
||||
/// <summary>
|
||||
/// Down unit vector.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3(0, -1, 0)`</value>
|
||||
public static Vector3 Down { get { return _down; } }
|
||||
/// <summary>
|
||||
/// Right unit vector. Represents the local direction of right,
|
||||
/// and the global direction of east.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3(1, 0, 0)`</value>
|
||||
public static Vector3 Right { get { return _right; } }
|
||||
/// <summary>
|
||||
/// Left unit vector. Represents the local direction of left,
|
||||
/// and the global direction of west.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3(-1, 0, 0)`</value>
|
||||
public static Vector3 Left { get { return _left; } }
|
||||
/// <summary>
|
||||
/// Forward unit vector. Represents the local direction of forward,
|
||||
/// and the global direction of north.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3(0, 0, -1)`</value>
|
||||
public static Vector3 Forward { get { return _forward; } }
|
||||
/// <summary>
|
||||
/// Back unit vector. Represents the local direction of back,
|
||||
/// and the global direction of south.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3(0, 0, 1)`</value>
|
||||
public static Vector3 Back { get { return _back; } }
|
||||
|
||||
// Constructors
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Vector3"/> with the given components.
|
||||
/// </summary>
|
||||
/// <param name="x">The vector's X component.</param>
|
||||
/// <param name="y">The vector's Y component.</param>
|
||||
/// <param name="z">The vector's Z component.</param>
|
||||
public Vector3(real_t x, real_t y, real_t z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Vector3"/> from an existing <see cref="Vector3"/>.
|
||||
/// </summary>
|
||||
/// <param name="v">The existing <see cref="Vector3"/>.</param>
|
||||
public Vector3(Vector3 v)
|
||||
{
|
||||
x = v.x;
|
||||
|
@ -515,6 +774,12 @@ namespace Godot
|
|||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this vector and `other` are approximately equal, by running
|
||||
/// <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare.</param>
|
||||
/// <returns>Whether or not the vectors are approximately equal.</returns>
|
||||
public bool IsEqualApprox(Vector3 other)
|
||||
{
|
||||
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z);
|
||||
|
|
|
@ -16,6 +16,10 @@ namespace Godot
|
|||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Vector3i : IEquatable<Vector3i>
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerated index values for the axes.
|
||||
/// Returned by <see cref="MaxAxis"/> and <see cref="MinAxis"/>.
|
||||
/// </summary>
|
||||
public enum Axis
|
||||
{
|
||||
X = 0,
|
||||
|
@ -23,10 +27,23 @@ namespace Godot
|
|||
Z
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The vector's X component. Also accessible by using the index position `[0]`.
|
||||
/// </summary>
|
||||
public int x;
|
||||
/// <summary>
|
||||
/// The vector's Y component. Also accessible by using the index position `[1]`.
|
||||
/// </summary>
|
||||
public int y;
|
||||
/// <summary>
|
||||
/// The vector's Z component. Also accessible by using the index position `[2]`.
|
||||
/// </summary>
|
||||
public int z;
|
||||
|
||||
/// <summary>
|
||||
/// Access vector components using their index.
|
||||
/// </summary>
|
||||
/// <value>`[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`, `[2]` is equivalent to `.z`.</value>
|
||||
public int this[int index]
|
||||
{
|
||||
get
|
||||
|
@ -62,39 +79,51 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new vector with all components in absolute values (i.e. positive).
|
||||
/// </summary>
|
||||
/// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns>
|
||||
public Vector3i Abs()
|
||||
{
|
||||
Vector3i v = this;
|
||||
if (v.x < 0)
|
||||
{
|
||||
v.x = -v.x;
|
||||
}
|
||||
if (v.y < 0)
|
||||
{
|
||||
v.y = -v.y;
|
||||
}
|
||||
if (v.z < 0)
|
||||
{
|
||||
v.z = -v.z;
|
||||
}
|
||||
return v;
|
||||
return new Vector3i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the squared distance between this vector and `b`.
|
||||
/// This method runs faster than <see cref="DistanceTo"/>, so prefer it if
|
||||
/// you need to compare vectors or need the squared distance for some formula.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to use.</param>
|
||||
/// <returns>The squared distance between the two vectors.</returns>
|
||||
public int DistanceSquaredTo(Vector3i b)
|
||||
{
|
||||
return (b - this).LengthSquared();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the distance between this vector and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to use.</param>
|
||||
/// <returns>The distance between the two vectors.</returns>
|
||||
public real_t DistanceTo(Vector3i b)
|
||||
{
|
||||
return (b - this).Length();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dot product of this vector and `b`.
|
||||
/// </summary>
|
||||
/// <param name="b">The other vector to use.</param>
|
||||
/// <returns>The dot product of the two vectors.</returns>
|
||||
public int Dot(Vector3i b)
|
||||
{
|
||||
return x * b.x + y * b.y + z * b.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length (magnitude) of this vector.
|
||||
/// </summary>
|
||||
/// <returns>The length of this vector.</returns>
|
||||
public real_t Length()
|
||||
{
|
||||
int x2 = x * x;
|
||||
|
@ -104,6 +133,12 @@ namespace Godot
|
|||
return Mathf.Sqrt(x2 + y2 + z2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the squared length (squared magnitude) of this vector.
|
||||
/// This method runs faster than <see cref="Length"/>, so prefer it if
|
||||
/// you need to compare vectors or need the squared length for some formula.
|
||||
/// </summary>
|
||||
/// <returns>The squared length of this vector.</returns>
|
||||
public int LengthSquared()
|
||||
{
|
||||
int x2 = x * x;
|
||||
|
@ -113,16 +148,31 @@ namespace Godot
|
|||
return x2 + y2 + z2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the axis of the vector's largest value. See <see cref="Axis"/>.
|
||||
/// If all components are equal, this method returns <see cref="Axis.X"/>.
|
||||
/// </summary>
|
||||
/// <returns>The index of the largest axis.</returns>
|
||||
public Axis MaxAxis()
|
||||
{
|
||||
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the axis of the vector's smallest value. See <see cref="Axis"/>.
|
||||
/// If all components are equal, this method returns <see cref="Axis.Z"/>.
|
||||
/// </summary>
|
||||
/// <returns>The index of the smallest axis.</returns>
|
||||
public Axis MinAxis()
|
||||
{
|
||||
return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components and `mod`.
|
||||
/// </summary>
|
||||
/// <param name="mod">A value representing the divisor of the operation.</param>
|
||||
/// <returns>A vector with each component <see cref="Mathf.PosMod(int, int)"/> by `mod`.</returns>
|
||||
public Vector3i PosMod(int mod)
|
||||
{
|
||||
Vector3i v = this;
|
||||
|
@ -132,6 +182,11 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector composed of the <see cref="Mathf.PosMod(int, int)"/> of this vector's components and `modv`'s components.
|
||||
/// </summary>
|
||||
/// <param name="modv">A vector representing the divisors of the operation.</param>
|
||||
/// <returns>A vector with each component <see cref="Mathf.PosMod(int, int)"/> by `modv`'s components.</returns>
|
||||
public Vector3i PosMod(Vector3i modv)
|
||||
{
|
||||
Vector3i v = this;
|
||||
|
@ -141,6 +196,12 @@ namespace Godot
|
|||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector with each component set to one or negative one, depending
|
||||
/// on the signs of this vector's components, or zero if the component is zero,
|
||||
/// by calling <see cref="Mathf.Sign(int)"/> on each component.
|
||||
/// </summary>
|
||||
/// <returns>A vector with all components as either `1`, `-1`, or `0`.</returns>
|
||||
public Vector3i Sign()
|
||||
{
|
||||
Vector3i v = this;
|
||||
|
@ -161,29 +222,81 @@ namespace Godot
|
|||
private static readonly Vector3i _forward = new Vector3i(0, 0, -1);
|
||||
private static readonly Vector3i _back = new Vector3i(0, 0, 1);
|
||||
|
||||
/// <summary>
|
||||
/// Zero vector, a vector with all components set to `0`.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3i(0, 0, 0)`</value>
|
||||
public static Vector3i Zero { get { return _zero; } }
|
||||
/// <summary>
|
||||
/// One vector, a vector with all components set to `1`.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3i(1, 1, 1)`</value>
|
||||
public static Vector3i One { get { return _one; } }
|
||||
|
||||
/// <summary>
|
||||
/// Up unit vector.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3i(0, 1, 0)`</value>
|
||||
public static Vector3i Up { get { return _up; } }
|
||||
/// <summary>
|
||||
/// Down unit vector.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3i(0, -1, 0)`</value>
|
||||
public static Vector3i Down { get { return _down; } }
|
||||
/// <summary>
|
||||
/// Right unit vector. Represents the local direction of right,
|
||||
/// and the global direction of east.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3i(1, 0, 0)`</value>
|
||||
public static Vector3i Right { get { return _right; } }
|
||||
/// <summary>
|
||||
/// Left unit vector. Represents the local direction of left,
|
||||
/// and the global direction of west.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3i(-1, 0, 0)`</value>
|
||||
public static Vector3i Left { get { return _left; } }
|
||||
/// <summary>
|
||||
/// Forward unit vector. Represents the local direction of forward,
|
||||
/// and the global direction of north.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3i(0, 0, -1)`</value>
|
||||
public static Vector3i Forward { get { return _forward; } }
|
||||
/// <summary>
|
||||
/// Back unit vector. Represents the local direction of back,
|
||||
/// and the global direction of south.
|
||||
/// </summary>
|
||||
/// <value>Equivalent to `new Vector3i(0, 0, 1)`</value>
|
||||
public static Vector3i Back { get { return _back; } }
|
||||
|
||||
// Constructors
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Vector3i"/> with the given components.
|
||||
/// </summary>
|
||||
/// <param name="x">The vector's X component.</param>
|
||||
/// <param name="y">The vector's Y component.</param>
|
||||
/// <param name="z">The vector's Z component.</param>
|
||||
public Vector3i(int x, int y, int z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Vector3i"/> from an existing <see cref="Vector3i"/>.
|
||||
/// </summary>
|
||||
/// <param name="vi">The existing <see cref="Vector3i"/>.</param>
|
||||
public Vector3i(Vector3i vi)
|
||||
{
|
||||
this.x = vi.x;
|
||||
this.y = vi.y;
|
||||
this.z = vi.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Vector3i"/> from an existing <see cref="Vector3"/>
|
||||
/// by rounding the components via <see cref="Mathf.RoundToInt(real_t)"/>.
|
||||
/// </summary>
|
||||
/// <param name="v">The <see cref="Vector3"/> to convert.</param>
|
||||
public Vector3i(Vector3 v)
|
||||
{
|
||||
this.x = Mathf.RoundToInt(v.x);
|
||||
|
|
Loading…
Reference in a new issue