Exemplo n.º 1
0
 public static bool hasOutOfBoundsUVs(Mesh m, ref MeshAnalysisResult putResultHere, int submeshIndex = -1, int uvChannel = 0)
 {
     if (m == null)
     {
         putResultHere.hasOutOfBoundsUVs = false;
         return(putResultHere.hasOutOfBoundsUVs);
     }
     Vector2[] uvs;
     if (uvChannel == 0)
     {
         uvs = m.uv;
     }
     else if (uvChannel == 1)
     {
         uvs = m.uv2;
     }
     else if (uvChannel == 2)
     {
         uvs = m.uv3;
     }
     else
     {
         uvs = m.uv4;
     }
     return(hasOutOfBoundsUVs(uvs, m, ref putResultHere, submeshIndex));
 }
Exemplo n.º 2
0
        public static int doSubmeshesShareVertsOrTris(Mesh m, ref MeshAnalysisResult mar)
        {
            MB_Triangle consider = new MB_Triangle();
            MB_Triangle other    = new MB_Triangle();

            //cache all triangles
            int[][] tris = new int[m.subMeshCount][];
            for (int i = 0; i < m.subMeshCount; i++)
            {
                tris[i] = m.GetTriangles(i);
            }
            bool sharesVerts = false;
            bool sharesTris  = false;

            for (int i = 0; i < m.subMeshCount; i++)
            {
                int[] smA = tris[i];
                for (int j = i + 1; j < m.subMeshCount; j++)
                {
                    int[] smB = tris[j];
                    for (int k = 0; k < smA.Length; k += 3)
                    {
                        consider.Initialize(smA, k, i);
                        for (int l = 0; l < smB.Length; l += 3)
                        {
                            other.Initialize(smB, l, j);
                            if (consider.isSame(other))
                            {
                                sharesTris = true;
                                break;
                            }
                            if (consider.sharesVerts(other))
                            {
                                sharesVerts = true;
                                break;
                            }
                        }
                    }
                }
            }
            if (sharesTris)
            {
                mar.hasOverlappingSubmeshVerts = true;
                mar.hasOverlappingSubmeshTris  = true;
                return(2);
            }
            else if (sharesVerts)
            {
                mar.hasOverlappingSubmeshVerts = true;
                mar.hasOverlappingSubmeshTris  = false;
                return(1);
            }
            else
            {
                mar.hasOverlappingSubmeshTris  = false;
                mar.hasOverlappingSubmeshVerts = false;
                return(0);
            }
        }
Exemplo n.º 3
0
        public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds)
        {
            MeshAnalysisResult mar = new MeshAnalysisResult();
            bool outVal            = hasOutOfBoundsUVs(m, ref mar);

            uvBounds = mar.uvRect;
            return(outVal);
        }
 public static bool hasOutOfBoundsUVs(Mesh m, ref MeshAnalysisResult putResultHere, int submeshIndex = -1)
 {
     if (m == null)
     {
         putResultHere.hasOutOfBoundsUVs = false;
         return(putResultHere.hasOutOfBoundsUVs);
     }
     Vector2[] uvs = m.uv;
     return(hasOutOfBoundsUVs(uvs, m, ref putResultHere, submeshIndex));
 }
