Skip to main content
GameDev.net gamedev.net
🔒 Locked

Linker error

Started by PoLiSh_Peta Jan 9, 2004 at 11:02 PM 14 replies 850+ views
Original Post
PoLiSh_Peta
PoLiSh_Peta
Hi again, I''m working with 3D stuff now, and I''m getting a linker error. The thing is, I have no idea what it''s referring to! It seems these linker errors are killer. I don''t know what to post either, I don''t wanna post the entire thing, cause someone said people are less likely to look at it, but I don''t kno what segment to post because the error is so generic. Here''s the error: Compiling... WinMain.cpp Linking... LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main Debug/Lesson 5.exe : fatal error LNK1120: 1 unresolved externals Error executing link.exe. Lesson 5.exe - 2 error(s), 0 warning(s) Perhaps I need to add something before working in 3D? I am using the z-buffer of course, but I don''t remember initializing it or something if I have to. Thanks.
There are two inevitabilities in life: death and failure.-PoLiSh
overflowed
overflowed
Call me crazy, but I think we might be missing a main() function.

Check to make sure you''re making a Windows application and not a console app as Windows would be looking for WinMain() and console apps (read: anything other than Windows) would check for main()
PoLiSh_Peta
PoLiSh_Peta
Yikes, I don''t know how that happened. Thanks overflowed, it still doesn''t yield the results, just a black screen but, I''ll see what I can do.

-Peter
There are two inevitabilities in life: death and failure.-PoLiSh
overflowed
overflowed
Heh, don''t worry. Of course, I''VE never done this......................shhh
PoLiSh_Peta
PoLiSh_Peta
I couldn''t find out why it was only showing a black screen
Here''s the source:



//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 CUSTOMVERTEX
{
FLOAT x, y, z;
DWORD color;
};

#define D3D8T_CUSTOMVERTEX ( D3DFVF_XYZ | D3DFVF_DIFFUSE )

CUSTOMVERTEX g_vertices[] =
{
//PYRAMID

{ 0.0f, 1.0f, 0.0f, 0x00FF0000 }, //Top corner

{ 1.0f, -1.0f,-1.0f, 0x0000FF00 }, //Right front

{ -1.0f, -1.0f,-1.0f, 0x000000FF }, //Left front


{ -1.0f, -1.0f, 1.0f, 0x0000FF00 }, //back, left


{ 1.0f, -1.0f, 1.0f, 0x000000FF }, //back, right

{ 1.0f, -1.0f,-1.0f, 0x0000FF00 }, //Right front (repeated to close it up)


//CUBE


{ -1.0f, -1.0f, -1.0f, 0x000000FF }, //Front face

{ -1.0f, 1.0f, -1.0f, 0x000000FF },
{ 1.0f, 1.0f, -1.0f, 0x000000FF },
{ 1.0f, 1.0f, -1.0f, 0x000000FF },
{ 1.0f, -1.0f, -1.0f, 0x000000FF },
{ -1.0f, -1.0f, -1.0f, 0x000000FF },

{ 1.0f, -1.0f, 1.0f, 0x0000FF00 }, //Back face

{ 1.0f, 1.0f, 1.0f, 0x0000FF00 },
{ -1.0f, 1.0f, 1.0f, 0x0000FF00 },
{ -1.0f, 1.0f, 1.0f, 0x0000FF00 },
{ -1.0f, -1.0f, 1.0f, 0x0000FF00 },
{ 1.0f, -1.0f, 1.0f, 0x0000FF00 },


{ -1.0f, 1.0f, -1.0f, 0x00FF0000 }, //Top face

{ -1.0f, 1.0f, 1.0f, 0x00FF0000 },
{ 1.0f, 1.0f, 1.0f, 0x00FF0000 },
{ 1.0f, 1.0f, 1.0f, 0x00FF0000 },
{ 1.0f, 1.0f, -1.0f, 0x00FF0000 },
{ -1.0f, 1.0f, -1.0f, 0x00FF0000 },

{ 1.0f, -1.0f, -1.0f, 0x00FFFF00 }, //Bottom face

{ 1.0f, -1.0f, 1.0f, 0x00FFFF00 },
{ -1.0f, -1.0f, 1.0f, 0x00FFFF00 },
{ -1.0f, -1.0f, 1.0f, 0x00FFFF00 },
{ -1.0f, -1.0f, -1.0f, 0x00FFFF00 },
{ 1.0f, -1.0f, -1.0f, 0x00FFFF00 },

{ -1.0f, -1.0f, 1.0f, 0x00FF00FF }, //Left face

{ -1.0f, 1.0f, 1.0f, 0x00FF00FF },
{ -1.0f, 1.0f, -1.0f, 0x00FF00FF },
{ -1.0f, 1.0f, -1.0f, 0x00FF00FF },
{ -1.0f, -1.0f, -1.0f, 0x00FF00FF },
{ -1.0f, -1.0f, 1.0f, 0x00FF00FF },

{ 1.0f, -1.0f, -1.0f, 0x0000FFFF }, //Right face

{ 1.0f, 1.0f, -1.0f, 0x0000FFFF },
{ 1.0f, 1.0f, 1.0f, 0x0000FFFF },
{ 1.0f, 1.0f, 1.0f, 0x0000FFFF },
{ 1.0f, -1.0f, 1.0f, 0x0000FFFF },
{ 1.0f, -1.0f, -1.0f, 0x0000FFFF },

};

#define NUM_VERTICES (sizeof(g_vertices)/sizeof(CUSTOMVERTEX))

IDirect3DVertexBuffer8* g_VB = 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;

D3DXMATRIX view_matrix;
D3DXMATRIX matProj;

g_d3d_device->SetRenderState( D3DRS_LIGHTING, FALSE );

g_d3d_device->SetRenderState( D3DRS_ZENABLE, TRUE );


hr = g_d3d_device->CreateVertexBuffer( NUM_VERTICES * sizeof( CUSTOMVERTEX ),
D3DUSAGE_WRITEONLY,
D3D8T_CUSTOMVERTEX,
D3DPOOL_MANAGED,
&g_VB );

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

memcpy( Ptr, g_VB, sizeof( g_VB ) );

g_VB->Unlock();


//CAMERA

D3DXMatrixLookAtLH( &view_matrix, &D3DXVECTOR3( 0.0f, 0.0f, -8.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );

g_d3d_device->SetTransform( D3DTS_VIEW, &view_matrix );

//PROJECTION

D3DXMatrixPerspectiveFovLH( &matProj,
D3DX_PI,
((float)g_width / (float)g_height),
1.0f,
100.0f );

g_d3d_device->SetTransform( D3DTS_PROJECTION, &matProj );


}

//Kill scene

void kill_scene()
{

if( g_VB != NULL )
{
g_VB->Release();
g_VB = 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()
{
D3DXMATRIX matWorld;
D3DXMATRIX rot_matrix;
D3DXMATRIX trans_matrix;

static float rot_triangle = 0;
static float rot_square = 0;

rot_triangle+=0.004f;
rot_square+=0.007f;

g_d3d_device->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );

g_d3d_device->BeginScene();

g_d3d_device->SetVertexShader( D3D8T_CUSTOMVERTEX );

g_d3d_device->SetStreamSource( 0,g_VB,sizeof(CUSTOMVERTEX));

D3DXMatrixRotationY( &rot_matrix, rot_triangle );

D3DXMatrixTranslation( &trans_matrix, -1.5f, 0.0f, -1.0f );

D3DXMatrixMultiply( &matWorld, &rot_matrix, &trans_matrix );

g_d3d_device->SetTransform( D3DTS_WORLD, &matWorld );

g_d3d_device->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 4 );

D3DXMatrixRotationX( &rot_matrix, rot_square );

D3DXMatrixTranslation( &trans_matrix, 1.5f, 0.0f, 1.0f );

D3DXMatrixMultiply( &matWorld, &rot_matrix, &trans_matrix );

g_d3d_device->SetTransform( D3DTS_WORLD, &matWorld );

g_d3d_device->DrawPrimitive( D3DPT_TRIANGLELIST, 6, 12 );

g_d3d_device->EndScene();

}

//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
Galapaegos
Galapaegos
Hey PoLiSh_Peta,

