コード例 #1
0
        /// <summary>
        /// CreateSurfaceLightmap
        /// ---------------------
        /// Creates a lightmap surface
        /// </summary>
        public void CreateSurfaceLightmap(CModel.SModel _SModel, ref CModel.SMSurface surf)
        {
            int smax;
            int tmax;
            int bytepos;

            if (
                (surf.flags & CModel.EMSurface.SURF_DRAWSKY) == CModel.EMSurface.SURF_DRAWSKY
                | (surf.flags & CModel.EMSurface.SURF_DRAWTURB) == CModel.EMSurface.SURF_DRAWTURB
                )
            {
                return;
            }

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

            if (LM_AllocBlock(smax, tmax, ref surf.light_s, ref surf.light_t) == false)
            {
                LM_UploadBlock(false);
                LM_InitBlock();

                if (LM_AllocBlock(smax, tmax, ref surf.light_s, ref surf.light_t) == false)
                {
                    CMain.Error(CMain.EErrorParm.ERR_FATAL, "Consecutive calls to LM_AllocBlock(" + smax + "," + tmax + ") failed\n");
                }
            }

            surf.lightmaptexturenum = CProgram.gQ2Game.gCMain.gCImage.current_lightmap_texture;

            bytepos = (surf.light_t * BLOCK_WIDTH + surf.light_s) * LIGHTMAP_BYTES;

            CProgram.gQ2Game.gCMain.gCLight.SetCacheState(ref surf);
            CProgram.gQ2Game.gCMain.gCLight.BuildLightMap(_SModel, ref surf, bytepos, ref lms.lightmap_buffer, BLOCK_WIDTH * LIGHTMAP_BYTES);
        }
コード例 #2
0
        /// <summary>
        /// SubdivideSurface
        /// ----------------
        /// Breaks a polygon up along axial 64 unit boundaries
        /// so that turbulent and sky warps can be done reasonably.
        /// </summary>
        public void SubdivideSurface(ref CModel.SMSurface surf)
        {
            float[] verts;
            int     numverts;
            List <CModel.SGLPoly> polys;

            if ((surf.flags & CModel.EMSurface.SURF_DRAWTURB) != CModel.EMSurface.SURF_DRAWTURB)
            {
                return;
            }

            verts    = new float[64 * 3];
            numverts = surf.polys[0].numverts;

            for (int i = 0; i < surf.polys[0].numverts; i++)
            {
                verts[(i * 3) + 0] = surf.polys[0].verts[i].vertex.Position.X;
                verts[(i * 3) + 1] = surf.polys[0].verts[i].vertex.Position.Y;
                verts[(i * 3) + 2] = surf.polys[0].verts[i].vertex.Position.Z;
            }

            surf.polys = null;
            polys      = new List <CModel.SGLPoly>();

            SubdividePolygon(surf, ref polys, numverts, verts);

            surf.polys = polys.ToArray();
            polys.Clear();
        }
コード例 #3
0
        public void SetCacheState(ref CModel.SMSurface surf)
        {
            surf.cached_light = new float[CQ2BSP.MAXLIGHTMAPS];

            for (int maps = 0; maps < CQ2BSP.MAXLIGHTMAPS && surf.styles[maps] != 255; maps++)
            {
                surf.cached_light[maps] = CClient.cl.RefDef.lightstyles[surf.styles[maps]].white;
            }
        }
コード例 #4
0
        /// <summary>
        /// BuildSurfaceIndex
        /// ------------------
        /// Convert the surface's vertex format from triangle fan to triangle list
        /// This is used to speed up surface warping by using an index buffer
        /// </summary>
        public int[] BuildSurfaceIndex(CModel.SMSurface surf)
        {
            List <int> ib = new List <int>();

            ib.Clear();

            for (int i = 0; i < surf.polys.Length; i++)
            {
                for (int j = 2; j < surf.polys[i].verts.Length; j++)
                {
                    ib.Add(surf.polys[i].verts[0].offset);
                    ib.Add(surf.polys[i].verts[j - 1].offset);
                    ib.Add(surf.polys[i].verts[j].offset);
                }
            }

            return(ib.ToArray());
        }
