static int parse_vertex( tokenize_t *tok, BotRwxVertex *v ) { tokenize_next( tok ); parse_double( tok, &v->pos[0] ); parse_double( tok, &v->pos[1] ); parse_double( tok, &v->pos[2] ); if (!strcmp (tok->token, "UV")) { // TODO tokenize_next (tok); double uv; parse_double (tok, &uv); parse_double (tok, &uv); } if( tok->token[0] != '#' ) { parse_error( tok, "expected vertex id prefixed with '#'!" ); } while (tok->token[1] == 0) { tokenize_next (tok); if (tok->token[0] != '!') break; tokenize_next (tok); while (tok->token[0] != '#') tokenize_next (tok); } char *endptr; v->id = strtol( tok->token + 1, &endptr, 10 ); if( tok->token+1 == endptr ) { parse_error( tok, "expected numerical vertex id!" ); } return 0; }
static void parse_require(tokenize_t *t, char *tok) { int res = tokenize_next(t); if (res == EOF || strcmp(t->token, tok)) parse_error(t, "expected token %s", tok); }
static int parse_triangle( tokenize_t *tok, BotRwxTriangle *t ) { tokenize_next( tok ); parse_int( tok, &t->vertices[0], 10 ); parse_int( tok, &t->vertices[1], 10 ); parse_int( tok, &t->vertices[2], 10 ); return 0; }
static int parse_double(tokenize_t *t, double *f) { char *endptr = NULL; *f = strtod(t->token, &endptr); if( t->token == endptr ) { parse_error(t, "expected float!"); } tokenize_next(t); return 0; }
static int parse_int(tokenize_t *t, int *d, int radix) { char *endptr = NULL; *d = strtol(t->token, &endptr, radix); if( t->token == endptr ) { parse_error(t, "expected integer!"); } tokenize_next(t); return 0; }
int tokenize_peek(tokenize_t *t) { int res = 0; if (t->hasnext) return res; res = tokenize_next(t); t->hasnext = 1; return res; }
BotRwxModel* bot_rwx_model_create( const char *fname ) { BotRwxModel *model = calloc(1, sizeof(BotRwxModel)); tokenize_t *tok = tokenize_create( fname ); int status; if (NULL==tok) { perror(fname); free(model); return NULL; } parse_require( tok, "ModelBegin" ); parse_require( tok, "ClumpBegin" ); while (tokenize_next(tok)!=EOF) { if( 0 == strcmp( tok->token, "ClumpBegin" ) ) { BotRwxClump *clump = (BotRwxClump*)calloc(1, sizeof(BotRwxClump)); model->clumps = g_list_append( model->clumps, clump ); status = parse_clump( clump, tok ); if( 0 != status ) { tokenize_destroy(tok); bot_rwx_model_destroy(model); return NULL; } } else if( 0 == strcmp( tok->token, "ClumpEnd" ) ) { parse_require( tok, "ModelEnd" ); break; } } tokenize_destroy( tok ); return model; }
static int parse_clump( BotRwxClump *clump, tokenize_t *tok ) { // get clump name parse_require( tok, "#Layer" ); parse_require( tok, ":" ); tokenize_next( tok ); clump->name = strdup( tok->token ); // defaults clump->color[0] = clump->color[1] = clump->color[2] = 0; clump->opacity = 1; clump->ambient = 1; clump->diffuse = 1; clump->specular = 0; int nvbuf = 20000; BotRwxVertex *vbuf = (BotRwxVertex*)calloc(1, nvbuf*sizeof(BotRwxVertex)); // clump color tokenize_next( tok ); while( 0 != strcmp( tok->token, "#texbegin" ) ) { if( ! strcmp( tok->token, "Color" ) ) { tokenize_next( tok ); parse_double( tok, &clump->color[0] ); parse_double( tok, &clump->color[1] ); parse_double( tok, &clump->color[2] ); } else if( ! strcmp( tok->token, "Surface" ) ) { tokenize_next( tok ); // parse_double( tok, &clump->surface[0] ); // parse_double( tok, &clump->surface[1] ); // parse_double( tok, &clump->surface[2] ); parse_double( tok, &clump->ambient ); parse_double( tok, &clump->diffuse ); parse_double( tok, &clump->specular ); } else if( ! strcmp( tok->token, "Diffuse" ) ) { tokenize_next( tok ); parse_double( tok, &clump->diffuse ); } else if( ! strcmp( tok->token, "Specular" ) ) { tokenize_next( tok ); parse_double( tok, &clump->specular ); } else if( ! strcmp( tok->token, "Opacity" ) ) { tokenize_next( tok ); parse_double( tok, &clump->opacity ); } else { tokenize_next( tok ); } } // expect the clump name parse_require( tok, clump->name ); // start with a single vertex that should never be used. clump->nvertices = 1; // parse the list of vertices while( tokenize_next( tok ) != EOF ) { if( ! strcmp( tok->token, "Vertex" ) ) { parse_vertex( tok, vbuf + clump->nvertices ); if( vbuf[clump->nvertices].id != clump->nvertices ) { parse_error( tok, "expected vertex %d (got %d)!\n", clump->nvertices, vbuf[clump->nvertices].id ); } clump->nvertices++; if( clump->nvertices >= nvbuf ) { nvbuf += 10000; vbuf = (BotRwxVertex*)realloc(vbuf, nvbuf*sizeof(BotRwxVertex)); } } else if( ! strcmp( tok->token, "#texend" ) ) { // expect the clump name parse_require( tok, clump->name ); break; } else { parse_error( tok, "expected Vertex or #texend token!" ); } } clump->vertices = (BotRwxVertex*)malloc(clump->nvertices*sizeof(BotRwxVertex)); memcpy( clump->vertices, vbuf, clump->nvertices*sizeof(BotRwxVertex) ); free( vbuf ); int ntbuf = 20000; BotRwxTriangle *tbuf = (BotRwxTriangle*)calloc(1, ntbuf*sizeof(BotRwxTriangle)); // parse the list of triangles tokenize_next( tok ); while( 1 ) { // while( tokenize_next( tok ) != EOF ) { if( ! strcmp( tok->token, "Triangle" ) ) { parse_triangle( tok, tbuf + clump->ntriangles ); clump->ntriangles++; if( clump->ntriangles >= ntbuf ) { ntbuf += 10000; tbuf = (BotRwxTriangle*)realloc(tbuf, ntbuf*sizeof(BotRwxTriangle)); } } else if( ! strcmp( tok->token, "ClumpEnd" ) ) { break; } } clump->triangles = (BotRwxTriangle*)malloc(clump->ntriangles*sizeof(BotRwxTriangle)); memcpy( clump->triangles, tbuf, clump->ntriangles*sizeof(BotRwxTriangle) ); free( tbuf ); return 0; }