Okay, so I found something that works for me. First off, I'm using this equation to find the intersection point of three planes. (If the denominator is 0 there's no intersection.) I have to loop through all the planes multiple times, but in my case I'm doing it as a pre-process so it's not a big deal.
Just because three planes of the hull intersect, however, does not mean the intersection actually reside on the hull itself. In order to weed out the outliers I test the point to see if it lies "inside" the hull, within a reasonable margin of error. The algorithm for that is pretty simple:
function pointInHull(planes, point) {
for (i = 0; i < planes.length; i++) {
plane = planes[i];
dist = point.dot(plane.normal) - plane.distance;
if (dist > 0.01) return false; // indicates the point lies in outside the hull
}
return true;
}
Since no planes will ever intersect inside the hull (that's what makes it convex!) this gives me all the edge points.
So the basic code is something like this:
pointCloud = [];
for (i = 0; i < planes.length; i++) {
p1 = planes[i];
for (j = i+1; j < planes.length; j++) {
p2 = planes[j];
for (k = j+1; k < planes.length; k++) {
p3 = planes[k];
point = getPlaneIntersectionPoint(p1, p2, p3);
if(point && pointInHull(planes, point)) {
pointCloud.push(point);
}
}
}
}
I certainly wouldn't recommend trying this in a realtime situation, but as an offline process it's fine.