diff --git a/src/SceneKit/SCNMatrix4_dotnet.cs b/src/SceneKit/SCNMatrix4_dotnet.cs
index 0bc1f3151650..1b0469c0d628 100644
--- a/src/SceneKit/SCNMatrix4_dotnet.cs
+++ b/src/SceneKit/SCNMatrix4_dotnet.cs
@@ -1,7 +1,4 @@
/*
- * This keeps the code of OpenTK's Matrix4 almost intact, except we replace the
- * Vector4 with a SCNVector4
-
Copyright (c) 2006 - 2008 The Open Toolkit library.
Copyright (c) 2014 Xamarin Inc. All rights reserved
@@ -52,28 +49,55 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
namespace SceneKit {
///
- /// Represents a 4x4 Matrix
+ /// Represents a 4x4 matrix using a column-major memory layout.
///
[Serializable]
public struct SCNMatrix4 : IEquatable {
#region Fields
+ /*
+ * SCNMatrix4 is defined like this for iOS, tvOS and watchOS:
+ *
+ * typedef struct SCNMatrix4 {
+ * float m11, m12, m13, m14;
+ * float m21, m22, m23, m24;
+ * float m31, m32, m33, m34;
+ * float m41, m42, m43, m44;
+ * } SCNMatrix4;
+ *
+ * and like this for macOS:
+ *
+ * struct CATransform3D
+ * {
+ * CGFloat m11, m12, m13, m14;
+ * CGFloat m21, m22, m23, m24;
+ * CGFloat m31, m32, m33, m34;
+ * CGFloat m41, m42, m43, m44;
+ * };
+ * typedef CATransform3D SCNMatrix4;
+ *
+ * It's not obvious from this definitions whether the matrix is row-major or column-major, and neither the documentation
+ * nor the headers are particularly helpful, but it's possible to do some math to figure it out. See this for more info:
+ * https://github.com/xamarin/xamarin-macios/issues/15094#issuecomment-1139699662 (result: SCNMatrix4 is using a column-major layout)
+ *
+ **/
+
///
/// Left-most column of the matrix
///
- public SCNVector4 Column0;
+ public SCNVector4 Column0; // m11, m12, m13, m14
///
/// 2nd column of the matrix
///
- public SCNVector4 Column1;
+ public SCNVector4 Column1; // m21, m22, m23, m24
///
/// 3rd column of the matrix
///
- public SCNVector4 Column2;
+ public SCNVector4 Column2; // m31, m32, m33, m34
///
/// Right-most column of the matrix
///
- public SCNVector4 Column3;
+ public SCNVector4 Column3; // m41, m42, m43, m44
///
/// The identity matrix
@@ -133,10 +157,10 @@ public SCNMatrix4 (
#if !WATCH
public SCNMatrix4 (CoreAnimation.CATransform3D transform)
{
- Column0 = new SCNVector4 ((pfloat) transform.M11, (pfloat) transform.M21, (pfloat) transform.M31, (pfloat) transform.M41);
- Column1 = new SCNVector4 ((pfloat) transform.M12, (pfloat) transform.M22, (pfloat) transform.M32, (pfloat) transform.M42);
- Column2 = new SCNVector4 ((pfloat) transform.M13, (pfloat) transform.M23, (pfloat) transform.M33, (pfloat) transform.M43);
- Column3 = new SCNVector4 ((pfloat) transform.M14, (pfloat) transform.M24, (pfloat) transform.M34, (pfloat) transform.M44);
+ Column0 = new SCNVector4 ((pfloat) transform.M11, (pfloat) transform.M12, (pfloat) transform.M13, (pfloat) transform.M14);
+ Column1 = new SCNVector4 ((pfloat) transform.M21, (pfloat) transform.M22, (pfloat) transform.M23, (pfloat) transform.M24);
+ Column2 = new SCNVector4 ((pfloat) transform.M31, (pfloat) transform.M32, (pfloat) transform.M33, (pfloat) transform.M34);
+ Column3 = new SCNVector4 ((pfloat) transform.M41, (pfloat) transform.M42, (pfloat) transform.M43, (pfloat) transform.M44);
}
#endif
@@ -167,10 +191,10 @@ public pfloat Determinant {
public SCNVector4 Row0 {
get { return new SCNVector4 (Column0.X, Column1.X, Column2.X, Column3.X); }
set {
- M11 = value.X;
- M12 = value.Y;
- M13 = value.Z;
- M14 = value.W;
+ Column0.X = value.X;
+ Column1.X = value.Y;
+ Column2.X = value.Z;
+ Column3.X = value.W;
}
}
@@ -180,10 +204,10 @@ public SCNVector4 Row0 {
public SCNVector4 Row1 {
get { return new SCNVector4 (Column0.Y, Column1.Y, Column2.Y, Column3.Y); }
set {
- M21 = value.X;
- M22 = value.Y;
- M23 = value.Z;
- M24 = value.W;
+ Column0.Y = value.X;
+ Column1.Y = value.Y;
+ Column2.Y = value.Z;
+ Column3.Y = value.W;
}
}
@@ -193,10 +217,10 @@ public SCNVector4 Row1 {
public SCNVector4 Row2 {
get { return new SCNVector4 (Column0.Z, Column1.Z, Column2.Z, Column3.Z); }
set {
- M31 = value.X;
- M32 = value.Y;
- M33 = value.Z;
- M34 = value.W;
+ Column0.Z = value.X;
+ Column1.Z = value.Y;
+ Column2.Z = value.Z;
+ Column3.Z = value.W;
}
}
@@ -206,90 +230,90 @@ public SCNVector4 Row2 {
public SCNVector4 Row3 {
get { return new SCNVector4 (Column0.W, Column1.W, Column2.W, Column3.W); }
set {
- M41 = value.X;
- M42 = value.Y;
- M43 = value.Z;
- M44 = value.W;
+ Column0.W = value.X;
+ Column1.W = value.Y;
+ Column2.W = value.Z;
+ Column3.W = value.W;
}
}
///
- /// Gets or sets the value at row 1, column 1 of this instance.
+ /// Gets or sets the value at column 1, row 1 of this instance.
///
public pfloat M11 { get { return Column0.X; } set { Column0.X = value; } }
///
- /// Gets or sets the value at row 1, column 2 of this instance.
+ /// Gets or sets the value at column 1, row 2 of this instance.
///
- public pfloat M12 { get { return Column1.X; } set { Column1.X = value; } }
+ public pfloat M12 { get { return Column0.Y; } set { Column0.Y = value; } }
///
- /// Gets or sets the value at row 1, column 3 of this instance.
+ /// Gets or sets the value at column 1, row 3 of this instance.
///
- public pfloat M13 { get { return Column2.X; } set { Column2.X = value; } }
+ public pfloat M13 { get { return Column0.Z; } set { Column0.Z = value; } }
///
- /// Gets or sets the value at row 1, column 4 of this instance.
+ /// Gets or sets the value at column 1, row 4 of this instance.
///
- public pfloat M14 { get { return Column3.X; } set { Column3.X = value; } }
+ public pfloat M14 { get { return Column0.W; } set { Column0.W = value; } }
///
- /// Gets or sets the value at row 2, column 1 of this instance.
+ /// Gets or sets the value at column 2, row 1 of this instance.
///
- public pfloat M21 { get { return Column0.Y; } set { Column0.Y = value; } }
+ public pfloat M21 { get { return Column1.X; } set { Column1.X = value; } }
///
- /// Gets or sets the value at row 2, column 2 of this instance.
+ /// Gets or sets the value at column 2, row 2 of this instance.
///
public pfloat M22 { get { return Column1.Y; } set { Column1.Y = value; } }
///
- /// Gets or sets the value at row 2, column 3 of this instance.
+ /// Gets or sets the value at column 2, row 3 of this instance.
///
- public pfloat M23 { get { return Column2.Y; } set { Column2.Y = value; } }
+ public pfloat M23 { get { return Column1.Z; } set { Column1.Z = value; } }
///
- /// Gets or sets the value at row 2, column 4 of this instance.
+ /// Gets or sets the value at column 2, row 4 of this instance.
///
- public pfloat M24 { get { return Column3.Y; } set { Column3.Y = value; } }
+ public pfloat M24 { get { return Column1.W; } set { Column1.W = value; } }
///
- /// Gets or sets the value at row 3, column 1 of this instance.
+ /// Gets or sets the value at column 3, row 1 of this instance.
///
- public pfloat M31 { get { return Column0.Z; } set { Column0.Z = value; } }
+ public pfloat M31 { get { return Column2.X; } set { Column2.X = value; } }
///
- /// Gets or sets the value at row 3, column 2 of this instance.
+ /// Gets or sets the value at column 3, row 2 of this instance.
///
- public pfloat M32 { get { return Column1.Z; } set { Column1.Z = value; } }
+ public pfloat M32 { get { return Column2.Y; } set { Column2.Y = value; } }
///
- /// Gets or sets the value at row 3, column 3 of this instance.
+ /// Gets or sets the value at column 3, row 3 of this instance.
///
public pfloat M33 { get { return Column2.Z; } set { Column2.Z = value; } }
///
- /// Gets or sets the value at row 3, column 4 of this instance.
+ /// Gets or sets the value at column 3, row 4 of this instance.
///
- public pfloat M34 { get { return Column3.Z; } set { Column3.Z = value; } }
+ public pfloat M34 { get { return Column2.W; } set { Column2.W = value; } }
///
- /// Gets or sets the value at row 4, column 1 of this instance.
+ /// Gets or sets the value at column 4, row 1 of this instance.
///
- public pfloat M41 { get { return Column0.W; } set { Column0.W = value; } }
+ public pfloat M41 { get { return Column3.X; } set { Column3.X = value; } }
///
- /// Gets or sets the value at row 4, column 2 of this instance.
+ /// Gets or sets the value at column 4, row 2 of this instance.
///
- public pfloat M42 { get { return Column1.W; } set { Column1.W = value; } }
+ public pfloat M42 { get { return Column3.Y; } set { Column3.Y = value; } }
///
- /// Gets or sets the value at row 4, column 3 of this instance.
+ /// Gets or sets the value at column 4, row 3 of this instance.
///
- public pfloat M43 { get { return Column2.W; } set { Column2.W = value; } }
+ public pfloat M43 { get { return Column3.Z; } set { Column3.Z = value; } }
///
- /// Gets or sets the value at row 4, column 4 of this instance.
+ /// Gets or sets the value at column 4, row 4 of this instance.
///
public pfloat M44 { get { return Column3.W; } set { Column3.W = value; } }
@@ -358,44 +382,85 @@ public static void CreateFromColumns (SCNVector4 column0, SCNVector4 column1, SC
/// A matrix instance.
public static void CreateFromAxisAngle (SCNVector3 axis, pfloat angle, out SCNMatrix4 result)
{
- pfloat cos = (float) System.Math.Cos (-angle);
- pfloat sin = (float) System.Math.Sin (-angle);
- pfloat t = 1.0f - cos;
-
axis.Normalize ();
- result = new SCNMatrix4 (t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f,
- t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f,
- t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f,
- 0, 0, 0, 1);
+ CreateFromAxisAngle (axis.X, axis.Y, axis.Z, angle, out result);
}
public static void CreateFromAxisAngle (Vector3 axis, float angle, out SCNMatrix4 result)
{
- pfloat cos = (float) System.Math.Cos (-angle);
- pfloat sin = (float) System.Math.Sin (-angle);
- pfloat t = 1.0f - cos;
-
axis = Vector3.Normalize (axis);
- result = new SCNMatrix4 (t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f,
- t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f,
- t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f,
- 0, 0, 0, 1);
+ CreateFromAxisAngle (axis.X, axis.Y, axis.Z, angle, out result);
}
public static void CreateFromAxisAngle (Vector3d axis, double angle, out SCNMatrix4 result)
{
- double cos = System.Math.Cos (-angle);
- double sin = System.Math.Sin (-angle);
- double t = 1.0f - cos;
-
axis.Normalize ();
- result = new SCNMatrix4 ((pfloat) (t * axis.X * axis.X + cos), (pfloat) (t * axis.X * axis.Y - sin * axis.Z), (pfloat) (t * axis.X * axis.Z + sin * axis.Y), (pfloat) (0.0f),
- (pfloat) ( t * axis.X * axis.Y + sin * axis.Z), (pfloat) (t * axis.Y * axis.Y + cos), (pfloat) (t * axis.Y * axis.Z - sin * axis.X), (pfloat) 0.0f,
- (pfloat) (t * axis.X * axis.Z - sin * axis.Y), (pfloat) (t * axis.Y * axis.Z + sin * axis.X), (pfloat) (t * axis.Z * axis.Z + cos), (pfloat) 0.0f,
- 0, 0, 0, 1);
+ CreateFromAxisAngle (axis.X, axis.Y, axis.Z, angle, out result);
+ }
+
+ ///
+ /// Build a rotation matrix from the specified axis/angle rotation.
+ ///
+ /// The x part of the normalized axis to rotate about.
+ /// The y part of the normalized axis to rotate about.
+ /// The z part of the normalized axis to rotate about.
+ /// Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).
+ /// A matrix instance.
+ static void CreateFromAxisAngle (float x, float y, float z, float angle, out SCNMatrix4 result)
+ {
+ var cos = MathF.Cos (-angle);
+ var sin = MathF.Sin (-angle);
+ var t = 1.0f - cos;
+
+ var m11 = t * x * x + cos;
+ var m12 = t * x * y - sin * z;
+ var m13 = t * x * z + sin * y;
+ var m21 = t * x * y + sin * z;
+ var m22 = t * y * y + cos;
+ var m23 = t * y * z - sin * x;
+ var m31 = t * x * z - sin * y;
+ var m32 = t * y * z + sin * x;
+ var m33 = t * z * z + cos;
+
+ result = new SCNMatrix4 (
+ m11, m21, m31, 0.0f,
+ m12, m22, m32, 0.0f,
+ m13, m23, m33, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ ///
+ /// Build a rotation matrix from the specified axis/angle rotation.
+ ///
+ /// The x part of the normalized axis to rotate about.
+ /// The y part of the normalized axis to rotate about.
+ /// The z part of the normalized axis to rotate about.
+ /// Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).
+ /// A matrix instance.
+ static void CreateFromAxisAngle (double x, double y, double z, double angle, out SCNMatrix4 result)
+ {
+ var cos = Math.Cos (-angle);
+ var sin = Math.Sin (-angle);
+ var t = 1.0f - cos;
+
+ var m11 = (pfloat) (t * x * x + cos);
+ var m12 = (pfloat) (t * x * y - sin * z);
+ var m13 = (pfloat) (t * x * z + sin * y);
+ var m21 = (pfloat) (t * x * y + sin * z);
+ var m22 = (pfloat) (t * y * y + cos);
+ var m23 = (pfloat) (t * y * z - sin * x);
+ var m31 = (pfloat) (t * x * z - sin * y);
+ var m32 = (pfloat) (t * y * z + sin * x);
+ var m33 = (pfloat) (t * z * z + cos);
+
+ result = new SCNMatrix4 (
+ m11, m21, m31, 0.0f,
+ m12, m22, m32, 0.0f,
+ m13, m23, m33, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
}
///
@@ -425,11 +490,11 @@ public static void CreateRotationX (pfloat angle, out SCNMatrix4 result)
pfloat cos = (pfloat) System.Math.Cos (angle);
pfloat sin = (pfloat) System.Math.Sin (angle);
- result = new SCNMatrix4 ();
- result.Row0 = SCNVector4.UnitX;
- result.Row1 = new SCNVector4 (0.0f, cos, sin, 0.0f);
- result.Row2 = new SCNVector4 (0.0f, -sin, cos, 0.0f);
- result.Row3 = SCNVector4.UnitW;
+ result = new SCNMatrix4 (
+ 1, 0, 0, 0,
+ 0, cos, -sin, 0,
+ 0, sin, cos, 0,
+ 0, 0, 0, 1);
}
///
@@ -454,11 +519,11 @@ public static void CreateRotationY (pfloat angle, out SCNMatrix4 result)
pfloat cos = (pfloat) System.Math.Cos (angle);
pfloat sin = (pfloat) System.Math.Sin (angle);
- result = new SCNMatrix4 ();
- result.Row0 = new SCNVector4 (cos, 0.0f, -sin, 0.0f);
- result.Row1 = SCNVector4.UnitY;
- result.Row2 = new SCNVector4 (sin, 0.0f, cos, 0.0f);
- result.Row3 = SCNVector4.UnitW;
+ result = new SCNMatrix4 (
+ cos, 0, sin, 0,
+ 0, 1, 0, 0,
+ -sin, 0, cos, 0,
+ 0, 0, 0, 1);
}
///
@@ -483,11 +548,11 @@ public static void CreateRotationZ (pfloat angle, out SCNMatrix4 result)
pfloat cos = (pfloat) System.Math.Cos (angle);
pfloat sin = (pfloat) System.Math.Sin (angle);
- result = new SCNMatrix4 ();
- result.Row0 = new SCNVector4 (cos, sin, 0.0f, 0.0f);
- result.Row1 = new SCNVector4 (-sin, cos, 0.0f, 0.0f);
- result.Row2 = SCNVector4.UnitZ;
- result.Row3 = SCNVector4.UnitW;
+ result = new SCNMatrix4 (
+ cos, -sin, 0, 0,
+ sin, cos, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
}
///
@@ -515,8 +580,11 @@ public static SCNMatrix4 CreateRotationZ (pfloat angle)
/// The resulting SCNMatrix4 instance.
public static void CreateTranslation (pfloat x, pfloat y, pfloat z, out SCNMatrix4 result)
{
- result = Identity;
- result.Row3 = new SCNVector4 (x, y, z, 1);
+ result = new SCNMatrix4 (
+ 1, 0, 0, x,
+ 0, 1, 0, y,
+ 0, 0, 1, z,
+ 0, 0, 0, 1);
}
///
@@ -526,8 +594,7 @@ public static void CreateTranslation (pfloat x, pfloat y, pfloat z, out SCNMatri
/// The resulting SCNMatrix4 instance.
public static void CreateTranslation (ref SCNVector3 vector, out SCNMatrix4 result)
{
- result = Identity;
- result.Row3 = new SCNVector4 (vector.X, vector.Y, vector.Z, 1);
+ CreateTranslation (vector.X, vector.Y, vector.Z, out result);
}
///
@@ -743,10 +810,11 @@ public static void CreatePerspectiveOffCenter (pfloat left, pfloat right, pfloat
pfloat c = -(zFar + zNear) / (zFar - zNear);
pfloat d = -(2.0f * zFar * zNear) / (zFar - zNear);
- result = new SCNMatrix4 (x, 0, 0, 0,
- 0, y, 0, 0,
- a, b, c, -1,
- 0, 0, d, 0);
+ result = new SCNMatrix4 (
+ x, 0, a, 0,
+ 0, y, b, 0,
+ 0, 0, c, d,
+ 0, 0, -1, 0);
}
///
@@ -807,12 +875,11 @@ public static SCNMatrix4 Scale (SCNVector3 scale)
/// A scaling matrix
public static SCNMatrix4 Scale (pfloat x, pfloat y, pfloat z)
{
- var result = new SCNMatrix4 ();
- result.Row0 = SCNVector4.UnitX * x;
- result.Row1 = SCNVector4.UnitY * y;
- result.Row2 = SCNVector4.UnitZ * z;
- result.Row3 = SCNVector4.UnitW;
- return result;
+ return new SCNMatrix4 (
+ x, 0, 0, 0,
+ 0, y, 0, 0,
+ 0, 0, z, 0,
+ 0, 0, 0, 1);
}
#endregion
@@ -865,10 +932,11 @@ public static SCNMatrix4 LookAt (SCNVector3 eye, SCNVector3 target, SCNVector3 u
SCNVector3 x = SCNVector3.Normalize (SCNVector3.Cross (up, z));
SCNVector3 y = SCNVector3.Normalize (SCNVector3.Cross (z, x));
- SCNMatrix4 rot = new SCNMatrix4 (new SCNVector4 (x.X, y.X, z.X, 0.0f),
- new SCNVector4 (x.Y, y.Y, z.Y, 0.0f),
- new SCNVector4 (x.Z, y.Z, z.Z, 0.0f),
- SCNVector4.UnitW);
+ SCNMatrix4 rot = new SCNMatrix4 (
+ x.X, x.Y, x.Z, 0.0f,
+ y.X, y.Y, y.Z, 0.0f,
+ z.X, z.Y, z.Z, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
SCNMatrix4 trans = SCNMatrix4.CreateTranslation (-eye);
@@ -898,43 +966,92 @@ public static SCNMatrix4 LookAt (pfloat eyeX, pfloat eyeY, pfloat eyeZ, pfloat t
#region Multiply Functions
///
- /// Multiplies two instances.
+ /// Combines two transformation matrices.
///
- /// The left operand of the multiplication.
- /// The right operand of the multiplication.
- /// A new instance that is the result of the multiplication
- public static SCNMatrix4 Mult (SCNMatrix4 left, SCNMatrix4 right)
+#if XAMCORE_5_0
+ ///
+ /// Combining two transformation matrices means using matrix multiplication to multiply them in the reverse order (secondTransformation * firstTransformation).
+ ///
+ /// The first transformation of the combination.
+ /// The second transformation of the combination.
+#else
+ ///
+ /// Combining two transformation matrices means using matrix multiplication to multiply them in the reverse order (right * left).
+ ///
+ /// The first transformation of the combination.
+ /// The second transformation of the combination.
+#endif
+ /// A new instance that is the result of the combination
+#if XAMCORE_5_0
+ public static SCNMatrix4 Mult (SCNMatrix4 firstTransformation, SCNMatrix4 secondTransformation)
+#else
+ public static SCNMatrix4 Mult(SCNMatrix4 left, SCNMatrix4 right)
+#endif
{
SCNMatrix4 result;
- Mult (ref left, ref right, out result);
+ // the matrices are reversed: https://github.com/xamarin/xamarin-macios/issues/15094#issuecomment-1139699662
+#if XAMCORE_5_0
+ MatrixMultiply (ref secondTransformation, ref firstTransformation, out result);
+#else
+ MatrixMultiply (ref right, ref left, out result);
+#endif
return result;
}
///
- /// Multiplies two instances.
+ /// Combines two transformation matrices.
///
- /// The left operand of the multiplication.
- /// The right operand of the multiplication.
- /// A new instance that is the result of the multiplication
- public static void Mult (ref SCNMatrix4 left, ref SCNMatrix4 right, out SCNMatrix4 result)
+#if XAMCORE_5_0
+ ///
+ /// Combining two transformation matrices means using matrix multiplication to multiply them in the reverse order (secondTransformation * firstTransformation).
+ ///
+ /// The first transformation of the combination.
+ /// The second transformation of the combination.
+#else
+ ///
+ /// Combining two transformation matrices means using matrix multiplication to multiply them in the reverse order (right * left).
+ ///
+ /// The first transformation of the combination.
+ /// The second transformation of the combination.
+#endif
+ /// A new instance that is the result of the combination
+#if XAMCORE_5_0
+ public static void Mult (ref SCNMatrix4 firstTransformation, ref SCNMatrix4 secondTransformation, out SCNMatrix4 result)
+#else
+ public static void Mult(ref SCNMatrix4 left, ref SCNMatrix4 right, out SCNMatrix4 result)
+#endif
{
- result = new SCNMatrix4 (
- left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41,
- left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42,
- left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43,
- left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44,
- left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41,
- left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42,
- left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43,
- left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44,
- left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41,
- left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42,
- left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43,
- left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44,
- left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41,
- left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42,
- left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43,
- left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44);
+ // the matrices are reversed: https://github.com/xamarin/xamarin-macios/issues/15094#issuecomment-1139699662
+#if XAMCORE_5_0
+ MatrixMultiply (ref secondTransformation, ref firstTransformation, out result);
+#else
+ MatrixMultiply (ref right, ref left, out result);
+#endif
+ }
+
+ // Multiply two matrices in the order you'd expect (left * right).
+ static void MatrixMultiply (ref SCNMatrix4 left, ref SCNMatrix4 right, out SCNMatrix4 result)
+ {
+ result = new SCNMatrix4(
+ left.Column0.X * right.Column0.X + left.Column1.X * right.Column0.Y + left.Column2.X * right.Column0.Z + left.Column3.X * right.Column0.W,
+ left.Column0.X * right.Column1.X + left.Column1.X * right.Column1.Y + left.Column2.X * right.Column1.Z + left.Column3.X * right.Column1.W,
+ left.Column0.X * right.Column2.X + left.Column1.X * right.Column2.Y + left.Column2.X * right.Column2.Z + left.Column3.X * right.Column2.W,
+ left.Column0.X * right.Column3.X + left.Column1.X * right.Column3.Y + left.Column2.X * right.Column3.Z + left.Column3.X * right.Column3.W,
+
+ left.Column0.Y * right.Column0.X + left.Column1.Y * right.Column0.Y + left.Column2.Y * right.Column0.Z + left.Column3.Y * right.Column0.W,
+ left.Column0.Y * right.Column1.X + left.Column1.Y * right.Column1.Y + left.Column2.Y * right.Column1.Z + left.Column3.Y * right.Column1.W,
+ left.Column0.Y * right.Column2.X + left.Column1.Y * right.Column2.Y + left.Column2.Y * right.Column2.Z + left.Column3.Y * right.Column2.W,
+ left.Column0.Y * right.Column3.X + left.Column1.Y * right.Column3.Y + left.Column2.Y * right.Column3.Z + left.Column3.Y * right.Column3.W,
+
+ left.Column0.Z * right.Column0.X + left.Column1.Z * right.Column0.Y + left.Column2.Z * right.Column0.Z + left.Column3.Z * right.Column0.W,
+ left.Column0.Z * right.Column1.X + left.Column1.Z * right.Column1.Y + left.Column2.Z * right.Column1.Z + left.Column3.Z * right.Column1.W,
+ left.Column0.Z * right.Column2.X + left.Column1.Z * right.Column2.Y + left.Column2.Z * right.Column2.Z + left.Column3.Z * right.Column2.W,
+ left.Column0.Z * right.Column3.X + left.Column1.Z * right.Column3.Y + left.Column2.Z * right.Column3.Z + left.Column3.Z * right.Column3.W,
+
+ left.Column0.W * right.Column0.X + left.Column1.W * right.Column0.Y + left.Column2.W * right.Column0.Z + left.Column3.W * right.Column0.W,
+ left.Column0.W * right.Column1.X + left.Column1.W * right.Column1.Y + left.Column2.W * right.Column1.Z + left.Column3.W * right.Column1.W,
+ left.Column0.W * right.Column2.X + left.Column1.W * right.Column2.Y + left.Column2.W * right.Column2.Z + left.Column3.W * right.Column2.W,
+ left.Column0.W * right.Column3.X + left.Column1.W * right.Column3.Y + left.Column2.W * right.Column3.Z + left.Column3.W * right.Column3.W);
}
#endregion
@@ -1102,7 +1219,7 @@ public static void Transpose (ref SCNMatrix4 mat, out SCNMatrix4 result)
#region public override string ToString()
///
- /// Returns a System.String that represents the current SCNMatrix44.
+ /// Returns a System.String that represents the current SCNMatrix4.
///
///
public override string ToString ()
diff --git a/src/SceneKit/SCNVector3.cs b/src/SceneKit/SCNVector3.cs
index 22ed3c65c5c4..b25d792bb14e 100644
--- a/src/SceneKit/SCNVector3.cs
+++ b/src/SceneKit/SCNVector3.cs
@@ -740,29 +740,53 @@ public static void BaryCentric(ref SCNVector3 a, ref SCNVector3 b, ref SCNVector
#region Transform
+#if NET
+ /// Transform a direction vector by the given Matrix
+ /// Assumes the matrix has a right-most column of (0,0,0,1), that is the translation part is ignored.
+ ///
+ /// The column vector to transform
+#else
/// Transform a direction vector by the given Matrix
/// Assumes the matrix has a bottom row of (0,0,0,1), that is the translation part is ignored.
///
- /// The vector to transform
+ /// The row vector to transform
+#endif
/// The desired transformation
/// The transformed vector
public static SCNVector3 TransformVector(SCNVector3 vec, SCNMatrix4 mat)
{
- SCNVector3 v;
- v.X = SCNVector3.Dot(vec, new SCNVector3(mat.Column0));
- v.Y = SCNVector3.Dot(vec, new SCNVector3(mat.Column1));
- v.Z = SCNVector3.Dot(vec, new SCNVector3(mat.Column2));
+ TransformVector (ref vec, ref mat, out var v);
return v;
}
+#if NET
+ /// Transform a direction vector by the given Matrix
+ /// Assumes the matrix has a right-most column of (0,0,0,1), that is the translation part is ignored.
+ ///
+ /// The column vector to transform
+#else
/// Transform a direction vector by the given Matrix
/// Assumes the matrix has a bottom row of (0,0,0,1), that is the translation part is ignored.
///
- /// The vector to transform
+ /// The row vector to transform
+#endif
/// The desired transformation
/// The transformed vector
public static void TransformVector(ref SCNVector3 vec, ref SCNMatrix4 mat, out SCNVector3 result)
{
+#if NET
+ result.X = vec.X * mat.Row0.X +
+ vec.Y * mat.Row0.Y +
+ vec.Z * mat.Row0.Z;
+
+ result.Y = vec.X * mat.Row1.X +
+ vec.Y * mat.Row1.Y +
+ vec.Z * mat.Row1.Z;
+
+ result.Z = vec.X * mat.Row2.X +
+ vec.Y * mat.Row2.Y +
+ vec.Z * mat.Row2.Z;
+#else
result.X = vec.X * mat.Row0.X +
vec.Y * mat.Row1.X +
vec.Z * mat.Row2.X;
@@ -774,6 +798,7 @@ public static void TransformVector(ref SCNVector3 vec, ref SCNMatrix4 mat, out S
result.Z = vec.X * mat.Row0.Z +
vec.Y * mat.Row1.Z +
vec.Z * mat.Row2.Z;
+#endif
}
/// Transform a Normal by the given Matrix
@@ -781,7 +806,11 @@ public static void TransformVector(ref SCNVector3 vec, ref SCNMatrix4 mat, out S
/// This calculates the inverse of the given matrix, use TransformNormalInverse if you
/// already have the inverse to avoid this extra calculation
///
- /// The normal to transform
+#if NET
+ /// The column-based normal to transform
+#else
+ /// The row-based normal to transform
+#endif
/// The desired transformation
/// The transformed normal
public static SCNVector3 TransformNormal(SCNVector3 norm, SCNMatrix4 mat)
@@ -795,7 +824,11 @@ public static SCNVector3 TransformNormal(SCNVector3 norm, SCNMatrix4 mat)
/// This calculates the inverse of the given matrix, use TransformNormalInverse if you
/// already have the inverse to avoid this extra calculation
///
- /// The normal to transform
+#if NET
+ /// The column-based normal to transform
+#else
+ /// The row-based normal to transform
+#endif
/// The desired transformation
/// The transformed normal
public static void TransformNormal(ref SCNVector3 norm, ref SCNMatrix4 mat, out SCNVector3 result)
@@ -809,15 +842,16 @@ public static void TransformNormal(ref SCNVector3 norm, ref SCNMatrix4 mat, out
/// This version doesn't calculate the inverse matrix.
/// Use this version if you already have the inverse of the desired transform to hand
///
- /// The normal to transform
+#if NET
+ /// The column-based normal to transform
+#else
+ /// The row-based normal to transform
+#endif
/// The inverse of the desired transformation
/// The transformed normal
public static SCNVector3 TransformNormalInverse(SCNVector3 norm, SCNMatrix4 invMat)
{
- SCNVector3 n;
- n.X = SCNVector3.Dot(norm, new SCNVector3(invMat.Row0));
- n.Y = SCNVector3.Dot(norm, new SCNVector3(invMat.Row1));
- n.Z = SCNVector3.Dot(norm, new SCNVector3(invMat.Row2));
+ TransformNormalInverse (ref norm, ref invMat, out var n);
return n;
}
@@ -826,11 +860,28 @@ public static SCNVector3 TransformNormalInverse(SCNVector3 norm, SCNMatrix4 invM
/// This version doesn't calculate the inverse matrix.
/// Use this version if you already have the inverse of the desired transform to hand
///
- /// The normal to transform
+#if NET
+ /// The column-based normal to transform
+#else
+ /// The row-based normal to transform
+#endif
/// The inverse of the desired transformation
/// The transformed normal
public static void TransformNormalInverse(ref SCNVector3 norm, ref SCNMatrix4 invMat, out SCNVector3 result)
{
+#if NET
+ result.X = norm.X * invMat.Column0.X +
+ norm.Y * invMat.Column0.Y +
+ norm.Z * invMat.Column0.Z;
+
+ result.Y = norm.X * invMat.Column1.X +
+ norm.Y * invMat.Column1.Y +
+ norm.Z * invMat.Column1.Z;
+
+ result.Z = norm.X * invMat.Column2.X +
+ norm.Y * invMat.Column2.Y +
+ norm.Z * invMat.Column2.Z;
+#else
result.X = norm.X * invMat.Row0.X +
norm.Y * invMat.Row0.Y +
norm.Z * invMat.Row0.Z;
@@ -842,27 +893,49 @@ public static void TransformNormalInverse(ref SCNVector3 norm, ref SCNMatrix4 in
result.Z = norm.X * invMat.Row2.X +
norm.Y * invMat.Row2.Y +
norm.Z * invMat.Row2.Z;
+#endif
}
/// Transform a Position by the given Matrix
- /// The position to transform
+#if NET
+ /// The column-based position to transform
+#else
+ /// The row-based position to transform
+#endif
/// The desired transformation
/// The transformed position
public static SCNVector3 TransformPosition(SCNVector3 pos, SCNMatrix4 mat)
{
- SCNVector3 p;
- p.X = SCNVector3.Dot(pos, new SCNVector3(mat.Column0)) + mat.Row3.X;
- p.Y = SCNVector3.Dot(pos, new SCNVector3(mat.Column1)) + mat.Row3.Y;
- p.Z = SCNVector3.Dot(pos, new SCNVector3(mat.Column2)) + mat.Row3.Z;
+ TransformPosition (ref pos, ref mat, out var p);
return p;
}
/// Transform a Position by the given Matrix
- /// The position to transform
+#if NET
+ /// The column-based position to transform
+#else
+ /// The row-based position to transform
+#endif
/// The desired transformation
/// The transformed position
public static void TransformPosition(ref SCNVector3 pos, ref SCNMatrix4 mat, out SCNVector3 result)
{
+#if NET
+ result.X = mat.Row0.X * pos.X +
+ mat.Row0.Y * pos.Y +
+ mat.Row0.Z * pos.Z +
+ mat.Row0.W;
+
+ result.Y = mat.Row1.X * pos.X +
+ mat.Row1.Y * pos.Y +
+ mat.Row1.Z * pos.Z +
+ mat.Row1.W;
+
+ result.Z = mat.Row2.X * pos.X +
+ mat.Row2.Y * pos.Y +
+ mat.Row2.Z * pos.Z +
+ mat.Row2.W;
+#else
result.X = pos.X * mat.Row0.X +
pos.Y * mat.Row1.X +
pos.Z * mat.Row2.X +
@@ -877,25 +950,29 @@ public static void TransformPosition(ref SCNVector3 pos, ref SCNMatrix4 mat, out
pos.Y * mat.Row1.Z +
pos.Z * mat.Row2.Z +
mat.Row3.Z;
+#endif
}
/// Transform a Vector by the given Matrix
- /// The vector to transform
+#if NET
+ /// The column vector to transform
+#else
+ /// The row vector to transform
+#endif
/// The desired transformation
/// The transformed vector
public static SCNVector4 Transform(SCNVector3 vec, SCNMatrix4 mat)
{
SCNVector4 v4 = new SCNVector4(vec.X, vec.Y, vec.Z, 1.0f);
- SCNVector4 result;
- result.X = SCNVector4.Dot(v4, mat.Column0);
- result.Y = SCNVector4.Dot(v4, mat.Column1);
- result.Z = SCNVector4.Dot(v4, mat.Column2);
- result.W = SCNVector4.Dot(v4, mat.Column3);
- return result;
+ return SCNVector4.Transform (v4, mat);
}
/// Transform a Vector by the given Matrix
- /// The vector to transform
+#if NET
+ /// The column vector to transform
+#else
+ /// The row vector to transform
+#endif
/// The desired transformation
/// The transformed vector
public static void Transform(ref SCNVector3 vec, ref SCNMatrix4 mat, out SCNVector4 result)
diff --git a/src/SceneKit/SCNVector4.cs b/src/SceneKit/SCNVector4.cs
index f8097c2cb4e8..d07bd7345437 100644
--- a/src/SceneKit/SCNVector4.cs
+++ b/src/SceneKit/SCNVector4.cs
@@ -843,25 +843,50 @@ public static void BaryCentric(ref SCNVector4 a, ref SCNVector4 b, ref SCNVector
#region Transform
/// Transform a Vector by the given Matrix
- /// The vector to transform
+#if NET
+ /// The column vector to transform
+#else
+ /// The row vector to transform
+#endif
/// The desired transformation
/// The transformed vector
public static SCNVector4 Transform(SCNVector4 vec, SCNMatrix4 mat)
{
- SCNVector4 result;
- result.X = SCNVector4.Dot(vec, mat.Column0);
- result.Y = SCNVector4.Dot(vec, mat.Column1);
- result.Z = SCNVector4.Dot(vec, mat.Column2);
- result.W = SCNVector4.Dot(vec, mat.Column3);
+ Transform(ref vec, ref mat, out var result);
return result;
}
- /// Transform a Vector by the given Matrix
- /// The vector to transform
+ /// Transform a Vector by the given Matrix.
+#if NET
+ /// The column vector to transform
+#else
+ /// The row vector to transform
+#endif
/// The desired transformation
/// The transformed vector
public static void Transform(ref SCNVector4 vec, ref SCNMatrix4 mat, out SCNVector4 result)
{
+#if NET
+ result.X = vec.X * mat.Column0.X +
+ vec.Y * mat.Column1.X +
+ vec.Z * mat.Column2.X +
+ vec.W * mat.Column3.X;
+
+ result.Y = vec.X * mat.Column0.Y +
+ vec.Y * mat.Column1.Y +
+ vec.Z * mat.Column2.Y +
+ vec.W * mat.Column3.Y;
+
+ result.Z = vec.X * mat.Column0.Z +
+ vec.Y * mat.Column1.Z +
+ vec.Z * mat.Column2.Z +
+ vec.W * mat.Column3.Z;
+
+ result.W = vec.X * mat.Column0.W +
+ vec.Y * mat.Column1.W +
+ vec.Z * mat.Column2.W +
+ vec.W * mat.Column3.W;
+#else
result.X = vec.X * mat.Row0.X +
vec.Y * mat.Row1.X +
vec.Z * mat.Row2.X +
@@ -881,6 +906,7 @@ public static void Transform(ref SCNVector4 vec, ref SCNMatrix4 mat, out SCNVect
vec.Y * mat.Row1.W +
vec.Z * mat.Row2.W +
vec.W * mat.Row3.W;
+#endif
}
#endregion
diff --git a/tests/bindings-test/StructsAndEnums.cs b/tests/bindings-test/StructsAndEnums.cs
index e4737da9d9d6..a8c66280a921 100644
--- a/tests/bindings-test/StructsAndEnums.cs
+++ b/tests/bindings-test/StructsAndEnums.cs
@@ -3,6 +3,7 @@
using Foundation;
using ObjCRuntime;
+using SceneKit;
#if NET
using MatrixFloat2x2 = global::CoreGraphics.NMatrix2;
@@ -16,6 +17,16 @@
using MatrixFloat4x4 = global::OpenTK.NMatrix4;
#endif
+#if __MACOS__
+#if NET
+using pfloat = System.Runtime.InteropServices.NFloat;
+#else
+using pfloat = System.nfloat;
+#endif
+#else
+using pfloat = System.Single;
+#endif
+
public static class LibTest {
[DllImport ("__Internal")]
public static extern int theUltimateAnswer ();
@@ -126,5 +137,14 @@ public static MatrixFloat4x4 MDLTransform_GetRotationMatrix (INativeObject obj,
r3c0, r3c1, r3c2, r3c3);
}
#endif
+
+ [DllImport ("__Internal")]
+ public static extern SCNMatrix4 x_SCNMatrix4MakeTranslation (pfloat tx, pfloat ty, pfloat tz);
+
+ [DllImport ("__Internal")]
+ public static extern SCNMatrix4 x_SCNMatrix4MakeScale (pfloat tx, pfloat ty, pfloat tz);
+
+ [DllImport ("__Internal")]
+ public static extern SCNMatrix4 x_SCNMatrix4Translate (SCNMatrix4 m, pfloat tx, pfloat ty, pfloat tz);
}
}
diff --git a/tests/monotouch-test/Asserts.cs b/tests/monotouch-test/Asserts.cs
index 9a4557d20557..852a5800bbdc 100644
--- a/tests/monotouch-test/Asserts.cs
+++ b/tests/monotouch-test/Asserts.cs
@@ -1,8 +1,15 @@
using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
#if !__WATCHOS__
using ModelIO;
using MetalPerformanceShaders;
#endif
+#if HAS_SCENEKIT
+using SceneKit;
+#endif
#if NET
using System.Numerics;
@@ -31,6 +38,16 @@
using VectorDouble3 = global::OpenTK.NVector3d;
#endif
+#if __MACOS__
+#if NET
+using pfloat = System.Runtime.InteropServices.NFloat;
+#else
+using pfloat = System.nfloat;
+#endif
+#else
+using pfloat = System.Single;
+#endif
+
using NUnit.Framework;
public static class Asserts
@@ -714,4 +731,285 @@ public static void AreEqual (NMatrix4x3 expected, NMatrix4x3 actual, string mess
AreEqual (expected.M34, actual.M34, $"{message} (M34) expected: {expected} actual: {actual}");
}
#endregion
+
+#if HAS_SCENEKIT
+ public static void AreEqual (SCNVector3 expected, SCNVector3 actual, string message)
+ {
+ if (AreEqual (expected.X, actual.X, out var dX) &
+ AreEqual (expected.Y, actual.Y, out var dY) &
+ AreEqual (expected.Z, actual.Z, out var dZ))
+ return;
+
+ var diffString = $"({dX}, {dY}, {dZ})";
+ var msg = $"{message}\nExpected:\n{expected}\nActual:\n{actual}\nDiff:\n{diffString}";
+ Assert.Fail (msg);
+ }
+
+ public static void AreEqual (SCNVector3 expected, SCNVector3 actual, pfloat delta, string message)
+ {
+ if (AreEqual (expected.X, actual.X, delta, out var dX) &
+ AreEqual (expected.Y, actual.Y, delta, out var dY) &
+ AreEqual (expected.Z, actual.Z, delta, out var dZ))
+ return;
+
+ var diffString = $"({dX}, {dY}, {dZ})";
+ var msg = $"{message}\nExpected:\n{expected}\nActual:\n{actual}\nDiff:\n{diffString}";
+ Assert.Fail (msg);
+ }
+
+ public static void AreEqual (SCNVector4 expected, SCNVector4 actual, string message)
+ {
+ if (AreEqual (expected.X, actual.X, out var dX) &
+ AreEqual (expected.Y, actual.Y, out var dY) &
+ AreEqual (expected.Z, actual.Z, out var dZ) &
+ AreEqual (expected.W, actual.W, out var dW))
+ return;
+
+ var diffString = $"({dX}, {dY}, {dZ}, {dW})";
+ var msg = $"{message}\nExpected:\n{expected}\nActual:\n{actual}\nDiff:\n{diffString}";
+ Assert.Fail (msg);
+ }
+
+
+ public static void AreEqual (SCNVector4 expected, SCNVector4 actual, pfloat delta, string message)
+ {
+ if (AreEqual (expected.X, actual.X, delta, out var dX) &
+ AreEqual (expected.Y, actual.Y, delta, out var dY) &
+ AreEqual (expected.Z, actual.Z, delta, out var dZ) &
+ AreEqual (expected.W, actual.W, delta, out var dW))
+ return;
+
+ var diffString = $"({dX}, {dY}, {dZ}, {dW})";
+ var msg = $"{message}\nExpected:\n{expected}\nActual:\n{actual}\nDiff:\n{diffString}";
+ Assert.Fail (msg);
+ }
+
+ public static void AreEqual (SCNQuaternion expected, SCNQuaternion actual, string message)
+ {
+ if (AreEqual (expected.X, actual.X, out var dX) &
+ AreEqual (expected.Y, actual.Y, out var dY) &
+ AreEqual (expected.Z, actual.Z, out var dZ) &
+ AreEqual (expected.W, actual.W, out var dW))
+ return;
+
+ var diffString = $"[{dX}, {dY}, {dZ}, {dW}]";
+ var msg = $"{message}\nExpected:\n{expected}\nActual:\n{actual}\nDiff:\n{diffString}";
+ Assert.Fail (msg);
+ }
+
+ public static void AreEqual (SCNQuaternion expected, SCNQuaternion actual, pfloat delta, string message)
+ {
+ if (AreEqual (expected.X, actual.X, delta, out var dX) &
+ AreEqual (expected.Y, actual.Y, delta, out var dY) &
+ AreEqual (expected.Z, actual.Z, delta, out var dZ) &
+ AreEqual (expected.W, actual.W, delta, out var dW))
+ return;
+
+ var diffString = $"[{dX}, {dY}, {dZ}, {dW}]";
+ var msg = $"{message}\nExpected:\n{expected}\nActual:\n{actual}\nDiff:\n{diffString}";
+ Assert.Fail (msg);
+ }
+
+ public static void AreEqual (SCNMatrix4 expected, SCNMatrix4 actual, string message)
+ {
+ if (AreEqual (expected.M11, actual.M11, out var d11) &
+ AreEqual (expected.M21, actual.M21, out var d21) &
+ AreEqual (expected.M31, actual.M31, out var d31) &
+ AreEqual (expected.M41, actual.M41, out var d41) &
+ AreEqual (expected.M12, actual.M12, out var d12) &
+ AreEqual (expected.M22, actual.M22, out var d22) &
+ AreEqual (expected.M32, actual.M32, out var d32) &
+ AreEqual (expected.M42, actual.M42, out var d42) &
+ AreEqual (expected.M13, actual.M13, out var d13) &
+ AreEqual (expected.M23, actual.M23, out var d23) &
+ AreEqual (expected.M33, actual.M33, out var d33) &
+ AreEqual (expected.M43, actual.M43, out var d43) &
+ AreEqual (expected.M14, actual.M14, out var d14) &
+ AreEqual (expected.M24, actual.M24, out var d24) &
+ AreEqual (expected.M34, actual.M34, out var d34) &
+ AreEqual (expected.M44, actual.M44, out var d44)) {
+
+ var size = Marshal.SizeOf (typeof (SCNMatrix4));
+ unsafe {
+ byte* e = (byte*) (void*) &expected;
+ byte* a = (byte*) (void*) &actual;
+ AreEqual (e, a, size, message);
+ }
+ return;
+ }
+
+ var actualString = actual.ToString ();
+
+ var expectedString = expected.ToString ();
+
+ var diffRow1 = $"({d11}, {d12}, {d13}, {d14})";
+ var diffRow2 = $"({d21}, {d22}, {d23}, {d24})";
+ var diffRow3 = $"({d31}, {d32}, {d33}, {d34})";
+ var diffRow4 = $"({d41}, {d42}, {d43}, {d44})";
+ var diffString = $"{diffRow1}\n{diffRow2}\n{diffRow3}\n{diffRow4}";
+
+ var msg = $"{message}\nExpected:\n{expected}\nActual:\n{actual}\nDiff:\n{diffString}";
+ Assert.Fail (msg);
+ }
+
+ public static void AreEqual (SCNMatrix4 expected, SCNMatrix4 actual, pfloat delta, string message)
+ {
+ if (AreEqual (expected.M11, actual.M11, delta, out var d11) &
+ AreEqual (expected.M21, actual.M21, delta, out var d21) &
+ AreEqual (expected.M31, actual.M31, delta, out var d31) &
+ AreEqual (expected.M41, actual.M41, delta, out var d41) &
+ AreEqual (expected.M12, actual.M12, delta, out var d12) &
+ AreEqual (expected.M22, actual.M22, delta, out var d22) &
+ AreEqual (expected.M32, actual.M32, delta, out var d32) &
+ AreEqual (expected.M42, actual.M42, delta, out var d42) &
+ AreEqual (expected.M13, actual.M13, delta, out var d13) &
+ AreEqual (expected.M23, actual.M23, delta, out var d23) &
+ AreEqual (expected.M33, actual.M33, delta, out var d33) &
+ AreEqual (expected.M43, actual.M43, delta, out var d43) &
+ AreEqual (expected.M14, actual.M14, delta, out var d14) &
+ AreEqual (expected.M24, actual.M24, delta, out var d24) &
+ AreEqual (expected.M34, actual.M34, delta, out var d34) &
+ AreEqual (expected.M44, actual.M44, delta, out var d44))
+ return;
+
+ var actualString = actual.ToString ();
+ var expectedString = expected.ToString ();
+
+ var diffRow1 = $"({d11}, {d12}, {d13}, {d14})";
+ var diffRow2 = $"({d21}, {d22}, {d23}, {d24})";
+ var diffRow3 = $"({d31}, {d32}, {d33}, {d34})";
+ var diffRow4 = $"({d41}, {d42}, {d43}, {d44})";
+ var diffString = $"{diffRow1}\n{diffRow2}\n{diffRow3}\n{diffRow4}";
+
+ var msg = $"{message}\nExpected:\n{expectedString}\nActual:\n{actualString}\nDiff:\n{diffString}";
+ Assert.Fail (msg);
+ }
+
+
+ // The m## arguments correspond with the M## fields in SCNMatrix4
+ // For .NET this means the first four values are the first column (and the first row for legacy Xamarin).
+ public static void AreEqual (SCNMatrix4 actual, string message,
+ pfloat m11, pfloat m12, pfloat m13, pfloat m14,
+ pfloat m21, pfloat m22, pfloat m23, pfloat m24,
+ pfloat m31, pfloat m32, pfloat m33, pfloat m34,
+ pfloat m41, pfloat m42, pfloat m43, pfloat m44)
+ {
+ AreEqual (actual, message,
+ m11, m12, m13, m14,
+ m21, m22, m23, m24,
+ m31, m32, m33, m34,
+ m41, m42, m43, m44,
+ delta: 0);
+ }
+
+ // The m## arguments correspond with the M## fields in SCNMatrix4
+ // For .NET this means the first four values are the first column (and the first row for legacy Xamarin).
+ public static void AreEqual (SCNMatrix4 actual, string message,
+ pfloat m11, pfloat m12, pfloat m13, pfloat m14,
+ pfloat m21, pfloat m22, pfloat m23, pfloat m24,
+ pfloat m31, pfloat m32, pfloat m33, pfloat m34,
+ pfloat m41, pfloat m42, pfloat m43, pfloat m44,
+ pfloat delta
+ )
+ {
+ if (AreEqual (m11, actual.M11, delta, out var d11) &
+ AreEqual (m21, actual.M21, delta, out var d21) &
+ AreEqual (m31, actual.M31, delta, out var d31) &
+ AreEqual (m41, actual.M41, delta, out var d41) &
+ AreEqual (m12, actual.M12, delta, out var d12) &
+ AreEqual (m22, actual.M22, delta, out var d22) &
+ AreEqual (m32, actual.M32, delta, out var d32) &
+ AreEqual (m42, actual.M42, delta, out var d42) &
+ AreEqual (m13, actual.M13, delta, out var d13) &
+ AreEqual (m23, actual.M23, delta, out var d23) &
+ AreEqual (m33, actual.M33, delta, out var d33) &
+ AreEqual (m43, actual.M43, delta, out var d43) &
+ AreEqual (m14, actual.M14, delta, out var d14) &
+ AreEqual (m24, actual.M24, delta, out var d24) &
+ AreEqual (m34, actual.M34, delta, out var d34) &
+ AreEqual (m44, actual.M44, delta, out var d44))
+ return;
+
+ var actualString = actual.ToString ();
+
+#if NET
+ var row1 = $"({m11}, {m21}, {m31}, {m41})";
+ var row2 = $"({m12}, {m22}, {m32}, {m42})";
+ var row3 = $"({m13}, {m23}, {m33}, {m43})";
+ var row4 = $"({m14}, {m24}, {m34}, {m44})";
+#else
+ var row1 = $"({m11}, {m12}, {m13}, {m14})";
+ var row2 = $"({m21}, {m22}, {m23}, {m24})";
+ var row3 = $"({m31}, {m32}, {m33}, {m34})";
+ var row4 = $"({m41}, {m42}, {m43}, {m44})";
+#endif
+ var expectedString = $"{row1}\n{row2}\n{row3}\n{row4}";
+
+ var diffRow1 = $"({d11}, {d12}, {d13}, {d14})";
+ var diffRow2 = $"({d21}, {d22}, {d23}, {d24})";
+ var diffRow3 = $"({d31}, {d32}, {d33}, {d34})";
+ var diffRow4 = $"({d41}, {d42}, {d43}, {d44})";
+ var diffString = $"{diffRow1}\n{diffRow2}\n{diffRow3}\n{diffRow4}";
+
+ var msg = $"{message}\nExpected:\n{expectedString}\nActual:\n{actualString}\nDiff:\n{diffString}";
+ Assert.Fail (msg);
+ }
+#endif // HAS_SCENEKIT
+
+ static bool AreEqual (pfloat expected, pfloat actual, out string emojii)
+ {
+ return AreEqual (expected, actual, 0, out emojii);
+ }
+
+ // Use our own implementation to compare two floating point numbers with a tolerance, because
+ // the NUnit version doesn't seem to work correctly in legacy Xamarin (older NUnit version?).
+ static bool AreEqual (pfloat expected, pfloat actual, pfloat tolerance, out string emojii)
+ {
+ bool rv;
+
+ if (pfloat.IsNaN (expected) && pfloat.IsNaN (actual)) {
+ rv = true;
+ } else if (pfloat.IsInfinity (expected) || pfloat.IsNaN (expected) || pfloat.IsNaN (actual)) {
+ // Handle infinity specially since subtracting two infinite values gives
+ // NaN and the following test fails. mono also needs NaN to be handled
+ // specially although ms.net could use either method. Also, handle
+ // situation where no tolerance is used.
+ rv = expected.Equals (actual);
+ } else {
+ rv = Math.Abs (expected - actual) <= tolerance;
+ }
+
+ emojii = rv ? "✅" : "❌";
+
+ return rv;
+ }
+
+ public unsafe static void AreEqual (byte* expected, byte* actual, int length, string message)
+ {
+ // Check if the byte arrays are identical
+ var equal = true;
+ for (var i = 0; i < length; i++) {
+ var e = expected [i];
+ var a = actual [i];
+ equal &= e == a;
+ }
+ if (equal)
+ return;
+ // They're not. Create the assertion message and assert.
+ var e_sb = new StringBuilder ();
+ var a_sb = new StringBuilder ();
+ var d_sb = new StringBuilder ();
+ for (var i = 0; i < length; i++) {
+ var e = expected [i];
+ var a = actual [i];
+ e_sb.Append ($"0x{e:X2} ");
+ a_sb.Append ($"0x{a:X2} ");
+ if (e == a) {
+ d_sb.Append (" ");
+ } else {
+ d_sb.Append ("^^^^ ");
+ }
+ }
+ Assert.Fail ($"{message}\nExpected: {e_sb}\nActual: {a_sb}\n {d_sb}");
+ }
}
diff --git a/tests/monotouch-test/SceneKit/SCNMatrixTest.cs b/tests/monotouch-test/SceneKit/SCNMatrixTest.cs
index 7f10d5a9d829..f7e0ad37f602 100644
--- a/tests/monotouch-test/SceneKit/SCNMatrixTest.cs
+++ b/tests/monotouch-test/SceneKit/SCNMatrixTest.cs
@@ -12,6 +12,7 @@
#nullable enable
using System;
+using System.Runtime.InteropServices;
using CoreAnimation;
using Foundation;
using SceneKit;
@@ -57,67 +58,21 @@ public class SCNMatrix4Test {
static pfloat SqrtTwelve = (pfloat) (Math.Sqrt (12)); // 3.464102
static pfloat OhPointFive = (pfloat) 0.5;
- public static bool CloseEnough (double a, double b, double epsilon = 0.00001)
- {
- const double MinNormal = 2.2250738585072014E-308d;
- var absA = Math.Abs (a);
- var absB = Math.Abs (b);
- var diff = Math.Abs (a - b);
-
- if (a == b) {
- return true;
- } else if (a == 0 || b == 0 || absA + absB < MinNormal) {
- // a or b is zero or both are extremely close to it
- // relative error is less meaningful here
- return diff < (epsilon * MinNormal);
- } else { // use relative error
- return diff / (absA + absB) < epsilon;
- }
- }
-
- void AssertEqual (SCNMatrix4 matrix, string message,
- pfloat m11, pfloat m12, pfloat m13, pfloat m14,
- pfloat m21, pfloat m22, pfloat m23, pfloat m24,
- pfloat m31, pfloat m32, pfloat m33, pfloat m34,
- pfloat m41, pfloat m42, pfloat m43, pfloat m44
- )
- {
- if (CloseEnough (m11, matrix.M11) && CloseEnough (m12, matrix.M12) && CloseEnough (m13, matrix.M13) && CloseEnough (m14, matrix.M14) &&
- CloseEnough (m21, matrix.M21) && CloseEnough (m22, matrix.M22) && CloseEnough (m23, matrix.M23) && CloseEnough (m24, matrix.M24) &&
- CloseEnough (m31, matrix.M31) && CloseEnough (m32, matrix.M32) && CloseEnough (m33, matrix.M33) && CloseEnough (m34, matrix.M34) &&
- CloseEnough (m41, matrix.M41) && CloseEnough (m42, matrix.M42) && CloseEnough (m43, matrix.M43) && CloseEnough (m44, matrix.M44))
- return;
-
- var actualString = matrix.ToString ();
-
- var row1 = $"({m11}, {m12}, {m13}, {m14})";
- var row2 = $"({m21}, {m22}, {m23}, {m24})";
- var row3 = $"({m31}, {m32}, {m33}, {m34})";
- var row4 = $"({m41}, {m42}, {m43}, {m44})";
- var expectedString = $"{row1}\n{row2}\n{row3}\n{row4}";
- Assert.Fail ($"Expected matrix:\n{expectedString}\nActual matrix:\n{actualString}\n{message}");
- }
-
- void AssertEqual (SCNVector4 vector, string message, pfloat m1, pfloat m2, pfloat m3, pfloat m4)
- {
- if (m1 == vector.X && m2 == vector.Y && m3 == vector.Z && m4 == vector.W)
- return;
-
- var expectedString = vector.ToString ();
- var actualString = $"({m1}, {m2}, {m3}, {m4})";
-
- Assert.Fail ($"Expected vector:\n{expectedString}\nActual vector:\n{actualString}\n{message}");
- }
-
[Test]
public void Identity ()
{
var matrix = SCNMatrix4.Identity;
- AssertEqual (matrix, "Identity",
+ var expected = new SCNMatrix4 (
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
+
+ Asserts.AreEqual (expected, matrix, "Identity");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (pos, transformed, "Transformed");
}
[Test]
@@ -128,11 +83,20 @@ public void Constructor_RowVectors ()
new SCNVector4 (21, 22, 23, 24),
new SCNVector4 (31, 32, 33, 34),
new SCNVector4 (41, 42, 43, 44));
- AssertEqual (matrix, "Constructor",
+ var expected = new SCNMatrix4 (
11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34,
41, 42, 43, 44);
+ Asserts.AreEqual (expected, matrix, "Constructor");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+#if NET
+ Asserts.AreEqual (new SCNVector3 (754, 1364, 1974), transformed, "Transformed");
+#else
+ Asserts.AreEqual (new SCNVector3 (1501, 1562, 1623), transformed, "Transformed");
+#endif
}
[Test]
@@ -143,11 +107,27 @@ public void Constructor_Elements ()
21, 22, 23, 24,
31, 32, 33, 34,
41, 42, 43, 44);
- AssertEqual (matrix, "Constructor",
+
+ Asserts.AreEqual (matrix, "Constructor",
+#if NET
+ 11, 21, 31, 41,
+ 12, 22, 32, 42,
+ 13, 23, 33, 43,
+ 14, 24, 34, 44);
+#else
11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34,
41, 42, 43, 44);
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+#if NET
+ Asserts.AreEqual (new SCNVector3 (754, 1364, 1974), transformed, "Transformed");
+#else
+ Asserts.AreEqual (new SCNVector3 (1501, 1562, 1623), transformed, "Transformed");
+#endif
}
#if !WATCH
@@ -155,29 +135,25 @@ public void Constructor_Elements ()
public void Constructor_CATransform3d ()
{
var transform = new CATransform3D () {
- M11 = 11,
- M12 = 12,
- M13 = 13,
- M14 = 14,
- M21 = 21,
- M22 = 22,
- M23 = 23,
- M24 = 24,
- M31 = 31,
- M32 = 32,
- M33 = 33,
- M34 = 34,
- M41 = 41,
- M42 = 42,
- M43 = 43,
- M44 = 44,
+ M11 = 11, M12 = 12, M13 = 13, M14 = 14,
+ M21 = 21, M22 = 22, M23 = 23, M24 = 24,
+ M31 = 31, M32 = 32, M33 = 33, M34 = 34,
+ M41 = 41, M42 = 42, M43 = 43, M44 = 44,
};
var matrix = new SCNMatrix4 (transform);
- AssertEqual (matrix, "Constructor",
- 11, 12, 13, 14,
- 21, 22, 23, 24,
- 31, 32, 33, 34,
- 41, 42, 43, 44);
+ var expected = new SCNMatrix4 (
+ 11, 21, 31, 41,
+ 12, 22, 32, 42,
+ 13, 23, 33, 43,
+ 14, 24, 34, 44);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, "Constructor");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (1501, 1562, 1623), transformed, "Transformed");
}
#endif
@@ -201,20 +177,30 @@ public void Rows ()
21, 22, 23, 24,
31, 32, 33, 34,
41, 42, 43, 44);
- AssertEqual (matrix.Row0, "Row0", 11, 12, 13, 14);
- AssertEqual (matrix.Row1, "Row1", 21, 22, 23, 24);
- AssertEqual (matrix.Row2, "Row2", 31, 32, 33, 34);
- AssertEqual (matrix.Row3, "Row3", 41, 42, 43, 44);
+ Asserts.AreEqual (matrix.Row0, new SCNVector4 (11, 12, 13, 14), "Row0");
+ Asserts.AreEqual (matrix.Row1, new SCNVector4 (21, 22, 23, 24), "Row1");
+ Asserts.AreEqual (matrix.Row2, new SCNVector4 (31, 32, 33, 34), "Row2");
+ Asserts.AreEqual (matrix.Row3, new SCNVector4 (41, 42, 43, 44), "Row3");
}
[Test]
public void Elements ()
{
+ // We're column-major in .NET, which means the first number (M#.) is the column,
+ // and the second number (M.#) is the row. That's the reverse of how it's in legacy
+ // Xamarin.
var matrix = new SCNMatrix4 (
+#if NET
+ 11, 21, 31, 41,
+ 12, 22, 32, 42,
+ 13, 23, 33, 43,
+ 14, 24, 34, 44);
+#else
11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34,
41, 42, 43, 44);
+#endif
Assert.AreEqual ((pfloat) 11, matrix.M11, "M11");
Assert.AreEqual ((pfloat) 12, matrix.M12, "M12");
Assert.AreEqual ((pfloat) 13, matrix.M13, "M13");
@@ -231,6 +217,10 @@ public void Elements ()
Assert.AreEqual ((pfloat) 42, matrix.M42, "M42");
Assert.AreEqual ((pfloat) 43, matrix.M43, "M43");
Assert.AreEqual ((pfloat) 44, matrix.M44, "M44");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (1501, 1562, 1623), transformed, "Transformed");
}
#if NET // The legacy Invert implementation seems very wrong, so only verify .NET behavior
@@ -250,13 +240,22 @@ public void Invert ()
5, 3, 5, 8,
9, 6, 4, 2,
4, 6, 9, 8);
+ var originalMatrix = matrix;
matrix.Invert ();
- AssertEqual (matrix, "Invert",
+ Assert.AreEqual (SCNMatrix4Invert (originalMatrix), matrix, "Native");
+
+ var expected = new SCNMatrix4 (
(pfloat) (-0.6181818181818182), (pfloat) (0.3151515151515151), (pfloat) (-0.030303030303030304), (pfloat) (0.3878787878787879),
(pfloat) (1.6363636363636365), (pfloat) (-0.696969696969697), (pfloat) (0.3939393939393939), (pfloat) (-1.2424242424242424),
(pfloat) (-1.3818181818181818), (pfloat) (0.3515151515151515), (pfloat) (-0.30303030303030304), (pfloat) (1.2787878787878788),
(pfloat) (0.6363636363636364), (pfloat) (-0.030303030303030304), (pfloat) (0.06060606060606061), (pfloat) (-0.5757575757575758));
+
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.00001, "Invert");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (-0.4f, 13, -14.6f), transformed, 0.00001f, "Transformed");
}
#endif
@@ -269,11 +268,20 @@ public void Transpose ()
new SCNVector4 (31, 32, 33, 34),
new SCNVector4 (41, 42, 43, 44));
matrix.Transpose ();
- AssertEqual (matrix, "Transpose",
+ var expected = new SCNMatrix4 (
11, 21, 31, 41,
12, 22, 32, 42,
13, 23, 33, 43,
14, 24, 34, 44);
+ Asserts.AreEqual (expected, matrix, "Transpose");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+#if NET
+ Asserts.AreEqual (new SCNVector3 (1501, 1562, 1623), transformed, "Transformed");
+#else
+ Asserts.AreEqual (new SCNVector3 (754, 1364, 1974), transformed, "Transformed");
+#endif
}
[Test]
@@ -284,11 +292,20 @@ public void CreateFromColumns ()
new SCNVector4 (21, 22, 23, 24),
new SCNVector4 (31, 32, 33, 34),
new SCNVector4 (41, 42, 43, 44));
- AssertEqual (matrix, "CreateFromColumns",
+ var expected = new SCNMatrix4 (
11, 21, 31, 41,
12, 22, 32, 42,
13, 23, 33, 43,
14, 24, 34, 44);
+ Asserts.AreEqual (expected, matrix, "CreateFromColumns");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+#if NET
+ Asserts.AreEqual (new SCNVector3 (1501, 1562, 1623), transformed, "Transformed");
+#else
+ Asserts.AreEqual (new SCNVector3 (754, 1364, 1974), transformed, "Transformed");
+#endif
}
[Test]
@@ -300,132 +317,249 @@ public void CreateFromColumns_Out ()
new SCNVector4 (31, 32, 33, 34),
new SCNVector4 (41, 42, 43, 44),
out var matrix);
- AssertEqual (matrix, "CreateFromColumns",
+ var expected = new SCNMatrix4 (
11, 21, 31, 41,
12, 22, 32, 42,
13, 23, 33, 43,
14, 24, 34, 44);
+ Asserts.AreEqual (expected, matrix, "CreateFromColumns");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+#if NET
+ Asserts.AreEqual (new SCNVector3 (1501, 1562, 1623), transformed, "Transformed");
+#else
+ Asserts.AreEqual (new SCNVector3 (754, 1364, 1974), transformed, "Transformed");
+#endif
}
[Test]
public void CreateFromAxisAngle_pfloat_Out ()
{
SCNMatrix4.CreateFromAxisAngle (new SCNVector3 (2, 2, 2), (pfloat) (Math.PI / 3), out var matrix);
- AssertEqual (matrix, "CreateFromAxisAngle",
+ var expected = new SCNMatrix4 (
+ TwoThirds, -OneThird, TwoThirds, 0,
TwoThirds, TwoThirds, -OneThird, 0,
-OneThird, TwoThirds, TwoThirds, 0,
- TwoThirds, -OneThird, TwoThirds, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreateFromAxisAngle");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (20, 10, 30), transformed, (pfloat) 0.00001, "Transformed");
}
[Test]
public void CreateFromAxisAngle_float_Out ()
{
SCNMatrix4.CreateFromAxisAngle (new Vector3 (2, 2, 2), (float) (Math.PI / 3), out var matrix);
- AssertEqual (matrix, "CreateFromAxisAngle",
+ var expected = new SCNMatrix4 (
+ TwoThirds, -OneThird, TwoThirds, 0,
TwoThirds, TwoThirds, -OneThird, 0,
-OneThird, TwoThirds, TwoThirds, 0,
- TwoThirds, -OneThird, TwoThirds, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreateFromAxisAngle");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (20, 10, 30), transformed, (pfloat) 0.00001, "Transformed");
}
[Test]
public void CreateFromAxisAngle_double_Out ()
{
SCNMatrix4.CreateFromAxisAngle (new Vector3d (2, 2, 2), (double) (Math.PI / 3), out var matrix);
- AssertEqual (matrix, "CreateFromAxisAngle",
+ var expected = new SCNMatrix4 (
+ TwoThirds, -OneThird, TwoThirds, 0,
TwoThirds, TwoThirds, -OneThird, 0,
-OneThird, TwoThirds, TwoThirds, 0,
- TwoThirds, -OneThird, TwoThirds, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreateFromAxisAngle");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (20, 10, 30), transformed, (pfloat) 0.000001, "Transformed");
}
[Test]
public void CreateFromAxisAngle ()
{
var matrix = SCNMatrix4.CreateFromAxisAngle (new SCNVector3 (2, 2, 2), (pfloat) (Math.PI / 3));
- AssertEqual (matrix, "CreateFromAxisAngle",
+ var expected = new SCNMatrix4 (
+ TwoThirds, -OneThird, TwoThirds, 0,
TwoThirds, TwoThirds, -OneThird, 0,
-OneThird, TwoThirds, TwoThirds, 0,
- TwoThirds, -OneThird, TwoThirds, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreateFromAxisAngle");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (20, 10, 30), transformed, 0.00001f, "Transformed");
}
[Test]
public void CreateRotationX_Out ()
{
- SCNMatrix4.CreateRotationX ((pfloat) (Math.PI / 3), out var matrix);
- AssertEqual (matrix, "CreateRotationX",
+ var angle = (pfloat) (Math.PI / 3);
+ SCNMatrix4.CreateRotationX (angle, out var matrix);
+ var expected = new SCNMatrix4 (
1, 0, 0, 0,
- 0, OhPointFive, SqrtThreeHalved, 0,
- 0, -SqrtThreeHalved, OhPointFive, 0,
+ 0, OhPointFive, -SqrtThreeHalved, 0,
+ 0, SqrtThreeHalved, OhPointFive, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreateRotationX");
+
+ Asserts.AreEqual (SCNMatrix4MakeRotation (angle, 1, 0, 0), matrix, 0.00001f, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (10, -15.980762f, 32.320508f), transformed, 0.0001f, "Transformed");
}
[Test]
public void CreateRotationX ()
{
- var matrix = SCNMatrix4.CreateRotationX ((pfloat) (Math.PI / 3));
- AssertEqual (matrix, "CreateRotationX",
+ var angle = (pfloat) (Math.PI / 3);
+ var matrix = SCNMatrix4.CreateRotationX (angle);
+ var expected = new SCNMatrix4 (
1, 0, 0, 0,
- 0, OhPointFive, SqrtThreeHalved, 0,
- 0, -SqrtThreeHalved, OhPointFive, 0,
+ 0, OhPointFive, -SqrtThreeHalved, 0,
+ 0, SqrtThreeHalved, OhPointFive, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreateRotationX");
+
+ Asserts.AreEqual (SCNMatrix4MakeRotation (angle, 1, 0, 0), matrix, 0.00001f, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (10, -15.980762f, 32.320508f), transformed, 0.0001f, "Transformed");
}
[Test]
public void CreateRotationY_Out ()
{
+ var angle = (pfloat) (Math.PI / 3);
SCNMatrix4.CreateRotationY ((pfloat) (Math.PI / 3), out var matrix);
- AssertEqual (matrix, "CreateRotationY",
- OhPointFive, 0, -SqrtThreeHalved, 0,
+ var expected = new SCNMatrix4 (
+ OhPointFive, 0, SqrtThreeHalved, 0,
0, 1, 0, 0,
- SqrtThreeHalved, 0, OhPointFive, 0,
+ -SqrtThreeHalved, 0, OhPointFive, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreateRotationY");
+
+ Asserts.AreEqual (SCNMatrix4MakeRotation (angle, 0, 1, 0), matrix, 0.00001f, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (30.98076f, 20, 6.33974f), transformed, 0.0001f, "Transformed");
}
[Test]
public void CreateRotationY ()
{
- var matrix = SCNMatrix4.CreateRotationY ((pfloat) (Math.PI / 3));
- AssertEqual (matrix, "CreateRotationY",
- OhPointFive, 0, -SqrtThreeHalved, 0,
+ var angle = (pfloat) (Math.PI / 3);
+ var matrix = SCNMatrix4.CreateRotationY (angle);
+ var expected = new SCNMatrix4 (
+ OhPointFive, 0, SqrtThreeHalved, 0,
0, 1, 0, 0,
- SqrtThreeHalved, 0, OhPointFive, 0,
+ -SqrtThreeHalved, 0, OhPointFive, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreateRotationY");
+
+ Asserts.AreEqual (SCNMatrix4MakeRotation (angle, 0, 1, 0), matrix, 0.00001f, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (30.98076f, 20, 6.33974f), transformed, 0.00001f, "Transformed");
}
[Test]
public void CreateRotationZ_Out ()
{
- SCNMatrix4.CreateRotationZ ((pfloat) (Math.PI / 3), out var matrix);
- AssertEqual (matrix, "CreateRotationZ",
- OhPointFive, SqrtThreeHalved, 0, 0,
- -SqrtThreeHalved, OhPointFive, 0, 0,
+ var angle = (pfloat) (Math.PI / 3);
+ SCNMatrix4.CreateRotationZ (angle, out var matrix);
+ var expected = new SCNMatrix4 (
+ OhPointFive, -SqrtThreeHalved, 0, 0,
+ SqrtThreeHalved, OhPointFive, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreateRotationZ");
+
+ Asserts.AreEqual (SCNMatrix4MakeRotation (angle, 0, 0, 1), matrix, 0.00001f, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (-12.320508f, 18.66025f, 30), transformed, 0.00001f, "Transformed");
}
[Test]
public void CreateRotationZ ()
{
- var matrix = SCNMatrix4.CreateRotationZ ((pfloat) (Math.PI / 3));
- AssertEqual (matrix, "CreateRotationZ",
- OhPointFive, SqrtThreeHalved, 0, 0,
- -SqrtThreeHalved, OhPointFive, 0, 0,
+ var angle = (pfloat) (Math.PI / 3);
+ var matrix = SCNMatrix4.CreateRotationZ (angle);
+ var expected = new SCNMatrix4 (
+ OhPointFive, -SqrtThreeHalved, 0, 0,
+ SqrtThreeHalved, OhPointFive, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreateRotationZ");
+
+ Asserts.AreEqual (SCNMatrix4MakeRotation (angle, 0, 0, 1), matrix, 0.00001f, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (-12.320508f, 18.66025f, 30), transformed, 0.00001f, "Transformed");
}
[Test]
public void CreateTranslation_Out ()
{
SCNMatrix4.CreateTranslation (1, 2, 3, out var matrix);
- AssertEqual (matrix, "CreateTranslation",
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 2, 3, 1);
+ var expected = new SCNMatrix4 (
+ 1, 0, 0, 1,
+ 0, 1, 0, 2,
+ 0, 0, 1, 3,
+ 0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, "CreateTranslation");
+
+ Asserts.AreEqual (SCNMatrix4MakeTranslation (new SCNVector3 (1, 2, 3)), matrix, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (11, 22, 33), transformed, "Transformed");
}
[Test]
@@ -433,22 +567,42 @@ public void CreateTranslation_Vector_Out ()
{
var translation = new SCNVector3 (1, 2, 3);
SCNMatrix4.CreateTranslation (ref translation, out var matrix);
- AssertEqual (matrix, "CreateTranslation",
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 2, 3, 1);
+ var expected = new SCNMatrix4 (
+ 1, 0, 0, 1,
+ 0, 1, 0, 2,
+ 0, 0, 1, 3,
+ 0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, "CreateTranslation");
+
+ Asserts.AreEqual (SCNMatrix4MakeTranslation (new SCNVector3 (1, 2, 3)), matrix, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (11, 22, 33), transformed, "Transformed");
}
[Test]
public void CreateTranslation ()
{
var matrix = SCNMatrix4.CreateTranslation (1, 2, 3);
- AssertEqual (matrix, "CreateTranslation",
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 2, 3, 1);
+ var expected = new SCNMatrix4 (
+ 1, 0, 0, 1,
+ 0, 1, 0, 2,
+ 0, 0, 1, 3,
+ 0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, "CreateTranslation");
+
+ Asserts.AreEqual (SCNMatrix4MakeTranslation (new SCNVector3 (1, 2, 3)), matrix, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (11, 22, 33), transformed, "Transformed");
}
[Test]
@@ -456,132 +610,227 @@ public void CreateTranslation_Vector ()
{
var translation = new SCNVector3 (1, 2, 3);
var matrix = SCNMatrix4.CreateTranslation (translation);
- AssertEqual (matrix, "CreateTranslation",
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 2, 3, 1);
+ var expected = new SCNMatrix4 (
+ 1, 0, 0, 1,
+ 0, 1, 0, 2,
+ 0, 0, 1, 3,
+ 0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, "CreateTranslation");
+
+ Asserts.AreEqual (SCNMatrix4MakeTranslation (translation), matrix, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (11, 22, 33), transformed, "Transformed");
}
[Test]
public void CreateOrthographic_Out ()
{
SCNMatrix4.CreateOrthographic (1, 2, 3, 4, out var matrix);
- AssertEqual (matrix, "CreateOrthographic",
+ var expected = new SCNMatrix4 (
2, 0, 0, 0,
0, 1, 0, 0,
- 0, 0, -2, 0,
- 0, 0, -7, 1);
+ 0, 0, -2, -7,
+ 0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, 0, "CreateOrthographic");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (20, 20, -67), transformed, 0.00001f, "Transformed");
}
[Test]
public void CreateOrthographic ()
{
var matrix = SCNMatrix4.CreateOrthographic (1, 2, 3, 4);
- AssertEqual (matrix, "CreateOrthographic",
+ var expected = new SCNMatrix4 (
2, 0, 0, 0,
0, 1, 0, 0,
- 0, 0, -2, 0,
- 0, 0, -7, 1);
+ 0, 0, -2, -7,
+ 0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, 0, "CreateOrthographic");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (20, 20, -67), transformed, 0.00001f, "Transformed");
}
[Test]
public void CreateOrthographicOffCenter_Out ()
{
SCNMatrix4.CreateOrthographicOffCenter (1, 2, 3, 4, 5, 6, out var matrix);
- AssertEqual (matrix, "CreateOrthographicOffCenter",
- 2, 0, 0, 0,
- 0, 2, 0, 0,
- 0, 0, -2, 0,
- -3, -7, -11, 1);
+ var expected = new SCNMatrix4 (
+ 2, 0, 0, -3,
+ 0, 2, 0, -7,
+ 0, 0, -2, -11,
+ 0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, "CreateOrthographicOffCenter");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (17, 33, -71), transformed, 0.00001f, "Transformed");
}
[Test]
public void CreateOrthographicOffCenter ()
{
var matrix = SCNMatrix4.CreateOrthographicOffCenter (1, 2, 3, 4, 5, 6);
- AssertEqual (matrix, "CreateOrthographicOffCenter",
- 2, 0, 0, 0,
- 0, 2, 0, 0,
- 0, 0, -2, 0,
- -3, -7, -11, 1);
+ var expected = new SCNMatrix4 (
+ 2, 0, 0, -3,
+ 0, 2, 0, -7,
+ 0, 0, -2, -11,
+ 0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, "CreateOrthographicOffCenter");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (17, 33, -71), transformed, 0.00001f, "Transformed");
}
[Test]
public void CreatePerspectiveFieldOfView_Out ()
{
SCNMatrix4.CreatePerspectiveFieldOfView ((pfloat) (Math.PI / 3), 2, 3, 4, out var matrix);
- AssertEqual (matrix, "CreatePerspectiveFieldOfView",
+ var expected = new SCNMatrix4 (
SqrtThreeHalved, 0, 0, 0,
0, SqrtThree, 0, 0,
- 0, 0, -7, -1,
- 0, 0, -24, 0);
+ 0, 0, -7, -24,
+ 0, 0, -1, 0);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreatePerspectiveFieldOfView");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (8.660254f, 34.641016f, -234), transformed, 0.00001f, "Transformed");
}
[Test]
public void CreatePerspectiveFieldOfView ()
{
var matrix = SCNMatrix4.CreatePerspectiveFieldOfView ((pfloat) (Math.PI / 3), 2, 3, 4);
- AssertEqual (matrix, "CreatePerspectiveFieldOfView",
+ var expected = new SCNMatrix4 (
SqrtThreeHalved, 0, 0, 0,
0, SqrtThree, 0, 0,
- 0, 0, -7, -1,
- 0, 0, -24, 0);
+ 0, 0, -7, -24,
+ 0, 0, -1, 0);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.000001f, "CreatePerspectiveFieldOfView");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (8.660254f, 34.641016f, -234), transformed, 0.00001f, "Transformed");
}
[Test]
public void CreatePerspectiveOffCenter_Out ()
{
SCNMatrix4.CreatePerspectiveOffCenter (1, 2, 3, 4, 5, 6, out var matrix);
- AssertEqual (matrix, "CreatePerspectiveOffCenter",
- 10, 0, 0, 0,
- 0, 10, 0, 0,
- 3, 7, -11, -1,
- 0, 0, -60, 0);
+ var expected = new SCNMatrix4 (
+ 10, 0, 3, 0,
+ 0, 10, 7, 0,
+ 0, 0, -11, -60,
+ 0, 0, -1, 0);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, "CreatePerspectiveOffCenter");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (190, 410, -390), transformed, "Transformed");
}
[Test]
public void CreatePerspectiveOffCenter ()
{
var matrix = SCNMatrix4.CreatePerspectiveOffCenter (1, 2, 3, 4, 5, 6);
- AssertEqual (matrix, "CreatePerspectiveOffCenter",
- 10, 0, 0, 0,
- 0, 10, 0, 0,
- 3, 7, -11, -1,
- 0, 0, -60, 0);
+ var expected = new SCNMatrix4 (
+ 10, 0, 3, 0,
+ 0, 10, 7, 0,
+ 0, 0, -11, -60,
+ 0, 0, -1, 0);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, "CreatePerspectiveOffCenter");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (190, 410, -390), transformed, "Transformed");
}
[Test]
public void Scale ()
{
var matrix = SCNMatrix4.Scale (2);
- AssertEqual (matrix, "CreateScale",
+ var expected = new SCNMatrix4 (
2, 0, 0, 0,
0, 2, 0, 0,
0, 0, 2, 0,
0, 0, 0, 1);
+ Asserts.AreEqual (expected, matrix, "CreateScale");
+
+ Asserts.AreEqual (SCNMatrix4MakeScale (new SCNVector3 (2, 2, 2)), matrix, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (20, 40, 60), transformed, "Transformed");
}
[Test]
public void Scale_Vector ()
{
var matrix = SCNMatrix4.Scale (new SCNVector3 (1, 2, 3));
- AssertEqual (matrix, "CreateScale",
+ var expected = new SCNMatrix4 (
1, 0, 0, 0,
0, 2, 0, 0,
0, 0, 3, 0,
0, 0, 0, 1);
+ Asserts.AreEqual (expected, matrix, "CreateScale");
+
+ Asserts.AreEqual (SCNMatrix4MakeScale (new SCNVector3 (1, 2, 3)), matrix, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (10, 40, 90), transformed, "Transformed");
}
[Test]
public void Scale_3 ()
{
var matrix = SCNMatrix4.Scale (1, 2, 3);
- AssertEqual (matrix, "CreateScale",
+ var expected = new SCNMatrix4 (
1, 0, 0, 0,
0, 2, 0, 0,
0, 0, 3, 0,
0, 0, 0, 1);
+ Asserts.AreEqual (expected, matrix, "CreateScale");
+
+ Asserts.AreEqual (SCNMatrix4MakeScale (new SCNVector3 (1, 2, 3)), matrix, "Native");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (10, 40, 90), transformed, "Transformed");
}
[Test]
@@ -589,11 +838,19 @@ public void Rotate ()
{
var quaternion = new Quaternion (1, 2, 3, 4);
var matrix = SCNMatrix4.Rotate (quaternion);
- AssertEqual (matrix, "Rotate",
- TwoFifteenths, 7 * TwoFifteenths, -OneThird, 0,
- -TwoThirds, OneThird, TwoThirds, 0,
- 11 * OneFifteenth, TwoFifteenths, TwoThirds, 0,
+ var expected = new SCNMatrix4 (
+ TwoFifteenths, -TwoThirds, 11 * OneFifteenth, 0,
+ 7 * TwoFifteenths, OneThird, TwoFifteenths, 0,
+ -OneThird, TwoThirds, TwoThirds, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.00001, "Rotate");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (pos, transformed, 0.0001f, "Transformed");
}
[Test]
@@ -601,33 +858,57 @@ public void Rotate_d ()
{
var quaternion = new Quaterniond (1, 2, 3, 4);
var matrix = SCNMatrix4.Rotate (quaternion);
- AssertEqual (matrix, "Rotate",
- TwoFifteenths, 7 * TwoFifteenths, -OneThird, 0,
- -TwoThirds, OneThird, TwoThirds, 0,
- 11 * OneFifteenth, TwoFifteenths, TwoThirds, 0,
+ var expected = new SCNMatrix4 (
+ TwoFifteenths, -TwoThirds, 11 * OneFifteenth, 0,
+ 7 * TwoFifteenths, OneThird, TwoFifteenths, 0,
+ -OneThird, TwoThirds, TwoThirds, 0,
0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.00001, "Rotate");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (pos, transformed, 0.0001f, "Transformed");
}
[Test]
public void LookAt_Vectors ()
{
var matrix = SCNMatrix4.LookAt (new SCNVector3 (1, 2, 3), new SCNVector3 (4, 5, 6), new SCNVector3 (7, 8, 9));
- AssertEqual (matrix, "LookAt",
- SqrtSixInverted, -SqrtTwoHalved, -SqrtThreeInverted, 0,
- -2 * SqrtSixInverted, 0, -SqrtThreeInverted, 0,
- SqrtSixInverted, SqrtTwoHalved, -SqrtThreeInverted, 0,
- 0, -SqrtTwo, SqrtTwelve, 1);
+ var expected = new SCNMatrix4 (
+ SqrtSixInverted, -2 * SqrtSixInverted, SqrtSixInverted, 0,
+ -SqrtTwoHalved, 0, SqrtTwoHalved, -SqrtTwo,
+ -SqrtThreeInverted, -SqrtThreeInverted, -SqrtThreeInverted, SqrtTwelve,
+ 0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.00001, "LookAt");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (0, 12.7279220f, -31.1769145f), transformed, 0.00001f, "Transformed");
}
[Test]
public void LookAt_Elements ()
{
var matrix = SCNMatrix4.LookAt (1, 2, 3, 4, 5, 6, 7, 8, 9);
- AssertEqual (matrix, "LookAt",
- SqrtSixInverted, -SqrtTwoHalved, -SqrtThreeInverted, 0,
- -2 * SqrtSixInverted, 0, -SqrtThreeInverted, 0,
- SqrtSixInverted, SqrtTwoHalved, -SqrtThreeInverted, 0,
- 0, -SqrtTwo, SqrtTwelve, 1);
+ var expected = new SCNMatrix4 (
+ SqrtSixInverted, -2 * SqrtSixInverted, SqrtSixInverted, 0,
+ -SqrtTwoHalved, 0, SqrtTwoHalved, -SqrtTwo,
+ -SqrtThreeInverted, -SqrtThreeInverted, -SqrtThreeInverted, SqrtTwelve,
+ 0, 0, 0, 1);
+#if !NET
+ expected.Transpose ();
+#endif
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.00001, "LookAt");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (0, 12.7279220f, -31.1769145f), transformed, 0.00001f, "Transformed");
}
[Test]
@@ -644,11 +925,29 @@ public void Mult ()
new SCNVector4 (931, 932, 933, 934),
new SCNVector4 (941, 942, 943, 944));
var matrix = SCNMatrix4.Mult (a, b);
- AssertEqual (matrix, "Mult",
+
+ Asserts.AreEqual (SCNMatrix4Mult (a, b), matrix, "Native");
+ var expected = new SCNMatrix4 (
+#if NET
+ 94950, 98600, 102250, 105900,
+ 95990, 99680, 103370, 107060,
+ 97030, 100760, 104490, 108220,
+ 98070, 101840, 105610, 109380);
+#else
46350, 46400, 46450, 46500,
83390, 83480, 83570, 83660,
120430, 120560, 120690, 120820,
157470, 157640, 157810, 157980);
+#endif
+ Asserts.AreEqual (expected, matrix, "Mult");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+#if NET
+ Asserts.AreEqual (new SCNVector3 (6094900, 6161660, 6228420), transformed, "Transformed");
+#else
+ Asserts.AreEqual (new SCNVector3 (5901670, 5908040, 5914410), transformed, "Transformed");
+#endif
}
[Test]
@@ -665,11 +964,29 @@ public void Mult_ByRef ()
new SCNVector4 (931, 932, 933, 934),
new SCNVector4 (941, 942, 943, 944));
SCNMatrix4.Mult (ref a, ref b, out var matrix);
- AssertEqual (matrix, "Mult",
+
+ Asserts.AreEqual (SCNMatrix4Mult (a, b), matrix, "Native");
+ var expected = new SCNMatrix4 (
+#if NET
+ 94950, 98600, 102250, 105900,
+ 95990, 99680, 103370, 107060,
+ 97030, 100760, 104490, 108220,
+ 98070, 101840, 105610, 109380);
+#else
46350, 46400, 46450, 46500,
83390, 83480, 83570, 83660,
120430, 120560, 120690, 120820,
157470, 157640, 157810, 157980);
+#endif
+ Asserts.AreEqual (expected, matrix, "Mult");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+#if NET
+ Asserts.AreEqual (new SCNVector3 (6094900, 6161660, 6228420), transformed, "Transformed");
+#else
+ Asserts.AreEqual (new SCNVector3 (5901670, 5908040, 5914410), transformed, "Transformed");
+#endif
}
#if NET // The legacy Invert implementation seems very wrong, so only verify .NET behavior
@@ -692,11 +1009,16 @@ public void Static_Invert ()
var matrix = SCNMatrix4.Invert (a);
- AssertEqual (matrix, "Invert",
+ var expected = new SCNMatrix4 (
(pfloat) (-0.6181818181818182), (pfloat) (0.3151515151515151), (pfloat) (-0.030303030303030304), (pfloat) (0.3878787878787879),
(pfloat) (1.6363636363636365), (pfloat) (-0.696969696969697), (pfloat) (0.3939393939393939), (pfloat) (-1.2424242424242424),
(pfloat) (-1.3818181818181818), (pfloat) (0.3515151515151515), (pfloat) (-0.30303030303030304), (pfloat) (1.2787878787878788),
(pfloat) (0.6363636363636364), (pfloat) (-0.030303030303030304), (pfloat) (0.06060606060606061), (pfloat) (-0.5757575757575758));
+ Asserts.AreEqual (expected, matrix, (pfloat) 0.00001f, "Invert");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (-0.4f, 13, -14.6f), transformed, 0.00001f, "Transformed");
}
#endif
@@ -709,11 +1031,20 @@ public void Static_Transpose ()
new SCNVector4 (31, 32, 33, 34),
new SCNVector4 (41, 42, 43, 44));
var matrix = SCNMatrix4.Transpose (a);
- AssertEqual (matrix, "Transpose",
+ var expected = new SCNMatrix4 (
11, 21, 31, 41,
12, 22, 32, 42,
13, 23, 33, 43,
14, 24, 34, 44);
+ Asserts.AreEqual (expected, matrix, "Transpose");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+#if NET
+ Asserts.AreEqual (new SCNVector3 (1501, 1562, 1623), transformed, "Transformed");
+#else
+ Asserts.AreEqual (new SCNVector3 (754, 1364, 1974), transformed, "Transformed");
+#endif
}
[Test]
@@ -725,11 +1056,20 @@ public void Static_Transpose_ByRef ()
new SCNVector4 (31, 32, 33, 34),
new SCNVector4 (41, 42, 43, 44));
SCNMatrix4.Transpose (ref a, out var matrix);
- AssertEqual (matrix, "Transpose",
+ var expected = new SCNMatrix4 (
11, 21, 31, 41,
12, 22, 32, 42,
13, 23, 33, 43,
14, 24, 34, 44);
+ Asserts.AreEqual (expected, matrix, "Transpose");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+#if NET
+ Asserts.AreEqual (new SCNVector3 (1501, 1562, 1623), transformed, "Transformed");
+#else
+ Asserts.AreEqual (new SCNVector3 (754, 1364, 1974), transformed, "Transformed");
+#endif
}
[Test]
@@ -746,11 +1086,28 @@ public void Operator_Multiply ()
new SCNVector4 (931, 932, 933, 934),
new SCNVector4 (941, 942, 943, 944));
var matrix = a * b;
- AssertEqual (matrix, "*",
+ Asserts.AreEqual (SCNMatrix4Mult (a, b), matrix, "Native");
+ var expected = new SCNMatrix4 (
+#if NET
+ 94950, 98600, 102250, 105900,
+ 95990, 99680, 103370, 107060,
+ 97030, 100760, 104490, 108220,
+ 98070, 101840, 105610, 109380);
+#else
46350, 46400, 46450, 46500,
83390, 83480, 83570, 83660,
120430, 120560, 120690, 120820,
157470, 157640, 157810, 157980);
+#endif
+ Asserts.AreEqual (expected, matrix, "*");
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+#if NET
+ Asserts.AreEqual (new SCNVector3 (6094900, 6161660, 6228420), transformed, "Transformed");
+#else
+ Asserts.AreEqual (new SCNVector3 (5901670, 5908040, 5914410), transformed, "Transformed");
+#endif
}
[Test]
@@ -827,6 +1184,151 @@ public void IEquatable_Equals ()
new SCNVector4 (941, 942, 943, 944));
Assert.IsFalse (((IEquatable) a).Equals (b), "object.Equals");
}
+
+ [Test]
+ public void CreateRotationX_NodeComparison ()
+ {
+ // Create a test node (it defaults to position 0,0,0)
+ var node = SCNNode.Create ();
+ // Create a translation matrix
+ var angle = (pfloat) (Math.PI / 2);
+ // Use that matrix to transform the node
+ node.Transform = SCNMatrix4.CreateRotationX (angle);
+ Asserts.AreEqual (new SCNVector3 (angle, 0, 0), node.EulerAngles, 0.000001f, "EulerAngles");
+ Asserts.AreEqual (new SCNQuaternion (SqrtTwoHalved, 0, 0, SqrtTwoHalved), node.Orientation, 0.000001f, "Orientation");
+ Asserts.AreEqual (new SCNVector3 (0, 0, 0), node.Position, "Position");
+ Asserts.AreEqual (new SCNVector4 (1, 0, 0, angle), node.Rotation, 0.000001f, "Rotation");
+ Asserts.AreEqual (new SCNVector3 (1, 1, 1), node.Scale, "Scale");
+ }
+
+ [Test]
+ public void CreateTranslationAndTransformPosition ()
+ {
+ // Create test point
+ var point = new SCNVector3 (1, 2, 3);
+ // Create translation
+ var matrix = SCNMatrix4.CreateTranslation (10, 0, 0);
+ // Transform the point
+ var newPoint = SCNVector3.TransformPosition (point, matrix);
+ Asserts.AreEqual (new SCNVector3 (11, 2, 3), newPoint, "A");
+ }
+
+ [Test]
+ public void TranslationPosition_ret ()
+ {
+ // Create test point
+ var point = new SCNVector3 (1, 2, 3);
+ // Create translation
+ var matrix =
+ SCNMatrix4.CreateTranslation (-1, 0, 0) *
+ SCNMatrix4.Scale (10, 1, 1);
+ // Transform the point
+ var newPoint = SCNVector3.TransformPosition (point, matrix);
+ Asserts.AreEqual (new SCNVector3 (0, 2, 3), newPoint, "A");
+ }
+
+ [Test]
+ public void TranslationPosition_out ()
+ {
+ // Create test point
+ var point = new SCNVector3 (1, 2, 3);
+ // Create translation
+ var matrix =
+ SCNMatrix4.CreateTranslation (-1, 0, 0) *
+ SCNMatrix4.Scale (10, 1, 1);
+ // Transform the point
+ SCNVector3.TransformPosition (ref point, ref matrix, out var newPoint);
+ Asserts.AreEqual (new SCNVector3 (0, 2, 3), newPoint, "A");
+ }
+
+ [Test]
+ public void CreateTranslations_ret_floats ()
+ {
+ // Create a test node (it defaults to position 0,0,0)
+ var node = SCNNode.Create ();
+ // Create a translation matrix
+ var matrix = SCNMatrix4.CreateTranslation (1, 2, 3);
+ // Use that matrix to transform the node
+ node.Transform = matrix;
+ // Ask the node to extract just the translation part of the matrix
+ var newPoint = node.Position;
+ // Verify that it is now positioned at (1,2,3)
+ Asserts.AreEqual (new SCNVector3 (1, 2, 3), newPoint, "A");
+ }
+
+ [Test]
+ public void CreateTranslations_ret_SCNVector3 ()
+ {
+ // Create a test node (it defaults to position 0,0,0)
+ var node = SCNNode.Create ();
+ // Create a translation matrix
+ var matrix = SCNMatrix4.CreateTranslation (new SCNVector3 (1, 2, 3));
+ // Use that matrix to transform the node
+ node.Transform = matrix;
+ // Ask the node to extract just the translation part of the matrix
+ var newPoint = node.Position;
+ // Verify that it is now positioned at (1,2,3)
+ Asserts.AreEqual (new SCNVector3 (1, 2, 3), newPoint, "A");
+ }
+
+ [Test]
+ public void CreateTranslations_out_floats ()
+ {
+ // Create a test node (it defaults to position 0,0,0)
+ var node = SCNNode.Create ();
+ // Create a translation matrix
+ SCNMatrix4.CreateTranslation (1, 2, 3, out var matrix);
+ // Use that matrix to transform the node
+ node.Transform = matrix;
+ // Ask the node to extract just the translation part of the matrix
+ var newPoint = node.Position;
+ // Verify that it is now positioned at (1,2,3)
+ Asserts.AreEqual (new SCNVector3 (1, 2, 3), newPoint, "A");
+ }
+
+ [Test]
+ public void CreateTranslations_out_SCNVector3 ()
+ {
+ // Create a test node (it defaults to position 0,0,0)
+ var node = SCNNode.Create ();
+ // Create a translation matrix
+ var vector = new SCNVector3 (1, 2, 3);
+ SCNMatrix4.CreateTranslation (ref vector, out var matrix);
+ // Use that matrix to transform the node
+ node.Transform = matrix;
+ // Ask the node to extract just the translation part of the matrix
+ var newPoint = node.Position;
+ // Verify that it is now positioned at (1,2,3)
+ Asserts.AreEqual (new SCNVector3 (1, 2, 3), newPoint, "A");
+ }
+
+ [Test]
+ public void SCNMatrix4Translate ()
+ {
+ var translationVector = new SCNVector3 (1, 2, 3);
+ var managedTranslation = SCNMatrix4.CreateTranslation (translationVector);
+ var nativeTranslation = SCNMatrix4MakeTranslation (translationVector);
+ Asserts.AreEqual (nativeTranslation, managedTranslation, "A");
+ }
+
+ static SCNMatrix4 SCNMatrix4MakeTranslation (SCNVector3 v)
+ {
+ return global::Bindings.Test.CFunctions.x_SCNMatrix4MakeTranslation (v.X, v.Y, v.Z);
+ }
+
+ static SCNMatrix4 SCNMatrix4MakeScale (SCNVector3 v)
+ {
+ return global::Bindings.Test.CFunctions.x_SCNMatrix4MakeScale (v.X, v.Y, v.Z);
+ }
+
+ [DllImport (global::ObjCRuntime.Constants.SceneKitLibrary)]
+ static extern SCNMatrix4 SCNMatrix4MakeRotation (pfloat angle, pfloat x, pfloat y, pfloat z);
+
+ [DllImport (global::ObjCRuntime.Constants.SceneKitLibrary)]
+ static extern SCNMatrix4 SCNMatrix4Mult (SCNMatrix4 a, SCNMatrix4 b);
+
+ [DllImport (global::ObjCRuntime.Constants.SceneKitLibrary)]
+ static extern SCNMatrix4 SCNMatrix4Invert (SCNMatrix4 a);
}
}
#endif // !__WATCHOS__
diff --git a/tests/monotouch-test/SceneKit/SCNVector3Test.cs b/tests/monotouch-test/SceneKit/SCNVector3Test.cs
new file mode 100644
index 000000000000..381055025ff3
--- /dev/null
+++ b/tests/monotouch-test/SceneKit/SCNVector3Test.cs
@@ -0,0 +1,247 @@
+//
+// Unit tests for SCNMatrix4
+//
+// Authors:
+// Sebastien Pouliot
+//
+// Copyright 2014 Xamarin Inc. All rights reserved.
+//
+
+#if HAS_SCENEKIT
+
+#nullable enable
+
+using System;
+using Foundation;
+using SceneKit;
+
+using NUnit.Framework;
+
+#if __MACOS__
+#if NET
+using pfloat = System.Runtime.InteropServices.NFloat;
+#else
+using pfloat = System.nfloat;
+#endif
+#else
+using pfloat = System.Single;
+#endif
+
+namespace MonoTouchFixtures.SceneKit {
+
+ [TestFixture]
+ [Preserve (AllMembers = true)]
+ public class SCNVector3Test
+ {
+ static pfloat delta = (pfloat) 0.000001;
+
+ [Test]
+ public void TransformVector()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformVector (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (740, 1340, 1940), transformed, "Transformed");
+ }
+
+ [Test]
+ public void TransformVector_out ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ SCNVector3.TransformVector (ref pos, ref matrix, out var transformed);
+ Asserts.AreEqual (new SCNVector3 (740, 1340, 1940), transformed, "Transformed");
+ }
+
+ [Test]
+ public void TransformNormal ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, -22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, -44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ pos.Normalize ();
+ var transformed = SCNVector3.TransformNormal (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 ((pfloat) 0.406966, 0, (pfloat) (-0.151853)), transformed, delta, "Transformed");
+ }
+
+ [Test]
+ public void TransformNormal_out ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, -22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, -44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ pos.Normalize ();
+ SCNVector3.TransformNormal (ref pos, ref matrix, out var transformed);
+ Asserts.AreEqual (new SCNVector3 ((pfloat) 0.406966, 0, (pfloat) (-0.151853)), transformed, delta, "Transformed");
+ }
+
+ [Test]
+ public void TransformNormalInverse ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ pos.Normalize ();
+ var transformed = SCNVector3.TransformNormalInverse (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 ((pfloat) 39.0201413, (pfloat) 40.62370877, (pfloat) 42.2272762), transformed, delta, "Transformed");
+ }
+
+ [Test]
+ public void TransformNormalInverse_out ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ pos.Normalize ();
+ SCNVector3.TransformNormalInverse (ref pos, ref matrix, out var transformed);
+ Asserts.AreEqual (new SCNVector3 ((pfloat) 39.0201413, (pfloat) 40.62370877, (pfloat) 42.2272762), transformed, delta, "Transformed");
+ }
+
+ [Test]
+ public void TransformPosition ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPosition (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 (754, 1364, 1974), transformed, "Transformed");
+ }
+
+ [Test]
+ public void TransformPosition_out ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ SCNVector3.TransformPosition (ref pos, ref matrix, out var transformed);
+ Asserts.AreEqual (new SCNVector3 (754, 1364, 1974), transformed, "Transformed");
+ }
+
+ [Test]
+ public void Transform ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.Transform (pos, matrix);
+ Asserts.AreEqual (new SCNVector4 (754, 1364, 1974, 2584), transformed, "Transformed");
+ }
+
+ [Test]
+ public void Transform_out ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ SCNVector3.Transform (ref pos, ref matrix, out var transformed);
+ Asserts.AreEqual (new SCNVector4 (754, 1364, 1974, 2584), transformed, "Transformed");
+ }
+
+ [Test]
+ public void TransformPerspective ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ var transformed = SCNVector3.TransformPerspective (pos, matrix);
+ Asserts.AreEqual (new SCNVector3 ((pfloat) 0.291795, (pfloat) 0.5278637, (pfloat) 0.76393188), transformed, delta, "Transformed");
+ }
+
+ [Test]
+ public void TransformPerspective_out ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector3 (10, 20, 30);
+ SCNVector3.TransformPerspective (ref pos, ref matrix, out var transformed);
+ Asserts.AreEqual (new SCNVector3 ((pfloat) 0.291795, (pfloat) 0.5278637, (pfloat) 0.76393188), transformed, delta, "Transformed");
+ }
+ }
+}
+#endif // HAS_SCENEKIT
diff --git a/tests/monotouch-test/SceneKit/SCNVector4Test.cs b/tests/monotouch-test/SceneKit/SCNVector4Test.cs
new file mode 100644
index 000000000000..8029638d5dda
--- /dev/null
+++ b/tests/monotouch-test/SceneKit/SCNVector4Test.cs
@@ -0,0 +1,73 @@
+//
+// Unit tests for SCNMatrix4
+//
+// Authors:
+// Sebastien Pouliot
+//
+// Copyright 2014 Xamarin Inc. All rights reserved.
+//
+
+#if HAS_SCENEKIT
+
+#nullable enable
+
+using System;
+using Foundation;
+using SceneKit;
+
+using NUnit.Framework;
+
+#if __MACOS__
+#if NET
+using pfloat = System.Runtime.InteropServices.NFloat;
+#else
+using pfloat = System.nfloat;
+#endif
+#else
+using pfloat = System.Single;
+#endif
+
+namespace MonoTouchFixtures.SceneKit {
+
+ [TestFixture]
+ [Preserve (AllMembers = true)]
+ public class SCNVector4Test
+ {
+ [Test]
+ public void Transform ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector4 (10, 20, 30, 40);
+ var transformed = SCNVector4.Transform (pos, matrix);
+ Asserts.AreEqual (new SCNVector4 (1300, 2300, 3300, 4300), transformed, "Transformed");
+ }
+
+ [Test]
+ public void Transform_out ()
+ {
+ var matrix = new SCNMatrix4 (
+ 11, 12, 13, 14,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44);
+#if !NET
+ matrix.Transpose ();
+#endif
+
+ var pos = new SCNVector4 (10, 20, 30, 40);
+ SCNVector4.Transform (ref pos, ref matrix, out var transformed);
+ Asserts.AreEqual (new SCNVector4 (1300, 2300, 3300, 4300), transformed, "Transformed");
+ }
+
+ }
+}
+
+#endif // HAS_SCENEKIT
diff --git a/tests/monotouch-test/monotouch-test.csproj b/tests/monotouch-test/monotouch-test.csproj
index 8160ca4c9731..19e77aa2b97f 100644
--- a/tests/monotouch-test/monotouch-test.csproj
+++ b/tests/monotouch-test/monotouch-test.csproj
@@ -223,6 +223,8 @@
ApplePlatform.cs
+
+
diff --git a/tests/test-libraries/libtest.h b/tests/test-libraries/libtest.h
index 311327e0e4df..c0e7211e73e5 100644
--- a/tests/test-libraries/libtest.h
+++ b/tests/test-libraries/libtest.h
@@ -8,6 +8,8 @@
#import
#endif
+#import
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -29,6 +31,16 @@ void x_mdltransform_create_global_transform (MDLObject *object, NSTimeInterval t
void x_mdltransform_get_rotation_matrix (MDLTransform *self, NSTimeInterval time, float* r0c0, float* r0c1, float* r0c2, float* r0c3, float* r1c0, float* r1c1, float* r1c2, float* r1c3, float* r2c0, float* r2c1, float* r2c2, float* r2c3, float* r3c0, float* r3c1, float* r3c2, float* r3c3);
#endif
+#if TARGET_OS_OSX
+#define pfloat CGFloat
+#else
+#define pfloat float
+#endif
+
+SCNMatrix4 x_SCNMatrix4MakeTranslation (pfloat tx, pfloat ty, pfloat tz);
+SCNMatrix4 x_SCNMatrix4MakeScale (pfloat tx, pfloat ty, pfloat tz);
+SCNMatrix4 x_SCNMatrix4Translate (SCNMatrix4 m, pfloat tx, pfloat ty, pfloat tz);
+
/*
* Various structs used in ObjCRegistrarTest
*/
diff --git a/tests/test-libraries/libtest.m b/tests/test-libraries/libtest.m
index 8b980bc0316b..689a950e0995 100644
--- a/tests/test-libraries/libtest.m
+++ b/tests/test-libraries/libtest.m
@@ -250,6 +250,24 @@ void x_call_block (x_block_callback block)
}
#endif // !TARGET_OS_WATCH
+SCNMatrix4
+x_SCNMatrix4MakeTranslation (pfloat tx, pfloat ty, pfloat tz)
+{
+ return SCNMatrix4MakeTranslation (tx, ty, tz);
+}
+
+SCNMatrix4
+x_SCNMatrix4MakeScale (pfloat tx, pfloat ty, pfloat tz)
+{
+ return SCNMatrix4MakeScale (tx, ty, tz);
+}
+
+SCNMatrix4
+x_SCNMatrix4Translate (SCNMatrix4 m, pfloat tx, pfloat ty, pfloat tz)
+{
+ return SCNMatrix4Translate (m, tx, ty, tz);
+}
+
@interface UltimateMachine : NSObject {
}
diff --git a/tests/test-libraries/rename.h b/tests/test-libraries/rename.h
index 86146b801cf2..9f07f7da0eea 100644
--- a/tests/test-libraries/rename.h
+++ b/tests/test-libraries/rename.h
@@ -68,6 +68,9 @@
#define x_get_matrix_float3x3 object_x_get_matrix_float3x3
#define x_get_matrix_float2x2 object_x_get_matrix_float2x2
#define x_call_block object_x_call_block
+ #define x_SCNMatrix4MakeTranslation object_x_SCNMatrix4MakeTranslation
+ #define x_SCNMatrix4MakeScale object_x_SCNMatrix4MakeScale
+ #define x_SCNMatrix4Translate object_x_SCNMatrix4Translate
#elif PREFIX == 2
#define theUltimateAnswer ar_theUltimateAnswer
#define useZLib ar_useZLib
@@ -137,6 +140,9 @@
#define x_get_matrix_float3x3 ar_x_get_matrix_float3x3
#define x_get_matrix_float2x2 ar_x_get_matrix_float2x2
#define x_call_block ar_x_call_block
+ #define x_SCNMatrix4MakeTranslation ar_x_SCNMatrix4MakeTranslation
+ #define x_SCNMatrix4MakeScale ar_x_SCNMatrix4MakeScale
+ #define x_SCNMatrix4Translate ar_x_SCNMatrix4Translate
#else
// keep original names
#endif
diff --git a/tests/xammac_tests/xammac_tests.csproj b/tests/xammac_tests/xammac_tests.csproj
index 852d06b86265..e24917711cc2 100644
--- a/tests/xammac_tests/xammac_tests.csproj
+++ b/tests/xammac_tests/xammac_tests.csproj
@@ -14,6 +14,7 @@
latest
PackageReference
..
+ $(RootTestsDirectory)\..\src\build\macos-defines.rsp
true
diff --git a/tools/devops/automation/templates/tests/run-tests.yml b/tools/devops/automation/templates/tests/run-tests.yml
index 698f879f65b4..5d72aa808676 100644
--- a/tools/devops/automation/templates/tests/run-tests.yml
+++ b/tools/devops/automation/templates/tests/run-tests.yml
@@ -148,6 +148,7 @@ steps:
make -C src build/ios.rsp
make -C src build/ios-defines.rsp
make -C src build/tvos-defines.rsp
+ make -C src build/macos-defines.rsp
make -C src build/dotnet/macos-defines-dotnet.rsp
make -C src build/dotnet/ios-defines-dotnet.rsp
make -C src build/dotnet/maccatalyst-defines-dotnet.rsp