Modifying camera location based on keypress - c++

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

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

Related

OpenGL - Trying to add texture to triangle

I am trying to add a stop sign texture to a triangle in opengl.
But for some reason the image is coming up weird like I have the coordinates in the wrong order and the image is 1, mirrored and 2, not angled correctly:
I believe I set the texture coordinates correct but I am unsure. Have i got the texture coordinates in the wrong order?
Here is the code I have for it:
#include <glm\glm.hpp>
#include <graphics_framework.h>
#include <memory>
using namespace std;
using namespace graphics_framework;
using namespace glm;
mesh m;
effect eff;
target_camera cam;
texture tex;
bool load_content() {
// Construct geometry object
geometry geom;
// Create triangle data
// Positions
vector<vec3> positions{vec3(0.0f, 1.0f, 0.0f), vec3(-1.0f, -1.0f, 0.0f), vec3(1.0f, -1.0f, 0.0f)};
// *********************************
// Define texture coordinates for triangle
vector<vec2> tex_coords{ vec2(0.0f, 0.0f), vec2(1.0f, 0.0f), vec2(0.5f, 1.0f) };
// *********************************
// Add to the geometry
geom.add_buffer(positions, BUFFER_INDEXES::POSITION_BUFFER);
// *********************************
// Add texture coordinate buffer to geometry
geom.add_buffer(tex_coords, BUFFER_INDEXES::TEXTURE_COORDS_0);
// *********************************
// Create mesh object
m = mesh(geom);
// Load in texture shaders here
eff.add_shader("27_Texturing_Shader/simple_texture.vert", GL_VERTEX_SHADER);
eff.add_shader("27_Texturing_Shader/simple_texture.frag", GL_FRAGMENT_SHADER);
// *********************************
// Build effect
eff.build();
// Load texture "textures/sign.jpg"
tex = texture("textures/sign.jpg");
// *********************************
// Set camera properties
cam.set_position(vec3(10.0f, 10.0f, 10.0f));
cam.set_target(vec3(0.0f, 0.0f, 0.0f));
auto aspect = static_cast<float>(renderer::get_screen_width()) / static_cast<float>(renderer::get_screen_height());
cam.set_projection(quarter_pi<float>(), aspect, 2.414f, 1000.0f);
return true;
}
bool update(float delta_time) {
// Update the camera
cam.update(delta_time);
return true;
}
bool render() {
// Bind effect
renderer::bind(eff);
// Create MVP matrix
auto M = m.get_transform().get_transform_matrix();
auto V = cam.get_view();
auto P = cam.get_projection();
auto MVP = P * V * M;
// Set MVP matrix uniform
glUniformMatrix4fv(eff.get_uniform_location("MVP"), // Location of uniform
1, // Number of values - 1 mat4
GL_FALSE, // Transpose the matrix?
value_ptr(MVP)); // Pointer to matrix data
// *********************************
// Bind texture to renderer
renderer::bind(tex, 0);
// Set the texture value for the shader here
glUniform1i(eff.get_uniform_location("tex"), 0);
// *********************************
// Render the mesh
renderer::render(m);
return true;
}
void main() {
// Create application
app application("27_Texturing_Shader");
// Set load content, update and render methods
application.set_load_content(load_content);
application.set_update(update);
application.set_render(render);
// Run application
application.run();
}
That's because the order of your vertex positions and texture coordinates do not match. The first position is the top corner (assuming y is up), but the first texture coordinate is the bottom left corner of the image. Moving the last texture coordinate to the front should do the trick.
Your texture is probably mirrored along the y-axis. OpenGL expects the texture lines to be bottom-up, but most image libraries provide them top-down. Depends on what library you use to load the image. And of course, it will depend on the side from which you view the triangle.

Not being able to rotate object in D2D1

