HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
0214
Humi立方体(hgimg3)10解決


Humi

リンク

2014/2/14(Fri) 11:30:54|NO.59939

XとYがなんかうまくいきません。
どこで方向を間違えたのでしょうか。。。
誰か"直し方"を教えてください。。

'X', 'Y', 'Z' で回転を決定、2度同じのを押すと変更
Enter or 左click で回転
方向キー でカメラ移動
Ctrl+方向キー上下 で拡大縮小


#include "hgimg3.as" //回転処理(2次元) #module #deffunc rot var a,var b,double t c= cos(t)*a - sin(t)*b d= sin(t)*a + cos(t)*b a=c b=d return #global //ローカル座標からワールド座標への変換 #module #deffunc local2world array position, array euler rot position(2), position(1), euler(0) rot position(2), position(0), euler(1) rot position(1), position(0), euler(2) return #global #module #deffunc xrot int objid, array position, double t selpos objid objgetfv position rot position.0, position.1, t selpos objid objsetfv position return #deffunc yrot int objid, array position, double t selpos objid objgetfv position rot position.1, position.2, t selpos objid objsetfv position return #deffunc zrot int objid, array position, double t selpos objid objgetfv position rot position.2, position.0, t selpos objid objsetfv position return #global #module __CUBECORE__ #deffunc wherecube array body, int maxID, array position repeat maxID selpos body.cnt objgetfv position xid = 1+position.0/9.0 yid = 1+position.1/9.0 zid = 1+position.2/9.0 cube@(9*zid + 3*yid + xid) = cnt loop return #deffunc wherecentercube for i, 0, 9, 1 repeat 6 if tbody(i) == cbody(cnt) :center = i :break loop if center != -1 :_break next return #define global cuberot(%1, %2, %3, %4=-1, %5=-1, %6=-1) cuberot__ %1, %2, %3, %4, %5, %6 #deffunc cuberot__ array body, int frotmax, array position, int xline, int yline, int zline if frot :return if xline == -1 && yline == -1 && zline == -1 :return dim tbody, 9 :bodycnt = 0 :center = -1 cbody = 4, 10, 12, 14, 16, 22 // is center cube when cube version 3x3 for j, 0, 3, 1 :for i, 0, 3, 1 :repeat 3 if j == zline { id = 9*j +3*i +cnt tbody(bodycnt) = cube@(id) bodycnt++ } if i == yline { id = 9*j +3*i +cnt tbody(bodycnt) = cube@(id) bodycnt++ } if cnt == xline { id = 9*j +3*i +cnt tbody(bodycnt) = cube@(id) bodycnt++ } loop :next :next wherecentercube selpos body.center objgetfv position xcen = position.0 ycen = position.1 zcen = position.2 if zline != -1 :way = 3 if yline != -1 :way = 2 if xline != -1 :way = 1 frot = frotmax add = M_PI/2.0 / double(frotmax) return way #deffunc cube90rot array body, int frotmax, array position if frot == 0 :return // sin( PI*2 / 周期 * Count ) * 振幅 repeat 9 addrot = sin(M_PI*2.0 / double(frotmax) * double(frotmax-frot-frotmax/5)) * add + add if way == 3 { xrot body(tbody(cnt)), position, addrot addang body(tbody(cnt)),,, -addrot } if way == 2 { zrot body(tbody(cnt)), position, addrot addang body(tbody(cnt)),, addrot } if way == 1 { yrot body(tbody(cnt)), position, addrot addang body(tbody(cnt)), -addrot } loop frot-- return frot #global #module // set2ary3 position, 0, 0, 5.0, 0.0, 0.0 #deffunc set2ary3 array ary, int iBegin, int iBegin2, double p1, double p2, double p3 ary(iBegin, iBegin2) = p1 ary(iBegin, iBegin2+1) = p2 ary(iBegin, iBegin2+2) = p3 return #deffunc addary3 array ary, int iBegin, double p1, double p2, double p3 ary(iBegin) += p1 ary(iBegin+1) += p2 ary(iBegin+2) += p3 return #deffunc subary3 array ary, int iBegin, double p1, double p2, double p3 ary(iBegin) -= p1 ary(iBegin+1) -= p2 ary(iBegin+2) -= p3 return #global rBox = 9.0 // 半径 xBox = 3.0 // x個数 yBox = 3.0 // y個数 zBox = 3.0 // z個数 aBox = xBox*yBox // 一面個数 aaBox = aBox*zBox // 全体個数 mBox = 0.2 // 隙間 0.3 pmBox = 0.5 // 板間 pbmBox = M_PI/(2.0*rBox) center = int(aBox+xBox+1) camang = 0.0, 0.0, 0.0, 50.0 // x, y, z, 距離 frotmax = 20 // 回転周期 frot = 0 dim cube, aaBox // 位置記憶用 dim bTop, aBox dim bLeft, aBox dim bRight, aBox dim bBottom, aBox dim bFront, aBox dim bBack, aBox ddim euler, 3 ddim position, 6, 3 ddim position_, 3 ddim addeuler, 6, 3 screen 0, 320, 320 title "Cube" hgini // 貼り付ける板 // 上面 setcolor 255, 255, 255 addbox white_plate, 0.2, rBox-pmBox repeat aBox :regobj bTop(cnt), white_plate :loop // 右面 setcolor 255, 255, 0 addbox yellow_plate, 0.2, rBox-pmBox repeat aBox :regobj bRight(cnt), yellow_plate :loop // 正面 setcolor 255, 128, 0 addbox orange_plate, 0.2, rBox-pmBox repeat aBox :regobj bFront(cnt), orange_plate :loop // 左面 setcolor 44, 175, 44 addbox green_plate, 0.2, rBox-pmBox repeat aBox :regobj bLeft(cnt), green_plate :loop // 下面 setcolor 44, 44, 175 addbox blue_plate, 0.2, rBox-pmBox repeat aBox :regobj bBottom(cnt), blue_plate :loop // 裏面 setcolor 255, 0, 0 addbox red_plate, 0.2, rBox-pmBox repeat aBox :regobj bBack(cnt), red_plate :loop // 貼り付けられる本体 setcolor 30, 30, 30 addbox box, rBox, rBox setcolor 255, 255, 255 addbox cenBox, rBox, rBox for j, 0, 3, 1 :for i, 0, 3, 1 :repeat 3 id = 9*j +3*i +cnt if id == center { regobj body(id), cenBox }else : regobj body(id), box r = rBox+mBox position = double(cnt-(3/2))*r, double(i-(3/2))*r, double(j-(3/2))*r setpos body(id), position.0, position.1, position.2 loop :next :next /* xyz lines * addline m_x_line,, 0xFF0000 addline m_y_line,, 0x00FF00 addline m_z_line,, 0x0000FF regobj x_line, m_x_line regobj y_line, m_y_line regobj z_line, m_z_line setpos x_line, 0.0, 0.0, 0.0 setpos y_line, 0.0, 0.0, 0.0 setpos z_line, 0.0, 0.0, 0.0 setwork x_line, 100.0, 0.0, 0.0 setwork y_line, 0.0, 100.0, 0.0 setwork z_line, 0.0, 0.0, 100.0 /**/ // ライト // reglight light // setscale light, 255, 255, 255 // setang light, -M_PI/4.0 // objlight body.0, light // カメラ cammode CAM_MODE_LOOKAT camang = -45.0, -45.0, -45.0 // 初回処理 gosub *calcplate gosub *setcamerapos gosub *setlightpos hgdraw hgsync 20 wherecube body, aaBox, position *main clscolor $FFFFFF if frot :cube90rot body, frotmax, position :if stat == 0 :frot = 0 getkey ky, 'Z' :if ky :fzky = 1 :else { if active != 3 :zcolumn = -1 if fzky { fzky = 0 zcolumn = zcolumned if active == 3 :zcolumn = (zcolumn+1)\3 :else :active = 3 zcolumned = zcolumn title "Z : "+zcolumn } } getkey ky, 'Y' :if ky :fyky = 1 :else { if active != 2 :ycolumn = -1 if fyky { fyky = 0 ycolumn = ycolumned if active == 2 :ycolumn = (ycolumn+1)\3 :else :active = 2 ycolumned = ycolumn title "Y : "+ycolumn } } getkey ky, 'X' :if ky :fxky = 1 :else { if active != 1 :xcolumn = -1 if fxky { fxky = 0 xcolumn = xcolumned if active == 1 :xcolumn = (xcolumn+1)\3 :else :active = 1 xcolumned = xcolumn title "X : "+xcolumn } } stick@hsp ky, 15+64+16+256 if frot == 0 :if ky & 288 { title "clicked "+xcolumn+" : "+ycolumn+" : "+zcolumn wherecube body, aaBox, position cuberot body, frotmax, position, xcolumn, ycolumn, zcolumn :frot = stat } /* 適当に回転 * addang body.0, 0, 0, 0.005 // debo addang body.2, 0, 0, 0.005 // debo addang body.18, 0, 0, 0.005 // debo addang body.20, 0, 0, 0.005 // debo addang body.6, 0, 0, 0.005 // debo addang body.8, 0, 0, 0.005 // debo addang body.24, 0, 0, 0.005 // debo addang body.26, 0, 0, 0.005 // debo /**/ gosub *calcplate // カメラ位置移動 if ky & 15 { if ky & 64 { if ky & 2 :camang.3 -= 2.0 if ky & 8 :camang.3 += 2.0 }else :if ky & 16 { if ky & 1 :adddir HGOBJ_CAMERA, 1.0 if ky & 4 :adddir HGOBJ_CAMERA, -1.0 if ky & 2 :adddir HGOBJ_CAMERA,, -1.0 if ky & 8 :adddir HGOBJ_CAMERA,, 1.0 }else { if ky & 1 :camang.0 += 2.0 if ky & 4 :camang.0 -= 2.0 if ky & 2 :camang.1 -= 2.0 if ky & 8 :camang.1 += 2.0 } gosub *setcamerapos gosub *setlightpos } hgdraw hgsync 20 goto *main *calcplate bTopMax = 0 bRightMax = 0 bFrontMax = 0 bLeftMax = 0 bBottomMax = 0 bBackMax = 0 for j, 0, 3, 1 :for i, 0, 3, 1 :repeat 3 id = 9*j +3*i +cnt plateMax = 0 gosub *platefix if plateMax == 0 :continue // 回転角取得 selang body.id objgetfv euler repeat plateMax // 回転角取得 selang body.id objgetfv euler selang plateID.cnt addary3 euler, 0, addeuler(cnt, 0), addeuler(cnt, 1), addeuler(cnt, 2) objsetfv euler // 座標変換(local → world) position_ = position(cnt, 0), position(cnt, 1), position(cnt, 2) local2world position_, euler // body別に位置設定 position(cnt, 0) = position_.0 position(cnt, 1) = position_.1 position(cnt, 2) = position_.2 selpos body.id objgetfv position_ addary3 position_, 0, position(cnt, 0), position(cnt, 1), position(cnt, 2) selpos plateID.cnt objsetfv position_ // subary3 euler, 0, addeuler(cnt, 0), addeuler(cnt, 1), addeuler(cnt, 2) loop loop :next :next return *platefix if i == 0 {// 上面 plateID.plateMax = bTop.bTopMax // set2ary3 position, plateMax, 0, rBox/4.0+pbmBox, -rBox/4.0-pbmBox, 0.0 set2ary3 position, plateMax, 0, rBox/2.0+pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, 0.0, M_PI/2.0 bTopMax++ plateMax++ } if j == 0 {// 右面 plateID.plateMax = bRight.bRightMax // set2ary3 position, plateMax, 0, rBox/4.0+pbmBox, 0.0, -rBox/4.0-pbmBox set2ary3 position, plateMax, 0, rBox/2.0+pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, M_PI/2.0, 0.0 bRightMax++ plateMax++ } if cnt == 2 {// 正面 plateID.plateMax = bFront.bFrontMax // set2ary3 position, plateMax, 0, rBox/4.0+pbmBox, 0.0, 0.0 set2ary3 position, plateMax, 0, rBox/2.0+pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, 0.0, 0.0 bFrontMax++ plateMax++ } if j == 2 {// 左面 plateID.plateMax = bLeft.bLeftMax // set2ary3 position, plateMax, 0, -rBox/4.0-pbmBox, 0.0, rBox/4.0+pbmBox set2ary3 position, plateMax, 0, -rBox/2.0-pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, M_PI/2.0, 0.0 bLeftMax++ plateMax++ } if i == 2 {// 下面 plateID.plateMax = bBottom.bBottomMax // set2ary3 position, plateMax, 0, -rBox/4.0-pbmBox, rBox/4.0+pbmBox, 0.0 set2ary3 position, plateMax, 0, -rBox/2.0-pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, 0.0, M_PI/2.0 bBottomMax++ plateMax++ } if cnt == 0 {// 裏面 plateID.plateMax = bBack.bBackMax // set2ary3 position, plateMax, 0, -rBox/4.0-pbmBox, 0.0, 0.0 set2ary3 position, plateMax, 0, -rBox/2.0-pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, 0.0, 0.0 bBackMax++ plateMax++ } return *setcamerapos position.0 = cos(M_PI/180.0*camang.0)*camang.3 position.1 = sin(M_PI/180.0*camang.1)*camang.3 position.2 = sin(M_PI/180.0*camang.0)*camang.3 selpos HGOBJ_CAMERA objsetfv position return *setlightpos // カメラとライトを同じ位置・角度に設定 selpos HGOBJ_CAMERA objgetfv position selpos HGOBJ_LIGHT objsetfv position selang HGOBJ_CAMERA objgetfv euler selang HGOBJ_LIGHT objsetfv euler return



