Beispiel #1
0
        TextureImportSettings CheckTextureImportSettings(Texture2D texture)
        {
            TextureImportSettings importSettings;

#if UNITY_EDITOR
            string path = AssetDatabase.GetAssetPath(texture);
            // Check if textures settings has already been setted up
            if (importedTextures.ContainsKey(texture.GetInstanceID()))
            {
                importSettings = importedTextures[texture.GetInstanceID()];
                if (!importSettings.isNormal)
                {
                    return(importSettings);
                }
            }
            else
            {
                importSettings = new TextureImportSettings();
            }

            TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
            if (textureImporter != null)
            {
                if (!textureImporter.isReadable)
                {
                    textureImporter.isReadable = true;
                    AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
                }

#if UNITY_2017_1_OR_NEWER
                if (textureImporter.textureType == TextureImporterType.NormalMap)
                {
                    textureImporter.textureType = TextureImporterType.Default;
                    AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
                    importSettings.isNormal = true;
                }
#endif
            }
            else
            {
                try
                {
                    texture.GetPixel(0, 0);
                }
                catch
                {
                    importSettings.isReadable = false;
                    Logger.Instance.AddLog("SuperCombiner", "The texture '" + texture.name + "' has a format not handled by Unity, the result in atlas may be inconsistent.", Logger.LogLevel.LOG_WARNING);
                }
            }
#else
            importSettings = new TextureImportSettings();
#endif
            importSettings.isReadable = true;
            if (!importedTextures.ContainsKey(texture.GetInstanceID()))
            {
                importedTextures.Add(texture.GetInstanceID(), importSettings);
            }
            return(importSettings);
        }
Beispiel #2
0
        /// <summary>
        /// Returns the texture that will be put in the atlas.
        /// This texture may differs from original texture in case of tiling, or if texture needs to be resized
        /// </summary>
        /// <param name="texture"></param>
        /// <param name="materialUVBounds"></param>
        /// <param name="meshUVBounds"></param>
        /// <param name="mat"></param>
        /// <param name="textureInAtlasSize"></param>
        /// <param name="targetTextureSize"></param>
        /// <param name="isMainTexture"></param>
        /// <returns></returns>
        private Texture2D CopyTexture(Texture2D texture, Rect materialUVBounds, Rect meshUVBounds, Material mat, Vector3 textureInAtlasSize, Vector2 targetTextureSize, bool isMainTexture)
        {
            int   xSens     = (int)Mathf.Sign(materialUVBounds.width);
            int   ySens     = (int)Mathf.Sign(materialUVBounds.height);
            float repeatX   = Mathf.Abs(materialUVBounds.width);
            float repeatY   = Mathf.Abs(materialUVBounds.height);
            Color mainColor = Color.white;

            if (mat.HasProperty("_Color"))
            {
                mainColor = mat.color;
            }

            bool hasUVoutOfBound = false;

            if (repeatX != 1 || repeatY != 1 || materialUVBounds.position != Vector2.zero)
            {
                hasUVoutOfBound = true;
            }

            // Check Texture import settings
            TextureImportSettings importSettings = CheckTextureImportSettings(texture);

            // If an error occured, return a simple white texture
            if (!importSettings.isReadable)
            {
                Logger.Instance.AddLog("SuperCombiner", "The format of texture '" + texture.name + "' is not handled by Unity. Try manually setting 'Read/Write Enabled' parameter to true or converting this texture into a known format.", Logger.LogLevel.LOG_ERROR);
                return(CreateColoredTexture2D((int)textureInAtlasSize.x, (int)textureInAtlasSize.y, Color.white));
            }

            // Get a copy of the original texture so that it remains intact
            Texture2D uncompressedTexture = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);

            uncompressedTexture.name = texture.name;
            // Copy original pixels /!\ Only possible if the texture could be red correctly
            uncompressedTexture.SetPixels(texture.GetPixels());

            if (texture.width != (int)targetTextureSize.x || texture.height != (int)targetTextureSize.y)
            {
                // Scale the texture to it's max size so that all textures from this _material share the same texture size
                TextureScale.Bilinear(uncompressedTexture, (int)targetTextureSize.x, (int)targetTextureSize.y);
                Logger.Instance.AddLog("SuperCombiner", "Texture '" + texture.name + "' will be scaled from " + GetStringTextureSize(texture.width, texture.height) + " to " + GetStringTextureSize(targetTextureSize.x, targetTextureSize.y) + " to match the size of the other textures in _material '" + mat.name + "'", Logger.LogLevel.LOG_WARNING);
            }

            // Create a new Texture2D which will contain the adjusted texture tilled and scaled
            Texture2D copy = new Texture2D((int)textureInAtlasSize.x, (int)textureInAtlasSize.y, uncompressedTexture.format, false);

            copy.name = texture.name;

            // If the tiled texture exceeds the maximum texture size, we have to shrink the texture
            if (textureInAtlasSize.z != 1 && textureInAtlasSize.z > 0)
            {
                TextureScale.Bilinear(uncompressedTexture, uncompressedTexture.width / (int)textureInAtlasSize.z, uncompressedTexture.height / (int)textureInAtlasSize.z);
            }

            if (hasUVoutOfBound)
            {
                if (Mathf.Abs(textureInAtlasSize.x - uncompressedTexture.width) > 1 || Mathf.Abs(textureInAtlasSize.y - uncompressedTexture.height) > 1)
                {
                    Logger.Instance.AddLog("SuperCombiner", "Texture '" + texture.name + "' is being tiled in the atlas because mesh using it has UVs out of [0, 1] bound. The tiled size is " + GetStringTextureSize(textureInAtlasSize.x, textureInAtlasSize.y) + ".");
                }
                // If UVs are out of [0, 1] bound we have to duplicate the texture
                int xOffset = (int)(meshUVBounds.xMin * uncompressedTexture.width * mat.mainTextureScale.x + mat.mainTextureOffset.x * uncompressedTexture.width);
                int yOffset = (int)(meshUVBounds.yMin * uncompressedTexture.height * mat.mainTextureScale.y + mat.mainTextureOffset.y * uncompressedTexture.height);

                int i = 0, j = 0;
                if (xSens < 0 || ySens < 0 || ((!mainColor.Equals(Color.white)) && isMainTexture))
                {
                    for (i = 0; i < copy.width; i++)
                    {
                        for (j = 0; j < copy.height; j++)
                        {
                            copy.SetPixel(i, j, uncompressedTexture.GetPixel(xSens * (i + xOffset) % uncompressedTexture.width, ySens * (j + yOffset) % uncompressedTexture.height) * mainColor);
                        }
                    }
                }
                else
                {
                    int blockWidth = 0, blockHeight = 0;
                    while (i < copy.width)
                    {
                        int posx = (xSens * (i + xOffset) % uncompressedTexture.width + uncompressedTexture.width) % uncompressedTexture.width;
                        blockWidth = (i + uncompressedTexture.width <= copy.width) ? uncompressedTexture.width : copy.width - i;
                        if (posx + blockWidth > uncompressedTexture.width)
                        {
                            blockWidth = uncompressedTexture.width - posx;
                        }
                        while (j < copy.height)
                        {
                            int posy = (ySens * (j + yOffset) % uncompressedTexture.height + uncompressedTexture.height) % uncompressedTexture.height;
                            blockHeight = (j + uncompressedTexture.height <= copy.height) ? uncompressedTexture.height : copy.height - j;
                            if (posy + blockHeight > uncompressedTexture.height)
                            {
                                blockHeight = uncompressedTexture.height - posy;
                            }
                            copy.SetPixels(i, j, blockWidth, blockHeight, uncompressedTexture.GetPixels(posx, posy, blockWidth, blockHeight));
                            j += blockHeight;
                        }
                        j  = 0;
                        i += blockWidth;
                    }
                }
            }
            else
            {
                if (mainColor.Equals(Color.white) || !isMainTexture)
                {
                    // UVs are all inside [0, 1] bound, so we can fast copy this texture
                    copy.LoadRawTextureData(uncompressedTexture.GetRawTextureData());
                }
                else
                {
                    for (int i = 0; i < copy.width; i++)
                    {
                        for (int j = 0; j < copy.height; j++)
                        {
                            copy.SetPixel(i, j, uncompressedTexture.GetPixel(i, j) * mainColor);
                        }
                    }
                }
            }
            return(copy);
        }