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

3
我正在使用Unity展示使用open3D创建的网格。由于带有顶点颜色的obj文件并不是官方规范的一部分,因此Unity不会将其与几何图形一起导入。我编写了一个脚本在运行时导入,但结果看起来非常奇怪。
这里有4张图片: 应该是什么样子的(从Unity外部:使用Python和open3d):

How it should look (from outside of unity: python with open3d)

如何导入Unity - 没有颜色,几何形状良好:

How unity imported it - no color, good geometry

我的脚本读取了obj文件,并使用了标准的粒子着色器,颜色不错但几何形状有问题。

The result of my script that reads the obj, and a standard particle shader - good colors, bad geometry

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

The same result but with hdr colors and different angle that better shows the problem

调试器显示顶点和三角形被正确读取(至少前几行),索引格式确实设置为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表示三角形面,格式为顶点idx//顶点法向量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#
...

我希望你能帮助解决这个谜团,并正确显示网格。提前感谢您所有的帮助!


1
我建议使用已经存在的免费OBJ Runtime Importer作为起点...它远非完美,但代码是完全开放的,所以你可以将其作为起点并进行改进 ;) - derHugo
您的 OBJ 文件包含法线 (vn) ... 为什么不直接使用它们,而要使用 RecalculateNormals 呢? - derHugo
@derHugo,现有代码的想法很好,谢谢。我会尝试添加顶点颜色。而且在添加其他内容之前,我主要希望我的代码能够最小化地工作。 - tair
1个回答

1
问题是Unity需要进行索引重新映射,我仍然不确定原因——也许是为了使索引顺序与三角形中出现的顺序相匹配。OBJ Runtime Importer Unity插件可以实现这一点,所以我只需要将其着色器更改为粒子着色器,使其读取顶点颜色格式,并将颜色列表添加到重新映射中即可。
一个花瓶,既有正确的颜色又有正确的几何形状 (链接)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接