cis_config: /root/cis_interface/cis_interface/cis_interface/serialize/ObjSerialize.h Source File

cis_config

ObjSerialize.h
1 #ifndef CISOBJSERIALIZE_H_
2 #define CISOBJSERIALIZE_H_
3
4 #include <../tools.h>
5
6 #ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
7 extern "C" {
8 #endif
9
11 typedef struct obj_t {
12 int nvert;
13 int nface;
14 float **vertices;
15 int **faces;
16 int **vertex_colors;
17 char material[100];
18 int ntexc;
19 int nnorm;
20 float **texcoords;
21 float **normals;
22 int **face_texcoords;
23 int **face_normals;
24 } obj_t;
25
30 static inline
31 obj_t init_obj() {
32 obj_t x;
33 x.nvert = 0;
34 x.nface = 0;
35 x.ntexc = 0;
36 x.nnorm = 0;
37 x.vertices = NULL;
38 x.faces = NULL;
39 x.vertex_colors = NULL;
40 x.material[0] = '\0';
41 x.texcoords = NULL;
42 x.normals = NULL;
43 x.face_texcoords = NULL;
44 x.face_normals = NULL;
45 return x;
46 };
47
52 static inline
53 void free_obj(obj_t *p) {
54 int i;
55 if (p->vertices != NULL) {
56 for (i = 0; i < p->nvert; i++) {
57 if (p->vertices[i] != NULL) {
58 free(p->vertices[i]);
59 p->vertices[i] = NULL;
60 }
61 }
62 free(p->vertices);
63 p->vertices = NULL;
64 }
65 if (p->vertex_colors != NULL) {
66 for (i = 0; i < p->nvert; i++) {
67 if (p->vertex_colors[i] != NULL) {
68 free(p->vertex_colors[i]);
69 p->vertex_colors[i] = NULL;
70 }
71 }
72 free(p->vertex_colors);
73 p->vertex_colors = NULL;
74 }
75 if (p->faces != NULL) {
76 for (i = 0; i < p->nface; i++) {
77 if (p->faces[i] != NULL) {
78 free(p->faces[i]);
79 p->faces[i] = NULL;
80 }
81 }
82 free(p->faces);
83 p->faces = NULL;
84 }
85 if (p->texcoords != NULL) {
86 for (i = 0; i < p->ntexc; i++) {
87 if (p->texcoords[i] != NULL) {
88 free(p->texcoords[i]);
89 p->texcoords[i] = NULL;
90 }
91 }
92 free(p->texcoords);
93 p->texcoords = NULL;
94 }
95 if (p->normals != NULL) {
96 for (i = 0; i < p->nnorm; i++) {
97 if (p->normals[i] != NULL) {
98 free(p->normals[i]);
99 p->normals[i] = NULL;
100 }
101 }
102 free(p->normals);
103 p->normals = NULL;
104 }
105 if (p->face_texcoords != NULL) {
106 for (i = 0; i < p->nface; i++) {
107 if (p->face_texcoords[i] != NULL) {
108 free(p->face_texcoords[i]);
109 p->face_texcoords[i] = NULL;
110 }
111 }
112 free(p->face_texcoords);
113 p->face_texcoords = NULL;
114 }
115 if (p->face_normals != NULL) {
116 for (i = 0; i < p->nface; i++) {
117 if (p->face_normals[i] != NULL) {
118 free(p->face_normals[i]);
119 p->face_normals[i] = NULL;
120 }
121 }
122 free(p->face_normals);
123 p->face_normals = NULL;
124 }
125 p->material[0] = '\0';
126 p->nvert = 0;
127 p->nface = 0;
128 p->ntexc = 0;
129 p->nnorm = 0;
130 };
131
142 static inline
143 int alloc_obj(obj_t *p, int nvert, int nface,
144 int ntexc, int nnorm, int do_color) {
145 int i;
146 free_obj(p); // Ensure that existing data is freed
147 p->nvert = nvert;
148 p->nface = nface;
149 p->ntexc = ntexc;
150 p->nnorm = nnorm;
151 // Allocate vertices
152 float **new_vert = (float**)malloc(p->nvert*sizeof(float*));
153 if (new_vert == NULL) {
154 cislog_error("alloc_obj: Failed to allocate vertices.");
155 free_obj(p);
156 return -1;
157 }
158 p->vertices = new_vert;
159 for (i = 0; i < p->nvert; i++) {
160 float *ivert = (float*)malloc(3*sizeof(float));
161 if (ivert == NULL) {
162 cislog_error("alloc_obj: Failed to allocate vertex %d.", i);
163 free_obj(p);
164 return -1;
165 }
166 p->vertices[i] = ivert;
167 }
168 cislog_debug("alloc_obj: Allocated %d vertices.", nvert);
169 // Allocate vertex colors
170 if (do_color) {
171 int **new_vert = (int**)malloc(p->nvert*sizeof(int*));
172 if (new_vert == NULL) {
173 cislog_error("alloc_obj: Failed to allocate vertex_colors.");
174 free_obj(p);
175 return -1;
176 }
177 p->vertex_colors = new_vert;
178 for (i = 0; i < p->nvert; i++) {
179 int *ivert = (int*)malloc(3*sizeof(int));
180 if (ivert == NULL) {
181 cislog_error("alloc_obj: Failed to allocate vertex color %d.", i);
182 free_obj(p);
183 return -1;
184 }
185 p->vertex_colors[i] = ivert;
186 }
187 cislog_debug("alloc_obj: Allocated %d vertex colors.", nvert);
188 }
189 // Allocate texcoords
190 float **new_texc = (float**)malloc(p->ntexc*sizeof(float*));
191 if (new_texc == NULL) {
192 cislog_error("alloc_obj: Failed to allocate texcoords.");
193 free_obj(p);
194 return -1;
195 }
196 p->texcoords = new_texc;
197 for (i = 0; i < p->ntexc; i++) {
198 float *itexc = (float*)malloc(2*sizeof(float));
199 if (itexc == NULL) {
200 cislog_error("alloc_obj: Failed to allocate texcoord %d.", i);
201 free_obj(p);
202 return -1;
203 }
204 p->texcoords[i] = itexc;
205 }
206 cislog_debug("alloc_obj: Allocated %d texcoords.", ntexc);
207 // Allocate normals
208 float **new_norm = (float**)malloc(p->nnorm*sizeof(float*));
209 if (new_norm == NULL) {
210 cislog_error("alloc_obj: Failed to allocate normals.");
211 free_obj(p);
212 return -1;
213 }
214 p->normals = new_norm;
215 for (i = 0; i < p->nnorm; i++) {
216 float *inorm = (float*)malloc(3*sizeof(float));
217 if (inorm == NULL) {
218 cislog_error("alloc_obj: Failed to allocate normal %d.", i);
219 free_obj(p);
220 return -1;
221 }
222 p->normals[i] = inorm;
223 }
224 cislog_debug("alloc_obj: Allocated %d normals.", nnorm);
225 // Allocate faces
226 int **new_face = (int**)malloc(p->nface*sizeof(int*));
227 if (new_face == NULL) {
228 cislog_error("alloc_obj: Failed to allocate faces.");
229 free_obj(p);
230 return -1;
231 }
232 p->faces = new_face;
233 for (i = 0; i < p->nface; i++) {
234 int *iface = (int*)malloc(3*sizeof(int));
235 if (iface == NULL) {
236 cislog_error("alloc_obj: Failed to allocate face %d.", i);
237 free_obj(p);
238 return -1;
239 }
240 p->faces[i] = iface;
241 }
242 cislog_debug("alloc_obj: Allocated %d faces.", nface);
243 // Allocate face texcoords
244 int **new_ftexc = (int**)malloc(p->nface*sizeof(int*));
245 if (new_ftexc == NULL) {
246 cislog_error("alloc_obj: Failed to allocate face texcoords.");
247 free_obj(p);
248 return -1;
249 }
250 p->face_texcoords = new_ftexc;
251 for (i = 0; i < p->nface; i++) {
252 int *iftexc = (int*)malloc(3*sizeof(int));
253 if (iftexc == NULL) {
254 cislog_error("alloc_obj: Failed to allocate texcoords for face %d.", i);
255 free_obj(p);
256 return -1;
257 }
258 p->face_texcoords[i] = iftexc;
259 }
260 cislog_debug("alloc_obj: Allocated %d face texcoords.", nface);
261 // Allocate face normals
262 int **new_fnorm = (int**)malloc(p->nface*sizeof(int*));
263 if (new_fnorm == NULL) {
264 cislog_error("alloc_obj: Failed to allocate face normals.");
265 free_obj(p);
266 return -1;
267 }
268 p->face_normals = new_fnorm;
269 for (i = 0; i < p->nface; i++) {
270 int *ifnorm = (int*)malloc(3*sizeof(int));
271 if (ifnorm == NULL) {
272 cislog_error("alloc_obj: Failed to allocate normals for face %d.", i);
273 free_obj(p);
274 return -1;
275 }
276 p->face_normals[i] = ifnorm;
277 }
278 cislog_debug("alloc_obj: Allocated %d face normals.", nface);
279 // Return
280 cislog_debug("alloc_obj: Allocated for %d vertices and %d faces.",
281 p->nvert, p->nface);
282 return 0;
283 };
284
295 static inline
296 int serialize_obj(const seri_t s, char *buf, const size_t buf_size,
297 int *args_used, va_list ap) {
298 args_used[0] = 0;
299 int msg_len = 0;
300 int ilen;
301 char iline[500];
302 // Get argument
303 obj_t p = va_arg(ap, obj_t);
304 args_used[0] = 1;
305 buf[0] = '\0';
306 // Format header
307 char header_format[500] = "# Author cis_auto\n"
308 "# Generated by cis_interface\n";
309 if (strlen(p.material) != 0) {
310 sprintf(header_format + strlen(header_format), "usemtl %s\n", p.material);
311 }
312 ilen = strlen(header_format);
313 if (ilen >= (buf_size - msg_len)) {
314 cislog_error("serialize_obj: Buffer (size = %d) is not large "
315 "enough to contain the header (size = %d).", buf_size, ilen);
316 return msg_len + ilen;
317 }
318 strcat(buf, header_format);
319 msg_len = msg_len + ilen;
320 // Add vertex information
321 int i, j;
322 for (i = 0; i < p.nvert; i++) {
323 if (p.vertex_colors != NULL) {
324 ilen = snprintf(buf + msg_len, buf_size - msg_len, "v %f %f %f %d %d %d\n",
325 p.vertices[i][0], p.vertices[i][1], p.vertices[i][2],
326 p.vertex_colors[i][0], p.vertex_colors[i][1], p.vertex_colors[i][2]);
327 } else {
328 ilen = snprintf(buf + msg_len, buf_size - msg_len, "v %f %f %f\n",
329 p.vertices[i][0], p.vertices[i][1], p.vertices[i][2]);
330 }
331 if (ilen < 0) {
332 cislog_error("serialize_obj: Error formatting vertex %d.", i);
333 return -1;
334 } else if (ilen >= (buf_size - msg_len)) {
335 cislog_error("serialize_obj: Buffer (size = %d) is not large "
336 "enough to contain vertex %d (size = %d).",
337 buf_size, i, ilen + msg_len);
338 return msg_len + ilen;
339 }
340 msg_len = msg_len + ilen;
341 }
342 // Add texcoord information
343 for (i = 0; i < p.ntexc; i++) {
344 ilen = snprintf(buf + msg_len, buf_size - msg_len, "vt %f %f\n",
345 p.texcoords[i][0], p.texcoords[i][1]);
346 if (ilen < 0) {
347 cislog_error("serialize_obj: Error formatting texcoord %d.", i);
348 return -1;
349 } else if (ilen >= (buf_size - msg_len)) {
350 cislog_error("serialize_obj: Buffer (size = %d) is not large "
351 "enough to contain texcoord %d (size = %d).",
352 buf_size, i, ilen + msg_len);
353 return msg_len + ilen;
354 }
355 msg_len = msg_len + ilen;
356 }
357 // Add normal information
358 for (i = 0; i < p.nnorm; i++) {
359 ilen = snprintf(buf + msg_len, buf_size - msg_len, "vn %f %f %f\n",
360 p.normals[i][0], p.normals[i][1], p.normals[i][2]);
361 if (ilen < 0) {
362 cislog_error("serialize_obj: Error formatting normal %d.", i);
363 return -1;
364 } else if (ilen >= (buf_size - msg_len)) {
365 cislog_error("serialize_obj: Buffer (size = %d) is not large "
366 "enough to contain normal %d (size = %d).",
367 buf_size, i, ilen + msg_len);
368 return msg_len + ilen;
369 }
370 msg_len = msg_len + ilen;
371 }
372 // Add face information
373 for (i = 0; i < p.nface; i++) {
374 char ival[10];
375 sprintf(iline, "f");
376 for (j = 0; j < 3; j++) {
377 sprintf(ival, " %d", p.faces[i][j] + 1);
378 strcat(iline, ival);
379 strcat(iline, "/");
380 if (p.face_texcoords[i][j] >= 0) {
381 sprintf(ival, "%d", p.face_texcoords[i][j] + 1);
382 strcat(iline, ival);
383 }
384 strcat(iline, "/");
385 if (p.face_normals[i][j] >= 0) {
386 sprintf(ival, "%d", p.face_normals[i][j] + 1);
387 strcat(iline, ival);
388 }
389 }
390 ilen = snprintf(buf + msg_len, buf_size - msg_len, "%s\n", iline);
391 if (ilen < 0) {
392 cislog_error("serialize_obj: Error formatting line face %d.", i);
393 return -1;
394 } else if (ilen > (buf_size - msg_len)) {
395 cislog_error("serialize_obj: Buffer (size = %d) is not large "
396 "enough to contain line for face %d (size = %d).",
397 buf_size, i, ilen + msg_len);
398 return msg_len + ilen;
399 }
400 msg_len = msg_len + ilen;
401 }
402 return msg_len;
403 };
404
405
414 static inline
415 int deserialize_obj(const seri_t s, const char *buf, const size_t buf_siz,
416 va_list ap) {
417 int out = 1;
418 int do_colors = 0;
419 size_t *sind = NULL;
420 size_t *eind = NULL;
421 int nlines = 0;
422 int j;
423 int nvert = 0, nface = 0, ntexc = 0, nnorm = 0, nmatl = 0;
424 // Get argument
425 obj_t *p = va_arg(ap, obj_t*);
426 // Counts
427 int n_re_vert = 7;
428 int n_re_face = 3*3 + 1;
429 int n_re_texc = 3;
430 int n_re_norm = 4;
431 int n_re_matl = 2;
432 char re_vert[100] = "v ([^ \n]+) ([^ \n]+) ([^ \n]+) ([^ \n]+) ([^ \n]+) ([^ \n]+)";
433 char re_face[100] = "f ([^ \n/]*)/([^ \n/]*)/([^ \n/]*) "
434 "([^ \n/]*)/([^ \n/]*)/([^ \n/]*) "
435 "([^ \n/]*)/([^ \n/]*)/([^ \n/]*)";
436 char re_texc[100] = "vt ([^ \n]+) ([^ \n]+)";
437 char re_norm[100] = "vn ([^ \n]+) ([^ \n]+) ([^ \n]+)";
438 char re_matl[100] = "usemtl ([^\n]+)";
439 nvert = count_matches(re_vert, buf);
440 if (nvert != 0) {
441 do_colors = 1;
442 } else {
443 strcpy(re_vert, "v ([^ \n]+) ([^ \n]+) ([^ \n]+)");
444 n_re_vert = 4;
445 nvert = count_matches(re_vert, buf);
446 }
447 nface = count_matches(re_face, buf);
448 ntexc = count_matches(re_texc, buf);
449 nnorm = count_matches(re_norm, buf);
450 nmatl = count_matches(re_matl, buf);
451 cislog_debug("deserialize_obj: expecting %d verts, %d faces, %d texcoords, %d normals",
452 nvert, nface, ntexc, nnorm);
453 // Allocate
454 if (out > 0) {
455 int ret = alloc_obj(p, nvert, nface, ntexc, nnorm, do_colors);
456 if (ret < 0) {
457 cislog_error("deserialize_obj: Error allocating obj structure.");
458 out = -1;
459 }
460 }
461 // Locate lines
462 int cvert = 0, cface = 0, ctexc = 0, cnorm = 0, cmatl = 0;
463 size_t cur_pos = 0;
464 char iline[500];
465 size_t iline_siz = 0;
466 size_t sind_line, eind_line;
467 if (out > 0) {
468 /* char ival[10]; */
469 /* size_t ival_siz = 0; */
470 while (cur_pos < buf_siz) {
471 cislog_debug("deserialize_obj: Starting position %d/%d",
472 cur_pos, buf_siz);
473 int n_sub_matches = find_match("([^\n]*)\n", buf + cur_pos,
474 &sind_line, &eind_line);
475 if (n_sub_matches == 0) {
476 cislog_debug("deserialize_obj: End of file.");
477 sind_line = 0;
478 eind_line = buf_siz - cur_pos;
479 }
480 iline_siz = eind_line - sind_line;
481 memcpy(iline, buf + cur_pos, iline_siz);
482 iline[iline_siz] = '\0';
483 cislog_debug("deserialize_obj: iline = %s", iline);
484 // Match line
485 if (find_matches("#[^\n]*", iline, &sind, &eind) == 1) {
486 // Comment
487 cislog_debug("deserialize_obj: Comment");
488 } else if (find_matches(re_matl, iline, &sind, &eind) == n_re_matl) {
489 // Material
490 cislog_debug("deserialize_obj: Material");
491 int matl_size = eind[1] - sind[1];
492 memcpy(p->material, iline+sind[1], matl_size);
493 p->material[matl_size] = '\0';
494 cmatl++;
495 } else if (find_matches(re_vert, iline, &sind, &eind) == n_re_vert) {
496 // Vertex
497 cislog_debug("deserialize_obj: Vertex");
498 for (j = 0; j < 3; j++) {
499 p->vertices[cvert][j] = atof(iline + sind[j+1]);
500 }
501 if (do_colors) {
502 for (j = 0; j < 3; j++) {
503 p->vertex_colors[cvert][j] = atoi(iline + sind[j+4]);
504 }
505 }
506 cvert++;
507 } else if (find_matches(re_norm, iline, &sind, &eind) == n_re_norm) {
508 // Normals
509 cislog_debug("deserialize_obj: Normals");
510 for (j = 0; j < 3; j++) {
511 p->normals[cnorm][j] = atof(iline + sind[j+1]);
512 }
513 cnorm++;
514 } else if (find_matches(re_texc, iline, &sind, &eind) == n_re_texc) {
515 // Texcoords
516 cislog_debug("deserialize_obj: Texcoords");
517 for (j = 0; j < 2; j++) {
518 p->texcoords[ctexc][j] = atof(iline + sind[j+1]);
519 }
520 ctexc++;
521 } else if (find_matches(re_face, iline, &sind, &eind) == n_re_face) {
522 // Face
523 int n_sub_matches = find_matches(re_face, iline, &sind, &eind);
524 cislog_debug("deserialize_obj: Face");
525 for (j = 0; j < 3; j++) {
526 p->faces[cface][j] = atoi(iline + sind[3*j+1]) - 1;
527 if ((eind[3*j+2] - sind[3*j+2]) == 0)
528 p->face_texcoords[cface][j] = -1;
529 else
530 p->face_texcoords[cface][j] = atoi(iline + sind[3*j+2]) - 1;
531 if ((eind[3*j+3] - sind[3*j+3]) == 0)
532 p->face_normals[cface][j] = -1;
533 else
534 p->face_normals[cface][j] = atoi(iline + sind[3*j+3]) - 1;
535 }
536 cface++;
537 } else if (find_matches("\n+", iline, &sind, &eind) == 1) {
538 // Empty line
539 cislog_debug("deserialize_obj: Empty line");
540 } else {
541 cislog_error("deserialize_obj: Could not match line: %s", iline);
542 out = -1;
543 break;
544 }
545 nlines++;
546 cur_pos = cur_pos + eind_line;
547 cislog_debug("deserialize_obj: Advancing to position %d/%d",
548 cur_pos, buf_siz);
549 }
550 }
551 if (out > 0) {
552 if (cvert != nvert) {
553 cislog_error("deserialize_obj: Found %d verts, expected %d.", cvert, nvert);
554 out = -1;
555 }
556 if (cface != nface) {
557 cislog_error("deserialize_obj: Found %d faces, expected %d.", cface, nface);
558 out = -1;
559 }
560 if (ctexc != ntexc) {
561 cislog_error("deserialize_obj: Found %d texcs, expected %d.", ctexc, ntexc);
562 out = -1;
563 }
564 if (cnorm != nnorm) {
565 cislog_error("deserialize_obj: Found %d norms, expected %d.", cnorm, nnorm);
566 out = -1;
567 }
568 if (cmatl != nmatl) {
569 cislog_error("deserialize_obj: Found %d materials, expected %d.", cmatl, nmatl);
570 out = -1;
571 }
572 }
573 // Return
574 if (sind != NULL) free(sind);
575 if (eind != NULL) free(eind);
576 if (out < 0) {
577 free_obj(p);
578 }
579 return out;
580 };
581
582 #ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
583 }
584 #endif
585
586 #endif /*CISOBJSERIALIZE_H_*/
obj_t::face_normals
int ** face_normals
Indices of normals for each face.
Definition: ObjSerialize.h:23
obj_t::face_texcoords
int ** face_texcoords
Indices of texcoords for each face.
Definition: ObjSerialize.h:22
seri_t
Serializer structure.
Definition: SerializeBase.h:19
obj_t
Obj structure.
Definition: ObjSerialize.h:11
obj_t::nvert
int nvert
Number of vertices.
Definition: ObjSerialize.h:12
obj_t::material
char material[100]
Material that should be used for faces.
Definition: ObjSerialize.h:17
obj_t::ntexc
int ntexc
Number of texture coordinates.
Definition: ObjSerialize.h:18
obj_t::vertex_colors
int ** vertex_colors
RGB colors of each vertex.
Definition: ObjSerialize.h:16
obj_t::nface
int nface
Number faces.
Definition: ObjSerialize.h:13
obj_t::faces
int ** faces
Indices of the vertices composing each face.
Definition: ObjSerialize.h:15
obj_t::normals
float ** normals
X, Y, Z direction of normals.
Definition: ObjSerialize.h:21
obj_t::texcoords
float ** texcoords
Texture coordinates.
Definition: ObjSerialize.h:20
obj_t::vertices
float ** vertices
X, Y, Z positions of vertices.
Definition: ObjSerialize.h:14
obj_t::nnorm
int nnorm
Number of normals.
Definition: ObjSerialize.h:19