The camera, it's defeating me!

Started by
8 comments, last by Magmatwister 12 years, 8 months ago
Hello all,
I'm having a great deal of difficulty with my camera. I have a test triangle on the screen that I've been using to troubleshoot my camera. But I'm clearly doing something incorrect in generating my camera matrix. When I turn even slightly away from head on towards the triangle, the triangle distorts wildly. I've included two screenshots, the first shows the triangle head on, and it looks correct. All three vertices appear correct and are colored correctly. But when I turn slightly away, everything distorts. You can see it in the second screenshot.

Triangle head on http://i.imgur.com/11XvT.jpg
Turned slightly left http://i.imgur.com/2cBkC.jpg

Does anyone have any advice for me?

Let me give you a peek at the code that generates this utter failure:

Camera class definition:
class Camera
{

public:
Camera(ID3D11Device*);
~Camera();
void Update();
void Draw( ID3D11DeviceContext* );

void move ( float x );
void Yaw ( float x );
void Pitch ( float x );
void Roll ( float x );
void Slew ( float x );
void Elevate ( float x );
void Accelerate( float x );
void Stop();
void ResetToStartPosition();
D3DXVECTOR3* GetPosition();
D3DXVECTOR3* GetLook();
float GetNearClippingPlane();
float GetFarClippingPlane();
void SetNearClippingPlane( float );
void SetFarClippingPlane( float );
void SetPerspectiveAngle( float );
float GetPerspectiveAngle();

float GetYaw(){ return m_yaw; }
float GetPitch(){ return m_pitch; }
float GetRoll(){ return m_roll; }

private:

HRESULT SendCameraDataToGraphicsCard( ID3D11DeviceContext* pDeviceContext );


D3DXMATRIX m_view;
D3DXMATRIX m_perspective;
D3DXMATRIX m_world;
D3DXVECTOR3 m_pos;
D3DXVECTOR3 m_look;
D3DXVECTOR3 m_up;
D3DXVECTOR3 m_right;
float m_fov;
float m_yaw;
float m_pitch;
float m_roll;
float m_vel;
float m_acc;
float m_nearClippingPlane;
float m_farClippingPlane;
ID3D11Buffer* m_ConstantBuffer;
VS_CONSTANT_BUFFER m_ConstantBufferContents;
};



Camera constructor:


Camera::Camera( ID3D11Device* pDevice )
{
m_pos = D3DXVECTOR3 (0.0f, 0.0f, -10.0f);
m_look = D3DXVECTOR3 (0.0f, 0.0f, 1.0f);
m_right = D3DXVECTOR3 (1.0f, 0.0f, 0.0f);
m_up = D3DXVECTOR3 (0.0f, 1.0f, 0.0f);
m_vel = 0.0f;
m_acc = 0.0f;
m_fov = D3DX_PI / 4.0f;
m_yaw = 0.0f;
m_pitch = 0.0f;
m_roll = 0.0f;
m_farClippingPlane = 1000.0f;
m_nearClippingPlane = 0.01f;


// Supply the vertex shader constant data.
D3DXMATRIX identity;
D3DXMatrixIdentity( &identity );
m_view = identity;
m_perspective = identity;
m_world = identity;
m_ConstantBufferContents.m_WorldViewProj = identity;
m_ConstantBufferContents.m_World = identity;

// Fill in a buffer description.
D3D11_BUFFER_DESC cbDesc;
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
cbDesc.ByteWidth = sizeof( VS_CONSTANT_BUFFER );
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbDesc.MiscFlags = 0;
cbDesc.StructureByteStride = 0;

// Create the buffer.
HRESULT hr = pDevice->CreateBuffer( &cbDesc, nullptr, &m_ConstantBuffer );

D3DXMatrixPerspectiveFovLH( &m_perspective, m_fov, 1.f, m_nearClippingPlane, m_farClippingPlane );
}

Camera draw function:


