Javaプログラミング

トップページ      |      目次
←前へ      次へ→

  • 隠面処理(Zソート法)
  •  

    • Zソート法と法線ベクトル法
    • 法線ベクトルでは視点に対して表を向いているか、裏を向いているかによって可視性を判定して、表示・非表示を切り替えることで隠面処理をするアルゴリズムである。
      この方法は立方体や球のような凸面のみで構成される形状に対してはうまく働くが、トーラス(ドーナツ型)のような凹面を含む形状に対しては可視性の判定が失敗することがある。
      以下の図のように、奥側の面も表側であるため法線ベクトル法では判定しきれずに失敗する。
      これを解決するには奥側か手前側かについても考える必要がある。
      Zソート法は隠面処理アルゴリズムのうち優先順位アルゴリズムの1つで、奥側か手前側かについても対応できる。 そのため、凹面を含むような形状も正しく表示できる。
      実行結果 実行結果 実行結果
      凹面を含む図形(トーラス)
      法線ベクトル法による表示
      表示が失敗している
      Zソート法による表示
      本来表示されるべき状態
    • 優先順位アルゴリズムとZソート法
    • 優先順位アルゴリズムは面の可視性の優先順位に基づいて隠面処理を行う方法である。 画面に図形を表示するとき、二つの面が重なる場合を考える。
      この場合、描画の順序が後の図形は先に描画された図形を上書きする。つまり視点から見て奥側から優先的に描画すれば、前後関係が正しく表示される。
      Zソート法はこの考え方に基づいてポリゴン単位で描画の優先順位を決定して奥側から描画することで隠面処理を行う。
      この方法が画家が絵を描くとき、背景から書いて、最後に手前を描く方法と同じためペインタアルゴリズム(画家のアルゴリズム)とも呼ばれる またZソートのZはZ軸のことで、奥行きを表すことから奥行きソートとも呼ばれる。

       
    • Zソート法の実装
    • コード
      
      	public void zSort(Graphics g,Shape shape) {
      
      		g.setColor(Color.white);
      		g.fillRect(0, 0, screenW, screenH);
      
      
      		//面の重心から視点の距離を求める
      		double[] dist=new double[shape.faces.length];
      		for(int i=0;i<shape.faces.length;i++) {
      			double[] fg=new double[3];
      			fg=viewOrtho(shape.fg[i]);
      			dist[i]=(fg[0]-vp[0])*(fg[0]-vp[0])+
      					(fg[1]-vp[1])*(fg[1]-vp[1])+
      					(fg[2]-vp[2])*(fg[2]-vp[2]);
      		}
      
      		int[] faceList=new int[shape.faces.length];
      		for(int i=0;i<shape.faces.length;i++) {
      			faceList[i]=i;
      		}
      		for(int i=0;i<shape.faces.length-1;i++) {
      			for(int j=i+1;j<shape.faces.length;j++) {
      				if(dist[i]<dist[j]) {
      					double wd=dist[i];
      					dist[i]=dist[j];
      					dist[j]=wd;
      					int wl=faceList[i];
      					faceList[i]=faceList[j];
      					faceList[j]=wl;
      				}
      			}
      		}
      
      		double[] p=new double[3];
      		int[] px=new int[shape.faces[0].length];
      		int[] py=new int[shape.faces[0].length];
      
      		for(int i=0;i<shape.faces.length;i++) {
      			for(int j=0;j<shape.faces[i].length;j++) {
      				p=viewOrtho(shape.vertices[shape.faces[faceList[i]][j]]);
      				px[j]=(int)p[0];
      				py[j]=(int)p[1];
      			}
      
      
                  g.setColor(c);
                  g.fillPolygon(px, py, shape.faces[i].length	);
      		}
      	}
      
      
        実行結果
        実行結果
        サンプルプログラム(実行可能JARファイル)
        サンプルコード


      ←前へ      次へ→