|
> No.758[元記事へ]
!次の問題が解けなかったが、
!「見え隠れする路面の裏側を、別な色で塗る方法」が、見つかった。
!------------
! ハイウェイ
!------------
!SET bitmap SIZE 671,671 !← 大きい画面にするとき。(1024x768 にぴったり)
DIM Mp(4,4) !視点からの被写体の相対座標(一点投影用)
DIM Xz(4,4),zY(4,4) !XY_Xz変換, XY_zY変換
DIM XYz(4,4) !XY平面のz平行移動
!
!※投影面の裏側に、操作対象が有るので、座標は左手系(Z軸が裏向き)です。
! 投影面を、車両前縁d に置き、Z=1.5 、視点 Z=0 が 手前。
! 視点 Z=0 を頂点に、投影面 Z=1.5 へ 一点投影。面中心から±1を画面とし、
! 外界面を、投影面 前方+150 から、投影面 Z=1.5 までを、奥から描く。
!-------------------------------------------------------------------------
! 一点投影用 Mp
!
!原画_行ベクトル Mp 表示_行ベクトル
! (X,Y,Z,1)|1 0 0 0| →(X+x,Y+y, * ,Z+z) の4列目 Z+z で縮小。
! |0 1 0 0| ↓
! |0 0 0 1| 座標 (X+x)/(Z+z),(Y+y)/(Z+z) の描点群。
! |x y 0 z| * 印は「最終的表示で無効」のz座標。
MAT READ Mp
DATA 1,0,0,0 !小文字 x y z は、視点から、道路左端の相対座標。
DATA 0,1,0,0
DATA 0,0,0,1 !変形指示 MAT 文で効果する。
DATA 0,0,0,0
!-------------------------------------------------------------------------
! 道路など、画面に垂直な広がりは、以下の Xz zY XYz 行列を、先に通します。
! 上の原画の Z は通常0ですが、以下の様に 変形を行なうと、発生します。
!-------------------------------------------------------------------------
!<路面>の原画用 Xz XY平面→ XZ平面として描く。
!
!原画_行ベクトル 新しい原画_行ベクトル
! (X,Y,0,1)|1 0 0 0| →(X+Y*dxdz, Y*dydz, Y, 1)
! |dxdz dydz 1 0|
! |0 0 0 0| dxdz: Z軸カーブの微分 dx/dz
! |0 0 0 1| dydz: Z軸ピッチの微分 dy/dz
MAT READ Xz
DATA 1,0,0,0
DATA 0,0,1,0
DATA 0,0,0,0
DATA 0,0,0,1
!-------------------------------------------------------------------------
!<建物>の原画用 zY XY平面→ ZY平面として描く。
!
!原画_行ベクトル 新しい原画_行ベクトル
! (X,Y,0,1)|dxdz 0 1 0| →(X*dxdz+x, Y, X, 1)
! |0 1 0 0|
! |0 0 0 0| dxdz: Z軸カーブの微分 dx/dz
! |x 0 0 1| x: ZY平面のx座標
MAT READ zY
DATA 0,0,1,0
DATA 0,1,0,0
DATA 0,0,0,0
DATA 0,0,0,1
!-------------------------------------------------------------------------
!<建物>の原画用 XYz XY平面の Z軸移動。
!
!原画_行ベクトル 新しい原画_行ベクトル
! (X,Y,0,1)|1 0 0 0| →(X+(dxdz)*z, Y, z, 1)
! |0 1 0 0|
! |0 0 0 0| dxdz: Z軸カーブの微分 dx/dz
! |(dxdz)*z 0 z 1| z: Z軸 移動差分
MAT READ XYz
DATA 1,0,0,0
DATA 0,1,0,0
DATA 0,0,0,0
DATA 0,0,0,1
!-------------------------------------------------------------------------
!
DEF yaw(z)= 10*SIN((z-2)*0.1) !カーブ、横の偏差 x(z)
DEF d_yaw(z)= COS((z-2)*0.1) !カーブ、微分係数 dx/dz
DEF pitch(z)= 5*SIN(z*0.1) !ピッチ、縦の偏差 y(z)
DEF d_pitch(z)= 0.5*COS(z*0.1) !ピッチ、微分係数 dy/dz
!
DEF v(t)=v0+a*t !速度
DEF I_v(t)=v0*t+a*t*t/2 !移動距離 ∫v(t)dt
!
LET v0=15 !初速度
LET a=-v0^2/2/100 !減速加速度, -v0^2/2/移動距離
!
LET Zs=1.5 !透視面のz座標( 視点 Z=0)
SET WINDOW -1,1,-1,1 !画面スケール±1
LET t0=TIME
DO
LET t1=TIME-t0
IF t1>tb+0.15 THEN
LET tb=t1
LET d=I_v(t) !車両前縁d のz座標
PRINT USING "時間=###.## 速度=###.## 走行距離=###.##":t,v(t),d
SET DRAW mode hidden !裏ページに書く
CALL Animation !描画
SET DRAW mode explicit !裏ページの表示
LET t=t+.15
END IF
MOUSE POLL msx,msy,mlb,mrb
LOOP UNTIL v(t)<=0 OR mrb=1
SUB Animation
!----sky
SET AREA COLOR 17
PLOT AREA:-1,0; 1,0; 1,1; -1,1
!----ground
SET AREA COLOR 42
PLOT AREA:-1,0; 1,0; 1,-1; -1,-1
!----guide message
SET TEXT COLOR 1
SET TEXT FONT "",11
PLOT TEXT,AT.35,.9:"右クリック保持 Stop"
SET TEXT COLOR 0
SET TEXT FONT "",90
!----
LET ss=5/2
FOR i=IP((d+150)/ss)*ss TO d STEP -ss
LET z=i-d+Zs !視点 Z=0 ~iのz座標。
LET Mp(4,1)= yaw(i)-yaw(d) -1.5 !投影面中心線から道路左端のx座標
LET Mp(4,2)=pitch(i)-pitch(d)-1.5 !投影面中心線から道路左端のy座標
LET Mp(4,4)= z
!----
! 1 ,0 ,0 ,0|
! 0 ,1 ,0 ,0|
! 0 ,0 ,0 ,1|
! yaw(i)-yaw(d)-1.5 ,pitch(i)-pitch(d)-1.5 ,0 ,z|
!----
IF MOD(i,10)=0 THEN
DRAW Building( 0-2,-9, -3,20,-2 ) WITH Mp !x,y, W,H,D
DRAW Building( 6+2,-9, -3,19, 2.5) WITH Mp !x,y, W,H,D
DRAW Sign WITH Mp
END IF
IF MOD(i,10)=5 THEN DRAW Tree WITH Mp
DRAW Road(-.993*ss) WITH Mp
NEXT i
END SUB
!パーツのサイズ。
!画面( z=投影面Zs 1.5:車両前縁d )で、表示倍率 1/z ( 実幅3→ 描画幅2)
!原画座標で、道路左端xyz( 0 , 0 ,1.5)= 画面左下角(-1,-1)
!原画座標で、左車線上xyz(1.5, 1.5 ,1.5)= 画面中心点( 0, 0) …投影中心
PICTURE Building(x,y,w,h,d1)
IF Zs-z<=w THEN
!---back plane
LET zY(1,1)=d_yaw(i+w/2) !Z軸カーブの微分 dx/dz
LET zY(4,1)=x+d1 !ZY平面のx座標
DRAW Wall((y),w,h) WITH zY
!---facade
LET zY(4,1)=x !ZY平面のx座標
DRAW Wall((y),w,h) WITH zY
!---side plane
LET XYz(4,1)=d_yaw(i+w/2)*w !Z軸カーブによるx移動差分
LET XYz(4,3)=w !Z軸 移動差分
DRAW Side(x,y,h,d1) WITH XYz
END IF
END PICTURE
!
PICTURE Wall(y,w,h)
SET AREA COLOR 8 !gray
PLOT AREA: 0,y; w,y; w,y+h; 0,y+h !(Z,Y)平面として描く。
FOR y=y+h-.5 TO y+1 STEP -2.5
PLOT LINES: 0,y; w,y !(Z,Y)平面として描く。
NEXT y
END PICTURE
!
PICTURE Side(x,y,h,d1)
SET AREA COLOR 16 !dark gray
PLOT AREA: x,y; x+d1,y; x+d1,y+h; x,y+h !移動前(X,Y)平面として描く。
END PICTURE
PICTURE Road(e)
IF e< Zs-z THEN LET e=Zs-z
LET Xz(2,1)=d_yaw(i+e/2) !Z軸カーブの微分 dx/dz
LET Xz(2,2)=d_pitch(i+e/2) !Z軸ピッチの微分 dy/dz
DRAW Surface(e) WITH Xz
END PICTURE
!
PICTURE Surface(e)
IF Mp(4,2)/z<=d_pitch(i+e/2) THEN
SET AREA COLOR 15
PLOT AREA: 0,0; 6,0; 6,e; 0,e !(X,Z)平面として描く。
!---center line
SET AREA COLOR 0
PLOT AREA: 2.9,0; 2.9,e; 3.1,e; 3.1,0 !(X,Z)平面として描く。
ELSE
!---back side
SET AREA COLOR 2
PLOT AREA: 0,0; 6,0; 6,e; 0,e !(X,Z)平面として描く。
END IF
!---joint line
PLOT LINES: 0 ,0; 2.9,0
PLOT LINES: 3.1,0; 6 ,0
END PICTURE
PICTURE Tree
SET AREA COLOR 12 !幹
PLOT AREA:-0.075,0; 0.075,0; 0.025,3;-0.025,3
SET AREA COLOR 10
FOR w=1 TO 7 !葉
DRAW disk WITH SCALE(0.3+0.05-RND*0.1)*SHIFT(0.4-RND*0.8, 2.7+0.325-RND*0.75)
NEXT W
END PICTURE
PICTURE Sign
IF MOD(i,50)=0 THEN SET AREA COLOR 2 ELSE SET AREA COLOR 4
PLOT AREA:-0.025,0; 0.025,0; 0.025,2;-0.025,2 !pole
DRAW disk WITH SCALE(0.5)*SHIFT(0,2) !plate
!PLOT TEXT,AT -.35,1.74,USING ">%%":STR$(i) !sign
CALL Plot_7segment(0 ,2 ,0.15 ,STR$(i)) !sign( PLOT TEXT が重い時)
END PICTURE
SUB Plot_7segment(x,y,s,i$) !文字列中心(x,y) 文字の横幅(s) 数字の文字列(i$)
SET LINE COLOR 0
SET LINE width 9/z !一点投影・縮小の補償。(線幅は MAT 文で縮まない)
LET w=LEN(i$)
LET s1=s ! y軸↑:s1=s y軸↓:s1=-s
LET s2=s/2
LET x=x-(w-1)*s2*1.6
FOR p=1 TO w
SELECT CASE VAL(i$(p:p))
CASE 0
PLOT LINES:x-s2,y+s;x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s
CASE 1
PLOT LINES:x,y-s;x,y+s
CASE 2
PLOT LINES:x-s2,y+s1;x+s2,y+s1;x+s2,y;x-s2,y;x-s2,y-s1;x+s2,y-s1
CASE 3
PLOT LINES:x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s
PLOT LINES:x-s2,y;x+s2,y
CASE 4
PLOT LINES:x-s2,y+s1;x-s2,y;x+s2,y
PLOT LINES:x+s2,y+s1;x+s2,y-s1
CASE 5
PLOT LINES:x+s2,y+s1;x-s2,y+s1;x-s2,y;x+s2,y;x+s2,y-s1;x-s2,y-s1
CASE 6
PLOT LINES:x+s2,y+s1;x-s2,y+s1;x-s2,y-s1;x+s2,y-s1;x+s2,y;x-s2,y
CASE 7
PLOT LINES:x-s2,y+s1;x+s2,y+s1;x+s2,y-s1
CASE 8
PLOT LINES:x-s2,y;x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s;x-s2,y;x+s2,y
CASE 9
PLOT LINES:x+s2,y;x-s2,y;x-s2,y+s1;x+s2,y+s1;x+s2,y-s1;x-s2,y-s1
CASE ELSE
END SELECT
LET x=x+s*1.6
NEXT p
SET LINE width 1
SET LINE COLOR 1
END SUB
END
|
|