つづき
以下のプログラムを、それぞれのサンプルのEND文以降につなげてください。
MODULE PLOT !各頂点の色をもとに線分と凸多角形にグラデーションをかける
SET POINT STYLE 1 !マークの形状
SHARE NUMERIC Xmin(0 TO 1024),Xmax(0 TO 1024) !y座標(y行)におけるx座標の最小値、最大値 ※要調整
SHARE NUMERIC Rmin(0 TO 1024),Rmax(0 TO 1024)
SHARE NUMERIC Gmin(0 TO 1024),Gmax(0 TO 1024)
SHARE NUMERIC Bmin(0 TO 1024),Bmax(0 TO 1024)
SHARE NUMERIC ww,hh !スクリーンの位置、大きさ
EXTERNAL SUB Init !レンダリングターゲットを初期化する
SET COLOR mode "NATIVE" !RGB指定
SET TEXT font "",12 !文字サイズ
ASK WINDOW x1,x2,y1,y2 !座標系の端の座標を取得する
ASK PIXEL SIZE (x1,y1; x2,y2) ww,hh !画面の大きさ(ピクセル単位)を調べる
END SUB
EXTERNAL SUB SetPixel(x,y,c) !座標(x,y,z)に色(r,g,b)で点を描く ※PLOT POINTS: x,y と同じ
SET POINT COLOR c
PLOT POINTS: WORLDX(x), WORLDX(y) !問題座標に戻して描く
!!!PLOT POINTS: x * (x2 - x1) / ww + x1, y * (y2 - y1) / hh + y1 !問題座標に戻して描く
END SUB
PUBLIC SUB POINTS !※PLOT POINTS: x,y と同じ
EXTERNAL SUB POINTS(xx,yy,rr,gg,bb) !線分を描画する
LET x1 = PIXELX(xx)
LET y1 = PIXELY(yy)
IF (y1 >= 0) AND (y1 < hh) THEN !画面内なら
IF (x1 >= 0) AND (x1 < ww) THEN
CALL SetPixel(INT(x1),INT(y1), colorindex(rr,gg,bb))
END IF
END IF
END SUB
PUBLIC SUB LINES !※PLOT LINES: x0,y0; x1,y1 または MAT PLOT LINES,LIMIT 2: x,y と同じ
EXTERNAL SUB LINES(xx(),yy(),rr(),gg(),bb()) !線分を描画する
LET x1 = PIXELX(xx(0))
LET y1 = PIXELY(yy(0))
LET x2 = PIXELX(xx(1))
LET y2 = PIXELY(yy(1))
LET r1 = rr(0) !初期値を設定する
LET g1 = gg(0)
LET b1 = bb(0)
SET DRAW mode hidden !ちらつき防止(開始)
IF (x1 = x2) AND (y1 = y2) THEN !始点と終点が同じなら
IF (y1 >= 0) AND (y1 < hh) THEN !画面内なら
IF (x1 >= 0) AND (x1 < ww) THEN
CALL SetPixel(INT(x1),INT(y1), colorindex(r1,g1,b1))
END IF
END IF
ELSE
LET dx = x2 - x1 !相対的長さ
LET dy = y2 - y1
IF ABS(dy) < ABS(dx) THEN !xの方が増分が多い
!□□□■
!□■■□ y=l*x+mの式として考える
!■□□□
LET l = dy / dx !傾きを求める
LET dr = (rr(1) - rr(0)) / dx
LET dg = (gg(1) - gg(0)) / dx
LET db = (bb(1) - bb(0)) / dx
FOR i=0 TO dx STEP SGN(dx)
LET x = x1 + i
LET y = l * i + y1
LET r = dr * i + r1
LET g = dg * i + g1
LET b = db * i + b1
IF (y >= 0) AND (y < hh) THEN !画面内なら
IF (x >= 0) AND (x < ww) THEN
CALL SetPixel(INT(x),INT(y), colorindex(r,g,b))
END IF
END IF
NEXT i
ELSE !yの方が増分が多い
!□□■
!□■□ x=l*y+mの式として考える
!□■□
!■□□
LET l = dx / dy !傾きを求める
LET dr = (rr(1) - rr(0)) / dy
LET dg = (gg(1) - gg(0)) / dy
LET db = (bb(1) - bb(0)) / dy
FOR i=0 TO dy STEP SGN(dy)
LET x = l * i + x1
LET y = y1 + i
LET r = dr * i + r1
LET g = dg * i + g1
LET b = db * i + b1
IF (y >= 0) AND (y < hh) THEN !画面内なら
IF (x >= 0) AND (x < ww) THEN
CALL SetPixel(INT(x),INT(y), colorindex(r,g,b))
END IF
END IF
NEXT i
END IF
END IF
SET DRAW mode explicit !ちらつき防止(終了)
END SUB
PUBLIC SUB AREALIMIT !!※MAT PLOT AREA,LIMIT n: x,y と同じ
EXTERNAL SUB AREALIMIT(NumOfVtx, xx(),yy(),rr(),gg(),bb()) !凸多角形(頂点番号による面の定義)を描画する
IF NumOfVtx < 3 THEN EXIT SUB
DIM sx(0 TO NumOfVtx-1),sy(0 TO NumOfVtx-1)
FOR i=0 TO NumOfVtx-1 !問題座標からピクセル座標に変換する
LET sx(i) = PIXELX(xx(i))
LET sy(i) = PIXELY(yy(i))
!!!LET sx(i) = (xx(i) - x1) * ww / (x2 - x1)
!!!LET sy(i) = (yy(i) - y1) * hh / (y2 - y1)
NEXT i
LET top = +2147483647 !バッファの使用範囲を設定する
LET btm = -2147483648
FOR i=0 TO NumOfVtx-1
IF top > sy(i) THEN LET top = sy(i)
IF btm < sy(i) THEN LET btm = sy(i)
NEXT i
LET top = INT(top)
LET btm = INT(btm)
IF top < 0 THEN LET top = 0
IF btm > hh THEN LET btm = hh
FOR i=top TO btm-1 !最大最小バッファを初期化する
LET Xmin(i) = +2147483647
LET Xmax(i) = -2147483648
NEXT i
FOR i=0 TO NumOfVtx-2 !稜線の数だけ
CALL ScanEdge(i,i+1, sx,sy,rr,gg,bb) !稜線が描く各点を求める
NEXT i
CALL ScanEdge(NumOfVtx-1,0, sx,sy,rr,gg,bb)
SET DRAW mode hidden !ちらつき防止(開始)
FOR y=top TO btm-1 !各ライン(y座標)ごとに走査する - ラスタライズ
LET l = (Xmax(y) - Xmin(y)) + 1 !増分値を計算する
LET dr = (Rmax(y) - Rmin(y)) / l
LET dg = (Gmax(y) - Gmin(y)) / l
LET db = (Bmax(y) - Bmin(y)) / l
LET r = Rmin(y) !初期値を設定する
LET g = Gmin(y)
LET b = Bmin(y)
FOR x=Xmin(y) TO Xmax(y) !ライン上での直線を描く ※PLOT LINES: Xmin(y),y; Xmax(y),y
IF (x >= 0) AND (x < ww) THEN !画面内なら
CALL SetPixel(x,y,colorindex(r,g,b)) !問題座標に戻して描く
END IF
LET r = r + dr !次へ
LET g = g + dg
LET b = b + db
NEXT x
NEXT y
SET DRAW mode explicit !ちらつき防止(終了)
END SUB
EXTERNAL SUB ScanEdge(v1,v2, xx(),yy(),rr(),gg(),bb()) !頂点v1と頂点v2を結ぶ稜線(辺)が描く各点を求める
LET l = ABS(INT(yy(v2) - yy(v1))) + 1 !幅を計算する
LET dx = (xx(v2) - xx(v1)) / l !増分値を計算する
LET dy = (yy(v2) - yy(v1)) / l
LET dr = (rr(v2) - rr(v1)) / l
LET dg = (gg(v2) - gg(v1)) / l
LET db = (bb(v2) - bb(v1)) / l
LET x = xx(v1) !初期値を設定する
LET y = yy(v1)
LET r = rr(v1)
LET g = gg(v1)
LET b = bb(v1)
FOR i=0 TO l-1 !各ライン(y座標)ごとに
LET px = INT(x)
LET py = INT(y)
IF (py >= 0) AND (py < hh) THEN !画面内なら
IF Xmin(py) > px THEN !左端位置を記録する
LET Xmin(py) = px
LET Rmin(py) = r
LET Gmin(py) = g
LET Bmin(py) = b
END IF
IF Xmax(py) < px THEN !右端位置を記録する
LET Xmax(py) = px
LET Rmax(py) = r
LET Gmax(py) = g
LET Bmax(py) = b
END IF
END IF
LET x = x + dx !次へ
LET y = y + dy
LET r = r + dr
LET g = g + dg
LET b = b + db
NEXT i
END SUB
END MODULE