Sign in to follow this  

Camera Problem

This topic is 4861 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 guys, I am having a problem with the camera function I am using now. can you guys please tell me the problem? Thanks and here is the code
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dxerr9.h>
#include <dinput.h>

// Globals
typedef struct _D3DCurrentSettings
{
	int m_nDeviceHeight;
	int m_nDeviceWidth;
    float m_fScreenAspect;
	BOOL m_bWindowed;
	BOOL m_bMultiSampling;
	D3DFORMAT m_D3DFormat;
	D3DPRESENT_PARAMETERS m_PresentParams;
} D3DCURRENTSETTINGS;

static char strAppname[]="Direct3D Object-World Space";
LPDIRECT3D9 g_pD3D;
LPDIRECT3DDEVICE9 g_pDevice;
LPDIRECT3DSURFACE9 g_pBackSurface;
HWND g_hWnd;

D3DCURRENTSETTINGS g_D3DSettings;

// Function declarations
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );

HRESULT GameInit();
HRESULT GameLoop();
HRESULT GameShutDown();
HRESULT Render();
void InitialiseMesh(char filename[]);
void DrawMesh();
void updateViewMatrix();HRESULT D3DError(HRESULT hrCode, int nLine, char* szFile, char* szExtraInfo);
HRESULT ValidateDevice(LPDIRECT3DDEVICE9& pDevice, LPDIRECT3DSURFACE9& pBackSurface, D3DCURRENTSETTINGS& d3dcurrentsettings);
int InitDirect3DDevice(HWND hWndTarget, D3DCURRENTSETTINGS& d3dcurrentsettings, LPDIRECT3D9 pD3D,
					   LPDIRECT3DDEVICE9* ppDevice);


// Globals specifically for this source

LPD3DXMESH				m_pMesh;					// The mesh object
	
LPD3DXBUFFER			m_pMaterialsBuffer;			// Receives the materials when the X file is loaded
D3DMATERIAL9*			m_pMaterials;				// Array of materials extracted from m_pMaterialsBuffer
LPDIRECT3DTEXTURE9*		m_pTextures;				// Array of textures extracted from m_pMaterialsBuffer
DWORD					m_dwNumMaterials;			// The number of materials in this mesh

// Camera

D3DXVECTOR3 g_vEye(0.0f,0.0f,-5.0f);
D3DXVECTOR3 g_vLook(0.0f,0.0f,0.0f);
D3DXVECTOR3 g_vRight(1.0f,0.0f,0.0f);
D3DXVECTOR3 g_vUp(0.0f,1.0f,0.0f);

float camChange = 0.001f;


//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
	
	ZeroMemory(&wc, sizeof(WNDCLASSEX));
	wc.cbSize=sizeof(WNDCLASSEX);						// size of the window struct in bytes
	wc.style=CS_HREDRAW | CS_VREDRAW | CS_OWNDC;		// window styles to use
	wc.lpfnWndProc=MsgProc;								// function name of event handler
	wc.hInstance=hInstance;								// handle to this apps instance
	wc.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);// background colour of window
	wc.hIcon= LoadIcon(NULL, IDI_APPLICATION);			// icon for the app window
	wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);			// icon when minimized to taskbar
	wc.hCursor=LoadCursor(NULL, IDC_ARROW);				// cursor to use for this window
	wc.lpszClassName=strAppname;						// name for this class

    // Register the window class
    RegisterClassEx( &wc );

	g_D3DSettings.m_nDeviceWidth=1024;
	g_D3DSettings.m_nDeviceHeight=768;
	g_D3DSettings.m_fScreenAspect=(float)g_D3DSettings.m_nDeviceWidth / (float)g_D3DSettings.m_nDeviceHeight;
	
    // Create the application's window
    g_hWnd = CreateWindow(strAppname, strAppname, WS_OVERLAPPEDWINDOW, 10, 10,
						  g_D3DSettings.m_nDeviceWidth, g_D3DSettings.m_nDeviceHeight,
						  NULL, NULL, wc.hInstance, NULL );

	// Show the window
	ShowWindow(g_hWnd, nCmdShow);
	UpdateWindow(g_hWnd);
	
	if(FAILED(GameInit()))
	{
		UnregisterClass( strAppname, wc.hInstance );
		return -1;
	}

	// Enter the message loop
	MSG msg;
	ZeroMemory( &msg, sizeof(msg) );
	int count=0;
	while( msg.message!=WM_QUIT )
	{
		if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
		else
		{
			GameLoop();
		}
	}

	GameShutDown();
	UnregisterClass( strAppname, wc.hInstance );
    return 0;
}


