From 3ab5183ffaf88e906aa04a64936b7a5e4a1f437d Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Tue, 21 Jul 2020 21:21:41 -0400 Subject: [PATCH 1/2] [3.2] Backport core documentation changes to 3.2 Also add AABB.abs() --- core/math/aabb.h | 4 ++ core/math/plane.cpp | 1 - core/variant_call.cpp | 2 + doc/classes/AABB.xml | 16 +++-- doc/classes/Basis.xml | 35 ++++++----- doc/classes/Color.xml | 26 ++++---- doc/classes/Plane.xml | 25 ++++---- doc/classes/Quat.xml | 41 +++++++------ doc/classes/Rect2.xml | 7 ++- doc/classes/Transform.xml | 16 ++--- doc/classes/Transform2D.xml | 34 ++++++----- doc/classes/Vector2.xml | 65 ++++++++++---------- doc/classes/Vector3.xml | 70 ++++++++++++---------- modules/gdscript/doc_classes/@GDScript.xml | 64 ++++++++------------ 14 files changed, 219 insertions(+), 187 deletions(-) diff --git a/core/math/aabb.h b/core/math/aabb.h index 235a678fa00..35748151d45 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -101,6 +101,10 @@ public: _FORCE_INLINE_ void project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const; _FORCE_INLINE_ void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */ + _FORCE_INLINE_ AABB abs() const { + return AABB(Vector3(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0), position.z + MIN(size.z, 0)), size.abs()); + } + operator String() const; _FORCE_INLINE_ AABB() {} diff --git a/core/math/plane.cpp b/core/math/plane.cpp index a3818698bc0..9d9bc75e209 100644 --- a/core/math/plane.cpp +++ b/core/math/plane.cpp @@ -56,7 +56,6 @@ Plane Plane::normalized() const { } Vector3 Plane::get_any_point() const { - return get_normal() * d; } diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 4283a4395c8..d3ff10b1175 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -743,6 +743,7 @@ struct _VariantCall { #define VCALL_PTR5R(m_type, m_method) \ static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast(p_self._data._ptr)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); } + VCALL_PTR0R(AABB, abs); VCALL_PTR0R(AABB, get_area); VCALL_PTR0R(AABB, has_no_area); VCALL_PTR0R(AABB, has_no_surface); @@ -1909,6 +1910,7 @@ void register_variant_methods() { //pointerbased + ADDFUNC0R(AABB, AABB, AABB, abs, varray()); ADDFUNC0R(AABB, REAL, AABB, get_area, varray()); ADDFUNC0R(AABB, BOOL, AABB, has_no_area, varray()); ADDFUNC0R(AABB, BOOL, AABB, has_no_surface, varray()); diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index cfb0435ce6c..0a7724581db 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -18,7 +18,14 @@ - Optional constructor, accepts position and size. + Constructs an [AABB] from a position and size. + + + + + + + Returns an AABB with equivalent position and size, modified so that the most-negative corner is the origin and the size is positive. @@ -197,13 +204,14 @@ - Ending corner. This is calculated as [code]position + size[/code]. Changing this property changes [member size] accordingly. + Ending corner. This is calculated as [code]position + size[/code]. Setting this value will change the size. - Beginning corner. + Beginning corner. Typically has values lower than [member end]. - Size from position to end. + Size from [member position] to [member end]. Typically all components are positive. + If the size is negative, you can use [method abs] to fix it. diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml index dcfd68eca75..16bba528b56 100644 --- a/doc/classes/Basis.xml +++ b/doc/classes/Basis.xml @@ -4,10 +4,13 @@ 3×3 matrix datatype. - 3×3 matrix used for 3D rotation and scale. Contains 3 vector fields X, Y and Z as its columns, which can be interpreted as the local basis vectors of a transformation. Can also be accessed as array of 3D vectors. These vectors are orthogonal to each other, but are not necessarily normalized (due to scaling). Almost always used as an orthogonal basis for a [Transform]. - For such use, it is composed of a scaling and a rotation matrix, in that order (M = R.S). + 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 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 the "Matrices and transforms" documentation article. + https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html @@ -17,7 +20,7 @@ - Create a rotation matrix from the given quaternion. + Constructs a pure rotation basis matrix from the given quaternion. @@ -26,7 +29,8 @@ - Create a rotation matrix (in the YXZ convention: first Z, then X, and Y last) from the specified Euler angles, given in the vector format as (X angle, Y angle, Z angle). + 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 [Quat] constructor instead, which uses a quaternion instead of Euler angles. @@ -37,7 +41,7 @@ - Create a rotation matrix which rotates around the given axis by the specified angle, in radians. The axis must be a normalized vector. + Constructs a pure rotation basis matrix, rotated around the given [code]axis[/code] by [code]phi[/code], in radians. The axis must be a normalized vector. @@ -50,28 +54,30 @@ - Create a matrix from 3 axis vectors. + Constructs a basis matrix from 3 axis vectors (matrix columns). - Returns the determinant of the matrix. + 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. - Returns the basis's rotation in the form of Euler angles (in the YXZ convention: first Z, then X, and Y last). The returned vector contains the rotation angles in the format (X angle, Y angle, Z angle). See [method get_rotation_quat] if you need a quaternion instead. + 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 [method get_rotation_quat] method instead, which returns a [Quat] quaternion instead of Euler angles. - 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 grid map editor. For further details, refer to the Godot source code. + 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 [GridMap] editor. For further details, refer to the Godot source code. @@ -193,25 +199,26 @@ - Returns a vector transformed (multiplied) by the transposed matrix. + Returns a vector transformed (multiplied) by the transposed basis matrix. [b]Note:[/b] This results in a multiplication by the inverse of the matrix only if it represents a rotation-reflection. - The basis matrix's X vector. + The basis matrix's X vector (column 0). Equivalent to array index [code]0[/code]. - The basis matrix's Y vector. + The basis matrix's Y vector (column 1). Equivalent to array index [code]1[/code]. - The basis matrix's Z vector. + The basis matrix's Z vector (column 2). Equivalent to array index [code]2[/code]. - The identity basis. This is identical to calling [code]Basis()[/code] without any parameters. This constant can be used to make your code clearer. + The identity basis, with no rotation or scaling applied. + This is identical to calling [code]Basis()[/code] without any parameters. This constant can be used to make your code clearer, and for consistency with C#. The basis that will flip something along the X axis when used in a transformation. diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index b54911b1873..37b9a4903bb 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -1,10 +1,10 @@ - Color in RGBA format with some support for ARGB format. + Color in RGBA format using floats on the range of 0 to 1. - A color is represented by red, green, and blue [code](r, g, b)[/code] components. Additionally, [code]a[/code] represents the alpha component, often used for transparency. Values are in floating-point and usually range from 0 to 1. Some properties (such as [member CanvasItem.modulate]) may accept values greater than 1. + A color represented by red, green, blue, and alpha (RGBA) components. The alpha component is often used for transparency. Values are in floating-point and usually range from 0 to 1. Some properties (such as CanvasItem.modulate) may accept values greater than 1 (overbright or HDR colors). You can also create a color from standardized color names by using [method @GDScript.ColorN] or directly using the color constants defined here. The standardized color set is based on the [url=https://en.wikipedia.org/wiki/X11_color_names]X11 color names[/url]. If you want to supply values in a range of 0 to 255, you should use [method @GDScript.Color8]. [b]Note:[/b] In a boolean context, a Color will evaluate to [code]false[/code] if it's equal to [code]Color(0, 0, 0, 1)[/code] (opaque black). Otherwise, a Color will always evaluate to [code]true[/code]. @@ -275,37 +275,37 @@ - Alpha value (range 0 to 1). + The color's alpha (transparency) component, typically on the range of 0 to 1. - Alpha value (range 0 to 255). + Wrapper for [member a] that uses the range 0 to 255 instead of 0 to 1. - Blue value (range 0 to 1). + The color's blue component, typically on the range of 0 to 1. - Blue value (range 0 to 255). + Wrapper for [member b] that uses the range 0 to 255 instead of 0 to 1. - Green value (range 0 to 1). + The color's green component, typically on the range of 0 to 1. - Green value (range 0 to 255). + Wrapper for [member g] that uses the range 0 to 255 instead of 0 to 1. - HSV hue value (range 0 to 1). + The HSV hue of this color, on the range 0 to 1. - Red value (range 0 to 1). + The color's red component, typically on the range of 0 to 1. - Red value (range 0 to 255). + Wrapper for [member r] that uses the range 0 to 255 instead of 0 to 1. - HSV saturation value (range 0 to 1). + The HSV saturation of this color, on the range 0 to 1. - HSV value (range 0 to 1). + The HSV value (brightness) of this color, on the range 0 to 1. diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml index 5209c62ef49..85b3571e96d 100644 --- a/doc/classes/Plane.xml +++ b/doc/classes/Plane.xml @@ -69,7 +69,8 @@ - Returns a point on the plane. + Returns the center of the plane. + This method is deprecated, please use [method center] instead. @@ -80,7 +81,7 @@ - Returns [code]true[/code] if [code]point[/code] is inside the plane (by a very minimum [code]epsilon[/code] threshold). + Returns [code]true[/code] if [code]point[/code] is inside the plane. Comparison uses a custom minimum [code]epsilon[/code] threshold. @@ -147,36 +148,38 @@ - Returns the orthogonal projection of point [code]p[/code] into a point in the plane. + Returns the orthogonal projection of [code]point[/code] into a point in the plane. - Distance from the origin to the plane, in the direction of [member normal]. + The distance from the origin to the plane, in the direction of [member normal]. This value is typically non-negative. + In the scalar equation of the plane [code]ax + by + cz = d[/code], this is [code]d[/code], while the [code](a, b, c)[/code] coordinates are represented by the [member normal] property. - The normal of the plane. "Over" or "Above" the plane is considered the side of the plane towards where the normal is pointing. + The normal of the plane, which must be normalized. + In the scalar equation of the plane [code]ax + by + cz = d[/code], this is the vector [code](a, b, c)[/code], where [code]d[/code] is the [member d] property. - The [member normal]'s X component. + The X component of the plane's [member normal] vector. - The [member normal]'s Y component. + The Y component of the plane's [member normal] vector. - The [member normal]'s Z component. + The Z component of the plane's [member normal] vector. - A plane that extends in the Y and Z axes. + A plane that extends in the Y and Z axes (normal vector points +X). - A plane that extends in the X and Z axes. + A plane that extends in the X and Z axes (normal vector points +Y). - A plane that extends in the X and Y axes. + A plane that extends in the X and Y axes (normal vector points +Z). diff --git a/doc/classes/Quat.xml b/doc/classes/Quat.xml index a4540becab8..abc2ecc0e5a 100644 --- a/doc/classes/Quat.xml +++ b/doc/classes/Quat.xml @@ -4,9 +4,9 @@ Quaternion. - A unit quaternion used for representing 3D rotations. - It is similar to [Basis], which implements matrix representation of rotations, and can be parametrized using both an axis-angle pair or Euler angles. But 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. - Quaternions need to be (re)normalized. + 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. https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html#interpolating-with-quaternions @@ -18,7 +18,7 @@ - Returns the rotation matrix corresponding to the given quaternion. + Constructs a quaternion from the given [Basis]. @@ -27,7 +27,7 @@ - Returns a quaternion that will perform a rotation specified by Euler angles (in the YXZ convention: first Z, then X, and Y last), given in the vector format as (X angle, Y angle, Z angle). + 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). @@ -38,7 +38,7 @@ - Returns a quaternion that will rotate around the given axis by the specified angle. The axis must be a normalized vector. + Constructs a quaternion that will rotate around the given axis by the specified angle. The axis must be a normalized vector. @@ -53,7 +53,7 @@ - Returns a quaternion defined by these values. + Constructs a quaternion defined by the given values. @@ -68,7 +68,7 @@ - Performs a cubic spherical-linear interpolation with another quaternion. + Performs a cubic spherical interpolation between quaternions [code]preA[/code], this vector, [code]b[/code], and [code]postB[/code], by the given amount [code]t[/code]. @@ -84,7 +84,7 @@ - Returns Euler angles (in the YXZ convention: 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). + 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). @@ -144,7 +144,7 @@ - Sets the quaternion to a rotation specified by Euler angles (in the YXZ convention: first Z, then X, and Y last), given in the vector format as (X angle, Y angle, Z angle). + Sets the quaternion to 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). @@ -155,7 +155,8 @@ - Performs a spherical-linear interpolation with another quaternion. + Returns the result of the spherical linear interpolation between this quaternion and [code]to[/code] by amount [code]weight[/code]. + [b]Note:[/b] Both quaternions must be normalized. @@ -166,7 +167,7 @@ - Performs a spherical-linear interpolation with another quaterion without checking if the rotation path is not bigger than 90°. + Returns the result of the spherical linear interpolation between this quaternion and [code]to[/code] by amount [code]weight[/code], but without checking if the rotation path is not bigger than 90 degrees. @@ -175,27 +176,31 @@ - Transforms the vector [code]v[/code] by this quaternion. + Returns a vector transformed (multiplied) by this quaternion. - W component of the quaternion. + W component of the quaternion (real part). + Quaternion components should usually not be manipulated directly. - X component of the quaternion. + X component of the quaternion (imaginary [code]i[/code] axis part). + Quaternion components should usually not be manipulated directly. - Y component of the quaternion. + Y component of the quaternion (imaginary [code]j[/code] axis part). + Quaternion components should usually not be manipulated directly. - Z component of the quaternion. + Z component of the quaternion (imaginary [code]k[/code] axis part). + Quaternion components should usually not be manipulated directly. - The identity rotation. Equivalent to an identity matrix. If a vector is transformed by an identity quaternion, it will not change. + The identity quaternion, representing no rotation. Equivalent to an identity [Basis] matrix. If a vector is transformed by an identity quaternion, it will not change. diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml index d3624031ec5..ce622db5106 100644 --- a/doc/classes/Rect2.xml +++ b/doc/classes/Rect2.xml @@ -161,13 +161,14 @@ - Ending corner. + Ending corner. This is calculated as [code]position + size[/code]. Setting this value will change the size. - Position (starting corner). + Beginning corner. Typically has values lower than [member end]. - Size from position to end. + Size from [member position] to [member end]. Typically all components are positive. + If the size is negative, you can use [method abs] to fix it. diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml index e3166a177db..5729226d122 100644 --- a/doc/classes/Transform.xml +++ b/doc/classes/Transform.xml @@ -4,10 +4,12 @@ 3D transformation (3×4 matrix). - Represents one or many transformations in 3D space such as translation, rotation, or scaling. It consists of a [member basis] and an [member origin]. It is similar to a 3×4 matrix. + 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 [member basis] (first 3 columns) and a [Vector3] for the [member origin] (last column). + For more information, read the "Matrices and transforms" documentation article. https://docs.godotengine.org/en/latest/tutorials/math/index.html + https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html @@ -23,7 +25,7 @@ - Constructs the Transform from four [Vector3]. Each axis corresponds to local basis vectors (some of which may be scaled). + Constructs a Transform from four [Vector3] values (matrix columns). Each axis corresponds to local basis vectors (some of which may be scaled). @@ -34,7 +36,7 @@ - Constructs the Transform from a [Basis] and [Vector3]. + Constructs a Transform from a [Basis] and [Vector3]. @@ -43,7 +45,7 @@ - Constructs the Transform from a [Transform2D]. + Constructs a Transform from a [Transform2D]. @@ -52,7 +54,7 @@ - Constructs the Transform from a [Quat]. The origin will be Vector3(0, 0, 0). + Constructs a Transform from a [Quat]. The origin will be [code]Vector3(0, 0, 0)[/code]. @@ -79,7 +81,7 @@ - Interpolates the transform to other Transform by weight amount (0-1). + Interpolates the transform to other Transform by weight amount (on the range of 0.0 to 1.0). @@ -172,7 +174,7 @@ The basis is a matrix containing 3 [Vector3] as its columns: X axis, Y axis, and Z axis. These vectors can be interpreted as the basis vectors of local coordinate system traveling with the object. - The translation offset of the transform. + The translation offset of the transform (column 3, the fourth column). Equivalent to array index [code]3[/code]. diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index 4a7ba611600..292ad716dc7 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -1,12 +1,14 @@ - 2D transformation (3×2 matrix). + 2D transformation (2×3 matrix). - Represents one or many transformations in 2D space such as translation, rotation, or scaling. It consists of two [member x] and [member y] [Vector2]s and an [member origin]. It is similar to a 3×2 matrix. + 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 [Vector2] values: [member x], [member y], and the [member origin]. + For more information, read the "Matrices and transforms" documentation article. + https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html @@ -28,7 +30,7 @@ - Constructs the transform from 3 [Vector2]s representing x, y, and origin. + Constructs the transform from 3 [Vector2] values representing [member x], [member y], and the [member origin] (the three column vectors). @@ -46,7 +48,7 @@ - Returns the inverse of the matrix. + Returns the inverse of the transform, under the assumption that the transformation is composed of rotation, scaling and translation. @@ -55,7 +57,8 @@ - Transforms the given vector by this transform's basis (no translation). + Returns a vector transformed (multiplied) by the basis matrix. + This method does not account for translation (the origin vector). @@ -64,7 +67,8 @@ - Inverse-transforms the given vector by this transform's basis (no translation). + Returns a vector transformed (multiplied) by the inverse basis matrix. + This method does not account for translation (the origin vector). @@ -96,14 +100,14 @@ - Returns a transform interpolated between this transform and another by a given weight (0-1). + Returns a transform interpolated between this transform and another by a given weight (on the range of 0.0 to 1.0). - Returns the inverse of the transform, under the assumption that the transformation is composed of rotation and translation (no scaling, use affine_inverse for transforms with scaling). + Returns the inverse of the transform, under the assumption that the transformation is composed of rotation and translation (no scaling, use [method affine_inverse] for transforms with scaling). @@ -119,7 +123,7 @@ - Returns the transform with the basis orthogonal (90 degrees), and normalized axis vectors. + Returns the transform with the basis orthogonal (90 degrees), and normalized axis vectors (scale of 1 or -1). @@ -171,24 +175,24 @@ - The transform's translation offset. + The origin vector (column 2, the third column). Equivalent to array index [code]2[/code]. The origin vector represents translation. - The X axis of 2×2 basis matrix containing 2 [Vector2]s as its columns: X axis and Y axis. These vectors can be interpreted as the basis vectors of local coordinate system traveling with the object. + The basis matrix's X vector (column 0). Equivalent to array index [code]0[/code]. - The Y axis of 2×2 basis matrix containing 2 [Vector2]s as its columns: X axis and Y axis. These vectors can be interpreted as the basis vectors of local coordinate system traveling with the object. + The basis matrix's Y vector (column 1). Equivalent to array index [code]1[/code]. - [Transform2D] with no translation, rotation or scaling applied. When applied to other data structures, [constant IDENTITY] performs no transformation. + The identity [Transform2D] with no translation, rotation or scaling applied. When applied to other data structures, [constant IDENTITY] performs no transformation. - [Transform2D] with mirroring applied parallel to the X axis. + The [Transform2D] that will flip something along the X axis. - [Transform2D] with mirroring applied parallel to the Y axis. + The [Transform2D] that will flip something along the Y axis. diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index d67a72e2de2..6ea12c6965d 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -33,7 +33,7 @@ - Returns the vector's angle in radians with respect to the X axis, or [code](1, 0)[/code] vector. + Returns this vector's angle with respect to the X axis, or [code](1, 0)[/code] vector, in radians. Equivalent to the result of [method @GDScript.atan2] when called with the vector's [member y] and [member x] as parameters: [code]atan2(y, x)[/code]. @@ -43,7 +43,7 @@ - Returns the angle in radians between the two vectors. + Returns the angle to the given vector, in radians. @@ -52,14 +52,14 @@ - Returns the angle in radians between the line connecting the two points and the X coordinate. + Returns the angle between the line connecting the two points and the X axis, in radians. - Returns the ratio of [member x] to [member y]. + Returns the aspect ratio of this vector, the ratio of [member x] to [member y]. @@ -75,7 +75,7 @@ - Returns the vector with all components rounded up. + Returns the vector with all components rounded up (towards positive infinity). @@ -84,7 +84,7 @@ - Returns the vector with a maximum length. + Returns the vector with a maximum length by limiting its length to [code]length[/code]. @@ -93,7 +93,7 @@ - Returns the 2-dimensional analog of the cross product with the given vector. + Returns the cross product of this vector and [code]with[/code]. @@ -108,7 +108,7 @@ - Cubically interpolates between this vector and [code]b[/code] using [code]pre_a[/code] and [code]post_b[/code] as handles, and returns the result at position [code]t[/code]. [code]t[/code] is in the range of [code]0.0 - 1.0[/code], representing the amount of interpolation. + Cubically interpolates between this vector and [code]b[/code] using [code]pre_a[/code] and [code]post_b[/code] as handles, and returns the result at position [code]t[/code]. [code]t[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. @@ -126,7 +126,8 @@ - Returns the squared distance to vector [code]b[/code]. Prefer this function over [method distance_to] if you need to sort vectors or need the squared distance for some formula. + Returns the squared distance between this vector and [code]b[/code]. + This method runs faster than [method distance_to], so prefer it if you need to compare vectors or need the squared distance for some formula. @@ -135,7 +136,7 @@ - Returns the distance to vector [code]b[/code]. + Returns the distance between this vector and [code]to[/code]. @@ -144,14 +145,17 @@ - Returns the dot product with vector [code]b[/code]. + Returns the dot product of this vector and [code]with[/code]. This can be used to compare the angle between two vectors. For example, this can be used to determine whether an enemy is facing the player. + The dot product will be [code]0[/code] for a straight angle (90 degrees), greater than 0 for angles narrower than 90 degrees and lower than 0 for angles wider than 90 degrees. + When using unit (normalized) vectors, the result will always be between [code]-1.0[/code] (180 degree angle) when the vectors are facing opposite directions, and [code]1.0[/code] (0 degree angle) when the vectors are aligned. + [b]Note:[/b] [code]a.dot(b)[/code] is equivalent to [code]b.dot(a)[/code]. - Returns the vector with all components rounded down. + Returns the vector with all components rounded down (towards negative infinity). @@ -167,21 +171,22 @@ - Returns [code]true[/code] if the vector is normalized. + Returns [code]true[/code] if the vector is normalized, and false otherwise. - Returns the vector's length. + Returns the length (magnitude) of this vector. - Returns the vector's length squared. Prefer this method over [method length] if you need to sort vectors or need the squared length for some formula. + Returns the squared length (squared magnitude) of this vector. + This method runs faster than [method length], so prefer it if you need to compare vectors or need the squared distance for some formula. @@ -192,7 +197,7 @@ - Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]t[/code]. [code]t[/code] is in the range of [code]0.0 - 1.0[/code], representing the amount of interpolation. + Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]t[/code]. [code]t[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. @@ -219,7 +224,7 @@ - Returns a vector composed of the [code]fposmod[/code] of this vector's components and [code]mod[/code]. + Returns a vector composed of the [method @GDScript.fposmod] of this vector's components and [code]mod[/code]. @@ -228,7 +233,7 @@ - Returns a vector composed of the [code]fposmod[/code] of this vector's components and [code]modv[/code]'s components. + Returns a vector composed of the [method @GDScript.fposmod] of this vector's components and [code]modv[/code]'s components. @@ -269,7 +274,7 @@ - Returns the vector with each component set to one or negative one, depending on the signs of the components. + Returns the vector with each component set to one or negative one, depending on the signs of the components, or zero if the component is zero, by calling [method @GDScript.sign] on each component. @@ -280,7 +285,7 @@ - Returns the result of spherical linear interpolation between this vector and [code]b[/code], by amount [code]t[/code]. [code]t[/code] is in the range of [code]0.0 - 1.0[/code], representing the amount of interpolation. + Returns the result of spherical linear interpolation between this vector and [code]b[/code], by amount [code]t[/code]. [code]t[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. [b]Note:[/b] Both vectors must be normalized. @@ -290,7 +295,7 @@ - Returns the component of the vector along a plane defined by the given normal. + Returns this vector slid along a plane defined by the given normal. @@ -299,14 +304,14 @@ - Returns the vector snapped to a grid with the given size. + Returns this vector with each component snapped to the nearest multiple of [code]step[/code]. This can also be used to round to an arbitrary number of decimals. - Returns a perpendicular vector. + Returns a perpendicular vector rotated 90 degrees counter-clockwise compared to the original, with the same length. @@ -326,25 +331,25 @@ Enumerated value for the Y axis. - Zero vector. + Zero vector, a vector with all components set to [code]0[/code]. - One vector. + One vector, a vector with all components set to [code]1[/code]. - Infinity vector. + Infinity vector, a vector with all components set to [constant @GDScript.INF]. - Left unit vector. + Left unit vector. Represents the direction of left. - Right unit vector. + Right unit vector. Represents the direction of right. - Up unit vector. + Up unit vector. Y is down in 2D, so this vector points -Y. - Down unit vector. + Down unit vector. Y is down in 2D, so this vector points +Y. diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index 5d192008263..f78295bd7eb 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -37,7 +37,7 @@ - Returns the minimum angle to the given vector. + Returns the minimum angle to the given vector, in radians. @@ -53,7 +53,7 @@ - Returns a new vector with all components rounded up. + Returns a new vector with all components rounded up (towards positive infinity). @@ -62,7 +62,7 @@ - Returns the cross product with [code]b[/code]. + Returns the cross product of this vector and [code]b[/code]. @@ -77,7 +77,7 @@ - Performs a cubic interpolation between vectors [code]pre_a[/code], [code]a[/code], [code]b[/code], [code]post_b[/code] ([code]a[/code] is current), by the given amount [code]t[/code]. [code]t[/code] is in the range of [code]0.0 - 1.0[/code], representing the amount of interpolation. + Performs a cubic interpolation between vectors [code]pre_a[/code], [code]a[/code], [code]b[/code], [code]post_b[/code] ([code]a[/code] is current), by the given amount [code]t[/code]. [code]t[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. @@ -95,7 +95,8 @@ - Returns the squared distance to [code]b[/code]. Prefer this function over [method distance_to] if you need to sort vectors or need the squared distance for some formula. + Returns the squared distance between this vector and [code]b[/code]. + This method runs faster than [method distance_to], so prefer it if you need to compare vectors or need the squared distance for some formula. @@ -104,7 +105,7 @@ - Returns the distance to [code]b[/code]. + Returns the distance between this vector and [code]b[/code]. @@ -113,14 +114,17 @@ - Returns the dot product with [code]b[/code]. + Returns the dot product of this vector and [code]b[/code]. This can be used to compare the angle between two vectors. For example, this can be used to determine whether an enemy is facing the player. + The dot product will be [code]0[/code] for a straight angle (90 degrees), greater than 0 for angles narrower than 90 degrees and lower than 0 for angles wider than 90 degrees. + When using unit (normalized) vectors, the result will always be between [code]-1.0[/code] (180 degree angle) when the vectors are facing opposite directions, and [code]1.0[/code] (0 degree angle) when the vectors are aligned. + [b]Note:[/b] [code]a.dot(b)[/code] is equivalent to [code]b.dot(a)[/code]. - Returns a new vector with all components rounded down. + Returns a new vector with all components rounded down (towards negative infinity). @@ -143,21 +147,22 @@ - Returns [code]true[/code] if the vector is normalized. + Returns [code]true[/code] if the vector is normalized, and false otherwise. - Returns the vector's length. + Returns the length (magnitude) of this vector. - Returns the vector's length squared. Prefer this function over [method length] if you need to sort vectors or need the squared length for some formula. + Returns the squared length (squared magnitude) of this vector. + This method runs faster than [method length], so prefer it if you need to compare vectors or need the squared distance for some formula. @@ -168,21 +173,21 @@ - Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]t[/code]. [code]t[/code] is in the range of [code]0.0 - 1.0[/code], representing the amount of interpolation.. + Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]t[/code]. [code]t[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. - Returns the axis of the vector's largest value. See [code]AXIS_*[/code] constants. + Returns the axis of the vector's largest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_X]. - Returns the axis of the vector's smallest value. See [code]AXIS_*[/code] constants. + Returns the axis of the vector's smallest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_Z]. @@ -193,7 +198,7 @@ - Moves the vector toward [code]to[/code] by the fixed [code]delta[/code] amount. + Moves this vector toward [code]to[/code] by the fixed [code]delta[/code] amount. @@ -218,7 +223,7 @@ - Returns a vector composed of the [code]fposmod[/code] of this vector's components and [code]mod[/code]. + Returns a vector composed of the [method @GDScript.fposmod] of this vector's components and [code]mod[/code]. @@ -227,7 +232,7 @@ - Returns a vector composed of the [code]fposmod[/code] of this vector's components and [code]modv[/code]'s components. + Returns a vector composed of the [method @GDScript.fposmod] of this vector's components and [code]modv[/code]'s components. @@ -236,7 +241,7 @@ - Returns the vector projected onto the vector [code]b[/code]. + Returns this vector projected onto another vector [code]b[/code]. @@ -245,7 +250,7 @@ - Returns the vector reflected from a plane defined by the given normal. + Returns this vector reflected from a plane defined by the given normal. @@ -256,21 +261,21 @@ - Rotates the vector around a given axis by [code]phi[/code] radians. The axis must be a normalized vector. + Rotates this vector around a given axis by [code]phi[/code] radians. The axis must be a normalized vector. - Returns the vector with all components rounded to the nearest integer, with halfway cases rounded away from zero. + Returns this vector with all components rounded to the nearest integer, with halfway cases rounded away from zero. - Returns the vector with each component set to one or negative one, depending on the signs of the components. + 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 [method @GDScript.sign] on each component. @@ -281,7 +286,7 @@ - Returns the result of spherical linear interpolation between this vector and [code]b[/code], by amount [code]t[/code]. [code]t[/code] is in the range of [code]0.0 - 1.0[/code], representing the amount of interpolation. + Returns the result of spherical linear interpolation between this vector and [code]b[/code], by amount [code]t[/code]. [code]t[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. [b]Note:[/b] Both vectors must be normalized. @@ -291,7 +296,7 @@ - Returns the component of the vector along a plane defined by the given normal. + Returns this vector slid along a plane defined by the given normal. @@ -300,7 +305,7 @@ - Returns the vector snapped to a grid with the given size. + Returns this vector with each component snapped to the nearest multiple of [code]step[/code]. This can also be used to round to an arbitrary number of decimals. @@ -308,6 +313,7 @@ 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. @@ -333,19 +339,19 @@ Enumerated value for the Z axis. Returned by [method max_axis] and [method min_axis]. - Zero vector. + Zero vector, a vector with all components set to [code]0[/code]. - One vector. + One vector, a vector with all components set to [code]1[/code]. - Infinity vector. + Infinity vector, a vector with all components set to [constant @GDScript.INF]. - Left unit vector. + Left unit vector. Represents the local direction of left, and the global direction of west. - Right unit vector. + Right unit vector. Represents the local direction of right, and the global direction of east. Up unit vector. @@ -354,10 +360,10 @@ Down unit vector. - Forward unit vector. + Forward unit vector. Represents the local direction of forward, and the global direction of north. - Back unit vector. + Back unit vector. Represents the local direction of back, and the global direction of south. diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 80923532846..e1fa7536302 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -52,7 +52,7 @@ - Returns the absolute value of parameter [code]s[/code] (i.e. unsigned value, works for integer and float). + Returns the absolute value of parameter [code]s[/code] (i.e. positive value). [codeblock] # a is 1 a = abs(-1) @@ -112,7 +112,7 @@ Returns the arc tangent of [code]s[/code] in radians. Use it to get the angle from an angle's tangent in trigonometry: [code]atan(tan(angle)) == angle[/code]. - The method cannot know in which quadrant the angle should fall. See [method atan2] if you always want an exact angle. + The method cannot know in which quadrant the angle should fall. See [method atan2] if you have both [code]y[code] and [code]x[/code]. [codeblock] a = atan(0.5) # a is 0.463648 [/codeblock] @@ -127,6 +127,7 @@ Returns the arc tangent of [code]y/x[/code] in radians. Use to get the angle of tangent [code]y/x[/code]. 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. [codeblock] a = atan2(0, -1) # a is 3.141593 [/codeblock] @@ -161,7 +162,7 @@ - Rounds [code]s[/code] upward, returning the smallest integral value that is not less than [code]s[/code]. + Rounds [code]s[/code] upward (towards positive infinity), returning the smallest whole number that is not less than [code]s[/code]. [codeblock] i = ceil(1.45) # i is 2 i = ceil(1.001) # i is 2 @@ -292,7 +293,7 @@ - Returns degrees converted to radians. + Converts an angle expressed in degrees to radians. [codeblock] # r is 3.141593 r = deg2rad(180) @@ -316,7 +317,7 @@ - Easing function, based on exponent. 0 is constant, 1 is linear, 0 to 1 is ease-in, 1+ is ease out. Negative values are in-out/out in. + Easing function, based on exponent. The curve values are: 0 is constant, 1 is linear, 0 to 1 is ease-in, 1+ is ease out. Negative values are in-out/out in. @@ -339,7 +340,7 @@ - Rounds [code]s[/code] to the closest smaller integer and returns it. + Rounds [code]s[/code] downward (towards negative infinity), returning the largest whole number that is not more than [code]s[/code]. [codeblock] # a is 2.0 a = floor(2.99) @@ -539,7 +540,7 @@ - Returns whether [code]s[/code] is a NaN (Not-A-Number) value. + Returns whether [code]s[/code] is a NaN ("Not a Number" or invalid) value. @@ -549,6 +550,7 @@ Returns [code]true[/code] if [code]s[/code] is zero or almost zero. + This method is faster than using [method is_equal_approx] with one value as zero. @@ -916,7 +918,7 @@ - Converts from radians to degrees. + Converts an angle expressed in radians to degrees. [codeblock] rad2deg(0.523599) # Returns 30 [/codeblock] @@ -1035,7 +1037,7 @@ - Returns the integral value that is nearest to [code]s[/code], with halfway cases rounded away from zero. + Rounds [code]s[/code] to the nearest whole number, with halfway cases rounded away from zero. [codeblock] round(2.6) # Returns 3 [/codeblock] @@ -1117,10 +1119,11 @@ - Returns the square root of [code]s[/code]. + Returns the square root of [code]s[/code], where [code]s[/code] is a non-negative number. [codeblock] sqrt(9) # Returns 3 [/codeblock] + If you need negative inputs, use [code]System.Numerics.Complex[/code] in C#. @@ -1321,27 +1324,19 @@ Wraps float [code]value[/code] between [code]min[/code] and [code]max[/code]. Usable for creating loop-alike behavior or infinite surfaces. [codeblock] - # a is 0.5 - a = wrapf(10.5, 0.0, 10.0) - [/codeblock] - [codeblock] - # a is 9.5 - a = wrapf(-0.5, 0.0, 10.0) - [/codeblock] - [codeblock] - # Infinite loop between 0.0 and 0.99 - f = wrapf(f + 0.1, 0.0, 1.0) + # Infinite loop between 5.0 and 9.9 + value = wrapf(value + 0.1, 5.0, 10.0) [/codeblock] [codeblock] # Infinite rotation (in radians) angle = wrapf(angle + 0.1, 0.0, TAU) [/codeblock] - [b]Note:[/b] If you just want to wrap between 0.0 and [code]n[/code] (where [code]n[/code] is a positive floating-point value), it is better for performance to use the [method fmod] method like [code]fmod(number, n)[/code]. - [code]wrapf[/code] is more flexible than using the [method fmod] approach by giving the user a simple control over the minimum value. It also fully supports negative numbers, e.g. [codeblock] # Infinite rotation (in radians) angle = wrapf(angle + 0.1, -PI, PI) [/codeblock] + [b]Note:[/b] If [code]min[/code] is [code]0[/code], this is equivalent to [method fposmod], so prefer using that instead. + [code]wrapf[/code] is more flexible than using the [method fposmod] approach by giving the user control over the minimum value. @@ -1357,23 +1352,15 @@ Wraps integer [code]value[/code] between [code]min[/code] and [code]max[/code]. Usable for creating loop-alike behavior or infinite surfaces. [codeblock] - # a is 0 - a = wrapi(10, 0, 10) + # Infinite loop between 5 and 9 + frame = wrapi(frame + 1, 5, 10) [/codeblock] [codeblock] - # a is 9 - a = wrapi(-1, 0, 10) - [/codeblock] - [codeblock] - # Infinite loop between 0 and 9 - frame = wrapi(frame + 1, 0, 10) - [/codeblock] - [b]Note:[/b] If you just want to wrap between 0 and [code]n[/code] (where [code]n[/code] is a positive integer value), it is better for performance to use the modulo operator like [code]number % n[/code]. - [code]wrapi[/code] is more flexible than using the modulo approach by giving the user a simple control over the minimum value. It also fully supports negative numbers, e.g. - [codeblock] # result is -2 var result = wrapi(-6, -5, -1) [/codeblock] + [b]Note:[/b] If [code]min[/code] is [code]0[/code], this is equivalent to [method posmod], so prefer using that instead. + [code]wrapi[/code] is more flexible than using the [method posmod] approach by giving the user control over the minimum value. @@ -1415,17 +1402,16 @@ - Constant that represents how many times the diameter of a circle fits around its perimeter. + Constant that represents how many times the diameter of a circle fits around its perimeter. This is equivalent to [code]TAU / 2[/code]. - The circle constant, the circumference of the unit circle. + The circle constant, the circumference of the unit circle in radians. - A positive infinity. (For negative infinity, use -INF). + Positive infinity. For negative infinity, use -INF. - Macro constant that expands to an expression of type float that represents a NaN. - The NaN values are used to identify undefined or non-representable values for floating-point elements, such as the square root of negative numbers or the result of 0/0. + "Not a Number", an invalid value. [code]NaN[/code] has special properties, including that it is not equal to itself. It is output by some invalid operations, such as dividing zero by zero. From e10a1e078f835934d39f7e575904939e9019bb7d Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Tue, 21 Jul 2020 20:10:35 -0400 Subject: [PATCH 2/2] [3.2] Add C# XML documentation to core C# math types --- .../glue/GodotSharp/GodotSharp/Core/AABB.cs | 234 ++++++++++- .../glue/GodotSharp/GodotSharp/Core/Basis.cs | 301 ++++++++++++-- .../glue/GodotSharp/GodotSharp/Core/Color.cs | 276 ++++++++++++- .../glue/GodotSharp/GodotSharp/Core/Colors.cs | 4 + .../glue/GodotSharp/GodotSharp/Core/Mathf.cs | 329 ++++++++++++++- .../GodotSharp/GodotSharp/Core/MathfEx.cs | 49 +++ .../glue/GodotSharp/GodotSharp/Core/Plane.cs | 149 ++++++- .../glue/GodotSharp/GodotSharp/Core/Quat.cs | 230 +++++++++-- .../glue/GodotSharp/GodotSharp/Core/Rect2.cs | 183 ++++++++- .../GodotSharp/GodotSharp/Core/Transform.cs | 142 ++++++- .../GodotSharp/GodotSharp/Core/Transform2D.cs | 180 +++++++- .../GodotSharp/GodotSharp/Core/Vector2.cs | 371 +++++++++++++++-- .../GodotSharp/GodotSharp/Core/Vector3.cs | 387 +++++++++++++++--- 13 files changed, 2605 insertions(+), 230 deletions(-) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs index 6a4f7855517..3aecce50f54 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs @@ -14,6 +14,10 @@ using real_t = System.Single; namespace Godot { + /// + /// Axis-Aligned Bounding Box. AABB consists of a position, a size, and + /// several utility functions. It is typically used for fast overlap tests. + /// [Serializable] [StructLayout(LayoutKind.Sequential)] public struct AABB : IEquatable @@ -21,24 +25,55 @@ namespace Godot private Vector3 _position; private Vector3 _size; + /// + /// Beginning corner. Typically has values lower than End. + /// + /// Directly uses a private field. public Vector3 Position { get { return _position; } set { _position = value; } } + /// + /// Size from Position to End. Typically all components are positive. + /// If the size is negative, you can use to fix it. + /// + /// Directly uses a private field. public Vector3 Size { get { return _size; } set { _size = value; } } + /// + /// Ending corner. This is calculated as plus + /// . Setting this value will change the size. + /// + /// Getting is equivalent to `value = Position + Size`, setting is equivalent to `Size = value - Position`. public Vector3 End { get { return _position + _size; } set { _size = value - _position; } } + /// + /// Returns an AABB with equivalent position and size, modified so that + /// the most-negative corner is the origin and the size is positive. + /// + /// The modified AABB. + 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()); + } + + /// + /// Returns true if this AABB completely encloses another one. + /// + /// The other AABB that may be enclosed. + /// A bool for whether or not this AABB encloses `b`. public bool Encloses(AABB with) { Vector3 src_min = _position; @@ -54,33 +89,59 @@ namespace Godot src_max.z > dst_max.z; } + /// + /// Returns this AABB expanded to include a given point. + /// + /// The point to include. + /// The expanded AABB. 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); } + /// + /// Returns the area of the AABB. + /// + /// The area. public real_t GetArea() { return _size.x * _size.y * _size.z; } + /// + /// Gets the position of one of the 8 endpoints of the AABB. + /// + /// Which endpoint to get. + /// An endpoint of the AABB. public Vector3 GetEndpoint(int idx) { switch (idx) @@ -106,6 +167,10 @@ namespace Godot } } + /// + /// Returns the normalized longest axis of the AABB. + /// + /// A vector representing the normalized longest axis of the AABB. public Vector3 GetLongestAxis() { var axis = new Vector3(1f, 0f, 0f); @@ -125,6 +190,10 @@ namespace Godot return axis; } + /// + /// Returns the index of the longest axis of the AABB. + /// + /// A index for which axis is longest. public Vector3.Axis GetLongestAxisIndex() { var axis = Vector3.Axis.X; @@ -144,6 +213,10 @@ namespace Godot return axis; } + /// + /// Returns the scalar length of the longest axis of the AABB. + /// + /// The scalar length of the longest axis of the AABB. public real_t GetLongestAxisSize() { real_t max_size = _size.x; @@ -157,6 +230,10 @@ namespace Godot return max_size; } + /// + /// Returns the normalized shortest axis of the AABB. + /// + /// A vector representing the normalized shortest axis of the AABB. public Vector3 GetShortestAxis() { var axis = new Vector3(1f, 0f, 0f); @@ -176,6 +253,10 @@ namespace Godot return axis; } + /// + /// Returns the index of the shortest axis of the AABB. + /// + /// A index for which axis is shortest. public Vector3.Axis GetShortestAxisIndex() { var axis = Vector3.Axis.X; @@ -195,6 +276,10 @@ namespace Godot return axis; } + /// + /// Returns the scalar length of the shortest axis of the AABB. + /// + /// The scalar length of the shortest axis of the AABB. public real_t GetShortestAxisSize() { real_t max_size = _size.x; @@ -208,6 +293,12 @@ namespace Godot return max_size; } + /// + /// Returns the support point in a given direction. + /// This is useful for collision detection algorithms. + /// + /// The direction to find support for. + /// A vector representing the support. 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); } + /// + /// Returns a copy of the AABB grown a given amount of units towards all the sides. + /// + /// The amount to grow by. + /// The grown AABB. public AABB Grow(real_t by) { var res = this; @@ -233,16 +329,29 @@ namespace Godot return res; } + /// + /// Returns true if the AABB is flat or empty, or false otherwise. + /// + /// A bool for whether or not the AABB has area. public bool HasNoArea() { return _size.x <= 0f || _size.y <= 0f || _size.z <= 0f; } + /// + /// Returns true if the AABB has no surface (no size), or false otherwise. + /// + /// A bool for whether or not the AABB has area. public bool HasNoSurface() { return _size.x <= 0f && _size.y <= 0f && _size.z <= 0f; } + /// + /// Returns true if the AABB contains a point, or false otherwise. + /// + /// The point to check. + /// A bool for whether or not the AABB contains `point`. public bool HasPoint(Vector3 point) { if (point.x < _position.x) @@ -261,6 +370,11 @@ namespace Godot return true; } + /// + /// Returns the intersection of this AABB and `b`. + /// + /// The other AABB. + /// The clipped AABB. 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) + /// + /// 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. + /// + /// The other AABB to check for intersections with. + /// Whether or not to consider borders. + /// A bool for whether or not they are intersecting. + 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; } + /// + /// Returns true if the AABB is on both sides of `plane`. + /// + /// The plane to check for intersection. + /// A bool for whether or not the AABB intersects the plane. 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; } + /// + /// Returns true if the AABB intersects the line segment between `from` and `to`. + /// + /// The start of the line segment. + /// The end of the line segment. + /// A bool for whether or not the AABB intersects the line segment. 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; } + /// + /// Returns a larger AABB that contains this AABB and `b`. + /// + /// The other AABB. + /// The merged AABB. public AABB Merge(AABB with) { Vector3 beg1 = _position; @@ -411,22 +581,52 @@ namespace Godot return new AABB(min, max - min); } - // Constructors + /// + /// Constructs an AABB from a position and size. + /// + /// The position. + /// The size, typically positive. public AABB(Vector3 position, Vector3 size) { _position = position; _size = size; } + + /// + /// Constructs an AABB from a position, width, height, and depth. + /// + /// The position. + /// The width, typically positive. + /// The height, typically positive. + /// The depth, typically positive. public AABB(Vector3 position, real_t width, real_t height, real_t depth) { _position = position; _size = new Vector3(width, height, depth); } + + /// + /// Constructs an AABB from x, y, z, and size. + /// + /// The position's X coordinate. + /// The position's Y coordinate. + /// The position's Z coordinate. + /// The size, typically positive. public AABB(real_t x, real_t y, real_t z, Vector3 size) { _position = new Vector3(x, y, z); _size = size; } + + /// + /// Constructs an AABB from x, y, z, width, height, and depth. + /// + /// The position's X coordinate. + /// The position's Y coordinate. + /// The position's Z coordinate. + /// The width, typically positive. + /// The height, typically positive. + /// The depth, typically positive. 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; } + /// + /// Returns true if this AABB and `other` are approximately equal, by running + /// on each component. + /// + /// The other AABB to compare. + /// Whether or not the AABBs are approximately equal. public bool IsEqualApprox(AABB other) { return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other._size); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs index 55408fecb8a..bbc4dfdfeb6 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs @@ -8,6 +8,20 @@ using real_t = System.Single; namespace Godot { + /// + /// 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 + /// [Serializable] [StructLayout(LayoutKind.Sequential)] public struct Basis : IEquatable @@ -15,9 +29,9 @@ namespace Godot // NOTE: x, y and z are public-only. Use Column0, Column1 and Column2 internally. /// - /// Returns the basis matrix’s x vector. - /// This is equivalent to . + /// The basis matrix's X vector (column 0). /// + /// Equivalent to and array index `[0]`. public Vector3 x { get => Column0; @@ -25,9 +39,9 @@ namespace Godot } /// - /// Returns the basis matrix’s y vector. - /// This is equivalent to . + /// The basis matrix's Y vector (column 1). /// + /// Equivalent to and array index `[1]`. public Vector3 y { get => Column1; @@ -35,19 +49,40 @@ namespace Godot } /// - /// Returns the basis matrix’s z vector. - /// This is equivalent to . + /// The basis matrix's Z vector (column 2). /// + /// Equivalent to and array index `[2]`. public Vector3 z { get => Column2; set => Column2 = value; } + /// + /// 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. + /// public Vector3 Row0; + + /// + /// 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. + /// public Vector3 Row1; + + /// + /// 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. + /// public Vector3 Row2; + /// + /// Column 0 of the basis matrix (the X vector). + /// + /// Equivalent to and array index `[0]`. public Vector3 Column0 { get => new Vector3(Row0.x, Row1.x, Row2.x); @@ -58,6 +93,11 @@ namespace Godot this.Row2.x = value.z; } } + + /// + /// Column 1 of the basis matrix (the Y vector). + /// + /// Equivalent to and array index `[1]`. public Vector3 Column1 { get => new Vector3(Row0.y, Row1.y, Row2.y); @@ -68,6 +108,11 @@ namespace Godot this.Row2.y = value.z; } } + + /// + /// Column 2 of the basis matrix (the Z vector). + /// + /// Equivalent to and array index `[2]`. public Vector3 Column2 { get => new Vector3(Row0.z, Row1.z, Row2.z); @@ -79,6 +124,10 @@ namespace Godot } } + /// + /// The scale of this basis. + /// + /// Equivalent to the lengths of each column vector, but negative if the determinant is negative. 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; + } } /// @@ -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); } + /// + /// 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. + /// + /// The determinant of the basis matrix. 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; } + /// + /// 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 method instead, which + /// returns a quaternion instead of Euler angles. + /// + /// A Vector3 representing the basis rotation in Euler angles. public Vector3 GetEuler() { Basis m = Orthonormalized(); @@ -223,6 +299,12 @@ namespace Godot return euler; } + /// + /// Get rows by index. Rows are not very useful for user code, + /// but are more efficient for some internal calculations. + /// + /// Which row. + /// One of `Row0`, `Row1`, or `Row2`. public Vector3 GetRow(int index) { switch (index) @@ -238,6 +320,12 @@ namespace Godot } } + /// + /// Sets rows by index. Rows are not very useful for user code, + /// but are more efficient for some internal calculations. + /// + /// Which row. + /// The vector to set the row to. public void SetRow(int index, Vector3 value) { switch (index) @@ -256,22 +344,49 @@ namespace Godot } } + /// + /// Deprecated, please use the array operator instead. + /// + /// Which column. + /// One of `Column0`, `Column1`, or `Column2`. + [Obsolete("GetColumn is deprecated. Use the array operator instead.")] public Vector3 GetColumn(int index) { return this[index]; } + /// + /// Deprecated, please use the array operator instead. + /// + /// Which column. + /// The vector to set the column to. + [Obsolete("SetColumn is deprecated. Use the array operator instead.")] public void SetColumn(int index, Vector3 value) { this[index] = value; } - [Obsolete("GetAxis is deprecated. Use GetColumn instead.")] + /// + /// Deprecated, please use the array operator instead. + /// + /// Which column. + /// One of `Column0`, `Column1`, or `Column2`. + [Obsolete("GetAxis is deprecated. Use the array operator instead.")] public Vector3 GetAxis(int axis) { return new Vector3(this.Row0[axis], this.Row1[axis], this.Row2[axis]); } + /// + /// 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 editor. + /// + /// For further details, refer to the Godot source code. + /// + /// The orthogonal index. public int GetOrthogonalIndex() { var orth = this; @@ -285,11 +400,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; @@ -300,12 +421,18 @@ namespace Godot for (int i = 0; i < 24; i++) { if (orth == _orthoBases[i]) + { return i; + } } return 0; } + /// + /// Returns the inverse of the matrix. + /// + /// The inverse matrix. public Basis Inverse() { real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1]; @@ -315,7 +442,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; @@ -334,11 +463,17 @@ namespace Godot ); } + /// + /// 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. + /// + /// An orthonormalized basis matrix. 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); @@ -349,48 +484,86 @@ namespace Godot return new Basis(column0, column1, column2); } + /// + /// Introduce an additional rotation around the given `axis` + /// by `phi` (in radians). The axis must be a normalized vector. + /// + /// The axis to rotate around. Must be normalized. + /// The angle to rotate, in radians. + /// The rotated basis matrix. public Basis Rotated(Vector3 axis, real_t phi) { return new Basis(axis, phi) * this; } + /// + /// Introduce an additional scaling specified by the given 3D scaling factor. + /// + /// The scale to introduce. + /// The scaled basis matrix. 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) + /// + /// Assuming that the matrix is a proper rotation matrix, slerp performs + /// a spherical-linear interpolation with another rotation matrix. + /// + /// The destination basis for interpolation. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting basis matrix of the interpolation. + 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; } + /// + /// Transposed dot product with the X axis of the matrix. + /// + /// A vector to calculate the dot product with. + /// The resulting dot product. public real_t Tdotx(Vector3 with) { return this.Row0[0] * with[0] + this.Row1[0] * with[1] + this.Row2[0] * with[2]; } + /// + /// Transposed dot product with the Y axis of the matrix. + /// + /// A vector to calculate the dot product with. + /// The resulting dot product. public real_t Tdoty(Vector3 with) { return this.Row0[1] * with[0] + this.Row1[1] * with[1] + this.Row2[1] * with[2]; } + /// + /// Transposed dot product with the Z axis of the matrix. + /// + /// A vector to calculate the dot product with. + /// The resulting dot product. public real_t Tdotz(Vector3 with) { return this.Row0[2] * with[0] + this.Row1[2] * with[1] + this.Row2[2] * with[2]; } + /// + /// Returns the transposed version of the basis matrix. + /// + /// The transposed basis matrix. public Basis Transposed() { var tr = this; @@ -410,6 +583,11 @@ namespace Godot return tr; } + /// + /// Returns a vector transformed (multiplied) by the basis matrix. + /// + /// A vector to transform. + /// The transfomed vector. public Vector3 Xform(Vector3 v) { return new Vector3 @@ -420,6 +598,14 @@ namespace Godot ); } + /// + /// 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. + /// + /// A vector to inversely transform. + /// The inversely transfomed vector. public Vector3 XformInv(Vector3 v) { return new Vector3 @@ -430,6 +616,12 @@ namespace Godot ); } + /// + /// Returns the basis's rotation in the form of a quaternion. + /// See if you need Euler angles, but keep in + /// mind that quaternions should generally be preferred to Euler angles. + /// + /// A representing the basis's rotation. public Quat Quat() { real_t trace = Row0[0] + Row1[1] + Row2[2]; @@ -514,11 +706,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); + /// + /// 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. + /// + /// Equivalent to `new Basis(Vector3.Right, Vector3.Up, Vector3.Back)`. public static Basis Identity { get { return _identity; } } + /// + /// The basis that will flip something along the X axis when used in a transformation. + /// + /// Equivalent to `new Basis(Vector3.Left, Vector3.Up, Vector3.Back)`. public static Basis FlipX { get { return _flipX; } } + /// + /// The basis that will flip something along the Y axis when used in a transformation. + /// + /// Equivalent to `new Basis(Vector3.Right, Vector3.Down, Vector3.Back)`. public static Basis FlipY { get { return _flipY; } } + /// + /// The basis that will flip something along the Z axis when used in a transformation. + /// + /// Equivalent to `new Basis(Vector3.Right, Vector3.Up, Vector3.Forward)`. public static Basis FlipZ { get { return _flipZ; } } + /// + /// Constructs a pure rotation basis matrix from the given quaternion. + /// + /// The quaternion to create the basis from. public Basis(Quat quat) { real_t s = 2.0f / quat.LengthSquared; @@ -541,26 +755,41 @@ namespace Godot Row2 = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy)); } - public Basis(Vector3 euler) + /// + /// 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 constructor instead, which + /// uses a quaternion instead of Euler angles. + /// + /// The Euler angles to create the basis from. + 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; } + /// + /// Constructs a pure rotation basis matrix, rotated around the given `axis` + /// by `phi` (in radians). The axis must be a normalized vector. + /// + /// The axis to rotate around. Must be normalized. + /// The angle to rotate, in radians. public Basis(Vector3 axis, real_t phi) { Vector3 axisSq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z); @@ -588,6 +817,12 @@ namespace Godot Row2.y = xyzt + zyxs; } + /// + /// Constructs a basis matrix from 3 axis vectors (matrix columns). + /// + /// The X vector, or Column0. + /// The Y vector, or Column1. + /// The Z vector, or Column2. public Basis(Vector3 column0, Vector3 column1, Vector3 column2) { Row0 = new Vector3(column0.x, column1.x, column2.x); @@ -643,6 +878,12 @@ namespace Godot return Row0.Equals(other.Row0) && Row1.Equals(other.Row1) && Row2.Equals(other.Row2); } + /// + /// Returns true if this basis and `other` are approximately equal, by running + /// on each component. + /// + /// The other basis to compare. + /// Whether or not the matrices are approximately equal. public bool IsEqualApprox(Basis other) { return Row0.IsEqualApprox(other.Row0) && Row1.IsEqualApprox(other.Row1) && Row2.IsEqualApprox(other.Row2); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs index 0462ef11259..59b67e3315d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs @@ -3,15 +3,44 @@ using System.Runtime.InteropServices; namespace Godot { + /// + /// A color represented by red, green, blue, and alpha (RGBA) components. + /// The alpha component is often used for transparency. + /// Values are in floating-point and usually range from 0 to 1. + /// Some properties (such as CanvasItem.modulate) may accept values + /// greater than 1 (overbright or HDR colors). + /// + /// If you want to supply values in a range of 0 to 255, you should use + /// and the `r8`/`g8`/`b8`/`a8` properties. + /// [Serializable] [StructLayout(LayoutKind.Sequential)] public struct Color : IEquatable { + /// + /// The color's red component, typically on the range of 0 to 1. + /// public float r; + + /// + /// The color's green component, typically on the range of 0 to 1. + /// public float g; + + /// + /// The color's blue component, typically on the range of 0 to 1. + /// public float b; + + /// + /// The color's alpha (transparency) component, typically on the range of 0 to 1. + /// public float a; + /// + /// Wrapper for that uses the range 0 to 255 instead of 0 to 1. + /// + /// Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255. public int r8 { get @@ -24,6 +53,10 @@ namespace Godot } } + /// + /// Wrapper for that uses the range 0 to 255 instead of 0 to 1. + /// + /// Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255. public int g8 { get @@ -36,6 +69,10 @@ namespace Godot } } + /// + /// Wrapper for that uses the range 0 to 255 instead of 0 to 1. + /// + /// Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255. public int b8 { get @@ -48,6 +85,10 @@ namespace Godot } } + /// + /// Wrapper for that uses the range 0 to 255 instead of 0 to 1. + /// + /// Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255. public int a8 { get @@ -60,6 +101,10 @@ namespace Godot } } + /// + /// The HSV hue of this color, on the range 0 to 1. + /// + /// Getting is a long process, refer to the source code for details. Setting uses . public float h { get @@ -70,21 +115,31 @@ namespace Godot float delta = max - min; if (delta == 0) + { return 0; + } float h; if (r == max) + { h = (g - b) / delta; // Between yellow & magenta + } else if (g == max) + { h = 2 + (b - r) / delta; // Between cyan & yellow + } else + { h = 4 + (r - g) / delta; // Between magenta & cyan + } h /= 6.0f; if (h < 0) + { h += 1.0f; + } return h; } @@ -94,6 +149,10 @@ namespace Godot } } + /// + /// The HSV saturation of this color, on the range 0 to 1. + /// + /// Getting is equivalent to the ratio between the min and max RGB value. Setting uses . public float s { get @@ -103,7 +162,7 @@ namespace Godot float delta = max - min; - return max != 0 ? delta / max : 0; + return max == 0 ? 0 : delta / max; } set { @@ -111,6 +170,10 @@ namespace Godot } } + /// + /// The HSV value (brightness) of this color, on the range 0 to 1. + /// + /// Getting is equivalent to using `Max()` on the RGB components. Setting uses . public float v { get @@ -123,6 +186,14 @@ namespace Godot } } + /// + /// Returns a color according to the standardized name, with the + /// specified alpha value. Supported color names are the same as + /// the constants defined in . + /// + /// The name of the color. + /// The alpha (transparency) component represented on the range of 0 to 1. Default: 1. + /// The constructed color. public static Color ColorN(string name, float alpha = 1f) { name = name.Replace(" ", String.Empty); @@ -142,6 +213,10 @@ namespace Godot return color; } + /// + /// Access color components using their index. + /// + /// `[0]` is equivalent to `.r`, `[1]` is equivalent to `.g`, `[2]` is equivalent to `.b`, `[3]` is equivalent to `.a`. public float this[int index] { get @@ -182,6 +257,13 @@ namespace Godot } } + /// + /// Converts a color to HSV values. This is equivalent to using each of + /// the `h`/`s`/`v` properties, but much more efficient. + /// + /// Output parameter for the HSV hue. + /// Output parameter for the HSV saturation. + /// Output parameter for the HSV value. public void ToHsv(out float hue, out float saturation, out float value) { float max = (float)Mathf.Max(r, Mathf.Max(g, b)); @@ -212,6 +294,16 @@ namespace Godot value = max; } + /// + /// Constructs a color from an HSV profile, with values on the + /// range of 0 to 1. This is equivalent to using each of + /// the `h`/`s`/`v` properties, but much more efficient. + /// + /// The HSV hue, typically on the range of 0 to 1. + /// The HSV saturation, typically on the range of 0 to 1. + /// The HSV value (brightness), typically on the range of 0 to 1. + /// The alpha (transparency) value, typically on the range of 0 to 1. + /// The constructed color. public static Color FromHsv(float hue, float saturation, float value, float alpha = 1.0f) { if (saturation == 0) @@ -249,6 +341,13 @@ namespace Godot } } + /// + /// Returns a new color resulting from blending this color over another. + /// If the color is opaque, the result is also opaque. + /// The second color may have a range of alpha values. + /// + /// The color to blend over. + /// This color blended over `over`. public Color Blend(Color over) { Color res; @@ -268,6 +367,10 @@ namespace Godot return res; } + /// + /// Returns the most contrasting color. + /// + /// The most contrasting color public Color Contrasted() { return new Color( @@ -278,6 +381,12 @@ namespace Godot ); } + /// + /// Returns a new color resulting from making this color darker + /// by the specified ratio (on the range of 0 to 1). + /// + /// The ratio to darken by. + /// The darkened color. public Color Darkened(float amount) { Color res = this; @@ -287,6 +396,10 @@ namespace Godot return res; } + /// + /// Returns the inverted color: `(1 - r, 1 - g, 1 - b, a)`. + /// + /// The inverted color. public Color Inverted() { return new Color( @@ -297,6 +410,12 @@ namespace Godot ); } + /// + /// Returns a new color resulting from making this color lighter + /// by the specified ratio (on the range of 0 to 1). + /// + /// The ratio to lighten by. + /// The darkened color. public Color Lightened(float amount) { Color res = this; @@ -306,18 +425,48 @@ namespace Godot return res; } - public Color LinearInterpolate(Color c, float t) + /// + /// Returns the result of the linear interpolation between + /// this color and `to` by amount `weight`. + /// + /// The destination color for interpolation. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting color of the interpolation. + public Color LinearInterpolate(Color to, float weight) { - var res = this; - - res.r += t * (c.r - r); - res.g += t * (c.g - g); - res.b += t * (c.b - b); - res.a += t * (c.a - a); - - return res; + return new Color + ( + Mathf.Lerp(r, to.r, weight), + Mathf.Lerp(g, to.g, weight), + Mathf.Lerp(b, to.b, weight), + Mathf.Lerp(a, to.a, weight) + ); } + /// + /// Returns the result of the linear interpolation between + /// this color and `to` by color amount `weight`. + /// + /// The destination color for interpolation. + /// A color with components on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting color of the interpolation. + public Color LinearInterpolate(Color to, Color weight) + { + return new Color + ( + Mathf.Lerp(r, to.r, weight.r), + Mathf.Lerp(g, to.g, weight.g), + Mathf.Lerp(b, to.b, weight.b), + Mathf.Lerp(a, to.a, weight.a) + ); + } + + /// + /// Returns the color's 32-bit integer in ABGR format + /// (each byte represents a component of the ABGR profile). + /// ABGR is the reversed version of the default format. + /// + /// An int representing this color in ABGR32 format. public int ToAbgr32() { int c = (byte)Math.Round(a * 255); @@ -331,6 +480,12 @@ namespace Godot return c; } + /// + /// Returns the color's 64-bit integer in ABGR format + /// (each byte represents a component of the ABGR profile). + /// ABGR is the reversed version of the default format. + /// + /// An int representing this color in ABGR64 format. public long ToAbgr64() { long c = (ushort)Math.Round(a * 65535); @@ -344,6 +499,12 @@ namespace Godot return c; } + /// + /// Returns the color's 32-bit integer in ARGB format + /// (each byte represents a component of the ARGB profile). + /// ARGB is more compatible with DirectX, but not used much in Godot. + /// + /// An int representing this color in ARGB32 format. public int ToArgb32() { int c = (byte)Math.Round(a * 255); @@ -357,6 +518,12 @@ namespace Godot return c; } + /// + /// Returns the color's 64-bit integer in ARGB format + /// (each word represents a component of the ARGB profile). + /// ARGB is more compatible with DirectX, but not used much in Godot. + /// + /// A long representing this color in ARGB64 format. public long ToArgb64() { long c = (ushort)Math.Round(a * 65535); @@ -370,6 +537,12 @@ namespace Godot return c; } + /// + /// Returns the color's 32-bit integer in RGBA format + /// (each byte represents a component of the RGBA profile). + /// RGBA is Godot's default and recommended format. + /// + /// An int representing this color in RGBA32 format. public int ToRgba32() { int c = (byte)Math.Round(r * 255); @@ -383,6 +556,12 @@ namespace Godot return c; } + /// + /// Returns the color's 64-bit integer in RGBA format + /// (each word represents a component of the RGBA profile). + /// RGBA is Godot's default and recommended format. + /// + /// A long representing this color in RGBA64 format. public long ToRgba64() { long c = (ushort)Math.Round(r * 65535); @@ -396,6 +575,11 @@ namespace Godot return c; } + /// + /// Returns the color's HTML hexadecimal color string in RGBA format. + /// + /// Whether or not to include alpha. If false, the color is RGB instead of RGBA. + /// A string for the HTML hexadecimal representation of this color. public string ToHtml(bool includeAlpha = true) { var txt = string.Empty; @@ -410,7 +594,13 @@ namespace Godot return txt; } - // Constructors + /// + /// Constructs a color from RGBA values on the range of 0 to 1. + /// + /// The color's red component, typically on the range of 0 to 1. + /// The color's green component, typically on the range of 0 to 1. + /// The color's blue component, typically on the range of 0 to 1. + /// The color's alpha (transparency) value, typically on the range of 0 to 1. Default: 1. public Color(float r, float g, float b, float a = 1.0f) { this.r = r; @@ -419,6 +609,24 @@ namespace Godot this.a = a; } + /// + /// Constructs a color from an existing color and an alpha value. + /// + /// The color to construct from. Only its RGB values are used. + /// The color's alpha (transparency) value, typically on the range of 0 to 1. Default: 1. + public Color(Color c, float a = 1.0f) + { + r = c.r; + g = c.g; + b = c.b; + this.a = a; + } + + /// + /// Constructs a color from a 32-bit integer + /// (each byte represents a component of the RGBA profile). + /// + /// The int representing the color. public Color(int rgba) { a = (rgba & 0xFF) / 255.0f; @@ -430,6 +638,11 @@ namespace Godot r = (rgba & 0xFF) / 255.0f; } + /// + /// Constructs a color from a 64-bit integer + /// (each word represents a component of the RGBA profile). + /// + /// The long representing the color. public Color(long rgba) { a = (rgba & 0xFFFF) / 65535.0f; @@ -470,9 +683,13 @@ namespace Godot } if (i == 0) + { ig += v * 16; + } else + { ig += v; + } } return ig; @@ -490,9 +707,13 @@ namespace Godot int lv = v & 0xF; if (lv < 10) + { c = (char)('0' + lv); + } else + { c = (char)('a' + lv - 10); + } v >>= 4; ret = c + ret; @@ -504,10 +725,14 @@ namespace Godot internal static bool HtmlIsValid(string color) { if (color.Length == 0) + { return false; + } if (color[0] == '#') + { color = color.Substring(1, color.Length - 1); + } bool alpha; @@ -526,7 +751,9 @@ namespace Godot if (alpha) { if (ParseCol8(color, 0) < 0) + { return false; + } } int from = alpha ? 2 : 0; @@ -541,11 +768,24 @@ namespace Godot return true; } + /// + /// Returns a color constructed from integer red, green, blue, and alpha channels. + /// Each channel should have 8 bits of information ranging from 0 to 255. + /// + /// The red component represented on the range of 0 to 255. + /// The green component represented on the range of 0 to 255. + /// The blue component represented on the range of 0 to 255. + /// The alpha (transparency) component represented on the range of 0 to 255. + /// The constructed color. public static Color Color8(byte r8, byte g8, byte b8, byte a8 = 255) { return new Color(r8 / 255f, g8 / 255f, b8 / 255f, a8 / 255f); } + /// + /// Constructs a color from the HTML hexadecimal color string in RGBA format. + /// + /// A string for the HTML hexadecimal representation of this color. public Color(string rgba) { if (rgba.Length == 0) @@ -690,13 +930,13 @@ namespace Godot if (Mathf.IsEqualApprox(left.g, right.g)) { if (Mathf.IsEqualApprox(left.b, right.b)) + { return left.a < right.a; + } return left.b < right.b; } - return left.g < right.g; } - return left.r < right.r; } @@ -707,13 +947,13 @@ namespace Godot if (Mathf.IsEqualApprox(left.g, right.g)) { if (Mathf.IsEqualApprox(left.b, right.b)) + { return left.a > right.a; + } return left.b > right.b; } - return left.g > right.g; } - return left.r > right.r; } @@ -732,6 +972,12 @@ namespace Godot return r == other.r && g == other.g && b == other.b && a == other.a; } + /// + /// Returns true if this color and `other` are approximately equal, by running + /// on each component. + /// + /// The other color to compare. + /// Whether or not the colors are approximately equal. public bool IsEqualApprox(Color other) { return Mathf.IsEqualApprox(r, other.r) && Mathf.IsEqualApprox(g, other.g) && Mathf.IsEqualApprox(b, other.b) && Mathf.IsEqualApprox(a, other.a); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs index f41f5e9fc84..d05a0414aa5 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs @@ -3,6 +3,10 @@ using System.Collections.Generic; namespace Godot { + /// + /// This class contains color constants created from standardized color names. + /// The standardized color set is based on the X11 and .NET color names. + /// public static class Colors { // Color names and values are derived from core/color_names.inc diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs index 4f7aa99df86..6eecc262d6c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs @@ -11,79 +11,185 @@ namespace Godot { // Define constants with Decimal precision and cast down to double or float. + /// + /// The circle constant, the circumference of the unit circle in radians. + /// public const real_t Tau = (real_t) 6.2831853071795864769252867666M; // 6.2831855f and 6.28318530717959 + + /// + /// Constant that represents how many times the diameter of a circle + /// fits around its perimeter. This is equivalent to `Mathf.Tau / 2`. + /// public const real_t Pi = (real_t) 3.1415926535897932384626433833M; // 3.1415927f and 3.14159265358979 + + /// + /// Positive infinity. For negative infinity, use `-Mathf.Inf`. + /// public const real_t Inf = real_t.PositiveInfinity; + + /// + /// "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. + /// 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 + /// + /// Returns the absolute value of `s` (i.e. positive value). + /// + /// The input number. + /// The absolute value of `s`. public static int Abs(int s) { return Math.Abs(s); } + /// + /// Returns the absolute value of `s` (i.e. positive value). + /// + /// The input number. + /// The absolute value of `s`. public static real_t Abs(real_t s) { return Math.Abs(s); } + /// + /// Returns the arc cosine of `s` in radians. Use to get the angle of cosine s. + /// + /// The input cosine value. Must be on the range of -1.0 to 1.0. + /// An angle that would result in the given cosine value. On the range `0` to `Tau/2`. public static real_t Acos(real_t s) { return (real_t)Math.Acos(s); } + /// + /// Returns the arc sine of `s` in radians. Use to get the angle of sine s. + /// + /// The input sine value. Must be on the range of -1.0 to 1.0. + /// An angle that would result in the given sine value. On the range `-Tau/4` to `Tau/4`. public static real_t Asin(real_t s) { return (real_t)Math.Asin(s); } + /// + /// 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 if you have both `y` and `x`. + /// + /// The input tangent value. + /// An angle that would result in the given tangent value. On the range `-Tau/4` to `Tau/4`. public static real_t Atan(real_t s) { return (real_t)Math.Atan(s); } + /// + /// 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. + /// + /// The Y coordinate of the point to find the angle to. + /// The X coordinate of the point to find the angle to. + /// An angle that would result in the given tangent value. On the range `-Tau/2` to `Tau/2`. public static real_t Atan2(real_t y, real_t x) { return (real_t)Math.Atan2(y, x); } + /// + /// 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). + /// + /// The input X coordinate. + /// The input Y coordinate. + /// A with X representing the distance and Y representing the angle. public static Vector2 Cartesian2Polar(real_t x, real_t y) { return new Vector2(Sqrt(x * x + y * y), Atan2(y, x)); } + /// + /// Rounds `s` upward (towards positive infinity). + /// + /// The number to ceil. + /// The smallest whole number that is not less than `s`. public static real_t Ceil(real_t s) { return (real_t)Math.Ceiling(s); } + /// + /// Clamps a `value` so that it is not less than `min` and not more than `max`. + /// + /// The value to clamp. + /// The minimum allowed value. + /// The maximum allowed value. + /// The clamped value. public static int Clamp(int value, int min, int max) { return value < min ? min : value > max ? max : value; } + /// + /// Clamps a `value` so that it is not less than `min` and not more than `max`. + /// + /// The value to clamp. + /// The minimum allowed value. + /// The maximum allowed value. + /// The clamped value. public static real_t Clamp(real_t value, real_t min, real_t max) { return value < min ? min : value > max ? max : value; } + /// + /// Returns the cosine of angle `s` in radians. + /// + /// The angle in radians. + /// The cosine of that angle. public static real_t Cos(real_t s) { return (real_t)Math.Cos(s); } + /// + /// Returns the hyperbolic cosine of angle `s` in radians. + /// + /// The angle in radians. + /// The hyperbolic cosine of that angle. public static real_t Cosh(real_t s) { return (real_t)Math.Cosh(s); } + /// + /// Converts an angle expressed in degrees to radians. + /// + /// An angle expressed in degrees. + /// The same angle expressed in radians. public static real_t Deg2Rad(real_t deg) { return deg * Deg2RadConst; } + /// + /// 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. + /// + /// The value to ease. + /// `0` is constant, `1` is linear, `0` to `1` is ease-in, `1` or more is ease-out. + /// The eased value. public static real_t Ease(real_t s, real_t curve) { if (s < 0f) @@ -118,21 +224,47 @@ namespace Godot return 0f; } + /// + /// The natural exponential function. It raises the mathematical + /// constant `e` to the power of `s` and returns it. + /// + /// The exponent to raise `e` to. + /// `e` raised to the power of `s`. public static real_t Exp(real_t s) { return (real_t)Math.Exp(s); } + /// + /// Rounds `s` downward (towards negative infinity). + /// + /// The number to floor. + /// The largest whole number that is not more than `s`. public static real_t Floor(real_t s) { return (real_t)Math.Floor(s); } + /// + /// Returns a normalized value considering the given range. + /// This is the opposite of . + /// + /// The interpolated value. + /// The destination value for interpolation. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting value of the inverse interpolation. public static real_t InverseLerp(real_t from, real_t to, real_t weight) { return (weight - from) / (to - from); } + /// + /// Returns true if `a` and `b` are approximately equal to each other. + /// The comparison is done using a tolerance calculation with . + /// + /// One of the values. + /// The other value. + /// A bool for whether or not the two values are approximately equal. 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; } + /// + /// Returns whether `s` is an infinity value (either positive infinity or negative infinity). + /// + /// The value to check. + /// A bool for whether or not the value is an infinity value. public static bool IsInf(real_t s) { return real_t.IsInfinity(s); } + /// + /// Returns whether `s` is a `NaN` ("Not a Number" or invalid) value. + /// + /// The value to check. + /// A bool for whether or not the value is a `NaN` value. public static bool IsNaN(real_t s) { return real_t.IsNaN(s); } + /// + /// Returns true if `s` is approximately zero. + /// The comparison is done using a tolerance calculation with . + /// + /// This method is faster than using with one value as zero. + /// + /// The value to check. + /// A bool for whether or not the value is nearly zero. public static bool IsZeroApprox(real_t s) { return Abs(s) < Epsilon; } + /// + /// Linearly interpolates between two values by a normalized value. + /// This is the opposite . + /// + /// The start value for interpolation. + /// The destination value for interpolation. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting value of the interpolation. public static real_t Lerp(real_t from, real_t to, real_t weight) { return from + (to - from) * weight; } + /// + /// Linearly interpolates between two angles (in radians) by a normalized value. + /// + /// Similar to , + /// but interpolates correctly when the angles wrap around . + /// + /// The start angle for interpolation. + /// The destination angle for interpolation. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting angle of the interpolation. 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; } + /// + /// 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. + /// + /// The input value. + /// The natural log of `s`. public static real_t Log(real_t s) { return (real_t)Math.Log(s); } + /// + /// Returns the maximum of two values. + /// + /// One of the values. + /// The other value. + /// Whichever of the two values is higher. public static int Max(int a, int b) { return a > b ? a : b; } + /// + /// Returns the maximum of two values. + /// + /// One of the values. + /// The other value. + /// Whichever of the two values is higher. public static real_t Max(real_t a, real_t b) { return a > b ? a : b; } + /// + /// Returns the minimum of two values. + /// + /// One of the values. + /// The other value. + /// Whichever of the two values is lower. public static int Min(int a, int b) { return a < b ? a : b; } + /// + /// Returns the minimum of two values. + /// + /// One of the values. + /// The other value. + /// Whichever of the two values is lower. public static real_t Min(real_t a, real_t b) { return a < b ? a : b; } + /// + /// Moves `from` toward `to` by the `delta` value. + /// + /// Use a negative delta value to move away. + /// + /// The start value. + /// The value to move towards. + /// The amount to move by. + /// The value after moving. 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; } + /// + /// Returns the nearest larger power of 2 for the integer `value`. + /// + /// The input value. + /// The nearest larger power of 2. public static int NearestPo2(int value) { value--; @@ -218,14 +431,25 @@ namespace Godot return value; } + /// + /// 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). + /// + /// The distance from the origin. + /// The angle of the point. + /// A representing the cartesian coordinate. public static Vector2 Polar2Cartesian(real_t r, real_t th) { return new Vector2(r * Cos(th), r * Sin(th)); } /// - /// 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)`. /// + /// The dividend, the primary input. + /// The divisor. The output is on the range `[0, b)`. + /// The resulting output. public static int PosMod(int a, int b) { int c = a % b; @@ -237,8 +461,11 @@ namespace Godot } /// - /// 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)`. /// + /// The dividend, the primary input. + /// The divisor. The output is on the range `[0, b)`. + /// The resulting output. public static real_t PosMod(real_t a, real_t b) { real_t c = a % b; @@ -249,43 +476,89 @@ namespace Godot return c; } + /// + /// Returns the result of `x` raised to the power of `y`. + /// + /// The base. + /// The exponent. + /// `x` raised to the power of `y`. public static real_t Pow(real_t x, real_t y) { return (real_t)Math.Pow(x, y); } + /// + /// Converts an angle expressed in radians to degrees. + /// + /// An angle expressed in radians. + /// The same angle expressed in degrees. public static real_t Rad2Deg(real_t rad) { return rad * Rad2DegConst; } + /// + /// Rounds `s` to the nearest whole number, + /// with halfway cases rounded towards the nearest multiple of two. + /// + /// The number to round. + /// The rounded number. public static real_t Round(real_t s) { return (real_t)Math.Round(s); } + /// + /// Returns the sign of `s`: `-1` or `1`. Returns `0` if `s` is `0`. + /// + /// The input number. + /// One of three possible values: `1`, `-1`, or `0`. public static int Sign(int s) { if (s == 0) return 0; return s < 0 ? -1 : 1; } + /// + /// Returns the sign of `s`: `-1` or `1`. Returns `0` if `s` is `0`. + /// + /// The input number. + /// One of three possible values: `1`, `-1`, or `0`. public static int Sign(real_t s) { if (s == 0) return 0; return s < 0 ? -1 : 1; } + /// + /// Returns the sine of angle `s` in radians. + /// + /// The angle in radians. + /// The sine of that angle. public static real_t Sin(real_t s) { return (real_t)Math.Sin(s); } + /// + /// Returns the hyperbolic sine of angle `s` in radians. + /// + /// The angle in radians. + /// The hyperbolic sine of that angle. public static real_t Sinh(real_t s) { return (real_t)Math.Sinh(s); } + /// + /// Returns a number smoothly interpolated between `from` and `to`, + /// based on the `weight`. Similar to , + /// but interpolates faster at the beginning and slower at the end. + /// + /// The start value for interpolation. + /// The destination value for interpolation. + /// A value representing the amount of interpolation. + /// The resulting value of the interpolation. 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); } + /// + /// Returns the square root of `s`, where `s` is a non-negative number. + /// + /// If you need negative inputs, use `System.Numerics.Complex`. + /// + /// The input number. Must not be negative. + /// The square root of `s`. public static real_t Sqrt(real_t s) { return (real_t)Math.Sqrt(s); } + /// + /// 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. + /// + /// The input value. + /// The position of the first non-zero digit. public static int StepDecimals(real_t step) { double[] sd = new double[] { @@ -326,32 +613,68 @@ namespace Godot return 0; } + /// + /// 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. + /// + /// The value to stepify. + /// The step size to snap to. + /// 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; } + /// + /// Returns the tangent of angle `s` in radians. + /// + /// The angle in radians. + /// The tangent of that angle. public static real_t Tan(real_t s) { return (real_t)Math.Tan(s); } + /// + /// Returns the hyperbolic tangent of angle `s` in radians. + /// + /// The angle in radians. + /// The hyperbolic tangent of that angle. public static real_t Tanh(real_t s) { return (real_t)Math.Tanh(s); } + /// + /// Wraps `value` between `min` and `max`. Usable for creating loop-alike + /// behavior or infinite surfaces. If `min` is `0`, this is equivalent + /// to , so prefer using that instead. + /// + /// The value to wrap. + /// The minimum allowed value and lower bound of the range. + /// The maximum allowed value and upper bound of the range. + /// The wrapped value. public static int Wrap(int value, int min, int max) { int range = max - min; return range == 0 ? min : min + ((value - min) % range + range) % range; } + /// + /// Wraps `value` between `min` and `max`. Usable for creating loop-alike + /// behavior or infinite surfaces. If `min` is `0`, this is equivalent + /// to , so prefer using that instead. + /// + /// The value to wrap. + /// The minimum allowed value and lower bound of the range. + /// The maximum allowed value and upper bound of the range. + /// The wrapped value. public static real_t Wrap(real_t value, real_t min, real_t max) { real_t range = max - min; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs index 1b7fd4906f6..c2f4701b5fa 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs @@ -12,40 +12,89 @@ namespace Godot { // Define constants with Decimal precision and cast down to double or float. + /// + /// The natural number `e`. + /// public const real_t E = (real_t) 2.7182818284590452353602874714M; // 2.7182817f and 2.718281828459045 + + /// + /// The square root of 2. + /// public const real_t Sqrt2 = (real_t) 1.4142135623730950488016887242M; // 1.4142136f and 1.414213562373095 + /// + /// 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`. + /// #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 + /// + /// Returns the amount of digits after the decimal place. + /// + /// The input value. + /// The amount of digits. public static int DecimalCount(real_t s) { return DecimalCount((decimal)s); } + /// + /// Returns the amount of digits after the decimal place. + /// + /// The input value. + /// The amount of digits. public static int DecimalCount(decimal s) { return BitConverter.GetBytes(decimal.GetBits(s)[3])[2]; } + /// + /// Rounds `s` upward (towards positive infinity). + /// + /// This is the same as , but returns an `int`. + /// + /// The number to ceil. + /// The smallest whole number that is not less than `s`. public static int CeilToInt(real_t s) { return (int)Math.Ceiling(s); } + /// + /// Rounds `s` downward (towards negative infinity). + /// + /// This is the same as , but returns an `int`. + /// + /// The number to floor. + /// The largest whole number that is not more than `s`. public static int FloorToInt(real_t s) { return (int)Math.Floor(s); } + /// + /// + /// + /// + /// public static int RoundToInt(real_t s) { return (int)Math.Round(s); } + /// + /// 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 . + /// + /// One of the values. + /// The other value. + /// The pre-calculated tolerance value. + /// A bool for whether or not the two values are equal. public static bool IsEqualApprox(real_t a, real_t b, real_t tolerance) { // Check for exact equality first, required to handle "infinity" values. diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs index 885845e3a46..cc273c906b1 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs @@ -8,18 +8,33 @@ using real_t = System.Single; namespace Godot { + /// + /// Plane represents a normalized plane equation. + /// "Over" or "Above" the plane is considered the side of + /// the plane towards where the normal is pointing. + /// [Serializable] [StructLayout(LayoutKind.Sequential)] public struct Plane : IEquatable { private Vector3 _normal; + /// + /// The normal of the plane, which must be normalized. + /// In the scalar equation of the plane `ax + by + cz = d`, this is + /// the vector `(a, b, c)`, where `d` is the property. + /// + /// Equivalent to `x`, `y`, and `z`. public Vector3 Normal { get { return _normal; } set { _normal = value; } } + /// + /// The X component of the plane's normal vector. + /// + /// Equivalent to 's X value. public real_t x { get @@ -32,6 +47,10 @@ namespace Godot } } + /// + /// The Y component of the plane's normal vector. + /// + /// Equivalent to 's Y value. public real_t y { get @@ -44,6 +63,10 @@ namespace Godot } } + /// + /// The Z component of the plane's normal vector. + /// + /// Equivalent to 's Z value. public real_t z { get @@ -56,38 +79,82 @@ namespace Godot } } + /// + /// The distance from the origin to the plane (in the direction of + /// ). This value is typically non-negative. + /// In the scalar equation of the plane `ax + by + cz = d`, + /// this is `d`, while the `(a, b, c)` coordinates are represented + /// by the property. + /// + /// The plane's distance from the origin. public real_t D { get; set; } + /// + /// The center of the plane, the point where the normal line intersects the plane. + /// + /// Equivalent to multiplied by `D`. public Vector3 Center { get { return _normal * D; } + set + { + _normal = value.Normalized(); + D = value.Length(); + } } + /// + /// Returns the shortest distance from this plane to the position `point`. + /// + /// The position to use for the calcualtion. + /// The shortest distance. public real_t DistanceTo(Vector3 point) { return _normal.Dot(point) - D; } + /// + /// The center of the plane, the point where the normal line intersects the plane. + /// Deprecated, use the Center property instead. + /// + /// Equivalent to multiplied by `D`. + [Obsolete("GetAnyPoint is deprecated. Use the Center property instead.")] public Vector3 GetAnyPoint() { return _normal * D; } + /// + /// Returns true if point is inside the plane. + /// Comparison uses a custom minimum epsilon threshold. + /// + /// The point to check. + /// The tolerance threshold. + /// A bool for whether or not the plane has the point. public bool HasPoint(Vector3 point, real_t epsilon = Mathf.Epsilon) { real_t dist = _normal.Dot(point) - D; return Mathf.Abs(dist) <= epsilon; } + /// + /// Returns the intersection point of the three planes: `b`, `c`, + /// and this plane. If no intersection is found, `null` is returned. + /// + /// One of the three planes to use in the calculation. + /// One of the three planes to use in the calculation. + /// The intersection, or `null` if none is found. 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 +163,94 @@ namespace Godot return result / denom; } + /// + /// 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. + /// + /// The start of the ray. + /// The direction of the ray, normalized. + /// The intersection, or `null` if none is found. 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; } + /// + /// 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. + /// + /// The start of the line segment. + /// The end of the line segment. + /// The intersection, or `null` if none is found. 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; } + /// + /// Returns true if `point` is located above the plane. + /// + /// The point to check. + /// A bool for whether or not the point is above the plane. public bool IsPointOver(Vector3 point) { return _normal.Dot(point) > D; } + /// + /// Returns the plane scaled to unit length. + /// + /// A normalized version of the plane. 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); } + /// + /// Returns the orthogonal projection of `point` into the plane. + /// + /// The point to project. + /// The projected point. public Vector3 Project(Vector3 point) { return point - _normal * DistanceTo(point); @@ -154,22 +261,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); + /// + /// A plane that extends in the Y and Z axes (normal vector points +X). + /// + /// Equivalent to `new Plane(1, 0, 0, 0)`. public static Plane PlaneYZ { get { return _planeYZ; } } + + /// + /// A plane that extends in the X and Z axes (normal vector points +Y). + /// + /// Equivalent to `new Plane(0, 1, 0, 0)`. public static Plane PlaneXZ { get { return _planeXZ; } } + + /// + /// A plane that extends in the X and Y axes (normal vector points +Z). + /// + /// Equivalent to `new Plane(0, 0, 1, 0)`. public static Plane PlaneXY { get { return _planeXY; } } - // Constructors + /// + /// Constructs a plane from four values. `a`, `b` and `c` become the + /// components of the resulting plane's vector. + /// `d` becomes the plane's distance from the origin. + /// + /// The X component of the plane's normal vector. + /// The Y component of the plane's normal vector. + /// The Z component of the plane's normal vector. + /// The plane's distance from the origin. This value is typically non-negative. public Plane(real_t a, real_t b, real_t c, real_t d) { _normal = new Vector3(a, b, c); this.D = d; } + + /// + /// Constructs a plane from a normal vector and the plane's distance to the origin. + /// + /// The normal of the plane, must be normalized. + /// The plane's distance from the origin. This value is typically non-negative. public Plane(Vector3 normal, real_t d) { this._normal = normal; this.D = d; } + /// + /// Constructs a plane from the three points, given in clockwise order. + /// + /// The first point. + /// The second point. + /// The third point. public Plane(Vector3 v1, Vector3 v2, Vector3 v3) { _normal = (v1 - v3).Cross(v1 - v2); @@ -207,6 +348,12 @@ namespace Godot return _normal == other._normal && D == other.D; } + /// + /// Returns true if this plane and `other` are approximately equal, by running + /// on each component. + /// + /// The other plane to compare. + /// Whether or not the planes are approximately equal. public bool IsEqualApprox(Plane other) { return _normal.IsEqualApprox(other._normal) && Mathf.IsEqualApprox(D, other.D); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs index 6702634c510..902c6b4662a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quat.cs @@ -8,15 +8,51 @@ using real_t = System.Single; namespace Godot { + /// + /// 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. + /// [Serializable] [StructLayout(LayoutKind.Sequential)] public struct Quat : IEquatable { + /// + /// X component of the quaternion (imaginary `i` axis part). + /// Quaternion components should usually not be manipulated directly. + /// public real_t x; + + /// + /// Y component of the quaternion (imaginary `j` axis part). + /// Quaternion components should usually not be manipulated directly. + /// public real_t y; + + /// + /// Z component of the quaternion (imaginary `k` axis part). + /// Quaternion components should usually not be manipulated directly. + /// public real_t z; + + /// + /// W component of the quaternion (real part). + /// Quaternion components should usually not be manipulated directly. + /// public real_t w; + /// + /// Access quaternion components using their index. + /// + /// `[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`, `[2]` is equivalent to `.z`, `[3]` is equivalent to `.w`. public real_t this[int index] { get @@ -57,16 +93,35 @@ namespace Godot } } + /// + /// Returns the length (magnitude) of the quaternion. + /// + /// Equivalent to `Mathf.Sqrt(LengthSquared)`. public real_t Length { get { return Mathf.Sqrt(LengthSquared); } } + /// + /// Returns the squared length (squared magnitude) of the quaternion. + /// This method runs faster than , so prefer it if + /// you need to compare quaternions or need the squared length for some formula. + /// + /// Equivalent to `Dot(this)`. public real_t LengthSquared { get { return Dot(this); } } + /// + /// Performs a cubic spherical interpolation between quaternions `preA`, + /// this vector, `b`, and `postB`, by the given amount `t`. + /// + /// The destination quaternion. + /// A quaternion before this quaternion. + /// A quaternion after `b`. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The interpolated quaternion. public Quat CubicSlerp(Quat b, Quat preA, Quat postB, real_t t) { real_t t2 = (1.0f - t) * t * 2f; @@ -75,30 +130,63 @@ namespace Godot return sp.Slerpni(sq, t2); } + /// + /// Returns the dot product of two quaternions. + /// + /// The other quaternion. + /// The dot product. public real_t Dot(Quat b) { return x * b.x + y * b.y + z * b.z + w * b.w; } + /// + /// 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). + /// + /// The Euler angle representation of this quaternion. public Vector3 GetEuler() { #if DEBUG if (!IsNormalized()) + { throw new InvalidOperationException("Quat is not normalized"); + } #endif var basis = new Basis(this); return basis.GetEuler(); } + /// + /// Returns the inverse of the quaternion. + /// + /// The inverse quaternion. public Quat Inverse() { #if DEBUG if (!IsNormalized()) + { throw new InvalidOperationException("Quat is not normalized"); + } #endif return new Quat(-x, -y, -z, w); } + /// + /// Returns whether the quaternion is normalized or not. + /// + /// A bool for whether the quaternion is normalized or not. + public bool IsNormalized() + { + return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon; + } + + /// + /// Returns a copy of the quaternion, normalized to unit length. + /// + /// The normalized quaternion. public Quat Normalized() { return this / Length; @@ -131,56 +219,69 @@ namespace Godot this = new Quat(eulerYXZ); } - public Quat Slerp(Quat b, real_t t) + /// + /// Returns the result of the spherical linear interpolation between + /// this quaternion and `to` by amount `weight`. + /// + /// Note: Both quaternions must be normalized. + /// + /// The destination quaternion for interpolation. Must be normalized. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting quaternion of the interpolation. + 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, @@ -190,9 +291,17 @@ namespace Godot ); } - public Quat Slerpni(Quat b, real_t t) + /// + /// 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. + /// + /// The destination quaternion for interpolation. Must be normalized. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting quaternion of the interpolation. + public Quat Slerpni(Quat to, real_t weight) { - real_t dot = Dot(b); + real_t dot = Dot(to); if (Mathf.Abs(dot) > 0.9999f) { @@ -201,33 +310,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 ); } + /// + /// Returns a vector transformed (multiplied) by this quaternion. + /// + /// A vector to transform. + /// The transfomed vector. 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 + /// + /// The identity quaternion, representing no rotation. + /// Equivalent to an identity matrix. If a vector is transformed by + /// an identity quaternion, it will not change. + /// + /// Equivalent to `new Quat(0, 0, 0, 1)`. + public static Quat Identity { get { return _identity; } } + + /// + /// Constructs a quaternion defined by the given values. + /// + /// X component of the quaternion (imaginary `i` axis part). + /// Y component of the quaternion (imaginary `j` axis part). + /// Z component of the quaternion (imaginary `k` axis part). + /// W component of the quaternion (real part). public Quat(real_t x, real_t y, real_t z, real_t w) { this.x = x; @@ -236,21 +366,31 @@ namespace Godot this.w = w; } - public bool IsNormalized() - { - return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon; - } - + /// + /// Constructs a quaternion from the given quaternion. + /// + /// The existing quaternion. public Quat(Quat q) { this = q; } + /// + /// Constructs a quaternion from the given . + /// + /// The basis to construct from. public Quat(Basis basis) { this = basis.Quat(); } + /// + /// 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). + /// + /// public Quat(Vector3 eulerYXZ) { real_t half_a1 = eulerYXZ.y * 0.5f; @@ -274,11 +414,19 @@ namespace Godot w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3; } + /// + /// Constructs a quaternion that will rotate around the given axis + /// by the specified angle. The axis must be a normalized vector. + /// + /// The axis to rotate around. Must be normalized. + /// The angle to rotate, in radians. 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(); @@ -391,6 +539,12 @@ namespace Godot return x == other.x && y == other.y && z == other.z && w == other.w; } + /// + /// Returns true if this quaternion and `other` are approximately equal, by running + /// on each component. + /// + /// The other quaternion to compare. + /// Whether or not the quaternions are approximately equal. 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); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs index 1098ffe4e5f..f7703c77cc4 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs @@ -8,6 +8,10 @@ using real_t = System.Single; namespace Godot { + /// + /// 2D axis-aligned bounding box. Rect2 consists of a position, a size, and + /// several utility functions. It is typically used for fast overlap tests. + /// [Serializable] [StructLayout(LayoutKind.Sequential)] public struct Rect2 : IEquatable @@ -15,29 +19,52 @@ namespace Godot private Vector2 _position; private Vector2 _size; + /// + /// Beginning corner. Typically has values lower than End. + /// + /// Directly uses a private field. public Vector2 Position { get { return _position; } set { _position = value; } } + /// + /// Size from Position to End. Typically all components are positive. + /// If the size is negative, you can use to fix it. + /// + /// Directly uses a private field. public Vector2 Size { get { return _size; } set { _size = value; } } + /// + /// Ending corner. This is calculated as plus + /// . Setting this value will change the size. + /// + /// Getting is equivalent to `value = Position + Size`, setting is equivalent to `Size = value - Position`. public Vector2 End { get { return _position + _size; } set { _size = value - _position; } } + /// + /// The area of this rect. + /// + /// Equivalent to . public real_t Area { get { return GetArea(); } } + /// + /// Returns a Rect2 with equivalent position and size, modified so that + /// the top-left corner is the origin and width and height are positive. + /// + /// The modified rect. public Rect2 Abs() { Vector2 end = End; @@ -45,12 +72,19 @@ namespace Godot return new Rect2(topLeft, _size.Abs()); } + /// + /// Returns the intersection of this Rect2 and `b`. + /// + /// The other rect. + /// The clipped rect. 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; } + /// + /// Returns true if this Rect2 completely encloses another one. + /// + /// The other rect that may be enclosed. + /// A bool for whether or not this rect encloses `b`. 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; } + /// + /// Returns this Rect2 expanded to include a given point. + /// + /// The point to include. + /// The expanded rect. 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; } + /// + /// Returns the area of the Rect2. + /// + /// The area. public real_t GetArea() { return _size.x * _size.y; } + /// + /// Returns a copy of the Rect2 grown a given amount of units towards all the sides. + /// + /// The amount to grow by. + /// The grown rect. public Rect2 Grow(real_t by) { var g = this; @@ -111,6 +172,14 @@ namespace Godot return g; } + /// + /// Returns a copy of the Rect2 grown a given amount of units towards each direction individually. + /// + /// The amount to grow by on the left. + /// The amount to grow by on the top. + /// The amount to grow by on the right. + /// The amount to grow by on the bottom. + /// The grown rect. 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; } + /// + /// Returns a copy of the Rect2 grown a given amount of units towards the direction. + /// + /// The direction to grow in. + /// The amount to grow by. + /// The grown rect. public Rect2 GrowMargin(Margin margin, real_t by) { var g = this; @@ -135,11 +210,20 @@ namespace Godot return g; } + /// + /// Returns true if the Rect2 is flat or empty, or false otherwise. + /// + /// A bool for whether or not the rect has area. public bool HasNoArea() { return _size.x <= 0 || _size.y <= 0; } + /// + /// Returns true if the Rect2 contains a point, or false otherwise. + /// + /// The point to check. + /// A bool for whether or not the rect contains `point`. public bool HasPoint(Vector2 point) { if (point.x < _position.x) @@ -155,20 +239,65 @@ namespace Godot return true; } - public bool Intersects(Rect2 b) + /// + /// 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. + /// + /// The other rect to check for intersections with. + /// Whether or not to consider borders. + /// A bool for whether or not they are intersecting. + 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; } + /// + /// Returns a larger Rect2 that contains this Rect2 and `b`. + /// + /// The other rect. + /// The merged rect. 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 + /// + /// Constructs a Rect2 from a position and size. + /// + /// The position. + /// The size. public Rect2(Vector2 position, Vector2 size) { _position = position; _size = size; } + + /// + /// Constructs a Rect2 from a position, width, and height. + /// + /// The position. + /// The width. + /// The height. public Rect2(Vector2 position, real_t width, real_t height) { _position = position; _size = new Vector2(width, height); } + + /// + /// Constructs a Rect2 from x, y, and size. + /// + /// The position's X coordinate. + /// The position's Y coordinate. + /// The size. public Rect2(real_t x, real_t y, Vector2 size) { _position = new Vector2(x, y); _size = size; } + + /// + /// Constructs a Rect2 from x, y, width, and height. + /// + /// The position's X coordinate. + /// The position's Y coordinate. + /// The width. + /// The height. 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); } + /// + /// Returns true if this rect and `other` are approximately equal, by running + /// on each component. + /// + /// The other rect to compare. + /// Whether or not the rects are approximately equal. public bool IsEqualApprox(Rect2 other) { return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other.Size); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs index aa8815d1aa4..b176111d6ad 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs @@ -8,11 +8,28 @@ using real_t = System.Single; namespace Godot { + /// + /// 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 (first 3 columns) and a + /// for the origin (last column). + /// + /// For more information, read this documentation article: + /// https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html + /// [Serializable] [StructLayout(LayoutKind.Sequential)] public struct Transform : IEquatable { + /// + /// The of this transform. Contains the X, Y, and Z basis + /// vectors (columns 0 to 2) and is responsible for rotation and scale. + /// public Basis basis; + + /// + /// The origin vector (column 3, the fourth column). Equivalent to array index `[3]`. + /// public Vector3 origin; /// @@ -85,13 +102,24 @@ namespace Godot } } + /// + /// Returns the inverse of the transform, under the assumption that + /// the transformation is composed of rotation, scaling, and translation. + /// + /// The inverse transformation matrix. public Transform AffineInverse() { Basis basisInv = basis.Inverse(); return new Transform(basisInv, basisInv.Xform(-origin)); } - public Transform InterpolateWith(Transform transform, real_t c) + /// + /// Interpolates this transform to the other `transform` by `weight`. + /// + /// The other transform. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The interpolated transform. + 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.LinearInterpolate(destinationScale, c)); - interpolated.origin = sourceLocation.LinearInterpolate(destinationLocation, c); + interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, weight).Normalized(), sourceScale.LinearInterpolate(destinationScale, weight)); + interpolated.origin = sourceLocation.LinearInterpolate(destinationLocation, weight); return interpolated; } + /// + /// Returns the inverse of the transform, under the assumption that + /// the transformation is composed of rotation and translation + /// (no scaling, use for transforms with scaling). + /// + /// The inverse matrix. public Transform Inverse() { Basis basisTr = basis.Transposed(); return new Transform(basisTr, basisTr.Xform(-origin)); } + /// + /// 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. + /// + /// The object to look at. + /// The relative up direction + /// The resulting transform. public Transform LookingAt(Vector3 target, Vector3 up) { var t = this; @@ -123,16 +170,33 @@ namespace Godot return t; } + /// + /// Returns the transform with the basis orthogonal (90 degrees), + /// and normalized axis vectors (scale of 1 or -1). + /// + /// The orthonormalized transform. public Transform Orthonormalized() { return new Transform(basis.Orthonormalized(), origin); } + /// + /// Rotates the transform around the given `axis` by `phi` (in radians), + /// using matrix multiplication. The axis must be a normalized vector. + /// + /// The axis to rotate around. Must be normalized. + /// The angle to rotate, in radians. + /// The rotated transformation matrix. public Transform Rotated(Vector3 axis, real_t phi) { return new Transform(new Basis(axis, phi), new Vector3()) * this; } + /// + /// Scales the transform by the given 3D scaling factor, using matrix multiplication. + /// + /// The scale to introduce. + /// The scaled transformation matrix. public Transform Scaled(Vector3 scale) { return new Transform(basis.Scaled(scale), origin * scale); @@ -161,16 +225,30 @@ namespace Godot origin = eye; } - public Transform Translated(Vector3 ofs) + /// + /// Translates the transform by the given `offset`, + /// relative to the transform's basis vectors. + /// + /// Unlike and , + /// this does not use matrix multiplication. + /// + /// The offset to translate by. + /// The translated matrix. + 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) )); } + /// + /// Returns a vector transformed (multiplied) by this transformation matrix. + /// + /// A vector to transform. + /// The transfomed vector. public Vector3 Xform(Vector3 v) { return new Vector3 @@ -181,6 +259,14 @@ namespace Godot ); } + /// + /// 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. + /// + /// A vector to inversely transform. + /// The inversely transfomed vector. 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); + /// + /// 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. + /// + /// Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Back, Vector3.Zero)`. public static Transform Identity { get { return _identity; } } + /// + /// The transform that will flip something along the X axis. + /// + /// Equivalent to `new Transform(Vector3.Left, Vector3.Up, Vector3.Back, Vector3.Zero)`. public static Transform FlipX { get { return _flipX; } } + /// + /// The transform that will flip something along the Y axis. + /// + /// Equivalent to `new Transform(Vector3.Right, Vector3.Down, Vector3.Back, Vector3.Zero)`. public static Transform FlipY { get { return _flipY; } } + /// + /// The transform that will flip something along the Z axis. + /// + /// Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Forward, Vector3.Zero)`. public static Transform FlipZ { get { return _flipZ; } } - // Constructors + /// + /// Constructs a transformation matrix from 4 vectors (matrix columns). + /// + /// The X vector, or column index 0. + /// The Y vector, or column index 1. + /// The Z vector, or column index 2. + /// The origin vector, or column index 3. public Transform(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin) { basis = new Basis(column0, column1, column2); this.origin = origin; } + /// + /// Constructs a transformation matrix from the given quaternion and origin vector. + /// + /// The to create the basis from. + /// The origin vector, or column index 3. public Transform(Quat quat, Vector3 origin) { basis = new Basis(quat); this.origin = origin; } + /// + /// Constructs a transformation matrix from the given basis and origin vector. + /// + /// The to create the basis from. + /// The origin vector, or column index 3. public Transform(Basis basis, Vector3 origin) { this.basis = basis; @@ -255,6 +375,12 @@ namespace Godot return basis.Equals(other.basis) && origin.Equals(other.origin); } + /// + /// Returns true if this transform and `other` are approximately equal, by running + /// on each component. + /// + /// The other transform to compare. + /// Whether or not the matrices are approximately equal. public bool IsEqualApprox(Transform other) { return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index e72a44809a7..4e069c2f4be 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -8,25 +8,44 @@ using real_t = System.Single; namespace Godot { + /// + /// 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 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 + /// [Serializable] [StructLayout(LayoutKind.Sequential)] public struct Transform2D : IEquatable { + /// + /// The basis matrix's X vector (column 0). Equivalent to array index `[0]`. + /// + /// public Vector2 x; + + /// + /// The basis matrix's Y vector (column 1). Equivalent to array index `[1]`. + /// public Vector2 y; + + /// + /// The origin vector (column 2, the third column). Equivalent to array index `[2]`. + /// The origin vector represents translation. + /// public Vector2 origin; + /// + /// The rotation of this transformation matrix. + /// + /// Getting is equivalent to calling with the values of . 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 } } + /// + /// The scale of this transformation matrix. + /// + /// Equivalent to the lengths of each column vector, but Y is negative if the determinant is negative. 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 } } + /// + /// Returns the inverse of the transform, under the assumption that + /// the transformation is composed of rotation, scaling, and translation. + /// + /// The inverse transformation matrix. public Transform2D AffineInverse() { real_t det = BasisDeterminant(); @@ -135,28 +162,58 @@ namespace Godot return inv; } + /// + /// 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. + /// + /// The determinant of the basis matrix. private real_t BasisDeterminant() { return x.x * y.y - x.y * y.x; } + /// + /// Returns a vector transformed (multiplied) by the basis matrix. + /// This method does not account for translation (the origin vector). + /// + /// A vector to transform. + /// The transfomed vector. public Vector2 BasisXform(Vector2 v) { return new Vector2(Tdotx(v), Tdoty(v)); } + /// + /// 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. + /// + /// A vector to inversely transform. + /// The inversely transfomed vector. public Vector2 BasisXformInv(Vector2 v) { return new Vector2(x.Dot(v), y.Dot(v)); } - public Transform2D InterpolateWith(Transform2D m, real_t c) + /// + /// Interpolates this transform to the other `transform` by `weight`. + /// + /// The other transform. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The interpolated transform. + 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.LinearInterpolate(v2, c).Normalized(); + v = v1.LinearInterpolate(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.LinearInterpolate(p2, c)); - Vector2 scale = s1.LinearInterpolate(s2, c); + var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.LinearInterpolate(p2, weight)); + Vector2 scale = s1.LinearInterpolate(s2, weight); res.x *= scale; res.y *= scale; return res; } + /// + /// Returns the inverse of the transform, under the assumption that + /// the transformation is composed of rotation and translation + /// (no scaling, use for transforms with scaling). + /// + /// The inverse matrix. public Transform2D Inverse() { var inv = this; @@ -208,6 +271,11 @@ namespace Godot return inv; } + /// + /// Returns the transform with the basis orthogonal (90 degrees), + /// and normalized axis vectors (scale of 1 or -1). + /// + /// The orthonormalized transform. public Transform2D Orthonormalized() { var on = this; @@ -225,11 +293,21 @@ namespace Godot return on; } + /// + /// Rotates the transform by `phi` (in radians), using matrix multiplication. + /// + /// The angle to rotate, in radians. + /// The rotated transformation matrix. public Transform2D Rotated(real_t phi) { return this * new Transform2D(phi, new Vector2()); } + /// + /// Scales the transform by the given scaling factor, using matrix multiplication. + /// + /// The scale to introduce. + /// The scaled transformation matrix. 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]; } + /// + /// Translates the transform by the given `offset`, + /// relative to the transform's basis vectors. + /// + /// Unlike and , + /// this does not use matrix multiplication. + /// + /// The offset to translate by. + /// The translated matrix. public Transform2D Translated(Vector2 offset) { var copy = this; @@ -264,11 +351,21 @@ namespace Godot return copy; } + /// + /// Returns a vector transformed (multiplied) by this transformation matrix. + /// + /// A vector to transform. + /// The transfomed vector. public Vector2 Xform(Vector2 v) { return new Vector2(Tdotx(v), Tdoty(v)) + origin; } + /// + /// Returns a vector transformed (multiplied) by the inverse transformation matrix. + /// + /// A vector to inversely transform. + /// The inversely transfomed vector. 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; + /// + /// 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. + /// + /// Equivalent to `new Transform2D(Vector2.Right, Vector2.Down, Vector2.Zero)`. + public static Transform2D Identity { get { return _identity; } } + /// + /// The transform that will flip something along the X axis. + /// + /// Equivalent to `new Transform2D(Vector2.Left, Vector2.Down, Vector2.Zero)`. + public static Transform2D FlipX { get { return _flipX; } } + /// + /// The transform that will flip something along the Y axis. + /// + /// Equivalent to `new Transform2D(Vector2.Right, Vector2.Up, Vector2.Zero)`. + public static Transform2D FlipY { get { return _flipY; } } - // Constructors + /// + /// Constructs a transformation matrix from 3 vectors (matrix columns). + /// + /// The X vector, or column index 0. + /// The Y vector, or column index 1. + /// The origin vector, or column index 2. 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 + /// + /// Constructs a transformation matrix from the given components. + /// Arguments are named such that xy is equal to calling x.y + /// + /// The X component of the X column vector, accessed via `t.x.x` or `[0][0]` + /// The Y component of the X column vector, accessed via `t.x.y` or `[0][1]` + /// The X component of the Y column vector, accessed via `t.y.x` or `[1][0]` + /// The Y component of the Y column vector, accessed via `t.y.y` or `[1][1]` + /// The X component of the origin vector, accessed via `t.origin.x` or `[2][0]` + /// The Y component of the origin vector, accessed via `t.origin.y` or `[2][1]` 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); } + /// + /// Constructs a transformation matrix from a rotation value and origin vector. + /// + /// The rotation of the new transform, in radians. + /// The origin vector, or column index 2. 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); } + /// + /// Returns true if this transform and `other` are approximately equal, by running + /// on each component. + /// + /// The other transform to compare. + /// Whether or not the matrices are approximately equal. public bool IsEqualApprox(Transform2D other) { return x.IsEqualApprox(other.x) && y.IsEqualApprox(other.y) && origin.IsEqualApprox(other.origin); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index f92453f546c..5e64f01d04e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -21,15 +21,29 @@ namespace Godot [StructLayout(LayoutKind.Sequential)] public struct Vector2 : IEquatable { + /// + /// Enumerated index values for the axes. + /// Returned by and . + /// public enum Axis { X = 0, Y } + /// + /// The vector's X component. Also accessible by using the index position `[0]`. + /// public real_t x; + /// + /// The vector's Y component. Also accessible by using the index position `[1]`. + /// public real_t y; + /// + /// Access vector components using their index. + /// + /// `[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`. public real_t this[int index] { get @@ -76,46 +90,80 @@ namespace Godot } } - public real_t Cross(Vector2 b) - { - return x * b.y - y * b.x; - } - + /// + /// Returns a new vector with all components in absolute values (i.e. positive). + /// + /// A vector with called on each component. public Vector2 Abs() { return new Vector2(Mathf.Abs(x), Mathf.Abs(y)); } + /// + /// Returns this vector's angle with respect to the X axis, or (1, 0) vector, in radians. + /// + /// Equivalent to the result of when + /// called with the vector's `y` and `x` as parameters: `Mathf.Atan2(v.y, v.x)`. + /// + /// The angle of this vector, in radians. public real_t Angle() { return Mathf.Atan2(y, x); } + /// + /// Returns the angle to the given vector, in radians. + /// + /// The other vector to compare this vector to. + /// The angle between the two vectors, in radians. public real_t AngleTo(Vector2 to) { return Mathf.Atan2(Cross(to), Dot(to)); } + /// + /// Returns the angle between the line connecting the two points and the X axis, in radians. + /// + /// The other vector to compare this vector to. + /// The angle between the two vectors, in radians. public real_t AngleToPoint(Vector2 to) { return Mathf.Atan2(y - to.y, x - to.x); } + /// + /// Returns the aspect ratio of this vector, the ratio of `x` to `y`. + /// + /// The `x` component divided by the `y` component. public real_t Aspect() { return x / y; } - public Vector2 Bounce(Vector2 n) + /// + /// Returns the vector "bounced off" from a plane defined by the given normal. + /// + /// The normal vector defining the plane to bounce off. Must be normalized. + /// The bounced vector. + public Vector2 Bounce(Vector2 normal) { - return -Reflect(n); + return -Reflect(normal); } + /// + /// Returns a new vector with all components rounded up (towards positive infinity). + /// + /// A vector with called on each component. public Vector2 Ceil() { return new Vector2(Mathf.Ceil(x), Mathf.Ceil(y)); } + /// + /// Returns the vector with a maximum length by limiting its length to `length`. + /// + /// The length to limit to. + /// The vector with its length limited. public Vector2 Clamped(real_t length) { var v = this; @@ -130,12 +178,30 @@ namespace Godot return v; } + /// + /// Returns the cross product of this vector and `b`. + /// + /// The other vector. + /// The cross product value. + public real_t Cross(Vector2 b) + { + return x * b.y - y * b.x; + } + + /// + /// Performs a cubic interpolation between vectors `preA`, this vector, `b`, and `postB`, by the given amount `t`. + /// + /// The destination vector. + /// A vector before this vector. + /// A vector after `b`. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The interpolated vector. 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,56 +212,153 @@ namespace Godot (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3); } + /// + /// Returns the normalized vector pointing from this vector to `b`. + /// + /// The other vector to point towards. + /// The direction from this vector to `b`. public Vector2 DirectionTo(Vector2 b) { return new Vector2(b.x - x, b.y - y).Normalized(); } + /// + /// Returns the squared distance between this vector and `to`. + /// This method runs faster than , so prefer it if + /// you need to compare vectors or need the squared distance for some formula. + /// + /// The other vector to use. + /// The squared distance between the two vectors. public real_t DistanceSquaredTo(Vector2 to) { return (x - to.x) * (x - to.x) + (y - to.y) * (y - to.y); } + /// + /// Returns the distance between this vector and `to`. + /// + /// The other vector to use. + /// The distance between the two vectors. public real_t DistanceTo(Vector2 to) { return Mathf.Sqrt((x - to.x) * (x - to.x) + (y - to.y) * (y - to.y)); } + /// + /// Returns the dot product of this vector and `with`. + /// + /// The other vector to use. + /// The dot product of the two vectors. public real_t Dot(Vector2 with) { return x * with.x + y * with.y; } + /// + /// Returns a new vector with all components rounded down (towards negative infinity). + /// + /// A vector with called on each component. public Vector2 Floor() { return new Vector2(Mathf.Floor(x), Mathf.Floor(y)); } + /// + /// Returns the inverse of this vector. This is the same as `new Vector2(1 / v.x, 1 / v.y)`. + /// + /// The inverse of this vector. + public Vector2 Inverse() + { + return new Vector2(1 / x, 1 / y); + } + + /// + /// Returns true if the vector is normalized, and false otherwise. + /// + /// A bool indicating whether or not the vector is normalized. public bool IsNormalized() { return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon; } + /// + /// Returns the length (magnitude) of this vector. + /// + /// The length of this vector. public real_t Length() { return Mathf.Sqrt(x * x + y * y); } + /// + /// Returns the squared length (squared magnitude) of this vector. + /// This method runs faster than , so prefer it if + /// you need to compare vectors or need the squared length for some formula. + /// + /// The squared length of this vector. public real_t LengthSquared() { return x * x + y * y; } - public Vector2 LinearInterpolate(Vector2 b, real_t t) + /// + /// Returns the result of the linear interpolation between + /// this vector and `to` by amount `weight`. + /// + /// The destination vector for interpolation. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting vector of the interpolation. + public Vector2 LinearInterpolate(Vector2 to, real_t weight) { - var res = this; - - res.x += t * (b.x - x); - res.y += t * (b.y - y); - - return res; + return new Vector2 + ( + Mathf.Lerp(x, to.x, weight), + Mathf.Lerp(y, to.y, weight) + ); } + /// + /// Returns the result of the linear interpolation between + /// this vector and `to` by the vector amount `weight`. + /// + /// The destination vector for interpolation. + /// A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting vector of the interpolation. + public Vector2 LinearInterpolate(Vector2 to, Vector2 weight) + { + return new Vector2 + ( + Mathf.Lerp(x, to.x, weight.x), + Mathf.Lerp(y, to.y, weight.y) + ); + } + + /// + /// Returns the axis of the vector's largest value. See . + /// If both components are equal, this method returns . + /// + /// The index of the largest axis. + public Axis MaxAxis() + { + return x < y ? Axis.Y : Axis.X; + } + + /// + /// Returns the axis of the vector's smallest value. See . + /// If both components are equal, this method returns . + /// + /// The index of the smallest axis. + public Axis MinAxis() + { + return x < y ? Axis.X : Axis.Y; + } + + /// + /// Moves this vector toward `to` by the fixed `delta` amount. + /// + /// The vector to move towards. + /// The amount to move towards by. + /// The resulting vector. public Vector2 MoveToward(Vector2 to, real_t delta) { var v = this; @@ -204,6 +367,10 @@ namespace Godot return len <= delta || len < Mathf.Epsilon ? to : v + vd / len * delta; } + /// + /// Returns the vector scaled to unit length. Equivalent to `v / v.Length()`. + /// + /// A normalized version of the vector. public Vector2 Normalized() { var v = this; @@ -211,6 +378,21 @@ namespace Godot return v; } + /// + /// Returns a perpendicular vector rotated 90 degrees counter-clockwise + /// compared to the original, with the same length. + /// + /// The perpendicular vector. + public Vector2 Perpendicular() + { + return new Vector2(y, -x); + } + + /// + /// Returns a vector composed of the of this vector's components and `mod`. + /// + /// A value representing the divisor of the operation. + /// A vector with each component by `mod`. public Vector2 PosMod(real_t mod) { Vector2 v; @@ -219,6 +401,11 @@ namespace Godot return v; } + /// + /// Returns a vector composed of the of this vector's components and `modv`'s components. + /// + /// A vector representing the divisors of the operation. + /// A vector with each component by `modv`'s components. public Vector2 PosMod(Vector2 modv) { Vector2 v; @@ -227,22 +414,48 @@ namespace Godot return v; } + /// + /// Returns this vector projected onto another vector. + /// + /// The vector to project onto. + /// The projected vector. public Vector2 Project(Vector2 onNormal) { return onNormal * (Dot(onNormal) / onNormal.LengthSquared()); } - public Vector2 Reflect(Vector2 n) + /// + /// Returns this vector reflected from a plane defined by the given `normal`. + /// + /// The normal vector defining the plane to reflect from. Must be normalized. + /// The reflected vector. + public Vector2 Reflect(Vector2 normal) { - return 2.0f * n * Dot(n) - this; +#if DEBUG + if (!normal.IsNormalized()) + { + throw new ArgumentException("Argument is not normalized", nameof(normal)); + } +#endif + return 2 * Dot(normal) * normal - this; } + /// + /// Rotates this vector by `phi` radians. + /// + /// The angle to rotate by, in radians. + /// The rotated vector. public Vector2 Rotated(real_t phi) { real_t rads = Angle() + phi; return new Vector2(Mathf.Cos(rads), Mathf.Sin(rads)) * Length(); } + /// + /// Returns this vector with all components rounded to the nearest integer, + /// with halfway cases rounded towards the nearest multiple of two. + /// + /// The rounded vector. public Vector2 Round() { return new Vector2(Mathf.Round(x), Mathf.Round(y)); @@ -261,6 +474,12 @@ namespace Godot y = v.y; } + /// + /// 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 on each component. + /// + /// A vector with all components as either `1`, `-1`, or `0`. public Vector2 Sign() { Vector2 v; @@ -269,22 +488,57 @@ namespace Godot return v; } - public Vector2 Slerp(Vector2 b, real_t t) + /// + /// Returns the result of the spherical linear interpolation between + /// this vector and `to` by amount `weight`. + /// + /// Note: Both vectors must be normalized. + /// + /// The destination vector for interpolation. Must be normalized. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting vector of the interpolation. + 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) + /// + /// Returns this vector slid along a plane defined by the given normal. + /// + /// The normal vector defining the plane to slide on. + /// The slid vector. + public Vector2 Slide(Vector2 normal) { - return this - n * Dot(n); + return this - normal * Dot(normal); } - public Vector2 Snapped(Vector2 by) + /// + /// 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. + /// + /// A vector value representing the step size to snap to. + /// The snapped vector. + 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)); } + /// + /// Returns a perpendicular vector rotated 90 degrees counter-clockwise + /// compared to the original, with the same length. + /// Deprecated, will be replaced by in 4.0. + /// + /// The perpendicular vector. public Vector2 Tangent() { return new Vector2(y, -x); @@ -301,22 +555,63 @@ namespace Godot private static readonly Vector2 _right = new Vector2(1, 0); private static readonly Vector2 _left = new Vector2(-1, 0); + /// + /// Zero vector, a vector with all components set to `0`. + /// + /// Equivalent to `new Vector2(0, 0)` public static Vector2 Zero { get { return _zero; } } + /// + /// Deprecated, please use a negative sign with instead. + /// + /// Equivalent to `new Vector2(-1, -1)` public static Vector2 NegOne { get { return _negOne; } } + /// + /// One vector, a vector with all components set to `1`. + /// + /// Equivalent to `new Vector2(1, 1)` public static Vector2 One { get { return _one; } } + /// + /// Infinity vector, a vector with all components set to `Mathf.Inf`. + /// + /// Equivalent to `new Vector2(Mathf.Inf, Mathf.Inf)` public static Vector2 Inf { get { return _inf; } } + /// + /// Up unit vector. Y is down in 2D, so this vector points -Y. + /// + /// Equivalent to `new Vector2(0, -1)` public static Vector2 Up { get { return _up; } } + /// + /// Down unit vector. Y is down in 2D, so this vector points +Y. + /// + /// Equivalent to `new Vector2(0, 1)` public static Vector2 Down { get { return _down; } } + /// + /// Right unit vector. Represents the direction of right. + /// + /// Equivalent to `new Vector2(1, 0)` public static Vector2 Right { get { return _right; } } + /// + /// Left unit vector. Represents the direction of left. + /// + /// Equivalent to `new Vector2(-1, 0)` public static Vector2 Left { get { return _left; } } - // Constructors + /// + /// Constructs a new with the given components. + /// + /// The vector's X component. + /// The vector's Y component. public Vector2(real_t x, real_t y) { this.x = x; this.y = y; } + + /// + /// Constructs a new from an existing . + /// + /// The existing . public Vector2(Vector2 v) { x = v.x; @@ -365,18 +660,18 @@ namespace Godot return left; } - public static Vector2 operator /(Vector2 vec, real_t scale) + public static Vector2 operator /(Vector2 vec, real_t divisor) { - vec.x /= scale; - vec.y /= scale; + vec.x /= divisor; + vec.y /= divisor; return vec; } - public static Vector2 operator /(Vector2 left, Vector2 right) + public static Vector2 operator /(Vector2 vec, Vector2 divisorv) { - left.x /= right.x; - left.y /= right.y; - return left; + vec.x /= divisorv.x; + vec.y /= divisorv.y; + return vec; } public static Vector2 operator %(Vector2 vec, real_t divisor) @@ -458,6 +753,12 @@ namespace Godot return x == other.x && y == other.y; } + /// + /// Returns true if this vector and `other` are approximately equal, by running + /// on each component. + /// + /// The other vector to compare. + /// Whether or not the vectors are approximately equal. public bool IsEqualApprox(Vector2 other) { return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index fded34002df..fe36ac81d1c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -21,6 +21,10 @@ namespace Godot [StructLayout(LayoutKind.Sequential)] public struct Vector3 : IEquatable { + /// + /// Enumerated index values for the axes. + /// Returned by and . + /// public enum Axis { X = 0, @@ -28,10 +32,23 @@ namespace Godot Z } + /// + /// The vector's X component. Also accessible by using the index position `[0]`. + /// public real_t x; + /// + /// The vector's Y component. Also accessible by using the index position `[1]`. + /// public real_t y; + /// + /// The vector's Z component. Also accessible by using the index position `[2]`. + /// public real_t z; + /// + /// Access vector components using their index. + /// + /// `[0]` is equivalent to `.x`, `[1]` is equivalent to `.y`, `[2]` is equivalent to `.z`. public real_t this[int index] { get @@ -84,26 +101,49 @@ namespace Godot } } + /// + /// Returns a new vector with all components in absolute values (i.e. positive). + /// + /// A vector with called on each component. public Vector3 Abs() { return new Vector3(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z)); } + /// + /// Returns the minimum angle to the given vector, in radians. + /// + /// The other vector to compare this vector to. + /// The angle between the two vectors, in radians. public real_t AngleTo(Vector3 to) { return Mathf.Atan2(Cross(to).Length(), Dot(to)); } - public Vector3 Bounce(Vector3 n) + /// + /// Returns this vector "bounced off" from a plane defined by the given normal. + /// + /// The normal vector defining the plane to bounce off. Must be normalized. + /// The bounced vector. + public Vector3 Bounce(Vector3 normal) { - return -Reflect(n); + return -Reflect(normal); } + /// + /// Returns a new vector with all components rounded up (towards positive infinity). + /// + /// A vector with called on each component. public Vector3 Ceil() { return new Vector3(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z)); } + /// + /// Returns the cross product of this vector and `b`. + /// + /// The other vector. + /// The cross product vector. public Vector3 Cross(Vector3 b) { return new Vector3 @@ -114,12 +154,21 @@ namespace Godot ); } + /// + /// Performs a cubic interpolation between vectors `preA`, this vector, + /// `b`, and `postB`, by the given amount `t`. + /// + /// The destination vector. + /// A vector before this vector. + /// A vector after `b`. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The interpolated vector. 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 ); } + /// + /// Returns the normalized vector pointing from this vector to `b`. + /// + /// The other vector to point towards. + /// The direction from this vector to `b`. public Vector3 DirectionTo(Vector3 b) { return new Vector3(b.x - x, b.y - y, b.z - z).Normalized(); } + /// + /// Returns the squared distance between this vector and `b`. + /// This method runs faster than , so prefer it if + /// you need to compare vectors or need the squared distance for some formula. + /// + /// The other vector to use. + /// The squared distance between the two vectors. public real_t DistanceSquaredTo(Vector3 b) { return (b - this).LengthSquared(); } + /// + /// Returns the distance between this vector and `b`. + /// + /// The other vector to use. + /// The distance between the two vectors. public real_t DistanceTo(Vector3 b) { return (b - this).Length(); } + /// + /// Returns the dot product of this vector and `b`. + /// + /// The other vector to use. + /// The dot product of the two vectors. public real_t Dot(Vector3 b) { return x * b.x + y * b.y + z * b.z; } + /// + /// Returns a new vector with all components rounded down (towards negative infinity). + /// + /// A vector with called on each component. public Vector3 Floor() { return new Vector3(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z)); } + /// + /// Returns the inverse of this vector. This is the same as `new Vector3(1 / v.x, 1 / v.y, 1 / v.z)`. + /// + /// The inverse of this vector. public Vector3 Inverse() { - return new Vector3(1.0f / x, 1.0f / y, 1.0f / z); + return new Vector3(1 / x, 1 / y, 1 / z); } + /// + /// Returns true if the vector is normalized, and false otherwise. + /// + /// A bool indicating whether or not the vector is normalized. public bool IsNormalized() { return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon; } + /// + /// Returns the length (magnitude) of this vector. + /// + /// The length of this vector. public real_t Length() { real_t x2 = x * x; @@ -175,6 +262,12 @@ namespace Godot return Mathf.Sqrt(x2 + y2 + z2); } + /// + /// Returns the squared length (squared magnitude) of this vector. + /// This method runs faster than , so prefer it if + /// you need to compare vectors or need the squared length for some formula. + /// + /// The squared length of this vector. public real_t LengthSquared() { real_t x2 = x * x; @@ -184,16 +277,66 @@ namespace Godot return x2 + y2 + z2; } - public Vector3 LinearInterpolate(Vector3 b, real_t t) + /// + /// Returns the result of the linear interpolation between + /// this vector and `to` by amount `weight`. + /// + /// The destination vector for interpolation. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting vector of the interpolation. + public Vector3 LinearInterpolate(Vector3 to, real_t weight) { return new Vector3 ( - x + t * (b.x - x), - y + t * (b.y - y), - z + t * (b.z - z) + Mathf.Lerp(x, to.x, weight), + Mathf.Lerp(y, to.y, weight), + Mathf.Lerp(z, to.z, weight) ); } + /// + /// Returns the result of the linear interpolation between + /// this vector and `to` by the vector amount `weight`. + /// + /// The destination vector for interpolation. + /// A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting vector of the interpolation. + public Vector3 LinearInterpolate(Vector3 to, Vector3 weight) + { + return new Vector3 + ( + Mathf.Lerp(x, to.x, weight.x), + Mathf.Lerp(y, to.y, weight.y), + Mathf.Lerp(z, to.z, weight.z) + ); + } + + /// + /// Returns the axis of the vector's largest value. See . + /// If all components are equal, this method returns . + /// + /// The index of the largest axis. + public Axis MaxAxis() + { + return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X); + } + + /// + /// Returns the axis of the vector's smallest value. See . + /// If all components are equal, this method returns . + /// + /// The index of the smallest axis. + public Axis MinAxis() + { + return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z); + } + + /// + /// Moves this vector toward `to` by the fixed `delta` amount. + /// + /// The vector to move towards. + /// The amount to move towards by. + /// The resulting vector. public Vector3 MoveToward(Vector3 to, real_t delta) { var v = this; @@ -202,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); - } - + /// + /// Returns the vector scaled to unit length. Equivalent to `v / v.Length()`. + /// + /// A normalized version of the vector. public Vector3 Normalized() { var v = this; @@ -219,6 +356,11 @@ namespace Godot return v; } + /// + /// Returns the outer product with `b`. + /// + /// The other vector. + /// A representing the outer product matrix. public Basis Outer(Vector3 b) { return new Basis( @@ -228,6 +370,11 @@ namespace Godot ); } + /// + /// Returns a vector composed of the of this vector's components and `mod`. + /// + /// A value representing the divisor of the operation. + /// A vector with each component by `mod`. public Vector3 PosMod(real_t mod) { Vector3 v; @@ -237,6 +384,11 @@ namespace Godot return v; } + /// + /// Returns a vector composed of the of this vector's components and `modv`'s components. + /// + /// A vector representing the divisors of the operation. + /// A vector with each component by `modv`'s components. public Vector3 PosMod(Vector3 modv) { Vector3 v; @@ -246,30 +398,60 @@ namespace Godot return v; } + /// + /// Returns this vector projected onto another vector `b`. + /// + /// The vector to project onto. + /// The projected vector. public Vector3 Project(Vector3 onNormal) { return onNormal * (Dot(onNormal) / onNormal.LengthSquared()); } - public Vector3 Reflect(Vector3 n) + /// + /// Returns this vector reflected from a plane defined by the given `normal`. + /// + /// The normal vector defining the plane to reflect from. Must be normalized. + /// The reflected vector. + 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; } + /// + /// Rotates this vector around a given `axis` vector by `phi` radians. + /// The `axis` vector must be a normalized vector. + /// + /// The vector to rotate around. Must be normalized. + /// The angle to rotate by, in radians. + /// The rotated vector. + 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); + } + + /// + /// Returns this vector with all components rounded to the nearest integer, + /// with halfway cases rounded towards the nearest multiple of two. + /// + /// The rounded vector. 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); - } - [Obsolete("Set is deprecated. Use the Vector3(" + nameof(real_t) + ", " + nameof(real_t) + ", " + nameof(real_t) + ") constructor instead.", error: true)] public void Set(real_t x, real_t y, real_t z) { @@ -285,6 +467,12 @@ namespace Godot z = v.z; } + /// + /// 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 on each component. + /// + /// A vector with all components as either `1`, `-1`, or `0`. public Vector3 Sign() { Vector3 v; @@ -294,37 +482,70 @@ namespace Godot return v; } - public Vector3 Slerp(Vector3 b, real_t t) + /// + /// Returns the result of the spherical linear interpolation between + /// this vector and `to` by amount `weight`. + /// + /// Note: Both vectors must be normalized. + /// + /// The destination vector for interpolation. Must be normalized. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The resulting vector of the interpolation. + 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) + /// + /// Returns this vector slid along a plane defined by the given normal. + /// + /// The normal vector defining the plane to slide on. + /// The slid vector. + public Vector3 Slide(Vector3 normal) { - return this - n * Dot(n); + return this - normal * Dot(normal); } - public Vector3 Snapped(Vector3 by) + /// + /// 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. + /// + /// A vector value representing the step size to snap to. + /// The snapped vector. + 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) ); } + /// + /// 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. + /// + /// A Basis with the vector as its main diagonal. public Basis ToDiagonalMatrix() { return new Basis( - x, 0f, 0f, - 0f, y, 0f, - 0f, 0f, z + x, 0, 0, + 0, y, 0, + 0, 0, z ); } @@ -341,25 +562,79 @@ namespace Godot private static readonly Vector3 _forward = new Vector3(0, 0, -1); private static readonly Vector3 _back = new Vector3(0, 0, 1); + /// + /// Zero vector, a vector with all components set to `0`. + /// + /// Equivalent to `new Vector3(0, 0, 0)` public static Vector3 Zero { get { return _zero; } } + /// + /// One vector, a vector with all components set to `1`. + /// + /// Equivalent to `new Vector3(1, 1, 1)` public static Vector3 One { get { return _one; } } + /// + /// Deprecated, please use a negative sign with instead. + /// + /// Equivalent to `new Vector3(-1, -1, -1)` public static Vector3 NegOne { get { return _negOne; } } + /// + /// Infinity vector, a vector with all components set to `Mathf.Inf`. + /// + /// Equivalent to `new Vector3(Mathf.Inf, Mathf.Inf, Mathf.Inf)` public static Vector3 Inf { get { return _inf; } } + /// + /// Up unit vector. + /// + /// Equivalent to `new Vector3(0, 1, 0)` public static Vector3 Up { get { return _up; } } + /// + /// Down unit vector. + /// + /// Equivalent to `new Vector3(0, -1, 0)` public static Vector3 Down { get { return _down; } } + /// + /// Right unit vector. Represents the local direction of right, + /// and the global direction of east. + /// + /// Equivalent to `new Vector3(1, 0, 0)` public static Vector3 Right { get { return _right; } } + /// + /// Left unit vector. Represents the local direction of left, + /// and the global direction of west. + /// + /// Equivalent to `new Vector3(-1, 0, 0)` public static Vector3 Left { get { return _left; } } + /// + /// Forward unit vector. Represents the local direction of forward, + /// and the global direction of north. + /// + /// Equivalent to `new Vector3(0, 0, -1)` public static Vector3 Forward { get { return _forward; } } + /// + /// Back unit vector. Represents the local direction of back, + /// and the global direction of south. + /// + /// Equivalent to `new Vector3(0, 0, 1)` public static Vector3 Back { get { return _back; } } - // Constructors + /// + /// Constructs a new with the given components. + /// + /// The vector's X component. + /// The vector's Y component. + /// The vector's Z component. public Vector3(real_t x, real_t y, real_t z) { this.x = x; this.y = y; this.z = z; } + + /// + /// Constructs a new from an existing . + /// + /// The existing . public Vector3(Vector3 v) { x = v.x; @@ -415,20 +690,20 @@ namespace Godot return left; } - public static Vector3 operator /(Vector3 vec, real_t scale) + public static Vector3 operator /(Vector3 vec, real_t divisor) { - vec.x /= scale; - vec.y /= scale; - vec.z /= scale; + vec.x /= divisor; + vec.y /= divisor; + vec.z /= divisor; return vec; } - public static Vector3 operator /(Vector3 left, Vector3 right) + public static Vector3 operator /(Vector3 vec, Vector3 divisorv) { - left.x /= right.x; - left.y /= right.y; - left.z /= right.z; - return left; + vec.x /= divisorv.x; + vec.y /= divisorv.y; + vec.z /= divisorv.z; + return vec; } public static Vector3 operator %(Vector3 vec, real_t divisor) @@ -520,6 +795,12 @@ namespace Godot return x == other.x && y == other.y && z == other.z; } + /// + /// Returns true if this vector and `other` are approximately equal, by running + /// on each component. + /// + /// The other vector to compare. + /// Whether or not the vectors are approximately equal. public bool IsEqualApprox(Vector3 other) { return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z);