Exemplo n.º 5
0
        public static bool hasOutOfBoundsUVs(Vector2[] uvs, Mesh m, ref MeshAnalysisResult putResultHere, int submeshIndex = -1)
        {
            putResultHere.hasUVs = true;
            if (uvs.Length == 0)
            {
                putResultHere.hasUVs            = false;
                putResultHere.hasOutOfBoundsUVs = false;
                putResultHere.uvRect            = new Rect();
                return(putResultHere.hasOutOfBoundsUVs);
            }
            float minx, miny, maxx, maxy;

            if (submeshIndex >= m.subMeshCount)
            {
                putResultHere.hasOutOfBoundsUVs = false;
                putResultHere.uvRect            = new Rect();
                return(putResultHere.hasOutOfBoundsUVs);
            }
            else if (submeshIndex >= 0)
            {
                //checking specific submesh
                int[] tris = m.GetTriangles(submeshIndex);
                if (tris.Length == 0)
                {
                    putResultHere.hasOutOfBoundsUVs = false;
                    putResultHere.uvRect            = new Rect();
                    return(putResultHere.hasOutOfBoundsUVs);
                }
                minx = maxx = uvs[tris[0]].x;
                miny = maxy = uvs[tris[0]].y;
                for (int idx = 0; idx < tris.Length; idx++)
                {
                    int i = tris[idx];
                    if (uvs[i].x < minx)
                    {
                        minx = uvs[i].x;
                    }
                    if (uvs[i].x > maxx)
                    {
                        maxx = uvs[i].x;
                    }
                    if (uvs[i].y < miny)
                    {
                        miny = uvs[i].y;
                    }
                    if (uvs[i].y > maxy)
                    {
                        maxy = uvs[i].y;
                    }
                }
            }
            else
            {
                //checking all UVs
                minx = maxx = uvs[0].x;
                miny = maxy = uvs[0].y;
                for (int i = 0; i < uvs.Length; i++)
                {
                    if (uvs[i].x < minx)
                    {
                        minx = uvs[i].x;
                    }
                    if (uvs[i].x > maxx)
                    {
                        maxx = uvs[i].x;
                    }
                    if (uvs[i].y < miny)
                    {
                        miny = uvs[i].y;
                    }
                    if (uvs[i].y > maxy)
                    {
                        maxy = uvs[i].y;
                    }
                }
            }
            Rect uvBounds = new Rect();

            uvBounds.x      = minx;
            uvBounds.y      = miny;
            uvBounds.width  = maxx - minx;
            uvBounds.height = maxy - miny;
            if (maxx > 1f || minx < 0f || maxy > 1f || miny < 0f)
            {
                putResultHere.hasOutOfBoundsUVs = true;
            }
            else
            {
                putResultHere.hasOutOfBoundsUVs = false;
            }
            putResultHere.uvRect = uvBounds;
            return(putResultHere.hasOutOfBoundsUVs);
        }