i am new to Direct 2D and a little lost.
I am trying to rotate an object but the way i am doing, it is rotating the whole screen of game rather than just one object. I am clueless on how to approach about rotating just specific object. I hope i have provided enough information, but if not please let me know. And i'm sorry if it is stupidly simple question.
Any help will be much appreciated.
void SpriteSheet::Draw(bool rotate)
{
ID2D1Effect *chromakeyEffect = NULL;
ID2D1Effect *scaleit = NULL;
ID2D1Effect * rotation = NULL;
D2D1_POINT_2F ptss = { 50, 50 };
D2D1_VECTOR_3F vec{ -5.0f, -500.0f, 100.0f };
D2D1_VECTOR_3F vector{ 0.0f, 1.0f, 0.0f };
// this is the rotating part
if (rotate)
{
//D2D1::Matrix3x2F::Identity()._11;
gfx->GetRenderTarget()->SetTransform(
D2D1::Matrix3x2F::Rotation(20, D2D1::Point2F(100, 100)));
}
gfx->GetDeviceContext()->CreateEffect(CLSID_D2D1ChromaKey, &chromakeyEffect);
gfx->GetDeviceContext()->CreateEffect(CLSID_D2D1Scale, &scaleit);
gfx->GetDeviceContext()->CreateEffect(CLSID_D2D12DAffineTransform, &rotation);
// applying chroma key
chromakeyEffect->SetInput(0, bmp);
chromakeyEffect->SetValue(D2D1_CHROMAKEY_PROP_COLOR, vector);
chromakeyEffect->SetValue(D2D1_CHROMAKEY_PROP_TOLERANCE, 0.8f);
chromakeyEffect->SetValue(D2D1_CHROMAKEY_PROP_INVERT_ALPHA, false);
chromakeyEffect->SetValue(D2D1_CHROMAKEY_PROP_FEATHER, false);
// scale the object
scaleit->SetInputEffect(0, chromakeyEffect);
//scaleit->SetValue(D2D1_SCALE_PROP_BORDER_MODE, vec);
//scaleit->SetValue(D2D1_SCALE_PROP_CENTER_POINT, D2D1::Vector2F(1.0f, 1.0f));
scaleit->SetValue(D2D1_SCALE_PROP_SCALE, D2D1::Vector2F(0.50f, 0.50f));
// draw it on screen
gfx->GetDeviceContext()->DrawImage(scaleit, ptss);
if (chromakeyEffect) chromakeyEffect->Release();
}
Just came across Rotation matrix, and that solved the issue. I'm taking the scale effect and applying rotation to it.
if(rotate)
{
rotation->SetInputEffect(0, scaleit);
D2D1_MATRIX_3X2_F matrix = D2D1::Matrix3x2F::Rotation(98, D2D1::Point2F(50, 40));
rotation->SetValue(D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX, matrix);
}

C++ DirectX10 Mesh Disappearing After One Frame, Why?

