public static void BuildSurfaceDisplayList(msurface_t fa) { // reconstruct the polygon medge_t[] pedges = currentmodel.edges; int lnumverts = fa.numedges; // // draw texture // glpoly_t poly = new glpoly_t(); poly.AllocVerts(lnumverts); poly.next = fa.polys; poly.flags = fa.flags; fa.polys = poly; ushort[] r_pedge_v; Vector3 vec; for (int i = 0; i < lnumverts; i++) { int lindex = currentmodel.surfedges[fa.firstedge + i]; if (lindex > 0) { r_pedge_v = pedges[lindex].v; vec = r_pcurrentvertbase[r_pedge_v[0]].position; } else { r_pedge_v = pedges[-lindex].v; vec = r_pcurrentvertbase[r_pedge_v[1]].position; } float s = Mathlib.DotProduct(ref vec, ref fa.texinfo.vecs[0]) + fa.texinfo.vecs[0].W; s /= fa.texinfo.texture.width; float t = Mathlib.DotProduct(ref vec, ref fa.texinfo.vecs[1]) + fa.texinfo.vecs[1].W; t /= fa.texinfo.texture.height; poly.verts[i][0] = vec.X; poly.verts[i][1] = vec.Y; poly.verts[i][2] = vec.Z; poly.verts[i][3] = s; poly.verts[i][4] = t; // // lightmap texture coordinates // s = Mathlib.DotProduct(ref vec, ref fa.texinfo.vecs[0]) + fa.texinfo.vecs[0].W; s -= fa.texturemins[0]; s += fa.light_s * 16; s += 8; s /= BLOCK_WIDTH * 16; t = Mathlib.DotProduct(ref vec, ref fa.texinfo.vecs[1]) + fa.texinfo.vecs[1].W; t -= fa.texturemins[1]; t += fa.light_t * 16; t += 8; t /= BLOCK_HEIGHT * 16; poly.verts[i][5] = s; poly.verts[i][6] = t; } // // remove co-linear points - Ed // if (gl_keeptjunctions.value == 0 && (fa.flags & q_shared.SURF_UNDERWATER) == 0) { for (int i = 0; i < lnumverts; ++i) { if (IsCollinear(poly.verts[(i + lnumverts - 1) % lnumverts], poly.verts[i], poly.verts[(i + 1) % lnumverts])) { int j; for (j = i + 1; j < lnumverts; ++j) { //int k; for (int k = 0; k < q_shared.VERTEXSIZE; ++k) { poly.verts[j - 1][k] = poly.verts[j][k]; } } --lnumverts; ++nColinElim; // retry next vertex next time, which is now current vertex --i; } } } poly.numverts = lnumverts; }
static void SubdividePolygon(int numverts, Vector3[] verts) { if (numverts > 60) { Sys_Error("numverts = {0}", numverts); } Vector3 mins, maxs; BoundPoly(numverts, verts, out mins, out maxs); float[] dist = new float[64]; for (int i = 0; i < 3; i++) { double m = (Mathlib.Comp(ref mins, i) + Mathlib.Comp(ref maxs, i)) * 0.5; m = gl_subdivide_size.value * Math.Floor(m / gl_subdivide_size.value + 0.5); if (Mathlib.Comp(ref maxs, i) - m < 8) { continue; } if (m - Mathlib.Comp(ref mins, i) < 8) { continue; } for (int j = 0; j < numverts; j++) { dist[j] = (float)(Mathlib.Comp(ref verts[j], i) - m); } Vector3[] front = new Vector3[64]; Vector3[] back = new Vector3[64]; // cut it // wrap cases dist[numverts] = dist[0]; verts[numverts] = verts[0]; // Uze: source array must be at least numverts + 1 elements long int f = 0, b = 0; for (int j = 0; j < numverts; j++) { if (dist[j] >= 0) { front[f] = verts[j]; f++; } if (dist[j] <= 0) { back[b] = verts[j]; b++; } if (dist[j] == 0 || dist[j + 1] == 0) { continue; } if ((dist[j] > 0) != (dist[j + 1] > 0)) { // clip point float frac = dist[j] / (dist[j] - dist[j + 1]); front[f] = back[b] = verts[j] + (verts[j + 1] - verts[j]) * frac; f++; b++; } } SubdividePolygon(f, front); SubdividePolygon(b, back); return; } glpoly_t poly = new glpoly_t(); poly.next = _WarpFace.polys; _WarpFace.polys = poly; poly.AllocVerts(numverts); for (int i = 0; i < numverts; i++) { Copy(ref verts[i], poly.verts[i]); float s = Vector3.Dot(verts[i], _WarpFace.texinfo.vecs[0].Xyz); float t = Vector3.Dot(verts[i], _WarpFace.texinfo.vecs[1].Xyz); poly.verts[i][3] = s; poly.verts[i][4] = t; } }