Why does Transvoxel make blocky terrain?

1.3k Views Asked by At

I've been working on an implementation of Transvoxel since while. Now it works, it polygonizes, but it's kind of blocky. Like the image below:

enter image description here

This is the code for polygonization:

private static Mesh PolygonizeRegularCell (Vector3i pos, Mesh mesh, int lodIndex, Chunk samples)
{
    int lod = 1 << lodIndex;

    for (int i = 0; i < density.Length; i++) {
        density [i] = samples [pos + Transvoxel.cornerIndex [i] * lod].Density;
    }

    byte caseCode = getCaseCode(density);

    if ((caseCode ^ ((density [7] >> 7) & 0xFF)) != 0) {
        byte cellClass = Transvoxel.regularCellClass [caseCode];
        vertexLocations = Transvoxel.regularVertexData [caseCode];

        Transvoxel.RegularCell c = Transvoxel.regularCellData [cellClass];
        vertexCount = (long)c.GetVertexCount ();
        triangleCount = (long)c.GetTriangleCount ();
        indexOffset = c.Indizes ();

        localVertexMapping = new int[indexOffset.Length];

        for (int i = 0; i < vertexCount; i++) {
            ushort edgeCode = (ushort)(vertexLocations [i] & 0xFF);

            byte v0 = (byte)((edgeCode >> 4) & 0x0F);
            byte v1 = (byte)(edgeCode & 0x0F);

            Vector3 p0 = (pos + Transvoxel.cornerIndex [v0] * lod).ToVector3 ();
            Vector3 p1 = (pos + Transvoxel.cornerIndex [v1] * lod).ToVector3 ();

            long t = (density [v1] << 8) / (density [v1] - density [v0]);
            long u = 0x0100 - t;

            localVertexMapping [i] = vertices.Count;
            Vector3 Q = p0 * t + p1 * u;
            Q /= 256f;
            AddVertex (Q, samples [pos.x, pos.y, pos.z].block);
        }

        for (int t = 0; t < triangleCount; t++) {
            for (int i = 0; i < 3; i++) {
                triangles.Add (localVertexMapping [c.Indizes () [t * 3 + i]]);
            }
        }
    }
    return mesh;
}

And here is another one for generating heightmap and density values:

public void GenerateNewDensityField (int x, int z)
{
    densityColumn = new sbyte[128];
    noise = (float)(Noise.noise (x * 0.01f, z * 0.01f) * 0.25f);
    fHeight = ((noise + 1f) * 54f) + worldSize;
    height = Mathf.FloorToInt (fHeight);
    for (int i = 0; i < densityColumn.Length; i++) {
        if (i < height - 1)
            densityColumn [i] = -128;
        else if (i == height - 1)
            densityColumn [height - 1] = (sbyte)Mathf.Clamp (height - 128, -127, 128);
        else if (i == height)
            densityColumn [height] = (sbyte)Mathf.Clamp (-height, -128, 127);
        else if (i == height + 1)
            densityColumn [height + 1] = (sbyte)Mathf.Clamp (127 - height, -128, 127);
        else
            densityColumn [i] = 127;
    }

    densityCache [x, z] = new DensityColumn (densityColumn, height);
}

If you have used Transvoxel before or you have any idea about this then please comment or answer. I'm really stuck with this.

EDIT: Changes in density generation code, to not to generate too much zeros and so on, but it's still blocky.

1

There are 1 best solutions below

7
On

I haven't looked at your code in detail, but the blocky pattern in your screenshot is reminiscent of imprecise voxel density values. You would see this pattern, for example, if all voxel data values were -1.0 or +1.0 (or -127 and +127 as integer data) without anything in between. The voxels should represent the distance to the surface in units of a single voxel width, with +127 meaning the data point is one voxel outside the surface and -127 meaning the data point is one voxel inside the surface. You may just need to rescale your data accordingly, and then you'll see smooth results.