Need help with code

Started by
4 comments, last by PoLiSh_Peta 20 years, 3 months ago
Hi everyone, Expect posts from me on this forum now :D I''m using Jim Adam''s book and Drunken Hyena''s tutorials. After 4.5 months of C++, it''s a welcoming change :D Anyway, I''m basically playing around at the moment, mixing some of his code with Drunken Hyena''s, and this program isn''t working correctly. I can''t find the problem either. This is supposed to open at fullscreen, display a square, with a texture on it. The screen is constantly flashing a purple like color on opening. The texture is in the correct directory, but I doubt that''s having an impact at the moment. Here''s my code: Thanks -Peter

//These are the necessary includes

#define WIN32_LEAN_AND_MEAN //Excludes rarely used stuff

#include <windows.h>
#include <d3dx8.h>

#pragma comment( lib, "d3d8.lib" )//Includes libraries

#pragma comment( lib, "d3dx8.lib" )

//All the function prototypes

void FatalError( const char* p_error_msg );
void FatalError( HRESULT p_hr, const char* p_error_msg );
LRESULT CALLBACK default_window_proc(HWND p_hwnd,UINT p_msg,WPARAM p_wparam,LPARAM p_lparam);
void init_window();
void kill_window();
void init_d3d();
void kill_d3d();
void init_scene();
void kill_scene();
void message_pump();
D3DFORMAT find_16bit_mode();
void render();
void NOP(HINSTANCE p_prev_instance,LPSTR p_cmd_line,int p_show);

//Name of the application

const char g_app_name[] = "Framework for Tutorials";

//Screen window sizes

const int g_width = 640;
const int g_height = 480;

//Global handle to main window

HWND g_main_window = NULL;

//Global handle to our instance

HINSTANCE g_instance;

//Global flag to check if app should end

bool g_app_done = false;

//Main DIRECT3D8 object

IDirect3D8* g_D3D=NULL;

//DIRECT3DDEVICE object

IDirect3DDevice8* g_d3d_device = NULL;

struct my_vertex
{
	FLOAT x, y, z;
	FLOAT rhw;
	FLOAT u, v;
};

#define VERTEXFVF ( D3DFVF_XYZRHW | D3DFVF_TEX1 )

my_vertex g_Square[ 4 ] =
{
	{ 150.0f, 150.0f, 0.0f, 1.0f, 0.0f, 0.0f },
	{ 150.0f, 300.0f, 0.0f, 1.0f, 0.0f, 1.0f },
	{ 300.0f, 150.0f, 0.0f, 1.0f, 1.0f, 0.0f },
	{ 300.0f, 300.0f, 0.0f, 1.0f, 1.0f, 1.0f }
};



//Make a vertex buffer

IDirect3DVertexBuffer8* g_VB = NULL;

//Make a texture pointer

IDirect3DTexture8* g_Texture = NULL;


//WinMain function

int APIENTRY WinMain(HINSTANCE p_instance,HINSTANCE p_prev_instance,LPSTR p_cmd_line,int p_show)
{
	//Save the instance in the function

	g_instance = p_instance;

	//Quiet compiler warnings

	NOP(p_prev_instance,p_cmd_line,p_show);

	//Build window

	init_window();

	//Build 3D objects

	init_d3d();
	
	//Preparation to build objects and other stuff

	init_scene();

	//Loop until the user aborts

	while( !g_app_done )
	{
		message_pump(); //Check for window messages

		render(); // Render stuff

	}

	//Free all objects and resources

	kill_scene();

	//Clean up all 3D objects

	kill_d3d();

	//Close down window

	kill_window();

	//Exit

	return 0;
}

//FUNCTION DEFINITIONS


void NOP(HINSTANCE p_prev_instance,LPSTR p_cmd_line,int p_show)
{

   p_prev_instance=p_prev_instance;
   p_cmd_line=p_cmd_line;
   p_show=p_show;
}

