Пример #1
0
        // This renders the sorted sector surfaces
        internal void RenderSectorSurfaces(RenderDevice graphics)
        {
            if (!resourcesunloaded)
            {
                ShaderName pass = Renderer.FullBrightness ? ShaderName.display2d_fullbright : ShaderName.display2d_normal;                 //mxd
                foreach (KeyValuePair <ImageData, List <SurfaceEntry> > imgsurfaces in surfaces)
                {
                    graphics.SetShader(pass);
                    graphics.SetTexture(imgsurfaces.Key.Texture);

                    // Go for all surfaces
                    VertexBuffer lastbuffer = null;
                    foreach (SurfaceEntry entry in imgsurfaces.Value)
                    {
                        graphics.SetUniform(UniformName.desaturation, entry.desaturation);

                        // Set the vertex buffer
                        SurfaceBufferSet set = sets[entry.numvertices];
                        if (set.buffers[entry.bufferindex] != lastbuffer)
                        {
                            lastbuffer = set.buffers[entry.bufferindex];
                            graphics.SetVertexBuffer(lastbuffer);
                        }

                        // Draw
                        graphics.Draw(PrimitiveType.TriangleList, entry.vertexoffset + (entry.numvertices * surfacevertexoffsetmul), entry.numvertices / 3);
                    }
                }
                graphics.SetUniform(UniformName.desaturation, 0.0f);
            }
        }
Пример #2
0
        // This renders the sorted sector surfaces
        internal void RenderSectorSurfaces(D3DDevice graphics)
        {
            if (!resourcesunloaded)
            {
                int pass = Renderer.FullBrightness ? 2 : 1;                 //mxd
                graphics.Shaders.Display2D.Begin();
                foreach (KeyValuePair <ImageData, List <SurfaceEntry> > imgsurfaces in surfaces)
                {
                    // Set texture
                    graphics.Shaders.Display2D.Texture1 = imgsurfaces.Key.Texture;

                    graphics.Shaders.Display2D.BeginPass(pass);

                    // Go for all surfaces
                    VertexBuffer lastbuffer = null;
                    foreach (SurfaceEntry entry in imgsurfaces.Value)
                    {
                        // Set the vertex buffer
                        SurfaceBufferSet set = sets[entry.numvertices];
                        if (set.buffers[entry.bufferindex] != lastbuffer)
                        {
                            lastbuffer = set.buffers[entry.bufferindex];
                            graphics.Device.SetStreamSource(0, lastbuffer, 0, FlatVertex.Stride);
                        }

                        // Draw
                        graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, entry.vertexoffset + (entry.numvertices * surfacevertexoffsetmul), entry.numvertices / 3);
                    }

                    graphics.Shaders.Display2D.EndPass();
                }
                graphics.Shaders.Display2D.End();
            }
        }
Пример #3
0
        // Updating sector surface geometry should go in this order;
        // - Triangulate sectors
        // - Call FreeSurfaces to remove entries that have changed number of vertices
        // - Call AllocateBuffers
        // - Call UpdateSurfaces to add/update entries
        // - Call UnlockBuffers

        // This (re)allocates the buffers based on an analysis of the map
        // The map must be updated (triangulated) before calling this
        public void AllocateBuffers()
        {
            // Make analysis of sector geometry
            Dictionary <int, int> sectorverts = new Dictionary <int, int>();

            foreach (Sector s in General.Map.Map.Sectors)
            {
                if (s.Triangles != null)
                {
                    // We count the number of sectors that have specific number of vertices
                    if (!sectorverts.ContainsKey(s.Triangles.Vertices.Count))
                    {
                        sectorverts.Add(s.Triangles.Vertices.Count, 0);
                    }
                    sectorverts[s.Triangles.Vertices.Count]++;
                }
            }

            // Now (re)allocate the needed buffers
            foreach (KeyValuePair <int, int> sv in sectorverts)
            {
                // Zero vertices can't be drawn
                if (sv.Key > 0)
                {
                    SurfaceBufferSet set = GetSet(sv.Key);

                    // Calculte how many free entries we need
                    int neededentries     = sv.Value;
                    int freeentriesneeded = neededentries - set.entries.Count;

                    // Allocate the space needed
                    EnsureFreeBufferSpace(set, freeentriesneeded);
                }
            }
        }
Пример #4
0
 // This frees the given surface entry
 public void FreeSurfaces(SurfaceEntry entry)
 {
     if ((entry.numvertices > 0) && (entry.bufferindex > -1))
     {
         SurfaceBufferSet set = sets[entry.numvertices];
         set.entries.Remove(entry);
         SurfaceEntry newentry = new SurfaceEntry(entry);
         set.holes.Add(newentry);
     }
     entry.numvertices = -1;
     entry.bufferindex = -1;
 }
Пример #5
0
 // This frees the given surface entry
 public void FreeSurfaces(SurfaceEntryCollection entries)
 {
     foreach (SurfaceEntry e in entries)
     {
         if ((e.numvertices > 0) && (e.bufferindex > -1))
         {
             SurfaceBufferSet set = sets[e.numvertices];
             set.entries.Remove(e);
             SurfaceEntry newentry = new SurfaceEntry(e);
             set.holes.Add(newentry);
         }
         e.numvertices = -1;
         e.bufferindex = -1;
     }
 }
Пример #6
0
        // Updating sector surface geometry should go in this order;
        // - Triangulate sectors
        // - Call FreeSurfaces to remove entries that have changed number of vertices
        // - Call AllocateBuffers
        // - Call UpdateSurfaces to add/update entries
        // - Call UnlockBuffers

        // This (re)allocates the buffers based on an analysis of the map
        // The map must be updated (triangulated) before calling this
        public void AllocateBuffers()
        {
            // Make analysis of sector geometry
            Dictionary <int, int> sectorverts = new Dictionary <int, int>();

            foreach (Sector s in General.Map.Map.Sectors)
            {
                if (s.Triangles != null)
                {
                    int numvertices = s.Triangles.Vertices.Count;
                    while (numvertices > 0)
                    {
                        // Determine for how many vertices in this entry
                        int vertsinentry = (numvertices > MAX_VERTICES_PER_SECTOR) ? MAX_VERTICES_PER_SECTOR : numvertices;

                        // We count the number of sectors that have specific number of vertices
                        if (!sectorverts.ContainsKey(vertsinentry))
                        {
                            sectorverts.Add(vertsinentry, 0);
                        }
                        sectorverts[vertsinentry]++;

                        numvertices -= vertsinentry;
                    }
                }
            }

            // Now (re)allocate the needed buffers
            foreach (KeyValuePair <int, int> sv in sectorverts)
            {
                // Zero vertices can't be drawn
                if (sv.Key > 0)
                {
                    SurfaceBufferSet set = GetSet(sv.Key);

                    // Calculte how many free entries we need
                    int neededentries     = sv.Value;
                    int freeentriesneeded = neededentries - set.entries.Count;

                    // Allocate the space needed
                    EnsureFreeBufferSpace(set, freeentriesneeded);
                }
            }
        }
Пример #7
0
        // This renders the sorted sector surfaces
        internal void RenderSectorSurfaces(D3DDevice graphics)
        {
            int counter = 0;

            if (!resourcesunloaded)
            {
                graphics.Shaders.Display2D.Begin();
                foreach (KeyValuePair <ImageData, List <SurfaceEntry> > imgsurfaces in surfaces)
                {
                    // Set texture
                    graphics.Shaders.Display2D.Texture1 = imgsurfaces.Key.Texture;
                    if (!graphics.Shaders.Enabled)
                    {
                        graphics.Device.SetTexture(0, imgsurfaces.Key.Texture);
                    }

                    graphics.Shaders.Display2D.BeginPass(1);

                    // Go for all surfaces
                    VertexBuffer lastbuffer = null;
                    foreach (SurfaceEntry entry in imgsurfaces.Value)
                    {
                        // Set the vertex buffer
                        SurfaceBufferSet set = sets[entry.numvertices];
                        if (set.buffers[entry.bufferindex] != lastbuffer)
                        {
                            lastbuffer = set.buffers[entry.bufferindex];
                            graphics.Device.SetStreamSource(0, lastbuffer, 0, FlatVertex.Stride);
                        }

                        // Draw
                        counter++;
                        graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, entry.vertexoffset + (entry.numvertices * surfacevertexoffsetmul), entry.numvertices / 3);
                    }

                    graphics.Shaders.Display2D.EndPass();
                }
                graphics.Shaders.Display2D.End();
            }
            Console.WriteLine("Calls: " + counter);
        }
