This repository has been archived by the owner on Jun 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
t_obj.c
132 lines (109 loc) · 3.9 KB
/
t_obj.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// This program is fragile.
// A comment in the obj file that's too long will overflow the buffer.
// A double space between two values is counted as a zero. Then the last value
// will overflow the buffer.
#include "t_obj.h"
// It takes in a ["f", "1/2/3", "1/2/3", "1/2/3"]
// and returns a [[1, 2, 3], [1, 2, 3], [1, 2, 3]].
// Only used internally.
static void t_splitFace(char** token_array, int out[3][3]) {
char copy[17];
char *token, *saveptr;
int out_index = 0;
// Tokenize input.
int i;
for (i = 0; i < 3; i++) {
// i + 1 because 0th term is "f".
strcpy(copy, token_array[i + 1]);
// "1/2/3" --> "1"
token = strtok_r(copy, "/", &saveptr);
while (token != NULL) {
// Convert to integer, save to out[i]
out[i][out_index++] = atoi(token);
// "2/3" --> "2" "3" --> "3"
token = strtok_r(NULL, "/", &saveptr);
}
out_index = 0;
}
}
// Takes in the filename of the obj file, and puts an
// array of faces in the second argument t_Face* faces.
// Return value is number of faces, zero in case of failure.
int t_decodeOBJ(char* filename, t_Face faces[]) {
FILE * file = fopen(filename, "r");
char line_buffer[80];
char *token;
char* token_array[6];
int token_index;
// Save the values.
t_Point vertices[MAX_VERTICES];
t_Point normals[MAX_NORMALS];
int face_references[4][MAX_FACES];
// Which one am I on?
int vertices_index = 0;
int normals_index = 0;
int faces_index = 0;
// Line by line sequence
while(fgets(line_buffer, 80, file) != NULL) {
// Copy string, otherwise same pointer. rest will be destroyed.
// It's ok to destroy line_buffer, because it is only used once.
char* rest = line_buffer;
token_index = 0;
// Token by token sequence
while ((token = strtok_r(rest, " ", &rest))) {
token_array[token_index++] = token;
}
// Process lines
// "v" Vertex
if(!(strcmp(token_array[0], "v"))) {
// Haha... don't want to mess up the memory...
if (vertices_index == MAX_VERTICES) return 0;
vertices[vertices_index++] = (t_Point) {{
atof(token_array[1]),
atof(token_array[2]),
atof(token_array[3]),
1.0
}};
}
// "vn" Normal
if(!(strcmp(token_array[0], "vn"))) {
if (normals_index == MAX_NORMALS) return 0;
normals[normals_index++] = (t_Point) {{
atof(token_array[1]),
atof(token_array[2]),
atof(token_array[3]),
1.0
}};
}
// "f" Face (3 sides)
// 0 - normal
// 1, 2, 3 - vertices
// Returns integers instead of t_Point, it will
// be processed later.
// Remember: Vertex/(ignore for now)/Vertex normal
if (!(strcmp(token_array[0], "f"))) {
int references[3][3];
t_splitFace(token_array, references);
// normal (same for all vertices, so use first one)
face_references[0][faces_index] = references[0][2]; // 2nd term, 0th token
face_references[1][faces_index] = references[0][0];
face_references[2][faces_index] = references[1][0];
face_references[3][faces_index] = references[2][0];
faces_index++;
}
// End processing lines
}
// Leave line processing sequence
// Associate points with faces.
int j;
for (j = 0; j < faces_index; j++) {
faces[j] = (t_Face) { // faces is the output
vertices[face_references[1][j]],
vertices[face_references[2][j]],
vertices[face_references[3][j]],
normals[face_references[0][j]]
};
}
fclose(file);
return faces_index + 1;
}