AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Unit System.Math.Vectors

Ein Thema von SMO · begonnen am 28. Feb 2015 · letzter Beitrag vom 28. Feb 2015
Antwort Antwort
SMO

Registriert seit: 20. Jul 2005
178 Beiträge
 
Delphi XE6 Professional
 
#1

Unit System.Math.Vectors

  Alt 28. Feb 2015, 18:32
Delphi-Version: XE6
Hallo,

kennt ihr die Unit System.Math.Vectors? Ich weiß nicht, in welcher Delphi-Version sie dazugekommen ist, aber ich habe sie erst vor kurzem entdeckt.
Die Unit enthält eine nette kleine Sammlung von Records mit Methoden für 2D und 3D Vektoren, Matrizen und Quaternionen.
Ich wollte mich schon länger mal in die Grundlagen von 3D-Grafik einarbeiten, da kam diese Unit gerade richtig.

Allerdings glaube ich ein paar Fehler in der Unit gefunden zu haben! Ich würde deshalb gerne dazu die Meinung von Leuten hören, die sich mit der Materie auskennen.

Zunächst mal: Die Unit scheint sich an Microsoft DirectX / .NET zu orientieren. Zu OpenGL gibt es da kleine Unterschiede.

Erster Punkt: TMatrix3D.CreateOrthoLH sowie die rechtshändige Version CreateOrthoRH haben mit ziemlicher Sicherheit einen Bug.
Delphi-Quellcode:
class function TMatrix3D.CreateOrthoLH(const AWidth, AHeight, AZNear, AZFar: Single): TMatrix3D;
begin
  Result := TMatrix3D.Identity;
  Result.m11 := 2 / AWidth;
  Result.m22 := 2 / AHeight;
  Result.m33 := 1 / (AZFar - AZNear);
  Result.m42 := AZNear / (AZNear - AZFar);
end;
Im letzten Befehl wird das Matrixelement m42 befüllt, aber es müsste meiner Meinung nach m43 sein. Siehe Microsoft sowie die Funktion CreateOrthoOffCenterLH in der Unit, praktisch eine Verallgemeinerung von CreateOrthoLH:
Delphi-Quellcode:
class function TMatrix3D.CreateOrthoOffCenterLH(const ALeft, ATop, ARight, ABottom, AZNear, AZFar: Single): TMatrix3D;
begin
  Result := TMatrix3D.Identity;
  Result.m11 := 2 / (ARight - ALeft);
  Result.m22 := 2 / (ATop - ABottom);
  Result.m33 := 1 / (AZFar - AZNear);
  Result.m41 := (ALeft + ARight) / (ALeft - ARight);
  Result.m42 := (ATop + ABottom) / (ABottom - ATop);
  Result.m43 := AZNear / (AZNear - AZFar);
end;

Zweiter Punkt: TMatrix3D.CreateRotationYawPitchRoll
Rotationen sind etwas kompliziert, die Reihenfolge, in welcher um die drei Achsen rotiert wird, macht einen Unterschied (Matrixmultiplikation ist nicht kommutativ).
MSDN sagt zu RotationYawPitchRoll:
  1. Roll = Drehung um Z-Achse
  2. Pitch = Drehung um X-Achse
  3. Yaw = Drehung um Y-Achse
Das entspricht der gängingen "YXZ" Konvention, d.h. ich würde erwarten, dass gilt:
TMatrix3D.CreateRotationYawPitchRoll(Yaw, Pitch, Roll) = TMatrix3D.CreateRotationZ(Roll) * TMatrix3D.CreateRotationX(Pitch) * TMatrix3D.CreateRotationY(Yaw)
oder wenn von "rechts nach links" multipliziert wird:
TMatrix3D.CreateRotationYawPitchRoll(Yaw, Pitch, Roll) = TMatrix3D.CreateRotationY(Yaw) * TMatrix3D.CreateRotationX(Pitch) * TMatrix3D.CreateRotationZ(Roll)

Dem ist aber nicht so! Stattdessen bekomme ich:
TMatrix3D.CreateRotationYawPitchRoll(Yaw, Pitch, Roll) = TMatrix3D.CreateRotationY(Roll) * TMatrix3D.CreateRotationX(Pitch) * TMatrix3D.CreateRotationZ(-Yaw)

Was ist da denn los? Die Reihenfolge stimmt (YXZ Konvention). Aber Yaw und Roll sind den falschen Achsen zugewiesen! Oder hat jemand eine andere Erklärung dafür?

Testcode:
Delphi-Quellcode:
uses
  System.Math.Vectors;

function MatrixEqual(const M1, M2: TMatrix3D): Boolean;
var
  i: Integer;
begin
  Result := True;
  // Leider ist kein TMatrix3D.Equal Operator definiert. Also reduziere das Problem auf
  // TVector3D.Equal und vergleiche die Komponentenvektoren beider Matrizen
  for i := Low(M1.M) to High(M1.M) do
    Result := Result and (M1.M[i] = M2.M[i]);
end;

procedure RotTest;
const
  B2S: array [Boolean] of string = ('false', 'TRUE!');
var
  M1, M2, M3, M4: TMatrix3D;
  Yaw, Pitch, Roll: Single;
  s: string;
begin
  Yaw := 1.0;
  Pitch := 2.0;
  Roll := 3.0;
  M1 := TMatrix3D.CreateRotationYawPitchRoll(Yaw, Pitch, Roll);
  M2 := TMatrix3D.CreateRotationZ(Roll) * TMatrix3D.CreateRotationX(Pitch) * TMatrix3D.CreateRotationY(Yaw);
  M3 := TMatrix3D.CreateRotationY(Yaw) * TMatrix3D.CreateRotationX(Pitch) * TMatrix3D.CreateRotationZ(Roll);
  M4 := TMatrix3D.CreateRotationY(Roll) * TMatrix3D.CreateRotationX(Pitch) * TMatrix3D.CreateRotationZ(-Yaw);
  s := '';
  s := s + 'M1 (YPR) = M2 (RzPxYy): ' + B2S[MatrixEqual(M1, M2)] + sLineBreak;
  s := s + 'M1 (YPR) = M3 (YyPxRz): ' + B2S[MatrixEqual(M1, M3)] + sLineBreak;
  s := s + 'M1 (YPR) = M4 (RyPx-Yz): ' + B2S[MatrixEqual(M1, M4)] + sLineBreak;
  ShowMessage(s);
  // Ausgabe:
  // M1 (YPR) = M2 (RzPxYy): false
  // M1 (YPR) = M3 (YyPxRz): false
  // M1 (YPR) = M4 (RyPx-Yz): TRUE!
end;

Geändert von SMO (28. Feb 2015 um 21:09 Uhr)
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
670 Beiträge
 
#2

AW: Unit System.Math.Vectors

  Alt 28. Feb 2015, 20:18
Zitat:
Ich würde deshalb gerne dazu die Meinung von Leuten hören, die sich mit der Materie auskennen.
Also, so tief hänge ich jetzt nicht in der Materie, aber ich gebe Dir mal meine Meinung dazu.
Mit meinem Wechsel zu xe7 von xe2 habe ich diese Unit auch entdeckt. Für mich ist diese Art von Vektoren und Matrizen ein guter Ansatz, aber für eine praktische Verwendung sind sie einfach nicht umfangreich genug. Das Problem ist einfach, dass es records sind und man sie nicht ableiten kann. Ich habe deshalb auf diesem Ansatz meinen eigenen Record-Vektor überarbeitet und bin sehr zufrieden damit.

Wenn man Opengl oder Direct3d machen will, benötigt man aus meiner Sicht eine umfangreichere Lib wie z.B. die Vectorgeometry.pas aus dem GLScene-Projekt. Diese ist aber von der Anlage sehr veraltet. Ich habe deshalb für die Zukunft (wann immer die auch ist) in meiner Grafikengine einen Umbau auf etwas Modereres geplant. Dazu wollte ich eigentlich wieder den Ansatz von Emba übernehmen und Stück für Stück auf der Basis von der Vectorgeometry erweitern.

Wenn Du nach Fehlern suchst, könntest Du Dir vielleicht die Vectorgeometry als Referenz nehmen. Die ist nach meiner Meinung gut ausgetestet.
Achtung: Bin kein Informatiker sondern komme vom Bau.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz