Ejemplo n.º 1
0
        /// <summary>
        /// Creates an atlas with the given TexImage.
        /// </summary>
        /// <param name="textureList">The texture list.</param>
        /// <param name="forceSquaredAtlas">boolean to decide wheter the atlas will be squared (default is false).</param>
        /// <returns>An instance of <see cref="TexAtlas"/>.</returns>
        /// <exception cref="TextureToolsException">No available library could create the atlas.</exception>
        public TexAtlas CreateAtlas(List<TexImage> textureList, bool forceSquaredAtlas = false)
        {
            TexAtlas atlas = new TexAtlas();
            AtlasCreationRequest request = new AtlasCreationRequest(textureList, forceSquaredAtlas);

            ITexLibrary library = FindLibrary(atlas, request);
            if(library == null)
            {
                Log.Error("No available library could create the atlas.");
                throw new TextureToolsException("No available library could create the atlas.");
            }

            atlas.Format = textureList[0].Format;
            foreach (TexImage texture in textureList)
            {
                if (texture.Format != atlas.Format)
                {
                    Log.Error("The textures in the list must all habe the same format.");
                    throw new TextureToolsException("The textures in the list must all habe the same format.");
                }
                texture.Update();
            }

            ExecuteRequest(atlas, request);

            return atlas;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates an atlas.
        /// </summary>
        /// <param name="atlas">The atlas.</param>
        /// <param name="request">The request.</param>
        /// <param name="atlasSizeIncrement">An indice used to increment the atlas size</param>
        public void Create(TexAtlas atlas, AtlasCreationRequest request, int atlasSizeIncrement)
        {
            Log.Info("Creating atlas ...");

            // Initalizing Atlas : trying to determine the minimum atlas size and allocating the needed memory
            InitalizeAtlas(atlas, request, atlasSizeIncrement);

            // Ordering textures in decreasing order : best heuristic with this algorithm.
            if (atlasSizeIncrement == 0) OrderTexture(request);

            // Finding the best layout for the textures in the atlas 
            Node tree = PositionTextures(atlas, request);

            // One of many textures couldn't be positioned which means the atlas is too small
            if (tree == null)
            {
                Marshal.FreeHGlobal(atlas.Data);
                Create(atlas, request, atlasSizeIncrement + 1);
            }
            else
            {
                // Everything went well, we can copy the textures data into the atlas
                CopyTexturesIntoAtlasMemory(tree, atlas);

                // Creating the atlas data
                CreateAtlasData(tree, atlas, request.TextureList.Count);
            }
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Orders the textures list in decreasing size.
 /// </summary>
 /// <param name="request">The request.</param>
 private void OrderTexture(AtlasCreationRequest request)
 {
     QuickSort(request.TextureList, 0, request.TextureList.Count - 1);
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Determines the positions of the textures in the Atlas.
        /// </summary>
        /// <param name="atlas">The atlas.</param>
        /// <param name="request">The request.</param>
        /// <returns>The binary tree containing the positioned textures or null if the atlas is too small.</returns>
        private Node PositionTextures(TexAtlas atlas, AtlasCreationRequest request)
        {
            Node root = new Node(0, 0, atlas.Width, atlas.Height);

            foreach (TexImage texture in request.TextureList)
            {
                if (!Insert(root, texture))
                {
                    return null;
                }
            }

            return root;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Initalizes the atlas. Predictes the minimum size required by the atlas according to the textures
        /// </summary>
        /// <param name="atlas">The atlas.</param>
        /// <param name="request">The request.</param>
        private void InitalizeAtlas(TexAtlas atlas, AtlasCreationRequest request, int atlasSizeIncrement)
        {
            // Calculating the total number of pixels of every texture to be included
            int pixelCount = 0;
            bool hasMipMap = false;
            foreach (TexImage texture in request.TextureList)
            {
                pixelCount += texture.Width * texture.Height;
                if (texture.MipmapCount > 1) hasMipMap = true;
            }

            // setting the new size to the atlas
            int alpha = (int)Math.Log(pixelCount, 2) + 1 + atlasSizeIncrement;
            atlas.Width = (int)Math.Pow(2, alpha / 2);
            atlas.Height = (int)Math.Pow(2, alpha - alpha / 2);

            // If we want a square texture, we compute the max of the width and height and assign it to both
            if (request.ForceSquaredAtlas)
            {
                int size = Math.Max(atlas.Width, atlas.Height);
                atlas.Width = size;
                atlas.Height = size;
            }

            // Setting the TexImage features
            int rowPitch, slicePitch;
            Tools.ComputePitch(atlas.Format, atlas.Width, atlas.Height, out rowPitch, out slicePitch);
            atlas.RowPitch = rowPitch;
            atlas.SlicePitch = slicePitch;

            // Allocating memory
            if (hasMipMap)
            {
                int dataSize = 0;
                int mipmapCount = 0;
                int w, h;
                List<TexImage.SubImage> subImages = new List<TexImage.SubImage>();

                w = atlas.Width;
                h = atlas.Height;  

                while (w != 1 || h != 1)
                {
                    Tools.ComputePitch(atlas.Format, w, h, out rowPitch, out slicePitch);
                    subImages.Add(new TexImage.SubImage()
                    {
                        Data = IntPtr.Zero,
                        DataSize = slicePitch,
                        Width = w,
                        Height = h,
                        RowPitch = rowPitch,
                        SlicePitch = slicePitch,
                    });

                    dataSize += slicePitch;
                    ++mipmapCount;

                    w = w > 1 ? w >>= 1 : w;
                    h = h > 1 ? h >>= 1 : h;
                }

                atlas.DataSize = dataSize;
                atlas.Data = Marshal.AllocHGlobal(atlas.DataSize);

                atlas.SubImageArray = subImages.ToArray();

                int offset = 0;
                for (int i = 0; i < atlas.SubImageArray.Length; ++i)
                {
                    atlas.SubImageArray[i].Data = new IntPtr(atlas.Data.ToInt64() + offset);
                    offset += atlas.SubImageArray[i].DataSize;
                }
                atlas.MipmapCount = mipmapCount;
            }
            else
            {
                atlas.DataSize = atlas.SlicePitch;
                atlas.Data = Marshal.AllocHGlobal(atlas.DataSize);

                atlas.SubImageArray[0].Data = atlas.Data;
                atlas.SubImageArray[0].DataSize = atlas.DataSize;
                atlas.SubImageArray[0].Width = atlas.Width;
                atlas.SubImageArray[0].Height = atlas.Height;
                atlas.SubImageArray[0].RowPitch = rowPitch;
                atlas.SubImageArray[0].SlicePitch = slicePitch;
            }

            atlas.DisposingLibrary = this;
        }