如何修复此 Unity 手动网格导入?

How to fix this Unity manual mesh-import?

我正在使用 Unity 来展示使用 open3D 创建的网格。因为带有网格的 obj 文件有顶点颜色,这不是 obj 规范的正式部分,Unity 不会将它们与几何体一起导入。我写了一个脚本在运行时导入它,但我得到了一个非常奇怪的结果。

这里有4张图片: 它应该是什么样子(从统一外部看:python with open3d):

unity 如何导入它 - 无颜色,良好的几何形状:

我的脚本读取 obj 和标准粒子着色器的结果 - 颜色好,几何形状差:

相同的结果,但使用 hdr 颜色和不同的角度可以更好地显示问题:

调试器显示顶点和三角形被正确读取(至少前几行),索引格式确实设置为 32k。而且,三角形似乎使用了错误的顶点?

我的代码:

// (Note that most built-in Shaders don't display vertex colors. Use one that does, such as a Particle Shader, to see vertex colors)

using UnityEngine;
using System.IO;
using System.Collections.Generic;

public class vercol : MonoBehaviour
{
    public GameObject flower;

    void Start()
    {
        flower = GameObject.Find("flower_mesh_ascii");
        Mesh mesh = flower.GetComponent<MeshFilter>().mesh;
        mesh.Clear();
        mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
        int[] triangles = mesh.triangles;

        // create new colors array where the colors will be created.
        List<Color> colors = new List<Color>();
        List<Vector3> newVertices = new List<Vector3>();
        List<int> newTriangles = new List<int>();
        System.IO.StreamReader file = new System.IO.StreamReader("C:\roomie3d\models\flower_mesh_ascii.obj");
        //string[] lines = File.ReadAllLines("C:\roomie3d\models\flower_mesh_ascii.obj");
        Debug.Log("before loop");
        string line;
        while ((line = file.ReadLine()) != null)
        {
            if (line.Substring(0, 2) == "v ")// & col < vertices.Length - 1)
            {
                string[] subs = line.Split(' ');
                float x = float.Parse(subs[1]);
                float y = float.Parse(subs[2]);
                float z = float.Parse(subs[3]);
                newVertices.Add(new Vector3(x, y, z));
                float red = float.Parse(subs[4]);
                float green = float.Parse(subs[5]);
                float blue = float.Parse(subs[6]);
                colors.Add(new Color(red, green, blue));
            }
        }
        file.Close();

        System.IO.StreamReader file2 = new System.IO.StreamReader("C:\roomie3d\models\flower_mesh_ascii.obj");
        while ((line = file2.ReadLine()) != null)
        { 
            if (line.Substring(0, 2) == "f ")// & trig < triangles.Length - 1)
            {
                
                string[] subs = line.Split(new char[] { ' ' });               
                if (subs.Length == 4)
                {
                    int v1 = int.Parse(subs[1].Split('/')[0]);
                    
                    int v2 = int.Parse(subs[2].Split('/')[0]);
                    int v3 = int.Parse(subs[3].Split('/')[0]);
                    if (v1 > newVertices.Count - 1 || v2 > newVertices.Count - 1 || v3 > newVertices.Count - 1)
                    {
                        
                        continue;
                    }
                    newTriangles.Add(v1);
                    newTriangles.Add(v2);
                    newTriangles.Add(v3);
                }
            }
        }
        file2.Close();
        mesh.vertices = newVertices.ToArray();
        mesh.triangles = newTriangles.ToArray();
        mesh.colors = colors.ToArray();
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
    }
}

下面是一些 obj 文件。 v 代表顶点,格式为 x y z r g b vn 是法线,我忽略这些 f是三角形面,格式vertex idx//vertex normal idx.

# Created by Open3D 
# object name: flower_mesh_bin
# number of vertices: 1107833
# number of triangles: 2216689
v 0.893667 0.319232 1.01478 0.368658 0.325527 0.258864
vn 0.57735 0.57735 0.57735
v 1.47767 0.171788 1.01478 0.196129 0.150972 0.0960534
vn 0.57735 0.57735 0.57735
v 0.625564 0.707096 1.01478 0.455021 0.423702 0.380564
vn 0.57735 0.57735 0.57735
v 1.47171 0.179605 1.01478 0.196129 0.150972 0.0960534
vn 0.57735 0.57735 0.57735
...
#more vertices here#
...
f 8//8 141//141 10//10
f 44//44 151//151 46//46
f 74//74 166//166 77//77
f 77//77 167//167 78//78
f 166//166 167//167 77//77
...
#more triangles here#
...

对于解决这个谜题和正确显示网格的任何帮助,我将不胜感激。 提前谢谢大家!

问题原来是 Unity 需要重新映射索引,我仍然不确定为什么 - 也许让索引顺序与它们在三角形中出现的顺序相匹配。 OBJ Runtime Importer Unity 插件可以做到这一点,所以我需要做的就是将其着色器更改为粒子着色器,使其读取顶点颜色格式,并将颜色列表添加到重新映射中。

A flowers vase with both color and geometry appearing correctly