Gary King gking@cs.stanford.edu SUID: 4662144 Project 4 (Infinitum) Partner: Dennis Hwang ------------------------------------------------ To run: Use a Windows 9X or NT based system with a good OpenGL implementation (e.g. nVidia RivaTNT/TNT2/GeForce, or any card that supports the ARB multitexture extensions). First, start the server (\bin\SrvStart.exe), and select the number of clients that will be participating (1-8 can 'play'). Then start the game by running Infinitum.exe. Command line options are -window (forces the game to start in a window) and -noarb (uses single-pass texturing, even if hardware multitexturing is available). After the full-motion video introduction (press Ctrl+Break to skip), you will be greeted with the UI. To control the camera, you may either click on the "Navigate" button and use the double-control pad at the bottom of the screen (the controls should be self-explanatory), or use the following keys (all lower case): 'w' : track forward 'a' : pan left 's' : track back 'd' : pan right 'q' : look left 'e' : look right 'r' : move up 'f' : move down 't' : look up 'g' : look down 'ESC' : quit The three buttons on the right side of the control bar (that have pictures of a tank, helicopter, and plane) will create a new tank, helicopter, or plane. The tank is created at ground level directly below the camera, while the plane is created at an altitude of 400m and the helicopter at 500m. While in Navigate mode, it is possible to click on any of the created objects to select them. To move objects around, click on the "Control Units" button. This will allow you to control the motion of the objects in full 3D. The Red attack button will fire a missile which does 200 points of damage to whatever it hits, but the actual firing is a bit buggy. When aircraft collide with each other they will do enormous amounts of damage, and an aircraft colliding with the ground results in instant death. The 'goal' of the game is to destroy everyone else's headquarters; however, this is an extremely easy task thanks to the kamikaze-style attacks. When in Control Units mode, it is impossible to select new units - the main window becomes a control grid, with the left side of the window equating to accelerating orthogonally to the front vector of the object, etc. The space bar will immediately stop any moving units. Please note also that the tank's axes are reversed. The bounding boxes also do not properly rotate around the y-axis after an x-axis rotation (this is a large reason why the missiles fire incorrectly). This is obviously because transformed coordinates are stored in the bounding boxes, rather than re-transforming them every frame to match the object's front vector. This was a bug I intended on fixing, but due to finals will not be able to accomplish. Also note that it is possible to play all the clients on the same machine, but it is not recommended. Playing both players on a RivaTNT-equipped PC (Windows NT4 SP5, 128MB RAM, P2-300) resulted in about 10 fps gameplay, which is *very* slow. ------------------------------------------------- Technology: Multipass rendering: I implemented the multipass effects (our engine supports both opacity mapping *and* bump mapping (check GLobject.c if you are incredulous), although we only had time to create opacity maps on the tank) using the ARB multitexture extensions. Although this is a hardware-effect, it was actually probably harder to implement than actually rendering multiple passes in the code, since the extensions are barely documented anywhere (I did extensive research and testing to figure out the proper texture combination settings). Even with the extensions though, because bump maps are stored as an external 8-bit map apart from the texture, bump mapping requires two passes (one to create the embossed map and another to blend the texture on top). Bump mapping is implemented through the use of the constant-jitter embossment technique - a grayscale map is subtracted from a constant-shifted copy of itself, with the texture being blended on top of it. Proper embossing requires the jitter value to be based on vertex normals; however, that, too, was canceled due to a lack of time. Networking: UDP over Winsock. Collision detection: bounding boxes. Simulated Dynamics: When a collision occurs (partially randomly do to terrible collision detection) objects will react in a somewhat realistic fashion. Since the Avatar engine (see Avatar.*) supports jerk, angular acceleration, etc.-based motion, the physics engine roughly calculates moments of inertia, momentum, energy transfer, etc. and adjusts the objects accordingly. It is slightly buggy, but working. Hierarchical Scene Graph: My 3DS loader properly handles all the sub-objects in a 3D Studio file and converts them into my self-created GLobject format. The GLobject format keeps all of the sub-object properties in-tact, making it possible to animate small parts of objects (see the helicopter rotor spinning). View Frustum Culling: I did not implement the standard frustum culling technique. What I do is check if any angle between the camera's front vector and the vectors from the 8 corners of an object's bounding box to the camera's center is less than 60 (approx). The caveat to this technique is when viewing a very tall object very closely at a very high angle (i.e. the headquarters) it will occassionally disappear. This could be alleviated in most cases by also testing the center of the object. Again, I didn't have time before submission to fix this. "Fractal" Terrain. Although I did not implement a proper noise function (I did want to write a Perlin noise generator), the terrain is generated by quadtree-subdividing a 512x512 bitmap and adding the average of the four corners of the nearest sub-box to a random number (see Terrain.c). Then everything is converted into 32-polygon (8x4) chunks that are textured. Normals are per-surface. Although I had a technique worked out for calculating vertex normals, this just didn't make it in time. Sound. I did actually write a working DirectSound engine (see Sound.zip); however, when a good friend of mine (Daniel Dannenberg) wrote a custom Impulse Tracker song for us, I decided to scrap my (still-buggy) audio engine and use FSound instead, which included an IT player. Full-motion video introduction. After hunting around the GLUT source to locate the name of the window, I hacked out a routine to play AVI files on top of OpenGL contexts. I think the opening of our game demonstrates that quite well. On-Screen Control Panel. The beautiful control panel was designed by Dennis. ------------------------------------------- Resources: Some of the textures in the terrain were downloaded from various net sites linked to on 3DCafe, but all were modified by me (in Photoshop) to work better as tiles. The textures on the tank were quickly thrown together by me. The models were designed by Dennis, and the song was written by Danny (as mentioned before, and in the credits). The FMV intro was a quick-hack rendered in 3D Studio MAX and edited in Adobe Premiere by me. All the UI images were created by Dennis. The timer code (as mentioned in Timer.c) is a C conversion of Bryan Cook's C++ class that was posted to the newsgroup. I copied *no* canned source code in the development of this project. In addition to the Red Book and FvD, I used the Microsoft Platform SDK for Winsock and MCI information, nVidia and ATI Developer support for ARB_multitexture information, and Martin van Velsen and Robin Fercoq's 3DS_SPEC.txt document that details (most of) the 3D Studio file format. Some additional hacking was done in order to perfect my loader. Additionally, comp.graphics.*, x2ftp.oulu.fi, and Gamasutra proved invaluable resources for suggesting techniques, whether or not I actually implemented them. --------------------------------------------- Images: Infinitum.jpg This demonstrates the massive polygon and unit-pushing capabilities we used in Infinitum. Each plane is composed of 6 sub-objects, totalling 122 faces, each helicopter has 5 sub-object, totalling 80 faces (the rotor is animated separately for each helicopter), the headquarters has 5 objects totaling 436 faces, and each tank has 7 sub-objects totaling 276 faces, plus a texture and opacity map. The terrain has 32768 faces, each textured and lit, generated fractally at startup. Yes, that means that in excess of 600k tris/sec are rendered with this game running at 60fps. This scene shows several tanks trying to infiltrate a well-defended (but poorly-played) enemy base. Not seen in this image are the 20+ forces the infiltrating player has in reserves.