Well it does come kinda close to working, but still no cigar..
Test it by creating a 10x10 grid, and check the mouse position as it goes around the grid.. it comes up very inaccurate.
with my camera facing the origin (0,0,0) at location: (8,10,4) with an up vector of (0,1,0) it works good in perspective projection.
perspective projection:
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 100.0f );
however, if i change the camera location to be (0,10,4) with up vector of (0,1,0) the coordinates do not come out correctly any more.
when i hold the mouse over the grid line at ''1'', it says i have intersected at .5 ..
how does the camera location affect the outcome of this function so much? this is in perspective projection!
in orthogonal projection at the same camera position it says: 18.9,0,17.27 at (1,0,0) this is obviously unsatisfactory.
i dont know how you have your view matrix set up, but i can assure you if you change your camera''s (view matrix) location your coordinates will not come up correct.
i have attatched the code i used below. it is basically a stripped "Pick" example that where i have removed the mesh and put in a 10x10 grid centered at the origin. I am calling D3DXPlaneIntersectsLine to get the world coordinates from the "pick ray".
What Gives? I know i''m not messing this stuff up that bad.. There is definately something wrong with D3DXVec3Unproject, for it doesnt even work when the camera is at different angles.
any more ideas? There must be a way to do this correctly.. they got projected to the screen somehow..
Zygote-
#define STRICT#include <math.h>#include <stdio.h>#include <D3DX8.h>#include "D3DApp.h"#include "D3DFont.h"#include "D3DFile.h"#include "D3DUtil.h"#include "DXUtil.h"#include "Resource.h"bool g_ortho = false;D3DXVECTOR3 g_mouse;D3DXVECTOR3 g_cam;struct lineVert{ D3DXVECTOR3 p; D3DCOLOR color;};#define FVF_LINE ( D3DFVF_XYZ | D3DFVF_DIFFUSE )//-----------------------------------------------------------------------------// Name: Pick()// Desc: Checks if mouse point hits geometry// the scene.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::Pick(){ POINT ptCursor2; GetCursorPos( &ptCursor2 ); ScreenToClient( m_hWnd, &ptCursor2 ); D3DVIEWPORT8 viewport; m_pd3dDevice->GetViewport(&viewport); SHORT ScreenX = ptCursor2.x; SHORT ScreenY = ptCursor2.y; D3DXMATRIX w, v, p; D3DXMatrixIdentity(&w); m_pd3dDevice->GetTransform( D3DTS_VIEW, &v ); m_pd3dDevice->GetTransform( D3DTS_PROJECTION, &p ); D3DXVECTOR3 in, RayPos, RayPos2, Intersect; // Get the inverse view matrix (eye position) D3DXMATRIX iv; D3DXMatrixInverse( &iv, NULL, &v ); in.x = iv._41; in.y = iv._42; in.z = iv._43; D3DXVec3Unproject(&RayPos, &in, &viewport, &p, &v, &w); //RayPos = in; in.x = ScreenX; in.y = ScreenY; if( g_ortho ) { in.z = 0.0f; } else { in.z = 1.0f; } D3DXVec3Unproject(&RayPos2, &in, &viewport, &p, &v, &w); D3DXPLANE plane; D3DXPlaneFromPointNormal( &plane, &D3DXVECTOR3(0,0, 0), &D3DXVECTOR3(0,1,0) ); D3DXPlaneIntersectLine(&Intersect, &plane, &RayPos, &RayPos2); g_mouse = Intersect; return 1; }//-----------------------------------------------------------------------------// Name: FrameMove()// Desc: Called once per frame, the call is the entry point for animating// the scene.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::FrameMove(){ // Rotate the camera about the y-axis D3DXVECTOR3 vFromPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); vFromPt.x = 8.0f; vFromPt.y = 10.0f; vFromPt.z = 8.0f; D3DXMATRIX matView; D3DXMatrixLookAtLH( &matView, &vFromPt, &vLookatPt, &vUpVec ); m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); return S_OK;}//-----------------------------------------------------------------------------// Name: Render()// Desc: Called once per frame, the call is the entry point for 3d// rendering. This function sets up render states, clears the// viewport, and renders the scene.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::Render(){ // Set up the cursor POINT ptCursor; GetCursorPos( &ptCursor ); ScreenToClient( m_hWnd, &ptCursor ); m_pd3dDevice->SetCursorPosition( ptCursor.x, ptCursor.y, 0L ); // Check for picked triangles Pick(); // Clear the viewport m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0L ); // Begin the scene if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) { // Set render mode to lit, solid triangles m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); // If a triangle is picked, draw it if( m_dwNumIntersections > 0 ) { // Draw the picked triangle m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX ); m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(D3DVERTEX) ); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, m_dwNumIntersections ); // Set render mode to unlit, wireframe triangles m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME ); m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); } // Set render mode to unlit, wireframe triangles m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME ); m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); int width = 10; for(int x=-10;x<11;x++) { lineVert v[2]; if(x == 0) { v[0].color = D3DCOLOR_XRGB(0,0,0); v[1].color = D3DCOLOR_XRGB(0,0,0); } else if(x % 2 == 0) { v[0].color = D3DCOLOR_XRGB(100,100,100); v[1].color = D3DCOLOR_XRGB(100,100,100); } else { v[0].color = D3DCOLOR_XRGB(255,0,0); v[1].color = D3DCOLOR_XRGB(255,0,0); } v[0].p.x = x; v[0].p.y = 0; v[0].p.z = -width; v[1].p.x = x; v[1].p.y = 0; v[1].p.z = width; m_pd3dDevice->SetVertexShader(FVF_LINE); m_pd3dDevice->DrawPrimitiveUP(D3DPT_LINELIST,1,(void*)v,sizeof(lineVert)); v[0].p.x = -width; v[0].p.y = 0; v[0].p.z = x; v[1].p.x = width; v[1].p.y = 0; v[1].p.z = x; m_pd3dDevice->DrawPrimitiveUP(D3DPT_LINELIST,1,(void*)v,sizeof(lineVert)); } // Render the mesh m_pObject->Render( m_pd3dDevice ); // Output statistics char buff[255]; sprintf(buff,"mouse world: (%.2f,%.2f,%.2f)",g_mouse.x,g_mouse.y,g_mouse.z); m_pFont->DrawText( 2, 0, D3DCOLOR_ARGB(255,255,255,0), buff); sprintf(buff,"camera loc: (%.2f,%.2f,%.2f)",g_cam.x,g_cam.y,g_cam.z); m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), buff); // End the scene. m_pd3dDevice->EndScene(); } return S_OK;}//-----------------------------------------------------------------------------// Name: RestoreDeviceObjects()// Desc: Initialize scene objects.//-----------------------------------------------------------------------------HRESULT CMyD3DApplication::RestoreDeviceObjects(){ m_pFont->RestoreDeviceObjects(); m_pFontSmall->RestoreDeviceObjects(); // Set miscellaneous render states m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, FALSE ); m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE ); m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00444444 ); // Set the world matrix D3DXMATRIX matIdentity; D3DXMatrixIdentity( &matIdentity ); m_pd3dDevice->SetTransform( D3DTS_WORLD, &matIdentity ); // Set the projection matrix D3DXMATRIX matProj; FLOAT fAspect = ((FLOAT)m_d3dsdBackBuffer.Width) / m_d3dsdBackBuffer.Height; if(GetKeyState(VK_SPACE) & 0x80) g_ortho = true; else g_ortho = false; if(g_ortho) { D3DXMatrixOrthoLH(&matProj,40,40,1,100); } else { D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 100.0f ); } m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); // Setup a material D3DMATERIAL8 mtrl; D3DUtil_InitMaterial( mtrl, 1.0f, 1.0f, 1.0f, 1.0f ); m_pd3dDevice->SetMaterial( &mtrl ); // Set up lighting states D3DLIGHT8 light; D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.1f, -1.0f, 0.1f ); m_pd3dDevice->SetLight( 0, &light ); m_pd3dDevice->LightEnable( 0, TRUE ); m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); return S_OK;}