From 29d86022bd23748b940de4645396eb89f9b1134d Mon Sep 17 00:00:00 2001 From: Valtteri Koskivuori Date: Tue, 7 Nov 2023 21:59:50 +0200 Subject: [PATCH] Use dyn_array in wavefront mtllib parser Starting to look much better. Another neat thing about dyn_array is that if you are okay with a shallow copy, you can just value-assign them. No function for a deep copy yet, will see how much I need it first. --- .../loaders/formats/wavefront/mtlloader.c | 29 +++++------------ .../loaders/formats/wavefront/mtlloader.h | 3 +- .../loaders/formats/wavefront/wavefront.c | 31 +++++++------------ 3 files changed, 22 insertions(+), 41 deletions(-) diff --git a/src/utils/loaders/formats/wavefront/mtlloader.c b/src/utils/loaders/formats/wavefront/mtlloader.c index 2c67afc5..63efed14 100644 --- a/src/utils/loaders/formats/wavefront/mtlloader.c +++ b/src/utils/loaders/formats/wavefront/mtlloader.c @@ -19,36 +19,22 @@ #include "../../../assert.h" #include "../../textureloader.h" -static size_t countMaterials(textBuffer *buffer) { - size_t mtlCount = 0; - char *head = firstLine(buffer); - while (head) { - if (stringStartsWith("newmtl", head)) mtlCount++; - head = nextLine(buffer); - } - logr(debug, "File contains %zu materials\n", mtlCount); - firstLine(buffer); - return mtlCount; -} - static struct color parse_color(lineBuffer *line) { ASSERT(line->amountOf.tokens == 4); return (struct color){ atof(nextToken(line)), atof(nextToken(line)), atof(nextToken(line)), 1.0f }; } -struct material *parseMTLFile(const char *filePath, int *mtlCount, struct file_cache *cache) { +struct material_arr parse_mtllib(const char *filePath, struct file_cache *cache) { size_t bytes = 0; char *rawText = load_file(filePath, &bytes, cache); - if (!rawText) return NULL; + if (!rawText) return (struct material_arr){ 0 }; logr(debug, "Loading MTL at %s\n", filePath); textBuffer *file = newTextBuffer(rawText); free(rawText); char *assetPath = get_file_path(filePath); - size_t materialAmount = countMaterials(file); - struct material *materials = calloc(materialAmount, sizeof(*materials)); - size_t currentMaterialIdx = 0; + struct material_arr materials = { 0 }; struct material *current = NULL; char *head = firstLine(file); @@ -64,11 +50,12 @@ struct material *parseMTLFile(const char *filePath, int *mtlCount, struct file_c head = nextLine(file); continue; } else if (stringEquals(first, "newmtl")) { - current = &materials[currentMaterialIdx++]; + size_t idx = material_arr_add(&materials, (struct material){ 0 }); + current = &materials.items[idx]; if (!peekNextToken(&line)) { logr(warning, "newmtl without a name on line %zu\n", line.current.line); - free(materials); - return NULL; + material_arr_free(&materials); + return (struct material_arr){ 0 }; } current->name = stringCopy(peekNextToken(&line)); } else if (stringEquals(first, "Ka")) { @@ -117,6 +104,6 @@ struct material *parseMTLFile(const char *filePath, int *mtlCount, struct file_c destroyTextBuffer(file); free(assetPath); - if (mtlCount) *mtlCount = (int)materialAmount; + logr(debug, "Found %zu materials\n", materials.count); return materials; } diff --git a/src/utils/loaders/formats/wavefront/mtlloader.h b/src/utils/loaders/formats/wavefront/mtlloader.h index 782c3b04..e1338309 100644 --- a/src/utils/loaders/formats/wavefront/mtlloader.h +++ b/src/utils/loaders/formats/wavefront/mtlloader.h @@ -9,5 +9,6 @@ #pragma once struct file_cache; +struct material_arr; -struct material *parseMTLFile(const char *filePath, int *mtlCount, struct file_cache *cache); +struct material_arr parse_mtllib(const char *filePath, struct file_cache *cache); diff --git a/src/utils/loaders/formats/wavefront/wavefront.c b/src/utils/loaders/formats/wavefront/wavefront.c index fa52a798..300022e4 100644 --- a/src/utils/loaders/formats/wavefront/wavefront.c +++ b/src/utils/loaders/formats/wavefront/wavefront.c @@ -20,15 +20,6 @@ #include "wavefront.h" -static int findMaterialIndex(struct material *materialSet, int materialCount, char *mtlName) { - for (int i = 0; i < materialCount; ++i) { - if (stringEquals(materialSet[i].name, mtlName)) { - return i; - } - } - return 0; -} - static struct vector parseVertex(lineBuffer *line) { ASSERT(line->amountOf.tokens == 4); return (struct vector){ atof(nextToken(line)), atof(nextToken(line)), atof(nextToken(line)) }; @@ -122,9 +113,8 @@ struct mesh *parseWavefront(const char *filePath, size_t *finalMeshCount, struct //size_t currentMesh = 0; size_t valid_meshes = 0; - struct material *materialSet = NULL; - int materialCount = 0; - int currentMaterialIndex = 0; + struct material_arr mtllib = { 0 }; + int current_material_idx = 0; //FIXME: Handle more than one mesh struct mesh *meshes = calloc(1, sizeof(*meshes)); @@ -168,16 +158,21 @@ struct mesh *parseWavefront(const char *filePath, size_t *finalMeshCount, struct //TODO: Check if we actually need the file totals here fixIndices(&p, currentMeshPtr->vertices.count, currentMeshPtr->texture_coords.count, currentMeshPtr->normals.count); surface_area += get_poly_area(&p, currentMeshPtr->vertices.items); - p.materialIndex = currentMaterialIndex; + p.materialIndex = current_material_idx; p.hasNormals = p.normalIndex[0] != -1; poly_arr_add(¤tMeshPtr->polygons, p); } } else if (stringEquals(first, "usemtl")) { - currentMaterialIndex = findMaterialIndex(materialSet, materialCount, peekNextToken(&line)); + char *name = peekNextToken(&line); + for (size_t i = 0; i < mtllib.count; ++i) { + if (stringEquals(mtllib.items[i].name, name)) { + current_material_idx = i; + } + } } else if (stringEquals(first, "mtllib")) { char *mtlFilePath = stringConcat(assetPath, peekNextToken(&line)); windowsFixPath(mtlFilePath); - materialSet = parseMTLFile(mtlFilePath, &materialCount, cache); + mtllib = parse_mtllib(mtlFilePath, cache); free(mtlFilePath); } else { char *fileName = get_file_name(filePath); @@ -193,11 +188,9 @@ struct mesh *parseWavefront(const char *filePath, size_t *finalMeshCount, struct free(rawText); free(assetPath); - if (materialSet) { + if (mtllib.count) { for (size_t i = 0; i < meshCount; ++i) { - for (size_t m = 0; m < materialCount; ++m) { - material_arr_add(&meshes[i].materials, materialSet[m]); - } + meshes[i].materials = mtllib; } } else { for (size_t i = 0; i < meshCount; ++i) {