All Projects → TeamHypersomnia → Rectpack2d

TeamHypersomnia / Rectpack2d

Licence: mit
A header-only, quite efficient rectangle packing library.

Projects that are alternatives of or similar to Rectpack2d

Smartbreadcrumbs
A utility library for ASP.NET Core (both MVC and Razor Pages) websites to easily add and customize breadcrumbs.
Stars: ✭ 113 (-36.16%)
Mutual labels:  utility-library
Notils
Never again need a .utils. package yur scurvy sea dogs!
Stars: ✭ 126 (-28.81%)
Mutual labels:  utility-library
Utils
Ruby core extentions and class utilities for Hanami
Stars: ✭ 159 (-10.17%)
Mutual labels:  utility-library
Openmvs
open Multi-View Stereo reconstruction library
Stars: ✭ 1,842 (+940.68%)
Mutual labels:  texture
Grained
Generate animated noise texture with grained.js
Stars: ✭ 122 (-31.07%)
Mutual labels:  texture
Mmtexturechat
AsyncDisplayKit(Texture) Smooth Scroll Chat Simulation for Whatsapp and iMessage
Stars: ✭ 149 (-15.82%)
Mutual labels:  texture
Counter culture
Turbo-charged counter caches for your Rails app.
Stars: ✭ 1,397 (+689.27%)
Mutual labels:  utility-library
Nvjob Water Shader Simple And Fast
#NVJOB Simple Water Shaders. Free Unity Asset.
Stars: ✭ 172 (-2.82%)
Mutual labels:  texture
Adversarialtexture
Adversarial Texture Optimization from RGB-D Scans (CVPR 2020).
Stars: ✭ 124 (-29.94%)
Mutual labels:  texture
Awesome Pytorch List
A comprehensive list of pytorch related content on github,such as different models,implementations,helper libraries,tutorials etc.
Stars: ✭ 12,475 (+6948.02%)
Mutual labels:  utility-library
Pex Context
Modern WebGL state wrapper for PEX: allocate GPU resources (textures, buffers), setup state pipelines and passes, and combine them into commands.
Stars: ✭ 117 (-33.9%)
Mutual labels:  texture
Cube2sphere
Python script to map 6 cube (cubemap, skybox) faces into an equirectangular (cylindrical projection, skysphere) map.
Stars: ✭ 120 (-32.2%)
Mutual labels:  texture
Unity Texture Curve
✏️ Example showing how to bake an AnimatedCurve into a Texture and use it in a shader.
Stars: ✭ 149 (-15.82%)
Mutual labels:  texture
Rxasdatasources
RxDataSource for AsyncDisplayKit/Texture
Stars: ✭ 114 (-35.59%)
Mutual labels:  texture
Patches
Patches is a visual programming editor for building WebVR and WebGL experiences.
Stars: ✭ 164 (-7.34%)
Mutual labels:  texture
Textureswiftsupport
A library to gain us the DSL to define layout spec in Texture [like SwiftUI]
Stars: ✭ 105 (-40.68%)
Mutual labels:  texture
Gltfforue4
Import glTF 2.0 in Unreal Engine
Stars: ✭ 145 (-18.08%)
Mutual labels:  texture
Ui Components
Most used UI Components — of web applications. Curated/Most loved components for web development
Stars: ✭ 175 (-1.13%)
Mutual labels:  utility-library
Threejs Path Flow
🐬🐟 ↶Mesh Deformation / Bending / Following on a Curve
Stars: ✭ 165 (-6.78%)
Mutual labels:  texture
React Children Utilities
Extended utils for ⚛️ React.Children data structure that adds recursive filter, map and more methods to iterate nested children.
Stars: ✭ 154 (-12.99%)
Mutual labels:  utility-library

If you are looking for the old version of rectpack2D, it can still be found in a legacy branch.

rectpack2D

Build Status Appveyor Build Status

Table of contents:

Rectangle packing library (no longer tiny!).
This is a refactored and highly optimized branch of the original library which is easier to use and customize.
It was originally developed for the needs of Hypersomnia, a free and open-source multiplayer shooter.

7

Benchmarks

Tests were conducted on a Intel(R) Core(TM) i7-4770K CPU @ 3.50GHz.
The binary was built with clang 6.0.0, using an -03 switch.

Arbitrary game sprites: 582 subjects.

Runtime: 0.8 ms
Wasted pixels: 10982 (0.24% - equivalent of a 105 x 105 square)

Output (1896 x 2382):

1

In color:
(black is wasted space)

2