Exemplo n.º 6
0
        //posibilities
        //  using fixOutOfBoundsUVs or not
        //
        /// <summary>
        /// 根据合并列表物体配置多材质
        /// </summary>
        /// <param name="mom"></param>
        /// <param name="resultMaterials"></param>
        /// <param name="textureBaker"></param>
        public static void ConfigureMutiMaterialsFromObjsToCombine(TextureCombineEntrance mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
        {
            if (mom.GetObjectsToCombine().Count == 0)
            {
                Debug.LogError("合并列表为空");
                return;
            }
            if (resultMaterials.arraySize > 0)
            {
                Debug.LogError("多材质映射已配置,在进行当前操作前需清除旧配置");
                return;
            }
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Texture Bake Result 为空");
                return;
            }

            //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("合并列表中有空物体于 " + i);
                    return;
                }
                Renderer r = go.GetComponent <Renderer>();
                if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
                {
                    Debug.LogError("合并列表中第 " + i + " 个游戏物体没有 renderer 组件");
                    return;
                }
                if (r.sharedMaterial == null)
                {
                    Debug.LogError("合并列表中第 " + i + " 个游戏物体没有材质");
                    return;
                }
            }



            Dictionary <Material, Mesh> obUVobjectToMesh_map = new Dictionary <Material, Mesh>();

            //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs
            //1.将所有带有obUV的网格置于单独的材质中,(如果不固定OB UV)
            if (mom.doMultiMaterialSplitAtlasesIfOBUVs)
            {
                for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
                {
                    GameObject         go       = mom.GetObjectsToCombine()[i];
                    Mesh               m        = MeshBakerUtility.GetMesh(go);
                    MeshAnalysisResult dummyMar = new MeshAnalysisResult();
                    Renderer           r        = go.GetComponent <Renderer>();
                    for (int j = 0; j < r.sharedMaterials.Length; j++)
                    {
                        if (MeshBakerUtility.hasOutOfBoundsUVs(m, ref dummyMar, j))
                        {
                            if (!obUVobjectToMesh_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");
                                obUVobjectToMesh_map.Add(r.sharedMaterials[j], m);
                            }
                        }
                    }
                }
            }

            Dictionary <MultiMatSubmeshInfo, List <List <Material> > > shaderToMaterial_map = new Dictionary <MultiMatSubmeshInfo, List <List <Material> > >();

            //2.没有 OB uvs 的材质按 shader 添加到 shader2Material_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 (!obUVobjectToMesh_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 (!shaderToMaterial_map.TryGetValue(newKey, out binsOfMatsThatUseShader))
                        {
                            binsOfMatsThatUseShader = new List <List <Material> >();
                            binsOfMatsThatUseShader.Add(new List <Material>());
                            shaderToMaterial_map.Add(newKey, binsOfMatsThatUseShader);
                        }
                        if (!binsOfMatsThatUseShader[0].Contains(r.sharedMaterials[j]))
                        {
                            binsOfMatsThatUseShader[0].Add(r.sharedMaterials[j]);
                        }
                    }
                }
            }

            int ResultMatsCount = shaderToMaterial_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
            // 3.检查每个 Shader-Mat 组的最终打包的 atlas 大小,过大则分到另一个图集中
            if (mom.doMultiMaterialSplitAtlasesIfTooBig)
            {
                if (mom.packingAlgorithm == PackingAlgorithmEnum.UnitysPackTextures)
                {
                    Debug.LogWarning("Unity texture packer does not support splitting atlases if too big. Atlases will not be split.");
                }
                else
                {
                    ResultMatsCount = 0;
                    foreach (MultiMatSubmeshInfo sh in shaderToMaterial_map.Keys)
                    {
                        List <List <Material> > binsOfMatsThatUseShader = shaderToMaterial_map[sh];
                        List <Material>         allMatsThatUserShader   = binsOfMatsThatUseShader[0];//at this point everything is in the same list
                        binsOfMatsThatUseShader.RemoveAt(0);
                        TextureCombineHandler 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, 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);
                        }
                        ResultMatsCount += binsOfMatsThatUseShader.Count;
                    }
                }
            }

            //build the result materials
            if (shaderToMaterial_map.Count == 0 && obUVobjectToMesh_map.Count == 0)
            {
                Debug.LogError("合并列表中没有材质");
            }

            mom.resultMaterials = new MultiMaterial[ResultMatsCount + obUVobjectToMesh_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 shaderToMaterial_map.Keys)
            {
                foreach (List <Material> sourseMatsThatUseSameShader in shaderToMaterial_map[sh])
                {
                    MultiMaterial mm = mom.resultMaterials[k] = new MultiMaterial();
                    mm.sourceMaterials = sourseMatsThatUseSameShader;
                    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 (sourseMatsThatUseSameShader.Count > 0 && sourseMatsThatUseSameShader[0] != null)
                    {
                        //复制参数值
                        TextureCombineEntrance.ConfigureNewMaterialToMatchOld(newMat, sourseMatsThatUseSameShader[0]);
                    }
                    AssetDatabase.CreateAsset(newMat, matName);
                    //合并材质初始值为源材质列表第一个的值
                    mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                    k++;
                }
            }

            foreach (Material m in obUVobjectToMesh_map.Keys)
            {
                MultiMaterial mm = mom.resultMaterials[k] = new 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"));
                TextureCombineEntrance.ConfigureNewMaterialToMatchOld(newMat, m);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            SceneBakerUtilityInEditor.UpdateIfDirtyOrScript(textureBaker);
        }