この記事に返信する


ソイスープ

リンク

2014/2/15(Sat) 02:57:54|NO.59979

objchild命令を使用してみてはどうでしょうか?
これでしたら、複数のオブジェクトをグループ化して一つのオブジェクトのように、動かす事が出来ます。



暇人

リンク

2014/2/16(Sun) 14:25:11|NO.60030

ローカル定義した命令をグローバルマクロで使用してしまうポカをしたので修正して再掲載(QCopyもついでに修正)



objchildは色付きオブジェを最初にキューブへ貼り付けるのには使えるかな・・・

>XとYがなんかうまくいきません。
ジンバルロックって奴だろう
ローカル軸で回転させようとすると必ずぶち当たる問題
回避方法としてクォータニオンが使われる

HSPでクォータニオンを使って回転


//モジュールここから(このモジュールはDirectX9が必須です。二年前以降にDirectXを更新してれば問題無いだろう) #module "mod_D3DXQuaternion" #uselib "d3dx9_39.dll" #func D3DXMatrixRotationX "D3DXMatrixRotationX" var,float #func D3DXMatrixTranslation "D3DXMatrixTranslation" var,float,float,float #func D3DXQuaternionRotationAxis "D3DXQuaternionRotationAxis" int,var,float #func global D3DXMatRotQ "D3DXMatrixRotationQuaternion" var,int #func D3DXQuaternionRotationYawPitchRoll "D3DXQuaternionRotationYawPitchRoll" int,float,float,float #func D3DXQuaternionMultiply "D3DXQuaternionMultiply" int,int,int #func D3DXMatrixMultiply "D3DXMatrixMultiply" var,var,var #func D3DXMatrixRotationYawPitchRoll "D3DXMatrixRotationYawPitchRoll" var,float,float,float #func D3DXQuaternionToAxisAngle "D3DXQuaternionToAxisAngle" int,var,var #func D3DXVec3Transform "D3DXVec3Transform" var,var,var #func D3DXQuaternionInverse "D3DXQuaternionInverse" int,int #func D3DXQuaternionSlerp "D3DXQuaternionSlerp" int,int,int,float #func D3DXMatrixRotationAxis "D3DXMatrixRotationAxis" var,var,float #func D3DXQuaternionRotationMatrix "D3DXQuaternionRotationMatrix" int,int #cfunc global D3DXQuaternionN "D3DXQuaternionNormalize" int,int #const H_PI M_PI/2.0 //「----クォータニオンモジュールの初期化----」 //D3DXQuaternion_init qmax //qmax [クォータニオンID使用最大数(省略時1024)]int #deffunc D3DXQuaternion_init int qmax if qmax<=0 {_qmax=1024}else{_qmax=qmax} dim q,4*_qmax q_ptr=varptr(q) dim qid_list,_qmax ddim temp_double,1 dim tq,4 tq_ptr=varptr(tq) dim TurnMat,16 dim temp_Mat,16 dim D3DXVECTOR4,4 dupptr dup_x,varptr(temp_Mat(12)),4,4 dupptr dup_y,varptr(temp_Mat(13)),4,4 dupptr dup_z,varptr(temp_Mat(14)),4,4 dupptr dup_vx,varptr(D3DXVECTOR4),4,4 dupptr dup_vy,varptr(D3DXVECTOR4(1)),4,4 dupptr dup_vz,varptr(D3DXVECTOR4(2)),4,4 dupptr mov,varptr(temp_Mat(12)),4*3,4 return //「----クォータニオンから各オイラー角取得----」 //q2xyz(%1 ,%2 ,%3 ,%4) //%1 [クォータニオンID(入力)]int //%2 ,%3 ,%4 [各オイラー角(出力)]double #define global QtoRxyz(%1,%2,%3,%4) D3DXMatRotQ TurnMat@mod_D3DXQuaternion,D3DXQuaternionN(tq_ptr@mod_D3DXQuaternion,qid_list@mod_D3DXQuaternion(%1)):MatToEul TurnMat@mod_D3DXQuaternion,%2,%3,%4 //「----指定角度から指定QIDにクォータニオン作成----」 // QSetXYZ qid, rx, ry, rz //qid [クォータニオンID(入力)]int //rx, ry, rz [各オイラー角(入力)]double //使用できる最大IDを超えるとstatに-1が返る #deffunc QSetXYZ int qid,double rx,double ry,double rz if qid<_qmax { D3DXMatrixRotationYawPitchRoll temp_Mat,-ry, 0.0, rz D3DXMatrixRotationX TurnMat,rx D3DXMatrixMultiply temp_Mat,temp_Mat,TurnMat D3DXQuaternionRotationMatrix varptr(q(qid*4)),stat qid_list(qid)=stat }else{ return -1 } return 0 //「----QIDを指定して入力クォータニオンを回転後のクォータニオンにして各オイラー角も出力----」 //QRotXYZ qid ,rx,ry,rz ,drx,dry,drz // qid [クォータニオンID(入力)]int // rx ,ry ,rz [回転量(入力)]double // drx,dry,drz [回転後の角度(出力)]double #deffunc QRotXYZ int qid ,double rx,double ry,double rz ,var drx,var dry,var drz D3DXQuaternionRotationYawPitchRoll tq_ptr,ry,rx,rz D3DXQuaternionMultiply qid_list(qid),qid_list(qid),stat QtoRxyz qid ,drx,dry,drz return //「----QIDを指定して入力クォータニオンの姿勢を基準にした移動量を出力----」 //QPosXYZ qid ,vx,vy,vz ,dvx,dvy,dvz // qid [クォータニオンID(入力)]int // vx ,vy ,vz [移動量(入力)]double // dvx ,dvy ,dvz [回転処理された移動量(出力)]double //(fvdir fv,vx,vy,vz だとfvに出力されるのをdvx,dvy,dvzに出力されるようにした感じ) #deffunc QPosXYZ int qid,double vx,double vy,double vz ,var dvx,var dvy,var dvz D3DXMatrixTranslation temp_Mat,vx, vy, vz //移動量をfloatに変換(temp_Mat(12〜14)をクローン変数movにしてある) D3DXQuaternionInverse tq_ptr,qid_list(qid) D3DXMatRotQ TurnMat,stat D3DXVec3Transform D3DXVECTOR4,mov,TurnMat //移動量回転 dvx=ftd(dup_vx) //結果をdoubleにして座標に出力(dup_v?はD3DXVECTOR4(0〜2)のクローン) dvy=ftd(dup_vy) dvz=ftd(dup_vz) return //「----QIDを指定して入力クォータニオンの姿勢を基準に軸を指定して入力クォータニオンを回転----」 //QSetAxisRot qid, vx, vy, vz , rot // qid [クォータニオンID(入力)]int // vx ,vy ,vz [回転軸(入力)]double // rot [回転量(入力)]double #deffunc QSetAxisRot int qid,double vx,double vy,double vz ,double rot D3DXMatrixTranslation temp_Mat,vx, vy, vz D3DXQuaternionRotationAxis tq_ptr,mov,rot D3DXQuaternionMultiply qid_list(qid),qid_list(qid),tq_ptr return //「----QIDを指定して入力ォータニオンの回転軸と回転角度を取得----」 //QGetAxisAng qid, ax, ay, az , ang // qid [クォータニオンID(入力)]int // ax ,ay ,az [回転軸(出力)]double // ang [クォータニオン回転角度(出力)]double #deffunc QGetAxisAng int qid,var ax,var ay,var az ,var ang D3DXQuaternionInverse tq_ptr,qid_list(qid) D3DXQuaternionToAxisAngle tq_ptr,D3DXVECTOR4,ang_f ang=ftd(ang_f) ax=ftd(dup_vx) ay=ftd(dup_vy) az=ftd(dup_vz) return //「----QIDを指定して球面線形補間を使って、2 つのクォータニオン間を補間する----」 //QSlerp qid1, qid2, qid3, t // qid1 [補間後のクォータニオンID(入力)]int // qid2 [回転前のクォータニオンID(入力)]double // qid3 [回転後クォータニオンID(入力)]double // t [補間するクォータニオン間の間隔を示すパラメータ、1.0でqid1の姿勢がqid3の姿勢になる(入力)]double #deffunc QSlerp int qid1,int qid2,int qid3,double t D3DXQuaternionSlerp q_ptr+qid1*16,q_ptr+qid2*16,q_ptr+qid3*16,t qid_list(qid1)=stat return //「----QIDを指定して2つのクォータニオンを乗算する。----」 //QSlerp qid1, qid2, qid3 // qid1 [演算結果のクォータニオンID(入力)]int // qid2 [処理の基になるクォータニオンID(入力)]double // qid3 [処理の基になるクォータニオンID(入力)]double #deffunc QMultiply int qid1,int qid2,int qid3 D3DXQuaternionMultiply q_ptr+qid1*16,q_ptr+qid2*16,q_ptr+qid3*16 qid_list(qid1)=stat return //「----QIDを指定してクォータニオンをコピー----」 //QCopy qid1, qid2 // qid1 [コピー先のクォータニオンID(入力)]int // qid2 [コピー元のクォータニオンID(入力)]int #deffunc QCopy int qid1,int qid2 memcpy q(qid1*4),q(qid2*4),16 qid_list(qid1)=varptr(q(qid1*4)) return //「----回転行列から各オイラー角取得ー----(QtoRxyzから使われる事が前提で単体では使用しない)」 //MatToEul Mat ,tx,ty,tz // Mat [回転行列4*4(入力)]float // ex ,ey ,ez [各オイラー角(出力)]double #deffunc MatToEul array Mat ,var ex,var ey,var ez Mat8=limitf(ftd(Mat(8)),-1.0,1.0) ey=-atan(Mat8,sqrt(1.0-Mat8*Mat8)) if absf(cos(ey))<0.001{ ex=atan(ftd(Mat(6)),ftd(Mat(5))) if Mat8>0.0 {ey=-H_PI}else{ey=H_PI} ez=0.0 }else{ ex=atan(-ftd(Mat(9)),ftd(Mat(10))) ez=atan(-ftd(Mat(4)),ftd(Mat(0))) } return //「----doubleからfloatに変換----」 //変数 = dtf( double ) #defcfunc dtf double _x D3DXMatrixTranslation temp_Mat,_x return dup_x //「----floatからdoubleに変換----」 //変数 = ftd( float ) #defcfunc ftd int p1 temp=p1 << 29,p1 & 0x80000000 | ((p1 & 0x7fffffff) >> 3) + ((p1 & 0x7fffffff) ! 0) * 0x38000000 memcpy temp_double,temp,8 return temp_double //「----回転行列初期化----」 //D3DXMatrixIdentity Mat // Mat [回転行列16要素(入力)]float #deffunc D3DXMatrixIdentity array Mat Mat(15)=0 D3DXMatrixRotationYawPitchRoll Mat return #global //モジュールここまで #include "hgimg3.as" //モジュール初期化(必ず必要) D3DXQuaternion_init screen 0,640,480,0 cls 4 hgini setfont 16,16,12,1 ; font Tex select(cx,cy,px,mode) texload dir_exe+"\\sample\\hgimg3\\fontchr.bmp" ; フォントテクスチャの登録 //親オブジェクト setcolor 100,100,100 addbox mbox, 9,9 regobj obox,mbox //XYZ軸視認用オブジェクト repeat 3 addline mline(cnt),-1,$ff<<(cnt*8) regobj oline(cnt), mline(cnt) objchild obox,oline(cnt)//親オブジェクトにジョイント setwork oline(cnt),-12*(cnt=0),-12*(cnt=1),12*(cnt=2) loop //色パネルの貼り準 // 3 //1 0 2 // 4 // 5 pbx=0,-1,1,0,0,0 pby=0,0,0,-1,1,0 pbz=1,0,0,0,0,-1 //色パネルオブジェクト repeat 6 setcolor (cnt<4)*255+(cnt>3)*44,((cnt=1) | (cnt=2))*255+(cnt=3)*128+(cnt=4)*175+(cnt=5)*44,(cnt=2)*255+(cnt=4)*44+(cnt=5)*175 addbox pmbox(cnt),0.2, 8.5 regobj pobox(cnt), pmbox(cnt) objchild obox,pobox(cnt)//親オブジェクトにジョイント setpos pobox(cnt),4.5*pbx(cnt),4.5*pby(cnt),4.5*pbz(cnt)//親オブジェクトのそれぞれの面に配置 setang pobox(cnt),,atan(pbz(cnt),pbx(cnt)),atan(pby(cnt),pbz(cnt))//配置された面に応じて回転 loop selcpos objset3 0.0, 0.0, 35.0 cammode CAM_MODE_LOOKAT setang obox,0,0,0 getang obox,rx,ry,rz getpos HGOBJ_CAMERA,cpx,cpy,cpz setscale HGOBJ_LIGHT,175,175,175 setang HGOBJ_LIGHT,atan(cpy,cpz),atan(cpx,cpz), qid=0 QSetXYZ qid,rx,ry,rz //初期クォータニオン作成(開始時の姿勢) rotfps=10 //一回の操作で連続で回転するフレーム数 r_90=M_PI/2.0/rotfps //1フレームで回転する角度 typname="クォータニオン","オイラー角" title typname(typ) *main stick k,$fff-16 if k&128 : goto *owari ; [ESC]で終了 getkey shift,16 getkey ctrl,17 if k&256 {//左クリック、カメラ移動 selcpos objset3 -0.1*(mousex-320), -0.1*(mousey-240), 35.0 getpos HGOBJ_CAMERA,cpx,cpy,cpz setang HGOBJ_LIGHT,atan(cpy,cpz),atan(cpx,cpz),0.0 } if k&512 {//右クリック、カメラ初期位置に戻す selcpos objset3 0,0, 35.0 getpos HGOBJ_CAMERA,cpx,cpy,cpz setang HGOBJ_LIGHT,atan(cpy,cpz),atan(cpx,cpz),0.0 } if k&16 {//スペースでクォータニオンとオイラー角の回転を変更します typ^1 title typname(typ) if typ=0 {getang obox,rx,ry,rz QSetXYZ qid ,rx,ry,rz //クォータニオン再設定 } } if shift or ctrl {k = shift*2048 | ctrl*4096} if (k ! 0) and ((rotx or roty or rotz)=0){//同時に2軸回転させると斜めに回転するので一つだけになるように処理 //Y軸回転(緑軸) if k=1 : roty+rotfps//(←)回転カウントセット if k=4 : roty-rotfps//(→) //X軸回転(青軸) if k=2 : rotx-rotfps//(↑) if k=8 : rotx+rotfps//(↓) //Z軸回転(赤軸) if k=2048 : rotz+rotfps //(Shift) if k=4096 : rotz-rotfps //(Ctrl) } if rotx {addx=rotx/abs(rotx):rotx-addx}else{addx=0} //回転カウントが0になるまで回転方向を設定 if roty {addy=roty/abs(roty):roty-addy}else{addy=0} if rotz {addz=rotz/abs(rotz):rotz-addz}else{addz=0} if addx or addy or addz {//回転方向が設定されてる if typ=0 { QRotXYZ qid,r_90*addx,r_90*addy,r_90*addz,rx,ry,rz setang obox,rx,ry,rz }else{ addang obox,r_90*addx,r_90*addy,r_90*addz } } hgdraw getang obox,rx,ry,rz fprt strf(" rx(%.3f) ry(%.3f) rz(%.3f)",rad2deg(rx),rad2deg(ry),rad2deg(rz)),16,16 hgsync 16 goto *main *owari end
スペースを押すとクォータニオンと通常の回転を切換できる
オイラー角モードだと回転軸が重なって軸の色と操作が合わなくなるのが分かる


