tyrav2 init
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "loaders/3d/builder/mesh_builder_data.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
MeshBuilderData::MeshBuilderData() {
|
||||
normalsEnabled = false;
|
||||
textureCoordsEnabled = false;
|
||||
manyColorsEnabled = false;
|
||||
}
|
||||
|
||||
MeshBuilderData::~MeshBuilderData() {
|
||||
if (frames) {
|
||||
for (u32 i = 0; i < framesCount; i++) {
|
||||
delete frames[i];
|
||||
}
|
||||
delete[] frames;
|
||||
}
|
||||
|
||||
if (materials) {
|
||||
for (u32 i = 0; i < materialsCount; i++) {
|
||||
delete materials[i];
|
||||
}
|
||||
delete[] materials;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshBuilderData::allocate(const u32& framesCount,
|
||||
const u32& materialsCount) {
|
||||
allocateFrames(framesCount);
|
||||
allocateMaterials(materialsCount);
|
||||
}
|
||||
|
||||
void MeshBuilderData::allocateFrames(const u32& count) {
|
||||
this->framesCount = count;
|
||||
|
||||
frames = new MeshBuilderFrameData*[count];
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
frames[i] = new MeshBuilderFrameData();
|
||||
}
|
||||
}
|
||||
|
||||
void MeshBuilderData::allocateMaterials(const u32& count) {
|
||||
this->materialsCount = count;
|
||||
|
||||
materials = new MeshBuilderMaterialData*[count];
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
materials[i] = new MeshBuilderMaterialData();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "loaders/3d/builder/mesh_builder_frame_data.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
MeshBuilderFrameData::MeshBuilderFrameData() {
|
||||
vertices = nullptr;
|
||||
normals = nullptr;
|
||||
textureCoords = nullptr;
|
||||
colors = nullptr;
|
||||
verticesCount = 0;
|
||||
textureCoordsCount = 0;
|
||||
normalsCount = 0;
|
||||
colorsCount = 0;
|
||||
}
|
||||
|
||||
MeshBuilderFrameData::~MeshBuilderFrameData() {}
|
||||
|
||||
void MeshBuilderFrameData::allocateTextureCoords(const u32& count) {
|
||||
textureCoordsCount = count;
|
||||
textureCoords = new Vec4[count];
|
||||
}
|
||||
|
||||
void MeshBuilderFrameData::allocateVertices(const u32& count) {
|
||||
verticesCount = count;
|
||||
vertices = new Vec4[count];
|
||||
}
|
||||
|
||||
void MeshBuilderFrameData::allocateNormals(const u32& count) {
|
||||
normalsCount = count;
|
||||
normals = new Vec4[count];
|
||||
}
|
||||
|
||||
void MeshBuilderFrameData::allocateColors(const u32& count) {
|
||||
colorsCount = count;
|
||||
colors = new Color[count];
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "loaders/3d/builder/mesh_builder_material_data.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
MeshBuilderMaterialData::MeshBuilderMaterialData() {
|
||||
vertexFaces = nullptr;
|
||||
textureCoordFaces = nullptr;
|
||||
normalFaces = nullptr;
|
||||
colorFaces = nullptr;
|
||||
name = "";
|
||||
count = 0;
|
||||
}
|
||||
|
||||
MeshBuilderMaterialData::~MeshBuilderMaterialData() {}
|
||||
|
||||
void MeshBuilderMaterialData::allocateFaces(const u32& t_count) {
|
||||
vertexFaces = new u32[t_count];
|
||||
textureCoordFaces = new u32[t_count];
|
||||
normalFaces = new u32[t_count];
|
||||
colorFaces = new u32[t_count];
|
||||
count = t_count;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include "debug/debug.hpp"
|
||||
#include "loaders/3d/builder/mesh_builder_data.hpp"
|
||||
#include "loaders/3d/md2/anorms.hpp"
|
||||
#include "loaders/loader.hpp"
|
||||
#include "loaders/3d/md2/md2_loader.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
// magic number "IDP2" or 844121161
|
||||
#define MD2_IDENT (('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
|
||||
|
||||
// model version
|
||||
#define MD2_VERSION 8
|
||||
|
||||
typedef struct {
|
||||
int ident; // magic number. must be equal to "IDP2"
|
||||
int version; // md2 version. must be equal to 8
|
||||
|
||||
int skinwidth; // width of the texture
|
||||
int skinheight; // height of the texture
|
||||
int framesize; // size of one frame in bytes
|
||||
|
||||
int num_skins; // number of textures
|
||||
int num_xyz; // number of vertices
|
||||
int num_st; // number of texture coordinates
|
||||
int num_tris; // number of triangles
|
||||
int num_glcmds; // number of opengl commands
|
||||
int num_frames; // total number of frames
|
||||
|
||||
int ofs_skins; // offset to skin names (64 bytes each)
|
||||
int ofs_st; // offset to s-t texture coordinates
|
||||
int ofs_tris; // offset to triangles
|
||||
int ofs_frames; // offset to frame data
|
||||
int ofs_glcmds; // offset to opengl commands
|
||||
int ofs_end; // offset to end of file
|
||||
} md2_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char v[3]; // compressed vertex (x, y, z) coordinates
|
||||
unsigned char lightnormalindex; // index to a normal vector for the lighting
|
||||
} mvertex_t;
|
||||
|
||||
typedef struct {
|
||||
float scale[3]; // scale values
|
||||
float translate[3]; // translation vector
|
||||
char name[16]; // frame name
|
||||
mvertex_t verts[1]; // first vertex of this frame
|
||||
} frame_t;
|
||||
|
||||
typedef float vec3_t[3];
|
||||
|
||||
typedef struct {
|
||||
s16 index_xyz[3]; // indexes to triangle's vertices
|
||||
s16 index_st[3]; // indexes to vertices' texture coorinates
|
||||
} triangle_t;
|
||||
|
||||
typedef struct {
|
||||
s16 s;
|
||||
s16 t;
|
||||
} texCoord_t;
|
||||
|
||||
MD2Loader::MD2Loader() {}
|
||||
|
||||
MD2Loader::~MD2Loader() {}
|
||||
|
||||
MeshBuilderData* MD2Loader::load(const char* fullpath, const float& t_scale,
|
||||
const u8& t_invertT) {
|
||||
std::string path = fullpath;
|
||||
TYRA_ASSERT(!path.empty(), "Provided path is empty!");
|
||||
|
||||
auto filename = getFilenameFromPath(path);
|
||||
|
||||
FILE* file = fopen(fullpath, "rb");
|
||||
TYRA_ASSERT(file != NULL, "Failed to load: ", filename);
|
||||
md2_t header;
|
||||
|
||||
fread(reinterpret_cast<char*>(&header), sizeof(md2_t), 1, file);
|
||||
|
||||
TYRA_ASSERT((header.ident == MD2_IDENT) && (header.version == MD2_VERSION),
|
||||
"This MD2 file is not in correct format!");
|
||||
|
||||
u32 framesCount = header.num_frames;
|
||||
u32 vertexCount = header.num_xyz;
|
||||
u32 stsCount = header.num_st;
|
||||
u32 trianglesCount = header.num_tris;
|
||||
|
||||
auto framesBuffer = new char[framesCount * header.framesize];
|
||||
fseek(file, header.ofs_frames, SEEK_SET);
|
||||
fread(framesBuffer, framesCount * header.framesize, 1, file);
|
||||
|
||||
auto stsBuffer = new char[stsCount * sizeof(texCoord_t)];
|
||||
fseek(file, header.ofs_st, SEEK_SET);
|
||||
fread(stsBuffer, stsCount * sizeof(texCoord_t), 1, file);
|
||||
|
||||
auto trianglesBuffer = new char[trianglesCount * sizeof(triangle_t)];
|
||||
fseek(file, header.ofs_tris, SEEK_SET);
|
||||
fread(trianglesBuffer, trianglesCount * sizeof(triangle_t), 1, file);
|
||||
|
||||
fclose(file);
|
||||
|
||||
auto result = new MeshBuilderData();
|
||||
result->allocate(framesCount, 1);
|
||||
result->normalsEnabled = true;
|
||||
result->textureCoordsEnabled = true;
|
||||
result->manyColorsEnabled = false;
|
||||
|
||||
frame_t* frame;
|
||||
Vec4 temp(0.0F, 0.0F, 0.0F, 1.0F);
|
||||
for (u32 j = 0; j < framesCount; j++) {
|
||||
result->frames[j]->allocateVertices(vertexCount);
|
||||
result->frames[j]->allocateNormals(vertexCount);
|
||||
result->frames[j]->allocateTextureCoords(stsCount);
|
||||
|
||||
result->materials[0]->allocateFaces(trianglesCount * 3);
|
||||
result->materials[0]->name = getFilenameWithoutExtension(filename);
|
||||
|
||||
frame = reinterpret_cast<frame_t*>(&framesBuffer[header.framesize * j]);
|
||||
|
||||
for (u32 i = 0; i < vertexCount; i++) {
|
||||
temp.set(
|
||||
((frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0]) *
|
||||
t_scale,
|
||||
((frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1]) *
|
||||
t_scale,
|
||||
((frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2]) *
|
||||
t_scale);
|
||||
|
||||
result->frames[j]->vertices[i].set(temp);
|
||||
|
||||
temp.set(ANORMS[frame->verts[i].lightnormalindex][0],
|
||||
ANORMS[frame->verts[i].lightnormalindex][1],
|
||||
ANORMS[frame->verts[i].lightnormalindex][2]);
|
||||
|
||||
result->frames[j]->normals[i].set(temp);
|
||||
}
|
||||
}
|
||||
|
||||
texCoord_t* texCoord;
|
||||
|
||||
TYRA_LOG("Skin width: ", header.skinwidth,
|
||||
" Skin height: ", header.skinheight);
|
||||
|
||||
for (u32 i = 0; i < stsCount; i++) {
|
||||
texCoord =
|
||||
reinterpret_cast<texCoord_t*>(&stsBuffer[sizeof(texCoord_t) * i]);
|
||||
|
||||
temp.set(static_cast<float>(texCoord->s) / header.skinwidth,
|
||||
static_cast<float>(texCoord->t) / header.skinheight, 1.0F, 0.0F);
|
||||
|
||||
if (t_invertT) temp.y = 1.0F - temp.y;
|
||||
|
||||
for (u32 j = 0; j < framesCount; j++)
|
||||
result->frames[j]->textureCoords[i].set(temp);
|
||||
}
|
||||
|
||||
triangle_t* triangle;
|
||||
for (u32 i = 0; i < trianglesCount; i++) {
|
||||
triangle =
|
||||
reinterpret_cast<triangle_t*>(&trianglesBuffer[sizeof(triangle_t) * i]);
|
||||
|
||||
for (u8 j = 0; j < 3; j++) {
|
||||
for (u32 x = 0; x < framesCount; x++) {
|
||||
result->materials[0]->vertexFaces[(i * 3) + j] = triangle->index_xyz[j];
|
||||
|
||||
result->materials[0]->textureCoordFaces[(i * 3) + j] =
|
||||
triangle->index_st[j];
|
||||
|
||||
result->materials[0]->normalFaces[(i * 3) + j] = triangle->index_xyz[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TYRA_LOG("MD2 file \"", filename, "\" loaded!");
|
||||
|
||||
delete[] framesBuffer;
|
||||
delete[] stsBuffer;
|
||||
delete[] trianglesBuffer;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "loaders/loader.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
std::string Loader::getFilenameFromPath(const std::string& path) {
|
||||
std::string filename = path.substr(path.find_last_of("/\\") + 1);
|
||||
if (filename.size() == path.size()) {
|
||||
filename = path.substr(path.find_last_of(":\\") + 1);
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
std::string Loader::getFilenameWithoutExtension(const std::string& filename) {
|
||||
auto lastindex = filename.find_last_of(".");
|
||||
return filename.substr(0, lastindex);
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "loaders/texture/builder/texture_builder_data.hpp"
|
||||
#include <draw_buffers.h>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
TextureBuilderData::TextureBuilderData() {
|
||||
width = 0;
|
||||
height = 0;
|
||||
data = nullptr;
|
||||
bpp = bpp32;
|
||||
gsComponents = TEXTURE_COMPONENTS_RGBA;
|
||||
|
||||
clut = nullptr;
|
||||
clutWidth = 0;
|
||||
clutHeight = 0;
|
||||
clutBpp = bpp32;
|
||||
clutGsComponents = TEXTURE_COMPONENTS_RGBA;
|
||||
}
|
||||
|
||||
TextureBuilderData::~TextureBuilderData() {}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include "debug/debug.hpp"
|
||||
#include "loaders/texture/base/texture_loader.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
u32 TextureLoader::getTextureSize(const u32& width, const u32& height,
|
||||
const TextureBpp& bpp) {
|
||||
switch (bpp) {
|
||||
case bpp32:
|
||||
return (width * height * 4);
|
||||
case bpp24:
|
||||
return (width * height * 3);
|
||||
case bpp8:
|
||||
return (width * height);
|
||||
case bpp4:
|
||||
return (width * height / 2);
|
||||
default:
|
||||
TYRA_TRAP("Unknown texture bpp");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "debug/debug.hpp"
|
||||
#include "renderer/core/texture/models/texture.hpp"
|
||||
#include "loaders/texture/base/texture_loader_selector.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
TextureLoaderSelector::TextureLoaderSelector() {}
|
||||
|
||||
TextureLoaderSelector::~TextureLoaderSelector() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
TextureLoader& TextureLoaderSelector::getLoaderByFileName(
|
||||
const char* fullpath) {
|
||||
std::string path = fullpath;
|
||||
std::string extension = path.substr(path.find_last_of(".") + 1);
|
||||
return getLoaderByExtension(extension);
|
||||
}
|
||||
|
||||
TextureLoader& TextureLoaderSelector::getLoaderByExtension(
|
||||
const std::string& extension) {
|
||||
std::string extensionLower = extension;
|
||||
std::transform(extensionLower.begin(), extensionLower.end(),
|
||||
extensionLower.begin(), ::tolower);
|
||||
if (extensionLower == "png") {
|
||||
return pngLoader;
|
||||
} else {
|
||||
TYRA_TRAP("There is no texture loader for extension: ", extensionLower);
|
||||
return pngLoader;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "debug/debug.hpp"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <png.h>
|
||||
#include <string>
|
||||
#include <draw_buffers.h>
|
||||
#include "loaders/texture/png_loader.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
PngLoader::PngLoader() {}
|
||||
|
||||
PngLoader::~PngLoader() {}
|
||||
|
||||
struct PngClut {
|
||||
u8 r, g, b, a;
|
||||
};
|
||||
|
||||
/** Based on GsKit texture loading - thank you guys! */
|
||||
TextureBuilderData* PngLoader::load(const char* fullPath) {
|
||||
std::string path = fullPath;
|
||||
TYRA_ASSERT(!path.empty(), "Provided path is empty!");
|
||||
|
||||
auto filename = getFilenameFromPath(path);
|
||||
|
||||
FILE* file = fopen(fullPath, "rb");
|
||||
TYRA_ASSERT(file != nullptr, "Failed to load ", fullPath);
|
||||
|
||||
png_structp pngPtr;
|
||||
png_infop infoPtr;
|
||||
png_uint_32 width, height;
|
||||
png_bytep* rowPointers = nullptr;
|
||||
|
||||
u32 sigRead = 0;
|
||||
int bitDepth, colorType, interlaceType;
|
||||
|
||||
pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) nullptr,
|
||||
nullptr, nullptr);
|
||||
TYRA_ASSERT(pngPtr, "PNG read struct init failed for: ", filename);
|
||||
|
||||
infoPtr = png_create_info_struct(pngPtr);
|
||||
TYRA_ASSERT(infoPtr, "PNG read struct init failed for: ", filename);
|
||||
|
||||
TYRA_ASSERT(!setjmp(png_jmpbuf(pngPtr)), "PNG read error for: ", filename);
|
||||
|
||||
png_init_io(pngPtr, file);
|
||||
png_set_sig_bytes(pngPtr, sigRead);
|
||||
png_read_info(pngPtr, infoPtr);
|
||||
png_get_IHDR(pngPtr, infoPtr, &width, &height, &bitDepth, &colorType,
|
||||
&interlaceType, nullptr, nullptr);
|
||||
|
||||
if (bitDepth == 16) png_set_strip_16(pngPtr);
|
||||
if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 4) png_set_expand(pngPtr);
|
||||
|
||||
png_set_filler(pngPtr, 0xff, PNG_FILLER_AFTER);
|
||||
|
||||
png_read_update_info(pngPtr, infoPtr);
|
||||
|
||||
auto* result = new TextureBuilderData();
|
||||
result->width = width;
|
||||
result->height = height;
|
||||
result->name = filename;
|
||||
|
||||
auto updatedColorType = png_get_color_type(pngPtr, infoPtr);
|
||||
|
||||
if (updatedColorType == PNG_COLOR_TYPE_PALETTE) {
|
||||
handlePalletized(result, pngPtr, infoPtr, rowPointers, bitDepth);
|
||||
} else if (updatedColorType == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
handle32bpp(result, pngPtr, infoPtr, rowPointers);
|
||||
} else if (updatedColorType == PNG_COLOR_TYPE_RGB) {
|
||||
handle24bpp(result, pngPtr, infoPtr, rowPointers);
|
||||
} else
|
||||
TYRA_TRAP("This texture depth is not supported!");
|
||||
|
||||
png_read_end(pngPtr, nullptr);
|
||||
png_destroy_read_struct(&pngPtr, &infoPtr, nullptr);
|
||||
fclose(file);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PngLoader::handle32bpp(TextureBuilderData* result, png_structp pngPtr,
|
||||
png_infop infoPtr, png_bytep* rowPointers) {
|
||||
int rowBytes = png_get_rowbytes(pngPtr, infoPtr);
|
||||
|
||||
result->gsComponents = TEXTURE_COMPONENTS_RGBA;
|
||||
result->bpp = bpp32;
|
||||
result->data = static_cast<unsigned char*>(memalign(
|
||||
128, getTextureSize(result->width, result->height, result->bpp)));
|
||||
|
||||
rowPointers =
|
||||
static_cast<png_bytep*>(calloc(result->height, sizeof(png_bytep)));
|
||||
|
||||
for (int row = 0; row < result->height; row++)
|
||||
rowPointers[row] = static_cast<png_bytep>(malloc(rowBytes));
|
||||
|
||||
png_read_image(pngPtr, rowPointers);
|
||||
|
||||
struct Pixel {
|
||||
u8 r, g, b, a;
|
||||
};
|
||||
|
||||
struct Pixel* pixels = (struct Pixel*)result->data;
|
||||
|
||||
int k = 0;
|
||||
for (int i = 0; i < result->height; i++) {
|
||||
for (int j = 0; j < result->width; j++) {
|
||||
pixels[k].r = rowPointers[i][4 * j];
|
||||
pixels[k].g = rowPointers[i][4 * j + 1];
|
||||
pixels[k].b = rowPointers[i][4 * j + 2];
|
||||
pixels[k++].a = ((int)rowPointers[i][4 * j + 3] * 128 / 255);
|
||||
}
|
||||
}
|
||||
|
||||
for (int row = 0; row < result->height; row++) free(rowPointers[row]);
|
||||
|
||||
free(rowPointers);
|
||||
}
|
||||
|
||||
void PngLoader::handle24bpp(TextureBuilderData* result, png_structp pngPtr,
|
||||
png_infop infoPtr, png_bytep* rowPointers) {
|
||||
int rowBytes = png_get_rowbytes(pngPtr, infoPtr);
|
||||
|
||||
result->gsComponents = TEXTURE_COMPONENTS_RGB;
|
||||
result->bpp = bpp24;
|
||||
result->data = static_cast<unsigned char*>(memalign(
|
||||
128, getTextureSize(result->width, result->height, result->bpp)));
|
||||
|
||||
rowPointers =
|
||||
static_cast<png_bytep*>(calloc(result->height, sizeof(png_bytep)));
|
||||
|
||||
for (int row = 0; row < result->height; row++)
|
||||
rowPointers[row] = static_cast<png_bytep>(malloc(rowBytes));
|
||||
|
||||
png_read_image(pngPtr, rowPointers);
|
||||
|
||||
struct Pixel3 {
|
||||
u8 r, g, b;
|
||||
};
|
||||
struct Pixel3* pixels = (struct Pixel3*)result->data;
|
||||
|
||||
int k = 0;
|
||||
for (int i = 0; i < result->height; i++) {
|
||||
for (int j = 0; j < result->width; j++) {
|
||||
pixels[k].r = rowPointers[i][4 * j];
|
||||
pixels[k].g = rowPointers[i][4 * j + 1];
|
||||
pixels[k++].b = rowPointers[i][4 * j + 2];
|
||||
}
|
||||
}
|
||||
|
||||
for (int row = 0; row < result->height; row++) free(rowPointers[row]);
|
||||
|
||||
free(rowPointers);
|
||||
}
|
||||
|
||||
void PngLoader::handlePalletized(TextureBuilderData* result, png_structp pngPtr,
|
||||
png_infop infoPtr, png_bytep* rowPointers,
|
||||
const int& bitDepth) {
|
||||
png_colorp palette = nullptr;
|
||||
png_bytep trans = nullptr;
|
||||
int numPallete = 0;
|
||||
int numTrans = 0;
|
||||
|
||||
png_get_PLTE(pngPtr, infoPtr, &palette, &numPallete);
|
||||
png_get_tRNS(pngPtr, infoPtr, &trans, &numTrans, nullptr);
|
||||
result->clutBpp = bpp32;
|
||||
result->clutGsComponents = TEXTURE_COMPONENTS_RGBA;
|
||||
|
||||
if (bitDepth == 4) {
|
||||
handle4bppPalletized(result, pngPtr, infoPtr, rowPointers, palette, trans,
|
||||
numPallete, numTrans);
|
||||
} else if (bitDepth == 8) {
|
||||
handle8bppPalletized(result, pngPtr, infoPtr, rowPointers, palette, trans,
|
||||
numPallete, numTrans);
|
||||
} else {
|
||||
TYRA_TRAP("Only 4 and 8 bits palettes are supported");
|
||||
}
|
||||
}
|
||||
|
||||
void PngLoader::handle8bppPalletized(TextureBuilderData* result,
|
||||
png_structp pngPtr, png_infop infoPtr,
|
||||
png_bytep* rowPointers, png_colorp palette,
|
||||
png_bytep trans, const int& numPallete,
|
||||
const int& numTrans) {
|
||||
int rowBytes = png_get_rowbytes(pngPtr, infoPtr);
|
||||
result->bpp = bpp8;
|
||||
result->clutWidth = 16;
|
||||
result->clutHeight = 16;
|
||||
|
||||
result->gsComponents = TEXTURE_COMPONENTS_RGBA;
|
||||
result->data = static_cast<unsigned char*>(memalign(
|
||||
128, getTextureSize(result->width, result->height, result->bpp)));
|
||||
|
||||
rowPointers =
|
||||
static_cast<png_bytep*>(calloc(result->height, sizeof(png_bytep)));
|
||||
|
||||
for (int row = 0; row < result->height; row++)
|
||||
rowPointers[row] = static_cast<png_bytep>(malloc(rowBytes));
|
||||
|
||||
png_read_image(pngPtr, rowPointers);
|
||||
|
||||
result->clut =
|
||||
static_cast<unsigned char*>(memalign(128, getTextureSize(16, 16, bpp32)));
|
||||
memset(result->clut, 0, getTextureSize(16, 16, bpp32));
|
||||
|
||||
auto* pixel = static_cast<unsigned char*>(result->data);
|
||||
struct PngClut* clut = (struct PngClut*)result->clut;
|
||||
|
||||
for (int i = numPallete; i < 256; i++) {
|
||||
memset(&clut[i], 0, sizeof(clut[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < numPallete; i++) {
|
||||
clut[i].r = palette[i].red;
|
||||
clut[i].g = palette[i].green;
|
||||
clut[i].b = palette[i].blue;
|
||||
clut[i].a = 0x80;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numTrans; i++) clut[i].a = trans[i] >> 1;
|
||||
|
||||
// rotate clut
|
||||
for (int i = 0; i < numPallete; i++) {
|
||||
if ((i & 0x18) == 8) {
|
||||
struct PngClut tmp = clut[i];
|
||||
clut[i] = clut[i + 8];
|
||||
clut[i + 8] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
int k = 0;
|
||||
for (int i = 0; i < result->height; i++) {
|
||||
for (int j = 0; j < result->width; j++) {
|
||||
memcpy(&pixel[k++], &rowPointers[i][1 * j], 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int row = 0; row < result->height; row++) free(rowPointers[row]);
|
||||
|
||||
free(rowPointers);
|
||||
}
|
||||
|
||||
void PngLoader::handle4bppPalletized(TextureBuilderData* result,
|
||||
png_structp pngPtr, png_infop infoPtr,
|
||||
png_bytep* rowPointers, png_colorp palette,
|
||||
png_bytep trans, const int& numPallete,
|
||||
const int& numTrans) {
|
||||
int rowBytes = png_get_rowbytes(pngPtr, infoPtr);
|
||||
result->bpp = bpp4;
|
||||
result->clutWidth = 8;
|
||||
result->clutHeight = 2;
|
||||
result->gsComponents = TEXTURE_COMPONENTS_RGBA;
|
||||
result->data = static_cast<unsigned char*>(memalign(
|
||||
128, getTextureSize(result->width, result->height, result->bpp)));
|
||||
|
||||
rowPointers =
|
||||
static_cast<png_bytep*>(calloc(result->height, sizeof(png_bytep)));
|
||||
|
||||
for (int row = 0; row < result->height; row++)
|
||||
rowPointers[row] = static_cast<png_bytep>(malloc(rowBytes));
|
||||
|
||||
png_read_image(pngPtr, rowPointers);
|
||||
|
||||
result->clut =
|
||||
static_cast<unsigned char*>(memalign(128, getTextureSize(8, 2, bpp32)));
|
||||
memset(result->clut, 0, getTextureSize(8, 2, bpp32));
|
||||
|
||||
auto* pixel = static_cast<unsigned char*>(result->data);
|
||||
struct PngClut* clut = (struct PngClut*)result->clut;
|
||||
|
||||
for (int i = numPallete; i < 16; i++) {
|
||||
memset(&clut[i], 0, sizeof(clut[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < numPallete; i++) {
|
||||
clut[i].r = palette[i].red;
|
||||
clut[i].g = palette[i].green;
|
||||
clut[i].b = palette[i].blue;
|
||||
clut[i].a = 0x80;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numTrans; i++) clut[i].a = trans[i] >> 1;
|
||||
|
||||
int k = 0;
|
||||
for (int i = 0; i < result->height; i++) {
|
||||
for (int j = 0; j < result->width / 2; j++)
|
||||
memcpy(&pixel[k++], &rowPointers[i][1 * j], 1);
|
||||
}
|
||||
unsigned char* tmpdst = (unsigned char*)result->data;
|
||||
unsigned char* tmpsrc = (unsigned char*)pixel;
|
||||
|
||||
for (u32 byte = 0;
|
||||
byte < getTextureSize(result->width, result->height, result->bpp);
|
||||
byte++)
|
||||
tmpdst[byte] = (tmpsrc[byte] << 4) | (tmpsrc[byte] >> 4);
|
||||
|
||||
for (int row = 0; row < result->height; row++) free(rowPointers[row]);
|
||||
|
||||
free(rowPointers);
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
Reference in New Issue
Block a user