鼠标抓取

--------------------西昌.何雨锋 鼠标抓取
让鼠标抓住东西也就是鼠标直接碰撞检测,那是肯定不行的,至少用对象
TVCollisionResult是决对行不通的,因为那会出现实时错误,那么怎么判断一个鼠标已经对准了一个东西的什么位置呢?
只有从global上想办法了,因为VB下有而C++中没有的什么数学函数啦,什么其他类型啦都在里面找得到。
global1->MovePoint(&结果点,&源点,x角度,y角度,距离)
这个函数的作用是已知一个源点坐标,也知道这个源点坐标要转xy角度对准了一个方向,请问距离多少多少的那个点的三维坐标。
通过这个函数,我们就可以让源点是摄像机的点,再知道转动的角度(就是那两个xangle和yangle)然后再将幅度转换成角度就可以
得到固定距离处那个点的坐标,这样我们就得到了从摄象点到lookat点的一条直线,用高级碰撞不就可以知道撞到哪里了吗?
以下是具体使用方法:
****************
global1->MovePoint(&vector3,&vector2,-xangle * 180 / 3.14,90-yangle*180/3.14,2000);
//这样vector3就是vector2点出发,旋转xangle与yangle后距离2000的点了。
//这样就得到了屏幕正中所发射出的直线了。
****************
当然了,还有一个函数为global1->MousePickVector(mousex,mousey,&vector2,&vector3);
也就是将鼠标的位置形成两个点,一个是观察起点,一个是鼠标指向的位置点,
但是一定要注意,这里的mousex,mousey必须是input1->GetAbsMouseState()得到的值,而不是input1->GetMouseState()得到的值,否则出来的线就会偏很远。
下面的例子是一个用鼠标点中陆地,就将人物放在碰撞位置的例子:
*****************
TV_COLLISIONRESULT col1;   //注意,这里绝对不能用ITVCollisionResult,否则实时错误必然出现
//甚至不需要建立出来。
if(mouse_b1)   //当鼠标按下时,判断是否碰撞
 {  
  input1->GetAbsMouseState(&mousex,&mousey,(short *)&mouse_b1,(short *)&mouse_b2,(short *)&mouse_b3);       
//必须是input1->GetAbsMouseState()得到的值,而不是input1->GetMouseState()得到的值
  global1->MousePickVector(mousex,mousey,&vector2,&vector3);
//得到鼠标的起点与终点。
  scene1->AdvancedCollision(&vector2,&vector3,&col1,TV_COLLIDE_LANDSCAPE,TV_TESTTYPE_ACCURATETESTING,tvtrue);
//与陆地进行碰撞检测,检测到的结果给col1
        if(col1.hascollided)
  {
     man2->SetPosition(col1.collisionimpact.x,col1.collisionimpact.Y,col1.collisionimpact.Z);
//注意这里碰撞点的xyz的大小写。
  }           
 }
//如果是第一人称射击,这里就改成
global1->MousePickVector(mousex,mousey,&vector2,&vector3);//这里只需要得到vector2,也就是摄像机的位置,vector3鼠标点的位置在这里没用
global1->MovePoint(&vector3,&vector2,-xangle * 180 / 3.14,90-yangle*180/3.14,2000);
//这里是以玩家的当前位置出发,旋转的x角度与y角度,距离2000的一个点(也就是屏幕正中瞄准的那个点)
//然后再做同上的碰撞检测就知道中心瞄准器瞄准了什么了。

******************
碰撞到的结果装在TV_COLLISIONRESULT结构里,它有以下成员可供访问:
collisionnormal      普通的点
collisionimpact      碰撞的点
distance             碰撞距离
U  U barycentric coordinate for collided face. 
v  V barycentric coordinate for collided face. 
faceindex            面的index(for meshs) 
GroupIndex           碰撞组的index(for meshs) 
hascollided          是否碰撞 
collidedobjecttype   long 碰撞物体类型
entityid             角色id(for actors和actor2) 
MeshID               物体的id(for mesh) 
landscapeid          陆地的id (for landscape) 
boneId               骨骼的id(for actor2 with bones) 

如果要抓取的对象是多个,有的是一个,有的是用一个数组建立出来的多个,那么会发现这些对象的ID很可能是岔开了的,
怎么才能准确的判断出是哪一个对象被抓取了呢?

