Page 1 of 1

Introduction to DirectX Part II Drawing flashing color text / DirectX Framework

#1 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3121
  • View blog
  • Posts: 19,167
  • Joined: 14-September 07

Posted 04 March 2008 - 05:11 AM

Alright! Well we can all agree that part one to the DirectX intro was boring. all that code and nothing really cool to show for it. This time we'll have something neat to show for it. I'd like to take this opportunity to reiterate that knowledge of Win API and C++ is assumed as well as DirectX/D3D initialization that was covered in the previous tutorial. Here we go!

In this tutorial we will be covering some more indepth functions of DirectX as well as creating a reusable framework for future work. This is the most important part since typing all this crap over and over gets old quick. The idea will be to eventually create your own libraries for repeated use, but we aren't there yet. NOTE: This project has ALOT of code and takes a while to disgest; patience is key here (I was tearing my hair out on a few DX9 changes that my compiler was hating). I compiled this on MSVS 2005 in case you are curious.

Let's first look at the class D3DAPP, which we will use to derive children classes of apps we are currently developing:

//This is the header file including class declaration
//Some directX framework
#ifndef D3DAPP_H
#define D3DAPP_H

#include "d3dUtil.h"
#include <string>

class D3DApp
{
public:
	D3DApp(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP);
	virtual ~D3DApp();

	HINSTANCE getAppInst();
	HWND	  getMainWnd();

	// Framework methods.  Derived client class overrides these methods to 
	// implement specific application requirements.
	virtual bool checkDeviceCaps()	 { return true; }
	virtual void onLostDevice()		{}
	virtual void onresetDevice()	   {}
	virtual void updateScene(float dt) {}
	virtual void drawScene()		   {}

	// Virtual methods
	virtual void initMainWindow();
	virtual void initDirect3D();
	virtual int run();
	virtual LRESULT msgProc(UINT msg, WPARAM wParam, LPARAM lParam);

	void enableFullScreenMode(bool enable);
	bool isDeviceLost();

protected:
	// Derived client class can modify these data members in the constructor to 
	// customize the application.  
	std::string mMainWndCaption;
	D3DDEVTYPE  mDevType;
	DWORD	   mRequestedVP;
	
	// Application, Windows, and Direct3D data members.
	HINSTANCE			 mhAppInst;
	HWND				  mhMainWnd;
	IDirect3D9*		   md3dObject;
	bool				  mAppPaused;
	D3DPRESENT_PARAMETERS md3dPP;
};

// Globals for convenient access.
extern D3DApp* gd3dApp;
extern IDirect3DDevice9* gd3dDevice;

#endif // D3DAPP_H



This is one of two header files and there are only 2 cpp files, only four files total. Let's take a look at the class.


Why make a class? Well, in short we can keep all the good features we want in a reasonable area so we don't have to reinvent the wheel everytime we sit down to write a D3D app. Like in all directx programs we declare a 'global variable pointer' pointing to the device we are making/using. This allows us to make calls to all of the features directx has. For the purpose of this tutorial the virtual functions can be ignored, they are there in the future if you want to override some directx goodies.

We also have data members to check if we are in windowed or full screen mode (the window can change if you click the button in the right hand corner.)

Now let's look at the 'utility' file:

// Contains various utility code for DirectX applications, such as clean up
// and debugging code.

#ifndef D3DUTIL_H
#define D3DUTIL_H

// Enable extra D3D debugging in debug builds if using the debug DirectX runtime.  
// This makes D3D objects work well in the debugger watch window, but slows down 
// performance slightly.
#if defined(DEBUG) | defined(_DEBUG)
#ifndef D3D_DEBUG_INFO
#define D3D_DEBUG_INFO
#endif
#endif

#include <d3d9.h>
#include <d3dx9.h>
#include <dxerr9.h>
#include <string>
#include <sstream>

//===============================================================
// Globals for convenient access.
class D3DApp;
extern D3DApp* gd3dApp;
extern IDirect3DDevice9* gd3dDevice;

//===============================================================
// Clean up

#define ReleaseCOM(x) { if(x){ x->Release();x = 0; } }

//===============================================================
// Debug