Пример #8
0
        // This gets or creates a set for a specific number of vertices
        private SurfaceBufferSet GetSet(int numvertices)
        {
            SurfaceBufferSet set;

            // Get or create the set
            if (!sets.ContainsKey(numvertices))
            {
                set             = new SurfaceBufferSet();
                set.numvertices = numvertices;
                set.buffers     = new List <VertexBuffer>();
                set.buffersizes = new List <int>();
                set.entries     = new List <SurfaceEntry>();
                set.holes       = new List <SurfaceEntry>();
                sets.Add(numvertices, set);
            }
            else
            {
                set = sets[numvertices];
            }

            return(set);
        }
Пример #9
0
        // This adds or updates sector geometry into a buffer.
        // Modiies the list of SurfaceEntries with the new surface entry for the stored geometry.
        public void UpdateSurfaces(SurfaceEntryCollection entries, SurfaceUpdate update)
        {
            // Free entries when number of vertices has changed
            if ((entries.Count > 0) && (entries.totalvertices != update.numvertices))
            {
                FreeSurfaces(entries);
                entries.Clear();
            }

            if ((entries.Count == 0) && (update.numvertices > 0))
            {
                                #if DEBUG
                if ((update.floorvertices == null) || (update.ceilvertices == null))
                {
                    General.Fail("We need both floor and ceiling vertices when the number of vertices changes!");
                }
                                #endif

                // If we have no entries yet, we have to make them now
                int vertsremaining = update.numvertices;
                while (vertsremaining > 0)
                {
                    // Determine for how many vertices in this entry
                    int vertsinentry = (vertsremaining > MAX_VERTICES_PER_SECTOR) ? MAX_VERTICES_PER_SECTOR : vertsremaining;

                    // Lookup the set that holds entries for this number of vertices
                    SurfaceBufferSet set = GetSet(vertsinentry);

                    // Make sure we can get a new entry in this set
                    EnsureFreeBufferSpace(set, 1);

                    // Get a new entry in this set
                    SurfaceEntry e = set.holes[set.holes.Count - 1];
                    set.holes.RemoveAt(set.holes.Count - 1);
                    set.entries.Add(e);

                    // Fill the entry data
                    e.floorvertices = new FlatVertex[vertsinentry];
                    e.ceilvertices  = new FlatVertex[vertsinentry];
                    Array.Copy(update.floorvertices, update.numvertices - vertsremaining, e.floorvertices, 0, vertsinentry);
                    Array.Copy(update.ceilvertices, update.numvertices - vertsremaining, e.ceilvertices, 0, vertsinentry);
                    e.floortexture = update.floortexture;
                    e.ceiltexture  = update.ceiltexture;
                    e.desaturation = update.desaturation;

                    entries.Add(e);
                    vertsremaining -= vertsinentry;
                }
            }
            else
            {
                // We re-use the same entries, just copy over the updated data
                int vertsremaining = update.numvertices;
                foreach (SurfaceEntry e in entries)
                {
                    if (update.floorvertices != null)
                    {
                        Array.Copy(update.floorvertices, update.numvertices - vertsremaining, e.floorvertices, 0, e.numvertices);
                        e.floortexture = update.floortexture;
                    }

                    if (update.ceilvertices != null)
                    {
                        Array.Copy(update.ceilvertices, update.numvertices - vertsremaining, e.ceilvertices, 0, e.numvertices);
                        e.ceiltexture = update.ceiltexture;
                    }

                    e.desaturation = update.desaturation;

                    vertsremaining -= e.numvertices;
                }
            }

            entries.totalvertices = update.numvertices;

            // Time to update or create the buffers
            foreach (SurfaceEntry e in entries)
            {
                SurfaceBufferSet set = GetSet(e.numvertices);

                // Update bounding box
                e.UpdateBBox();

                if (!resourcesunloaded)
                {
                    VertexBuffer vb = set.buffers[e.bufferindex];
                    General.Map.Graphics.SetBufferSubdata(vb, e.vertexoffset, e.floorvertices);
                    General.Map.Graphics.SetBufferSubdata(vb, e.vertexoffset + e.floorvertices.Length, e.ceilvertices);
                }
            }
        }
