HashItem *construct_preset(char const *setkey, char *rest) { char *key; HashItem *mapItem; if (!(key = string_firstword(&rest))) /* get the key */ { /* e.g., title */ message_error("`preset ...: missing key"); return 0; } if (strcmp(key, "nohtmlfive") == 0) global.d_html5 = 0; else { if (!*string_strip(&rest)) /* get the value */ warning("Empty value of symbol `%s'", key); /* e.g., This is... */ if (strcmp(key, "styleopt") == 0) /* store styleopts */ lines_add(&global.d_styleopt, rest); else { /* look up the key */ mapItem = hashmap_find(&global.d_symbol, key, ANY); if (mapItem != PFAILED) /* reassign */ hashitem_set(mapItem, rest, free); /* existing value */ else /* or insert new */ hashmap_insert(&global.d_symbol, /* element */ hashitem_construct(VOIDPTR, key, new_str(rest), free)); } } free(key); return hashitem_construct(VOIDPTR, "", 0, root_nop); }
HashItem *construct_tocentry(char const *key, char *rest) { size_t level; char *section = string_firstword(&rest); if (!section) { message_error("incomplete tocentry"); return 0; } string_strip(&rest); /* find the section's index */ level = lines_find(section, section_levels, sizeofSectionLevels); if (level == UFAILED) /* no section given is err. */ { message_error("unknown toc-section `%s'", section); free(section); return 0; } free(section); /* write <dd><dl> for deeper levels */ for (; level > global.d_toclevel; ++global.d_toclevel) lines_add(&global.d_toc, "<dd><dl>"); /* write </dl></dd> when returning to shallower levels */ for (; level < global.d_toclevel; --global.d_toclevel) lines_add(&global.d_toc, "</dl></dd>"); /* add a new entry */ lines_format(&global.d_toc, "<dt>%s<a href=\"%s#l%u\">%s</a>%s</dt>", toc_section[global.d_doctype][level][0], string_str(&global.d_outName), (unsigned)++s_lastLabelNr, rest, toc_section[global.d_doctype][level][1]); return hashitem_construct(VOIDPTR, "", (void *)s_lastLabelNr, root_nop); }
HashItem *construct_txt_tocentry(char const *key, char *rest) { lines_add(&global.d_toc, rest); /* add a new entry */ return hashitem_construct(VOIDPTR, "", 0, root_nop); }
void wavefront_export(const mesh_t *mesh, const char *path) { // XXX: Merge faces that can be merged into bigger ones. // Allow to chose between quads or triangles. // Also export mlt file for the colors. block_t *block; voxel_vertex_t* verts; vec3_t v; int nb_quads, i, j; mat4_t mat; FILE *out; const int N = BLOCK_SIZE; UT_array *lines; line_t line, face, *line_ptr; utarray_new(lines, &line_icd); verts = calloc(N * N * N * 6 * 4, sizeof(*verts)); face = (line_t){"f "}; MESH_ITER_BLOCKS(mesh, block) { mat = mat4_identity; mat4_itranslate(&mat, block->pos.x, block->pos.y, block->pos.z); mat4_itranslate(&mat, -N / 2 + 0.5, -N / 2 + 0.5, -N / 2 + 0.5); nb_quads = block_generate_vertices(block->data, 0, verts); for (i = 0; i < nb_quads; i++) { // Put the vertices. for (j = 0; j < 4; j++) { v = vec3(verts[i * 4 + j].pos.x, verts[i * 4 + j].pos.y, verts[i * 4 + j].pos.z); v = mat4_mul_vec3(mat, v); line = (line_t){"v ", .v = v}; face.vs[j] = lines_add(lines, &line); } // Put the normals for (j = 0; j < 4; j++) { v = vec3(verts[i * 4 + j].normal.x, verts[i * 4 + j].normal.y, verts[i * 4 + j].normal.z); line = (line_t){"vn", .vn = v}; face.vns[j] = lines_add(lines, &line); } lines_add(lines, &face); } } out = fopen(path, "w"); fprintf(out, "# Goxel " GOXEL_VERSION_STR "\n"); line_ptr = NULL; while( (line_ptr = (line_t*)utarray_next(lines, line_ptr))) { if (strncmp(line_ptr->type, "v ", 2) == 0) fprintf(out, "v %g %g %g\n", VEC3_SPLIT(line_ptr->v)); } while( (line_ptr = (line_t*)utarray_next(lines, line_ptr))) { if (strncmp(line_ptr->type, "vn", 2) == 0) fprintf(out, "vn %g %g %g\n", VEC3_SPLIT(line_ptr->vn)); } while( (line_ptr = (line_t*)utarray_next(lines, line_ptr))) { if (strncmp(line_ptr->type, "f ", 2) == 0) fprintf(out, "f %d//%d %d//%d %d//%d %d//%d\n", line_ptr->vs[0], line_ptr->vns[0], line_ptr->vs[1], line_ptr->vns[1], line_ptr->vs[2], line_ptr->vns[2], line_ptr->vs[3], line_ptr->vns[3]); } fclose(out); utarray_free(lines); } void ply_export(const mesh_t *mesh, const char *path) { block_t *block; voxel_vertex_t* verts; vec3_t v; uvec3b_t c; int nb_quads, i, j; mat4_t mat; FILE *out; const int N = BLOCK_SIZE; UT_array *lines; line_t line, face, *line_ptr; utarray_new(lines, &line_icd); verts = calloc(N * N * N * 6 * 4, sizeof(*verts)); face = (line_t){"f "}; MESH_ITER_BLOCKS(mesh, block) { mat = mat4_identity; mat4_itranslate(&mat, block->pos.x, block->pos.y, block->pos.z); mat4_itranslate(&mat, -N / 2 + 0.5, -N / 2 + 0.5, -N / 2 + 0.5); nb_quads = block_generate_vertices(block->data, 0, verts); for (i = 0; i < nb_quads; i++) { // Put the vertices. for (j = 0; j < 4; j++) { v = vec3(verts[i * 4 + j].pos.x, verts[i * 4 + j].pos.y, verts[i * 4 + j].pos.z); v = mat4_mul_vec3(mat, v); c = verts[i * 4 + j].color.rgb; line = (line_t){"v ", .v = v, .c = c}; face.vs[j] = lines_add(lines, &line); } // Put the normals for (j = 0; j < 4; j++) { v = vec3(verts[i * 4 + j].normal.x, verts[i * 4 + j].normal.y, verts[i * 4 + j].normal.z); line = (line_t){"vn", .vn = v}; face.vns[j] = lines_add(lines, &line); } lines_add(lines, &face); } } out = fopen(path, "w"); fprintf(out, "ply\n"); fprintf(out, "format ascii 1.0\n"); fprintf(out, "comment Generated from Goxel " GOXEL_VERSION_STR "\n"); fprintf(out, "element vertex %d\n", lines_count(lines, "v ")); fprintf(out, "property float x\n"); fprintf(out, "property float y\n"); fprintf(out, "property float z\n"); fprintf(out, "property uchar red\n"); fprintf(out, "property uchar green\n"); fprintf(out, "property uchar blue\n"); fprintf(out, "element face %d\n", lines_count(lines, "f ")); fprintf(out, "property list uchar int vertex_index\n"); fprintf(out, "end_header\n"); line_ptr = NULL; while( (line_ptr = (line_t*)utarray_next(lines, line_ptr))) { if (strncmp(line_ptr->type, "v ", 2) == 0) fprintf(out, "%g %g %g %d %d %d\n", VEC3_SPLIT(line_ptr->v), VEC3_SPLIT(line_ptr->c)); } while( (line_ptr = (line_t*)utarray_next(lines, line_ptr))) { if (strncmp(line_ptr->type, "f ", 2) == 0) fprintf(out, "4 %d %d %d %d\n", line_ptr->vs[0] - 1, line_ptr->vs[1] - 1, line_ptr->vs[2] - 1, line_ptr->vs[3] - 1); } fclose(out); utarray_free(lines); } static void export_as_obj(goxel_t *goxel, const char *path) { wavefront_export(goxel->layers_mesh, path); }
int main (int argc, char **argv) { char const *doctype; char const **ptr; args_data = postqueue_data = message_data; message_construct(argv[0]); args_construct(argc, argv, "?x:l:", 0); hashmap_construct(&symtab); lines_construct(&global.d_toc); lines_construct(&global.d_section); lines_add(&global.d_section, ""); hashmap_constructText(&global.d_symbol, default_symbols); if (!args_ok() || args_nArgs() < 2) /* check arguments */ usage(); if (args_nArgs() == 2) /* file name specified */ { global.d_out = stdout; global.d_noext = 0; } else { global.d_noext = file_rmExtension(args_arg(2)); global.d_ext = file_extension(args_arg(2)); if (!global.d_ext) { global.d_ext = new_str(args_optarg('x')); if (!global.d_ext) global.d_ext = "ypp"; /* Yodl Post Processor */ } } string_construct(&global.d_outName, 0); postqueue_construct(task); if (global.d_noext) { string_format(&global.d_outName, "%s.%s", global.d_noext, global.d_ext); global.d_out = file_open(string_str(&global.d_outName), "w"); } doctypes[sizeofDocType - 1] = doctype = hashmap_textOf(&global.d_symbol, "documenttype"); for ( ptr = doctypes, global.d_doctype = 1; strcmp(doctype, *ptr); ptr++, global.d_doctype <<= 1 ) ; postqueue_process(); fclose(global.d_out); return 0; }