|
> No.3386[元記事へ]
lark12_longさんへのお返事です。
> 立方体の原始データbx()は初期状態を維持したまま、
> 回転処理は、表示のみにしたいと思い、
座標変換 (x',y',z',w')=(x,y,z,w)M[1]M[2]M[3] … M[n] より、
前回の場合
1回目の操作 (x',y',z',w')=(x,y,z,w) M[1]
2回目の操作 (x",y",z",w")=(x',y',z',w') M[2]=( (x,y,z,w) M[1] ) M[2]
3回目の操作 (x"',y"',z"',w"')=(x",y",z",w") M[3]=( ( (x,y,z,w) M[1] ) M[2] ) M[3]
:
累積するのは、変換された図形の座標とする。
今回の場合
1回目の操作 (x',y',z',w')=(x,y,z,w) M[1]
2回目の操作 (x',y',z',w')=(x,y,z,w) ( M[1..2] )=(x,y,z,w) ( M[1] M[2] )
3回目の操作 (x',y',z',w')=(x,y,z,w) ( M[1..3] )=(x,y,z,w) ( M[1] M[2] M[3] )
:
n回目の操作 (x',y',z',w')=(x,y,z,w)( ( ( ( M[1] M[2] ) M[3] ) … ) M[n] )
累積するのは、変換行列とする。
SET WINDOW -3,3,-3,3 !表示領域
DIM AX(3,4) !XYZ軸の形をした図形(3本の方向ベクトル、3本の矢)
DATA 1,0,0 !X
DATA 0,1,0 !Y
DATA 0,0,1 !Z
FOR i=1 TO 3
FOR J=1 TO 3
READ AX(i,J) !x,y,z
LET AX(i,4)=1 !w
NEXT J
NEXT i
DIM BX(8,4) !立方体の8頂点
DATA -1,-1, 1 !上面
DATA 1,-1, 1
DATA 1, 1, 1
DATA -1, 1, 1
DATA -1,-1,-1 !下面
DATA 1,-1,-1
DATA 1, 1,-1
DATA -1, 1,-1
FOR i=1 TO 8
FOR J=1 TO 3
READ BX(i,J) !x,y,z
LET BX(i,4)=1 !w
NEXT J
NEXT i
DIM T(50,4) !(x',y',z',w')=(x,y,z,w)M による座標変換
DIM MA(4,4),MB(4,4), M(4,4)
MAT MA=IDN !図形Aに対する累積された変換
MAT MB=IDN !図形Bに対する累積された変換
DATA "+RX","-RX","+RY","-RY","+RZ","-RZ" !ボタン
DATA "+TX","-TX","+TY","-TY","+TZ","-TZ" !ボタン
DIM BTN1$(6),BTN2$(6)
MAT READ BTN1$
MAT READ BTN2$
DO
SET DRAW mode hidden !ちらつき防止(開始)
CLEAR
MAT T=AX*MA !軸の傾き
CALL button(-2.8,2.8, 0.6,0.3, 6, BTN1$, S,S2) !回転メニュー
SELECT CASE S
CASE 1 !+x
CALL D3ROTATE(RAD(5),T(1,1),T(1,2),T(1,3), M) !5度ずつ
CASE 2 !-x
CALL D3ROTATE(RAD(-5),T(1,1),T(1,2),T(1,3), M)
CASE 3 !+y
CALL D3ROTATE(RAD(5),T(2,1),T(2,2),T(2,3), M)
CASE 4 !-y
CALL D3ROTATE(RAD(-5),T(2,1),T(2,2),T(2,3), M)
CASE 5 !+z
CALL D3ROTATE(RAD(5),T(3,1),T(3,2),T(3,3), M)
CASE 6 !-z
CALL D3ROTATE(RAD(-5),T(3,1),T(3,2),T(3,3), M)
CASE ELSE
MAT M=IDN
END SELECT
MAT MB=MB*M
IF S2=2 THEN !左ボタン押下で軸も回転させる
MAT MA=MA*M
END IF
CALL button(-2.0,0.0, 0.6,0.3, 6, BTN2$, S,S2) !図形の平行移動メニュー
SELECT CASE S
CASE 1 !+x
CALL VEC3NORMALIZE(T(1,1),T(1,2),T(1,3), xx,yy,zz) !方向ベクトル
CASE 2 !-x
CALL VEC3NORMALIZE(-T(1,1),-T(1,2),-T(1,3), xx,yy,zz)
CASE 3 !+y
CALL VEC3NORMALIZE(T(2,1),T(2,2),T(2,3), xx,yy,zz)
CASE 4 !-y
CALL VEC3NORMALIZE(-T(2,1),-T(2,2),-T(2,3), xx,yy,zz)
CASE 5 !+z
CALL VEC3NORMALIZE(T(3,1),T(3,2),T(3,3), xx,yy,zz)
CASE 6 !-z
CALL VEC3NORMALIZE(-T(3,1),-t(3,2),-T(3,3), xx,yy,zz)
CASE ELSE
LET xx=0
LET yy=0
LET zz=0
END SELECT
CALL D3SHIFT(xx*0.05,yy*0.05,zz*0.05, M) !0.05ずつ
MAT MB=MB*M
!XYZ軸を描く
! ワールド座標(x,y,z) → スクリーン座標(x,y)
! Y
! ↑
! Z→X
! のXY平面(スクリーン座標)へ投影する。
MAT T=AX*MA !図形を回転させる
SET LINE COLOR 4 !X軸
PLOT LINES: 0,0; T(1,1),T(1,2)
PLOT TEXT, AT T(1,1),T(1,2): "x"
SET LINE COLOR 3 !Y軸
PLOT LINES: 0,0; T(2,1),T(2,2)
PLOT TEXT, AT T(2,1),T(2,2): "y"
SET LINE COLOR 2 !Z軸
PLOT LINES: 0,0; T(3,1),T(3,2)
PLOT TEXT, AT T(3,1),T(3,2): "z"
!立方体を描く
MAT T=BX*MB !図形を回転させる
SET LINE COLOR 1
FOR i=1 TO 3 !上面
PLOT LINES: T(i,1),T(i,2); T(i+1,1),T(i+1,2)
NEXT i
PLOT LINES: T(4,1),T(4,2); T(1,1),T(1,2)
FOR i=1 TO 4 !側面の稜線
PLOT LINES: T(i,1),T(i,2); T(i+4,1),T(i+4,2)
NEXT i
FOR i=5 TO 7 !下面
PLOT LINES: T(i,1),T(i,2); T(i+1,1),T(i+1,2)
NEXT i
PLOT LINES: T(8,1),T(8,2); T(5,1),T(5,2)
SET DRAW mode explicit !ちらつき防止(終了)
WAIT DELAY 0.1
LOOP
SUB button(x,y, dx,dy, n, btn$(), s,s2) !左上位置(x,y)、大きさdx,dy、n個のボタン
mouse poll mx,my,left,right !マウスポインタの状態を得る
LET s2=left*2+right !0:なし、1:右、2:左、3:左右
LET s=-1 !マウスポインタが、どのボタンと重なっているか
LET x1=x !左上
LET y1=y
FOR k=1 TO n !タイル貼り
LET x2=x1+dx !右下
LET y2=y1-dy
IF (mx>=MIN(x1,x2) AND mx<=MAX(x1,x2)) AND (my>=MIN(y1,y2) AND my<=MAX(y1,y2)) THEN
LET s=k !k番目のボタン内なら
END IF
PLOT LINES: x1,y1; x2,y1 !枠を描く
PLOT LINES: x2,y1; x2,y2
PLOT LINES: x2,y2; x1,y2
PLOT LINES: x1,y2; x1,y1
PLOT TEXT ,AT x1+dx/5,y1-4*dy/5: btn$(k) !名前 ※調整が必要
LET y1=y2 !次へ
NEXT k
!!!PRINT s !debug
END SUB
END
EXTERNAL SUB VEC3NORMALIZE(Vx,Vy,Vz, x,y,z) !単位ベクトルへ正規化する
LET l=SQR(Vx*Vx+Vy*Vy+Vz*Vz)
IF l<>0 THEN
LET x=Vx/l
LET y=Vy/l
LET z=Vz/l
END IF
END SUB
EXTERNAL SUB D3ROTATE(a,Vx,Vy,Vz, M(,)) !任意軸(位置ベクトル(Vx,Vy,Vz) )まわりの回転
CALL VEC3NORMALIZE(Vx,Vy,Vz, x,y,z)
LET c=COS(a)
LET s=SIN(a)
MAT M=ZER
LET M(1,1)=x*x*(1-c)+c
LET M(1,2)=x*y*(1-c)+z*s
LET M(1,3)=z*x*(1-c)-y*s
LET M(2,1)=x*y*(1-c)-z*s
LET M(2,2)=y*y*(1-c)+c
LET M(2,3)=y*z*(1-c)+x*s
LET M(3,1)=z*x*(1-c)+y*s
LET M(3,2)=y*z*(1-c)-x*s
LET M(3,3)=z*z*(1-c)+c
LET M(4,4)=1
END SUB
EXTERNAL SUB D3SCALE(a,b,c, M(,)) !拡大・縮小
MAT M=IDN
LET M(1,1)=a
LET M(2,2)=b
LET M(3,3)=c
END SUB
EXTERNAL SUB D3SHIFT(l,m,n, A(,)) !平行移動
MAT A=IDN
LET A(4,1)=l
LET A(4,2)=m
LET A(4,3)=n
END SUB
前回 ※サブルーチン部分は省略
SET WINDOW -3,3,-3,3 !表示領域
DIM AX(3,4) !XYZ軸の形をした図形(3本の方向ベクトル、3本の矢)
DATA 1,0,0 !X
DATA 0,1,0 !Y
DATA 0,0,1 !Z
FOR i=1 TO 3
FOR J=1 TO 3
READ AX(i,J) !x,y,z
LET AX(i,4)=1 !w
NEXT J
NEXT i
DIM BX(8,4) !立方体の8頂点
DATA -1,-1, 1 !上面
DATA 1,-1, 1
DATA 1, 1, 1
DATA -1, 1, 1
DATA -1,-1,-1 !下面
DATA 1,-1,-1
DATA 1, 1,-1
DATA -1, 1,-1
FOR i=1 TO 8
FOR J=1 TO 3
READ BX(i,J) !x,y,z
LET BX(i,4)=1 !w
NEXT J
NEXT i
DIM T(50,4) !(x',y',z',w')=(x,y,z,w)M による座標変換
DIM M(4,4)
DATA "+RX","-RX","+RY","-RY","+RZ","-RZ" !ボタン
DATA "+TX","-TX","+TY","-TY","+TZ","-TZ" !ボタン
DIM BTN1$(6),BTN2$(6)
MAT READ BTN1$
MAT READ BTN2$
DO
SET DRAW mode hidden !ちらつき防止(開始)
CLEAR
CALL button(-2.8,2.8, 0.6,0.3, 6, BTN1$, S,S2) !回転メニュー
SELECT CASE S
CASE 1 !+x
CALL D3ROTATE(RAD(5),AX(1,1),AX(1,2),AX(1,3), M) !5度ずつ
CASE 2 !-x
CALL D3ROTATE(RAD(-5),AX(1,1),AX(1,2),AX(1,3), M)
CASE 3 !+y
CALL D3ROTATE(RAD(5),AX(2,1),AX(2,2),AX(2,3), M)
CASE 4 !-y
CALL D3ROTATE(RAD(-5),AX(2,1),AX(2,2),AX(2,3), M)
CASE 5 !+z
CALL D3ROTATE(RAD(5),AX(3,1),AX(3,2),AX(3,3), M)
CASE 6 !-z
CALL D3ROTATE(RAD(-5),AX(3,1),AX(3,2),AX(3,3), M)
CASE ELSE
MAT M=IDN
END SELECT
MAT T=BX*M !図形を回転させる
MAT BX=T
IF S2=2 THEN !左ボタン押下で軸も回転させる
MAT T=AX*M
MAT AX=T
END IF
CALL button(-2.0,0.0, 0.6,0.3, 6, BTN2$, S,S2) !図形の平行移動メニュー
SELECT CASE S
CASE 1 !+x
CALL VEC3NORMALIZE(AX(1,1),AX(1,2),AX(1,3), xx,yy,zz) !方向ベクトル
CASE 2 !-x
CALL VEC3NORMALIZE(-AX(1,1),-AX(1,2),-AX(1,3), xx,yy,zz)
CASE 3 !+y
CALL VEC3NORMALIZE(AX(2,1),AX(2,2),AX(2,3), xx,yy,zz)
CASE 4 !-y
CALL VEC3NORMALIZE(-AX(2,1),-AX(2,2),-AX(2,3), xx,yy,zz)
CASE 5 !+z
CALL VEC3NORMALIZE(AX(3,1),AX(3,2),AX(3,3), xx,yy,zz)
CASE 6 !-z
CALL VEC3NORMALIZE(-AX(3,1),-AX(3,2),-AX(3,3), xx,yy,zz)
CASE ELSE
LET xx=0
LET yy=0
LET zz=0
END SELECT
CALL D3SHIFT(xx*0.05,yy*0.05,zz*0.05, M) !0.05ずつ
MAT T=BX*M
MAT BX=T
!XYZ軸を描く
! ワールド座標(x,y,z) → スクリーン座標(x,y)
! Y
! ↑
! Z→X
! のXY平面(スクリーン座標)へ投影する。
SET LINE COLOR 4 !X軸
PLOT LINES: 0,0; AX(1,1),AX(1,2)
PLOT TEXT, AT AX(1,1),AX(1,2): "x"
SET LINE COLOR 3 !Y軸
PLOT LINES: 0,0; AX(2,1),AX(2,2)
PLOT TEXT, AT AX(2,1),AX(2,2): "y"
SET LINE COLOR 2 !Z軸
PLOT LINES: 0,0; AX(3,1),AX(3,2)
PLOT TEXT, AT AX(3,1),AX(3,2): "z"
!立方体を描く
SET LINE COLOR 1
FOR i=1 TO 3 !上面
PLOT LINES: BX(i,1),BX(i,2); BX(i+1,1),BX(i+1,2)
NEXT i
PLOT LINES: BX(4,1),BX(4,2); BX(1,1),BX(1,2)
FOR i=1 TO 4 !側面の稜線
PLOT LINES: BX(i,1),BX(i,2); BX(i+4,1),BX(i+4,2)
NEXT i
FOR i=5 TO 7 !下面
PLOT LINES: BX(i,1),BX(i,2); BX(i+1,1),BX(i+1,2)
NEXT i
PLOT LINES: BX(8,1),BX(8,2); BX(5,1),BX(5,2)
SET DRAW mode explicit !ちらつき防止(終了)
WAIT DELAY 0.1
LOOP
:(以下省略)
:
|
|