プチコン3号 24日目 擬似3D(1) 遠近感の表現

今回からオブジェクト指向はいったんお休みにして、3次元グラフィックスを扱います。
といっても、まずは映画のCGのような本格的なものではなく、スプライトの拡大・縮小を使った疑似3Dについて考えます。

プチコン3号では、スプライトの拡大・縮小を自由に行うことができます。
スプライトの表示を、視点から遠くなるほど縮小し、近くでは拡大すれば、遠近感を表現できます。
また、動きを遠くのものほど小さく、近くのものでは大きくすることで、距離感を強調できます。

スプライト自体は2次元の絵なのですが、大きさを変化させることによって疑似的に3次元ぽく見せることができます。
さらに、プチコン3号はSPOFS命令でZ値を指定することで視差による奥行きもつけられますので、より3次元ぽさを強調することもできます。

今回は、まず「遠くのものほど小さく表示され動きも小さくなる」プログラムを作ります。

pc24-1.jpg

図のように、2000×2000×2000(X,Yがそれぞれ-1000~1000、Zが0~2000)の立方体の空間を、スクリーンから覗くことを考えます。
スクリーンは立方体の1つの面の中央に貼りついていて、大きさは400×240です。
座標軸は、スクリーンから見て右方向をX軸、下方向をY軸、奥行き方向をZ軸と考えましょう。
原点はスクリーンの中央とします。

そして、スクリーンに表示される範囲は、立方体のスクリーンと反対側の面がスクリーンの横幅に収まるようにします。
つまり、XY座標での表示範囲は

 Z=0のとき、  400×240、座標では(-200, 120)~(200,-120)
 Z=2000のとき、2000×1200、座標では(-1000, 600)~(1000,-600)

となります。

pc24-2.jpg

上(XZ平面)から見ると、図左の明るい灰色で示した台形の範囲が、スクリーンに表示されることになります。
横(YZ平面)から見ても同様に表示範囲は台形になります。
3次元で考えると、表示される空間は四角錘の先端を切り取ったような形になります。

では、この空間の中に200×200の正方形を表示することを考えてみましょう。
Z=0のときは、正方形のサイズは200×200です。
Z=2000のときは、スクリーン全体では2000×1200の領域を400×240に縮小して表示しています。
比率は、400/2000=1/5になりますので、200×200の正方形は40×40に縮小されることになります。

つまり、Zの値が0から2000まで変化するとき、

 ・スクリーンに表示される範囲はZに比例して400×240から2000×1200まで変化。
 ・正方形のサイズはZに反比例して200×200から40×40まで変化。

となります。

以上をプログラムにしてみると、以下のようになります。
Zの値を200ずつ変化させながら正方形を描画しました。

GCLS

LEFT  = -100
TOP   = -100
RIGHT =  100
BOTTOM=  100

FOR Z=0 TO 2000 STEP 200
W     = 400+(2000-400)*(Z/2000)
SCALE = 400/W
X1    = LEFT * SCALE + 200
X2    = RIGHT* SCALE + 200
Y1    = TOP  * SCALE + 120
Y2    =BOTTOM* SCALE + 120
GBOX X1,Y1,X2,Y2
NEXT

結果はこんな感じになります。

pc24-3.jpg

プログラム中のWは、スクリーンに表示される範囲を表し、下のグラフのようにZに応じて400から2000まで変化します。
この範囲が、スクリーン上では400ピクセルの範囲に縮小表示されます。
その縮小率がSCALEで、Zに反比例します。

pc24-4.jpg
pc24-5.jpg

さて、このプログラムで、Zの値を変化させるたびに画面をクリアしてから正方形を描画してみます。
すると、正方形が手前から奥へと飛んでいくようなアニメーションが作れます。
さらに、グラフィック画面のZの値を、正方形のZの値に合わせて設定すると、距離感が強調されます。

以上の変更を加えたものが以下のプログラムです。
アニメーションなのでZの変化幅をより小さくし、Zの最大値も5000にして、より遠くまで表現しています。

GCLS

LEFT  = -100
TOP   = -100
RIGHT =  100
BOTTOM=  100
@LOOP
FOR Z=0 TO 5000 STEP 50
 GCLS
GPRIO Z/5
W=400+1600*(Z/2000)
SCALE=400/W
X1=LEFT*SCALE+200
X2=RIGHT*SCALE+200
Y1=TOP*SCALE+120
Y2=BOTTOM*SCALE+120
GBOX X1,Y1,X2,Y2
 VSYNC 1
NEXT
GOTO @LOOP

さらに、この正方形に上下左右の動きを加えてみましょう。
スライドパッドで、正方形のXY座標を変化させてみます。
このとき「遠くほど小さく、近くほど大きく動かす」ことを考慮する必要はありません。
表示の際に行う座標変換で、移動量も変換されるからです。

GCLS

LEFT  = -100
TOP   = -100
RIGHT =  100
BOTTOM=  100
@LOOP
FOR Z=0 TO 5000 STEP 50
 STICK OUT X,Y
LEFT  = LEFT  + X*10
RIGHT = RIGHT + X*10
TOP   = TOP   - Y*10
BOTTOM= BOTTOM- Y*10
 GCLS
GPRIO Z/5
W=400+1600*(Z/2000)
SCALE=400/W
X1=LEFT*SCALE+200
X2=RIGHT*SCALE+200
Y1=TOP*SCALE+120
Y2=BOTTOM*SCALE+120
GBOX X1,Y1,X2,Y2
VSYNC 1
NEXT
GOTO @LOOP

正方形が手前から向こうへ飛び去っていくだけですが、スライドパッドで軌道を変更することができます。

では、最後にグラフィックスではなくスプライトで同じことをやってみましょう。
グラフィックスでは正方形の4つの座標値を指定して描画していましたが、スプライトでは中心座標とスケール値での指定になります。
プログラムは以下のようになります。
スプライトが遠くへ行くほど、色が暗くなるようにして、遠近感を強調しています。

ACLS
SPSET 0,3482
LEFT  = -100
TOP   = -100
@LOOP
FOR Z=0 TO 5000 STEP 50
STICK OUT X,Y
LEFT  = LEFT  + X*10
TOP   = TOP   - Y*10
W=400+1600*(Z/2000)
SCALE=400/W
X1=LEFT*SCALE+200
Y1=TOP*SCALE+120
 SPSCALE 0,6*SCALE,6*SCALE
SPOFS 0,X1,Y1,Z/5-100
C=127+128*SCALE
SPCOLOR 0,RGB(255,C,C,C)
 VSYNC 1
NEXT
GOTO @LOOP

コメント