diff --git a/Builder.sln b/Builder.sln
index 012faef1..58a838a1 100644
--- a/Builder.sln
+++ b/Builder.sln
@@ -51,6 +51,7 @@ Global
{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Debug|Mixed Platforms.Build.0 = Debug|x86
{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Debug|x86.ActiveCfg = Debug|x86
+ {FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Debug|x86.Build.0 = Debug|x86
{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Release|Any CPU.ActiveCfg = Release|x86
{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Release|Mixed Platforms.ActiveCfg = Release|x86
{FBC0A503-9152-4BE2-9B5C-128FFD0B0D3F}.Release|Mixed Platforms.Build.0 = Release|x86
@@ -59,6 +60,7 @@ Global
{A5F93B70-18D9-4F3C-9B72-BC8B5B13998E}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{A5F93B70-18D9-4F3C-9B72-BC8B5B13998E}.Debug|Mixed Platforms.Build.0 = Debug|x86
{A5F93B70-18D9-4F3C-9B72-BC8B5B13998E}.Debug|x86.ActiveCfg = Debug|x86
+ {A5F93B70-18D9-4F3C-9B72-BC8B5B13998E}.Debug|x86.Build.0 = Debug|x86
{A5F93B70-18D9-4F3C-9B72-BC8B5B13998E}.Release|Any CPU.ActiveCfg = Release|x86
{A5F93B70-18D9-4F3C-9B72-BC8B5B13998E}.Release|Mixed Platforms.ActiveCfg = Release|x86
{A5F93B70-18D9-4F3C-9B72-BC8B5B13998E}.Release|Mixed Platforms.Build.0 = Release|x86
@@ -67,6 +69,7 @@ Global
{CBD14608-D467-458A-97B3-CA767CA85203}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{CBD14608-D467-458A-97B3-CA767CA85203}.Debug|Mixed Platforms.Build.0 = Debug|x86
{CBD14608-D467-458A-97B3-CA767CA85203}.Debug|x86.ActiveCfg = Debug|x86
+ {CBD14608-D467-458A-97B3-CA767CA85203}.Debug|x86.Build.0 = Debug|x86
{CBD14608-D467-458A-97B3-CA767CA85203}.Release|Any CPU.ActiveCfg = Release|x86
{CBD14608-D467-458A-97B3-CA767CA85203}.Release|Mixed Platforms.ActiveCfg = Release|x86
{CBD14608-D467-458A-97B3-CA767CA85203}.Release|Mixed Platforms.Build.0 = Release|x86
diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index 7e1c0f99..b288c7d6 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -703,7 +703,9 @@
+
+
diff --git a/Source/Core/Map/Sector.cs b/Source/Core/Map/Sector.cs
index 25c37049..b9c23c6f 100644
--- a/Source/Core/Map/Sector.cs
+++ b/Source/Core/Map/Sector.cs
@@ -73,7 +73,7 @@ namespace CodeImp.DoomBuilder.Map
private Triangulation triangles;
private FlatVertex[] flatvertices;
private ReadOnlyCollection labels;
- private SurfaceEntry surfaceentry;
+ private SurfaceEntryCollection surfaceentries;
#endregion
@@ -121,7 +121,7 @@ namespace CodeImp.DoomBuilder.Map
this.longceiltexname = MapSet.EmptyLongName;
this.updateneeded = true;
this.triangulationneeded = true;
- this.surfaceentry = new SurfaceEntry(-1, -1, -1);
+ this.surfaceentries = new SurfaceEntryCollection();
if(map == General.Map.Map)
General.Map.UndoRedo.RecAddSector(this);
@@ -156,7 +156,7 @@ namespace CodeImp.DoomBuilder.Map
map.AddSectorIndexHole(fixedindex);
// Free surface entry
- General.Map.CRenderer2D.Surfaces.FreeSurfaces(surfaceentry);
+ General.Map.CRenderer2D.Surfaces.FreeSurfaces(surfaceentries);
// Clean up
sidedefs = null;
@@ -273,8 +273,8 @@ namespace CodeImp.DoomBuilder.Map
labels = Array.AsReadOnly(Tools.FindLabelPositions(this).ToArray());
// Number of vertices changed?
- if((surfaceentry != null) && (triangles.Vertices.Count != surfaceentry.numvertices))
- General.Map.CRenderer2D.Surfaces.FreeSurfaces(surfaceentry);
+ if(triangles.Vertices.Count != surfaceentries.totalvertices)
+ General.Map.CRenderer2D.Surfaces.FreeSurfaces(surfaceentries);
}
}
}
@@ -302,25 +302,17 @@ namespace CodeImp.DoomBuilder.Map
// Create bounding box
bbox = CreateBBox();
- // Make a dummy entry if we don't have one yet
- if(surfaceentry == null) surfaceentry = new SurfaceEntry(-1, -1, -1);
-
- // Create floor vertices
- FlatVertex[] floorvertices = new FlatVertex[flatvertices.Length];
- flatvertices.CopyTo(floorvertices, 0);
- General.Plugins.OnSectorFloorSurfaceUpdate(this, ref floorvertices);
- surfaceentry.floorvertices = floorvertices;
- surfaceentry.floortexture = longfloortexname;
-
- // Create ceiling vertices
- FlatVertex[] ceilvertices = new FlatVertex[flatvertices.Length];
- flatvertices.CopyTo(ceilvertices, 0);
- General.Plugins.OnSectorCeilingSurfaceUpdate(this, ref ceilvertices);
- surfaceentry.ceilvertices = ceilvertices;
- surfaceentry.ceiltexture = longceiltexname;
+ // Make update info (this lets the plugin fill in texture coordinates and such)
+ SurfaceUpdate updateinfo = new SurfaceUpdate(flatvertices.Length, true, true);
+ flatvertices.CopyTo(updateinfo.floorvertices, 0);
+ General.Plugins.OnSectorFloorSurfaceUpdate(this, ref updateinfo.floorvertices);
+ flatvertices.CopyTo(updateinfo.ceilvertices, 0);
+ General.Plugins.OnSectorCeilingSurfaceUpdate(this, ref updateinfo.ceilvertices);
+ updateinfo.floortexture = longfloortexname;
+ updateinfo.ceiltexture = longceiltexname;
- // Update entry
- surfaceentry = General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentry);
+ // Update surfaces
+ General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentries, updateinfo);
// Updated
updateneeded = false;
@@ -333,16 +325,13 @@ namespace CodeImp.DoomBuilder.Map
if(flatvertices == null) return;
// Create floor vertices
- FlatVertex[] floorvertices = new FlatVertex[flatvertices.Length];
- flatvertices.CopyTo(floorvertices, 0);
- General.Plugins.OnSectorFloorSurfaceUpdate(this, ref floorvertices);
- surfaceentry.floorvertices = floorvertices;
- surfaceentry.floortexture = longfloortexname;
- if(surfaceentry.ceilvertices == null)
- surfaceentry.ceilvertices = floorvertices;
+ SurfaceUpdate updateinfo = new SurfaceUpdate(flatvertices.Length, true, false);
+ flatvertices.CopyTo(updateinfo.floorvertices, 0);
+ General.Plugins.OnSectorFloorSurfaceUpdate(this, ref updateinfo.floorvertices);
+ updateinfo.floortexture = longfloortexname;
// Update entry
- surfaceentry = General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentry);
+ General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentries, updateinfo);
General.Map.CRenderer2D.Surfaces.UnlockBuffers();
}
@@ -352,16 +341,13 @@ namespace CodeImp.DoomBuilder.Map
if(flatvertices == null) return;
// Create ceiling vertices
- FlatVertex[] ceilvertices = new FlatVertex[flatvertices.Length];
- flatvertices.CopyTo(ceilvertices, 0);
- General.Plugins.OnSectorCeilingSurfaceUpdate(this, ref ceilvertices);
- surfaceentry.ceilvertices = ceilvertices;
- surfaceentry.ceiltexture = longceiltexname;
- if(surfaceentry.floorvertices == null)
- surfaceentry.floorvertices = ceilvertices;
+ SurfaceUpdate updateinfo = new SurfaceUpdate(flatvertices.Length, false, true);
+ flatvertices.CopyTo(updateinfo.ceilvertices, 0);
+ General.Plugins.OnSectorCeilingSurfaceUpdate(this, ref updateinfo.ceilvertices);
+ updateinfo.ceiltexture = longceiltexname;
// Update entry
- surfaceentry = General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentry);
+ General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentries, updateinfo);
General.Map.CRenderer2D.Surfaces.UnlockBuffers();
}
diff --git a/Source/Core/Rendering/SurfaceEntryCollection.cs b/Source/Core/Rendering/SurfaceEntryCollection.cs
new file mode 100644
index 00000000..8eafd581
--- /dev/null
+++ b/Source/Core/Rendering/SurfaceEntryCollection.cs
@@ -0,0 +1,49 @@
+
+#region ================== Copyright (c) 2007 Pascal vd Heiden
+
+/*
+ * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
+ * This program is released under GNU General Public License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.Windows.Forms;
+using System.IO;
+using System.Reflection;
+using System.Drawing;
+using System.ComponentModel;
+using CodeImp.DoomBuilder.Map;
+using SlimDX.Direct3D9;
+using SlimDX;
+using CodeImp.DoomBuilder.Geometry;
+using System.Drawing.Imaging;
+using CodeImp.DoomBuilder.Data;
+using CodeImp.DoomBuilder.Editing;
+
+using Configuration = CodeImp.DoomBuilder.IO.Configuration;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Rendering
+{
+ // This contains information to update surface entries with. This may exceed the maximum number
+ // of sector vertices, the surface manager will take care of splitting it up in several SurfaceEntries.
+ internal class SurfaceEntryCollection : List
+ {
+ public int totalvertices = 0;
+ }
+}
diff --git a/Source/Core/Rendering/SurfaceManager.cs b/Source/Core/Rendering/SurfaceManager.cs
index ce927ca4..13f9c64c 100644
--- a/Source/Core/Rendering/SurfaceManager.cs
+++ b/Source/Core/Rendering/SurfaceManager.cs
@@ -48,6 +48,10 @@ namespace CodeImp.DoomBuilder.Rendering
// is a scary big number for a vertexbuffer.
private const int MAX_VERTICES_PER_BUFFER = 30000;
+ // When a sector exceeds this number of vertices, it should split up it's triangles
+ // This number must be a multiple of 3.
+ public const int MAX_VERTICES_PER_SECTOR = 6000;
+
#endregion
#region ================== Variables
@@ -220,10 +224,19 @@ namespace CodeImp.DoomBuilder.Rendering
{
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]++;
+ 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;
+ }
}
}
@@ -385,53 +398,95 @@ namespace CodeImp.DoomBuilder.Rendering
}
// 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)
+ // Modiies the list of SurfaceEntries with the new surface entry for the stored geometry.
+ public void UpdateSurfaces(SurfaceEntryCollection entries, SurfaceUpdate update)
{
- 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)
+ // Free entries when number of vertices has changed
+ if((entries.Count > 0) && (entries.totalvertices != update.numvertices))
{
- SurfaceBufferSet set = GetSet(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
- entry.UpdateBBox();
+ e.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];
+ 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 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);
+ // 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);
}
@@ -441,27 +496,28 @@ namespace CodeImp.DoomBuilder.Rendering
}
// Write the vertices to buffer
- bstream.Seek(entry.vertexoffset * FlatVertex.Stride, SeekOrigin.Begin);
- bstream.WriteRange(entry.floorvertices);
- bstream.WriteRange(entry.ceilvertices);
+ bstream.Seek(e.vertexoffset * FlatVertex.Stride, SeekOrigin.Begin);
+ bstream.WriteRange(e.floorvertices);
+ bstream.WriteRange(e.ceilvertices);
}
}
-
- return entry;
}
// This frees the given surface entry
- public void FreeSurfaces(SurfaceEntry entry)
+ public void FreeSurfaces(SurfaceEntryCollection entries)
{
- if((entry.numvertices > 0) && (entry.bufferindex > -1))
+ foreach(SurfaceEntry e in entries)
{
- SurfaceBufferSet set = sets[entry.numvertices];
- set.entries.Remove(entry);
- SurfaceEntry newentry = new SurfaceEntry(entry);
- set.holes.Add(newentry);
+ 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;
}
- entry.numvertices = -1;
- entry.bufferindex = -1;
}
// This unlocks the locked buffers
diff --git a/Source/Core/Rendering/SurfaceUpdate.cs b/Source/Core/Rendering/SurfaceUpdate.cs
new file mode 100644
index 00000000..96f8bf58
--- /dev/null
+++ b/Source/Core/Rendering/SurfaceUpdate.cs
@@ -0,0 +1,77 @@
+
+#region ================== Copyright (c) 2007 Pascal vd Heiden
+
+/*
+ * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
+ * This program is released under GNU General Public License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.Windows.Forms;
+using System.IO;
+using System.Reflection;
+using System.Drawing;
+using System.ComponentModel;
+using CodeImp.DoomBuilder.Map;
+using SlimDX.Direct3D9;
+using SlimDX;
+using CodeImp.DoomBuilder.Geometry;
+using System.Drawing.Imaging;
+using CodeImp.DoomBuilder.Data;
+using CodeImp.DoomBuilder.Editing;
+
+using Configuration = CodeImp.DoomBuilder.IO.Configuration;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Rendering
+{
+ // This contains information to update surface entries with. This may exceed the maximum number
+ // of sector vertices, the surface manager will take care of splitting it up in several SurfaceEntries.
+ internal class SurfaceUpdate
+ {
+ public int numvertices;
+
+ // Sector geometry (local copy used to quickly refill buffers)
+ // The sector must set these!
+ public FlatVertex[] floorvertices;
+ public FlatVertex[] ceilvertices;
+
+ // Sector images
+ // The sector must set these!
+ public long floortexture;
+ public long ceiltexture;
+
+ // Constructor
+ internal SurfaceUpdate(int numvertices, bool updatefloor, bool updateceiling)
+ {
+ this.numvertices = numvertices;
+ this.floortexture = 0;
+ this.ceiltexture = 0;
+
+ if(updatefloor)
+ this.floorvertices = new FlatVertex[numvertices];
+ else
+ this.floorvertices = null;
+
+ if(updateceiling)
+ this.ceilvertices = new FlatVertex[numvertices];
+ else
+ this.ceilvertices = null;
+ }
+ }
+}