コード例 #5
0
        /// <summary>
        /// BuildSurfaceIndex
        /// ------------------
        /// Convert the surface's vertex format from triangle fan to triangle list
        /// This is used to speed up surface warping by using an index buffer
        /// </summary>
        public void BuildSurfaceIndex(ref CModel.SMSurface surf)
        {
            List <int> ib;

            //if ((surf.flags & CModel.EMSurface.SURF_DRAWTURB) != CModel.EMSurface.SURF_DRAWTURB)
            //    return;

            ib = new List <int>();
            ib.Clear();

            for (int i = 0; i < surf.polys.Length; i++)
            {
                for (int j = 2; j < surf.polys[i].verts.Length; j++)
                {
                    ib.Add(surf.polys[i].verts[0].offset);
                    ib.Add(surf.polys[i].verts[j - 1].offset);
                    ib.Add(surf.polys[i].verts[j].offset);
                }
            }

            surf.ibData = ib.ToArray();

            // setup the index buffer
            if (CProgram.gQ2Game.gGraphicsDevice.GraphicsProfile == GraphicsProfile.HiDef)
            {
                surf.ibSurface = new IndexBuffer(CProgram.gQ2Game.gGraphicsDevice, IndexElementSize.ThirtyTwoBits /*typeof(int)*/, surf.ibData.Length, BufferUsage.WriteOnly);
                surf.ibSurface.SetData(surf.ibData);
            }
            else
            {
                short[] ibData16 = new short[surf.ibData.Length];

                for (int i = 0; i < surf.ibData.Length; i++)
                {
                    ibData16[i] = (short)surf.ibData[i];
                }

                surf.ibSurface = new IndexBuffer(CProgram.gQ2Game.gGraphicsDevice, IndexElementSize.SixteenBits, ibData16.Length, BufferUsage.WriteOnly);
                surf.ibSurface.SetData(ibData16);
            }

            //surf.ibSurface.SetData(surf.ibData);
        }
