• Advertisement
Sign in to follow this  

Custom Vertex Problem

This topic is 4526 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

I created a FVF as follows:
struct CUSTOMVERTEX
{
	float x, y, z;
	DWORD color;
};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)



When I attempted to draw the primitives, the functions succeeded, but no triangle had appeared. I then changed my FVF to:
struct CUSTOMVERTEX
{
	float x, y, z, rhw;
	DWORD color;
};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)


This second form worked. I was hoping someone could tell me why. I have working code at the moment, but I still would like to understand why the first FVF didn't work. Here's the entire working code portion if you need to view it. Please note that if you simply change the FVF in the working version... it no longer works (Please excuse the look of the code. It's all temp stuff for this new book I got on learning DirectX).
// main.cpp
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <fstream.h>

struct CUSTOMVERTEX
{
	float x, y, z, rhw;
	DWORD color;
};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

HWND hWnd = NULL;
HDC	hDC = NULL;
IDirect3D9 *pD3D = NULL;
RECT windowRect;

int aryKeys[256];

IDirect3DDevice9* CreateDevice();
// Returns a pointer to a newly created device for use of this program

LRESULT CALLBACK WndProc (HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
{
	switch (umsg)
	{
		// *****KEY INPUT*****
		case WM_KEYDOWN:
			aryKeys[wParam] = 1;
			break;

		case WM_KEYUP:
			aryKeys[wParam] = 0;
			break;

		// *****EXTRA*****
		case WM_CLOSE:
			PostQuitMessage(0);
			return 0;
			break;

		case WM_DESTROY:
			PostQuitMessage (0);
			return 0;
			break;
	}

	return DefWindowProc (hwnd, umsg, wParam, lParam);
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
{
	// Window Variables
	MSG msg;
	WNDCLASS mainWindow;
	DEVMODE *mainScreen = NULL;

	// Direct3D Variables
	IDirect3DDevice9 *pd3dDevice1 = NULL;

	// Temp Variables
	IDirect3DSurface9 *backBuffer = NULL;
	IDirect3DSurface9 *surface1 = NULL;
	D3DXIMAGE_INFO imageInfo;
	IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
	VOID *pVertices = NULL;
	D3DXMATRIX transform;
	D3DXMATRIX view;
		D3DXVECTOR3 eyes (0.0f, -5.0f, 0.0f);
		D3DXVECTOR3 lookAt (0.0f, 0.0f, 0.0f);
		D3DXVECTOR3 up (0.0f, 1.0f, 0.0f);
	D3DXMATRIX projection;


	// Setup Errors
	HRESULT error;
	fstream errorFile;
	errorFile.open("ErrorFile.txt", ios::out, filebuf::sh_write);

	// Initialize any variables
	windowRect.top = 0;
	windowRect.left = 0;
	windowRect.bottom = 768;
	windowRect.right = 1024;
	memset(&aryKeys, 0, sizeof(aryKeys));

	// Setup the main window
	memset(&mainWindow, 0, sizeof(mainWindow));
	mainWindow.lpszClassName = "Supply Lines";
	mainWindow.lpszMenuName = NULL;
	mainWindow.cbClsExtra = 0;
	mainWindow.cbWndExtra = 0;
	mainWindow.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	mainWindow.hCursor = LoadCursor(NULL, IDC_ARROW);
	mainWindow.hIcon = NULL;
	mainWindow.lpfnWndProc = (WNDPROC)WndProc;
	mainWindow.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

	// Register the main window
	if (!RegisterClass(&mainWindow))
	{
		MessageBox(NULL, "Error Registering Class", NULL, NULL);
		return FALSE;
	}
	
	// Create the window
	hWnd = CreateWindowEx(WS_EX_APPWINDOW, "Supply Lines", "Supply Lines", WS_POPUP, 0, 0, 
		windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, NULL, NULL, hInstance, NULL);

	if (!(hDC = GetDC(hWnd)))
	{
		MessageBox(NULL, "Error Creating Window", NULL, NULL);
		return FALSE;
	}	

	// Create and setup for Direct3D
	if (!(pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
	{
		MessageBox(NULL, "Error Creating Direct3D Object", NULL, NULL);
		return FALSE;
	}

	// Create device 1
	if ((pd3dDevice1 = CreateDevice()) == NULL)
		return false;

	// Show the window
	ShowWindow(hWnd, SW_SHOW);

	// Setup Temp stuff
	pd3dDevice1->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
	D3DXGetImageInfoFromFile("starship.bmp", &imageInfo);
	pd3dDevice1->CreateOffscreenPlainSurface(imageInfo.Width, imageInfo.Height, 
		D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surface1, NULL);
	D3DXLoadSurfaceFromFile(surface1, NULL, NULL, "starship.bmp", NULL, D3DX_FILTER_NONE, 0, NULL);

	CUSTOMVERTEX triangle1[] = 
	{
		{150.0f, 50.0f, .5f, 1.0f, D3DCOLOR_XRGB(255, 0, 255), },
		{250.0f, 250.0f, .5f, 1.0f, D3DCOLOR_XRGB(0, 255, 0), },
		{50.0f, 250.0f, .5f, 1.0f, D3DCOLOR_XRGB(255, 255, 0), },
	};
	
	// Create the vertex buffer
	pd3dDevice1->CreateVertexBuffer(sizeof(CUSTOMVERTEX)*3, 0, D3DFVF_CUSTOMVERTEX, 
		D3DPOOL_SYSTEMMEM, &pVertexBuffer, NULL);

	// Lock the buffer
	pVertexBuffer->Lock(0, sizeof(triangle1), (void**)&pVertices, 0);

	// Fill it
	memcpy(pVertices, triangle1, sizeof(triangle1));

	// Unloack the buffer
	pVertexBuffer->Unlock();

	// **************MAIN LOOP******************
	while (msg.message != WM_QUIT)
	{
		if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
		{
			TranslateMessage (&msg);
			DispatchMessage (&msg);	
		}	
		else
		{
			// Make sure device 1 is ready for use
			if ((pd3dDevice1->TestCooperativeLevel()) == D3DERR_DEVICENOTRESET)
			{
				pd3dDevice1->Release();
				pd3dDevice1 = CreateDevice();

				// Setup temp stuff
				pd3dDevice1->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
				D3DXGetImageInfoFromFile("starship.bmp", &imageInfo);
				pd3dDevice1->CreateOffscreenPlainSurface(imageInfo.Width, imageInfo.Height, 
					D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surface1, NULL);
				D3DXLoadSurfaceFromFile(surface1, NULL, NULL, "starship.bmp", NULL, D3DX_FILTER_NONE, 0, NULL);
				
			}
			else
			{
				// Key Input
				if (aryKeys[VK_ESCAPE] == 1)
					PostQuitMessage(0);	

				// Clear the scene
				pd3dDevice1->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 
					D3DCOLOR_XRGB(200, 200, 200), 1.0f, 0);
				
				// Setup the Transformation Matrix
				D3DXMatrixIdentity(&transform);
				D3DXMatrixTranslation(&transform, 0, 0, 0);
				pd3dDevice1->SetTransform(D3DTS_WORLD, &transform);

				// Setup the View Matrix
				D3DXMatrixIdentity(&view);
				D3DXMatrixLookAtLH(&view, &eyes, &lookAt, &up);
				pd3dDevice1->SetTransform(D3DTS_VIEW, &view);

				// Setup the Projection Matrix
				D3DXMatrixIdentity(&projection);
				D3DXMatrixPerspectiveFovLH(&projection, D3DX_PI / 4,
					windowRect.right / windowRect.bottom, 1.0f, 500.0f);
				pd3dDevice1->SetTransform(D3DTS_VIEW, &projection);
				
				// Draw the scene
				pd3dDevice1->BeginScene();
					pd3dDevice1->SetStreamSource(0, pVertexBuffer, 0, sizeof(CUSTOMVERTEX));
					pd3dDevice1->SetFVF(D3DFVF_CUSTOMVERTEX);
					pd3dDevice1->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
					pd3dDevice1->UpdateSurface(surface1, NULL, backBuffer, NULL);	
				pd3dDevice1->EndScene();

				// Present the scene
				pd3dDevice1->Present(NULL, NULL, NULL, NULL);
			}
		}
	}
	// **************END MAIN LOOP *************

	// Clean up
	pd3dDevice1->Release();
	pD3D->Release();
	ReleaseDC(hWnd, hDC);
	DestroyWindow(hWnd);
	UnregisterClass("Supply Lines", hInstance);

	// Close Error File
	errorFile.close();
	
	return msg.wParam;
}

IDirect3DDevice9* CreateDevice()
{
	IDirect3DDevice9 *pd3dDevice = NULL;
	D3DPRESENT_PARAMETERS d3dPP;
	ZeroMemory(&d3dPP, sizeof(d3dPP));

		// Setup the Present Paramters
	d3dPP.BackBufferWidth = windowRect.right;
	d3dPP.BackBufferHeight = windowRect.bottom;
	d3dPP.BackBufferFormat = D3DFMT_X8R8G8B8;
	d3dPP.BackBufferCount = 1;
	d3dPP.MultiSampleType = D3DMULTISAMPLE_NONE;
	d3dPP.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dPP.Windowed = true;
	d3dPP.hDeviceWindow = hWnd;
	d3dPP.EnableAutoDepthStencil = true;
	d3dPP.AutoDepthStencilFormat = D3DFMT_D16;
	d3dPP.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

	if (D3D_OK != (pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 
		D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dPP, &pd3dDevice)))
	{
		MessageBox(NULL, "Error Creating Direct3D Device 1", NULL, NULL);
		return NULL;
	}

	return pd3dDevice;
}



Share this post


Link to post
Share on other sites
Advertisement
Hi there sniper1263,
How are you doing?

The Problem
Changing the vertex format from xyz -> xyzrhw makes the primitive visible.

The Solution
A couple of things that I notice right off the bat.

1) XYZRHW tells direct3d that you are drawing transformed vertices, by that I mean that the vertices you define are in screenspace (of your window).

2) Another thing that I noticed is that your camera is moved -5 in the y axis, so you are essentially moving the camera to the bottom of your primitive. So if you decided to define vertices of sizes
(-1.0f, 0.0f, 0.0f)
( 0.0f, 1.0f, 0.0f)
( 1.0f, 0.0f, 0.0f)
for a triangle and if you move the camera -5 in the y-axiz, you won't see the triangle.

3) Another thing that I noticed is that you are defining a pretty large primitive. This might mean that if you did choose the D3DFVF_XYZ your primitive might not be visible.

