soimy / maxrects-packer

A max rectangle 2d bin packer npm-module for packing glyphs or images into multiple sprite-sheet/atlas

Home Page:https://soimy.github.io/maxrects-packer/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Grouping rectangles to single bin

tionkje opened this issue · comments

I have a set of rectangles that have to be packed into some bins.
But there are some rects that have to be together in the same bin (to prevent multiple textures in a shader)

Is there a way to achieve this using tags?
I noticed currently each tag creates a new bin, and a bin with a tag does not accept any untagged rects.

Yes, I think we don't have that feature yet. Currently, rect without tag will have a defaut bin tag, thus tagged rects will not packed into the defaut bins.

It will be epic if it is implemented. My use case is packing animated sprites into atlases, but not spreading any animation over multiple atlases.

I have some heuristics in mind that might help with this job, but I need to check whether an array of rectangles may fit into the current bin prior to actually adding them. Maybe I can do it with packer.save() method. Will share the results later once I flesh out my alorithm.

Implemented on branch https://github.com/soimy/maxrects-packer/tree/non-exclusive-tag
introducing new packer option exclusiveTag, if set to false, packer will try to pack sprites with the same tag into the same bin, if all bin cannot fit, new bin is created.

Test needed @CosmoMyzrailGorynych @tionkje

This feature is merged in the new 2.7.0 version, just update maxrects-packer

Ok, here is the "comparison". Both cases use the same set of sprites. Restrictions:

First case — 2048x2048 atlases.

It is expected that there will be a lot of backgrounds alone in separate atlases, as they have padding and two of them won't fit.

My approach: (13 bins)

2020-09-17_13-38

https://github.com/soimy/maxrects-packer/tree/non-exclusive-tag (12 bins)

2020-09-17_13-21

Okay, this case sucks, now:

Second case — 4kx4k bins

My approach (2 bins):

2020-09-17_13-40

https://github.com/soimy/maxrects-packer/tree/non-exclusive-tag (2 bins):

2020-09-17_13-26

Observations

Both methods seem to work. My method seems to be more space-efficient with sprites relatively smaller than the bin's size.

There is no sorting algorithm across numerous tags in https://github.com/soimy/maxrects-packer/tree/non-exclusive-tag (using
b4827b8 commit), or there is something wrong with it. See the 4kx4k case. We clearly see that the a0 atlas (on the left) could contain all the coins, flags, diamons, and keys (they all have different tags), and probably all the aliens, too. It seems that it creates a new bin after the first failure, skipping all the smaller rectangles. I feel that a combination of very wide and very long sprites will make unreasonably large amount of bins (will try to do so soon).

Ok so I set up that "extreme" case with horizontal/vertical sprites:

3 boxes of 2000x64 size and 3 rects of 64x2000 (blue ones).
2 rects of 1800x64 and 2 of 64x1800 (pink ones).
Each rect is tagged, but each rects' tag is unique.
Bins are restricted to be at max 2048x2048 pixels.

Here is how I created them: one vertical, one horizontal, one vertical, one horizontal...

A simple solution is putting all the vertical rects in one bin, and the horizontal ones — into another. We can get 2 bins this way.

The results

They both are awful.

Upper images — v2.7.0, bottom images — my approach. Both produce 4 bins.

In v2.7.0, all the images are added through packer.addArray(blocks); in one go.

изображение

And here is the packed result without tagging at all:
изображение

Thanks, @CosmoMyzrailGorynych ! Very detailed testing.
Currently, I do not have time to do any practical case test so yours is really helpful!.

New tweak on logic by commit 8b59925, let's see it will make any difference.

I just adopted this new feature into my Repo https://github.com/soimy/atlasify by adding new option --group-folder. Everything working as expected so far.

fix: Non-exclusive tag logic: Restart test iteration on next tag group
изображение

:D

Testing 8b59925

"Extreme" case with very long/very tall images:

2020-09-18_09-24

Perfect 👌

Aliens and ships, 2k×2k

2020-09-18_09-25

11 atlases, it is an improvement if compared to the previous 12 atlases from v2.7.0. 👍

Aliens and ships, 4k×4k

2020-09-18_09-36

Does the job in a pretty optimal way 👏

Summary

Great work 👏 I feel it is time to ship 8b59925 and close this issue 🚀