Sign in to follow this  
uncle albert

Why aren't my matrix transformations working?

Recommended Posts

uncle albert    122
Hi all, Been soaking up information from this wondrous website for months/years but have only just plucked up the courage to join and post on the forum! Anyways, afraid I've gotta start my input to the forum with a question: I'm just going through the basics on vertices/primitives etc. using DirectX 9 which is going smoothly, but I'm now trying to scale/translate/rotate my object using the helper functions given by DX9. I've written my code and gone over it time and again, comparing it to example programs, and I can't understand why it doesn't actually carry out the transformations! Here's the code:
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>

// usual stuff for any DirectX app.
HINSTANCE hInstance;
HWND wndHandle;
LPDIRECT3D9 pD3D;
LPDIRECT3DDEVICE9 pd3dDevice;
// easier just to make this a global, as it's used a lot
HRESULT hr;

bool initWindow(HINSTANCE hInstance);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
bool initDirect3D(void);
void render(void);
void cleanUp(void);

// vertex stuff
LPDIRECT3DVERTEXBUFFER9 vBuffer = NULL;
LPDIRECT3DINDEXBUFFER9 iBuffer = NULL;
LPDIRECT3DVERTEXBUFFER9 createVertexBuffer(int size, DWORD usage);
LPDIRECT3DINDEXBUFFER9 createIndexBuffer(int size, DWORD usage);
bool setupVBuffer();
bool setupIBuffer();
void drawVBuffer(LPDIRECT3DVERTEXBUFFER9 vertexBuffer, LPDIRECT3DINDEXBUFFER9 indexBuffer);

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

struct Vertex
{
	float x, y, z, rhw;
	DWORD colour;
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	if (!initWindow(hInstance)){
		return false;
	}
	if (!initDirect3D()){
		return false;
	}

	if (!setupVBuffer()){
		return false;
	}

	if (!setupIBuffer()){
		return false;
	}

	MSG msg;
	ZeroMemory(&msg, sizeof(msg));

	while(msg.message!=WM_QUIT){
		if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)){
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else{
			render();
		}
	}

	cleanUp();
	return (int) msg.wParam;
}

bool initWindow(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = (WNDPROC)WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInstance;
	wcex.hIcon = 0;
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = "VerticesExample";
	wcex.hIconSm = 0;

	RegisterClassEx(&wcex);

	wndHandle = CreateWindow("VerticesExample",
							 "My first vertices example",
							 WS_OVERLAPPEDWINDOW,
							 CW_USEDEFAULT,
							 CW_USEDEFAULT,
							 800,
							 600,
							 NULL,
							 NULL,
							 
							 hInstance,
							 NULL);

	if (!wndHandle){
		return false;
	}

	ShowWindow(wndHandle, SW_SHOW);
	UpdateWindow(wndHandle);

	return true;
}

bool initDirect3D(void)
{
	pD3D = NULL;
	pd3dDevice = NULL;

	if (NULL == (pD3D = Direct3DCreate9(D3D_SDK_VERSION))){
		return false;
	}

	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
	d3dpp.BackBufferCount = 1;
	d3dpp.BackBufferHeight = 600;
	d3dpp.BackBufferWidth = 800;
	d3dpp.hDeviceWindow = wndHandle;

	if (FAILED ( pD3D->CreateDevice(D3DADAPTER_DEFAULT,
									D3DDEVTYPE_HAL,
									wndHandle,
									D3DCREATE_SOFTWARE_VERTEXPROCESSING,
									&d3dpp,
									&pd3dDevice))){
		return false;
	}

	pd3dDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(255, 255, 255));
	pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
	pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

	D3DXMATRIX matProj;
	D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian( 45.0f ), 
                                800.0f / 600.0f, 0.1f, 100.0f );
	pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

	return true;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message){
		case WM_DESTROY:
			PostQuitMessage(1);
			break;
		case WM_KEYDOWN:
			if(wParam == VK_ESCAPE){
				PostQuitMessage(0);
			}
		break;
	}

	return DefWindowProc(hWnd, message, wParam, lParam);
}

void cleanUp(void)
{
	if (vBuffer != NULL){
		vBuffer->Release();
	}

	if (iBuffer != NULL){
		iBuffer->Release();
	}

	if (pd3dDevice != NULL){
		pd3dDevice->Release();
	}

	if (pD3D != NULL){
		pD3D->Release();
	}
}

