如何修复此 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
我正在使用 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