N88-BASICでレイトレーシング (1回目)

2021/6/1(火)

N88-BASICでレイトレーシング (1)

 

(by ULproject for N88-BASIC, NL-BASIC)

 

レイトレーシング球を表示するという

簡単なプログラムをN88-BASICで作ります

 

速度や色数に問題がありますのできれいな画面

描画する事より、動作原理を理解することが

目的です








1 視線方向の単位ベクトルE(上記矢印)

    とその出発点V(視点位置ベクトル)

 

レイトレーシングは他の方法に比べて簡単です

上図1のように視線と球の1番近い交点の色

見えているので、その色をスクリーン上に描いて

行くという仕組みです

 

ちなみに、1の視点の位置は、z軸上にとる

場合と、スクリーン上の点(図のV)にとる場合が

ありますが、Vを視点とした場合は、球が

スクリーンに重なったとき、球をスクリーンで

切断した断面を描くことができますが、

z軸上の場合は断面を描くことはできません。

ここでは前者のやり方で進めていきます。

 

まず、視点から球までの距離を求めます。

ここから、数値(スカラー)を小文字、ベクトル

(x,y,z成分を持つ矢印)を大文字で描くこと

にします。

 

P:任意の位置ベクトル

r:球の半径

V:視点の位置ベクトル

E:視線の方向単位ベクトル

t:任意の値

 

とします。位置ベクトルPは点Pと同じような

ものだと思って下さい。Eは方向を表し、単位

ベクトルは距離(矢印の長さ)が1のベクトルで、

|E| = 1と書きます。|E|はEベクトルの長さです。

1を参考にして下さい

 

原点が中心で半径rの球は、

|P| = r

で表されます。

原点から点Pまでの長さがrの点の集まりです

ので、球になります。

 

視点VからE方向に向けた視線は、

P = V + Et

で表されます。

VからE方向に任意の距離t離れた点Pの集まり

ですので、点Vを通りE方向に平行な直線になります。

 

ここで、余談ですが、

任意の場所にある球は、中心の位置を点Cとすると、

|P - C| = rとなりますが、視線の方は視点が

移動してもP = V + Etと変わりませんので、

球と視線を移動して球を原点に持ってくれば、

|P| = rの式で求めることができます。

よって、|P - C| = rは必要なく

次の2式で十分です

 

|P| = r

P = V + Et

 

この式から視点と球間の距離tを求めます。

|P| = r にP = V + Etを代入

|V + Et| = r の絶対値記号を外すため両辺を2乗

(V + Et)(V + Et) = r2 を展開

V・V + 2(V・E)t + (E・E)t2 = r2 

ここでベクトル同士の積は内積になります

E・E = |E|2 = 1×1 = 1

同じベクトルの内積はベクトルの長さの2乗です

Eは単位ベクトルなので|E|=1です

V・V + 2(V・E)t + t2 = r2 これを変形すると

 

t2 +  2(V・E)t + (V・V - r2) = 0

tの2次方程式になり、解の公式で

 

距離t = -V・E±√{ (V・E)2 - V・V + r2 }

となります

 

判別式D = (V・E)2 - V・V + r2 によって

D < 0 → 交差しない  (tは虚数)

D = 0 → 1点で接する(tは1個)

D > 0 → 2点で貫く  (tは遠近2個)

3パターンを判別できます

 

これをBASICで書いていきます

 

ベクトルの成分は、

P=(x, y, z)、V=(Vx ,Vy ,Vz)、V=(V0, V1, V2)

などと表しますが、

BASICでは配列を使うことにします

 

DIM V(2)で、(DIMしないと DIM V(10)になります)

V(0),V(1),V(2)という変数が使えます。

0がx, 1がy, 2がzを意味し

V(0),V(1),V(2)がx,y,z成分です

 

VとEの内積は、V・E = ViEi = ΣViEi (i=0,1,2)

です。つまり、同じxyz成分同士の積の和です。

 

b = V・Eは、BASICでは

B = V(0)*E(0) + V(1)*E(1) + V(2)*E(2)

となります

BASICではすべて大文字になり

四則演算は + - * / です

√(n) は、SQR(n)

rの2乗は、r^2 または r*r と書きます

 

t = -V・E±√( (V・E) - V・V + r2)は、

b = V・E、d = V・V - r2 と置くとt = -b±√(b2 - d)

 

BASICは行番号(昇順に並ぶ)のあとにプログラムを書きます

BASICは関数をプログラムできませんので、サブルーチンで

代用します。先頭に呼び出すためのラベルを書きます

*から始まる英数字と.の組み合わせです

'はコメントでこれ以降は無視されます

 

10 *DISTANCE.SPHERE

20 B = V(0)*E(0) + V(1)*E(1) + V(2)*E(2)       'b = V・E

30 D = V(0)*V(0) + V(1)*V(1) + V(2)*V(2) - R*R 'd = V・V - rr

40 D = B*B - D

 

ここまででDに判別式(√の中身)が入ります

D = B*B - Dは、B×B-Dの計算結果をDに代入するので

元のDの値は上書きされてなくなります

 

50 IF D < 0 THEN T = -1: RETURN '交点なし

 

判別式が負のときは交点なしで、見えていない事になります

tが負のときも、後ろに交点があるのでやはり見えません

よって、見えないときはtを負にして返すことにします

 

60 D = SQR(D)

70 T = -B - D '視線と球の近い方の交点距離

√の前の±は、-が近いほう、+が遠い方になりますので、

ここまででTに近いほうの交点までの距離が入りました

 

80 IF T < 0 THEN T = -B + D '視線と球の遠い方の交点距離

 

近いほうが負ならば交点は後ろで見えないので、遠いほうの

距離をTに入れます

遠い方のTが負なら球は後ろにあります

近い方が負、遠い方が正なら視点が球の中にあります

 

90 RETURN

これで、呼出し元へ戻ります

 

ここで、このサブルーチンの呼び出し側では、球の中心が

原点になるよう視点Vを移動させて呼び出されるので、

移動前と区別するため、移動後をV0で表すことにします

呼び出し側でTを使用したいので、TもT0に変えます

サブルーチンの説明をコメントに書いてRENUM 9000で行番号

を付けなおしたプログラムリストをダウンロード出来る

ようにしておきます

プログラムリストはLIST(Enterキー)で表示されます

BASICはEnterキーを押して初めて反応します

 

プログラムの読込みは

LOAD “ファイル名”(Enterキー)

または、ファイルをNL-BASICの画面に重ねて下さい


NL-BASICとblg~.zip(ray001.bas)は

以下のリンクからダウンロードできます


NL-BASIC(N88-BASIC互換?)ホームページ

Readme.txtを読んで遊んで下さい


次回

N88-BASICでレイトレーシング (2回目)


このブログの人気の投稿

NEWS

N88-BASICでゲーム (1回目)