示例#1
0
    internal void TaskLoad(string name)
    {
        try
        {
            string path    = Path.GetDirectoryName(name);
            string zipName = null;
            string fltName = Path.GetFileName(name);
            if (path.EndsWith(".zip"))
            {
                zipName = Path.GetFileName(path);
                path    = Path.GetDirectoryName(path);
            }

            if (fltName == null)
            {
                Debug.LogErrorFormat("[MeshManager] MeshEntry.TaskLoad(): no FLT specified in {0}", name);
                Loaded = true;
                return;
            }

            if (zipName == null)
            {
                var bytes  = System.IO.File.ReadAllBytes(name);
                var parser = new Cognitics.BinaryParser(bytes);
                var reader = new FltReader(parser);
                Flt = new FltDatabase(null, RecordType.Invalid, reader, fltName);
                Flt.Parse();
            }
            else
            {
                byte[] bytes = null;
                ZipReader.DoDecompression(path, zipName, fltName, ref bytes);
                if (bytes == null)
                {
                    // TODO: this log is too spammy for a regular build right now. remove conditional check once that issue is addressed
                    if (Database.isDebugBuild)
                    {
                        Debug.LogErrorFormat("Missing model: {0} {1} {2}", path, zipName, fltName);
                    }
                    Loaded = true;
                    return;
                }
                var parser = new Cognitics.BinaryParser(bytes);
                var reader = new FltReader(parser);
                Flt = new FltDatabase(null, RecordType.Invalid, reader, fltName);
                Flt.Parse();
            }

            foreach (var texturePalette in Flt.TexturePalettes)
            {
                string texPath = Path.Combine(path, texturePalette.filename);
                if (File.Exists(texPath))
                {
                    Textures.Add(texPath);
                }
                else
                {
                    string textureFilename = Path.Combine(path, texturePalette.filename);
                    string zippath         = Path.GetDirectoryName(textureFilename);
                    string zipfn           = Path.GetFileNameWithoutExtension(textureFilename);
                    int    us_index        = 0;
                    for (int i = 0; i < 7; ++i)
                    {
                        us_index = zipfn.IndexOf('_', us_index) + 1;
                    }
                    zipfn = zipfn.Substring(0, us_index - 1);
                    string zipfile = Path.Combine(zippath, zipfn + ".zip");
                    texPath = Path.Combine(zipfile, Path.GetFileName(texturePalette.filename));
                    // TODO: we could query the zip here to verify the file exists within its contents
                    //if (File.Exists(texPath))
                    {
                        Textures.Add(texPath);
                    }
                    //else
                    //{
                    //    Debug.LogErrorFormat("[MeshManager] MeshEntry.TaskLoad(): texture {0} does not exist", texPath);
                    //    return;
                    //}
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogException(e);
        }
        if ((Flt != null) && (Flt.geometryRecords.Count == 0))
        {
            Debug.LogError("[MeshManager] MeshEntry.TaskLoad(): no primary geometry for " + Flt.Path);
            Flt = null;
        }

        if (Flt != null)
        {
            vertices = new Vector3[Flt.VertexPalette.Dict.Count];
            normals  = new Vector3[Flt.VertexPalette.Dict.Count];
            uvs      = new Vector2[Flt.VertexPalette.Dict.Count];

            int i = 0;
            foreach (var elem in Flt.VertexPalette.Dict)
            {
                var vert = elem.Value;
                if (vert is VertexWithColorNormal)
                {
                    var v = vert as VertexWithColorNormal;
                    vertices[i].x = (float)v.x;
                    vertices[i].y = (float)v.z;
                    vertices[i].z = (float)v.y;
                    normals[i].x  = v.i;
                    normals[i].y  = v.k;
                    normals[i].z  = v.j;
                    uvs[i]        = Vector2.zero;
                }
                else if (vert is VertexWithColorNormalUV)
                {
                    var v = vert as VertexWithColorNormalUV;
                    vertices[i].x = (float)v.x;
                    vertices[i].y = (float)v.z;
                    vertices[i].z = (float)v.y;
                    normals[i].x  = v.i;
                    normals[i].y  = v.k;
                    normals[i].z  = v.j;
                    uvs[i].x      = v.u;
                    uvs[i].y      = v.v;
                }
                else if (vert is VertexWithColorUV)
                {
                    var v = vert as VertexWithColorUV;
                    vertices[i].x = (float)v.x;
                    vertices[i].y = (float)v.z;
                    vertices[i].z = (float)v.y;
                    normals[i]    = Vector3.up;
                    uvs[i].x      = v.u;
                    uvs[i].y      = v.v;
                }
                else if (vert is VertexWithColor) // base class
                {
                    var v = vert as VertexWithColor;
                    vertices[i].x = (float)v.x;
                    vertices[i].y = (float)v.z;
                    vertices[i].z = (float)v.y;
                    normals[i]    = Vector3.up;
                    uvs[i]        = Vector2.zero;
                }

                ++i;
            }
        }

        Loaded = true;
    }
示例#2
0
    // Create mesh with loaded flt and assign to Mesh
    public IEnumerator GenerateMeshesCoroutine()
    {
        Lods = new List <LODData>();

        if (Flt == null)
        {
            yield break;
        }

        if (true)
        {
            ////////////////////////////////////////////////////////////////////////////////
            // this breaks LODs but makes models work for san diego

            var mesh = new UnityEngine.Mesh();
            mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
            var lod_data = new LODData {
                mesh = mesh
            };
            Lods.Add(lod_data);
            var submeshes = new List <Submesh>();
            foreach (var flt_record in Flt.geometryRecords)
            {
                var id_record     = flt_record as IdRecord;
                var rec_submeshes = id_record.Submeshes;

                /*
                 * for (int i = 0; i < rec_submeshes.Count; ++i)
                 * {
                 *  rec_submeshes[i].triangles.Reverse();
                 *  rec_submeshes[i].triangles.AddRange(rec_submeshes[i].backfaceTriangles);
                 * }
                 */
                rec_submeshes.AddRange(Flt.Submeshes);
                submeshes.AddRange(rec_submeshes);
                yield return(null);
            }

            Lods[0].mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;

            Lods[0].mesh.vertices = vertices;
            Lods[0].mesh.normals  = normals;
            Lods[0].mesh.uv       = uvs;

            if (submeshes == null)
            {
                Debug.LogError("[MeshManager] MeshEntry.GenerateMeshHelper() no meshes for " + Flt.Path);
                yield break;
            }

            var submeshes_temp = new List <Submesh>();
            foreach (var submesh in submeshes)
            {
                if (submesh.material == null)
                {
                    continue;
                }
                if (submesh.material.mainTexturePalette == null)
                {
                    continue;
                }
                submeshes_temp.Add(submesh);
            }
            submeshes = submeshes_temp;
            Lods[0].mesh.subMeshCount = submeshes.Count;
            for (int i = 0; i < submeshes.Count; ++i)
            {
                submeshToTexturePatternIndex[i] = submeshes[i].material.mainTexturePalette.texturePatternIndex;
                Lods[0].mesh.SetTriangles(submeshes[i].triangles, i);
                Memory += submeshes[i].triangles.Count * sizeof(int);
                yield return(null);
            }

            /*
             * Lods[0].mesh.subMeshCount = submeshes.Count;
             * bool abort = false;
             * for (int i = 0; i < submeshes.Count; ++i)
             * {
             *  //int texturePatternIndex = -1;     // we have to have something here or the materials won't be created correctly
             *  int texturePatternIndex = 0;
             *  if (submeshes[i].material != null && submeshes[i].material.mainTexturePalette != null)
             *      texturePatternIndex = submeshes[i].material.mainTexturePalette.texturePatternIndex;
             *  submeshToTexturePatternIndex[i] = texturePatternIndex;
             *
             *  for (int j = 0; j < submeshes[i].triangles.Count; ++j)
             *  {
             *      if (submeshes[i].triangles[j] > vertices.Length - 1)
             *      {
             *          Debug.LogError("[MeshManager] MeshEntry.GenerateMeshHelper() invalid vertex index for " + Flt.Path);
             *          abort = true;
             *          break;
             *      }
             *  }
             *  if (abort)
             *      break;
             *
             *  Lods[0].mesh.SetTriangles(submeshes[i].triangles, i);
             *  Memory += submeshes[i].triangles.Count * sizeof(int);
             *
             *  // Recalculate bounds if needed.
             *  // NOTE: in Unity, bounds are automatically recalculated when triangles are set
             *  //Lods[lodIndex].mesh.RecalculateBounds();
             *
             *  yield return null;
             * }
             */
        }
        else ////////////////////////////////////////////////////////////////////////////////
        {
            int lodIndex = 0;
            foreach (var record in Flt.geometryRecords)
            {
                var mesh = new UnityEngine.Mesh();
                mesh.name = lodIndex.ToString();
                var lodData = new LODData {
                    mesh = mesh
                };
                Lods.Add(lodData);
                mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;

                var idRecord  = record as IdRecord;
                var lodRecord = record as LevelOfDetail;
                if (lodRecord != null)
                {
                    if (lodRecord.significantSize == 0f)
                    {
                        // significantSize undefined -> pre-15.8
                        lodData.switchInDistanceSq  = (float)lodRecord.switchInDistance * (float)lodRecord.switchInDistance;
                        lodData.switchOutDistanceSq = (float)lodRecord.switchOutDistance * (float)lodRecord.switchOutDistance;
                    }
                    else
                    {
                        lodData.CalculateFromSignificantSize((float)lodRecord.significantSize);
                    }
                }
                else
                {
                    lodData.switchInDistanceSq  = 2500f * lodIndex * lodIndex;// TEMP - artificial distances for prototyping
                    lodData.switchOutDistanceSq = 2500f * (lodIndex + 1) * (lodIndex + 1);
                }

                var submeshes = record.Submeshes;
                for (int i = 0; i < submeshes.Count; ++i)
                {
                    submeshes[i].triangles.Reverse();
                    submeshes[i].triangles.AddRange(submeshes[i].backfaceTriangles);
                }

                // TODO: this isn't going to work right with LODs
                submeshes.AddRange(Flt.Submeshes);

                GenerateMeshHelper(lodIndex++, submeshes.ToArray(), vertices, normals, uvs);
            }
        }

        // Fix up switch-in distances. They should match the switch-out distances of the next highest quality LOD
        Lods[0].switchInDistanceSq = 0f;
        for (int i = 1; i < Lods.Count; ++i)
        {
            Lods[i].switchInDistanceSq = Lods[i - 1].switchOutDistanceSq;
        }

        Memory += vertices.Length * sizeof(float) * 3;
        Memory += normals.Length * sizeof(float) * 3;
        Memory += uvs.Length * sizeof(float) * 2;

        Flt      = null;
        vertices = null;
        normals  = null;
        uvs      = null;
    }