示例#1
0
            public void Place(PlacingTexture p)
            {
                if (occupant != null || first != null) throw new InvalidOperationException();
                if (p.CorrectedWidth > width || p.CorrectedHeight > height) throw new InvalidOperationException();

                if (p.CorrectedWidth == width)
                {
                    if (p.CorrectedHeight == height)
                    {
                        occupant = p;
                    }
                    else
                    {
                        SplitY(p.CorrectedHeight);
                        first.Place(p);
                    }
                }
                else
                {
                    if (p.CorrectedHeight == height)
                    {
                        SplitX(p.CorrectedWidth);
                        first.Place(p);
                    }
                    else
                    {
                        int diff_w = width - p.CorrectedWidth;
                        int diff_h = height - p.CorrectedHeight;
                        if (diff_w >= diff_h)
                        {
                            SplitX(p.CorrectedWidth);
                            first.Place(p);
                        }
                        else
                        {
                            SplitY(p.CorrectedHeight);
                            first.Place(p);
                        }
                    }
                }
            }
示例#2
0
        private List<PlacingTexture> PlaceAllTextures(out int width, out int height)
        {
            // Divides space using a binary tree and places textures in nodes containing enough room.
            // http://www.blackpawn.com/texts/lightmaps/

            List<PlacingTexture> result = new List<PlacingTexture>(m_textures.Count);
            long pixelcount = 0;
            int max_width = 0;
            int max_height = 0;
            int y = 0;

            foreach (LoadingTexture l in m_textures)
            {
                PlacingTexture p = new PlacingTexture(l);
                max_width = Math.Max(max_width, p.CorrectedWidth);
                max_height = Math.Max(max_height, p.CorrectedHeight);
                pixelcount += p.Area;
                p.index = y;
                result.Add(p);
                y++;
            }

            // sort by area descending
            result.Sort((p, q) => q.Area.CompareTo(p.Area));

            int min_width = Math.Max(max_width, MinWidth);
            int min_height = Math.Max(max_height, MinHeight);
            int guess_width, guess_height;
            if (MinWidth == 0 && MinHeight == 0)
            {
                guess_width = (int)(Math.Sqrt(pixelcount * 2.0d) + 1);
                guess_height = Math.Max(min_height, guess_width);
                guess_width = Math.Max(min_width, guess_width);
            }
            else if (MinWidth == 0)
            {
                guess_width = Math.Max((int)(pixelcount / min_height), min_width);
                guess_height = min_height;
            }
            else if (MinHeight == 0)
            {
                guess_width = min_width;
                guess_height = Math.Max((int)(pixelcount / MinWidth), min_height);
            }
            else
            {
                guess_width = min_width;
                guess_height = min_height;
            }

            int real_max_width = MaxWidth;
            int real_max_height = MaxHeight;

            if (RequirePot)
            {
                guess_width = 1 << (MathHelper.Log2(guess_width));
                guess_height = 1 << (MathHelper.Log2(guess_height));

                real_max_width = 1 << (MathHelper.Log2(MaxWidth));
                real_max_height = 1 << (MathHelper.Log2(MaxHeight));
            }

            if (guess_width == 0) guess_width = guess_height;
            if (guess_width == 0)
            {
                guess_width = 512;
                guess_height = 512;
            }

            PlacingNode root = new PlacingNode(0, 0, guess_width, guess_height);
            for (int x = 0; x < result.Count; x++)
            {
                PlacingTexture p = result[x];
                PlacingNode node = root.FindPlacement(p);
                if (node == null)
                {
                    if (guess_width <= guess_height && (guess_width < real_max_width || real_max_width == 0))
                        guess_width = 1 << (MathHelper.Log2(guess_width) + 1);
                    else if (guess_height < real_max_height || real_max_height == 0)
                        guess_height = 1 << (MathHelper.Log2(guess_height) + 1);
                    else if (guess_width < real_max_width || real_max_width == 0)
                        guess_width = 1 << (MathHelper.Log2(guess_width) + 1);
                    else
                        throw new Exception("No room left to place textures.");

                    AssertHelper.Assert(guess_width > root.width || guess_height > root.height);
                    PlacingNode new_root = new PlacingNode(guess_width, guess_height);
                    if (guess_width > root.width)
                    {
                        AssertHelper.Assert(guess_height == root.height);
                        new_root.first = root;
                        new_root.second = new PlacingNode(root.width, 0, guess_width - root.width, root.height);
                    }
                    else
                    {
                        AssertHelper.Assert(guess_width == root.width);
                        new_root.first = root;
                        new_root.second = new PlacingNode(0, root.height, root.width, guess_height - root.height);
                    }
                    root = new_root;

                    x--;
                    continue;
                }

                node.Place(p);
                p.X = node.x;
                p.Y = node.y;
                result[x] = p;
            }

            width = root.width;
            height = root.height;
            result.Sort((p, q) => p.index.CompareTo(q.index));

            return result;
        }
示例#3
0
            public PlacingNode FindPlacement(PlacingTexture p)
            {
                // finds the best spot to put this texture, returns it.
                // returns null if this texture can't fit.
                if (occupant != null) return null;
                if (first != null)
                {
                    PlacingNode n1 = first.FindPlacement(p);

                    if (n1 == null) return second.FindPlacement(p);
                    return n1;
                }
                else
                {
                    if (width < p.CorrectedWidth || height < p.CorrectedHeight) return null;
                    return this;
                }
            }
示例#4
0
        private void DrawPlacingTexture(System.Drawing.Graphics g, PlacingTexture p)
        {
            bool draw_topleft_margin = p.LoadingTexture.PaddingFill != PaddingFill.None && p.LoadingTexture.TexelPosition != TexelPosition.Stretch && p.LoadingTexture.TexelPosition != TexelPosition.TopLeft;
            bool draw_bottomright_margin = p.LoadingTexture.PaddingFill != PaddingFill.None && p.LoadingTexture.TexelPosition != TexelPosition.Stretch;

            int offset_topleft = draw_topleft_margin ? 1 : 0;
            // draw the actual texture
            g.DrawImage(p.LoadingTexture.Bitmap, p.X + offset_topleft, p.Y + offset_topleft, p.LoadingTexture.Bitmap.Width, p.LoadingTexture.Bitmap.Height);

            switch (p.LoadingTexture.PaddingFill)
            {
                case PaddingFill.Wrap:
                    if (draw_topleft_margin)
                    {
                        // left
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X, p.Y + 1, 1, p.LoadingTexture.Bitmap.Height), new Rectangle(p.LoadingTexture.Bitmap.Width - 1, 0, 1, p.LoadingTexture.Bitmap.Height), GraphicsUnit.Pixel);
                        // top
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X + 1, p.Y, p.LoadingTexture.Bitmap.Width, 1), new Rectangle(0, p.LoadingTexture.Bitmap.Height - 1, p.LoadingTexture.Bitmap.Width, 1), GraphicsUnit.Pixel);
                        // topleft pixel
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X, p.Y, 1, 1), new Rectangle(p.LoadingTexture.Bitmap.Width - 1, p.LoadingTexture.Bitmap.Height - 1, 1, 1), GraphicsUnit.Pixel);

                        AssertHelper.Assert(draw_bottomright_margin);
                        // bottomleft pixel
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X, p.Y + p.LoadingTexture.Bitmap.Height + 1, 1, 1), new Rectangle(p.LoadingTexture.Bitmap.Width - 1, 0, 1, 1), GraphicsUnit.Pixel);
                        // topright pixel
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X + p.LoadingTexture.Bitmap.Width + 1, p.Y, 1, 1), new Rectangle(0, p.LoadingTexture.Bitmap.Height - 1, 1, 1), GraphicsUnit.Pixel);
                    }

                    if (draw_bottomright_margin)
                    {
                        // right
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X + p.LoadingTexture.Bitmap.Width + offset_topleft, p.Y + offset_topleft, 1, p.LoadingTexture.Bitmap.Height), new Rectangle(0, 0, 1, p.LoadingTexture.Bitmap.Height), GraphicsUnit.Pixel);
                        // bottom
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X + offset_topleft, p.Y + p.LoadingTexture.Bitmap.Height + offset_topleft, p.LoadingTexture.Bitmap.Width, 1), new Rectangle(0, 0, p.LoadingTexture.Bitmap.Width, 1), GraphicsUnit.Pixel);
                        // bottomright pixel
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X + p.LoadingTexture.Bitmap.Width + offset_topleft, p.Y + p.LoadingTexture.Bitmap.Height + offset_topleft, 1, 1), new Rectangle(0, 0, 1, 1), GraphicsUnit.Pixel);
                    }
                    break;
                case PaddingFill.Clamp:
                    if (draw_topleft_margin)
                    {
                        // left
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X, p.Y + 1, 1, p.LoadingTexture.Bitmap.Height), new Rectangle(0, 0, 1, p.LoadingTexture.Bitmap.Height), GraphicsUnit.Pixel);
                        // top
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X + 1, p.Y, p.LoadingTexture.Bitmap.Width, 1), new Rectangle(0, 0, p.LoadingTexture.Bitmap.Width, 1), GraphicsUnit.Pixel);
                        // topleft pixel
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X, p.Y, 1, 1), new Rectangle(0, 0, 1, 1), GraphicsUnit.Pixel);

                        AssertHelper.Assert(draw_bottomright_margin);
                        // bottomleft pixel
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X, p.Y + p.LoadingTexture.Bitmap.Height + 1, 1, 1), new Rectangle(0, p.LoadingTexture.Bitmap.Height - 1, 1, 1), GraphicsUnit.Pixel);
                        // topright pixel
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X + p.LoadingTexture.Bitmap.Width + 1, p.Y, 1, 1), new Rectangle(p.LoadingTexture.Bitmap.Width - 1, 0, 1, 1), GraphicsUnit.Pixel);
                    }

                    if (draw_bottomright_margin)
                    {
                        // right
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X + p.LoadingTexture.Bitmap.Width + offset_topleft, p.Y + offset_topleft, 1, p.LoadingTexture.Bitmap.Height), new Rectangle(p.LoadingTexture.Bitmap.Width - 1, 0, 1, p.LoadingTexture.Bitmap.Height), GraphicsUnit.Pixel);
                        // bottom
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X + offset_topleft, p.Y + p.LoadingTexture.Bitmap.Height + offset_topleft, p.LoadingTexture.Bitmap.Width, 1), new Rectangle(0, p.LoadingTexture.Bitmap.Height - 1, p.LoadingTexture.Bitmap.Width, 1), GraphicsUnit.Pixel);
                        // bottomright pixel
                        g.DrawImage(p.LoadingTexture.Bitmap, new Rectangle(p.X + p.LoadingTexture.Bitmap.Width + offset_topleft, p.Y + p.LoadingTexture.Bitmap.Height + offset_topleft, 1, 1), new Rectangle(p.LoadingTexture.Bitmap.Width - 1, p.LoadingTexture.Bitmap.Height - 1, 1, 1), GraphicsUnit.Pixel);
                    }
                    break;
                case PaddingFill.Solid:
                    Brush brush = new SolidBrush(p.LoadingTexture.PaddingColour);

                    if (draw_topleft_margin)
                    {
                        // left
                        g.FillRectangle(brush, new Rectangle(p.X, p.Y + 1, 1, p.LoadingTexture.Bitmap.Height));
                        // top
                        g.FillRectangle(brush, new Rectangle(p.X + 1, p.Y, p.LoadingTexture.Bitmap.Width, 1));
                        // topleft pixel
                        g.FillRectangle(brush, new Rectangle(p.X, p.Y, 1, 1));

                        AssertHelper.Assert(draw_bottomright_margin);
                        // bottomleft pixel
                        g.FillRectangle(brush, new Rectangle(p.X, p.Y + p.LoadingTexture.Bitmap.Height + 1, 1, 1));
                        // topright pixel
                        g.FillRectangle(brush, new Rectangle(p.X + p.LoadingTexture.Bitmap.Width + 1, p.Y, 1, 1));
                    }

                    if (draw_bottomright_margin)
                    {
                        // right
                        g.FillRectangle(brush, new Rectangle(p.X + p.LoadingTexture.Bitmap.Width + offset_topleft, p.Y + offset_topleft, 1, p.LoadingTexture.Bitmap.Height));
                        // bottom
                        g.FillRectangle(brush, new Rectangle(p.X + offset_topleft, p.Y + p.LoadingTexture.Bitmap.Height + offset_topleft, p.LoadingTexture.Bitmap.Width, 1));
                        // bottomright pixel
                        g.FillRectangle(brush, new Rectangle(p.X + p.LoadingTexture.Bitmap.Width + offset_topleft, p.Y + p.LoadingTexture.Bitmap.Height + offset_topleft, 1, 1));
                    }
                    break;
            }
        }