一般在碰撞后只能用循环的办法判断出是哪个被抓取了,比如mesh:
        scene1->AdvancedCollision(&vector2,&vector3,&col1,TV_COLLIDE_MESH,TV_TESTTYPE_ACCURATETESTING,tvtrue);
        if(col1.hascollided)
 {   
         tickid=col1.MeshID;
                        for(i=0;i<8;i++)
   {
    if(col1.MeshID==obj1[i]->GetMeshIndex())
       obj1[i]->SetPosition(0,0,0);
   }
  }

但是要把所有的物体遍历到可不容易啊.....,是不是TVCollisionResult要好一些呢?

常数:
CONST_TV_OBJECT_TYPE

TV_COLLIDE_MESH = 1 
TV_COLLIDE_TERRAIN = 2 
TV_COLLIDE_LANDSCAPE = 4 
TV_COLLIDE_BSPTREE = 8 
TV_COLLIDE_OCTREE = 16 
TV_COLLIDE_ACTOR = 32 
TV_COLLIDE_PHYSICOBJECT = 64 
TV_COLLIDE_ACTOR2 = 128 
}

CONST_TV_TESTTYPE 
{
TV_TESTTYPE_BOUNDINGBOX = 1  Uses ray-boundingbox collision 
TV_TESTTYPE_BOUNDINGSPHERE = 2  Uses ray-boundingsphere collision 
TV_TESTTYPE_ACCURATETESTING = 3  Uses ray-triangle collision 
TV_TESTTYPE_MDL_HITBOXES = 4 
}

------------------以下为解释贴:
在VB中一般用TVCollisionResult对象,这个对象用起来很容易,如col=land->mousepick(..)、col=scene->mousepick(...)的都可以,但是在C+下面无论怎么样一用col->iscollision()都会出现实时错误,根本无法使用。

但是这个小组还开发了一个结构(不是对象)叫TV_COLLISIONRESULT,这个结构可以被用到一些高级碰撞的检测中。(而且这些碰撞检测函数还只能用TV_COLLISIONRESULT结构而不能用TVCollisionResult对象),比如:

scene1->AdvancedCollision(&vector2,&vector3,&col1,TV_COLLIDE_LANDSCAPE,TV_TESTTYPE_ACCURATETESTING,tvtrue);

中的col1就是TV_COLLISIONRESULT,这个函数用来检测vector2,vector3两点连线是否穿过land,那么如何把mouse的二维坐标转换成场景中的三维点呢?同样,在Global这个包罗了很多函数的对象中有两个函数:

global1->MousePickVector(mousex,mousey,&vector2,&vector3);  //当然这里的mousex,mousey都得从GetABSMouseState(...)中而非GetMouseState()中得到。

这样就获得了两个点,vector2代表了摄象机的位置(当然也可以建立出摄象机然后用场景相机赋给它,但那就要稍复杂些),vector3代表的就是鼠标在三维场景中点中的那个点了(当然那个点很远很远),得到了这两个点再配合上前面的高级碰撞检测函数就实现了VB中的TVCollisionResult col=scene->mousepick(...)的同等功能了.

如果是第一人称射击的话,这个过程还可以简化至:

global1->MousePickVector(mousex,mousey,&vector2,&vectorx);  //这里的vectorx毫无用处,因为根本没必要知道鼠标点中哪里,我们要的实际就是camera.position   :)
global1->MovePoint(&vector3,&vector2,-xangle * 180 / 3.14,90-yangle*180/3.14,2000);

//这个函数的意义在于已知一个空间点vector2(实际就是主角的位置),以这个空间点为中心,沿x,y分别转动xangle,yangle幅度,距离2000的得到的点坐标vector3 (这里的xangle与yangle是幅度,我只是用些公式把它转化成了角度而已,还记得VB例子中所有第一人称动作的教程都是只能左转右转而不能象CS那样左右平移的吗?而VC6里虽然教程很少,但是凡FPS的都是左右平移的,而望向方向与绝对坐标的夹角就是这个xangle与yangle,为了得到这个公式,身为数学盲的我花了整整3个热得不得了的晚上的时间才实践出来的,这个公式稍微修改后还可用于my枪始终on my front这个问题上),这两个点就是屏幕中央(实际就是瞄准器中央而不是鼠标)发出子弹的弹道了.
----------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值