4) For your projection matrix I see you have setup your near clipping plane to be at 1.0f and 500.0f, this might also be a problem if you are rendering primitives at 0.5 in the z axiz since direct3d will just clip them.
To fix it just change your triangle's z axis to 1.0f instead of 0.5f

I hope this helps. Take care.

Share this post


Link to post
Share on other sites
Well, thank you for the help... I haven't gotten it to work without the RHW, but I atleast now know what the RHW is for. I guess I'm just going to have to fiddle with it here and there, or do some more research on this. If anyone else could help me... please do.

Share this post


Link to post
Share on other sites
Ok, no need for help. I fixed the problem I had. I needed:


// Turn off culling, so we see the front and back of the triangle
pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

// Turn off D3D lighting, since we are providing our own vertex colors
pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

Share this post


Link to post
Share on other sites
Transformed vertices are best used for 2D stuff. Here's an article on rendering 2D images... the fast and easy way without having to modify the camera or deal with any vertex buffers.

Click here
The example is written in Direct3D 8, but you can easily port it to Direct3D 9 by changing the numbers and includes and change IDirect3DDevice8::SetVertexShader to IDirect3DDevice9::SetFVF. I encourage you to take advantage of the IDirect3DDevice9::DrawPrimitiveUP command.

I hope that this is useful to you :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement