Question

I have an application which renders graphics onscreen using DirectX. The default view of first person is set using the below code, setting the Y axis to 0. The code is contained within the SetupCamera() function which is called prior to Render().

 D3DXVECTOR3 vCamera(5.0f, 0.0f, -45.0f); 

I am using DirectInput to manage user input. I want to be able to allow the user to press SPACE and change the Y axis value to 90 to switch to a top down view, then press again to switch it back. I currently have the below code in my ProcessKeyboardInput() function, called prior to Render().

if (KEYDOWN(buffer, DIK_SPACE))
{
  \\ ???    
}

but I am unsure what I need to do to allow the user to adjust the value which doesn't interrupt the rendering. I must be missing something simple here. Any help would be much appreciated. Thanks!

Full CameraSetup() code...

void SetupCamera()
{
// Setup View Matrix
D3DXVECTOR3 vCamera(5.0f, 0.0f, -45.0f);    // camera location  x,y,z plane
D3DXVECTOR3 vLookat(5.0f, 5.0f, 0.0f);      // camera direction x,y,z plane
D3DXVECTOR3 vUpVector(0.0f, 1.0f, 0.0f);    // which way is up x,y,z plane
    D3DXMATRIX matView;
    D3DXMatrixLookAtLH( &matView, &vCamera, &vLookat, &vUpVector);
    D3D_Device -> SetTransform(D3DTS_VIEW, &matView);


 // Setup Projection Matrix to transform 2D geometry into 3D space
 D3DXMATRIX matProj;
     D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f);
     D3D_Device -> SetTransform(D3DTS_PROJECTION, &matProj);
}

Full ProcessKeyboardInput() code...

void WINAPI ProcessKeyboardInput()
{ 
// Define a macro to represent the key detection predicate
#define KEYDOWN(name, key) (name[key] & 0x80) 

// Create buffer to contain keypress data
char     buffer[256];
HRESULT  hr;

// Clear the buffer prior to use
ZeroMemory(&buffer, 256);

 hr = g_pDIKeyboardDevice -> GetDeviceState(sizeof(buffer),(LPVOID)&buffer); 
if FAILED(hr) 
{ 
    // If device state cannot be attained, check if it has been lost and try to      aquire it again
    hr = g_pDIKeyboardDevice -> Acquire();
    while (hr == DIERR_INPUTLOST) hr = g_pDIKeyboardDevice -> Acquire();

    hr = g_pDIKeyboardDevice -> GetDeviceState(sizeof(buffer),(LPVOID)&buffer); 
} 

bool topView = false;

if (KEYDOWN(buffer, DIK_Q))
{
    // 'Q' has been pressed - instruct the application to exit.
    PostQuitMessage(0);
}

if (KEYDOWN(buffer, DIK_SPACE))
{
    // Space has been pressed - swap from 1st person view to overhead view

    // topView is true
 topView = !topView;

 // if topView is true, adjust camera accordingly
 if (topView) 
    {
        vCamera.y = 90.f;
    } 
    else        // if untrue, set camera to 1st person
        {
            vCamera.y = 0.f;
        }

    }
}
Was it helpful?

Solution

I think you're on the right track. Don't worry about "interrupt the rendering". There is a lot of processing going on between render calls in any graphics application. How about something like this:

// Have this somewhere appropriate in the code
bool topView = false;

if (KEYDOWN(buffer, DIK_SPACE))
{
    // Toggle top view
    topView = !topView;

    // Set camera vector
    if (topView) {
        vCamera.y = 90.f;
    } else {
        vCamera.y = 0.f:
    }
}

After updating, you need to send your matrices to DirectX again. Basically you need to call the following chunk of code again now that the vCamera (or any of the other view vectors) have been changed. I'd suggest bundling the code up in the SetupCamera() function and call it in the Render() function, after checking for user input. That would also require to move vCamera etc out outside the function so that other functions can use them.

// vCamera, vLookat, vUpVector defined outside function

// Call this in rendering loop to set up camera
void SetupCamera() {
    // Calculate new view matrix from view vectors
    D3DXMATRIX matView;
    D3DXMatrixLookAtLH( &matView, &vCamera, &vLookat, &vUpVector);
    D3D_Device -> SetTransform(D3DTS_VIEW, &matView);

    // Setup Projection Matrix to transform 2D geometry into 3D space
    D3DXMATRIX matProj;
    D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f);
    D3D_Device -> SetTransform(D3DTS_PROJECTION, &matProj);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top