void Camera::Draw( ID3D11DeviceContext* pDeviceContext )
{
float yaw = D3DXToRadian( m_yaw ); // rotation around the y axis
float pitch = D3DXToRadian( m_pitch ); // rotation around the x axis
float roll = D3DXToRadian( m_roll ); // rotation around the z axis
D3DXVECTOR3 position = m_pos; // camera position
D3DXVECTOR3 up = m_up;
D3DXVECTOR3 look = m_look;
D3DXVECTOR3 right = m_right;

D3DXMATRIX rotation;
D3DXMatrixRotationYawPitchRoll(&rotation, m_yaw, m_pitch, m_roll);
D3DXVec3TransformCoord(&look, &look, &rotation);
D3DXVec3TransformCoord(&up, &up, &rotation);
D3DXVec3TransformCoord(&right, &right, &rotation);

D3DXMATRIX viewMatrix;
D3DXMatrixIdentity(&viewMatrix);

viewMatrix._11 = right.x; viewMatrix._12 = up.x; viewMatrix._13 = look.x;
viewMatrix._21 = right.y; viewMatrix._22 = up.y; viewMatrix._23 = look.y;
viewMatrix._31 = right.z; viewMatrix._32 = up.z; viewMatrix._33 = look.z;

viewMatrix._41 = - D3DXVec3Dot( &position, &right );
viewMatrix._42 = - D3DXVec3Dot( &position, &up );
viewMatrix._43 = - D3DXVec3Dot( &position, &look );

m_view = viewMatrix;
SendCameraDataToGraphicsCard( pDeviceContext );
}

Function to transfer the view projection matrix to the shader:


HRESULT Camera::SendCameraDataToGraphicsCard( ID3D11DeviceContext* pDeviceContext )
{
D3DXMATRIX worldViewProjection = m_view * m_perspective;

D3D11_MAPPED_SUBRESOURCE mappedResource;
pDeviceContext->Map( m_ConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );

VS_CONSTANT_BUFFER* dataPtr = (VS_CONSTANT_BUFFER*)mappedResource.pData;

dataPtr->m_WorldViewProj = worldViewProjection;
dataPtr->m_World = m_world;

pDeviceContext->Unmap( m_ConstantBuffer, 0 );
// Set the buffer.
pDeviceContext->VSSetConstantBuffers( 0, 1, &m_ConstantBuffer );

return S_OK; //You might want to have something real returned, dork
}



And finally, the shader:


//--------------------------------------------------------------------------------------
// Constant Buffers
//--------------------------------------------------------------------------------------
cbuffer cbPerObject //: register( b0 )
{
matrix g_mWorldViewProjection : packoffset( c0 );
matrix g_mWorld : packoffset( c4 );
}

cbuffer cbPerFrame //: register( b1 )
{
float3 g_vLightDir : packoffset( c0 );
float g_fTime : packoffset( c0.w );
float4 g_LightDiffuse : packoffset( c1 );
};

//-----------------------------------------------------------------------------------------
// Textures and Samplers
//-----------------------------------------------------------------------------------------
Texture2D g_txDiffuse : register( t0 );
SamplerState g_samLinear : register( s0 );

//--------------------------------------------------------------------------------------
// shader input/output structure
//--------------------------------------------------------------------------------------
struct VS_INPUT
{
float4 Position : POSITION; // vertex position
float4 Color0 : COLOR0; // vertex color
};

struct VS_OUTPUT
{
float4 Position : SV_POSITION; // vertex position
float4 Diffuse : COLOR0; // vertex diffuse color (note that COLOR0 is clamped from 0..1)
};

//--------------------------------------------------------------------------------------
// This shader computes standard transform and lighting
//--------------------------------------------------------------------------------------
VS_OUTPUT RenderSceneVS( VS_INPUT input )
{
VS_OUTPUT Output;
float3 vNormalWorldSpace;

// Transform the position from object space to homogeneous projection space
Output.Position = mul( input.Position, g_mWorldViewProjection );

// Calc diffuse color
Output.Diffuse = input.Color0;
return Output;
}

//--------------------------------------------------------------------------------------
// This shader outputs the pixel's color by modulating the texture's
// color with diffuse material color
//--------------------------------------------------------------------------------------
float4 RenderScenePS( VS_OUTPUT In ) : SV_TARGET
{
return In.Diffuse;
}