#if defined(DEBUG) | defined(_DEBUG)
	#ifndef HR
	#define HR(x)									  \
	{												  \
		HRESULT hr = x;								\
		if(FAILED(hr))								 \
		{											  \
			DXTrace(__FILE__, __LINE__, hr, #x, TRUE); \
		}											  \
	}
	#endif

#else
	#ifndef HR
	#define HR(x) x;
	#endif
#endif 

#endif // D3DUTIL_H



Again, its a lot to digest all at once, but the good news most of this isn't necessary to dive in and experiment. We again have global pointers for access to our class and derivatives of that class. The other important thing here is the debugging code. Directx is a damn complicated library and the easier you can make debugging the more fun you'll have. Putting HR in front of a directx/D3D function call will alert you if the call is bad for whatever reason. This can save a lot of time if you are hunting for a bug. Why did it fail, what parameters made it fail...

All this code and still no coolness. :( I know, but all this framwork/infrastructure will allow us to do minimal coding in the next two files. Here is the cpp file that creates our instance of the D3DApp class seen above and gives it its methods and data members:

//A sample directX demo outputting some flashing color text

#include "d3dApp.h"
#include <tchar.h>
#include <crtdbg.h>

//Our application is derived from the D3DAPP class, making setup for a game 
//or other program easier in the long run
class HelloD3DApp : public D3DApp
{
public:
	HelloD3DApp(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP);
	~HelloD3DApp();

	bool checkDeviceCaps();
	void onLostDevice();
	void onresetDevice();
	void updateScene(float dt);
	void drawScene();

private:

	ID3DXFont* mFont;
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
				   PSTR cmdLine, int showCmd)
{
	// Enable run-time memory check for debug builds.
	#if defined(DEBUG) | defined(_DEBUG)
		_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
	#endif


	HelloD3DApp app(hInstance, "Hello Direct3D", D3DDEVTYPE_HAL, D3DCREATE_HARDWARE_VERTEXPROCESSING);
	gd3dApp = &app;
	
	return gd3dApp->run();
}

HelloD3DApp::HelloD3DApp(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP)
: D3DApp(hInstance, winCaption, devType, requestedVP)
{
	srand(time_t(0));

	if(!checkDeviceCaps())
	{
		MessageBox(0, "checkDeviceCaps() Failed", 0, 0);
		PostQuitMessage(0);
	}

	LOGFONTA font;
	font.lfHeight		   = 80;
				font.lfWidth			= 40;
	font.lfEscapement		= 0;
	font.lfOrientation		= 0;
				font.lfWeight		   = FW_BOLD;
				font.lfItalic		   = true;
	font.lfUnderline		= false;
	font.lfStrikeOut		= false;
				font.lfCharSet		  = DEFAULT_CHARSET;
				font.lfOutPrecision	 = OUT_DEFAULT_PRECIS;
	font.lfClipPrecision	= CLIP_CHARACTER_PRECIS;
				font.lfQuality		  = DEFAULT_QUALITY;
				font.lfPitchAndFamily   = DEFAULT_PITCH | FF_DONTCARE;
			   _tcscpy(font.lfFaceName, _T("Times New Roman"));

	HR(D3DXCreateFontIndirect(gd3dDevice, &font, &mFont));
}

HelloD3DApp::~HelloD3DApp()
{
	ReleaseCOM(mFont);
}

bool HelloD3DApp::checkDeviceCaps()
{
	// Nothing to check.
	return true;
}

void HelloD3DApp::onLostDevice()
{
	HR(mFont->OnLostDevice());
}

void HelloD3DApp::onresetDevice()
{
	HR(mFont->onresetDevice());
}

void HelloD3DApp::updateScene(float dt)
{
}

void HelloD3DApp::drawScene()
{
	HR(gd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0));

	RECT formatRect;
	GetClientRect(mhMainWnd, &formatRect);

	HR(gd3dDevice->BeginScene());

	mFont->DrawText(TEXT("Hello </DIC>!"), -1, 
		&formatRect, DT_CENTER | DT_VCENTER, 
		D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256));

	HR(gd3dDevice->EndScene());
	HR(gd3dDevice->Present(0, 0, 0, 0));
}



Notice in the beginning we derive HelloD3DApp to be from D3DApp class (it inherits all of the functions as well as any new ones you want to put in.) This is the best example of where we don't have to retype all the features of the basic D3DApp into our new class. We simply add the functions that will draw the flashing text and clean up after us. There are other font structs you can use, such as D3DXFONT_DESC it is really your preference and what you can get to compile, they offer virtually all the same features of text customization.

It is important to note that we call the DrawText method inbetween BeginScene and EndScene renders. This gives us the opportunity to update the backbuffer with the current frame each cycle. If we called it somewhere else, it would not be updated.


