|
> No.3375[元記事へ]
lark12_longさんへのお返事です。
> どなたか、スマートなプログラム事例を、示して頂けると、嬉しいです
XYZ軸の形をした図形をワールド座標の原点で回転させて、
その図形をもとに、「任意軸での回転」と「方向ベクトルに沿う移動」で立方体の位置を求めています。
SET WINDOW -3,3,-3,3 !表示領域
DIM AX(3,4) !XYZ軸の形をした図形
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(8,4) !(x',y',z')
DIM M(4,4)
DATA "+X","-X","+Y","-Y","+Z","-Z" !ボタン
DIM BTN$(6)
MAT READ BTN$
DO
SET DRAW mode hidden !ちらつき防止(開始)
CLEAR
CALL button(-2.8,2.8, 0.6,0.3, 6, BTN$,S) !軸の回転メニュー
SELECT CASE S
CASE 0 !+x
CALL D3ROTATE(RAD(5),AX(1,1),AX(1,2),AX(1,3), M) !5度ずつ
CASE 1 !-x
CALL D3ROTATE(RAD(-5),AX(1,1),AX(1,2),AX(1,3), M)
CASE 2 !+y
CALL D3ROTATE(RAD(5),AX(2,1),AX(2,2),AX(2,3), M)
CASE 3 !-y
CALL D3ROTATE(RAD(-5),AX(2,1),AX(2,2),AX(2,3), M)
CASE 4 !+z
CALL D3ROTATE(RAD(5),AX(3,1),AX(3,2),AX(3,3), M)
CASE 5 !-z
CALL D3ROTATE(RAD(-5),AX(3,1),AX(3,2),AX(3,3), M)
CASE ELSE
MAT M=IDN
END SELECT
MAT T=AX*M
MAT AX=T
MAT T=BX*M
MAT BX=T
CALL button(-2.0,2.8, 0.6,0.3, 6, BTN$,S) !図形の回転メニュー
SELECT CASE S
CASE 0 !+x
CALL D3ROTATE(RAD(5),AX(1,1),AX(1,2),AX(1,3), M) !5度ずつ
CASE 1 !-x
CALL D3ROTATE(RAD(-5),AX(1,1),AX(1,2),AX(1,3), M)
CASE 2 !+y
CALL D3ROTATE(RAD(5),AX(2,1),AX(2,2),AX(2,3), M)
CASE 3 !-y
CALL D3ROTATE(RAD(-5),AX(2,1),AX(2,2),AX(2,3), M)
CASE 4 !+z
CALL D3ROTATE(RAD(5),AX(3,1),AX(3,2),AX(3,3), M)
CASE 5 !-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
CALL button(-2.0,0.0, 0.6,0.3, 6, BTN$,S) !図形の平行移動メニュー
SELECT CASE S
CASE 0 !+x
CALL VEC3NORMALIZE(AX(1,1),AX(1,2),AX(1,3), xx,yy,zz) !方向ベクトル
CASE 1 !-x
CALL VEC3NORMALIZE(-AX(1,1),-AX(1,2),-AX(1,3), xx,yy,zz)
CASE 2 !+y
CALL VEC3NORMALIZE(AX(2,1),AX(2,2),AX(2,3), xx,yy,zz)
CASE 3 !-y
CALL VEC3NORMALIZE(-AX(2,1),-AX(2,2),-AX(2,3), xx,yy,zz)
CASE 4 !+z
CALL VEC3NORMALIZE(AX(3,1),AX(3,2),AX(3,3), xx,yy,zz)
CASE 5 !-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: AX(1,1),AX(1,2); 0,0
PLOT TEXT, AT AX(1,1),AX(1,2): "x"
SET LINE COLOR 3 !Y軸
PLOT LINES: AX(2,1),AX(2,2); 0,0
PLOT TEXT, AT AX(2,1),AX(2,2): "y"
SET LINE COLOR 2 !Z軸
PLOT LINES: AX(3,1),AX(3,2); 0,0
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
SUB button(x,y, dx,dy, n, btn$(),s) !左上位置(x,y)、大きさdx,dy、n個のボタン
LET xx=x
LET yy=y
FOR i=1 TO n
PLOT LINES: xx,yy; xx+dx,yy !枠を描く
PLOT LINES: xx+dx,yy; xx+dx,yy-dy
PLOT LINES: xx+dx,yy-dy; xx,yy-dy
PLOT LINES: xx,yy-dy; xx,yy
PLOT TEXT ,AT xx+dx/3,yy-4*dy/5: btn$(i) !名前 ※調整が必要
LET yy=yy-dy
NEXT i
mouse poll mx,my,left,right !マウスポインタの位置を得る
LET s=-1
FOR K=0 TO 6-1
IF ABS(mx-(x+dx/2))<dx/2 AND ABS(my-((y-dy*K)-dy/2))<dy/2 THEN LET s=K !k番目のボタン内なら
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
|
|