First time poster on this site. But I have hit a serious block and am lost. If this is too much to read, the question is at the bottom. But I thought the background would help.
A little background on the project:
I currently have a rendering engine set up using DirectX10. It seems that after implementing my design of component(data) pointers inside of a component manager(holds pointers to components of entities inside of world) and sending that data to an interface manager (all methods for loading, creation, updating, rendering, etc.).
Here is an image of a class diagram to make it easier to visualize:
edited: (Do not have enough rep to post, so here is a link instead: http://imgur.com/L3nOyoY
edit:
My rendering engine has a weird issue of rending a cube (parsed from a Wavefront .obj file and put into an array of custom vertices) for only one frame. After the initial presentation of the back buffer, my cube disappears.
I have gone through a lot of debugging to fix this issue, but have yielded no answers. I have files of dumps of the change in vectors for position, scale, rotation, etc. as well as the world matrix. All data in regards to the position of the object in world space and the camera position in world space maintains its integrity. I have also checked to see if there were issues with other pointers either being corrupted, being modified where they ought not to be, or deleted by accident.
Stepping through the locals over several updates and renders I find no change in Movement Components,
no change in Texture components, and no change to my shader variables and pointers.
Here is the code running initially, and then the loop,
void GameWorld::Load()
{
//initialize all members here
mInterface = InterfaceManager(pDXManager);
//create entities here
mEHouse = CEntity(
CT::MESH | CT::MOVEMENT | CT::SHADER | CT::TEXTURE,
"House", &mCManager);
mECamera = CEntity(
CT::CAMERA | CT::MOVEMENT | CT::LIGHT,
"Camera", &mCManager);
//HACKS FOR TESTING ONLY
//Ideally create script to parse to create entities;
//GameWorld will have dynamic entity list;
//////////////////////////////////////////////////
tm = CMesh("../Models/Box.obj");
mCManager.mMesh[0] = &tm;
//hmmm.... how to make non-RDMS style entities...
tc = CCamera(
XMFLOAT3(0.0f, 0.0f, 1.0f),
XMFLOAT3(0.0f, 0.0f, 0.0f),
XMFLOAT3(0.0f, 1.0f, 0.0f), 1);
mCManager.mCamera[0] = &tc;
tmc = CMovement(
XMFLOAT3(0.0f, 0.0f, -10.0f),
XMFLOAT3(0.0f, 0.0f, 0.0f),
XMFLOAT3(0.0f, 0.0f, 0.0f));
mCManager.mMovement[1] = &tmc;
////////////////////////////////////////////////////
//only after all entities are created
mInterface.onLoad(&mCManager);
}
//core game logic goes here
void GameWorld::Update(float dt)
{
mInterface.Update(dt, &mCManager);
}
//core rendering logic goes here
void GameWorld::Render()
{
pDXManager->BeginScene();
//render calls go here
mInterface.Render(&mCManager);
//disappears after end scene
pDXManager->EndScene();
}
And here is the interface render and update methods:
void InterfaceManager::onLoad(CComponentManager* pCManager)
{
//create all
for(int i = 0; i < pCManager->mTexture.size(); ++i)
{
mTexture2D.loadTextureFromFile(pDXManager->mD3DDevice, pCManager->mTexture[i]);
}
for(int i = 0; i < pCManager->mMesh.size(); ++i)
{
mMesh.loadMeshFromOBJ(pCManager->mMesh[i]);
mMesh.createMesh(pDXManager->mD3DDevice, pCManager->mMesh[i]);
}
for(int i = 0; i < pCManager->mShader.size(); ++i)
{
mShader.Init(pDXManager->mD3DDevice, pDXManager->mhWnd, pCManager->mShader[i], pCManager->mTexture[i]);
}
//TODO: put this somewhere else to maintain structure
XMMATRIX pFOVLH = XMMatrixPerspectiveFovLH((float)D3DX_PI / 4.0f, (float)pDXManager->mWindowWidth/pDXManager->mWindowHeight, 0.1f, 1000.0f);
XMStoreFloat4x4(&pCManager->mCamera[0]->mProjectionMat, pFOVLH);
}
void InterfaceManager::Update(float dt, CComponentManager* pCManager)
{
//update input
//update ai
//update collision detection
//update physics
//update movement
for(int i = 0; i < pCManager->mMovement.size(); ++i)
{
mMovement.transformToWorld(pCManager->mMovement[i]);
}
//update animations
//update camera
//There is only ever one active camera
//TODO: somehow set up for an activecamera variable
mCamera.Update(pCManager->mCamera[0], pCManager->mMovement[pCManager->mCamera[0]->mOwnerID]);
}
void InterfaceManager::Render(CComponentManager* pCManager)
{
for(int i = 0; i < pCManager->mMesh.size(); ++i)
{
//render meshes
mMesh.RenderMeshes(pDXManager->mD3DDevice, pCManager->mMesh[i]);
//set shader variables
mShader.setShaderMatrices(pCManager->mCamera[0], pCManager->mShader[i], pCManager->mMovement[i]);
mShader.setShaderLight(pCManager->mLight[i], pCManager->mShader[i]);
mShader.setShaderTexture(pCManager->mTexture[i]);
//render shader
mShader.RenderShader(pDXManager->mD3DDevice, pCManager->mShader[i], pCManager->mMesh[i]);
}
}
In short, my question could be this: Why is my cube only rendering for one frame, then disappearing?
UPDATE: I found the method causing the issues by isolating it. It lays within my update() method, before render(). It is when my camera is updated that it causes issues. Here is the code for that method, perhaps someone can see what I am not?
void ICamera::Update(CCamera* pCamera, CMovement* pMovement)
{
XMMATRIX rotMat = XMMatrixRotationRollPitchYaw(pMovement->mRotation.x,
pMovement->mRotation.y,
pMovement->mRotation.z);
XMMATRIX view = XMLoadFloat4x4(&pCamera->mViewMat);
XMVECTOR up = XMLoadFloat3(&pCamera->mUp);
XMVECTOR lookAt = XMLoadFloat3(&pCamera->mEye);
XMVECTOR pos = XMLoadFloat3(&pMovement->mPosition);
lookAt = XMVector3TransformCoord(lookAt, rotMat);
up = XMVector3TransformCoord(up, rotMat);
lookAt = pos + lookAt;
view = XMMatrixLookAtLH(pos,
lookAt,
up);
XMStoreFloat3(&pCamera->mEye, lookAt);
XMStoreFloat3(&pCamera->mUp, up);
XMStoreFloat4x4(&pCamera->mViewMat, view);
}
From the camera update code, one obvious issue is the lookAt variable.
Usually lookAt variable is a "point" not a "vector" (direction), but from your code, it seems you saved it as a point, but used it as a vector. And your camera definition is also not complete, a standard camera should at least contains: position, up direction and view direction (or lookAt point).
I assume you want to rotate and translate your camera in ICamera::Update function, so you rotate up and view direction, and translate the position.
I guess your CMovement will give you a new camera position and apply a rotation to the camera. Then, you can try to modify as below, (mEye and mLookAt is position, mUp is the direction)
XMVECTOR up = XMLoadFloat3(&pCamera->mUp);
XMVECTOR lookAt = XMLoadFloat3(&pCamera->mLookAt);
XMVECTOR oldPos = XMLoadFloat3(&pCamera->mEye);
XMVECTOR viewDir = lookAt - oldPos;
XMVECTOR pos = XMLoadFloat3(&pMovement->mPosition);
viewDir = XMVector3TransformCoord(viewDir, rotMat);
up = XMVector3TransformCoord(up, rotMat);
lookAt = pos + viewDir;
view = XMMatrixLookAtLH(pos,
lookAt,
up);
XMStoreFloat3(&pCamera->mEye, position);
XMStoreFloat3(&pCamera->mLookAt, lookAt);
XMStoreFloat3(&pCamera->mUp, up);

how to convert XMMATRIX to D3DMATRIX in DirectX 9?

I learn DirectX (DirectX 9) from www.directxtutorial.com and using visual studio 2012 in windows 8.
d3dx9 (d3dx) replace by other header like DirectXMath, therefore I replaced all that is needed, but there is a problem - convert XMMATRIX to D3DMATRIX.
The problem code (The problem written - /problem!/):
void render_frame(void) {
// clear the window to a deep blue
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->BeginScene(); // begins the 3D scene
// select which vertex format we are using
d3ddev->SetFVF(CUSTOMFVF);
// SET UP THE PIPELINE
DirectX::XMMATRIX matRotateY; // a matrix to store the rotation information
static float index = 0.0f; index+=0.05f; // an ever-increasing float value
// build a matrix to rotate the model based on the increasing float value
matRotateY = DirectX::XMMatrixRotationY(index);
D3DMATRIX D3DMatRotateY = matRotateY.r;
// tell Direct3D about our matrix
d3ddev->SetTransform(D3DTS_WORLD, &matRotateY); /*problem!*/
DirectX::XMMATRIX matView; // the view transform matrix
DirectX::XMVECTOR CameraPosition = {0.0f,0.0f,10.0f};
DirectX::XMVECTOR LookAtPosition = {0.0f,0.0f,0.0f};
DirectX::XMVECTOR TheUpDirection = {0.0f,1.0f,0.0f};
matView = DirectX::XMMatrixLookAtLH(CameraPosition, // the camera position
LookAtPosition, // the look-at position
TheUpDirection); // the up direction
d3ddev->SetTransform(D3DTS_VIEW, &matView); /*problem!*/ // set the view transform to matView
DirectX::XMMATRIX matProjection; // the projection transform matrix
DirectX::XMMatrixPerspectiveFovLH(&matProjection,
DirectX::XMConvertToRadians(45), // the horizontal field of view
1.0f, // the near view-plane
100.0f); // the far view-plane
d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection); /*problem!*/ // set the projection
// select the vertex buffer to display
d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
// copy the vertex buffer to the back buffer
d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
d3ddev->EndScene(); // ends the 3D scene
d3ddev->Present(NULL, NULL, NULL, NULL); /* displays the created frame on the screen */ }
You can use XMStoreFloat4x4 to convert XMMATRIX to a XMFLOAT4X4.
You should be able to pass in XMFLOAT4X4 to setTransform by casting.
DirectX::XMMATRIX matProjection;  
DirectX::XMFLOAT4X4 projectionMatrix;
DirectX::XMMatrixPerspectiveFovLH(&matProjection,DirectX::XMConvertToRadians(45),1.0f,100.0f);
XMStoreFloat4x4(&projectionMatrix, matProjection);
d3ddev->SetTransform(D3DTS_PROJECTION, (D3DXMATRIX*)&projectionMatrix);  /*problem!*/   // set the projection

