このホームページのBLOG内リンク先のブログで公開しました。
第1回~第8回の記事(~.doc)とBASIC(~.bas)は
このホームページからダウンロードできます。
以下に、r008.bas の LISt と画面を載せておきます。
1000 '----------------------------------------------------------------------
1010 ' N88-BASICでかんたんにレイトレーシング 第8回
1020 '
1030 ' by ULproject
1040 '
1050 ' for BASIC ( N88-BASIC、VL-BASICなど )
1060 '
1070 ' 2019.12
1080 '
1090 ' スクリーン上の各点からの視線で球をトレース
1100 ' 球0~2の存在を色で確認する(3つの円が見える)
1110 ' 球0は減衰しない点光源(陰対応)
1120 '
1130 ' コメントの大文字はベクトル、小文字はスカラー
1140 '----------------------------------------------------------------------
2000 SN = 3 ' 球の個数
2010 DIM SX(SN), SY(SN), SZ(SN), SR(SN), SC(SN)
2020 ' center radius color
2030 SX(0) = -500: SY(0) = 500:SZ(0) = 500: SR(0) = 2:SC(0) = 7 ' light
2040 SX(1) = 3: SY(1) = 0:SZ(1) = -40: SR(1) = 12:SC(1) = 5 ' big
2050 SX(2) = -3: SY(2) = 9:SZ(2) = -20: SR(2) = 4:SC(2) = 6 ' small
2100 '
2110 CLS 3
2120 '
2130 DIM RES(2), VXYZ(2), V(2), E(2), V0(2), P(2), N(2)
2140 '
2150 RES(0) = 128 ' x dots
2160 RES(1) = 80 ' y dots
2170 RES(2) = 4 ' dot size
2200 '
2210 VXYZ(0) = 16 ' Screen 幅 / 2
2220 VXYZ(1) = 10 ' Screen 高 / 2
2230 VXYZ(2) = 40 ' Screenから視点までの距離
2240 '
2250 GOSUB *RAY.TRACE
2260 END
4000 '----------------------------------------------------------------------
4010 ' 解像度RESのx,y(-1≦x,y≦1)方向視線で球をトレース
4020 ' RES(0),(1),(2)=x,yのドット数,ドットサイズ
4030 ' 球x,y,z,r,c=中心x,y,z,半径,色 x,y,z座標の正方向=右,上,後ろ
4040 '
4050 ' inp VXYZ,sx,sy,sz,sr,sc
4060 ' tmp x,y,ix,iy,iw,ih,iz,x0,y0,a,c,V0,r,b,d,t0,w,h,w1,h1,N,V0,P,N
4070 '----------------------------------------------------------------------
4080 *RAY.TRACE
4090 IW = RES(0): IH = RES(1): IZ = RES(2)
4100 X0 = (640 - IW*IZ) / 2: Y0 = (400 - IH*IZ) / 2
4110 LINE(X0 - 1, Y0 - 1)-STEP(IW*IZ + 1, IH*IZ + 1),7,B
4120 IW = IW - 1: IH = IH - 1
4130 FOR IY = 0 TO IH
4140 Y = 1 - 2 * IY / IH
4150 FOR IX = 0 TO IW
4160 X = 2 * IX / IW - 1
4170 GOSUB *RAY.VIEW
4180 GOSUB *DISTANCE
4190 IF T >= 0 THEN GOSUB *SHADE: GOSUB *DRAW
4200 NEXT
4210 NEXT
4220 RETURN
5000 '----------------------------------------------------------------------
5010 ' 視線と球の交点の色cl、陰影と陰(0≦b≦1)を求める
5020 '
5030 ' inp V,E,si,t
5040 ' out cl,b
5050 ' tmp a,c,b,w,h,w1,h1,N,V0,P,N,am,si,V,E,t1
5060 '----------------------------------------------------------------------
5070 *SHADE
5080 CL = SC(SI)
5090 IF SI = 0 THEN B = 1: RETURN ' light
5100 AM = 0.1 ' ambient
5110 V0(0) = V(0) - SX(SI)
5120 V0(1) = V(1) - SY(SI)
5130 V0(2) = V(2) - SZ(SI)
5140 P(0) = V0(0) + E(0) * T
5150 P(1) = V0(1) + E(1) * T
5160 P(2) = V0(2) + E(2) * T
5170 B = SQR(P(0)*P(0) + P(1)*P(1) + P(2)*P(2)) ' P = V0+Et
5180 IF B <> 0 THEN B = 1/B ELSE B = 0
5190 N(0) = P(0) * B
5200 N(1) = P(1) * B
5210 N(2) = P(2) * B ' N = P/|P|
5220 V(0) = P(0) + SX(SI)
5230 V(1) = P(1) + SY(SI)
5240 V(2) = P(2) + SZ(SI) ' V = P (元の座標)
5250 E(0) = SX(0) - V(0)
5260 E(1) = SY(0) - V(1)
5270 E(2) = SZ(0) - V(2)
5280 B = SQR(E(0)*E(0) + E(1)*E(1) + E(2)*E(2))
5290 T1 = B - SR(0) ' 光源表面までの距離
5300 IF B <> 0 THEN B = 1/B ELSE B = 0
5310 E(0) = E(0) * B
5320 E(1) = E(1) * B
5330 E(2) = E(2) * B ' E = L(光源方向)
5340 B = 1.0E-8 ' 少し
5350 T1 = T1 - B*2 ' 光源表面までより短く
5360 V(0) = V(0) + E(0) * B
5370 V(1) = V(1) + E(1) * B ' 点Pと重ならないように
5380 V(2) = V(2) + E(2) * B ' Vを少し光源に寄せる
5390 GOSUB *DISTANCE
5400 B = E(0)*N(0) + E(1)*N(1) + E(2)*N(2) ' b = L・N
5410 IF 0 < T AND T < T1 THEN B = 0 ' 陰
5420 IF B < AM THEN B = AM ' ambient
5430 RETURN
6000 '----------------------------------------------------------------------
6010 ' 点を描く
6020 '
6030 ' inp cl,b,x0,y0,ix,iy,iz
6040 ' tmp w,h,w1,h1
6050 '----------------------------------------------------------------------
6060 *DRAW
6070 FOR H=0 TO IZ-1
6080 H1 = IY*IZ + Y0 + H
6090 W1 = IX*IZ + X0
6100 FOR W=0 TO IZ-1
6110 IF RND(1)*0.99 < B THEN PSET(W1 + W, H1),CL
6120 NEXT
6130 NEXT
6140 RETURN
7000 '----------------------------------------------------------------------
7010 ' スクリーンVXYZからの視点位置ベクトルVと視線単位ベクトルEの生成
7020 ' VXYZ(0),(1),(2)=スクリーン幅/2,高/2,視点スクリーン間距離
7030 '
7040 ' V(0) = VXYZ(0)*x , V(1) = VXYZ(1)*y , V(2) = 0 (-1≦x,y≦1)
7050 ' E(0) = V(0)/|E| , E(1) = V(1)/|E| , E(2) = -VXYZ(2)/|E|
7060 '
7070 ' inp VXYZ,x,y
7080 ' out V,E
7090 ' tmp a
7100 '----------------------------------------------------------------------
7110 *RAY.VIEW
7120 V(0) = VXYZ(0) * X: V(1) = VXYZ(1) * Y: V(2) = 0
7130 E(0) = V(0) : E(1) = V(1) : E(2) = -VXYZ(2)
7140 A = SQR(E(0)*E(0) + E(1)*E(1) + E(2)*E(2))
7150 E(0) = E(0) / A : E(1) = E(1) / A : E(2) = E(2) / A
7160 RETURN
8000 '----------------------------------------------------------------------
8010 ' 視点位置ベクトルVから、視線単位ベクトルE方向の視線と
8020 ' 球との交点との距離tの内で一番近い前方のtと球番号siを求める
8030 '
8040 ' inp V,E,sx,sy,sz,sr,sc,sn
8050 ' out t,si
8060 ' tmp c,V0,r,b,d,t0
8070 '----------------------------------------------------------------------
8080 *DISTANCE
8090 T = -1: SI = -1
8100 FOR C=0 TO SN-1
8110 V0(0) = V(0) - SX(C):V0(1) = V(1) - SY(C):V0(2) = V(2) - SZ(C)
8120 R = SR(C) ' V0 = V - (sx(c),sy(c),sz(c)) , r = sr(c)
8130 GOSUB *DISTANCE.SPHERE ' t0 ← distance.sphere(V0, r)
8140 IF T0 >= 0 THEN IF T0 < T OR T < 0 THEN T = T0: SI = C
8150 NEXT
8160 RETURN
9000 '----------------------------------------------------------------------
9010 ' 視点位置ベクトルVから、視線単位ベクトルE方向の視線と
9020 ' 原点中心で半径rの球との交点までの距離tを求める
9030 '
9040 ' |P|=r … 球 (V+Et)^2=rr tt + 2(V・E)t + V・V - rr = 0
9050 ' P=V+Et … 視線 t = -(V・E)±sqr{(V・E)^2 - V・V + rr}
9060 '
9070 ' inp V0,E,r V0は球が原点の時のVの値
9080 ' out t0
9090 ' tmp b,d
9100 '----------------------------------------------------------------------
9110 *DISTANCE.SPHERE
9120 B = V0(0)* E(0)+V0(1)* E(1)+V0(2)* E(2) ' b = V・E
9130 D = V0(0)*V0(0)+V0(1)*V0(1)+V0(2)*V0(2)-R*R ' d = V・V - rr
9140 D = B*B - D ' d判別式
9150 IF D < 0 THEN T0 = -1:RETURN ' 交点なし
9160 D = SQR(D)
9170 T0 = -B-D ' 視線と球の近い方の交点距離
9180 IF T0 < 0 THEN T0 = -B+D ' 視線と球の遠い方の交点距離
9190 RETURN
0コメント