void render(void)
{
	if (NULL == pd3dDevice){
		return;
	}
		
	pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0);
	
	drawVBuffer(vBuffer, iBuffer);

	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 2);
	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 4, 2);
	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 8, 2);
	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 12, 2);
	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 16, 2);
	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 20, 2);

	pd3dDevice->EndScene();
	pd3dDevice->Present(NULL, NULL, NULL, NULL);
}

LPDIRECT3DVERTEXBUFFER9 createVBuffer(int size, DWORD usage)
{
	LPDIRECT3DVERTEXBUFFER9 newVBuffer;
	hr = pd3dDevice->CreateVertexBuffer(size, 
										0, 
										usage,
										D3DPOOL_DEFAULT,
										&newVBuffer,
										NULL);
	if FAILED (hr){
		return NULL;
	}

	return newVBuffer;
}

LPDIRECT3DINDEXBUFFER9 createIndexBuffer(int size)
{
	LPDIRECT3DINDEXBUFFER9 newIBuffer;
	hr = pd3dDevice->CreateIndexBuffer(size, 
										D3DUSAGE_WRITEONLY, 
										D3DFMT_INDEX16,
										D3DPOOL_DEFAULT,
										&newIBuffer,
										NULL);
	if FAILED (hr){
		return NULL;
	}

	return newIBuffer;
}

bool setupVBuffer()
{
	Vertex myVertices [] = {
						{-1.0f, 1.0f,-1.0f, 1.0f, D3DCOLOR_ARGB (0, 0, 0, 255), }, // 1
						{1.0f, 1.0f,-1.0f, 1.0f, D3DCOLOR_ARGB (0, 0, 0, 255), }, // 2
						{-1.0f,-1.0f,-1.0f, 1.0f, D3DCOLOR_ARGB (0, 0, 0, 255), }, // 3
						{1.0f,-1.0f,-1.0f, 1.0f, D3DCOLOR_ARGB (0, 0, 0, 255), }, // 4
						{-1.0f, 1.0f, 1.0f, 1.0f, D3DCOLOR_ARGB (0, 0, 0, 255), }, // 5
						{-1.0f,-1.0f, 1.0f, 1.0f, D3DCOLOR_ARGB (0, 0, 0, 255), }, // 6
						{1.0f, 1.0f, 1.0f, 1.0f, D3DCOLOR_ARGB (0, 0, 0, 255), }, // 7
						{1.0f,-1.0f, 1.0f, 1.0f, D3DCOLOR_ARGB (0, 0, 0, 255), }, // 8
						};

	// create buffer
	vBuffer = createVBuffer(sizeof(myVertices) * sizeof(Vertex), D3DFVF_CUSTOMVERTEX);
	
	Vertex* pVertices;
	// lock buffer to be written to
	hr = vBuffer->Lock(0, sizeof(myVertices), (void**) &pVertices, 0);

	if FAILED(hr){
		return false;
	}

	// fill buffer with vertex data
	memcpy(pVertices, myVertices, sizeof(myVertices));

	// unlock the buffer
	vBuffer->Unlock();

	return true;
}

bool setupIBuffer()
{
	WORD indexData [] = {
						0, 1, 2, 3, // Quad 0
						4, 5, 6, 7, // Quad 1
						4, 6, 0, 1, // Quad 2
						5, 2, 7, 3, // Quad 3
						1, 6, 3, 7, // Quad 4
						0, 2, 4, 5  // Quad 5
						};

	// create buffer
	iBuffer = createIndexBuffer(sizeof(indexData) * sizeof(WORD));

	WORD* pIndices;
	// lock buffer to be written to
	hr = iBuffer->Lock(0, sizeof(indexData), (void**) &pIndices, 0);

	if FAILED(hr){
		return false;
	}

	// fill buffer with index data
	memcpy(pIndices, indexData, sizeof(indexData));

	// unlock the buffer
	iBuffer->Unlock();

	return true;
}

