fc2ブログ
キャラクタ3Dがまあまあ動いたので気をよくして、次は「ワイヤフレーム3Dいってみよう!」ということにしました。

「まずはラインルーチンから」と考えたところで、はたと困りました。

普通にブレゼンハムのアルゴリズムを考えたのですが、これって傾きが1未満と1以上で描画を分けるのですよね。つまり2倍のコードが必要なわけです。始点と終点のX,Y大小関係も考慮が必要です。
これまでの経験上、これはichigojam用としてはメモリが足りないだろう、とわかります。

どうしたものかなあ、と考えていたところ、通勤中の電車内でひらめきました。

  ・ichigojamのセミグラフィックを64x64しかないのを逆手に取り、その範囲にあったアルゴリズムにします。

   ・描画する座標x,yそれぞての始点と終点の差分を取りdx、dyとします。 
   ・描画座標は64倍で計算します。
   ・64倍された始点座標にdx、dyを加算していくと、64回加算でちょうど終点座標の64倍になります。
   ・その加算過程の座標を1/64してドットをうつと、始点から終点にいたる線が描画されます。

これは普通に縦横数百PIXEL以上の画面では演算回数が多くなりすぎて使えないでしょう。
また、短い線だと同じPIXELに何回も無駄に書きます。(極端な話長さ1piexlの線でも同じところに64回点を打ちます。)
64x64しかないから画面でマシン語だから使えるアルゴリズムです。

帰宅して早速C言語にしてみました。

最初の行の<と>は全角ですが、使用する場合は半角の<と>変えてください。
FC2ブログ文字化けを防ぐためにこうしています。


#include <stdint.h>
#define VRAM_ADR 0x900
#define WORK_ADR 0x800

uint16_t stars(uint16_t c, uint8_t* m_p, uint8_t* f_p)
{
int16_t p,x0,y0,x1,y1,i,x,y,xp,yp,dx,dy,w;
uint8_t c1;
int16_t* w_p = m_p + WORK_ADR;
uint8_t* v_p = m_p + VRAM_ADR;

p=0;
while (p<4) {
x0 = w_p[p++];y0 = w_p[p++];
x1 = w_p[p++];y1 = w_p[p++];
dx = x1 - x0;
dy = y1 - y0;
x = x0 << 6;
y = y0 << 6;
for (i=0;i<64;i++) {
xp=x>>6;
yp=y>>6;
w=((yp&0xfffe) <<4) + (xp>>1) + 384+16; //*** 変換した座標に対応するVRAMアドレス計算
c1= ( 1 <<( ( ( xp&1) | (yp&1)<<1) ) ) | 0x80; //*********** セミグラフィックキャラ計算
if ((xp>-32)&&(xp<32)&&(yp>-24)&&(yp<24)&&((v_p[w]&0x70)==0) ) {v_p[w] |= c1;}
x += dx;
y += dy;
}
}
return 0;
}


で、BASICでは以下のコードでテストしてみました。

10 cls
20 for i=-5to5
25 cls
30 [0]=31:[1]=-i:[2]=-31:[3]=i
40 a=usr(#700,0)
45 wait 10
50 next
100 for i=-5to5
110 cls
120 [0]=-i:[1]=-i:[2]=i:[3]=i
130 a=usr(#700,0)
140 wait 10
150 next
200 for i=-5to5
210 cls
220 [0]=-i-5:[1]=-i+5:[2]=i:[3]=i*2
230 a=usr(#700,0)
240 wait 10
250 next


意図通りに線が描画されます。傾きも始点・終点位置関係も問題なしです。

いけるようなので明日はZ座標を導入して3Dのラインを書けるようにします。

その次はいよいよワイヤフレーム3Dです。

それではまたです。


2016.06.29 Wed l ICHIGOJAM l コメント (0) l top

コメント

コメントの投稿