2016-06-15 6 views
3

Я пытаюсь загрузить модели OBJ во время выполнения с использованием Unity и C#. Я использую парсер Unity Wiki «FastOBJImporter» http://wiki.unity3d.com/index.php/FastObjImporter для разбора файлов OBJ. я не могу загрузить сетку с более чем 65534 вершин, так как это ограничение единства (http://answers.unity3d.com/questions/471639/mesh-with-more-than-65000-vertices.html)Разборная сетка с более чем 65k-вершинами в Unity во время выполнения

Моя идея проходит большой путь сетки на FastOBJImporter и генерировать несколько GameObjects менее 65k вершин, чтобы загрузить больше моделей ,

Кто-нибудь знает, как можно безопасно модифицировать FastOBJimporter, чтобы вернуть список суб-мешей вместо большой сетки? Любые другие решения/идеи приветствуются.

+0

Для более конкретной реализации я выполняю синтаксический анализ одного суперлиста из вершин, одного суперлиста треугольников и т. Д. Затем я создаю sub-vertex-list A, sub-vertex-list B и т. Д. с вершинами менее 64 КБ. Тогда я бы сгенерировал суб-треугольники-список A из списка под вершин A и т. Д. Мой вопрос: как мне сгенерировать списки под треугольников, чтобы содержать только вершину из одного списка под вершины? Я боюсь, что множество треугольников будет сформировано вершиной из разных суб-вершинных списков, и это будет проблемой. – user3543240

ответ

1

This script делает то, что вы хотите, но с файлами модели STL. Он импортирует модель, независимо от того, насколько она велика, разбивая меш на подмашины каждый раз, когда достигается 65 тыс. Вершин. Файлы STL могут быть преобразованы в OBJ-файлы, поэтому, я полагаю, использование простого конвертера или изменение скрипта может сделать трюк.

Код ниже (я не беру на себя ответственность за код).

#pragma warning disable 0219 

using UnityEngine; 
using System.Text; 
using System.Collections; 
using System.Collections.Generic; 
using System.IO; 
using System; 
using UnityEngine.UI; 
using UnityEngine.EventSystems; 
using System.Threading; 

namespace Parabox.STL 
{ 
    /*Import methods for STL files*/ 
    public class STL_ImportScript : MonoBehaviour 
    { 

     const int MAX_FACETS_PER_MESH = 65535/3; 

     class Facet 
     { 
      public Vector3 normal; 
      public Vector3 a, b, c; 

      public override string ToString() 
      { 
       return string.Format("{0:F2}: {1:F2}, {2:F2}, {3:F2}", normal, a, b, c); 
      } 
     } 

     /** 
     * Import an STL file at path. 
     */ 
     public static Mesh[] Import(string path) 
     { 
       try 
       { 
        return ImportBinary(path); 
       } 
       catch (System.Exception e) 
       { 
        UnityEngine.Debug.LogWarning(string.Format("Failed importing mesh at path {0}.\n{1}", path, e.ToString())); 
        return null; 
       } 
     } 

     private static Mesh[] ImportBinary(string path) 
     { 
      List<Facet> facets = new List<Facet>(); 
      byte[] header; 
      uint facetCount; 

      using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) 
      { 
       using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding())) 
       { 
        while (br.BaseStream.Position < br.BaseStream.Length) 
        { 
         // read header 
         header = br.ReadBytes(80); 
         facetCount = br.ReadUInt32(); 

         for (uint i = 0; i < facetCount; i++) 
         { 
          try 
          { 
           Facet facet = new Facet(); 

           facet.normal.x = br.ReadSingle(); 
           facet.normal.y = br.ReadSingle(); 
           facet.normal.z = br.ReadSingle(); 

           facet.a.x = br.ReadSingle(); 
           facet.a.y = br.ReadSingle(); 
           facet.a.z = br.ReadSingle(); 

           facet.b.x = br.ReadSingle(); 
           facet.b.y = br.ReadSingle(); 
           facet.b.z = br.ReadSingle(); 

           facet.c.x = br.ReadSingle(); 
           facet.c.y = br.ReadSingle(); 
           facet.c.z = br.ReadSingle(); 

           facets.Add(facet); 


           // padding 
           br.ReadUInt16(); 
          } 
          catch (Exception e) 
          { 
           //Console.WriteLine(e.Message); 
           Debug.Log(e.Message); 
          } 
         } 
        } 
       } 
      } 

      return CreateMeshWithFacets(facets); 
     } 

     const int SOLID = 1; 
     const int FACET = 2; 
     const int OUTER = 3; 
     const int VERTEX = 4; 
     const int ENDLOOP = 5; 
     const int ENDFACET = 6; 
     const int ENDSOLID = 7; 
     const int EMPTY = 0; 

     private static int ReadState(string line) 
     { 
      if (line.StartsWith("solid")) 
       return SOLID; 
      else if (line.StartsWith("facet")) 
       return FACET; 
      else if (line.StartsWith("outer")) 
       return OUTER; 
      else if (line.StartsWith("vertex")) 
       return VERTEX; 
      else if (line.StartsWith("endloop")) 
       return ENDLOOP; 
      else if (line.StartsWith("endfacet")) 
       return ENDFACET; 
      else if (line.StartsWith("endsolid")) 
       return ENDSOLID; 
      else 
       return EMPTY; 
     } 

     private static Vector3 StringToVec3(string str) 
     { 
      string[] split = str.Trim().Split(null); 
      Vector3 v = new Vector3(); 

      float.TryParse(split[0], out v.x); 
      float.TryParse(split[1], out v.y); 
      float.TryParse(split[2], out v.z); 

      return v; 
     } 


     private static Mesh[] CreateMeshWithFacets(IList<Facet> facets) 
     { 
      int fl = facets.Count, f = 0, mvc = MAX_FACETS_PER_MESH * 3; 
      Mesh[] meshes = new Mesh[fl/MAX_FACETS_PER_MESH + 1]; 

      for (int i = 0; i < meshes.Length; i++) 
      { 
       int len = System.Math.Min(mvc, (fl - f) * 3); 
       Vector3[] v = new Vector3[len]; 
       Vector3[] n = new Vector3[len]; 
       int[] t = new int[len]; 

       for (int it = 0; it < len; it += 3) 
       { 
        v[it] = facets[f].a; 
        v[it + 1] = facets[f].b; 
        v[it + 2] = facets[f].c; 

        n[it] = facets[f].normal; 
        n[it + 1] = facets[f].normal; 
        n[it + 2] = facets[f].normal; 

        t[it] = it; 
        t[it + 1] = it + 1; 
        t[it + 2] = it + 2; 

        f++; 
       } 

       meshes[i] = new Mesh(); 
       meshes[i].vertices = v; 
       meshes[i].normals = n; 
       meshes[i].triangles = t; 

      } 

      return meshes; 
     } 

    } 
} 

Другим решением может быть dynamically combine vertices that share the same space. Когда вы вводите свои модели во время выполнения, вы объединяете вершины, которые находятся в пределах определенного порога друг друга, чтобы уменьшить общее количество вершин ниже предела 65k.

В качестве альтернативы используйте инструменты, такие как Mesh Simplify, чтобы снизить уровень детализации, что позволяет оптимизировать производительность и уменьшить количество полигонов ниже 65k для импорта ваших сеток без превышения предела 65k. Существуют разные и более доступные варианты, но это, по-видимому, одно из лучших.