Well, that ended up being quite the code dump, and I apologize for that. I just feel at my wits end as I've been struggling and googling and trying a billion different things to make it work. But at least I've gotten this far!

Thanks to everyone who takes a look, and even if you don't have anything to offer, I hope you all have a great weekend!
Advertisement
[font="Arial"]
[/font]
[font="Arial"]Maybe there is something wrong in the way you construct your view matrix.[/font]
[font="Arial"]
[/font]
[font="Arial"]Try using D3DXMatrixLookAtLH to create a view matrix. [/font]
[font="Arial"]
[/font]
[font="Arial"]Good luck![/font]
The view matrix is the inverse of the camera matrix. You construct a matrix representing the camera transform. Pass the inverse to Direct3D.
I also don’t see your logic in constructing _41 through _43. They should be the camera positions (before the matrix is inverted). Why dot-product them?
You never set _44 to 1.0f.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid


The view matrix is the inverse of the camera matrix. You construct a matrix representing the camera transform. Pass the inverse to Direct3D.
I also don’t see your logic in constructing _41 through _43. They should be the camera positions (before the matrix is inverted). Why dot-product them?
You never set _44 to 1.0f.


L. Spiro


actually he sets _44 to 1.0 by calling identity on that matrix. He is constructing directly the inverted matrix (from world space to camera space), it is a commonly used technique. That is the reason for the dot products.

Best regards
Otherwise, I'd make sure that the matrix majoreness is correct (ie. if the shader expects row or column major matrices). Means practically that you may need to transpose your matrices when sending them to the shader.

Good luck!
I didn’t noticed he called D3DXMatrixIdentity.I also got my ordering of the camera look vectors mixed up in my head while looking at his post. I was thinking he was putting them into rows, not columns.

I suggest transposing the matrix.
And also not using such a confusing method of creating the view matrix until you have made a simpler method so that you can test that nothing else has a problem. Make it work, then make it faster.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

go lunas book code and download either part two or three. Take a look at the example of the camera class in the code. This will help you.
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.

Hello all,
I'm having a great deal of difficulty with my camera. I have a test triangle on the screen that I've been using to troubleshoot my camera. But I'm clearly doing something incorrect in generating my camera matrix. When I turn even slightly away from head on towards the triangle, the triangle distorts wildly. I've included two screenshots, the first shows the triangle head on, and it looks correct. All three vertices appear correct and are colored correctly. But when I turn slightly away, everything distorts. You can see it in the second screenshot.

Triangle head on http://i.imgur.com/11XvT.jpg
Turned slightly left http://i.imgur.com/2cBkC.jpg

Does anyone have any advice for me?

Let me give you a peek at the code that generates this utter failure:

Camera class definition:
class Camera
{

public:
Camera(ID3D11Device*);
~Camera();
void Update();
void Draw( ID3D11DeviceContext* );

void move ( float x );
void Yaw ( float x );
void Pitch ( float x );
void Roll ( float x );
void Slew ( float x );
void Elevate ( float x );
void Accelerate( float x );
void Stop();
void ResetToStartPosition();
D3DXVECTOR3* GetPosition();
D3DXVECTOR3* GetLook();
float GetNearClippingPlane();
float GetFarClippingPlane();
void SetNearClippingPlane( float );
void SetFarClippingPlane( float );
void SetPerspectiveAngle( float );
float GetPerspectiveAngle();

float GetYaw(){ return m_yaw; }
float GetPitch(){ return m_pitch; }
float GetRoll(){ return m_roll; }

private:

HRESULT SendCameraDataToGraphicsCard( ID3D11DeviceContext* pDeviceContext );


D3DXMATRIX m_view;
D3DXMATRIX m_perspective;
D3DXMATRIX m_world;
D3DXVECTOR3 m_pos;
D3DXVECTOR3 m_look;
D3DXVECTOR3 m_up;
D3DXVECTOR3 m_right;
float m_fov;
float m_yaw;
float m_pitch;
float m_roll;
float m_vel;
float m_acc;
float m_nearClippingPlane;
float m_farClippingPlane;
ID3D11Buffer* m_ConstantBuffer;
VS_CONSTANT_BUFFER m_ConstantBufferContents;
};



Camera constructor:


Camera::Camera( ID3D11Device* pDevice )
{
m_pos = D3DXVECTOR3 (0.0f, 0.0f, -10.0f);
m_look = D3DXVECTOR3 (0.0f, 0.0f, 1.0f);
m_right = D3DXVECTOR3 (1.0f, 0.0f, 0.0f);
m_up = D3DXVECTOR3 (0.0f, 1.0f, 0.0f);
m_vel = 0.0f;
m_acc = 0.0f;
m_fov = D3DX_PI / 4.0f;
m_yaw = 0.0f;
m_pitch = 0.0f;
m_roll = 0.0f;
m_farClippingPlane = 1000.0f;
m_nearClippingPlane = 0.01f;


// Supply the vertex shader constant data.
D3DXMATRIX identity;
D3DXMatrixIdentity( &identity );
m_view = identity;
m_perspective = identity;
m_world = identity;
m_ConstantBufferContents.m_WorldViewProj = identity;
m_ConstantBufferContents.m_World = identity;

// Fill in a buffer description.
D3D11_BUFFER_DESC cbDesc;
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
cbDesc.ByteWidth = sizeof( VS_CONSTANT_BUFFER );
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbDesc.MiscFlags = 0;
cbDesc.StructureByteStride = 0;

// Create the buffer.
HRESULT hr = pDevice->CreateBuffer( &cbDesc, nullptr, &m_ConstantBuffer );

D3DXMatrixPerspectiveFovLH( &m_perspective, m_fov, 1.f, m_nearClippingPlane, m_farClippingPlane );
}

Camera draw function:


void Camera::Draw( ID3D11DeviceContext* pDeviceContext )
{
float yaw = D3DXToRadian( m_yaw ); // rotation around the y axis
float pitch = D3DXToRadian( m_pitch ); // rotation around the x axis
float roll = D3DXToRadian( m_roll ); // rotation around the z axis
D3DXVECTOR3 position = m_pos; // camera position
D3DXVECTOR3 up = m_up;
D3DXVECTOR3 look = m_look;
D3DXVECTOR3 right = m_right;

D3DXMATRIX rotation;
D3DXMatrixRotationYawPitchRoll(&rotation, m_yaw, m_pitch, m_roll);
D3DXVec3TransformCoord(&look, &look, &rotation);
D3DXVec3TransformCoord(&up, &up, &rotation);
D3DXVec3TransformCoord(&right, &right, &rotation);

D3DXMATRIX viewMatrix;
D3DXMatrixIdentity(&viewMatrix);

viewMatrix._11 = right.x; viewMatrix._12 = up.x; viewMatrix._13 = look.x;
viewMatrix._21 = right.y; viewMatrix._22 = up.y; viewMatrix._23 = look.y;
viewMatrix._31 = right.z; viewMatrix._32 = up.z; viewMatrix._33 = look.z;

viewMatrix._41 = - D3DXVec3Dot( &position, &right );
viewMatrix._42 = - D3DXVec3Dot( &position, &up );
viewMatrix._43 = - D3DXVec3Dot( &position, &look );

m_view = viewMatrix;
SendCameraDataToGraphicsCard( pDeviceContext );
}

Function to transfer the view projection matrix to the shader:


HRESULT Camera::SendCameraDataToGraphicsCard( ID3D11DeviceContext* pDeviceContext )
{
D3DXMATRIX worldViewProjection = m_view * m_perspective;

D3D11_MAPPED_SUBRESOURCE mappedResource;
pDeviceContext->Map( m_ConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );

VS_CONSTANT_BUFFER* dataPtr = (VS_CONSTANT_BUFFER*)mappedResource.pData;

dataPtr->m_WorldViewProj = worldViewProjection;
dataPtr->m_World = m_world;

pDeviceContext->Unmap( m_ConstantBuffer, 0 );
// Set the buffer.
pDeviceContext->VSSetConstantBuffers( 0, 1, &m_ConstantBuffer );

return S_OK; //You might want to have something real returned, dork
}



And finally, the shader:


