Sign in to follow this  
m4gnus

just rednering a quad(2 trianagles)

Recommended Posts

Hi First: I'm totally new to DirectX and i just want to render a simple quad to the screen...i finally found a directX 9.0 script that worked on my pc (i searched 3 days for a working dx9 tut [i have visual c++ 6 compiler] because the dx9 samples didn't work). This script just creates a simple triangle on the screen and i want to expand the script and let it draw a quad using an indexbuffer. After fixing some errors it just shows an empty window :( can somebody tell me what's wrong?? btw.i don't understand the indexBuffer->Lock part i just copied that void *p Vertices part from the vertexBUffer...so i would be glad if soemone could explain that part. The code:
//****************************************************************************
//**
//**	Direct3D9 Tutorial #2
//**    Direct3D9Tutorial002.cpp
//**    Ein Dreieck
//**
//**    Copyright (c) 2004 Christoph Slamanig
//**
//****************************************************************************

//============================================================================
//    VORKOMPILIERTE HEADER
//============================================================================

#include				<windows.h>
#include				<d3d9.h>

//============================================================================
//    DEFINITIONEN
//============================================================================

#define					ERRORMSG "Fehler"

//============================================================================
//    TYPDEFINITIONEN
//============================================================================

typedef struct
{
    float x, y, z, rhw;
    DWORD color;

	enum FVF
	{
		FVF_Flags = D3DFVF_XYZRHW|D3DFVF_DIFFUSE,
	};

} VERTEX;

//============================================================================
//    FUNKTIONSPROTOTYPEN
//============================================================================

HRESULT					InitD3D();
HRESULT					InitGeometry();
void					CleanUp();
void					Render();
LRESULT CALLBACK		MsgProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

//============================================================================
//    GLOBALE VARIABLEN
//============================================================================

LPDIRECT3D9				g_pD3D			= NULL;
LPDIRECT3DDEVICE9		g_pD3DDevice	= NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB			= NULL;
LPDIRECT3DINDEXBUFFER9  iBuffer			= NULL;
HWND					g_hWnd;
HINSTANCE				g_hInstance;
WNDCLASSEX				g_WndClassEx;
int						g_iWidth		= 640;
int						g_iHeight		= 480;
bool					g_bWindowed		= false;

//============================================================================
//    FUNKTIONEN
//============================================================================

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
					PSTR szCmdLine, int iCmdShow)
{
	if ( E_FAIL == InitD3D() )
	{
		MessageBox(0,"Fehler bei der D3D Initialisierung.",ERRORMSG,0);
		CleanUp();
		PostQuitMessage(1);
	}

	if ( E_FAIL == InitGeometry() )
	{
		MessageBox(0,"Fehler bei der Geometrie Initialisierung.",ERRORMSG,0);
		CleanUp();
		PostQuitMessage(1);
	}

	ShowWindow(g_hWnd, iCmdShow);
	UpdateWindow(g_hWnd) ;

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

	return msg.wParam;
}

//============================================================================

