2013-04-21 2 views
1

У меня есть приложение, которое отображает графику на экране с помощью DirectX. Представление по умолчанию для первого лица устанавливается с использованием приведенного ниже кода, устанавливая ось Y на 0. Код содержится в функции SetupCamera(), которая вызывается до Render().Изменение местоположения камеры на основе нажатия клавиши

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

Я использую DirectInput для управления пользовательским вводом. Я хочу, чтобы пользователь мог нажать SPACE и изменить значение оси Y на 90, чтобы переключиться на верхний вниз, а затем снова нажмите, чтобы переключить его обратно. В настоящее время у меня есть код ниже в моей функции ProcessKeyboardInput(), вызываемой до Render().

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

но я не уверен, что мне нужно сделать, чтобы пользователь мог настроить значение, которое не прерывает рендеринг. Мне, должно быть, здесь что-то не хватает. Любая помощь приветствуется. Благодаря!

Полный CameraSetup (код) ...

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); 
} 

Полный ProcessKeyboardInput (код) ...

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; 
     } 

    } 
} 

ответ

0

Я думаю, что вы на правильном пути. Не беспокойтесь о «прерывании рендеринга». Между обработкой вызовов в любом графическом приложении происходит много обработки. Как насчет чего-то вроде этого:

// 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: 
    } 
} 

После обновления вам необходимо снова отправить свои матрицы в DirectX. В основном вам нужно снова вызвать следующий фрагмент кода, когда были изменены vCamera (или любые другие векторы вида). Я бы предложил связать код в функции SetupCamera() и вызвать его в функции Render() после проверки ввода пользователя. Для этого также потребуется переместить vCamera и т. Д. Вне функции, чтобы другие функции могли их использовать.

// 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); 
} 
+0

Спасибо за быстрый ответ на этот Виктор :) - Я понимаю логику вашего предложения, выглядит хорошо - но я получаю «идентификатор vCamera» не определено после его реализации (я поместил BOOL в ProcessKeyboardInput после установки устройства). Я знаю, что это ошибка области, но я не уверен, как правильно ссылаться на vCamera.y здесь. Я попробовал переместить D3DXVECTOR3 vCamera (5.0f, 0.0f, -45.0f); Из функции SetupCamera и сделать ее глобальной, и хотя ошибка исчезает, нажатие пробела не изменяет вид, grr – Vault13

+0

Показать все функции SetupCamera и Render, кажется, что там есть какой-то вызов, который позволяет DirectX знаете, какой вектор использовать - возможно, используя матричные умножения (не знакомы с DirectX). –

+0

Хорошо, я добавлю это в свой первоначальный код, спасибо. – Vault13

Смежные вопросы