Initial Commit
This commit is contained in:
131
source/lib/atlas.cpp
Normal file
131
source/lib/atlas.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 tobid7
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <d7rc/atlas.hpp>
|
||||
|
||||
namespace D7RC {
|
||||
Atlas::Atlas(int size) {
|
||||
Size = PD::ivec2(size, size);
|
||||
Space.push_back(PD::ivec4(0, 0, size, size));
|
||||
}
|
||||
|
||||
bool Atlas::AppendImage(PD::Image::Ref img, const std::string& name) {
|
||||
for (size_t i = 0; i < Space.size(); i++) {
|
||||
auto& it = Space[i];
|
||||
PD::ivec2 size = PD::ivec2(it.z, it.w);
|
||||
if (img->Width() <= size.x && img->Height() <= size.y) {
|
||||
Entry e;
|
||||
e.Name = name;
|
||||
e.iImg = img;
|
||||
e.iPos = PD::ivec2(it.x, it.y);
|
||||
e.Size = PD::ivec2(img->Width(), img->Height());
|
||||
e.UV = PD::fvec4((float)it.x / (float)Size.x, (float)it.y / (float)Size.y,
|
||||
(float)(it.x + img->Width()) / (float)Size.x,
|
||||
(float)(it.x + img->Height()) / (float)Size.y);
|
||||
Entries.push_back(e);
|
||||
#ifdef DEBUG
|
||||
std::cout << std::format("Created Image {} ({})\n", name,
|
||||
PD::ivec4(e.iPos, e.Size));
|
||||
#endif
|
||||
if (e.iPos.x + e.Size.x > Max.x) {
|
||||
Max.x = e.iPos.x + e.Size.x;
|
||||
}
|
||||
if (e.iPos.y + e.Size.y > Max.y) {
|
||||
Max.y = e.iPos.y + e.Size.y;
|
||||
}
|
||||
pSplit(i, PD::ivec4(it.x, it.y, img->Width(), img->Height()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Need a smarter splitting algo
|
||||
* Does not really find free spaces yet
|
||||
*/
|
||||
void Atlas::pSplit(int i, PD::ivec4 area) {
|
||||
auto s = Space[i];
|
||||
Space.erase(Space.begin() + i);
|
||||
|
||||
if (area.x + area.z < s.x + s.z)
|
||||
Space.emplace_back(area.x + area.z, s.y, (s.x + s.z) - (area.x + area.z),
|
||||
area.w);
|
||||
if (area.y + area.w < s.y + s.w)
|
||||
Space.emplace_back(s.x, area.y + area.w, s.z,
|
||||
(s.y + s.w) - (area.y + area.w));
|
||||
std::sort(Space.begin(), Space.end(),
|
||||
[](PD::ivec4& a, PD::ivec4& b) { return a.y < b.y && a.x < b.x; });
|
||||
}
|
||||
|
||||
void Atlas::Pack() {
|
||||
if (!PD::BitUtil::IsSingleBit(Max.x)) {
|
||||
Size.x = PD::BitUtil::GetPow2(Max.x);
|
||||
}
|
||||
if (!PD::BitUtil::IsSingleBit(Max.y)) {
|
||||
Size.y = PD::BitUtil::GetPow2(Max.y);
|
||||
}
|
||||
Img.resize(Size.x * Size.y * 4);
|
||||
for (auto& it : Entries) {
|
||||
for (int i = 0; i < it.Size.x; i++) {
|
||||
for (int j = 0; j < it.Size.y; j++) {
|
||||
Img[((j + it.iPos.y) * Size.x + (it.iPos.x + i)) * 4] =
|
||||
it.iImg->pBuffer[(j * it.iImg->pWidth + i) * 4];
|
||||
Img[((j + it.iPos.y) * Size.x + (it.iPos.x + i)) * 4 + 1] =
|
||||
it.iImg->pBuffer[(j * it.iImg->pWidth + i) * 4 + 1];
|
||||
Img[((j + it.iPos.y) * Size.x + (it.iPos.x + i)) * 4 + 2] =
|
||||
it.iImg->pBuffer[(j * it.iImg->pWidth + i) * 4 + 2];
|
||||
Img[((j + it.iPos.y) * Size.x + (it.iPos.x + i)) * 4 + 3] =
|
||||
it.iImg->pBuffer[(j * it.iImg->pWidth + i) * 4 + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cout << std::format("Created Texture ({})\n", Size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Atlas::LoadTextures() {
|
||||
pTex = PD::Gfx::LoadTex(Img, Size.x, Size.y);
|
||||
for (auto& it : Entries) {
|
||||
it.iTex = PD::Li::Texture::New();
|
||||
it.iTex->Address = pTex->Address;
|
||||
it.iTex->Size = it.Size;
|
||||
it.iTex->UV = it.UV;
|
||||
}
|
||||
}
|
||||
|
||||
PD::Li::Texture::Ref Atlas::Get(const std::string& name) {
|
||||
if (!pTex) {
|
||||
return nullptr;
|
||||
}
|
||||
for (auto& it : Entries) {
|
||||
if (it.Name == name) {
|
||||
return it.iTex;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace D7RC
|
||||
129
source/lib/file.cpp
Normal file
129
source/lib/file.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 tobid7
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <d7rc/file.hpp>
|
||||
|
||||
namespace D7RC {
|
||||
File::Header File::Header::New() {
|
||||
Header ret;
|
||||
ret.Magic = 0;
|
||||
ret.Width = 0;
|
||||
ret.Height = 0;
|
||||
ret.DataSize = 0;
|
||||
ret.TabLen = 0;
|
||||
ret.Format = 0;
|
||||
ret.pUnk = 0;
|
||||
ret.NumEntries = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void File::Header::Write(std::ofstream& off) {
|
||||
off.write(reinterpret_cast<const char*>(&Magic), sizeof(Magic));
|
||||
off.write(reinterpret_cast<const char*>(&Width), sizeof(Width));
|
||||
off.write(reinterpret_cast<const char*>(&Height), sizeof(Height));
|
||||
off.write(reinterpret_cast<const char*>(&DataSize), sizeof(DataSize));
|
||||
off.write(reinterpret_cast<const char*>(&TabLen), sizeof(TabLen));
|
||||
off.write(reinterpret_cast<const char*>(&Format), sizeof(Format));
|
||||
off.write(reinterpret_cast<const char*>(&pUnk), sizeof(pUnk));
|
||||
off.write(reinterpret_cast<const char*>(&NumEntries), sizeof(NumEntries));
|
||||
}
|
||||
|
||||
void File::Header::Read(std::ifstream& iff) {
|
||||
iff.read(reinterpret_cast<char*>(&Magic), sizeof(Magic));
|
||||
iff.read(reinterpret_cast<char*>(&Width), sizeof(Width));
|
||||
iff.read(reinterpret_cast<char*>(&Height), sizeof(Height));
|
||||
iff.read(reinterpret_cast<char*>(&DataSize), sizeof(DataSize));
|
||||
iff.read(reinterpret_cast<char*>(&TabLen), sizeof(TabLen));
|
||||
iff.read(reinterpret_cast<char*>(&Format), sizeof(Format));
|
||||
iff.read(reinterpret_cast<char*>(&pUnk), sizeof(pUnk));
|
||||
iff.read(reinterpret_cast<char*>(&NumEntries), sizeof(NumEntries));
|
||||
}
|
||||
|
||||
void File::Write(Atlas& atlas, const std::string& path) {
|
||||
hdr = Header::New();
|
||||
hdr.Magic = 0x43523744;
|
||||
hdr.Width = atlas.Size.x;
|
||||
hdr.Height = atlas.Size.y;
|
||||
hdr.DataSize = atlas.Img.size();
|
||||
hdr.TabLen = pCalcTabLen(atlas);
|
||||
hdr.Format = 0;
|
||||
hdr.NumEntries = atlas.Entries.size();
|
||||
std::ofstream off(path, std::ios::out | std::ios::binary);
|
||||
hdr.Write(off);
|
||||
pWriteTab(off, atlas);
|
||||
off.write(reinterpret_cast<const char*>(atlas.Img.data()), atlas.Img.size());
|
||||
off.close();
|
||||
}
|
||||
|
||||
size_t File::pCalcTabLen(Atlas& atlas) {
|
||||
size_t ret = 0;
|
||||
size_t s_uv = sizeof(PD::Li::Rect);
|
||||
size_t s_size = sizeof(PD::u16) * 2;
|
||||
for (auto& it : atlas.Entries) {
|
||||
ret += s_uv + s_size + sizeof(PD::u8) + it.Name.size();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void File::pWriteTab(std::ofstream& off, Atlas& atlas) {
|
||||
for (auto& it : atlas.Entries) {
|
||||
if (it.Name.size() > 255) {
|
||||
continue;
|
||||
}
|
||||
off.write(reinterpret_cast<const char*>(&it.UV), sizeof(it.UV));
|
||||
PD::u16 w = it.Size.x;
|
||||
PD::u16 h = it.Size.y;
|
||||
off.write(reinterpret_cast<const char*>(&w), sizeof(w));
|
||||
off.write(reinterpret_cast<const char*>(&h), sizeof(h));
|
||||
PD::u32 size = (PD::u32)it.Name.size();
|
||||
off.write(reinterpret_cast<const char*>(&size), sizeof(PD::u32));
|
||||
off.write(it.Name.data(), it.Name.size());
|
||||
}
|
||||
}
|
||||
|
||||
void File::Read(Atlas& atlas, const std::string& path) {
|
||||
std::ifstream iff(path, std::ios::in | std::ios::binary);
|
||||
hdr.Read(iff);
|
||||
pReadTab(iff, atlas);
|
||||
atlas.Img.resize(hdr.DataSize);
|
||||
iff.read(reinterpret_cast<char*>(atlas.Img.data()), hdr.DataSize);
|
||||
iff.close();
|
||||
}
|
||||
|
||||
void File::pReadTab(std::ifstream& iff, Atlas& atlas) {
|
||||
for (PD::u32 i = 0; i < hdr.NumEntries; i++) {
|
||||
Atlas::Entry e;
|
||||
PD::u16 w = 0, h = 0;
|
||||
PD::u32 namelen = 0;
|
||||
iff.read(reinterpret_cast<char*>(&e.UV), sizeof(e.UV));
|
||||
iff.read(reinterpret_cast<char*>(&w), sizeof(w));
|
||||
iff.read(reinterpret_cast<char*>(&w), sizeof(h));
|
||||
iff.read(reinterpret_cast<char*>(&namelen), sizeof(PD::u32));
|
||||
e.Name.resize(namelen);
|
||||
iff.read(e.Name.data(), namelen);
|
||||
e.Size = PD::ivec2(w, h);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace D7RC
|
||||
48
source/tool/main.cpp
Normal file
48
source/tool/main.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 tobid7
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <d7rc.hpp>
|
||||
|
||||
#ifndef VERSION
|
||||
#define VERSION ""
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
std::cout << "d7rc-make v" VERSION << std::endl;
|
||||
int szs = 1024;
|
||||
D7RC::Atlas a(szs);
|
||||
std::map<PD::Image::Ref, std::string> imgs;
|
||||
for (auto& it : std::filesystem::directory_iterator("images")) {
|
||||
auto img = PD::Image::New(it.path().string());
|
||||
PD::Image::Convert(img, PD::Image::RGBA);
|
||||
imgs[img] = it.path().filename().string();
|
||||
}
|
||||
for (auto& it : imgs) {
|
||||
a.AppendImage(it.first, it.second);
|
||||
}
|
||||
a.Pack();
|
||||
D7RC::File f;
|
||||
f.Write(a, "test.d7rc");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user