Exemple #1
0
        bool _validateTextureBakeResults()
        {
            if (_textureBakeResults == null)
            {
                Debug.LogError("Texture Bake Results is null. Can't combine meshes.");
                return(false);
            }
            if ((_textureBakeResults.materialsAndUVRects == null || _textureBakeResults.materialsAndUVRects.Length == 0))
            {
                Debug.LogError("Texture Bake Results has no materials in material to sourceUVRect map. Try baking materials. Can't combine meshes.");
                return(false);
            }


            if (_textureBakeResults.resultMaterials == null || _textureBakeResults.resultMaterials.Length == 0)
            {
                if (_textureBakeResults.materialsAndUVRects != null && _textureBakeResults.materialsAndUVRects.Length > 0 &&
                    _textureBakeResults.doMultiMaterial == false && _textureBakeResults.resultMaterial != null)
                {
                    //backward compatibility
                    MB_MultiMaterial[] mm = _textureBakeResults.resultMaterials = new MB_MultiMaterial[1];
                    mm[0] = new MB_MultiMaterial();
                    mm[0].combinedMaterial = _textureBakeResults.resultMaterial;
                    mm[0].considerMeshUVs  = _textureBakeResults.fixOutOfBoundsUVs;
                    List <Material> mats = mm[0].sourceMaterials = new List <Material>();
                    for (int i = 0; i < _textureBakeResults.materialsAndUVRects.Length; i++)
                    {
                        if (!mats.Contains(_textureBakeResults.materialsAndUVRects[i].material))
                        {
                            mats.Add(_textureBakeResults.materialsAndUVRects[i].material);
                        }
                    }
                }
                else
                {
                    Debug.LogError("Texture Bake Results has no result materials. Try baking materials. Can't combine meshes.");
                    return(false);
                }
            }

            return(true);
        }
Exemple #2
0
    bool _ValidateResultMaterials()
    {
        HashSet <Material> allMatsOnObjs = new HashSet <Material>();

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

        for (int i = 0; i < resultMaterials.Length; i++)
        {
            MB_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);
    }
Exemple #3
0
    public IEnumerator CreateAtlasesCoroutine(ProgressUpdateDelegate progressInfo, CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f)
    {
        MBVersionConcrete mbv = new MBVersionConcrete();

        if (!MB3_TextureCombiner._RunCorutineWithoutPauseIsRunning && (mbv.GetMajorVersion() < 5 || (mbv.GetMajorVersion() == 5 && mbv.GetMinorVersion() < 3)))
        {
            Debug.LogError("Running the texture combiner as a coroutine only works in Unity 5.3 and higher");
            coroutineResult.success = false;
            yield break;
        }
        this.OnCombinedTexturesCoroutineAtlasesAndRects = null;

        if (maxTimePerFrame <= 0f)
        {
            Debug.LogError("maxTimePerFrame must be a value greater than zero");
            coroutineResult.isFinished = true;
            yield break;
        }
        MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust;

        if (!DoCombinedValidate(this, MB_ObjsToCombineTypes.dontCare, null, vl))
        {
            coroutineResult.isFinished = true;
            yield break;
        }
        if (_doMultiMaterial && !_ValidateResultMaterials())
        {
            coroutineResult.isFinished = true;
            yield break;
        }
        else if (!_doMultiMaterial)
        {
            if (_resultMaterial == null)
            {
                Debug.LogError("Combined Material is null please create and assign a result material.");
                coroutineResult.isFinished = true;
                yield break;
            }
            Shader targShader = _resultMaterial.shader;
            for (int i = 0; i < objsToMesh.Count; i++)
            {
                Material[] ms = MB_Utility.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.");
                    }
                }
            }
        }

        MB3_TextureCombiner combiner = CreateAndConfigureTextureCombiner();

        combiner.saveAtlasesAsAssets = saveAtlasesAsAssets;

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

        if (_doMultiMaterial)
        {
            numResults = resultMaterials.Length;
        }
        OnCombinedTexturesCoroutineAtlasesAndRects = new MB_AtlasesAndRects[numResults];
        for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++)
        {
            OnCombinedTexturesCoroutineAtlasesAndRects[i] = new MB_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;
                combiner.fixOutOfBoundsUVs = resultMaterials[i].considerMeshUVs;
            }
            else
            {
                resMatToPass = _resultMaterial;
            }

            MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult coroutineResult2 = new MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult();
            yield return(combiner.CombineTexturesIntoAtlasesCoroutine(progressInfo, OnCombinedTexturesCoroutineAtlasesAndRects[i], resMatToPass, objsToMesh, sourceMats, editorMethods, coroutineResult2, maxTimePerFrame));

            coroutineResult.success = coroutineResult2.success;
            if (!coroutineResult.success)
            {
                coroutineResult.isFinished = true;
                yield break;
            }
        }

        unpackMat2RectMap(textureBakeResults);
        //Save the results
        textureBakeResults.doMultiMaterial = _doMultiMaterial;
        //textureBakeResults.resultMaterial = _resultMaterial;
        if (_doMultiMaterial)
        {
            textureBakeResults.resultMaterials = resultMaterials;
        }
        else
        {
            MB_MultiMaterial[] resMats = new MB_MultiMaterial[1];
            resMats[0] = new MB_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;
        }
        //textureBakeResults.fixOutOfBoundsUVs = combiner.fixOutOfBoundsUVs;


        //set the texture bake resultAtlasesAndRects on the Mesh Baker component if it exists
        MB3_MeshBakerCommon[] mb = GetComponentsInChildren <MB3_MeshBakerCommon>();
        for (int i = 0; i < mb.Length; i++)
        {
            mb[i].textureBakeResults = textureBakeResults;
        }

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

        coroutineResult.isFinished = true;
        if (coroutineResult.success && onBuiltAtlasesSuccess != null)
        {
            onBuiltAtlasesSuccess();
        }
        if (!coroutineResult.success && onBuiltAtlasesFail != null)
        {
            onBuiltAtlasesFail();
        }
    }
        //posibilities
        //  using fixOutOfBoundsUVs or not
        //
        public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
        {
            if (mom.GetObjectsToCombine().Count == 0)
            {
                Debug.LogError("You need to add some objects to combine before building the multi material list.");
                return;
            }
            if (resultMaterials.arraySize > 0)
            {
                Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
                return;
            }
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Texture Bake Result asset must be set before using this operation.");
                return;
            }
            Dictionary <MultiMatSubmeshInfo, List <List <Material> > > shader2Material_map = new Dictionary <MultiMatSubmeshInfo, List <List <Material> > >();
            Dictionary <Material, Mesh> obUVobject2mesh_map = new Dictionary <Material, Mesh>();

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

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

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

            int numResMats = shader2Material_map.Count;

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

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

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

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

            //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, MB_Utility.MeshAnalysisResult> meshAnalysisResultCache = new Dictionary <int, MB_Utility.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     = MB_Utility.GetMesh(gameObjects[i].go);
                int  nVerts = 0;
                if (mm != null)
                {
                    nVerts += mm.vertexCount;
                    MB_Utility.MeshAnalysisResult mar;
                    if (!meshAnalysisResultCache.TryGetValue(mm.GetInstanceID(), out mar))
                    {
                        //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Check Out Of Bounds UVs", .6f);
                        MB_Utility.hasOutOfBoundsUVs(mm, ref mar);
                        //Rect dummy = mar.uvRect;
                        MB_Utility.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 (!MB_Utility.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 = MB3_MeshBakerEditorWindow.sortIntoBakeGroups3(gameObjects, objsNotAddedToBaker, filters, false, mom.maxAtlasSize);

            mom.resultMaterials = new MB_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)
            {
                MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_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"));
                MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m.materials[0]);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            MBVersionEditor.UpdateIfDirtyOrScript(textureBaker);
        }
    private IEnumerator _CreateAtlasesCoroutineAtlases(MB3_TextureCombiner combiner, ProgressUpdateDelegate progressInfo, MB3_TextureCombiner.CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f)
    {
        int numResults = 1;

        if (_doMultiMaterial)
        {
            numResults = resultMaterials.Length;
        }

        OnCombinedTexturesCoroutineAtlasesAndRects = new MB_AtlasesAndRects[numResults];
        for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++)
        {
            OnCombinedTexturesCoroutineAtlasesAndRects[i] = new MB_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;
                combiner.fixOutOfBoundsUVs = resultMaterials[i].considerMeshUVs;
            }
            else
            {
                resMatToPass = _resultMaterial;
            }

            MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult coroutineResult2 = new MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult();
            yield return(combiner.CombineTexturesIntoAtlasesCoroutine(progressInfo, OnCombinedTexturesCoroutineAtlasesAndRects[i], resMatToPass, objsToMesh, sourceMats, editorMethods, coroutineResult2, maxTimePerFrame,
                                                                      onlyPackRects: false, splitAtlasWhenPackingIfTooBig: false));

            coroutineResult.success = coroutineResult2.success;
            if (!coroutineResult.success)
            {
                coroutineResult.isFinished = true;
                yield break;
            }
        }

        unpackMat2RectMap(OnCombinedTexturesCoroutineAtlasesAndRects);
        if (coroutineResult.success && editorMethods != null)
        {
            editorMethods.GetMaterialPrimaryKeysIfAddressables(textureBakeResults);
        }
        //Save the results
        textureBakeResults.resultType = MB2_TextureBakeResults.ResultType.atlas;
        textureBakeResults.resultMaterialsTexArray = new MB_MultiMaterialTexArray[0];
        textureBakeResults.doMultiMaterial         = _doMultiMaterial;
        if (_doMultiMaterial)
        {
            textureBakeResults.resultMaterials = resultMaterials;
        }
        else
        {
            MB_MultiMaterial[] resMats = new MB_MultiMaterial[1];
            resMats[0] = new MB_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;
        }

        if (LOG_LEVEL >= MB2_LogLevel.info)
        {
            Debug.Log("Created Atlases");
        }
    }
        public void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker mom)
        {
            if (mom.objsToMesh.Count == 0)
            {
                Debug.LogError("You need to add some objects to combine before building the multi material list.");
                return;
            }
            if (resultMaterials.arraySize > 0)
            {
                Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
                return;
            }
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Material Bake Result asset must be set before using this operation.");
                return;
            }
            Dictionary <Shader, List <Material> > shader2Material_map     = new Dictionary <Shader, List <Material> >();
            Dictionary <Material, Mesh>           obUVobject2material_map = new Dictionary <Material, Mesh>();

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

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

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

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

            foreach (Shader sh in shader2Material_map.Keys)
            {
                List <Material>  matsThatUse = shader2Material_map[sh];
                MB_MultiMaterial mm          = mom.resultMaterials[k] = new MB_MultiMaterial();
                mm.sourceMaterials = matsThatUse;
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                if (matsThatUse.Count > 0 && matsThatUse[0] != null)
                {
                    MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]);
                }
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            foreach (Material m in obUVobject2material_map.Keys)
            {
                MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
                mm.sourceMaterials = new List <Material>();
                mm.sourceMaterials.Add(m);
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            textureBaker.UpdateIfDirtyOrScript();
        }
    public MB_AtlasesAndRects[] CreateAtlases(ProgressUpdateDelegate progressInfo, bool saveAtlasesAsAssets = false, MB_TextureCombiner.FileSaveFunction fileSaveFunction = null)
    {
        if (doMultiMaterial)
        {
            for (int i = 0; i < resultMaterials.Length; i++)
            {
                MB_MultiMaterial mm = resultMaterials[i];
                if (mm.combinedMaterial == null)
                {
                    Debug.LogError("Combined Material is null please create and assign a result material.");
                    return(null);
                }
                UnityEngine.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(null);
                    }
                    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.");
                    }
                }
            }
        }
        else
        {
            if (resultMaterial == null)
            {
                Debug.LogError("Combined Material is null please create and assign a result material.");
                return(null);
            }
            UnityEngine.Shader targShader = resultMaterial.shader;
            for (int i = 0; i < objsToMesh.Count; i++)
            {
                Material[] ms = MB_Utility.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");
                        return(null);
                    }
                    if (m.shader != targShader)
                    {
                        Debug.LogWarning("Game object " + objsToMesh[i] + " does not use shader " + targShader + " it may not have the required textures. If not empty textures will be generated.");
                    }
                }
            }
        }

        int numResults = 1;

        if (doMultiMaterial)
        {
            numResults = resultMaterials.Length;
        }
        MB_AtlasesAndRects[] results = new MB_AtlasesAndRects[numResults];
        for (int i = 0; i < results.Length; i++)
        {
            results[i] = new MB_AtlasesAndRects();
        }
        MB_TextureCombiner tc = new MB_TextureCombiner();

        Material        resMatToPass = null;
        List <Material> sourceMats   = null;

        for (int i = 0; i < results.Length; i++)
        {
            if (doMultiMaterial)
            {
                sourceMats   = resultMaterials[i].sourceMaterials;
                resMatToPass = resultMaterials[i].combinedMaterial;
            }
            else
            {
                resMatToPass = resultMaterial;
            }
            Debug.Log("Creating atlases for result material " + resMatToPass);
            if (!tc.combineTexturesIntoAtlases(progressInfo, results[i], resMatToPass, objsToMesh, sourceMats, atlasPadding, customShaderPropNames, resizePowerOfTwoTextures, fixOutOfBoundsUVs, maxTilingBakeSize, saveAtlasesAsAssets, texturePackingAlgorithm, fileSaveFunction))
            {
                return(null);
            }
        }

        if (results != null)
        {
            textureBakeResults.combinedMaterialInfo = results;
            textureBakeResults.doMultiMaterial      = doMultiMaterial;
            textureBakeResults.resultMaterial       = resultMaterial;
            textureBakeResults.resultMaterials      = resultMaterials;
            textureBakeResults.fixOutOfBoundsUVs    = fixOutOfBoundsUVs;
            unpackMat2RectMap(textureBakeResults);

            if (UnityEngine.Application.isPlaying)
            {
                if (doMultiMaterial)
                {
                    for (int j = 0; j < resultMaterials.Length; j++)
                    {
                        Material    resMat  = resultMaterials[j].combinedMaterial;                     //resultMaterials[j].combinedMaterial;
                        Texture2D[] atlases = results[j].atlases;
                        for (int i = 0; i < atlases.Length; i++)
                        {
                            resMat.SetTexture(results[j].texPropertyNames[i], atlases[i]);
                            //				_setMaterialTextureProperty(resMat, newMesh.texPropertyNames[i], relativePath);
                        }
                    }
                }
                else
                {
                    Material    resMat  = resultMaterial;                 //resultMaterials[j].combinedMaterial;
                    Texture2D[] atlases = results[0].atlases;
                    for (int i = 0; i < atlases.Length; i++)
                    {
                        resMat.SetTexture(results[0].texPropertyNames[i], atlases[i]);
                        //				_setMaterialTextureProperty(resMat, newMesh.texPropertyNames[i], relativePath);
                    }
                }
            }
        }

        if (VERBOSE)
        {
            Debug.Log("Created Atlases");
        }
        return(results);
    }
Exemple #9
0
    private bool _ValidateResultMaterials()
    {
        HashSet <Material> hashSet = new HashSet <Material>();

        for (int i = 0; i < this.objsToMesh.Count; i++)
        {
            if (this.objsToMesh[i] != null)
            {
                Material[] gomaterials = MB_Utility.GetGOMaterials(this.objsToMesh[i]);
                for (int j = 0; j < gomaterials.Length; j++)
                {
                    if (gomaterials[j] != null)
                    {
                        hashSet.Add(gomaterials[j]);
                    }
                }
            }
        }
        HashSet <Material> hashSet2 = new HashSet <Material>();

        for (int k = 0; k < this.resultMaterials.Length; k++)
        {
            MB_MultiMaterial mb_MultiMaterial = this.resultMaterials[k];
            if (mb_MultiMaterial.combinedMaterial == null)
            {
                Debug.LogError("Combined Material is null please create and assign a result material.");
                return(false);
            }
            Shader shader = mb_MultiMaterial.combinedMaterial.shader;
            for (int l = 0; l < mb_MultiMaterial.sourceMaterials.Count; l++)
            {
                if (mb_MultiMaterial.sourceMaterials[l] == null)
                {
                    Debug.LogError("There are null entries in the list of Source Materials");
                    return(false);
                }
                if (shader != mb_MultiMaterial.sourceMaterials[l].shader)
                {
                    Debug.LogWarning(string.Concat(new object[]
                    {
                        "Source material ",
                        mb_MultiMaterial.sourceMaterials[l],
                        " does not use shader ",
                        shader,
                        " it may not have the required textures. If not empty textures will be generated."
                    }));
                }
                if (hashSet2.Contains(mb_MultiMaterial.sourceMaterials[l]))
                {
                    Debug.LogError("A Material " + mb_MultiMaterial.sourceMaterials[l] + " 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);
                }
                hashSet2.Add(mb_MultiMaterial.sourceMaterials[l]);
            }
        }
        if (hashSet.IsProperSubsetOf(hashSet2))
        {
            hashSet2.ExceptWith(hashSet);
            Debug.LogWarning("There are materials in the mapping that are not used on your source objects: " + this.PrintSet(hashSet2));
        }
        if (hashSet2.IsProperSubsetOf(hashSet))
        {
            hashSet.ExceptWith(hashSet2);
            Debug.LogError("There are materials on the objects to combine that are not in the mapping: " + this.PrintSet(hashSet));
            return(false);
        }
        return(true);
    }
Exemple #10
0
    bool _addToCombined(GameObject[] goToAdd, GameObject[] goToDelete, bool disableRendererInSource)
    {
        if (goToAdd == null)
        {
            goToAdd = empty;
        }
        if (goToDelete == null)
        {
            goToDelete = empty;
        }
        if (_mesh == null)
        {
            _mesh = new Mesh();
        }
        if (mat2rect_map.Keys.Count == 0)
        {
            _initialize();
        }

        int numResultMats = 1;

        if (doMultiMaterial)
        {
            numResultMats = resultMaterials.Length;
        }

        if (VERBOSE)
        {
            Debug.Log("_addToCombined objs adding:" + goToAdd.Length + " objs deleting:" + goToDelete.Length + " fixOutOfBounds:" + fixOutOfBoundsUVs + " doMultiMaterial:" + doMultiMaterial);
        }

        OrderedDictionary sourceMats2submeshIdx_map = null;

        if (doMultiMaterial)
        {
            //build the sourceMats to submesh index map
            sourceMats2submeshIdx_map = new OrderedDictionary();
            for (int i = 0; i < numResultMats; i++)
            {
                MB_MultiMaterial mm = resultMaterials[i];
                for (int j = 0; j < mm.sourceMaterials.Count; j++)
                {
                    if (mm.sourceMaterials[j] == null)
                    {
                        Debug.LogError("Found null material in source materials for combined mesh materials " + i);
                        return(false);
                    }
                    if (!sourceMats2submeshIdx_map.Contains(mm.sourceMaterials[j]))
                    {
                        sourceMats2submeshIdx_map.Add(mm.sourceMaterials[j], i);
                    }
                }
            }
        }

        if (submeshTris.Length == 0)
        {
            submeshTris = new int[numResultMats][];
            for (int i = 0; i < submeshTris.Length; i++)
            {
                submeshTris[i] = new int[0];
            }
        }

        //calculate num to delete
        int totalDeleteVerts = 0;

//		int totalDeleteTris = 0;
        int[] totalDeleteSubmeshTris = new int[numResultMats];
        for (int i = 0; i < goToDelete.Length; i++)
        {
            MB_DynamicGameObject dgo;
            if (instance2combined_map.TryGetValue(goToDelete[i], out dgo))
            {
                totalDeleteVerts += dgo.numVerts;
//				totalDeleteTris += dgo.numTris;
                for (int j = 0; j < dgo.submeshNumTris.Length; j++)
                {
                    totalDeleteSubmeshTris[j] += dgo.submeshNumTris[j];
                }
            }
            else
            {
                Debug.LogWarning("Trying to delete an object that is not in combined mesh");
            }
        }

        //now add
        List <MB_DynamicGameObject> toAddDGOs = new List <MB_DynamicGameObject>();
        int totalAddVerts = 0;

//		int totalAddTris = 0;
        int[] totalAddSubmeshTris = new int[numResultMats];
        for (int i = 0; i < goToAdd.Length; i++)
        {
            if (!instance2combined_map.ContainsKey(goToAdd[i]))
            {
                MB_DynamicGameObject dgo = new MB_DynamicGameObject();

                GameObject go = goToAdd[i];

                Material[] sharedMaterials = MB_Utility.GetGOMaterials(go);

                if (sharedMaterials == null)
                {
                    Debug.LogError("Object " + go.name + " does not have a Renderer");
                    goToAdd[i] = null;
                    continue;
                }

                Mesh m = MB_Utility.GetMesh(go);
                if (m == null)
                {
                    Debug.LogError("Object " + go.name + " MeshFilter or SkinedMeshRenderer had no mesh");
                    goToAdd[i] = null;
                }

                Rect[] uvRects = new Rect[sharedMaterials.Length];
                for (int j = 0; j < sharedMaterials.Length; j++)
                {
                    if (!mat2rect_map.TryGetValue(sharedMaterials[j], out uvRects[j]))
                    {
                        Debug.LogError("Object " + go.name + " has an unknown material " + sharedMaterials[j] + ". Try baking textures");
                        goToAdd[i] = null;
                    }
                }
                if (goToAdd[i] != null)
                {
                    dgo.go         = goToAdd[i];
                    dgo.uvRects    = uvRects;
                    dgo.sharedMesh = m;
                    dgo.numVerts   = m.vertexCount;

                    if (!_collectMaterialTriangles(m, dgo, sharedMaterials, sourceMats2submeshIdx_map))
                    {
                        return(false);
                    }
                    dgo.submeshNumTris = new int[numResultMats];
                    dgo.submeshTriIdxs = new int[numResultMats];

                    if (fixOutOfBoundsUVs)
                    {
                        if (!_collectOutOfBoundsUVRects(m, dgo, sharedMaterials, sourceMats2submeshIdx_map))
                        {
                            return(false);
                        }
                    }
                    toAddDGOs.Add(dgo);
                    totalAddVerts += dgo.numVerts;
//					totalAddTris += dgo.numTris;

                    for (int j = 0; j < dgo._submeshTris.Length; j++)
                    {
                        totalAddSubmeshTris[dgo.targetSubmeshIdxs[j]] += dgo._submeshTris[j].Count;
                    }
                }
            }
            else
            {
                Debug.LogWarning("Object " + goToAdd[i].name + " has already been added to " + name);
                goToAdd[i] = null;
            }
        }

        for (int i = 0; i < goToAdd.Length; i++)
        {
            if (goToAdd[i] != null && disableRendererInSource)
            {
                MB_Utility.DisableRendererInSource(goToAdd[i]);
            }
        }

        int newVertSize = verts.Length + totalAddVerts - totalDeleteVerts;

//		int newTrisSize = tris.Length + totalAddTris - totalDeleteTris;
        int[] newSubmeshTrisSize = new int[numResultMats];
        if (VERBOSE)
        {
            Debug.Log("Verts adding:" + totalAddVerts + " deleting:" + totalDeleteVerts);
        }

        if (VERBOSE)
        {
            Debug.Log("Submeshes:" + newSubmeshTrisSize.Length);
        }
        for (int i = 0; i < newSubmeshTrisSize.Length; i++)
        {
            newSubmeshTrisSize[i] = submeshTris[i].Length + totalAddSubmeshTris[i] - totalDeleteSubmeshTris[i];
            if (VERBOSE)
            {
                Debug.Log("    submesh :" + i + " already contains:" + submeshTris[i].Length + " trisAdded:" + totalAddSubmeshTris[i] + " trisDeleted:" + totalDeleteSubmeshTris[i]);
            }
        }

        if (newVertSize > 65534)
        {
            Debug.LogError("Cannot add objects. Resulting mesh will have more than 64k vertices .");
            return(false);
        }

        Vector3[] nverts    = new Vector3[newVertSize];
        Vector3[] nnormals  = new Vector3[newVertSize];
        Vector4[] ntangents = new Vector4[newVertSize];
        Vector2[] nuvs      = new Vector2[newVertSize];
        Vector2[] nuv1s     = new Vector2[newVertSize];
        Vector2[] nuv2s     = new Vector2[newVertSize];
        Color[]   ncolors   = new Color[newVertSize];
//		int[] ntris = new int[newTrisSize];
        int[][] nsubmeshTris = null;

        nsubmeshTris = new int[numResultMats][];
        for (int i = 0; i < nsubmeshTris.Length; i++)
        {
            nsubmeshTris[i] = new int[newSubmeshTrisSize[i]];
        }

        for (int i = 0; i < goToDelete.Length; i++)
        {
            MB_DynamicGameObject dgo;
            if (instance2combined_map.TryGetValue(goToDelete[i], out dgo))
            {
                dgo._beingDeleted = true;
            }
        }

        objectsInCombinedMesh.Sort();

        //copy existing arrays to narrays gameobj by gameobj omitting deleted ones
        int targVidx = 0;

        int[] targSubmeshTidx       = new int[numResultMats];
        int   triangleIdxAdjustment = 0;

        for (int i = 0; i < objectsInCombinedMesh.Count; i++)
        {
            MB_DynamicGameObject dgo = objectsInCombinedMesh[i];
            if (!dgo._beingDeleted)
            {
                if (VERBOSE)
                {
                    Debug.Log("Copying obj in combined arrays idx:" + i);
                }
                Array.Copy(verts, dgo.vertIdx, nverts, targVidx, dgo.numVerts);
                Array.Copy(normals, dgo.vertIdx, nnormals, targVidx, dgo.numVerts);
                Array.Copy(tangents, dgo.vertIdx, ntangents, targVidx, dgo.numVerts);
                Array.Copy(uvs, dgo.vertIdx, nuvs, targVidx, dgo.numVerts);
                Array.Copy(uv1s, dgo.vertIdx, nuv1s, targVidx, dgo.numVerts);
                Array.Copy(uv2s, dgo.vertIdx, nuv2s, targVidx, dgo.numVerts);
                Array.Copy(colors, dgo.vertIdx, ncolors, targVidx, dgo.numVerts);

                //adjust triangles, then copy them over

                for (int subIdx = 0; subIdx < numResultMats; subIdx++)
                {
                    int[] sTris    = submeshTris[subIdx];
                    int   sTriIdx  = dgo.submeshTriIdxs[subIdx];
                    int   sNumTris = dgo.submeshNumTris[subIdx];
                    if (VERBOSE)
                    {
                        Debug.Log("    Adjusting submesh triangles submesh:" + subIdx + " startIdx:" + sTriIdx + " num:" + sNumTris);
                    }
                    for (int j = sTriIdx; j < sTriIdx + sNumTris; j++)
                    {
                        sTris[j] = sTris[j] - triangleIdxAdjustment;
                    }
                    Array.Copy(sTris, sTriIdx, nsubmeshTris[subIdx], targSubmeshTidx[subIdx], sNumTris);
                }



//				dgo.triIdx = targTidx;
                dgo.vertIdx = targVidx;
//				targTidx += dgo.numTris;

                for (int j = 0; j < targSubmeshTidx.Length; j++)
                {
                    dgo.submeshTriIdxs[j] = targSubmeshTidx[j];
                    targSubmeshTidx[j]   += dgo.submeshNumTris[j];
                }

                targVidx += dgo.numVerts;
            }
            else
            {
                if (VERBOSE)
                {
                    Debug.Log("Not copying obj: " + i);
                }
                triangleIdxAdjustment += dgo.numVerts;
            }
        }

        for (int i = objectsInCombinedMesh.Count - 1; i >= 0; i--)
        {
            if (objectsInCombinedMesh[i]._beingDeleted)
            {
                instance2combined_map.Remove(objectsInCombinedMesh[i].go);
                objectsInCombinedMesh.RemoveAt(i);
            }
        }

        verts    = nverts;
        normals  = nnormals;
        tangents = ntangents;
        uvs      = nuvs;
        uv1s     = nuv1s;
        uv2s     = nuv2s;
        colors   = ncolors;
//		tris = ntris;
        submeshTris = nsubmeshTris;

        //add new
        for (int i = 0; i < toAddDGOs.Count; i++)
        {
            MB_DynamicGameObject dgo = toAddDGOs[i];
            GameObject           go  = dgo.go;
            int vertsIdx             = targVidx;
//			int trisIdx = targTidx;

            Mesh       mesh   = dgo.sharedMesh;
            Matrix4x4  l2wMat = go.transform.localToWorldMatrix;
            Quaternion l2wQ   = go.transform.rotation;
            nverts = mesh.vertices;
            Vector3[] nnorms = mesh.normals;
            Vector4[] ntangs = mesh.tangents;
            for (int j = 0; j < nverts.Length; j++)
            {
                nverts[j] = l2wMat.MultiplyPoint(nverts[j]);
                nnorms[j] = l2wQ * nnorms[j];
                float w = ntangs[j].w;                 //need to preserve the w value
                ntangs[j]   = l2wQ * ntangs[j];
                ntangs[j].w = w;
            }

            int numTriSets = mesh.subMeshCount;
            if (dgo.uvRects.Length < numTriSets)
            {
                Debug.LogWarning("Mesh " + dgo.go.name + " has more submeshes than materials");
                numTriSets = dgo.uvRects.Length;
            }
            else if (dgo.uvRects.Length > numTriSets)
            {
                Debug.LogWarning("Mesh " + dgo.go.name + " has fewer submeshes than materials");
            }
            nuvs = mesh.uv;
            int[] done = new int[nuvs.Length];             //use this to track uvs that have already been adjusted don't adjust twice
            for (int l = 0; l < done.Length; l++)
            {
                done[l] = -1;
            }

            bool triangleArraysOverlap = false;
            Rect obUVRect = new Rect();
            for (int k = 0; k < dgo._submeshTris.Length; k++)
            {
                List <int> subTris = dgo._submeshTris[k];
                Rect       uvRect  = dgo.uvRects[k];
                if (fixOutOfBoundsUVs)
                {
                    obUVRect = dgo.obUVRects[dgo.targetSubmeshIdxs[k]];
                }
                for (int l = 0; l < subTris.Count; l++)
                {
                    int vidx = subTris[l];
                    if (done[vidx] == -1)
                    {
                        done[vidx] = k;                         //prevents a uv from being adjusted twice
                        if (fixOutOfBoundsUVs)
                        {
                            nuvs[vidx].x = nuvs[vidx].x / obUVRect.width - obUVRect.x / obUVRect.width;
                            nuvs[vidx].y = nuvs[vidx].y / obUVRect.height - obUVRect.y / obUVRect.height;
                        }
                        nuvs[vidx].x = uvRect.x + nuvs[vidx].x * uvRect.width;
                        nuvs[vidx].y = uvRect.y + nuvs[vidx].y * uvRect.height;
                    }
                    if (done[vidx] != k)
                    {
                        triangleArraysOverlap = true;
                    }
                }
            }
            if (triangleArraysOverlap)
            {
                Debug.LogWarning(dgo.go.name + "has submeshes which share verticies. Adjusted uvs may not map correctly in combined atlas.");
            }

            nverts.CopyTo(verts, vertsIdx);
            nnorms.CopyTo(normals, vertsIdx);
            ntangs.CopyTo(tangents, vertsIdx);
            nuvs.CopyTo(uvs, vertsIdx);
            mesh.uv1.CopyTo(uv1s, vertsIdx);
            mesh.uv2.CopyTo(uv2s, vertsIdx);
            mesh.colors.CopyTo(colors, vertsIdx);
//			ntris = mesh.triangles;
//			for (int j = 0; j < ntris.Length; j++){
//				ntris[j] = ntris[j] + vertsIdx;
//			}

            for (int combinedMeshIdx = 0; combinedMeshIdx < targSubmeshTidx.Length; combinedMeshIdx++)
            {
                dgo.submeshTriIdxs[combinedMeshIdx] = targSubmeshTidx[combinedMeshIdx];
            }
            for (int j = 0; j < dgo._submeshTris.Length; j++)
            {
                List <int> sts = dgo._submeshTris[j];
                for (int k = 0; k < sts.Count; k++)
                {
                    sts[k] = sts[k] + vertsIdx;
                }
                int combinedMeshIdx = dgo.targetSubmeshIdxs[j];
                sts.CopyTo(submeshTris[combinedMeshIdx], targSubmeshTidx[combinedMeshIdx]);
                dgo.submeshNumTris[combinedMeshIdx] += sts.Count;
                targSubmeshTidx[combinedMeshIdx]    += sts.Count;
            }

            dgo.vertIdx = targVidx;

            instance2combined_map.Add(go, dgo);
            objectsInCombinedMesh.Add(dgo);

            targVidx += nverts.Length;
            for (int j = 0; j < dgo._submeshTris.Length; j++)
            {
                dgo._submeshTris[j].Clear();
            }
            dgo._submeshTris = null;
            if (VERBOSE)
            {
                Debug.Log("Added to combined:" + dgo.go.name + " verts:" + nverts.Length);
            }
        }
        return(true);
    }
Exemple #11
0
    public MB_AtlasesAndRects[] CreateAtlases(ProgressUpdateDelegate progressInfo)
    {
        if (doMultiMaterial)
        {
            for (int i = 0; i < resultMaterials.Length; i++)
            {
                MB_MultiMaterial mm         = resultMaterials[i];
                Shader           targShader = mm.combinedMaterial.shader;
                for (int j = 0; j < mm.sourceMaterials.Count; j++)
                {
                    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.");
                    }
                }
            }
        }
        else
        {
            Shader targShader = resultMaterial.shader;
            for (int i = 0; i < objsToMesh.Count; i++)
            {
                Material[] ms = MB_Utility.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");
                        return(null);
                    }
                    if (m.shader != targShader)
                    {
                        Debug.LogWarning("Game object " + objsToMesh[i] + " does not use shader " + targShader + " it may not have the required textures. If not empty textures will be generated.");
                    }
                }
            }
        }

        int numResults = 1;

        if (doMultiMaterial)
        {
            numResults = resultMaterials.Length;
        }
        MB_AtlasesAndRects[] results = new MB_AtlasesAndRects[numResults];
        for (int i = 0; i < results.Length; i++)
        {
            results[i] = new MB_AtlasesAndRects();
        }
        MB_TextureCombiner tc = new MB_TextureCombiner();

        Material[]      resMatsToPass = new Material[1];
        List <Material> sourceMats    = null;

        for (int i = 0; i < results.Length; i++)
        {
            if (doMultiMaterial)
            {
                sourceMats       = resultMaterials[i].sourceMaterials;
                resMatsToPass[0] = resultMaterials[i].combinedMaterial;
            }
            else
            {
                resMatsToPass[0] = resultMaterial;
            }
            Debug.Log("Creating atlases for result material " + resMatsToPass[0]);
            if (!tc.combineTexturesIntoAtlases(progressInfo, results[i], resMatsToPass, objsToMesh, sourceMats, atlasPadding, customShaderPropNames, resizePowerOfTwoTextures, fixOutOfBoundsUVs, 1024))
            {
                return(null);
            }
        }
        updateMaterialToRectMapping(results);
        return(results);
    }
