moved from h4570/tyra
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/loaders/bmp_loader.hpp"
|
||||
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
BmpLoader::BmpLoader() {}
|
||||
|
||||
BmpLoader::~BmpLoader() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/**
|
||||
* @param t_name Without extension. Example "skyfall2"
|
||||
* @param t_extension With dot and extension. Example ".BMP"
|
||||
*/
|
||||
void BmpLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension)
|
||||
{
|
||||
char *t_path_part = String::createConcatenated(t_subfolder, t_name);
|
||||
char *t_path = String::createConcatenated(t_path_part, t_extension);
|
||||
delete[] t_path_part;
|
||||
|
||||
FILE *file = fopen(t_path, "rb");
|
||||
|
||||
if (file == NULL)
|
||||
PRINT_ERR("Failed to load .bmp file!");
|
||||
|
||||
unsigned char header[54];
|
||||
fread(header, sizeof(unsigned char), 54, file);
|
||||
|
||||
u32 width = *(u32 *)&header[18];
|
||||
u32 height = *(u32 *)&header[22];
|
||||
o_texture.id = rand() % 100000;
|
||||
o_texture.width = width;
|
||||
o_texture.height = height;
|
||||
o_texture.data = new unsigned char[width * height * 3];
|
||||
printf("BMPLoader - width: %d | height: %d\n", width, height);
|
||||
|
||||
u64 rowPadded = (width * 3 + 3) & (~3);
|
||||
|
||||
unsigned char *data = new unsigned char[rowPadded];
|
||||
unsigned char tmp;
|
||||
|
||||
u32 x = 0;
|
||||
for (u32 i = 0; i < height; i++)
|
||||
{
|
||||
fread(data, sizeof(unsigned char), rowPadded, file);
|
||||
for (u32 j = 0; j < width * 3; j += 3)
|
||||
{
|
||||
// Convert (B, G, R) to (R, G, B)
|
||||
tmp = data[j];
|
||||
data[j] = data[j + 2];
|
||||
data[j + 2] = tmp;
|
||||
|
||||
o_texture.data[x] = data[j];
|
||||
o_texture.data[x + 1] = data[j + 1];
|
||||
o_texture.data[x + 2] = data[j + 2];
|
||||
x += 3;
|
||||
}
|
||||
}
|
||||
delete[] t_path;
|
||||
delete[] data;
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTICE: Based on
|
||||
* https://github.com/mrqo/rw_parse/blob/master/rw_utils/rw_utils.cpp
|
||||
* rw_utils.cpp Written by Marek Iwaniuk (c).
|
||||
* Dff structure documentation http://www.chronetal.co.uk/gta/index.php?page=dff
|
||||
* Created on 02/04/2017 (MM/DD/YYYY)
|
||||
*/
|
||||
|
||||
#include "../include/loaders/dff_loader.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/math.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
#include <cstring>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
DffLoader::DffLoader() {}
|
||||
|
||||
DffLoader::~DffLoader() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void DffLoader::load(RwClump &o_clump, char *t_filename, float t_scale)
|
||||
{
|
||||
PRINT_LOG("Loading dff file");
|
||||
FILE *file = fopen(t_filename, "rb");
|
||||
if (file == NULL)
|
||||
PRINT_ERR("Failed to load .obj file!");
|
||||
fseek(file, 0L, SEEK_END);
|
||||
long fileSize = ftell(file);
|
||||
u8 *data = new u8[fileSize];
|
||||
rewind(file);
|
||||
fread(data, sizeof(u8), fileSize, file);
|
||||
fclose(file);
|
||||
serialize(o_clump, data, t_scale);
|
||||
delete[] data;
|
||||
PRINT_LOG("Dff file loaded!");
|
||||
}
|
||||
|
||||
void DffLoader::serialize(RwClump &t_clump, u8 *t_data, float t_scale)
|
||||
{
|
||||
u32 ptrPos = 0;
|
||||
readSectionHeader(t_clump, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.data, t_data, ptrPos);
|
||||
readClumpData(t_clump.data, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.frameList, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.frameList.data, t_data, ptrPos);
|
||||
readFrameListData(t_clump.frameList.data, t_data, ptrPos);
|
||||
|
||||
t_clump.frameList.extensions = new RwFrameListExtension[t_clump.frameList.data.frameCount];
|
||||
for (u32 i = 0; i < t_clump.frameList.data.frameCount; i++)
|
||||
{
|
||||
readSectionHeader(t_clump.frameList.extensions[i], t_data, ptrPos);
|
||||
ptrPos += t_clump.frameList.extensions[i].sectionSize;
|
||||
}
|
||||
|
||||
readSectionHeader(t_clump.geometryList, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.data, t_data, ptrPos);
|
||||
readGeometryListData(t_clump.geometryList.data, t_data, ptrPos);
|
||||
|
||||
t_clump.geometryList.geometries = new RwGeometry[t_clump.geometryList.data.geometryCount];
|
||||
printf("Geometries:%d\n", t_clump.geometryList.data.geometryCount);
|
||||
for (u32 i = 0; i < t_clump.geometryList.data.geometryCount; i++)
|
||||
{
|
||||
readSectionHeader(t_clump.geometryList.geometries[i], t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].data, t_data, ptrPos);
|
||||
readGeometryData(t_clump.geometryList.geometries[i].data, t_data, ptrPos, t_scale);
|
||||
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.data, t_data, ptrPos);
|
||||
readMaterialListData(t_clump.geometryList.geometries[i].materialList.data, t_data, ptrPos);
|
||||
|
||||
u32 materialCount = t_clump.geometryList.geometries[i].materialList.data.materialCount;
|
||||
printf("Materials:%d\n", materialCount);
|
||||
|
||||
t_clump.geometryList.geometries[i].materialList.materials = new RwMaterial[materialCount];
|
||||
for (u32 j = 0; j < materialCount; j++)
|
||||
{
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j], t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].data, t_data, ptrPos);
|
||||
readMaterialData(t_clump.geometryList.geometries[i].materialList.materials[j].data, t_data, ptrPos);
|
||||
|
||||
u32 textureCount = t_clump.geometryList.geometries[i].materialList.materials[j].data.textureCount;
|
||||
t_clump.geometryList.geometries[i].materialList.materials[j].textures = new RwTexture[textureCount];
|
||||
for (u32 k = 0; k < textureCount; k++)
|
||||
{
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k], t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].data, t_data, ptrPos);
|
||||
readTextureData(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].data, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureName, t_data, ptrPos);
|
||||
readStringData(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureName, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureAlphaName, t_data, ptrPos);
|
||||
readStringData(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureAlphaName, t_data, ptrPos);
|
||||
|
||||
// The content of extension is Sky Mipmap Val
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].extension, t_data, ptrPos);
|
||||
ptrPos += t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].extension.sectionSize;
|
||||
}
|
||||
// Probably always void extension
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].extension, t_data, ptrPos);
|
||||
ptrPos += t_clump.geometryList.geometries[i].materialList.materials[j].extension.sectionSize;
|
||||
}
|
||||
// For Bin Mesh aka Material split
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].extension, t_data, ptrPos);
|
||||
readGeometryExtension(t_clump.geometryList.geometries[i].extension, t_data, ptrPos);
|
||||
ptrPos += t_clump.geometryList.geometries[i].extension.sectionSize;
|
||||
}
|
||||
|
||||
readSectionHeader(t_clump.atomic, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.atomic.data, t_data, ptrPos);
|
||||
ptrPos += t_clump.atomic.data.sectionSize;
|
||||
}
|
||||
|
||||
void DffLoader::readSectionHeader(RwSectionHeader &t_sh, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_sh.sectionType = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_sh.sectionSize = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_sh.versionNumber = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
void DffLoader::readFrameListData(RwFrameListData &t_frd, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_frd.frameCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
printf("Frame count:%d\n", t_frd.frameCount);
|
||||
t_frd.frameInformation = new RwFrameListChunk[t_frd.frameCount];
|
||||
|
||||
for (u32 i = 0; i < t_frd.frameCount; i++)
|
||||
{
|
||||
t_frd.frameInformation[i].rotationalMatrix = new float[t_frd.ROT_MAT_DIM];
|
||||
for (u32 j = 0; j < t_frd.ROT_MAT_DIM; j++)
|
||||
t_frd.frameInformation[i].rotationalMatrix[j] = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
t_frd.frameInformation[i].coordinatesOffsetX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_frd.frameInformation[i].coordinatesOffsetY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_frd.frameInformation[i].coordinatesOffsetZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_frd.frameInformation[i]
|
||||
.parentFrame = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_frd.frameInformation[i].unk1 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
}
|
||||
|
||||
void DffLoader::readClumpData(RwClumpData &t_cd, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_cd.objectCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_cd.unk1 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_cd.unk2 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
|
||||
void DffLoader::readGeometryListData(RwGeometryListData &t_gld, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_gld.geometryCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
|
||||
void DffLoader::readGeometryExtension(RwGeometryExtension &t_ge, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
for (u8 i = 0; i < 3; i++)
|
||||
t_ptrPos += sizeof(u32);
|
||||
|
||||
t_ge.materialSplit.header.triangleStrip = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_ge.materialSplit.header.splitCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_ge.materialSplit.header.faceCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
t_ge.materialSplit.splitInformation = new RwGeometryListInfoChunk[t_ge.materialSplit.header.splitCount];
|
||||
for (u32 i = 0; i < t_ge.materialSplit.header.splitCount; i++)
|
||||
{
|
||||
t_ge.materialSplit.splitInformation[i].faceIndex = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_ge.materialSplit.splitInformation[i].materialIndex = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
t_ge.materialSplit.splitInformation[i].vertexInformation = new RwGeometryListVertexInfoChunk[t_ge.materialSplit.splitInformation[i].faceIndex];
|
||||
for (u32 j = 0; j < t_ge.materialSplit.splitInformation[i].faceIndex; j++)
|
||||
t_ge.materialSplit.splitInformation[i].vertexInformation[j].vertex1 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
}
|
||||
|
||||
void DffLoader::readGeometryData(RwGeometryData &t_gd, u8 *t_buffer, u32 &t_ptrPos, float t_scale)
|
||||
{
|
||||
t_gd.dataHeader.flags = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.dataHeader.unk1 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.dataHeader.triangleCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.dataHeader.vertexCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.dataHeader.morphTargetCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
if (false)
|
||||
{ // version equals 4099 according to old documentation, disabled as for now
|
||||
t_gd.lightingHeader.ambient = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.lightingHeader.diffuse = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.lightingHeader.specular = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
|
||||
if (t_gd.dataHeader.flags & rwOBJECT_VERTEX_PRELIT)
|
||||
{
|
||||
t_gd.colorInformation = new RwGeometryDataColorInformationChunk[t_gd.dataHeader.vertexCount];
|
||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
||||
{
|
||||
t_gd.colorInformation[i].red = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.colorInformation[i].green = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.colorInformation[i].blue = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.colorInformation[i].alpha = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
}
|
||||
|
||||
if (t_gd.dataHeader.flags & rwOBJECT_VERTEX_TEXTURED)
|
||||
{
|
||||
t_gd.textureMappingInformation = new RwGeometryDataTextureMappingInformationChunk[t_gd.dataHeader.vertexCount];
|
||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
||||
{
|
||||
t_gd.textureMappingInformation[i].u = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.textureMappingInformation[i].v = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
}
|
||||
|
||||
t_gd.faceInformation = new RwGeometryDataFaceInformation[t_gd.dataHeader.triangleCount];
|
||||
for (u32 i = 0; i < t_gd.dataHeader.triangleCount; i++)
|
||||
{
|
||||
t_gd.faceInformation[i].vertex2 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.faceInformation[i].vertex1 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.faceInformation[i].flags = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.faceInformation[i].vertex3 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
|
||||
t_gd.nonameInfo.boundingSphereX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.nonameInfo.boundingSphereY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.nonameInfo.boundingSphereZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.nonameInfo.boundingSphereR = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.nonameInfo.hasPosition = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.nonameInfo.hasNormals = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
t_gd.vertexInformation = new Vector3[t_gd.dataHeader.vertexCount];
|
||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
||||
{
|
||||
t_gd.vertexInformation[i].x = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||
t_gd.vertexInformation[i].y = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||
t_gd.vertexInformation[i].z = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||
}
|
||||
|
||||
if (t_gd.dataHeader.flags & rwOBJECT_VERTEX_NORMALS)
|
||||
{
|
||||
t_gd.normalInformation = new Vector3[t_gd.dataHeader.vertexCount];
|
||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
||||
{
|
||||
t_gd.normalInformation[i].x = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.normalInformation[i].y = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.normalInformation[i].z = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DffLoader::readMaterialListData(RwMaterialListData &t_mld, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_mld.materialCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_mld.arrayOfUnks = new u32[t_mld.materialCount];
|
||||
for (u32 i = 0; i < t_mld.materialCount; i++)
|
||||
{
|
||||
t_mld.arrayOfUnks[i] = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
}
|
||||
|
||||
void DffLoader::readMaterialData(RwMaterialData &t_md, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_md.unk1 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_md.R = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_md.G = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_md.B = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_md.A = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_md.unk2 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_md.textureCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_md.unkPosX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_md.unkPosY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_md.unkPosZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
|
||||
void DffLoader::readTextureData(RwTextureData &t_td, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_td.textureFilterModeFlags = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_td.unk = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
|
||||
void DffLoader::readStringData(RwString &t_s, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_s.text = readString(t_buffer, t_ptrPos, t_s.sectionSize);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
u8 DffLoader::readByteFromArrayLE(u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
return t_buffer[t_ptrPos++];
|
||||
}
|
||||
|
||||
u16 DffLoader::readWordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
u16 res = (t_buffer[t_ptrPos + 1] << 8) + (t_buffer[t_ptrPos]);
|
||||
t_ptrPos += sizeof(u16);
|
||||
return res;
|
||||
}
|
||||
|
||||
u32 DffLoader::readDwordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
u32 res = (t_buffer[t_ptrPos + 3] << 24) + (t_buffer[t_ptrPos + 2] << 16) + (t_buffer[t_ptrPos + 1] << 8) + (t_buffer[t_ptrPos]);
|
||||
t_ptrPos += sizeof(u32);
|
||||
return res;
|
||||
}
|
||||
|
||||
float DffLoader::readFloatFromArrayLE(u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
float res;
|
||||
memcpy(&res, t_buffer + t_ptrPos, sizeof(float));
|
||||
t_ptrPos += sizeof(float);
|
||||
return res;
|
||||
}
|
||||
|
||||
u8 *DffLoader::readData(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize)
|
||||
{
|
||||
u8 *arr = new u8[t_dataSize];
|
||||
for (u32 i = 0; i < t_dataSize; ++i)
|
||||
arr[i] = t_buffer[i + t_ptrPos];
|
||||
t_ptrPos += t_dataSize;
|
||||
return arr;
|
||||
}
|
||||
|
||||
char *DffLoader::readString(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize)
|
||||
{
|
||||
u32 strLength = String::getLength((char *)&t_buffer[t_ptrPos]);
|
||||
char *result = new char[strLength + 1];
|
||||
for (u32 i = 0; i < strLength; i++)
|
||||
result[i] = (char)t_buffer[t_ptrPos + i];
|
||||
result[strLength] = '\0';
|
||||
t_ptrPos += t_dataSize;
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/loaders/md2_loader.hpp"
|
||||
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/models/math/vector3.hpp"
|
||||
#include "../include/models/math/point.hpp"
|
||||
#include <string.h>
|
||||
#include <iosfwd>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
MD2Loader::MD2Loader() {}
|
||||
|
||||
MD2Loader::~MD2Loader() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/** Load, parse .obj file and load data into given MeshSpec */
|
||||
void MD2Loader::load(MD2Model *o_result, char *t_filename, float t_scale)
|
||||
{
|
||||
PRINT_LOG("Loading new MD2 file");
|
||||
md2_t header; // md2 header
|
||||
char *buffer; // buffer storing frame data
|
||||
|
||||
FILE *file = fopen(t_filename, "rb");
|
||||
|
||||
if (file == NULL)
|
||||
PRINT_ERR("Failed to load .md2 file!");
|
||||
|
||||
fread((char *)&header, sizeof(md2_t), 1, file);
|
||||
|
||||
if ((header.ident != MD2_IDENT) && (header.version != MD2_VERSION))
|
||||
PRINT_ERR("This MD2 file was not in correct format!");
|
||||
|
||||
o_result->framesCount = header.num_frames;
|
||||
o_result->verticesPerFrameCount = header.num_xyz;
|
||||
o_result->coordinatesCount = header.num_st;
|
||||
o_result->trianglesCount = header.num_tris;
|
||||
|
||||
printf("MD2 - Frames: %d\n", header.num_frames);
|
||||
printf("MD2 - Vert: %d\n", header.num_xyz);
|
||||
printf("MD2 - Tris: %d\n", header.num_tris);
|
||||
printf("MD2 - STs: %d\n", header.num_st);
|
||||
printf("MD2 - Skin W:%d H: %d\n", header.skinwidth, header.skinheight);
|
||||
|
||||
o_result->allocateMemory();
|
||||
|
||||
buffer = new char[o_result->framesCount * header.framesize];
|
||||
fseek(file, header.ofs_frames, SEEK_SET);
|
||||
fread((char *)buffer, o_result->framesCount * header.framesize, 1, file);
|
||||
|
||||
frame_t *frame; // temporary vars
|
||||
Vector3 *ptrVerts;
|
||||
u32 *ptrNormals;
|
||||
// vertex array initialization
|
||||
for (u32 j = 0; j < o_result->framesCount; j++)
|
||||
{
|
||||
frame = (frame_t *)&buffer[header.framesize * j];
|
||||
ptrVerts = &o_result->vertices[o_result->verticesPerFrameCount * j];
|
||||
ptrNormals = &o_result->normalIndexes[o_result->verticesPerFrameCount * j];
|
||||
|
||||
for (u32 i = 0; i < o_result->verticesPerFrameCount; i++)
|
||||
{
|
||||
ptrVerts[i].x = ((frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0]) * t_scale;
|
||||
ptrVerts[i].y = ((frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1]) * t_scale;
|
||||
ptrVerts[i].z = ((frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2]) * t_scale;
|
||||
|
||||
ptrNormals[i] = frame->verts[i].lightnormalindex;
|
||||
}
|
||||
if (j == o_result->framesCount - 1)
|
||||
printf("Last frame, last vert: X:%f Y:%f Z:%f\n",
|
||||
ptrVerts[o_result->verticesPerFrameCount - 1].x,
|
||||
ptrVerts[o_result->verticesPerFrameCount - 1].y,
|
||||
ptrVerts[o_result->verticesPerFrameCount - 1].z);
|
||||
}
|
||||
delete[] buffer;
|
||||
|
||||
buffer = new char[o_result->coordinatesCount * sizeof(texCoord_t)];
|
||||
fseek(file, header.ofs_st, SEEK_SET);
|
||||
fread((char *)buffer, o_result->coordinatesCount * sizeof(texCoord_t), 1, file);
|
||||
|
||||
texCoord_t *texCoord;
|
||||
for (u32 i = 0; i < o_result->coordinatesCount; i++)
|
||||
{
|
||||
texCoord = (texCoord_t *)&buffer[sizeof(texCoord_t) * i];
|
||||
o_result->coordinates[i].x = (float)texCoord->s / header.skinwidth;
|
||||
o_result->coordinates[i].y = (float)texCoord->t / header.skinheight;
|
||||
}
|
||||
delete[] buffer;
|
||||
|
||||
printf("Last tex coord(%d): S:%f T:%f\n",
|
||||
o_result->coordinatesCount,
|
||||
o_result->coordinates[o_result->coordinatesCount - 1].x,
|
||||
o_result->coordinates[o_result->coordinatesCount - 1].y);
|
||||
|
||||
buffer = new char[o_result->trianglesCount * sizeof(triangle_t)];
|
||||
fseek(file, header.ofs_tris, SEEK_SET);
|
||||
fread((char *)buffer, o_result->trianglesCount * sizeof(triangle_t), 1, file);
|
||||
|
||||
triangle_t *triangle; // temporary var
|
||||
// vertex array initialization
|
||||
for (u32 i = 0; i < o_result->trianglesCount; i++)
|
||||
{
|
||||
triangle = (triangle_t *)&buffer[sizeof(triangle_t) * i];
|
||||
for (u8 j = 0; j < 3; j++)
|
||||
{
|
||||
o_result->triangles[i].verticeIndexes[j] = triangle->index_xyz[j];
|
||||
o_result->triangles[i].coordIndexes[j] = triangle->index_st[j];
|
||||
}
|
||||
}
|
||||
delete[] buffer;
|
||||
|
||||
fclose(file);
|
||||
PRINT_LOG("MD2 file loaded!");
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/loaders/obj_loader.hpp"
|
||||
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include <string.h>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
ObjLoader::ObjLoader() {}
|
||||
|
||||
ObjLoader::~ObjLoader() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/** Load, parse .obj file and load data into given MeshSpec */
|
||||
void ObjLoader::load(ObjModel *o_result, char *t_filename, float t_scale)
|
||||
{
|
||||
FILE *file = fopen(t_filename, "rb");
|
||||
if (file == NULL)
|
||||
PRINT_ERR("Failed to load .obj file!");
|
||||
setObjDataQuantities(file, o_result);
|
||||
o_result->allocateMemory();
|
||||
u32 verticesI = 0, cordsI = 0, normalsI = 0, i = 0, vertexIndex[3], coordIndex[3], normalIndex[3];
|
||||
while (1)
|
||||
{
|
||||
char lineHeader[128]; // read the first word of the line
|
||||
int res = fscanf(file, "%s", lineHeader);
|
||||
if (res != EOF)
|
||||
{
|
||||
if (strcmp(lineHeader, "v") == 0)
|
||||
{
|
||||
Vector3 vector = Vector3();
|
||||
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
|
||||
o_result->vertices[verticesI++] = vector * t_scale;
|
||||
}
|
||||
else if (strcmp(lineHeader, "vt") == 0)
|
||||
{
|
||||
Vector3 vector = Vector3();
|
||||
fscanf(file, "%f %f\n", &vector.x, &vector.y);
|
||||
o_result->coordinates[cordsI++] = vector;
|
||||
}
|
||||
else if (strcmp(lineHeader, "vn") == 0)
|
||||
{
|
||||
Vector3 vector = Vector3();
|
||||
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
|
||||
o_result->normals[normalsI++] = vector;
|
||||
}
|
||||
else if (strcmp(lineHeader, "f") == 0)
|
||||
{
|
||||
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
|
||||
&vertexIndex[0], &coordIndex[0], &normalIndex[0],
|
||||
&vertexIndex[1], &coordIndex[1], &normalIndex[1],
|
||||
&vertexIndex[2], &coordIndex[2], &normalIndex[2]);
|
||||
if (matches != 9)
|
||||
PRINT_ERR(".obj can't be read by this simple parser. Try exporting with other options");
|
||||
else
|
||||
{
|
||||
o_result->verticeFaces[i] = vertexIndex[0] - 1;
|
||||
o_result->verticeFaces[i + 1] = vertexIndex[1] - 1;
|
||||
o_result->verticeFaces[i + 2] = vertexIndex[2] - 1;
|
||||
|
||||
o_result->coordinateFaces[i] = coordIndex[0] - 1;
|
||||
o_result->coordinateFaces[i + 1] = coordIndex[1] - 1;
|
||||
o_result->coordinateFaces[i + 2] = coordIndex[2] - 1;
|
||||
|
||||
o_result->normalFaces[i] = normalIndex[0] - 1;
|
||||
o_result->normalFaces[i + 1] = normalIndex[1] - 1;
|
||||
o_result->normalFaces[i + 2] = normalIndex[2] - 1;
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
/** Calculate how many vertices(v), coordinates(vt), normals(vn) and faces(f) have .obj file
|
||||
* When done, file read offset is resetted to the begginning of file
|
||||
*/
|
||||
void ObjLoader::setObjDataQuantities(FILE *t_file, ObjModel *o_result)
|
||||
{
|
||||
o_result->verticesCount = 0;
|
||||
o_result->coordinatesCount = 0;
|
||||
o_result->normalsCount = 0;
|
||||
o_result->facesCount = 0;
|
||||
while (1)
|
||||
{
|
||||
char lineHeader[128];
|
||||
int res = fscanf(t_file, "%s", lineHeader);
|
||||
if (res != EOF)
|
||||
{
|
||||
if (strcmp(lineHeader, "v") == 0)
|
||||
o_result->verticesCount += 1;
|
||||
else if (strcmp(lineHeader, "vt") == 0)
|
||||
o_result->coordinatesCount += 1;
|
||||
else if (strcmp(lineHeader, "vn") == 0)
|
||||
o_result->normalsCount += 1;
|
||||
else if (strcmp(lineHeader, "f") == 0)
|
||||
o_result->facesCount += 3;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
fseek(t_file, 0, SEEK_SET);
|
||||
}
|
||||
Reference in New Issue
Block a user