OGRE中实现鼠标选取

MovableObject* CMFCRenderView::pick3D( Real relX, Real relY )
{

    // 首先获得从摄像机出发穿过视口上某点的射线

    Ray pickRay = mCamera->getCameraToViewportRay( relX, relY ); 

    // 基于刚才的射线创建一个查询
    RaySceneQuery* query = mSceneMgr->createRayQuery( pickRay );  

    // 根据距离排序,只返回最近的一个MovableObject。设定查询掩码,
    // 这里的查询掩码是客户程序自己指定的,使用MovableObject的setQueryFlags接口

    query->setSortByDistance( true, 1 );
    query->setQueryMask( OGRE_HEAD_ENTITY_FLAG ); 

    // 执行查询
    RaySceneQueryResult& result = query->execute();

    // 因为指定返回最近的MovableObject,只需要判断是否有结果返回即可
    MovableObject *closestObject = NULL;
    RaySceneQueryResult::iterator rayIterator = result.begin(); 
    if( rayIterator != result.end() )
      closestObject = rayIterator->movable;

    // 清除查询结果并释放查询对象
    query->clearResults( ); 
    mSceneMgr->destroyQuery( query );

    // 返回结果
    return closestObject;
}

需要注意的是上面代码中的屏幕坐标是normal之后的坐标,范围为[0,1]

  RECT clientRect;

  GetClientRect( &clientRect );

  MovableObject *pickObject = pick3D(

    ( Real )point.x/( Real )clientRect.right, 
    ( Real )point.y/( Real )clientRect.bottom );

还有个需要注意的是查询的时候指定的掩码,Entity对象(从MovableObject继承)掩码初始化为
0xffffffff, 只要使用任何非0的值去标识某组对象然后查询,都会错误的得到射线上的所有Entity对象!暂时还没有发现办法改变默认值,只能手工将不想查询的对象的queryflag设置为0.

 

以下演示的是查询与地面的交点增加模型:

代码:

//--------------------------------------------------------------------------------
void CMainView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    //get mouse pos and translate
    static POINT mousePos;
    GetCursorPos(&mousePos);
    ScreenToClient(&mousePos);

    //get client rect
    RECT rect;
    GetClientRect(&rect);

    Ray mouseRay = m_Camera->getCameraToViewportRay(
        mousePos.x/float(rect.right),
        mousePos.y/float(rect.bottom));
    m_raySceneQuery->setRay(mouseRay);
    m_raySceneQuery->setSortByDistance(true);

    // Execute query
    RaySceneQueryResult &result = m_raySceneQuery->execute();
    RaySceneQueryResult::iterator itr;

    // Get results, create a node/entity on the position
    for ( itr = result.begin(); itr != result.end(); itr++ )
    {
        if (itr->movable && itr->movable->getName().substr(0, 5) != "tile[")
        {
            mCurrentObject = itr->movable->getParentSceneNode();
            break;
        } // if
        else if (itr->worldFragment)
        {
            Entity *ent;
            char name[16];

            static int mCount=0;
            sprintf(name, "Robot%d", mCount++);
            ent = m_SceneManager->createEntity(name, "robot.mesh");

            mCurrentObject = m_SceneManager->
                getRootSceneNode()->createChildSceneNode(
                String(name) + "Node", itr->worldFragment->singleIntersection);
            mCurrentObject->attachObject(ent);
            mCurrentObject->setScale(0.1f, 0.1f, 0.1f);
            break;
        } // else if
    } // for

    CView::OnLButtonDown(nFlags, point);
}

image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值