I threw the pyramid into one of my engines and it didn''t render either. One HUGE problem with it is that you are using triangle lists when they are more setup for using indexices, or strips, or something of that nature. When you use the triangle stips to make a box, you have to specify 6 verts for one side of the box (ie three verts for:
|\
|_\, and three verts for:

\-|
\| (sorry about the ascii art, you''ll have to bare with it! Hopefully you can see the side of a box from these two triangles. If you need more help the sdk has a ton of help

-brad
-brad
PoLiSh_Peta
PoLiSh_Peta
Now I''ve created another one, with a cube and a pyrmid on top to create a sorta hourse looking figure, and it still doesn''t show up! I used the triangle list again, so you''re saying I need to use a strip? Alot of this is coming from Drunken Hyena''s tutorials. Here''s my latest project without errors or anything, and another black screen. Pissing me off.



//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 CUSTOMVERTEX
{
FLOAT x, y, z;
FLOAT tu, tv;
};

#define D3D8T_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1)

CUSTOMVERTEX g_vertices[] =
{
{ -100.0f, 100.0f, -100.0f, 0.0f, 0.0f },//Front face

{ -100.0f, -100.0f, -100.0f, 0.0f, 1.0f },
{ 100.0f, -100.0f, -100.0f, 1.0f, 1.0f },
{ 100.0f, -100.0f, -100.0f, 1.0f, 1.0f },
{ 100.0f, 100.0f, -100.0f, 1.0f, 0.0f },
{ -100.0f, 100.0f, -100.0f, 0.0f, 0.0f },

{ -100.0f, 100.0f, 100.0f, 0.0f, 0.0f },//Back face

{ -100.0f, -100.0f, 100.0f, 0.0f, 1.0f },
{ 100.0f, -100.0f, 100.0f, 1.0f, 1.0f },
{ 100.0f, -100.0f, 100.0f, 1.0f, 1.0f },
{ 100.0f, 100.0f, 100.0f, 1.0f, 0.0f },
{ -100.0f, 100.0f, 100.0f, 0.0f, 0.0f },

{ 100.0f, 100.0f, -100.0f, 0.0f, 0.0f },//Right face

{ 100.0f, 100.0f, 100.0f, 1.0f, 0.0f },
{ 100.0f, -100.0f, 100.0f, 1.0f, 1.0f },
{ 100.0f, -100.0f, 100.0f, 1.0f, 1.0f },
{ 100.0f, -100.0f, -100.0f, 0.0f, 1.0f },
{ 100.0f, 100.0f, -100.0f, 0.0f, 0.0f },

{ -100.0f, 100.0f, -100.0f, 0.0f, 0.0f },//Left face

{ -100.0f, 100.0f, 100.0f, 1.0f, 0.0f },
{ -100.0f, -100.0f, 100.0f, 1.0f, 1.0f },
{ -100.0f, -100.0f, 100.0f, 1.0f, 1.0f },
{ -100.0f, -100.0f, -100.0f, 0.0f, 1.0f },
{ -100.0f, 100.0f, -100.0f, 0.0f, 0.0f },


//PYRAMID TOP

{ 0.0f, 200.0f, 0.0f, 0.0f, 0.0f },//Top corner

{ 100.0f, 100.0f, -100.0f, 0.0f, 0.0f },//Right front

{ -100.0f, 100.0f, -100.0f, 0.0f, 0.0f },//Left front

{ -100.0f, 100.0f, 100.0f, 0.0f, 0.0f },//Left back

{ 100.0f, 100.0f, 100.0f, 0.0f, 0.0f },
{ 100.0f, 100.0f, -100.0f, 0.0f, 0.0f }
};

#define NUM_VERTICES (sizeof(g_vertices)/sizeof(CUSTOMVERTEX))

IDirect3DVertexBuffer8* g_VB = NULL;

LPDIRECT3DTEXTURE8 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;
D3DXMATRIX view_matrix;
D3DXMATRIX proj_matrix;

g_d3d_device->SetRenderState( D3DRS_LIGHTING, FALSE );

g_d3d_device->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);

g_d3d_device->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);

g_d3d_device->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_DISABLE);

