示例#1
0
/*
 * -------------
 * Big ol parser code.
 * Maybe I should split it out? Probably not worth the effort
 * Translated from the original MaxScript import
 * --------------
 */



    public static AMF ParseAMF(string path)
    {
        AMF amf = new AMF();

        using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open)))
        {
            Debug.Log("File length:" + reader.BaseStream.Length);

            readHeader(reader, amf);
            Debug.Log(amf.header + " " + amf.version + " " + amf.modelName);
            //tvRegions.Nodes.Clear()

            EditorUtility.DisplayProgressBar("Parsing " + path, "[0/5] Parsing nodes...", 0);
            readNodes(reader, amf);
            EditorUtility.DisplayProgressBar("Parsing " + path, "[1/5] Parsing Markers...", (1f / 5f));
            readMarkers(reader, amf);
            EditorUtility.DisplayProgressBar("Parsing " + path, "[2/5] Parsing Regions...", (2f / 5f));
            readRegions(reader, amf);
            EditorUtility.DisplayProgressBar("Parsing " + path, "[3/5] Parsing Shaders...", (3f / 5f));
            readShaders(reader, amf);

            //loadRegions(tvRegions)
        }
        return(amf);
    }
示例#2
0
        public void AMF_EncodeNamedNumberTest()
        {
            AVal   name = AVal.AVC("name");
            double val  = -2.3456; // 0xC0 02 C3 C9 EE CB FB 16

            byte[] buf = new byte[100];
            int    enc = 0, pend = buf.Length;
            int    len = 2 + 4 + 1 + 8; // "name".len + "name" + AMF_NUMBER + 8

            enc = AMF.AMF_EncodeNamedNumber(buf, enc, pend, name, val);
            Assert.AreEqual(len, enc);
            Assert.AreEqual(0x00, buf[0]);
            Assert.AreEqual(0x04, buf[1]);
            Assert.AreEqual('n', buf[2]);
            Assert.AreEqual('a', buf[3]);
            Assert.AreEqual('m', buf[4]);
            Assert.AreEqual('e', buf[5]);
            Assert.AreEqual((byte)AMFDataType.AMF_NUMBER, buf[6]);
            Assert.AreEqual(0xC0, buf[7]);
            Assert.AreEqual(0x02, buf[8]);
            Assert.AreEqual(0xC3, buf[9]);
            Assert.AreEqual(0xC9, buf[10]);
            Assert.AreEqual(0xEE, buf[11]);
            Assert.AreEqual(0xCB, buf[12]);
            Assert.AreEqual(0xFB, buf[13]);
            Assert.AreEqual(0x16, buf[14]);
        }
示例#3
0
        public void AMF_EncodeNamedStringTest2()
        {
            AVal name = AVal.AVC("name"), val = AVal.AVC("val");

            byte[] buf = new byte[100];
            int    offset = 20;
            int    enc = offset, pend = buf.Length;
            int    len = 2 + 4 + 1 + 2 + 3; // "name".len + "name" + AMF_STRING + "val".len + "val"

            enc = AMF.AMF_EncodeNamedString(buf, enc, pend, name, val);
            Assert.AreEqual(len + offset, enc);
            Assert.AreEqual(0x00, buf[0 + offset]);
            Assert.AreEqual(0x04, buf[1 + offset]);
            Assert.AreEqual('n', buf[2 + offset]);
            Assert.AreEqual('a', buf[3 + offset]);
            Assert.AreEqual('m', buf[4 + offset]);
            Assert.AreEqual('e', buf[5 + offset]);
            Assert.AreEqual((byte)AMFDataType.AMF_STRING, buf[6 + offset]);
            Assert.AreEqual(0x00, buf[7 + offset]);
            Assert.AreEqual(0x03, buf[8 + offset]);
            Assert.AreEqual('v', buf[9 + offset]);
            Assert.AreEqual('a', buf[10 + offset]);
            Assert.AreEqual('l', buf[11 + offset]);
            Assert.AreEqual(0x00, buf[12 + offset]);
        }
示例#4
0
    static void readMarkers(BinaryReader reader, AMF amf, bool skip = false)
    {
        int groupCount = reader.ReadInt32();

        Debug.Log("Groups Of Markers:[" + groupCount + "]");
        long groupAddress = reader.ReadInt32();
        long fPos         = reader.BaseStream.Position;

        amf.markerGroups = new List <AMF_MarkerGroup>();
        if (groupCount > 0 && !skip)
        {
            reader.BaseStream.Seek(groupAddress, SeekOrigin.Begin);
            for (int i = 0; i < groupCount; i++)
            {
                AMF_MarkerGroup amg = new AMF_MarkerGroup();
                amg.name = "#" + reader.ReadCString();
                long markerCount   = reader.ReadInt32();
                long markerAddress = reader.ReadInt32();
                long cPos          = reader.BaseStream.Position;
                amg.markers = new List <AMF_Marker>();
                if (markerCount > 0)
                {
                    reader.BaseStream.Seek(markerAddress, SeekOrigin.Begin);
                    for (int j = 0; j < markerCount; j++)
                    {
                        amg.markers.Add(new AMF_Marker(reader));
                    }
                }
                amf.markerGroups.Add(amg);
                reader.BaseStream.Seek(cPos, SeekOrigin.Begin);
            }
            reader.BaseStream.Seek(fPos, SeekOrigin.Begin);
        }
    }
示例#5
0
        public void AMF_EncodeStringTest2()
        {
            AVal app = AVal.AVC("appp");

            byte[] buf = new byte[4];
            int    enc = 0, pend = buf.Length;

            enc = AMF.AMF_EncodeString(buf, enc, pend, app);
            Assert.AreEqual(0, enc);
        }
示例#6
0
        public void AMF_DecodeInt32Test()
        {
            uint expected = 0x12345678;
            var  buf      = new byte[100];

            AMF.AMF_EncodeInt32(buf, 0, buf.Length, expected);
            var actual = AMF.AMF_DecodeInt32(buf);

            Assert.AreEqual(expected, actual);
        }
示例#7
0
        public void memcpyTest()
        {
            var src = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89 };
            var dst = new byte[src.Length];

            AMF.memcpy(dst, 0, src, 3);
            Assert.AreEqual(src[0], dst[0]);
            Assert.AreEqual(src[1], dst[1]);
            Assert.AreEqual(src[2], dst[2]);
            Assert.AreEqual(0x00, dst[3]);
        }
