Example #1
0
        public static int doSubmeshesShareVertsOrTris(Mesh m, ref MB_Utility.MeshAnalysisResult mar)
        {
            MB_Utility.MB_Triangle mb_Triangle  = new MB_Utility.MB_Triangle();
            MB_Utility.MB_Triangle mb_Triangle2 = new MB_Utility.MB_Triangle();
            int[][] array = new int[m.subMeshCount][];
            for (int i = 0; i < m.subMeshCount; i++)
            {
                array[i] = m.GetTriangles(i);
            }
            bool flag  = false;
            bool flag2 = false;

            for (int j = 0; j < m.subMeshCount; j++)
            {
                int[] array2 = array[j];
                for (int k = j + 1; k < m.subMeshCount; k++)
                {
                    int[] array3 = array[k];
                    for (int l = 0; l < array2.Length; l += 3)
                    {
                        mb_Triangle.Initialize(array2, l, j);
                        for (int n = 0; n < array3.Length; n += 3)
                        {
                            mb_Triangle2.Initialize(array3, n, k);
                            if (mb_Triangle.isSame(mb_Triangle2))
                            {
                                flag2 = true;
                                break;
                            }
                            if (mb_Triangle.sharesVerts(mb_Triangle2))
                            {
                                flag = true;
                                break;
                            }
                        }
                    }
                }
            }
            if (flag2)
            {
                mar.hasOverlappingSubmeshVerts = true;
                mar.hasOverlappingSubmeshTris  = true;
                return(2);
            }
            if (flag)
            {
                mar.hasOverlappingSubmeshVerts = true;
                mar.hasOverlappingSubmeshTris  = false;
                return(1);
            }
            mar.hasOverlappingSubmeshTris  = false;
            mar.hasOverlappingSubmeshVerts = false;
            return(0);
        }
Example #2
0
        public void SuggestTreatment(List <GameObject> objsToMesh, Material[] resultMaterials, List <ShaderTextureProperty> _customShaderPropNames)
        {
            this._customShaderPropNames = _customShaderPropNames;
            StringBuilder sb = new StringBuilder();
            Dictionary <int, MB_Utility.MeshAnalysisResult[]> meshAnalysisResultsCache = new Dictionary <int, MB_Utility.MeshAnalysisResult[]>(); //cache results

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                GameObject obj = objsToMesh[i];
                if (obj == null)
                {
                    continue;
                }
                Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
                if (ms.Length > 1)
                { // and each material is not mapped to its own layer
                    sb.AppendFormat("\nObject {0} uses {1} materials. Possible treatments:\n", objsToMesh[i].name, ms.Length);
                    sb.AppendFormat("  1) Collapse the submeshes together into one submesh in the combined mesh. Each of the original submesh materials will map to a different UV rectangle in the atlas(es) used by the combined material.\n");
                    sb.AppendFormat("  2) Use the multiple materials feature to map submeshes in the source mesh to submeshes in the combined mesh.\n");
                }
                Mesh m = MB_Utility.GetMesh(obj);

                MB_Utility.MeshAnalysisResult[] mar;
                if (!meshAnalysisResultsCache.TryGetValue(m.GetInstanceID(), out mar))
                {
                    mar = new MB_Utility.MeshAnalysisResult[m.subMeshCount];
                    MB_Utility.doSubmeshesShareVertsOrTris(m, ref mar[0]);
                    for (int j = 0; j < m.subMeshCount; j++)
                    {
                        MB_Utility.hasOutOfBoundsUVs(m, ref mar[j], j);
                        //DRect outOfBoundsUVRect = new DRect(mar[j].uvRect);
                        mar[j].hasOverlappingSubmeshTris  = mar[0].hasOverlappingSubmeshTris;
                        mar[j].hasOverlappingSubmeshVerts = mar[0].hasOverlappingSubmeshVerts;
                    }
                    meshAnalysisResultsCache.Add(m.GetInstanceID(), mar);
                }

                for (int j = 0; j < ms.Length; j++)
                {
                    if (mar[j].hasOutOfBoundsUVs)
                    {
                        DRect r = new DRect(mar[j].uvRect);
                        sb.AppendFormat("\nObject {0} submesh={1} material={2} uses UVs outside the range 0,0 .. 1,1 to create tiling that tiles the box {3},{4} .. {5},{6}. This is a problem because the UVs outside the 0,0 .. 1,1 " +
                                        "rectangle will pick up neighboring textures in the atlas. Possible Treatments:\n", obj, j, ms[j], r.x.ToString("G4"), r.y.ToString("G4"), (r.x + r.width).ToString("G4"), (r.y + r.height).ToString("G4"));
                        sb.AppendFormat("    1) Ignore the problem. The tiling may not affect result significantly.\n");
                        sb.AppendFormat("    2) Use the 'fix out of bounds UVs' feature to bake the tiling and scale the UVs to fit in the 0,0 .. 1,1 rectangle.\n");
                        sb.AppendFormat("    3) Use the Multiple Materials feature to map the material on this submesh to its own submesh in the combined mesh. No other materials should map to this submesh. This will result in only one texture in the atlas(es) and the UVs should tile correctly.\n");
                        sb.AppendFormat("    4) Combine only meshes that use the same (or subset of) the set of materials on this mesh. The original material(s) can be applied to the result\n");
                    }
                }
                if (mar[0].hasOverlappingSubmeshVerts)
                {
                    sb.AppendFormat("\nObject {0} has submeshes that share vertices. This is a problem because each vertex can have only one UV coordinate and may be required to map to different positions in the various atlases that are generated. Possible treatments:\n", objsToMesh[i]);
                    sb.AppendFormat(" 1) Ignore the problem. The vertices may not affect the result.\n");
                    sb.AppendFormat(" 2) Use the Multiple Materials feature to map the submeshs that overlap to their own submeshs in the combined mesh. No other materials should map to this submesh. This will result in only one texture in the atlas(es) and the UVs should tile correctly.\n");
                    sb.AppendFormat(" 3) Combine only meshes that use the same (or subset of) the set of materials on this mesh. The original material(s) can be applied to the result\n");
                }
            }
            Dictionary <Material, List <GameObject> > m2gos = new Dictionary <Material, List <GameObject> >();

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                if (objsToMesh[i] != null)
                {
                    Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
                    for (int j = 0; j < ms.Length; j++)
                    {
                        if (ms[j] != null)
                        {
                            List <GameObject> lgo;
                            if (!m2gos.TryGetValue(ms[j], out lgo))
                            {
                                lgo = new List <GameObject>();
                                m2gos.Add(ms[j], lgo);
                            }
                            if (!lgo.Contains(objsToMesh[i]))
                            {
                                lgo.Add(objsToMesh[i]);
                            }
                        }
                    }
                }
            }

            for (int i = 0; i < resultMaterials.Length; i++)
            {
                string resultMatShaderName = resultMaterials[i] != null ? "None" : resultMaterials[i].shader.name;
                MB3_TextureCombinerPipeline.TexturePipelineData data = LoadPipelineData(resultMaterials[i], new List <ShaderTextureProperty>(), objsToMesh, new List <Material>(), new List <MB_TexSet>());
                MB3_TextureCombinerPipeline._CollectPropertyNames(data, LOG_LEVEL);
                foreach (Material m in m2gos.Keys)
                {
                    for (int j = 0; j < data.texPropertyNames.Count; j++)
                    {
                        if (m.HasProperty(data.texPropertyNames[j].name))
                        {
                            Texture txx = MB3_TextureCombinerPipeline.GetTextureConsideringStandardShaderKeywords(resultMatShaderName, m, data.texPropertyNames[j].name);
                            if (txx != null)
                            {
                                Vector2 o = m.GetTextureOffset(data.texPropertyNames[j].name);
                                Vector3 s = m.GetTextureScale(data.texPropertyNames[j].name);
                                if (o.x < 0f || o.x + s.x > 1f ||
                                    o.y < 0f || o.y + s.y > 1f)
                                {
                                    sb.AppendFormat("\nMaterial {0} used by objects {1} uses texture {2} that is tiled (scale={3} offset={4}). If there is more than one texture in the atlas " +
                                                    " then Mesh Baker will bake the tiling into the atlas. If the baked tiling is large then quality can be lost. Possible treatments:\n", m, PrintList(m2gos[m]), txx, s, o);
                                    sb.AppendFormat("  1) Use the baked tiling.\n");
                                    sb.AppendFormat("  2) Use the Multiple Materials feature to map the material on this object/submesh to its own submesh in the combined mesh. No other materials should map to this submesh. The original material can be applied to this submesh.\n");
                                    sb.AppendFormat("  3) Combine only meshes that use the same (or subset of) the set of textures on this mesh. The original material can be applied to the result.\n");
                                }
                            }
                        }
                    }
                }
            }
            string outstr = "";

            if (sb.Length == 0)
            {
                outstr = "====== No problems detected. These meshes should combine well ====\n  If there are problems with the combined meshes please report the problem to digitalOpus.ca so we can improve Mesh Baker.";
            }
            else
            {
                outstr = "====== There are possible problems with these meshes that may prevent them from combining well. TREATMENT SUGGESTIONS (copy and paste to text editor if too big) =====\n" + sb.ToString();
            }
            Debug.Log(outstr);
        }
        //Will be populated, is a subset of allObjsToMesh
        //Fills distinctMaterialTextures and usedObjsToMesh
        //If allowedMaterialsFilter is empty then all materials on allObjsToMesh will be collected and usedObjsToMesh will be same as allObjsToMesh
        //else only materials in allowedMaterialsFilter will be included and usedObjsToMesh will be objs that use those materials.
        bool __Step1_CollectDistinctMatTexturesAndUsedObjects(List<GameObject> allObjsToMesh, 
															 List<Material> allowedMaterialsFilter, 
															 List<ShaderTextureProperty> texPropertyNames, 
															 MB2_EditorMethodsInterface textureEditorMethods, 
															 List<MB_TexSet> distinctMaterialTextures, //Will be populated
															 List<GameObject> usedObjsToMesh)
        {
            // Collect distinct list of textures to combine from the materials on objsToCombine
            bool outOfBoundsUVs = false;
            Dictionary<int,MB_Utility.MeshAnalysisResult[]> meshAnalysisResultsCache = new Dictionary<int, MB_Utility.MeshAnalysisResult[]>(); //cache results
            for (int i = 0; i < allObjsToMesh.Count; i++){
                GameObject obj = allObjsToMesh[i];
                if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Collecting textures for object " + obj);

                if (obj == null){
                    Debug.LogError("The list of objects to mesh contained nulls.");
                    return false;
                }

                Mesh sharedMesh = MB_Utility.GetMesh(obj);
                if (sharedMesh == null){
                    Debug.LogError("Object " + obj.name + " in the list of objects to mesh has no mesh.");
                    return false;
                }

                Material[] sharedMaterials = MB_Utility.GetGOMaterials(obj);
                if (sharedMaterials == null){
                    Debug.LogError("Object " + obj.name + " in the list of objects has no materials.");
                    return false;
                }

                //analyze mesh or grab cached result of previous analysis
                MB_Utility.MeshAnalysisResult[] mar;
                if (!meshAnalysisResultsCache.TryGetValue(sharedMesh.GetInstanceID(),out mar)){
                    mar = new MB_Utility.MeshAnalysisResult[sharedMesh.subMeshCount];
                    for (int j = 0; j < sharedMesh.subMeshCount; j++){
                        Rect outOfBoundsUVRect = new Rect();
                        MB_Utility.hasOutOfBoundsUVs(sharedMesh,ref outOfBoundsUVRect,ref mar[j], j);
                    }
                    meshAnalysisResultsCache.Add(sharedMesh.GetInstanceID(),mar);
                }

                for(int matIdx = 0; matIdx < sharedMaterials.Length; matIdx++){
                    Material mat = sharedMaterials[matIdx];

                    //check if this material is in the list of source materaials
                    if (allowedMaterialsFilter != null && !allowedMaterialsFilter.Contains(mat)){
                        continue;
                    }

                    //Rect uvBounds = mar[matIdx].uvRect;
                    outOfBoundsUVs = outOfBoundsUVs || mar[matIdx].hasOutOfBoundsUVs;

                    if (mat.name.Contains("(Instance)")){
                        Debug.LogError("The sharedMaterial on object " + obj.name + " has been 'Instanced'. This was probably caused by a script accessing the meshRender.material property in the editor. " +
                                       " The material to UV Rectangle mapping will be incorrect. To fix this recreate the object from its prefab or re-assign its material from the correct asset.");
                        return false;
                    }

                    if (_fixOutOfBoundsUVs){
                        if (!MB_Utility.AreAllSharedMaterialsDistinct(sharedMaterials)){
                            if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Object " + obj.name + " uses the same material on multiple submeshes. This may generate strange resultAtlasesAndRects especially when used with fix out of bounds uvs. Try duplicating the material.");
                        }
                    }

                    //collect textures scale and offset for each texture in objects material
                    MeshBakerMaterialTexture[] mts = new MeshBakerMaterialTexture[texPropertyNames.Count];
                    for (int j = 0; j < texPropertyNames.Count; j++){
                        Texture2D tx = null;
                        Vector2 scale = Vector2.one;
                        Vector2 offset = Vector2.zero;
                        Vector2 obUVscale = Vector2.one;
                        Vector2 obUVoffset = Vector2.zero;
                        Color colorIfNoTexture = Color.clear;
                        Color tintColor = GetColorIfNoTexture(mat,texPropertyNames[j]);
                        if (mat.HasProperty(texPropertyNames[j].name)){
                            Texture txx = mat.GetTexture(texPropertyNames[j].name);
                            if (txx != null){
                                if (txx is Texture2D){
                                    tx = (Texture2D) txx;
                                    TextureFormat f = tx.format;
                                    bool isNormalMap = false;
                                    if (!Application.isPlaying && textureEditorMethods != null) isNormalMap = textureEditorMethods.IsNormalMap(tx);
                                    if ((f == TextureFormat.ARGB32 ||
                                        f == TextureFormat.RGBA32 ||
                                        f == TextureFormat.BGRA32 ||
                                        f == TextureFormat.RGB24  ||
                                        f == TextureFormat.Alpha8) && !isNormalMap) //DXT5 does not work
                                    {
                                        //good
                                    } else {
                                        //TRIED to copy texture using tex2.SetPixels(tex1.GetPixels()) but bug in 3.5 means DTX1 and 5 compressed textures come out skewed
                                        //MB2_Log.Log(MB2_LogLevel.warn,obj.name + " in the list of objects to mesh uses Texture "+tx.name+" uses format " + f + " that is not in: ARGB32, RGBA32, BGRA32, RGB24, Alpha8 or DXT. These formats cannot be resized. MeshBaker will create duplicates.");
                                        //tx = createTextureCopy(tx);
                                        if (Application.isPlaying){
                                            Debug.LogError("Object " + obj.name + " in the list of objects to mesh uses Texture "+tx.name+" uses format " + f + " that is not in: ARGB32, RGBA32, BGRA32, RGB24, Alpha8 or DXT. These textures cannot be resized at runtime. Try changing texture format. If format says 'compressed' try changing it to 'truecolor'" );
                                            return false;
                                        } else {
                                            //Debug.LogWarning("Object " + obj.name + " in the list of objects to mesh uses Texture "+tx.name+" uses format " + f + " that is not in: ARGB32, RGBA32, BGRA32, RGB24, Alpha8 or DXT. These textures cannot be resized. Try changing texture format. If format says 'compressed' try changing it to 'truecolor'");
                                            if (textureEditorMethods != null) textureEditorMethods.AddTextureFormat(tx, isNormalMap);
                                            tx = (Texture2D) mat.GetTexture(texPropertyNames[j].name);
                                        }
                                    }
                                } else {
                                    Debug.LogError("Object " + obj.name + " in the list of objects to mesh uses a Texture that is not a Texture2D. Cannot build atlases.");
                                    return false;
                                }
                            } else {
                                //has texture property but no texture try to set a resonable color from the other texture properties
                                colorIfNoTexture = tintColor;
                            }
                            offset = mat.GetTextureOffset(texPropertyNames[j].name);
                            scale = mat.GetTextureScale(texPropertyNames[j].name);
                        }
                        if (mar[matIdx].hasOutOfBoundsUVs){
                            obUVscale = new Vector2(mar[matIdx].uvRect.width,mar[matIdx].uvRect.height);
                            obUVoffset = new Vector2(mar[matIdx].uvRect.x,mar[matIdx].uvRect.y);
                        }
                        mts[j] = new MeshBakerMaterialTexture(tx,offset,scale,obUVoffset,obUVscale,colorIfNoTexture,tintColor);
                    }

                    //Add to distinct set of textures if not already there
                    MB_TexSet setOfTexs = new MB_TexSet(mts);
                    MB_TexSet setOfTexs2 = distinctMaterialTextures.Find(x => x.IsEqual(setOfTexs,_fixOutOfBoundsUVs));
                    if (setOfTexs2 != null){
                        setOfTexs = setOfTexs2;
                    } else {
                        distinctMaterialTextures.Add(setOfTexs);
                    }
                    if (!setOfTexs.mats.Contains(mat)){
                        setOfTexs.mats.Add(mat);
                    }
                    if (!setOfTexs.gos.Contains(obj)){
                        setOfTexs.gos.Add(obj);
                        if (!usedObjsToMesh.Contains(obj)) usedObjsToMesh.Add(obj);
                    }
                }
            }

            return true;
        }
        public void SuggestTreatment(List<GameObject> objsToMesh, Material[] resultMaterials, List<ShaderTextureProperty> _customShaderPropNames)
        {
            this._customShaderPropNames = _customShaderPropNames;
            StringBuilder sb = new StringBuilder();
            Dictionary<int,MB_Utility.MeshAnalysisResult[]> meshAnalysisResultsCache = new Dictionary<int, MB_Utility.MeshAnalysisResult[]>(); //cache results
            for (int i = 0; i < objsToMesh.Count; i++){
                GameObject obj = objsToMesh[i];
                if (obj == null) continue;
                Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
                if (ms.Length > 1){ // and each material is not mapped to its own layer
                    sb.AppendFormat("\nObject {0} uses {1} materials. Possible treatments:\n", objsToMesh[i].name, ms.Length);
                    sb.AppendFormat("  1) Collapse the submeshes together into one submesh in the combined mesh. Each of the original submesh materials will map to a different UV rectangle in the atlas(es) used by the combined material.\n");
                    sb.AppendFormat("  2) Use the multiple materials feature to map submeshes in the source mesh to submeshes in the combined mesh.\n");
                }
                Mesh m = MB_Utility.GetMesh(obj);

                MB_Utility.MeshAnalysisResult[] mar;
                if (!meshAnalysisResultsCache.TryGetValue(m.GetInstanceID(),out mar)){
                    mar = new MB_Utility.MeshAnalysisResult[m.subMeshCount];
                    MB_Utility.doSubmeshesShareVertsOrTris(m,ref mar[0]);
                    for (int j = 0; j < m.subMeshCount; j++){
                        Rect outOfBoundsUVRect = new Rect();
                        MB_Utility.hasOutOfBoundsUVs(m,ref outOfBoundsUVRect,ref mar[j], j);
                        mar[j].hasOverlappingSubmeshTris = mar[0].hasOverlappingSubmeshTris;
                        mar[j].hasOverlappingSubmeshVerts = mar[0].hasOverlappingSubmeshVerts;
                    }
                    meshAnalysisResultsCache.Add(m.GetInstanceID(),mar);
                }

                for (int j = 0; j < ms.Length; j++){
                    if (mar[j].hasOutOfBoundsUVs){
                        Rect r = mar[j].uvRect;
                        sb.AppendFormat("\nObject {0} submesh={1} material={2} uses UVs outside the range 0,0 .. 1,1 to create tiling that tiles the box {3},{4} .. {5},{6}. This is a problem because the UVs outside the 0,0 .. 1,1 " +
                                        "rectangle will pick up neighboring textures in the atlas. Possible Treatments:\n",obj,j,ms[j],r.x.ToString("G4"),r.y.ToString("G4"),(r.x+r.width).ToString("G4"),(r.y+r.height).ToString("G4"));
                        sb.AppendFormat("    1) Ignore the problem. The tiling may not affect result significantly.\n");
                        sb.AppendFormat("    2) Use the 'fix out of bounds UVs' feature to bake the tiling and scale the UVs to fit in the 0,0 .. 1,1 rectangle.\n");
                        sb.AppendFormat("    3) Use the Multiple Materials feature to map the material on this submesh to its own submesh in the combined mesh. No other materials should map to this submesh. This will result in only one texture in the atlas(es) and the UVs should tile correctly.\n");
                        sb.AppendFormat("    4) Combine only meshes that use the same (or subset of) the set of materials on this mesh. The original material(s) can be applied to the result\n");
                    }
                }
                if (mar[0].hasOverlappingSubmeshVerts){
                    //todo be specific about which submeshes overlap
                    sb.AppendFormat("\nObject {0} has submeshes that share vertices. This is a problem because each vertex can have only one UV coordinate and may be required to map to different positions in the various atlases that are generated. Possible treatments:\n", objsToMesh[i]);
                    sb.AppendFormat(" 1) Ignore the problem. The vertices may not affect the result.\n");
                    sb.AppendFormat(" 2) Use the Multiple Materials feature to map the submeshs that overlap to their own submeshs in the combined mesh. No other materials should map to this submesh. This will result in only one texture in the atlas(es) and the UVs should tile correctly.\n");
                    sb.AppendFormat(" 3) Combine only meshes that use the same (or subset of) the set of materials on this mesh. The original material(s) can be applied to the result\n");
                }
            }
            Dictionary<Material,List<GameObject>> m2gos = new Dictionary<Material, List<GameObject>>();
            for (int i = 0; i < objsToMesh.Count; i++){
                if (objsToMesh[i] != null){
                    Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
                    for (int j = 0; j < ms.Length; j++){
                        if (ms[j] != null){
                            List<GameObject> lgo;
                            if (!m2gos.TryGetValue(ms[j],out lgo)){
                                lgo = new List<GameObject>();
                                m2gos.Add(ms[j],lgo);
                            }
                            if (!lgo.Contains(objsToMesh[i])) lgo.Add(objsToMesh[i]);
                        }
                    }
                }
            }

            List<ShaderTextureProperty> texPropertyNames = new List<ShaderTextureProperty>();
            for (int i = 0; i < resultMaterials.Length; i++){
                _CollectPropertyNames(resultMaterials[i], texPropertyNames);
                foreach(Material m in m2gos.Keys){
                    for (int j = 0; j < texPropertyNames.Count; j++){
            //						Texture2D tx = null;
            //						Vector2 scale = Vector2.one;
            //						Vector2 offset = Vector2.zero;
            //						Vector2 obUVscale = Vector2.one;
            //						Vector2 obUVoffset = Vector2.zero;
                        if (m.HasProperty(texPropertyNames[j].name)){
                            Texture txx = m.GetTexture(texPropertyNames[j].name);
                            if (txx != null){
                                Vector2 o = m.GetTextureOffset(texPropertyNames[j].name);
                                Vector3 s = m.GetTextureScale(texPropertyNames[j].name);
                                if (o.x < 0f || o.x + s.x > 1f ||
                                    o.y < 0f || o.y + s.y > 1f){
                                    sb.AppendFormat("\nMaterial {0} used by objects {1} uses texture {2} that is tiled (scale={3} offset={4}). If there is more than one texture in the atlas " +
                                                        " then Mesh Baker will bake the tiling into the atlas. If the baked tiling is large then quality can be lost. Possible treatments:\n",m,PrintList(m2gos[m]),txx,s,o);
                                    sb.AppendFormat("  1) Use the baked tiling.\n");
                                    sb.AppendFormat("  2) Use the Multiple Materials feature to map the material on this object/submesh to its own submesh in the combined mesh. No other materials should map to this submesh. The original material can be applied to this submesh.\n");
                                    sb.AppendFormat("  3) Combine only meshes that use the same (or subset of) the set of textures on this mesh. The original material can be applied to the result.\n");
                                }
                            }
                        }
                    }
                }
            }
            string outstr = "";
            if (sb.Length == 0){
                outstr = "====== No problems detected. These meshes should combine well ====\n  If there are problems with the combined meshes please report the problem to digitalOpus.ca so we can improve Mesh Baker.";
            } else {
                outstr = "====== There are possible problems with these meshes that may prevent them from combining well. TREATMENT SUGGESTIONS (copy and paste to text editor if too big) =====\n" + sb.ToString();
            }
            Debug.Log(outstr);
        }
        //posibilities
        //  using fixOutOfBoundsUVs or not
        //
        public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
        {
            if (mom.GetObjectsToCombine().Count == 0)
            {
                Debug.LogError("You need to add some objects to combine before building the multi material list.");
                return;
            }
            if (resultMaterials.arraySize > 0)
            {
                Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
                return;
            }
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Texture Bake Result asset must be set before using this operation.");
                return;
            }
            Dictionary <MultiMatSubmeshInfo, List <List <Material> > > shader2Material_map = new Dictionary <MultiMatSubmeshInfo, List <List <Material> > >();
            Dictionary <Material, Mesh> obUVobject2mesh_map = new Dictionary <Material, Mesh>();

            //validate that the objects to be combined are valid
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                GameObject go = mom.GetObjectsToCombine()[i];
                if (go == null)
                {
                    Debug.LogError("Null object in list of objects to combine at position " + i);
                    return;
                }
                Renderer r = go.GetComponent <Renderer>();
                if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
                    return;
                }
                if (r.sharedMaterial == null)
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
                    return;
                }
            }

            //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs
            if (mom.doMultiMaterialSplitAtlasesIfOBUVs)
            {
                for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
                {
                    GameObject go = mom.GetObjectsToCombine()[i];
                    Mesh       m  = MB_Utility.GetMesh(go);
                    MB_Utility.MeshAnalysisResult dummyMar = new MB_Utility.MeshAnalysisResult();
                    Renderer r = go.GetComponent <Renderer>();
                    for (int j = 0; j < r.sharedMaterials.Length; j++)
                    {
                        if (MB_Utility.hasOutOfBoundsUVs(m, ref dummyMar, j))
                        {
                            if (!obUVobject2mesh_map.ContainsKey(r.sharedMaterials[j]))
                            {
                                Debug.LogWarning("Object " + go + " submesh " + j + " uses UVs outside the range 0,0..1,1 to generate tiling. This object has been mapped to its own submesh in the combined mesh. It can share a submesh with other objects that use different materials if you use the fix out of bounds UVs feature which will bake the tiling");
                                obUVobject2mesh_map.Add(r.sharedMaterials[j], m);
                            }
                        }
                    }
                }
            }

            //second pass  put other materials without OB uvs in a shader to material map
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                Renderer r = mom.GetObjectsToCombine()[i].GetComponent <Renderer>();
                for (int j = 0; j < r.sharedMaterials.Length; j++)
                {
                    if (!obUVobject2mesh_map.ContainsKey(r.sharedMaterials[j]))
                    { //if not already added
                        if (r.sharedMaterials[j] == null)
                        {
                            continue;
                        }
                        List <List <Material> > binsOfMatsThatUseShader = null;
                        MultiMatSubmeshInfo     newKey = new MultiMatSubmeshInfo(r.sharedMaterials[j].shader, r.sharedMaterials[j]);
                        if (!shader2Material_map.TryGetValue(newKey, out binsOfMatsThatUseShader))
                        {
                            binsOfMatsThatUseShader = new List <List <Material> >();
                            binsOfMatsThatUseShader.Add(new List <Material>());
                            shader2Material_map.Add(newKey, binsOfMatsThatUseShader);
                        }
                        if (!binsOfMatsThatUseShader[0].Contains(r.sharedMaterials[j]))
                        {
                            binsOfMatsThatUseShader[0].Add(r.sharedMaterials[j]);
                        }
                    }
                }
            }

            int numResMats = shader2Material_map.Count;

            //third pass for each shader grouping check how big the atlas would be and group into bins that would fit in an atlas
            if (mom.doMultiMaterialSplitAtlasesIfTooBig)
            {
                if (mom.packingAlgorithm == MB2_PackingAlgorithmEnum.UnitysPackTextures)
                {
                    Debug.LogWarning("Unity texture packer does not support splitting atlases if too big. Atlases will not be split.");
                }
                else
                {
                    numResMats = 0;
                    foreach (MultiMatSubmeshInfo sh in shader2Material_map.Keys)
                    {
                        List <List <Material> > binsOfMatsThatUseShader = shader2Material_map[sh];
                        List <Material>         allMatsThatUserShader   = binsOfMatsThatUseShader[0];//at this point everything is in the same list
                        binsOfMatsThatUseShader.RemoveAt(0);
                        MB3_TextureCombiner combiner = mom.CreateAndConfigureTextureCombiner();
                        combiner.saveAtlasesAsAssets = false;
                        if (allMatsThatUserShader.Count > 1)
                        {
                            combiner.fixOutOfBoundsUVs = mom.fixOutOfBoundsUVs;
                        }
                        else
                        {
                            combiner.fixOutOfBoundsUVs = false;
                        }

                        // Do the texture pack
                        List <AtlasPackingResult> packingResults = new List <AtlasPackingResult>();
                        Material tempMat = new Material(sh.shader);
                        combiner.CombineTexturesIntoAtlases(null, null, tempMat, mom.GetObjectsToCombine(), allMatsThatUserShader, null, packingResults, true);
                        for (int i = 0; i < packingResults.Count; i++)
                        {
                            List <MatsAndGOs> matsData = (List <MatsAndGOs>)packingResults[i].data;
                            List <Material>   mats     = new List <Material>();
                            for (int j = 0; j < matsData.Count; j++)
                            {
                                for (int kk = 0; kk < matsData[j].mats.Count; kk++)
                                {
                                    if (!mats.Contains(matsData[j].mats[kk].mat))
                                    {
                                        mats.Add(matsData[j].mats[kk].mat);
                                    }
                                }
                            }
                            binsOfMatsThatUseShader.Add(mats);
                        }
                        numResMats += binsOfMatsThatUseShader.Count;
                    }
                }
            }

            //build the result materials
            if (shader2Material_map.Count == 0 && obUVobject2mesh_map.Count == 0)
            {
                Debug.LogError("Found no materials in list of objects to combine");
            }
            mom.resultMaterials = new MB_MultiMaterial[numResMats + obUVobject2mesh_map.Count];
            string pth        = AssetDatabase.GetAssetPath(mom.textureBakeResults);
            string baseName   = Path.GetFileNameWithoutExtension(pth);
            string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
            int    k          = 0;

            foreach (MultiMatSubmeshInfo sh in shader2Material_map.Keys)
            {
                foreach (List <Material> matsThatUse in shader2Material_map[sh])
                {
                    MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
                    mm.sourceMaterials = matsThatUse;
                    if (mm.sourceMaterials.Count == 1)
                    {
                        mm.considerMeshUVs = false;
                    }
                    else
                    {
                        mm.considerMeshUVs = mom.fixOutOfBoundsUVs;
                    }
                    string   matName = folderPath + baseName + "-mat" + k + ".mat";
                    Material newMat  = new Material(Shader.Find("Diffuse"));
                    if (matsThatUse.Count > 0 && matsThatUse[0] != null)
                    {
                        MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]);
                    }
                    AssetDatabase.CreateAsset(newMat, matName);
                    mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                    k++;
                }
            }
            foreach (Material m in obUVobject2mesh_map.Keys)
            {
                MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
                mm.sourceMaterials = new List <Material>();
                mm.sourceMaterials.Add(m);
                mm.considerMeshUVs = false;
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            MBVersionEditor.UpdateIfDirtyOrScript(textureBaker);
        }
        public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
        {
            if (mom.GetObjectsToCombine().Count == 0)
            {
                Debug.LogError("You need to add some objects to combine before building the multi material list.");
                return;
            }
            if (resultMaterials.arraySize > 0)
            {
                Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
                return;
            }
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Material Bake Result asset must be set before using this operation.");
                return;
            }
            Dictionary <Shader, List <Material> > shader2Material_map     = new Dictionary <Shader, List <Material> >();
            Dictionary <Material, Mesh>           obUVobject2material_map = new Dictionary <Material, Mesh>();

            //validate that the objects to be combined are valid
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                GameObject go = mom.GetObjectsToCombine()[i];
                if (go == null)
                {
                    Debug.LogError("Null object in list of objects to combine at position " + i);
                    return;
                }
                Renderer r = go.GetComponent <Renderer>();
                if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
                    return;
                }
                if (r.sharedMaterial == null)
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
                    return;
                }
            }

            //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs
            if (!mom.fixOutOfBoundsUVs)
            {
                for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
                {
                    GameObject go    = mom.GetObjectsToCombine()[i];
                    Mesh       m     = MB_Utility.GetMesh(go);
                    Rect       dummy = new Rect();
                    MB_Utility.MeshAnalysisResult dummyMar = new MB_Utility.MeshAnalysisResult();
                    Renderer r = go.GetComponent <Renderer>();
                    for (int j = 0; j < r.sharedMaterials.Length; j++)
                    {
                        if (MB_Utility.hasOutOfBoundsUVs(m, ref dummy, ref dummyMar, j))
                        {
                            if (!obUVobject2material_map.ContainsKey(r.sharedMaterials[j]))
                            {
                                Debug.LogWarning("Object " + go + " submesh " + j + " uses UVs outside the range 0,0..1,1 to generate tiling. This object has been mapped to its own submesh in the combined mesh. It can share a submesh with other objects that use different materials if you use the fix out of bounds UVs feature which will bake the tiling");
                                obUVobject2material_map.Add(r.sharedMaterials[j], m);
                            }
                        }
                    }
                }
            }

            //second pass  put other materials without OB uvs in a shader to material map
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                Renderer r = mom.GetObjectsToCombine()[i].GetComponent <Renderer>();
                for (int j = 0; j < r.sharedMaterials.Length; j++)
                {
                    if (!obUVobject2material_map.ContainsKey(r.sharedMaterials[j]))
                    {
                        if (r.sharedMaterials[j] == null)
                        {
                            continue;
                        }
                        List <Material> matsThatUseShader = null;
                        if (!shader2Material_map.TryGetValue(r.sharedMaterials[j].shader, out matsThatUseShader))
                        {
                            matsThatUseShader = new List <Material>();
                            shader2Material_map.Add(r.sharedMaterials[j].shader, matsThatUseShader);
                        }
                        if (!matsThatUseShader.Contains(r.sharedMaterials[j]))
                        {
                            matsThatUseShader.Add(r.sharedMaterials[j]);
                        }
                    }
                }
            }

            if (shader2Material_map.Count == 0 && obUVobject2material_map.Count == 0)
            {
                Debug.LogError("Found no materials in list of objects to combine");
            }
            mom.resultMaterials = new MB_MultiMaterial[shader2Material_map.Count + obUVobject2material_map.Count];
            string pth        = AssetDatabase.GetAssetPath(mom.textureBakeResults);
            string baseName   = Path.GetFileNameWithoutExtension(pth);
            string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
            int    k          = 0;

            foreach (Shader sh in shader2Material_map.Keys)
            {
                List <Material>  matsThatUse = shader2Material_map[sh];
                MB_MultiMaterial mm          = mom.resultMaterials[k] = new MB_MultiMaterial();
                mm.sourceMaterials = matsThatUse;
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                if (matsThatUse.Count > 0 && matsThatUse[0] != null)
                {
                    MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]);
                }
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            foreach (Material m in obUVobject2material_map.Keys)
            {
                MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
                mm.sourceMaterials = new List <Material>();
                mm.sourceMaterials.Add(m);
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            textureBaker.UpdateIfDirtyOrScript();
        }
		public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterials, SerializedObject textureBaker){
			if (mom.GetObjectsToCombine().Count == 0){
				Debug.LogError("You need to add some objects to combine before building the multi material list.");
				return;
			}
			if (resultMaterials.arraySize > 0){
				Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
				return;			
			}
			if (mom.textureBakeResults == null){
				Debug.LogError("Material Bake Result asset must be set before using this operation.");
				return;
			}
			Dictionary<Shader,List<Material>> shader2Material_map = new Dictionary<Shader, List<Material>>();
			Dictionary<Material,Mesh> obUVobject2material_map = new Dictionary<Material,Mesh>();
			
			//validate that the objects to be combined are valid
			for (int i = 0; i < mom.GetObjectsToCombine().Count; i++){
				GameObject go = mom.GetObjectsToCombine()[i];
				if (go == null) {
					Debug.LogError("Null object in list of objects to combine at position " + i);
					return;
				}
				Renderer r = go.GetComponent<Renderer>();
				if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer))){
					Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
					return;
				}
				if (r.sharedMaterial == null){
					Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
					return;						
				}			
			}
			
			//first pass put any meshes with obUVs on their own submesh if not fixing OB uvs
			if (!mom.fixOutOfBoundsUVs){
				for (int i = 0; i < mom.GetObjectsToCombine().Count; i++){
					GameObject go = mom.GetObjectsToCombine()[i];
					Mesh m = MB_Utility.GetMesh(go);
					Rect dummy = new Rect();
					MB_Utility.MeshAnalysisResult dummyMar = new MB_Utility.MeshAnalysisResult();
					Renderer r = go.GetComponent<Renderer>();	
					for (int j = 0; j < r.sharedMaterials.Length; j++){
						if (MB_Utility.hasOutOfBoundsUVs(m, ref dummy, ref dummyMar, j)){
							if (!obUVobject2material_map.ContainsKey(r.sharedMaterials[j])){
								Debug.LogWarning("Object " + go + " submesh " + j + " uses UVs outside the range 0,0..1,1 to generate tiling. This object has been mapped to its own submesh in the combined mesh. It can share a submesh with other objects that use different materials if you use the fix out of bounds UVs feature which will bake the tiling");
								obUVobject2material_map.Add(r.sharedMaterials[j],m);
							}
						}
					}
				}
			}
			
			//second pass  put other materials without OB uvs in a shader to material map
			for (int i = 0; i < mom.GetObjectsToCombine().Count; i++){
				Renderer r = mom.GetObjectsToCombine()[i].GetComponent<Renderer>();
				for (int j = 0; j < r.sharedMaterials.Length; j++){
					if (!obUVobject2material_map.ContainsKey(r.sharedMaterials[j])) {
						if (r.sharedMaterials[j] == null) continue;
						List<Material> matsThatUseShader = null;
						if (!shader2Material_map.TryGetValue(r.sharedMaterials[j].shader, out matsThatUseShader)){
							matsThatUseShader = new List<Material>();
							shader2Material_map.Add(r.sharedMaterials[j].shader, matsThatUseShader);
						}
						if (!matsThatUseShader.Contains(r.sharedMaterials[j])) matsThatUseShader.Add(r.sharedMaterials[j]);
					}
				}			
			}
			
			if (shader2Material_map.Count == 0 && obUVobject2material_map.Count == 0) Debug.LogError("Found no materials in list of objects to combine");
			mom.resultMaterials = new MB_MultiMaterial[shader2Material_map.Count + obUVobject2material_map.Count];
			string pth = AssetDatabase.GetAssetPath(mom.textureBakeResults);
			string baseName = Path.GetFileNameWithoutExtension(pth);
			string folderPath = pth.Substring(0,pth.Length - baseName.Length - 6);		
			int k = 0;
			foreach(Shader sh in shader2Material_map.Keys){ 
				List<Material> matsThatUse = shader2Material_map[sh];
				MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
				mm.sourceMaterials = matsThatUse;
				string matName = folderPath +  baseName + "-mat" + k + ".mat";
				Material newMat = new Material(Shader.Find("Diffuse"));
				if (matsThatUse.Count > 0 && matsThatUse[0] != null){
					MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]);
				}
				AssetDatabase.CreateAsset(newMat, matName);
				mm.combinedMaterial = (Material) AssetDatabase.LoadAssetAtPath(matName,typeof(Material));
				k++;
			}
			foreach(Material m in obUVobject2material_map.Keys){
				MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
				mm.sourceMaterials = new List<Material>();
				mm.sourceMaterials.Add(m);
				string matName = folderPath +  baseName + "-mat" + k + ".mat";
				Material newMat = new Material(Shader.Find("Diffuse"));
				MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat,m);
				AssetDatabase.CreateAsset(newMat, matName);
				mm.combinedMaterial = (Material) AssetDatabase.LoadAssetAtPath(matName,typeof(Material));
				k++;
			}
			textureBaker.UpdateIfDirtyOrScript();
		}
Example #8
0
        public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds, ref MB_Utility.MeshAnalysisResult putResultHere, int submeshIndex = -1)
        {
            if (m == null)
            {
                putResultHere.hasOutOfBoundsUVs = false;
                return(putResultHere.hasOutOfBoundsUVs);
            }
            Vector2[] uv = m.uv;
            if (uv.Length == 0)
            {
                putResultHere.hasOutOfBoundsUVs = false;
                putResultHere.uvRect            = uvBounds;
                return(putResultHere.hasOutOfBoundsUVs);
            }
            if (submeshIndex >= m.subMeshCount)
            {
                putResultHere.hasOutOfBoundsUVs = false;
                putResultHere.uvRect            = uvBounds;
                return(putResultHere.hasOutOfBoundsUVs);
            }
            float x;
            float num;
            float y;
            float num2;

            if (submeshIndex >= 0)
            {
                int[] triangles = m.GetTriangles(submeshIndex);
                if (triangles.Length == 0)
                {
                    putResultHere.hasOutOfBoundsUVs = false;
                    putResultHere.uvRect            = uvBounds;
                    return(putResultHere.hasOutOfBoundsUVs);
                }
                num  = (x = uv[triangles[0]].x);
                num2 = (y = uv[triangles[0]].y);
                foreach (int num3 in triangles)
                {
                    if (uv[num3].x < x)
                    {
                        x = uv[num3].x;
                    }
                    if (uv[num3].x > num)
                    {
                        num = uv[num3].x;
                    }
                    if (uv[num3].y < y)
                    {
                        y = uv[num3].y;
                    }
                    if (uv[num3].y > num2)
                    {
                        num2 = uv[num3].y;
                    }
                }
            }
            else
            {
                num  = (x = uv[0].x);
                num2 = (y = uv[0].y);
                for (int j = 0; j < uv.Length; j++)
                {
                    if (uv[j].x < x)
                    {
                        x = uv[j].x;
                    }
                    if (uv[j].x > num)
                    {
                        num = uv[j].x;
                    }
                    if (uv[j].y < y)
                    {
                        y = uv[j].y;
                    }
                    if (uv[j].y > num2)
                    {
                        num2 = uv[j].y;
                    }
                }
            }
            uvBounds.x      = x;
            uvBounds.y      = y;
            uvBounds.width  = num - x;
            uvBounds.height = num2 - y;
            if (num > 1f || x < 0f || num2 > 1f || y < 0f)
            {
                putResultHere.hasOutOfBoundsUVs = true;
                putResultHere.uvRect            = uvBounds;
                return(putResultHere.hasOutOfBoundsUVs);
            }
            float num4 = 0f;

            uvBounds.y                      = num4;
            uvBounds.x                      = num4;
            num4                            = 1f;
            uvBounds.height                 = num4;
            uvBounds.width                  = num4;
            putResultHere.uvRect            = uvBounds;
            putResultHere.hasOutOfBoundsUVs = false;
            return(putResultHere.hasOutOfBoundsUVs);
        }