Пример #10
0
        // This ensures there is enough space for a given number of free entries (also adds new bufers if needed)
        private void EnsureFreeBufferSpace(SurfaceBufferSet set, int freeentries)
        {
            VertexBuffer vb = null;

            // Check if we have to add entries
            int addentries = freeentries - set.holes.Count;

            // Begin resizing buffers starting with the last in this set
            int bufferindex = set.buffers.Count - 1;

            // Calculate the maximum number of entries we can put in a new buffer
            // Note that verticesperentry is the number of vertices multiplied by 2, because
            // we have to store both the floor and ceiling
            int verticesperentry    = set.numvertices * 2;
            int maxentriesperbuffer = MAX_VERTICES_PER_BUFFER / verticesperentry;

            // Make a new bufer when the last one is full
            if ((bufferindex > -1) && (set.buffersizes[bufferindex] >= (maxentriesperbuffer * verticesperentry)))
            {
                bufferindex = -1;
            }

            while (addentries > 0)
            {
                // Create a new buffer?
                if ((bufferindex == -1) || (bufferindex > (set.buffers.Count - 1)))
                {
                    // Determine the number of entries we will be making this buffer for
                    int bufferentries = (addentries > maxentriesperbuffer) ? maxentriesperbuffer : addentries;

                    // Calculate the number of vertices that will be
                    int buffernumvertices = bufferentries * verticesperentry;

                    if (!resourcesunloaded)
                    {
                        // Make the new buffer!
                        vb = new VertexBuffer();
                        General.Map.Graphics.SetBufferData(vb, buffernumvertices, VertexFormat.Flat);

                        // Add it.
                        set.buffers.Add(vb);
                    }
                    else
                    {
                        // We can't make a vertexbuffer right now
                        set.buffers.Add(null);
                    }

                    // Also add available entries as holes, because they are not used yet.
                    set.buffersizes.Add(buffernumvertices);
                    for (int i = 0; i < bufferentries; i++)
                    {
                        set.holes.Add(new SurfaceEntry(set.numvertices, set.buffers.Count - 1, i * verticesperentry));
                    }

                    // Done
                    addentries -= bufferentries;
                }
                // Reallocate a buffer
                else
                {
                    if ((set.buffers[bufferindex] != null) && !resourcesunloaded)
                    {
                        set.buffers[bufferindex].Dispose();
                    }

                    // Get the entries that are in this buffer only
                    List <SurfaceEntry> theseentries = new List <SurfaceEntry>();
                    foreach (SurfaceEntry e in set.entries)
                    {
                        if (e.bufferindex == bufferindex)
                        {
                            theseentries.Add(e);
                        }
                    }

                    // Determine the number of entries we will be making this buffer for
                    int bufferentries = ((theseentries.Count + addentries) > maxentriesperbuffer) ? maxentriesperbuffer : (theseentries.Count + addentries);

                    // Calculate the number of vertices that will be
                    int buffernumvertices = bufferentries * verticesperentry;

                    if (!resourcesunloaded)
                    {
                        // Make the new buffer and lock it
                        vb = new VertexBuffer();
                        General.Map.Graphics.SetBufferData(vb, buffernumvertices, VertexFormat.Flat);
                    }

                    // Start refilling the buffer with sector geometry
                    int vertexoffset = 0;
                    foreach (SurfaceEntry e in theseentries)
                    {
                        if (!resourcesunloaded)
                        {
                            // Fill buffer
                            General.Map.Graphics.SetBufferSubdata(vb, vertexoffset, e.floorvertices);
                            General.Map.Graphics.SetBufferSubdata(vb, vertexoffset + e.floorvertices.Length, e.ceilvertices);
                        }

                        // Set the new location in the buffer
                        e.vertexoffset = vertexoffset;

                        // Move on
                        vertexoffset += verticesperentry;
                    }

                    if (!resourcesunloaded)
                    {
                        set.buffers[bufferindex] = vb;
                    }
                    else
                    {
                        // No vertex buffer at this time, sorry
                        set.buffers[bufferindex] = null;
                    }

                    // Set the new buffer and add available entries as holes, because they are not used yet.
                    set.buffersizes[bufferindex] = buffernumvertices;
                    set.holes.Clear();
                    for (int i = 0; i < bufferentries - theseentries.Count; i++)
                    {
                        set.holes.Add(new SurfaceEntry(set.numvertices, bufferindex, i * verticesperentry + vertexoffset));
                    }

                    // Done
                    addentries -= bufferentries;
                }

                // Always continue in next (new) buffer
                bufferindex = set.buffers.Count;
            }
        }
Пример #11
0
        // This adds or updates sector geometry into a buffer.
        // Modiies the list of SurfaceEntries with the new surface entry for the stored geometry.
        public void UpdateSurfaces(SurfaceEntryCollection entries, SurfaceUpdate update)
        {
            // Free entries when number of vertices has changed
            if ((entries.Count > 0) && (entries.totalvertices != update.numvertices))
            {
                FreeSurfaces(entries);
                entries.Clear();
            }

            if ((entries.Count == 0) && (update.numvertices > 0))
            {
                                #if DEBUG
                if ((update.floorvertices == null) || (update.ceilvertices == null))
                {
                    General.Fail("We need both floor and ceiling vertices when the number of vertices changes!");
                }
                                #endif

                // If we have no entries yet, we have to make them now
                int vertsremaining = update.numvertices;
                while (vertsremaining > 0)
                {
                    // Determine for how many vertices in this entry
                    int vertsinentry = (vertsremaining > MAX_VERTICES_PER_SECTOR) ? MAX_VERTICES_PER_SECTOR : vertsremaining;

                    // Lookup the set that holds entries for this number of vertices
                    SurfaceBufferSet set = GetSet(vertsinentry);

                    // Make sure we can get a new entry in this set
                    EnsureFreeBufferSpace(set, 1);

                    // Get a new entry in this set
                    SurfaceEntry e = set.holes[set.holes.Count - 1];
                    set.holes.RemoveAt(set.holes.Count - 1);
                    set.entries.Add(e);

                    // Fill the entry data
                    e.floorvertices = new FlatVertex[vertsinentry];
                    e.ceilvertices  = new FlatVertex[vertsinentry];
                    Array.Copy(update.floorvertices, update.numvertices - vertsremaining, e.floorvertices, 0, vertsinentry);
                    Array.Copy(update.ceilvertices, update.numvertices - vertsremaining, e.ceilvertices, 0, vertsinentry);
                    e.floortexture = update.floortexture;
                    e.ceiltexture  = update.ceiltexture;

                    entries.Add(e);
                    vertsremaining -= vertsinentry;
                }
            }
            else
            {
                // We re-use the same entries, just copy over the updated data
                int vertsremaining = update.numvertices;
                foreach (SurfaceEntry e in entries)
                {
                    if (update.floorvertices != null)
                    {
                        Array.Copy(update.floorvertices, update.numvertices - vertsremaining, e.floorvertices, 0, e.numvertices);
                        e.floortexture = update.floortexture;
                    }

                    if (update.ceilvertices != null)
                    {
                        Array.Copy(update.ceilvertices, update.numvertices - vertsremaining, e.ceilvertices, 0, e.numvertices);
                        e.ceiltexture = update.ceiltexture;
                    }

                    vertsremaining -= e.numvertices;
                }
            }

            entries.totalvertices = update.numvertices;

            // Time to update or create the buffers
            foreach (SurfaceEntry e in entries)
            {
                SurfaceBufferSet set = GetSet(e.numvertices);

                // Update bounding box
                e.UpdateBBox();

                if (!resourcesunloaded)
                {
                    // Lock the buffer
                    DataStream   bstream;
                    VertexBuffer vb = set.buffers[e.bufferindex];
                    if (vb.Tag == null)
                    {
                        // Note: DirectX warns me that I am not using LockFlags.Discard or LockFlags.NoOverwrite here,
                        // but we don't have much of a choice since we want to update our data and not destroy other data
                        bstream = vb.Lock(0, set.buffersizes[e.bufferindex] * FlatVertex.Stride, LockFlags.None);
                        vb.Tag  = bstream;
                        lockedbuffers.Add(vb);
                    }
                    else
                    {
                        bstream = (DataStream)vb.Tag;
                    }

                    // Write the vertices to buffer
                    bstream.Seek(e.vertexoffset * FlatVertex.Stride, SeekOrigin.Begin);
                    bstream.WriteRange(e.floorvertices);
                    bstream.WriteRange(e.ceilvertices);
                }
            }
        }
