obj loader refactor
This commit is contained in:
@@ -19,6 +19,10 @@ MeshBuilder2Data::MeshBuilder2Data() {
|
||||
lightMapEnabled = false;
|
||||
}
|
||||
|
||||
MeshBuilder2Data::~MeshBuilder2Data() {}
|
||||
MeshBuilder2Data::~MeshBuilder2Data() {
|
||||
for (auto& material : materials) {
|
||||
delete material;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
|
||||
@@ -13,7 +13,13 @@
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
MeshBuilder2MaterialData::MeshBuilder2MaterialData() {}
|
||||
MeshBuilder2MaterialData::~MeshBuilder2MaterialData() {}
|
||||
MeshBuilder2MaterialData::MeshBuilder2MaterialData() {
|
||||
ambient.set(128.0F, 128.0F, 128.0F, 128.0F);
|
||||
}
|
||||
MeshBuilder2MaterialData::~MeshBuilder2MaterialData() {
|
||||
for (auto& frame : frames) {
|
||||
delete frame;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
|
||||
+8
-9
@@ -12,9 +12,9 @@
|
||||
#include <string>
|
||||
#include "debug/debug.hpp"
|
||||
#include "loaders/3d/builder/mesh_builder_data.hpp"
|
||||
#include "loaders/3d/md2/anorms.hpp"
|
||||
#include "loaders/3d/md2_loader/anorms.hpp"
|
||||
#include "loaders/loader.hpp"
|
||||
#include "loaders/3d/md2/md2_loader.hpp"
|
||||
#include "loaders/3d/md2_loader/md2_loader.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
@@ -96,9 +96,10 @@ MeshBuilderData* MD2Loader::load(const char* fullpath, const float& scale,
|
||||
u32 stsCount = header.num_st;
|
||||
u32 trianglesCount = header.num_tris;
|
||||
|
||||
auto framesBuffer = new char[framesCount * header.framesize];
|
||||
auto framesBufferSize = framesCount * header.framesize;
|
||||
auto framesBuffer = new char[framesBufferSize];
|
||||
fseek(file, header.ofs_frames, SEEK_SET);
|
||||
fread(framesBuffer, framesCount * header.framesize, 1, file);
|
||||
fread(framesBuffer, framesBufferSize, 1, file);
|
||||
|
||||
auto stsBuffer = new char[stsCount * sizeof(texCoord_t)];
|
||||
fseek(file, header.ofs_st, SEEK_SET);
|
||||
@@ -116,6 +117,9 @@ MeshBuilderData* MD2Loader::load(const char* fullpath, const float& scale,
|
||||
result->textureCoordsEnabled = true;
|
||||
result->manyColorsEnabled = false;
|
||||
|
||||
result->materials[0]->allocateFaces(trianglesCount * 3);
|
||||
result->materials[0]->name = getFilenameWithoutExtension(filename);
|
||||
|
||||
frame_t* frame;
|
||||
Vec4 temp(0.0F, 0.0F, 0.0F, 1.0F);
|
||||
for (u32 j = 0; j < framesCount; j++) {
|
||||
@@ -123,9 +127,6 @@ MeshBuilderData* MD2Loader::load(const char* fullpath, const float& scale,
|
||||
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++) {
|
||||
@@ -179,8 +180,6 @@ MeshBuilderData* MD2Loader::load(const char* fullpath, const float& scale,
|
||||
}
|
||||
}
|
||||
|
||||
TYRA_LOG("MD2 file \"", filename, "\" loaded!");
|
||||
|
||||
delete[] framesBuffer;
|
||||
delete[] stsBuffer;
|
||||
delete[] trianglesBuffer;
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "math/vec2.hpp"
|
||||
#include "math/vec4.hpp"
|
||||
#include "renderer/models/color.hpp"
|
||||
#include "debug/debug.hpp"
|
||||
#include "loaders/3d/obj_loader/obj_loader.hpp"
|
||||
|
||||
#define TINYOBJLOADER_USE_MAPBOX_EARCUT
|
||||
#define TINYOBJLOADER_IMPLEMENTATION
|
||||
#include "loaders/3d/obj_loader/tiny_obj_loader.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
ObjLoader::ObjLoader() {}
|
||||
|
||||
ObjLoader::~ObjLoader() {}
|
||||
|
||||
MeshBuilder2Data* ObjLoader::load(const char* fullpath, const u16& count,
|
||||
const float& scale, const bool& invertY) {
|
||||
std::string path = fullpath;
|
||||
std::string basePath = getPathFromFilename(path);
|
||||
|
||||
TYRA_ASSERT(!path.empty(), "Provided path is empty!");
|
||||
|
||||
auto rawFilename = getFilenameWithoutExtension(path);
|
||||
auto extension = getExtensionOfFilename(path);
|
||||
|
||||
auto* result = new MeshBuilder2Data();
|
||||
|
||||
tinyobj::ObjReaderConfig readerConfig;
|
||||
readerConfig.triangulate = count == 1;
|
||||
readerConfig.triangulation_method = count == 1 ? "earcut" : "simple";
|
||||
readerConfig.mtl_search_path = basePath;
|
||||
|
||||
for (u16 i = 1; i <= count; i++) {
|
||||
std::string filePath = rawFilename + std::to_string(i) + "." + extension;
|
||||
if (count == 1) filePath = path;
|
||||
|
||||
tinyobj::ObjReader reader;
|
||||
|
||||
if (!reader.ParseFromFile(filePath, readerConfig)) {
|
||||
if (!reader.Error().empty()) {
|
||||
TYRA_TRAP("TinyObjLoader: ", reader.Error());
|
||||
}
|
||||
TYRA_TRAP("Unknown TinyObjLoader error!");
|
||||
}
|
||||
|
||||
if (!reader.Warning().empty()) {
|
||||
TYRA_WARN("TinyObjReader: ", reader.Warning());
|
||||
}
|
||||
|
||||
auto& attrib = reader.GetAttrib();
|
||||
auto& shapes = reader.GetShapes();
|
||||
auto& materials = reader.GetMaterials();
|
||||
|
||||
TYRA_ASSERT(
|
||||
materials.size() > 0,
|
||||
"No material data found! Please add .mtl file(s) and assign them via "
|
||||
"mtlib in obj file");
|
||||
|
||||
if (i == 1) {
|
||||
setInitialData(result, attrib, shapes, materials, count);
|
||||
}
|
||||
|
||||
importFrame(result, attrib, shapes, materials, i - 1, scale, invertY,
|
||||
count);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ObjLoader::setInitialData(
|
||||
MeshBuilder2Data* output, const tinyobj::attrib_t& attrib,
|
||||
const std::vector<tinyobj::shape_t>& shapes,
|
||||
const std::vector<tinyobj::material_t>& materials, const u16& framesCount) {
|
||||
if (attrib.texcoords.size()) output->textureCoordsEnabled = true;
|
||||
|
||||
if (attrib.normals.size()) output->normalsEnabled = true;
|
||||
|
||||
TYRA_ASSERT(materials.size() > 0,
|
||||
"No material data found! Please add .mtl "
|
||||
"file(s) and assign them via mtlib in obj "
|
||||
"file");
|
||||
|
||||
for (size_t i = 0; i < materials.size(); i++) {
|
||||
auto* material = new MeshBuilder2MaterialData();
|
||||
|
||||
material->name = materials[i].name;
|
||||
|
||||
material->ambient.set(materials[i].ambient[0] * 255.0F,
|
||||
materials[i].ambient[1] * 255.0F,
|
||||
materials[i].ambient[2] * 255.0F, 128.0F);
|
||||
|
||||
for (size_t j = 0; j < framesCount; j++) {
|
||||
auto* frame = new MeshBuilder2MaterialFrameData();
|
||||
material->frames.push_back(frame);
|
||||
}
|
||||
|
||||
output->materials.push_back(material);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjLoader::importFrame(MeshBuilder2Data* output,
|
||||
const tinyobj::attrib_t& attrib,
|
||||
const std::vector<tinyobj::shape_t>& shapes,
|
||||
const std::vector<tinyobj::material_t>& materials,
|
||||
const u16& frameIndex, const float& scale,
|
||||
const bool& invertY, const u16& count) {
|
||||
for (size_t i = 0; i < shapes.size(); i++) {
|
||||
const auto& mesh = shapes[i].mesh;
|
||||
|
||||
// Loop over shapes
|
||||
for (size_t s = 0; s < shapes.size(); s++) {
|
||||
size_t index_offset = 0;
|
||||
// Loop over faces
|
||||
for (size_t f = 0; f < mesh.num_face_vertices.size(); f++) {
|
||||
auto materialId = mesh.material_ids[f];
|
||||
auto* outFrame = output->materials[materialId]->frames[frameIndex];
|
||||
|
||||
auto isAllocated = outFrame->vertices != nullptr;
|
||||
|
||||
if (!isAllocated) {
|
||||
auto vertCount = mesh.num_face_vertices.size() * 3;
|
||||
|
||||
outFrame->count = vertCount;
|
||||
outFrame->vertices = new Vec4[vertCount];
|
||||
|
||||
if (output->textureCoordsEnabled)
|
||||
outFrame->textureCoords = new Vec4[vertCount];
|
||||
|
||||
if (output->normalsEnabled) outFrame->normals = new Vec4[vertCount];
|
||||
} else {
|
||||
TYRA_ASSERT(outFrame->count == mesh.num_face_vertices.size() * 3,
|
||||
"Multiple usage of the same \"usemtl\" is not supported! "
|
||||
"Please merge them!");
|
||||
}
|
||||
|
||||
size_t fv = size_t(mesh.num_face_vertices[f]);
|
||||
|
||||
TYRA_ASSERT(count == 1 || fv == 3,
|
||||
"Please triangulate obj files if you are animating!",
|
||||
"Recommended Blender options: ",
|
||||
"- Obj exporting: triangulate off, keep vertex order",
|
||||
"- Object modifiers: triangulate (as first!), then other "
|
||||
"modifiers");
|
||||
|
||||
// Loop over vertices in the face.
|
||||
for (size_t v = 0; v < fv; v++) {
|
||||
// access to vertex
|
||||
tinyobj::index_t idx = mesh.indices[index_offset + v];
|
||||
tinyobj::real_t vx =
|
||||
attrib.vertices[3 * size_t(idx.vertex_index) + 0];
|
||||
tinyobj::real_t vy =
|
||||
attrib.vertices[3 * size_t(idx.vertex_index) + 1];
|
||||
tinyobj::real_t vz =
|
||||
attrib.vertices[3 * size_t(idx.vertex_index) + 2];
|
||||
|
||||
outFrame->vertices[index_offset + v].set(vx, vy, vz, 1.0F);
|
||||
outFrame->vertices[index_offset + v] *= scale;
|
||||
|
||||
// Check if `normal_index` is zero or positive. negative = no normal
|
||||
// data
|
||||
if (idx.normal_index >= 0) {
|
||||
tinyobj::real_t nx =
|
||||
attrib.normals[3 * size_t(idx.normal_index) + 0];
|
||||
tinyobj::real_t ny =
|
||||
attrib.normals[3 * size_t(idx.normal_index) + 1];
|
||||
tinyobj::real_t nz =
|
||||
attrib.normals[3 * size_t(idx.normal_index) + 2];
|
||||
|
||||
outFrame->normals[index_offset + v].set(nx, ny, nz, 1.0F);
|
||||
}
|
||||
|
||||
// Check if `texcoord_index` is zero or positive. negative =
|
||||
// notexcoord data
|
||||
if (idx.texcoord_index >= 0) {
|
||||
tinyobj::real_t tx =
|
||||
attrib.texcoords[2 * size_t(idx.texcoord_index) + 0];
|
||||
tinyobj::real_t ty =
|
||||
attrib.texcoords[2 * size_t(idx.texcoord_index) + 1];
|
||||
|
||||
auto finalY = invertY ? 1.0F - ty : ty;
|
||||
outFrame->textureCoords[index_offset + v].set(tx, finalY, 1.0F,
|
||||
0.0F);
|
||||
}
|
||||
}
|
||||
|
||||
index_offset += fv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -1,322 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include "math/vec2.hpp"
|
||||
#include "math/vec4.hpp"
|
||||
#include "renderer/models/color.hpp"
|
||||
#include "debug/debug.hpp"
|
||||
#include "loaders/3d/tyrobj/tyrobj_loader.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
TyrobjLoader::TyrobjLoader() {}
|
||||
|
||||
TyrobjLoader::~TyrobjLoader() {}
|
||||
|
||||
MeshBuilderData* TyrobjLoader::load(const char* fullpath, const u16& count,
|
||||
const float& scale, const bool& invertT) {
|
||||
std::string path = fullpath;
|
||||
TYRA_ASSERT(!path.empty(), "Provided path is empty!");
|
||||
|
||||
auto rawFilename = getFilenameWithoutExtension(path);
|
||||
auto extension = getExtensionOfFilename(path);
|
||||
|
||||
std::string firstFile = path;
|
||||
if (count > 1) firstFile = rawFilename + "1." + extension;
|
||||
|
||||
FILE* firstFileHandler = fopen(firstFile.c_str(), "rb");
|
||||
TYRA_ASSERT(firstFileHandler != nullptr, "Failed to load: ", firstFile);
|
||||
auto data = scan(firstFileHandler, count);
|
||||
data.scale = scale;
|
||||
data.invertT = invertT;
|
||||
fclose(firstFileHandler);
|
||||
|
||||
auto result = new MeshBuilderData();
|
||||
result->allocate(data.framesCount, data.materialsCount);
|
||||
result->normalsEnabled = data.normalsCount > 0;
|
||||
result->textureCoordsEnabled = data.stsCount > 0;
|
||||
result->manyColorsEnabled = data.colorsCount > 0;
|
||||
|
||||
for (u16 i = 1; i <= count; i++) {
|
||||
std::string filePath = rawFilename + std::to_string(i) + "." + extension;
|
||||
if (count == 1) filePath = path;
|
||||
|
||||
FILE* fileHandler = fopen(filePath.c_str(), "rb");
|
||||
TYRA_ASSERT(fileHandler != nullptr, "Failed to load: ", filePath);
|
||||
loadFile(fileHandler, filePath, i - 1, data, result);
|
||||
fclose(fileHandler);
|
||||
}
|
||||
|
||||
delete data.materialsFaces;
|
||||
return result;
|
||||
}
|
||||
|
||||
TyraobjData TyrobjLoader::scan(FILE* file, const u32& framesCount) {
|
||||
TyraobjData result;
|
||||
result.vertexCount = 0;
|
||||
result.stsCount = 0;
|
||||
result.normalsCount = 0;
|
||||
result.colorsCount = 0;
|
||||
result.materialsCount = 0;
|
||||
result.framesCount = framesCount;
|
||||
|
||||
while (1) {
|
||||
char lineHeader[128];
|
||||
int res = fscanf(file, "%s", lineHeader);
|
||||
if (res != EOF) {
|
||||
if (strcmp(lineHeader, "v") == 0)
|
||||
result.vertexCount += 1;
|
||||
else if (strcmp(lineHeader, "vt") == 0)
|
||||
result.stsCount += 1;
|
||||
else if (strcmp(lineHeader, "vn") == 0)
|
||||
result.normalsCount += 1;
|
||||
else if (strcmp(lineHeader, "vc") == 0)
|
||||
result.colorsCount += 1;
|
||||
else if (strcmp(lineHeader, "usemtl") == 0)
|
||||
result.materialsCount += 1;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
result.materialsFaces = new u32[result.materialsCount];
|
||||
s16 currentMatI = -1;
|
||||
|
||||
fseek(file, 0, SEEK_SET);
|
||||
u32 facesCounter = 0;
|
||||
while (1) {
|
||||
char lineHeader[128];
|
||||
int res = fscanf(file, "%s", lineHeader);
|
||||
if (res != EOF) {
|
||||
if (strcmp(lineHeader, "usemtl") == 0) {
|
||||
if (currentMatI >= 0) // Skip -1
|
||||
{
|
||||
result.materialsFaces[currentMatI] = facesCounter;
|
||||
facesCounter = 0;
|
||||
}
|
||||
currentMatI++;
|
||||
} else if (strcmp(lineHeader, "f") == 0)
|
||||
facesCounter += 3;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
result.materialsFaces[currentMatI] = facesCounter; // Allocate last one
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TyrobjLoader::loadFile(FILE* file, const std::string& path,
|
||||
const u16& frameIndex, const TyraobjData& inputData,
|
||||
MeshBuilderData* outputData) {
|
||||
outputData->frames[frameIndex]->allocateVertices(inputData.vertexCount);
|
||||
outputData->frames[frameIndex]->allocateNormals(inputData.normalsCount);
|
||||
outputData->frames[frameIndex]->allocateTextureCoords(inputData.stsCount);
|
||||
outputData->frames[frameIndex]->allocateColors(inputData.colorsCount);
|
||||
|
||||
TyraobjReadInfo readInfo;
|
||||
initReadInfo(&readInfo);
|
||||
|
||||
int res = 0;
|
||||
char* lineHeader = new char[128];
|
||||
|
||||
while (res != EOF) {
|
||||
if (strcmp(lineHeader, "v") == 0) {
|
||||
readVertices(&readInfo, file, frameIndex, inputData, outputData);
|
||||
} else if (strcmp(lineHeader, "vt") == 0) {
|
||||
readTextureCoords(&readInfo, file, frameIndex, inputData, outputData);
|
||||
} else if (strcmp(lineHeader, "vn") == 0) {
|
||||
readNormals(&readInfo, file, frameIndex, outputData);
|
||||
} else if (strcmp(lineHeader, "vc") == 0) {
|
||||
readColors(&readInfo, file, frameIndex, outputData);
|
||||
} else if (strcmp(lineHeader, "usemtl") == 0) {
|
||||
readInfo.materialsI++;
|
||||
readInfo.faceI = 0;
|
||||
if (frameIndex == 0) {
|
||||
readMaterials(&readInfo, file, inputData, outputData);
|
||||
}
|
||||
} else if (strcmp(lineHeader, "f") == 0) {
|
||||
if (frameIndex == 0) {
|
||||
readFaces(&readInfo, file, outputData);
|
||||
}
|
||||
}
|
||||
|
||||
res = fscanf(file, "%s", lineHeader);
|
||||
}
|
||||
|
||||
delete[] lineHeader;
|
||||
}
|
||||
|
||||
void TyrobjLoader::initReadInfo(TyraobjReadInfo* info) {
|
||||
info->verticesI = 0;
|
||||
info->coordsI = 0;
|
||||
info->normalsI = 0;
|
||||
info->colorsI = 0;
|
||||
info->faceI = 0;
|
||||
info->materialsI = -1;
|
||||
}
|
||||
|
||||
void TyrobjLoader::readVertices(TyraobjReadInfo* info, FILE* file,
|
||||
const u16& frameIndex,
|
||||
const TyraobjData& inputData,
|
||||
MeshBuilderData* outputData) {
|
||||
Vec4 vector(0.0F, 0.0F, 0.0F, 1.0F);
|
||||
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
|
||||
outputData->frames[frameIndex]->vertices[info->verticesI++].set(
|
||||
vector * inputData.scale);
|
||||
}
|
||||
|
||||
void TyrobjLoader::readTextureCoords(TyraobjReadInfo* info, FILE* file,
|
||||
const u16& frameIndex,
|
||||
const TyraobjData& inputData,
|
||||
MeshBuilderData* outputData) {
|
||||
Vec2 point(0.0F, 0.0F);
|
||||
fscanf(file, "%f %f\n", &point.x, &point.y);
|
||||
if (inputData.invertT) point.y = 1.0F - point.y;
|
||||
outputData->frames[frameIndex]->textureCoords[info->coordsI++].set(
|
||||
point.x, point.y, 1.0F, 0.0F);
|
||||
}
|
||||
|
||||
void TyrobjLoader::readNormals(TyraobjReadInfo* info, FILE* file,
|
||||
const u16& frameIndex,
|
||||
MeshBuilderData* outputData) {
|
||||
Vec4 vector(0.0F, 0.0F, 0.0F, 1.0F);
|
||||
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
|
||||
outputData->frames[frameIndex]->normals[info->normalsI++].set(vector);
|
||||
}
|
||||
|
||||
void TyrobjLoader::readColors(TyraobjReadInfo* info, FILE* file,
|
||||
const u16& frameIndex,
|
||||
MeshBuilderData* outputData) {
|
||||
Color color(128.0F, 128.0F, 128.0F, 128.0F);
|
||||
fscanf(file, "%f %f %f %f\n", &color.r, &color.g, &color.b, &color.a);
|
||||
outputData->frames[frameIndex]->colors[info->colorsI++].set(color);
|
||||
}
|
||||
|
||||
void TyrobjLoader::readMaterials(TyraobjReadInfo* info, FILE* file,
|
||||
const TyraobjData& inputData,
|
||||
MeshBuilderData* outputData) {
|
||||
char temp[30];
|
||||
fscanf(file, "%s\n", temp);
|
||||
outputData->materials[info->materialsI]->allocateFaces(
|
||||
inputData.materialsFaces[info->materialsI]);
|
||||
outputData->materials[info->materialsI]->name = temp;
|
||||
}
|
||||
|
||||
int test123 = 0;
|
||||
|
||||
void TyrobjLoader::readFaces(TyraobjReadInfo* info, FILE* file,
|
||||
MeshBuilderData* outputData) {
|
||||
int* x = new int[9];
|
||||
fpos_t start;
|
||||
fgetpos(file, &start);
|
||||
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &x[0], &x[1],
|
||||
&x[2], &x[3], &x[4], &x[5], &x[6], &x[7], &x[8]);
|
||||
fsetpos(file, &start);
|
||||
|
||||
// TODO: No support of vc!
|
||||
u32 vertexIndex[3], coordIndex[3], normalIndex[3]; // ,colorIndex[3];
|
||||
for (u16 i = 0; i < 3; i++) {
|
||||
vertexIndex[i] = 0;
|
||||
coordIndex[i] = 0;
|
||||
normalIndex[i] = 0;
|
||||
// colorIndex[i] = 0;
|
||||
}
|
||||
|
||||
int newerMatches = 0;
|
||||
|
||||
switch (matches) {
|
||||
/** Vs, VTs and VNs all set */
|
||||
case 9: {
|
||||
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]);
|
||||
} break;
|
||||
|
||||
/** Loaded only two digits (V, VT) succesfuly. Not setting VN. */
|
||||
case 3: {
|
||||
fscanf(file, "%d/%d/ %d/%d/ %d/%d/\n", &vertexIndex[0], &coordIndex[0],
|
||||
&vertexIndex[1], &coordIndex[1], &vertexIndex[2], &coordIndex[2]);
|
||||
} break;
|
||||
|
||||
/** Only V set. Checking for existance of VT or VN. */
|
||||
case 1: {
|
||||
/** Check for existance of V/// configuration.. */
|
||||
newerMatches = fscanf(file, "%d// %d// %d//\n", &x[0], &x[1], &x[2]);
|
||||
fsetpos(file, &start);
|
||||
if (newerMatches == 3) {
|
||||
/** Configuration confirmed. */
|
||||
fscanf(file, "%d// %d// %d//\n", &vertexIndex[0], &vertexIndex[1],
|
||||
&vertexIndex[2]);
|
||||
} else {
|
||||
/** Failed, checking configuration V//VN */
|
||||
newerMatches = fscanf(file, "%d//%d %d//%d %d//%d", &x[0], &x[1], &x[2],
|
||||
&x[3], &x[4], &x[5]);
|
||||
fsetpos(file, &start);
|
||||
TYRA_ASSERT(newerMatches == 6, "Unknown .obj face for .obj file!");
|
||||
/** Configuration confirmed. */
|
||||
newerMatches = fscanf(file, "%d//%d %d//%d %d//%d", &vertexIndex[0],
|
||||
&normalIndex[0], &vertexIndex[1], &normalIndex[1],
|
||||
&vertexIndex[2], &normalIndex[2]);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
default: {
|
||||
TYRA_TRAP("Unknown faces format in .obj file!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set vertex indices
|
||||
if (matches == 9 || matches == 2 || matches == 1) {
|
||||
outputData->materials[info->materialsI]->vertexFaces[info->faceI] =
|
||||
vertexIndex[0] - 1;
|
||||
outputData->materials[info->materialsI]->vertexFaces[info->faceI + 1] =
|
||||
vertexIndex[1] - 1;
|
||||
outputData->materials[info->materialsI]->vertexFaces[info->faceI + 2] =
|
||||
vertexIndex[2] - 1;
|
||||
}
|
||||
|
||||
// Set texture coord indices
|
||||
if (matches == 9 || matches == 2) {
|
||||
outputData->materials[info->materialsI]->textureCoordFaces[info->faceI] =
|
||||
coordIndex[0] - 1;
|
||||
outputData->materials[info->materialsI]
|
||||
->textureCoordFaces[info->faceI + 1] = coordIndex[1] - 1;
|
||||
outputData->materials[info->materialsI]
|
||||
->textureCoordFaces[info->faceI + 2] = coordIndex[2] - 1;
|
||||
}
|
||||
|
||||
// Set normal indices
|
||||
if (matches == 9) {
|
||||
outputData->materials[info->materialsI]->normalFaces[info->faceI] =
|
||||
normalIndex[0] - 1;
|
||||
outputData->materials[info->materialsI]->normalFaces[info->faceI + 1] =
|
||||
normalIndex[1] - 1;
|
||||
outputData->materials[info->materialsI]->normalFaces[info->faceI + 2] =
|
||||
normalIndex[2] - 1;
|
||||
} else if (matches == 1 && newerMatches == 6) {
|
||||
outputData->materials[info->materialsI]->normalFaces[info->faceI] =
|
||||
normalIndex[0] - 1;
|
||||
outputData->materials[info->materialsI]->normalFaces[info->faceI + 1] =
|
||||
normalIndex[1] - 1;
|
||||
outputData->materials[info->materialsI]->normalFaces[info->faceI + 2] =
|
||||
normalIndex[2] - 1;
|
||||
}
|
||||
|
||||
// Push index
|
||||
info->faceI += 3;
|
||||
|
||||
delete[] x;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -21,6 +21,14 @@ std::string Loader::getFilenameFromPath(const std::string& path) {
|
||||
return filename;
|
||||
}
|
||||
|
||||
std::string Loader::getPathFromFilename(const std::string& path) {
|
||||
std::string basepath = path.substr(0, path.find_last_of("/\\"));
|
||||
if (basepath.size() == path.size()) {
|
||||
basepath = path.substr(0, path.find_last_of(":\\"));
|
||||
}
|
||||
return basepath;
|
||||
}
|
||||
|
||||
std::string Loader::getFilenameWithoutExtension(const std::string& filename) {
|
||||
auto lastindex = filename.find_last_of(".");
|
||||
return filename.substr(0, lastindex);
|
||||
|
||||
@@ -18,9 +18,9 @@ namespace Tyra {
|
||||
DynamicMesh::DynamicMesh(const MeshBuilderData& data) : Mesh(data) {
|
||||
framesCount = data.framesCount;
|
||||
|
||||
TYRA_ERROR(framesCount > 1,
|
||||
"Frames count should be greater than 1 for DynamicMesh! Maybe you "
|
||||
"should use StaticMesh?");
|
||||
TYRA_WARN(
|
||||
"Frames count should be greater than 1 for DynamicMesh! Maybe you "
|
||||
"should use StaticMesh?");
|
||||
|
||||
frames = new MeshFrame*[framesCount];
|
||||
for (u32 i = 0; i < framesCount; i++) {
|
||||
@@ -33,9 +33,9 @@ DynamicMesh::DynamicMesh(const MeshBuilderData& data) : Mesh(data) {
|
||||
DynamicMesh::DynamicMesh(const MeshBuilder2Data& data) : Mesh(data) {
|
||||
framesCount = data.materials[0]->frames.size();
|
||||
|
||||
TYRA_ERROR(framesCount > 1,
|
||||
"Frames count should be greater than 1 for DynamicMesh! Maybe you "
|
||||
"should use StaticMesh?");
|
||||
TYRA_WARN(
|
||||
"Frames count should be greater than 1 for DynamicMesh! Maybe you "
|
||||
"should use StaticMesh?");
|
||||
|
||||
frames = new MeshFrame*[framesCount];
|
||||
for (u32 i = 0; i < framesCount; i++) {
|
||||
|
||||
@@ -37,7 +37,7 @@ MeshMaterial::MeshMaterial(const MeshBuilder2Data& data,
|
||||
singleColorFlag = true;
|
||||
}
|
||||
|
||||
color.set(128.0F, 128.0F, 128.0F, 128.0F);
|
||||
color.set(material->ambient);
|
||||
|
||||
_name = material->name;
|
||||
TYRA_ASSERT(_name.length() > 0, "MeshMaterial name cannot be empty");
|
||||
|
||||
@@ -56,10 +56,12 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshBuilder2Data& data,
|
||||
|
||||
TYRA_ASSERT(frame->count > 0, "Vertex count must be greater than 0");
|
||||
TYRA_ASSERT(frame->vertices != nullptr, "Vertex array can't be null");
|
||||
TYRA_ASSERT(frame->normals != nullptr, "Normal array can't be null");
|
||||
TYRA_ASSERT(frame->textureCoords != nullptr,
|
||||
TYRA_ASSERT(!data.normalsEnabled || frame->normals != nullptr,
|
||||
"Normal array can't be null");
|
||||
TYRA_ASSERT(!data.textureCoordsEnabled || frame->textureCoords != nullptr,
|
||||
"Texture coordinate array can't be null");
|
||||
TYRA_ASSERT(frame->colors != nullptr, "Color array can't be null");
|
||||
TYRA_ASSERT(!data.lightMapEnabled || frame->colors != nullptr,
|
||||
"Color array can't be null");
|
||||
|
||||
bbox = new BBox(frame->vertices, frame->count);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user