示例#8
0
        public void AMF_DecodeNumberTest()
        {
            double expected = -2.3456, actual;
            var    buf  = new byte[100];
            int    enc  = 0;
            var    pend = buf.Length;

            AMF.AMF_EncodeNumber(buf, enc, pend, expected);
            actual = AMF.AMF_DecodeNumber(buf, 1); // skip AMFDatatype
            Assert.AreEqual(expected, actual);
        }
示例#9
0
        public void AMF_EncodeInt16Test()
        {
            short sval = 0x1234;

            byte[] buf = new byte[100];
            int    enc = 0, pend = buf.Length;

            enc = AMF.AMF_EncodeInt16(buf, enc, pend, (ushort)sval);
            Assert.AreEqual(2, enc);
            Assert.AreEqual(0x12, buf[0]);
            Assert.AreEqual(0x34, buf[1]);
        }
示例#10
0
        public void AMF_EncodeInt24Test()
        {
            int val = 0x123456;

            byte[] buf = new byte[100];
            int    enc = 0, pend = buf.Length;

            enc = AMF.AMF_EncodeInt24(buf, enc, pend, (uint)val);
            Assert.AreEqual(3, enc, "result");
            Assert.AreEqual(0x12, buf[0], "0");
            Assert.AreEqual(0x34, buf[1], "1");
            Assert.AreEqual(0x56, buf[2], "2");
        }
示例#11
0
        public void AMF_EncodeInt32Test()
        {
            int val = 0x12345678;

            byte[] buf = new byte[100];
            int    enc = 0, pend = buf.Length;

            enc = AMF.AMF_EncodeInt32(buf, enc, pend, (uint)val);
            Assert.AreEqual(4, enc);
            Assert.AreEqual(0x12, buf[0]);
            Assert.AreEqual(0x34, buf[1]);
            Assert.AreEqual(0x56, buf[2]);
            Assert.AreEqual(0x78, buf[3]);
        }
示例#12
0
        public void AMF_EncodeStringTest()
        {
            AVal app = AVal.AVC("app");

            byte[] buf = new byte[50];
            int    output = 0, pend = buf.Length;

            output = AMF.AMF_EncodeString(buf, output, pend, app);
            Assert.AreEqual(6, output);
            Assert.AreEqual((byte)AMFDataType.AMF_STRING, buf[0]);
            Assert.AreEqual(0, buf[1]);
            Assert.AreEqual(3, buf[2]);
            Assert.AreEqual('a', buf[3]);
            Assert.AreEqual('p', buf[4]);
            Assert.AreEqual('p', buf[5]);
        }
示例#13
0
        public void AMF_DecodeStringTest()
        {
            var  buf = new byte[100];
            AVal str = AVal.AVC("foobar");

            AMF.AMF_EncodeString(buf, 0, buf.Length, str);
            AVal actual;

            AMF.AMF_DecodeString(buf, 1, out actual); // Skip AMFDatatype flag
            Assert.AreEqual(6, actual.av_len);
            Assert.AreEqual('f', actual.av_val[0]);
            Assert.AreEqual('o', actual.av_val[1]);
            Assert.AreEqual('o', actual.av_val[2]);
            Assert.AreEqual('b', actual.av_val[3]);
            Assert.AreEqual('a', actual.av_val[4]);
            Assert.AreEqual('r', actual.av_val[5]);
        }
示例#14
0
        public void AMF_EncodeBooleanTest()
        {
            byte[] buf = new byte[100];
            int    enc = 0, pend = buf.Length;

            enc = AMF.AMF_EncodeBoolean(buf, enc, pend, false);
            Assert.AreEqual(2, enc);
            Assert.AreEqual((byte)AMFDataType.AMF_BOOLEAN, buf[0]);
            Assert.AreEqual(0x00, buf[1]);

            enc  = 0;
            pend = buf.Length;
            enc  = AMF.AMF_EncodeBoolean(buf, enc, pend, true);
            Assert.AreEqual(2, enc);
            Assert.AreEqual((byte)AMFDataType.AMF_BOOLEAN, buf[0]);
            Assert.AreEqual(0x01, buf[1]);
        }
示例#15
0
        public void AMF_EncodeNamedBooleanTest()
        {
            AVal name = AVal.AVC("name");

            byte[] buf = new byte[100];
            int    enc = 0, pend = buf.Length;
            int    len = 2 + 4 + 1 + 1; // "name".len + "name" + AMF_NUMBER + 8

            enc = AMF.AMF_EncodeNamedBoolean(buf, enc, pend, name, true);
            Assert.AreEqual(len, enc);
            Assert.AreEqual(0x00, buf[0]);
            Assert.AreEqual(0x04, buf[1]);
            Assert.AreEqual('n', buf[2]);
            Assert.AreEqual('a', buf[3]);
            Assert.AreEqual('m', buf[4]);
            Assert.AreEqual('e', buf[5]);
            Assert.AreEqual((byte)AMFDataType.AMF_BOOLEAN, buf[6]);
            Assert.AreEqual(0x01, buf[7]);
        }
示例#16
0
        public void AMF_EncodeNumberTest()
        {
            double val = -2.3456; // 0xC0 02 C3 C9 EE CB FB 16

            byte[] buf = new byte[100];
            int    enc = 0, pend = buf.Length;

            enc = AMF.AMF_EncodeNumber(buf, enc, pend, val);
            Assert.AreEqual(9, enc);
            Assert.AreEqual((byte)AMFDataType.AMF_NUMBER, buf[0]);
            Assert.AreEqual(0xC0, buf[1]);
            Assert.AreEqual(0x02, buf[2]);
            Assert.AreEqual(0xC3, buf[3]);
            Assert.AreEqual(0xC9, buf[4]);
            Assert.AreEqual(0xEE, buf[5]);
            Assert.AreEqual(0xCB, buf[6]);
            Assert.AreEqual(0xFB, buf[7]);
            Assert.AreEqual(0x16, buf[8]);
        }
