├── README.md ├── example.html └── rectpack.js /README.md: -------------------------------------------------------------------------------- 1 | ## RectPack – Super Simple Rectangle Packing for JS 2 | 3 | An extremly simple yet reasonably fast rectangle packing utility. This can be 4 | used to pack textures into an atlas. 5 | 6 | ### Demo 7 | 8 | See `example.html` for a [demo](https://phoboslab.org/files/rectpack/). 9 | 10 | ### Synopsis 11 | 12 | ```js 13 | // Create a new bucket with 512x512 14 | let rp = new RectPack(512, 512); 15 | 16 | // Insert one rect at the "best" position 17 | let packed = rp.insert(32, 16); 18 | if (packed) { 19 | console.log('inserted at', packed.x, packed.y); 20 | } 21 | 22 | // Remove all rects 23 | rp.clear(); 24 | 25 | ``` 26 | 27 | If you're packing textures, consider dividing the bucket size and the sizes 28 | of the rects to be inserted by `128` or whatever your minimum texture size is. 29 | The size of the bucket (specifically the width) is directly proportional to the 30 | insertion time. 31 | 32 | ### Why 33 | 34 | This is not the most effecient or fastest algorithm, but it's tiny, simple and 35 | gets the job done. 36 | 37 | -------------------------------------------------------------------------------- /example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /rectpack.js: -------------------------------------------------------------------------------- 1 | /* 2 | == RectPack – Super Simple Rectangle Packing for JS 3 | 4 | Dominic Szablewski - https://phoboslab.org 5 | 6 | -- LICENSE: The MIT License(MIT) 7 | Copyright(c) 2021 Dominic Szablewski 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | this software and associated documentation files(the "Software"), to deal in 10 | the Software without restriction, including without limitation the rights to 11 | use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies 12 | of the Software, and to permit persons to whom the Software is furnished to do 13 | so, subject to the following conditions : 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | class RectPack { 26 | constructor(width, height) { 27 | this.width = width; 28 | this.height = height; 29 | this.grid = new Uint32Array(width); 30 | } 31 | 32 | insert(width, height) { 33 | let bestX = 0; 34 | let bestY = this.height - height + 1; 35 | 36 | for (let x = 0; x < this.width - width; x++) { 37 | let cy = this.grid[x]; 38 | let isBest = true; 39 | for (let bx = x; bx < x + width; bx++) { 40 | if (this.grid[bx] > bestY) { 41 | isBest = false; 42 | x = bx; 43 | break; 44 | } 45 | if (this.grid[bx] > cy) { 46 | cy = this.grid[bx]; 47 | } 48 | } 49 | if (isBest) { 50 | bestX = x; 51 | bestY = cy; 52 | } 53 | } 54 | 55 | if (bestY + height < this.height) { 56 | for (let x = bestX; x < bestX + width; x++) { 57 | this.grid[x] = bestY + height; 58 | } 59 | return {x: bestX, y: bestY}; 60 | } 61 | else { 62 | return null; 63 | } 64 | } 65 | 66 | clear() { 67 | this.grid.fill(0); 68 | } 69 | } 70 | --------------------------------------------------------------------------------