static bool ValidateSingleResultMaterial(List <GameObject> objsToMesh, Material singleResultMaterial)
        {
            //合并为单独材质
            if (singleResultMaterial == null)
            {
                Debug.LogError("Combined Material is null please create and assign a result material.");
                return(false);
            }
            Shader targShader = singleResultMaterial.shader;

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                Material[] ms = MeshBakerUtility.GetGOMaterials(objsToMesh[i]);
                for (int j = 0; j < ms.Length; j++)
                {
                    Material m = ms[j];
                    if (m != null && m.shader != targShader)
                    {
                        Debug.LogWarning("游戏物体" + objsToMesh[i] + " 没有使用 shader " + targShader +
                                         " it may not have the required textures. " +
                                         "If not small solid color textures will be generated.");
                    }
                }
            }
            return(true);
        }
        /// <summary>
        /// 合并游戏物体列表,空物体,重复物体,空材质,网格验证
        /// </summary>
        /// <param name="gameObjectsToMesh"></param>
        /// <returns></returns>
        private static bool ValidateCombineGameObject(List <GameObject> gameObjectsToMesh)
        {
            //网格分析结果缓存
            Dictionary <int, MeshAnalysisResult> meshAnalysisResultCache =
                new Dictionary <int, MeshAnalysisResult>();;
            //获取将合并网格的游戏物体
            List <GameObject> objsToMesh = gameObjectsToMesh;

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                GameObject go = objsToMesh[i];
                if (go == null)
                {
                    Debug.LogError("合并网格游戏物体列表中包含 null 物体,在位置" + i);
                    return(false);
                }
                for (int j = i + 1; j < objsToMesh.Count; j++)
                {
                    if (objsToMesh[i] == objsToMesh[j])
                    {
                        Debug.LogError("合并网格游戏物体列表中包含重复游戏物体 " + i + " 和 " + j);
                        return(false);
                    }
                }
                if (MeshBakerUtility.GetGOMaterials(go).Length == 0)
                {
                    Debug.LogError("游戏物体 " + go + " 没有材质");
                    return(false);
                }
                Mesh m = MeshBakerUtility.GetMesh(go);
                if (m == null)
                {
                    Debug.LogError("合并网格游戏物体列表中, " + go + " 没有网格 ");
                    return(false);
                }
                if (m != null)
                {
                    //This check can be very expensive and it only warns so only do this if we are in the editor.
                    if (!Application.isEditor && Application.isPlaying && combineData.DoMultiMaterial)
                    {
                        MeshAnalysisResult mar;
                        if (!meshAnalysisResultCache.TryGetValue(m.GetInstanceID(), out mar))
                        {
                            MeshBakerUtility.doSubmeshesShareVertsOrTris(m, ref mar);
                            meshAnalysisResultCache.Add(m.GetInstanceID(), mar);
                        }
                        //检查重叠的子网格顶点
                        if (mar.hasOverlappingSubmeshVerts)
                        {
                            Debug.LogWarning("游戏物体 " + objsToMesh[i] + " has overlapping submeshes (submeshes share vertices)." +
                                             "If the UVs associated with the shared vertices are important then this bake may not work. " +
                                             "If you are using multiple materials then this object can only be combined with objects that use the exact same set of textures " +
                                             "(each atlas contains one texture). There may be other undesirable side affects as well. Mesh Master, " +
                                             "available in the asset store can fix overlapping submeshes.");
                        }
                    }
                }
            }
            return(true);
        }
        /// <summary>
        /// 多材质验证
        /// </summary>
        /// <returns></returns>
        static bool _ValidateResultMaterials(List <GameObject> objsToMesh, MultiMaterial[] resultMaterials)
        {
            HashSet <Material> allMatsOnObjs = new HashSet <Material>();

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                if (objsToMesh[i] != null)
                {
                    Material[] ms = MeshBakerUtility.GetGOMaterials(objsToMesh[i]);
                    for (int j = 0; j < ms.Length; j++)
                    {
                        if (ms[j] != null)
                        {
                            allMatsOnObjs.Add(ms[j]);
                        }
                    }
                }
            }

            //多材质判断
            HashSet <Material> allMatsInMapping = new HashSet <Material>();

            for (int i = 0; i < resultMaterials.Length; i++)
            {
                //查重
                for (int j = i + 1; j < resultMaterials.Length; j++)
                {
                    if (resultMaterials[i].combinedMaterial == resultMaterials[j].combinedMaterial)
                    {
                        Debug.LogError(string.Format("Source To Combined Mapping: Submesh {0} and Submesh {1} use the same combined material. These should be different", i, j));
                        return(false);
                    }
                }

                //判空
                MultiMaterial mm = resultMaterials[i];
                if (mm.combinedMaterial == null)
                {
                    Debug.LogError("Combined Material is null please create and assign a result material.");
                    return(false);
                }
                Shader targShader = mm.combinedMaterial.shader;
                for (int j = 0; j < mm.sourceMaterials.Count; j++)
                {
                    if (mm.sourceMaterials[j] == null)
                    {
                        Debug.LogError("There are null entries in the list of Source Materials");
                        return(false);
                    }
                    if (targShader != mm.sourceMaterials[j].shader)
                    {
                        Debug.LogWarning("Source material " + mm.sourceMaterials[j] + " does not use shader " + targShader + " it may not have the required textures. If not empty textures will be generated.");
                    }
                    if (allMatsInMapping.Contains(mm.sourceMaterials[j]))
                    {
                        Debug.LogError("A Material " + mm.sourceMaterials[j] + " appears more than once in the list of source materials in the source material to combined mapping. Each source material must be unique.");
                        return(false);
                    }
                    allMatsInMapping.Add(mm.sourceMaterials[j]);
                }
            }

            if (allMatsOnObjs.IsProperSubsetOf(allMatsInMapping))
            {
                allMatsInMapping.ExceptWith(allMatsOnObjs);
                ////Debug.LogWarning("There are materials in the mapping that are not used on your source objects: " + PrintSet(allMatsInMapping));
            }
            if (resultMaterials != null && resultMaterials.Length > 0 && allMatsInMapping.IsProperSubsetOf(allMatsOnObjs))
            {
                allMatsOnObjs.ExceptWith(allMatsInMapping);
                ////Debug.LogError("There are materials on the objects to combine that are not in the mapping: " + PrintSet(allMatsOnObjs));
                return(false);
            }
            return(true);
        }
        static void CombineTexturesIntoAtlases(AtlasesAndRects resultAtlasesAndRects,
                                               Material resultMaterial,
                                               List <GameObject> objsToMesh,
                                               List <Material> allowedMaterialsFilter,
                                               EditorMethodsInterface textureEditorMethods,
                                               bool splitAtlasWhenPackingIfTooBig = false)
        {
            try
            {
                MaterialPropTexture.readyToBuildAtlases = false;

                // ---- 1.合并材质参数校验
                if (objsToMesh == null || objsToMesh.Count == 0)
                {
                    Debug.LogError("没有游戏物体参与合并");
                    return;
                }

                if (combineData.atlasPadding < 0)
                {
                    Debug.LogError("Atlas padding 必须大于等于零");
                    return;
                }

                if (combineData.maxTilingBakeSize < 2 || combineData.maxTilingBakeSize > 4096)
                {
                    Debug.LogError("无效Tilling尺寸的值Invalid value for max tiling bake size.");
                }

                for (int i = 0; i < objsToMesh.Count; i++)
                {
                    Material[] ms = MeshBakerUtility.GetGOMaterials(objsToMesh[i]);
                    for (int j = 0; j < ms.Length; j++)
                    {
                        Material m = ms[j];
                        if (m == null)
                        {
                            Debug.LogError("游戏物体" + objsToMesh[i] + " 材质为空 ");
                        }
                    }
                }

                if (combineData.fixOutOfBoundsUVs && (combineData.packingAlgorithm == PackingAlgorithmEnum.MeshBakerTexturePacker_Horizontal ||
                                                      combineData.packingAlgorithm == PackingAlgorithmEnum.MeshBakerTexturePacker_Vertical))
                {
                    Debug.LogWarning("合并算法为 MeshBakerTexturePacker_Horizontal 或 MeshBakerTexturePacker_Vertical,建议不打开 Consider Mesh UVs 选项");
                }

                // ---- 2.将材质的 shader 各参数信息写入管线数据中
                if (!TextureCombinePipeline.CollectPropertyNames(combineData))
                {
                    return;
                }

                // ---- 3.加载 Texture 混合器
                combineData.nonTexturePropertyBlender.LoadTextureBlendersIfNeeded(combineData.ResultMaterial);

                // ---- 4.合并管道
                BeginCombineTexturesIntoAtlases(resultAtlasesAndRects, combineData, splitAtlasWhenPackingIfTooBig, textureEditorMethods);
            }
            finally
            {
                // ---- 6.删除缓存,合并材质完成回调
                //_destroyAllTemporaryTextures();
            }
        }