Now, I know what you're all saying. WTF?! Still nothing to show for our work! Well here is the boilerplate windows code that will give us our awesome flashing text window (either windowed or full screen your choice):

#include "d3dApp.h"

D3DApp* gd3dApp			  = 0;
IDirect3DDevice9* gd3dDevice = 0;

LRESULT CALLBACK
MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	// Don't start processing messages until the application has been created.
	if( gd3dApp != 0 )
		return gd3dApp->msgProc(msg, wParam, lParam);
	else
		return DefWindowProc(hwnd, msg, wParam, lParam);
}

D3DApp::D3DApp(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP)
{
	mMainWndCaption = winCaption;
	mDevType		= devType;
	mRequestedVP	= requestedVP;
	
	mhAppInst   = hInstance;
	mhMainWnd   = 0;
	md3dObject  = 0;
	mAppPaused  = false;
	ZeroMemory(&md3dPP, sizeof(md3dPP));

	initMainWindow();
	initDirect3D();
}

D3DApp::~D3DApp()
{
	ReleaseCOM(md3dObject);
	ReleaseCOM(gd3dDevice);
}

HINSTANCE D3DApp::getAppInst()
{
	return mhAppInst;
}

HWND D3DApp::getMainWnd()
{
	return mhMainWnd;
}

void D3DApp::initMainWindow()
{
	WNDCLASS wc;
	wc.style		 = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc   = MainWndProc; 
	wc.cbClsExtra	= 0;
	wc.cbWndExtra	= 0;
	wc.hInstance	 = mhAppInst;
	wc.hIcon		 = LoadIcon(0, IDI_APPLICATION);
	wc.hCursor	   = LoadCursor(0, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName  = 0;
	wc.lpszClassName = "D3DWndClassName";

	if( !RegisterClass(&wc) )
	{
		MessageBox(0, "RegisterClass FAILED", 0, 0);
		PostQuitMessage(0);
	}

	// Default to a window with a client area rectangle of 800x600.

	RECT R = {0, 0, 800, 600};
	AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false);
	mhMainWnd = CreateWindow("D3DWndClassName", mMainWndCaption.c_str(), 
		WS_OVERLAPPEDWINDOW, 100, 100, R.right, R.bottom, 
		0, 0, mhAppInst, 0); 

	if( !mhMainWnd )
	{
		MessageBox(0, "CreateWindow FAILED", 0, 0);
		PostQuitMessage(0);
	}

	ShowWindow(mhMainWnd, SW_SHOW);
	UpdateWindow(mhMainWnd);
}

void D3DApp::initDirect3D()
{
	// Step 1: Create the IDirect3D9 object.

	md3dObject = Direct3DCreate9(D3D_SDK_VERSION);
	if( !md3dObject )
	{
		MessageBox(0, "Direct3DCreate9 FAILED", 0, 0);
		PostQuitMessage(0);
	}


	// Step 2: Verify hardware support for specified formats in windowed and full screen modes.
	
	D3DDISPLAYMODE mode;
	md3dObject->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);
	HR(md3dObject->CheckDeviceType(D3DADAPTER_DEFAULT, mDevType, mode.Format, mode.Format, true));
	HR(md3dObject->CheckDeviceType(D3DADAPTER_DEFAULT, mDevType, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, false));

	// Step 3: Check for requested vertex processing and pure device.

	D3DCAPS9 caps;
	HR(md3dObject->GetDeviceCaps(D3DADAPTER_DEFAULT, mDevType, &caps));

	DWORD devbehaviorFlags = 0;
	if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
		devbehaviorFlags |= mRequestedVP;
	else
		devbehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;

	// If pure device and HW T&L supported
	if( caps.DevCaps & D3DDEVCAPS_PUREDEVICE &&
		devbehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING)
			devbehaviorFlags |= D3DCREATE_PUREDEVICE;

	// Step 4: Fill out the D3DPRESENT_PARAMETERS structure.

	md3dPP.BackBufferWidth			= 0; 
	md3dPP.BackBufferHeight		   = 0;
	md3dPP.BackBufferFormat		   = D3DFMT_UNKNOWN;
	md3dPP.BackBufferCount			= 1;
	md3dPP.MultiSampleType			= D3DMULTISAMPLE_NONE;
	md3dPP.MultiSampleQuality		 = 0;
	md3dPP.SwapEffect				 = D3DSWAPEFFECT_DISCARD; 
	md3dPP.hDeviceWindow			  = mhMainWnd;
	md3dPP.Windowed				   = true;
	md3dPP.EnableAutoDepthStencil	 = true; 
	md3dPP.AutoDepthStencilFormat	 = D3DFMT_D24S8;
	md3dPP.Flags					  = 0;
	md3dPP.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	md3dPP.PresentationInterval	   = D3DPRESENT_INTERVAL_IMMEDIATE;


	// Step 5: Create the device.

	HR(md3dObject->CreateDevice(
		D3DADAPTER_DEFAULT, // primary adapter
		mDevType,		   // device type
		mhMainWnd,		  // window associated with device
		devbehaviorFlags,   // vertex processing
		&md3dPP,			// present parameters
		&gd3dDevice));	  // return created device
}

