Beispiel #1
0
        /// <summary>
        /// R_RenderBrushPoly
        /// </summary>
        private static void RenderBrushPoly(msurface_t fa)
        {
            _BrushPolys++;

            if ((fa.flags & Surf.SURF_DRAWSKY) != 0)
            {   // warp texture, no lightmaps
                EmitBothSkyLayers(fa);
                return;
            }

            texture_t t = TextureAnimation(fa.texinfo.texture);

            Drawer.Bind(t.gl_texturenum);

            if ((fa.flags & Surf.SURF_DRAWTURB) != 0)
            {   // warp texture, no lightmaps
                EmitWaterPolys(fa);
                return;
            }

            if ((fa.flags & Surf.SURF_UNDERWATER) != 0)
            {
                DrawGLWaterPoly(fa.polys);
            }
            else
            {
                DrawGLPoly(fa.polys);
            }

            // add the poly to the proper lightmap chain

            fa.polys.chain = _LightMapPolys[fa.lightmaptexturenum];
            _LightMapPolys[fa.lightmaptexturenum] = fa.polys;

            // check for lightmap modification
            bool modified = false;

            for (int maps = 0; maps < bsp_file.MAXLIGHTMAPS && fa.styles[maps] != 255; maps++)
            {
                if (_LightStyleValue[fa.styles[maps]] != fa.cached_light[maps])
                {
                    modified = true;
                    break;
                }
            }

            if (modified ||
                fa.dlightframe == _FrameCount ||        // dynamic this frame
                fa.cached_dlight)                       // dynamic previously
            {
                if (_Dynamic.Value != 0)
                {
                    _LightMapModified[fa.lightmaptexturenum] = true;
                    UpdateRect(fa, ref _LightMapRectChange[fa.lightmaptexturenum]);
                    int offset = fa.lightmaptexturenum * _LightMapBytes * BLOCK_WIDTH * BLOCK_HEIGHT;
                    offset += fa.light_t * BLOCK_WIDTH * _LightMapBytes + fa.light_s * _LightMapBytes;
                    BuildLightMap(fa, new ByteArraySegment(_LightMaps, offset), BLOCK_WIDTH * _LightMapBytes);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// GL_SubdivideSurface
        /// Breaks a polygon up along axial 64 unit boundaries
        /// so that turbulent and sky warps can be done reasonably.
        /// </summary>
        public static void SubdivideSurface(msurface_t fa)
        {
            _WarpFace = fa;

            //
            // convert edges back to a normal polygon
            //
            int numverts = 0;

            Vector3[] verts     = new Vector3[fa.numedges + 1]; // + 1 for wrap case
            Model     loadmodel = Mod.Model;

            for (int i = 0; i < fa.numedges; i++)
            {
                int lindex = loadmodel.surfedges[fa.firstedge + i];

                if (lindex > 0)
                {
                    verts[numverts] = loadmodel.vertexes[loadmodel.edges[lindex].v[0]].position;
                }
                else
                {
                    verts[numverts] = loadmodel.vertexes[loadmodel.edges[-lindex].v[1]].position;
                }

                numverts++;
            }

            SubdividePolygon(numverts, verts);
        }
Beispiel #3
0
        private static void UpdateRect(msurface_t fa, ref glRect_t theRect)
        {
            if (fa.light_t < theRect.t)
            {
                if (theRect.h != 0)
                {
                    theRect.h += (byte)(theRect.t - fa.light_t);
                }
                theRect.t = (byte)fa.light_t;
            }
            if (fa.light_s < theRect.l)
            {
                if (theRect.w != 0)
                {
                    theRect.w += (byte)(theRect.l - fa.light_s);
                }
                theRect.l = (byte)fa.light_s;
            }
            int smax = (fa.extents[0] >> 4) + 1;
            int tmax = (fa.extents[1] >> 4) + 1;

            if ((theRect.w + theRect.l) < (fa.light_s + smax))
            {
                theRect.w = (byte)((fa.light_s - theRect.l) + smax);
            }
            if ((theRect.h + theRect.t) < (fa.light_t + tmax))
            {
                theRect.h = (byte)((fa.light_t - theRect.t) + tmax);
            }
        }
Beispiel #4
0
        /// <summary>
        /// R_DrawSkyChain
        /// </summary>
        private static void DrawSkyChain(msurface_t s)
        {
            DisableMultitexture();

            // used when gl_texsort is on
            Drawer.Bind(_SolidSkyTexture);
            _SpeedScale  = (float)Host.RealTime * 8;
            _SpeedScale -= (int)_SpeedScale & ~127;

            for (msurface_t fa = s; fa != null; fa = fa.texturechain)
            {
                EmitSkyPolys(fa);
            }

            GL.Enable(EnableCap.Blend);
            Drawer.Bind(_AlphaSkyTexture);
            _SpeedScale  = (float)Host.RealTime * 16;
            _SpeedScale -= (int)_SpeedScale & ~127;

            for (msurface_t fa = s; fa != null; fa = fa.texturechain)
            {
                EmitSkyPolys(fa);
            }

            GL.Disable(EnableCap.Blend);
        }
Beispiel #5
0
 /// <summary>
 /// R_MirrorChain
 /// </summary>
 private static void MirrorChain(msurface_t s)
 {
     if (_IsMirror)
     {
         return;
     }
     _IsMirror    = true;
     _MirrorPlane = s.plane;
 }
Beispiel #6
0
        static void DrawTextureChains()
        {
            if (_glTexSort.Value == 0)
            {
                DisableMultitexture();

                if (_SkyChain != null)
                {
                    DrawSkyChain(_SkyChain);
                    _SkyChain = null;
                }
                return;
            }
            Model world = Client.Cl.worldmodel;

            for (int i = 0; i < world.numtextures; i++)
            {
                texture_t t = world.textures[i];
                if (t == null)
                {
                    continue;
                }

                msurface_t s = t.texturechain;
                if (s == null)
                {
                    continue;
                }

                if (i == _SkyTextureNum)
                {
                    DrawSkyChain(s);
                }
                else if (i == _MirrorTextureNum && _MirrorAlpha.Value != 1.0f)
                {
                    MirrorChain(s);
                    continue;
                }
                else
                {
                    if ((s.flags & Surf.SURF_DRAWTURB) != 0 && _WaterAlpha.Value != 1.0f)
                    {
                        continue;   // draw translucent water later
                    }

                    for (; s != null; s = s.texturechain)
                    {
                        RenderBrushPoly(s);
                    }
                }

                t.texturechain = null;
            }
        }
Beispiel #7
0
        static msurface_t _WaterChain; // waterchain

        #endregion Fields

        #region Methods

        /// <summary>
        /// R_AddDynamicLights
        /// </summary>
        static void AddDynamicLights(msurface_t surf)
        {
            int smax = (surf.extents[0] >> 4) + 1;
            int tmax = (surf.extents[1] >> 4) + 1;
            mtexinfo_t tex = surf.texinfo;
            dlight_t[] dlights = Client.DLights;

            for (int lnum = 0; lnum < Client.MAX_DLIGHTS; lnum++)
            {
                if ((surf.dlightbits & (1 << lnum)) == 0)
                    continue;		// not lit by this light

                float rad = dlights[lnum].radius;
                float dist = Vector3.Dot(dlights[lnum].origin, surf.plane.normal) - surf.plane.dist;
                rad -= Math.Abs(dist);
                float minlight = dlights[lnum].minlight;
                if (rad < minlight)
                    continue;
                minlight = rad - minlight;

                Vector3 impact = dlights[lnum].origin - surf.plane.normal * dist;

                float local0 = Vector3.Dot(impact, tex.vecs[0].Xyz) + tex.vecs[0].W;
                float local1 = Vector3.Dot(impact, tex.vecs[1].Xyz) + tex.vecs[1].W;

                local0 -= surf.texturemins[0];
                local1 -= surf.texturemins[1];

                for (int t = 0; t < tmax; t++)
                {
                    int td = (int)(local1 - t * 16);
                    if (td < 0)
                        td = -td;
                    for (int s = 0; s < smax; s++)
                    {
                        int sd = (int)(local0 - s * 16);
                        if (sd < 0)
                            sd = -sd;
                        if (sd > td)
                            dist = sd + (td >> 1);
                        else
                            dist = td + (sd >> 1);
                        if (dist < minlight)
                            _BlockLights[t * smax + s] += (uint)((rad - dist) * 256);
                    }
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// GL_CreateSurfaceLightmap
        /// </summary>
        private static void CreateSurfaceLightmap(msurface_t surf)
        {
            if ((surf.flags & (Surf.SURF_DRAWSKY | Surf.SURF_DRAWTURB)) != 0)
            {
                return;
            }

            int smax = (surf.extents[0] >> 4) + 1;
            int tmax = (surf.extents[1] >> 4) + 1;

            surf.lightmaptexturenum = AllocBlock(smax, tmax, ref surf.light_s, ref surf.light_t);
            int offset = surf.lightmaptexturenum * _LightMapBytes * BLOCK_WIDTH * BLOCK_HEIGHT;

            offset += (surf.light_t * BLOCK_WIDTH + surf.light_s) * _LightMapBytes;
            BuildLightMap(surf, new ByteArraySegment(_LightMaps, offset), BLOCK_WIDTH * _LightMapBytes);
        }
Beispiel #9
0
        /// <summary>
        /// EmitBothSkyLayers
        /// Does a sky warp on the pre-fragmented glpoly_t chain
        /// This will be called for brushmodels, the world
        /// will have them chained together.
        /// </summary>
        private static void EmitBothSkyLayers(msurface_t fa)
        {
            DisableMultitexture();

            Drawer.Bind(_SolidSkyTexture);
            _SpeedScale  = (float)Host.RealTime * 8;
            _SpeedScale -= (int)_SpeedScale & ~127;

            EmitSkyPolys(fa);

            GL.Enable(EnableCap.Blend);
            Drawer.Bind(_AlphaSkyTexture);
            _SpeedScale  = (float)Host.RealTime * 16;
            _SpeedScale -= (int)_SpeedScale & ~127;

            EmitSkyPolys(fa);

            GL.Disable(EnableCap.Blend);
        }
Beispiel #10
0
        /// <summary>
        /// R_RenderDynamicLightmaps
        /// Multitexture
        /// </summary>
        private static void RenderDynamicLightmaps(msurface_t fa)
        {
            _BrushPolys++;

            if ((fa.flags & (Surf.SURF_DRAWSKY | Surf.SURF_DRAWTURB)) != 0)
            {
                return;
            }

            fa.polys.chain = _LightMapPolys[fa.lightmaptexturenum];
            _LightMapPolys[fa.lightmaptexturenum] = fa.polys;

            // check for lightmap modification
            bool flag = false;

            for (int maps = 0; maps < bsp_file.MAXLIGHTMAPS && fa.styles[maps] != 255; maps++)
            {
                if (_LightStyleValue[fa.styles[maps]] != fa.cached_light[maps])
                {
                    flag = true;
                    break;
                }
            }

            if (flag ||
                fa.dlightframe == _FrameCount || // dynamic this frame
                fa.cached_dlight)                // dynamic previously
            {
                if (_Dynamic.Value != 0)
                {
                    _LightMapModified[fa.lightmaptexturenum] = true;
                    UpdateRect(fa, ref _LightMapRectChange[fa.lightmaptexturenum]);
                    int offset = fa.lightmaptexturenum * _LightMapBytes * BLOCK_WIDTH * BLOCK_HEIGHT +
                                 fa.light_t * BLOCK_WIDTH * _LightMapBytes + fa.light_s * _LightMapBytes;
                    BuildLightMap(fa, new ByteArraySegment(_LightMaps, offset), BLOCK_WIDTH * _LightMapBytes);
                }
            }
        }
Beispiel #11
0
        /// <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();
            }
        }
Beispiel #12
0
        /// <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();
            }
        }
Beispiel #13
0
        /// <summary>
        /// R_MarkLights
        /// </summary>
        private static void MarkLights(dlight_t light, int bit, mnodebase_t node)
        {
            if (node.contents < 0)
            {
                return;
            }

            mnode_t  n          = (mnode_t)node;
            mplane_t splitplane = n.plane;
            float    dist       = Vector3.Dot(light.origin, splitplane.normal) - splitplane.dist;

            if (dist > light.radius)
            {
                MarkLights(light, bit, n.children[0]);
                return;
            }
            if (dist < -light.radius)
            {
                MarkLights(light, bit, n.children[1]);
                return;
            }

            // mark the polygons
            for (int i = 0; i < n.numsurfaces; i++)
            {
                msurface_t surf = client.cl.worldmodel.surfaces[n.firstsurface + i];
                if (surf.dlightframe != _DlightFrameCount)
                {
                    surf.dlightbits  = 0;
                    surf.dlightframe = _DlightFrameCount;
                }
                surf.dlightbits |= bit;
            }

            MarkLights(light, bit, n.children[0]);
            MarkLights(light, bit, n.children[1]);
        }
Beispiel #14
0
        /// <summary>
        /// R_RecursiveWorldNode
        /// </summary>
        private static void RecursiveWorldNode(mnodebase_t node)
        {
            if (node.contents == Contents.CONTENTS_SOLID)
            {
                return;         // solid
            }
            if (node.visframe != _VisFrameCount)
            {
                return;
            }
            if (CullBox(ref node.mins, ref node.maxs))
            {
                return;
            }

            int c;

            // if a leaf node, draw stuff
            if (node.contents < 0)
            {
                mleaf_t      pleaf = (mleaf_t)node;
                msurface_t[] marks = pleaf.marksurfaces;
                int          mark  = pleaf.firstmarksurface;
                c = pleaf.nummarksurfaces;

                if (c != 0)
                {
                    do
                    {
                        marks[mark].visframe = _FrameCount;
                        mark++;
                    } while(--c != 0);
                }

                // deal with model fragments in this leaf
                if (pleaf.efrags != null)
                {
                    StoreEfrags(pleaf.efrags);
                }

                return;
            }

            // node is just a decision point, so go down the apropriate sides

            mnode_t n = (mnode_t)node;

            // find which side of the node we are on
            mplane_t plane = n.plane;
            double   dot;

            switch (plane.type)
            {
            case Planes.PLANE_X:
                dot = _ModelOrg.X - plane.dist;
                break;

            case Planes.PLANE_Y:
                dot = _ModelOrg.Y - plane.dist;
                break;

            case Planes.PLANE_Z:
                dot = _ModelOrg.Z - plane.dist;
                break;

            default:
                dot = Vector3.Dot(_ModelOrg, plane.normal) - plane.dist;
                break;
            }

            int side = (dot >= 0 ? 0 : 1);

            // recurse down the children, front side first
            RecursiveWorldNode(n.children[side]);

            // draw stuff
            c = n.numsurfaces;

            if (c != 0)
            {
                msurface_t[] surf   = client.cl.worldmodel.surfaces;
                int          offset = n.firstsurface;

                if (dot < 0 - QDef.BACKFACE_EPSILON)
                {
                    side = Surf.SURF_PLANEBACK;
                }
                else if (dot > QDef.BACKFACE_EPSILON)
                {
                    side = 0;
                }

                for ( ; c != 0; c--, offset++)
                {
                    if (surf[offset].visframe != _FrameCount)
                    {
                        continue;
                    }

                    // don't backface underwater surfaces, because they warp
                    if ((surf[offset].flags & Surf.SURF_UNDERWATER) == 0 && ((dot < 0) ^ ((surf[offset].flags & Surf.SURF_PLANEBACK) != 0)))
                    {
                        continue;               // wrong side
                    }
                    // if sorting by texture, just store it out
                    if (_glTexSort.Value != 0)
                    {
                        if (!_IsMirror || surf[offset].texinfo.texture != client.cl.worldmodel.textures[_MirrorTextureNum])
                        {
                            surf[offset].texturechain = surf[offset].texinfo.texture.texturechain;
                            surf[offset].texinfo.texture.texturechain = surf[offset];
                        }
                    }
                    else if ((surf[offset].flags & Surf.SURF_DRAWSKY) != 0)
                    {
                        surf[offset].texturechain = _SkyChain;
                        _SkyChain = surf[offset];
                    }
                    else if ((surf[offset].flags & Surf.SURF_DRAWTURB) != 0)
                    {
                        surf[offset].texturechain = _WaterChain;
                        _WaterChain = surf[offset];
                    }
                    else
                    {
                        DrawSequentialPoly(surf[offset]);
                    }
                }
            }

            // recurse down the back side
            RecursiveWorldNode(n.children[side == 0 ? 1 : 0]);
        }
Beispiel #15
0
        /// <summary>
        /// Mod_LoadMarksurfaces
        /// </summary>
        static void LoadMarkSurfaces(ref lump_t l)
        {
            if ((l.filelen % sizeof(short)) != 0)
                Sys.Error("MOD_LoadBmodel: funny lump size in {0}", _LoadModel.name);

            int count = l.filelen / sizeof(short);
            msurface_t[] dest = new msurface_t[count];

            _LoadModel.marksurfaces = dest;
            _LoadModel.nummarksurfaces = count;

            for (int i = 0; i < count; i++)
            {
                int j = BitConverter.ToInt16(_ModBase, l.fileofs + i * sizeof(short));
                if (j >= _LoadModel.numsurfaces)
                    Sys.Error("Mod_ParseMarksurfaces: bad surface number");
                dest[i] = _LoadModel.surfaces[j];
            }
        }
Beispiel #16
0
        /// <summary>
        /// CalcSurfaceExtents
        /// Fills in s->texturemins[] and s->extents[]
        /// </summary>
        static void CalcSurfaceExtents(msurface_t s)
        {
            float[] mins = new float[] { 999999, 999999 };
            float[] maxs = new float[] { -99999, -99999 };

            mtexinfo_t tex = s.texinfo;
            mvertex_t[] v = _LoadModel.vertexes;

            for (int i = 0; i < s.numedges; i++)
            {
                int idx;
                int e = _LoadModel.surfedges[s.firstedge + i];
                if (e >= 0)
                    idx = _LoadModel.edges[e].v[0];
                else
                    idx = _LoadModel.edges[-e].v[1];

                for (int j = 0; j < 2; j++)
                {
                    float val = v[idx].position.X * tex.vecs[j].X +
                        v[idx].position.Y * tex.vecs[j].Y +
                        v[idx].position.Z * tex.vecs[j].Z +
                        tex.vecs[j].W;
                    if (val < mins[j])
                        mins[j] = val;
                    if (val > maxs[j])
                        maxs[j] = val;
                }
            }

            int[] bmins = new int[2];
            int[] bmaxs = new int[2];
            for (int i = 0; i < 2; i++)
            {
                bmins[i] = (int)Math.Floor(mins[i] / 16);
                bmaxs[i] = (int)Math.Ceiling(maxs[i] / 16);

                s.texturemins[i] = (short)(bmins[i] * 16);
                s.extents[i] = (short)((bmaxs[i] - bmins[i]) * 16);
                if ((tex.flags & BspFile.TEX_SPECIAL) == 0 && s.extents[i] > 512)
                    Sys.Error("Bad surface extents");
            }
        }
Beispiel #17
0
        /// <summary>
        /// GL_SubdivideSurface
        /// Breaks a polygon up along axial 64 unit boundaries
        /// so that turbulent and sky warps can be done reasonably.
        /// </summary>
        public static void SubdivideSurface(msurface_t fa)
        {
            _WarpFace = fa;

            //
            // convert edges back to a normal polygon
            //
            int numverts = 0;
            Vector3[] verts = new Vector3[fa.numedges + 1]; // + 1 for wrap case
            model_t loadmodel = Mod.Model;
            for (int i = 0; i < fa.numedges; i++)
            {
                int lindex = loadmodel.surfedges[fa.firstedge + i];

                if (lindex > 0)
                    verts[numverts] = loadmodel.vertexes[loadmodel.edges[lindex].v[0]].position;
                else
                    verts[numverts] = loadmodel.vertexes[loadmodel.edges[-lindex].v[1]].position;

                numverts++;
            }

            SubdividePolygon(numverts, verts);
        }
Beispiel #18
0
        /// <summary>
        /// R_DrawSequentialPoly
        /// Systems that have fast state and texture changes can
        /// just do everything as it passes with no need to sort
        /// </summary>
        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(BeginMode.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(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();

                    Drawer.Bind(_LightMapTextures + s.lightmaptexturenum);
                    GL.Enable(EnableCap.Blend);
                    GL.Begin(BeginMode.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(BeginMode.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);
            }
        }
Beispiel #19
0
        /// <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();
            }
        }
Beispiel #20
0
 private static void UpdateRect(msurface_t fa, ref glRect_t theRect)
 {
     if (fa.light_t < theRect.t)
     {
         if (theRect.h != 0)
             theRect.h += (byte)(theRect.t - fa.light_t);
         theRect.t = (byte)fa.light_t;
     }
     if (fa.light_s < theRect.l)
     {
         if (theRect.w != 0)
             theRect.w += (byte)(theRect.l - fa.light_s);
         theRect.l = (byte)fa.light_s;
     }
     int smax = (fa.extents[0] >> 4) + 1;
     int tmax = (fa.extents[1] >> 4) + 1;
     if ((theRect.w + theRect.l) < (fa.light_s + smax))
         theRect.w = (byte)((fa.light_s - theRect.l) + smax);
     if ((theRect.h + theRect.t) < (fa.light_t + tmax))
         theRect.h = (byte)((fa.light_t - theRect.t) + tmax);
 }
Beispiel #21
0
        /// <summary>
        /// R_RenderBrushPoly
        /// </summary>
        private static void RenderBrushPoly(msurface_t fa)
        {
            _BrushPolys++;

            if ((fa.flags & Surf. SURF_DRAWSKY) != 0)
            {	// warp texture, no lightmaps
                EmitBothSkyLayers(fa);
                return;
            }

            texture_t t = TextureAnimation(fa.texinfo.texture);
            Drawer.Bind(t.gl_texturenum);

            if ((fa.flags & Surf. SURF_DRAWTURB) != 0)
            {	// warp texture, no lightmaps
                EmitWaterPolys(fa);
                return;
            }

            if ((fa.flags & Surf.SURF_UNDERWATER) != 0)
                DrawGLWaterPoly(fa.polys);
            else
                DrawGLPoly(fa.polys);

            // add the poly to the proper lightmap chain

            fa.polys.chain = _LightMapPolys[fa.lightmaptexturenum];
            _LightMapPolys[fa.lightmaptexturenum] = fa.polys;

            // check for lightmap modification
            bool modified = false;
            for (int maps = 0; maps < BspFile.MAXLIGHTMAPS && fa.styles[maps] != 255; maps++)
                if (_LightStyleValue[fa.styles[maps]] != fa.cached_light[maps])
                {
                    modified = true;
                    break;
                }

            if (modified ||
                fa.dlightframe == _FrameCount ||	// dynamic this frame
                fa.cached_dlight)			// dynamic previously
            {
                if (_Dynamic.Value != 0)
                {
                    _LightMapModified[fa.lightmaptexturenum] = true;
                    UpdateRect(fa, ref _LightMapRectChange[fa.lightmaptexturenum]);
                    int offset = fa.lightmaptexturenum * _LightMapBytes * BLOCK_WIDTH * BLOCK_HEIGHT;
                    offset += fa.light_t * BLOCK_WIDTH * _LightMapBytes + fa.light_s * _LightMapBytes;
                    BuildLightMap(fa, new ByteArraySegment(_LightMaps, offset), BLOCK_WIDTH * _LightMapBytes);
                }
            }
        }
Beispiel #22
0
        /// <summary>
        /// R_DrawSkyChain
        /// </summary>
        private static void DrawSkyChain(msurface_t s)
        {
            DisableMultitexture();

            // used when gl_texsort is on
            Drawer.Bind(_SolidSkyTexture);
            _SpeedScale = (float)Host.RealTime * 8;
            _SpeedScale -= (int)_SpeedScale & ~127;

            for (msurface_t fa = s; fa != null; fa = fa.texturechain)
                EmitSkyPolys(fa);

            GL.Enable(EnableCap.Blend);
            Drawer.Bind(_AlphaSkyTexture);
            _SpeedScale = (float)Host.RealTime * 16;
            _SpeedScale -= (int)_SpeedScale & ~127;

            for (msurface_t fa = s; fa != null; fa = fa.texturechain)
                EmitSkyPolys(fa);

            GL.Disable(EnableCap.Blend);
        }
Beispiel #23
0
        /// <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);
            }
        }
