Jump to content
  • Advertisement
Sign in to follow this  
exextatic

Tracing a ray to a certain X value

This topic is 2448 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all,

I'm trying to work on an editor for my game, and I'm having issues tracing a ray to a certain point.
On click, the Editor needs to trace the mouse ray to the Z point of 3, and add a 'plane' (rectangle) at that point.
It seems to be getting in the right sort of area on click, but its always off.
33mmjwo.png
The red dot illustrates where I've clicked.
I've uploaded the files for you to play with (easier than me trying to explain)
http://jameswarner.c...ther/Editor.rar

And heres the code that handles the tracing of the ray and adding plane:
void Editor::addPlane(D3DXVECTOR3 oldMPos, D3DXVECTOR3 oldMDir, string texName, float* texScale, int whichForm)
{
D3DXMATRIX matView, matWorld;

d3ddev->SetTransform(D3DTS_WORLD, &matStart);
matWorld = matStart;

if(whichForm == 0)
{
fpsCamera->calculateViewMatrix(&matView);
cameraPos[whichForm] = fpsCamera->getPosition();
cameraEyePos[whichForm] = fpsCamera->getEyePos();
}
else
{
D3DXMatrixLookAtLH(&matView,
&cameraPos[whichForm],
&cameraEyePos[whichForm],
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f));
}
d3ddev->SetTransform(D3DTS_VIEW, &matView);

D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(45),
(FLOAT)screenSize[whichForm].x / (FLOAT)screenSize[whichForm].y,
1.0f,
100.0f);
d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);

POINT mousePos;
GetCursorPos(&mousePos);

D3DXVECTOR3 mouseOut, mouseOut2;
D3DVIEWPORT9 viewPort;

d3ddev->GetViewport(&viewPort);

ScreenToClient(hWnd[whichForm], &mousePos);

RECT temp;
GetClientRect(hWnd[whichForm], &temp);

D3DXVec3Unproject(&mouseOut, &D3DXVECTOR3(mousePos.x, mousePos.y, viewPort.MinZ), &viewPort, &matProjection, &matView, &matWorld);
D3DXVec3Unproject(&mouseOut2, &D3DXVECTOR3(mousePos.x, mousePos.y, viewPort.MaxZ), &viewPort, &matProjection, &matView, &matWorld);

float wz = 3.0f;
float wx = ((wz - mouseOut.z) * (mouseOut2.x - mouseOut.x)) / (mouseOut2.z - mouseOut.z) + mouseOut.x;
float wy = ((wz - mouseOut.z) * (mouseOut2.y - mouseOut.y)) / (mouseOut2.z - mouseOut.z) + mouseOut.y;
D3DXVECTOR3 mouseFinal = D3DXVECTOR3(wx, wy, wz);

addPlane(D3DXVECTOR2(mouseFinal.x, mouseFinal.y), D3DXVECTOR2(1.0f, 1.0f), 0.0f, PhysDefinition(NoPhysics, 0.0f, 0.0f, 0.0f), ForeGroundPlane, TextureDefinition(texName, D3DXVECTOR2(texScale[0], texScale[1]), 0.0f));
}


Any help appreciated

Thanks,
James

Share this post


Link to post
Share on other sites
Advertisement
I downloaded the app and gave it a try - the picking is correct when picking the centre of a viewport, but gets more and more wrong as you pick towards the edges, which indicates that the viewport size or FOV is possibly incorrect (I.e. the pick values don't match the render values).

I notice you use GetViewport() to get the viewport - are you sure this is returning the same viewport as you're clicking in?

You could try manually hacking the viewport values until it looks correct - I.e. try a viewport that's 10px bigger in X and Y, or try a slightly different FOV or something similar. When you get a viewport that gives you the values you expect, it might be obvious what the problem is by how much you had to fudge the values.

Share this post


Link to post
Share on other sites
Using
RECT temp;
GetClientRect(hWnd[whichForm], &temp);

Gets a different window size to that of the viewport and the recorded window size I have. (recorded window size and viewport size are the same)
May that be the cause?

Share this post


Link to post
Share on other sites
Yes, definitely. Your backbuffer, client area, and viewport should all have the same dimensions. Are you making sure to use AdjustWindowRect when creating your windows? Remember that CreateWindow() takes the size of the window, which may be larger than the size of the client area.

E.g. if you had a "normal" WS_OVERLAPPED style window, and you passed 800,600 for the width and height to CreateWindow, you may end up with a client area of 792x554 because of the extra space taken up by the window title bar and border. If your backbuffer is still 800x600, then it'll be stretched to fit your window at Present() time which may blur your output, and will certainly throw off any picking values you're using.

Share this post


Link to post
Share on other sites
All the swap chain window sizes are converted and stored like so:
RECT wr = {0, 0, windowWidths[0], windowHeights[0]};
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
screenSize[0].x = wr.right;
screenSize[0].y = wr.bottom;

wr.right = windowWidths[1]; wr.bottom = windowHeights[1];
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
screenSize[1].x = wr.right;
screenSize[1].y = wr.bottom;

wr.right = windowWidths[2]; wr.bottom = windowHeights[2];
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
screenSize[2].x = wr.right;
screenSize[2].y = wr.bottom;

wr.right = windowWidths[3]; wr.bottom = windowHeights[3];
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
screenSize[3].x = wr.right;
screenSize[3].y = wr.bottom;


All the windows are initialised like so:
for(int i = 0; i < 4; i++)
{
HRESULT hr;
d3dpp.BackBufferHeight = screenSize.y;
d3dpp.BackBufferWidth = screenSize.x;
d3dpp.hDeviceWindow = hWnd;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;

if(i > 0)
hr = d3ddev->CreateAdditionalSwapChain(&d3dpp, &swapchains);

}


Heres what happens when one of the windows resizes:
void Editor::updateBackBuffer(int width, int height, short which)
{
RECT wr = {0, 0, width, height};
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
screenSize[which].x = wr.right;
screenSize[which].y = wr.bottom;

d3dpp.BackBufferHeight = screenSize[which].y;
d3dpp.BackBufferWidth = screenSize[which].x;
d3dpp.hDeviceWindow = hWnd[which];


hasWindowResized = true;
}

hasWindowResized basically tells it to call this:
void Editor::doWindowUpdate()
{
invalidateDeviceObjects();

d3dpp.BackBufferHeight = screenSize[0].y;
d3dpp.BackBufferWidth = screenSize[0].x;
d3dpp.hDeviceWindow = hWnd[0];

HRESULT hr = d3ddev->Reset(&d3dpp);

if(hr != D3D_OK)
{
MessageBox(NULL, "Call to Reset() failed!", "ERROR", MB_OK | MB_ICONEXCLAMATION);
}

restoreDeviceObjects();

hasWindowResized = false;
}


Is there a way to check the backbuffer size while the app is running?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!