示例#17
0
    static void readNodes(BinaryReader reader, AMF amf, bool skip = false)
    {
        int count = reader.ReadInt32();

        Debug.Log("Node count:" + count);
        long            address = (long)reader.ReadInt32();
        long            fPos    = reader.BaseStream.Position;
        List <AMF_Node> nodes   = new List <AMF_Node>();

        if (count > 0 && !skip)
        {
            reader.BaseStream.Seek(address, SeekOrigin.Begin);
            for (int i = 0; i < count; i++)
            {
                nodes.Add(new AMF_Node(reader, i));
            }
            reader.BaseStream.Seek(fPos, SeekOrigin.Begin);
        }
        amf.nodes = nodes;
    }
示例#18
0
    /*
     *
     * Create Bone Hierarchy
     */
    List <Transform> CreateRigging(AMF amf)
    {
        List <Transform> bones = new List <Transform>();

        //first past to instantiate references
        for (int i = 0; i < amf.nodes.Count; i++)
        {
            bones.Add(new GameObject(amf.nodes[i].name).transform);
        }

        //second pass to setup hierarchy
        for (int i = 0; i < amf.nodes.Count; i++)
        {
            if (amf.nodes[i].parentIndex > -1)
            {
                bones[i].parent = bones[amf.nodes[i].parentIndex];
                Matrix4x4 flip = Matrix4x4.identity;
                flip.SetRow(0, new Vector4(-1, 0));
                bones[i].localPosition = flip.MultiplyPoint3x4(amf.nodes[i].pos);                                                          //new Vector3(amf.nodes[i].pos.x,amf.nodes[i].pos.y,-amf.nodes[i].pos.z);
                bones[i].localRotation = new Quaternion(amf.nodes[i].rot.x, -amf.nodes[i].rot.y, -amf.nodes[i].rot.z, amf.nodes[i].rot.w); //amf.nodes[i].rot;//
            }
        }
        //third pass to reorder siblings.
        for (int i = 0; i < amf.nodes.Count; i++)
        {
            if (amf.nodes[i].siblingIndex > -1)
            {
                bones[i].parent.SetSiblingIndex(amf.nodes[i].siblingIndex);
            }
        }
        bones.Insert(0, new GameObject("Root").transform);
        bones[1].parent        = bones[0];
        bones[0].localScale    = new Vector3(m_FileScaleFactor * globalScale, m_FileScaleFactor * globalScale, m_FileScaleFactor * globalScale);
        bones[0].localRotation = Quaternion.Euler(rigEulerRoot);//0,-90f,-90f);
        bones[0].localPosition = rigOffset;
        //bones[0].localPosition=Vector3.up;
        return(bones);
    }
示例#19
0
    static void readNodes(BinaryReader reader, AMF amf, bool skip = false)
    {
        int count = reader.ReadInt32();

        Debug.Log("Node count:" + count);
        long address = (long)reader.ReadInt32();
        //Debug.Log("Address:" + address);
        //Debug.Log("Current Pos:" + reader.BaseStream.Position);
        long            fPos  = reader.BaseStream.Position;
        List <AMF_Node> nodes = new List <AMF_Node>();

        if (count > 0 && !skip)
        {
            reader.BaseStream.Seek(address, SeekOrigin.Begin);
            for (int i = 0; i < count; i++)
            {
                string     name         = reader.ReadCString();
                short      parentIndex  = reader.ReadInt16();
                short      childIndex   = reader.ReadInt16();
                short      siblingIndex = reader.ReadInt16();
                Vector3    pos          = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                Quaternion rot          = new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                name = i.ToString().PadLeft(3, '0') + name;
                nodes.Add(new AMF_Node(name, parentIndex, childIndex, siblingIndex, pos, rot));
            }
            reader.BaseStream.Seek(fPos, SeekOrigin.Begin);
        }

        //if (count == 0)
        //{
        //    count = reader.ReadInt64();
        //    Debug.Log("Node count:" + count);
        //    address = reader.ReadInt64();
        //    Debug.Log("Address:" + address);
        //}

        //Debug.Log(ReadCString(reader));
    }
示例#20
0
        public void AMF_EncodeNamedStringTest()
        {
            AVal name = AVal.AVC("name"), val = AVal.AVC("val");

            byte[] buf = new byte[100];
            int    enc = 0, pend = buf.Length;
            int    len = 2 + 4 + 1 + 2 + 3; // "name".len + "name" + AMF_STRING + "val".len + "val"

            enc = AMF.AMF_EncodeNamedString(buf, enc, pend, name, val);
            Assert.AreEqual(len, enc);
            Assert.AreEqual(0x00, buf[0]);
            Assert.AreEqual(0x04, buf[1]);
            Assert.AreEqual('n', buf[2]);
            Assert.AreEqual('a', buf[3]);
            Assert.AreEqual('m', buf[4]);
            Assert.AreEqual('e', buf[5]);
            Assert.AreEqual((byte)AMFDataType.AMF_STRING, buf[6]);
            Assert.AreEqual(0x00, buf[7]);
            Assert.AreEqual(0x03, buf[8]);
            Assert.AreEqual('v', buf[9]);
            Assert.AreEqual('a', buf[10]);
            Assert.AreEqual('l', buf[11]);
            Assert.AreEqual(0x00, buf[12]);
        }
示例#21
0
    static void readShaders(BinaryReader reader, AMF amf, bool skip = false, bool dumpNames = false)
    {
        //ShaderInfo
        amf.shaderInfos = new List <AdjutantSharp.ShaderInfo>();
        //ShaderTypes
        List <int> shaderTypes = new List <int>();
        long       sCount      = reader.ReadInt32();

        Debug.Log("Shader Count:" + sCount);
        long sAddress   = reader.ReadInt32();
        long fPos       = reader.BaseStream.Position;
        int  debugCount = 0;

        if (sCount > 0)
        {
            reader.BaseStream.Seek(sAddress, SeekOrigin.Begin);
            for (int i = 0; i < sCount; i++)
            {
                string sName = reader.ReadCString();


                int sType = 0;
                if (sName.Substring(0, 1).Equals("*"))
                {
                    sType = 1;
                    sName = sName.Substring(1);
                }
                if (dumpNames)
                {
                    if (sType == 0)
                    {
                        Console.Write("Regular");
                    }
                    else
                    {
                        Console.Write("Terrain");
                    }
                    Debug.Log("Shader:" + sName + " tints:" + (amf.version > 1.1f));
                }
                shaderTypes.Add(sType);

                if (sType == 0)
                {
                    amf.shaderInfos.Add(new RegularShader(sName, reader, amf.version > 1.1f, (dumpNames && debugCount < 1)));
                    debugCount++;
                }
                else
                {
                    amf.shaderInfos.Add(new TerrainShader(sName, reader));
                    if (dumpNames && amf.shaderInfos[i].sName.Equals("cust_wall"))
                    {
                        TerrainShader ts = (TerrainShader)amf.shaderInfos[i];
                        Debug.Log("cust_wall");
                        for (int maps = 0; maps < ts.baseMaps.Count; maps++)
                        {
                            Debug.Log("[" + maps + "]:" + ts.baseMaps[maps] + " [" + ts.baseTiles[maps].x + "," + ts.baseTiles[maps].y + "] " + ts.detMaps[maps] + " " + ts.detTiles[maps].ToString());
                        }
                        Debug.Log("Blend tile:" + ts.blendPath + " " + ts.blendTile.ToString());
                    }
                }
            }
        }
        reader.BaseStream.Seek(fPos, SeekOrigin.Begin);
    }
示例#22
0
    static void readRegions(BinaryReader reader, AMF amf, bool skip = false)
    {
        int regionCount = reader.ReadInt32();

        Debug.Log("Region Count:" + regionCount);
        long regionAddress = reader.ReadInt32();
        long fPos          = reader.BaseStream.Position;

        amf.regionInfo = new List <AMF_RegionInfo>();
        //List <List<AMF_Permutations>>
        if (regionCount > 0 && !skip)
        {
            reader.BaseStream.Seek(regionAddress, SeekOrigin.Begin);
            for (int i = 0; i < regionCount; i++)
            {
                List <AMF_Permutations> permutations = new List <AMF_Permutations>();
                string regionName = reader.ReadCString();
                int    pCount     = reader.ReadInt32();
                long   pAddress   = reader.ReadInt32();
                long   pPos       = reader.BaseStream.Position;
                if (pCount > 0)
                {
                    reader.BaseStream.Seek(pAddress, SeekOrigin.Begin);
                    for (int j = 0; j < pCount; j++)
                    {
                        string pName = reader.ReadCString();

                        sbyte vTemp    = reader.ReadSByte();
                        byte  nIndex   = reader.ReadByte();
                        int   vCount   = reader.ReadInt32();
                        long  vAddress = reader.ReadInt32();
                        int   fCount   = reader.ReadInt32();
                        long  fAddress = reader.ReadInt32();
                        int   sCount   = reader.ReadInt32();
                        long  sAddress = reader.ReadInt32();
                        //Debug.LogFormat("vTemp {0}",vTemp.ToString());
                        int   vFormat = vTemp & 15;
                        int   cFormat = (vTemp & 240) >> 4;
                        float mult    = 0f;
                        //Debug.LogFormat("Parse Permutation: {0} - {1}v-{2}f-{3}s",pName,vCount,fCount,sCount);

                        //transform = matrix3 1      ???
                        Matrix4x4 trnsfm = Matrix4x4.identity;

                        if (amf.version > 0.1)
                        {
                            mult = reader.ReadSingle();
                            //NANI?!
                            if (!float.IsNaN(mult))
                            {
                                trnsfm = reader.ReadMatrix4x4(true);  //new Matrix4x4(reader.ReadVector4(0f),reader.ReadVector4(0f),reader.ReadVector4(0f),reader.ReadVector4(0f));
                                //transform = new Matrix4x4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), 1.0f, reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), 1.0f, reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), 1.0f, reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), 1.0f);
                                //3DS uses a 4x3 so we need to pad an extra column for the identity
                                trnsfm.m33 = 1;
                            }
                        }
                        long xPos  = reader.BaseStream.Position;
                        bool vDone = false;
                        bool fDone = false;
                        List <AMF_Vertex> vertices = new List <AMF_Vertex>();
                        Matrix4x4         vMat     = Matrix4x4.identity;
                        List <Vector3Int> faces    = null;
                        foreach (AMF_Permutations permX in permutations)
                        {
                            //do some weird copy verts thing
                            if (permX.vAddress == vAddress && !vDone)
                            {
                                //not really a copy, it's actually just caclulating vMat
                                //but I'm trying to preserve the original script as much
                                //as possible before refactoring
                                vMat     = copyVertices(reader, permX.vertices, cFormat);
                                vertices = permX.vertices;
                                vDone    = true;
                            }
                            if (permX.fAddress == fAddress && !fDone)
                            {
                                faces = permX.faces;
                                fDone = true;
                            }
                            if (vDone && fDone)
                            {
                                break;
                            }
                        }
                        List <Vector2> bounds = new List <Vector2>();
                        if (!vDone)
                        {
                            reader.BaseStream.Seek(vAddress, SeekOrigin.Begin);
                            vMat = readVertices(reader, vFormat, cFormat, vCount, vertices, bounds);
                            //verts list = readVertices vFormat,cFormat,vCount
                        }

                        if (!fDone)
                        {
                            reader.BaseStream.Seek(fAddress, SeekOrigin.Begin);
                            //faces list = readFaces vCount,fCount
                            faces = readFaces(reader, vCount, fCount);
                        }
                        reader.BaseStream.Seek(sAddress, SeekOrigin.Begin);
                        List <AMF_Mesh> meshes = readMeshes(reader, sCount);

                        /* Debug.LogFormat("vMat:{0}",vMat);
                         * Debug.LogFormat("trnsfm:{0}",trnsfm); */

                        //meshes list = readMeshes sCount
                        //vMat*trnsfm
                        permutations.Add(new AMF_Permutations(pName, vFormat, nIndex, vertices, faces, meshes, vAddress, fAddress, mult, vMat * trnsfm, bounds, cFormat));

                        //permutations[j].DebugCheck();
                        reader.BaseStream.Seek(xPos, SeekOrigin.Begin);
                    }
                }


                amf.regionInfo.Add(new AMF_RegionInfo(regionName, permutations));
                reader.BaseStream.Seek(pPos, SeekOrigin.Begin);
            }
        }
        reader.BaseStream.Seek(fPos, SeekOrigin.Begin);
    }
示例#23
0
 static void readHeader(BinaryReader reader, AMF amf)
 {
     amf.header    = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(4));
     amf.version   = reader.ReadSingle();
     amf.modelName = reader.ReadCString();
 }
示例#24
0
    public override void OnImportAsset(AssetImportContext ctx)
    {
        /* if(amf!=null&&!shouldReimport)
         *  return; */
        Debug.Log("Attempting to import AMF:" + ctx.assetPath);

        EditorUtility.DisplayProgressBar("Parsing" + ctx.assetPath, "Parsing...", 0);
        this.amf = ParseAMF(ctx.assetPath);

        string workingDir = ctx.assetPath.Substring(0, ctx.assetPath.LastIndexOf("/") + 1);

        /*
         * Setup materials first
         */
        Dictionary <string, Material>      mats        = new Dictionary <string, Material>();
        Dictionary <string, AMFShaderInfo> matsHelpers = new Dictionary <string, AMFShaderInfo>();

        System.IO.Directory.CreateDirectory(workingDir + "Materials/");
        //System.IO.Directory.CreateDirectory(workingDir+"MaterialHelpers/");
        AMFShaderInfo asi;
        float         totalMats    = amf.shaderInfos.Count;
        float         matsComplete = 0;

        foreach (AdjutantSharp.ShaderInfo si in amf.shaderInfos)
        {
            EditorUtility.DisplayProgressBar("Setting up Materials...", si.sName, (matsComplete / totalMats));
            asi      = (AMFShaderInfo)AMFShaderInfo.CreateInstance(typeof(AMFShaderInfo));
            asi.name = si.sName;
            asi.SaveData(si);
            if (!mats.ContainsKey(si.sName))
            {
                string   path     = workingDir + "Materials/" + si.sName + ".mat";
                Material material = (Material)AssetDatabase.LoadAssetAtPath(workingDir + "Materials/" + si.sName + ".mat", typeof(Material));

                if (material == null)
                {
                    asi.workingDir = workingDir;
                    material       = asi.CreateMaterial();

                    /* if(si.GetType()==typeof(RegularShader)){
                     *  material=SetupRegularMaterial((RegularShader)si,workingDir);
                     * }else{
                     *  material=SetupTerrainMaterial((TerrainShader)si,workingDir);
                     * } */

                    AssetDatabase.CreateAsset(material, workingDir + "Materials/" + si.sName + ".mat");
                }



                mats.Add(si.sName, material);
                matsHelpers.Add(si.sName, asi);
                ctx.AddObjectToAsset("MaterialHelper-" + asi.sName, asi);
                ctx.DependsOnSourceAsset(workingDir + "Materials/" + si.sName + ".mat");

                /* if(material!=null)
                 *  ctx.AddObjectToAsset(material.name,material); */
            }
            matsComplete++;
        }

        /*
         * Create Meshes
         */

        GameObject root = new GameObject(amf.modelName);

        //amf.name=amf.modelName+"-RawAMF";
        ctx.AddObjectToAsset(amf.modelName, root);

        /* ctx.AddObjectToAsset(amf.name,amf);
         * EditorUtility.SetDirty(amf); */
        ctx.SetMainObject(root);
        Dictionary <long, Mesh> meshList = ConvertMeshes(amf, mats, matsHelpers, root);

        EditorUtility.DisplayProgressBar("Parsing " + ctx.assetPath, "[5/5] Finishing up...", (5f / 5f));
        foreach (Mesh m in meshList.Values)
        {
            ctx.AddObjectToAsset(m.name, m);
        }
        if (CreateSkinnedMeshes)
        {
            Avatar a = root.GetComponent <Animator>().avatar;
            ctx.AddObjectToAsset(a.name, a);
        }


        Debug.Log("AMF import complete");
        EditorUtility.ClearProgressBar();
        shouldReimport = false;
    }
示例#25
0
    /*
     *
     * Convert Meshes
     */
    public Dictionary <long, Mesh> ConvertMeshes(AMF amf, Dictionary <string, Material> mats, Dictionary <string, AMFShaderInfo> matHelpers, GameObject root)
    {
        //List<Mesh> meshList = new List<Mesh>();
        Dictionary <long, Mesh> meshCache = new Dictionary <long, Mesh>();
        float             meshComplete    = 0;
        float             totalMeshCount  = 0;
        List <GameObject> meshNodes       = new List <GameObject>();
        List <Transform>  nodes           = null;

        if (CreateSkinnedMeshes)
        {
            nodes           = CreateRigging(amf);
            nodes[0].parent = root.transform;
            Animator anim = root.AddComponent <Animator>();
            //Transform rigRoot=root.GetComponentInChildren<SkinnedMeshRenderer>().rootBone;
            if (copyAvatar)
            {
                //ctx.AddObjectToAsset(m_LastHumanDescriptionAvatarSource.name,m_LastHumanDescriptionAvatarSource);
                anim.avatar = m_LastHumanDescriptionAvatarSource;
            }
            else
            {
                //EditorUtility.DisplayProgressBar("Parsing "+ctx.assetPath,"Creating Avatar",(5f/5f));
                List <string>    reports = new List <string>();
                HumanDescription hd      = new HumanDescription();
                AvatarSetupTool.SkeletonBone[] skeletonBones;
                bool hasTranslationDOF;
                reports = AvatarSetupTool.SetupHumanSkeleton(nodes[0].parent.gameObject, ref hd.human, out skeletonBones, out hasTranslationDOF);
                hd.hasTranslationDoF = hasTranslationDOF;
                SkeletonBone[] sb = new SkeletonBone[skeletonBones.Length + 1];
                Array.Copy(Array.ConvertAll(skeletonBones, (p => (SkeletonBone)p)), sb, sb.Length - 1);
                sb[sb.Length - 1].name     = nodes[0].parent.name;
                sb[sb.Length - 1].position = nodes[0].parent.localPosition;
                sb[sb.Length - 1].rotation = nodes[0].parent.localRotation;
                sb[sb.Length - 1].scale    = nodes[0].parent.localScale;
                hd.skeleton = sb;
                Avatar a;
                if (rigType == RigType.Humanoid)
                {
                    a = AvatarBuilder.BuildHumanAvatar(nodes[0].parent.gameObject, hd);
                }
                else
                {
                    a = AvatarBuilder.BuildGenericAvatar(nodes[0].parent.gameObject, nodes[0].parent.name);
                }
                a.name = root.name + "Avatar";
                //ctx.AddObjectToAsset(a.name,a);
                anim.avatar = a;
            }
        }


        foreach (AMF_RegionInfo ri in amf.regionInfo)
        {
            totalMeshCount += ri.permutations.Count;
        }

        for (int ri = 0; ri < amf.regionInfo.Count; ri++)
        {
            GameObject riNode = new GameObject(amf.regionInfo[ri].name);
            GameObjectUtility.SetParentAndAlign(riNode, root);
            foreach (AMF_Permutations perm in amf.regionInfo[ri].permutations)
            {
                EditorUtility.DisplayProgressBar("Creating Meshes", perm.pName, (meshComplete / totalMeshCount));
                Mesh temp;
                if (createDuplicateInstances || !meshCache.ContainsKey(perm.vAddress))
                {
                    temp = ConvertInstanceToMesh(perm);
                    //we have to flip the normals due to the coordinate system translation
                    temp.FlipNormals();
                    temp.RecalculateNormals();
                    if (GenerateLightmapUVs)
                    {
                        EditorUtility.DisplayProgressBar("Generating Lightmap UVs", perm.pName, (meshComplete / totalMeshCount));
                        uvSettings.angleError = angleError;
                        uvSettings.areaError  = areaError;
                        uvSettings.hardAngle  = hardAngle;
                        uvSettings.packMargin = packMargin;
                        Unwrapping.GenerateSecondaryUVSet(temp, uvSettings);
                    }
                    meshCache.Add(perm.vAddress, temp);
                }
                else
                {
                    temp = meshCache[perm.vAddress];
                }
                GameObject meshNode = new GameObject(perm.pName);
                Matrix4x4  matr     = Matrix4x4.identity;
                if (!float.IsNaN(perm.mult))
                {
                    Matrix4x4 scalerM = new Matrix4x4();
                    scalerM.SetRow(0, new Vector4(100f * m_FileScaleFactor, 0));
                    scalerM.SetRow(1, new Vector4(0, 100f * m_FileScaleFactor));
                    scalerM.SetRow(2, new Vector4(0, 0, 100f * m_FileScaleFactor));
                    scalerM.SetRow(3, new Vector4(0, 0, 0, 1));
                    matr.SetRow(0, new Vector4(perm.mult, 0));
                    matr.SetRow(1, new Vector4(0, perm.mult));
                    matr.SetRow(2, new Vector4(0, 0, perm.mult));
                    matr.SetRow(3, new Vector4(0, 0, 0, 1));
                    matr *= perm.matrix4x4;
                    matr *= scalerM;
                    Matrix4x4 unityMatr = matr.Convert3DSMatrixToUnity();
                    meshNode.transform.localScale    = unityMatr.ExtractScale();
                    meshNode.transform.localRotation = unityMatr.GetRotation();
                    meshNode.transform.localPosition = unityMatr.ExtractPosition();
                }
                else
                {
                    meshNode.transform.localScale = new Vector3(m_FileScaleFactor, m_FileScaleFactor, m_FileScaleFactor);
                }

                //GameObjectUtility.SetParentAndAlign(meshNode,riNode);

                //meshNode.transform.localToWorldMatrix=matr;


                Renderer mr;
                if (temp.boneWeights.Length > 0 && CreateSkinnedMeshes)
                {
                    mr = meshNode.AddComponent <SkinnedMeshRenderer>();
                    meshNode.transform.localRotation = Quaternion.Euler(0, 90, 0);
                    Matrix4x4[] bindPoses = new Matrix4x4[nodes.Count];
                    for (int m = 0; m < bindPoses.Length; m++)
                    {
                        bindPoses[m] = nodes[m].worldToLocalMatrix * meshNode.transform.localToWorldMatrix;
                    }
                    temp.bindposes = bindPoses;
                    ((SkinnedMeshRenderer)mr).sharedMesh = temp;
                    ((SkinnedMeshRenderer)mr).bones      = nodes.ToArray();
                    ((SkinnedMeshRenderer)mr).rootBone   = nodes[0];
                }
                else
                {
                    MeshFilter mf = meshNode.AddComponent <MeshFilter>();
                    mf.sharedMesh = temp;
                    mr            = meshNode.AddComponent <MeshRenderer>();
                    if (RecenterPivots && !splitSubmeshes)
                    {
                        //for safety, lets guard this against splitting submeshes.
                        mf.RecenterPivot();
                    }
                }


                meshNode.transform.parent = riNode.transform;
                if (GenerateMeshCollidersOnClusters && amf.regionInfo[ri].name.Equals("Clusters"))
                {
                    MeshCollider mc = meshNode.AddComponent <MeshCollider>();
                    mc.sharedMesh = temp;
                }
                Material[]           materials = new Material[temp.subMeshCount];
                List <AMFShaderInfo> si        = new List <AMFShaderInfo>();
                for (int i = 0; i < materials.Length; i++)
                {
                    materials[i] = mats[amf.shaderInfos[perm.meshes[i].shaderIndex].sName];
                    si.Add(matHelpers[amf.shaderInfos[perm.meshes[i].shaderIndex].sName]);
                    //si[i].SaveData(amf.shaderInfos[perm.meshes[i].shaderIndex]);
                }
                mr.sharedMaterials = materials;



                AMFMaterialHelper mh = meshNode.AddComponent <AMFMaterialHelper>();
                mh.shaderSettings = si;

                //mh.SaveData(amf.shaderInfos[perm.meshes[0].shaderIndex]);
                //Debug.LogFormat("Transform: Pos:{0} Rot:{1} Scale:{2}",perm.matrix4x4.ExtractPosition(),perm.matrix4x4.ExtractRotation(),perm.matrix4x4.ExtractScale());
                meshComplete++;
                meshNodes.Add(meshNode);
            }
        }

        //This is annoying to do this here, but we have to wait until after the mesh cache is fully populated before we start splitting submeshes out.
        if (splitSubmeshes)
        {
            meshCache.Clear();
            long fakeKey = 0;
            foreach (GameObject go in meshNodes)
            {
                MeshFilter mf = go.GetComponent <MeshFilter>();
                if (mf != null && mf.sharedMesh.subMeshCount > 1)
                {
                    Renderer r = go.GetComponent <MeshRenderer>();
                    for (int i = 0; i < mf.sharedMesh.subMeshCount; i++)
                    {
                        int        matIndex = Mathf.Min(i, r.sharedMaterials.Length);
                        GameObject tempGo   = new GameObject(go.name + "_" + r.sharedMaterials[matIndex].name);
                        MeshFilter tempMF   = tempGo.AddComponent <MeshFilter>();
                        tempMF.sharedMesh = mf.sharedMesh.ExtractSubmesh(i);

                        tempGo.AddComponent <MeshRenderer>().sharedMaterial = r.sharedMaterials[matIndex];
                        GameObjectUtility.SetParentAndAlign(tempGo, go);
                        if (RecenterPivots)
                        {
                            tempMF.RecenterPivot();
                        }
                        meshCache.Add(fakeKey, tempGo.GetComponent <MeshFilter>().sharedMesh);
                        fakeKey++;
                    }
                    DestroyImmediate(mf);
                    DestroyImmediate(r);
                }
                else
                {
                    if (RecenterPivots)
                    {
                        go.GetComponent <MeshFilter>().RecenterPivot();
                    }
                    meshCache.Add(fakeKey, go.GetComponent <MeshFilter>().sharedMesh);
                    fakeKey++;
                }
            }
        }

        return(meshCache);
    }
