// This frees the given surface entry
 public void FreeSurfaces(SurfaceEntryCollection entries)
 {
     foreach (SurfaceEntry e in entries)
     {
         if ((e.VerticesCount > 0) && (e.BufferIndex > -1))
         {
             SurfaceBufferSet set = sets[e.VerticesCount];
             set.entries.Remove(e);
             SurfaceEntry newentry = new SurfaceEntry(e);
             set.holes.Add(newentry);
         }
         e.VerticesCount = -1;
         e.BufferIndex   = -1;
     }
 }
        // 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.VerticesCount))
            {
                FreeSurfaces(entries);
                entries.Clear();
            }

            if ((entries.Count == 0) && (update.VerticesCount > 0))
            {
                                #if DEBUG
                if ((update.FloorVertices == null) || (update.CeilingVertices == 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.VerticesCount;
                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.CeilingVertices = new FlatVertex[vertsinentry];
                    Array.Copy(update.FloorVertices, update.VerticesCount - vertsremaining, e.FloorVertices, 0, vertsinentry);
                    Array.Copy(update.CeilingVertices, update.VerticesCount - vertsremaining, e.CeilingVertices, 0, vertsinentry);
                    e.FloorTileIndex   = update.FloorTileIndex;
                    e.CeilingTileIndex = update.CeilingTileIndex;

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

                    if (update.CeilingVertices != null)
                    {
                        Array.Copy(update.CeilingVertices, update.VerticesCount - vertsremaining, e.CeilingVertices, 0, e.VerticesCount);
                        e.CeilingTileIndex = update.CeilingTileIndex;
                    }

                    vertsremaining -= e.VerticesCount;
                }
            }

            entries.TotalVertices = update.VerticesCount;

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

                // 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.CeilingVertices);
                }
            }
        }