int D3DApp::run()
{
   MSG  msg;
   msg.message = WM_NULL;
   while(msg.message != WM_QUIT)
   {
	  // If there are Window messages then process them.
	  if(PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
	{
		 TranslateMessage( &msg );
		 DispatchMessage( &msg );
	}
	// Otherwise, do animation/game stuff.
	else
	  {	
	   // If the application is paused then free some CPU 
		 // cycles to other applications and then continue on
		 // to the next frame.
	   if( mAppPaused )
	   {
		Sleep(20);
		continue;
	   }

	   if( !isDeviceLost() )
	   {
		updateScene(0.0f);
		drawScene();
	   }
	  }
   }
   return (int)msg.wParam;
}


LRESULT D3DApp::msgProc(UINT msg, WPARAM wParam, LPARAM lParam)
{
	// Is the application in a minimized or maximized state?
	static bool minOrMaxed = false;

	RECT clientRect = {0, 0, 0, 0};
	switch( msg )
	{

	// WM_ACTIVE is sent when the window is activated or deactivated.
	// We pause the game when the main window is deactivated and 
	// unpause it when it becomes active.
	case WM_ACTIVATE:
		if( LOWORD(wParam) == WA_INACTIVE )
			mAppPaused = true;
		else
			mAppPaused = false;
		return 0;


	// WM_SIZE is sent when the user resizes the window.  
	case WM_SIZE:
		if( gd3dDevice )
		{
			md3dPP.BackBufferWidth  = LOWORD(lParam);
			md3dPP.BackBufferHeight = HIWORD(lParam);

			if( wParam == SIZE_MINIMIZED )
			{
				mAppPaused = true;
				minOrMaxed = true;
			}
			else if( wParam == SIZE_MAXIMIZED )
			{
				mAppPaused = false;
				minOrMaxed = true;
				onLostDevice();
				HR(gd3dDevice->Reset(&md3dPP));
				onresetDevice();
			}
			// Restored is any resize that is not a minimize or maximize.
			// For example, restoring the window to its default size
			// after a minimize or maximize, or from dragging the resize
			// bars.
			else if( wParam == SIZE_RESTORED )
			{
				mAppPaused = false;

				// Restoration from windowed to fullscreen
				if( minOrMaxed && md3dPP.Windowed )
				{
					onLostDevice();
					HR(gd3dDevice->Reset(&md3dPP));
					onresetDevice();
				}
				else
				{
					//empty on purpose
				}
				minOrMaxed = false;
			}
		}
		return 0;


	// WM_EXITSIZEMOVE is sent when the user releases the resize bars.
	// Here we reset everything based on the new window dimensions.
	case WM_EXITSIZEMOVE:
		GetClientRect(mhMainWnd, &clientRect);
		md3dPP.BackBufferWidth  = clientRect.right;
		md3dPP.BackBufferHeight = clientRect.bottom;
		onLostDevice();
		HR(gd3dDevice->Reset(&md3dPP));
		onresetDevice();

		return 0;

	// WM_CLOSE is sent when the user presses the 'X' button in the
	// caption bar menu.
	case WM_CLOSE:
		DestroyWindow(mhMainWnd);
		return 0;

	// WM_DESTROY is sent when the window is being destroyed.
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	case WM_KEYDOWN:
		if( wParam == VK_ESCAPE )
			enableFullScreenMode(false);
		else if( wParam == 'F' )
			enableFullScreenMode(true);
		return 0;
	}
	return DefWindowProc(mhMainWnd, msg, wParam, lParam);
}

void D3DApp::enableFullScreenMode(bool enable)
{
	// Switch to fullscreen mode.
	if( enable )
	{
		// Are we already in fullscreen mode?
		if( !md3dPP.Windowed ) 
			return;

		int width  = GetSystemMetrics(SM_CXSCREEN);
		int height = GetSystemMetrics(SM_CYSCREEN);

		md3dPP.BackBufferFormat = D3DFMT_X8R8G8B8;
		md3dPP.BackBufferWidth  = width;
		md3dPP.BackBufferHeight = height;
		md3dPP.Windowed		 = false;

		// Change the window style to a more fullscreen friendly style.
		SetWindowLongPtr(mhMainWnd, GWL_STYLE, WS_POPUP);

		SetWindowPos(mhMainWnd, HWND_TOP, 0, 0, width, height, SWP_NOZORDER | SWP_SHOWWINDOW);	
	}
	// Switch to windowed mode.
	else
	{
		// Are we already in windowed mode?
		if( md3dPP.Windowed ) 
			return;

		RECT R = {0, 0, 800, 600};
		AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false);
		md3dPP.BackBufferFormat = D3DFMT_UNKNOWN;
		md3dPP.BackBufferWidth  = 800;
		md3dPP.BackBufferHeight = 600;
		md3dPP.Windowed		 = true;
	
		// Change the window style to a more windowed friendly style.
		SetWindowLongPtr(mhMainWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);

		SetWindowPos(mhMainWnd, HWND_TOP, 100, 100, R.right, R.bottom, SWP_NOZORDER | SWP_SHOWWINDOW);
	}

	// Reset the device with the changes.
	onLostDevice();
	HR(gd3dDevice->Reset(&md3dPP));
	onresetDevice();
}

