2013-08-18 11 views
7

Jest to kod błędu ..Stała obiekt nie może być przekazany jako parametr var

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

Pełna procedura

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 funkcja

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; 

i sprzężoną

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

a jeśli potrzebna TQuaternion

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

jakiś pomysł, dlaczego ten błąd i jak go naprawić?

Odpowiedz

13

Odpowiedź na pytanie zadane Ci to, że parametry do mult powinien być const. Nie modyfikujesz ich (i nie powinieneś), więc zmodyfikuj je. Następnie Twój kod się kompiluje.

W podobnym duchu źle nadaje się Conjugate do modyfikowania parametrów wejściowych. To sprawia, że ​​funkcja jest okropna. Nie rób tego.

Rozważmy następujący wiersz:

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

Od sprzężoną modyfikuje temp, lepiej nadzieję, że wezwanie do koniugatu jest po drugiej wykorzystania temp. Język nie udziela takiej gwarancji. Więc skrzyżuj palce!

Jedną z zasad wartych przestrzegania z kodem arytmetycznym jest to, że parametry wejściowe/operandy nie powinny być nigdy modyfikowane, a funkcje zawsze zwracają wartości nowe. Postępuj zgodnie z tą zasadą i nigdy nie wpadniesz w pułapkę zaznaczoną powyżej. Zobacz drugą część mojej odpowiedzi na ilustrację.

Jednak kod nie będzie działał nawet przy tych zmianach, ponieważ nie tworzysz żadnych instancji klasy TQuaternion. Jesteś pewien, że to nie jest płyta?


Prawdziwy postęp do przodu nastąpi po utworzeniu dobrego typu kwaternionów. Powinien to być typ wartości, ponieważ operacje arytmetyczne są lepiej dostosowane do typów wartości z wielu powodów.

W nowoczesnym Delphi chcesz użyć rekordu z operatorami. Oto smak tego, czego potrzebujesz, gotowy do rozszerzenia w miarę potrzeb.

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; 

Z tego typu rozmowa mnożenie postać:

multresult := temp*quatview*temp.Conjugate; 

Będziesz na pewno chcesz napisać więcej operatory i funkcje pomocnicze dla tego typu.

To naprawdę ważne, aby przenieść funkcje arytmetyczne do tego typu iz formy. Nie używaj klasy formularza GUI wysokiego poziomu do implementacji arytmetyki niskiego poziomu.

Jedna ostatnia rada. Twój kod wielokrotnie używał nieprawidłowych parametrów var. Proponuję traktować parametry var jako rzeczy, których należy unikać. Spróbuj napisać kod bez nich, jeśli to możliwe.

+0

Dzięki, świetna rada. Podczas gdy spróbuję i wykorzystam to ponownie ... od teraz muszę się dowiedzieć, jak użyć tego z kamerą z firemonkey .. ponieważ FMX ma pozycję (x, y, z) i rotację (x, y, z), podczas gdy wszystkie przykłady, w których mogłem znaleźć wygląd OpenGL (positionx, y, z, viewx, y, z, upx, y, z), więc pracuję nad tym wszystkim. –

5

Metoda mult deklaruje parametr A jako var, więc musisz przekazać zmienną do metody, aby działała, tak jak w przypadku.

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

Dzięki, nie wiedziałem, musiałem podzielić to .. –

+1

@GlenMorse Myślę, że deklarujesz parametr jako ** var ** z powodu błędu kompilacji, jeśli nie. Spróbuj pozbyć się tego var i będzie dobrze –

+5

Myślę, że ta odpowiedź jest dość płytką analizą problemu. Tak, ta zmiana spowoduje, że kod się skompiluje. Pozostaje ci jednak wiele innych problemów. I nawet wtedy proponowane tutaj rozwiązanie jest słabe, ponieważ pierwszą wadą do przezwyciężenia jest błędne użycie parametru var. Co wydaje się być powtarzającym się motywem. –

Powiązane problemy