C#: Basis fixes and cleanup

Fix Basis operator[int]. Now it returns columns instead of rows.
Fix Transform2D.AfficeInverse() mutating rather than returning a new Transform2D.
This commit is contained in:
Ignacio Etcheverry 2019-02-23 18:22:27 +01:00
parent aa5b99821b
commit 2c26e7f174
5 changed files with 318 additions and 254 deletions

View File

@ -45,74 +45,119 @@ namespace Godot
new Basis(0f, -1f, 0f, 0f, 0f, -1f, 1f, 0f, 0f) new Basis(0f, -1f, 0f, 0f, 0f, -1f, 1f, 0f, 0f)
}; };
// NOTE: x, y and z are public-only. Use Column0, Column1 and Column2 internally.
/// <summary>
/// Returns the basis matrixs x vector.
/// This is equivalent to <see cref="Column0"/>.
/// </summary>
public Vector3 x public Vector3 x
{ {
get { return GetAxis(0); } get => Column0;
set { SetAxis(0, value); } set => Column0 = value;
} }
/// <summary>
/// Returns the basis matrixs y vector.
/// This is equivalent to <see cref="Column1"/>.
/// </summary>
public Vector3 y public Vector3 y
{ {
get { return GetAxis(1); }
set { SetAxis(1, value); } get => Column1;
set => Column1 = value;
} }
/// <summary>
/// Returns the basis matrixs z vector.
/// This is equivalent to <see cref="Column2"/>.
/// </summary>
public Vector3 z public Vector3 z
{ {
get { return GetAxis(2); }
set { SetAxis(2, value); } get => Column2;
set => Column2 = value;
} }
private Vector3 _x; public Vector3 Row0;
private Vector3 _y; public Vector3 Row1;
private Vector3 _z; public Vector3 Row2;
public static Basis Identity public Vector3 Column0
{ {
get { return identity; } get => new Vector3(Row0.x, Row1.x, Row2.x);
set
{
this.Row0.x = value.x;
this.Row1.x = value.y;
this.Row2.x = value.z;
} }
}
public Vector3 Column1
{
get => new Vector3(Row0.y, Row1.y, Row2.y);
set
{
this.Row0.y = value.x;
this.Row1.y = value.y;
this.Row2.y = value.z;
}
}
public Vector3 Column2
{
get => new Vector3(Row0.z, Row1.z, Row2.z);
set
{
this.Row0.z = value.x;
this.Row1.z = value.y;
this.Row2.z = value.z;
}
}
public static Basis Identity => identity;
public Vector3 Scale public Vector3 Scale
{ {
get get
{ {
return new Vector3 real_t detSign = Mathf.Sign(Determinant());
return detSign * new Vector3
( (
new Vector3(this[0, 0], this[1, 0], this[2, 0]).Length(), new Vector3(this.Row0[0], this.Row1[0], this.Row2[0]).Length(),
new Vector3(this[0, 1], this[1, 1], this[2, 1]).Length(), new Vector3(this.Row0[1], this.Row1[1], this.Row2[1]).Length(),
new Vector3(this[0, 2], this[1, 2], this[2, 2]).Length() new Vector3(this.Row0[2], this.Row1[2], this.Row2[2]).Length()
); );
} }
} }
public Vector3 this[int index] public Vector3 this[int columnIndex]
{ {
get get
{ {
switch (index) switch (columnIndex)
{ {
case 0: case 0:
return _x; return Column0;
case 1: case 1:
return _y; return Column1;
case 2: case 2:
return _z; return Column2;
default: default:
throw new IndexOutOfRangeException(); throw new IndexOutOfRangeException();
} }
} }
set set
{ {
switch (index) switch (columnIndex)
{ {
case 0: case 0:
_x = value; Column0 = value;
return; return;
case 1: case 1:
_y = value; Column1 = value;
return; return;
case 2: case 2:
_z = value; Column2 = value;
return; return;
default: default:
throw new IndexOutOfRangeException(); throw new IndexOutOfRangeException();
@ -120,51 +165,53 @@ namespace Godot
} }
} }
public real_t this[int index, int axis] public real_t this[int columnIndex, int rowIndex]
{ {
get get
{ {
switch (index) switch (columnIndex)
{ {
case 0: case 0:
return _x[axis]; return Column0[rowIndex];
case 1: case 1:
return _y[axis]; return Column1[rowIndex];
case 2: case 2:
return _z[axis]; return Column2[rowIndex];
default: default:
throw new IndexOutOfRangeException(); throw new IndexOutOfRangeException();
} }
} }
set set
{ {
switch (index) switch (columnIndex)
{ {
case 0: case 0:
_x[axis] = value; {
var column0 = Column0;
column0[rowIndex] = value;
Column0 = column0;
return; return;
}
case 1: case 1:
_y[axis] = value; {
var column1 = Column1;
column1[rowIndex] = value;
Column1 = column1;
return; return;
}
case 2: case 2:
_z[axis] = value; {
var column2 = Column2;
column2[rowIndex] = value;
Column2 = column2;
return; return;
}
default: default:
throw new IndexOutOfRangeException(); throw new IndexOutOfRangeException();
} }
} }
} }
internal static Basis CreateFromAxes(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis)
{
return new Basis
(
xAxis.x, yAxis.x, zAxis.x,
xAxis.y, yAxis.y, zAxis.y,
xAxis.z, yAxis.z, zAxis.z
);
}
internal Quat RotationQuat() internal Quat RotationQuat()
{ {
Basis orthonormalizedBasis = Orthonormalized(); Basis orthonormalizedBasis = Orthonormalized();
@ -191,29 +238,19 @@ namespace Godot
private void SetDiagonal(Vector3 diagonal) private void SetDiagonal(Vector3 diagonal)
{ {
_x = new Vector3(diagonal.x, 0, 0); Row0 = new Vector3(diagonal.x, 0, 0);
_y = new Vector3(0, diagonal.y, 0); Row1 = new Vector3(0, diagonal.y, 0);
_z = new Vector3(0, 0, diagonal.z); Row2 = new Vector3(0, 0, diagonal.z);
} }
public real_t Determinant() public real_t Determinant()
{ {
return this[0, 0] * (this[1, 1] * this[2, 2] - this[2, 1] * this[1, 2]) - real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1];
this[1, 0] * (this[0, 1] * this[2, 2] - this[2, 1] * this[0, 2]) + real_t cofac10 = Row1[2] * Row2[0] - Row1[0] * Row2[2];
this[2, 0] * (this[0, 1] * this[1, 2] - this[1, 1] * this[0, 2]); real_t cofac20 = Row1[0] * Row2[1] - Row1[1] * Row2[0];
}
public Vector3 GetAxis(int axis) return Row0[0] * cofac00 + Row0[1] * cofac10 + Row0[2] * cofac20;
{
return new Vector3(this[0, axis], this[1, axis], this[2, axis]);
}
public void SetAxis(int axis, Vector3 value)
{
this[0, axis] = value.x;
this[1, axis] = value.y;
this[2, axis] = value.z;
} }
public Vector3 GetEuler() public Vector3 GetEuler()
@ -223,32 +260,80 @@ namespace Godot
Vector3 euler; Vector3 euler;
euler.z = 0.0f; euler.z = 0.0f;
real_t mxy = m[1, 2]; real_t mxy = m.Row1[2];
if (mxy < 1.0f) if (mxy < 1.0f)
{ {
if (mxy > -1.0f) if (mxy > -1.0f)
{ {
euler.x = Mathf.Asin(-mxy); euler.x = Mathf.Asin(-mxy);
euler.y = Mathf.Atan2(m[0, 2], m[2, 2]); euler.y = Mathf.Atan2(m.Row0[2], m.Row2[2]);
euler.z = Mathf.Atan2(m[1, 0], m[1, 1]); euler.z = Mathf.Atan2(m.Row1[0], m.Row1[1]);
} }
else else
{ {
euler.x = Mathf.Pi * 0.5f; euler.x = Mathf.Pi * 0.5f;
euler.y = -Mathf.Atan2(-m[0, 1], m[0, 0]); euler.y = -Mathf.Atan2(-m.Row0[1], m.Row0[0]);
} }
} }
else else
{ {
euler.x = -Mathf.Pi * 0.5f; euler.x = -Mathf.Pi * 0.5f;
euler.y = -Mathf.Atan2(-m[0, 1], m[0, 0]); euler.y = -Mathf.Atan2(-m.Row0[1], m.Row0[0]);
} }
return euler; return euler;
} }
public Vector3 GetRow(int index)
{
switch (index)
{
case 0:
return Row0;
case 1:
return Row1;
case 2:
return Row2;
default:
throw new IndexOutOfRangeException();
}
}
public void SetRow(int index, Vector3 value)
{
switch (index)
{
case 0:
Row0 = value;
return;
case 1:
Row1 = value;
return;
case 2:
Row2 = value;
return;
default:
throw new IndexOutOfRangeException();
}
}
public Vector3 GetColumn(int index)
{
return this[index];
}
public void SetColumn(int index, Vector3 value)
{
this[index] = value;
}
[Obsolete("GetAxis is deprecated. Use GetColumn instead.")]
public Vector3 GetAxis(int axis)
{
return new Vector3(this.Row0[axis], this.Row1[axis], this.Row2[axis]);
}
public int GetOrthogonalIndex() public int GetOrthogonalIndex()
{ {
var orth = this; var orth = this;
@ -257,7 +342,9 @@ namespace Godot
{ {
for (int j = 0; j < 3; j++) for (int j = 0; j < 3; j++)
{ {
real_t v = orth[i, j]; var row = orth.GetRow(i);
real_t v = row[j];
if (v > 0.5f) if (v > 0.5f)
v = 1.0f; v = 1.0f;
@ -266,7 +353,9 @@ namespace Godot
else else
v = 0f; v = 0f;
orth[i, j] = v; row[j] = v;
orth.SetRow(i, row);
} }
} }
@ -281,57 +370,45 @@ namespace Godot
public Basis Inverse() public Basis Inverse()
{ {
var inv = this; real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1];
real_t cofac10 = Row1[2] * Row2[0] - Row1[0] * Row2[2];
real_t cofac20 = Row1[0] * Row2[1] - Row1[1] * Row2[0];
real_t[] co = { real_t det = Row0[0] * cofac00 + Row0[1] * cofac10 + Row0[2] * cofac20;
inv[1, 1] * inv[2, 2] - inv[1, 2] * inv[2, 1],
inv[1, 2] * inv[2, 0] - inv[1, 0] * inv[2, 2],
inv[1, 0] * inv[2, 1] - inv[1, 1] * inv[2, 0]
};
real_t det = inv[0, 0] * co[0] + inv[0, 1] * co[1] + inv[0, 2] * co[2];
if (det == 0) if (det == 0)
{ throw new InvalidOperationException("Matrix determinant is zero and cannot be inverted.");
real_t detInv = 1.0f / det;
real_t cofac01 = Row0[2] * Row2[1] - Row0[1] * Row2[2];
real_t cofac02 = Row0[1] * Row1[2] - Row0[2] * Row1[1];
real_t cofac11 = Row0[0] * Row2[2] - Row0[2] * Row2[0];
real_t cofac12 = Row0[2] * Row1[0] - Row0[0] * Row1[2];
real_t cofac21 = Row0[1] * Row2[0] - Row0[0] * Row2[1];
real_t cofac22 = Row0[0] * Row1[1] - Row0[1] * Row1[0];
return new Basis return new Basis
( (
real_t.NaN, real_t.NaN, real_t.NaN, cofac00 * detInv, cofac01 * detInv, cofac02 * detInv,
real_t.NaN, real_t.NaN, real_t.NaN, cofac10 * detInv, cofac11 * detInv, cofac12 * detInv,
real_t.NaN, real_t.NaN, real_t.NaN cofac20 * detInv, cofac21 * detInv, cofac22 * detInv
); );
} }
real_t s = 1.0f / det;
inv = new Basis
(
co[0] * s,
inv[0, 2] * inv[2, 1] - inv[0, 1] * inv[2, 2] * s,
inv[0, 1] * inv[1, 2] - inv[0, 2] * inv[1, 1] * s,
co[1] * s,
inv[0, 0] * inv[2, 2] - inv[0, 2] * inv[2, 0] * s,
inv[0, 2] * inv[1, 0] - inv[0, 0] * inv[1, 2] * s,
co[2] * s,
inv[0, 1] * inv[2, 0] - inv[0, 0] * inv[2, 1] * s,
inv[0, 0] * inv[1, 1] - inv[0, 1] * inv[1, 0] * s
);
return inv;
}
public Basis Orthonormalized() public Basis Orthonormalized()
{ {
Vector3 xAxis = GetAxis(0); Vector3 column0 = GetColumn(0);
Vector3 yAxis = GetAxis(1); Vector3 column1 = GetColumn(1);
Vector3 zAxis = GetAxis(2); Vector3 column2 = GetColumn(2);
xAxis.Normalize(); column0.Normalize();
yAxis = yAxis - xAxis * xAxis.Dot(yAxis); column1 = column1 - column0 * column0.Dot(column1);
yAxis.Normalize(); column1.Normalize();
zAxis = zAxis - xAxis * xAxis.Dot(zAxis) - yAxis * yAxis.Dot(zAxis); column2 = column2 - column0 * column0.Dot(column2) - column1 * column1.Dot(column2);
zAxis.Normalize(); column2.Normalize();
return CreateFromAxes(xAxis, yAxis, zAxis); return new Basis(column0, column1, column2);
} }
public Basis Rotated(Vector3 axis, real_t phi) public Basis Rotated(Vector3 axis, real_t phi)
@ -343,49 +420,49 @@ namespace Godot
{ {
var m = this; var m = this;
m[0, 0] *= scale.x; m.Row0[0] *= scale.x;
m[0, 1] *= scale.x; m.Row0[1] *= scale.x;
m[0, 2] *= scale.x; m.Row0[2] *= scale.x;
m[1, 0] *= scale.y; m.Row1[0] *= scale.y;
m[1, 1] *= scale.y; m.Row1[1] *= scale.y;
m[1, 2] *= scale.y; m.Row1[2] *= scale.y;
m[2, 0] *= scale.z; m.Row2[0] *= scale.z;
m[2, 1] *= scale.z; m.Row2[1] *= scale.z;
m[2, 2] *= scale.z; m.Row2[2] *= scale.z;
return m; return m;
} }
public real_t Tdotx(Vector3 with) public real_t Tdotx(Vector3 with)
{ {
return this[0, 0] * with[0] + this[1, 0] * with[1] + this[2, 0] * with[2]; return this.Row0[0] * with[0] + this.Row1[0] * with[1] + this.Row2[0] * with[2];
} }
public real_t Tdoty(Vector3 with) public real_t Tdoty(Vector3 with)
{ {
return this[0, 1] * with[0] + this[1, 1] * with[1] + this[2, 1] * with[2]; return this.Row0[1] * with[0] + this.Row1[1] * with[1] + this.Row2[1] * with[2];
} }
public real_t Tdotz(Vector3 with) public real_t Tdotz(Vector3 with)
{ {
return this[0, 2] * with[0] + this[1, 2] * with[1] + this[2, 2] * with[2]; return this.Row0[2] * with[0] + this.Row1[2] * with[1] + this.Row2[2] * with[2];
} }
public Basis Transposed() public Basis Transposed()
{ {
var tr = this; var tr = this;
real_t temp = tr[0, 1]; real_t temp = tr.Row0[1];
tr[0, 1] = tr[1, 0]; tr.Row0[1] = tr.Row1[0];
tr[1, 0] = temp; tr.Row1[0] = temp;
temp = tr[0, 2]; temp = tr.Row0[2];
tr[0, 2] = tr[2, 0]; tr.Row0[2] = tr.Row2[0];
tr[2, 0] = temp; tr.Row2[0] = temp;
temp = tr[1, 2]; temp = tr.Row1[2];
tr[1, 2] = tr[2, 1]; tr.Row1[2] = tr.Row2[1];
tr[2, 1] = temp; tr.Row2[1] = temp;
return tr; return tr;
} }
@ -394,9 +471,9 @@ namespace Godot
{ {
return new Vector3 return new Vector3
( (
this[0].Dot(v), this.Row0.Dot(v),
this[1].Dot(v), this.Row1.Dot(v),
this[2].Dot(v) this.Row2.Dot(v)
); );
} }
@ -404,60 +481,60 @@ namespace Godot
{ {
return new Vector3 return new Vector3
( (
this[0, 0] * v.x + this[1, 0] * v.y + this[2, 0] * v.z, this.Row0[0] * v.x + this.Row1[0] * v.y + this.Row2[0] * v.z,
this[0, 1] * v.x + this[1, 1] * v.y + this[2, 1] * v.z, this.Row0[1] * v.x + this.Row1[1] * v.y + this.Row2[1] * v.z,
this[0, 2] * v.x + this[1, 2] * v.y + this[2, 2] * v.z this.Row0[2] * v.x + this.Row1[2] * v.y + this.Row2[2] * v.z
); );
} }
public Quat Quat() public Quat Quat()
{ {
real_t trace = _x[0] + _y[1] + _z[2]; real_t trace = Row0[0] + Row1[1] + Row2[2];
if (trace > 0.0f) if (trace > 0.0f)
{ {
real_t s = Mathf.Sqrt(trace + 1.0f) * 2f; real_t s = Mathf.Sqrt(trace + 1.0f) * 2f;
real_t inv_s = 1f / s; real_t inv_s = 1f / s;
return new Quat( return new Quat(
(_z[1] - _y[2]) * inv_s, (Row2[1] - Row1[2]) * inv_s,
(_x[2] - _z[0]) * inv_s, (Row0[2] - Row2[0]) * inv_s,
(_y[0] - _x[1]) * inv_s, (Row1[0] - Row0[1]) * inv_s,
s * 0.25f s * 0.25f
); );
} }
if (_x[0] > _y[1] && _x[0] > _z[2]) if (Row0[0] > Row1[1] && Row0[0] > Row2[2])
{ {
real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f; real_t s = Mathf.Sqrt(Row0[0] - Row1[1] - Row2[2] + 1.0f) * 2f;
real_t inv_s = 1f / s; real_t inv_s = 1f / s;
return new Quat( return new Quat(
s * 0.25f, s * 0.25f,
(_x[1] + _y[0]) * inv_s, (Row0[1] + Row1[0]) * inv_s,
(_x[2] + _z[0]) * inv_s, (Row0[2] + Row2[0]) * inv_s,
(_z[1] - _y[2]) * inv_s (Row2[1] - Row1[2]) * inv_s
); );
} }
if (_y[1] > _z[2]) if (Row1[1] > Row2[2])
{ {
real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f; real_t s = Mathf.Sqrt(-Row0[0] + Row1[1] - Row2[2] + 1.0f) * 2f;
real_t inv_s = 1f / s; real_t inv_s = 1f / s;
return new Quat( return new Quat(
(_x[1] + _y[0]) * inv_s, (Row0[1] + Row1[0]) * inv_s,
s * 0.25f, s * 0.25f,
(_y[2] + _z[1]) * inv_s, (Row1[2] + Row2[1]) * inv_s,
(_x[2] - _z[0]) * inv_s (Row0[2] - Row2[0]) * inv_s
); );
} }
else else
{ {
real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f; real_t s = Mathf.Sqrt(-Row0[0] - Row1[1] + Row2[2] + 1.0f) * 2f;
real_t inv_s = 1f / s; real_t inv_s = 1f / s;
return new Quat( return new Quat(
(_x[2] + _z[0]) * inv_s, (Row0[2] + Row2[0]) * inv_s,
(_y[2] + _z[1]) * inv_s, (Row1[2] + Row2[1]) * inv_s,
s * 0.25f, s * 0.25f,
(_y[0] - _x[1]) * inv_s (Row1[0] - Row0[1]) * inv_s
); );
} }
} }
@ -479,9 +556,9 @@ namespace Godot
real_t yz = quat.y * zs; real_t yz = quat.y * zs;
real_t zz = quat.z * zs; real_t zz = quat.z * zs;
_x = new Vector3(1.0f - (yy + zz), xy - wz, xz + wy); Row0 = new Vector3(1.0f - (yy + zz), xy - wz, xz + wy);
_y = new Vector3(xy + wz, 1.0f - (xx + zz), yz - wx); Row1 = new Vector3(xy + wz, 1.0f - (xx + zz), yz - wx);
_z = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy)); Row2 = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy));
} }
public Basis(Vector3 euler) public Basis(Vector3 euler)
@ -511,21 +588,21 @@ namespace Godot
real_t cosine = Mathf.Cos(phi); real_t cosine = Mathf.Cos(phi);
real_t sine = Mathf.Sin(phi); real_t sine = Mathf.Sin(phi);
_x = new Vector3 Row0 = new Vector3
( (
axis_sq.x + cosine * (1.0f - axis_sq.x), axis_sq.x + cosine * (1.0f - axis_sq.x),
axis.x * axis.y * (1.0f - cosine) - axis.z * sine, axis.x * axis.y * (1.0f - cosine) - axis.z * sine,
axis.z * axis.x * (1.0f - cosine) + axis.y * sine axis.z * axis.x * (1.0f - cosine) + axis.y * sine
); );
_y = new Vector3 Row1 = new Vector3
( (
axis.x * axis.y * (1.0f - cosine) + axis.z * sine, axis.x * axis.y * (1.0f - cosine) + axis.z * sine,
axis_sq.y + cosine * (1.0f - axis_sq.y), axis_sq.y + cosine * (1.0f - axis_sq.y),
axis.y * axis.z * (1.0f - cosine) - axis.x * sine axis.y * axis.z * (1.0f - cosine) - axis.x * sine
); );
_z = new Vector3 Row2 = new Vector3
( (
axis.z * axis.x * (1.0f - cosine) - axis.y * sine, axis.z * axis.x * (1.0f - cosine) - axis.y * sine,
axis.y * axis.z * (1.0f - cosine) + axis.x * sine, axis.y * axis.z * (1.0f - cosine) + axis.x * sine,
@ -533,32 +610,32 @@ namespace Godot
); );
} }
public Basis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis) public Basis(Vector3 column0, Vector3 column1, Vector3 column2)
{ {
_x = new Vector3(xAxis.x, yAxis.x, zAxis.x); Row0 = new Vector3(column0.x, column1.x, column2.x);
_y = new Vector3(xAxis.y, yAxis.y, zAxis.y); Row1 = new Vector3(column0.y, column1.y, column2.y);
_z = new Vector3(xAxis.z, yAxis.z, zAxis.z); Row2 = new Vector3(column0.z, column1.z, column2.z);
// Same as: // Same as:
// SetAxis(0, xAxis); // Column0 = column0;
// SetAxis(1, yAxis); // Column1 = column1;
// SetAxis(2, zAxis); // Column2 = column2;
// We need to assign the struct fields so we can't do that... // We need to assign the struct fields here first so we can't do it that way...
} }
internal Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) internal Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz)
{ {
_x = new Vector3(xx, xy, xz); Row0 = new Vector3(xx, xy, xz);
_y = new Vector3(yx, yy, yz); Row1 = new Vector3(yx, yy, yz);
_z = new Vector3(zx, zy, zz); Row2 = new Vector3(zx, zy, zz);
} }
public static Basis operator *(Basis left, Basis right) public static Basis operator *(Basis left, Basis right)
{ {
return new Basis return new Basis
( (
right.Tdotx(left[0]), right.Tdoty(left[0]), right.Tdotz(left[0]), right.Tdotx(left.Row0), right.Tdoty(left.Row0), right.Tdotz(left.Row0),
right.Tdotx(left[1]), right.Tdoty(left[1]), right.Tdotz(left[1]), right.Tdotx(left.Row1), right.Tdoty(left.Row1), right.Tdotz(left.Row1),
right.Tdotx(left[2]), right.Tdoty(left[2]), right.Tdotz(left[2]) right.Tdotx(left.Row2), right.Tdoty(left.Row2), right.Tdotz(left.Row2)
); );
} }
@ -584,21 +661,21 @@ namespace Godot
public bool Equals(Basis other) public bool Equals(Basis other)
{ {
return _x.Equals(other[0]) && _y.Equals(other[1]) && _z.Equals(other[2]); return Row0.Equals(other.Row0) && Row1.Equals(other.Row1) && Row2.Equals(other.Row2);
} }
public override int GetHashCode() public override int GetHashCode()
{ {
return _x.GetHashCode() ^ _y.GetHashCode() ^ _z.GetHashCode(); return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode();
} }
public override string ToString() public override string ToString()
{ {
return String.Format("({0}, {1}, {2})", new object[] return String.Format("({0}, {1}, {2})", new object[]
{ {
_x.ToString(), Row0.ToString(),
_y.ToString(), Row1.ToString(),
_z.ToString() Row2.ToString()
}); });
} }
@ -606,9 +683,9 @@ namespace Godot
{ {
return String.Format("({0}, {1}, {2})", new object[] return String.Format("({0}, {1}, {2})", new object[]
{ {
_x.ToString(format), Row0.ToString(format),
_y.ToString(format), Row1.ToString(format),
_z.ToString(format) Row2.ToString(format)
}); });
} }
} }

