2013-08-18 78 views
7

這是麻煩代碼..常量對象不能作爲變量參數傳遞

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

全過程

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功能

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; 

和共軛

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

,如果需要TQuaternion

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

任何想法,爲什麼我得到這個錯誤,以及如何解決它?

回答

13

您問到的問題的答案是,mult的參數應該是const。你不修改它們(你不應該),所以讓它們爲const。然後你的代碼編譯。

與此類似,Conjugate修改其輸入參數的方式很糟糕。這使得可以使用函數horrid。不要這樣做。

考慮這條線:

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

由於共軛修改臨時,你最好希望以共軛呼叫其他使用溫度的後作出的。該語言沒有這樣的保證。所以,交叉你的手指!

算術代碼值得遵循的原則之一是輸入參數/操作數不應該被修改,並且該函數總是返回新值值。遵循這個原則,你永遠不會陷入上面強調的陷阱。看到我的答案的第二部分的插圖。

但是,即使對於這些更改,代碼也不起作用,因爲您沒有實例化TQuaternion類的任何實例。你確定這不是一個記錄嗎?


當您創建一個很好的四元數類型時,真正的轉發進度就會到來。這應該是一個值類型,因爲算術運算由於多種原因更適合值類型。

在現代德爾福你想與操作員一起使用記錄。這裏有你需要的東西的味道,隨時可以根據你的需要進行擴展。

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; 

對於這種類型的乘法呼叫變成:

multresult := temp*quatview*temp.Conjugate; 

你肯定會想要寫更多的運營商和輔助功能,對於這種類型的。

的算術函數進入這個類型,你的形式,這一點至關重要。不要使用高級GUI表單類來實現低級算術。

最後一條建議。你的代碼重複使用了var參數。我建議你把var參數當作是要避免的東西。如果可能的話,嘗試編寫代碼。

+0

謝謝,很好的建議。雖然我會嘗試並再次使用這個...截至目前我必須找出如何使用這與firemonkey相機..因爲FMX的位置(x,y,z)和rotateposition(x,y,z)雖然所有例子我可以找到使用opengl的外觀(positionx,y,z,viewx,y,z,upx,y,z) –

5

mult方法聲明A參數爲var,因此您必須將該變量傳遞給該方法才能工作,如此。

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

謝謝,不知道我不得不把它分裂.. –

+1

@GlenMorse我想你聲明參數爲** **變種,因爲編譯錯誤的,如果沒有。試着擺脫那個變種,它會沒事 –

+5

我認爲這個答案是對問題的淺析淺析。是的,這個改變會使代碼編譯。但是,您將面臨許多其他問題。即使如此,這裏提出的解決方案也很糟糕,因爲要克服的第一個缺點是var參數的錯誤使用。這似乎是一個反覆出現的主題。 –