Example #1
0
 public MeshBakerMaterialTexture(Texture tx, Vector2 o, Vector2 s, float texelDens)
 {
     if (tx is Texture2D)
     {
         _t = (Texture2D)tx;
     }
     //else if (tx is ProceduralTexture)
     //{
     //    _procT = (ProceduralTexture)tx;
     //}
     else if (tx == null)
     {
         //do nothing
     }
     else
     {
         Debug.LogError("An error occured. Texture must be Texture2D " + tx);
     }
     matTilingRect = new DRect(o, s);
     texelDensity  = texelDens;
 }
        internal void CalcMatAndUVSamplingRects()
        {
            DRect matTiling = new DRect(0f, 0f, 1f, 1f);

            if (allTexturesUseSameMatTiling)
            {
                for (int propIdx = 0; propIdx < ts.Length; propIdx++)
                {
                    if (!ts[propIdx].isNull)
                    {
                        matTiling = ts[propIdx].matTilingRect;
                        break;
                    }
                }
            }

            for (int matIdx = 0; matIdx < matsAndGOs.mats.Count; matIdx++)
            {
                matsAndGOs.mats[matIdx].AssignInitialValuesForMaterialTilingAndSamplingRectMatAndUVTiling(allTexturesUseSameMatTiling, matTiling);
            }
        }
        /*
         * public MeshBakerMaterialTexture() { }
         * public MeshBakerMaterialTexture(Texture tx)
         * {
         *  if (tx is Texture2D)
         *  {
         *      _t = (Texture2D)tx;
         *  }
         *  //else if (tx is ProceduralTexture)
         *  //{
         *  //    _procT = (ProceduralTexture)tx;
         *  //}
         *  else if (tx == null)
         *  {
         *      //do nothing
         *  }
         *  else
         *  {
         *      Debug.LogError("An error occured. Texture must be Texture2D " + tx);
         *  }
         * }
         */

        public MeshBakerMaterialTexture(Texture tx, Vector2 matTilingOffset, Vector2 matTilingScale, float texelDens, int isImportedAsNormalMap)
        {
            if (tx is Texture2D)
            {
                _t = (Texture2D)tx;
            }
            //else if (tx is ProceduralTexture)
            //{
            //    _procT = (ProceduralTexture)tx;
            //}
            else if (tx == null)
            {
                //do nothing
            }
            else
            {
                Debug.LogError("An error occured. Texture must be Texture2D " + tx);
            }
            matTilingRect = new DRect(matTilingOffset, matTilingScale);
            texelDensity  = texelDens;
            this.isImportedAsNormalMap = isImportedAsNormalMap;
        }
Example #4
0
        //assumes all materials use the same obUVrects.
        internal void CalcInitialFullSamplingRects(bool fixOutOfBoundsUVs)
        {
            DRect validFullSamplingRect = new Core.DRect(0, 0, 1, 1);

            if (fixOutOfBoundsUVs)
            {
                validFullSamplingRect = obUVrect;
            }

            for (int propIdx = 0; propIdx < ts.Length; propIdx++)
            {
                if (!ts[propIdx].isNull)
                {
                    DRect matTiling = ts[propIdx].matTilingRect;
                    DRect ruv;
                    if (fixOutOfBoundsUVs)
                    {
                        ruv = obUVrect;
                    }
                    else
                    {
                        ruv = new DRect(0.0, 0.0, 1.0, 1.0);
                    }

                    ts[propIdx].SetEncapsulatingSamplingRect(this, MB3_UVTransformUtility.CombineTransforms(ref ruv, ref matTiling));
                    validFullSamplingRect = ts[propIdx].GetEncapsulatingSamplingRect();
                }
            }

            //if some of the textures were null make them match the sampling of one of the other textures
            for (int propIdx = 0; propIdx < ts.Length; propIdx++)
            {
                if (ts[propIdx].isNull)
                {
                    ts[propIdx].SetEncapsulatingSamplingRect(this, validFullSamplingRect);
                }
            }
        }
Example #5
0
 /*
 public void SetMaterialTilingTo0011()
 {
     matTilingRect = new DRect(0, 0, 1, 1);
 }
 */
 /// <summary>
 /// The ts variable serves no functional purpose. I would like this method to ONLY be called from 
 /// MB_TexSet but there is no way in C# to enforce that. If you want to use this 
 /// outside  of MB_TexSet then add a method to MB_TexSet that does the add on your 
 /// behalf. The new method should assert that MB_TexSet is in the correct state and should 
 /// do any necessary stated changes to MB_TexSet depending on the context.
 /// 
 /// After you are done you should "FindAllReferences" for this function to ensure that it is only
 /// called by MB_TexSet.
 /// </summary>
 /// <param name="ts">
 /// Not used, provided as an indicator to developers that all
 /// access to this must go through MB_TexSet.
 /// </param>
 public void SetEncapsulatingSamplingRect(MB_TexSet ts, DRect r)
 {
     encapsulatingSamplingRect = r;
 }
Example #6
0
        public void AssignInitialValuesForMaterialTilingAndSamplingRectMatAndUVTiling(bool allTexturesUseSameMatTiling, DRect matTiling)
        {
            if (allTexturesUseSameMatTiling)
            {
                materialTiling = matTiling;

            }
            else
            {
                materialTiling = new DRect(0f, 0f, 1f, 1f);
            }
            DRect tmpMatTiling = materialTiling;
            DRect obUVrect = obUVRectIfTilingSame;
            samplingRectMatAndUVTiling = MB3_UVTransformUtility.CombineTransforms(ref obUVrect, ref tmpMatTiling);
        }
Example #7
0
 public void SetEncapsulatingSamplingRectForTesting(int propIdx, DRect newEncapsulatingSamplingRect)
 {
     ts[propIdx].SetEncapsulatingSamplingRect(this, newEncapsulatingSamplingRect);
 }
Example #8
0
 public MatAndTransformToMerged(DRect obUVrect, bool fixOutOfBoundsUVs, Material m)
 {
     _init(obUVrect, fixOutOfBoundsUVs, m);
 }
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Rect[] uvRects = packedAtlasRects.rects;
            if (uvRects.Length == 1)
            {
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Only one image per atlas. Will re-use original texture");
                }
                for (int i = 0; i < data.numAtlases; i++)
                {
                    MeshBakerMaterialTexture dmt = data.distinctMaterialTextures[0].ts[i];
                    atlases[i] = dmt.GetTexture2D();
                    data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, dmt.matTilingRect.size);
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, dmt.matTilingRect.min);
                }
            }
            else
            {
                int atlasSizeX = packedAtlasRects.atlasX;
                int atlasSizeY = packedAtlasRects.atlasY;
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
                }
                for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
                {
                    Texture2D atlas = null;
                    if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                    {
                        atlas = null;
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("=== Not creating atlas for " + data.texPropertyNames[propIdx].name + " because textures are null and default value parameters are the same.");
                        }
                    }
                    else
                    {
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("=== Creating atlas for " + data.texPropertyNames[propIdx].name);
                        }
                        GC.Collect();

                        //use a jagged array because it is much more efficient in memory
                        Color[][] atlasPixels = new Color[atlasSizeY][];
                        for (int j = 0; j < atlasPixels.Length; j++)
                        {
                            atlasPixels[j] = new Color[atlasSizeX];
                        }
                        bool isNormalMap = false;
                        if (data.texPropertyNames[propIdx].isNormalMap)
                        {
                            isNormalMap = true;
                        }

                        for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++)
                        {
                            string s = "Creating Atlas '" + data.texPropertyNames[propIdx].name + "' texture " + data.distinctMaterialTextures[texSetIdx];
                            if (progressInfo != null)
                            {
                                progressInfo(s, .01f);
                            }
                            MB_TexSet texSet = data.distinctMaterialTextures[texSetIdx];
                            if (LOG_LEVEL >= MB2_LogLevel.trace)
                            {
                                Debug.Log(string.Format("Adding texture {0} to atlas {1}", texSet.ts[propIdx].GetTexture2D() == null ? "null" : texSet.ts[propIdx].GetTexName(), data.texPropertyNames[propIdx]));
                            }
                            Rect      r  = uvRects[texSetIdx];
                            Texture2D t  = texSet.ts[propIdx].GetTexture2D();
                            int       x  = Mathf.RoundToInt(r.x * atlasSizeX);
                            int       y  = Mathf.RoundToInt(r.y * atlasSizeY);
                            int       ww = Mathf.RoundToInt(r.width * atlasSizeX);
                            int       hh = Mathf.RoundToInt(r.height * atlasSizeY);
                            if (ww == 0 || hh == 0)
                            {
                                Debug.LogError("Image in atlas has no height or width " + r);
                            }
                            if (progressInfo != null)
                            {
                                progressInfo(s + " set ReadWrite flag", .01f);
                            }
                            if (textureEditorMethods != null)
                            {
                                textureEditorMethods.SetReadWriteFlag(t, true, true);
                            }
                            if (progressInfo != null)
                            {
                                progressInfo(s + "Copying to atlas: '" + texSet.ts[propIdx].GetTexName() + "'", .02f);
                            }
                            DRect samplingRect = texSet.ts[propIdx].encapsulatingSamplingRect;
                            yield return(CopyScaledAndTiledToAtlas(texSet.ts[propIdx], texSet, data.texPropertyNames[propIdx], samplingRect, x, y, ww, hh, packedAtlasRects.padding[texSetIdx], atlasPixels, isNormalMap, data, combiner, progressInfo, LOG_LEVEL));
                            //							Debug.Log("after copyScaledAndTiledAtlas");
                        }
                        yield return(data.numAtlases);

                        if (progressInfo != null)
                        {
                            progressInfo("Applying changes to atlas: '" + data.texPropertyNames[propIdx].name + "'", .03f);
                        }
                        atlas = new Texture2D(atlasSizeX, atlasSizeY, TextureFormat.ARGB32, true);
                        for (int j = 0; j < atlasPixels.Length; j++)
                        {
                            atlas.SetPixels(0, j, atlasSizeX, 1, atlasPixels[j]);
                        }
                        atlas.Apply();
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Saving atlas " + data.texPropertyNames[propIdx].name + " w=" + atlas.width + " h=" + atlas.height);
                        }
                    }
                    atlases[propIdx] = atlas;
                    if (progressInfo != null)
                    {
                        progressInfo("Saving atlas: '" + data.texPropertyNames[propIdx].name + "'", .04f);
                    }
                    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                    sw.Start();

                    if (data._saveAtlasesAsAssets && textureEditorMethods != null)
                    {
                        textureEditorMethods.SaveAtlasToAssetDatabase(atlases[propIdx], data.texPropertyNames[propIdx], propIdx, data.resultMaterial);
                    }
                    else
                    {
                        data.resultMaterial.SetTexture(data.texPropertyNames[propIdx].name, atlases[propIdx]);
                    }
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[propIdx].name, Vector2.zero);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[propIdx].name, Vector2.one);
                    combiner._destroyTemporaryTextures(); // need to save atlases before doing this
                }
            }
            //data.rectsInAtlas = uvRects;
            //			Debug.Log("finished!");
            yield break;
        }
 public static DVector2 TransformPoint(ref DRect r, DVector2 p)
 {
     return(new DVector2((r.width * p.x + r.x), (r.height * p.y + r.y)));
 }
Example #11
0
        public override IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                                  MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                                  AtlasPackingResult packedAtlasRects,
                                                  Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                                  MB2_LogLevel LOG_LEVEL)
        {
            Rect[] uvRects = packedAtlasRects.rects;

            int atlasSizeX = packedAtlasRects.atlasX;
            int atlasSizeY = packedAtlasRects.atlasY;

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
            }

            for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
            {
                Texture2D             atlas    = null;
                ShaderTextureProperty property = data.texPropertyNames[propIdx];
                if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                {
                    atlas = null;
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("=== Not creating atlas for " + property.name + " because textures are null and default value parameters are the same.");
                    }
                }
                else
                {
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("=== Creating atlas for " + property.name);
                    }

                    GC.Collect();

                    CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);

                    //use a jagged array because it is much more efficient in memory
                    Color[][] atlasPixels = new Color[atlasSizeY][];
                    for (int j = 0; j < atlasPixels.Length; j++)
                    {
                        atlasPixels[j] = new Color[atlasSizeX];
                    }

                    bool isNormalMap = false;
                    if (property.isNormalMap)
                    {
                        isNormalMap = true;
                    }

                    for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++)
                    {
                        MB_TexSet texSet = data.distinctMaterialTextures[texSetIdx];
                        MeshBakerMaterialTexture matTex = texSet.ts[propIdx];
                        string s = "Creating Atlas '" + property.name + "' texture " + matTex.GetTexName();
                        if (progressInfo != null)
                        {
                            progressInfo(s, .01f);
                        }
                        if (LOG_LEVEL >= MB2_LogLevel.trace)
                        {
                            Debug.Log(string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName()));
                        }
                        Rect      r  = uvRects[texSetIdx];
                        Texture2D t  = texSet.ts[propIdx].GetTexture2D();
                        int       x  = Mathf.RoundToInt(r.x * atlasSizeX);
                        int       y  = Mathf.RoundToInt(r.y * atlasSizeY);
                        int       ww = Mathf.RoundToInt(r.width * atlasSizeX);
                        int       hh = Mathf.RoundToInt(r.height * atlasSizeY);
                        if (ww == 0 || hh == 0)
                        {
                            Debug.LogError("Image in atlas has no height or width " + r);
                        }
                        if (progressInfo != null)
                        {
                            progressInfo(s + " set ReadWrite flag", .01f);
                        }
                        if (textureEditorMethods != null)
                        {
                            textureEditorMethods.SetReadWriteFlag(t, true, true);
                        }
                        if (progressInfo != null)
                        {
                            progressInfo(s + "Copying to atlas: '" + matTex.GetTexName() + "'", .02f);
                        }
                        DRect samplingRect = texSet.ts[propIdx].GetEncapsulatingSamplingRect();
                        Debug.Assert(!texSet.ts[propIdx].isNull, string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName()));
                        yield return(CopyScaledAndTiledToAtlas(texSet.ts[propIdx], texSet, property, samplingRect, x, y, ww, hh, packedAtlasRects.padding[texSetIdx], atlasPixels, isNormalMap, data, combiner, progressInfo, LOG_LEVEL));
                    }

                    yield return(data.numAtlases);

                    if (progressInfo != null)
                    {
                        progressInfo("Applying changes to atlas: '" + property.name + "'", .03f);
                    }
                    atlas = new Texture2D(atlasSizeX, atlasSizeY, TextureFormat.ARGB32, true);
                    for (int j = 0; j < atlasPixels.Length; j++)
                    {
                        atlas.SetPixels(0, j, atlasSizeX, 1, atlasPixels[j]);
                    }

                    atlas.Apply();
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("Saving atlas " + property.name + " w=" + atlas.width + " h=" + atlas.height);
                    }
                }

                atlases[propIdx] = atlas;
                if (progressInfo != null)
                {
                    progressInfo("Saving atlas: '" + property.name + "'", .04f);
                }
                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                if (data.resultType == MB2_TextureBakeResults.ResultType.atlas)
                {
                    SaveAtlasAndConfigureResultMaterial(data, textureEditorMethods, atlases[propIdx], data.texPropertyNames[propIdx], propIdx);
                }

                combiner._destroyTemporaryTextures(data.texPropertyNames[propIdx].name);
            }

            yield break;
        }
Example #12
0
        public void MergeOverlappingDistinctMaterialTexturesAndCalcMaterialSubrects(List <MB_TexSet> distinctMaterialTextures)
        {
            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("MergeOverlappingDistinctMaterialTexturesAndCalcMaterialSubrects num atlas rects" + distinctMaterialTextures.Count);
            }

            int numMerged = 0;

            // IMPORTANT: Note that the verts stored in the mesh are NOT Normalized UV Coords. They are normalized * [UVTrans]. To get normalized UV
            // coords we must multiply them by [invUVTrans]. Need to do this to the verts in the mesh before we do any transforms with them.
            // Also check that all textures use same tiling. This is a prerequisite for merging.
            // Mark MB3_TexSet that are mergable (allTexturesUseSameMatTiling)
            for (int i = 0; i < distinctMaterialTextures.Count; i++)
            {
                MB_TexSet tx = distinctMaterialTextures[i];
                int       idxOfFirstNotNull = -1;
                bool      allAreSame        = true;
                DRect     firstRect         = new DRect();
                for (int propIdx = 0; propIdx < tx.ts.Length; propIdx++)
                {
                    if (idxOfFirstNotNull != -1)
                    {
                        if (!tx.ts[propIdx].isNull && firstRect != tx.ts[propIdx].matTilingRect)
                        {
                            allAreSame = false;
                        }
                    }
                    else if (!tx.ts[propIdx].isNull)
                    {
                        idxOfFirstNotNull = propIdx;
                        firstRect         = tx.ts[propIdx].matTilingRect;
                    }
                }
                if (LOG_LEVEL >= MB2_LogLevel.debug || LOG_LEVEL_TRACE_MERGE_MAT_SUBRECTS == true)
                {
                    if (allAreSame)
                    {
                        Debug.LogFormat("TextureSet {0} allTexturesUseSameMatTiling = {1}", i, allAreSame);
                    }
                    else
                    {
                        Debug.Log(string.Format("Textures in material(s) do not all use the same material tiling. This set of textures will not be considered for merge: {0} ", tx.GetDescription()));
                    }
                }
                if (allAreSame)
                {
                    tx.SetAllTexturesUseSameMatTilingTrue();
                }
            }

            for (int i = 0; i < distinctMaterialTextures.Count; i++)
            {
                MB_TexSet tx = distinctMaterialTextures[i];
                for (int matIdx = 0; matIdx < tx.matsAndGOs.mats.Count; matIdx++)
                {
                    if (tx.matsAndGOs.gos.Count > 0)
                    {
                        tx.matsAndGOs.mats[matIdx].objName = tx.matsAndGOs.gos[0].name;
                    }
                    else if (tx.ts[0] != null)
                    {
                        tx.matsAndGOs.mats[matIdx].objName = string.Format("[objWithTx:{0} atlasBlock:{1} matIdx{2}]", tx.ts[0].GetTexName(), i, matIdx);
                    }
                    else
                    {
                        tx.matsAndGOs.mats[matIdx].objName = string.Format("[objWithTx:{0} atlasBlock:{1} matIdx{2}]", "Unknown", i, matIdx);
                    }
                }

                tx.CalcInitialFullSamplingRects(fixOutOfBoundsUVs);
                tx.CalcMatAndUVSamplingRects();
            }

            _HasBeenInitialized = true;
            // need to calculate the srcSampleRect for the complete tiling in the atlas
            // for each material need to know what the subrect would be in the atlas if material UVRect was 0,0,1,1 and Merged uvRect was full tiling
            List <int> MarkedForDeletion = new List <int>();

            for (int i = 0; i < distinctMaterialTextures.Count; i++)
            {
                MB_TexSet tx2 = distinctMaterialTextures[i];
                for (int j = i + 1; j < distinctMaterialTextures.Count; j++)
                {
                    MB_TexSet tx1 = distinctMaterialTextures[j];
                    if (tx1.AllTexturesAreSameForMerge(tx2, _considerNonTextureProperties, resultMaterialTextureBlender))
                    {
                        double accumulatedAreaCombined    = 0f;
                        double accumulatedAreaNotCombined = 0f;
                        DRect  encapsulatingRectMerged    = new DRect();
                        int    idxOfFirstNotNull          = -1;
                        for (int propIdx = 0; propIdx < tx2.ts.Length; propIdx++)
                        {
                            if (!tx2.ts[propIdx].isNull)
                            {
                                if (idxOfFirstNotNull == -1)
                                {
                                    idxOfFirstNotNull = propIdx;
                                }
                            }
                        }

                        DRect encapsulatingRect1 = new DRect();
                        DRect encapsulatingRect2 = new DRect();
                        if (idxOfFirstNotNull != -1)
                        {
                            // only in here if all properties use the same tiling so don't need to worry about which propIdx we are dealing with
                            //Get the rect that encapsulates all material and UV tiling for materials and meshes in tx1
                            encapsulatingRect1 = tx1.matsAndGOs.mats[0].samplingRectMatAndUVTiling;
                            for (int matIdx = 1; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
                            {
                                DRect tmpSsamplingRectMatAndUVTilingTx1 = tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling;
                                encapsulatingRect1 = MB3_UVTransformUtility.GetEncapsulatingRectShifted(ref encapsulatingRect1, ref tmpSsamplingRectMatAndUVTilingTx1);
                            }

                            //same for tx2
                            encapsulatingRect2 = tx2.matsAndGOs.mats[0].samplingRectMatAndUVTiling;
                            for (int matIdx = 1; matIdx < tx2.matsAndGOs.mats.Count; matIdx++)
                            {
                                DRect tmpSsamplingRectMatAndUVTilingTx2 = tx2.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling;
                                encapsulatingRect2 = MB3_UVTransformUtility.GetEncapsulatingRectShifted(ref encapsulatingRect2, ref tmpSsamplingRectMatAndUVTilingTx2);
                            }

                            encapsulatingRectMerged     = MB3_UVTransformUtility.GetEncapsulatingRectShifted(ref encapsulatingRect1, ref encapsulatingRect2);
                            accumulatedAreaCombined    += encapsulatingRectMerged.width * encapsulatingRectMerged.height;
                            accumulatedAreaNotCombined += encapsulatingRect1.width * encapsulatingRect1.height + encapsulatingRect2.width * encapsulatingRect2.height;
                        }
                        else
                        {
                            encapsulatingRectMerged = new DRect(0f, 0f, 1f, 1f);
                        }

                        //the distinct material textures may overlap.
                        //if the area of these rectangles combined is less than the sum of these areas of these rectangles then merge these distinctMaterialTextures
                        if (accumulatedAreaCombined < accumulatedAreaNotCombined)
                        {
                            // merge tx2 into tx1
                            numMerged++;
                            StringBuilder sb = null;
                            if (LOG_LEVEL >= MB2_LogLevel.info)
                            {
                                sb = new StringBuilder();
                                sb.AppendFormat("About To Merge:\n   TextureSet1 {0}\n   TextureSet2 {1}\n", tx1.GetDescription(), tx2.GetDescription());
                                if (LOG_LEVEL >= MB2_LogLevel.trace)
                                {
                                    for (int matIdx = 0; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
                                    {
                                        sb.AppendFormat("tx1 Mat {0} matAndMeshUVRect {1} fullSamplingRect {2}\n",
                                                        tx1.matsAndGOs.mats[matIdx].mat, tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling, tx1.ts[0].GetEncapsulatingSamplingRect());
                                    }
                                    for (int matIdx = 0; matIdx < tx2.matsAndGOs.mats.Count; matIdx++)
                                    {
                                        sb.AppendFormat("tx2 Mat {0} matAndMeshUVRect {1} fullSamplingRect {2}\n",
                                                        tx2.matsAndGOs.mats[matIdx].mat, tx2.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling, tx2.ts[0].GetEncapsulatingSamplingRect());
                                    }
                                }
                            }

                            //copy game objects over
                            for (int k = 0; k < tx2.matsAndGOs.gos.Count; k++)
                            {
                                if (!tx1.matsAndGOs.gos.Contains(tx2.matsAndGOs.gos[k]))
                                {
                                    tx1.matsAndGOs.gos.Add(tx2.matsAndGOs.gos[k]);
                                }
                            }

                            //copy materials over from tx2 to tx1
                            for (int matIdx = 0; matIdx < tx2.matsAndGOs.mats.Count; matIdx++)
                            {
                                tx1.matsAndGOs.mats.Add(tx2.matsAndGOs.mats[matIdx]);
                            }

                            tx1.SetEncapsulatingSamplingRectWhenMergingTexSets(encapsulatingRectMerged);
                            if (!MarkedForDeletion.Contains(i))
                            {
                                MarkedForDeletion.Add(i);
                            }

                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                if (LOG_LEVEL >= MB2_LogLevel.trace)
                                {
                                    sb.AppendFormat("=== After Merge TextureSet {0}\n", tx1.GetDescription());
                                    for (int matIdx = 0; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
                                    {
                                        sb.AppendFormat("tx1 Mat {0} matAndMeshUVRect {1} fullSamplingRect {2}\n",
                                                        tx1.matsAndGOs.mats[matIdx].mat, tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling, tx1.ts[0].GetEncapsulatingSamplingRect());
                                    }
                                    //Integrity check that sampling rects fit into enapsulating rects
                                    if (MB3_MeshBakerRoot.DO_INTEGRITY_CHECKS)
                                    {
                                        if (MB3_MeshBakerRoot.DO_INTEGRITY_CHECKS)
                                        {
                                            DoIntegrityCheckMergedEncapsulatingSamplingRects(distinctMaterialTextures);
                                        }
                                    }
                                }
                                Debug.Log(sb.ToString());
                            }
                            break;
                        }
                        else
                        {
                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                Debug.Log(string.Format("Considered merging {0} and {1} but there was not enough overlap. It is more efficient to bake these to separate rectangles.",
                                                        tx1.GetDescription() + encapsulatingRect1,
                                                        tx2.GetDescription() + encapsulatingRect2));
                            }
                        }
                    }
                }
            }

            //remove distinctMaterialTextures that were merged
            for (int j = MarkedForDeletion.Count - 1; j >= 0; j--)
            {
                distinctMaterialTextures.RemoveAt(MarkedForDeletion[j]);
            }
            MarkedForDeletion.Clear();
            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log(string.Format("MergeOverlappingDistinctMaterialTexturesAndCalcMaterialSubrects complete merged {0} now have {1}", numMerged, distinctMaterialTextures.Count));
            }
            if (MB3_MeshBakerRoot.DO_INTEGRITY_CHECKS)
            {
                DoIntegrityCheckMergedEncapsulatingSamplingRects(distinctMaterialTextures);
            }
        }
Example #13
0
        // This should only be called after regular merge so that rects have been correctly setup.
        public void MergeDistinctMaterialTexturesThatWouldExceedMaxAtlasSizeAndCalcMaterialSubrects(List <MB_TexSet> distinctMaterialTextures, int maxAtlasSize)
        {
            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("MergeDistinctMaterialTexturesThatWouldExceedMaxAtlasSizeAndCalcMaterialSubrects num atlas rects" + distinctMaterialTextures.Count);
            }

            Debug.Assert(_HasBeenInitialized, "MergeOverlappingDistinctMaterialTexturesAndCalcMaterialSubrects must be called before MergeDistinctMaterialTexturesThatWouldExceedMaxAtlasSizeAndCalcMaterialSubrects");

            int numMerged = 0;

            List <int> MarkedForDeletion = new List <int>();

            for (int i = 0; i < distinctMaterialTextures.Count; i++)
            {
                MB_TexSet tx2 = distinctMaterialTextures[i];
                for (int j = i + 1; j < distinctMaterialTextures.Count; j++)
                {
                    MB_TexSet tx1 = distinctMaterialTextures[j];
                    if (tx1.AllTexturesAreSameForMerge(tx2, _considerNonTextureProperties, resultMaterialTextureBlender))
                    {
                        //Check if the size of the rect in the atlas would be greater than max atlas size.

                        DRect encapsulatingRectMerged = new DRect();
                        int   idxOfFirstNotNull       = -1;
                        for (int propIdx = 0; propIdx < tx2.ts.Length; propIdx++)
                        {
                            if (!tx2.ts[propIdx].isNull)
                            {
                                if (idxOfFirstNotNull == -1)
                                {
                                    idxOfFirstNotNull = propIdx;
                                }
                            }
                        }

                        DRect encapsulatingRect1 = new DRect();
                        DRect encapsulatingRect2 = new DRect();
                        if (idxOfFirstNotNull != -1)
                        {
                            // only in here if all properties use the same tiling so don't need to worry about which propIdx we are dealing with
                            //Get the rect that encapsulates all material and UV tiling for materials and meshes in tx1
                            encapsulatingRect1 = tx1.matsAndGOs.mats[0].samplingRectMatAndUVTiling;
                            for (int matIdx = 1; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
                            {
                                DRect tmpSsamplingRectMatAndUVTilingTx1 = tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling;
                                encapsulatingRect1 = MB3_UVTransformUtility.GetEncapsulatingRectShifted(ref encapsulatingRect1, ref tmpSsamplingRectMatAndUVTilingTx1);
                            }

                            //same for tx2
                            encapsulatingRect2 = tx2.matsAndGOs.mats[0].samplingRectMatAndUVTiling;
                            for (int matIdx = 1; matIdx < tx2.matsAndGOs.mats.Count; matIdx++)
                            {
                                DRect tmpSsamplingRectMatAndUVTilingTx2 = tx2.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling;
                                encapsulatingRect2 = MB3_UVTransformUtility.GetEncapsulatingRectShifted(ref encapsulatingRect2, ref tmpSsamplingRectMatAndUVTilingTx2);
                            }

                            encapsulatingRectMerged = MB3_UVTransformUtility.GetEncapsulatingRectShifted(ref encapsulatingRect1, ref encapsulatingRect2);
                        }
                        else
                        {
                            encapsulatingRectMerged = new DRect(0f, 0f, 1f, 1f);
                        }

                        Vector2 maxHeightWidth = tx1.GetMaxRawTextureHeightWidth();
                        if (encapsulatingRectMerged.width * maxHeightWidth.x > maxAtlasSize ||
                            encapsulatingRectMerged.height * maxHeightWidth.y > maxAtlasSize)
                        {
                            // merge tx2 into tx1
                            numMerged++;
                            StringBuilder sb = null;
                            if (LOG_LEVEL >= MB2_LogLevel.info)
                            {
                                sb = new StringBuilder();
                                sb.AppendFormat("About To Merge:\n   TextureSet1 {0}\n   TextureSet2 {1}\n", tx1.GetDescription(), tx2.GetDescription());
                                if (LOG_LEVEL >= MB2_LogLevel.trace)
                                {
                                    for (int matIdx = 0; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
                                    {
                                        sb.AppendFormat("tx1 Mat {0} matAndMeshUVRect {1} fullSamplingRect {2}\n",
                                                        tx1.matsAndGOs.mats[matIdx].mat, tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling, tx1.ts[0].GetEncapsulatingSamplingRect());
                                    }
                                    for (int matIdx = 0; matIdx < tx2.matsAndGOs.mats.Count; matIdx++)
                                    {
                                        sb.AppendFormat("tx2 Mat {0} matAndMeshUVRect {1} fullSamplingRect {2}\n",
                                                        tx2.matsAndGOs.mats[matIdx].mat, tx2.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling, tx2.ts[0].GetEncapsulatingSamplingRect());
                                    }
                                }
                            }

                            //copy game objects over
                            for (int k = 0; k < tx2.matsAndGOs.gos.Count; k++)
                            {
                                if (!tx1.matsAndGOs.gos.Contains(tx2.matsAndGOs.gos[k]))
                                {
                                    tx1.matsAndGOs.gos.Add(tx2.matsAndGOs.gos[k]);
                                }
                            }

                            //copy materials over from tx2 to tx1
                            for (int matIdx = 0; matIdx < tx2.matsAndGOs.mats.Count; matIdx++)
                            {
                                tx1.matsAndGOs.mats.Add(tx2.matsAndGOs.mats[matIdx]);
                            }

                            tx1.SetEncapsulatingSamplingRectWhenMergingTexSets(encapsulatingRectMerged);
                            if (!MarkedForDeletion.Contains(i))
                            {
                                MarkedForDeletion.Add(i);
                            }

                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                if (LOG_LEVEL >= MB2_LogLevel.trace)
                                {
                                    sb.AppendFormat("=== After Merge TextureSet {0}\n", tx1.GetDescription());
                                    for (int matIdx = 0; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
                                    {
                                        sb.AppendFormat("tx1 Mat {0} matAndMeshUVRect {1} fullSamplingRect {2}\n",
                                                        tx1.matsAndGOs.mats[matIdx].mat, tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling, tx1.ts[0].GetEncapsulatingSamplingRect());
                                    }
                                    //Integrity check that sampling rects fit into enapsulating rects
                                    if (MB3_MeshBakerRoot.DO_INTEGRITY_CHECKS)
                                    {
                                        if (MB3_MeshBakerRoot.DO_INTEGRITY_CHECKS)
                                        {
                                            DoIntegrityCheckMergedEncapsulatingSamplingRects(distinctMaterialTextures);
                                        }
                                    }
                                }
                                Debug.Log(sb.ToString());
                            }
                            break;
                        }
                        else
                        {
                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                Debug.Log(string.Format("Considered merging {0} and {1} but there was not enough overlap. It is more efficient to bake these to separate rectangles.",
                                                        tx1.GetDescription() + encapsulatingRect1,
                                                        tx2.GetDescription() + encapsulatingRect2));
                            }
                        }
                    }
                }
            }

            //remove distinctMaterialTextures that were merged
            for (int j = MarkedForDeletion.Count - 1; j >= 0; j--)
            {
                distinctMaterialTextures.RemoveAt(MarkedForDeletion[j]);
            }
            MarkedForDeletion.Clear();
            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log(string.Format("MergeDistinctMaterialTexturesThatWouldExceedMaxAtlasSizeAndCalcMaterialSubrects complete merged {0} now have {1}", numMerged, distinctMaterialTextures.Count));
            }
            if (MB3_MeshBakerRoot.DO_INTEGRITY_CHECKS)
            {
                DoIntegrityCheckMergedEncapsulatingSamplingRects(distinctMaterialTextures);
            }
        }
Example #14
0
            internal static void BuildAtlas(
                AtlasPackingResult packedAtlasRects,
                List <MB_TexSet> distinctMaterialTextures,
                int propIdx,
                int atlasSizeX, int atlasSizeY,
                Mesh m,
                List <Material> generatedMats,
                ShaderTextureProperty property,
                MB3_TextureCombinerPipeline.TexturePipelineData data,
                MB3_TextureCombiner combiner,
                MB2_EditorMethodsInterface textureEditorMethods,
                MB2_LogLevel LOG_LEVEL)
            {
                // Collect vertices and quads for mesh that we will use for the atlas.
                Debug.Assert(generatedMats.Count == 0, "Previous mats should have been destroyed");
                generatedMats.Clear();
                List <Vector3> vs  = new List <Vector3>();
                List <Vector2> uvs = new List <Vector2>();

                // One submesh and material per texture that we are packing
                List <int>[] ts = new List <int> [distinctMaterialTextures.Count];
                for (int i = 0; i < ts.Length; i++)
                {
                    ts[i] = new List <int>();
                }

                MeshBakerMaterialTexture.readyToBuildAtlases = true;
                GC.Collect();
                MB3_TextureCombinerPackerRoot.CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);

                Rect[] uvRects = packedAtlasRects.rects;
                for (int texSetIdx = 0; texSetIdx < distinctMaterialTextures.Count; texSetIdx++)
                {
                    MB_TexSet texSet = distinctMaterialTextures[texSetIdx];
                    MeshBakerMaterialTexture matTex = texSet.ts[propIdx];

                    if (LOG_LEVEL >= MB2_LogLevel.trace)
                    {
                        Debug.Log(string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName()));
                    }
                    Rect      r  = uvRects[texSetIdx];
                    Texture2D t  = matTex.GetTexture2D();
                    int       x  = Mathf.RoundToInt(r.x * atlasSizeX);
                    int       y  = Mathf.RoundToInt(r.y * atlasSizeY);
                    int       ww = Mathf.RoundToInt(r.width * atlasSizeX);
                    int       hh = Mathf.RoundToInt(r.height * atlasSizeY);
                    r = new Rect(x, y, ww, hh);
                    if (ww == 0 || hh == 0)
                    {
                        Debug.LogError("Image in atlas has no height or width " + r);
                    }
                    DRect samplingRect = texSet.ts[propIdx].GetEncapsulatingSamplingRect();
                    Debug.Assert(!texSet.ts[propIdx].isNull, string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName()));

                    AtlasPadding padding = packedAtlasRects.padding[texSetIdx];
                    AddNineSlicedRect(r, padding.leftRight, padding.topBottom, samplingRect.GetRect(), vs, uvs, ts[texSetIdx], t.width, t.height, t.name);

                    Material mt = new Material(Shader.Find("MeshBaker/Unlit/UnlitWithAlpha"));

                    bool isSavingAsANormalMapAssetThatWillBeImported = property.isNormalMap && data._saveAtlasesAsAssets;
                    MBVersion.PipelineType pipelineType = MBVersion.DetectPipeline();
                    if (pipelineType == MBVersion.PipelineType.URP)
                    {
                        ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                        //ConfigureMaterial_URP(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                    }
                    else if (pipelineType == MBVersion.PipelineType.HDRP)
                    {
                        ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                    }
                    else
                    {
                        ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                    }

                    generatedMats.Add(mt);
                }

                // Apply to the mesh
                m.Clear();
                m.vertices     = vs.ToArray();
                m.uv           = uvs.ToArray();
                m.subMeshCount = ts.Length;
                for (int i = 0; i < m.subMeshCount; i++)
                {
                    m.SetIndices(ts[i].ToArray(), MeshTopology.Triangles, i);
                }
                MeshBakerMaterialTexture.readyToBuildAtlases = false;
            }
 public static float TransformX(DRect r, double x)
 {
     return((float)(r.width * x + r.x));
 }
 public static Vector2 TransformPoint(ref DRect r, Vector2 p)
 {
     return(new Vector2((float)(r.width * p.x + r.x), (float)(r.height * p.y + r.y)));
 }
        internal static IEnumerator CopyScaledAndTiledToAtlas(MeshBakerMaterialTexture source, MB_TexSet sourceMaterial,
                                                              ShaderTextureProperty shaderPropertyName, DRect srcSamplingRect, int targX, int targY, int targW, int targH,
                                                              AtlasPadding padding,
                                                              Color[][] atlasPixels, bool isNormalMap,
                                                              MB3_TextureCombinerPipeline.TexturePipelineData data,
                                                              MB3_TextureCombiner combiner,
                                                              ProgressUpdateDelegate progressInfo = null,
                                                              MB2_LogLevel LOG_LEVEL = MB2_LogLevel.info)
        {
            //HasFinished = false;
            Texture2D t = source.GetTexture2D();

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log(String.Format("CopyScaledAndTiledToAtlas: {0} inAtlasX={1} inAtlasY={2} inAtlasW={3} inAtlasH={4} paddX={5} paddY={6} srcSamplingRect={7}",
                                        t, targX, targY, targW, targH, padding.leftRight, padding.topBottom, srcSamplingRect));
            }
            float newWidth  = targW;
            float newHeight = targH;
            float scx       = (float)srcSamplingRect.width;
            float scy       = (float)srcSamplingRect.height;
            float ox        = (float)srcSamplingRect.x;
            float oy        = (float)srcSamplingRect.y;
            int   w         = (int)newWidth;
            int   h         = (int)newHeight;

            if (data._considerNonTextureProperties)
            {
                t = combiner._createTextureCopy(shaderPropertyName.name, t);
                t = data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(t, sourceMaterial, shaderPropertyName);
            }
            for (int i = 0; i < w; i++)
            {
                if (progressInfo != null && w > 0)
                {
                    progressInfo("CopyScaledAndTiledToAtlas " + (((float)i / (float)w) * 100f).ToString("F0"), .2f);
                }
                for (int j = 0; j < h; j++)
                {
                    float u = i / newWidth * scx + ox;
                    float v = j / newHeight * scy + oy;
                    atlasPixels[targY + j][targX + i] = t.GetPixelBilinear(u, v);
                }
            }

            //bleed the border colors into the padding
            for (int i = 0; i < w; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    //top margin
                    atlasPixels[(targY - j)][targX + i] = atlasPixels[(targY)][targX + i];
                    //bottom margin
                    atlasPixels[(targY + h - 1 + j)][targX + i] = atlasPixels[(targY + h - 1)][targX + i];
                }
            }
            for (int j = 0; j < h; j++)
            {
                for (int i = 1; i <= padding.leftRight; i++)
                {
                    //left margin
                    atlasPixels[(targY + j)][targX - i] = atlasPixels[(targY + j)][targX];
                    //right margin
                    atlasPixels[(targY + j)][targX + w + i - 1] = atlasPixels[(targY + j)][targX + w - 1];
                }
            }
            //corners
            for (int i = 1; i <= padding.leftRight; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    atlasPixels[(targY - j)][targX - i]                 = atlasPixels[targY][targX];
                    atlasPixels[(targY + h - 1 + j)][targX - i]         = atlasPixels[(targY + h - 1)][targX];
                    atlasPixels[(targY + h - 1 + j)][targX + w + i - 1] = atlasPixels[(targY + h - 1)][targX + w - 1];
                    atlasPixels[(targY - j)][targX + w + i - 1]         = atlasPixels[targY][targX + w - 1];
                    yield return(null);
                }
                yield return(null);
            }
            //			Debug.Log("copyandscaledatlas finished too!");
            //HasFinished = true;
            yield break;
        }
        internal static IEnumerator CopyScaledAndTiledToAtlas(MeshBakerMaterialTexture source, MB_TexSet sourceMaterial,
                                                              ShaderTextureProperty shaderPropertyName, DRect srcSamplingRect, int targX, int targY, int targW, int targH,
                                                              AtlasPadding padding,
                                                              Color[][] atlasPixels, bool isNormalMap,
                                                              MB3_TextureCombinerPipeline.TexturePipelineData data,
                                                              MB3_TextureCombiner combiner,
                                                              ProgressUpdateDelegate progressInfo = null,
                                                              MB2_LogLevel LOG_LEVEL = MB2_LogLevel.info)
        {
            //HasFinished = false;
            Texture2D t = source.GetTexture2D();

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("CopyScaledAndTiledToAtlas: " + t + " inAtlasX=" + targX + " inAtlasY=" + targY + " inAtlasW=" + targW + " inAtlasH=" + targH);
            }
            float newWidth  = targW;
            float newHeight = targH;
            float scx       = (float)srcSamplingRect.width;
            float scy       = (float)srcSamplingRect.height;
            float ox        = (float)srcSamplingRect.x;
            float oy        = (float)srcSamplingRect.y;
            int   w         = (int)newWidth;
            int   h         = (int)newHeight;

            if (t == null)
            {
                if (LOG_LEVEL >= MB2_LogLevel.trace)
                {
                    Debug.Log("No source texture creating a 16x16 texture.");
                }
                t   = combiner._createTemporaryTexture(16, 16, TextureFormat.ARGB32, true);
                scx = 1;
                scy = 1;
                if (data._considerNonTextureProperties && data.nonTexturePropertyBlender != null)
                {
                    Color col = data.nonTexturePropertyBlender.GetColorIfNoTexture(sourceMaterial.matsAndGOs.mats[0].mat, shaderPropertyName);
                    if (LOG_LEVEL >= MB2_LogLevel.trace)
                    {
                        Debug.Log("Setting texture to solid color " + col);
                    }
                    MB_Utility.setSolidColor(t, col);
                }
                else
                {
                    Color col = MB3_TextureCombinerNonTextureProperties.GetColorIfNoTexture(shaderPropertyName);
                    MB_Utility.setSolidColor(t, col);
                }
            }
            if (data._considerNonTextureProperties && data.nonTexturePropertyBlender != null)
            {
                t = combiner._createTextureCopy(t);
                t = data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(t, sourceMaterial, shaderPropertyName);
            }
            for (int i = 0; i < w; i++)
            {
                if (progressInfo != null && w > 0)
                {
                    progressInfo("CopyScaledAndTiledToAtlas " + (((float)i / (float)w) * 100f).ToString("F0"), .2f);
                }
                for (int j = 0; j < h; j++)
                {
                    float u = i / newWidth * scx + ox;
                    float v = j / newHeight * scy + oy;
                    atlasPixels[targY + j][targX + i] = t.GetPixelBilinear(u, v);
                }
            }
            //bleed the border colors into the padding
            for (int i = 0; i < w; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    //top margin
                    atlasPixels[(targY - j)][targX + i] = atlasPixels[(targY)][targX + i];
                    //bottom margin
                    atlasPixels[(targY + h - 1 + j)][targX + i] = atlasPixels[(targY + h - 1)][targX + i];
                }
            }
            for (int j = 0; j < h; j++)
            {
                for (int i = 1; i <= padding.leftRight; i++)
                {
                    //left margin
                    atlasPixels[(targY + j)][targX - i] = atlasPixels[(targY + j)][targX];
                    //right margin
                    atlasPixels[(targY + j)][targX + w + i - 1] = atlasPixels[(targY + j)][targX + w - 1];
                }
            }
            //corners
            for (int i = 1; i <= padding.leftRight; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    atlasPixels[(targY - j)][targX - i]                 = atlasPixels[targY][targX];
                    atlasPixels[(targY + h - 1 + j)][targX - i]         = atlasPixels[(targY + h - 1)][targX];
                    atlasPixels[(targY + h - 1 + j)][targX + w + i - 1] = atlasPixels[(targY + h - 1)][targX + w - 1];
                    atlasPixels[(targY - j)][targX + w + i - 1]         = atlasPixels[targY][targX + w - 1];
                    yield return(null);
                }
                yield return(null);
            }
            //			Debug.Log("copyandscaledatlas finished too!");
            //HasFinished = true;
            yield break;
        }
 public static void InvertHierarchy(ref DRect uvRect, ref DRect matRect)
 {
     matRect.x = (uvRect.x * matRect.width + matRect.x - uvRect.x) / uvRect.width;
     matRect.y = (uvRect.y * matRect.height + matRect.y - uvRect.y) / uvRect.height;
 }
Example #20
0
        public void SuggestTreatment(List <GameObject> objsToMesh, Material[] resultMaterials, List <ShaderTextureProperty> _customShaderPropNames)
        {
            this._customShaderPropNames = _customShaderPropNames;
            StringBuilder sb = new StringBuilder();
            Dictionary <int, MB_Utility.MeshAnalysisResult[]> meshAnalysisResultsCache = new Dictionary <int, MB_Utility.MeshAnalysisResult[]>(); //cache results

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                GameObject obj = objsToMesh[i];
                if (obj == null)
                {
                    continue;
                }
                Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
                if (ms.Length > 1)
                { // and each material is not mapped to its own layer
                    sb.AppendFormat("\nObject {0} uses {1} materials. Possible treatments:\n", objsToMesh[i].name, ms.Length);
                    sb.AppendFormat("  1) Collapse the submeshes together into one submesh in the combined mesh. Each of the original submesh materials will map to a different UV rectangle in the atlas(es) used by the combined material.\n");
                    sb.AppendFormat("  2) Use the multiple materials feature to map submeshes in the source mesh to submeshes in the combined mesh.\n");
                }
                Mesh m = MB_Utility.GetMesh(obj);

                MB_Utility.MeshAnalysisResult[] mar;
                if (!meshAnalysisResultsCache.TryGetValue(m.GetInstanceID(), out mar))
                {
                    mar = new MB_Utility.MeshAnalysisResult[m.subMeshCount];
                    MB_Utility.doSubmeshesShareVertsOrTris(m, ref mar[0]);
                    for (int j = 0; j < m.subMeshCount; j++)
                    {
                        MB_Utility.hasOutOfBoundsUVs(m, ref mar[j], j);
                        //DRect outOfBoundsUVRect = new DRect(mar[j].uvRect);
                        mar[j].hasOverlappingSubmeshTris  = mar[0].hasOverlappingSubmeshTris;
                        mar[j].hasOverlappingSubmeshVerts = mar[0].hasOverlappingSubmeshVerts;
                    }
                    meshAnalysisResultsCache.Add(m.GetInstanceID(), mar);
                }

                for (int j = 0; j < ms.Length; j++)
                {
                    if (mar[j].hasOutOfBoundsUVs)
                    {
                        DRect r = new DRect(mar[j].uvRect);
                        sb.AppendFormat("\nObject {0} submesh={1} material={2} uses UVs outside the range 0,0 .. 1,1 to create tiling that tiles the box {3},{4} .. {5},{6}. This is a problem because the UVs outside the 0,0 .. 1,1 " +
                                        "rectangle will pick up neighboring textures in the atlas. Possible Treatments:\n", obj, j, ms[j], r.x.ToString("G4"), r.y.ToString("G4"), (r.x + r.width).ToString("G4"), (r.y + r.height).ToString("G4"));
                        sb.AppendFormat("    1) Ignore the problem. The tiling may not affect result significantly.\n");
                        sb.AppendFormat("    2) Use the 'fix out of bounds UVs' feature to bake the tiling and scale the UVs to fit in the 0,0 .. 1,1 rectangle.\n");
                        sb.AppendFormat("    3) Use the Multiple Materials feature to map the material on this submesh to its own submesh in the combined mesh. No other materials should map to this submesh. This will result in only one texture in the atlas(es) and the UVs should tile correctly.\n");
                        sb.AppendFormat("    4) Combine only meshes that use the same (or subset of) the set of materials on this mesh. The original material(s) can be applied to the result\n");
                    }
                }
                if (mar[0].hasOverlappingSubmeshVerts)
                {
                    sb.AppendFormat("\nObject {0} has submeshes that share vertices. This is a problem because each vertex can have only one UV coordinate and may be required to map to different positions in the various atlases that are generated. Possible treatments:\n", objsToMesh[i]);
                    sb.AppendFormat(" 1) Ignore the problem. The vertices may not affect the result.\n");
                    sb.AppendFormat(" 2) Use the Multiple Materials feature to map the submeshs that overlap to their own submeshs in the combined mesh. No other materials should map to this submesh. This will result in only one texture in the atlas(es) and the UVs should tile correctly.\n");
                    sb.AppendFormat(" 3) Combine only meshes that use the same (or subset of) the set of materials on this mesh. The original material(s) can be applied to the result\n");
                }
            }
            Dictionary <Material, List <GameObject> > m2gos = new Dictionary <Material, List <GameObject> >();

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                if (objsToMesh[i] != null)
                {
                    Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
                    for (int j = 0; j < ms.Length; j++)
                    {
                        if (ms[j] != null)
                        {
                            List <GameObject> lgo;
                            if (!m2gos.TryGetValue(ms[j], out lgo))
                            {
                                lgo = new List <GameObject>();
                                m2gos.Add(ms[j], lgo);
                            }
                            if (!lgo.Contains(objsToMesh[i]))
                            {
                                lgo.Add(objsToMesh[i]);
                            }
                        }
                    }
                }
            }

            for (int i = 0; i < resultMaterials.Length; i++)
            {
                string resultMatShaderName = resultMaterials[i] != null ? "None" : resultMaterials[i].shader.name;
                MB3_TextureCombinerPipeline.TexturePipelineData data = LoadPipelineData(resultMaterials[i], new List <ShaderTextureProperty>(), objsToMesh, new List <Material>(), new List <MB_TexSet>());
                MB3_TextureCombinerPipeline._CollectPropertyNames(data, LOG_LEVEL);
                foreach (Material m in m2gos.Keys)
                {
                    for (int j = 0; j < data.texPropertyNames.Count; j++)
                    {
                        if (m.HasProperty(data.texPropertyNames[j].name))
                        {
                            Texture txx = MB3_TextureCombinerPipeline.GetTextureConsideringStandardShaderKeywords(resultMatShaderName, m, data.texPropertyNames[j].name);
                            if (txx != null)
                            {
                                Vector2 o = m.GetTextureOffset(data.texPropertyNames[j].name);
                                Vector3 s = m.GetTextureScale(data.texPropertyNames[j].name);
                                if (o.x < 0f || o.x + s.x > 1f ||
                                    o.y < 0f || o.y + s.y > 1f)
                                {
                                    sb.AppendFormat("\nMaterial {0} used by objects {1} uses texture {2} that is tiled (scale={3} offset={4}). If there is more than one texture in the atlas " +
                                                    " then Mesh Baker will bake the tiling into the atlas. If the baked tiling is large then quality can be lost. Possible treatments:\n", m, PrintList(m2gos[m]), txx, s, o);
                                    sb.AppendFormat("  1) Use the baked tiling.\n");
                                    sb.AppendFormat("  2) Use the Multiple Materials feature to map the material on this object/submesh to its own submesh in the combined mesh. No other materials should map to this submesh. The original material can be applied to this submesh.\n");
                                    sb.AppendFormat("  3) Combine only meshes that use the same (or subset of) the set of textures on this mesh. The original material can be applied to the result.\n");
                                }
                            }
                        }
                    }
                }
            }
            string outstr = "";

            if (sb.Length == 0)
            {
                outstr = "====== No problems detected. These meshes should combine well ====\n  If there are problems with the combined meshes please report the problem to digitalOpus.ca so we can improve Mesh Baker.";
            }
            else
            {
                outstr = "====== There are possible problems with these meshes that may prevent them from combining well. TREATMENT SUGGESTIONS (copy and paste to text editor if too big) =====\n" + sb.ToString();
            }
            Debug.Log(outstr);
        }
Example #21
0
 public MatAndTransformToMerged(DRect obUVrect, bool fixOutOfBoundsUVs)
 {
     _init(obUVrect, fixOutOfBoundsUVs, null);
 }