I suppose it’s about time I elaborated on my project plan.
I was basically starting OpenGL from scratch. I had some prior experience with JOGL (that’s Java’s OpenGL) from my computer graphics course, but I found it hard going and could only just scrape through in the last assignment by the kindness of the lecturers. It was my own fault, I had started the assignment with only a few days left when I really should have committed a few weeks to it. Back then, I had chronic time management and prioritisation issues which I had to resolve painfully as I got older.
When I sat down and started re-learning Java, and learning C++, I had a fairly vague idea of the direction I wanted to go in, and subsequently, what capabilities I would need to have to realise these goals. I wanted to make a computer game set in space, where you could customise your ship and fleet of ships down to laying the circuit boards in the computer. Players could design the overall look of their ship basically by putting together predefined ship chunks, almost like building Lego, and then send those ships in to battle against other players ships. I wanted to avoid resource management and economy type decisions, the type that are prevalent in common RTS games, so that the only resources you are competing for are time and area. That’s a pretty high level description, so I extrapolated out the OpenGL requirements from there.
First of all, I wanted to use 3D graphics. That meant I would be using either OpenGL or DirectX. I went with OpenGL because at the time, I was programming on a Mac, and I didn’t think DirectX (which is owned and maintained by Microsoft) would ever play nice on their competitor’s machine. Secondarily, having been constrained to a Mac with very little options in the way of games, I resolved that any software I wrote in the future would be multi-platform. It’s true that the Mac segment of the market is very small compared to the Windows market, but the ‘Mac segment’ are people too, as are the Linux folk, and whatever other magic new operating systems pop up. I wanted to write software that could be used on any computer.
At a later date, I might write tools – I hate Microsoft’s new Office subscription model. Actually, Microsoft has really been turning me off since about Windows 7, the overall company behavior is very slimy and unbecoming of the pioneer of software. Regardless; I went with OpenGL.
Create a window, resize the window with no deformation of displayed data.
Display simple 2D objects -> 3D objects.
Camera rotation/translation, using the keyboard.
Create multiple objects and have them relate to each other/move correctly. This required a reintroduction to pointers and data structures in C++. In Java, it’s super easy, in C++, it took some work because I wasn’t aware of declaring memory on the stack vs on the heap. In Java you can just go on blissfully unaware what happens behind the scenes, and it will work out okay or break immediately and tell you it’s stuck. In C++ the computer assumes you know what you are doing. It’s exactly like somebody driving a car and following exactly what the GPS is saying, even if it just told you to drive off the end of a jetty. So this took some help from David to straighten me out.
At this point I found the limitation of the OpenGL matrix model and started to make my own matrix classes, vector classes and preliminary point4f classes.
Curved surface representation
This was actually surprisingly easy. There’s a few different ways of representing a curved surface. One is to provide averaged normals between surfaces. Another is to use tesselation (breaking down each surface into progressively smaller shapes to better represent the curve). I went with a combination of the two, so it was computationally expensive at the initialisation phase but looked great.
This required me to get my recursion and tesselation working, which was done.
I then started building curve segments and half circles and other kinds of crazy shapes. I wanted to make a tank track – a fairly complicated object, made up of many cylinders, circle segments and lots of polygons.
I was mostly learning OpenGL from various tutorials I had found on the web; and I had bought a whole bunch of books that had now arrived. Most of the books were dated around OpenGL 2.0, after the introduction of shaders, but before the matrix model had been fully deprecated. The examples did not compile, and worse, contained example code that the computer did not recognize. I considered avoiding shaders. However, the power of shaders couldn’t be ignored. Shaders would allow me to correctly represent curved surfaces without having to fake it, as well as have pixel level control of surfaces. Plus being able to offload the graphics calculations to the graphics card would allow for a significant frame per second boost. Features like proper transparency (such as for partially reflective surfaces, like glass, or water) or delayed light rendering (allowing me to use more than eight lights at a time if desired) mandated the use of shaders. Therefore, it was time to abandon the Immediate Mode model of OpenGL 2.0 and get into OpenGL 3.3 and later.
Getting shaders working has been exceptionally difficult. I tried to do it on my own first of all, and just use the OpenGL orange book and my bought books. I wanted to avoid using a pre-existing Hello World and reverse engineering it. This took a lot of time but the upshot is that I actually had to learn how to do it properly, so I can confidently declare, define, compile, link, and execute shaders. Great. The trouble was getting OpenGL to believe that I knew how to do it, because it kept giving me black screens of doom…
So I finally used a Hello World and now I’m going to reverse engineer it to see why mine didn’t work. And then I can start working on capabilities again.
Mouse movement/recognition of specific objects being selected with the mouse
Sound/music selectively being played in response to object selection
Simple object AI
Simple shader properties – textures, transparency, the brick GLSL in orange book test
Find out the correct way to use multiple shaders. At the moment it looks like you load the shader you want to use, draw the polygons you want shaded that way, unload the shader, load the next shader, draw the rest of the polygons, unload that shader, draw the next one etc etc. To me it would be great if you could have all your shaders active and just throw the polygons and it would automatically feed them to the right shader. Ugh well I guess having all of them loaded into memory at once isn’t very efficient. Maybe the first way is the right way. Well that’s why it’s a capability goal. I’ll look at it later.
Vertex Buffer Objects! Oh man last night was really exciting. When I was doing the original tank model, I had a whole bunch of vertexes. I drew each rectangle by feeding four coordinates to the triangle drawer and drawing two triangles next to each other. I wanted to have normals calculated at each vertex, but when I used a shared vertex, the normal would get lost, so I had to have lots of extra vertexes around. I saw this was very inefficient because the same edge was being redefined and I was all ‘BAH there must be a better way’. I tried to write a good algorithm where I could just throw a whole bunch of vertexes and edge data and the computer would crawl along it and automatically populate the triangles for me with no duplication.
Last night when I was reading about vertex buffer objects I could see how this related to the original immediate mode I was familiar with. Then I read on and BAM! Vertex Buffer INDEXES. What is this? It’s the proper, sanctioned way of doing that thing I was trying to do just before – throw vertexes and edge data at the GPU and let that thing sort it out.
It’s still not perfect though because I didn’t see how you can have multiple normals on a single vertex. So all my objects will appear curved until I solve that. But that’ll be a capability to assess later.
My short term game goal is to have a simple DOTA style game where tanks are automatically generated, drive around a simple terrain field towards the enemy base, and blow each other up. For fun, I will randomly generate tank components (light, medium, heavy types of: hull, track, turret, gun, making for 81 different tank types) for each tank. I want to be able to select a tank with the mouse and give it orders that will over ride the default AI. And I want four different teams instead of two so I can write some fun target-selection AI.
Many capability requirements are implied and as I discover them I’ll update them here.
My immediate goal is to fix the touchpad issue with Windows 8.1. It’s driving me crazy. I literally cannot write a sentence without the mouse trying to select and delete it all. I tried earlier with no result (the Elan driver hasn’t been updated or I can’t find it because searches keep assuming that since I am in Japan I must only ever want the Japanese sites) but it’s been a few weeks since then so it’s worth another shot.
On a related note, geo-locking of IP’s to people’s region is very frustrating. Google is one of the worst criminals! Whenever I go to http://www.google.com it says OH YOU MUST MEAN http://www.google.co.jp and redirects there, no matter how many times I do it. It’s annoying because I can’t read Japanese! I can translate the pages, but I shouldn’t have to – there are perfectly good English ones avaialable that I can’t access. BLARGH.