Beispiel #24
0
        /// <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();
            }
        }
Beispiel #25
0
 /// <summary>
 /// R_MirrorChain
 /// </summary>
 private static void MirrorChain(msurface_t s)
 {
     if (_IsMirror)
         return;
     _IsMirror = true;
     _MirrorPlane = s.plane;
 }
Beispiel #26
0
        /// <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;
        }
Beispiel #27
0
        /// <summary>
        /// R_RecursiveWorldNode
        /// </summary>
        static void RecursiveWorldNode(mnodebase_t node)
        {
            if (node.contents == Contents.CONTENTS_SOLID)
                return;		// solid

            if (node.visframe != _VisFrameCount)
                return;
            if (CullBox(ref node.mins, ref node.maxs))
                return;

            int c;

            // if a leaf node, draw stuff
            if (node.contents < 0)
            {
                mleaf_t pleaf = (mleaf_t)node;
                msurface_t[] marks = pleaf.marksurfaces;
                int mark = pleaf.firstmarksurface;
                c = pleaf.nummarksurfaces;

                if (c != 0)
                {
                    do
                    {
                        marks[mark].visframe = _FrameCount;
                        mark++;
                    } while (--c != 0);
                }

                // deal with model fragments in this leaf
                if (pleaf.efrags != null)
                    StoreEfrags(pleaf.efrags);

                return;
            }

            // node is just a decision point, so go down the apropriate sides

            mnode_t n = (mnode_t)node;

            // find which side of the node we are on
            mplane_t plane = n.plane;
            double dot;

            switch (plane.type)
            {
                case Planes.PLANE_X:
                    dot = _ModelOrg.X - plane.dist;
                    break;

                case Planes.PLANE_Y:
                    dot = _ModelOrg.Y - plane.dist;
                    break;

                case Planes.PLANE_Z:
                    dot = _ModelOrg.Z - plane.dist;
                    break;

                default:
                    dot = Vector3.Dot(_ModelOrg, plane.normal) - plane.dist;
                    break;
            }

            int side = (dot >= 0 ? 0 : 1);

            // recurse down the children, front side first
            RecursiveWorldNode(n.children[side]);

            // draw stuff
            c = n.numsurfaces;

            if (c != 0)
            {
                msurface_t[] surf = Client.cl.worldmodel.surfaces;
                int offset = n.firstsurface;

                if (dot < 0 - QDef.BACKFACE_EPSILON)
                    side = Surf.SURF_PLANEBACK;
                else if (dot > QDef.BACKFACE_EPSILON)
                    side = 0;

                for (; c != 0; c--, offset++)
                {
                    if (surf[offset].visframe != _FrameCount)
                        continue;

                    // don't backface underwater surfaces, because they warp
                    if ((surf[offset].flags & Surf.SURF_UNDERWATER) == 0 && ((dot < 0) ^ ((surf[offset].flags & Surf.SURF_PLANEBACK) != 0)))
                        continue;		// wrong side

                    // if sorting by texture, just store it out
                    if (_glTexSort.Value != 0)
                    {
                        if (!_IsMirror || surf[offset].texinfo.texture != Client.cl.worldmodel.textures[_MirrorTextureNum])
                        {
                            surf[offset].texturechain = surf[offset].texinfo.texture.texturechain;
                            surf[offset].texinfo.texture.texturechain = surf[offset];
                        }
                    }
                    else if ((surf[offset].flags & Surf.SURF_DRAWSKY) != 0)
                    {
                        surf[offset].texturechain = _SkyChain;
                        _SkyChain = surf[offset];
                    }
                    else if ((surf[offset].flags & Surf.SURF_DRAWTURB) != 0)
                    {
                        surf[offset].texturechain = _WaterChain;
                        _WaterChain = surf[offset];
                    }
                    else
                        DrawSequentialPoly(surf[offset]);
                }
            }

            // recurse down the back side
            RecursiveWorldNode(n.children[side == 0 ? 1 : 0]);
        }
Beispiel #28
0
        /// <summary>
        /// EmitBothSkyLayers
        /// Does a sky warp on the pre-fragmented glpoly_t chain
        /// This will be called for brushmodels, the world
        /// will have them chained together.
        /// </summary>
        private static void EmitBothSkyLayers(msurface_t fa)
        {
            DisableMultitexture();

            Drawer.Bind(_SolidSkyTexture);
            _SpeedScale = (float)Host.RealTime * 8;
            _SpeedScale -= (int)_SpeedScale & ~127;

            EmitSkyPolys(fa);

            GL.Enable(EnableCap.Blend);
            Drawer.Bind(_AlphaSkyTexture);
            _SpeedScale = (float)Host.RealTime * 16;
            _SpeedScale -= (int)_SpeedScale & ~127;

            EmitSkyPolys(fa);

            GL.Disable(EnableCap.Blend);
        }
Beispiel #29
0
        /// <summary>
        /// R_RenderDynamicLightmaps
        /// Multitexture
        /// </summary>
        static void RenderDynamicLightmaps(msurface_t fa)
        {
            _BrushPolys++;

            if ((fa.flags & (Surf.SURF_DRAWSKY | Surf.SURF_DRAWTURB)) != 0)
                return;

            fa.polys.chain = _LightMapPolys[fa.lightmaptexturenum];
            _LightMapPolys[fa.lightmaptexturenum] = fa.polys;

            // check for lightmap modification
            bool flag = false;
            for (int maps = 0; maps < BspFile.MAXLIGHTMAPS && fa.styles[maps] != 255; maps++)
                if (_LightStyleValue[fa.styles[maps]] != fa.cached_light[maps])
                {
                    flag = true;
                    break;
                }

            if (flag ||
                fa.dlightframe == _FrameCount || // dynamic this frame
                fa.cached_dlight)	// dynamic previously
            {
                if (_Dynamic.Value != 0)
                {
                    _LightMapModified[fa.lightmaptexturenum] = true;
                    UpdateRect(fa, ref _LightMapRectChange[fa.lightmaptexturenum]);
                    int offset = fa.lightmaptexturenum * _LightMapBytes * BLOCK_WIDTH * BLOCK_HEIGHT +
                        fa.light_t * BLOCK_WIDTH * _LightMapBytes + fa.light_s * _LightMapBytes;
                    BuildLightMap(fa, new ByteArraySegment(_LightMaps, offset), BLOCK_WIDTH * _LightMapBytes);
                }
            }
        }
