/ / Úplne nesprávna hodnota pre násobenie matice pomocou System.Numerics - c #, matice, číslica, system.numerics

Úplne nesprávna hodnota pre násobenie matice systémom System.Numerics - c #, matica, číslica, system.numerics

Aj keď System.Numerics.Vectors knižnica, ktorú možno získať prostredníctvom NuGet, má svoje vlastné funkcie pre zobrazovacie a premietacie matice, ktoré som chcel implementovať sám a len používať vektorové a maticové štruktúry.

Bohužiaľ, keď vynásobím môj cieľový vektor s (správnou) maticou zobrazenia, dostávam úplne nesprávny výsledok. Používam pravú ručnú súradnicovú sústavu a nasledujúce pokyny

var cameraVector4 = new Vector4(0, 4, 2, 1);
var focusVector4 = new Vector4(0, 0, 0, 1);
var vMatrix4 = LookAt(cameraVector4, focusVector4, new Vector4(0, 1.0f, 0, 0));
var targetVector4 = new Vector4(1, 0, -1, 1);
var targetViewVector4 = Vector4.Transform(targetVector4, vMatrix4);

s nasledujúcimi funkciami

private static Matrix4x4 LookAt(Vector4 cameraVector4, Vector4 focusVector4, Vector4 upVector4) {
if (cameraVector4 == focusVector4) return Matrix4x4.Identity;
var z = Vector4.Normalize(cameraVector4 - focusVector4);
var x = Vector4.Normalize(upVector4.Cross(z));
var y = Vector4.Normalize(z.Cross(x));

return new Matrix4x4(
x.X, x.Y, x.Z, -Vector4.Dot(x, cameraVector4),
y.X, y.Y, y.Z, -Vector4.Dot(y, cameraVector4),
z.X, z.Y, z.Z, -Vector4.Dot(z, cameraVector4),
0, 0, 0, 1);
}

public static class Vector4Extensions {
public static Vector4 Cross(this Vector4 self, Vector4 vector4) {
return new Vector4(
self.Y * vector4.Z - self.Z * vector4.Y,
self.Z * vector4.X - self.X * vector4.Z,
self.X * vector4.Y - self.Y * vector4.X,
0);
}
}

V mojej vzorke nad očakávanou maticou zobrazenia je

a vMatrix4 má skutočne rovnakú hodnotu. vynásobením vMatrix4 na targetVector4 mali by však priniesť <1, 0.894427, -4.91935, 1> ale správy Visual Studio <1, -0.8944272, -0.4472136, 5.472136>.

Moja otázka spočíva v tom, či má knižnica s číselnými problémami výpočet výsledku, či mám nesprávny typ údajov alebo či používam Vector4.Transform nesprávne očakáva, že sa vráti ViewMatrix * TargetVector.


Pri použití nasledujúcej metódy rozšírenia

public static Vector4 ApplyMatrix(this Vector4 self, Matrix4x4 matrix) {
return new Vector4(
matrix.M11 * self.X + matrix.M12 * self.Y + matrix.M13 * self.Z + matrix.M14 * self.W,
matrix.M21 * self.X + matrix.M22 * self.Y + matrix.M23 * self.Z + matrix.M24 * self.W,
matrix.M31 * self.X + matrix.M32 * self.Y + matrix.M33 * self.Z + matrix.M34 * self.W,
matrix.M41 * self.X + matrix.M42 * self.Y + matrix.M43 * self.Z + matrix.M44 * self.W
);
}

hovor targetVector4.ApplyMatrix(targetVector4) dosahuje správny výsledok. To znamená vnútorne Vector4.Transform zdá sa, že robí niečo naozaj nečakané.

odpovede:

1 pre odpoveď č. 1

Dekompiloval som System.Numerics knižnica pomocou dotPeek a narazila na to:

public static Vector4 Transform(Vector4 vector, Matrix4x4 matrix) {
return
new Vector4(
(float)
(vector.X * (double) matrix.M11 +
vector.Y * (double) matrix.M21 +
vector.Z * (double) matrix.M31 +
vector.W * (double) matrix.M41),
(float)
(vector.X * (double) matrix.M12 +
vector.Y * (double) matrix.M22 +
vector.Z * (double) matrix.M32 +
vector.W * (double) matrix.M42),
(float)
(vector.X * (double) matrix.M13 +
vector.Y * (double) matrix.M23 +
vector.Z * (double) matrix.M33 +
vector.W * (double) matrix.M43),
(float)
(vector.X * (double) matrix.M14 +
vector.Y * (double) matrix.M24 +
vector.Z * (double) matrix.M34 +
vector.W * (double) matrix.M44));
}

Táto metóda znamená, že knižnica jeinterpretovanie vektorov ako riadkových vektorov a násobenie matice z pravej strany namiesto "bežného" spôsobu násobenia matice vľavo od vektora stĺpca. Ak chcete tento problém vyriešiť, máte dve možnosti:

  • Napíšte vlastnú metódu na násobenie vektorov s matricami v poradí, ktoré potrebujete.
  • Transformujte maticu pred aplikáciou transformácie, ktorá môže byť mierne nadmerná.