I am using Unity to show a mesh created using open3D. Because the obj file with the mesh has vertex colors, which are not officially part of the obj specification, Unity would not import them with the geometry. I wrote a script to import it in runtime, but I get a very weird-looking result.
Here are 4 pictures: How it should look (from outside of unity: python with open3d):
How unity imported it - no color, good geometry:
The result of my script that reads the obj, and a standard particle shader - good colors, bad geometry:
The same result but with hdr colors and different angle that better shows the problem:
The debugger shows the vertices and triangles are read correctly (at least the first couple lines), and the index format is indeed set to 32k. And still, the triangles seem to use the wrong vertices?
my code:
// (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();
}
}
A bit of the obj file is below. the v is for vertex, format x y z r g b the vn are normals, I ignore these the f are triangle faces, format 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#
...
I would appreciate any help in solving this mystery and showing the mesh correctly. Thank you all in advance!
The problem turned out to be that Unity needs an index remap, I'm still not sure why - maybe to have the indices order match the order they appear in the triangles. The OBJ Runtime Importer Unity plugin does it, so all I needed to do was change its shader to a particle one, make it read the vertex colors format, and add the colors list to the remapping.
A flowers vase with both color and geometry appearing correctly