Added automatic sidedefs compression when number of sidedefs exceeds the maximum sidedefs

This commit is contained in:
codeimp 2009-04-13 15:21:45 +00:00
parent 2907da9341
commit 396ba7f764
4 changed files with 119 additions and 4 deletions

View file

@ -62,6 +62,14 @@ namespace CodeImp.DoomBuilder
#region ================== Methods #region ================== Methods
public void Add(long value)
{
uint lo = (uint)((ulong)value & 0x00000000FFFFFFFF);
uint hi = (uint)(((ulong)value & 0xFFFFFFFF00000000) >> 32);
crc.Update(unchecked((int)lo));
crc.Update(unchecked((int)hi));
}
public void Add(int value) public void Add(int value)
{ {
crc.Update(value); crc.Update(value);

View file

@ -448,8 +448,11 @@ namespace CodeImp.DoomBuilder
if(map.Sidedefs.Count > io.MaxSidedefs) if(map.Sidedefs.Count > io.MaxSidedefs)
{ {
// Compress sidedefs // Compress sidedefs
oldstatus = General.MainWindow.Status;
General.MainWindow.DisplayStatus(StatusType.Busy, "Compressing sidedefs...");
outputset.CompressSidedefs(); outputset.CompressSidedefs();
General.MainWindow.DisplayStatus(oldstatus);
// Check if it still doesnt fit // Check if it still doesnt fit
if(map.Sidedefs.Count > io.MaxSidedefs) if(map.Sidedefs.Count > io.MaxSidedefs)
{ {

View file

@ -2435,9 +2435,98 @@ namespace CodeImp.DoomBuilder.Map
} }
// This performs sidedefs compression // This performs sidedefs compression
public void CompressSidedefs() // Note: Only use this for saving, because this messes up the expected data structure horribly.
internal void CompressSidedefs()
{ {
// TODO: Make this happen Dictionary<uint, List<Sidedef>> storedsides = new Dictionary<uint, List<Sidedef>>(sidedefs.Count);
int originalsidescount = sidedefs.Count;
double starttime = General.Clock.GetCurrentTime();
LinkedListNode<Sidedef> sn = sidedefs.First;
while(sn != null)
{
Sidedef stored = null;
LinkedListNode<Sidedef> nextsn = sn.Next;
// Check if checksum is stored
bool samesidedef = false;
uint checksum = sn.Value.GetChecksum();
bool checksumstored = storedsides.ContainsKey(checksum);
if(checksumstored)
{
List<Sidedef> othersides = storedsides[checksum];
foreach(Sidedef os in othersides)
{
// They must be in the same sector
if(sn.Value.Sector == os.Sector)
{
// Check if sidedefs are really the same
stored = os;
MemoryStream sidemem = new MemoryStream(1024);
SerializerStream sidedata = new SerializerStream(sidemem);
MemoryStream othermem = new MemoryStream(1024);
SerializerStream otherdata = new SerializerStream(othermem);
sn.Value.ReadWrite(sidedata);
os.ReadWrite(otherdata);
if(sidemem.Length == othermem.Length)
{
samesidedef = true;
sidemem.Seek(0, SeekOrigin.Begin);
othermem.Seek(0, SeekOrigin.Begin);
for(int i = 0; i < sidemem.Length; i++)
{
if(sidemem.ReadByte() != othermem.ReadByte())
{
samesidedef = false;
break;
}
}
}
if(samesidedef) break;
}
}
}
// Same sidedef?
if(samesidedef)
{
// Replace with stored sidedef
bool isfront = sn.Value.IsFront;
sn.Value.Line.DetachSidedef(sn.Value);
if(isfront)
sn.Value.Line.AttachFront(stored);
else
sn.Value.Line.AttachBack(stored);
// Remove the sidedef
sn.Value.ChangeSector(null);
sidedefs.Remove(sn);
}
else
{
// Store this new one
if(checksumstored)
{
storedsides[checksum].Add(sn.Value);
}
else
{
List<Sidedef> newlist = new List<Sidedef>(4);
newlist.Add(sn.Value);
storedsides.Add(checksum, newlist);
}
}
// Next
sn = nextsn;
}
// Output info
double endtime = General.Clock.GetCurrentTime();
double deltatimesec = (endtime - starttime) / 1000.0d;
float ratio = 100.0f - (((float)sidedefs.Count / (float)originalsidescount) * 100.0f);
General.WriteLogLine("Sidedefs compressed: " + sidedefs.Count + " remaining out of " + originalsidescount + " (" + ratio.ToString("########0.00") + "%) in " + deltatimesec.ToString("########0.00") + " seconds");
} }
// This converts flags and activations to UDMF fields // This converts flags and activations to UDMF fields

View file

@ -23,6 +23,7 @@ using System.Globalization;
using System.Text; using System.Text;
using CodeImp.DoomBuilder.IO; using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Types;
#endregion #endregion
@ -210,6 +211,19 @@ namespace CodeImp.DoomBuilder.Map
return map.GetIndexForSidedef(this); return map.GetIndexForSidedef(this);
} }
// This creates a checksum from the sidedef properties
// Used for faster sidedefs compression
public uint GetChecksum()
{
CRC crc = new CRC();
crc.Add(sector.FixedIndex);
crc.Add(offsetx);
crc.Add(offsety);
crc.Add(longtexnamehigh);
crc.Add(longtexnamelow);
crc.Add(longtexnamemid);
return (uint)(crc.Value & 0x00000000FFFFFFFF);
}
// This copies textures to another sidedef // This copies textures to another sidedef
// And possibly also the offsets // And possibly also the offsets
@ -392,7 +406,8 @@ namespace CodeImp.DoomBuilder.Map
sector = newsector; sector = newsector;
// Attach to sector // Attach to sector
sectorlistitem = sector.AttachSidedef(this); if(sector != null)
sectorlistitem = sector.AttachSidedef(this);
General.Map.IsChanged = true; General.Map.IsChanged = true;
} }