//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	HDC hDC;
	PAINTSTRUCT PaintStruct;


    switch( msg )
    {
	case WM_PAINT:
		{
			hDC=BeginPaint(hWnd, &PaintStruct);		// Tell windows we want to update the window

			// Do GDI drawing here

			EndPaint(hWnd, &PaintStruct);
			return 0;
		}
	case WM_KEYDOWN:
		{
			switch(wParam)
			{
			case VK_SPACE:
			case VK_ESCAPE:
				{
					PostQuitMessage( 0 );
					return 0;			
				}
			default:	
				return DefWindowProc( hWnd, msg, wParam, lParam );
			}

			return 0;
		}
	
	case WM_DESTROY:
		{
			PostQuitMessage( 0 );
			return 0;
		}
		
	default:	
		return DefWindowProc( hWnd, msg, wParam, lParam );
    }
	
}


// =====================================================================================
//  High level functions for initialization, loop and shutdown
// =====================================================================================

HRESULT GameInit()
{
	HRESULT rslt=0;

	g_pD3D=Direct3DCreate9(D3D_SDK_VERSION);
	if(g_pD3D==NULL)
	{
		return D3DError(E_FAIL, __LINE__, __FILE__, "Failed to create a D3D9 object.");
	}


	// Populate our struct with how we want to set up D3D...
	g_D3DSettings.m_bWindowed=FALSE;
	g_D3DSettings.m_bMultiSampling=FALSE;
	g_D3DSettings.m_D3DFormat=D3DFMT_X8R8G8B8;

	// ...and pass it to our function to create the device!
	rslt=InitDirect3DDevice(g_hWnd, g_D3DSettings, g_pD3D, &g_pDevice);
	if(FAILED(rslt))
	{
		return E_FAIL;
	}

	// ===================================================================================
	// Set up our Projection, View and World transformations
	// ===================================================================================
	
	// Create a matrix to store our Projection transform. Null all the fields.
	D3DXMATRIX matProjection;
	ZeroMemory(&matProjection, sizeof(matProjection));

	// Use D3DX to create a left handed cartesian Field Of View transform
	D3DXMatrixPerspectiveFovLH(&matProjection, D3DX_PI/4, g_D3DSettings.m_fScreenAspect,
							   1.0f, 100.0f);
	
	// Tell D3D to use our Projection matrix for the projection transformation stage
	rslt=g_pDevice->SetTransform(D3DTS_PROJECTION, &matProjection);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set Projection Transform."); }


	/*

	// Create a matrix to store our View transform. Null all the fields.
	D3DXMATRIX matView;
	ZeroMemory(&matView, sizeof(matView));

	// Use D3DX to create a Look At matrix from eye, lookat and up vectors.
	D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f, -5.0f),
								 &D3DXVECTOR3(0.0f, 0.0f,  0.0f),
								 &D3DXVECTOR3(0.0f, 1.0f,  0.0f));

	// Tell D3D to use our View matrix for the view transformation stage
	g_pDevice->SetTransform(D3DTS_VIEW, &matView);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set View Transform."); }

	

		// Create a matrix to store our World transform
	D3DXMATRIX matWorld;
	// Set the matrix to an identity matrix (one that makes no change)
	D3DXMatrixIdentity(&matWorld);

	// Tell D3D to use our World matrix for the world transformation stage
	g_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set World Transform."); }

	*/

	// ===================================================================================
	// Set up our primitive and vertex buffer
	// ===================================================================================

	// Set our culling renderstate
	g_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	g_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

	InitialiseMesh("tiger.x");

	return S_OK;
}


HRESULT GameLoop()
{
	return Render();
}


HRESULT GameShutDown()
{
	// Don't forget to release the vertex buffer - it's a COM interface
	if(g_pBackSurface)
		g_pBackSurface->Release();
	if(g_pDevice)
		g_pDevice->Release();
	if(g_pD3D)
		g_pD3D->Release();
	return S_OK;
}


// =====================================================================================
// Main render function to perform D3D drawing
// =====================================================================================

