hgimg3を使うかどうかは分からないけど
一応球のオブジェクト判定のモジュール
http://hsp.tv/play/pforum.php?mode=pastwch&num=58413
ここ↑で使ったモジュールに命令追加
#include "hgimg3.as"
//必ず#include "hgimg3.as"の後に配置
#module
#uselib "User32.dll"
#func SetRectfloat "SetRect" var,float,float,float,float
#define setfloat4(%1,%2=0.0,%3=0.0,%4=0.0,%5=0.0) %1(3) + 0:SetRectfloat %1,%2,%3,%4,%5
#uselib "d3dx9_39.dll"
#cfunc D3DXSphereBoundProbe "D3DXSphereBoundProbe" var,float,var,var
//[---モジュールの初期化---]
//cnvsptowp_init
//必ずhginiの後に実行(カメラのefxグループを変更したりスクリーンサイズを変更した時も実行する必要がある)
//返り値refdvalにスクリーン座標系から3D座標系に変換する実数値が返る
//refdval*スクリーン座標*カメラからの距離で2Dから3Dに出来る
#deffunc cnvsptowp_init
getefx HGOBJ_CAMERA,FOV,NearZ,FarZ
ssx=1.0*ginfo_sx
ssy=1.0*ginfo_sy
whsx=0.5*ssx
whsy=0.5*ssy
wwx=ssx/ginfo_winx
wwy=ssy/ginfo_winy
tc=sin(0.5*FOV)/cos(0.5*FOV)/whsy
return tc
//[---スクリーン座標をワールド座標に変換---]
//fvstw wp, sx, sy, cdz
// wp = 3D座標を取得する配列(wp=x,y,z)
// sx = スクリーンX座標指定
// sy = スクリーンY座標指定
// cdz = カメラからの距離を3D座標系で指定(プラスがカメラの前方向)
//カメラの移動回転に対応
#deffunc fvstw array wp,double sx,double sy,double cdz
getpos HGOBJ_CAMERA,cpx,cpy,cpz
getang HGOBJ_CAMERA,crx,cry,crz
fvset wp,crx,-cry,crz
fvdir wp,(((sx-whsx/wwx)*cdz*tc)*wwx),(sy-whsy/wwy)*cdz*tc*wwy,-cdz
fvadd wp,cpx,cpy,cpz
return
//[---スクリーン座標からレイを飛ばすベクトルを取得---]
//fvray rvec, sx, sy, cdz
// rvec = レイのベクトル(rvec=vx,vy,vz)
// sx = スクリーンX座標指定
// sy = スクリーンY座標指定
// cdz = カメラからの距離を3D座標系で指定
//カメラの移動回転に対応
#deffunc fvray array rvec,double sx,double sy
getang HGOBJ_CAMERA,crx,cry,crz
fvset rvec,crx,-cry,crz
fvdir rvec,(((sx-whsx/wwx)*tc)*wwx),(sy-whsy/wwy)*tc*wwy,-1.0
return
//[---スクリーン座標からレイを飛ばしてワールドY座標が0になる時のワールドX,Z座標を取得---]
//getRayPos wpx, wpy, wpz, sx, sy
// wpx = 3DX座標を取得
// wpy = 3DY座標を取得
// wpz = 3DZ座標を取得
// sx = スクリーンX座標指定
// sy = スクリーンY座標指定
//カメラの移動回転に対応
#deffunc getRayPos var wpx,var wpy,var wpz,double sx,double sy
fvray _rvec, sx, sy
getpos HGOBJ_CAMERA,cpx,cpy,cpz
if 0.0 = _rvec(1) {_rvec(1)=0.00000001}//_rvec(1)が0.0だと次の行で割り算に使えないので適当な小さい数値を入れる(これは地面方向の傾きが0の時の対策)
dis=-cpy/_rvec(1) //カメラの高さをレイのYで割るとY座標0までのカメラからの距離が出る
fvmul _rvec,dis,dis,dis //レイの方向ベクトルに距離を掛ければワールド座標になる
fvadd _rvec,cpx,cpy,cpz //カメラ座標を足してカメラを基準にした座標にする (この二行は fvstw _rvec,sx,sy,dis に置き換ても同等の事が出来る)
wpx=_rvec
wpy=_rvec(1)
wpz=_rvec(2)
return
//[---スクリーン座標からレイを飛ばしてオブジェクトの球と接触判定、交点取得、ドラッグする---]
//getSphereRayColl tid, ip, msize, sx, sy, f, exmode, group, mode
// tid = レイと接触した球のオブジェID(出力)[接触が無ければ-1]
// ip = レイと接触したxyz座標(出力)[ip=x,y,z 但しドラッグ中は最初に接触した部分を掴んでる感じになる]
// msize = 球のモデルサイズ(入力)[これにオブジェクトスケールを掛けて利用]
// sx = スクリーンX座標指定(入力)
// sy = スクリーンY座標指定(入力)
// f = 判定用キー(入力)[0以外なら接触判定をしてドラッグ、0なら判定ドラッグ解除]
// exmode = 検索を除外するモード(入力)[findobjの解説を参照]
// group = 検索対象コリジョングループ値(入力)[findobjの解説を参照]
// mode = 検索モード(入力)[0=接触判定をしてドラッグ、1=接触判定のみ]
//システム変数refdvalにカメラから交点の距離が返る
#deffunc getSphereRayColl var tid,array ip,double msize,double sx,double sy,int f,int exmode,int group,int mode
if f {
if (tf=0) or (mode&1) {
tf=0
getpos HGOBJ_CAMERA,cx,cy,cz
setfloat4 RayPosition_f,cx,cy,cz//ベクトルdoubleをfloatにして配列に入れる
sx_bak=sx
sy_bak=sy
fvray _rvec, sx, sy //レイベクトル
setfloat4 RayDirection_f,_rvec(0),_rvec(1),_rvec(2)
fvset inrv,_rvec(0),_rvec(1),_rvec(2)
fvinner inrv,_rvec(0),_rvec(1),_rvec(2)
fvset ip,0.0,0.0,0.0
ttim=0.0
findobj exmode,group
repeat
nextobj obj_id
if obj_id<0 {
if tf {
ip=cx +_rvec(0) * ttim ,cy +_rvec(1) * ttim ,cz +_rvec(2) * ttim
hgcnvaxis tdx,tdy,tdz,ip,ip(1),ip(2),2
selpos tid
objgetfv difxyz
fvsub difxyz,ip,ip(1),ip(2) //交点からオブジェクトまでの差分
_tid=tid
}else{tid=-1}
break
}
getscale obj_id,obj_sclx,obj_scly,obj_sclz
hsize=0.5*obj_sclx*msize //球の半径
getpos obj_id,ox,oy,oz
setfloat4 SphereCenter_f,ox,oy,oz
//光線が球の境界ボックスに当たるかどうかを判定
if D3DXSphereBoundProbe(SphereCenter_f,hsize,RayPosition_f,RayDirection_f) {//当った
cox=cx-ox
coy=cy-oy
coz=cz-oz
fvset inrvco,_rvec(0),_rvec(1),_rvec(2)
fvinner inrvco,cox,coy,coz
fvset inco,cox,coy,coz
fvinner inco,cox,coy,coz
inco-=hsize * hsize
tim = ( -inrvco - sqrt( inrvco * inrvco - inrv * inco) ) / inrv //接触までの時間
if (ttim > tim) or tf=0 {
ttim=tim
tf=1 //接触したフラグ
tid=obj_id
}
}
loop
}else{
if (sx_bak ! sx) or (sy_bak !sy) {
fvstw ip, sx, sy, -tdz
setpos _tid,ip+difxyz,ip(1)+difxyz(1),ip(2)+difxyz(2) //差分を加算
}
}
}else{
fvset ip,0.0,0.0,0.0
tf=0
tid=-1
tdz=0.0
}
return tdz
#global
//モジュールここまで
randomize
screen 0,800,600,0
cls 4
hgini
//必ずhginiの後に実行(カメラのefxグループを変更したりスクリーンサイズを変更した時も実行)
cnvsptowp_init
setfont 16,16,12,1 ; font Tex select(cx,cy,px,mode)
texload "fontchr.bmp" ; フォントテクスチャの登録
msize=14.5 //モデルのサイズ
addxfile m_xmodel,dir_exe+"\\sample\\hgimg3\\eye.x"
repeat 40
regobj obj, m_xmodel ; オブジェクトの登録
setpos obj,150-rnd(300),150-rnd(300),-150-rnd(200)
scl=0.5+0.01*rnd(400)
setscale obj,scl,scl,scl
setcoli obj,2,1
loop
clscolor $80 ; 背景色の設定
*main
stick key,$3ff
if key&128 : goto *owari
getSphereRayColl target_id,ipfv,msize,mousex,mousey,key&256,0,2,0
if target_id>0 {
addang target_id,0,0.05,0
}
hgdraw ; 描画
title str(target_id)+" x="+ipfv+" y="+ipfv(1)+" z="+ipfv(2)
hgsync 10 ; 時間待ち
if key&512 {//マウス右ドラッグでカメラ回転
addang HGOBJ_CAMERA, 0.01*(my-mousey), 0.01*(mx-mousex)
}
mx=mousex
my=mousey
//マウスホイール回転でカメラZ軸移動
addpos HGOBJ_CAMERA, 0.0, 0.0, 0.05*mousew
; カーソルキーでカメラXY軸移動
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
goto *main
*owari
end
一番近い球を検索するのに総当りになるから
どれぐらいの数まで使い物になるかは分からない