libbubulle/tools/importobj.c

351 lines
7.7 KiB
C
Raw Normal View History

2020-06-05 09:17:17 +11:00
/*
2023-04-09 20:13:56 +11:00
LIBBUBULLES IMPORT_OBJ
2020-06-05 09:17:17 +11:00
some functions for importing bubulles from dot-OBJ files.
2023-04-09 20:13:56 +11:00
https://git.tetalab.org/tTh/libbubulle/src/branch/master/tools/
http://fegemo.github.io/cefet-cg/attachments/obj-spec.pdf
2020-06-05 09:17:17 +11:00
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2023-04-03 09:52:09 +11:00
#include <unistd.h>
2023-04-23 03:41:34 +11:00
#include <libgen.h> /* for basename(3) */
2020-06-05 09:17:17 +11:00
2023-03-22 06:31:50 +11:00
#include "../bubulles.h"
#include "../edges.h"
2020-06-05 09:17:17 +11:00
2023-04-09 20:13:56 +11:00
#include "objtrucs.h"
2020-06-05 10:05:01 +11:00
extern int verbosity;
2020-06-05 09:17:17 +11:00
/* --------------------------------------------------------------------- */
2023-03-28 23:50:40 +11:00
#define LINE_SZ 666
static BBList *bublist;
static EdgeList *edges;
2023-04-09 20:13:56 +11:00
static int dropped;
static int linenumber;
static char obj_filename[LINE_SZ+1];
2023-03-28 23:50:40 +11:00
2021-05-19 02:14:00 +11:00
/* --------------------------------------------------------------------- */
typedef struct {
char *token;
int id;
} Tokens;
2023-04-03 09:52:09 +11:00
enum token_id { T_comment=1, T_vertice, T_group, T_face, T_vt, T_vn,
T_line, T_object, T_smoothing, T_usemtl, T_mtllib };
2021-05-19 02:14:00 +11:00
Tokens TokenList[] = {
{ "#", T_comment },
{ "v", T_vertice },
2023-03-28 23:50:40 +11:00
{ "g", T_group }, // to be verified !
2023-03-22 06:31:50 +11:00
{ "f", T_face },
2023-03-28 23:50:40 +11:00
{ "vt", T_vt }, // c'est quoi ce truc ?
2023-04-03 09:52:09 +11:00
{ "vn", T_vt }, // c'est quoi ce truc ?
{ "l", T_line },
{ "o", T_object },
{ "s", T_smoothing },
{ "usemtl", T_usemtl },
{ "mtllib", T_mtllib },
2023-04-09 20:13:56 +11:00
/* and more to come... */
2021-05-19 02:14:00 +11:00
{ NULL, 0 }
};
2023-04-21 07:33:46 +11:00
/* --------------------------------------------------------------------- */
2021-05-19 02:14:00 +11:00
static int type_of_the_line(char *text)
{
Tokens *token;
2023-03-28 23:50:40 +11:00
#if DEBUG_LEVEL > 1
fprintf(stderr, "%s is searching for '%s'\n", __func__, text);
2021-05-19 02:14:00 +11:00
#endif
for (token=TokenList; token->token; token++) {
// fprintf(stderr, " %5s -> %d\n", token->token, token->id);
if (!strcmp(token->token, text)) {
return token->id;
}
}
2020-06-05 10:05:01 +11:00
2021-05-19 02:14:00 +11:00
return -1;
}
/* --------------------------------------------------------------------- */
2023-04-09 20:13:56 +11:00
static int parse_vertice(char *cptr, float *px, float *py, float *pz)
2021-05-19 02:14:00 +11:00
{
float x, y, z;
int foo;
2023-04-09 20:13:56 +11:00
/* /!\ this function kill the input buffer */
2021-05-19 02:14:00 +11:00
foo = 0;
cptr = strtok(NULL, " ");
foo += sscanf(cptr, "%f", &x);
cptr = strtok(NULL, " ");
foo += sscanf(cptr, "%f", &y);
cptr = strtok(NULL, " ");
foo += sscanf(cptr, "%f", &z);
if (3 == foo) {
*px = x; *py = y; *pz = z;
}
return foo;
}
2023-04-09 20:13:56 +11:00
2021-05-19 02:14:00 +11:00
/* --------------------------------------------------------------------- */
2023-04-03 09:52:09 +11:00
/* new Mon 27 Mar 2023 12:08:18 AM CEST
*
* mmmm... complex thing to do...
2023-04-09 20:13:56 +11:00
* and what is this "phy" parameter ?
2023-04-03 09:52:09 +11:00
*/
2023-04-21 07:33:46 +11:00
static int parse_face(char *cptr)
2023-03-28 23:50:40 +11:00
{
2023-04-09 20:13:56 +11:00
int ix, foo, a, b;
2023-04-03 09:52:09 +11:00
int pts[3];
2023-03-28 23:50:40 +11:00
2023-03-30 14:39:36 +11:00
#if DEBUG_LEVEL
2023-04-24 23:12:15 +11:00
fprintf(stderr, ">>> %s ( '%s' )\n", __func__, cptr);
2023-03-30 14:39:36 +11:00
#endif
2023-03-28 23:50:40 +11:00
2023-04-03 09:52:09 +11:00
#if (0)
fprintf(stderr, "parse_face");
for (foo=0; foo<16; foo++) {
fprintf(stderr, " %02X", ((unsigned char *)cptr)[foo]);
}
fprintf(stderr, "\n");
#endif
2023-03-28 23:50:40 +11:00
for (ix=0; ix<3; ix++) {
cptr = strtok(NULL, " ");
2023-03-30 14:39:36 +11:00
if (NULL == cptr) {
fprintf(stderr, "incomplete face in %s\n", __func__);
return -4;
}
2023-04-03 09:52:09 +11:00
if (1 != sscanf(cptr, "%d", &pts[ix])) {
2023-03-28 23:50:40 +11:00
fprintf(stderr, "%s: err sscanf\n", __func__);
exit(1);
return -3;
}
2023-04-03 09:52:09 +11:00
}
2023-03-28 23:50:40 +11:00
2023-04-03 09:52:09 +11:00
/** check the freshly read datas **/
if ( pts[0]==pts[1] || pts[0]==pts[2] || pts[2]==pts[1] ) {
2023-04-09 20:13:56 +11:00
fprintf(stderr, "%s: degenerated face ( %d %d %d )\n", __func__,
2023-04-03 09:52:09 +11:00
pts[0], pts[1], pts[2]);
2023-04-09 20:13:56 +11:00
dropped++;
2023-04-03 09:52:09 +11:00
}
2023-03-28 23:50:40 +11:00
2023-04-09 20:13:56 +11:00
/*
* may be we can check the "degenerated cylinder" here ?
*/
for (ix=0; ix<3; ix++) {
a = ix % 3;
b = (ix+1) % 3;
foo = push_a_missing_edge(edges, pts[a], pts[b]);
if (foo) {
fprintf(stderr, "%s: disaster #%d line %d\n",
__func__, foo, linenumber);
return -2;
}
2023-04-03 09:52:09 +11:00
}
2023-04-09 20:13:56 +11:00
if (dropped) {
fprintf(stderr, "%s: %d dropped...\n", __func__, dropped);
2023-04-15 09:56:48 +11:00
// exit(1);
2023-03-28 23:50:40 +11:00
}
2023-03-30 14:39:36 +11:00
#if DEBUG_LEVEL
fprintf(stderr, "<<< %s\n", __func__);
#endif
2023-03-28 23:50:40 +11:00
return 0;
}
/* --------------------------------------------------------------------- */
2023-04-21 07:33:46 +11:00
/*
*
*/
int try_to_read_an_OBJ_file(char *infname, int outstyle)
2020-06-05 09:17:17 +11:00
{
FILE *fpin;
2023-04-03 09:52:09 +11:00
char line[LINE_SZ+1], *cptr, *token;
2020-06-05 10:05:01 +11:00
float x, y, z;
2023-04-21 07:33:46 +11:00
int foo, tokenid;
2020-06-05 19:57:43 +11:00
Bubulle bubulle;
2020-06-05 09:17:17 +11:00
2023-04-23 03:41:34 +11:00
char *outfname, *baseptr;
2023-03-28 23:50:40 +11:00
2020-06-05 09:17:17 +11:00
#if DEBUG_LEVEL
2023-04-24 23:12:15 +11:00
fprintf(stderr, ">>> %s ( '%s' %d )\n\n", __func__, infname, outstyle);
2020-06-05 09:17:17 +11:00
#endif
2023-04-21 07:33:46 +11:00
/* get memory for generated output filename(s) */
if (NULL==(outfname=malloc(strlen(infname)+33)) ) {
fprintf(stderr, "%s : not enough mem, sorry\n", __func__);
return -666;
}
2022-05-21 22:41:20 +11:00
if (NULL==(fpin=fopen(infname, "r"))) {
perror(infname);
2020-06-05 10:05:01 +11:00
exit(1);
}
2023-04-09 20:13:56 +11:00
linenumber = 0;
2020-06-05 10:05:01 +11:00
2023-04-21 07:33:46 +11:00
bublist = alloc_bubulles(infname, 600000, 0);
2020-06-05 19:57:43 +11:00
if (NULL==bublist) {
2023-03-28 23:50:40 +11:00
fprintf(stderr, "in %s, no mem for bubls, aborting...\n", __func__);
2020-06-05 19:57:43 +11:00
abort();
}
2023-04-09 20:13:56 +11:00
if (verbosity > 1) print_bublist_desc(bublist, 0);
2020-06-05 19:57:43 +11:00
2023-04-21 07:33:46 +11:00
edges = alloc_edgelist("krkrkr", 2200000, 0);
2023-03-28 23:50:40 +11:00
if (NULL==edges) {
fprintf(stderr, "no mem for edges in %s, aborting...\n", __func__);
abort();
}
2023-04-09 20:13:56 +11:00
if (verbosity > 1) print_edgelist_desc(edges, 0);
2023-03-28 23:50:40 +11:00
2023-04-21 07:33:46 +11:00
fprintf(stderr, "\n ***************************************\n");
2023-03-28 23:50:40 +11:00
2021-05-07 21:27:16 +11:00
while(NULL!=(cptr=fgets(line, LINE_SZ, fpin))) {
2020-06-05 10:05:01 +11:00
2021-05-19 02:14:00 +11:00
if ('\n' != line[strlen(line)-1]) {
2023-04-21 07:33:46 +11:00
fprintf(stderr, "%s: short read on %s line %d\n",
__func__, infname, linenumber);
2022-06-06 20:43:19 +11:00
// return -2;
break;
2021-05-19 02:14:00 +11:00
}
line[strlen(line)-1] = '\0'; /* kill the newline */
2023-03-28 23:50:40 +11:00
if (verbosity>1) fprintf(stderr, "line read ==|%s|==\n", line);
2020-06-05 10:05:01 +11:00
2023-04-09 20:13:56 +11:00
linenumber++;
2020-06-05 10:05:01 +11:00
cptr = strtok(line, " ");
2021-05-19 02:14:00 +11:00
if (NULL == cptr) {
2023-04-03 09:52:09 +11:00
/* this is an empty line */
// fprintf(stderr, "no token ?\n");
2021-05-19 02:14:00 +11:00
continue;
}
2023-04-16 02:30:50 +11:00
if ('#' == cptr[0]) { // found a comment
fprintf(stderr, " %s\n", cptr);
continue;
}
2023-04-03 09:52:09 +11:00
token = cptr;
2021-05-19 02:14:00 +11:00
tokenid = type_of_the_line(cptr);
2023-03-22 06:31:50 +11:00
if (verbosity > 1)
fprintf(stderr, "token '%s' --> %d\n", cptr, tokenid);
2020-06-05 10:05:01 +11:00
2020-06-05 19:57:43 +11:00
memset(&bubulle, 0, sizeof(Bubulle));
2020-06-05 10:05:01 +11:00
2021-05-19 02:14:00 +11:00
switch (tokenid) {
case T_comment:
/* do nothing */
break;
2023-03-22 06:31:50 +11:00
2021-05-19 02:14:00 +11:00
case T_vertice:
2022-05-21 22:41:20 +11:00
x = y = z = 0.0;
2021-05-19 02:14:00 +11:00
foo = parse_vertice(cptr, &x, &y, &z);
2023-03-28 23:50:40 +11:00
if (3!=foo) {
abort();
}
2021-05-19 02:14:00 +11:00
bubulle.p.x = x;
bubulle.p.y = y;
bubulle.p.z = z;
if (verbosity > 1) niceprint_bubulle(&bubulle, 0);
2023-03-28 23:50:40 +11:00
foo = push_bubulle(bublist, &bubulle);
if (foo) {
abort();
}
2021-05-19 02:14:00 +11:00
break;
2023-04-03 09:52:09 +11:00
case T_face:
/* experimental code here */
2023-04-21 07:33:46 +11:00
foo = parse_face(cptr);
2023-04-03 09:52:09 +11:00
if (foo) {
2023-04-09 20:13:56 +11:00
fprintf(stderr, "line %d '%s' parse face -> %d\n",
linenumber, cptr, foo);
2023-04-03 09:52:09 +11:00
exit(1);
}
break;
2023-03-22 06:31:50 +11:00
2023-04-03 09:52:09 +11:00
case T_object:
cptr = strtok(NULL, " ");
fprintf(stderr, "\tObject: %s\n", cptr);
break;
2023-03-22 06:31:50 +11:00
case T_group:
cptr = strtok(NULL, " ");
2023-04-03 09:52:09 +11:00
fprintf(stderr, "\tGroup: %s\n", cptr);
break;
case T_usemtl:
cptr = strtok(NULL, " ");
fprintf(stderr, "\tUsemtl: %s\n", cptr);
break;
case T_mtllib:
cptr = strtok(NULL, " ");
fprintf(stderr, "\tMtllib: %s\n", cptr);
2023-03-22 06:31:50 +11:00
break;
2023-04-03 09:52:09 +11:00
case T_line:
break;
case T_smoothing:
break;
case T_vt:
2023-03-22 06:31:50 +11:00
break;
2021-05-19 02:14:00 +11:00
default:
2023-04-03 09:52:09 +11:00
fprintf(stderr, "token %s -> %d ?\n", token, tokenid);
break;
2021-05-19 02:14:00 +11:00
}
2020-06-05 19:57:43 +11:00
}
2023-04-21 07:33:46 +11:00
2020-06-05 10:05:01 +11:00
fclose(fpin);
2023-04-21 07:33:46 +11:00
fprintf(stderr, " ***************************************\n");
2023-03-28 23:50:40 +11:00
2020-06-05 19:57:43 +11:00
if(verbosity) {
2023-04-09 20:13:56 +11:00
fprintf(stderr, "%s(): %d vertices loaded\n", __func__, bublist->fidx);
fprintf(stderr, "%s(): %d edges loaded\n", __func__, edges->fidx);
}
if (verbosity > 1) {
print_bublist_desc(bublist, 0);
print_edgelist_desc(edges, 0);
2020-06-05 19:57:43 +11:00
}
2023-04-21 07:33:46 +11:00
if (outstyle) { /* two ascii files */
strcpy(outfname, infname);
cptr = rindex(outfname, '.');
fprintf(stderr, "rindex -> [%s]\n", cptr);
strcpy(cptr, ".vertices");
bubulles_to_data(outfname, NULL, bublist, 0);
// edges_to_data(file_edges, edges, 0);
}
else { /* one 'evblob' file */
strcpy(outfname, infname);
2023-04-23 03:41:34 +11:00
/* see manpage basename(3) */
baseptr = basename(outfname);
// fprintf(stderr, "baseptr -> [%s]\n", baseptr);
cptr = rindex(baseptr, '.');
2023-04-21 07:33:46 +11:00
strcpy(cptr, ".evblob");
2023-04-23 03:41:34 +11:00
// fprintf(stderr, "baseptr-> [%s]\n", baseptr);
foo = x_write_vertedges(baseptr, bublist, edges);
2023-04-21 07:33:46 +11:00
if (foo) {
fprintf(stderr, "Err #%d when writing edges&vertices file\n", foo);
}
}
2023-04-09 20:13:56 +11:00
// Cleanup
free_bubulles(bublist, 0);
2023-03-28 23:50:40 +11:00
free_edgelist(edges, 0);
2020-06-12 00:30:03 +11:00
2020-06-05 19:57:43 +11:00
return 0;
2020-06-05 09:17:17 +11:00
}
/* --------------------------------------------------------------------- */