Функция выбора C ++ не работает - PullRequest
0 голосов
/ 15 ноября 2010

У меня есть эта функция выбора, но она не работает.функция должна возвращать true, если она сталкивается с объектом, но возвращает 0;и это никогда не изменится.
вот моя функция выбора

BOOL D3dDevice::Picking(HWND hWnd, LPDIRECT3DDEVICE9 d3ddev, CXFileEntity *entity)
{
 D3DXVECTOR3 v;
 D3DXMATRIX matProj;
 POINT pt;
 D3DVIEWPORT9 vp;
 GetCursorPos(&pt);
 ScreenToClient(hWnd, &pt);
 d3ddev->GetTransform(D3DTS_PROJECTION, &matProj);
 d3ddev->GetViewport(&vp);
 v.x =  ( ( ( 2.0f * pt.x ) / vp.Height  ) - 1 ) / matProj._11;
 v.y = -( ( ( 2.0f * pt.x ) / vp.Width ) - 1 ) / matProj._22;
 v.z =  1.0f;

 D3DXMATRIX m;
 D3DXVECTOR3 rayOrigin,rayDir;
 D3DXMATRIX matView;
 d3ddev->GetTransform(D3DTS_VIEW, &matView);

 D3DXMatrixInverse( &m, NULL, &matView );

 // Transform the screen space pick ray into 3D space
 rayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
 rayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
 rayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
 rayOrigin.x = m._41;
 rayOrigin.y = m._42;
 rayOrigin.z = m._43;

 // Use inverse of matrix
 D3DXMATRIX matInverse, matWorld;
 d3ddev->GetTransform(D3DTS_WORLD, &matWorld);

 // Use inverse of matrix
 D3DXMatrixInverse(&matInverse,NULL,&matWorld);

 // Transform ray origin and direction by inv matrix
 D3DXVECTOR3 rayObjOrigin,rayObjDirection, rayDirection;

 D3DXVec3TransformCoord(&rayObjOrigin,&rayOrigin,&matInverse);
 D3DXVec3TransformNormal(&rayObjDirection,&rayDirection,&matInverse);
 D3DXVec3Normalize(&rayObjDirection,&rayObjDirection);

 BOOL hasHit;
 float distanceToCollision;

 D3DXIntersect(entity->pDrawMesh, &rayObjOrigin, &rayObjDirection, &hasHit, NULL, NULL, NULL, &distanceToCollision, NULL, NULL);

 return hasHit;
}

примечание: мой pDrawMesh является изменяемым LPD3DXMESH, а не LPD3DXBASEMESH. ОБНОВЛЕНИЕ

BOOL D3dDevice::Picking(HWND hWnd, LPDIRECT3DDEVICE9 d3ddev, CXFileEntity *entity)
{
    D3DXVECTOR3 v;
    D3DXMATRIX matProj;
    POINT pt;
    D3DVIEWPORT9 vp;
    D3DXMATRIX matInverse, matWorld;
    D3DXMATRIX m;
    D3DXVECTOR3 rayOrigin,rayDir;
    D3DXMATRIX matView;
    D3DXVECTOR3 rayObjSpace;
    D3DXVECTOR3 rayObjOrigin,rayObjDirection, rayDirection;

    GetCursorPos(&pt);
    ScreenToClient(hWnd, &pt);
    d3ddev->GetTransform(D3DTS_PROJECTION, &matProj);
    d3ddev->GetViewport(&vp);

    d3ddev->GetTransform(D3DTS_VIEW, &matView);

    // Use inverse of matrix
    d3ddev->GetTransform(D3DTS_WORLD, &matWorld);
    D3DXVECTOR3 vec3( pt.x, pt.y, 1.0f );
    D3DXVec3Unproject( &rayObjSpace, &vec3, &vp, &matProj, &matView, &matWorld );
    // Transform ray origin and direction by inv matrix

    D3DXMATRIX invWorld;
    D3DXMatrixInverse( &invWorld, NULL, &matWorld );

    D3DXVECTOR3 camObjSpace;
    D3DXVECTOR3 camPos(0.0, 0.0, -14.0f);
    D3DXVec3TransformCoord( &camObjSpace, &camPos, &invWorld ); 

    rayDir = rayObjSpace - camObjSpace;

    BOOL hasHit;
    float distanceToCollision;

    if(FAILED(D3DXIntersect(entity->pDrawMesh, &rayObjSpace, &rayDir, &hasHit, NULL, NULL, NULL, &distanceToCollision, NULL, NULL)))
    {
        PostQuitMessage(0);
    };

    if(hasHit==1)
    {
        PostQuitMessage(0);
    }

    return hasHit;
}

