DrawTriangle
三角形の描き方
三角形を二次元配列上に描くには、三角形の縦を基準にして考えたとき、
ある高さ(Y値)の時は、横幅(X値)はどこからどこまでが分かれば
その横幅を線として描いて、三角形にできます。
まず、高さの下から上までをループを作ります。(low_yを三角形の一番下、top_yを
一番上とします。)
for (int i = low_y; i < top_y; i++)
{
}
2順目のループを中に作ります。今度はその高さ(i)の時の一番左端をmin[i]、右端をmax[i]
として、左から右に移動していきます。
for (int i = low_y; i < top_y; i++)
{//三角形の下から上へ
for (int j = min[i]; j < max[i]; j++)
{//その高さの左端から右端へ
}
}
その時に、配列に色を設定すれば、描画の完成です。
for (int i = low_y; i < top_y; i++) {
for (int j = min[i]; j < max[i]; j++) {
pix[i * wid + j] = 255 << 24 | 0 << 16 | 0 << 8 | 255;
}
}
void drawTriangle(Vertex v1, Vertex v2, Vertex v3, int[] pix)
{
for (int i = 0; i < hei; i++) {
min[i] = 9999999;//minに巨大な数で初期化
max[i] = -9999999;//maxに微小な数
}
int v1x = (int)v1.x + cenWid;
int v2x = (int)v2.x + cenWid;
int v3x = (int)v3.x + cenWid;
int v1y = hei - (int)v1.y - cenHei;
int v2y = hei - (int)v2.y - cenHei;
int v3y = hei - (int)v3.y - cenHei;
int top_y = -9999999;
int low_y = 9999999;
if (low_y > v1y) low_y = v1y;
if (low_y > v2y) low_y = v2y;
if (low_y > v3y) low_y = v3y;
if (top_y < v1y) top_y = v1y;
if (top_y < v2y) top_y = v2y;
if (top_y < v3y) top_y = v3y;
drawLineTate(v1x, v1y, v2x, v2y);
drawLineTate(v2x, v2y, v3x, v3y);
drawLineTate(v3x, v3y, v1x, v1y);
for (int i = low_y; i < top_y; i++) {
for (int j = min[i]; j < max[i]; j++) {
if ( j < 0 | wid <= j) continue;//画面内に収める
pix[i * wid + j] = 255 << 24 | 0 << 16 | 0 << 8 | 255;
}
}
}
三角形の横幅の端(min)から端(max)までを、線形補間を使って計算します。
lenに線の縦の長さ+1を入れます。
//int len = Math.abs(p2y - p1y) + 1;
それぞれの頂点に巨大な数を掛けます。今回は最適化のためシフト演算してます。
int x16_x1 = p1x << 16;//16シフト倍
int x16_y1 = p1y << 16;
int x16_x2 = p2x << 16;
int x16_y2 = p2y << 16;
巨大な数を掛けた後の、1つの線の横幅と縦幅(注:三角形の横幅・縦幅ではない)を出し、
実際の線の縦の長さ(len)で割ります。これが、縦が一つ増える度の横と縦の増加の割合になります。
int zouka_x = (x16_x2 - x16_x1) / len;
int zouka_y = (x16_y2 - x16_y1) / len;
void calcLineTate(int p1x, int p1y, int p2x, int p2y)
{
int len = Math.abs(p2y - p1y) + 1;
int x16_x1 = p1x << 16;//16シフト倍
int x16_y1 = p1y << 16;
int x16_x2 = p2x << 16;
int x16_y2 = p2y << 16;
int zouka_x = (x16_x2 - x16_x1) / len;
int zouka_y = (x16_y2 - x16_y1) / len;
int tmp_x = x16_x1;
int tmp_y = x16_y1;
for (int i = 0; i < len; i++, tmp_x += zouka_x, tmp_y += zouka_y)
{
if ((tmp_y >> 16) < 0 | hei <= (tmp_y >> 16)) continue;
if (min[tmp_y >> 16] > (tmp_x >> 16)) min[tmp_y >> 16] = tmp_x >> 16;
if (max[tmp_y >> 16] < (tmp_x >> 16)) max[tmp_y >> 16] = tmp_x >> 16;
}
}
void drawLineTate(int p1x, int p1y, int p2x, int p2y)
{
int startY, endY, startX, endX;
if (p1y < p2y) { startY = p1y; endY = p2y; startX = p1x; endX = p2x;}
else { startY = p2y; endY = p1y; startX = p2x; endX = p1x;};
calcLineTate(startX, startY, endX, endY);
}
2007年12月24日(月) 19:06:07 Modified by eruvasu