void drawVBuffer(LPDIRECT3DVERTEXBUFFER9 vertexBuffer, LPDIRECT3DINDEXBUFFER9 indexBuffer)
{
	D3DXMATRIX matWorld, matScale, matRotate, matTrans;

	D3DXMatrixIdentity(&matWorld);
	D3DXMatrixScaling(&matScale, 200.0f, 200.0f, 200.0f);
	D3DXMatrixTranslation( &matTrans, 0.0f, 0.0f, 5.0f );
	matWorld = matScale * matTrans;
	pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);
	pd3dDevice->BeginScene();
	pd3dDevice->SetStreamSource(0, vertexBuffer, 0, sizeof(Vertex));
	pd3dDevice->SetIndices(indexBuffer);
	pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);

	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 2);
	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 4, 2);
	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 8, 2);
	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 12, 2);
	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 16, 2);
	pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 20, 2);

	pd3dDevice->EndScene();
}

Any help on this would be greatly appreciated! Cheers, James [Edited by - Coder on October 20, 2005 5:36:28 PM]

Share this post


Link to post
Share on other sites
MasterWorks    496
I'm not an expert at this but I'll post some of my Visual Basic code that works. The problem might be in the way you set up and multiply your matrices, but I'm not sure... this is just what I've seen, building up your matrices (exactly what I'm doing isn't relevent to your example):
    'world matrix
D3DXMatrixIdentity mWorldMatrix

D3DXMatrixIdentity matTemp
D3DXMatrixRotationY matTemp, landOffset
D3DXMatrixMultiply mWorldMatrix, mWorldMatrix, matTemp

D3DXMatrixIdentity matTemp
D3DXMatrixRotationX matTemp, msngRotX + msngCubeRotX
D3DXMatrixMultiply mWorldMatrix, mWorldMatrix, matTemp

D3DXMatrixIdentity matTemp
D3DXMatrixRotationY matTemp, msngRotY + msngCubeRotY
D3DXMatrixMultiply mWorldMatrix, mWorldMatrix, matTemp

D3DXMatrixIdentity matTemp
D3DXMatrixRotationZ matTemp, msngRotZ + msngCubeRotZ
D3DXMatrixMultiply mWorldMatrix, mWorldMatrix, matTemp

D3DXMatrixIdentity matTemp
D3DXMatrixTranslation matTemp, msngX + xOffs, msngY + yOffs, msngZ + zOffs

D3DXMatrixMultiply mWorldMatrix, mWorldMatrix, matTemp




...which gives me a mWorldMatrix to use. Maybe this will be some help to you? My code is to rotate/position the Earth (a sphere) on the screen. (The cubeRotX/Y/Z variables are for the skybox rotation.) Some of it is obviously redundant, but maybe you could try that and then delete things that are unnecessary if it works. :)

Share this post


Link to post
Share on other sites
Illco    928
Welcome to the forums. At first glance it seems ok, but at the end of your drawVBuffer function there is a call to EndScene(). Because you are calling this during rendering, which itself calls EndScene() later on, you are calling it one too many times -- remove the one in drawVBuffer. Then, temporarily, remove the polys explicitly drawn in the render function and focus on drawing the vertex buffer contents. Should be ok. If not, please continue the thread.

Greetz,

Illco

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
The custom vertex format you've defined is what's causing your problem:


#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)



By including D3DFVF_XYZRHW in the vertex definition, you're telling the pipeline not to apply any transformations to the geometry. Try changing
your vertex definition to:


#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)



and the vertex struct to:


struct Vertex
{
float x, y, z;
DWORD colour;
};



Hopefully that'll fix your problem.

Share this post


Link to post
Share on other sites
matches81    474
I´m a bit confused since you seem to render the same stuff in render() and drawVBuffer(), additionally to the double EndScene() calls already mentioned.
This shouldn´t have any effect on the transformations, though, as far as I can see, just though I´d mention it.

Share this post


Link to post
Share on other sites
uncle albert    122
Quote:
Original post by Anonymous Poster
The custom vertex format you've defined is what's causing your problem:

*** Source Snippet Removed ***

By including D3DFVF_XYZRHW in the vertex definition, you're telling the pipeline not to apply any transformations to the geometry. Try changing
your vertex definition to:

*** Source Snippet Removed ***

and the vertex struct to:

*** Source Snippet Removed ***

Hopefully that'll fix your problem.


Someone give this man a medal! THANK YOU! :D

As for the duplicate code, that was due to me poorly copying code into a separate function (i.e. forgetting to remove the code from the render() function).

What a wonderful start to life on the forums! I've been looking at this problem for 2 nights in a row, and within 30 minutes you guys have shed some light!

Many thanks all,

James

Share this post


Link to post
Share on other sites

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