回転行列から各オイラー角取得は色々試して変な回転にならないようにしたけど
完全じゃ無いかも知れない・・・



暇人

リンク

2014/2/16(Sun) 17:26:52|NO.60039

オイラー角とクオータニオンでY軸回転が反対になってた・・・

> D3DXQuaternionRotationYawPitchRoll tq_ptr,ry,rx,rz
これを

D3DXQuaternionRotationYawPitchRoll tq_ptr,-ry,rx,rz
に置換え


> //Y軸回転(緑軸)
> if k=1 : roty+rotfps//(←)回転カウントセット
> if k=4 : roty-rotfps//(→)
これを

//Y軸回転(緑軸) if k=1 : roty-rotfps//(←)回転カウントセット if k=4 : roty+rotfps//(→)
に置換え(こっちは特に必要ないけど感覚的にこっちかなと・・・)



暇人

リンク

2014/2/17(Mon) 07:24:11|NO.60066

あ、NO.59939のはジンバルロックだけの問題じゃなかった
ルービックキューブの場合グローバルの座標軸で回さないといけない
Y軸を左に90度回転させてから、X軸を90度回転させたい場合
ワールド座標軸のX軸と重なってるローカルのZ軸を回転させる必要がある

で、この回転にクォータニオンを使う
回転軸を決めて回転させるならQSetAxisRotの方が使いやすいかも
でも、rotがQSetAxisRotでパラメータとして使ってるので
rotを命令として使われてるNO.59939ではエラーになるから
どちらかの名前を修正する必要がある