Exemplo n.º 7
0
        public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds, ref MeshAnalysisResult putResultHere, int submeshIndex = -1)
        {
            if (m == null)
            {
                putResultHere.hasOutOfBoundsUVs = false;
                return(putResultHere.hasOutOfBoundsUVs);
            }
            Vector2[] uvs = m.uv;
            if (uvs.Length == 0)
            {
                putResultHere.hasOutOfBoundsUVs = false;
                putResultHere.uvRect            = uvBounds;
                return(putResultHere.hasOutOfBoundsUVs);
            }
            float minx, miny, maxx, maxy;

            if (submeshIndex >= m.subMeshCount)
            {
                putResultHere.hasOutOfBoundsUVs = false;
                putResultHere.uvRect            = uvBounds;
                return(putResultHere.hasOutOfBoundsUVs);
            }
            else if (submeshIndex >= 0)
            {
                //checking specific submesh
                int[] tris = m.GetTriangles(submeshIndex);
                if (tris.Length == 0)
                {
                    putResultHere.hasOutOfBoundsUVs = false;
                    putResultHere.uvRect            = uvBounds;
                    return(putResultHere.hasOutOfBoundsUVs);
                }
                minx = maxx = uvs[tris[0]].x;
                miny = maxy = uvs[tris[0]].y;
                for (int idx = 0; idx < tris.Length; idx++)
                {
                    int i = tris[idx];
                    if (uvs[i].x < minx)
                    {
                        minx = uvs[i].x;
                    }
                    if (uvs[i].x > maxx)
                    {
                        maxx = uvs[i].x;
                    }
                    if (uvs[i].y < miny)
                    {
                        miny = uvs[i].y;
                    }
                    if (uvs[i].y > maxy)
                    {
                        maxy = uvs[i].y;
                    }
                }
            }
            else
            {
                //checking all UVs
                minx = maxx = uvs[0].x;
                miny = maxy = uvs[0].y;
                for (int i = 0; i < uvs.Length; i++)
                {
                    if (uvs[i].x < minx)
                    {
                        minx = uvs[i].x;
                    }
                    if (uvs[i].x > maxx)
                    {
                        maxx = uvs[i].x;
                    }
                    if (uvs[i].y < miny)
                    {
                        miny = uvs[i].y;
                    }
                    if (uvs[i].y > maxy)
                    {
                        maxy = uvs[i].y;
                    }
                }
            }
            uvBounds.x      = minx;
            uvBounds.y      = miny;
            uvBounds.width  = maxx - minx;
            uvBounds.height = maxy - miny;
            if (maxx > 1f || minx < 0f || maxy > 1f || miny < 0f)
            {
                putResultHere.hasOutOfBoundsUVs = true;
                putResultHere.uvRect            = uvBounds;
                return(putResultHere.hasOutOfBoundsUVs);
            }
            //all well behaved objs use the same rect so TexSets compare properly
            uvBounds.x                      = uvBounds.y = 0f;
            uvBounds.width                  = uvBounds.height = 1f;
            putResultHere.uvRect            = uvBounds;
            putResultHere.hasOutOfBoundsUVs = false;
            return(putResultHere.hasOutOfBoundsUVs);
        }
Exemplo n.º 8
0
        public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds)
        {
            MeshAnalysisResult mar = new MeshAnalysisResult();

            return(hasOutOfBoundsUVs(m, ref uvBounds, ref mar));
        }
