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