bool D3DApp::isDeviceLost()
{
	// Get the state of the graphics device.
	HRESULT hr = gd3dDevice->TestCooperativeLevel();

	if( hr == D3DERR_DEVICELOST )
	{
		Sleep(20);
		return true;
	}
	// Driver error, exit.
	else if( hr == D3DERR_DRIVERINTERNALERROR )
	{
		MessageBox(0, "Internal Driver Error...Exiting", 0, 0);
		PostQuitMessage(0);
		return true;
	}
	// The device is lost but we can reset and restore it.
	else if( hr == D3DERR_DEVICENOTRESET )
	{
		onLostDevice();
		HR(gd3dDevice->Reset(&md3dPP));
		onresetDevice();
		return false;
	}
	else
		return false;
}



First few things, this is a little different then the first tutorials game loop. In theory, it it the same, but I call it here differently, since we are using more D3D functions rather then vanilla directx. The steps taken when first starting the program are numbered for convience. Again, a lot of this you might not even use unless you were designing a commerical app (such as confirming hardware support of various lighting and shading functions), but are nice to have in the event you want to play around with them. you probably have noticed at this point that directx uses a lot of CAPS when it is defining things, rather then numbers or variables. I find this to be a good thing as there is little confusion between DEFAULT_SOMETHING and NOT_DEFAULT.


As long as our device is still valid the game will run and draw a random color of text, which will result in 'flashing' text of all kinds of colors. Even though this last file is my least favorite it is important in the regards that it takes care of all the possible window functions (destroyed, moved, focus loss, etc...) that is annoying to program and if not implemented leads the program to not shut down properly, perhaps causing a memory leak.

The flashing code says:

"Hello </DIC>!"

IMPORTANT: Don't forget to link the following into your code for it to compile:
d3d9.lib
d3dx9.lib
dxguid.lib
DxErr9.lib
dinput8.lib

For compiling issues the file names in order of apperance:
d3dApp.h
d3dUtil.h
HelloDirect3D.cpp
d3dApp.cpp
(I can upload the files later if so desired)

Also, for the debug features, you need the latest Directx SDK installed (debug mode). Hopefully you found this enjoyable. I'll delve into some 3D stuff once I brush up on the subject some more. Happy coding all!

Code referenced from Introduction to 3D Game Programming with DirectX 9.0c A Shader Approach by Frank D. Luna
--kya

Is This A Good Question/Topic? 0
  • +

Replies To: Introduction to DirectX Part II

#2 KyleHatch  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 21-January 09

Posted 21 January 2009 - 12:32 PM

Thanks for the tutorials, both first and second part, i've spent a long time trying to understand how you can go from tut1 to tut2 and create a wrapper class, i think i'm a step closer to understanding, so thank you. If you (or anyone else) knows of anything that could help futher my understanding of wrapper classes i would greatly appreciate it.