コード例 #6
0
        /// <summary>
        /// R_BuildLightMap
        /// ---------------
        /// Combine and scale multiple lightmaps into the floating format in blocklights
        /// </summary>
        public void BuildLightMap(CModel.SModel _SModel, ref CModel.SMSurface surf, int dest_pos, ref byte[] dest, int stride)
        {
            int smax, tmax;
            int r, g, b, a, max;
            int size;
            int lightmap;

            float[] scale;
            int     nummaps;

            float[]            bl;
            CLocal.SLightStyle style;

            int   bl_pos;
            float modulate = 1.0f;

            if (
                (_SModel.texinfo[surf.texinfo].flags & CQ2BSP.ESurface.SURF_SKY) == CQ2BSP.ESurface.SURF_SKY
                | (_SModel.texinfo[surf.texinfo].flags & CQ2BSP.ESurface.SURF_TRANS33) == CQ2BSP.ESurface.SURF_TRANS33
                | (_SModel.texinfo[surf.texinfo].flags & CQ2BSP.ESurface.SURF_TRANS66) == CQ2BSP.ESurface.SURF_TRANS66
                | (_SModel.texinfo[surf.texinfo].flags & CQ2BSP.ESurface.SURF_WARP) == CQ2BSP.ESurface.SURF_WARP
                )
            {
                CMain.Error(CMain.EErrorParm.ERR_WARNING, "BuildLightMap called for non-lit surface");
            }

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

            if (size > ((sizeof(float) * s_blocklights.Length) >> 4))
            {
                CMain.Error(CMain.EErrorParm.ERR_WARNING, "Bad s_blocklights size");
            }

            // set to full bright if no light data
            if (surf.samples == -1)
            {
                for (int i = 0; i < size * 3; i++)
                {
                    s_blocklights[i] = 255;
                }

                for (int maps = 0; maps < CQ2BSP.MAXLIGHTMAPS && surf.styles[maps] != 255; maps++)
                {
                    style = CClient.cl.RefDef.lightstyles[surf.styles[maps]];
                }

                goto store;
            }

            // count the # of maps
            for (nummaps = 0; nummaps < CQ2BSP.MAXLIGHTMAPS && surf.styles[nummaps] != 255; nummaps++)
            {
                ;
            }

            lightmap = surf.samples;

            // add all the lightmaps
            if (nummaps == 1)
            {
                scale = new float[3];

                for (int maps = 0; maps < CQ2BSP.MAXLIGHTMAPS && surf.styles[maps] != 255; maps++)
                {
                    bl     = s_blocklights;
                    bl_pos = 0;

                    for (int i = 0; i < 3; i++)
                    {
                        scale[i] = modulate * CClient.cl.RefDef.lightstyles[surf.styles[maps]].rgb[i];
                    }

                    if (scale[0] == 1.0f && scale[1] == 1.0f && scale[2] == 1.0f)
                    {
                        for (int i = 0; i < size; i++, bl_pos += 3)
                        {
                            bl[bl_pos + 0] = _SModel.lightdata[lightmap + (i * 3) + 0];
                            bl[bl_pos + 1] = _SModel.lightdata[lightmap + (i * 3) + 1];
                            bl[bl_pos + 2] = _SModel.lightdata[lightmap + (i * 3) + 2];
                        }
                    }
                    else
                    {
                        for (int i = 0; i < size; i++, bl_pos += 3)
                        {
                            bl[bl_pos + 0] = _SModel.lightdata[lightmap + (i * 3) + 0] * scale[0];
                            bl[bl_pos + 1] = _SModel.lightdata[lightmap + (i * 3) + 1] * scale[1];
                            bl[bl_pos + 2] = _SModel.lightdata[lightmap + (i * 3) + 2] * scale[2];
                        }
                    }

                    // skip to next lightmap
                    lightmap += size * 3;
                }
            }
            else
            {
                scale = new float[3];

                for (int i = 0; i < (sizeof(float) * size * 3); i++)
                {
                    s_blocklights[i] = 0;
                }

                for (int maps = 0; maps < CQ2BSP.MAXLIGHTMAPS && surf.styles[maps] != 255; maps++)
                {
                    bl     = s_blocklights;
                    bl_pos = 0;

                    for (int i = 0; i < 3; i++)
                    {
                        scale[i] = modulate * CClient.cl.RefDef.lightstyles[surf.styles[maps]].rgb[i];
                    }

                    if (scale[0] == 1.0f && scale[1] == 1.0f && scale[2] == 1.0f)
                    {
                        for (int i = 0; i < size; i++, bl_pos += 3)
                        {
                            bl[bl_pos + 0] += _SModel.lightdata[lightmap + (i * 3) + 0];
                            bl[bl_pos + 1] += _SModel.lightdata[lightmap + (i * 3) + 1];
                            bl[bl_pos + 2] += _SModel.lightdata[lightmap + (i * 3) + 2];
                        }
                    }
                    else
                    {
                        for (int i = 0; i < size; i++, bl_pos += 3)
                        {
                            bl[bl_pos + 0] += _SModel.lightdata[lightmap + (i * 3) + 0] * scale[0];
                            bl[bl_pos + 1] += _SModel.lightdata[lightmap + (i * 3) + 1] * scale[1];
                            bl[bl_pos + 2] += _SModel.lightdata[lightmap + (i * 3) + 2] * scale[2];
                        }
                    }

                    // skip to next lightmap
                    lightmap += size * 3;
                }
            }

            // add all the dynamic lights
            //if (surf.dlightframe == CMain.r_framecount)
            //    R_AddDynamicLights(surf);

            // put into texture format
store:
            stride -= (smax << 2);
            bl      = s_blocklights;
            bl_pos  = 0;

            for (int i = 0; i < tmax; i++, dest_pos += stride)
            {
                for (int j = 0; j < smax; j++)
                {
                    r = Convert.ToInt32(bl[bl_pos + 0]);
                    g = Convert.ToInt32(bl[bl_pos + 1]);
                    b = Convert.ToInt32(bl[bl_pos + 2]);

                    // catch negative lights
                    if (r < 0)
                    {
                        r = 0;
                    }
                    if (g < 0)
                    {
                        g = 0;
                    }
                    if (b < 0)
                    {
                        b = 0;
                    }

                    // determine the brightest of the three color components
                    if (r > g)
                    {
                        max = r;
                    }
                    else
                    {
                        max = g;
                    }
                    if (b > max)
                    {
                        max = b;
                    }

                    // alpha is ONLY used for the mono lightmap case.  For this reason
                    // we set it to the brightest of the color components so that
                    // things don't get too dim.
                    a = max;

                    // rescale all the color components if the intensity of the greatest
                    // channel exceeds 1.0
                    if (max > 255)
                    {
                        float t = 255.0f / max;

                        r = (int)(r * t);
                        g = (int)(g * t);
                        b = (int)(b * t);
                        a = (int)(a * t);
                    }

                    dest[dest_pos + 0] = (byte)r;
                    dest[dest_pos + 1] = (byte)g;
                    dest[dest_pos + 2] = (byte)b;
                    dest[dest_pos + 3] = (byte)a;

                    bl_pos   += 3;
                    dest_pos += 4;
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// SubdividePolygon
        /// ----------------
        /// Breaks a polygon up along axial 64 unit boundaries
        /// so that turbulent and sky warps can be done reasonably.
        /// </summary>
        public void SubdividePolygon(CModel.SMSurface surf, ref List <CModel.SGLPoly> polys, int numverts, float[] verts)
        {
            float[] mins, maxs, dist;
            float   m;
            float   frac;
            int     i, j, k, v;

            float[] Front, Back;
            int     f, b;

            CModel.SGLPoly poly;
            Vector3        total;
            float          total_s;
            float          total_t;

            mins = new float[3];
            maxs = new float[3];
            dist = new float[64];

            Front = new float[64 * 3];
            Back  = new float[64 * 3];

            if (numverts > 60)
            {
                CMain.Error(CMain.EErrorParm.ERR_WARNING, "(error) numverts = " + numverts);
            }

            // Bind mins and maxs
            BoundPoly(numverts, verts, ref mins, ref maxs);

            for (i = 0; i < 3; i++)
            {
                m = (mins[i] + maxs[i]) * 0.5f;
                m = SUBDIVIDE_SIZE * (float)Math.Floor(m / (float)SUBDIVIDE_SIZE + 0.5f);

                if (maxs[i] - m < 8)
                {
                    continue;
                }
                if (m - mins[i] < 8)
                {
                    continue;
                }

                // cut it
                v = i;
                for (j = 0; j < numverts; j++, v += 3)
                {
                    dist[j] = verts[v] - m;
                }

                // wrap cases
                dist[j]      = dist[0];
                v           -= i;
                verts[v + 0] = verts[0 + 0];
                verts[v + 1] = verts[0 + 1];
                verts[v + 2] = verts[0 + 2];

                f = 0;
                b = 0;
                v = 0;
                for (j = 0; j < numverts; j++, v += 3)
                {
                    if (dist[j] >= 0)
                    {
                        Front[(f * 3) + 0] = verts[v + 0];
                        Front[(f * 3) + 1] = verts[v + 1];
                        Front[(f * 3) + 2] = verts[v + 2];
                        f++;
                    }
                    if (dist[j] <= 0)
                    {
                        Back[(b * 3) + 0] = verts[v + 0];
                        Back[(b * 3) + 1] = verts[v + 1];
                        Back[(b * 3) + 2] = verts[v + 2];
                        b++;
                    }

                    if (dist[j] == 0 || dist[j + 1] == 0)
                    {
                        continue;
                    }

                    if ((dist[j] > 0) != (dist[j + 1] > 0))
                    {
                        // clip point
                        frac = dist[j] / (dist[j] - dist[j + 1]);

                        for (k = 0; k < 3; k++)
                        {
                            Front[(f * 3) + k] = Back[(b * 3) + k] = verts[v + k] + frac * (verts[3 + v + k] - verts[v + k]);
                        }
                        f++;
                        b++;
                    }
                }

                SubdividePolygon(surf, ref polys, f, Front);
                SubdividePolygon(surf, ref polys, b, Back);

                return;
            }


            // add a point in the center to help keep warp valid
            poly.next     = 0;
            poly.chain    = 0;
            poly.numverts = numverts + 2;
            poly.verts    = new CModel.SPolyVerts[poly.numverts];

            total   = Vector3.Zero;
            total_s = 0.0f;
            total_t = 0.0f;

            v = 0;
            for (i = 0; i < numverts; i++, v += 3)
            {
                float   s;
                float   t;
                Vector3 vec0;
                Vector3 vec1;

                poly.verts[i + 1].vertex.Position.X = verts[v + 0];
                poly.verts[i + 1].vertex.Position.Y = verts[v + 1];
                poly.verts[i + 1].vertex.Position.Z = verts[v + 2];

                vec0.X = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[0].X;
                vec0.Y = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[0].Y;
                vec0.Z = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[0].Z;
                vec1.X = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[1].X;
                vec1.Y = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[1].Y;
                vec1.Z = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[1].Z;

                s = Vector3.Dot(poly.verts[i + 1].vertex.Position, vec0);
                t = Vector3.Dot(poly.verts[i + 1].vertex.Position, vec1);

                total_s += s;
                total_t += t;
                total.X += verts[v + 0];
                total.Y += verts[v + 1];
                total.Z += verts[v + 2];

                poly.verts[i + 1].vertex.TextureCoordinate.X = s;
                poly.verts[i + 1].vertex.TextureCoordinate.Y = t;

                poly.verts[i + 1].vertex.LightmapCoordinate.X = 0.0f;
                poly.verts[i + 1].vertex.LightmapCoordinate.Y = 0.0f;

                poly.verts[i + 1].vertex.Normal.X = 0.0f;
                poly.verts[i + 1].vertex.Normal.Y = 0.0f;
                poly.verts[i + 1].vertex.Normal.Z = 0.0f;
            }

            CShared.VectorScale(total, (1.0f / numverts), ref poly.verts[0].vertex.Position);
            poly.verts[0].vertex.TextureCoordinate.X = total_s / numverts;
            poly.verts[0].vertex.TextureCoordinate.Y = total_t / numverts;

            // copy first vertex to last
            poly.verts[i + 1] = poly.verts[1];

            // insert centered point at first index
            polys.Insert(0, poly);
        }
コード例 #8
0
 public void BuildPolygonFromSurface(ref CModel.SMSurface surf)
 {
     // most parts of the BuildWorld() function in CMain could be done here
     // if so, the polygons needs to be subdivided first most likely
     // see the function calling this function
 }