|
|
|
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が張り付く
|
|
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
| |
|
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
を追加すると改善された
|
|