initial commit
This commit is contained in:
commit
40636632af
6 changed files with 216 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
build/
|
||||
recovery/
|
||||
BeefSpace_User.toml
|
6
BeefProj.toml
Normal file
6
BeefProj.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
FileVersion = 1
|
||||
|
||||
[Project]
|
||||
Name = "Paka"
|
||||
TargetType = "BeefLib"
|
||||
StartupObject = "Paka.Program"
|
5
BeefSpace.toml
Normal file
5
BeefSpace.toml
Normal file
|
@ -0,0 +1,5 @@
|
|||
FileVersion = 1
|
||||
Projects = {Paka = {Path = "."}}
|
||||
|
||||
[Workspace]
|
||||
StartupProject = "Paka"
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 Jannis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
2
README.md
Normal file
2
README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Paka
|
||||
Pack rectangles
|
179
src/Paka.bf
Normal file
179
src/Paka.bf
Normal file
|
@ -0,0 +1,179 @@
|
|||
namespace Paka;
|
||||
using System.Collections;
|
||||
/*-----------------------------------------------------------------
|
||||
This is an implementation of the following algorithm by blackpawn, slightly adapted to support sized rectangles:
|
||||
https://blackpawn.com/texts/lightmaps/default.html
|
||||
-----------------------------------------------------------------*/
|
||||
class Paka
|
||||
{
|
||||
public struct PakaRectangle
|
||||
{
|
||||
public int64 id;
|
||||
public int64 x = 0;
|
||||
public int64 y = 0;
|
||||
public int64 width;
|
||||
public int64 height;
|
||||
|
||||
public this(int64 pId = 0, int64 pW = 32, int64 pH = 32)
|
||||
{
|
||||
id = pId;
|
||||
width = pW;
|
||||
height = pH;
|
||||
}
|
||||
}
|
||||
|
||||
//This stores all rectangles being input
|
||||
List<PakaRectangle> Rects = new .(20) ~ delete _; //20 rects should be a resonable base for this type of thing
|
||||
|
||||
//Only used internally in order for the node structure to work correctly
|
||||
private class PakaNode
|
||||
{
|
||||
public PakaRectangle Size = .(-1);
|
||||
public int64[4] Rect = .();
|
||||
public PakaNode[2] Nodes = .(null, null);
|
||||
|
||||
public this() {}
|
||||
public this(int64 width, int64 height) {
|
||||
Rect[0] = 0;
|
||||
Rect[1] = 0;
|
||||
Rect[2] = width;
|
||||
Rect[3] = height;
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
if(Nodes[0] != null)
|
||||
delete Nodes[0];
|
||||
if(Nodes[1] != null)
|
||||
delete Nodes[1];
|
||||
}
|
||||
|
||||
public bool Insert(PakaRectangle pToInsert)
|
||||
{
|
||||
if(!(Nodes[1] == null && Nodes[0] == null))
|
||||
{
|
||||
if(Nodes[0].Insert(pToInsert))
|
||||
return true;
|
||||
return Nodes[1].Insert(pToInsert);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Size.id != -2)
|
||||
return false;
|
||||
|
||||
if(!(pToInsert.width <= Rect[2] && pToInsert.height <= Rect[3]))
|
||||
return false;
|
||||
|
||||
if(pToInsert.width == Rect[2] && pToInsert.height == Rect[3])
|
||||
{
|
||||
Size = pToInsert;
|
||||
return true;
|
||||
}
|
||||
|
||||
Nodes[0] = new .();
|
||||
Nodes[1] = new .();
|
||||
|
||||
int64 dw = Rect[2] - pToInsert.width;
|
||||
int64 dh = Rect[3] - pToInsert.height;
|
||||
|
||||
if(dw > dh)
|
||||
{
|
||||
|
||||
Nodes[0].Rect = .(Rect[0], Rect[1], pToInsert.width, Rect[3]);
|
||||
Nodes[1].Rect = .(Rect[0] + pToInsert.width, Rect[1], Rect[2] - pToInsert.width, Rect[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Nodes[0].Rect = .(Rect[0], Rect[1], Rect[2], pToInsert.width);
|
||||
Nodes[1].Rect = .(Rect[0], Rect[1] + pToInsert.width, Rect[2], Rect[3] - pToInsert.width);
|
||||
}
|
||||
|
||||
return Nodes[0].Insert(pToInsert);
|
||||
}
|
||||
}
|
||||
|
||||
public void GetPackedSorted(List<PakaRectangle> pToAddTo, int32 xOffset, int32 yOffset)
|
||||
{
|
||||
if(Size.id != -2)
|
||||
{
|
||||
Size.x = xOffset + Rect[0];
|
||||
Size.y = yOffset + Rect[1];
|
||||
pToAddTo.Add(Img);
|
||||
return;
|
||||
}
|
||||
|
||||
if(Nodes[0] != null)
|
||||
Nodes[0].GetPackedSorted(pToAddTo, xOffset, yOffset);
|
||||
|
||||
if(Nodes[1] != null)
|
||||
Nodes[1].GetPackedSorted(pToAddTo, xOffset, yOffset);
|
||||
}
|
||||
}
|
||||
|
||||
List<packerNode> _bins = new .() ~ DeleteContainerAndItems!(_);
|
||||
|
||||
public void Sort(List<packerRectangle> pToSort)
|
||||
{
|
||||
pToSort.Sort(scope => _Compare);
|
||||
}
|
||||
|
||||
private int _Compare(packerRectangle lhs, packerRectangle rhs)
|
||||
{
|
||||
return rhs.rect[2] * rhs.rect[3] - lhs.rect[2] * lhs.rect[3];
|
||||
}
|
||||
|
||||
//Retrieve the updated packed items
|
||||
public void GetPackedSorted(List<packerRectangle> pToAddTo)
|
||||
{
|
||||
int32 sideLenght = 1;
|
||||
while(sideLenght * sideLenght < _bins.Count)
|
||||
sideLenght += 1; //Retrieve the side lenght
|
||||
int32 xOffset = 0;
|
||||
int32 yOffset = 0;
|
||||
|
||||
for(let b in _bins)
|
||||
{
|
||||
b.GetPackedSorted(pToAddTo,xOffset,yOffset);
|
||||
xOffset += b.Rect[2];
|
||||
if(xOffset % ((sideLenght)*b.Rect[2]) == 0)
|
||||
{
|
||||
yOffset += b.Rect[3];
|
||||
xOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///Input objects need to be sorted by height and then width
|
||||
public void PackSorted(List<PakaRectangle> pRects)
|
||||
{
|
||||
this.Sort(pRects);
|
||||
|
||||
if(pRects.Count <= 0)
|
||||
return;
|
||||
|
||||
int64 binWidth = pRects[0].width;
|
||||
int64 binHeight = pRects[0].height;
|
||||
|
||||
int64 area = 0;
|
||||
|
||||
for(let e in pRects)
|
||||
{
|
||||
area += e.width * e.height;
|
||||
}
|
||||
area = (.)(area * 1.15);
|
||||
_bins.Add(new .(
|
||||
(.)(Math.Sqrt(area)+1),
|
||||
(area/((.)Math.Sqrt(area)+1)+1)
|
||||
));
|
||||
|
||||
outer: for(let e in pRects)
|
||||
{
|
||||
for(let b in _bins)
|
||||
if(b.Insert(e))
|
||||
continue outer;
|
||||
var toAdd = new PakaNode(binWidth, binHeight);
|
||||
toAdd.Insert(e);
|
||||
_bins.Add(toAdd);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue