I decided to go with method 2 – create a face object, and attach vertexes to each face. I justified this decision because I was able to automate it after all; when I start importing models I will need to create a new face for each, err, face on the model and build its vertex list accordingly.
So what was happening to cause the bug? Well, to draw the 3D object, I had to send all the vertexes to the graphics card with their associated graphics data, and the list of indexes to tell the GPU what vertexes were related to each other in each triangle. To do this, I needed to put all the vertexes into one big vector object and send that huge thing off to the graphics card via a buffer. However, I quickly realised that I could optimise the number of triangles I drew by welding vertexes that were very close together in to one vertex.
I ran this optimisation each time a vertex was added to the list, starting at the back and going forwards. This meant that if a vertex had been added recently, as was the case for 2/3 of all vertexes, the algorithm would check the two most-recently-added vertexes, and if it found a match, early-exit and weld the matched vertexes together. However, if the vertex wasn’t recently added, the algorithm was continuing through and matching up with vertexes that were on another side of the sphere, and welding there. This wasn’t the desired behavior – the reason I went to such effort to get seperated sections of the sphere in the first place was to avoid this kind of texture/polygon bleed.
The solution was to isolate each set of vertexes by face. One way was for each vertex to be ‘smart’ and to know what face it belonged to; however this would require me to bloat the vertexes and wouldn’t actually cut down on the number of checks I had to make. I also think it was a fairly inelegant solution in hindsight, because vertexes would still have to check with every other vertex from other faces to make sure there was no match.
In the end I created a Face class. At the moment its sole job is to hold the list of vertexes associated with it, but later on I could see other properties being added. I created six faces, one for each side of the sphere, and stuffed them in a vector. Vectors copy their objects so they are handy for object storage, as opposed to linked lists where you need to manually assign memory and deallocate it after it’s been used. Less maintenance = happy me.
As vertexes are created, I send them to the appropriate face (in the code, the vertexes are built according to their location on the sphere, so their address tells us what their face is) and when all the vertexes are complete, I pop the faces back out and grab their completed vertex lists, then assemble them all into one big list. Then I send that, along with the associated index data, off to the GPU.
So now the cube shouldn’t have any bleeding edges.
OK, that’s working, let’s re-enable the normals to get the sphere.
Great, unfortunately somewhere along the way I broke my lighting on the sphere. I had optimised my vertex creation – originally when I was testing out my lighting, I had been sending vertex positions, normals and colors off to the GPU. Since I was using textures now, I removed colors; however the vertex object still had color data in it and the GPU couldn’t figure out what to do with it. So the solution apparently was just to ignore it without giving any kind of error, okay, well never mind. Fortunately I was able to go to my previous version of working code, check it against the new one, and quickly identify it.
Anyway with that working, lights are up and textures are good. We still have some small jobs to do – in particular, the cube next to the sphere has changed color.
Direction wise, there’s some more points to work with on textures before I consider them ‘actually’ done.
1 – In the real world, we don’t ordinarily use one texture plastered on different sides of the object (for simple objects like crates or boxes we probably do). Instead, we have something called a texture map – if you look at a real map of the world, it’s usually 2D, but it represents a 3D object.
I want to put a map of the world on my sphere, so that means I need to find a way to map the 2D world on to the 3D object.
2 – Complex objects often have multiple textures. I should be able to put a different texture on different parts of this sphere. I should also be able to put a different texture on the cube. I’ll be trying to make the cube look like a crate, and the sphere to look like a…I don’t know, maybe a skull or something, as an in-between-step.
3 – Related to step 2, ‘multitexturing’. Putting multiple textures over the same object. If you imagine a nicely painted wall, then you put some thin wallpaper over the wall – the paint color still comes through a little bit. One neat trick I want to try out is cycling textures to ‘fake’ animation. Imagine if I have a texture of lava on the sphere, and over that, a texture of white. I can cycle the white through different shades of transparency to give the illusion that the sphere is glowing hot.
Well with this I can do some neat things. The next ‘stage’ after this little play around is to put up a little sun, with some planets orbiting around it, and moons orbiting around those planets. I’ll use point-pixels (or maybe particles? I’ll read up to see what is best) for stars in the background.
Then it might be time to take the plunge and look at shadows/delayed rendering and see if I’m going to go that way. I probably don’t need to implement this though! That would be ‘frosting on the cake’ and it’s probably going to be a lot of effort. I think my time will be better invested learning how to port models into my program, and writing some simple games. So maybe I’ll do that first, and then after I have a demo or three up, I’ll look at advanced lighting.
I have basically a year before I return to Australia, and I want to get a good port folio together well before then. There are several very interesting game development companies in Adelaide, where I plan to live, so I want to contact them in advance and see what they think I should be doing to get a job there.
Failing that, it seems like Melbourne is the best place to go in Australia. I’d also happily move to USA to work for a company like Blizzard. My dream job back when I was in high school was to join a very old company called ‘Westwood Studios’, the company that made Dune, Dune 2, and started the Command and Conquer series. They were eventually bought out by EA Studios and it seems the franchise fell apart from there. After that, I (and every other programmer) wanted to work for iD Software. Ironically, I was scared off by the heavy focus on graphics programming because I thought the maths involving first person shooters was too hard. Now I’m about wrist-deep in graphics code, loving it, and want more.
These days I feel like I want to be involved with a company that ‘feels good’. I like Blizzard a lot, because they are large and successful enough that they are able to make a lot of their own rules about how the industry operates. I respect their ‘when it is ready’ attitude; as opposed to other companies that are scrambling to meet release dates, it seems like Blizzard has an emphasis on quality over quantity. I don’t have a whole lot of time for games these days, so I appreciate beautiful things.
That’s not to say I agree with everything about Blizzard’s design philosophies. One thing I dislike is artificial constraints on gameplay. For example, raiding in Warcraft is a lot of fun, but to be able to do it, you need to:
1 – Get a character to maximum level (not in itself a quick or easy feat, although you can buy one for a hefty sixty bucks)
2 – Get appropriate gear to actually enter a raid. The progression is something like: 5 man -> scenario -> heroic 5 man -> heroic scenario -> LFR -> Flex -> Raid.
I tried very hard in Pandaria to enter ‘Raid’ but the closest I got was ‘Flex’ because of 3…
3 – Find a bunch of players willing to do the same content as you at the right time.
This isn’t even considering farming materials up for various raid consumables, gearing properly, learning the encounters, grinding reputations as required, knowing your role, etc etc etc, and I haven’t even touched on the thing that should be the most important -> your actual skill with the character.
That’s a lot of things in between starting the game and just jumping in to the fun part. I think that if you have a roadblock to fun, that’s a design flaw.
I hope that one day I have the opportunity to work personally on Warcraft, but I hope even more that I get the opportunity to work on something that many people enjoy and feel positive about. Ultimately I want to tell a good story, and provide an environment where people feel they can be immersed and relax. These days, it seems like people have to commit to games for several hours and it becomes more like a chore. Games where you can just ‘jump in and have fun’ seem to be a dying breed.
Hmm, I wonder if there’s still life in the old dog yet….