Example #5
0
        public IEnumerator CreateAtlasesCoroutine()
        {
            this.OnCombinedTexturesCoroutineAtlasesAndRects = null;
            MBValidationLevel vl = MBValidationLevel.quick;

            if (!DoCombinedValidate(this, MB_ObjsToCombineTypes.dontCare, vl))
            {
                yield break;
            }
            if (_doMultiMaterial && !_ValidateResultMaterials())
            {
                yield break;
            }
            else if (!_doMultiMaterial)
            {
                if (_resultMaterial == null)
                {
                    Debug.LogError("Combined Material is null please create and assign a result material.");
                    yield break;
                }
                Shader targShader = _resultMaterial.shader;
                for (int i = 0; i < objsToMesh.Count; i++)
                {
                    Material[] ms = MeshBakerUtility.GetGOMaterials(objsToMesh[i]);
                    for (int j = 0; j < ms.Length; j++)
                    {
                        Material m = ms[j];
                        if (m != null && m.shader != targShader)
                        {
                            Debug.LogWarning("Game object " + objsToMesh[i] + " does not use shader " + targShader + " it may not have the required textures. If not small solid color textures will be generated.");
                        }
                    }
                }
            }

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                Material[] ms = MeshBakerUtility.GetGOMaterials(objsToMesh[i]);
                for (int j = 0; j < ms.Length; j++)
                {
                    Material m = ms[j];
                    if (m == null)
                    {
                        Debug.LogError("Game object " + objsToMesh[i] + " has a null material. Can't build atlases");
                        yield break;
                    }
                }
            }

            TextureCombiner combiner = new TextureCombiner();

            combiner.LOG_LEVEL             = LOG_LEVEL;
            combiner.atlasPadding          = _atlasPadding;
            combiner.maxAtlasSize          = _maxAtlasSize;
            combiner.customShaderPropNames = _customShaderProperties;
            combiner.fixOutOfBoundsUVs     = _fixOutOfBoundsUVs;
            combiner.maxTilingBakeSize     = _maxTilingBakeSize;

            //initialize structure to store results
            int numResults = 1;

            if (_doMultiMaterial)
            {
                numResults = resultMaterials.Length;
            }
            OnCombinedTexturesCoroutineAtlasesAndRects = new AtlasesAndRects[numResults];
            for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++)
            {
                OnCombinedTexturesCoroutineAtlasesAndRects[i] = new AtlasesAndRects();
            }

            //Do the material combining.
            for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++)
            {
                Material        resMatToPass = null;
                List <Material> sourceMats   = null;
                if (_doMultiMaterial)
                {
                    sourceMats   = resultMaterials[i].sourceMaterials;
                    resMatToPass = resultMaterials[i].combinedMaterial;
                }
                else
                {
                    resMatToPass = _resultMaterial;
                }
                Debug.Log(string.Format("Creating atlases for result material {0} using shader {1}", resMatToPass, resMatToPass.shader));
                TextureCombiner.CombineTexturesIntoAtlasesResult result2 = new TextureCombiner.CombineTexturesIntoAtlasesResult();
                yield return(combiner.CombineTexturesIntoAtlases(OnCombinedTexturesCoroutineAtlasesAndRects[i],
                                                                 resMatToPass, objsToMesh, sourceMats, result2));

                if (!result2.success)
                {
                    yield break;
                }
            }

            //Save the results
            textureBakeResults.doMultiMaterial   = _doMultiMaterial;
            textureBakeResults.resultMaterial    = _resultMaterial;
            textureBakeResults.resultMaterials   = resultMaterials;
            textureBakeResults.fixOutOfBoundsUVs = combiner.fixOutOfBoundsUVs;
            unpackMat2RectMap(textureBakeResults);

            //set the texture bake resultAtlasesAndRects on the Mesh Baker component if it exists
            MeshBakerCommon[] mb = bakerCommons.ToArray();
            for (int i = 0; i < mb.Length; i++)
            {
                mb[i].textureBakeResults = textureBakeResults;
                mb[i].TexBaker           = this;
            }

            if (LOG_LEVEL >= MBLogLevel.info)
            {
                Debug.Log("Created Atlases");
            }

            if (onBuiltAtlasesSuccess != null)
            {
                onBuiltAtlasesSuccess(this);
            }
        }
Example #6
0
        public static bool DoCombinedValidate(MeshBakerRoot mom, MB_ObjsToCombineTypes objToCombineType, MBValidationLevel validationLevel)
        {
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Need to set Material Bake Result on " + mom);
                return(false);
            }
            if (mom is MeshBakerCommon)
            {
                MeshBakerCommon momMB = (MeshBakerCommon)mom;
                TextureBaker    tb    = momMB.GetTextureBaker();
                if (tb != null && tb.textureBakeResults != mom.textureBakeResults)
                {
                    Debug.LogWarning("Material Bake Result on this component is not the same as the Material Bake Result on the MB3_TextureBaker.");
                }
            }

            Dictionary <int, MeshBakerUtility.MeshAnalysisResult> meshAnalysisResultCache = null;

            if (validationLevel == MBValidationLevel.robust)
            {
                meshAnalysisResultCache = new Dictionary <int, MeshBakerUtility.MeshAnalysisResult>();
            }
            List <GameObject> objsToMesh = mom.GetObjectsToCombine();

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                GameObject go = objsToMesh[i];
                if (go == null)
                {
                    Debug.LogError("The list of objects to combine contains a null at position." + i + " Select and use [shift] delete to remove");
                    return(false);
                }
                for (int j = i + 1; j < objsToMesh.Count; j++)
                {
                    if (objsToMesh[i] == objsToMesh[j])
                    {
                        Debug.LogError("The list of objects to combine contains duplicates at " + i + " and " + j);
                        return(false);
                    }
                }
                if (MeshBakerUtility.GetGOMaterials(go) == null)
                {
                    Debug.LogError("Object " + go + " in the list of objects to be combined does not have a material");
                    return(false);
                }
                Mesh m = MeshBakerUtility.GetMesh(go);
                if (m == null)
                {
                    Debug.LogError("Object " + go + " in the list of objects to be combined does not have a mesh");
                    return(false);
                }
                if (m != null)              //This check can be very expensive and it only warns so only do this if we are in the editor.
                {
                    if (!Application.isEditor &&
                        Application.isPlaying &&
                        mom.textureBakeResults.doMultiMaterial &&
                        validationLevel >= MBValidationLevel.robust)
                    {
                        MeshBakerUtility.MeshAnalysisResult mar;
                        if (!meshAnalysisResultCache.TryGetValue(m.GetInstanceID(), out mar))
                        {
                            MeshBakerUtility.doSubmeshesShareVertsOrTris(m, ref mar);
                            meshAnalysisResultCache.Add(m.GetInstanceID(), mar);
                        }
                        if (mar.hasOverlappingSubmeshVerts)
                        {
                            Debug.LogWarning("Object " + objsToMesh[i] + " in the list of objects to combine has overlapping submeshes (submeshes share vertices). If the UVs associated with the shared vertices are important then this bake may not work. If you are using multiple materials then this object can only be combined with objects that use the exact same set of textures (each atlas contains one texture). There may be other undesirable side affects as well. Mesh Master, available in the asset store can fix overlapping submeshes.");
                        }
                    }
                }
            }


            List <GameObject> objs = objsToMesh;

            if (mom is MeshBaker)
            {
                objs = mom.GetObjectsToCombine();
                //if (((MB3_MeshBaker)mom).useObjsToMeshFromTexBaker && tb != null) objs = tb.GetObjectsToCombine();
                if (objs == null || objs.Count == 0)
                {
                    Debug.LogError("No meshes to combine. Please assign some meshes to combine.");
                    return(false);
                }
            }

            return(true);
        }
