-
Eddie is staring at water damage in his living room ceiling.
Hungarian notation has always sat wrong with me. So has some of Joel on Software’s views in the past. I’m currently revisiting both opinions.
Firstly, Hungarian notation. For those of you not in the know, Hungarian notation is a coding convention that’s been around for a long time. It gets a lot of flak - and in my opinion, usually quite rightly.
You see, the idea in the Windows headers, was to encode the variable type into the variable itself, to great detail. For example, in windows, you’ll often see something like this:
- // Function passing in a variable that’s a long pointer to a zero-terminated string
- MyFunction(lpszBar);
This, in my opinion, is wrong. C++ is already a strongly typed language, so you’ll get a compiler error if you pass in an item of the wrong type, so of what benefit is it to store the variable type in the name?
I always assumed that this was the “only” type of Hungarian notation, and I spurned the idea on the whole because of it.
Reading a post on Joel on Software’s website with great skepticism, I actually ended up changing my mind.
Joel brought to my attention that there’s actually two ‘types’ of Hungarian notation. One of which is called “System Hungarian”, and “Application Hungarian”. The difference is that the former encodes the data type into the variable, whereas the latter encodes the domain-level usage into the variable.
I won’t describe the difference between the two, as I think both Joel’s article and WikiPedia’s do a fantastic job bringing both to light (Joel’s is a good read for the skeptic who wants a narrative to follow, WikiPedia’s is a good reference for those pressed for time). I will however talk about what brainstorm this set off in my head.
I now think that Application Hungarian is a good thing, but the difference I outlined above is huge:
Systems Hungarian is easier to define, because it’s domain agnostic. Application Hungarian is domain-specific.
Take for example Joel’s example of needing to Encode() strings before sending them to a webpage. That’s a domain-specific example. Building a game in C++ doesn’t have the same requirement, so using his ’s’ and ‘us’ prefix doesn’t make sense.
It might even change from application-to-application, depending on what happens. This means you can’t have a blanket statement like “Always prefix [insert-domain-specific-kind-of-type-here] with [prefix]” between projects, unless they have a similar domain, and set of constraints.
I’m trying to think of places where this matters in code. I already do a modified form of “Hungarian” (prefixes such as: ‘m_’ for member variables, ‘b’ for boolean values, ‘p’ for pointers and ‘k’ for constants), but this is project-agnostic (perhaps I’ll call it Eddie Systems Hungarian
). I have yet to see a need for integrating domain-specific/application-specific Hungarian in the games I program, but at least this gives me pause to think about usages for it. If anybody thinks of any, please let me know.
Popularity: 35% [?]
I’ve been dabbling in graphics programming a bit, mostly OpenGL glBegin/glEnd schtuff lately. A friend pointed me to vertex buffer objects (VBO’s) as a better alternative, so I decided to learn a bit about them. That said, I couldn’t find a tutorial that suited my needs, so I thought I’d offer one here.
First off, there are tutorials out there, just not what I need/want. Let me list them.
- NeHe, purveyor of all things graphical has a great tutorial (#45), that I even used as a reference for mine.
The problem for me was that it came with way more than what I wanted to learn at this point (heightmaps and the like), and I just wanted a focused example on VBO’s without having to worry about setting everything up “just right”.
- DevMaster, my surrogate home, had a decent tutorial that was brief (here), but had various errors and didn’t compile out of the box. It also didn’t work, at least not for me!
So here I decided to cobble together a working demo (once I figured out how), and post it up for all the world to see.
Now keep in mind a few things about this:
1.- I might have my terminology messed up. I keep hearing people refer to this as DrawArrays, Vertex Buffer Objects, Vertex Array something-or-other, etc. If someone can clear this up for me, I’d be happy to hear from you.
2.- I don’t do a lot of error checking in this demo. It’s definitely bad practice, but I wanted to keep things brief. There’s a couple of comments in there noting where I should be, and there might be a few places that I should mention these things.
Anyhow, without further ado, here’s the demo. I hope it helps someone.
- /**
- * Vertex Buffer Objects (herein after referred to as VBOs) demo.
- *
- * Author: Eddie Parker
- * www.kickingdragon.com
- *
- * This demo is a really simple example of how to use VBOs [1].
- *
- * Why would you use VBOs? Because the data is uploaded an manipulated
- * on the graphics card RAM instead of system RAM, therefore it's faster,
- * and doesn't clog up your BUS, and keeps your whites whiter.
- *
- * [1] http://steinsoft.net/index.php?site=Programming/Code%20Snippets/OpenGL/no11
- *
- */
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <SDL/SDL.h>
- #include <SDL/SDL_main.h>
- #include <GL/gl.h>
- #include <GL/glu.h>
- /**
- * glext.h snippet
- *
- * glext.h isn't always found in people's distributions.
- * I've copied the parts we need here -- if you have it available,
- * it would be better to include it directly.
- *
- * Basically, we have a couple of defines that are used later on for
- * glBindBufferARB and glBufferDataARB calls, as well as typedefs
- * that specify the function signatures for the functions we plan on using.
- *
- * Why do we need the typedefs?
- *
- * Quite simply, because the OpenGL Architecture Review Board (ARB) has
- * created these functions as 'extensions' - that is, they're not part
- * of the 'official' library, and therefore might or might not be
- * available. At runtime, it's necessary to crack open the OpenGL
- * DLL and retrieve the function pointers, assign them, and
- * then we're able to use them in our application.
- *
- * For more information, see [1].
- *
- * [1] http://www.opengl.org/resources/faq/technical/extensions.htm
- */
- #define GL_ARRAY_BUFFER_ARB 0x8892
- #define GL_STATIC_DRAW_ARB 0x88E4
- typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
- typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
- typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
- typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);
- /**
- *
- * END glext.h snippet
- *
- */
- /**
- * Allocate four function pointers on the data segment so we can assign to them later,
- * if we have them available.
- */
- PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
- PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
- PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
- PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
- /**
- * Initialization function to set up our requisite libraries.
- */
- int Initialize()
- {
- SDL_Init(SDL_INIT_VIDEO);
- SDL_SetVideoMode(640, 480, 32, 2);
- //! @TODO: I should check for the availability of DrawArrays and
- // check for failure to load these functions.
- glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
- glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
- glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
- }
- int main(int argc, char **argv)
- {
- // Setup our required libraries.
- Initialize();
- // Set up OpenGL
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- // Initialize a perspective.
- gluPerspective(45.f, 640.f / 480.f, 1.f, 512.f);
- // Set our clear colour to black
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- // Set up a purdy triangle as our vertex data.
- GLfloat vertexData[] = { 0.f, 1.f, 0.f
- , -1.f, -1.f, 0.f
- , 1.f, -1.f, 0.f
- };
- // Set a lovely teal with some Gouraud shading for
- // our triangle.
- GLfloat colourData[] = { 0.f, 0.f, 1.f
- , 0.f, 1.f, 1.f
- , 1.f, 1.f, 1.f
- };
- // Create some 'ids' for the buffers.
- GLuint vertexBuffer = 0;
- GLuint colourBuffer = 0;
- // 1.- Generated a buffer name for our vertex buffer,
- glGenBuffersARB(1, &vertexBuffer);
- // 2.- Set our current 'in-use' buffer to our vertex buffer.
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
- // 3.- Fill out the data buffer using our initialized values.
- glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertexData), vertexData, GL_STATIC_DRAW_ARB);
- // Same as steps 1, 2 and 3 above, but using colour data.
- glGenBuffersARB(1, &colourBuffer);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, colourBuffer);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(colourData), colourData, GL_STATIC_DRAW_ARB);
- // Initialize the ability to use vertex arrays and colour arrays.
- // I should really be making sure I have this capability and use
- // glIsEnabled first.
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- bool bRunning = true;
- SDL_Event event;
- while (bRunning)
- {
- if(SDL_PollEvent(&event))
- {
- if(event.key.keysym.sym == SDLK_ESCAPE)
- {
- bRunning = false;
- continue;
- }
- }
- // Clear our depth buffer and color bit
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // Reset our view
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- // Move back a bit to see our triangle in it's glory.
- glTranslatef(0, 0, -5);
- // --- VBO's in action.
- // Set the vertexBuffer as the current buffer.
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
- // Specify that it's data is vertex data.
- glVertexPointer(3, GL_FLOAT, 0, 0);
- // Set the colourBuffer as the current buffer.
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, colourBuffer);
- // Specify that it's data is colour data.
- glColorPointer (3, GL_FLOAT, 0, 0);
- // Tell OpenGL to draw what it sees. ;)
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
- // --- End VBO's in action.
- // Swap buffers!
- SDL_GL_SwapBuffers();
- }
- // Disable the client states.
- glDisableClientState( GL_VERTEX_ARRAY );
- glDisableClientState( GL_COLOR_ARRAY );
- //!TODO: Free the buffers created in glBufferDataARB
- return 0;
- }
Popularity: 71% [?]
RAWC: Run Applications Without a Console: RAWC.zip
This application will basically run a batch file of the same name whenever it starts up, but masking it’s console that would normally pop up.
That is, if you take the RAWC.exe, and run it as is, it will attempt to run RAWC.bat. Rename the .exe to whatever you like, say “foobar.exe” and it’ll try to run “foobar.bat”. It will also pass any command line parameters to it, should you like.
Please note: if you like this application, please don’t link to it directly, instead link to this page so people can be aware of any updates.
The history:
I wrote the original source code, and a mysterious benefactor by the name of DrV rewrote it in C to make the executable smaller.
Future plans for this is to rewrite it in assembly using masm, and see if I can make the executable smaller. Who knows.
Source code:
- /**
- * Author: DrV (http://drv.nu)
- * Modified by: Eddie Parker (http://www.kickingdragon.com/2006/07/04/run-batch-files-without-a-console-popup/)
- */
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <stdio.h>
- static STARTUPINFO si = { sizeof(STARTUPINFO) };
- static PROCESS_INFORMATION pi;
- unsigned int strlen(char * pStr)
- {
- unsigned int count = 0;
- while(*pStr != 0)
- {
- ++count;
- ++pStr;
- }
- return count;
- }
- void strcpy( char * pDestination, char * kpSource)
- {
- for(unsigned int i = 0; i < strlen(kpSource); ++i)
- {
- pDestination[i] = kpSource[i];
- }
- }
- int main(int argc, char **argv)
- {
- char applicationName[MAX_PATH + 1];
- char *pDot;
- GetModuleFileName(NULL, applicationName, sizeof(applicationName));
- pDot = applicationName;
- // Fast forward to the NULL.
- while (*(pDot++))
- ;
- // Move back until we find the start of the extension.
- while (*(--pDot) != '.')
- ;
- // Add a '.bat' to the extension.
- pDot[1] = 'b';
- pDot[2] = 'a';
- pDot[3] = 't';
- char commandLine[MAX_PATH + 1];
- char * pEndPoint = &commandLine[0];
- strcpy(pEndPoint, applicationName);
- pEndPoint += strlen(applicationName);
- {
- int i = 0;
- for(i = 1; i < argc; ++i)
- {
- pEndPoint[0] = ' ';
- ++pEndPoint;
- strcpy( pEndPoint, argv[i] );
- pEndPoint += strlen(argv[i]);
- }
- }
- pEndPoint[0] = 0;
- si.dwFlags = STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_HIDE;
- printf("Running %s.", &commandLine[0]);
- CreateProcess(applicationName, &commandLine[0], NULL, NULL, FALSE, 0, NULL, NULL, &si, π);
- return 0;
- }
Popularity: 50% [?]