g_d3d_device->SetTextureStageState(0,D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
g_d3d_device->SetTextureStageState(0,D3DTSS_MINFILTER, D3DTEXF_LINEAR);

g_d3d_device->SetRenderState( D3DRS_LIGHTING,FALSE);

g_d3d_device->SetRenderState( D3DRS_ZENABLE, TRUE );

hr = D3DXCreateTextureFromFile( g_d3d_device, "brick.bmp", &g_texture );

hr = g_d3d_device->CreateVertexBuffer( NUM_VERTICES * sizeof(CUSTOMVERTEX),
D3DUSAGE_WRITEONLY,
D3D8T_CUSTOMVERTEX,
D3DPOOL_MANAGED,
&g_VB);

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

memcpy( Ptr, g_vertices, sizeof( g_vertices ) );

g_VB->Unlock();

D3DXMatrixLookAtLH( &view_matrix,
&D3DXVECTOR3( 0.0f, 0.0f, -800.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );

g_d3d_device->SetTransform( D3DTS_VIEW, &view_matrix );

D3DXMatrixPerspectiveFovLH( &proj_matrix,
D3DX_PI/4,
((float)g_width / (float)g_height),
110.0f,
400.0f );

g_d3d_device->SetTransform( D3DTS_PROJECTION, &proj_matrix );

}

//Kill scene

void kill_scene()
{
if( g_texture != NULL )
{
g_texture->Release();
g_texture = NULL;
}

if( g_VB != NULL )
{
g_VB->Release();
g_VB = 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()
{
D3DXMATRIX worldMatrix;
D3DXMATRIX transMatrix;
D3DXMATRIX rotXMatrix;

static float rot_x_square = 0;
static float rot_x_triangle = 0;

rot_x_square += .07f;
rot_x_triangle += .07f;

g_d3d_device->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );

g_d3d_device->BeginScene();

g_d3d_device->SetVertexShader(D3D8T_CUSTOMVERTEX);

g_d3d_device->SetStreamSource( 0, g_VB, sizeof(CUSTOMVERTEX ) );

g_d3d_device->SetTexture( 0, g_texture );

D3DXMatrixRotationX( &rotXMatrix, rot_x_square );

D3DXMatrixTranslation(&transMatrix, 0.0f, 0.0f, 0.0f);

D3DXMatrixMultiply( &worldMatrix, &rotXMatrix, &transMatrix );

g_d3d_device->SetTransform( D3DTS_WORLD, &worldMatrix );

g_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST,0,NUM_VERTICES/3);

D3DXMatrixRotationX( &rotXMatrix, rot_x_triangle );

D3DXMatrixTranslation( &transMatrix, 0.0f, 0.0f, 0.0f );

D3DXMatrixMultiply( &worldMatrix, &rotXMatrix, &transMatrix );

g_d3d_device->SetTransform( D3DTS_WORLD, &worldMatrix );

g_d3d_device->DrawPrimitive( D3DPT_TRIANGLEFAN, 12, 4 );

g_d3d_device->EndScene();
}

//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
DrunkenHyena
DrunkenHyena
Galapaegos: Actually the Pyramid is rendered as a fan, which works quite well. And using strips isn''t good for the cube. Indices wouldn''t hurt but it is a beginner tutorial.

PoLiSh_Peta:
You''ve made some very strange edits to my code, but one thing that jumped out at me was this:
memcpy( Ptr, g_VB, sizeof( g_VB ) );

g_VB is a pointer, so it''s size is 4. You''re only copying 4 bytes rather than the data, and you''re trying to copy from the VB to the VB, which won''t work. The original line was:
memcpy(vb_vertices, g_vertices, sizeof(g_vertices) );

Where vb_vertices is the pointer returned by Lock, and g_vertices is the array of vertices declared at the top of the code. You''ll have to adjust the variable names to match what you changed them to in your version.



Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena</FON
PoLiSh_Peta
PoLiSh_Peta
Indeed hyena. I modified your code so there isn't any windowed screen stuff, I don't like that. So it goes full screen automatically like all other games. I see, but I only did that in the first source code post. The last code I posted with the cube and pyramid had it right.

Why am I getting a BLACK screen and no shapes?!
-Peter

[edited by - PoLiSh_Peta on January 10, 2004 3:30:48 PM]
There are two inevitabilities in life: death and failure.-PoLiSh
DrunkenHyena
DrunkenHyena
It appears that your near clipping plane is 110, so anything close than 110 units will be clipped, while your far plane is 400, so anything beyond 400 will be clipped. Your camera is 800 units away from the origin, which is where your primitives are being drawn. See the problem?

And by the way, most games do in fact support windowed mode, it''s usually just not documented and even the ones that don''t did during the development. Using windowed mode makes it a lot easier to debug your programs so I''d recommend that you leave windowed support in.


Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena</FON
PoLiSh_Peta
PoLiSh_Peta
I really don't see a problem with it, but I changed the camera position to -109.0f and it still doesn't work. The clipping is at 110, and the far clipping is at 400. The cube dimensions are 100x100x100, and the pyrmids base is the same. I didn't translate the shapes anywhere, I left them at (0.0f, 0.0f, 0.0f ), I'm not sure what the problem is.

[edited by - PoLiSh_Peta on January 10, 2004 9:07:43 PM]
There are two inevitabilities in life: death and failure.-PoLiSh
DrunkenHyena
DrunkenHyena
If your far plane is 400, but the scene is 800 away, then the entire scene is beyond the far clipping plane.

Moving your camera to -109, it''s unlikely you''ll see your pyramid since it''s 100 units above you. Also, you cube extends to 100 units from the origin, your near clipping plane is 110. Anything less than 110 units away will be clipped. If you do the math your camera is *9* units away from the cube.

Get yourself some graph paper. Make each square equal to 10 units. Draw the origin and your shapes. Plot your camera and draw the view cone. Mark the near and far planes. It should all be very clear when you draw it out.


Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena</FON
PoLiSh_Peta
PoLiSh_Peta
Man, I'm really dragging this out, and it shouldn't be hard. I came up with this after a google search.
http://www.cs.wpi.edu/~emmanuel/courses/cs4731/slides/lecture11.pdf

After looking at that, I moved the camera to -400.0f back, I changed the near clipping plane to 200.0f, and the far clipping plane to 600.0f. It still doesn't work!!



C=Camera
NP=Near clipping plane
FP=Far clipping plane

C(-400) NP(-200.0f) FP(200.0f)
| | 100x100x100 |
| | cube in here |



What do the far and near clipping numbers mean? Are they in relation to the origin or the camera position? Here I assumed they were in relation to the camera, so I added te near clipping plane to the camera's position, and I also added the far clipping plane. According to this, it should all work just fine.

[edited by - PoLiSh_Peta on January 11, 2004 12:07:59 PM]
There are two inevitabilities in life: death and failure.-PoLiSh
DrunkenHyena
DrunkenHyena
The planes are relative to the camera postion, so a near plane of 10 would be 10 units in front of the camera. At a glance it looks like you''ve got the planes sorted out, but there are so many more things that could be wrong.

Things to try:
- Use the debug runtime. Set the warning level to max (in the Control Panel) and check the debug output for hints.
- Turn culling off. If your polys are declared wrong, they may be getting culled
- Clear your backbuffer to a different colour. If something shows up after you did this, then it''s a colouring issue. Possibly lighting is enabled when it shouldn''t be, possibly your texturing is set up wrong.



Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena</FON
DrunkenHyena
DrunkenHyena
And to be really safe, you might want to set your near plane to something like 1, and far to 10,000. That way you''ll be pretty sure it''s not a clipping plane issue. Once you''ve sorted it out then you can start fiddling with those values.


Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena</FON
PoLiSh_Peta
PoLiSh_Peta
OMG!! I can''t believe this, notice anything missing at the bottom of my render function? AHH! I never flipped the back buffer. I''m thoroughly disgusted with myself, first I make a console app, then I exclude what is possibly the most satisfying function call while working with D3D. Hyena, thanks for your patience, I did get an understanding of how the clipping planes work from all this hassle though. Your tutorials are great, keep up the good work.

-Peter
There are two inevitabilities in life: death and failure.-PoLiSh

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.