// handles positive w only
idVec4 compute_homogeneous_plane( idVec4 a, idVec4 b, idVec4 c ) {
	idVec4 v, t;
	if( a[3] == 0 ) {
		t = a;
		a = b;
		b = c;
		c = t;
	}
	if( a[3] == 0 ) {
		t = a;
		a = b;
		b = c;
		c = t;
	}
	// can't handle 3 infinite points
	if( a[3] == 0 ) {
		return v;
	}
	idVec3 vb = homogeneous_difference( a, b );
	idVec3 vc = homogeneous_difference( a, c );
	idVec3 n = vb.Cross( vc );
	n.Normalize();
	v.x = n.x;
	v.y = n.y;
	v.z = n.z;
	v.w = - ( n * idVec3( a.x, a.y, a.z ) ) / a.w ;
	return v;
}
polyhedron make_sv(const polyhedron &oc, idVec4 light)
{
	static polyhedron lut[64];
	int index = 0;

	for (unsigned int i = 0; i < 6; i++) {
		if ((oc.p[i].plane * light) > 0)
			index |= 1<<i;
	}

	if (lut[index].e.size() == 0) {
		polyhedron &ph = lut[index];
		ph = oc;

		int V = ph.v.size();

		for (int j = 0; j < V; j++) {
			idVec3 proj = homogeneous_difference(light, ph.v[j]);
			ph.v.push_back(idVec4(proj.x, proj.y, proj.z, 0));
		}

		ph.p.empty();

		for (unsigned int i=0; i < oc.p.size(); i++) {
			if ((oc.p[i].plane * light) > 0) {
				ph.p.push_back(oc.p[i]);
			}
		}

		if (ph.p.size() == 0)
			return ph = polyhedron();

		ph.compute_neighbors();

		MyArrayPoly vpg;
		int I = ph.p.size();

		for (int i=0; i < I; i++) {
			MyArrayInt &vi = ph.p[i].vi;
			MyArrayInt &ni = ph.p[i].ni;
			int S = vi.size();

			for (int j = 0; j < S; j++) {
				if (ni[j] == -1) {
					poly pg;
					int a = vi[(j+1)%S];
					int b = vi[j];
					pg.vi = four_ints(a, b, b+V, a+V);
					pg.ni = four_ints(-1, -1, -1, -1);
					vpg.push_back(pg);
				}
			}
		}

		for (unsigned int i = 0; i < vpg.size(); i++)
			ph.p.push_back(vpg[i]);

		ph.compute_neighbors();
		ph.v.empty(); // no need to copy this data since it'll be replaced
	}

	polyhedron ph2 = lut[index];

	// initalize vertices
	ph2.v = oc.v;
	int V = ph2.v.size();

	for (int j = 0; j < V; j++) {
		idVec3 proj = homogeneous_difference(light, ph2.v[j]);
		ph2.v.push_back(idVec4(proj.x, proj.y, proj.z, 0));
	}

	// need to compute planes for the shadow volume (sv)
	ph2.recompute_planes();

	return ph2;
}