示例#26
0
    public override void OnImportAsset(AssetImportContext ctx)
    {
        Debug.Log("Attempting to import AMF:" + ctx.assetPath);
        progressString += ctx.assetPath;
        EditorUtility.DisplayProgressBar(progressString, "Parsing...", 0);
        AMF amf = ParseAMF(ctx.assetPath);

        string workingDir = ctx.assetPath.Substring(0, ctx.assetPath.LastIndexOf("/") + 1);

        /*
         * Setup materials first
         */
        Dictionary <string, Material>      mats        = new Dictionary <string, Material>();
        Dictionary <string, AMFShaderInfo> matsHelpers = new Dictionary <string, AMFShaderInfo>();

        System.IO.Directory.CreateDirectory(workingDir + "Materials/");
        //System.IO.Directory.CreateDirectory(workingDir+"MaterialHelpers/");
        AMFShaderInfo asi;
        float         totalMats    = amf.shaderInfos.Count;
        float         matsComplete = 0;

        foreach (AdjutantSharp.ShaderInfo si in amf.shaderInfos)
        {
            EditorUtility.DisplayProgressBar("Setting up Materials...", si.sName, (matsComplete / totalMats));
            asi      = (AMFShaderInfo)AMFShaderInfo.CreateInstance(typeof(AMFShaderInfo));
            asi.name = si.sName;
            asi.SaveData(si);
            if (!mats.ContainsKey(si.sName))
            {
                string   path     = workingDir + "Materials/" + si.sName + ".mat";
                Material material = (Material)AssetDatabase.LoadAssetAtPath(workingDir + "Materials/" + si.sName + ".mat", typeof(Material));

                if (material == null)
                {
                    asi.workingDir = workingDir;
                    material       = asi.CreateMaterial();

                    /* if(si.GetType()==typeof(RegularShader)){
                     *  material=SetupRegularMaterial((RegularShader)si,workingDir);
                     * }else{
                     *  material=SetupTerrainMaterial((TerrainShader)si,workingDir);
                     * } */

                    AssetDatabase.CreateAsset(material, workingDir + "Materials/" + si.sName + ".mat");
                }



                mats.Add(si.sName, material);
                matsHelpers.Add(si.sName, asi);
                ctx.AddObjectToAsset("MaterialHelper-" + asi.sName, asi);
                ctx.DependsOnSourceAsset(workingDir + "Materials/" + si.sName + ".mat");

                /* if(material!=null)
                 *  ctx.AddObjectToAsset(material.name,material); */
            }
            matsComplete++;
        }
        //EditorUtility.DisplayProgressBar(progressString,"[4/5] Creating Meshes...",(4f/5f));

        /*
         * Create Meshes
         */

        GameObject root = new GameObject(amf.modelName);

        ctx.AddObjectToAsset(amf.modelName, root);
        ctx.SetMainObject(root);
        Dictionary <long, Mesh> meshList = ConvertMeshes(amf, mats, matsHelpers, root);

        //root.transform.rotation=Quaternion.Euler(-90f,0f,0f);

        /* LoadRegions(amf,root);
         * List<Mesh> meshList=CreateMeshes(amf,root.transform,mats);
         */
        UnwrapParam.SetDefaults(out uvSettings);
        EditorUtility.DisplayProgressBar(progressString, "[5/5] Finishing up...", (5f / 5f));
        float lightCount = 0;
        float totalLight = meshList.Count;

        foreach (Mesh m in meshList.Values)
        {
            /* if(GenerateLightmapUVs){
             *  EditorUtility.DisplayProgressBar("Generating Lightmaps","["+lightCount+"/"+totalLight+"] Generating UVs...",(lightCount/totalLight));
             *  Unwrapping.GenerateSecondaryUVSet(m,uvSettings);
             *  lightCount++;
             * } */
            ctx.AddObjectToAsset(m.name, m);
        }

        Debug.Log("AMF import complete");
        EditorUtility.ClearProgressBar();
    }
