Ejemplo n.º 1
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.º 2
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.º 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>
        /// 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;
        }