1

私はこの古いグラフィック プロジェクト (オベロンで書かれています) を横たわっていましたが、最初のプロジェクトの 1 つとして書いたので、混沌として見えます。とにかく退屈なので、Javaで書き直すことにしました。

これまでのところすべてうまくいっているようです...回転および/または視点の変換を試みるまで。上記の操作を無視すると、画像は問題なく表示されますが、ポイントに変換行列を掛ける必要がある操作を実行しようとすると、すべてがうまくいきません。

  1. アイポイント変換は、[-0.002027571306540​​029、0.05938634628270456、-123.30022583847628] のような終了座標を持つ愚かな小さな数値を生成します。回転されているのは、(一見) ランダムな方向に移動しただけです。

次に、視点を無視して単に回転に焦点を合わせると、結果もかなり奇妙になります (注: 画像は座標の範囲に応じて自動スケーリングされます)。

  1. xRotation を 90° に設定すると、画像が非常に狭くなり、高すぎます (解像度は約 1000x1000 で、138x1000 になります)。
  2. yRotation を 90° に設定すると、非常に広くなります (1000x138)
  3. zRotation を 90° に設定すると、単純にイメージが画面の右側に完全に移動するように見えます。

私がこれまでにチェックしたこと:

  1. 私は回転行列を少なくとも15回チェックして再チェックしたので、(おそらく)正しいです
  2. ベクトルでテスト乗算を実行すると、単位行列は元のベクトルを返します
  3. 私の行列は、回転行列として使用される前に恒等行列として初期化されます
  4. ファイル内の角度は度単位ですが、読み取り時にラジアンに変換されます。

私はさらに2つのメモを持っていると言った:

  1. この場合のベクトルは double の単純な 3 つの値の配列です (x、y、z の値を表します)
  2. 行列は単位行列として初期化された double の 4x4 配列です

それらを回転させようとすると、次の順序で行います。

  1. スケール (倍率を掛ける)
  2. x軸に沿って回転
  3. y 軸に沿って回転
  4. z軸に沿って回転
  5. 翻訳
  6. 視点変換を行う
  7. 次に、点がまだ z 平面上にない場合は、それを投影します

そのようです:

protected void rotate() throws ParseException
    {
        Matrix rotate_x = Transformations.x_rotation(rotateX);
        Matrix rotate_y = Transformations.y_rotation(rotateY);
        Matrix rotate_z = Transformations.z_rotation(rotateZ);
        Matrix translate = Transformations.translation(center.x(), center.y(), center.z());

        for(Vector3D point : points)
        {
            point = Vector3D.mult(point, scale);
            point = Vector3D.mult(point, rotate_x);
            point = Vector3D.mult(point, rotate_y);
            point = Vector3D.mult(point, rotate_z);
            point = Vector3D.mult(point, translate);
            point = Vector3D.mult(point, eye);

            if(point.z() != 0)
            {
                point.setX(point.x()/(-point.z()));
                point.setY(point.y()/(-point.z()));
            }

            checkMinMax(point);
        }
    }

興味がある場合は、回転行列を初期化するコードを次に示します。

public static Matrix eye_transformation(Vector3D eye)throws ParseException
    {
        double r = eye.length();
        double teta = Math.atan2(eye.y(), eye.x());
        double zr = eye.z()/r;
        double fi = Math.acos(zr);

        Matrix v = new Matrix();

        v.set(0, 0, -Math.sin(teta));
        v.set(0, 1, -Math.cos(teta) * Math.cos(fi));
        v.set(0, 2, Math.cos(teta) * Math.sin(fi));
        v.set(1, 0, Math.cos(teta));
        v.set(1, 1, -Math.sin(teta) * Math.cos(fi));
        v.set(1, 2, Math.sin(teta) * Math.sin(fi));
        v.set(2, 1, Math.sin(fi));
        v.set(2, 2, Math.cos(fi));
        v.set(3, 2, -r);

        return v;
    }

    public static Matrix z_rotation(double angle) throws ParseException
    {
        Matrix v = new Matrix();

        v.set(0, 0, Math.cos(angle));
        v.set(0, 1, Math.sin(angle));
        v.set(1, 0, -Math.sin(angle));
        v.set(1, 1, Math.cos(angle));

        return v;
    }

    public static Matrix x_rotation(double angle) throws ParseException
    {
        Matrix v = new Matrix();;

        v.set(1, 1, Math.cos(angle));
        v.set(1, 2, Math.sin(angle));
        v.set(2, 1, -Math.sin(angle));
        v.set(2, 2, Math.cos(angle));

        return v;
    }

    public static Matrix y_rotation(double angle) throws ParseException
    {
        Matrix v = new Matrix();

        v.set(0, 0, Math.cos(angle));
        v.set(0, 2, -Math.sin(angle));
        v.set(2, 0, Math.sin(angle));
        v.set(2, 2, Math.cos(angle));

        return v;
    }

    public static Matrix translation(double a, double b, double c) throws ParseException
    {
        Matrix v = new Matrix();;

        v.set(3, 0, a);
        v.set(3, 1, b);
        v.set(3, 2, c);

        return v;
    }

