summaryrefslogtreecommitdiff
path: root/src/obj.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/obj.c')
-rw-r--r--src/obj.c194
1 files changed, 0 insertions, 194 deletions
diff --git a/src/obj.c b/src/obj.c
deleted file mode 100644
index 4887d52..0000000
--- a/src/obj.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Tuxánci 2 - A first person shooter
- * Copyright (C) 2007-2011 Tuxánci Development Team
- * Copyright (C) 2025-2026 Connor Thomson
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-#include <stdbool.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "obj.h"
-
-typedef struct ta_obj_position {
- float value[3];
-} ta_obj_position;
-
-typedef struct ta_obj_face {
- int position_indices[3];
-} ta_obj_face;
-
-static bool ta_obj_push_vertex(ta_obj_mesh *mesh, size_t *capacity, const ta_obj_vertex *vertex) {
- if (mesh->vertex_count == *capacity) {
- size_t next_capacity = *capacity == 0 ? 1024 : *capacity * 2;
- ta_obj_vertex *vertices = realloc(mesh->vertices, next_capacity * sizeof(*vertices));
- if (!vertices) {
- return false;
- }
- mesh->vertices = vertices;
- *capacity = next_capacity;
- }
- mesh->vertices[mesh->vertex_count++] = *vertex;
- return true;
-}
-
-bool ta_obj_parse(const unsigned char *data, size_t size, ta_obj_mesh *mesh) {
- ta_obj_position *positions = NULL;
- ta_obj_face *faces = NULL;
- float *normal_accum = NULL;
- size_t position_count = 0;
- size_t face_count = 0;
- size_t position_capacity = 0;
- size_t face_capacity = 0;
- size_t vertex_capacity = 0;
- bool success = false;
-
- memset(mesh, 0, sizeof(*mesh));
- char *text = malloc(size + 1);
- if (!text) {
- return false;
- }
- memcpy(text, data, size);
- text[size] = '\0';
-
- char *line = text;
- while (line && *line) {
- char *next_line = strchr(line, '\n');
- if (next_line) {
- *next_line = '\0';
- }
-
- if (line[0] == 'v' && line[1] == ' ') {
- ta_obj_position position;
- if (sscanf(line + 2, "%f %f %f", &position.value[0], &position.value[1], &position.value[2]) != 3) {
- goto done;
- }
- if (position_count == position_capacity) {
- size_t next_capacity = position_capacity == 0 ? 1024 : position_capacity * 2;
- ta_obj_position *grown = realloc(positions, next_capacity * sizeof(*grown));
- if (!grown) {
- goto done;
- }
- positions = grown;
- position_capacity = next_capacity;
- }
- positions[position_count++] = position;
- } else if (line[0] == 'f' && line[1] == ' ') {
- ta_obj_face face;
- int discarded_normal_indices[3];
- bool has_normals = sscanf(line + 2, "%d//%d %d//%d %d//%d",
- &face.position_indices[0], &discarded_normal_indices[0],
- &face.position_indices[1], &discarded_normal_indices[1],
- &face.position_indices[2], &discarded_normal_indices[2]) == 6;
- if (!has_normals && sscanf(line + 2, "%d %d %d",
- &face.position_indices[0], &face.position_indices[1], &face.position_indices[2]) != 3) {
- goto done;
- }
- for (int index = 0; index < 3; index++) {
- if (face.position_indices[index] <= 0 || (size_t)face.position_indices[index] > position_count) {
- goto done;
- }
- }
- if (face_count == face_capacity) {
- size_t next_capacity = face_capacity == 0 ? 1024 : face_capacity * 2;
- ta_obj_face *grown = realloc(faces, next_capacity * sizeof(*grown));
- if (!grown) {
- goto done;
- }
- faces = grown;
- face_capacity = next_capacity;
- }
- faces[face_count++] = face;
- }
-
- if (!next_line) {
- break;
- }
- line = next_line + 1;
- }
-
- if (position_count == 0 || face_count == 0) {
- goto done;
- }
-
- normal_accum = calloc(position_count * 3, sizeof(*normal_accum));
- if (!normal_accum) {
- goto done;
- }
-
- for (size_t index = 0; index < face_count; index++) {
- const float *first = positions[faces[index].position_indices[0] - 1].value;
- const float *second = positions[faces[index].position_indices[1] - 1].value;
- const float *third = positions[faces[index].position_indices[2] - 1].value;
- float edge_a[3] = {second[0] - first[0], second[1] - first[1], second[2] - first[2]};
- float edge_b[3] = {third[0] - first[0], third[1] - first[1], third[2] - first[2]};
- float face_normal[3] = {
- edge_a[1] * edge_b[2] - edge_a[2] * edge_b[1],
- edge_a[2] * edge_b[0] - edge_a[0] * edge_b[2],
- edge_a[0] * edge_b[1] - edge_a[1] * edge_b[0],
- };
- for (int corner = 0; corner < 3; corner++) {
- size_t position_index = (size_t)(faces[index].position_indices[corner] - 1);
- normal_accum[position_index * 3 + 0] += face_normal[0];
- normal_accum[position_index * 3 + 1] += face_normal[1];
- normal_accum[position_index * 3 + 2] += face_normal[2];
- }
- }
-
- for (size_t index = 0; index < position_count; index++) {
- float *normal = &normal_accum[index * 3];
- float length = sqrtf(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]);
- if (length > 0.0f) {
- normal[0] /= length;
- normal[1] /= length;
- normal[2] /= length;
- } else {
- normal[0] = 0.0f;
- normal[1] = 0.0f;
- normal[2] = 1.0f;
- }
- }
-
- for (size_t index = 0; index < face_count; index++) {
- for (int corner = 0; corner < 3; corner++) {
- size_t position_index = (size_t)(faces[index].position_indices[corner] - 1);
- ta_obj_vertex vertex;
- memcpy(vertex.position, positions[position_index].value, sizeof(vertex.position));
- memcpy(vertex.normal, &normal_accum[position_index * 3], sizeof(vertex.normal));
- if (!ta_obj_push_vertex(mesh, &vertex_capacity, &vertex)) {
- goto done;
- }
- }
- }
-
- success = mesh->vertex_count > 0;
-done:
- if (!success) {
- ta_obj_free(mesh);
- }
- free(positions);
- free(faces);
- free(normal_accum);
- free(text);
- return success;
-}
-
-void ta_obj_free(ta_obj_mesh *mesh) {
- free(mesh->vertices);
- mesh->vertices = NULL;
- mesh->vertex_count = 0;
-}