Beispiel #30
0
        static void DrawTextureChains()
        {
            if (_glTexSort.Value == 0)
            {
                DisableMultitexture();

                if (_SkyChain != null)
                {
                    DrawSkyChain(_SkyChain);
                    _SkyChain = null;
                }
                return;
            }
            model_t world = Client.cl.worldmodel;
            for (int i = 0; i < world.numtextures; i++)
            {
                texture_t t = world.textures[i];
                if (t == null)
                    continue;

                msurface_t s = t.texturechain;
                if (s == null)
                    continue;

                if (i == _SkyTextureNum)
                    DrawSkyChain(s);
                else if (i == _MirrorTextureNum && _MirrorAlpha.Value != 1.0f)
                {
                    MirrorChain(s);
                    continue;
                }
                else
                {
                    if ((s.flags & Surf.SURF_DRAWTURB) != 0 && _WaterAlpha.Value != 1.0f)
                        continue;	// draw translucent water later
                    for (; s != null; s = s.texturechain)
                        RenderBrushPoly(s);
                }

                t.texturechain = null;
            }
        }
Beispiel #31
0
        /// <summary>
        /// R_BuildLightMap
        /// Combine and scale multiple lightmaps into the 8.8 format in blocklights
        /// </summary>
        static void BuildLightMap(msurface_t surf, ByteArraySegment dest, int stride)
        {
            surf.cached_dlight = (surf.dlightframe == _FrameCount);

            int smax = (surf.extents[0] >> 4) + 1;
            int tmax = (surf.extents[1] >> 4) + 1;
            int size = smax * tmax;

            int srcOffset = surf.sampleofs;
            byte[] lightmap = surf.sample_base;// surf.samples;

            // set to full bright if no light data
            if (_FullBright.Value != 0 || Client.cl.worldmodel.lightdata == null)
            {
                for (int i = 0; i < size; i++)
                    _BlockLights[i] = 255 * 256;
            }
            else
            {
                // clear to no light
                for (int i = 0; i < size; i++)
                    _BlockLights[i] = 0;

                // add all the lightmaps
                if (lightmap != null)
                    for (int maps = 0; maps < BspFile.MAXLIGHTMAPS && surf.styles[maps] != 255; maps++)
                    {
                        int scale = _LightStyleValue[surf.styles[maps]];
                        surf.cached_light[maps] = scale;	// 8.8 fraction
                        for (int i = 0; i < size; i++)
                            _BlockLights[i] += (uint)(lightmap[srcOffset + i] * scale);
                        srcOffset += size; // lightmap += size;	// skip to next lightmap
                    }

                // add all the dynamic lights
                if (surf.dlightframe == _FrameCount)
                    AddDynamicLights(surf);
            }
            // bound, invert, and shift
            //store:
            int blOffset = 0;
            int destOffset = dest.StartIndex;
            byte[] data = dest.Data;
            switch (Drawer.LightMapFormat)
            {
                case PixelFormat.Rgba:
                    stride -= (smax << 2);
                    for (int i = 0; i < tmax; i++, destOffset += stride) // dest += stride
                    {
                        for (int j = 0; j < smax; j++)
                        {
                            uint t = _BlockLights[blOffset++];// *bl++;
                            t >>= 7;
                            if (t > 255)
                                t = 255;
                            data[destOffset + 3] = (byte)(255 - t); //dest[3] = 255 - t;
                            destOffset += 4;
                        }
                    }
                    break;

                case PixelFormat.Alpha:
                case PixelFormat.Luminance:
                    //case GL_INTENSITY:
                    for (int i = 0; i < tmax; i++, destOffset += stride)
                    {
                        for (int j = 0; j < smax; j++)
                        {
                            uint t = _BlockLights[blOffset++];// *bl++;
                            t >>= 7;
                            if (t > 255)
                                t = 255;
                            data[destOffset + j] = (byte)(255 - t); // dest[j] = 255 - t;
                        }
                    }
                    break;

                default:
                    Sys.Error("Bad lightmap format");
                    break;
            }
        }