Example #9
0
 public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds)
 {
     MB_Utility.MeshAnalysisResult meshAnalysisResult = default(MB_Utility.MeshAnalysisResult);
     return(MB_Utility.hasOutOfBoundsUVs(m, ref uvBounds, ref meshAnalysisResult, -1));
 }
            /// <summary>
            /// A material can appear more than once in an atlas if using fixOutOfBoundsUVs.
            /// in this case you need to use the UV rect of the mesh to find the correct rectangle.
            /// If the all properties on the mat use the same tiling then
            /// encapsulatingRect can be larger and will include baked UV and material tiling
            /// If mat uses different tiling for different maps then encapsulatingRect is the uvs of
            /// source mesh used to bake atlas and sourceMaterialTilingOut is 0,0,1,1. This works because
            /// material tiling was baked into the atlas.
            /// </summary>
            public bool TryMapMaterialToUVRect(Material mat, Mesh m, int submeshIdx, int idxInResultMats,
                                               MB3_MeshCombinerSingle.MeshChannelsCache meshChannelCache,
                                               Dictionary <int, MB_Utility.MeshAnalysisResult[]> meshAnalysisCache,
                                               out MB_TextureTilingTreatment tilingTreatment,
                                               out Rect rectInAtlas,
                                               out Rect encapsulatingRectOut,
                                               out Rect sourceMaterialTilingOut,
                                               out int sliceIdx,
                                               ref String errorMsg,
                                               MB2_LogLevel logLevel)
            {
                if (textureBakeResults.version < MB2_TextureBakeResults.VERSION)
                {
                    textureBakeResults.UpgradeToCurrentVersion(textureBakeResults);
                }
                tilingTreatment = MB_TextureTilingTreatment.unknown;
                if (textureBakeResults.materialsAndUVRects.Length == 0)
                {
                    errorMsg                = "The 'Texture Bake Result' needs to be re-baked to be compatible with this version of Mesh Baker. Please re-bake using the MB3_TextureBaker.";
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx                = -1;
                    return(false);
                }
                if (mat == null)
                {
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx = -1;
                    errorMsg = String.Format("Mesh {0} Had no material on submesh {1} cannot map to a material in the atlas", m.name, submeshIdx);
                    return(false);
                }
                if (submeshIdx >= m.subMeshCount)
                {
                    errorMsg                = "Submesh index is greater than the number of submeshes";
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx                = -1;
                    return(false);
                }

                //find the first index of this material
                int idx = -1;

                for (int i = 0; i < matsAndSrcUVRect.Length; i++)
                {
                    if (mat == matsAndSrcUVRect[i].material)
                    {
                        idx = i;
                        break;
                    }
                }
                // if couldn't find material
                if (idx == -1)
                {
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx = -1;
                    errorMsg = String.Format("Material {0} could not be found in the Texture Bake Result", mat.name);
                    return(false);
                }

                bool considerUVs = textureBakeResults.GetConsiderMeshUVs(idxInResultMats, mat);

                if (!considerUVs)
                {
                    if (numTimesMatAppearsInAtlas[idx] != 1)
                    {
                        Debug.LogError("There is a problem with this TextureBakeResults. FixOutOfBoundsUVs is false and a material appears more than once: " + matsAndSrcUVRect[idx].material + " appears: " + numTimesMatAppearsInAtlas[idx]);
                    }
                    MB_MaterialAndUVRect mr = matsAndSrcUVRect[idx];
                    rectInAtlas             = mr.atlasRect;
                    tilingTreatment         = mr.tilingTreatment;
                    encapsulatingRectOut    = mr.GetEncapsulatingRect();
                    sourceMaterialTilingOut = mr.GetMaterialTilingRect();
                    sliceIdx = mr.textureArraySliceIdx;
                    return(true);
                }
                else
                {
                    //todo what if no UVs
                    //Find UV rect in source mesh
                    MB_Utility.MeshAnalysisResult[] mar;
                    if (!meshAnalysisCache.TryGetValue(m.GetInstanceID(), out mar))
                    {
                        mar = new MB_Utility.MeshAnalysisResult[m.subMeshCount];
                        for (int j = 0; j < m.subMeshCount; j++)
                        {
                            Vector2[] uvss = meshChannelCache.GetUv0Raw(m);
                            MB_Utility.hasOutOfBoundsUVs(uvss, m, ref mar[j], j);
                        }
                        meshAnalysisCache.Add(m.GetInstanceID(), mar);
                    }

                    //this could be a mesh that was not used in the texture baking that has huge UV tiling too big for the rect that was baked
                    //find a record that has an atlas uvRect capable of containing this
                    bool found                = false;
                    Rect encapsulatingRect    = new Rect(0, 0, 0, 0);
                    Rect sourceMaterialTiling = new Rect(0, 0, 0, 0);
                    if (logLevel >= MB2_LogLevel.trace)
                    {
                        Debug.Log(String.Format("Trying to find a rectangle in atlas capable of holding tiled sampling rect for mesh {0} using material {1} meshUVrect={2}", m, mat, mar[submeshIdx].uvRect.ToString("f5")));
                    }
                    for (int i = idx; i < matsAndSrcUVRect.Length; i++)
                    {
                        MB_MaterialAndUVRect matAndUVrect = matsAndSrcUVRect[i];
                        if (matAndUVrect.material == mat)
                        {
                            if (matAndUVrect.allPropsUseSameTiling)
                            {
                                encapsulatingRect    = matAndUVrect.allPropsUseSameTiling_samplingEncapsulatinRect;
                                sourceMaterialTiling = matAndUVrect.allPropsUseSameTiling_sourceMaterialTiling;
                            }
                            else
                            {
                                encapsulatingRect    = matAndUVrect.propsUseDifferntTiling_srcUVsamplingRect;
                                sourceMaterialTiling = new Rect(0, 0, 1, 1);
                            }

                            if (MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect(
                                    matAndUVrect.tilingTreatment,
                                    mar[submeshIdx].uvRect,
                                    sourceMaterialTiling,
                                    encapsulatingRect,
                                    logLevel))
                            {
                                if (logLevel >= MB2_LogLevel.trace)
                                {
                                    Debug.Log("Found rect in atlas capable of containing tiled sampling rect for mesh " + m + " at idx=" + i);
                                }
                                idx   = i;
                                found = true;
                                break;
                            }
                        }
                    }
                    if (found)
                    {
                        MB_MaterialAndUVRect mr = matsAndSrcUVRect[idx];
                        rectInAtlas             = mr.atlasRect;
                        tilingTreatment         = mr.tilingTreatment;
                        encapsulatingRectOut    = mr.GetEncapsulatingRect();
                        sourceMaterialTilingOut = mr.GetMaterialTilingRect();
                        sliceIdx = mr.textureArraySliceIdx;
                        return(true);
                    }
                    else
                    {
                        rectInAtlas             = new Rect();
                        encapsulatingRectOut    = new Rect();
                        sourceMaterialTilingOut = new Rect();
                        sliceIdx = -1;
                        errorMsg = String.Format("Could not find a tiled rectangle in the atlas capable of containing the uv and material tiling on mesh {0} for material {1}. Was this mesh included when atlases were baked?", m.name, mat);
                        return(false);
                    }
                }
            }