mod_D3DXQuaternionの方を修正するなら

>#deffunc QSetAxisRot int qid,double vx,double vy,double vz ,double rot
> D3DXMatrixTranslation temp_Mat,vx, vy, vz
> D3DXQuaternionRotationAxis tq_ptr,mov,rot
の rot の部分を qrot にでも変更すれば良い



暇人

リンク

2014/2/17(Mon) 23:26:06|NO.60083

とりあえずNO.60030のモジュールを使えば(NO.60039、NO.60066の修正を加えて)
ちゃんとした回転になるのを確認(元のスクリプトを20行ぐらい追加修正すれば動いた)
ワールド空間の軸を探す方法が泥臭い方法しか思い付かなかったので
もっと良い方法あったら書き込むかも・・・


色パネルの回転はbodyの子としてobjchildでくっつければいちいち回転させる必要が無くなる
NO.59939の *main〜goto *main の間にある gosub *calcplate を削除して
*mainのの前に gosub *calcplate を配置
*calcplateのサブルーチンを
	
*calcplate bTopMax = 0 bRightMax = 0 bFrontMax = 0 bLeftMax = 0 bBottomMax = 0 bBackMax = 0 for j, 0, 3, 1 :for i, 0, 3, 1 :repeat 3 id = 9*j +3*i +cnt plateMax = 0 gosub *platefix if plateMax == 0 :continue // 回転角取得 selang body.id objgetfv euler repeat plateMax // 回転角取得 selang body.id objgetfv euler objchild body.id,plateID.cnt //ジョイント selang plateID.cnt addary3 euler, 0, addeuler(cnt, 0), addeuler(cnt, 1), addeuler(cnt, 2) objsetfv euler // 座標変換(local → world) position_ = position(cnt, 0), position(cnt, 1), position(cnt, 2) local2world position_, euler selpos plateID.cnt objsetfv position_ loop loop :next :next return
に置換えすればbodyにplateが張り付く



Humi

リンク

2014/2/17(Mon) 23:30:32|NO.60085

……む、難しい。。

3Dは今回始めてちゃんとやるんで、命令の内容もよく分からないまま使ってましたが。。。

とりあえずオイラーを回転の方法?を変えなければいけないようですね。

もうあきらめようかなと、思っていたところなんですが、
せっかく教えていただいたものがあるので、がんばりたいと思います。

暇人さん情報ありがとうございます。



暇人

リンク

2014/2/18(Tue) 21:26:12|NO.60097

>ワールド空間の軸を探す方法が泥臭い方法しか思い付かなかったので
クォータニオンを回転行列に変換すれば各軸がどの方向向いてるかそのまま入ってた・・・
回転行列から回転させる軸のベクトル抜き出してQSetAxisRotで回転させれば解決
後で抜き出す命令追加してモジュールを書き込む

>命令の内容もよく分からないまま使ってましたが。。。
hgimg3には便利な命令がある
座標の回転とか

fv=rx,-ry,yz //fvdirがY軸回転が逆になるので前もって逆を指定する fvdir fv,vx,vy,vz
fvに角度を入れてfvdirするときにベクトル(座標)を与えれば回転してくれる
NO.59939で使ってる rot 命令の3D版



暇人

リンク

2014/2/21(Fri) 00:54:58|NO.60155

