Em yeah a friend of mine and me have solved that problem.
A 2x2 grid check of the vertex was not enough to get the amount of detail so we decided to switch to a 3x3 grid check.
That alone did not give enough good results so we came up with a solution to fix this problem at least a lot better.
This solution only handles like 99.5% of the cases (only extreme edge cases are left that you can not directly detect in this system)
The solution was to generate all possible cases automatically and evaluate them manually.
Since we had a 3x3 grid that was 8 bits of data around that point of interest. Well technically 16 bit since we have to see the difference between is higher & is lower.
That was not really hard. Setting up a UI that asks you is this ok or does it need to be rotated was pretty simple. After that it was around 1 hour sitting there pressing 2-3 buttons constantly to say: Yay/Nay (I felt like monkey push button to get reward xD)
That resulted out of the 65k cases that there were like 2.6k broken cases that needed to be rotated.
It was a long list.
I leave the code here if other people have close issues with that kind of system.
//Calculates if the Vertex needs to be rotated to look nice in the map.
public int calculateVertexState(int x, int y)
{
int index = createIndex(x, y);
if(index == 109) //Edge Case where i needed to check what vertex rotation comes directly after that.
{
return createIndex(x + 1, y + 1) == 110 ? 1 : 0;
}
else if(index == 115)//Edge Case where i needed to check what vertex rotation comes directly after that.
{
return createIndex(x + 1, y + 1) == 118 ? 1 : 0;
}
//ROTATION_CACHE is just a IntSet(FastUtil)/Set<Integer> with all the possiblities that i had manually selected
return ROTATOR_CACHE.contains(index) ? 1 : 0;
}
//Creates a Bit Based index around the vertex that needs to be checked. (Right=>Left)First 8 Bits are if the terrain is higher then the vertex to check. Second 8 bits are if they are lower then the vertex to check.
public int createIndex(int x, int z)
{
int height = getHeight(x, z);
return getMultiFlag(x, z, height, 0, true) | getMultiFlag(x, z, height, 8, false);
}
//Helper function to reduce code size. It Just creates a 8 Bit Number the represents the HeightDiffereces
private int getMultiFlag(int x, int z, int height, int bitOffset, boolean up)
{
return getFlag(x - 1, z - 1, height, bitOffset, up) | getFlag(x, z - 1, height, bitOffset+1, up) | getFlag(x - 1, z, height, bitOffset+2, up) | getFlag(x + 1, z - 1, height, bitOffset+3, up) | getFlag(x - 1, z + 1, height, bitOffset+4, up) | getFlag(x + 1, z, height, bitOffset+5, up) | getFlag(x, z + 1, height, bitOffset+6, up) | getFlag(x + 1, z + 1, height, bitOffset+7, up);
}
//Helper function to reduce code size. Checks if the terrain is higher or lower and returns 1 bit based on that.
private int getFlag(int x, int z, int height, int bitOffset, boolean up)
{
if(up)
{
return (getHeight(x, z) > height ? 1 : 0) << bitOffset;
}
return (getHeight(x, z) < height ? 1 : 0) << bitOffset;
}
Thanks to fast util its only like 10-20kb of data that i actually store in ram.
Also this code is enough that you can easily generate yourself the “Automated Display Evaluation System” out of that.
That should at least cover enough cases that i can easly generate terrain without problems. And even if there is some left there is a manual fixing system for that. Once the map is generated the vertex data is anyway stored in the save file so players themselves don’t get any issues afterwards.
If you have any improvement ideas go ahead i will follow this thread at least a bit.
Thanks for reading/time. Speiger
Edit 1: Oh yeah i just forgot, why i return 0-1 in the function instead of the true/false is because this function actually parses directly into a Texture (which is the terraincolor, heightmap, colorOverlayForTerrain, VertexRotation, not in that order), because i use a Instanced Mesh renderer for a giant map and only have like 1 mesh for the entirety of it (mesh is 16x16 tiles). (Largest right now is 4096x4096 tiles)