垂直壁的正x轴和负x轴上的Unity Mesh UV问题

问题描述

我正在尝试制作一种3D体素游戏,该游戏使用行进立方体算法来程序化地生成游戏世界。到目前为止,这工作正常,但在给定的世界/块网格垂直块的正负x侧的正好垂直侧,看起来uv坐标不太正确,因为它仅显示实心颜色而不是纹理。 [![debug块和越野车视图] [1]] [1]

在处您可以看到块状墙的外观,而在处您可以看到怪异的错误。仅在完全垂直的x边三角形上发生!图像中的那些网格是用于显示问题的调试块。 所有从噪点到地形的翻译都可以正常工作,而且我那里也没有任何错误。只是uvs会引起问题。 我正在使用以下代码填充Mesh.vertices,Mesh.triangles和Mesh.uv:

void MakeChunkMeshData()
{
    for (int x = 0; x < Variables.chunkSize.x - 1; x++)
    {
        for (int y = 0; y < Variables.chunkSize.y - 1; y++)
        {
            for (int z = 0; z < Variables.chunkSize.z - 1; z++)
            {
                byte[] cubeCornerSolidityValues = new byte[8]{
                    chunkMapSolidity[x,y,z],chunkMapSolidity[x + 1,y + 1,chunkMapSolidity[x,z + 1],z + 1]
                };

                MarchOne(new Vector3Int(x,z),cubeCornerSolidityValues);
            }
        }
    }
}

void DrawChunk()
{
    chunkMesh.vertices = vertices.ToArray();
    chunkMesh.triangles = triangles.ToArray();
    chunkMesh.SetUVs(0,uvs.ToArray());
    chunkMesh.RecalculateNormals();
}

void ClearMesh()
{
    chunkMesh.Clear();
}

void ClearChunkMeshAndData()
{
    chunkMesh.Clear();
    uvs = new List<Vector2>();
    vertices = new List<Vector3>();
    triangles = new List<int>();
}

/// <summary>
/// cube contains bytes for each corner of the cube
/// </summary>
/// <param name="cube"></param>
/// <returns></returns>
int GetCubeConfiguration(byte[] cube)
{
    int u = 0;
    int result = 0;
    for(int corner = 0; corner < 8; corner++)
    {
        if (cube[corner] < Variables.solidityThreshold)
        {
            u++;
            result |= 1 << corner;
        }
    }
    return result;
}

Vector2[] getUvsPerTriangle(byte[] voxelTypes)
{
    int resId = voxelTypes[0];
    if (voxelTypes[1] == voxelTypes[2])
        resId = voxelTypes[1];
    resId = 1;

    Vector2 normalized = getUvCoordFromTextureIndex(resId) / Constants.TextureAtlasSizeTextures;
    float textureLength = 1f/Constants.TextureAtlasSizeTextures;
    
    Vector2[] result = new Vector2[3] {
        normalized + new Vector2(1,0) * textureLength,normalized + new Vector2(0,1) * textureLength,normalized + new Vector2(1,1) * textureLength
    };
    //Debug.Log(result);
    return result;
}

/// <summary>
/// returns the absolute x and y coordinates of the given texture in the atlas (example: [4,1])
/// </summary>
/// <param name="textureIndex"></param>
/// <returns></returns>
Vector2 getUvCoordFromTextureIndex(int textureIndex)
{
    int x = textureIndex % Constants.TextureAtlasSizeTextures;
    int y = (textureIndex - x) / Constants.TextureAtlasSizeTextures;
    return new Vector2(x,y);
}

/// <summary>
/// takes the chunk-wide mesh data and adds its results after marching one cube to it.
/// </summary>
/// <returns></returns>
void MarchOne(Vector3Int offset,byte[] cube)
{
    int configuration = GetCubeConfiguration(cube);

    byte[] voxelTypes = new byte[3];

    int edge = 0;
    for (int i = 0; i < 5; i++) //loop at max 5 times (max number of triangles in one cube config)
    {
        for(int v = 0; v < 3; v++)  // loop 3 times through shit(count of vertices in a TRIangle,who would have thought...)
        {
            int cornerIndex = VoxelData.TriangleTable[configuration,edge];

            if (cornerIndex == -1)  // indicates the end of the list of vertices/triangles
                return;

            Vector3 vertex1 = lwTo.Vec3(VoxelData.EdgeTable[cornerIndex,0]) + offset;
            Vector3 vertex2 = lwTo.Vec3(VoxelData.EdgeTable[cornerIndex,1]) + offset;

            Vector3Int vertexIndex1 = lwTo.Vec3Int(VoxelData.EdgeTable[cornerIndex,0]) + offset;
            Vector3Int vertexIndex2 = lwTo.Vec3Int(VoxelData.EdgeTable[cornerIndex,1]) + offset;

            Vector3 vertexPosition;
            if (Variables.badGraphics)
            {
                vertexPosition = (vertex1 + vertex2) / 2f;
            }
            else
            {
                // currently using this "profile" 
                // this code determines the position of the vertices per triangle based on the value in chunkSolidityMap[,]
                float vert1Solidity = chunkMapSolidity[vertexIndex1.x,vertexIndex1.y,vertexIndex1.z];
                float vert2Solidity = chunkMapSolidity[vertexIndex2.x,vertexIndex2.y,vertexIndex2.z];

                float difference = vert2Solidity - vert1Solidity;
                difference = (Variables.solidityThreshold - vert1Solidity) / difference;

                vertexPosition = vertex1 + ((vertex2 - vertex1) * difference);
            }
            vertices.Add(vertexPosition);
            triangles.Add(vertices.Count - 1);

            voxelTypes[v] = chunkMapVoxelTypes[vertexIndex1.x,vertexIndex1.z];

            edge++;
        }
        uvs.AddRange(getUvsPerTriangle(voxelTypes));
    }
}

编辑: 当仅稍微旋转块时,奇怪的问题立即消失。我不知道为什么,但是至少我现在知道这里发生了什么。 [1]:https://i.stack.imgur.com/kYnkl.jpg

解决方法

好吧,事实证明,这可能是一些来自统一的奇怪行为。当在网格填充过程之后将网格显式设置为meshFilters的网格时,它工作得很好。另外,我必须调用mesh.RecalculateTangents()使其起作用。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...