HRESULT Render()
{
	HRESULT rslt=NULL;
	
	// ====================================================================================
	// - Do all the usual checks to make sure we have the right pointers, etc...
	// ====================================================================================

	// Make sure we have a valid D3D Device
	if(!g_pDevice) { return E_FAIL;	}

	// Return if the device is not ready
	rslt=ValidateDevice(g_pDevice, g_pBackSurface, g_D3DSettings);
	if(FAILED(rslt)) { return rslt;	}

	// Clear the back buffer
	g_pDevice->Clear(0,0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

	// Get a pointer to the back buffer (remember, page flipping has taken place)
	rslt=g_pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &g_pBackSurface);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to get the back buffer."); }

	updateViewMatrix();

	D3DXMATRIX matWorld;	
   
	rslt=g_pDevice->BeginScene();
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "BeginScene() failed."); }

	// ====================================================================================
	// - Do our drawing operations
	// ====================================================================================

	g_pDevice->SetTransform( D3DTS_WORLD, &matWorld );
	DrawMesh();

	
	// ====================================================================================
	// - Clean up and present the back buffer to be page flipped
	// ====================================================================================

	g_pDevice->EndScene();
	g_pBackSurface->Release();

	// Present the back buffer to the display adapter to be drawn
	g_pDevice->Present(NULL, NULL, NULL, NULL);


	return S_OK;
}

void InitialiseMesh(char filename[])
{
	m_dwNumMaterials = 0;
	m_pMaterialsBuffer = NULL;
	m_pMaterials = NULL;
	m_pTextures = NULL;
	m_pMesh = NULL;

	// First, load the .X file into a mesh object, and fill out the materials buffer
	D3DXLoadMeshFromX(filename, D3DXMESH_MANAGED, g_pDevice, NULL,
							 &m_pMaterialsBuffer, NULL, &m_dwNumMaterials, &m_pMesh);

	// Next, get a pointer to the first element of data in the materials buffer, ready
	// to read out.
	D3DXMATERIAL* pMaterials = (D3DXMATERIAL*)m_pMaterialsBuffer->GetBufferPointer();

	// Create 2 arrays, 1 for textures and 1 for materials. D3DXLoadMeshFromX puts the
	// number of materials/textures (always the same) into m_dwNumMaterials above.
	m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
	m_pTextures = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];

	// Next, iterate through the pMaterials buffer.
	for(int iCount = 0; iCount < (int)m_dwNumMaterials; iCount++)
	{
		// For each material buffer element, copy the D3DMATERIAL into this class' array.
		m_pMaterials[iCount] = pMaterials[iCount].MatD3D;

		// As we learnt in the Lighting tutorial (D3D Basics Series 3 Tut 4), each material
		// has diffuse & ambient light properties. Set the Ambient light ARGB to the diffuse
		// light ARGB.
		m_pMaterials[iCount].Ambient = m_pMaterials[iCount].Diffuse;		
		
		// Finally, create a texture from the file specified in the mateirals buffer and put
		// it in the m_pTextures array.
		D3DXCreateTextureFromFile(g_pDevice, pMaterials[iCount].pTextureFilename, &m_pTextures[iCount]);
	}
	
	// m_pMaterialsBuffer is a COM object created by D3DXLoadMeshFromX. We only need it when
	// reading the data from the X file - now that we've populated our mesh, materials and
	// textures we can get rid of it.
	m_pMaterialsBuffer->Release();
	m_pMaterialsBuffer = NULL;
}

void DrawMesh()
{
		// Render the mesh
	
	for(int iCount = 0; iCount < (int)m_dwNumMaterials; iCount++)
	{
		//... set the material and texture in the normal way
		g_pDevice->SetMaterial(&m_pMaterials[iCount]);
				
		g_pDevice->SetTexture(0, m_pTextures[iCount]);
				
		//... then call ID3DXMesh::DrawSubset to draw the vertices in the mesh
		// that have this material and texture applied to them.
		m_pMesh->DrawSubset(iCount);
	}
}

void updateViewMatrix( void )
{
	// Create View matrix
	D3DXMATRIX view;
	// Initialize with identity matrix.
	D3DXMatrixIdentity( &view );

	D3DXVec3Normalize( &g_vLook, &g_vLook );
	D3DXVec3Cross( &g_vRight, &g_vUp, &g_vLook );
	D3DXVec3Normalize( &g_vRight, &g_vRight );
	D3DXVec3Cross( &g_vUp, &g_vLook, &g_vRight );
	D3DXVec3Normalize( &g_vUp, &g_vUp );

	// Fill up the view matrix 
	view._11 = g_vRight.x;
	view._12 = g_vUp.x;
	view._13 = g_vLook.x;
	view._14 = 0.0f;

	view._21 = g_vRight.y;
	view._22 = g_vUp.y;
	view._23 = g_vLook.y;
	view._24 = 0.0f;

	view._31 = g_vRight.z;
	view._32 = g_vUp.z;
	view._33 = g_vLook.z;
	view._34 = 0.0f;

	view._41 = -D3DXVec3Dot( &g_vEye, &g_vRight );
	view._42 = -D3DXVec3Dot( &g_vEye, &g_vUp );
	view._43 = -D3DXVec3Dot( &g_vEye, &g_vLook );
	view._44 = 1.0f;

	// Invoke the DirectX function to set the view matrix.
	g_pDevice->SetTransform( D3DTS_VIEW, &view ); 
}


int InitDirect3DDevice(HWND hWndTarget, D3DCURRENTSETTINGS& d3dcurrentsettings, LPDIRECT3D9 pD3D,
					   LPDIRECT3DDEVICE9* ppDevice)
{
	// PresentParams struct to hold info about the rendering method
	D3DPRESENT_PARAMETERS d3dpp;

	// Struct to hold info about the current display mode
	D3DDISPLAYMODE d3ddm;

	HRESULT rslt=0;

	// If ppDevice is a valid pointer, release it before we continue
	if(*ppDevice)
		(*ppDevice)->Release();

	// Empty out the structure
	ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));

	// Get the settings for the current display mode. This gives us hints on how to setup our
	// Present Parameters struct
	rslt=pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
	if(FAILED(rslt))
	{
		return E_FAIL;
	}

    

	// Now set up the Present Parameters struct

	// The Width of the back buffer in pixels
	d3dpp.BackBufferWidth=d3dcurrentsettings.m_nDeviceWidth;

	// The height of the back buffer in pixels
	d3dpp.BackBufferHeight=d3dcurrentsettings.m_nDeviceHeight;
	
	// The Format of the backbuffer
	d3dpp.BackBufferFormat = d3dcurrentsettings.m_bWindowed ? d3ddm.Format : d3dcurrentsettings.m_D3DFormat;

	// Handle to render target window
	d3dpp.hDeviceWindow=hWndTarget;
	
	// Window or Fullscreen
	d3dpp.Windowed=d3dcurrentsettings.m_bWindowed;

	// Number of back buffers
	d3dpp.BackBufferCount=1;

	// Swap method
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

	// Type of multisampling
	if(d3dcurrentsettings.m_bMultiSampling)
	{
		// CheckDeviceMultiSampleType() has gained an additional parameter from DX8. The last param,
		// pQualityLevels, gives us some information about the multisampling. We don't need it, so we
		// can pass NULL for this param.
		if( SUCCEEDED(pD3D->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
													   d3dpp.BackBufferFormat, 
													   d3dcurrentsettings.m_bWindowed, 
													   D3DMULTISAMPLE_2_SAMPLES, NULL)))
		{
			d3dpp.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
		}
		else
			d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;
	}
	else
		d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;

	// Let D3D manage the depth buffer
	d3dpp.EnableAutoDepthStencil=TRUE;

	// Set the depth buffer format to 16bits
	d3dpp.AutoDepthStencilFormat=D3DFMT_D16;
	
	// Use default refresh rate
	d3dpp.FullScreen_RefreshRateInHz=0;

	// Present the information as fast as possible
	// PresentationInterval used to be named FullScreen_PresentationInterval in DX8, this is only a name change.
	d3dpp.PresentationInterval = d3dcurrentsettings.m_bWindowed ? 0 : D3DPRESENT_INTERVAL_IMMEDIATE;

	// Allow the back buffer to be accessed for 2D work
	d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

	// Get a pointer to the IDirect3DDevice9 interface
	// First try to create a device using Hardware vertex processing (fast!). If that fails,
	// fall back to software vertex processing. If that fails, we've got a problem!
	rslt=pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWndTarget,
						 D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, ppDevice);
	if(FAILED(rslt))
	{
		rslt=pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWndTarget,
							    D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, ppDevice);
		if(FAILED(rslt))
		{
			return E_FAIL;
		}
	}

	d3dcurrentsettings.m_PresentParams=d3dpp;
	if(d3dcurrentsettings.m_bWindowed)
		d3dcurrentsettings.m_D3DFormat=d3dpp.BackBufferFormat;
	
	return S_OK;
}


HRESULT ValidateDevice(LPDIRECT3DDEVICE9& pDevice, LPDIRECT3DSURFACE9& pBackSurface, D3DCURRENTSETTINGS& d3dcurrentsettings)
{
	HRESULT rslt=NULL;

	// Test the current state of the device
	rslt=pDevice->TestCooperativeLevel();
	if(FAILED(rslt))
	{
		// if the device is lost, then return a fail
		if(rslt==D3DERR_DEVICELOST)
			return E_FAIL;

		// if the device is ready to be reset, then try it
		if(rslt==D3DERR_DEVICENOTRESET)
		{
			// Release the back surface so it can be re-created
			if(pBackSurface)
				pBackSurface->Release();
			
			// reset the device
			rslt=pDevice->Reset(&d3dcurrentsettings.m_PresentParams);
			if(FAILED(rslt))
			{
				// If the device was not reset, then exit
				PostQuitMessage(0);
				return E_FAIL;
			}

			// reacquire a pointer to the new back buffer
			// GetBackBuffer takes an extra parameter - parameter 1 is an integer specifying the "swap chain".
			// We're only interested in swap chain 1.
			rslt=pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackSurface);
			if(FAILED(rslt))
			{
				PostQuitMessage(0);
				return E_FAIL;
			}
		}

	}
	return S_OK;
}


HRESULT D3DError(HRESULT hrCode, int nLine, char* szFile, char* szExtraInfo)
{
	::OutputDebugString("-------------------------------------------32Bits.co.uk Error Handling-\n");
	char pszError[256];
	wsprintf(pszError, "The following error occurred on line %d of %s\n", nLine, szFile);
	::OutputDebugString(pszError);
	::OutputDebugString(DXGetErrorString9(hrCode));
	::OutputDebugString("\n");
	if(szExtraInfo)
	{
		::OutputDebugString("Extra information: ");
		::OutputDebugString(szExtraInfo);
		::OutputDebugString("\n");
	}

	return hrCode;
}

Edited by Coder: - Use source tags for large blocks of code - Paste relevant parts of the code only Jason [Edited by - Coder on August 22, 2004 7:07:31 AM]

Share this post


Link to post
Share on other sites
Before I add the updateViewMatrix() function, the code is working and the "tiger.x" mesh can be loaded, the view matrix is set to eye(0,0,-5)m look (0,0,0) and up(0,1,0) but now I have added the functionm I commented the original code

/*

// Create a matrix to store our View transform. Null all the fields.
D3DXMATRIX matView;
ZeroMemory(&matView, sizeof(matView));

// Use D3DX to create a Look At matrix from eye, lookat and up vectors.
D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f, -5.0f),
&D3DXVECTOR3(0.0f, 0.0f, 0.0f),
&D3DXVECTOR3(0.0f, 1.0f, 0.0f));

// Tell D3D to use our View matrix for the view transformation stage
g_pDevice->SetTransform(D3DTS_VIEW, &matView);
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set View Transform."); }



// Create a matrix to store our World transform
D3DXMATRIX matWorld;
// Set the matrix to an identity matrix (one that makes no change)
D3DXMatrixIdentity(&matWorld);

// Tell D3D to use our World matrix for the world transformation stage
g_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set World Transform."); }

*/




and use the updateViewMatrix instead. But since then mesh cannot be loaded.

[Edited by - Coder on August 22, 2004 7:59:30 AM]

Share this post


Link to post
Share on other sites
The application will work, but I cant see any textures on the screen. But if I change the coords of the camera, the textures can then be seen, why is this so?

I noticed that the problem will exist when the Look coordinates have more than two values containing zero.

For example,

if look=(0,0,1) or look=(1,0,0) then the textures can't be seen. However if Look=(1,1,0) or (1,0,1) then the textures can be seen. Can anyone explain this?

Thanks

Share this post


Link to post
Share on other sites

This topic is 4861 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this