![]() |
![]() |
|
|
ポリゴンの奥行きが交差する場合、 Zソート法は失敗する |
ポリゴンの奥行きが交差する場合でも、 Zバッファ法は対応が可能 |
![]() |
![]() |
フレームバッファの画素情報 |
Zバッファの画素情報 |
public void zBuffer(Graphics g,Shape shape) {
bg.setColor(Color.white);
bg.fillRect(0, 0, screenW, screenH);
//デプスバッファの初期化
for(int i=0;i<screenH;i++) {
for(int j=0;j<screenW;j++) {
depthBuffer[i][j]=-1e30;
}
}
//頂点データの座標変換
double[][] v=new double[shape.vertices.length][3];
for(int i=0;i<shape.vertices.length;i++) {
v[i]=viewOrtho(shape.vertices[i]);
}
//ポリゴン毎の処理
for(int j=0;j<shape.faces.length;j++) {
double[][] polygon=new double[shape.faces[j].length][3];
for(int i=0;i<shape.faces[j].length;i++) {
polygon[i]=v[shape.faces[j][i]];
}
//面の色を決定
//法線データの座標変換
double[] n=new double[3];
n=viewOrtho(shape.normal[j]);
//重心データの座標変換
double[] fg=new double[3];
fg=viewOrtho(shape.fg[j]);
double[] nv= {
n[0]-o[0],
n[1]-o[1],
n[2]
};
double[] vv= {
fg[0]-vp[0],
fg[1]-vp[1],
fg[2]-vp[2],
};
double dot=nv[0]*vv[0]+nv[1]*vv[1]+nv[2]*vv[2];
Color c=new Color(
(int)clip(dot/vp[2]*255,0,255),
(int)clip(dot/vp[2]*64,0,255),
(int)clip(dot/vp[2]*168,0,255)
);
bg.setColor(c);
if(j==1)
c=Color.blue;
else
c=Color.green;
int top=0;
int bottom=0;
int left=0;
int right=0;
int num=polygon.length;
//y軸の最大値と最小値を求める
for(int i=0;i<num;i++) {
if(polygon[top][1]>polygon[i][1]) {
left=i;
right=i;
top=i;
}
if(polygon[bottom][1]<polygon[i][1]) {
bottom=i;
}
}
//yを上から走査する
for(double y=polygon[top][1];y<polygon[bottom][1];y+=0.1) {
if(y<0||y>screenH)continue;
//左側の線分の終端を超えたら次の直線を走査(反時計回り)
if(polygon[(left+1)%num][1]<=y) {
left=(left+1)%num;
}
//右側の線分の終端を超えたら次の直線を走査(時計周り)
if(polygon[(right-1+polygon.length)%polygon.length][1]<=y) {
right=(right-1+polygon.length)%polygon.length;
}
//直線の内分点を求める
double[] p0=polygon[right];
double[] p1=polygon[left];
double[] p2=polygon[(left+1)%polygon.length];
double[] p3=polygon[(right-1+polygon.length)%polygon.length];
double[] start=new double[3];
start[0]=((p2[1]-y)*p1[0]+(y-p1[1])*p2[0])/(p2[1]-p1[1]);
start[1]=y;
start[2]=((p2[1]-y)*p1[2]+(y-p1[1])*p2[2])/(p2[1]-p1[1]);
double[] end=new double[3];
end[0]=((p3[1]-y)*p0[0]+(y-p0[1])*p3[0])/(p3[1]-p0[1]);
end[1]=y;
end[2]=((p3[1]-y)*p0[2]+(y-p0[1])*p3[2])/(p3[1]-p0[1]);
//始点と終点が入れ替わっていたら交換
if(start[0]>end[0]) {
double[] w=start;
start=end;
end=w;
}
//深度テスト
for(double x=start[0];x<end[0];x++) {
if(x<0||x>screenW)continue;
if(y<0||y>screenH)continue;
double[] q=new double[3];
q[0]=x;
q[1]=y;
q[2]=((end[0]-x)*start[2]+(x-start[0])*end[2])/(end[0]-start[0]);
if(depthBuffer[(int)y][(int)x]<q[2]) {
buffer.setRGB((int)x, (int)y, c.getRGB());
depthBuffer[(int)y][(int)x]=q[2];
buffer.setRGB((int)x, (int)y, c.getRGB());
}
}
}
}
g.drawImage(buffer,0,0,null);
}