1

斜めの投影 (キャビネットまたはキャバリエ) で 3D のものをレンダリングできるようにするために、処理を拡張したいと考えています。camera()、perspective()、ortho() メソッドのソースを調べた後、正射投影を設定し、PGraphics3D#camera マトリックスを適切な値に調整して部分的に成功させることができました。

void setup() {
   camera(30, 30, 30, 0, 0, 0, 1, 1, 0);
   ortho(-100, 100, -100, 100, -500, 500);
   p3d.camera.set(1, 0, -0.433f, 0, 0, 1, 0.25f, 0, 0, 0, 0, 0, 0, 0, 0, 1);
}

void draw() {
   box(20);
}

これにより、正しい遠近感が得られますが、表面の塗りつぶしはありません。カメラと ortho メソッド呼び出しのいずれか、またはその両方を削除すると、後で上書きされる同じマトリックスで camera(...) が動作すると予想されますが、画面は空です。

さらに、PGraphics3D のマトリックス化 (camera、modelView、projection) について少し混乱しています。OpenGL は 2 つのマトリックス スタック (modelView とプロジェクション) を保持しますが、ここには 3 つ目のスタック (カメラ) があります。これらの行列の違いと関係に光を当てられる人はいますか?

これは、いつどれを使用/設定するかを知るのに役立ちます。

4

1 に答える 1

2

素晴らしい質問です。

あなたが持っていたように次のコードを実行しましたが、それは白い立方体の等角図のように見えました.

1: size(300,300,P3D);
2: camera(30, 30, 30, 0, 0, 0, 1, 1, 0);
3: ortho(-100, 100, -100, 100, -500, 500);
4: PGraphics3D p3d = (PGraphics3D)g;
5: p3d.camera.set(1, 0, -0.433f, 0, 0, 1, 0.25f, 0, 0, 0, 0, 0, 0, 0, 0, 1);
6: box(20);

何が起こっているかは次のとおりです。

  • 2 行目:カメラモデルビューの両方の行列を設定します
  • 3 行目:射影行列を設定します
  • 4 行目:カメラマトリックスのみを設定しますが、これは実際には何もしませんでした。(読む)

変換は、モデル ビュー射影行列を使用してのみ実行されます。カメラマトリックスは、モデル ビューが通常初期化される ものを便利に分離したものにすぎません。

draw() 関数を使用した場合、モデルビュー マトリックスは、呼び出されるたびにカメラマトリックスに実際に初期化されます。draw() 関数を使用しなかったため、カメラ マトリックスはカメラ マトリックスの斜め変換で更新されませんでし


斜め投影の作成方法

免責事項として、行列を使用して座標を変換する方法を完全に理解する必要があります。順序は非常に重要です。これはそれを学ぶための良いリソースです: http://glprogramming.com/red/chapter03.html

私ができる最も簡単な説明は、モデルビューマトリックスがオブジェクト座標を相対的な目の座標に変換し、次に射影マトリックスがそれらの目の座標を取り、それらをスクリーン座標に変換するということです。したがって、スクリーン座標に変換する前に斜め投影を適用する必要があります。

いくつかの立方体を表示するキャビネット プロジェクションを作成するための実行可能な例を次に示します。

void setup()
{
  strokeWeight(2);
  smooth();
  noLoop();

  size(600,600,P3D);
  oblique(radians(60),0.5);
}

void draw()
{
  background(100);

  // size of the box
  float w = 100;

  // draw box in the middle
  translate(width/2,height/2);
  fill(random(255),random(255),random(255),100);
  box(w);

  // draw box behind
  translate(0,0,-w*4);
  fill(random(255),random(255),random(255),100);
  box(w);

  // draw box in front
  translate(0,0,w*8);
  fill(random(255),random(255),random(255),100);
  box(w);
}

void oblique(float angle, float zscale)
{
  PGraphics3D p3d = (PGraphics3D)g;

  // set orthographic projection
  ortho(-width/2,width/2,-height/2,height/2,-5000,5000);

  // get camera's z translation
  // ... so we can transform from the original z=0
  float z = p3d.camera.m23;

  // apply z translation
  p3d.projection.translate(0,0,z);

  // apply oblique projection 
  p3d.projection.apply(
    1,0,-zscale*cos(angle),0,
    0,1,zscale*sin(angle),0,
    0,0,1,0,
    0,0,0,1);

  // remove z translation
  p3d.projection.translate(0,0,-z);
}

処理中の斜め投影のスクリーンショット

于 2011-03-11T07:28:44.923 に答える