Beispiel #32
0
        /// <summary>
        /// Mod_LoadFaces
        /// </summary>
        static void LoadFaces(ref lump_t l)
        {
            if ((l.filelen % dface_t.SizeInBytes) != 0)
                Sys.Error("MOD_LoadBmodel: funny lump size in {0}", _LoadModel.name);

            int count = l.filelen / dface_t.SizeInBytes;
            msurface_t[] dest = new msurface_t[count];

            for (int i = 0; i < dest.Length; i++)
                dest[i] = new msurface_t();

            _LoadModel.surfaces = dest;
            _LoadModel.numsurfaces = count;
            int offset = l.fileofs;
            for (int surfnum = 0; surfnum < count; surfnum++, offset += dface_t.SizeInBytes)
            {
                dface_t src = Sys.BytesToStructure<dface_t>(_ModBase, offset);

                dest[surfnum].firstedge = Common.LittleLong(src.firstedge);
                dest[surfnum].numedges = Common.LittleShort(src.numedges);
                dest[surfnum].flags = 0;

                int planenum = Common.LittleShort(src.planenum);
                int side = Common.LittleShort(src.side);
                if (side != 0)
                    dest[surfnum].flags |= Surf.SURF_PLANEBACK;

                dest[surfnum].plane = _LoadModel.planes[planenum];
                dest[surfnum].texinfo = _LoadModel.texinfo[Common.LittleShort(src.texinfo)];

                CalcSurfaceExtents(dest[surfnum]);

                // lighting info

                for (int i = 0; i < BspFile.MAXLIGHTMAPS; i++)
                    dest[surfnum].styles[i] = src.styles[i];

                int i2 = Common.LittleLong(src.lightofs);
                if (i2 == -1)
                    dest[surfnum].sample_base = null;
                else
                {
                    dest[surfnum].sample_base = _LoadModel.lightdata;
                    dest[surfnum].sampleofs = i2;
                }

                // set the drawing flags flag
                if (dest[surfnum].texinfo.texture.name != null)
                {
                    if (dest[surfnum].texinfo.texture.name.StartsWith("sky"))	// sky
                    {
                        dest[surfnum].flags |= (Surf.SURF_DRAWSKY | Surf.SURF_DRAWTILED);
                        Render.SubdivideSurface(dest[surfnum]);	// cut up polygon for warps
                        continue;
                    }

                    if (dest[surfnum].texinfo.texture.name.StartsWith("*"))		// turbulent
                    {
                        dest[surfnum].flags |= (Surf.SURF_DRAWTURB | Surf.SURF_DRAWTILED);
                        for (int i = 0; i < 2; i++)
                        {
                            dest[surfnum].extents[i] = 16384;
                            dest[surfnum].texturemins[i] = -8192;
                        }
                        Render.SubdivideSurface(dest[surfnum]);	// cut up polygon for warps
                        continue;
                    }
                }
            }
        }