LRESULT CALLBACK MsgProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
	switch (iMsg)
	{
		case WM_CREATE:
			return 0;

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

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

//============================================================================

HRESULT InitD3D()
{
	ZeroMemory (&g_WndClassEx, sizeof (WNDCLASSEX));	

	g_hInstance = GetModuleHandle(NULL);
	if ( g_hInstance == NULL )
	{
		MessageBox(0,"Fehler - GetModuleHandle.",ERRORMSG,0);
		PostQuitMessage(1);
		return E_FAIL;
	}

	g_WndClassEx.cbSize			= sizeof (g_WndClassEx);
	g_WndClassEx.style			= CS_CLASSDC;
	g_WndClassEx.lpfnWndProc	= MsgProc;
	g_WndClassEx.cbClsExtra		= 0L;
	g_WndClassEx.cbWndExtra		= 0L;
	g_WndClassEx.hInstance		= g_hInstance;
	g_WndClassEx.hbrBackground	= NULL;
	g_WndClassEx.hCursor		= LoadCursor (NULL, IDC_ARROW);
	g_WndClassEx.hIcon			= LoadIcon (g_hInstance, IDI_APPLICATION);
	g_WndClassEx.hIconSm		= LoadIcon (g_hInstance, IDI_APPLICATION);
	g_WndClassEx.lpszClassName	= "Direct3D9 Tutorial #2";
	g_WndClassEx.lpszMenuName	= NULL;

	if ( RegisterClassEx( &g_WndClassEx ) == 0 )
	{
		MessageBox(0,"Klasse konnte nicht registriert werden.",ERRORMSG,0);
		PostQuitMessage(1);
		return E_FAIL;
	}

	g_hWnd = CreateWindow(	"Direct3D9 Tutorial #2", 
							"Direct3D9 Tutorial #2 - Ein Dreieck", 
							WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU,
							CW_USEDEFAULT,
							CW_USEDEFAULT,
							g_iWidth,
							g_iHeight,
							GetDesktopWindow(),
							NULL,
							g_hInstance,
							NULL);
	if ( g_hWnd == NULL )
	{
		MessageBox(0,"Fenster konnte nicht erstellt werden.",ERRORMSG,0);
		PostQuitMessage(1);
		return E_FAIL;
	}

	if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
	{
		MessageBox(0,"Das Direct3D Objekt konnte nicht erstellt werden.",ERRORMSG,0);
		PostQuitMessage(1);
		return E_FAIL;
	}

	D3DPRESENT_PARAMETERS D3Dpp; 
    ZeroMemory( &D3Dpp, sizeof(D3DPRESENT_PARAMETERS) );
    D3Dpp.Windowed					= g_bWindowed;
    D3Dpp.SwapEffect				= D3DSWAPEFFECT_DISCARD;
    D3Dpp.BackBufferWidth			= g_iWidth;
    D3Dpp.BackBufferHeight			= g_iHeight;
    D3Dpp.BackBufferFormat			= D3DFMT_X8R8G8B8;
    D3Dpp.PresentationInterval		= D3DPRESENT_INTERVAL_IMMEDIATE;
    D3Dpp.EnableAutoDepthStencil	= TRUE;
	D3Dpp.AutoDepthStencilFormat	= D3DFMT_D16;

	if( FAILED( g_pD3D->CreateDevice(	D3DADAPTER_DEFAULT,
										D3DDEVTYPE_HAL,
										g_hWnd,
										D3DCREATE_HARDWARE_VERTEXPROCESSING,
										&D3Dpp,
										&g_pD3DDevice ) ) )
    {
        MessageBox(0,"Direct3D konnte nicht initialisiert werden.",ERRORMSG,0);
		PostQuitMessage(1);
		return E_FAIL;
    }

	return S_OK;
}

//============================================================================

HRESULT InitGeometry()
{


//**************************************************************
//       VERTEX DEFINITION + VERTEXBUFFER + INDEXBUFFER
//**************************************************************
	VERTEX v[] =
    {
        { 100.0f, 100.0f, 0.5f, 1.0f, 0xffff0000, },
        { 300.0f, 100.0f, 0.5f, 1.0f, 0xff00ff00, },
        { 100.0f, 300.0f, 0.5f, 1.0f, 0xffffff00, },
		{ 300.0f, 300.0f, 0.5f, 1.0f, 0xffffff00, },
    };

    if( FAILED( g_pD3DDevice->CreateVertexBuffer(	4*sizeof(v),
													0, VERTEX::FVF_Flags,
													D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    {
		MessageBox(0,"Fehler bei der Erstellung des VertexBuffers.",ERRORMSG,0);
		PostQuitMessage(1);
		return E_FAIL;
    }


    VOID* pVertices;
    if( FAILED( g_pVB->Lock( 0, sizeof(v), (void**)&pVertices, 0 ) ) )
	{
		MessageBox(0,"Fehler beim Schließen des VertexBuffers.",ERRORMSG,0);
		PostQuitMessage(1);
        return E_FAIL;
	}
    memcpy( pVertices, v, sizeof(v) );
    g_pVB->Unlock();
 
//  INDEXBUFFER
    int indices[] ={1,2,4,2,4,3};
    
	g_pD3DDevice->CreateIndexBuffer( 5*sizeof(indices),0,D3DFMT_INDEX16,D3DPOOL_DEFAULT, &iBuffer, NULL);
	VOID* pIndices;
	iBuffer->Lock(0,5*sizeof(indices),(void**)&pIndices,0);
	memcpy (pIndices, indices, sizeof(indices) );
	iBuffer->Unlock();

    return S_OK;
}

//============================================================================

void Render()
{
    g_pD3DDevice->Clear(	0,
							NULL,
							D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
							D3DCOLOR_XRGB(0, 51, 102),
							1.0f,
							0 );

    if( SUCCEEDED( g_pD3DDevice->BeginScene() ) )
    {
		g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(VERTEX) );
		g_pD3DDevice->SetIndices(iBuffer);
		g_pD3DDevice->SetFVF( VERTEX::FVF_Flags );
		g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0,0,5,0,2 );
		
		g_pD3DDevice->EndScene();
    }

    g_pD3DDevice->Present( NULL, NULL, NULL, NULL );
}

//============================================================================

void CleanUp()
{
	if( g_pD3DDevice != NULL) 
		g_pD3DDevice->Release();

	if( g_pD3D != NULL)
        g_pD3D->Release();

	if( g_pVB != NULL )        
		g_pVB->Release();

	UnregisterClass( "Direct3D9 Tutorial #2", g_WndClassEx.hInstance );
}

//****************************************************************************
//**
//**    ENDE MODUL Direct3D9Tutorial002.cpp
//**
//****************************************************************************
regards, m4gnus

Share this post


Link to post
Share on other sites
To start, the vertices start at index 0, not index 1, so all your indices are off by 1.

You store you indices as int, but use index16. Index16 requires that you use short, not int. Also you allocate too many indices by a fluke. I think you were trying to reserve space for 5 indices, when you should have 6 (3 per triangle * 2), but you did 5 * sizeof(array), which allocates enough space for the array 5 times over. You probably want sizeof(short)*6.

There may be more...

edit:

As for the Lock. Lock gives you a pointer to a the actual vertex buffer, or index buffer memory. When locked, you can update the memory. When unlocked you cannot update the memory (you may get away with it, on some cards, in some cases, but it's wrong and is free to crash in the future). When locked, Direct3D cannot use the buffer for rendering. So, typically, you lock, modify, and unlock your resources. The arguments are "where to start to lock", "how much to lock", "where to put the pointer for you to use", and "flags".

If you pass 0 for both the offset and size of the lock, the entire buffer is locked, not just a portion of it. When you use dynamic buffers the lock flags will come into play. You can use the flags to make promises to D3D to not change data it's currently using, and only to append new data onto the end of a buffer. This lets D3D give you a pointer even before it's done using it. For static buffers, passing 0 for flags is fine.

Share this post


Link to post
Share on other sites
Thx for help...
i'll fix the stuff with the indexbuffer and edit this post if other errors occur. but i still don't understand the indexBuffer declaration...i don't understand what Void* pIndices should do...it's pointer to a void variable but void is "nothing" isn't it? and afterwards you use a cast to convert it to (void**). Why?

Edit: It almost works now he draws some verts but i think there are some problems with the order of the verts
Edit2: It works now!! thx a lot! my first self written(self modded) directX application! But i hope someone can help me with the index buffer code i don't understand

Edit3: Another Problem:
Ok now i'm trying to do sth taht is really 3d...first i want to setup the camera because i found out that at default everything with z< -1 or z> 1 will be clipped so i used :
D3DXMATRIX projmatrix;
D3DXMatrixPerspectiveFovLH(&projmatrix,45,D3DX_PI/4, 1.0f, 3.0f);

my first problem was that the compiler didn't find D3DXMATRIX but i had to include d3dmath. But after that the next error occured and nwo i don't know how to fix this :

--------------------Configuration: Direct3D9Tutorial002 - Win32 Debug--------------------
Compiling...
Direct3D9Tutorial002.cpp
Linking...
Direct3D9Tutorial002.obj : error LNK2001: unresolved external symbol _D3DXMatrixPerspectiveFovLH@20
Debug/Direct3D9Tutorial002.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

Direct3D9Tutorial002.exe - 2 error(s), 0 warning(s)


and the function i wrote:

HRESULT SetWorldMatrix()
{
D3DXMATRIX projmatrix;
D3DXMatrixPerspectiveFovLH(&projmatrix,45,D3DX_PI/4, 1.0f, 3.0f);

return S_OK;
}

i hope someone can help me with that...


regards,
m4gnus

[Edited by - m4gnus on November 26, 2004 8:09:12 AM]

Share this post


Link to post
Share on other sites
D3DXMatrixPerspectiveFovLH(mat, fov, aspect, near, far);

fov is the vertical angle, in radians, that you can see. D3DX_PI/4.0f would be good. 45 is way too large (invalid even).

aspect is the ratio of width to height. It's like a scale factor for fov to make it a horizontal fov. You can get away with leaving this at 1.0f, however most display modes at 4:3 (4.0f/3.0f). Widescreen TVs are 16:9 (16.0f/9.0f).

near and far control the closest visible depth and the furthest visible depth. A range of 1 to 3 is pretty small. Even for just learning, it'll probably cause you more trouble than it's worth. Pump up your far to 100, or 1000.

You need to link with d3d8x.lib or d3d8xd.lib (debug version). You can change your project settings or do this:

#ifdef _DEBUG
#pragma comment(lib, "d3d8xd.lib")
#else
#pragma comment(lib, "d3d8x.lib")
#endif

For the lock... it returns a pointer, which can be either a short *, or a long *, depending on whether it's an INDEX16 buffer or an INDEX32 buffer. They could have overloaded it and had two functions, one with short **, and one with long **, but it's simpler for MS to just give you a void ** and let you deal with the pointer type yourself.

The reason for the void**, instead of void * is because void * is a pointer, and void ** is a pointer to a pointer. You're giving D3D a pointer to where to store it's pointer.

Share this post


Link to post
Share on other sites
ok lets advance to problem #999:
now i want to create a cube and try to rotate it but it doesn't show up :( i haven't done the rotation part... the code:
verts:
VERTEX v[] =
{
{ 100.0f, 100.0f, 0.1f,1.0f, 0xffffff00, },//0
{ 300.0f, 100.0f, 0.1f,1.0f, 0xffff0000, },//1
{ 100.0f, 300.0f, 0.1f,1.0f, 0x00ffffff, },//2
{ 300.0f, 300.0f, 0.1f,1.0f, 0xff00ff00, },//3
{ 100.0f, 100.0f, 0.9f,1.0f, 0xffffffff, },//4
{ 300.0f, 100.0f, 0.9f,1.0f, 0xffff0000, },//5
{ 100.0f, 300.0f, 0.9f,1.0f, 0x00ffffff, },//6
{ 300.0f, 300.0f, 0.9f,1.0f, 0xff00ff00, },//7

};

Indices:

short indices[] ={
0,1,2, //FRONTSIDE
1,3,2,
4,5,6, //BACKSIDE
5,7,6,
3,5,1, //RIGHTSIDE
3,7,5,
1,4,5, //UPSIDE
1,4,0,
2,6,0, //LEFTSIDE
2,0,4,
2,6,3, //DOWNSIDE
3,7,6,

};

SetWorldMatrix (this part worked fine with the quad):

HRESULT SetWorldMatrix()
{
D3DXMATRIX projmatrix;
D3DXMatrixPerspectiveFovLH(&projmatrix,3.0f/4.0f,D3DX_PI/4.0f, 0.0f, 1000.0f);
g_pD3DDevice->SetTransform( D3DTS_PROJECTION, &projmatrix );
return S_OK;
}

Renderingpart:

g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(VERTEX) );
g_pD3DDevice->SetIndices(iBuffer);
g_pD3DDevice->SetFVF( VERTEX::FVF_Flags );
g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0,0,8,0,12 );


Btw does anyone know a good tutorial page with tutorials that work with visual c++ 6 and directX9.0?? not even the sdk samples work :( I need some tutorials for beginners..

regards,
m4gnus

Share this post


Link to post
Share on other sites
When using RHW coordinates (x,y,z,rhw), all transforms are skipped. World, View, and Projection matrices will do nothing. You'll need to move to regular XYZ only coordinates at some point, if you want to rotate around you box. Once you do this you're likely to see nothing as you've got no lights, and lighting default to being on. Use this:
pDev->SetRenderState(D3DRS_LIGHTING, false);

You projection matrix has a near of 0. This breaks the math behind projection. Near should be as large as you can tolerate. 1.0f is okay in most cases.

Your box may not be appearing because you've got the vertices in the wrong order. The need to be clockwise to render with default culling (the default value for D3DRS_CULLMODE is D3DCULL_CCW, which says "get rid of counterclockwise triangles).
I'm too lazy to check which order your triangles are in... but as you're just doing simple tests, try:
pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE)

Your VB and IB lock and copy routines had hardcoded sizes in them... Did you update them to new sizes? Go to the control panel, click DirectX, click Direct3D. Choose debug runtime (you did install the debug run time right? If not, there should be an item in the DirectX SDK start menu for installing it.) There should be a slider for debug output level. Put it one step below maximum (maximum tends to be annoying at times, especially for a beginner). Now, if a draw call fails, D3D will output why to your compiler's output window. If your VB or IB size was too small, it's possible that it's saying that you're trying to draw an invalid number of vertices or triangles. Whatever the error, it may be telling you.

If non of this works, try posting your full new version of the code. You've changed vertex structures and other items since your first post, and it's really hard to tell what your full code may be doing now.

Share this post


Link to post
Share on other sites
@ Cullmode,LightningSTuff:
Sorry i forgot to post that but i already added that...
@ <<When using RHW coordinates (x,y,z,rhw), all transforms are skipped>>:
I know but i also forgot to post that update...but i removed the rhw now it's just :
FVF_Flags = D3DFVF_XYZ|D3DFVF_DIFFUSE,

@ <<Your VB and IB lock and copy routines had hardcoded sizes in them... Did you update them to new sizes? Go to the control panel, click DirectX, click Direct3D. Choose debug runtime (you did install the debug run time right? If not, there should be an item in the DirectX SDK start menu for installing it.) There should be a slider for debug output level.>>:

hardcoded?,controlpanel??, what do you mean with hardcoded(sorry not that good at english)? I haven't found a control panel...where is it(in visual c++ 6)

regards,
m4gnus

Share this post


Link to post
Share on other sites
hardcoded: You did things like 4 * sizeof(VERTEX). You're hard coding it to use 4 vertices.

control panel: The one in Windows. Start/Settings/Control Panel/DirectX. You should have a DIRECTX entry in the control panel if your SDK is the same version as your retail DirectX. If your DX SDK is upto date, it should be there. The debug runtimes help track down many bugs. Definately a must for someone starting out.

RHW: You may have removed this from your FVF, but your structure seems to still have it. The data you posted has an x,y,z, some other value, then diffuse. If your structure and your FVF don't match, there's no way D3D can interpret the data correctly.

Share this post


Link to post
Share on other sites
oh yeah you're right with the FVF stuff, but i dunno which part to remove...
@Control Panel: I have a directX entry but i dunno where i can set the debug stuff..

regards,
m4gnus

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