Пример #12
0
        // This adds or updates sector geometry into a buffer.
        // Always specify the entry when a previous entry was already given for that sector!
        // Sector must set the floorvertices and ceilvertices members on the entry.
        // Returns the new surface entry for the stored geometry, floorvertices and ceilvertices will be preserved.
        public SurfaceEntry UpdateSurfaces(SurfaceEntry entry)
        {
            if (entry.floorvertices.Length != entry.ceilvertices.Length)
            {
                General.Fail("Floor vertices has different length from ceiling vertices!");
            }

            int numvertices = entry.floorvertices.Length;

            // Free entry when number of vertices have changed
            if ((entry.numvertices != numvertices) && (entry.numvertices != -1))
            {
                FreeSurfaces(entry);
            }

            // Check if we can render this at all
            if (numvertices > 0)
            {
                SurfaceBufferSet set = GetSet(numvertices);

                // Update bounding box
                entry.UpdateBBox();

                // Check if we need a new entry
                if (entry.numvertices == -1)
                {
                    EnsureFreeBufferSpace(set, 1);
                    SurfaceEntry nentry = set.holes[set.holes.Count - 1];
                    set.holes.RemoveAt(set.holes.Count - 1);
                    nentry.ceilvertices  = entry.ceilvertices;
                    nentry.floorvertices = entry.floorvertices;
                    nentry.floortexture  = entry.floortexture;
                    nentry.ceiltexture   = entry.ceiltexture;
                    nentry.bbox          = entry.bbox;
                    set.entries.Add(nentry);
                    entry = nentry;
                }

                if (!resourcesunloaded)
                {
                    // Lock the buffer
                    DataStream   bstream;
                    VertexBuffer vb = set.buffers[entry.bufferindex];
                    if (vb.Tag == null)
                    {
                        // Note: DirectX warns me that I am not using LockFlags.Discard or LockFlags.NoOverwrite here,
                        // but we don't care (we don't have much of a choice since we want to update our data)
                        bstream = vb.Lock(0, set.buffersizes[entry.bufferindex] * FlatVertex.Stride, LockFlags.None);
                        vb.Tag  = bstream;
                        lockedbuffers.Add(vb);
                    }
                    else
                    {
                        bstream = (DataStream)vb.Tag;
                    }

                    // Write the vertices to buffer
                    bstream.Seek(entry.vertexoffset * FlatVertex.Stride, SeekOrigin.Begin);
                    bstream.WriteRange(entry.floorvertices);
                    bstream.WriteRange(entry.ceilvertices);
                }
            }

            return(entry);
        }