DirectX 11 D3DXMatrixTranslation continues to run?

I want to bind moving an object to a button press. When I press the button, the object vanishes quickly and appears as if the first Translation was always running. Then when I let go of the button, it quickly vanishes and ends up where it would've been without touching the button. 'Bouncing' between the two when I press/release the button.
D3DXMATRIX worldMatrix, viewMatrix, projectionMatrix;
bool result;
// Generate the view matrix based on the camera's position.
m_Camera->Render();
// Get the world, view, and projection matrices from the camera and d3d objects.
m_Camera->GetViewMatrix(viewMatrix);
m_Direct3D->GetWorldMatrix(worldMatrix);
m_Direct3D->GetProjectionMatrix(projectionMatrix);
// Move the world matrix by the rotation value so that the object will move.
if(m_Input->IsAPressed() == true) {
D3DXMatrixTranslation(&worldMatrix, 1.0f*rotation, 0.0f, 0.0f);
}
else {
D3DXMatrixTranslation(&worldMatrix, 0.1f*rotation, 0.0f, 0.0f);
}
// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_Model->Render(m_Direct3D->GetDeviceContext());
// Render the model using the light shader.
result = m_LightShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix,
m_Model->GetTexture(), m_Light->GetDirection(), m_Light->GetDiffuseColor());
if(!result)
{
return false;
}
// Present the rendered scene to the screen.
m_Direct3D->EndScene();
I'm still really new to DX11 and I've had a good look around. I'm pulling my hair out here trying to work out whats going on.
That's what your code does. If a button is pressed you set one world matrix, if not - another. What you need to do is multiply the world matrix by a newly generated translation matrix. Notice that this multiplication will happen ~60 times every second, so you need to move only a very tiny distance with each one.
Your code should be like this
if (m_Input->IsAPressed() == true) {
D3DXMATRIX translation;
D3DXMatrixTranslation(&translation, 0.05f, 0.0f, 0.0f);
worldMatrix *= translation;
}
You may need to do
m_Direct3D->SetWorldMatrix(worldMatrix);
Or something similar. I don't think I'm familiar with the classes you're using for m_Camera and m_Direct3D.