Kyle.
Was This Post Helpful? 0
  • +
  • -

#3 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3121
  • View blog
  • Posts: 19,167
  • Joined: 14-September 07

Posted 01 February 2009 - 08:58 PM

Sorry for the delay in response. The idea is to make that step big enough so the reader could infer. The only reason a class in introduced is to cut down on boilerplate code.
Was This Post Helpful? 0
  • +
  • -

#4 Aspirina  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 18-July 09

Posted 18 July 2009 - 07:51 AM

View PostKYA, on 4 Mar, 2008 - 04:11 AM, said:

IMPORTANT: Don't forget to link the following into your code for it to compile:
dxguid.lib
dinput8.lib


Why linking to the directinput libs if you're not using directinput at all? It does not help at all by giving the wrong information. I think I know why you put that wrong... that's not your code! you just copied from somewhere else.. maybe a book? I think Frank D. Luna written exactly the same lines I'm reading now in "your" code.

View PostKYA, on 4 Mar, 2008 - 04:11 AM, said:

For compiling issues the file names in order of apperance:
d3dApp.h
d3dUtil.h
HelloDirect3D.cpp
d3dApp.cpp
(I can upload the files later if so desired)


Wouldn't it break some copyright laws if you upload the source from that book? You should give the credits for the one who wrote the code, like this line you removed from the code files:

//=============================================================================
// d3dApp.h by Frank Luna © 2005 All Rights Reserved.
//=============================================================================

I guess you're just trying to help (maybe), but how can I know that you know anything about what you're teaching if you're using stolen code? or maybe you have legal permission to use it. In that case, you should not remove the copyright notice from the code. Did you ever try the code? Also, there are better ways to write that code, I know because I'm reading that book and I've found better ways (I'm gonna upload my tutorial later, to compensate this trolling, but..), so if you already read it enough to speak about the code as if it was yours, you should be able to write a better tutorial, instead of copying it from somewhere else.

You posted someone else's private code and you are telling everyone "you can use this code for future work" which breaks a lot of other copyright laws. I say this because I've learned a lot from the author and I don't like someone else takes the credits for what he's done. Now I don't know if anything I read from you is written by you or by whom? ...

For everyone who wants to follow these tutorials about DirectX 9.0c, I recommend buying Introduction to 3D Game Programming with DirectX 9.0c - A shader approach, by Frank D. Luna. I already bought it and it was one of the best investments I did. There are clarified all those aspects you can't read in this thread. The author is a true proffessional, and the book worths it.

Sorry, I couldn't resist to post when I read this thread. Also sorry about my English, because my native language is Spanish, so actually I don't speak English, I just read or type it.

Cya (in my incoming tutorials).

PD: Looking forward to see the code written by yourself. This way I can compare mine to yours and watch how you solved it (or if you are just a copy & paste pirate kid?). It would be really helpful. Thanks in advance ;)

PD2 (for the readers): I think those books also can be downloaded from mininova or isohunt, just search "game programming books" and you may find it (I'm not sure but is a lot probably). And books don't have ads/banners!. Also ZophusX DirectX tutorials are on the web for free and they really teach the basics about DX, you should read them as your first DX tutorial.
Was This Post Helpful? 0
  • +
  • -

#5 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3121
  • View blog
  • Posts: 19,167
  • Joined: 14-September 07

Posted 21 July 2009 - 01:56 PM

You're absolutely right. I did reference that book. It's a great resource.

However, I didn't feel the need to mention it since it wasn't a direct copy. The tutorial itself is my own creation (albeit a poor one in your opinion) where some of the base for the code comes from Luna's book.

I find it horribly ironic that you are chastising me for using a reference and you advise people to pirate the book itself.

Also, does Frank Luna have copyright on DirectX? So if someone notes it down in a book, online tutorial, etc... no one else can ever use anything similar ever? Wouldn't be a wise investment on Microsoft's part if no one could use their SDK...

If it's not for commercial purposes you can use all the code you want. If you notice, I did not claim anywhere that this code belongs to me. I also doubt you've read the book because (if you had) you would notice that full source isn't even in the damn thing. Thus, one must piece together a project using the snippet provided (generally a piece of framework used as a jumping point).

edit: One more point. Of course there are better ways to write it. There always are. However, the caveat is that it says "introduction". Thus, it is to introduce the material rather then provide the best possible way to do it.

This post has been edited by KYA: 21 July 2009 - 02:09 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1