Example #7
0
        /// <summary>
        /// 第一步:
        /// 写入 TexturePipelineData 的 MaterialPropTexturesSet 列表,和 usedObjsToMesh 列表
        /// 每个TexSet在 Atlas 中都是一个矩形。
        /// 如果 allowedMaterialsFilter (过滤器)为空,则将收集 allObjsToMesh 上的所有材质,usedObjsToMesh 将与allObjsToMesh相同
        /// 否则,将仅包括 allowedMaterialsFilter 中的材质,usedObjsToMesh将是使用这些材料的objs。
        /// </summary>
        internal static void Step1_CollectDistinctMatTexturesAndUsedObjects(TextureCombinePipelineData data,
                                                                            EditorMethodsInterface textureEditorMethods,
                                                                            List <GameObject> usedObjsToMesh)
        {
            // 收集UsedObjects上不同的材质纹理
            bool outOfBoundsUVs = false;
            Dictionary <int, MeshAnalysisResult[]> meshAnalysisResultsCache = new Dictionary <int, MeshAnalysisResult[]>(); //cache results

            for (int i = 0; i < data.allObjsToMesh.Count; i++)
            {
                GameObject obj = data.allObjsToMesh[i];

                if (obj == null)
                {
                    Debug.LogError("合并游戏物体列表中包含空物体");
                    return;
                }

                Mesh sharedMesh = MeshBakerUtility.GetMesh(obj);
                if (sharedMesh == null)
                {
                    Debug.LogError("游戏物体 " + obj.name + " 网格为空");
                    return;
                }

                Material[] sharedMaterials = MeshBakerUtility.GetGOMaterials(obj);
                if (sharedMaterials.Length == 0)
                {
                    Debug.LogError("游戏物体 " + obj.name + " 材质为空.");
                    return;
                }

                //analyze mesh or grab cached result of previous analysis, stores one result for each submesh
                //处理网格数据
                MeshAnalysisResult[] meshAnalysisResults; //每个游戏物体的主网格子网格数据数组
                if (!meshAnalysisResultsCache.TryGetValue(sharedMesh.GetInstanceID(), out meshAnalysisResults))
                {                                         //获取参与合并物体的网格分析数据
                    meshAnalysisResults = new MeshAnalysisResult[sharedMesh.subMeshCount];
                    for (int j = 0; j < sharedMesh.subMeshCount; j++)
                    {
                        MeshBakerUtility.hasOutOfBoundsUVs(sharedMesh, ref meshAnalysisResults[j], j);
                        if (data.normalizeTexelDensity)
                        {
                            meshAnalysisResults[j].submeshArea = GetSubmeshArea(sharedMesh, j);
                        }

                        if (data.fixOutOfBoundsUVs && !meshAnalysisResults[j].hasUVs)
                        {
                            meshAnalysisResults[j].uvRect = new Rect(0, 0, 1, 1);
                            Debug.LogWarning("Mesh for object " + obj + " has no UV channel but 'consider UVs' is enabled." +
                                             " Assuming UVs will be generated filling 0,0,1,1 rectangle.");
                        }
                    }
                    meshAnalysisResultsCache.Add(sharedMesh.GetInstanceID(), meshAnalysisResults);
                }

                //处理材质数据
                for (int matIdx = 0; matIdx < sharedMaterials.Length; matIdx++)
                {
                    Material mat = sharedMaterials[matIdx];

                    // 材质过滤器
                    if (data.allowedMaterialsFilter != null &&
                        !data.allowedMaterialsFilter.Contains(mat))
                    {
                        continue;
                    }

                    outOfBoundsUVs = outOfBoundsUVs || meshAnalysisResults[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;
                    }

                    if (data.fixOutOfBoundsUVs)
                    {
                        if (!MeshBakerUtility.AreAllSharedMaterialsDistinct(sharedMaterials))
                        {
                            Debug.LogWarning("游戏物体 " + obj.name + " 使用相同的材质在多个子网格. " +
                                             "可能生成奇怪的 resultAtlasesAndRects,尤其是与 _fixOutOfBoundsUVs 为 true 时");
                        }
                    }

                    //材质属性 Texutre 信息
                    MaterialPropTexture[] mts = new MaterialPropTexture[data.texPropertyNames.Count];
                    for (int propIdx = 0; propIdx < data.texPropertyNames.Count; propIdx++)
                    {
                        Texture tx           = null;
                        Vector2 scale        = Vector2.one;
                        Vector2 offset       = Vector2.zero;
                        float   texelDensity = 0f;
                        if (mat.HasProperty(data.texPropertyNames[propIdx].name))
                        {
                            Texture txx = GetTextureConsideringStandardShaderKeywords(data.ResultMaterial.shader.name, mat, data.texPropertyNames[propIdx].name);
                            if (txx != null)
                            {
                                if (txx is Texture2D)
                                {
                                    //TextureFormat 验证
                                    tx = txx;
                                    TextureFormat f           = ((Texture2D)tx).format;
                                    bool          isNormalMap = false;
                                    if (!Application.isPlaying && textureEditorMethods != null)
                                    {
                                        isNormalMap = textureEditorMethods.IsNormalMap((Texture2D)tx);
                                    }
                                    if ((f == TextureFormat.ARGB32 ||
                                         f == TextureFormat.RGBA32 ||
                                         f == TextureFormat.BGRA32 ||
                                         f == TextureFormat.RGB24 ||
                                         f == TextureFormat.Alpha8) && !isNormalMap) //DXT5 does not work
                                    {
                                        //可使用
                                    }
                                    else
                                    {
                                        //TRIED to copy texture using tex2.SetPixels(tex1.GetPixels()) but bug in 3.5 means DTX1 and 5 compressed textures come out skewe
                                        //尝试使用tex2.SetPixels(tex1.GetPixels())复制纹理,但是3.5中的bug意味着DTX1和5压缩纹理出现扭曲
                                        if (Application.isPlaying && data.packingAlgorithm != PackingAlgorithmEnum.MeshBakerTexturePacker_Fast)
                                        {
                                            Debug.LogWarning("合并列表中,游戏物体 " + obj.name + " 所使用的 Texture " +
                                                             tx.name + " 使用的格式 " + f +
                                                             "不是: ARGB32, RGBA32, BGRA32, RGB24, Alpha8 或 DXT. " +
                                                             "无法在运行时重新设置尺寸" +
                                                             "If format says 'compressed' try changing it to 'truecolor'");
                                            return;
                                        }
                                        else
                                        {
                                            tx = (Texture2D)mat.GetTexture(data.texPropertyNames[propIdx].name);
                                        }
                                    }
                                }
                                else
                                {
                                    Debug.LogError("合并列表中,游戏物体 " + obj.name + " 渲染网格使用的 Texture 不是 Texture2D. ");
                                    return;
                                }
                            }
                            //像素密度
                            if (tx != null && data.normalizeTexelDensity)
                            {
                                //不考虑平铺和UV采样超出范围
                                if (meshAnalysisResults[propIdx].submeshArea == 0)
                                {
                                    texelDensity = 0f;
                                }
                                else
                                {
                                    texelDensity = (tx.width * tx.height) / (meshAnalysisResults[propIdx].submeshArea);
                                }
                            }
                            //规格,偏移
                            GetMaterialScaleAndOffset(mat, data.texPropertyNames[propIdx].name, out offset, out scale);
                        }

                        mts[propIdx] = new MaterialPropTexture(tx, offset, scale, texelDensity);
                    }

                    // 收集材质参数值的平均值
                    data.nonTexturePropertyBlender.CollectAverageValuesOfNonTextureProperties(data.ResultMaterial, mat);

                    Vector2 obUVscale  = new Vector2(meshAnalysisResults[matIdx].uvRect.width, meshAnalysisResults[matIdx].uvRect.height);
                    Vector2 obUVoffset = new Vector2(meshAnalysisResults[matIdx].uvRect.x, meshAnalysisResults[matIdx].uvRect.y);

                    //Add to distinct set of textures if not already there
                    TextureTilingTreatment tilingTreatment = TextureTilingTreatment.none;
                    if (data.fixOutOfBoundsUVs)
                    {
                        tilingTreatment = TextureTilingTreatment.considerUVs;
                    }

                    //合并信息 distinctMaterialTextures 数据设置

                    //材质各参数 Texture,及 UV 偏移数据映射
                    MaterialPropTexturesSet setOfTexs = new MaterialPropTexturesSet(mts, obUVoffset, obUVscale, tilingTreatment);  //one of these per submesh
                    //材质及各变化参数Rect 数据
                    MatAndTransformToMerged matt = new MatAndTransformToMerged(new DRect(obUVoffset, obUVscale), data.fixOutOfBoundsUVs, mat);

                    setOfTexs.matsAndGOs.mats.Add(matt);

                    MaterialPropTexturesSet setOfTexs2 = data.distinctMaterialTextures.Find(x => x.IsEqual(setOfTexs, data.fixOutOfBoundsUVs, data.nonTexturePropertyBlender));
                    if (setOfTexs2 != null)
                    {
                        setOfTexs = setOfTexs2;
                    }
                    else
                    {
                        data.distinctMaterialTextures.Add(setOfTexs);
                    }

                    if (!setOfTexs.matsAndGOs.mats.Contains(matt))
                    {
                        setOfTexs.matsAndGOs.mats.Add(matt);
                    }

                    if (!setOfTexs.matsAndGOs.gos.Contains(obj))
                    {
                        setOfTexs.matsAndGOs.gos.Add(obj);
                        //已使用 游戏物体
                        if (!usedObjsToMesh.Contains(obj))
                        {
                            usedObjsToMesh.Add(obj);
                        }
                    }
                }
            }

            Debug.Log(string.Format("第一阶段完成;" +
                                    "参与合并的游戏物体的不同材质,各自包含与shader属性对应的不同的纹理,收集到 {0} 组 textures,即 {0} 个不同的材质," +
                                    "fixOutOfBoundsUV:{1} " +
                                    "considerNonTextureProperties:{2}",
                                    data.distinctMaterialTextures.Count, data.fixOutOfBoundsUVs, data.considerNonTextureProperties));

            if (data.distinctMaterialTextures.Count == 0)
            {
                Debug.LogError("None of the source object materials matched any of the allowed materials for submesh with result material: " + data.ResultMaterial);
                return;
            }

            TextureCombinerMerging merger = new TextureCombinerMerging(data.considerNonTextureProperties,
                                                                       data.nonTexturePropertyBlender, data.fixOutOfBoundsUVs);

            merger.MergeOverlappingDistinctMaterialTexturesAndCalcMaterialSubrects(data.distinctMaterialTextures);
        }
        /// <summary>
        /// Creates for materials on renderer.
        /// </summary>
        /// <returns>Generates an MB2_TextureBakeResult that can be used if all objects to be combined use the same material.
        /// Returns a MB2_TextureBakeResults that will map all materials used by renderer r to
        /// the rectangle 0,0..1,1 in the atlas.</returns>
        /// <param name="r">The red component.</param>
        public static TextureBakeResults CreateForMaterialsOnRenderer(GameObject[] gos)
        {
            HashSet <Material> fullMaterialList = new HashSet <Material>();

            for (int i = 0; i < gos.Length; i++)
            {
                if (gos[i] == null)
                {
                    Debug.LogError(string.Format("Game object {0} in list of objects to add was null", i));
                    return(null);
                }
                Material[] oMats = MeshBakerUtility.GetGOMaterials(gos[i]);
                if (oMats == null)
                {
                    Debug.LogError(string.Format("Game object {0} in list of objects to add no renderer", i));
                    return(null);
                }
                for (int j = 0; j < oMats.Length; j++)
                {
                    fullMaterialList.Add(oMats[j]);
                }
            }
            Material[] rms = new Material[fullMaterialList.Count];
            fullMaterialList.CopyTo(rms);

            TextureBakeResults tbr = new TextureBakeResults();
            //Material[] ms = rms;
            //MB_MaterialAndUVRect[] mss = new MB_MaterialAndUVRect[rms.Length];
            List <MaterialAndUVRect> mss = new List <MaterialAndUVRect>();

            Material[] ms;
            for (int i = 0; i < rms.Length; i++)
            {
                if (rms[i] != null)
                {
                    MaterialAndUVRect matAndUVRect = new MaterialAndUVRect(rms[i], new Rect(0f, 0f, 1f, 1f),
                                                                           new Rect(0f, 0f, 1f, 1f),
                                                                           new Rect(0f, 0f, 1f, 1f),
                                                                           new Rect(0f, 0f, 1f, 1f), "");
                    if (!mss.Contains(matAndUVRect))
                    {
                        mss.Add(matAndUVRect);
                    }
                }
            }
            if (rms.Length > 1)
            {
                tbr.prefabUVRects   = new Rect[mss.Count];
                tbr.materials       = ms = new Material[mss.Count];
                tbr.resultMaterials = new MultiMaterial[mss.Count];
                for (int i = 0; i < mss.Count; i++)
                {
                    ms[i] = mss[i].material;
                    tbr.prefabUVRects[i]   = new Rect(0f, 0f, 1f, 1f);
                    tbr.resultMaterials[i] = new MultiMaterial();
                    List <Material> sourceMats = new List <Material>();
                    sourceMats.Add(ms[i]);
                    tbr.resultMaterials[i].sourceMaterials  = sourceMats;
                    tbr.resultMaterials[i].combinedMaterial = ms[i];
                }
                tbr.doMultiMaterial = true;
            }
            else
            {
                tbr.doMultiMaterial = false;
                tbr.prefabUVRects   = new Rect[] { new Rect(0f, 0f, 1f, 1f) };
                tbr.materials       = ms = new Material[] { mss[0].material };
                tbr.resultMaterial  = mss[0].material;
                tbr.resultMaterials = new MultiMaterial[] { new MultiMaterial() };
                List <Material> sourceMats = new List <Material>();
                sourceMats.Add(ms[0]);
                tbr.resultMaterials[0].sourceMaterials  = sourceMats;
                tbr.resultMaterials[0].combinedMaterial = mss[0].material;
            }
            tbr.materialsAndUVRects = mss.ToArray();
            tbr.fixOutOfBoundsUVs   = false;
            return(tbr);
        }