2013-08-18 15 views
7

Dies ist der Fehlercode ..Constant Objekt kann nicht als var-Parameter übergeben werden

multresult := mult(mult(temp, quatview), conjugate(temp)); 

Voll Verfahren

procedure TForm2.RotateCamera(var angle: Single; x: Single; y: Single; z: Single); 
var 
    temp, QuatView, multResult : TQuaternion; 
begin 
    temp.x := x * sin(Angle/2); 
    temp.y := y * sin(Angle/2); 
    temp.z := z * sin(Angle/2); 
    temp.w := cos(Angle/2); 

    quatview.x := camera1.Position.x; 
    quatview.y := camera1.Position.y; 
    quatview.z := camera1.Position.z; 
    quatview.w := 0; 

    multresult := mult(mult(temp, quatview), conjugate(temp)); 

    camera1.Position.x := multresult.x; 
    camera1.Position.y := multresult.y; 
    camera1.Position.z := multresult.z; 
end; 

mult Funktion

function TForm2.mult(var A: TQuaternion; B: TQuaternion) :TQuaternion; 
var 
    c : TQuaternion; 
begin 
    C.x := A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y; 
    C.y := A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x; 
    C.z := A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w; 
    C.w := A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z; 
result := C; 
End; 

und Konjugat

function TForm2.conjugate(var quat:TQuaternion) :TQuaternion; 
    begin 
    quat.x := -quat.x; 
    quat.y := -quat.y; 
    quat.z := -quat.z; 
    result := quat; 
    end; 

und bei Bedarf TQuaternion

type 
    TQuaternion = class 
    x: single; 
    y: single; 
    z: single; 
    w: single; 
    end; 

eine Ahnung, warum ich diesen Fehler und wie man es beheben?

Antwort

13

Die Antwort auf die Frage, die Sie gestellt haben, ist, dass die Parameter zu mult const sein sollten. Sie ändern sie nicht (und Sie sollten nicht), also machen Sie sie const. Dann kompiliert sich Ihr Code.

In ähnlicher Weise ist es eine schlechte Form für Conjugate, seine Eingabeparameter zu ändern. Das macht die Funktion schrecklich zu benutzen. Tu das nicht.

diese Zeile vor:

multresult := mult(mult(temp, quatview), conjugate(temp)); 

Da Konjugat Temperatur ändert, sollten Sie besser hoffen, dass der Anruf an Konjugat nach dem anderen Verwendung von Temp hergestellt wird. Die Sprache gibt keine solche Garantie. Also, Daumen drücken!

Eines der folgenden Prinzipien mit arithmetischem Code ist, dass Eingangsparameter/Operanden niemals geändert werden sollten und dass Funktionen immer neue Werte zurückgeben. Folgen Sie diesem Prinzip und Sie werden niemals in die oben erwähnte Falle fallen. Siehe den zweiten Teil meiner Antwort für eine Illustration.

Der Code funktioniert jedoch nicht mit diesen Änderungen, da Sie Instanzen der TQuaternion-Klasse nicht instanziieren. Bist du sicher, dass es kein Rekord ist?


Der echte Fortschritt wird kommen, wenn Sie einen guten Quaternion-Typ erstellen. Dies sollte ein Werttyp sein, da arithmetische Operationen aus verschiedenen Gründen besser für Werttypen geeignet sind.

Im modernen Delphi möchten Sie einen Datensatz mit Operatoren verwenden. Hier ist ein Geschmack von dem, was Sie brauchen, bereit zu verlängern, wie Sie brauchen.

type 
    TQuaternion = record 
    x: single; 
    y: single; 
    z: single; 
    w: single; 
    function Conjugate: TQuaternion; 
    class operator Multiply(const A, B: TQuaternion): TQuaternion; 
    end; 

function TQuaternion.Conjugate: TQuaternion; 
begin 
    Result.x := -x; 
    Result.y := -y; 
    Result.z := -z; 
    Result.w := w; 
end; 

class operator TQuaternion.Multiply(const A, B: TQuaternion): TQuaternion; 
begin 
    Result.x := A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y; 
    Result.y := A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x; 
    Result.z := A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w; 
    Result.w := A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z; 
end; 

Bei dieser Art Ihres Multiplikation Aufruf wird:

multresult := temp*quatview*temp.Conjugate; 

Sie wollen sicherlich für diese Art mehr Operatoren und Hilfsfunktionen schreiben.

Es ist wirklich wichtig, die arithmetischen Funktionen in diesen Typ und aus Ihrer Form zu verschieben. Verwenden Sie Ihre High-Level-GUI-Formularklasse nicht zum Implementieren von Low-Level-Arithmetik.

Ein letzter Ratschlag. Ihr Code hat wiederholt falsche var-Parameter verwendet. Ich schlage vor, Sie behandeln Var-Parameter als Dinge, die vermieden werden sollen. Versuchen Sie, Code ohne sie zu schreiben, wenn möglich.

+0

Danke, guter Rat. Während ich versuchen werde, das wieder zu verwenden ... ab jetzt muss ich herausfinden, wie man das mit der Feuerwaffe-Kamera benutzt .. wie FMX hat Position (x, y, z) und rotateposition (x, y, z) Während alle Beispiele, die ich finden könnte, benutze opengls Aussehen (Positionx, y, z, Ansichtx, y, z, upx, y, z) so arbeiten, all dies herauszufinden. –

5

Die mult Methode deklariert den A Parameter als var, also müssen Sie eine Variable an die Methode übergeben, um zu funktionieren, so.

multresult := mult(temp, quatview); 
multresult := mult(multresult, conjugate(temp)); 
+0

Danke, wusste nicht, ich musste es aufteilen .. –

+1

@GlenMorse Ich denke, Sie deklarieren den Parameter als ** var ** wegen eines Kompilierungsfehlers, wenn nicht. Versuchen Sie, diese Var loszuwerden und es wird gut –

+5

Ich denke, dass diese Antwort eine etwas oberflächliche Analyse des Problems ist. Ja, diese Änderung wird den Code kompilieren. Sie sind dann aber mit einer Vielzahl weiterer Probleme konfrontiert. Und selbst dann ist die hier vorgeschlagene Lösung schlecht, weil der erste zu überwindende Fehler die fehlerhafte Verwendung eines var-Parameters ist. Was scheint ein wiederkehrendes Thema zu sein. –

Verwandte Themen