void message_pump()
{
	MSG msg;

	if(PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
}

//Registers a window class and then creates the window

void init_window()
{
	ULONG window_width, window_height;
	WNDCLASS window_class;
	DWORD style;

   //Fill in all the fields for the WNDCLASS structure.  Window classes

   //are a sort of template for window creation.  You could create many

   //windows using the same window class.

   window_class.style          = CS_OWNDC;
   window_class.cbClsExtra     = 0;
   window_class.cbWndExtra     = 0;
   window_class.hInstance      = g_instance;
   window_class.hIcon          = LoadIcon(NULL,IDI_APPLICATION);
   window_class.hCursor        = LoadCursor(NULL,IDC_ARROW);
   window_class.hbrBackground  = (HBRUSH)GetStockObject(BLACK_BRUSH);
   window_class.lpszMenuName   = NULL;
   window_class.lpszClassName  = "DH Class";
   //Here we provide our default window handler, all windows messages

   //will be sent to this function.

   window_class.lpfnWndProc    = default_window_proc;


   //Register the class with windows

   if(!RegisterClass(&window_class)){
      FatalError("Error registering window class");
   }

   //When running full screen, we cover the desktop with our window.

   //This isn''t necessary, but it provides a smoother transition for the

   //user, especially when we''re going to change screen modes.

   
   window_width=GetSystemMetrics(SM_CXSCREEN);
   window_height=GetSystemMetrics(SM_CYSCREEN);
   style=WS_POPUP;

   //Here we actually create the window.  For more detail on the various

   //parameters please refer to the Win32 documentation.

   g_main_window=CreateWindow("DH Class", //name of our registered class

                              g_app_name, //Window name/title

                              style,      //Style flags

                              0,          //X position

                              0,          //Y position

                              window_width,//width of window

                              window_height,//height of window

                              NULL,       //Parent window

                              NULL,       //Menu

                              g_instance, //application instance handle

                              NULL);      //pointer to window-creation data


   if(!g_main_window){
      FatalError("Error opening window");
   }

   //The next 3 lines just make sure that our window is visible and has the

   //input focus.  It''s not strictly necessary, but it doesn''t hurt to be

   //thorough.

   ShowWindow(g_main_window,SW_SHOW);
   UpdateWindow(g_main_window);
   SetFocus(g_main_window);

}

//Unregister and destroy window

void kill_window(){

   //Test if our window is valid

   if(g_main_window){
      if(!DestroyWindow(g_main_window)){
         //We failed to destroy our window, this shouldn''t ever happen

         MessageBox(NULL,"Destroy Window Failed",g_app_name,MB_OK|MB_ICONERROR|MB_TOPMOST);
      }else{
         MSG msg;
         //Clean up any pending messages

         while(PeekMessage(&msg, NULL, 0, 0,PM_REMOVE)){
            DispatchMessage(&msg);
         }
      }
      //Set our window handle to NULL just to be safe

      g_main_window=NULL;
   }

   //Unregister our window, if we had opened multiple windows using this

   //class, we would have to close all of them before we unregistered the class.

   if(!UnregisterClass("DH Class",g_instance)){
      MessageBox(NULL,"Unregister Failed",g_app_name,MB_OK|MB_ICONERROR|MB_TOPMOST);
   }

}

//Set up Direct3D and create the device

void init_d3d()
{
	HRESULT hr;
	D3DPRESENT_PARAMETERS d3dpp;

   //Create Direct3D8, this is the first thing you have to do in any D3D8 program

   //Always pass D3D_SDK_VERSION to the function.

   g_D3D = Direct3DCreate8( D3D_SDK_VERSION );
   if(!g_D3D ){
      FatalError("Direct3DCreate8():Error creating Direct3D.");
   }

   //Clear out our D3DPRESENT_PARAMETERS structure.  Even though we''re going

   //to set virtually all of its members, it''s good practice to zero it out first.

   ZeroMemory(&d3dpp,sizeof(d3dpp));

   //Whether we''re full-screen or windowed these are the same.

   d3dpp.SwapEffect     = D3DSWAPEFFECT_DISCARD; // Throw away previous frames, we don''t need them

   d3dpp.hDeviceWindow  = g_main_window;  //This is our main (and only) window

   d3dpp.BackBufferCount= 1;  //We only need a single back buffer



   //BackBufferWidth/Height have to be set for full-screen apps, these values are

   //used (along with BackBufferFormat) to determine the display mode.

   //They aren''t needed in windowed mode since the size of the window will be used.

   //BackBufferFormat is the pixel format we want.  


   d3dpp.Windowed          = FALSE;
   d3dpp.BackBufferWidth   = g_width;
   d3dpp.BackBufferHeight  = g_height;
   //In full-screen we need to find a pixel format we like, see find_16bit_mode()

   //below for more details.

   d3dpp.BackBufferFormat  = find_16bit_mode();
 

   //After filling in our D3DPRESENT_PARAMETERS structure, we''re ready to create our device.

   //Most of the options in how the device is created are set in the D3DPRESENT_PARAMETERS

   //structure.

   hr=g_D3D->CreateDevice(D3DADAPTER_DEFAULT, //The default adapter, on a multimonitor system

                                              //there can be more than one.

                           //Use hardware acceleration rather than the software renderer

                          D3DDEVTYPE_HAL,
                          //Our Window

                          g_main_window,
                          //Process vertices in software. This is slower than in hardware,

                          //But will work on all graphics cards.

                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                          //Our D3DPRESENT_PARAMETERS structure, so it knows what we want to build

                          &d3dpp,
                          //This will be set to point to the new device

                          &g_d3d_device);
   if(FAILED(hr)){
      FatalError(hr,"CreateDevice():Error creating device");
   }


}

//Kill D3D

void kill_d3d(){

   if(g_d3d_device){
      g_d3d_device->Release();
      g_d3d_device=NULL;
   }

   if(g_D3D){
      g_D3D->Release();
      g_D3D=NULL;
   }

}

//Initialize scene

void init_scene()
{

	HRESULT hr;
	BYTE* Ptr;

	hr = g_d3d_device-> CreateVertexBuffer ( 4 * sizeof( my_vertex ),
											 D3DUSAGE_WRITEONLY,
											 VERTEXFVF,
											 D3DPOOL_MANAGED,
											 &g_VB );

	D3DXCreateTextureFromFile( g_d3d_device, "Texture.bmp", &g_Texture );

	hr = g_VB->Lock( 0, 0, &Ptr, 0 );

	memcpy( Ptr, g_Square, sizeof( g_Square ) );

}

//Kill scene

void kill_scene()
{

	if ( g_VB )
	{
		g_VB -> Release();
		g_VB = NULL;
	}

	if ( g_Texture )
	{
		g_Texture-> Release();
		g_Texture = NULL;
	}

}

//Find 16bit mode

D3DFORMAT find_16bit_mode()
{
	HRESULT hr;

   //CheckDeviceType() is used to verify that a Device can support a particular display mode.


   //First we test for R5G6B5.  All 16-bits are used in this format giving us a full 64K worth

   //worth of colours

   hr=g_D3D->CheckDeviceType(D3DADAPTER_DEFAULT, //Test the primary display device, this is

                                                 //necessary because systems can have add-on cards

                                                 //or multi-monitor setups

                             D3DDEVTYPE_HAL,  //This states that we want support for this mode

                                              //in hardware rather than emulated in software

                             D3DFMT_R5G6B5,   //The is the primary (viewable) buffer format

                             D3DFMT_R5G6B5,   //This is the back (drawable) buffer format

                             FALSE);   //Is this windowed mode?  Nope

   if(SUCCEEDED(hr)){
      return D3DFMT_R5G6B5;
   }

   //Next try X1R5G5B5. Since 1 bit is wasted it''s technically a 15-bit mode and only

   //provides 32K colours, though you''d be hard pressed to tell the difference between

   //15- & 16-bit modes.

   hr=g_D3D->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,D3DFMT_X1R5G5B5,D3DFMT_X1R5G5B5,FALSE);
   if(SUCCEEDED(hr)){
      return D3DFMT_X1R5G5B5;
   }

   //This is a freaky card.  Complain and bail out.

   FatalError(hr,"find_16bit_mode():Couldn''t find a decent 16-bit mode");

   //Won''t actually hit this line since FatalError() kills us, but it makes the compiler happy.

   return (D3DFORMAT)NULL;
}