キューブの動作に必要な部分だけのモジュールにして
NO.59939のに適応させてみた

//モジュールここから(このモジュールはDirectX9が必須です) #module "mod_D3DXQ" #uselib "d3dx9_39.dll" #func D3DXMatrixRotationX "D3DXMatrixRotationX" var,float #func D3DXMatrixTranslation "D3DXMatrixTranslation" var,float,float,float #func D3DXQuaternionRotationAxis "D3DXQuaternionRotationAxis" int,var,float #func global D3DXMatRotQ "D3DXMatrixRotationQuaternion" var,int #func D3DXQuaternionMultiply "D3DXQuaternionMultiply" int,int,int #func D3DXMatrixMultiply "D3DXMatrixMultiply" var,var,var #func D3DXMatrixRotationYawPitchRoll "D3DXMatrixRotationYawPitchRoll" var,float,float,float #func D3DXQuaternionRotationMatrix "D3DXQuaternionRotationMatrix" int,int #cfunc global D3DXQuaternionN "D3DXQuaternionNormalize" int,int #const H_PI M_PI/2.0 //「----クォータニオンモジュールの初期化----」 //D3DXQuaternion_init qmax //qmax [クォータニオンID使用最大数(省略時1024)]int #deffunc D3DXQ_init int qmax if qmax<=0 {_qmax=1024}else{_qmax=qmax} dim q,4*_qmax q_ptr=varptr(q) dim qid_list,_qmax ddim temp_double,1 dim tq,4 tq_ptr=varptr(tq) dim TurnMat,16 dim temp_Mat,16 dupptr dup_x,varptr(temp_Mat(12)),4,4 dupptr dup_y,varptr(temp_Mat(13)),4,4 dupptr dup_z,varptr(temp_Mat(14)),4,4 dupptr dup_mov,varptr(temp_Mat(12)),4*3,4 return //「--------------クォータニオンから各オイラー角取得----」 //QGetAngXYZ(%1 ,%2 ,%3 ,%4) //%1 [クォータニオンID(入力)]int //%2 ,%3 ,%4 [各オイラー角(出力)]double #define global QGetAngXYZ(%1,%2,%3,%4) D3DXMatRotQ TurnMat@mod_D3DXQ,D3DXQuaternionN(tq_ptr@mod_D3DXQ,qid_list@mod_D3DXQ(%1)):MatToEul TurnMat@mod_D3DXQ,%2,%3,%4 //「--------------指定角度から指定QIDにクォータニオン作成----」 //QSetRotXYZ qid, rx, ry, rz // qid [クォータニオンID(入力)]int // rx, ry, rz [各オイラー角(入力)]double //(使用できる最大IDを超えるとstatに-1が返る) #deffunc QSetRotXYZ int qid,double rx,double ry,double rz if qid < _qmax { D3DXMatrixRotationYawPitchRoll temp_Mat,-ry, 0.0, rz D3DXMatrixRotationX TurnMat,rx D3DXMatrixMultiply temp_Mat,temp_Mat,TurnMat D3DXQuaternionRotationMatrix varptr(q(qid*4)),stat qid_list(qid)=stat }else{ return -1 } return 0 //「-------------QIDを指定して入力クォータニオンの姿勢を基準に軸を指定して入力クォータニオンを回転----」 //QAddAxisRot qid, ax ,ay ,az , qrot // qid [クォータニオンID(入力)]int // ax ,ay ,az [回転軸ベクトル(入力)]double // qrot [回転量(入力)]double #deffunc QAddAxisRot int qid,double ax,double ay,double az,double qrot D3DXMatrixTranslation temp_Mat,ax ,ay ,az D3DXQuaternionRotationAxis tq_ptr,dup_mov,qrot D3DXQuaternionMultiply qid_list(qid),qid_list(qid),tq_ptr return //「-------------QIDを指定してワールド空間の軸でクォータニオンを回転----」 // QAddWorldAxisRot qid, ax, ay, az, qrot // qid [クォータニオンID(入力)]int // ax ,ay ,az [ワールド空間の回転軸ベクトル(入力)]double // qrot [回転量(入力)]double #deffunc QAddWorldAxisRot int qid,double ax,double ay,double az,double qrot D3DXMatRotQ TurnMat,qid_list(qid) QAddAxisRot qid, ftd(TurnMat(0))*ax+ftd(TurnMat(4))*ay+ftd(TurnMat(8))*az, ftd(TurnMat(1))*ax+ftd(TurnMat(5))*ay+ftd(TurnMat(9))*az, ftd(TurnMat(2))*ax+ftd(TurnMat(6))*ay+ftd(TurnMat(10))*az , qrot return //「-------------回転行列から各オイラー角取得----(QtoRxyzから使われる事が前提で単体では使用しない)」 //MatToEul Mat, ex, ey, ez // Mat [回転行列4*4(入力)]float // ex ,ey ,ez [各オイラー角(出力)]double #deffunc MatToEul array Mat ,var ex,var ey,var ez Mat8=limitf(ftd(Mat(8)),-1.0,1.0) ey=-atan(Mat8,sqrt(1.0-Mat8*Mat8)) if absf(cos(ey))<0.001{ ex=atan(ftd(Mat(6)),ftd(Mat(5))) if Mat8>0.0 {ey=-H_PI}else{ey=H_PI} ez=0.0 }else{ ex=atan(-ftd(Mat(9)),ftd(Mat(10))) ez=atan(-ftd(Mat(4)),ftd(Mat(0))) } return //「----doubleからfloatに変換----」 //変数 = dtf( double ) #defcfunc dtf double _x D3DXMatrixTranslation temp_Mat,_x return dup_x //「----floatからdoubleに変換----」 //変数 = ftd( float ) #defcfunc ftd int p1 temp=p1 << 29,p1 & 0x80000000 | ((p1 & 0x7fffffff) >> 3) + ((p1 & 0x7fffffff) ! 0) * 0x38000000 memcpy temp_double,temp,8 return temp_double #global //モジュールここまで D3DXQ_init //モジュール初期化 #include "hgimg3.as" #module __CUBECORE__ #deffunc wherecube array body, int maxID, array position repeat maxID selpos body.cnt objgetfv position xid = 1+position.0/9.0 yid = 1+position.1/9.0 zid = 1+position.2/9.0 cube@(9*zid + 3*yid + xid) = cnt loop return #deffunc wherecentercube for i, 0, 9, 1 repeat 6 if tbody(i) == cbody(cnt) :center = i :break loop if center != -1 :_break next return #define global cuberot(%1, %2, %3, %4=-1, %5=-1, %6=-1) cuberot__ %1, %2, %3, %4, %5, %6 #deffunc cuberot__ array body, int frotmax, array position, int xline, int yline, int zline if frot :return if xline == -1 && yline == -1 && zline == -1 :return dim tbody, 9 :bodycnt = 0 :center = -1 cbody = 4, 10, 12, 14, 16, 22 // is center cube when cube version 3x3 for j, 0, 3, 1 :for i, 0, 3, 1 :repeat 3 if j == zline { id = 9*j +3*i +cnt tbody(bodycnt) = cube@(id) bodycnt++ } if i == yline { id = 9*j +3*i +cnt tbody(bodycnt) = cube@(id) bodycnt++ } if cnt == xline { id = 9*j +3*i +cnt tbody(bodycnt) = cube@(id) bodycnt++ } loop :next :next wherecentercube selpos body.center objgetfv position xcen = position.0 ycen = position.1 zcen = position.2 if zline != -1 :way = 3 if yline != -1 :way = 2 if xline != -1 :way = 1 frot = frotmax add = M_PI/2.0 / double(frotmax) return way #deffunc cube90rot array body, int frotmax, array position if frot == 0 :return ddim addrot,3 //way-1の要素に回転量を代入(way-1=0がxline) addrot(way-1) = sin(M_PI*2.0 / double(frotmax) * double(frotmax-frot-frotmax/5)) * add + add ddim Axis,3 //ワールド空間の回転軸指定(addrotと同じようにway-1=0がxline) Axis(way-1) = 1.0 // sin( PI*2 / 周期 * Count ) * 振幅 repeat 9 id=body(tbody(cnt)) //オブジェクトIDと同じIDでクォータニオンを作ってるのでそのまま指定 QAddWorldAxisRot id,Axis(0),Axis(1),Axis(2),-addrot(way-1) //1.0が入ってるワールド空間の軸で回転される QGetAngXYZ id,brx,bry,brz //回転させたクォータニオンから角度を取得 setang id,brx,bry,brz getpos id,bpx,bpy,bpz fvset position,-addrot(0),-addrot(1),-addrot(2) //way-1の要素に入ってる回転量が設定され、それ以外は0に fvdir position,bpx,bpy,bpz //座標回転 selpos id objsetfv position loop frot-- return frot #global #module // set2ary3 position, 0, 0, 5.0, 0.0, 0.0 #deffunc set2ary3 array ary, int iBegin, int iBegin2, double p1, double p2, double p3 ary(iBegin, iBegin2) = p1 ary(iBegin, iBegin2+1) = p2 ary(iBegin, iBegin2+2) = p3 return #deffunc addary3 array ary, int iBegin, double p1, double p2, double p3 ary(iBegin) += p1 ary(iBegin+1) += p2 ary(iBegin+2) += p3 return #deffunc subary3 array ary, int iBegin, double p1, double p2, double p3 ary(iBegin) -= p1 ary(iBegin+1) -= p2 ary(iBegin+2) -= p3 return #global rBox = 9.0 // 半径 xBox = 3.0 // x個数 yBox = 3.0 // y個数 zBox = 3.0 // z個数 aBox = xBox*yBox // 一面個数 aaBox = aBox*zBox // 全体個数 mBox = 0.2 // 隙間 0.3 pmBox = 0.5 // 板間 pbmBox = M_PI/(2.0*rBox) center = int(aBox+xBox+1) camang = 0.0, 0.0, 0.0, 50.0 // x, y, z, 距離 frotmax = 20 // 回転周期 frot = 0 dim cube, aaBox // 位置記憶用 dim bTop, aBox dim bLeft, aBox dim bRight, aBox dim bBottom, aBox dim bFront, aBox dim bBack, aBox ddim euler, 3 ddim position, 6, 3 ddim position_, 3 ddim addeuler, 6, 3 screen 0, 320, 320 title "Cube" hgini // 貼り付ける板 // 上面 setcolor 255, 255, 255 addbox white_plate, 0.2, rBox-pmBox repeat aBox :regobj bTop(cnt), white_plate :loop // 右面 setcolor 255, 255, 0 addbox yellow_plate, 0.2, rBox-pmBox repeat aBox :regobj bRight(cnt), yellow_plate :loop // 正面 setcolor 255, 128, 0 addbox orange_plate, 0.2, rBox-pmBox repeat aBox :regobj bFront(cnt), orange_plate :loop // 左面 setcolor 44, 175, 44 addbox green_plate, 0.2, rBox-pmBox repeat aBox :regobj bLeft(cnt), green_plate :loop // 下面 setcolor 44, 44, 175 addbox blue_plate, 0.2, rBox-pmBox repeat aBox :regobj bBottom(cnt), blue_plate :loop // 裏面 setcolor 255, 0, 0 addbox red_plate, 0.2, rBox-pmBox repeat aBox :regobj bBack(cnt), red_plate :loop // 貼り付けられる本体 setcolor 30, 30, 30 addbox box, rBox, rBox setcolor 255, 255, 255 addbox cenBox, rBox, rBox for j, 0, 3, 1 :for i, 0, 3, 1 :repeat 3 id = 9*j +3*i +cnt if id == center { regobj body(id), cenBox }else : regobj body(id), box r = rBox+mBox position = double(cnt-(3/2))*r, double(i-(3/2))*r, double(j-(3/2))*r setpos body(id), position.0, position.1, position.2 //オブジェクトIDと同じIDでクォータニオンを作成 QSetRotXYZ body(id), 0.0, 0.0, 0.0 loop :next :next // カメラ cammode CAM_MODE_LOOKAT camang = -45.0, -45.0, -45.0 // 初回処理 gosub *calcplate gosub *setcamerapos hgdraw gosub *setlightpos //CAM_MODE_LOOKATの場合カメラアングルの更新はhgdraw時にしかされない感じ hgsync 20 wherecube body, aaBox, position *main clscolor $FFFFFF if frot :cube90rot body, frotmax, position :if stat == 0 {frot = 0} getkey ky, 'Z' :if ky :fzky = 1 :else { if active != 3 :zcolumn = -1 if fzky { fzky = 0 zcolumn = zcolumned if active == 3 :zcolumn = (zcolumn+1)\3 :else :active = 3 zcolumned = zcolumn title "Z : "+zcolumn } } getkey ky, 'Y' :if ky :fyky = 1 :else { if active != 2 :ycolumn = -1 if fyky { fyky = 0 ycolumn = ycolumned if active == 2 :ycolumn = (ycolumn+1)\3 :else :active = 2 ycolumned = ycolumn title "Y : "+ycolumn } } getkey ky, 'X' :if ky :fxky = 1 :else { if active != 1 :xcolumn = -1 if fxky { fxky = 0 xcolumn = xcolumned if active == 1 :xcolumn = (xcolumn+1)\3 :else :active = 1 xcolumned = xcolumn title "X : "+xcolumn } } stick@hsp ky, 15+64+16+256 if frot == 0 :if ky & 288 { title "clicked "+xcolumn+" : "+ycolumn+" : "+zcolumn wherecube body, aaBox, position cuberot body, frotmax, position, xcolumn, ycolumn, zcolumn :frot = stat } // カメラ位置移動 if ky & 15 { if ky & 64 { if ky & 2 :camang.3 -= 2.0 if ky & 8 :camang.3 += 2.0 }else :if ky & 16 { if ky & 1 :adddir HGOBJ_CAMERA, 1.0 if ky & 4 :adddir HGOBJ_CAMERA, -1.0 if ky & 2 :adddir HGOBJ_CAMERA,, -1.0 if ky & 8 :adddir HGOBJ_CAMERA,, 1.0 }else { if ky & 1 :camang.0 += 2.0 if ky & 4 :camang.0 -= 2.0 if ky & 2 :camang.1 -= 2.0 if ky & 8 :camang.1 += 2.0 } gosub *setcamerapos gosub *setlightpos } hgdraw hgsync 20 goto *main *calcplate bTopMax = 0 bRightMax = 0 bFrontMax = 0 bLeftMax = 0 bBottomMax = 0 bBackMax = 0 for j, 0, 3, 1 :for i, 0, 3, 1 :repeat 3 id = 9*j +3*i +cnt plateMax = 0 gosub *platefix if plateMax == 0 :continue // 回転角取得 selang body.id objgetfv euler repeat plateMax // 回転角取得 selang body.id objgetfv euler objchild body.id,plateID.cnt //ジョイント(子設定すれば親からの角度と距離を設定するだけで親と同じ動きになる) selang plateID.cnt fvadd euler, addeuler(cnt, 0), addeuler(cnt, 1), addeuler(cnt, 2)//fv用の加算命令 fvadd euler(3),x,y,z のような使い方は出来ないが・・・ objsetfv euler euler(1)*-1.0 //fvdirのY軸回転が逆になるので符号反転しとく fvdir euler, position(cnt, 0), position(cnt, 1), position(cnt, 2) selpos plateID.cnt objsetfv euler loop loop :next :next return *platefix if i == 0 {// 上面 plateID.plateMax = bTop.bTopMax // set2ary3 position, plateMax, 0, rBox/4.0+pbmBox, -rBox/4.0-pbmBox, 0.0 set2ary3 position, plateMax, 0, rBox/2.0+pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, 0.0, M_PI/2.0 bTopMax++ plateMax++ } if j == 0 {// 右面 plateID.plateMax = bRight.bRightMax // set2ary3 position, plateMax, 0, rBox/4.0+pbmBox, 0.0, -rBox/4.0-pbmBox set2ary3 position, plateMax, 0, rBox/2.0+pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, M_PI/2.0, 0.0 bRightMax++ plateMax++ } if cnt == 2 {// 正面 plateID.plateMax = bFront.bFrontMax // set2ary3 position, plateMax, 0, rBox/4.0+pbmBox, 0.0, 0.0 set2ary3 position, plateMax, 0, rBox/2.0+pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, 0.0, 0.0 bFrontMax++ plateMax++ } if j == 2 {// 左面 plateID.plateMax = bLeft.bLeftMax // set2ary3 position, plateMax, 0, -rBox/4.0-pbmBox, 0.0, rBox/4.0+pbmBox set2ary3 position, plateMax, 0, -rBox/2.0-pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, M_PI/2.0, 0.0 bLeftMax++ plateMax++ } if i == 2 {// 下面 plateID.plateMax = bBottom.bBottomMax // set2ary3 position, plateMax, 0, -rBox/4.0-pbmBox, rBox/4.0+pbmBox, 0.0 set2ary3 position, plateMax, 0, -rBox/2.0-pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, 0.0, M_PI/2.0 bBottomMax++ plateMax++ } if cnt == 0 {// 裏面 plateID.plateMax = bBack.bBackMax // set2ary3 position, plateMax, 0, -rBox/4.0-pbmBox, 0.0, 0.0 set2ary3 position, plateMax, 0, -rBox/2.0-pbmBox, 0.0, 0.0 set2ary3 addeuler, plateMax, 0, 0.0, 0.0, 0.0 bBackMax++ plateMax++ } return *setcamerapos position.0 = cos(M_PI/180.0*camang.0)*camang.3 position.1 = sin(M_PI/180.0*camang.1)*camang.3 position.2 = sin(M_PI/180.0*camang.0)*camang.3 selpos HGOBJ_CAMERA objsetfv position return *setlightpos // カメラとライトを同じ位置・角度に設定 selpos HGOBJ_CAMERA objgetfv position selpos HGOBJ_LIGHT objsetfv position selang HGOBJ_CAMERA objgetfv euler selang HGOBJ_LIGHT objsetfv euler return



Humi

リンク

2014/2/21(Fri) 14:40:22|NO.60165

あーこれ見て3d勉強しますー

暇人さんありがとうございましたー



暇人

リンク

2014/2/22(Sat) 20:26:49|NO.60200

もう解決してるけど後から分かった事を補足
> D3DXQuaternionMultiply qid_list(qid),qid_list(qid),tq_ptr
これの2と3番目のパラメータを逆にするだけで、回転順が逆になりワールド軸での回転に出来た
処理の基になるクォータニオンは正規化しないとダメとかあるが・・・
後、クォータニオンを使わなくても回転行列でも同じ事は出来る
でもオイラー角取得するのに正規化しないといけないので
クォータニオンの方が処理数は少ないかも

それからメインの方にバグがあるな
キーを連続で押してx,z切換ながら回転させると変な動きになる
> stick@hsp ky, 15+64+16+256
の上の行に

if active != 1 :xcolumn = -1 if active != 2 :ycolumn = -1 if active != 3 :zcolumn = -1
を追加すると改善された



ONION software Copyright 1997-2023(c) All rights reserved.