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