Wiki内検索
最近更新したページ
2011-08-24
2010-05-18
2010-05-03
2010-02-18
2010-02-10
2010-02-09
2010-02-08
2010-02-07
2010-02-02
2009-12-24
2009-12-05
2009-07-05
2009-07-03
最新コメント
MenuBar1 by stunning seo guys
MenuBar1 by stunning seo guys
MenuBar1 by stunning seo guys
MenuBar1 by awesome things!
MenuBar1 by awesome things!
MenuBar1 by awesome things!
MenuBar1 by check it out
MenuBar1 by awesome things!
MenuBar1 by check it out
MenuBar1 by stunning seo guys
Menu
Programming Tips
タグ

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




スマートフォン版で見る