そして、点に回転行列を掛ける実際の方法

注: NR_DIMS は 3 として定義されます。

public static Vector3D mult(Vector3D lhs, Matrix rhs) throws ParseException
    {
        if(rhs.get(0, 3)!=0 || rhs.get(1, 3)!=0 || rhs.get(2, 3)!=0 || rhs.get(3, 3)!=1)
            throw new ParseException("the matrix multiplificiation thingy just borked");

        Vector3D ret = new Vector3D();
        double[] vec = new double[NR_DIMS];

        double[] temp = new double[NR_DIMS+1];      
        temp[0] = lhs.x;
        temp[1] = lhs.y;
        temp[2] = lhs.z;
        temp[3] = lhs.infty? 0:1;

        for (int i = 0; i < NR_DIMS; i++)
        {
                vec[i] = 0;

                // Multiply the original vector with the i-th column of the matrix.
                for (int j = 0; j <= NR_DIMS; j++)
                {
                        vec[i] += temp[j] * rhs.get(j,i);
                }
        }

        ret.x = vec[0];
        ret.y = vec[1];
        ret.z = vec[2];
        ret.infty = lhs.infty;

        return ret;
    }

このコードを古いコードでチェックして再チェックしました(注:古いコードは機能します)。操作に関しては同じです。

だから私はここで途方に暮れています.同様の質問を探しましたが、実際には有用な情報を提供しませんでした.

ありがとう :)

小さな追加:

アイポイントと回転の両方を無視すると(したがって、画像のみを投影します)、完全に問題なく表示されます。回転以外は画像が完成しているのがわかります。

他に提案はありますか?

4

2 に答える 2

0

私が考えることができるいくつかの可能な間違い:

  • Matrix のコンストラクターでは、恒等行列をロードしていません。
  • 角度をラジアンではなく度で渡しています。
  • あなたの目の投影行列は、あなたが考える別の範囲に投影されますか? つまり、OpenGL では、すべての射影行列は四角形 [(-1,-1),(1,1)] に射影する必要があります。この長方形は画面を表します。
  • プリマルチプライとポストマルチプライの混同。Id est: 私は通常、matrix*vector を実行します。私の間違いでなければ、あなたのコードでは vector*matrix を実行しているように見えます。
  • マトリックスの列と行を混同していませんか?

明日、あなたの質問をもう一度見てみます。うまくいけば、これらの提案のいずれかがお役に立てば幸いです。

編集: 最初の 2 つの項目を既にチェックしているのを見落としていました。

于 2013-08-10T00:33:12.933 に答える
0

わかりました、私は現在、完全なばかのように感じています。問題は単純な論理エラーでした。エラーはコードの次の部分にあります。

for(Vector3D point : points)
        {
            point = Vector3D.mult(point, scale);
            point = Vector3D.mult(point, rotate_x);
            point = Vector3D.mult(point, rotate_y);
            point = Vector3D.mult(point, rotate_z);
            point = Vector3D.mult(point, translate);
            point = Vector3D.mult(point, eye);

            if(point.z() != 0)
            {
                point.setX(point.x()/(-point.z()));
                point.setY(point.y()/(-point.z()));
            }

            checkMinMax(point);
        }

リストからオブジェクトを取得するとき、それはそのオブジェクトへの参照ではなく、同じデータを持つそのオブジェクトの新しいインスタンスであることを忘れていました。

だから私がしたことは、古いエントリを削除して新しいエントリに置き換えるだけです。

問題が解決しました。

于 2013-08-16T22:38:02.643 に答える