コード例 #1
0
        /// <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);
        }
コード例 #2
0
        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);
        }
 public bool ValidateSkinnedMeshes(List <GameObject> objs)
 {
     for (int i = 0; i < objs.Count; i++)
     {
         Renderer r = MeshBakerUtility.GetRenderer(objs[i]);
         if (r is SkinnedMeshRenderer)
         {
             Transform[] bones = ((SkinnedMeshRenderer)r).bones;
             if (bones.Length == 0)
             {
                 Debug.LogWarning("SkinnedMesh " + i + " (" + objs[i] + ") in the list of objects to combine has no bones. Check that 'optimize game object' is not checked in the 'Rig' tab of the asset importer. Mesh Baker cannot combine optimized skinned meshes because the bones are not available.");
             }
             //					UnityEngine.Object parentObject = EditorUtility.GetPrefabParent(r.gameObject);
             //					string path = AssetDatabase.GetAssetPath(parentObject);
             //					Debug.Log (path);
             //					AssetImporter ai = AssetImporter.GetAtPath( path );
             //					Debug.Log ("bbb " + ai);
             //					if (ai != null && ai is ModelImporter){
             //						Debug.Log ("valing 2");
             //						ModelImporter modelImporter = (ModelImporter) ai;
             //						if(modelImporter.optimizeMesh){
             //							Debug.LogError("SkinnedMesh " + i + " (" + objs[i] + ") in the list of objects to combine is optimized. Mesh Baker cannot combine optimized skinned meshes because the bones are not available.");
             //						}
             //					}
         }
     }
     return(true);
 }
        /**
         *       pass in System.IO.File.WriteAllBytes for parameter fileSaveFunction. This is necessary because on Web Player file saving
         *       functions only exist for Editor classes
         */
        public void SaveAtlasToAssetDatabase(Texture2D atlas, ShaderTextureProperty texPropertyName, int atlasNum, Material resMat)
        {
            if (atlas == null)
            {
                SetMaterialTextureProperty(resMat, texPropertyName, null);
            }
            else
            {
                string prefabPth = AssetDatabase.GetAssetPath(resMat);
                if (prefabPth == null || prefabPth.Length == 0)
                {
                    Debug.LogError("Could save atlas. Could not find result material in AssetDatabase.");
                    return;
                }

                string baseName       = Path.GetFileNameWithoutExtension(prefabPth);
                string folderPath     = prefabPth.Substring(0, prefabPth.Length - baseName.Length - 4);
                string fullFolderPath = Application.dataPath + folderPath.Substring("Assets".Length, folderPath.Length - "Assets".Length);
                string pth            = fullFolderPath + baseName + "-" + texPropertyName.name + "-atlas" + atlasNum;
                string relativePath   = folderPath + baseName + "-" + texPropertyName.name + "-atlas" + atlasNum;
                //need to create a copy because sometimes the packed atlases are not in ARGB32 format
                Texture2D newTex = MeshBakerUtility.createTextureCopy(atlas);
                int       size   = Mathf.Max(newTex.height, newTex.width);
                if (SAVE_FORMAT == saveTextureFormat.png)
                {
                    pth          += ".png";
                    relativePath += ".png";
                    byte[] bytes = newTex.EncodeToPNG();
                    System.IO.File.WriteAllBytes(pth, bytes);
                }
                else
                {
                    pth          += ".tga";
                    relativePath += ".tga";
                    if (File.Exists(pth))
                    {
                        File.Delete(pth);
                    }

                    //Create the file.
                    FileStream fs = File.Create(pth);
                    MB_TGAWriter.Write(newTex.GetPixels(), newTex.width, newTex.height, fs);
                }
                UnityEditor.Editor.DestroyImmediate(newTex);
                AssetDatabase.Refresh();
                Debug.Log(String.Format("Wrote atlas for {0} to file:{1}", texPropertyName.name, pth));
                Texture2D txx = (Texture2D)(AssetDatabase.LoadAssetAtPath(relativePath, typeof(Texture2D)));
                SetTextureSize(txx, size);
                SetMaterialTextureProperty(resMat, texPropertyName, relativePath);
            }
        }
