微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决垂直壁的正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()使其起作用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。