// 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; }