3年ぐらい前に作ったモジュールなので自分でも説明が・・・
間違ってる可能性も・・・
#include "hgimg3.as"
#module hgpcv
// _rangescalxy [スケール変更時に変換係数をスケールに合わせる(初期化時、efx変更時に使われる)]
#define global _rangescalxy rangescalx@hgpcv=scalx@hgpcv/rangecoef@hgpcv:rangescaly@hgpcv=scaly@hgpcv/rangecoef@hgpcv:rangescalz@hgpcv=scalz@hgpcv/rangecoef@hgpcv
// _pcvsetcpos _pcvsetcang _pcvsetcscale _pcvsetcefx [hgpcv側にカメラ情報をセット(初期化時、カメラ操作時に使われる)]
#define global _pcvsetcpos getpos HGOBJ_CAMERA,cx@hgpcv,cy@hgpcv,cz@hgpcv
#define global _pcvsetcang getang HGOBJ_CAMERA,crx@hgpcv,cry@hgpcv,crz@hgpcv
#define global _pcvsetcscale getscale HGOBJ_CAMERA,scalx@hgpcv,scaly@hgpcv,scalz@hgpcv:_rangescalxy@
#define global _pcvsetcefx getefx HGOBJ_CAMERA,FOV@hgpcv,NearZ@hgpcv,FarZ@hgpcv
//hgfvwork [%1を省略した時に使われる配列変数]
#define global hgfvwork fvwork@hgpcv
#define global hgfvwork2 fvwork2@hgpcv
// _getfvector %1,%2,%3,%4 [カメラレイのベクトルを収得]
// %1 ベクトルが代入される変数名(配列要素4)
// %2,%3 x,yスクリーン座標(実数値)
#define global _getfvector(%1=fvwork@hgpcv,%2=0.0,%3=0.0) \
fvset %1,crx@hgpcv,-cry@hgpcv,crz@hgpcv: \
fvdir %1,double(%2)/rangescalx@hgpcv,double(%3)/rangescaly@hgpcv,-1.0: \
vx@hgpcv=%1:vy@hgpcv=%1(1):vz@hgpcv=%1(2)
// _getfvwpos %1,%2,%3,%4,%5 [スクリーン座標をカメラからの距離とベクトルでワールド座標に変換]
// %1 ワールド座標が代入される変数名(配列要素4)
// %2 カメラからの距離(実数値)
// %3,%4,%5 x,y,zベクトル(実数値)省略時は_getfvwpos実行前に_getfvectorで収得したものが使われる
#define global _getfvwpos(%1=fvwork@hgpcv,%2,%3=vx@hgpcv,%4=vy@hgpcv,%5=vz@hgpcv) \
fvset %1,(%3),(%4),(%5): \
fvmul %1,(%2),(%2),(%2): \
fvadd %1,cx@hgpcv,cy@hgpcv,cz@hgpcv
//hgposcvfovini [hgposcviniで初期化した数値から3D2D座標変換係数をセット]
#deffunc hgpcvfovini
hfvo=FOV/2
halfscr=sin(hfvo)/cos(hfvo)
hgwiny=ginfo_winy/2
rangecoef=halfscr/hgwiny
_rangescalxy@
return
//hgposcvini [初期化]
//システム変数 refdval に変換係数が返ります(この)
#deffunc hgpcvini
ddim fvz,4:ddim fv,4:ddim fvwork,4:ddim fvwork2,4
vx=0.0:vy=0.0:vz=0.0:tmpz=0.0
crx=0.0:cry=0.0:crz=0.0:cry2=0.0
cx=0.0:cy=0.0:cz=50.0
scalx=1.0:scaly=1.0:scalz=1.0
rangescalx=0.0:rangescaly=0.0:rangescalz=0.0
cx_=0.0:cy_=0.0:cz_=0.0
FOV=atan(1,1) //画角(getefx HGOBJ_CAMERAを)
NearZ=0.5
FarZ=768.0
hgpcvfovini
return rangecoef
//hgpcvini2 [再初期化 640*480以外で hgini を実行した時に必要]
//システム変数 refdval に変換係数が返ります
#deffunc hgpcvini2
_pcvsetcang@
_pcvsetcpos@
_pcvsetcefx@
_pcvsetcscale@
_rangescalxy@
hgpcvfovini
return rangecoef
// hg_getspos p1,p2,p3,p4 [ワールド座標からスクリーン座標に変換]
// p1 ワールド座標が代入されてる配列変数(配列要素4、実行後の内容はカメラからの相対座標)
// p2,p3 x,yスクリーン座標が代入される(実数値)
// p4 スクリーンからの距離 -ならスクリーンの前 +ならスクリーンの後ろにある
#deffunc hg_getspos array fvxyz,var sx,var sy,var sz
fvsub fvxyz,cx,cy,cz
fvset fvz,0.0,0.0,crz
fvdir fvz,fvxyz(1),fvxyz,fvxyz(2)
fvset fv,-cry,crx,0.0
fvdir fv,fvz,fvz(1),fvz(2)
;fvmul fv,scaly,scalx,scalz //カメラスケールを変更している時用
sz=fv(2)
fvz=-sz*rangecoef
fvdiv fv,fvz,fvz,0.0
sx=fv(1)
sy=fv
return
// hg_getwpos p1,p2,p3,p4 [スクリーン座標からワールド座標に変換]
// p1 ワールド座標が代入される配列変数(配列要素4)
// p2,p3 x,yスクリーン座標指定(実数値)
// p4 スクリーンからの距離指定(実数値、-50でスクリーン前距離50の位置)
#deffunc hg_getwpos array fvxyz,double ssx,double ssy,double ssz
fvset fvxyz,crx,-cry,crz
fvdir fvxyz,-rangecoef*ssx*ssz,-rangecoef*ssy*ssz,ssz
fvadd fvxyz,cx,cy,cz
return
#global
hgpcvini //モジュール初期化
randomize
screen 0,640,480,0
hgsetreq SYSREQ_DEFTIMER,1
hgini
addxfile m_xmodel.0,dir_exe+"\\sample\\hgimg3\\font_a.x"
regobj obja, m_xmodel
setuv 0,0,128,128
addmesh m_mesh,8,8,16,100,100
texload dir_exe+"\\sample\\hgimg3\\btex.bmp"
regobj obj, m_mesh
setpos obj,0,0,-25
setefx obj,700
newevent ev1
event_prmon ev1,PRMSET_MYGROUP,2
event_setpos ev1, -20,-20,-30 ,20,10,30
event_setdir ev1, -0.3,-0.2,-0.5,0.3,0.2,0.5
event_setefx ev1,150
event_addang ev1, 0, 0.1, 0
event_wait ev1, 80
event_prmset ev1,PRMSET_FLAG,0
newevent ev2
event_addang ev2, 0, 0.1, 0.1
event_wait ev2, 1
event_jump ev2, 0
ddim x,30: ddim y,30: ddim z,30
setcolor 0,255,0
addbox boxmid,0.2,0.2
regobj objbox, boxmid,,ev2
clscolor $5050
setpos HGOBJ_CAMERA, 0, -10,50
repeat
stick key,$3ff
if key&128 :break
if (cnt&7)=0 { ; 8フレームごとに実行
regobj obj, m_xmodel,OBJ_MOVE
setevent obj,ev1
}
if key&64{//Ctrl+カーソルキーでカメラ回転
if key&1 : addang HGOBJ_CAMERA, 0.0, 0.02
if key&4 : addang HGOBJ_CAMERA, 0.0, -0.02
if key&8 : addang HGOBJ_CAMERA, -0.02, 0.0
if key&2 : addang HGOBJ_CAMERA, 0.02, 0.0
}else{; カメラをカーソルキーで動かす
if key&1 : addpos HGOBJ_CAMERA, -0.2, 0.0
if key&4 : addpos HGOBJ_CAMERA, 0.2, 0.0
if key&8 : addpos HGOBJ_CAMERA, 0.0, 0.2
if key&2 : addpos HGOBJ_CAMERA, 0.0, -0.2
}
_pcvsetcang //カメラ操作した後にhgpcv側にも設定
_pcvsetcpos
hg_getwpos objafv,mox,moy,-10 //マウス座標を3D座標に
selpos objbox
objsetfv objafv
_getfvector mvxyz,mox,moy //レイの方向ベクトル収得
if mvxyz(1)!0.0{
getpos HGOBJ_CAMERA,cx,cy,cz
title ""+cy+" "+mvxyz(1)
_getfvwpos mvxyz,-(cy/mvxyz(1)) //ベクトルからカメラのy座標を割ってカメラからの距離にしてワールド座標に
mvxyz(1)-3
selpos obja
objsetfv mvxyz
}
oidcnt=0
findobj 0,2
repeat
nextobj oid
if oid<0{break}
selpos oid
objgetfv fv
hg_getspos fv,x(oidcnt),y(oidcnt),z(oidcnt) //3D座標から2D座標に(3D空間でスクリーンの中心だったら0,0)
oidcnt++
loop
hgdraw
color 255,0,0:gmode 3,32,32,128
repeat oidcnt
hgrect x(cnt)+320,y(cnt)+240,,limit(120+z(cnt),10,120),limit(120+z(cnt),10,120)
loop
hgsync 15
await 0
mox=mousex-320
moy=mousey-240
loop
end