public float[][] verts; //[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2) public void Clear() { this.next = null; this.chain = null; this.numverts = 0; this.flags = 0; this.verts = null; }
public float[][] verts; //[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2) public void Clear() { next = null; chain = null; numverts = 0; flags = 0; verts = null; }
private static void DrawGLPoly(glpoly_t p) { GL.Begin(PrimitiveType.Polygon); for (int i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.TexCoord2(v[3], v[4]); GL.Vertex3(v); } GL.End(); }
private static void DrawGLWaterPoly(glpoly_t p) { DisableMultitexture(); float[] nv = new float[3]; GL.Begin(PrimitiveType.TriangleFan); for (int i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.TexCoord2(v[3], v[4]); nv[0] = (float)(v[0] + 8 * Math.Sin(v[1] * 0.05 + host.RealTime) * Math.Sin(v[2] * 0.05 + host.RealTime)); nv[1] = (float)(v[1] + 8 * Math.Sin(v[0] * 0.05 + host.RealTime) * Math.Sin(v[2] * 0.05 + host.RealTime)); nv[2] = v[2]; GL.Vertex3(nv); } GL.End(); }
/// <summary> /// EmitSkyPolys /// </summary> static void EmitSkyPolys(msurface_t fa) { for (glpoly_t p = fa.polys; p != null; p = p.next) { GL.Begin(BeginMode.Polygon); for (int i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; Vector3 dir = new Vector3(v[0] - Render.Origin.X, v[1] - Render.Origin.Y, v[2] - Render.Origin.Z); dir.Z *= 3; // flatten the sphere dir.Normalize(); dir *= 6 * 63; float s = (_SpeedScale + dir.X) / 128.0f; float t = (_SpeedScale + dir.Y) / 128.0f; GL.TexCoord2(s, t); GL.Vertex3(v); } GL.End(); } }
/// <summary> /// EmitWaterPolys /// Does a water warp on the pre-fragmented glpoly_t chain /// </summary> static void EmitWaterPolys(msurface_t fa) { for (glpoly_t p = fa.polys; p != null; p = p.next) { GL.Begin(BeginMode.Polygon); for (int i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; float os = v[3]; float ot = v[4]; float s = os + _TurbSin[(int)((ot * 0.125 + Host.RealTime) * TURBSCALE) & 255]; s *= (1.0f / 64); float t = ot + _TurbSin[(int)((os * 0.125 + Host.RealTime) * TURBSCALE) & 255]; t *= (1.0f / 64); GL.TexCoord2(s, t); GL.Vertex3(v); } GL.End(); } }
private static void DrawGLWaterPolyLightmap(glpoly_t p) { DisableMultitexture(); float[] nv = new float[3]; GL.Begin(BeginMode.TriangleFan); for (int i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.TexCoord2(v[5], v[6]); nv[0] = (float)(v[0] + 8 * Math.Sin(v[1] * 0.05 + Host.RealTime) * Math.Sin(v[2] * 0.05 + Host.RealTime)); nv[1] = (float)(v[1] + 8 * Math.Sin(v[0] * 0.05 + Host.RealTime) * Math.Sin(v[2] * 0.05 + Host.RealTime)); nv[2] = v[2]; GL.Vertex3(nv); } GL.End(); }
private static void DrawGLPoly(glpoly_t p) { GL.Begin(BeginMode.Polygon); for (int i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.TexCoord2(v[3], v[4]); GL.Vertex3(v); } GL.End(); }
/// <summary> /// BuildSurfaceDisplayList /// </summary> 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 = _CurrentVertBase[r_pedge_v[0]].position; } else { r_pedge_v = pedges[-lindex].v; vec = _CurrentVertBase[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 (_glKeepTJunctions.Value == 0 && (fa.flags & Surf.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 < Mod.VERTEXSIZE; ++k) poly.verts[j - 1][k] = poly.verts[j][k]; } --lnumverts; ++_ColinElim; // retry next vertex next time, which is now current vertex --i; } } } poly.numverts = lnumverts; }
/// <summary> /// R_BlendLightmaps /// </summary> private static void BlendLightmaps() { if (_FullBright.Value != 0) { return; } if (_glTexSort.Value == 0) { return; } GL.DepthMask(false); // don't bother writing Z if (Drawer.LightMapFormat == PixelFormat.Luminance) { GL.BlendFunc(BlendingFactor.Zero, BlendingFactor.OneMinusSrcColor); } //else if (gl_lightmap_format == GL_INTENSITY) //{ // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // glColor4f(0, 0, 0, 1); // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //} if (_LightMap.Value == 0) { GL.Enable(EnableCap.Blend); } for (int i = 0; i < MAX_LIGHTMAPS; i++) { glpoly_t p = _LightMapPolys[i]; if (p == null) { continue; } Drawer.Bind(_LightMapTextures + i); if (_LightMapModified[i]) { CommitLightmap(i); } for ( ; p != null; p = p.chain) { if ((p.flags & Surf.SURF_UNDERWATER) != 0) { DrawGLWaterPolyLightmap(p); } else { GL.Begin(PrimitiveType.Polygon); for (int j = 0; j < p.numverts; j++) { float[] v = p.verts[j]; GL.TexCoord2(v[5], v[6]); GL.Vertex3(v); } GL.End(); } } } GL.Disable(EnableCap.Blend); if (Drawer.LightMapFormat == PixelFormat.Luminance) { GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); } //else if (gl_lightmap_format == GL_INTENSITY) //{ // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // glColor4f(1, 1, 1, 1); //} GL.DepthMask(true); // back to normal Z buffering }
/// <summary> /// BuildSurfaceDisplayList /// </summary> private 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 = _CurrentVertBase[r_pedge_v[0]].position; } else { r_pedge_v = pedges[-lindex].v; vec = _CurrentVertBase[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 (_glKeepTJunctions.Value == 0 && (fa.flags & Surf.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 < Mod.VERTEXSIZE; ++k) { poly.verts[j - 1][k] = poly.verts[j][k]; } } --lnumverts; ++_ColinElim; // retry next vertex next time, which is now current vertex --i; } } } poly.numverts = lnumverts; }
/// <summary> /// R_DrawSequentialPoly /// Systems that have fast state and texture changes can /// just do everything as it passes with no need to sort /// </summary> private static void DrawSequentialPoly(msurface_t s) { // // normal lightmaped poly // if ((s.flags & (Surf.SURF_DRAWSKY | Surf.SURF_DRAWTURB | Surf.SURF_UNDERWATER)) == 0) { RenderDynamicLightmaps(s); glpoly_t p = s.polys; texture_t t = TextureAnimation(s.texinfo.texture); if (vid.glMTexable) { // Binds world to texture env 0 Drawer.SelectTexture(MTexTarget.TEXTURE0_SGIS); Drawer.Bind(t.gl_texturenum); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace); // Binds lightmap to texenv 1 EnableMultitexture(); // Same as SelectTexture (TEXTURE1) Drawer.Bind(_LightMapTextures + s.lightmaptexturenum); int i = s.lightmaptexturenum; if (_LightMapModified[i]) { CommitLightmap(i); } GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Blend); GL.Begin(PrimitiveType.Polygon); for (i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.MultiTexCoord2(TextureUnit.Texture0, v[3], v[4]); GL.MultiTexCoord2(TextureUnit.Texture1, v[5], v[6]); GL.Vertex3(v); } GL.End(); return; } else { Drawer.Bind(t.gl_texturenum); GL.Begin(PrimitiveType.Polygon); for (int i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.TexCoord2(v[3], v[4]); GL.Vertex3(v); } GL.End(); Drawer.Bind(_LightMapTextures + s.lightmaptexturenum); GL.Enable(EnableCap.Blend); GL.Begin(PrimitiveType.Polygon); for (int i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.TexCoord2(v[5], v[6]); GL.Vertex3(v); } GL.End(); GL.Disable(EnableCap.Blend); } return; } // // subdivided water surface warp // if ((s.flags & Surf.SURF_DRAWTURB) != 0) { DisableMultitexture(); Drawer.Bind(s.texinfo.texture.gl_texturenum); EmitWaterPolys(s); return; } // // subdivided sky warp // if ((s.flags & Surf.SURF_DRAWSKY) != 0) { DisableMultitexture(); Drawer.Bind(_SolidSkyTexture); _SpeedScale = (float)host.RealTime * 8; _SpeedScale -= (int)_SpeedScale & ~127; EmitSkyPolys(s); GL.Enable(EnableCap.Blend); Drawer.Bind(_AlphaSkyTexture); _SpeedScale = (float)host.RealTime * 16; _SpeedScale -= (int)_SpeedScale & ~127; EmitSkyPolys(s); GL.Disable(EnableCap.Blend); return; } // // underwater warped with lightmap // RenderDynamicLightmaps(s); if (vid.glMTexable) { texture_t t = TextureAnimation(s.texinfo.texture); Drawer.SelectTexture(MTexTarget.TEXTURE0_SGIS); Drawer.Bind(t.gl_texturenum); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace); EnableMultitexture(); Drawer.Bind(_LightMapTextures + s.lightmaptexturenum); int i = s.lightmaptexturenum; if (_LightMapModified[i]) { CommitLightmap(i); } GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Blend); GL.Begin(PrimitiveType.TriangleFan); glpoly_t p = s.polys; float[] nv = new float[3]; for (i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.MultiTexCoord2(TextureUnit.Texture0, v[3], v[4]); GL.MultiTexCoord2(TextureUnit.Texture1, v[5], v[6]); nv[0] = (float)(v[0] + 8 * Math.Sin(v[1] * 0.05 + host.RealTime) * Math.Sin(v[2] * 0.05 + host.RealTime)); nv[1] = (float)(v[1] + 8 * Math.Sin(v[0] * 0.05 + host.RealTime) * Math.Sin(v[2] * 0.05 + host.RealTime)); nv[2] = v[2]; GL.Vertex3(nv); } GL.End(); } else { glpoly_t p = s.polys; texture_t t = TextureAnimation(s.texinfo.texture); Drawer.Bind(t.gl_texturenum); DrawGLWaterPoly(p); Drawer.Bind(_LightMapTextures + s.lightmaptexturenum); GL.Enable(EnableCap.Blend); DrawGLWaterPolyLightmap(p); GL.Disable(EnableCap.Blend); } }
public void Clear() { this.next = null; this.chain = null; this.numverts = 0; this.flags = 0; this.verts = null; }
/// <summary> /// SubdividePolygon /// </summary> 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 = Mod.SubdivideSize * Math.Floor(m / Mod.SubdivideSize + 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++) { Common.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; } }
/// <summary> /// SubdividePolygon /// </summary> 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 = Mod.SubdivideSize * Math.Floor(m / Mod.SubdivideSize + 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++) { Common.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; } }