コード例 #5
0
        public void DrawGUI(IMeshCombinerSetting momm, bool settingsEnabled)
        {
            EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle);
            GUI.enabled = settingsEnabled;
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(doNorm, gc_doNormGUIContent);
            EditorGUILayout.PropertyField(doTan, gc_doTanGUIContent);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(doUV, gc_doUVGUIContent);
            EditorGUILayout.PropertyField(doUV3, gc_doUV3GUIContent);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(doUV4, gc_doUV4GUIContent);
            EditorGUILayout.PropertyField(doCol, gc_doColGUIContent);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.PropertyField(doBlendShapes, gc_doBlendShapeGUIContent);

            //光照贴图处理
            if (momm.lightmapOption == LightmapOptions.preserve_current_lightmapping)
            {
                if (MeshBakerUtility.GetMajorVersion() == 5)
                {
                    EditorGUILayout.HelpBox("The best choice for Unity 5 is to Ignore_UV2 or Generate_New_UV2 layout. " +
                                            "Unity's baked GI will create the UV2 layout it wants. See manual for more information.", MessageType.Warning);
                }
            }

            if (momm.lightmapOption == LightmapOptions.generate_new_UV2_layout)
            {
                EditorGUILayout.HelpBox("Generating new lightmap UVs can split vertices which can push " +
                                        "the number of vertices over the 64k limit.", MessageType.Warning);
            }
            EditorGUILayout.PropertyField(lightmappingOption, gc_lightmappingOptionGUIContent);
            if (momm.lightmapOption == LightmapOptions.generate_new_UV2_layout)
            {
                EditorGUILayout.PropertyField(uv2OutputParamsHardAngle, gc_uv2HardAngleGUIContent);
                EditorGUILayout.PropertyField(uv2OutputParamsPackingMargin, gc_uv2PackingMarginUV3GUIContent);
                EditorGUILayout.Separator();
            }

            EditorGUILayout.PropertyField(renderType, gc_renderTypeGUIContent);
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(clearBuffersAfterBake, gc_clearBuffersAfterBakeGUIContent);
            EditorGUILayout.PropertyField(centerMeshToBoundsCenter, gc_CenterMeshToBoundsCenter);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.PropertyField(optimizeAfterBake, gc_OptimizeAfterBake);
            GUI.enabled = true;
            EditorGUILayout.EndVertical();
        }
        /// <summary>
        /// Bakes a combined mesh.
        /// </summary>
        /// <param name="mom"></param>
        /// <param name="so">This is needed to work around a Unity bug where UnpackPrefabInstance corrupts
        /// a SerializedObject. Only needed for bake into prefab.</param>
        public static bool bake(MeshBakerCommon mom, ref SerializedObject so)
        {
            bool createdDummyTextureBakeResults = false;
            bool success = false;

            try
            {
                if (mom.meshCombiner.outputOption == OutputOptions.bakeIntoSceneObject ||
                    mom.meshCombiner.outputOption == OutputOptions.bakeIntoPrefab)
                {
                    success = MeshCombinerEditorFunctions.BakeIntoCombined(mom, out createdDummyTextureBakeResults, ref so);
                }
                else
                {
                    //bake meshes in place
                    if (mom is MeshCombinerEntrance)
                    {
                        ValidationLevel vl = Application.isPlaying ? ValidationLevel.quick : ValidationLevel.robust;
                        if (!MeshBakerRoot.DoCombinedValidate(mom, ObjsToCombineTypes.prefabOnly, new EditorMethods(), vl))
                        {
                            return(false);
                        }

                        List <GameObject> objsToMesh = mom.GetObjectsToCombine();
                        ////success = MB3_BakeInPlace.BakeMeshesInPlace((MeshCombineHandler)((MeshCombinerEntrance)mom).meshCombiner, objsToMesh, mom.bakeAssetsInPlaceFolderPath, mom.clearBuffersAfterBake, updateProgressBar);
                    }
                    else
                    {
                        //多网格合并无法 Bake In Place
                        Debug.LogError("Multi-mesh Baker components cannot be used for Bake In Place. Use an ordinary Mesh Baker object instead.");
                    }
                }
                mom.meshCombiner.CheckIntegrity();
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            finally
            {
                if (createdDummyTextureBakeResults && mom.textureBakeResults != null)
                {
                    MeshBakerUtility.Destroy(mom.textureBakeResults);
                    mom.textureBakeResults = null;
                }
                EditorUtility.ClearProgressBar();
            }
            return(success);
        }
        /// <summary>
        /// 构建预制体
        /// </summary>
        /// <param name="mom"></param>
        /// <param name="so"></param>
        public static void RebuildPrefab(MeshBakerCommon mom, ref SerializedObject so)
        {
            GameObject prefabRoot = mom.resultPrefab;
            GameObject rootGO     = (GameObject)PrefabUtility.InstantiatePrefab(prefabRoot);

            SceneBakerUtilityInEditor.UnpackPrefabInstance(rootGO, ref so);

            //remove all renderer childeren of rootGO
            Renderer[] rs = rootGO.GetComponentsInChildren <Renderer>();
            for (int i = 0; i < rs.Length; i++)
            {
                if (rs[i] != null && rs[i].transform.parent == rootGO.transform)
                {
                    MeshBakerUtility.Destroy(rs[i].gameObject);
                }
            }

            if (mom is MeshCombinerEntrance)
            {
                MeshCombinerEntrance entrance = (MeshCombinerEntrance)mom;
                MeshCombineHandler   mbs      = (MeshCombineHandler)entrance.meshCombiner;
                MeshCombineHandler.BuildPrefabHierarchy(mbs, rootGO, mbs.GetMesh());
            }
            ////else if (mom is MB3_MultiMeshBaker)
            ////{
            ////    MB3_MultiMeshBaker mmb = (MB3_MultiMeshBaker)mom;
            ////    MB3_MultiMeshCombiner mbs = (MB3_MultiMeshCombiner)mmb.meshCombiner;
            ////    for (int i = 0; i < mbs.meshCombiners.Count; i++)
            ////    {
            ////        MB3_MeshCombinerSingle.BuildPrefabHierarchy(mbs.meshCombiners[i].combinedMesh, rootGO, mbs.meshCombiners[i].combinedMesh.GetMesh(), true);
            ////    }
            ////}
            else
            {
                Debug.LogError("MeshCombiner合并器类型错误");
            }

            //保存预制体
            string prefabPth = AssetDatabase.GetAssetPath(prefabRoot);

            SceneBakerUtilityInEditor.ReplacePrefab(rootGO, prefabPth, ReplacePrefabOption.connectToPrefab);
            if (mom.meshCombiner.renderType != RendererType.skinnedMeshRenderer)
            {
                // For Skinned meshes, leave the prefab instance in the scene so source game objects can moved into the prefab.
                UnityEditor.Editor.DestroyImmediate(rootGO);
            }
        }
コード例 #8
0
        public void EnableDisableSourceObjectRenderers(bool show)
        {
            for (int i = 0; i < GetObjectsToCombine().Count; i++)
            {
                GameObject go = GetObjectsToCombine()[i];
                if (go != null)
                {
                    Renderer mr = MeshBakerUtility.GetRenderer(go);
                    if (mr != null)
                    {
                        mr.enabled = show;
                    }
    #if UNITY_5
                    LODGroup lodG = mr.GetComponentInParent <LODGroup>();
                    if (lodG != null)
                    {
                        bool  isOnlyInGroup = true;
                        LOD[] lods          = lodG.GetLODs();
                        for (int j = 0; j < lods.Length; j++)
                        {
                            for (int k = 0; k < lods[j].renderers.Length; k++)
                            {
                                if (lods[j].renderers[k] != mr)
                                {
                                    isOnlyInGroup = false;
                                    break;
                                }
                            }
                        }

                        if (isOnlyInGroup)
                        {
                            lodG.enabled = show;
                        }
                    }
    #endif
                }
            }
        }
コード例 #9
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);
        }
コード例 #10
0
        /* tried to see if the MultiMaterialConfig could be done using the GroupBy filters. Saddly it didn't work  -_- */
        public static void ConfigureMutiMaterialsFromObjsToCombine2(TextureCombineEntrance 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;
            }

            //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;
                }
            }

            IGroupByFilter[] filters = new IGroupByFilter[3];
            filters[0] = new GroupByOutOfBoundsUVs();
            filters[1] = new GroupByShader();
            filters[2] = new MB3_GroupByStandardShaderType();

            List <GameObjectFilterInfo> gameObjects = new List <GameObjectFilterInfo>();
            HashSet <GameObject>        objectsAlreadyIncludedInBakers = new HashSet <GameObject>();

            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                GameObjectFilterInfo goaw = new GameObjectFilterInfo(mom.GetObjectsToCombine()[i], objectsAlreadyIncludedInBakers, filters);
                if (goaw.materials.Length > 0) //don't consider renderers with no materials
                {
                    gameObjects.Add(goaw);
                }
            }

            //analyse meshes
            Dictionary <int, MeshAnalysisResult> meshAnalysisResultCache = new Dictionary <int, MeshAnalysisResult>();
            int totalVerts = 0;

            for (int i = 0; i < gameObjects.Count; i++)
            {
                //string rpt = String.Format("Processing {0} [{1} of {2}]", gameObjects[i].go.name, i, gameObjects.Count);
                //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " A", .6f);
                Mesh mm     = MeshBakerUtility.GetMesh(gameObjects[i].go);
                int  nVerts = 0;
                if (mm != null)
                {
                    nVerts += mm.vertexCount;
                    MeshAnalysisResult mar;
                    if (!meshAnalysisResultCache.TryGetValue(mm.GetInstanceID(), out mar))
                    {
                        //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Check Out Of Bounds UVs", .6f);
                        MeshBakerUtility.hasOutOfBoundsUVs(mm, ref mar);
                        //Rect dummy = mar.uvRect;
                        MeshBakerUtility.doSubmeshesShareVertsOrTris(mm, ref mar);
                        meshAnalysisResultCache.Add(mm.GetInstanceID(), mar);
                    }
                    if (mar.hasOutOfBoundsUVs)
                    {
                        int w = (int)mar.uvRect.width;
                        int h = (int)mar.uvRect.height;
                        gameObjects[i].outOfBoundsUVs = true;
                        gameObjects[i].warning       += " [WARNING: has uvs outside the range (0,1) tex is tiled " + w + "x" + h + " times]";
                    }
                    if (mar.hasOverlappingSubmeshVerts)
                    {
                        gameObjects[i].submeshesOverlap = true;
                        gameObjects[i].warning         += " [WARNING: Submeshes share verts or triangles. 'Multiple Combined Materials' feature may not work.]";
                    }
                }
                totalVerts += nVerts;
                //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Validate OBuvs Multi Material", .6f);
                Renderer mr = gameObjects[i].go.GetComponent <Renderer>();
                if (!MeshBakerUtility.AreAllSharedMaterialsDistinct(mr.sharedMaterials))
                {
                    gameObjects[i].warning += " [WARNING: Object uses same material on multiple submeshes. This may produce poor results when used with multiple materials or fix out of bounds uvs.]";
                }
            }

            List <GameObjectFilterInfo> objsNotAddedToBaker = new List <GameObjectFilterInfo>();

            Dictionary <GameObjectFilterInfo, List <List <GameObjectFilterInfo> > > gs2bakeGroupMap = null;//MB3_MeshBakerEditorWindow.sortIntoBakeGroups3(gameObjects, objsNotAddedToBaker, filters, false, mom.maxAtlasSize);

            mom.resultMaterials = new MultiMaterial[gs2bakeGroupMap.Keys.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 (GameObjectFilterInfo m in gs2bakeGroupMap.Keys)
            {
                MultiMaterial mm = mom.resultMaterials[k] = new MultiMaterial();
                mm.sourceMaterials = new List <Material>();
                mm.sourceMaterials.Add(m.materials[0]);
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                TextureCombineEntrance.ConfigureNewMaterialToMatchOld(newMat, m.materials[0]);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            SceneBakerUtilityInEditor.UpdateIfDirtyOrScript(textureBaker);
        }
コード例 #11
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);
        }
コード例 #12
0
        /// <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);
        }
