mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-31 04:40:55 +00:00
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:
parent
3f93525ebc
commit
a8c23266bb
3 changed files with 118 additions and 65 deletions
|
@ -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
|
||||
|
|
|
@ -308,6 +308,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
lumpdata.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue