3D回転処理に付いて

 投稿者:lark12_long  投稿日:2014年 5月24日(土)08時59分45秒
  山中和義様

2014年 5月 9日(金)20時39分8秒
に、山中和義様より、Re: 3D回転処理として、
プログラム事例を提供して頂きました

提供頂いたプログラムでは、立方体の頂点座標xyz値を、
bx(i,1)、bx(i,2)、bx(i,3)に格納し、
回転処理結果も、bx(i,1)、bx(i,2)、bx(i,3)に
更新された値が格納されます

立方体の原始データbx()は初期状態を維持したまま、
回転処理は、表示のみにしたいと思い、立方体の表示データとして
bxw()設け、色々試してみたのですが、
うまく行かず、メゲています

方法を教示頂きたく思います

lark12_long




 

Re: 3D回転処理に付いて

 投稿者:山中和義  投稿日:2014年 5月24日(土)10時45分19秒
  > 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


  :(以下省略)
  :

 

3D回転処理に付いて

 投稿者:lark12_long  投稿日:2014年 5月26日(月)19時06分9秒
  山中和義様

早速プログラム提供頂き有難う御座いました

原始データを、弄ることなく表示のみが、
回転できる為、原始データの物理的関係は、
維持されるので、動作シミュレーションも
正しく実行できる様になりました

土星の膠着円盤もどきのシミュレーションを
行ってみました

lark12_long
 

戻る