Beispiel #33
0
        /// <summary>
        /// GL_CreateSurfaceLightmap
        /// </summary>
        static void CreateSurfaceLightmap(msurface_t surf)
        {
            if ((surf.flags & (Surf.SURF_DRAWSKY | Surf.SURF_DRAWTURB)) != 0)
                return;

            int smax = (surf.extents[0] >> 4) + 1;
            int tmax = (surf.extents[1] >> 4) + 1;

            surf.lightmaptexturenum = AllocBlock(smax, tmax, ref surf.light_s, ref surf.light_t);
            int offset = surf.lightmaptexturenum * _LightMapBytes * BLOCK_WIDTH * BLOCK_HEIGHT;
            offset += (surf.light_t * BLOCK_WIDTH + surf.light_s) * _LightMapBytes;
            BuildLightMap(surf, new ByteArraySegment(_LightMaps, offset), BLOCK_WIDTH * _LightMapBytes);
        }
Beispiel #34
0
        /// <summary>
        /// R_AddDynamicLights
        /// </summary>
        private static void AddDynamicLights(msurface_t surf)
        {
            int        smax = (surf.extents[0] >> 4) + 1;
            int        tmax = (surf.extents[1] >> 4) + 1;
            mtexinfo_t tex  = surf.texinfo;

            dlight_t[] dlights = client.DLights;

            for (int lnum = 0; lnum < client.MAX_DLIGHTS; lnum++)
            {
                if ((surf.dlightbits & (1 << lnum)) == 0)
                {
                    continue;           // not lit by this light
                }
                float rad  = dlights[lnum].radius;
                float dist = Vector3.Dot(dlights[lnum].origin, surf.plane.normal) - surf.plane.dist;
                rad -= Math.Abs(dist);
                float minlight = dlights[lnum].minlight;
                if (rad < minlight)
                {
                    continue;
                }
                minlight = rad - minlight;

                Vector3 impact = dlights[lnum].origin - surf.plane.normal * dist;

                float local0 = Vector3.Dot(impact, tex.vecs[0].Xyz) + tex.vecs[0].W;
                float local1 = Vector3.Dot(impact, tex.vecs[1].Xyz) + tex.vecs[1].W;

                local0 -= surf.texturemins[0];
                local1 -= surf.texturemins[1];

                for (int t = 0; t < tmax; t++)
                {
                    int td = (int)(local1 - t * 16);
                    if (td < 0)
                    {
                        td = -td;
                    }
                    for (int s = 0; s < smax; s++)
                    {
                        int sd = (int)(local0 - s * 16);
                        if (sd < 0)
                        {
                            sd = -sd;
                        }
                        if (sd > td)
                        {
                            dist = sd + (td >> 1);
                        }
                        else
                        {
                            dist = td + (sd >> 1);
                        }
                        if (dist < minlight)
                        {
                            _BlockLights[t * smax + s] += (uint)((rad - dist) * 256);
                        }
                    }
                }
            }
        }