//Render the scene

void render()
{
	g_d3d_device->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );

	if(SUCCEEDED(g_d3d_device->BeginScene()))
	{
		g_d3d_device-> SetVertexShader( VERTEXFVF );
		g_d3d_device-> SetStreamSource( 0, g_VB, sizeof( my_vertex ) );
		g_d3d_device-> SetTexture( 0, g_Texture );
		g_d3d_device-> DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

		g_d3d_device-> SetTexture( 0, NULL );

		g_d3d_device-> EndScene();

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

//FatalError Closes down all the stuff and notifies user

void FatalError(const char *p_error_msg)
{

   kill_scene();

   kill_d3d();

   kill_window();

   //Write our error message out to the debugger (if it''s active)

   OutputDebugString( p_error_msg );
   OutputDebugString("\n");
   MessageBox(NULL, p_error_msg,g_app_name, MB_OK );

   exit(5);

}

//Another FatalError

void FatalError(HRESULT p_hr,const char *p_error_msg)
{
	char buffer[255];

   
   D3DXGetErrorStringA(p_hr,buffer,250);

   strcat(buffer,"\n");
   strcat(buffer,p_error_msg);

   kill_scene();

   kill_d3d();

   kill_window();

   //Write our error message out to the debugger (if it''s active)

	OutputDebugString( buffer );
   OutputDebugString("\n");
	MessageBox(NULL, buffer,g_app_name, MB_OK );

   exit(5);

}

//Windows message handler

LRESULT CALLBACK default_window_proc(HWND p_hwnd,UINT p_msg,WPARAM p_wparam,LPARAM p_lparam)
{
   
   switch(p_msg)
   {
      case WM_KEYDOWN:  // A key has been pressed, end the app

      case WM_CLOSE:    //User hit the Close Window button, end the app

      case WM_LBUTTONDOWN: //user hit the left mouse button

         g_app_done=true;
         return 0;
      case WM_DESTROY:  //This window is being destroyed, tell Windows we''re quitting

         PostQuitMessage(0);
         return 0;
   }

   return (DefWindowProc(p_hwnd,p_msg,p_wparam,p_lparam));

}

There are two inevitabilities in life: death and failure.-PoLiSh
Advertisement
Your code works on mine, but there are a couple of things you need to do.

1. You need to unlock your vertex buffer after you''ve finished writing to it. E.G.

hr = g_VB->Lock( 0, 0, &Ptr, 0 );

memcpy( Ptr, g_Square, sizeof( g_Square ) );

g_VB->Unlock();

2. To make sure your square is visible, you should set the following render states:

g_d3d_device-> SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
g_d3d_device-> SetRenderState( D3DRS_LIGHTING, FALSE );

---------------------------------------

Let''s struggle for our dream of Game!

http://andrewporritt.4t.com
The way his vertices are setup, I would turn culling off, since the first triangle is clockwise, and the second is counter-clockwise.
TechleadEnilno, the Ultima 2 projectwww.dr-code.org/enilno
The culling line had to be in there, because my screen was just completely black without it. Thanks for the help!

-Peter
There are two inevitabilities in life: death and failure.-PoLiSh
Because he''s using tri-strips, D3D automatically alternates between counter- and clockwise culling

---------------------------------------

Let''s struggle for our dream of Game!

http://andrewporritt.4t.com
Welcome, Polish_Peta.
Hope you enjoy your time here

Just a couple of non-D3D guidlines:
- Make sure you read the FAQs. The general Forums FAQ, and the DirectX FAQ.
- Please use descriptive topic titles, so that you can get faster help.
- Generally, you should avoid posting much code - it scares people away
Seriously, a lot of people that want to help don''t have the time to read the whole code, or compile it and try it. So try to narrow down the problem and post the relevant code only.

Regarding D3D:
- I really recommend downloading and installing the DirectX debug runtime, then enabling the debug D3D version (via Control Panel->DirectX) whenever you do D3D development.

The help it provides is invaluable. Whenever something fails, it''ll tell you about it, in a - usually - very clear manner. Posting debug output along with code will also increase the chance of your post being replied to.

If you don''t have Visual Studio (and thus unable to view the debug output from your IDE) you can use debug viewers like dbmon.exe (or any other equivalents). You might also want to try D3DSpy (a tool that comes with the SDK), which tracks D3D calls, errors, and such stuff.

- I recommend following a tutorial series, instead of relying on the Docs. At least for the first few programs you write. I recommend DrunkenHyena''s tutorials. You may also want to look for Andy Pike''s tutorials (I think his website is down...There''s an alternate address though. A google search should find it)

That''s all for now. Good luck in your future endeavors, you''re going to need it

Muhammad Haggag

This topic is closed to new replies.

Advertisement