Example #1
0
 /// <summary>
 /// Creates the atlases.
 /// </summary>
 /// <returns>
 /// The atlases.
 /// </returns>
 /// <param name='progressInfo'>
 /// Progress info is a delegate function that displays a progress dialog. Can be null
 /// </param>
 /// <param name='saveAtlasesAsAssets'>
 /// if true atlases are saved as assets in the project folder. Othersise they are instances in memory
 /// </param>
 /// <param name='editorMethods'>
 /// Texture format tracker. Contains editor functionality such as save assets. Can be null.
 /// </param>
 public MB_AtlasesAndRects[] CreateAtlases(ProgressUpdateDelegate progressInfo, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null)
 {
     MB_AtlasesAndRects[] mAndAs = null;
     try
     {
         //mAndAs = _CreateAtlases(progressInfo, saveAtlasesAsAssets, editorMethods);
         CreateAtlasesCoroutineResult result = new CreateAtlasesCoroutineResult();
         MB3_TextureCombiner.RunCorutineWithoutPause(CreateAtlasesCoroutine(progressInfo, result, saveAtlasesAsAssets, editorMethods, 1000f), 0);
         if (result.success)
         {
             mAndAs = textureBakeResults.combinedMaterialInfo;
         }
     }
     catch (Exception e)
     {
         Debug.LogError(e);
     }
     finally
     {
         if (saveAtlasesAsAssets)
         { //Atlases were saved to project so we don't need these ones
             if (mAndAs != null)
             {
                 for (int j = 0; j < mAndAs.Length; j++)
                 {
                     MB_AtlasesAndRects mAndA = mAndAs[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
                                 {
                                     MB_Utility.Destroy(mAndA.atlases[i]);
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     return(mAndAs);
 }
Example #2
0
    public Texture2D OnRenderAtlas(MB3_TextureCombiner combiner)
    {
        fastRenderer   = new MB_TextureCombinerRenderTexture();
        _doRenderAtlas = true;
        TextureBlender blender = null;

        if (resultMaterialTextureBlender != null)
        {
            blender = resultMaterialTextureBlender.GetTextureBlender();
        }
        Texture2D atlas = fastRenderer.DoRenderAtlas(this.gameObject, width, height, padding, rects, textureSets, indexOfTexSetToRender, texPropertyName, blender, isNormalMap, fixOutOfBoundsUVs, considerNonTextureProperties, combiner, LOG_LEVEL);

        _doRenderAtlas = false;
        return(atlas);
    }
    public MB3_TextureCombiner CreateAndConfigureTextureCombiner()
    {
        MB3_TextureCombiner combiner = new MB3_TextureCombiner();

        combiner.LOG_LEVEL             = LOG_LEVEL;
        combiner.atlasPadding          = _atlasPadding;
        combiner.maxAtlasSize          = _maxAtlasSize;
        combiner.customShaderPropNames = _customShaderProperties;
        combiner.fixOutOfBoundsUVs     = _fixOutOfBoundsUVs;
        combiner.maxTilingBakeSize     = _maxTilingBakeSize;
        combiner.packingAlgorithm      = _packingAlgorithm;
        combiner.meshBakerTexturePackerForcePowerOfTwo = _meshBakerTexturePackerForcePowerOfTwo;
        combiner.resizePowerOfTwoTextures     = _resizePowerOfTwoTextures;
        combiner.considerNonTextureProperties = _considerNonTextureProperties;
        return(combiner);
    }
    private IEnumerator _CreateAtlasesCoroutine(ProgressUpdateDelegate progressInfo, MB3_TextureCombiner.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 (resultType == MB2_TextureBakeResults.ResultType.textureArray)
        {
            //TODO validate texture arrays.
        }
        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;

        OnCombinedTexturesCoroutineAtlasesAndRects = null;
        if (resultType == MB2_TextureBakeResults.ResultType.textureArray)
        {
            yield return(_CreateAtlasesCoroutineTextureArray(combiner, progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame));

            if (!coroutineResult.success)
            {
                yield break;
            }
        }
        else
        {
            yield return(_CreateAtlasesCoroutineAtlases(combiner, progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame));

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

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

        coroutineResult.isFinished = true;
    }
    internal IEnumerator _CreateAtlasesCoroutineTextureArray(MB3_TextureCombiner combiner, ProgressUpdateDelegate progressInfo, MB3_TextureCombiner.CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f)
    {
        MB_TextureArrayResultMaterial[] bakedMatsAndSlices = null;

        // Validate the formats
        if (textureArrayOutputFormats == null || textureArrayOutputFormats.Length == 0)
        {
            Debug.LogError("No Texture Array Output Formats. There must be at least one entry.");
            coroutineResult.isFinished = true;
            yield break;
        }

        for (int i = 0; i < textureArrayOutputFormats.Length; i++)
        {
            if (!textureArrayOutputFormats[i].ValidateTextureImporterFormatsExistsForTextureFormats(editorMethods, i))
            {
                Debug.LogError("Could not map the selected texture format to a Texture Importer Format. Safest options are ARGB32, or RGB24.");
                coroutineResult.isFinished = true;
                yield break;
            }
        }

        for (int resMatIdx = 0; resMatIdx < resultMaterialsTexArray.Length; resMatIdx++)
        {
            MB_MultiMaterialTexArray textureArraySliceConfig = resultMaterialsTexArray[resMatIdx];
            if (textureArraySliceConfig.combinedMaterial == null)
            {
                Debug.LogError("Material is null for Texture Array Slice Configuration: " + resMatIdx + ".");
                coroutineResult.isFinished = true;
                yield break;
            }


            List <MB_TexArraySlice> slices = textureArraySliceConfig.slices;
            for (int sliceIdx = 0; sliceIdx < slices.Count; sliceIdx++)
            {
                for (int srcMatIdx = 0; srcMatIdx < slices[sliceIdx].sourceMaterials.Count; srcMatIdx++)
                {
                    MB_TexArraySliceRendererMatPair sourceMat = slices[sliceIdx].sourceMaterials[srcMatIdx];
                    if (sourceMat.sourceMaterial == null)
                    {
                        Debug.LogError("Source material is null for Texture Array Slice Configuration: " + resMatIdx + " slice: " + sliceIdx);
                        coroutineResult.isFinished = true;
                        yield break;
                    }

                    if (slices[sliceIdx].considerMeshUVs)
                    {
                        if (sourceMat.renderer == null)
                        {
                            Debug.LogError("Renderer is null for Texture Array Slice Configuration: " + resMatIdx + " slice: " + sliceIdx + ". If considerUVs is enabled then a renderer must be supplied for each source material. The same source material can be used multiple times.");
                            coroutineResult.isFinished = true;
                            yield break;
                        }
                    }
                    else
                    {
                        // TODO check for duplicate source mats.
                    }
                }
            }
        }

        // initialize structure to store results. For texture arrays the structure is two layers deep.
        // First layer is resultMaterial / submesh (each result material can use a different shader)
        // Second layer is a set of TextureArrays for the TextureProperties on that result material.
        int numResultMats = resultMaterialsTexArray.Length;

        bakedMatsAndSlices = new MB_TextureArrayResultMaterial[numResultMats];
        for (int resMatIdx = 0; resMatIdx < bakedMatsAndSlices.Length; resMatIdx++)
        {
            bakedMatsAndSlices[resMatIdx] = new MB_TextureArrayResultMaterial();
            int numSlices = resultMaterialsTexArray[resMatIdx].slices.Count;
            MB_AtlasesAndRects[] slices = bakedMatsAndSlices[resMatIdx].slices = new MB_AtlasesAndRects[numSlices];
            for (int j = 0; j < numSlices; j++)
            {
                slices[j] = new MB_AtlasesAndRects();
            }
        }

        // Some of the slices will be atlases (more than one atlas per slice).
        // Do the material combining for these. First loop over the result materials (1 per submeshes).
        for (int resMatIdx = 0; resMatIdx < bakedMatsAndSlices.Length; resMatIdx++)
        {
            yield return(MB_TextureArrays._CreateAtlasesCoroutineSingleResultMaterial(resMatIdx, bakedMatsAndSlices[resMatIdx], resultMaterialsTexArray[resMatIdx],
                                                                                      objsToMesh,
                                                                                      combiner,
                                                                                      textureArrayOutputFormats,
                                                                                      resultMaterialsTexArray,
                                                                                      customShaderProperties,
                                                                                      progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame));

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

        if (coroutineResult.success)
        {
            // Save the results into the TextureBakeResults.
            unpackMat2RectMap(bakedMatsAndSlices);
            if (editorMethods != null)
            {
                editorMethods.GetMaterialPrimaryKeysIfAddressables(textureBakeResults);
            }
            textureBakeResults.resultType              = MB2_TextureBakeResults.ResultType.textureArray;
            textureBakeResults.resultMaterials         = new MB_MultiMaterial[0];
            textureBakeResults.resultMaterialsTexArray = resultMaterialsTexArray;
            if (LOG_LEVEL >= MB2_LogLevel.info)
            {
                Debug.Log("Created Texture2DArrays");
            }
        }
        else
        {
            if (LOG_LEVEL >= MB2_LogLevel.info)
            {
                Debug.Log("Failed to create Texture2DArrays");
            }
        }
    }
    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");
        }
    }
Example #7
0
    public Texture2D DoRenderAtlas(GameObject gameObject, int width, int height, int padding, Rect[] rss, List <MB3_TextureCombiner.MB_TexSet> textureSetss, int indexOfTexSetToRenders, ShaderTextureProperty texPropertyname, TextureBlender resultMaterialTextureBlender, bool isNormalMap, bool fixOutOfBoundsUVs, bool considerNonTextureProperties, MB3_TextureCombiner texCombiner, MB2_LogLevel LOG_LEV)
    {
        LOG_LEVEL             = LOG_LEV;
        textureSets           = textureSetss;
        indexOfTexSetToRender = indexOfTexSetToRenders;
        _texPropertyName      = texPropertyname;
        _padding           = padding;
        _isNormalMap       = isNormalMap;
        _fixOutOfBoundsUVs = fixOutOfBoundsUVs;
        //_considerNonTextureProperties = considerNonTextureProperties;
        _resultMaterialTextureBlender = resultMaterialTextureBlender;
        combiner = texCombiner;
        rs       = rss;
        Shader s;

        if (_isNormalMap)
        {
            s = Shader.Find("MeshBaker/NormalMapShader");
        }
        else
        {
            s = Shader.Find("MeshBaker/AlbedoShader");
        }
        if (s == null)
        {
            Debug.LogError("Could not find shader for RenderTexture. Try reimporting mesh baker");
            return(null);
        }
        mat = new Material(s);
        _destinationTexture            = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32);
        _destinationTexture.filterMode = FilterMode.Point;

        myCamera = gameObject.GetComponent <Camera>();
        myCamera.orthographic     = true;
        myCamera.orthographicSize = height >> 1;
        myCamera.aspect           = width / height;
        myCamera.targetTexture    = _destinationTexture;
        myCamera.clearFlags       = CameraClearFlags.Color;

        Transform camTransform = myCamera.GetComponent <Transform>();

        camTransform.localPosition = new Vector3(width / 2.0f, height / 2f, 3);
        camTransform.localRotation = Quaternion.Euler(0, 180, 180);

        _doRenderAtlas = true;
        if (LOG_LEVEL >= MB2_LogLevel.debug)
        {
            Debug.Log(string.Format("Begin Camera.Render destTex w={0} h={1} camPos={2}", width, height, camTransform.localPosition));
        }
        //This triggers the OnRenderObject callback
        myCamera.Render();
        _doRenderAtlas = false;

        MB_Utility.Destroy(mat);
        MB_Utility.Destroy(_destinationTexture);

        if (LOG_LEVEL >= MB2_LogLevel.debug)
        {
            Debug.Log("Finished Camera.Render ");
        }

        Texture2D tempTex = targTex;

        targTex = null;
        return(tempTex);
    }
Example #8
0
    private void CopyScaledAndTiledToAtlas(MB3_TextureCombiner.MB_TexSet texSet, MB3_TextureCombiner.MeshBakerMaterialTexture source, Vector2 obUVoffset, Vector2 obUVscale, Rect rec, ShaderTextureProperty texturePropertyName, TextureBlender resultMatTexBlender)
    {
        Rect r = rec;

        if (resultMatTexBlender != null)
        {
            myCamera.backgroundColor = resultMatTexBlender.GetColorIfNoTexture(texSet.mats[0].mat, texturePropertyName);
        }
        else
        {
            myCamera.backgroundColor = MB3_TextureCombiner.GetColorIfNoTexture(texturePropertyName);
        }

        if (source.t == null)
        {
            source.t = combiner._createTemporaryTexture(16, 16, TextureFormat.ARGB32, true);
        }

        r.y       = 1f - (r.y + r.height);   // DrawTexture uses topLeft 0,0, Texture2D uses bottomLeft 0,0
        r.x      *= _destinationTexture.width;
        r.y      *= _destinationTexture.height;
        r.width  *= _destinationTexture.width;
        r.height *= _destinationTexture.height;

        Rect rPadded = r;

        rPadded.x      -= _padding;
        rPadded.y      -= _padding;
        rPadded.width  += _padding * 2;
        rPadded.height += _padding * 2;

        Rect srcPrTex = source.matTilingRect.GetRect();
        Rect targPr   = new Rect();

        if (_fixOutOfBoundsUVs)
        {
            Rect ruv = new Rect(obUVoffset.x, obUVoffset.y, obUVscale.x, obUVscale.y);
            srcPrTex = MB3_UVTransformUtility.CombineTransforms(ref srcPrTex, ref ruv);
            if (LOG_LEVEL >= MB2_LogLevel.trace)
            {
                Debug.Log("Fixing out of bounds UVs for tex " + source.t);
            }
        }


        Texture2D tex = source.t;

        /*
         * if (_considerNonTextureProperties && resultMatTexBlender != null)
         * {
         *      if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(string.Format("Blending texture {0} mat {1} with non-texture properties using TextureBlender {2}", tex.name, texSet.mats[0].mat, resultMatTexBlender));
         *
         *      resultMatTexBlender.OnBeforeTintTexture(texSet.mats[0].mat, texturePropertyName.name);
         *      //combine the tintColor with the texture
         *      tex = combiner._createTextureCopy(tex);
         *      for (int i = 0; i < tex.height; i++)
         *      {
         *              Color[] cs = tex.GetPixels(0, i, tex.width, 1);
         *              for (int j = 0; j < cs.Length; j++)
         *              {
         *                      cs[j] = resultMatTexBlender.OnBlendTexturePixel(texturePropertyName.name, cs[j]);
         *              }
         *              tex.SetPixels(0, i, tex.width, 1, cs);
         *      }
         *      tex.Apply();
         * }
         */


        //main texture
        TextureWrapMode oldTexWrapMode = tex.wrapMode;

        if (srcPrTex.width == 1f && srcPrTex.height == 1f && srcPrTex.x == 0f && srcPrTex.y == 0f)
        {
            //fixes bug where there is a dark line at the edge of the texture
            tex.wrapMode = TextureWrapMode.Clamp;
        }
        else
        {
            tex.wrapMode = TextureWrapMode.Repeat;
        }


        if (LOG_LEVEL >= MB2_LogLevel.trace)
        {
            Debug.Log("DrawTexture tex=" + tex.name + " destRect=" + r + " srcRect=" + srcPrTex + " Mat=" + mat);
        }


        //fill the padding first
        Rect srcPr = new Rect();

        //top margin
        srcPr.x       = srcPrTex.x;
        srcPr.y       = srcPrTex.y + 1 - 1f / tex.height;
        srcPr.width   = srcPrTex.width;
        srcPr.height  = 1f / tex.height;
        targPr.x      = r.x;
        targPr.y      = rPadded.y;
        targPr.width  = r.width;
        targPr.height = _padding;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        //bot margin
        srcPr.x       = srcPrTex.x;
        srcPr.y       = srcPrTex.y;
        srcPr.width   = srcPrTex.width;
        srcPr.height  = 1f / tex.height;
        targPr.x      = r.x;
        targPr.y      = r.y + r.height;
        targPr.width  = r.width;
        targPr.height = _padding;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);


        //left margin
        srcPr.x       = srcPrTex.x;
        srcPr.y       = srcPrTex.y;
        srcPr.width   = 1f / tex.width;
        srcPr.height  = srcPrTex.height;
        targPr.x      = rPadded.x;
        targPr.y      = r.y;
        targPr.width  = _padding;
        targPr.height = r.height;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        //right margin
        srcPr.x       = srcPrTex.x + 1f - 1f / tex.width;
        srcPr.y       = srcPrTex.y;
        srcPr.width   = 1f / tex.width;
        srcPr.height  = srcPrTex.height;
        targPr.x      = r.x + r.width;
        targPr.y      = r.y;
        targPr.width  = _padding;
        targPr.height = r.height;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);


        //top left corner
        srcPr.x       = srcPrTex.x;
        srcPr.y       = srcPrTex.y + 1 - 1f / tex.height;
        srcPr.width   = 1f / tex.width;
        srcPr.height  = 1f / tex.height;
        targPr.x      = rPadded.x;
        targPr.y      = rPadded.y;
        targPr.width  = _padding;
        targPr.height = _padding;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        //top right corner
        srcPr.x       = srcPrTex.x + 1f - 1f / tex.width;
        srcPr.y       = srcPrTex.y + 1 - 1f / tex.height;
        srcPr.width   = 1f / tex.width;
        srcPr.height  = 1f / tex.height;
        targPr.x      = r.x + r.width;
        targPr.y      = rPadded.y;
        targPr.width  = _padding;
        targPr.height = _padding;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        //bot left corner
        srcPr.x       = srcPrTex.x;
        srcPr.y       = srcPrTex.y;
        srcPr.width   = 1f / tex.width;
        srcPr.height  = 1f / tex.height;
        targPr.x      = rPadded.x;
        targPr.y      = r.y + r.height;
        targPr.width  = _padding;
        targPr.height = _padding;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        //bot right corner
        srcPr.x       = srcPrTex.x + 1f - 1f / tex.width;
        srcPr.y       = srcPrTex.y;
        srcPr.width   = 1f / tex.width;
        srcPr.height  = 1f / tex.height;
        targPr.x      = r.x + r.width;
        targPr.y      = r.y + r.height;
        targPr.width  = _padding;
        targPr.height = _padding;
        Graphics.DrawTexture(targPr, tex, srcPr, 0, 0, 0, 0, mat);

        //now the texture
        Graphics.DrawTexture(r, tex, srcPrTex, 0, 0, 0, 0, mat);

        tex.wrapMode = oldTexWrapMode;
    }
Example #9
0
        public static string ReportTextureSizesAndFormats(MB3_TextureBaker mom)
        {
            if (mom.resultType != MB2_TextureBakeResults.ResultType.textureArray)
            {
                Debug.LogError("Result Type must be Texture Array.");
                return("");
            }

            for (int resMatIdx = 0; resMatIdx < mom.resultMaterialsTexArray.Length; resMatIdx++)
            {
                MB_MultiMaterialTexArray resMatTexArray = mom.resultMaterialsTexArray[resMatIdx];
                if (resMatTexArray.combinedMaterial == null)
                {
                    Debug.LogError("Result Material " + resMatIdx + " is null");
                    return("");
                }
            }

            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            // Visit each result material
            for (int resMatIdx = 0; resMatIdx < mom.resultMaterialsTexArray.Length; resMatIdx++)
            {
                MB_MultiMaterialTexArray resMatTexArray = mom.resultMaterialsTexArray[resMatIdx];

                // Do an atlas pack in order to collect all the textures needed by the result material
                // And group these by material texture property.

                MB3_TextureCombiner combiner = mom.CreateAndConfigureTextureCombiner();
                combiner.saveAtlasesAsAssets = false;
                combiner.fixOutOfBoundsUVs   = false;
                List <AtlasPackingResult> packingResults = new List <AtlasPackingResult>();
                Material tempMat = new Material(resMatTexArray.combinedMaterial.shader);

                List <Material> allSourceMaterials = new List <Material>();
                for (int sliceIdx = 0; sliceIdx < resMatTexArray.slices.Count; sliceIdx++)
                {
                    List <Material> srcMats = new List <Material>();
                    resMatTexArray.slices[sliceIdx].GetAllUsedMaterials(srcMats);
                    for (int srcMatIdx = 0; srcMatIdx < srcMats.Count; srcMatIdx++)
                    {
                        if (srcMats[srcMatIdx] != null && !allSourceMaterials.Contains(srcMats[srcMatIdx]))
                        {
                            allSourceMaterials.Add(srcMats[srcMatIdx]);
                        }
                    }
                }

                MB_AtlasesAndRects atlasesAndRects = new MB_AtlasesAndRects();
                combiner.CombineTexturesIntoAtlases(null, atlasesAndRects, tempMat, mom.GetObjectsToCombine(), allSourceMaterials, null, packingResults,
                                                    onlyPackRects: true, splitAtlasWhenPackingIfTooBig: false);

                // Now vist the packing results and collect all the textures
                Debug.Assert(packingResults.Count == 1);
                for (int texPropIdx = 0; texPropIdx < atlasesAndRects.texPropertyNames.Length; texPropIdx++)
                {
                    string propertyName = atlasesAndRects.texPropertyNames[texPropIdx];
                    sb.AppendLine(String.Format("Prop: {0}", propertyName));

                    List <MB_MaterialAndUVRect> matsData    = (List <MB_MaterialAndUVRect>)packingResults[0].data;
                    HashSet <Material>          visitedMats = new HashSet <Material>();
                    for (int matAndGoIdx = 0; matAndGoIdx < matsData.Count; matAndGoIdx++)
                    {
                        Material mat = matsData[matAndGoIdx].material;
                        if (visitedMats.Contains(mat))
                        {
                            continue;
                        }
                        visitedMats.Add(mat);
                        if (mat.HasProperty(propertyName))
                        {
                            Texture tex = mat.GetTexture(propertyName);
                            if (tex != null)
                            {
                                string texFormatString = "UnknownFormat";
                                string texWrapMode     = "UnknownClampMode";
                                if (tex is Texture2D)
                                {
                                    texFormatString = ((Texture2D)tex).format.ToString();
                                    texWrapMode     = ((Texture2D)tex).wrapMode.ToString();
                                }

                                sb.AppendLine(String.Format("    {0} x {1}  format:{2}  wrapMode:{3}   {4}", tex.width.ToString().PadLeft(6, ' '), tex.height.ToString().PadRight(6, ' '), texFormatString.PadRight(20, ' '), texWrapMode.PadRight(12, ' '), tex.name));
                            }
                        }
                    }
                }
            }

            return(sb.ToString());
        }
Example #10
0
    MB_AtlasesAndRects[] _CreateAtlases(ProgressUpdateDelegate progressInfo, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null)
    {
        //validation
        if (saveAtlasesAsAssets && editorMethods == null)
        {
            Debug.LogError("Error in CreateAtlases If saveAtlasesAsAssets = true then editorMethods cannot be null.");
            return(null);
        }
        if (saveAtlasesAsAssets && !Application.isEditor)
        {
            Debug.LogError("Error in CreateAtlases If saveAtlasesAsAssets = true it must be called from the Unity Editor.");
            return(null);
        }
        if (!DoCombinedValidate(this, MB_ObjsToCombineTypes.dontCare, editorMethods))
        {
            return(null);
        }
        if (_doMultiMaterial && !_ValidateResultMaterials())
        {
            return(null);
        }
        else if (!_doMultiMaterial)
        {
            if (_resultMaterial == null)
            {
                Debug.LogError("Combined Material is null please create and assign a result material.");
                return(null);
            }
            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 2x2 clear textures will be generated.");
                    }
                }
            }
        }

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

        MB3_TextureCombiner combiner = new MB3_TextureCombiner();

        combiner.LOG_LEVEL                = LOG_LEVEL;
        combiner.atlasPadding             = _atlasPadding;
        combiner.customShaderPropNames    = _customShaderPropNames;
        combiner.fixOutOfBoundsUVs        = _fixOutOfBoundsUVs;
        combiner.maxTilingBakeSize        = _maxTilingBakeSize;
        combiner.packingAlgorithm         = _packingAlgorithm;
        combiner.resizePowerOfTwoTextures = _resizePowerOfTwoTextures;
        combiner.saveAtlasesAsAssets      = saveAtlasesAsAssets;

        // if editor analyse meshes and suggest treatment
        if (!Application.isPlaying)
        {
            Material[] rms;
            if (_doMultiMaterial)
            {
                rms = new Material[resultMaterials.Length];
                for (int i = 0; i < rms.Length; i++)
                {
                    rms[i] = resultMaterials[i].combinedMaterial;
                }
            }
            else
            {
                rms    = new Material[1];
                rms[0] = _resultMaterial;
            }
            combiner.SuggestTreatment(objsToMesh, rms, combiner.customShaderPropNames);
        }

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

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

        //Do the material combining.
        for (int i = 0; i < resultAtlasesAndRects.Length; i++)
        {
            Material        resMatToPass = null;
            List <Material> sourceMats   = null;
            if (_doMultiMaterial)
            {
                sourceMats   = resultMaterials[i].sourceMaterials;
                resMatToPass = resultMaterials[i].combinedMaterial;
            }
            else
            {
                resMatToPass = _resultMaterial;
            }
            Debug.Log("Creating atlases for result material " + resMatToPass);
            if (!combiner.CombineTexturesIntoAtlases(progressInfo, resultAtlasesAndRects[i], resMatToPass, objsToMesh, sourceMats, editorMethods))
            {
                return(null);
            }
        }

        //Save the results
        textureBakeResults.combinedMaterialInfo = resultAtlasesAndRects;
        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
        MB3_MeshBakerCommon mb = GetComponent <MB3_MeshBakerCommon>();

        if (mb != null)
        {
            mb.textureBakeResults = textureBakeResults;
        }

        if (LOG_LEVEL >= MB2_LogLevel.info)
        {
            Debug.Log("Created Atlases");
        }
        return(resultAtlasesAndRects);
    }
    public Texture2D DoRenderAtlas(GameObject gameObject, int width, int height, int padding, Rect[] rss, List <MB3_TextureCombiner.MB_TexSet> textureSetss, int indexOfTexSetToRenders, bool isNormalMap, bool fixOutOfBoundsUVs, MB3_TextureCombiner texCombiner, MB2_LogLevel LOG_LEV)
    {
        this.LOG_LEVEL             = LOG_LEV;
        this.textureSets           = textureSetss;
        this.indexOfTexSetToRender = indexOfTexSetToRenders;
        this._padding           = padding;
        this._isNormalMap       = isNormalMap;
        this._fixOutOfBoundsUVs = fixOutOfBoundsUVs;
        this.combiner           = texCombiner;
        this.rs = rss;
        Shader shader;

        if (this._isNormalMap)
        {
            shader = Shader.Find("MeshBaker/NormalMapShader");
        }
        else
        {
            shader = Shader.Find("MeshBaker/AlbedoShader");
        }
        if (shader == null)
        {
            UnityEngine.Debug.LogError("Could not find shader for RenderTexture. Try reimporting mesh baker");
            return(null);
        }
        this.mat = new Material(shader);
        this._destinationTexture            = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32);
        this._destinationTexture.filterMode = FilterMode.Point;
        this.myCamera = gameObject.GetComponent <Camera>();
        this.myCamera.orthographic     = true;
        this.myCamera.orthographicSize = (float)(height >> 1);
        this.myCamera.aspect           = (float)(width / height);
        this.myCamera.targetTexture    = this._destinationTexture;
        this.myCamera.clearFlags       = CameraClearFlags.Color;
        Transform component = this.myCamera.GetComponent <Transform>();

        component.localPosition = new Vector3((float)width / 2f, (float)height / 2f, 3f);
        component.localRotation = Quaternion.Euler(0f, 180f, 180f);
        this._doRenderAtlas     = true;
        if (this.LOG_LEVEL >= MB2_LogLevel.debug)
        {
            UnityEngine.Debug.Log(string.Format("Begin Camera.Render destTex w={0} h={1} camPos={2}", width, height, component.localPosition));
        }
        this.myCamera.Render();
        this._doRenderAtlas = false;
        MB_Utility.Destroy(this.mat);
        MB_Utility.Destroy(this._destinationTexture);
        if (this.LOG_LEVEL >= MB2_LogLevel.debug)
        {
            UnityEngine.Debug.Log("Finished Camera.Render ");
        }
        Texture2D result = this.targTex;

        this.targTex = null;
        return(result);
    }
Example #12
0
        //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, 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);
        }
Example #13
0
    private MB_AtlasesAndRects[] _CreateAtlases(ProgressUpdateDelegate progressInfo, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null)
    {
        if (saveAtlasesAsAssets && editorMethods == null)
        {
            Debug.LogError("Error in CreateAtlases If saveAtlasesAsAssets = true then editorMethods cannot be null.");
            return(null);
        }
        if (saveAtlasesAsAssets && !Application.isEditor)
        {
            Debug.LogError("Error in CreateAtlases If saveAtlasesAsAssets = true it must be called from the Unity Editor.");
            return(null);
        }
        MB2_ValidationLevel validationLevel = (!Application.isPlaying) ? MB2_ValidationLevel.robust : MB2_ValidationLevel.quick;

        if (!MB3_MeshBakerRoot.DoCombinedValidate(this, MB_ObjsToCombineTypes.dontCare, editorMethods, validationLevel))
        {
            return(null);
        }
        if (this._doMultiMaterial && !this._ValidateResultMaterials())
        {
            return(null);
        }
        if (!this._doMultiMaterial)
        {
            if (this._resultMaterial == null)
            {
                Debug.LogError("Combined Material is null please create and assign a result material.");
                return(null);
            }
            Shader shader = this._resultMaterial.shader;
            for (int i = 0; i < this.objsToMesh.Count; i++)
            {
                foreach (Material material in MB_Utility.GetGOMaterials(this.objsToMesh[i]))
                {
                    if (material != null && material.shader != shader)
                    {
                        Debug.LogWarning(string.Concat(new object[]
                        {
                            "Game object ",
                            this.objsToMesh[i],
                            " does not use shader ",
                            shader,
                            " it may not have the required textures. If not 2x2 clear textures will be generated."
                        }));
                    }
                }
            }
        }
        for (int k = 0; k < this.objsToMesh.Count; k++)
        {
            foreach (Material x in MB_Utility.GetGOMaterials(this.objsToMesh[k]))
            {
                if (x == null)
                {
                    Debug.LogError("Game object " + this.objsToMesh[k] + " has a null material. Can't build atlases");
                    return(null);
                }
            }
        }
        MB3_TextureCombiner mb3_TextureCombiner = new MB3_TextureCombiner();

        mb3_TextureCombiner.LOG_LEVEL             = this.LOG_LEVEL;
        mb3_TextureCombiner.atlasPadding          = this._atlasPadding;
        mb3_TextureCombiner.maxAtlasSize          = this._maxAtlasSize;
        mb3_TextureCombiner.customShaderPropNames = this._customShaderProperties;
        mb3_TextureCombiner.fixOutOfBoundsUVs     = this._fixOutOfBoundsUVs;
        mb3_TextureCombiner.maxTilingBakeSize     = this._maxTilingBakeSize;
        mb3_TextureCombiner.packingAlgorithm      = this._packingAlgorithm;
        mb3_TextureCombiner.meshBakerTexturePackerForcePowerOfTwo = this._meshBakerTexturePackerForcePowerOfTwo;
        mb3_TextureCombiner.resizePowerOfTwoTextures = this._resizePowerOfTwoTextures;
        mb3_TextureCombiner.saveAtlasesAsAssets      = saveAtlasesAsAssets;
        if (!Application.isPlaying)
        {
            Material[] array;
            if (this._doMultiMaterial)
            {
                array = new Material[this.resultMaterials.Length];
                for (int m = 0; m < array.Length; m++)
                {
                    array[m] = this.resultMaterials[m].combinedMaterial;
                }
            }
            else
            {
                array = new Material[]
                {
                    this._resultMaterial
                };
            }
            mb3_TextureCombiner.SuggestTreatment(this.objsToMesh, array, mb3_TextureCombiner.customShaderPropNames);
        }
        int num = 1;

        if (this._doMultiMaterial)
        {
            num = this.resultMaterials.Length;
        }
        MB_AtlasesAndRects[] array2 = new MB_AtlasesAndRects[num];
        for (int n = 0; n < array2.Length; n++)
        {
            array2[n] = new MB_AtlasesAndRects();
        }
        for (int num2 = 0; num2 < array2.Length; num2++)
        {
            List <Material> allowedMaterialsFilter = null;
            Material        material2;
            if (this._doMultiMaterial)
            {
                allowedMaterialsFilter = this.resultMaterials[num2].sourceMaterials;
                material2 = this.resultMaterials[num2].combinedMaterial;
            }
            else
            {
                material2 = this._resultMaterial;
            }
            Debug.Log("Creating atlases for result material " + material2);
            if (!mb3_TextureCombiner.CombineTexturesIntoAtlases(progressInfo, array2[num2], material2, this.objsToMesh, allowedMaterialsFilter, editorMethods))
            {
                return(null);
            }
        }
        this.textureBakeResults.combinedMaterialInfo = array2;
        this.textureBakeResults.doMultiMaterial      = this._doMultiMaterial;
        this.textureBakeResults.resultMaterial       = this._resultMaterial;
        this.textureBakeResults.resultMaterials      = this.resultMaterials;
        this.textureBakeResults.fixOutOfBoundsUVs    = mb3_TextureCombiner.fixOutOfBoundsUVs;
        this.unpackMat2RectMap(this.textureBakeResults);
        MB3_MeshBakerCommon[] componentsInChildren = base.GetComponentsInChildren <MB3_MeshBakerCommon>();
        for (int num3 = 0; num3 < componentsInChildren.Length; num3++)
        {
            componentsInChildren[num3].textureBakeResults = this.textureBakeResults;
        }
        if (this.LOG_LEVEL >= MB2_LogLevel.info)
        {
            Debug.Log("Created Atlases");
        }
        return(array2);
    }
Example #14
0
        public static void ConfigureTextureArraysFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterialsTexArrays, SerializedObject textureBaker)
        {
            if (mom.GetObjectsToCombine().Count == 0)
            {
                Debug.LogError("You need to add some objects to combine before building the texture array result materials.");
                return;
            }
            if (resultMaterialsTexArrays.arraySize > 0)
            {
                Debug.LogError("You already have some texture array result materials 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;
                }

                if (MB_Utility.GetMesh(go) == null)
                {
                    Debug.LogError("Could not get mesh for 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;
                }
            }

            //Will sort into "result material"
            //  slices
            Dictionary <MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo, List <Slice> > shader2ResultMat_map = new Dictionary <MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo, List <Slice> >();

            // first pass split by shader and analyse meshes.
            List <GameObject> objsToCombine = mom.GetObjectsToCombine();

            for (int meshIdx = 0; meshIdx < objsToCombine.Count; meshIdx++)
            {
                GameObject srcGo = objsToCombine[meshIdx];
                Mesh       mesh  = MB_Utility.GetMesh(srcGo);
                Renderer   r     = MB_Utility.GetRenderer(srcGo);

                if (mom.LOG_LEVEL >= MB2_LogLevel.trace)
                {
                    Debug.Log("1st Pass 'Split By Shader' Processing Mesh: " + mesh + " Num submeshes: " + r.sharedMaterials.Length);
                }
                for (int submeshIdx = 0; submeshIdx < r.sharedMaterials.Length; submeshIdx++)
                {
                    if (r.sharedMaterials[submeshIdx] == null)
                    {
                        continue;
                    }

                    MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo newKey = new MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo(r.sharedMaterials[submeshIdx].shader, r.sharedMaterials[submeshIdx]);
                    // Initially we fill the list of srcMaterials with garbage MB_MaterialAndUVRects. Will get proper ones when we atlas pack.
                    MB_MaterialAndUVRect submeshMaterial = new MB_MaterialAndUVRect(
                        r.sharedMaterials[submeshIdx],
                        new Rect(0, 0, 0, 0),              // garbage value
                        false,                             //garbage value
                        new Rect(0, 0, 0, 0),              // garbage value
                        new Rect(0, 0, 0, 0),              // garbage value
                        new Rect(0, 0, 1, 1),              // garbage value
                        MB_TextureTilingTreatment.unknown, // garbage value
                        r.name);
                    submeshMaterial.objectsThatUse = new List <GameObject>();
                    submeshMaterial.objectsThatUse.Add(r.gameObject);
                    if (!shader2ResultMat_map.ContainsKey(newKey))
                    {
                        // this is a new shader create a new result material
                        Slice srcMaterials = new Slice
                        {
                            atlasRects    = new List <MB_MaterialAndUVRect>(),
                            numAtlasRects = 1,
                        };
                        srcMaterials.atlasRects.Add(submeshMaterial);
                        List <Slice> binsOfMatsThatUseShader = new List <Slice>();
                        binsOfMatsThatUseShader.Add(srcMaterials);
                        if (mom.LOG_LEVEL >= MB2_LogLevel.trace)
                        {
                            Debug.Log("  Adding Source Material: " + submeshMaterial.material);
                        }
                        shader2ResultMat_map.Add(newKey, binsOfMatsThatUseShader);
                    }
                    else
                    {
                        // there is a result material that uses this shader. Add this source material
                        Slice srcMaterials = shader2ResultMat_map[newKey][0]; // There should only be one list of source materials
                        if (srcMaterials.atlasRects.Find(x => x.material == submeshMaterial.material) == null)
                        {
                            if (mom.LOG_LEVEL >= MB2_LogLevel.trace)
                            {
                                Debug.Log("  Adding Source Material: " + submeshMaterial.material);
                            }
                            srcMaterials.atlasRects.Add(submeshMaterial);
                        }
                    }
                }
            }

            int resMatCount = 0;

            foreach (MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo resultMat in shader2ResultMat_map.Keys)
            {
                // at this point there there should be only one slice with all the source materials
                resMatCount++;

                // For each result material, all source materials are in the first slice.
                // We will now split these using a texture packer. Each "atlas" generated by the packer will be a slice.
                {
                    // All source materials should be in the first slice at this point.
                    List <Slice>      slices                = shader2ResultMat_map[resultMat];
                    List <Slice>      newSlices             = new List <Slice>();
                    Slice             firstSlice            = slices[0];
                    List <Material>   allMatsThatUserShader = new List <Material>();
                    List <GameObject> objsThatUseFirstSlice = new List <GameObject>();
                    for (int i = 0; i < firstSlice.atlasRects.Count; i++)
                    {
                        allMatsThatUserShader.Add(firstSlice.atlasRects[i].material);
                        if (!objsThatUseFirstSlice.Contains(firstSlice.atlasRects[i].objectsThatUse[0]))
                        {
                            objsThatUseFirstSlice.Add(firstSlice.atlasRects[i].objectsThatUse[0]);
                        }
                    }

                    MB3_TextureCombiner combiner = mom.CreateAndConfigureTextureCombiner();
                    combiner.packingAlgorithm    = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
                    combiner.saveAtlasesAsAssets = false;
                    combiner.fixOutOfBoundsUVs   = true;
                    combiner.doMergeDistinctMaterialTexturesThatWouldExceedAtlasSize = true;
                    List <AtlasPackingResult> packingResults = new List <AtlasPackingResult>();
                    Material tempMat = new Material(resultMat.shader);

                    if (mom.LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("======== 2nd pass. Use atlas packer to split the first slice into multiple if it exceeds atlas size. ");
                    }
                    combiner.CombineTexturesIntoAtlases(null, null, tempMat, mom.GetObjectsToCombine(), allMatsThatUserShader, null, packingResults,
                                                        onlyPackRects: true, splitAtlasWhenPackingIfTooBig: true);
                    if (mom.LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("======== Completed packing with texture packer. numPackingResults: " + packingResults.Count);
                    }
                    newSlices.Clear();

                    // The texture packing just split the atlas into multiple atlases. Each atlas will become a "slice".
                    for (int newSliceIdx = 0; newSliceIdx < packingResults.Count; newSliceIdx++)
                    {
                        List <MB_MaterialAndUVRect> sourceMats     = new List <MB_MaterialAndUVRect>();
                        List <MB_MaterialAndUVRect> packedMatRects = (List <MB_MaterialAndUVRect>)packingResults[newSliceIdx].data;
                        HashSet <Rect> distinctAtlasRects          = new HashSet <Rect>();
                        for (int packedMatRectIdx = 0; packedMatRectIdx < packedMatRects.Count; packedMatRectIdx++)
                        {
                            MB_MaterialAndUVRect muvr = packedMatRects[packedMatRectIdx];
                            distinctAtlasRects.Add(muvr.atlasRect);
                            {
                                Rect    encapsulatingRect = muvr.GetEncapsulatingRect();
                                Vector2 sizeInAtlas_px    = new Vector2(
                                    packingResults[newSliceIdx].atlasX * encapsulatingRect.width,
                                    packingResults[newSliceIdx].atlasY * encapsulatingRect.height);
                            }
                            sourceMats.Add(muvr);
                        }

                        Slice slice = new Slice()
                        {
                            atlasRects    = sourceMats,
                            packingResult = packingResults[newSliceIdx],
                            numAtlasRects = distinctAtlasRects.Count,
                        };

                        newSlices.Add(slice);
                    }

                    // Replace first slice with split version.
                    if (mom.LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("First slice exceeded atlas size splitting it into " + newSlices.Count + " slices");
                    }
                    slices.RemoveAt(0);
                    for (int i = 0; i < newSlices.Count; i++)
                    {
                        slices.Insert(i, newSlices[i]);
                    }
                }
            }

            // build the texture array result materials
            if (shader2ResultMat_map.Count == 0)
            {
                Debug.LogError("Found no materials in list of objects to combine");
            }
            mom.resultMaterialsTexArray = new MB_MultiMaterialTexArray[shader2ResultMat_map.Count];
            int k = 0;

            foreach (MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo resMatKey in shader2ResultMat_map.Keys)
            {
                List <Slice>             srcSlices = shader2ResultMat_map[resMatKey];
                MB_MultiMaterialTexArray mm        = mom.resultMaterialsTexArray[k] = new MB_MultiMaterialTexArray();
                for (int sliceIdx = 0; sliceIdx < srcSlices.Count; sliceIdx++)
                {
                    Slice            slice    = srcSlices[sliceIdx];
                    MB_TexArraySlice resSlice = new MB_TexArraySlice();
                    List <Material>  usedMats = new List <Material>();

                    for (int srcMatIdx = 0; srcMatIdx < slice.atlasRects.Count; srcMatIdx++)
                    {
                        MB_MaterialAndUVRect matAndUVRect = slice.atlasRects[srcMatIdx];
                        List <GameObject>    objsThatUse  = matAndUVRect.objectsThatUse;
                        for (int objsThatUseIdx = 0; objsThatUseIdx < objsThatUse.Count; objsThatUseIdx++)
                        {
                            GameObject obj = objsThatUse[objsThatUseIdx];
                            if (!resSlice.ContainsMaterialAndMesh(slice.atlasRects[srcMatIdx].material, MB_Utility.GetMesh(obj)))
                            {
                                resSlice.sourceMaterials.Add(
                                    new MB_TexArraySliceRendererMatPair()
                                {
                                    renderer       = obj,
                                    sourceMaterial = slice.atlasRects[srcMatIdx].material
                                }
                                    );
                            }
                        }
                    }

                    {
                        // Should we use considerUVs
                        bool doConsiderUVs = false;
                        //     If there is more than one atlas rectangle in a slice then use considerUVs
                        if (slice.numAtlasRects > 1)
                        {
                            doConsiderUVs = true;
                        }
                        else
                        {
                            //     There is only one source material, could be:
                            //          - lots of tiling (don't want consider UVs)
                            //          - We are extracting a small part of a large atlas (want considerUVs)
                            if (slice.packingResult.atlasX >= mom.maxAtlasSize ||
                                slice.packingResult.atlasY >= mom.maxAtlasSize)
                            {
                                doConsiderUVs = false; // lots of tiling
                            }
                            else
                            {
                                doConsiderUVs = true; // extracting a small part of an atlas
                            }
                        }

                        resSlice.considerMeshUVs = doConsiderUVs;
                    }

                    mm.slices.Add(resSlice);
                }

                // Enforce integrity. If a material appears in more than one slice then all those slices must be considerUVs=true
                {
                    // collect all distinct materials
                    HashSet <Material>         distinctMats   = new HashSet <Material>();
                    Dictionary <Material, int> mat2sliceCount = new Dictionary <Material, int>();
                    for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
                    {
                        for (int sliceMatIdx = 0; sliceMatIdx < mm.slices[sliceIdx].sourceMaterials.Count; sliceMatIdx++)
                        {
                            Material mat = mm.slices[sliceIdx].sourceMaterials[sliceMatIdx].sourceMaterial;
                            distinctMats.Add(mat);
                            mat2sliceCount[mat] = 0;
                        }
                    }

                    // Count the number of slices that use each material.
                    foreach (Material mat in distinctMats)
                    {
                        for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
                        {
                            if (mm.slices[sliceIdx].ContainsMaterial(mat))
                            {
                                mat2sliceCount[mat] = mat2sliceCount[mat] + 1;
                            }
                        }
                    }

                    // Check that considerUVs is true for any materials that appear more than once
                    foreach (Material mat in distinctMats)
                    {
                        if (mat2sliceCount[mat] > 1)
                        {
                            for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
                            {
                                if (mm.slices[sliceIdx].ContainsMaterial(mat))
                                {
                                    if (mom.LOG_LEVEL >= MB2_LogLevel.debug &&
                                        mm.slices[sliceIdx].considerMeshUVs)
                                    {
                                        Debug.Log("There was a material " + mat + " that was used by more than one slice and considerUVs was false. sliceIdx:" + sliceIdx);
                                    }
                                    mm.slices[sliceIdx].considerMeshUVs = true;
                                }
                            }
                        }
                    }
                }

                // Cleanup. remove "Renderer"s from source materials that do not use considerUVs and delete extra
                {
                    // put any slices with consider UVs first
                    List <MB_TexArraySlice> newSlices = new List <MB_TexArraySlice>();
                    for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
                    {
                        if (mm.slices[sliceIdx].considerMeshUVs == true)
                        {
                            newSlices.Add(mm.slices[sliceIdx]);
                        }
                    }

                    // for any slices without considerUVs, remove "renderer" and truncate
                    for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
                    {
                        MB_TexArraySlice slice = mm.slices[sliceIdx];
                        if (slice.considerMeshUVs == false)
                        {
                            newSlices.Add(slice);
                            HashSet <Material> distinctMats = slice.GetDistinctMaterials();
                            slice.sourceMaterials.Clear();
                            foreach (Material mat in distinctMats)
                            {
                                slice.sourceMaterials.Add(new MB_TexArraySliceRendererMatPair()
                                {
                                    sourceMaterial = mat
                                });
                            }
                        }
                    }

                    mm.slices = newSlices;
                }

                string   pth           = AssetDatabase.GetAssetPath(mom.textureBakeResults);
                string   baseName      = Path.GetFileNameWithoutExtension(pth);
                string   folderPath    = pth.Substring(0, pth.Length - baseName.Length - 6);
                string   matName       = folderPath + baseName + "-mat" + k + ".mat";
                Material existingAsset = AssetDatabase.LoadAssetAtPath <Material>(matName);
                if (!existingAsset)
                {
                    Material newMat = new Material(Shader.Find("Standard"));
                    // Don't try to configure the material we need the user to pick a shader that has TextureArrays
                    AssetDatabase.CreateAsset(newMat, matName);
                }

                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }


            MBVersionEditor.UpdateIfDirtyOrScript(textureBaker);
            textureBaker.Update();
        }
Example #15
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");
            yield return(null);
        }
        this.OnCombinedTexturesCoroutineAtlasesAndRects = null;
        //if (!Application.isPlaying)
        //{
        //    Debug.LogError("CombineTexturesIntoAtlasesCoroutine should only be called when the game is running. Use CombineTexturesIntoAtlases in the editor.");
        //    _CreateAtlasesCoroutineIsFinished = true;
        //    yield break;
        //}
        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.");
                    }
                }
            }
        }

        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");
                    coroutineResult.isFinished = true;
                    yield break;
                }
            }
        }

        MB3_TextureCombiner combiner = new MB3_TextureCombiner();

        combiner.LOG_LEVEL             = LOG_LEVEL;
        combiner.atlasPadding          = _atlasPadding;
        combiner.maxAtlasSize          = _maxAtlasSize;
        combiner.customShaderPropNames = _customShaderProperties;
        combiner.fixOutOfBoundsUVs     = _fixOutOfBoundsUVs;
        combiner.maxTilingBakeSize     = _maxTilingBakeSize;
        combiner.packingAlgorithm      = _packingAlgorithm;
        combiner.meshBakerTexturePackerForcePowerOfTwo = _meshBakerTexturePackerForcePowerOfTwo;
        combiner.resizePowerOfTwoTextures     = _resizePowerOfTwoTextures;
        combiner.saveAtlasesAsAssets          = saveAtlasesAsAssets;
        combiner.considerNonTextureProperties = _considerNonTextureProperties;

        //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;
            }
            else
            {
                resMatToPass = _resultMaterial;
            }
            Debug.Log(string.Format("Creating atlases for result material {0} using shader {1}", resMatToPass, resMatToPass.shader));
            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;
            }
        }

        //Save the results
        textureBakeResults.combinedMaterialInfo = OnCombinedTexturesCoroutineAtlasesAndRects;
        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
        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();
        }
    }
Example #16
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();
        }
    }
        public static Dictionary <GameObjectFilterInfo, List <List <GameObjectFilterInfo> > > sortIntoBakeGroups3(List <GameObjectFilterInfo> gameObjects, List <GameObjectFilterInfo> objsNotAddedToBaker, IGroupByFilter[] filters, bool splitAtlasesSoMeshesFit, int atlasSize)
        {
            Dictionary <GameObjectFilterInfo, List <List <GameObjectFilterInfo> > > gs2bakeGroupMap = new Dictionary <GameObjectFilterInfo, List <List <GameObjectFilterInfo> > >();

            List <GameObjectFilterInfo> gos = gameObjects;

            if (gos.Count < 1)
            {
                return(gs2bakeGroupMap);
            }

            gos.Sort();
            List <List <GameObjectFilterInfo> > l = null;
            GameObjectFilterInfo key = gos[0];

            for (int i = 0; i < gos.Count; i++)
            {
                GameObjectFilterInfo goaw = gos[i];
                //compare with key and decide if we need a new list
                for (int j = 0; j < filters.Length; j++)
                {
                    if (filters[j] != null && filters[j].Compare(key, goaw) != 0)
                    {
                        l = null;
                    }
                }
                if (l == null)
                {
                    l = new List <List <GameObjectFilterInfo> >();
                    l.Add(new List <GameObjectFilterInfo>());
                    gs2bakeGroupMap.Add(gos[i], l);
                    key = gos[i];
                }
                l[0].Add(gos[i]);
            }

            //now that objects have been grouped by the sort criteria we can see how many atlases are needed
            Dictionary <GameObjectFilterInfo, List <List <GameObjectFilterInfo> > > gs2bakeGroupMap2 = new Dictionary <GameObjectFilterInfo, List <List <GameObjectFilterInfo> > >();

            if (splitAtlasesSoMeshesFit)
            {
                foreach (GameObjectFilterInfo k in gs2bakeGroupMap.Keys)
                {
                    List <GameObjectFilterInfo> vs          = gs2bakeGroupMap[k][0];
                    List <GameObject>           objsInGroup = new List <GameObject>();
                    for (int i = 0; i < vs.Count; i++)
                    {
                        objsInGroup.Add(vs[i].go);
                    }
                    MB3_TextureCombiner tc = new MB3_TextureCombiner();
                    tc.maxAtlasSize     = atlasSize;
                    tc.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
                    tc.LOG_LEVEL        = MB2_LogLevel.warn;
                    List <AtlasPackingResult> packingResults = new List <AtlasPackingResult>();
                    Material           tempResMat            = k.materials[0];//we don't write to the materials so can use this as the result material
                    MB_AtlasesAndRects tempAtlasesAndRects   = new MB_AtlasesAndRects();
                    if (tc.CombineTexturesIntoAtlases(null, tempAtlasesAndRects, tempResMat, objsInGroup, null, null, packingResults,
                                                      onlyPackRects:true, splitAtlasWhenPackingIfTooBig:false))
                    {
                        List <List <GameObjectFilterInfo> > atlasGroups = new List <List <GameObjectFilterInfo> >();
                        for (int i = 0; i < packingResults.Count; i++)
                        {
                            List <GameObjectFilterInfo> ngos     = new List <GameObjectFilterInfo>();
                            List <MB_MaterialAndUVRect> matsData = (List <MB_MaterialAndUVRect>)packingResults[i].data;
                            for (int j = 0; j < matsData.Count; j++)
                            {
                                for (int kk = 0; kk < matsData[j].objectsThatUse.Count; kk++)
                                {
                                    GameObjectFilterInfo gofi = vs.Find(x => x.go == matsData[j].objectsThatUse[kk]);
                                    //Debug.Assert(gofi != null);
                                    ngos.Add(gofi);
                                }
                            }
                            ngos[0].atlasIndex = (short)i;
                            atlasGroups.Add(ngos);
                        }
                        gs2bakeGroupMap2.Add(k, atlasGroups);
                    }
                    else
                    {
                        gs2bakeGroupMap2.Add(k, gs2bakeGroupMap[k]);
                    }
                }
            }
            else
            {
                gs2bakeGroupMap2 = gs2bakeGroupMap;
            }
            return(gs2bakeGroupMap2);
        }