Arbitrary game sprites + Japanese glyphs: 3264 subjects.

Runtime: 4 ms
Wasted pixels: 15538 (0.31% - equivalent of a 125 x 125 square)

Output (2116 x 2382):

3

In color:
(black is wasted space)

4

Japanese glyphs + some GUI sprites: 3122 subjects.

Runtime: 3.5 - 7 ms
Wasted pixels: 9288 (1.23% - equivalent of a 96 x 96 square)

Output (866 x 871):

5

In color:
(black is wasted space)

6

Usage

This is a header-only library. Just include the src/finders_interface.h and you should be good to go.

For an example use, see example/main.cpp.

Building the example

Windows

From the repository's folder, run:

mkdir build
cd build
cmake -G "Visual Studio 15 2017 Win64" ..

Then just build the generated .sln file using the newest Visual Studio Preview.

Linux

From the repository's folder, run:

cmake/build_example.sh Release gcc g++
cd build/current
ninja run

Or, if you want to use clang, run:

cmake/build_example.sh Release clang clang++
cd build/current
ninja run

Algorithm

Insertion algorithm

The library started as an implementation of this algorithm:

http://blackpawn.com/texts/lightmaps/default.html

The current version somewhat derives from the concept described there -
however, it uses just a vector of empty spaces, instead of a tree - this turned out to be a performance breakthrough.

Given

struct rect_xywh {
	int x;
	int y;
	int w;
	int h;
};

Let us create a vector and call it empty_spaces.

std::vector<rect_xywh> empty_spaces;

Given a user-specified initial bin, which is a square of some size S, we initialize the first empty space.

empty_spaces.push_back(rect_xywh(0, 0, S, S));

Now, we'd like to insert the first image rectangle.

To do this, we iterate the vector of empty spaces backwards and look for an empty space into which the image can fit.
For now, we only have the S x S square: let's save the index of this candidate empty space,
which is candidate_space_index = 0;

If our image is strictly smaller than the candidate space, we have something like this:

diag01

The blue is our image rectangle.
We now calculate the gray rectangles labeled as "bigger split" and "smaller split",
and save them like this:

// Erase the space that we've just inserted to, by swapping and popping.
empty_spaces[candidate_space_index] = empty_spaces.back();
empty_spaces.pop_back();

// Save the resultant splits
empty_spaces.push_back(bigger_split);
empty_spaces.push_back(smaller_split);

Notice that we push the smaller split after the bigger one.
This is fairly important, because later the candidate images will encounter the smaller splits first,
which will make better use of empty spaces overall.

Corner cases:

  • If the image dimensions equal the dimensions of the candidate empty space (image fits exactly),
    • we just delete the space and create no splits.
  • If the image fits into the candidate empty space, but exactly one of the image dimensions equals the respective dimension of the candidate empty space (e.g. image = 20x40, candidate space = 30x40)
    • we delete the space and create a single split. In this case a 10x40 space.

To see the complete, modular procedure for calculating the splits (along with the corner cases), see this source.

If the insertion fails, we also try the same procedure for a flipped image.

Additional heuristics

Now we know how to insert individual images into a bin of a given initial size S.

  1. However, what S should be passed to the algorithm so that the rectangles end up wasting the least amount of space?
    • We perform a binary search.
      • We start with the size specified by the library user. Typically, it would be the maximum texture size allowed on a particular GPU.
      • If the packing was successful on the given bin size, decrease the size and try to pack again.
      • If the packing has failed on the given bin size - because some rectangles could not be further inserted - increase the size and try to pack again.
    • The search is aborted if we've successfully inserted into a bin and the dimensions of the next candidate would differ from the previous by less than discard_step.
      • This variable exists so that we may easily trade accuracy for a speedup. discard_step = 1 yields the highest accuracy. discard_step = 128 will yield worse packings, but will be a lot faster, etc.
    • The search is performed first by decreasing the bin size by both width and height, keeping it in square shape.
      • Then we do the same, but only decreasing width.
      • Then we do the same, but only decreasing height.
      • The last two were a breakthrough in packing tightness. It turns out important to consider non-square bins.
  2. In what order should the rectangles be inserted so that they pack the tightest?
    • By default, the library tries 6 decreasing orders:
      • By area.
      • By perimeter.
      • By the bigger side.
      • By width.
      • By height.
      • By 'a pathological multiplier": max(w, h) / min(w, h) * w * h
        • This makes some giant, irregular mutants always go first, which is good, because it doesn't shred our empty spaces to a lot of useless pieces.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].