Sunday, January 22, 2012
Well, that was a gigantic pain in the butt.
My goal, which I’ve gotten perhaps a bit irrationally fixated on the last few days, was to get accurate collision with these gigantic asteroids I for some reason decided to have in the game. The scheme I selected was to take the asteroid geometry, construct a 2-D heightfield (basically an unrolled horizontal map of the asteroid) full of altitudes from the center of the asteroid, and then at game time transform world points into asteroid-relative points and look them up in the heightfield to find the altitude of the asteroid at that location. If the distance of the point from the asteroid’s center is less than the altitude, then there’s a collision with the asteroid’s surface and appropriate action should be taken.
The first annoying step was to generate the heightfield data. This was troublesome because the source data is basically a cloud of points created by subdividing up a sphere, and naturally there’s not going to be a one-to-one correspondence between that and a rectangular map projection. I “solved” this, if you want to call it that, with a hilariously inefficient scheme that loops through every point on the map grid and locates the closest point to it in the cloud, latitude/longitude-wise, to obtain an altitude. As far as actually doing this efficiently, I expect I’d have to save a tree of triangles when generating the asteroid so it would be easier to search. I’m overcome by a vast tide of “I don’t feel like it” right now, though, so I’ll come back to this later if I have to.
The next, even more aggravating problem was that of transforming the point into the asteroid’s local space. Looking up points when the asteroid is standing still worked perfectly, but when it was rotating? No dice. I believe I’ve mentioned in the past I thought there was an error in my “transform into local space” code, and in this situation where extreme precision was required it indeed popped up to bite me. I spent two days thrashing around, trying to find mistakes at any level, searching the web for references and alternate methods, filling the code base up with debug hackery that’ll probably take me an hour to pick out again. I ultimately kept coming back to that transform code. And yeah, my tQuaternion::Inverse() function was wrong, just wrong in a way that wouldn’t show up by transforming the point into local space and back. As is always the case, the most irritating issues aren’t some deep-seated mathematical issue, structual problem or library bug: they’re one-line typos in your own code.
I suppose this wasn’t really a waste of time. Naturally, I have to be able to count on the low-level math code being right. And at the very least, the transform-into-local-space code really, really needed to be correct since it is used to do collision checking between the rectangular collision volumes used for ships (transform one rectangle into the other’s local space and suddenly the separating axes test is super-easy.) Aside from that, the whole asteroid endeavor was because at some point in the game I wanted to have a stage where the player attacks installations on the surface of an asteroid. Given that I’ve spent so much time dealing with this, maybe I should turn that into a bigger feature of the game.

Well, that was a gigantic pain in the butt.

My goal, which I’ve gotten perhaps a bit irrationally fixated on the last few days, was to get accurate collision with these gigantic asteroids I for some reason decided to have in the game. The scheme I selected was to take the asteroid geometry, construct a 2-D heightfield (basically an unrolled horizontal map of the asteroid) full of altitudes from the center of the asteroid, and then at game time transform world points into asteroid-relative points and look them up in the heightfield to find the altitude of the asteroid at that location. If the distance of the point from the asteroid’s center is less than the altitude, then there’s a collision with the asteroid’s surface and appropriate action should be taken.

The first annoying step was to generate the heightfield data. This was troublesome because the source data is basically a cloud of points created by subdividing up a sphere, and naturally there’s not going to be a one-to-one correspondence between that and a rectangular map projection. I “solved” this, if you want to call it that, with a hilariously inefficient scheme that loops through every point on the map grid and locates the closest point to it in the cloud, latitude/longitude-wise, to obtain an altitude. As far as actually doing this efficiently, I expect I’d have to save a tree of triangles when generating the asteroid so it would be easier to search. I’m overcome by a vast tide of “I don’t feel like it” right now, though, so I’ll come back to this later if I have to.

The next, even more aggravating problem was that of transforming the point into the asteroid’s local space. Looking up points when the asteroid is standing still worked perfectly, but when it was rotating? No dice. I believe I’ve mentioned in the past I thought there was an error in my “transform into local space” code, and in this situation where extreme precision was required it indeed popped up to bite me. I spent two days thrashing around, trying to find mistakes at any level, searching the web for references and alternate methods, filling the code base up with debug hackery that’ll probably take me an hour to pick out again. I ultimately kept coming back to that transform code. And yeah, my tQuaternion::Inverse() function was wrong, just wrong in a way that wouldn’t show up by transforming the point into local space and back. As is always the case, the most irritating issues aren’t some deep-seated mathematical issue, structual problem or library bug: they’re one-line typos in your own code.

I suppose this wasn’t really a waste of time. Naturally, I have to be able to count on the low-level math code being right. And at the very least, the transform-into-local-space code really, really needed to be correct since it is used to do collision checking between the rectangular collision volumes used for ships (transform one rectangle into the other’s local space and suddenly the separating axes test is super-easy.) Aside from that, the whole asteroid endeavor was because at some point in the game I wanted to have a stage where the player attacks installations on the surface of an asteroid. Given that I’ve spent so much time dealing with this, maybe I should turn that into a bigger feature of the game.

Notes

  1. mayflystudio posted this