Exemplo n.º 9
0
	public static int doSubmeshesShareVertsOrTris(Mesh m, ref MeshAnalysisResult mar){
		MB_Triangle consider = new MB_Triangle();
		MB_Triangle other = new MB_Triangle();
		//cache all triangles
		int[][] tris = new int[m.subMeshCount][];
		for (int i = 0; i < m.subMeshCount; i++){
			tris[i] = m.GetTriangles(i);
		}
		bool sharesVerts = false;
		bool sharesTris = false;
		for (int i = 0; i < m.subMeshCount; i++){
			int[] smA = tris[i];
			for (int j = i+1; j < m.subMeshCount; j++){
				int[] smB = tris[j];
				for (int k = 0; k < smA.Length; k+=3){
					consider.Initialize(smA,k,i);
					for (int l = 0; l < smB.Length; l+=3){
						other.Initialize(smB,l,j);
						if (consider.isSame(other)){
							sharesTris = true;
							break;
						}
						if (consider.sharesVerts(other)){
							sharesVerts = true;
							break;
						}					
					}
				}
			}
		}
		if (sharesTris){
				mar.hasOverlappingSubmeshVerts = true;
				mar.hasOverlappingSubmeshTris = true;
				return 2;
		} else if (sharesVerts){
				mar.hasOverlappingSubmeshVerts = true;
				mar.hasOverlappingSubmeshTris = false;
				return 1;
		} else {
				mar.hasOverlappingSubmeshTris = false;
				mar.hasOverlappingSubmeshVerts = false;
				return 0;
		}
	}	
Exemplo n.º 10
0
	public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds, ref MeshAnalysisResult putResultHere, int submeshIndex = -1){
		if (m == null){
			putResultHere.hasOutOfBoundsUVs = false;
			return putResultHere.hasOutOfBoundsUVs;
		}
		Vector2[] uvs = m.uv;
		if (uvs.Length == 0){
			putResultHere.hasOutOfBoundsUVs = false;
			putResultHere.uvRect = uvBounds;
			return putResultHere.hasOutOfBoundsUVs;
		}
		float minx,miny,maxx,maxy;
		if (submeshIndex >= m.subMeshCount){
			putResultHere.hasOutOfBoundsUVs = false;
			putResultHere.uvRect = uvBounds;
			return putResultHere.hasOutOfBoundsUVs;
		} else if (submeshIndex >= 0){
			//checking specific submesh
			int[] tris = m.GetTriangles(submeshIndex);
			if (tris.Length == 0) {
				putResultHere.hasOutOfBoundsUVs = false;
				putResultHere.uvRect = uvBounds;
				return putResultHere.hasOutOfBoundsUVs;
			}
			minx = maxx = uvs[tris[0]].x;
			miny = maxy = uvs[tris[0]].y;
			for (int idx = 0; idx < tris.Length; idx++){
				int i = tris[idx];
				if (uvs[i].x < minx) minx = uvs[i].x;
				if (uvs[i].x > maxx) maxx = uvs[i].x;
				if (uvs[i].y < miny) miny = uvs[i].y;
				if (uvs[i].y > maxy) maxy = uvs[i].y;
			}			
		} else {
			//checking all UVs
			minx = maxx = uvs[0].x;
			miny = maxy = uvs[0].y;
			for (int i = 0; i < uvs.Length; i++){
					if (uvs[i].x < minx) minx = uvs[i].x;
					if (uvs[i].x > maxx) maxx = uvs[i].x;
					if (uvs[i].y < miny) miny = uvs[i].y;
					if (uvs[i].y > maxy) maxy = uvs[i].y;
			}
		} 
		uvBounds.x = minx;
		uvBounds.y = miny;
		uvBounds.width = maxx - minx;
		uvBounds.height = maxy - miny;
		if (maxx > 1f || minx < 0f || maxy > 1f || miny < 0f){
			putResultHere.hasOutOfBoundsUVs = true;
			putResultHere.uvRect = uvBounds;
			return putResultHere.hasOutOfBoundsUVs;
		}
		//all well behaved objs use the same rect so TexSets compare properly
		uvBounds.x = uvBounds.y = 0f;
		uvBounds.width = uvBounds.height = 1f;
		putResultHere.uvRect = uvBounds;
		putResultHere.hasOutOfBoundsUVs = false;
		return putResultHere.hasOutOfBoundsUVs;
	}
Exemplo n.º 11
0
	public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds){
		MeshAnalysisResult mar = new MeshAnalysisResult();
		return hasOutOfBoundsUVs(m,ref uvBounds, ref mar);
	}
Exemplo n.º 12
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);
        }