Beispiel #35
0
        /// <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;
        }
Beispiel #36
0
        /// <summary>
        /// R_DrawWaterSurfaces
        /// </summary>
        private static void DrawWaterSurfaces()
        {
            if (_WaterAlpha.Value == 1.0f && _glTexSort.Value != 0)
            {
                return;
            }

            //
            // go back to the world matrix
            //
            GL.LoadMatrix(ref _WorldMatrix);

            if (_WaterAlpha.Value < 1.0)
            {
                GL.Enable(EnableCap.Blend);
                GL.Color4(1, 1, 1, _WaterAlpha.Value);
                GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate);
            }

            if (_glTexSort.Value == 0)
            {
                if (_WaterChain == null)
                {
                    return;
                }

                for (msurface_t s = _WaterChain; s != null; s = s.texturechain)
                {
                    Drawer.Bind(s.texinfo.texture.gl_texturenum);
                    EmitWaterPolys(s);
                }
                _WaterChain = null;
            }
            else
            {
                for (int i = 0; i < client.cl.worldmodel.numtextures; i++)
                {
                    texture_t t = client.cl.worldmodel.textures[i];
                    if (t == null)
                    {
                        continue;
                    }

                    msurface_t s = t.texturechain;
                    if (s == null)
                    {
                        continue;
                    }

                    if ((s.flags & Surf.SURF_DRAWTURB) == 0)
                    {
                        continue;
                    }

                    // set modulate mode explicitly

                    Drawer.Bind(t.gl_texturenum);

                    for ( ; s != null; s = s.texturechain)
                    {
                        EmitWaterPolys(s);
                    }

                    t.texturechain = null;
                }
            }

            if (_WaterAlpha.Value < 1.0)
            {
                GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace);
                GL.Color4(1f, 1, 1, 1);
                GL.Disable(EnableCap.Blend);
            }
        }
