My main character is a rolling ball. It has objects attached to it which stick out from the ball, but don’t roll (guns, actually). What I wanted to do was joint the physical rigid bodies together in such a way to achieve a nice physics-based simulation of what I want, which would also mean that the protrusions from the ball would collide and react with scenery and other world objects.
After singing Jitter’s praises last week, I’ve now got to pull it down a notch or two. Jitter is a great solution for simple rigid bodies all colliding with each other; but what it lacks is some good joints between those bodies. There is a basic joint type; but it’s a bit buggy – Jitter’s creator claims that it’s because the system doesn’t loose any energy which makes the joints squishy and not solid.
I attempted some fixes to the squishy joints, but I decided to leave it alone for now and work around the problem. The spherical ball character is what’s important, but I don’t want things that stick out from it to go through the walls. My current solution is to place a collision hull slightly away from the walls such that extrusions from the ball model don’t pass through the walls. I’ll build the hull by hand in Radiant so I can specify very specifically where the hull should be; calculating it automagically would likely result in more issues right now.
This approach has caused it’s own issues though, because the Quake3 BSP loader I have is only at version 0.4 and doesn’t support the many surfaceparm values that I need for things like clip objects.
Also, the traditional Quake3 clip brushes (using the nodraw texture) are not exported as faces by q3map2 which is what I need to collide with. They are exported only as brushes, which are convex polyhedrons made up of a finite number of planes. The collision hull I’ve built for use in Jitter uses a polygon mesh in a octree, the definition of a brush doesn’t contain polygon data. It only holds planar data. For the simple collisions of Quake3 this was an acceptable method for the computing power of the machines of the time. These days collisions are done on a per-poly basis for much more accuracy, so that brush data is slightly redundant.
There are algorithms out there that can triangulate such data into a mesh, but it’s a long-winded approach to the issue. Another option is to use the invisible texture of Quake3, which exports all the required faces for building my collision mesh but renders a transparent texture on them.
There were two issues with the invisible texture approach, firstly objects that have this texture still cast shadows. This can be solved easily be tweaking the Quake3 shader that associated with it. The second issue was that transparency doesn’t seem to work in my engine; I just get black where it should be clear. I’m not quite sure where the blame lies for that – but a few simple attempts to fix it by manipulating XNA 4.0′s BlendState didn’t bear any fruit.
What I really wanted was a flag on the faces that I don’t want to draw so they don’t get added to the render list. Ideally, that flag should be a surfaceparm and should be passed through to the engine. So, I fixed that.
After updating the Content Pipeline (which is what creates and/or copies the data files over) so it now supports the surfaceparm values I can now use those in the engine as I see fit, unfortunately many of the values have a bit of a dual-purpose use between q3map2 and the engine so I’m inventing my own for engine usage only. The first being an ‘invisible’ flag. As I mentioned, the way this was achieved in Quake3 was to render a transparent texture – regardless of my transparency issues it also seems like a bit of a waste of a render call, so instead I’m now setting a flag such that those faces never get drawn in the first place.
I also seem to remember that the extravagant curves that were in Quake3 had no collision data on them; you couldn’t run directly on a curved surface – a bit of clever fakery was used by the level designers to achieve that effect when it was needed. Now that I’m using the polygon data; collisions on curves should also be a fairly simple matter.
After sorting all that out I now have a bespoke invisible collision hull on my level, and after a little more coding I got the camera following the player object in a simple 3rd-person fashion. A ray is cast out from the player position in the opposite direction to that which it is facing; and is truncated if it collides with the level. It can result in a very close view of the player if you back into a wall; but I’m going to leave it at that for now.
The target for next week is some kind of local multiplayer with an aim for online multiplayer via Xbox LIVE. Multiplayer is my final major hurdle before I can get on with a bit of actual game development as opposed to engine development.