//////////////////////////////////////////////////////////// // graphics.h // // Header file declaring basic graphics objects and functions for EDrive, // a multiplatform driving simulator. // // Classes declared here are: // graphics - represents a display target (display device or region thereof) // graphicslist - list of potential available graphics objects // thing - something that can be displayed on a graphics object // color - a colour! // shapetype - a kind of shape which can be displayed // In addition there are a variety of graphics helper functions. // // Copyright 2004 by Evan Alexander Weaver // // Despite the copyright, this is free software. See edrive.cpp for details. // // Date last modified: 31 May 2004 #ifndef _edrive_graphics_h_ #define _edrive_graphics_h_ #include "platform.h" #include "edmath.h" #if ED_DIRECTX_9_GRAPHICS //************************************************ #include // shapetype is a kind of polygon that can be drawn typedef D3DPRIMITIVETYPE shapetype; #define TRIANGLEFAN D3DPT_TRIANGLEFAN #define TRIANGLELIST D3DPT_TRIANGLELIST #define TRIANGLESTRIP D3DPT_TRIANGLESTRIP #define POINTLIST D3DPT_POINTLIST #define LINELIST D3DPT_LINELIST #define LINESTRIP D3DPT_LINESTRIP // color is a colour for something that can be drawn typedef D3DCOLORVALUE color; #else //******************************************************************** #include #include #include // shapetype is a kind of polygon that can be drawn typedef GLenum shapetype; #define TRIANGLEFAN GL_TRIANGLE_FAN #define TRIANGLELIST GL_TRIANGLES #define TRIANGLESTRIP GL_TRIANGLE_STRIP #define POINTLIST GL_POINTS #define LINELIST GL_LINES #define LINESTRIP GL_LINE_STRIP // color is a colour for something that can be drawn class color { public: float r, g, b, a; color(float xr = 1, float xg = 1, float xb = 1, float xa = 1) { r = xr; g = xg; b = xb; a = xa; } }; #endif //******************************************************************* // Make a color instance, given RGB or RGBA values, each between 0 and 1 // inline color mkcolor(float r, float g, float b, float a = 1.0) { color rc; rc.r = r; rc.g = g; rc.b = b; rc.a = a; return rc; } // Rotate a vector, "v", "rad" radians around the axis "axis" vector &rotateaxis(vector &v, float rad, const vector &axis); // Determine if the point that projects to (x, z) on the XZ plane is // inside the triangle defined by the projection of p1, p2, p3 onto the // XZ plane bool inxztriangle(float x, float z, vector &p1, vector &p2, vector &p3); #if ED_DIRECTX_9_GRAPHICS //************************************************ // Lists available graphics modes for available devices // (currently only used for DirectX 9 version) // class graphicslist { int display; // currently listed display device int displaycnt; // how many display devices are available int *modes; // array of available modes for current device int modecnt; // number of elements in modes[] int *widths; // array of widths matching modes[] int *heights; // array of heights matching modes[] D3DFORMAT *formats; // array of display formats matching modes[] int *hzs; // array of refresh rates matching modes[] static D3DFORMAT formatid[6]; // possible display formats static char *formatdesc[7]; // descriptions of possible formats public: graphicslist(); graphicslist(const graphicslist&); // intentionally... graphicslist &operator=(const graphicslist &); // ...omitted ~graphicslist(); void destroy(); // empty the list (deallocates arrays) bool select(int dispid); // list a different device int displaycount(); // count of available devices int modecount(); // count of available modes for current dev const char *displayname(int i); // name of specific device const char *modedesc(int i); // description of specific mode bool getdetails(int i, int &mode, int &width, int &height, D3DFORMAT &format, int &hz); // get details of specific mode }; #endif //******************************************************************* // A target for drawing things class graphics { friend class thing; // thing is closely coupled bool full; // in fullscreen mode? int width; // width in pixels int height; // height in pixels void (*drawframe)(); // frame drawing function #if ED_DIRECTX_9_GRAPHICS //******************************************** LPDIRECT3DDEVICE9 d3dd; // Direct3D device D3DPRESENT_PARAMETERS d3dpp;// params for creating/restoring D3D device LPD3DXFONT font; // D3D font HWND hwnd; // main window HINSTANCE hinst; // application instance; D3DFORMAT windowformat; // format for windowed mode matrix view; // view matrix #else //**************************************************************** int owidth; // old width (while in fullscreen mode) int oheight; // old height (while in fullscreen mode) int id; // OpenGL window id float lpos[4]; // OpenGL light position #endif //*************************************************************** public: graphics(); graphics(const graphics &); // intentionally omitted... graphics &operator=(const graphics &); // ...to prevent copies ~graphics(); #if ED_DIRECTX_9_GRAPHICS //******************************************** // create graphics object bool create(HINSTANCE, WNDPROC, int display, int w, int h, D3DFORMAT fmt, int hz, void (*df)()); // change video mode bool change(int display, int w, int h, D3DFORMAT fmt, int hz); // get program's HINSTANCE HINSTANCE gethinstance(); // get main window's HWND HWND gethwnd(); #else //**************************************************************** // create graphics object bool create(int *pargc, char **argv, int w, int h, void (*df)()); // handle size change void newsize(int w, int h); // return to windowed mode bool gowindow(); // go to fullscreen mode bool gofullscreen(); #endif //*************************************************************** void destroy(); // unattaches object from hardware bool fullscreen() { return full; } // in fullscreen mode? void init(); // initializations required in multiple places void restore(); // reestablish connection to hardware void drawtext(int x, int y, const char *, color); // draw text // change user camera location void viewpoint(const vector &vpt, const vector &dir, const vector &up); void startframe(color); // begin drawing a frame void endframe(); // finished drawing a frame void chdrawframe(void (*df)()); // change frame drawing function bool isdrawframe(void (*df)()); // check frame drawing function void nextframe(bool immediate = false); // draw a frame }; #if ED_OPENGL //************************************************************ // load a BMP file into dynamically allocated memory for texture use unsigned char *createtexdata(const char *file, int &width, int &height); #endif //******************************************************************* // A thing in our 3-D universe. // It can be moved, rotated, and drawn. // // It is composed of up to 10 different pieces, stored in one vertex buffer // using a series of indices in an index buffer. If the thing is comprised // of only one piece, then the index buffer does not have to be used. // class thing { #if ED_DIRECTX_9_GRAPHICS //******************************************** LPDIRECT3DVERTEXBUFFER9 vb; // vertex buffer (stores vertices) LPDIRECT3DINDEXBUFFER9 ib; // index buffer (indices of vertices used) D3DMATERIAL9 mat; // material it is made of LPDIRECT3DTEXTURE9 tex; // a texture spread over the surface #else //**************************************************************** float (*vb)[3]; // vertex buffer (stores vertices) float (*nv)[3]; // normal vectors per vertex float (*tc)[2]; // texture coords per vertex short *ib; // index buffer (indices of vertices used) unsigned int tex; // a texture to spread over the surface #endif //*************************************************************** matrix world; // world transformation matrix int maxcount; // Maximum number of vertices int count; // actual number of vertices color col; // colour (in case no texture) int pieces; // how many pieces int maxicount; // maximum number of index buffer entries int icount; // actual number if indices // for each piece of the thing shapetype type[10]; // e.g. point, triangle strip, etc. int startindex[10]; // start index int primitivecnt[10]; // how many primitives public: thing(); thing(const thing &); // intentionally omitted... thing &operator=(const thing &); // ... to prevent copies virtual ~thing(); virtual void destroy(); // deallocates memory/releases hardware // Create the thing to size. If maxindices is 0, there will be only // one piece and the index buffer will not be used. // bool create(graphics &g, color c = mkcolor(1, 1, 1), shapetype = POINTLIST, const char *texfile = 0, int maxvertices = 200, int maxindices = 0); // Add the information for a vertex. "newprimitive" just tells us // whether this vertex completes a primitive (e.g. triangle, line // segment) or not; there is no need to use it if the index buffer // is being used (e.g. if the thing has more than one piece). // virtual void add(float x, float y, float z, float nx, float ny, float nz, float tu, float tv, bool newprimitive = false); // Add an index (only applicable if the thing has more than one piece). // "newprimitive" tell us if this index completes a primitive. // virtual void addind(short i, bool newprimitive = false); // Draw the thing, assuming g.startframe() has already been called // virtual void draw(graphics &g); // Rotates the thing "rad" radians around one of the axes. virtual void rotatex(float rad); virtual void rotatey(float rad); virtual void rotatez(float rad); // moves the thing by the vector (x, y, z) // virtual void move(float x, float y, float z); // repositions (or otherwise changes) the thing by resetting the world // matrix virtual void reposition(const matrix &m); // starts a new piece virtual void newpiece(shapetype = POINTLIST); }; #endif