Exemple #12
0
    public void ConfigureMutiMaterialsFromObjsToCombine(MB2_TextureBaker mom)
    {
        if (mom.objsToMesh.Count == 0)
        {
            Debug.LogError("You need to add some objects to combine before building the multi material list.");
            return;
        }
        if (resultMaterials.arraySize > 0)
        {
            Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
            return;
        }
        if (mom.textureBakeResults == null)
        {
            Debug.LogError("Material Bake Result asset must be set before using this operation.");
            return;
        }
        Dictionary <UnityEngine.Shader, List <Material> > shader2Material_map = new Dictionary <UnityEngine.Shader, List <Material> >();
        bool hasOutOfBoundsUVs = false;

        for (int i = 0; i < mom.objsToMesh.Count; i++)
        {
            UnityEngine.GameObject go = mom.objsToMesh[i];
            if (go == null)
            {
                Debug.LogError("Null object in list of objects to combine at position " + i);
                return;
            }
            UnityEngine.Renderer r = go.GetComponent <UnityEngine.Renderer>();
            if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
            {
                Debug.LogError("UnityEngine.GameObject at position " + i + " in list of objects to combine did not have a renderer");
                return;
            }

            Mesh m     = MB_Utility.GetMesh(go);
            Rect dummy = new Rect();
            if (MB_Utility.hasOutOfBoundsUVs(m, ref dummy, -1))
            {
                hasOutOfBoundsUVs = true;
            }

            for (int j = 0; j < r.sharedMaterials.Length; j++)
            {
                if (r.sharedMaterials[j] == null)
                {
                    continue;
                }
                List <Material> matsThatUseShader = null;;
                if (!shader2Material_map.TryGetValue(r.sharedMaterials[j].shader, out matsThatUseShader))
                {
                    matsThatUseShader = new List <Material>();
                    shader2Material_map.Add(r.sharedMaterials[j].shader, matsThatUseShader);
                }
                if (!matsThatUseShader.Contains(r.sharedMaterials[j]))
                {
                    matsThatUseShader.Add(r.sharedMaterials[j]);
                }
            }
        }
        if (hasOutOfBoundsUVs)
        {
            mom.fixOutOfBoundsUVs = true;
            Debug.LogWarning("Some game objects have out-of-bounds UVs. Setting the fix-out-of-bounds UVs flag");
        }
        if (shader2Material_map.Count == 0)
        {
            Debug.LogError("Found no materials in list of objects to combine");
        }
        mom.resultMaterials = new MB_MultiMaterial[shader2Material_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 (UnityEngine.Shader sh in shader2Material_map.Keys)
        {
            List <Material>  matsThatUse = shader2Material_map[sh];
            MB_MultiMaterial mm          = mom.resultMaterials[k] = new MB_MultiMaterial();
            mm.sourceMaterials = matsThatUse;
            string   matName = folderPath + baseName + "-mat" + k + ".mat";
            Material newMat  = new Material(UnityEngine.Shader.Find("Diffuse"));
            if (matsThatUse.Count > 0 && matsThatUse[0] != null)
            {
                MB2_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]);
            }
            AssetDatabase.CreateAsset(newMat, matName);
            mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
            k++;
        }
        textureBaker.UpdateIfDirtyOrScript();
    }