//--------------------------------------------------------------------------------------
// Constant Buffers
//--------------------------------------------------------------------------------------
cbuffer cbPerObject //: register( b0 )
{
matrix g_mWorldViewProjection : packoffset( c0 );
matrix g_mWorld : packoffset( c4 );
}

cbuffer cbPerFrame //: register( b1 )
{
float3 g_vLightDir : packoffset( c0 );
float g_fTime : packoffset( c0.w );
float4 g_LightDiffuse : packoffset( c1 );
};

//-----------------------------------------------------------------------------------------
// Textures and Samplers
//-----------------------------------------------------------------------------------------
Texture2D g_txDiffuse : register( t0 );
SamplerState g_samLinear : register( s0 );

//--------------------------------------------------------------------------------------
// shader input/output structure
//--------------------------------------------------------------------------------------
struct VS_INPUT
{
float4 Position : POSITION; // vertex position
float4 Color0 : COLOR0; // vertex color
};

struct VS_OUTPUT
{
float4 Position : SV_POSITION; // vertex position
float4 Diffuse : COLOR0; // vertex diffuse color (note that COLOR0 is clamped from 0..1)
};

//--------------------------------------------------------------------------------------
// This shader computes standard transform and lighting
//--------------------------------------------------------------------------------------
VS_OUTPUT RenderSceneVS( VS_INPUT input )
{
VS_OUTPUT Output;
float3 vNormalWorldSpace;

// Transform the position from object space to homogeneous projection space
Output.Position = mul( input.Position, g_mWorldViewProjection );

// Calc diffuse color
Output.Diffuse = input.Color0;
return Output;
}

//--------------------------------------------------------------------------------------
// This shader outputs the pixel's color by modulating the texture's
// color with diffuse material color
//--------------------------------------------------------------------------------------
float4 RenderScenePS( VS_OUTPUT In ) : SV_TARGET
{
return In.Diffuse;
}

Well, that ended up being quite the code dump, and I apologize for that. I just feel at my wits end as I've been struggling and googling and trying a billion different things to make it work. But at least I've gotten this far!

Thanks to everyone who takes a look, and even if you don't have anything to offer, I hope you all have a great weekend!


Directx11 requires the transposed matrices passed to it, it doesn't look like you're doing that. So in your shader, change this:


// Transform the position from object space to homogeneous projection space
Output.Position = mul( input.Position, g_mWorldViewProjection );


to this


// Transform the position from object space to homogeneous projection space
Output.Position = mul( input.Position, transpose(g_mWorldViewProjection) );
Currently trying to make a planet renderer. After many hours of work, somehow I know It'll never be complete.
Also, If I help you, please give me an ++

Directx11 requires the transposed matrices passed to it, it doesn't look like you're doing that. So in your shader, change this:


// Transform the position from object space to homogeneous projection space
Output.Position = mul( input.Position, g_mWorldViewProjection );


to this


// Transform the position from object space to homogeneous projection space
Output.Position = mul( input.Position, transpose(g_mWorldViewProjection) );

[/quote]



I get called away to help a friend clear a field, a full day's work, and I come back to an immediate answer? Instant Karma!!!

This was the answer, it works great!. Thank you so much, Snail Coder.


Directx11 requires the transposed matrices passed to it, it doesn't look like you're doing that. So in your shader, change this:


// Transform the position from object space to homogeneous projection space
Output.Position = mul( input.Position, g_mWorldViewProjection );


to this


// Transform the position from object space to homogeneous projection space
Output.Position = mul( input.Position, transpose(g_mWorldViewProjection) );





I get called away to help a friend clear a field, a full day's work, and I come back to an immediate answer? Instant Karma!!!

This was the answer, it works great!. Thank you so much, Snail Coder.
[/quote]

Also, that was just a quick fix, you really should be passing the matrices already transposed to the shader, simply use:

http://msdn.microsof...2(v=vs.85).aspx

Transposing matrices per vertex per frame isn't really good for performance or necessary :P. Oh, and could I have some rep? :D I'm pretty low as you can see...
Currently trying to make a planet renderer. After many hours of work, somehow I know It'll never be complete.
Also, If I help you, please give me an ++

This topic is closed to new replies.

Advertisement