Beispiel #37
0
        /// <summary>
        /// R_DrawWaterSurfaces
        /// </summary>
        static void DrawWaterSurfaces()
        {
            if (_WaterAlpha.Value == 1.0f && _glTexSort.Value != 0)
                return;

            //
            // go back to the world matrix
            //
            GL.LoadMatrix(ref _WorldMatrix);

            if (_WaterAlpha.Value < 1.0)
            {
                GL.Enable(EnableCap.Blend);
                GL.Color4(1, 1, 1, _WaterAlpha.Value);
                GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate);
            }

            if (_glTexSort.Value == 0)
            {
                if (_WaterChain == null)
                    return;

                for (msurface_t s = _WaterChain; s != null; s = s.texturechain)
                {
                    Drawer.Bind(s.texinfo.texture.gl_texturenum);
                    EmitWaterPolys(s);
                }
                _WaterChain = null;
            }
            else
            {
                for (int i = 0; i < Client.cl.worldmodel.numtextures; i++)
                {
                    texture_t t = Client.cl.worldmodel.textures[i];
                    if (t == null)
                        continue;

                    msurface_t s = t.texturechain;
                    if (s == null)
                        continue;

                    if ((s.flags & Surf.SURF_DRAWTURB) == 0)
                        continue;

                    // set modulate mode explicitly

                    Drawer.Bind(t.gl_texturenum);

                    for (; s != null; s = s.texturechain)
                        EmitWaterPolys(s);

                    t.texturechain = null;
                }
            }

            if (_WaterAlpha.Value < 1.0)
            {
                GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace);
                GL.Color4(1f, 1, 1, 1);
                GL.Disable(EnableCap.Blend);
            }
        }
Beispiel #38
0
        /// <summary>
        /// R_BuildLightMap
        /// Combine and scale multiple lightmaps into the 8.8 format in blocklights
        /// </summary>
        private static void BuildLightMap(msurface_t surf, ByteArraySegment dest, int stride)
        {
            surf.cached_dlight = (surf.dlightframe == _FrameCount);

            int smax = (surf.extents[0] >> 4) + 1;
            int tmax = (surf.extents[1] >> 4) + 1;
            int size = smax * tmax;

            int srcOffset = surf.sampleofs;

            byte[] lightmap = surf.sample_base;// surf.samples;

            // set to full bright if no light data
            if (_FullBright.Value != 0 || client.cl.worldmodel.lightdata == null)
            {
                for (int i = 0; i < size; i++)
                {
                    _BlockLights[i] = 255 * 256;
                }
            }
            else
            {
                // clear to no light
                for (int i = 0; i < size; i++)
                {
                    _BlockLights[i] = 0;
                }

                // add all the lightmaps
                if (lightmap != null)
                {
                    for (int maps = 0; maps < bsp_file.MAXLIGHTMAPS && surf.styles[maps] != 255; maps++)
                    {
                        int scale = _LightStyleValue[surf.styles[maps]];
                        surf.cached_light[maps] = scale;        // 8.8 fraction
                        for (int i = 0; i < size; i++)
                        {
                            _BlockLights[i] += (uint)(lightmap[srcOffset + i] * scale);
                        }
                        srcOffset += size; // lightmap += size;	// skip to next lightmap
                    }
                }

                // add all the dynamic lights
                if (surf.dlightframe == _FrameCount)
                {
                    AddDynamicLights(surf);
                }
            }
            // bound, invert, and shift
            //store:
            int blOffset   = 0;
            int destOffset = dest.StartIndex;

            byte[] data = dest.Data;
            switch (Drawer.LightMapFormat)
            {
            case PixelFormat.Rgba:
                stride -= (smax << 2);
                for (int i = 0; i < tmax; i++, destOffset += stride)      // dest += stride
                {
                    for (int j = 0; j < smax; j++)
                    {
                        uint t = _BlockLights[blOffset++];    // *bl++;
                        t >>= 7;
                        if (t > 255)
                        {
                            t = 255;
                        }
                        data[destOffset + 3] = (byte)(255 - t);       //dest[3] = 255 - t;
                        destOffset          += 4;
                    }
                }
                break;

            case PixelFormat.Alpha:
            case PixelFormat.Luminance:
                //case GL_INTENSITY:
                for (int i = 0; i < tmax; i++, destOffset += stride)
                {
                    for (int j = 0; j < smax; j++)
                    {
                        uint t = _BlockLights[blOffset++];    // *bl++;
                        t >>= 7;
                        if (t > 255)
                        {
                            t = 255;
                        }
                        data[destOffset + j] = (byte)(255 - t);       // dest[j] = 255 - t;
                    }
                }
                break;

            default:
                sys.Error("Bad lightmap format");
                break;
            }
        }