Changed: optimized generated voxel mesh size. Pro: they occupy ~50% less memory. Con: voxel loading takes ~30% more time.

Changed, Browse Textures window: several textures with the same name were displayed in "All" texture set when overriding WAD textures by Folder/PK3 textures.
This commit is contained in:
MaxED 2016-07-18 23:41:02 +00:00
parent 3f93525ebc
commit a8c23266bb
3 changed files with 118 additions and 65 deletions

View file

@ -16,6 +16,7 @@
#region ================== Namespaces
using System;
using System.Collections.Generic;
using CodeImp.DoomBuilder.Data;
@ -27,22 +28,22 @@ namespace CodeImp.DoomBuilder.Config
{
#region ================== Constants
public const string NAME = "All";
private const string NAME = "All";
#endregion
#region ================== Variables
// Matching textures and flats
private List<ImageData> textures;
private List<ImageData> flats;
private Dictionary<string, ImageData> textures;
private Dictionary<string, ImageData> flats;
#endregion
#region ================== Properties
public ICollection<ImageData> Textures { get { return textures; } }
public ICollection<ImageData> Flats { get { return flats; } }
public ICollection<ImageData> Textures { get { return textures.Values; } }
public ICollection<ImageData> Flats { get { return flats.Values; } }
#endregion
@ -52,8 +53,8 @@ namespace CodeImp.DoomBuilder.Config
public AllTextureSet()
{
this.name = NAME;
this.textures = new List<ImageData>();
this.flats = new List<ImageData>();
this.textures = new Dictionary<string, ImageData>(StringComparer.Ordinal);
this.flats = new Dictionary<string, ImageData>(StringComparer.Ordinal);
}
#endregion
@ -62,12 +63,15 @@ namespace CodeImp.DoomBuilder.Config
internal void AddTexture(ImageData image)
{
textures.Add(image);
//mxd. Use short name when adding a texture with "classic" name to override same-named textures
// with textures loaded from directory/pk3 containters
textures[image.DisplayName.Length > 8 ? image.Name : image.ShortName] = image;
}
internal void AddFlat(ImageData image)
{
flats.Add(image);
//mxd. Same with flats
flats[image.DisplayName.Length > 8 ? image.Name : image.ShortName] = image;
}
#endregion

View file

@ -308,6 +308,8 @@ namespace CodeImp.DoomBuilder.Data
}
}
}
lumpdata.Dispose();
}
else
{

View file

@ -634,7 +634,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
{
PixelColor[] palette = new PixelColor[256];
List<WorldVertex> verts = new List<WorldVertex>();
List<int> indices = new List<int>();
Dictionary<long, int> verthashes = new Dictionary<long, int>();
int xsize, ysize, zsize;
int facescount = 0;
Vector3D pivot;
using(BinaryReader reader = new BinaryReader(stream, Encoding.ASCII))
@ -724,7 +727,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
if((flags & 16) != 0)
{
AddFace(verts, new Vector3D(x, y, ztop), new Vector3D(x + 1, y, ztop), new Vector3D(x, y + 1, ztop), new Vector3D(x + 1, y + 1, ztop), pivot, colorIndices[0]);
AddFace(verts, indices, verthashes, new Vector3D(x, y, ztop), new Vector3D(x + 1, y, ztop), new Vector3D(x, y + 1, ztop), new Vector3D(x + 1, y + 1, ztop), pivot, colorIndices[0]);
facescount += 2;
}
int z = ztop;
@ -736,19 +740,23 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
if((flags & 1) != 0)
{
AddFace(verts, new Vector3D(x, y, z), new Vector3D(x, y + 1, z), new Vector3D(x, y, z + c), new Vector3D(x, y + 1, z + c), pivot, colorIndices[cstart]);
AddFace(verts, indices, verthashes, new Vector3D(x, y, z), new Vector3D(x, y + 1, z), new Vector3D(x, y, z + c), new Vector3D(x, y + 1, z + c), pivot, colorIndices[cstart]);
facescount += 2;
}
if((flags & 2) != 0)
{
AddFace(verts, new Vector3D(x + 1, y + 1, z), new Vector3D(x + 1, y, z), new Vector3D(x + 1, y + 1, z + c), new Vector3D(x + 1, y, z + c), pivot, colorIndices[cstart]);
AddFace(verts, indices, verthashes, new Vector3D(x + 1, y + 1, z), new Vector3D(x + 1, y, z), new Vector3D(x + 1, y + 1, z + c), new Vector3D(x + 1, y, z + c), pivot, colorIndices[cstart]);
facescount += 2;
}
if((flags & 4) != 0)
{
AddFace(verts, new Vector3D(x + 1, y, z), new Vector3D(x, y, z), new Vector3D(x + 1, y, z + c), new Vector3D(x, y, z + c), pivot, colorIndices[cstart]);
AddFace(verts, indices, verthashes, new Vector3D(x + 1, y, z), new Vector3D(x, y, z), new Vector3D(x + 1, y, z + c), new Vector3D(x, y, z + c), pivot, colorIndices[cstart]);
facescount += 2;
}
if((flags & 8) != 0)
{
AddFace(verts, new Vector3D(x, y + 1, z), new Vector3D(x + 1, y + 1, z), new Vector3D(x, y + 1, z + c), new Vector3D(x + 1, y + 1, z + c), pivot, colorIndices[cstart]);
AddFace(verts, indices, verthashes, new Vector3D(x, y + 1, z), new Vector3D(x + 1, y + 1, z), new Vector3D(x, y + 1, z + c), new Vector3D(x + 1, y + 1, z + c), pivot, colorIndices[cstart]);
facescount += 2;
}
if(c == 0) c++;
@ -759,7 +767,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
if((flags & 32) != 0)
{
z = ztop + zleng - 1;
AddFace(verts, new Vector3D(x + 1, y, z + 1), new Vector3D(x, y, z + 1), new Vector3D(x + 1, y + 1, z + 1), new Vector3D(x, y + 1, z + 1), pivot, colorIndices[zleng - 1]);
AddFace(verts, indices, verthashes, new Vector3D(x + 1, y, z + 1), new Vector3D(x, y, z + 1), new Vector3D(x + 1, y + 1, z + 1), new Vector3D(x, y + 1, z + 1), pivot, colorIndices[zleng - 1]);
facescount += 2;
}
}
}
@ -775,10 +784,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
int minY = (int)((ysize / 2f - pivot.y) * mde.Scale.Y);
int maxY = (int)((ysize / 2f + pivot.y) * mde.Scale.Y);
// calculate model radius
// Calculate model radius
mde.Model.Radius = Math.Max(Math.Max(Math.Abs(minY), Math.Abs(maxY)), Math.Max(Math.Abs(minX), Math.Abs(maxX)));
//create texture
// Create texture
MemoryStream memstream = new MemoryStream((4096 * 4) + 4096);
using(Bitmap bmp = CreateVoxelTexture(palette)) bmp.Save(memstream, ImageFormat.Bmp);
memstream.Seek(0, SeekOrigin.Begin);
@ -786,78 +795,116 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
Texture texture = Texture.FromStream(device, memstream, (int)memstream.Length, 64, 64, 0, Usage.None, Format.Unknown, Pool.Managed, Filter.Point, Filter.Box, 0);
memstream.Dispose();
//add texture
// Add texture
mde.Model.Textures.Add(texture);
//create mesh
int[] indices = new int[verts.Count];
for(int i = 0; i < verts.Count; i++)
{
indices[i] = i;
}
Mesh mesh = new Mesh(device, verts.Count / 3, verts.Count, MeshFlags.Use32Bit | MeshFlags.IndexBufferManaged | MeshFlags.VertexBufferManaged, vertexElements);
// Create mesh
MeshFlags meshflags = MeshFlags.Managed;
if(indices.Count > ushort.MaxValue - 1) meshflags |= MeshFlags.Use32Bit;
Mesh mesh = new Mesh(device, facescount, verts.Count, meshflags, vertexElements);
DataStream mstream = mesh.VertexBuffer.Lock(0, 0, LockFlags.None);
mstream.WriteRange(verts.ToArray());
mesh.VertexBuffer.Unlock();
mstream = mesh.IndexBuffer.Lock(0, 0, LockFlags.None);
mstream.WriteRange(indices);
if(indices.Count > ushort.MaxValue - 1)
mstream.WriteRange(indices.ToArray());
else
foreach(int index in indices) mstream.Write((ushort)index);
mesh.IndexBuffer.Unlock();
mesh.OptimizeInPlace(MeshOptimizeFlags.AttributeSort);
//add mesh
// Add mesh
mde.Model.Meshes.Add(mesh);
}
// Shameless GZDoom rip-off
private static void AddFace(List<WorldVertex> verts, Vector3D v1, Vector3D v2, Vector3D v3, Vector3D v4, Vector3D pivot, int colorIndex)
private static void AddFace(List<WorldVertex> verts, List<int> indices, Dictionary<long, int> hashes, Vector3D v1, Vector3D v2, Vector3D v3, Vector3D v4, Vector3D pivot, int colorIndex)
{
float pu0 = (colorIndex % 16) / 16f;
float pu1 = pu0 + 0.0001f;
float pu1 = pu0 + 0.001f;
float pv0 = (colorIndex / 16) / 16f;
float pv1 = pv0 + 0.0001f;
float pv1 = pv0 + 0.001f;
WorldVertex wv1 = new WorldVertex();
wv1.x = v1.x - pivot.x;
wv1.y = -v1.y + pivot.y;
wv1.z = -v1.z + pivot.z;
wv1.c = -1;
wv1.u = pu0;
wv1.v = pv0;
verts.Add(wv1);
WorldVertex wv1 = new WorldVertex
{
x = v1.x - pivot.x,
y = -v1.y + pivot.y,
z = -v1.z + pivot.z,
c = -1,
u = pu0,
v = pv0
};
int i1 = AddVertex(wv1, verts, indices, hashes);
WorldVertex wv2 = new WorldVertex();
wv2.x = v2.x - pivot.x;
wv2.y = -v2.y + pivot.y;
wv2.z = -v2.z + pivot.z;
wv2.c = -1;
wv2.u = pu1;
wv2.v = pv1;
verts.Add(wv2);
WorldVertex wv2 = new WorldVertex
{
x = v2.x - pivot.x,
y = -v2.y + pivot.y,
z = -v2.z + pivot.z,
c = -1,
u = pu1,
v = pv1
};
AddVertex(wv2, verts, indices, hashes);
WorldVertex wv4 = new WorldVertex();
wv4.x = v4.x - pivot.x;
wv4.y = -v4.y + pivot.y;
wv4.z = -v4.z + pivot.z;
wv4.c = -1;
wv4.u = pu0;
wv4.v = pv0;
verts.Add(wv4);
WorldVertex wv4 = new WorldVertex
{
x = v4.x - pivot.x,
y = -v4.y + pivot.y,
z = -v4.z + pivot.z,
c = -1,
u = pu0,
v = pv0
};
int i4 = AddVertex(wv4, verts, indices, hashes);
WorldVertex wv3 = new WorldVertex();
wv3.x = v3.x - pivot.x;
wv3.y = -v3.y + pivot.y;
wv3.z = -v3.z + pivot.z;
wv3.c = -1;
wv3.u = pu1;
wv3.v = pv1;
verts.Add(wv3);
WorldVertex wv3 = new WorldVertex
{
x = v3.x - pivot.x,
y = -v3.y + pivot.y,
z = -v3.z + pivot.z,
c = -1,
u = pu1,
v = pv1
};
AddVertex(wv3, verts, indices, hashes);
verts.Add(wv1);
verts.Add(wv4);
indices.Add(i1);
indices.Add(i4);
}
// Returns index of added vert
private static int AddVertex(WorldVertex v, List<WorldVertex> verts, List<int> indices, Dictionary<long, int> hashes)
{
long hash;
unchecked // Overflow is fine, just wrap
{
hash = 2166136261;
hash = (hash * 16777619) ^ v.x.GetHashCode();
hash = (hash * 16777619) ^ v.y.GetHashCode();
hash = (hash * 16777619) ^ v.z.GetHashCode();
hash = (hash * 16777619) ^ v.u.GetHashCode();
hash = (hash * 16777619) ^ v.v.GetHashCode();
}
if(hashes.ContainsKey(hash))
{
indices.Add(hashes[hash]);
return hashes[hash];
}
else
{
verts.Add(v);
hashes.Add(hash, verts.Count - 1);
indices.Add(verts.Count - 1);
return verts.Count - 1;
}
}
private unsafe static Bitmap CreateVoxelTexture(PixelColor[] palette)