43static inline char *gmu_skip_ws(
char *s) {
44 while (*s && *s ==
' ')
55static long long _gm3u_parse_idx(
char **ptr) {
56 if (!ptr || !*ptr || isspace((
unsigned char)**ptr) || **ptr ==
'/')
59 long long val = strtoll(*ptr, &end, 10);
80 memset(ln, 0,
sizeof(*ln));
83 char *p = gmu_skip_ws(*end);
87 if (p[0] ==
'v' && isspace((
unsigned char)p[1])) {
89 p = gmu_skip_ws(p + 1);
90 ln->
points[0] = strtod(p, &p);
91 ln->
points[1] = strtod(p, &p);
92 ln->
points[2] = strtod(p, &p);
93 }
else if (p[0] ==
'v' && p[1] ==
'n') {
95 p = gmu_skip_ws(p + 2);
96 ln->
points[0] = strtod(p, &p);
97 ln->
points[1] = strtod(p, &p);
98 ln->
points[2] = strtod(p, &p);
99 }
else if (p[0] ==
'v' && p[1] ==
't') {
101 p = gmu_skip_ws(p + 2);
102 ln->
points[0] = strtod(p, &p);
103 ln->
points[1] = strtod(p, &p);
104 }
else if (p[0] ==
'f' && isspace((
unsigned char)p[1])) {
106 p = gmu_skip_ws(p + 1);
107 while (*p !=
'\0' && *p !=
'\n' && *p !=
'\r' && ln->
n_indices < 64) {
120 }
else if (strncmp(p,
"mtllib", 6) == 0) {
122 gm3u_str_copy_eol(ln->
name, p + 6,
sizeof(ln->
name));
123 }
else if (strncmp(p,
"usemtl", 6) == 0) {
125 gm3u_str_copy_eol(ln->
name, p + 6,
sizeof(ln->
name));
126 }
else if (p[0] ==
'o' || p[0] ==
'g') {
128 gm3u_str_copy_eol(ln->
name, p + 1,
sizeof(ln->
name));
129 }
else if (p[0] ==
'#') {
133 while (*p && *p !=
'\n')
151static void _gm3u_normalize_idx(
long long *idx,
size_t total) {
155 *idx += (
long long)total;
171 size_t buffer_size = 128;
172 size_t buffer_index = 0;
179 if (buffer_index >= buffer_size) {
180 size_t new_size = buffer_size * 2;
187 buffer_size = new_size;
189 buffer[buffer_index++] = ln;
192 *n_lines = buffer_index;
211 char *content = NULL;
218 memset(m, 0,
sizeof(*m));
227 for (
size_t i = 0; i < n_lines; i++) {
228 if (parsed[i].type ==
'L') {
230 snprintf(mtl_path,
sizeof(mtl_path),
"%s/%s", dir, parsed[i].name);
232 memset(&mf, 0,
sizeof(mf));
248 size_t total_v = 0, total_f = 0, total_n = 0, total_t = 0;
249 for (
size_t i = 0; i < n_lines; i++) {
250 if (parsed[i].type ==
'v')
252 else if (parsed[i].type ==
'n')
254 else if (parsed[i].type ==
't')
256 else if (parsed[i].type ==
'f' && parsed[i].n_indices >= 3) {
271 size_t cv = 0, cf = 0, cn = 0, ct = 0;
272 int active_mat_file = -1;
275 for (
size_t i = 0; i < n_lines; i++) {
277 if (ln->
type ==
'L') {
278 for (
size_t j = 0; j < m->
n_mtllibs; j++)
280 active_mat_file = (int)j;
283 }
else if (ln->
type ==
'U') {
284 if (active_mat_file >= 0)
286 }
else if (ln->
type ==
'v') {
288 }
else if (ln->
type ==
'n') {
290 }
else if (ln->
type ==
't') {
292 }
else if (ln->
type ==
'f') {
294 for (
size_t j = 0; j < ln->
n_indices; j++) {
295 _gm3u_normalize_idx(&ln->
indices[j][0], total_v);
296 _gm3u_normalize_idx(&ln->
indices[j][1], total_t);
297 _gm3u_normalize_idx(&ln->
indices[j][2], total_n);
300 for (
size_t j = 0; j < ln->
n_indices - 2; j++) {
317 gm3_pos_normalize(&n);
#define gm3_pos_cross(a, b)
Calculates the cross product of two gm3Pos vectors (a x b).
Definition position.h:146
void * malloc(size_t size)
Custom implementation of malloc using a static memory pool.
Definition malloc.h:144
void * realloc(void *ptr, size_t size)
Custom implementation of realloc for memory allocated by malloc (this custom version).
Definition malloc.h:236
void * calloc(size_t count, size_t size)
Custom implementation of calloc using a static memory pool.
Definition malloc.h:215
void free(void *ptr)
Custom implementation of free for memory allocated by malloc (this custom version).
Definition malloc.h:189
int gm3_mesh_center(gm3Mesh *m)
Centers the mesh geometry around the origin (0,0,0).
Definition mesh.h:86
Defines structures for 3D materials and material libraries, and functions for loading MTL files.
gm3Material * gm3_mtl_find_mat(gm3MtlLib *file, const char *name, int *index)
Finds a material by name within a loaded MTL file.
Definition mtl.h:219
int gm3_mtl_load(gm3MtlLib *mtl_lib, const char *path, const char *dir)
Loads materials and textures from an OBJ-style .mtl file.
Definition mtl.h:118
int gm3_obj_parse(char *content, gm3ObjLine **result, size_t *n_lines)
Definition obj.h:169
int32_t gm3_obj_load(gm3Mesh *m, const char *path, const char *dir)
Loads a Wavefront OBJ 3D model from a file into a gm3Mesh structure.
Definition obj.h:210
int gm3_obj_parse_next_line(char **end, gm3ObjLine *ln)
Definition obj.h:79
Represents a single face (triangle) in a 3D mesh.
Definition mesh.h:10
int material
Definition mesh.h:13
int material_file
Definition mesh.h:14
size_t vertices[3]
Definition mesh.h:11
long uvs[3]
Definition mesh.h:12
gm3Pos normal
Definition mesh.h:15
Represents a 3D mesh composed of vertices, faces, normals, and texture coordinates.
Definition mesh.h:30
size_t n_mtllibs
Definition mesh.h:44
size_t n_normals
Definition mesh.h:38
gm3Tex * texs
Definition mesh.h:40
size_t n_texs
Definition mesh.h:41
gm3MeshFace * faces
Definition mesh.h:34
size_t n_vertices
Definition mesh.h:32
gm3Pos * vertices
Definition mesh.h:31
gm3MtlLib * mtllibs
Definition mesh.h:43
gm3Pos * normals
Definition mesh.h:37
size_t n_faces
Definition mesh.h:35
Represents a material library, typically loaded from an .mtl file.
Definition mtl.h:53
char name[256]
Definition mtl.h:54
long long indices[64][3]
Definition obj.h:33
size_t n_indices
Definition obj.h:34
double points[3]
Definition obj.h:32
char name[128]
Definition obj.h:31
char type
Definition obj.h:30
Represents a 3D position or vector.
Definition position.h:11
Represents a 2D texture coordinate.
Definition mesh.h:21
Represents a 2D position or vector.
Definition position.h:8
int gmu_read_file(const char *path, char **content, size_t *size)
Reads the entire content of a file into a dynamically allocated buffer.
Definition utils.h:98