View File

@ -123,22 +123,23 @@ namespace Godot
// Calculate cosine // Calculate cosine
real_t cosom = x * b.x + y * b.y + z * b.z + w * b.w; real_t cosom = x * b.x + y * b.y + z * b.z + w * b.w;
var to1 = new real_t[4]; var to1 = new Quat();
// Adjust signs if necessary // Adjust signs if necessary
if (cosom < 0.0) if (cosom < 0.0)
{ {
cosom = -cosom; to1[0] = -b.x; cosom = -cosom;
to1[1] = -b.y; to1.x = -b.x;
to1[2] = -b.z; to1.y = -b.y;
to1[3] = -b.w; to1.z = -b.z;
to1.w = -b.w;
} }
else else
{ {
to1[0] = b.x; to1.x = b.x;
to1[1] = b.y; to1.y = b.y;
to1[2] = b.z; to1.z = b.z;
to1[3] = b.w; to1.w = b.w;
} }
real_t sinom, scale0, scale1; real_t sinom, scale0, scale1;
@ -162,10 +163,10 @@ namespace Godot
// Calculate final values // Calculate final values
return new Quat return new Quat
( (
scale0 * x + scale1 * to1[0], scale0 * x + scale1 * to1.x,
scale0 * y + scale1 * to1[1], scale0 * y + scale1 * to1.y,
scale0 * z + scale1 * to1[2], scale0 * z + scale1 * to1.z,
scale0 * w + scale1 * to1[3] scale0 * w + scale1 * to1.w
); );
} }