コード例 #13
0
        /// <summary>
        /// 创建图集
        /// </summary>
        public static void CreateAtlases(List <GameObject> GameObjectsToCombine,
                                         bool saveAtlasesAsAssets = false)
        {
            try
            {
                combineData.ResultAtlasesAndRects = null;
                combineData.saveAtlasesAsAssets   = saveAtlasesAsAssets;
                //--- 1、合并前检测
                if (!ValidateCombineGameObject(GameObjectsToCombine))
                {
                    return;
                }

                //材质验证
                if (combineData.DoMultiMaterial)
                {
                    if (!_ValidateResultMaterials(GameObjectsToCombine, combineData.ResultMaterials))
                    {
                        return;
                    }
                }
                else
                {
                    if (!ValidateSingleResultMaterial(GameObjectsToCombine, combineData.ResultMaterial))
                    {
                        return;
                    }
                }


                ////--- 2、初始化存储合并结果的数据结构
                int numResults = 1;
                if (combineData.DoMultiMaterial)
                {
                    numResults = combineData.ResultMaterials.Length;
                }

                combineData.ResultAtlasesAndRects = new AtlasesAndRects[numResults];
                for (int i = 0; i < combineData.ResultAtlasesAndRects.Length; i++)
                {
                    combineData.ResultAtlasesAndRects[i] = new AtlasesAndRects();
                }

                //--- 3、开始合并材质(单个,多个)
                for (int i = 0; i < combineData.ResultAtlasesAndRects.Length; i++)
                {
                    Material        resultMat;
                    List <Material> sourceMats;
                    if (combineData.DoMultiMaterial)
                    {
                        sourceMats = combineData.ResultMaterials[i].sourceMaterials;
                        resultMat  = combineData.ResultMaterials[i].combinedMaterial;
                        combineData.fixOutOfBoundsUVs = combineData.ResultMaterials[i].considerMeshUVs;
                    }
                    else
                    {
                        resultMat  = combineData.ResultMaterial;
                        sourceMats = null;  //为空则为全部合并
                    }

                    CombineTexturesIntoAtlases(combineData.ResultAtlasesAndRects[i],
                                               resultMat,
                                               GameObjectsToCombine,
                                               sourceMats,
                                               null);
                }

                //--- 4、TextureBakeResults 保存合并结果
                //unpackMat2RectMap(textureBakeResults);
                //textureBakeResults.doMultiMaterial = _doMultiMaterial;
                //if (_doMultiMaterial)
                //{
                //    textureBakeResults.resultMaterials = resultMaterials;
                //}
                //else
                //{
                //    MultiMaterial[] resMats = new MultiMaterial[1];
                //    resMats[0] = new MultiMaterial();
                //    resMats[0].combinedMaterial = _resultMaterial;
                //    resMats[0].considerMeshUVs = _fixOutOfBoundsUVs;
                //    resMats[0].sourceMaterials = new List<Material>();
                //    for (int i = 0; i < textureBakeResults.materialsAndUVRects.Length; i++)
                //    {
                //        resMats[0].sourceMaterials.Add(textureBakeResults.materialsAndUVRects[i].material);
                //    }
                //    textureBakeResults.resultMaterials = resMats;
                //}

                ////--- 5、传递合并结果到 MeshCombiner
                //MeshBakerCommon[] mb = GetComponentsInChildren<MeshBakerCommon>();
                //for (int i = 0; i < mb.Length; i++)
                //{
                //    mb[i].textureBakeResults = textureBakeResults;
                //}
                //coroutineResult.isFinished = true;

                ////--- 6、合并材质结束回调
                //if (coroutineResult.success && onBuiltAtlasesSuccess != null)
                //{
                //    onBuiltAtlasesSuccess();
                //}
                //if (!coroutineResult.success && onBuiltAtlasesFail != null)
                //{
                //    onBuiltAtlasesFail();
                //}
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            finally
            {
                if (saveAtlasesAsAssets)
                { //Atlases were saved to project so we don't need these ones
                    if (combineData.ResultAtlasesAndRects != null)
                    {
                        for (int j = 0; j < combineData.ResultAtlasesAndRects.Length; j++)
                        {
                            AtlasesAndRects mAndA = combineData.ResultAtlasesAndRects[j];
                            if (mAndA != null && mAndA.atlases != null)
                            {
                                for (int i = 0; i < mAndA.atlases.Length; i++)
                                {
                                    if (mAndA.atlases[i] != null)
                                    {
                                        //if (editorMethods != null)
                                        //{
                                        //    editorMethods.Destroy(mAndA.atlases[i]);
                                        //}
                                        //else
                                        //{
                                        MeshBakerUtility.Destroy(mAndA.atlases[i]);
                                        //}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #14
0
        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();
            }
        }
コード例 #15
0
ファイル: TextureBaker.cs プロジェクト: lwx1010/2D_XProject
        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);
            }
        }
コード例 #16
0
            //a material can appear more than once in an atlas if using fixOutOfBoundsUVs.
            //in this case need to use the UV rect of the mesh to find the correct rectangle.
            public bool TryMapMaterialToUVRect(Material mat, Mesh m, int submeshIdx, MeshCombinerSingle.MeshChannelsCache meshChannelCache, Dictionary <int, MeshBakerUtility.MeshAnalysisResult[]> meshAnalysisCache,
                                               out Rect rectInAtlas,
                                               //out Rect subrectInAtlasMatTiling,
                                               out Rect encapsulatingRect,
                                               out Rect sourceMaterialTilingOut,
                                               ref String errorMsg,
                                               MBLogLevel logLevel)
            {
                if (tbr.materialsAndUVRects.Length == 0 && tbr.materials.Length > 0)
                {
                    errorMsg    = "The 'Material 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();
                    //subrectInAtlasMatTiling = new Rect();
                    encapsulatingRect       = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    return(false);
                }
                if (mat == null)
                {
                    rectInAtlas = new Rect();
                    //subrectInAtlasMatTiling = new Rect();
                    encapsulatingRect       = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    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();
                    //subrectInAtlasMatTiling = new Rect();
                    encapsulatingRect       = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    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();
                    //subrectInAtlasMatTiling = new Rect();
                    encapsulatingRect       = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    errorMsg = String.Format("Material {0} could not be found in the Material Bake Result", mat.name);
                    return(false);
                }

                if (!tbr.fixOutOfBoundsUVs)
                {
                    if (numTimesMatAppearsInAtlas[idx] != 1)
                    {
                        Debug.LogError("There is a problem with this TextureBakeResults. FixOutOfBoundsUVs is false and a material appears more than once.");
                    }
                    rectInAtlas = matsAndSrcUVRect[idx].atlasRect;
                    //subrectInAtlasMatTiling = matsAndSrcUVRect[idx].atlasSubrectMaterialOnly;
                    encapsulatingRect       = matsAndSrcUVRect[idx].samplingEncapsulatinRect;
                    sourceMaterialTilingOut = matsAndSrcUVRect[idx].sourceMaterialTiling;
                    return(true);
                }
                else
                {
                    //todo what if no UVs
                    //Find UV rect in source mesh

                    MeshBakerUtility.MeshAnalysisResult[] mar;
                    if (!meshAnalysisCache.TryGetValue(m.GetInstanceID(), out mar))
                    {
                        mar = new MeshBakerUtility.MeshAnalysisResult[m.subMeshCount];
                        for (int j = 0; j < m.subMeshCount; j++)
                        {
                            Vector2[] uvss = meshChannelCache.GetUv0Raw(m);
                            MeshBakerUtility.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;
                    if (logLevel >= MBLogLevel.trace)
                    {
                        Debug.LogWarning(String.Format("Trying to find a rectangle in atlas capable of holding tiled sampling rect for mesh {0} using material {1}", m, mat));
                    }
                    for (int i = idx; i < matsAndSrcUVRect.Length; i++)
                    {
                        if (matsAndSrcUVRect[i].material == mat)
                        {
                            //calculate what the UV rect in the atlas would be if we combined the material tiling of this rect with the UV tiling of this submesh
                            Rect potentialRect = new Rect();
                            Rect uvR           = mar[submeshIdx].uvRect;
                            Rect matR          = matsAndSrcUVRect[i].sourceMaterialTiling;
                            // test to see if this would fit in what was baked in the atlas
                            Rect rr = matsAndSrcUVRect[i].samplingEncapsulatinRect;
                            UVTransformUtility.Canonicalize(ref rr, 0, 0);

                            potentialRect = UVTransformUtility.CombineTransforms(ref uvR, ref matR);
                            if (logLevel >= MBLogLevel.trace)
                            {
                                Debug.Log("uvR=" + uvR.ToString("f5") + " matR=" + matR.ToString("f5") + "Potential Rect " + potentialRect.ToString("f5") + " encapsulating=" + rr.ToString("f5"));
                            }
                            UVTransformUtility.Canonicalize(ref potentialRect, rr.x, rr.y);
                            if (logLevel >= MBLogLevel.trace)
                            {
                                Debug.Log("Potential Rect Cannonical " + potentialRect.ToString("f5") + " encapsulating=" + rr.ToString("f5"));
                            }

                            if (UVTransformUtility.RectContains(ref rr, ref potentialRect))
                            {
                                if (logLevel >= MBLogLevel.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)
                    {
                        rectInAtlas = matsAndSrcUVRect[idx].atlasRect;
                        //subrectInAtlasMatTiling = matsAndSrcUVRect[idx].atlasSubrectMaterialOnly;
                        encapsulatingRect       = matsAndSrcUVRect[idx].samplingEncapsulatinRect;
                        sourceMaterialTilingOut = matsAndSrcUVRect[idx].sourceMaterialTiling;
                        return(true);
                    }
                    else
                    {
                        rectInAtlas = new Rect();
                        //subrectInAtlasMatTiling = new Rect();
                        encapsulatingRect       = new Rect();
                        sourceMaterialTilingOut = new Rect();
                        errorMsg = String.Format("Could not find a tiled rectangle in the atlas capable of containing the uv and material tiling on mesh {0}", m.name);
                        return(false);
                    }
                }
            }
        private void DrawGUI(SerializedObject meshBaker, MeshBakerCommon target, System.Type editorWindowType)
        {
            if (meshBaker == null)
            {
                return;
            }

            meshBaker.Update();

            //说明窗口
            showInstructions = EditorGUILayout.Foldout(showInstructions, "说明:");
            if (showInstructions)
            {
                EditorGUILayout.HelpBox("1. Bake combined material(s).\n\n" +
                                        "2. If necessary set the 'Texture Bake Results' field.\n\n" +
                                        "3. Add scene objects or prefabs to combine or check 'Same As Texture Baker'. For best results these should use the same shader as result material.\n\n" +
                                        "4. Select options and 'Bake'.\n\n" +
                                        "6. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" +
                                        "7. (optional) Disable renderers in source objects.", UnityEditor.MessageType.None);

                EditorGUILayout.Separator();
            }

            MeshBakerCommon momm = (MeshBakerCommon)target;

            //已合并材质资源
            EditorGUILayout.PropertyField(textureBakeResults, gc_textureBakeResultsGUIContent);
            if (textureBakeResults.objectReferenceValue != null)
            {
                showContainsReport = EditorGUILayout.Foldout(showContainsReport, "Shaders & Materials Contained");
                if (showContainsReport)
                {
                    EditorGUILayout.HelpBox(((TextureBakeResults)textureBakeResults.objectReferenceValue).GetDescription(), MessageType.Info);
                }
            }

            EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle);
            //参与网格合并物体列表
            EditorGUILayout.LabelField("合并物体列表", EditorStyles.whiteBoldLabel);
            if (momm.GetTextureBaker() != null)
            {
                EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent);
            }
            else
            {
                useObjsToMeshFromTexBaker.boolValue = false;
                momm.useObjsToMeshFromTexBaker      = false;
                GUI.enabled = false;
                EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent);
                GUI.enabled = true;
            }

            //与参与材质合并物体不同
            if (!momm.useObjsToMeshFromTexBaker)
            {
                //添加工具
                if (GUILayout.Button(gc_openToolsWindowLabelContent))
                {
                    IMeshCombinerEditorWindow mmWin = (IMeshCombinerEditorWindow)EditorWindow.GetWindow(editorWindowType);
                    mmWin.target = (MeshBakerRoot)target;
                }

                object[] objs = EditorMethods.DropZone("Drag & Drop Renderers Or Parents Here To Add Objects To Be Combined", 300, 50);
                EditorMethods.AddDroppedObjects(objs, momm);

                EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true);
                EditorGUILayout.Separator();
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("Select Objects In Scene"))
                {
                    Selection.objects = momm.GetObjectsToCombine().ToArray();
                    if (momm.GetObjectsToCombine().Count > 0)
                    {
                        SceneView.lastActiveSceneView.pivot = momm.GetObjectsToCombine()[0].transform.position;
                    }
                }
                if (GUILayout.Button(gc_SortAlongAxis))
                {
                    MeshBakerRoot.ZSortObjects sorter = new MeshBakerRoot.ZSortObjects();
                    sorter.sortAxis = sortOrderAxis.vector3Value;
                    sorter.SortByDistanceAlongAxis(momm.GetObjectsToCombine());
                }
                EditorGUILayout.PropertyField(sortOrderAxis, GUIContent.none);
                EditorGUILayout.EndHorizontal();
            }
            else
            {
                GUI.enabled = false;
                EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true);
                GUI.enabled = true;
            }
            EditorGUILayout.EndVertical();

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("输出:", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(outputOptions, gc_outputOptoinsGUIContent);
            //输出方式设置
            if (momm.meshCombiner.outputOption == OutputOptions.bakeIntoSceneObject)
            {
                momm.meshCombiner.resultSceneObject = (GameObject)EditorGUILayout.ObjectField("合并后游戏物体",
                                                                                              momm.meshCombiner.resultSceneObject, typeof(GameObject), true);
                if (momm is MeshCombinerEntrance)
                {
                    string l = "Mesh";
                    Mesh   m = (Mesh)mesh.objectReferenceValue;
                    if (m != null)
                    {
                        l += " (" + m.GetInstanceID() + ")";
                    }
                    Mesh nm = (Mesh)EditorGUILayout.ObjectField(new GUIContent(l), m, typeof(Mesh), true);
                    if (nm != m)
                    {
                        Undo.RecordObject(momm, "Assign Mesh");
                        ((MeshCombineHandler)momm.meshCombiner).SetMesh(nm);
                        mesh.objectReferenceValue = nm;
                    }
                }
            }
            //合并为预制体
            else if (momm.meshCombiner.outputOption == OutputOptions.bakeIntoPrefab)
            {
                momm.resultPrefab = (GameObject)EditorGUILayout.ObjectField(
                    gc_combinedMeshPrefabGUIContent, momm.resultPrefab, typeof(GameObject), true);
                if (momm is MeshCombinerEntrance)
                {
                    string l = "Mesh";
                    Mesh   m = (Mesh)mesh.objectReferenceValue;
                    if (m != null)
                    {
                        l += " (" + m.GetInstanceID() + ")";
                    }
                    Mesh nm = (Mesh)EditorGUILayout.ObjectField(new GUIContent(l), m, typeof(Mesh), true);
                    if (nm != m)
                    {
                        Undo.RecordObject(momm, "Assign Mesh");
                        ((MeshCombineHandler)momm.meshCombiner).SetMesh(nm);
                        mesh.objectReferenceValue = nm;
                    }
                }
            }
            //合并磁盘中文件
            else if (momm.meshCombiner.outputOption == OutputOptions.bakeMeshAssetsInPlace)
            {
                EditorGUILayout.HelpBox("Try the BatchPrefabBaker component. " +
                                        "It makes preparing a batch of prefabs for static/ dynamic batching much easier.", MessageType.Info);
                if (GUILayout.Button("Choose Folder For Bake In Place Meshes"))
                {
                    string newFolder = EditorUtility.SaveFolderPanel("Folder For Bake In Place Meshes", Application.dataPath, "");
                    if (!newFolder.Contains(Application.dataPath))
                    {
                        Debug.LogWarning("The chosen folder must be in your assets folder.");
                    }
                    momm.bakeAssetsInPlaceFolderPath = "Assets" + newFolder.Replace(Application.dataPath, "");
                }
                EditorGUILayout.LabelField("Folder For Meshes: " + momm.bakeAssetsInPlaceFolderPath);
            }

            //if (momm is MB3_MultiMeshBaker)
            //{
            //    ////MB3_MultiMeshCombiner mmc = (MB3_MultiMeshCombiner)momm.meshCombiner;
            //    ////mmc.maxVertsInMesh = EditorGUILayout.IntField("Max Verts In Mesh", mmc.maxVertsInMesh);
            //}

            //-----------------------------------
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("网格合并设置:", EditorStyles.boldLabel);
            bool settingsEnabled = true;

            //------------- Mesh Baker Settings is a bit tricky because it is an interface.

            UnityEngine.Object obj = settingsHolder.objectReferenceValue;

            //通用合并网格设置
            // Don't use a PropertyField because we may not be able to use the assigned object.
            // It may not implement requried interface.
            obj = EditorGUILayout.ObjectField(gc_Settings, obj, typeof(UnityEngine.Object), true);
            //通用设置为空,使用下方设置
            if (obj == null)
            {
                settingsEnabled = true;
                settingsHolder.objectReferenceValue = null;
                if (meshBakerSettingsExternal != null)
                {
                    meshBakerSettingsExternal.OnDisable();
                    meshBakerSettingsExternal = null;
                }
            }
            else if (obj is GameObject)
            {
                // Check to see if there is a component on this game object that implements MB_IMeshBakerSettingsHolder
                IMeshCombinerSettingHolder itf = (IMeshCombinerSettingHolder)((GameObject)obj).GetComponent(typeof(IMeshCombinerSettingHolder));
                if (itf != null)
                {
                    settingsEnabled = false;
                    Component settingsHolderComponent = (Component)itf;
                    if (settingsHolder.objectReferenceValue != settingsHolderComponent)
                    {
                        settingsHolder.objectReferenceValue = settingsHolderComponent;
                        meshBakerSettingsExternal           = new MeshCombineSettingEditor();
                        meshBakerSettingsExternal.OnEnable(itf.GetMeshBakerSettingsAsSerializedProperty());
                    }
                }
                else
                {
                    settingsEnabled = true;
                    settingsHolder  = null;
                    if (meshBakerSettingsExternal != null)
                    {
                        meshBakerSettingsExternal.OnDisable();
                        meshBakerSettingsExternal = null;
                    }
                }
            }
            else if (obj is IMeshCombinerSettingHolder)
            {
                settingsEnabled = false;
                if (settingsHolder.objectReferenceValue != obj)
                {
                    settingsHolder.objectReferenceValue = obj;
                    meshBakerSettingsExternal           = new MeshCombineSettingEditor();
                    meshBakerSettingsExternal.OnEnable(((IMeshCombinerSettingHolder)obj).GetMeshBakerSettingsAsSerializedProperty());
                }
            }
            else
            {
                Debug.LogError("Object was not a Mesh Baker Settings object.");
            }
            EditorGUILayout.Space();

            if (settingsHolder.objectReferenceValue == null)
            {
                // Use the meshCombiner settings
                meshBakerSettingsThis.DrawGUI(momm.meshCombiner, settingsEnabled);
            }
            else
            {
                if (meshBakerSettingsExternal == null)
                {
                    meshBakerSettingsExternal = new MeshCombineSettingEditor();
                    meshBakerSettingsExternal.OnEnable(((IMeshCombinerSettingHolder)obj).GetMeshBakerSettingsAsSerializedProperty());
                }
                var set      = settingsHolder.objectReferenceValue;
                var settings = (IMeshCombinerSettingHolder)settingsHolder.objectReferenceValue;
                meshBakerSettingsExternal.DrawGUI(settings.GetMeshBakerSettings(), settingsEnabled);
            }

            Color oldColor = GUI.backgroundColor;

            GUI.backgroundColor = buttonColor;
            if (GUILayout.Button("合并"))
            {
                bake(momm, ref meshBaker);
            }
            GUI.backgroundColor = oldColor;

            string enableRenderersLabel;
            bool   disableRendererInSource = false;

            if (momm.GetObjectsToCombine().Count > 0)
            {
                Renderer r = MeshBakerUtility.GetRenderer(momm.GetObjectsToCombine()[0]);
                if (r != null && r.enabled)
                {
                    disableRendererInSource = true;
                }
            }
            if (disableRendererInSource)
            {
                enableRenderersLabel = "隐藏源游戏物体";
            }
            else
            {
                enableRenderersLabel = "显示源游戏物体";
            }
            if (GUILayout.Button(enableRenderersLabel))
            {
                momm.EnableDisableSourceObjectRenderers(!disableRendererInSource);
            }

            meshBaker.ApplyModifiedProperties();
            meshBaker.SetIsDifferentCacheDirty();
        }
コード例 #18
0
ファイル: MeshBakerRoot.cs プロジェクト: lwx1010/2D_XProject
        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);
        }
コード例 #19
0
        public GameObjectFilterInfo(GameObject g, HashSet <GameObject> objsAlreadyInBakers, IGroupByFilter[] filts)
        {
            go = g;
            Renderer           r         = MeshBakerUtility.GetRenderer(g);
            HashSet <Material> matsSet   = new HashSet <Material>();
            HashSet <Shader>   shaderSet = new HashSet <Shader>();

            if (r is SkinnedMeshRenderer)
            {
                isMeshRenderer = false;
            }
            else
            {
                isMeshRenderer = true;
            }
            materials = r.sharedMaterials;
            for (int i = 0; i < materials.Length; i++)
            {
                if (materials[i] != null)
                {
                    matsSet.Add(materials[i]);
                    shaderSet.Add(materials[i].shader);
                }
            }
            materials = new Material[matsSet.Count];
            matsSet.CopyTo(materials);
            shaders = new Shader[shaderSet.Count];
            standardShaderBlendModes = new StandardShaderBlendMode[matsSet.Count];

            shaderSet.CopyTo(shaders);

            Array.Sort(materials, new NameComparer());
            Array.Sort(shaders, new NameComparer());

            List <string> standardShaderBlendModesNameSet = new List <string>();

            for (int i = 0; i < materials.Length; i++)
            {
                if (materials[i].shader.name.StartsWith("Standard") && materials[i].HasProperty("_Mode"))
                {
                    standardShaderBlendModes[i] = (StandardShaderBlendMode)materials[i].GetFloat("_Mode");
                }
                else
                {
                    standardShaderBlendModes[i] = StandardShaderBlendMode.NotApplicable;
                }
                if (!standardShaderBlendModesNameSet.Contains(standardShaderBlendModes[i].ToString()))
                {
                    standardShaderBlendModesNameSet.Add(standardShaderBlendModes[i].ToString());
                }
                materialName += (materials[i] == null ? "null" : materials[i].name);
                if (i < materials.Length - 1)
                {
                    materialName += ",";
                }
            }
            standardShaderBlendModesName = "";
            standardShaderBlendModesNameSet.Sort();
            foreach (string modeName in standardShaderBlendModesNameSet)
            {
                standardShaderBlendModesName += modeName + ",";
            }
            for (int i = 0; i < shaders.Length; i++)
            {
                shaderName += (shaders[i] == null ? "null" : shaders[i].name);
                if (i < shaders.Length - 1)
                {
                    shaderName += ",";
                }
            }

            lightmapIndex = r.lightmapIndex;
            Mesh mesh = MeshBakerUtility.GetMesh(g);

            numVerts = 0;
            if (mesh != null)
            {
                numVerts = mesh.vertexCount;
            }
            isStatic           = go.isStatic;
            numMaterials       = materials.Length;
            warning            = "";
            alreadyInBakerList = objsAlreadyInBakers.Contains(g);
            outOfBoundsUVs     = false;
            submeshesOverlap   = false;
            filters            = filts;
        }
        /// <summary>
        ///  Bakes a combined mesh.
        ///  如果是从Inspector代码中调用的,则传入该组件的SerializedObject
        ///  对于“烘焙到预制”可能会损坏SerializedObject。这是必需的
        /// </summary>
        public static bool BakeIntoCombined(MeshBakerCommon mom, out bool createdDummyTextureBakeResults, ref SerializedObject so)
        {
            OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption;

            createdDummyTextureBakeResults = false;
            if (prefabOrSceneObject != OutputOptions.bakeIntoPrefab && prefabOrSceneObject != OutputOptions.bakeIntoSceneObject)
            {
                Debug.LogError("Paramater prefabOrSceneObject must be bakeIntoPrefab or bakeIntoSceneObject");
                return(false);
            }

            //从父物体获得 贴图合并组件及其贴图合并结果 Asset
            TextureCombineEntrance tb = mom.GetComponentInParent <TextureCombineEntrance>();

            if (mom.textureBakeResults == null && tb != null)
            {
                mom.textureBakeResults = tb.textureBakeResults;
            }
            //贴图合并结果为空时,则创建
            if (mom.textureBakeResults == null)
            {
                if (_OkToCreateDummyTextureBakeResult(mom))
                {
                    createdDummyTextureBakeResults = true;
                    List <GameObject> gos = mom.GetObjectsToCombine();
                    if (mom.GetNumObjectsInCombined() > 0)
                    {
                        if (mom.clearBuffersAfterBake)
                        {
                            mom.ClearMesh();
                        }
                        else
                        {
                            Debug.LogError("'Texture Bake Result' must be set to add more objects to a combined mesh that " +
                                           "already contains objects. Try enabling 'clear buffers after bake'");
                            return(false);
                        }
                    }
                    mom.textureBakeResults = TextureBakeResults.CreateForMaterialsOnRenderer(
                        gos.ToArray(),
                        mom.meshCombiner.GetMaterialsOnTargetRenderer());
                    Debug.Log("'Texture Bake Result' was not set. " +
                              "Creating a temporary one. Each material will be mapped to a separate submesh.");
                }
            }

            //合并检测
            ValidationLevel vl = Application.isPlaying ? ValidationLevel.quick : ValidationLevel.robust;

            if (!MeshBakerRoot.DoCombinedValidate(mom, ObjsToCombineTypes.sceneObjOnly, new EditorMethods(), vl))
            {
                return(false);
            }

            //检测空预制体资源是否已创建
            if (prefabOrSceneObject == OutputOptions.bakeIntoPrefab &&
                mom.resultPrefab == null)
            {
                Debug.LogError("Need to set the Combined Mesh Prefab field. " +
                               "Create a prefab asset, drag an empty game object into it, and drag it to the 'Combined Mesh Prefab' field.");
                return(false);
            }

            if (mom.meshCombiner.resultSceneObject != null &&
                (SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject) == PrefabType.modelPrefab ||
                 SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject) == PrefabType.prefab))
            {
                Debug.LogWarning("Result Game Object was a project asset not a scene object instance. Clearing this field.");
                mom.meshCombiner.resultSceneObject = null;
            }

            mom.ClearMesh();

            //合并
            if (mom.AddDeleteGameObjects(mom.GetObjectsToCombine().ToArray(), null, false))
            {
                mom.Apply(UnwrapUV2);
                if (createdDummyTextureBakeResults)
                {
                    //临时合并的贴图
                    Debug.Log(String.Format("Successfully baked {0} meshes each material is mapped to its own submesh.",
                                            mom.GetObjectsToCombine().Count));
                }
                else
                {
                    Debug.Log(String.Format("Successfully baked {0} meshes", mom.GetObjectsToCombine().Count));
                }


                if (prefabOrSceneObject == OutputOptions.bakeIntoSceneObject)
                {
                    PrefabType pt = SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject);
                    if (pt == PrefabType.prefab || pt == PrefabType.modelPrefab)
                    {
                        Debug.LogError("Combined Mesh Object is a prefab asset. " +
                                       "If output option bakeIntoSceneObject then this must be an instance in the scene.");
                        return(false);
                    }
                }
                else if (prefabOrSceneObject == OutputOptions.bakeIntoPrefab)
                {
                    string prefabPth = AssetDatabase.GetAssetPath(mom.resultPrefab);
                    if (prefabPth == null || prefabPth.Length == 0)
                    {
                        Debug.LogError("无法保存,合并游戏物体并非磁盘上的资源。");
                        return(false);
                    }
                    string baseName    = Path.GetFileNameWithoutExtension(prefabPth);
                    string folderPath  = prefabPth.Substring(0, prefabPth.Length - baseName.Length - 7);
                    string newFilename = folderPath + baseName + "-mesh";

                    //保存网格资源
                    SaveMeshsToAssetDatabase(mom, folderPath, newFilename);

                    if (mom.meshCombiner.renderType == RendererType.skinnedMeshRenderer)
                    {
                        Debug.LogWarning("Render type is skinned mesh renderer. " +
                                         "Can't create prefab until all bones have been added to the combined mesh object " + mom.resultPrefab +
                                         " Add the bones then drag the combined mesh object to the prefab.");
                    }
                    //构建 Prefab
                    RebuildPrefab(mom, ref so);

                    MeshBakerUtility.Destroy(mom.meshCombiner.resultSceneObject);
                }
                else
                {
                    Debug.LogError("合并输出类型出错");
                    return(false);
                }
            }
            else
            {
                //加入合并失败
                if (mom.clearBuffersAfterBake)
                {
                    mom.meshCombiner.ClearBuffers();
                }
                if (createdDummyTextureBakeResults)
                {
                    MeshBakerUtility.Destroy(mom.textureBakeResults);
                }
                return(false);
            }

            //清除缓存数据
            if (mom.clearBuffersAfterBake)
            {
                mom.meshCombiner.ClearBuffers();
            }
            //临时Texture
            if (createdDummyTextureBakeResults)
            {
                MeshBakerUtility.Destroy(mom.textureBakeResults);
            }
            return(true);
        }
コード例 #21
0
        /// <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);
        }