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;

マルチ機能

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;

このエラーが発生する理由と修正方法はありますか?

4

2 に答える 2

13

あなたが尋ねた質問に対する答えは、mult へのパラメーターは const であるべきだということです。それらを変更しないでください (そして、変更すべきではありません)。したがって、それらを const にします。次に、コードがコンパイルされます。

同様に、Conjugate がその入力パラメータを変更するのは悪い形です。そのため、この関数は使用するのが恐ろしくなります。そうしないでください。

次の行を検討してください。

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

Conjugate は temp を変更するので、temp を別の方法で使用した後に、conjugate の呼び出しを行うことをお勧めします。言語はそのような保証をしません。だから、あなたの指を交差させてください!

算術コードで従う価値のある原則の 1 つは、入力パラメーター/オペランドを変更してはならず、関数は常に新しい値を返すことです。この原則に従えば、上で強調した罠に陥ることはありません。図については、私の回答の2番目の部分を参照してください。

ただし、TQuaternion クラスのインスタンスをインスタンス化していないため、これらの変更を行ってもコードは機能しません。レコードではないことは確かですか?


適切なクォータニオン タイプを作成すると、真の前進が得られます。さまざまな理由から、算術演算は値型に適しているため、これは値型にする必要があります。

最新の Delphi では、演算子を含むレコードを使用したいと考えています。これは、必要に応じて拡張する準備ができている、必要なもののフレーバーです。

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 フォーム クラスを使用しないでください。

最後に 1 つのアドバイス。コードで var パラメータの誤用が繰り返されています。var パラメータは避けるべきものとして扱うことをお勧めします。可能であれば、それらなしでコードを書くようにしてください。

于 2013-08-18T06:44:50.070 に答える
5

メソッドはパラメーターを としてmult宣言するため、そのように機能するには、メソッドに変数を渡す必要があります。Avar

 multresult := mult(temp, quatview);
 multresult := mult(multresult, conjugate(temp));
于 2013-08-18T03:59:06.863 に答える