Archive for the ‘Technical’ Category

Making Progress (2)

Tuesday, March 10th, 2009

Hooray, even more progress! It’s been a while, so I can’t remember all the things I’ve accomplished since then, and there is certainly a good number of them, although not as many as I would like. As promised, GUI is done. As is the laboratory level. Here is a screenshot.Screenshot Three things to note: fully dynamic light eminating from avatar’s body, things in the dark appear different, and a door. Yes, you can open the door.

Right now the game runs at about 30fps on NVidia 6600. There are four dynamic lights. If I can keep the same framerate and get to 8 lights, I will be satisfied. I am actually glad I have a low level graphics card, because this way I am sure the game will run smoothly on almost all computers.

Animation Controller

Previously, I animated the avatar almost by hand. That is, every frame I had to check: is user is trying to move forward and what animating is currently playing. Then  I had to setup the next animation, which would start after the current one is finished. It was a jungle of if statements. Clearly, that wasn’t the right way to do it.

What I have now is essentially a Deterministic Finite State Machine, which knows exactly what animation to play based on two inputs: user’s action and current animation. Every frame the program tells it what the user wants to do, but it only uses that information when the current animation is finished playing. In other words, it doesn’t try to predict what the next animation will be until it actually needs it. This simplifies things quiet a bit, since it has at most one animation active at any one point.

Now, there are still several drawbacks. Let’s say the player wants to jump; the game has to play the jump animation. But if the avatar is running, the game has to play the running animation and the jumping animation. Currently, Animation Controller doesn’t support that, so I have to handle it elsewhere. This will be OK if there are only a couple of animations like that, but if there are more, I will have to adapt my solution.

Shaders

The main shader is done, as you can see. It calculates the color of each pixel by summing up the light from all light sources and adjusting diffuse, specular, and texture colors accordingly. The shader also distinguishes between things in the dark and things in the light, by using different material and texture.

One shader I really want to implement is Bloom Filter for glowing objects, like the crystals. Now, usually I don’t like shaders that only beautify the game and don’t serve any real purpose. But in this case, it is cruicial for the player to know which objects are emitting light (or dark). One way to do it would be through a simple billboard flare texture. I suppose that could work, but Bloom Filter would just look more pleasing to the eye.

Collision Detection

Yes, the avatar no longer floats in space. Collision with the floor, the walls, and the game objects is fully implemented. So far I got away by using three types of bounds: tight, box, and point. Tight bounds are triangle based bounds, box bounds are boxes with arbitrary Y-axis rotation, and point bounds are useful for doing line segment collisions.

The biggest problem so far is the collision between avatar and the walls. Since avatar has a cube bound, it’s possible to get too close to the wall and not be able to rotate. While this make perfect sense mathematically, it feels very bad from gameplay perspective and will certainly need to be addressed at some point, perhaps by implementing a cylinder bound.

Optimization

I’ve also had to do a bit of optimization. The main bottleneck is the shader, so I twicked around with it a bit and discovered (yet again), that yes indeed, ‘if’ statements really do slow it down drastically. In fact, it’s faster to do the entire calculation for a light source, even if it’s not used by the object, than to check if it is used. The only ‘if’ branch I have right now is to check whether the fragment is in the dark or the light area, because this determines what material and texture it will use. I don’t think there is a way to get around that.

I’ve also done some optimizations for CPU. Surprisingly, it’s really easy to do with CodeBlocks and MinGW setup. All you have to do is set -pg compiler flag to profile the code when it’s executed. Once the program runs, it outputs a gmon.out file, which you can run through MinGW’s gprof program to create a really nice text file, showing exactly where the program spends most of its time. Surprisingly, my CPU hot spots weren’t at all where I expected them to be. There were two: rendering a block and getting box bound information. Both were quiet surprising, since neither does much calculation. Now, I render each block into an OpenGL list, which accounted for about 10% of the CPU use. I’ve also added additional values to box bounds, so getting its information is faster too.

Since the player always needs to be able to see the avatar, the objects (mostly walls) that get in the way have to be turned transparent. This, naturally, raises a series of issues. I fixed them by passing each object through a renderer, which detects if the object rendered is transparent. If it is, it’s stored to be rendered later. During that time all transparent objects are sorted based on the distance from the camera and then rendered together, saving on OpenGL state switching and preserving transparency consistency.

Future

Obviously, there is a lot more to be done in each of these areas, and a lot more areas still remain untouched, like dialog system, enemy and NPC AI, fighting and puzzle solving mechanics. For now, however, I am switching my focus back to game design for a bit, to decide exactly what kind of puzzles I want to have in the game. The ideas always seems good while they are in my head, so I need to lay them out on paper to expose all the flaws. I hope by the next update, I’ll have puzzles and fighting implemented. Until then!

SecuROM

Thursday, December 25th, 2008

I’ve never been a fan of SecuROM, but I’ve never before ran into it. My protest has been purely philosophical. Today, however, I had the misfortune to experience the pain SecuROM brings. I don’t play games often and when I do, they are usually somewhat old, but today I got Civilization IV: Colonization from my dad.

When I ran it, I was met with “Timeout verifying for original disc“. When I hit Retry I got “You are trying to start a copy-protected application which requires the original disc to be in the CD/DVD-ROM drive. SecuROM™ has determined that you used a copy instead of the original disc.

Now, obviously I was using a legal brand new CD, right out of the case. I tried changing the Transfer Mode settings, but to no avail. May be it would work if I restarted the computer, but I just gave up and downloaded a no-cd crack instead. It worked flawlessly.

Now, everyone who could understand this issue already did and they already expressed their feelings against it, backed up with all the reasons. I don’t feel I need to reiterate them here. And, as it usually happens, everyone who actually makes the decisions did not understand, will not understand, or refuse to understand this issue. What’s ironic is the people who actually pirate the game never have to worry about these problems. And I don’t know of any game which is actually protected from piracy by SecuROM.

More on Quaternions

Tuesday, December 16th, 2008

OK, this is probably as technical as this blog will ever get. How do you interpolate n quaternions? Now, I don’t know exactly how everybody else solves this problem (or if they have to solve it at all). I had to solve it by myself essentially from scratch, so I am going to share my solution.

Problem:

Bone’s rotation is determined by a quaternion. Several actions can affect the same bone. Each action tells the bone where it’s supposed to be by specifying a quaternion. How does one interpolate between all the given quaternions?

Wrong Paths:

The problem of interpolating two quaternions is easy and has been well documented. There is simple linear interpolation, which doesn’t work well. Then there is SLERP, which works really well. Then there are a whole bunch of methods which works really well for a set of quaternions specified through time line. None of these solutions, however, apply to my problem.

Solution:

The key lies with the following equation, which I found in some obscure PowerPoint presentation (Slide 19) on quaternions. Nowhere else did I see it:

q = exp(w0 * log(q0) + w1 * log(q1) + …)

q is the final quaternion result

q0, q1… are the quaternions we need to interpolate

w0, w1… are weights associated with these quaternions

Now, it seems complicated and slow, but, actually, we can precompute log() of all quaternions, since that’s all we will be using. That way we would only need to do the exp() once per bone, which is actually less expensive than one SLERP. I got the code for log() and exp() from Perone’s website.