View File

@ -71,21 +71,21 @@ namespace Godot
{ {
// Make rotation matrix // Make rotation matrix
// Z vector // Z vector
Vector3 zAxis = eye - target; Vector3 column2 = eye - target;
zAxis.Normalize(); column2.Normalize();
Vector3 yAxis = up; Vector3 column1 = up;
Vector3 xAxis = yAxis.Cross(zAxis); Vector3 column0 = column1.Cross(column2);
// Recompute Y = Z cross X // Recompute Y = Z cross X
yAxis = zAxis.Cross(xAxis); column1 = column2.Cross(column0);
xAxis.Normalize(); column0.Normalize();
yAxis.Normalize(); column1.Normalize();
basis = Basis.CreateFromAxes(xAxis, yAxis, zAxis); basis = new Basis(column0, column1, column2);
origin = eye; origin = eye;
} }
@ -94,9 +94,9 @@ namespace Godot
{ {
return new Transform(basis, new Vector3 return new Transform(basis, new Vector3
( (
origin[0] += basis[0].Dot(ofs), origin[0] += basis.Row0.Dot(ofs),
origin[1] += basis[1].Dot(ofs), origin[1] += basis.Row1.Dot(ofs),
origin[2] += basis[2].Dot(ofs) origin[2] += basis.Row2.Dot(ofs)
)); ));
} }
@ -104,9 +104,9 @@ namespace Godot
{ {
return new Vector3 return new Vector3
( (
basis[0].Dot(v) + origin.x, basis.Row0.Dot(v) + origin.x,
basis[1].Dot(v) + origin.y, basis.Row1.Dot(v) + origin.y,
basis[2].Dot(v) + origin.z basis.Row2.Dot(v) + origin.z
); );
} }
@ -116,9 +116,9 @@ namespace Godot
return new Vector3 return new Vector3
( (
basis[0, 0] * vInv.x + basis[1, 0] * vInv.y + basis[2, 0] * vInv.z, basis.Row0[0] * vInv.x + basis.Row1[0] * vInv.y + basis.Row2[0] * vInv.z,
basis[0, 1] * vInv.x + basis[1, 1] * vInv.y + basis[2, 1] * vInv.z, basis.Row0[1] * vInv.x + basis.Row1[1] * vInv.y + basis.Row2[1] * vInv.z,
basis[0, 2] * vInv.x + basis[1, 2] * vInv.y + basis[2, 2] * vInv.z basis.Row0[2] * vInv.x + basis.Row1[2] * vInv.y + basis.Row2[2] * vInv.z
); );
} }
@ -134,9 +134,9 @@ namespace Godot
public static Transform FlipZ { get { return _flipZ; } } public static Transform FlipZ { get { return _flipZ; } }
// Constructors // Constructors
public Transform(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis, Vector3 origin) public Transform(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin)
{ {
basis = Basis.CreateFromAxes(xAxis, yAxis, zAxis); basis = new Basis(column0, column1, column2);
this.origin = origin; this.origin = origin;
} }