ОБНОВЛЕНИЕ 2: Теперь оно не пересекается; /.BOOL D3dDevice :: Picking (HWND hWnd, LPDIRECT3DDEVICE9 d3ddev, CXFileEntity * entity, int z) {D3DXVECTOR3 v;POINT pt;D3DVIEWPORT9 vp;D3DXMATRIX matInverse, matWorld, m, matView, matProj;

    GetCursorPos(&pt);
    ScreenToClient(hWnd, &pt);
    d3ddev->GetTransform(D3DTS_PROJECTION, &matProj);
    d3ddev->GetViewport(&vp);
    d3ddev->GetTransform(D3DTS_WORLD, &matWorld);
    d3ddev->GetTransform(D3DTS_VIEW, &matView);

    // Use inverse of matrix
    D3DXVECTOR3 rayPos(pt.x, pt.y,0); // near-plane position
    D3DXVECTOR3 rayDir(pt.x, pt.x,1); // far-plane position
    D3DXVec3Unproject(&rayPos,&rayPos,&vp,&matProj,&matView,&matWorld);
    D3DXVec3Unproject(&rayDir,&rayDir,&vp,&matProj,&matView,&matWorld);
    rayDir -= rayPos; // make a direction from the 2 positions
    D3DXVec3Normalize(&rayDir,&rayDir); // don't know if this is necessary.
    // Transform ray origin and direction by inv matrix

    BOOL hasHit;
    float distanceToCollision;

    if(FAILED(D3DXIntersect(entity->pDrawMesh, &rayPos, &rayDir, &hasHit, NULL, NULL, NULL, &distanceToCollision, NULL, NULL)))
    {
        PostQuitMessage(0);
    };

    if(hasHit!=0)
        PostQuitMessage(0);

    return hasHit;
}

ОБНОВЛЕНИЕ 3: Хорошо, теперь оно всегда пересекается; / после изменения значений в этой функции

D3DXMatrixPerspectiveFovLH(&matProjection,
                               D3DXToRadian(45),    // the horizontal field of view
                               (FLOAT)Width / (FLOAT)Height, // aspect ratio
                               0.0f,   // the near view-plane
                               1.0f);    // the far view-plane

Ответы [ 2 ]

4 голосов
/ 16 ноября 2010

Сбор лучей - это весело.Вам нужно начать с преобразования координаты экрана в проекционное пространство.Поскольку пространство проекции DirectX (для x, y) варьируется от -1 до 1 в x и y, вам нужно сделать следующее:

float px = (((float)mousex / SCREEN_WIDTH) * 2.0f) - 1.0f;
float py = -(((float)mousey / SCREEN_HEIGHT) * 2.0f) - 1.0f;

Not py не имеет минус впереди, потому что координаты экрана идут сверхувниз, где пространство проекции противоположно.

Теперь у вас есть положение в пространстве проекции.Так что вам нужно создать вектор вдоль этой точки.К счастью, это тоже приятно и просто.

float pz = 1.0f;

Теперь мы можем откатить это обратно в пространство объектов:

D3DXVECTOR3 rayObjSpace;
D3DXVec3Unproject( &rayObjSpace, &rayOut, &viewport, &projectionMatrix, &viewMatrix, &worldMatrix );

Наконец, подключите это к D3DXIntersect, и вы готовы к работе:)

Редактировать : Я понимаю, что в моем объяснении выше есть ошибка.Фактически с D3DXVec3Unproject вы можете передать действительную экранную координату x, y с az, равным 1.

Итак:

D3DXVECTOR3 vec3( mousex, mousey, 1.0f );
D3DXVECTOR3 rayObjSpace;
D3DXVec3Unproject( &rayObjSpace, &vec3, &viewport, &projectionMatrix, &viewMatrix, &worldMatrix );

Намного проще.Поскольку преобразование порта просмотра применяется дважды.

Тем не менее, вы сказали, что вы на самом деле смотрели на полученные лучевые векторы?Они даже указывают на объект?

Редактировать 2: Хорошо, я буду более конкретным.Теперь у вас есть положение в мире точки, на которой вы щелкнули, вы можете рассчитать направление луча, выполнив следующие действия.

 D3DXMATRIX invWorld;
 D3DXMatrixInverse( &invWorld, NULL, &world );

 D3DXVECTOR3 camObjSpace;
 D3DXVec3TransformCoord( &camObjSpace, &camPos, &invWorld ); 

 D3XVECTOR3 rayDir = rayObjSpace - camObjSpace;

 BOOL bHit = FALSE;
 float distToHit = true;
 HRESULT hr = D3DXIntersect( pMesh, &rayObjSpace, &rayDir, &bHit, NULL, NULL, NULL, &distToHit, NULL, NULL );
0 голосов
/ 16 ноября 2010

Логика, которая устанавливает hasHit, находится в D3DXIntersect, который мы не можем видеть. Существует множество других функций (которые выглядят как функции C), которых мы тоже не видим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...