示例#27
0
    /*
     *
     * Convert Meshes
     */
    public Dictionary <long, Mesh> ConvertMeshes(AMF amf, Dictionary <string, Material> mats, Dictionary <string, AMFShaderInfo> matHelpers, GameObject root)
    {
        //List<Mesh> meshList = new List<Mesh>();
        Dictionary <long, Mesh> meshCache = new Dictionary <long, Mesh>();
        float meshComplete   = 0;
        float totalMeshCount = 0;

        foreach (AMF_RegionInfo ri in amf.regionInfo)
        {
            totalMeshCount += ri.permutations.Count;
        }

        for (int ri = 0; ri < amf.regionInfo.Count; ri++)
        {
            GameObject riNode = new GameObject(amf.regionInfo[ri].name);
            GameObjectUtility.SetParentAndAlign(riNode, root);
            foreach (AMF_Permutations perm in amf.regionInfo[ri].permutations)
            {
                EditorUtility.DisplayProgressBar("Creating Meshes", perm.pName, (meshComplete / totalMeshCount));
                Mesh temp;
                if (createDuplicateInstances || !meshCache.ContainsKey(perm.vAddress))
                {
                    temp      = new Mesh();
                    temp.name = perm.pName;
                    List <Vector3> verts    = new List <Vector3>();
                    List <Vector2> uvs      = new List <Vector2>();
                    List <int>     badIndex = new List <int>();
                    int[]          identity = new int[perm.vertices.Count];



                    //matr=matr.ConvertHandedness();
                    Matrix4x4 texMatrix = Matrix4x4.identity;
                    for (int i = 0; i < perm.vertices.Count; i++)
                    {
                        Vector3 pos = perm.vertices[i].pos;
                        identity[i] = i;
                        //pos=perm.matrix4x4*pos;
                        if (pos.IsBad())
                        {
                            Debug.LogErrorFormat("Invalid vertex found: [{0}]" + perm.vertices[i].pos.ToString(), i);
                            badIndex.Add(i);
                            verts.Add(Vector3.zero);
                            uvs.Add(Vector2.zero);
                        }
                        else
                        {
                            if (!float.IsNaN(perm.mult))
                            {
                                Matrix4x4 flip = Matrix4x4.identity;
                                flip.SetRow(0, new Vector4(-1, 0));
                                verts.Add(flip.MultiplyPoint3x4(pos));
                            }
                            else
                            {
                                //verts.Add(Matrix4x4.identity.Convert3DSMatrixToUnity().MultiplyPoint3x4(pos));
                                Matrix4x4 flip = Matrix4x4.identity;
                                flip.SetRow(0, new Vector4(-1, 0));
                                flip.SetRow(1, new Vector4(0, 0, 1));
                                flip.SetRow(2, new Vector4(0, -1));
                                verts.Add(flip.MultiplyPoint3x4(pos));
                            }

                            uvs.Add(perm.vertices[i].tex);
                            texMatrix = perm.vertices[i].tmat;
                        }
                    }
                    temp.SetVertices(verts);
                    temp.SetUVs(0, uvs);
                    List <int> tris;
                    int        faceTotal = 0;
                    temp.subMeshCount = perm.meshes.Count;
                    /* temp.SetIndices(identity,MeshTopology.Points,0); */
                    // Debug.LogFormat("{0} adding submeshes",perm.pName);
                    for (int s = 0; s < perm.meshes.Count; s++)
                    {
                        AMF_Mesh sinfo = perm.meshes[s];
                        faceTotal += sinfo.faceCount;
                        tris       = new List <int>();
                        // Debug.LogFormat("{0}:{1}-{2}",s,sinfo.startingFace,sinfo.faceCount);
                        for (int f = 0; f < sinfo.faceCount; f++)
                        {
                            Vector3Int face = perm.faces[f + sinfo.startingFace];
                            if (badIndex.Contains(face.x) || badIndex.Contains(face.y) || badIndex.Contains(face.z))
                            {
                                // Debug.LogWarning("Dumping face due to invalid vertex");
                            }
                            else
                            {
                                tris.Add(face.x);
                                tris.Add(face.y);
                                tris.Add(face.z);
                            }
                        }
                        //Debug.LogFormat("{0} Setting {1} triangles",s,tris.Count);
                        temp.SetTriangles(tris, s);
                    }
                    if (perm.faces.Count != faceTotal)
                    {
                        Debug.LogErrorFormat("Faces mistmatch: {0}vs{1} {2}", perm.faces.Count, faceTotal, perm.pName);
                    }
                    //if(!float.IsNaN(perm.mult)){
                    temp.FlipNormals();
                    //}

                    temp.RecalculateNormals();
                    if (GenerateLightmapUVs)
                    {
                        Unwrapping.GenerateSecondaryUVSet(temp);
                    }
                    meshCache.Add(perm.vAddress, temp);
                }
                else
                {
                    temp = meshCache[perm.vAddress];
                }
                GameObject meshNode = new GameObject(perm.pName);
                Matrix4x4  matr     = Matrix4x4.identity;
                if (!float.IsNaN(perm.mult))
                {
                    Matrix4x4 scalerM = new Matrix4x4();
                    scalerM.SetRow(0, new Vector4(100f * importScale, 0));
                    scalerM.SetRow(1, new Vector4(0, 100f * importScale));
                    scalerM.SetRow(2, new Vector4(0, 0, 100f * importScale));
                    scalerM.SetRow(3, new Vector4(0, 0, 0, 1));
                    matr.SetRow(0, new Vector4(perm.mult, 0));
                    matr.SetRow(1, new Vector4(0, perm.mult));
                    matr.SetRow(2, new Vector4(0, 0, perm.mult));
                    matr.SetRow(3, new Vector4(0, 0, 0, 1));
                    matr *= perm.matrix4x4;
                    matr *= scalerM;
                    Matrix4x4 unityMatr = matr.Convert3DSMatrixToUnity();
                    meshNode.transform.localScale    = unityMatr.ExtractScale();
                    meshNode.transform.localRotation = unityMatr.GetRotation();
                    meshNode.transform.localPosition = unityMatr.ExtractPosition();
                }
                else
                {
                    meshNode.transform.localScale = new Vector3(importScale, importScale, importScale);
                }

                //GameObjectUtility.SetParentAndAlign(meshNode,riNode);

                //meshNode.transform.localToWorldMatrix=matr;

                MeshFilter mf = meshNode.AddComponent <MeshFilter>();
                mf.sharedMesh = temp;
                MeshRenderer mr = meshNode.AddComponent <MeshRenderer>();

                meshNode.transform.parent = riNode.transform;
                if (GenerateMeshCollidersOnClusters && amf.regionInfo[ri].name.Equals("Clusters"))
                {
                    MeshCollider mc = meshNode.AddComponent <MeshCollider>();
                    mc.sharedMesh = mf.sharedMesh;
                }
                Material[]           materials = new Material[temp.subMeshCount];
                List <AMFShaderInfo> si        = new List <AMFShaderInfo>();
                for (int i = 0; i < materials.Length; i++)
                {
                    materials[i] = mats[amf.shaderInfos[perm.meshes[i].shaderIndex].sName];
                    si.Add(matHelpers[amf.shaderInfos[perm.meshes[i].shaderIndex].sName]);
                    //si[i].SaveData(amf.shaderInfos[perm.meshes[i].shaderIndex]);
                }
                mr.sharedMaterials = materials;
                AMFMaterialHelper mh = meshNode.AddComponent <AMFMaterialHelper>();
                mh.shaderSettings = si;

                //mh.SaveData(amf.shaderInfos[perm.meshes[0].shaderIndex]);
                //Debug.LogFormat("Transform: Pos:{0} Rot:{1} Scale:{2}",perm.matrix4x4.ExtractPosition(),perm.matrix4x4.ExtractRotation(),perm.matrix4x4.ExtractScale());
                meshComplete++;
            }
        }

        return(meshCache);
    }