View File

@ -53,11 +53,11 @@ namespace Godot
} }
} }
public Vector2 this[int index] public Vector2 this[int rowIndex]
{ {
get get
{ {
switch (index) switch (rowIndex)
{ {
case 0: case 0:
return x; return x;
@ -71,7 +71,7 @@ namespace Godot
} }
set set
{ {
switch (index) switch (rowIndex)
{ {
case 0: case 0:
x = value; x = value;
@ -88,29 +88,29 @@ namespace Godot
} }
} }
public real_t this[int index, int axis] public real_t this[int rowIndex, int columnIndex]
{ {
get get
{ {
switch (index) switch (rowIndex)
{ {
case 0: case 0:
return x[axis]; return x[columnIndex];
case 1: case 1:
return y[axis]; return y[columnIndex];
default: default:
throw new IndexOutOfRangeException(); throw new IndexOutOfRangeException();
} }
} }
set set
{ {
switch (index) switch (rowIndex)
{ {
case 0: case 0:
x[axis] = value; x[columnIndex] = value;
return; return;
case 1: case 1:
y[axis] = value; y[columnIndex] = value;
return; return;
default: default:
throw new IndexOutOfRangeException(); throw new IndexOutOfRangeException();
@ -120,30 +120,23 @@ namespace Godot
public Transform2D AffineInverse() public Transform2D AffineInverse()
{ {
var inv = this;
real_t det = BasisDeterminant(); real_t det = BasisDeterminant();
if (det == 0) if (det == 0)
{ throw new InvalidOperationException("Matrix determinant is zero and cannot be inverted.");
return new Transform2D
( var inv = this;
real_t.NaN, real_t.NaN,
real_t.NaN, real_t.NaN, real_t temp = inv[0, 0];
real_t.NaN, real_t.NaN inv[0, 0] = inv[1, 1];
); inv[1, 1] = temp;
}
real_t detInv = 1.0f / det; real_t detInv = 1.0f / det;
real_t temp = this[0, 0]; inv[0] *= new Vector2(detInv, -detInv);
this[0, 0] = this[1, 1]; inv[1] *= new Vector2(-detInv, detInv);
this[1, 1] = temp;
this[0] *= new Vector2(detInv, -detInv); inv[2] = BasisXform(-inv[2]);
this[1] *= new Vector2(-detInv, detInv);
this[2] = BasisXform(-this[2]);
return inv; return inv;
} }
@ -293,9 +286,9 @@ namespace Godot
private static readonly Transform2D _flipX = new Transform2D(-1, 0, 0, 1, 0, 0); private static readonly Transform2D _flipX = new Transform2D(-1, 0, 0, 1, 0, 0);
private static readonly Transform2D _flipY = new Transform2D(1, 0, 0, -1, 0, 0); private static readonly Transform2D _flipY = new Transform2D(1, 0, 0, -1, 0, 0);
public static Transform2D Identity { get { return _identity; } } public static Transform2D Identity => _identity;
public static Transform2D FlipX { get { return _flipX; } } public static Transform2D FlipX => _flipX;
public static Transform2D FlipY { get { return _flipY; } } public static Transform2D FlipY => _flipY;
// Constructors // Constructors
public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 originPos) public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 originPos)
@ -324,12 +317,10 @@ namespace Godot
{ {
left.origin = left.Xform(right.origin); left.origin = left.Xform(right.origin);
real_t x0, x1, y0, y1; real_t x0 = left.Tdotx(right.x);
real_t x1 = left.Tdoty(right.x);
x0 = left.Tdotx(right.x); real_t y0 = left.Tdotx(right.y);
x1 = left.Tdoty(right.x); real_t y1 = left.Tdoty(right.y);
y0 = left.Tdotx(right.y);
y1 = left.Tdoty(right.y);
left.x.x = x0; left.x.x = x0;
left.x.y = x1; left.x.y = x1;
@ -351,12 +342,7 @@ namespace Godot
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj is Transform2D) return obj is Transform2D transform2D && Equals(transform2D);
{
return Equals((Transform2D)obj);
}
return false;
} }
public bool Equals(Transform2D other) public bool Equals(Transform2D other)

View File

@ -11,7 +11,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>portable</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath> <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants> <DefineConstants>DEBUG;</DefineConstants>