I've flattened my 3D chunk array(Got nice 20ms speed up), modified my VertexData struct (that I use in Dictionary as a key) to have custom hashcode(another 20ms and -2.7mb GC.alloc data speedup). But I'm not sure what to do next, since 40ms still feels long for such a small chunk(In fact, its twice smaller the size of Minecrafts 16x256x16 and still managing to be slower.).
My biggest bottleneck still seems to be the dictionary.
This is current performance profile:
The code:
public void MakeChunk()
{
vertexCount = 0;
//these are all Lists except verticesDictionary
vertices.Clear();
normals.Clear();
verticesDict.Clear();
uvs.Clear();
triangles.Clear();
int len = 32 * 32 * 32;
for (int i = 0; i < len; i++)
{
int cubeType = data.raw[i];
if (cubeType != 0)
{
int x = i % 32;
int y = (i / 32) % 32;
int z = i / (32 * 32);
MakeCube(x, y, z, cubeType);
blocksGenerated++;
}
}
}
void MakeCube(int x, int y, int z, int cubeType)
{
for (int i = 0; i < 6; i++)
{
Direction dir = (Direction)i;
if (data.GetNeighbor(x, y, z, dir) == 0)
{
MakeFace(dir, x, y, z, cubeType);
}
}
}
void MakeFace(Direction dir, int x, int y, int z, int cubeType)
{
VertexSignature signature;
signature.normal = dir;
Vector3[] faceVertices = CubeMeshData.faceVertices((int)dir, x, y, z);
int[] triangleIndices = new int[4];
signature.cubeType = cubeType;
for (int i = 0; i < 4; i++)
{
signature.position = faceVertices[i];
Vector3 uv = CubeMeshData.ProjectPositionToUV(signature.position, dir);
uv.z = signature.cubeType;
int vertex = GetVertexIndex(signature);
triangleIndices[i] = vertex;
}
triangles.AddRange(new int[6] {
triangleIndices[0],
triangleIndices[1],
triangleIndices[2],
triangleIndices[0],
triangleIndices[2],
triangleIndices[3]
}
);
}
void PrepareMeshData()
{
foreach (var pair in verticesDict)
{
int index = pair.Value;
vertices.Add(pair.Key.position);
CubeMeshData.DataCoordinate coord = CubeMeshData.offsets[(int)pair.Key.normal];
normals.Add(new Vector3(coord.x, coord.y, coord.z));
Vector3 uv = CubeMeshData.ProjectPositionToUV(pair.Key.position, pair.Key.normal);
uv.z = pair.Key.cubeType;
uvs.Add(uv);
}
}
Hashing:
struct VertexSignature
{
public Vector3 position;
public Direction normal;
public int cubeType;
public override int GetHashCode()
{
uint h = 0x811c9dc5;
h = (h ^ (uint)position.x) * 0x01000193;
h = (h ^ (uint)position.y) * 0x01000193;
h = (h ^ (uint)position.z) * 0x01000193;
h = (h ^ (uint)normal) * 0x01000193;
h = (h ^ (uint)cubeType) * 0x01000193;
return (int)h;
}
};
Then I do this:
Vector3[] vertexArr = vertices.ToArray();
int[] triArr = triangles.ToArray();
Vector3[] normalsArr = normals.ToArray();
I've really run out of ideas on how to improve performance further.
Any help is welcome.