public static void GL_MipMap(uint[] src, int width, int height) { Union4b p1 = Union4b.Empty, p2 = Union4b.Empty, p3 = Union4b.Empty, p4 = Union4b.Empty; width >>= 1; height >>= 1; uint[] dest = src; int srcOffset = 0; int destOffset = 0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { p1.ui0 = src[srcOffset]; int offset = srcOffset + 1; p2.ui0 = offset < src.Length ? src[offset] : p1.ui0; offset = srcOffset + (width << 1); p3.ui0 = offset < src.Length ? src[offset] : p1.ui0; offset = srcOffset + (width << 1) + 1; p4.ui0 = offset < src.Length ? src[offset] : p1.ui0; p1.b0 = (byte)((p1.b0 + p2.b0 + p3.b0 + p4.b0) >> 2); p1.b1 = (byte)((p1.b1 + p2.b1 + p3.b1 + p4.b1) >> 2); p1.b2 = (byte)((p1.b2 + p2.b2 + p3.b2 + p4.b2) >> 2); p1.b3 = (byte)((p1.b3 + p2.b3 + p3.b3 + p4.b3) >> 2); dest[destOffset] = p1.ui0; destOffset++; srcOffset += 2; } srcOffset += width << 1; } }
// GL_MipMap // // Operates in place, quartering the size of the texture protected void MipMap(UInt32[] src, Int32 width, Int32 height) { Union4b p1 = Union4b.Empty, p2 = Union4b.Empty, p3 = Union4b.Empty, p4 = Union4b.Empty; width >>= 1; height >>= 1; var dest = src; var srcOffset = 0; var destOffset = 0; for (var i = 0; i < height; i++) { for (var j = 0; j < width; j++) { p1.ui0 = src[srcOffset]; var offset = srcOffset + 1; p2.ui0 = offset < src.Length ? src[offset] : p1.ui0; offset = srcOffset + (width << 1); p3.ui0 = offset < src.Length ? src[offset] : p1.ui0; offset = srcOffset + (width << 1) + 1; p4.ui0 = offset < src.Length ? src[offset] : p1.ui0; p1.b0 = ( Byte )((p1.b0 + p2.b0 + p3.b0 + p4.b0) >> 2); p1.b1 = ( Byte )((p1.b1 + p2.b1 + p3.b1 + p4.b1) >> 2); p1.b2 = ( Byte )((p1.b2 + p2.b2 + p3.b2 + p4.b2) >> 2); p1.b3 = ( Byte )((p1.b3 + p2.b3 + p3.b3 + p4.b3) >> 2); dest[destOffset] = p1.ui0; destOffset++; srcOffset += 2; } srcOffset += width << 1; } }
public static void WriteInt(byte[] dest, int offset, int value) { Union4b u = Union4b.Empty; u.i0 = value; dest[offset + 0] = u.b0; dest[offset + 1] = u.b1; dest[offset + 2] = u.b2; dest[offset + 3] = u.b3; }
/// <summary> /// VID_SetPalette /// called at startup and after any gamma correction /// </summary> public static void SetPalette(byte[] palette) { // // 8 8 8 encoding // int offset = 0; byte[] pal = palette; uint[] table = _8to24table; for (int i = 0; i < table.Length; i++) { uint r = pal[offset + 0]; uint g = pal[offset + 1]; uint b = pal[offset + 2]; table[i] = ((uint)0xff << 24) + (r << 0) + (g << 8) + (b << 16); offset += 3; } table[255] &= 0xffffff; // 255 is transparent // JACK: 3D distance calcs - k is last closest, l is the distance. // FIXME: Precalculate this and cache to disk. Union4b val = Union4b.Empty; for (uint i = 0; i < (1 << 15); i++) { // Maps // 000000000000000 // 000000000011111 = Red = 0x1F // 000001111100000 = Blue = 0x03E0 // 111110000000000 = Grn = 0x7C00 uint r = (((i & 0x1F) << 3) + 4); uint g = (((i & 0x03E0) >> 2) + 4); uint b = (((i & 0x7C00) >> 7) + 4); uint k = 0; uint l = 10000 * 10000; for (uint v = 0; v < 256; v++) { val.ui0 = _8to24table[v]; uint r1 = r - val.b0; uint g1 = g - val.b1; uint b1 = b - val.b2; uint j = (r1 * r1) + (g1 * g1) + (b1 * b1); if (j < l) { k = v; l = j; } } _15to8table[i] = (byte)k; } }
public static void GL_DrawAliasFrame(aliashdr_t paliashdr, int posenum) { lastposenum = posenum; trivertx_t[] verts = paliashdr.posedata; int vertsOffset = posenum * paliashdr.poseverts; int[] order = paliashdr.commands; int orderOffset = 0; while (true) { // get the vertex count and primitive type int count = order[orderOffset++]; if (count == 0) { break; // done } if (count < 0) { count = -count; GL.Begin(BeginMode.TriangleFan); } else { GL.Begin(BeginMode.TriangleStrip); } Union4b u1 = Union4b.Empty, u2 = Union4b.Empty; do { float[] v = { (float)verts[vertsOffset].v[0], verts[vertsOffset].v[1], verts[vertsOffset].v[2] }; // texture coordinates come from the draw list u1.i0 = order[orderOffset + 0]; u2.i0 = order[orderOffset + 1]; orderOffset += 2; GL.TexCoord2(u1.f0, u2.f0); // normals and vertexes come from the frame list float l = shadedots[verts[vertsOffset].lightnormalindex] * shadelight; GL.Color3(l, l, l); GL.Vertex3(v[0], v[1], v[2]); vertsOffset++; } while (--count > 0); GL.End(); } }
/// <summary> /// GL_DrawAliasFrame /// </summary> protected override void DrawAliasFrame(Single shadeLight, Single[] shadeDots, aliashdr_t paliashdr, Int32 posenum) { AliasDesc.LastPoseNumber = posenum; var verts = paliashdr.posedata; var vertsOffset = posenum * paliashdr.poseverts; var order = paliashdr.commands; var orderOffset = 0; while (true) { // get the vertex count and primitive type var count = order[orderOffset++]; if (count == 0) { break; // done } if (count < 0) { count = -count; GL.Begin(PrimitiveType.TriangleFan); } else { GL.Begin(PrimitiveType.TriangleStrip); } Union4b u1 = Union4b.Empty, u2 = Union4b.Empty; do { // texture coordinates come from the draw list u1.i0 = order[orderOffset + 0]; u2.i0 = order[orderOffset + 1]; orderOffset += 2; GL.TexCoord2(u1.f0, u2.f0); // normals and vertexes come from the frame list var l = shadeDots[verts[vertsOffset].lightnormalindex] * shadeLight; GL.Color3(l, l, l); GL.Vertex3(( Single )verts[vertsOffset].v[0], verts[vertsOffset].v[1], verts[vertsOffset].v[2]); vertsOffset++; } while (--count > 0); GL.End( ); } }
/// <summary> /// BuildTris /// Generate a list of trifans or strips for the model, which holds for all frames /// </summary> static void BuildTris() { int[] bestverts = new int[1024]; int[] besttris = new int[1024]; // Uze // All references to pheader from model.c changed to _AliasHdr (former paliashdr) // // build tristrips // stvert_t[] stverts = Mod.STVerts; dtriangle_t[] triangles = Mod.Triangles; _NumOrder = 0; _NumCommands = 0; Array.Clear(_Used, 0, _Used.Length); // memset (used, 0, sizeof(used)); int besttype = 0, len; for (int i = 0; i < _AliasHdr.numtris; i++) { // pick an unused triangle and start the trifan if (_Used[i] != 0) { continue; } int bestlen = 0; for (int type = 0; type < 2; type++) { for (int startv = 0; startv < 3; startv++) { if (type == 1) { len = StripLength(i, startv); } else { len = FanLength(i, startv); } if (len > bestlen) { besttype = type; bestlen = len; for (int j = 0; j < bestlen + 2; j++) { bestverts[j] = _StripVerts[j]; } for (int j = 0; j < bestlen; j++) { besttris[j] = _StripTris[j]; } } } } // mark the tris on the best strip as used for (int j = 0; j < bestlen; j++) { _Used[besttris[j]] = 1; } if (besttype == 1) { _Commands[_NumCommands++] = (bestlen + 2); } else { _Commands[_NumCommands++] = -(bestlen + 2); } Union4b uval = Union4b.Empty; for (int j = 0; j < bestlen + 2; j++) { // emit a vertex into the reorder buffer int k = bestverts[j]; _VertexOrder[_NumOrder++] = k; // emit s/t coords into the commands stream float s = stverts[k].s; float t = stverts[k].t; if (triangles[besttris[0]].facesfront == 0 && stverts[k].onseam != 0) { s += _AliasHdr.skinwidth / 2; // on back side } s = (s + 0.5f) / _AliasHdr.skinwidth; t = (t + 0.5f) / _AliasHdr.skinheight; uval.f0 = s; _Commands[_NumCommands++] = uval.i0; uval.f0 = t; _Commands[_NumCommands++] = uval.i0; } } _Commands[_NumCommands++] = 0; // end of list marker Con.DPrint("{0,3} tri {1,3} vert {2,3} cmd\n", _AliasHdr.numtris, _NumOrder, _NumCommands); _AllVerts += _NumOrder; _AllTris += _AliasHdr.numtris; }
public MessageReader(MessageWriter source) { this._Source = source; this._Val = Union4b.Empty; this._Tmp = new char[2048]; }
static msurface_t _WarpFace; // used by SubdivideSurface() /// <summary> /// R_InitSky /// called at level load /// A sky texture is 256*128, with the right side being a masked overlay /// </summary> public static void InitSky(texture_t mt) { byte[] src = mt.pixels; int offset = mt.offsets[0]; // make an average value for the back to avoid // a fringe on the top level const int size = 128 * 128; uint[] trans = new uint[size]; uint[] v8to24 = Vid.Table8to24; int r = 0; int g = 0; int b = 0; Union4b rgba = Union4b.Empty; for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { int p = src[offset + i * 256 + j + 128]; rgba.ui0 = v8to24[p]; trans[(i * 128) + j] = rgba.ui0; r += rgba.b0; g += rgba.b1; b += rgba.b2; } } rgba.b0 = (byte)(r / size); rgba.b1 = (byte)(g / size); rgba.b2 = (byte)(b / size); rgba.b3 = 0; uint transpix = rgba.ui0; if (_SolidSkyTexture == 0) { _SolidSkyTexture = Drawer.GenerateTextureNumber(); } Drawer.Bind(_SolidSkyTexture); GL.TexImage2D(TextureTarget.Texture2D, 0, Drawer.SolidFormat, 128, 128, 0, PixelFormat.Rgba, PixelType.UnsignedByte, trans); Drawer.SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear); for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { int p = src[offset + i * 256 + j]; if (p == 0) { trans[(i * 128) + j] = transpix; } else { trans[(i * 128) + j] = v8to24[p]; } } } if (_AlphaSkyTexture == 0) { _AlphaSkyTexture = Drawer.GenerateTextureNumber(); } Drawer.Bind(_AlphaSkyTexture); GL.TexImage2D(TextureTarget.Texture2D, 0, Drawer.AlphaFormat, 128, 128, 0, PixelFormat.Rgba, PixelType.UnsignedByte, trans); Drawer.SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear); }
// S_TransferStereo16 static void TransferStereo16(int endtime) { int snd_vol = (int)(_Volume.Value * 256); int lpaintedtime = _PaintedTime; byte[] buffer = _Controller.LockBuffer(); int srcOffset = 0; int destCount = 0;//uze int destOffset = 0; Union4b uval = Union4b.Empty; while (lpaintedtime < endtime) { // handle recirculating buffer issues int lpos = lpaintedtime & ((_shm.samples >> 1) - 1); //int destOffset = (lpos << 2); // in bytes!!! int snd_linear_count = (_shm.samples >> 1) - lpos; // in portable_samplepair_t's!!! if (lpaintedtime + snd_linear_count > endtime) { snd_linear_count = endtime - lpaintedtime; } // beginning of Snd_WriteLinearBlastStereo16 // write a linear blast of samples for (int i = 0; i < snd_linear_count; i++) { int val1 = (_PaintBuffer[srcOffset + i].left * snd_vol) >> 8; int val2 = (_PaintBuffer[srcOffset + i].right * snd_vol) >> 8; if (val1 > 0x7fff) { val1 = 0x7fff; } else if (val1 < C8000) { val1 = C8000; } if (val2 > 0x7fff) { val2 = 0x7fff; } else if (val2 < C8000) { val2 = C8000; } uval.s0 = (short)val1; uval.s1 = (short)val2; buffer[destOffset + 0] = uval.b0; buffer[destOffset + 1] = uval.b1; buffer[destOffset + 2] = uval.b2; buffer[destOffset + 3] = uval.b3; destOffset += 4; } // end of Snd_WriteLinearBlastStereo16 (); // Uze destCount += snd_linear_count * 4; srcOffset += snd_linear_count; // snd_p += snd_linear_count; lpaintedtime += (snd_linear_count); // >> 1); } _Controller.UnlockBuffer(destCount); }
// S_TransferPaintBuffer static void TransferPaintBuffer(int endtime) { if (_shm.samplebits == 16 && _shm.channels == 2) { TransferStereo16(endtime); return; } int count = (endtime - _PaintedTime) * _shm.channels; int out_mask = _shm.samples - 1; int out_idx = 0; //_PaintedTime * _shm.channels & out_mask; int step = 3 - _shm.channels; int snd_vol = (int)(_Volume.Value * 256); byte[] buffer = _Controller.LockBuffer(); Union4b uval = Union4b.Empty; int val, srcIndex = 0; bool useLeft = true; int destCount = (count * (_shm.samplebits >> 3)) & out_mask; if (_shm.samplebits == 16) { while (count-- > 0) { if (useLeft) { val = (_PaintBuffer[srcIndex].left * snd_vol) >> 8; } else { val = (_PaintBuffer[srcIndex].right * snd_vol) >> 8; } if (val > 0x7fff) { val = 0x7fff; } else if (val < C8000) // (short)0x8000) { val = C8000; // (short)0x8000; } uval.i0 = val; buffer[out_idx * 2] = uval.b0; buffer[out_idx * 2 + 1] = uval.b1; if (_shm.channels == 2 && useLeft) { useLeft = false; out_idx += 2; } else { useLeft = true; srcIndex++; out_idx = (out_idx + 1) & out_mask; } } } else if (_shm.samplebits == 8) { while (count-- > 0) { if (useLeft) { val = (_PaintBuffer[srcIndex].left * snd_vol) >> 8; } else { val = (_PaintBuffer[srcIndex].right * snd_vol) >> 8; } if (val > 0x7fff) { val = 0x7fff; } else if (val < C8000) //(short)0x8000) { val = C8000; //(short)0x8000; } buffer[out_idx] = (byte)((val >> 8) + 128); out_idx = (out_idx + 1) & out_mask; if (_shm.channels == 2 && useLeft) { useLeft = false; } else { useLeft = true; srcIndex++; } } } _Controller.UnlockBuffer(destCount); }
/* * ============= * GL_DrawAliasBlendedFrame * * [email protected]: model animation interpolation * ============= */ protected override void DrawAliasBlendedFrame(Single shadeLight, Single[] shadeDots, aliashdr_t paliashdr, Int32 posenum, Int32 posenum2, Single blend) { AliasDesc.LastPoseNumber0 = posenum; AliasDesc.LastPoseNumber = posenum2; var verts = paliashdr.posedata; var vert2 = verts; var vertsOffset = posenum * paliashdr.poseverts; var verts2Offset = posenum2 * paliashdr.poseverts; var order = paliashdr.commands; var orderOffset = 0; while (true) { if (orderOffset >= order.Length) { break; } // get the vertex count and primitive type var count = order[orderOffset]; orderOffset++; if (count == 0) { break; // done } if (count < 0) { count = -count; GL.Begin(PrimitiveType.TriangleFan); } else { GL.Begin(PrimitiveType.TriangleStrip); } Union4b u1 = Union4b.Empty, u2 = Union4b.Empty; do { if (orderOffset + 1 >= order.Length) { break; } // texture coordinates come from the draw list u1.i0 = order[orderOffset + 0]; u2.i0 = order[orderOffset + 1]; orderOffset += 2; GL.TexCoord2(u1.f0, u2.f0); // normals and vertexes come from the frame list // blend the light intensity from the two frames together Vector3 d = Vector3.Zero; if (vertsOffset >= verts.Length) { count = 0; break; } d.X = shadeDots[vert2[verts2Offset].lightnormalindex] - shadeDots[verts[vertsOffset].lightnormalindex]; //var l = shadeDots[verts[vertsOffset].lightnormalindex] * shadeLight; var l = shadeLight * (shadeDots[verts[vertsOffset].lightnormalindex] + (blend * d.X)); GL.Color3(l, l, l); var v = new Vector3(verts[vertsOffset].v[0], verts[vertsOffset].v[1], verts[vertsOffset].v[2]); var v2 = new Vector3(vert2[verts2Offset].v[0], vert2[verts2Offset].v[1], verts[verts2Offset].v[2]); d = v2 - v; GL.Vertex3(( Single )verts[vertsOffset].v[0] + (blend * d[0]), verts[vertsOffset].v[1] + (blend * d[1]), verts[vertsOffset].v[2] + (blend * d[2])); vertsOffset++; verts2Offset++; } while (--count > 0); GL.End( ); } }