static void draw(state_t * state, vx_world_t * world) { if (1) { vx_buffer_add_back(vx_world_get_buffer(world, "grid"), vxo_grid()); vx_buffer_set_draw_order(vx_world_get_buffer(world, "grid"), -100); vx_buffer_swap(vx_world_get_buffer(world, "grid")); } // Draw from the vx shape library if (1) { vx_buffer_add_back(vx_world_get_buffer(world, "fixed-cube"), vxo_chain(vxo_mat_translate3(3.0,0,0), vxo_mat_scale3(2,2,2), /* vxo_box(vxo_mesh_style(vx_orange)))); */ vxo_box(vxo_mesh_style_fancy(vx_orange, vx_orange, vx_white, 1.0, 400.0, 2)))); vx_buffer_add_back(vx_world_get_buffer(world, "fixed-cube"), vxo_chain(vxo_mat_translate3(0,3.0,0), vxo_mat_scale3(1,1,1), vxo_depth_test(0, vxo_box(vxo_mesh_style_solid(vx_green))))); vx_buffer_swap(vx_world_get_buffer(world, "fixed-cube")); } if (1) { float Tr = .2; float amb[] = {0.0,0.0,0.0}; float diff[] = {0.0,0.0,0.0}; float spec[] = {1.0,1.0,1.0}; float specularity = 1.0; int type = 2; vx_buffer_add_back(vx_world_get_buffer(world, "window"), vxo_chain(vxo_mat_translate3(0,0,2.5), vxo_mat_rotate_y(-M_PI/7), vxo_mat_rotate_z(M_PI/5), vxo_mat_rotate_x(M_PI/2), vxo_mat_scale3(10,10,1), vxo_rect(vxo_mesh_style_fancy(amb, diff, spec, Tr, specularity, type), vxo_lines_style(vx_black,2)))); vx_buffer_swap(vx_world_get_buffer(world, "window")); vx_buffer_set_draw_order(vx_world_get_buffer(world, "window"), 100); } if (1) { // Draw a custom ellipse: int npoints = 35; float points[npoints*3]; for (int i = 0; i < npoints; i++) { float angle = 2*M_PI*i/npoints; float x = 5.0f*cosf(angle); float y = 8.0f*sinf(angle); float z = 0.0f; points[3*i + 0] = x; points[3*i + 1] = y; points[3*i + 2] = z; } vx_buffer_add_back(vx_world_get_buffer(world, "ellipse"), vxo_lines(vx_resc_copyf (points, npoints*3), npoints, GL_LINE_LOOP, vxo_lines_style(vx_purple, 1.0f) )); vx_buffer_swap(vx_world_get_buffer(world, "ellipse")); } if (1) { vx_object_t *vt = vxo_text_create(VXO_TEXT_ANCHOR_TOP_RIGHT, "<<right,#0000ff>>Heads Up!\n"); vx_buffer_t *vb = vx_world_get_buffer(world, "text"); vx_buffer_add_back(vb, vxo_pix_coords(VX_ORIGIN_TOP_RIGHT,vt)); vx_buffer_swap(vb); } // Draw a texture if (state->img != NULL){ image_u32_t * img = state->img; vx_object_t * o3 = vxo_image_texflags(vx_resc_copyui(img->buf, img->stride*img->height), img->width, img->height, img->stride, GL_RGBA, VXO_IMAGE_FLIPY, VX_TEX_MIN_FILTER | VX_TEX_MAG_FILTER); // pack the image into the unit square vx_buffer_t * vb = vx_world_get_buffer(world, "texture"); vx_buffer_add_back(vb,vxo_chain( vxo_mat_scale(1.0/img->height), vxo_mat_translate3(0, - img->height, 0), o3)); vx_buffer_swap(vb); } }
vx_object_t * vxo_objmtl(const char * obj_filename) { int texture_flag = 0; FILE * fp_obj = fopen(obj_filename, "r"); if (fp_obj == NULL) return NULL; #define LNSZ 1024 char line_buffer[LNSZ]; // Store 3D vertices by value zarray_t * vertices = zarray_create(sizeof(float)*3); zarray_t * textures = zarray_create(sizeof(float)*3); zarray_t * normals = zarray_create(sizeof(float)*3); wav_group_t * cur_group = NULL; zarray_t * group_list = zarray_create(sizeof(wav_group_t*)); zhash_t * mtl_map = NULL; // created on reading mtllib entry //zhash_t * obj_map = zhash_create(sizeof(char*), sizeof(vx_object_t*), zhash_str_hash, zhash_str_equals); // Read in the entire file, save vertices, and indices for later processing. while (1) { int eof = fgets(line_buffer, LNSZ, fp_obj) == NULL; char * line = str_trim(line_buffer); // If possible, batch process the last group if (str_starts_with(line, "g ") || eof) { if (cur_group != NULL) { assert(cur_group->group_idx != NULL); zarray_add(group_list, &cur_group); cur_group = NULL; } } if (eof) break; if (str_starts_with(line, "#") || strlen(line) == 0 || !strcmp(line,"\r")) continue; if (str_starts_with(line, "g ")) { assert(mtl_map != NULL); char obj_name[LNSZ]; sscanf(line, "g %s", obj_name); cur_group = calloc(1, sizeof(wav_group_t)); cur_group->group_idx = zarray_create(sizeof(tri_idx_t)); } else if (str_starts_with(line, "v ")) { float vertex[3]; sscanf(line, "v %f %f %f", &vertex[0], &vertex[1], &vertex[2]); zarray_add(vertices, &vertex); } else if (str_starts_with(line, "vn ")) { float normal[3]; sscanf(line, "vn %f %f %f", &normal[0], &normal[1], &normal[2]); zarray_add(normals, &normal); } else if (str_starts_with(line, "vt ")) { texture_flag = 1; float texture[3]; sscanf(line, "vt %f %f %f", &texture[0], &texture[1], &texture[2]); zarray_add(textures, &texture); } else if (str_starts_with(line, "f ")) { tri_idx_t idxs; if (texture_flag) { sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d", &idxs.vIdxs[0], &idxs.tIdxs[0], &idxs.nIdxs[0], &idxs.vIdxs[1], &idxs.tIdxs[1], &idxs.nIdxs[1], &idxs.vIdxs[2], &idxs.tIdxs[2], &idxs.nIdxs[2]); } else { sscanf(line, "f %d//%d %d//%d %d//%d", &idxs.vIdxs[0], &idxs.nIdxs[0], &idxs.vIdxs[1], &idxs.nIdxs[1], &idxs.vIdxs[2], &idxs.nIdxs[2]); } zarray_add(cur_group->group_idx, &idxs); } else if (str_starts_with(line, "usemtl ")) { char *mname = calloc(1, sizeof(char)*1024); sscanf(line, "usemtl %s", mname); zhash_get(mtl_map, &mname, &cur_group->material); free(mname); } else if (str_starts_with(line, "s ")) { // No idea what to do with smoothing instructions } else if (str_starts_with(line, "mtllib ")) { char * cur_path = strdup(obj_filename); const char * dir_name = dirname(cur_path); char mtl_basename[LNSZ]; sscanf(line, "mtllib %s", mtl_basename); char mtl_filename[LNSZ]; sprintf(mtl_filename,"%s/%s", dir_name, mtl_basename); mtl_map = load_materials(mtl_filename); if (mtl_map == NULL) { zarray_destroy(vertices); zarray_destroy(normals); return NULL; // XXX cleanup! } free(cur_path); } else { printf("Did not parse: %s\n", line); for (int i = 0; i < strlen(line); i++) { printf("0x%x ", (int)line[i]); } printf("\n"); } } if (1) // useful to enable when compensating for model scale print_bounds(vertices); // Process the model sections in two passes -- first add all the // objects which are not transparent. Then render transparent // objects after vx_object_t * vchain = vxo_chain_create(); zarray_t * sorted_groups = zarray_create(sizeof(wav_group_t*)); for (int i = 0, sz = zarray_size(group_list); i < sz; i++) { wav_group_t * group = NULL; zarray_get(group_list, i, &group); // add to front if solid if (group->material.d == 1.0f) { zarray_insert(sorted_groups, 0, &group); } else { // add to back if transparent zarray_add(sorted_groups, &group); } } int total_triangles = 0; for (int i = 0, sz = zarray_size(sorted_groups); i < sz; i++) { wav_group_t * group = NULL; zarray_get(sorted_groups, i, &group); int ntri = zarray_size(group->group_idx); vx_resc_t * vert_resc = vx_resc_createf(ntri*9); vx_resc_t * norm_resc = vx_resc_createf(ntri*9); for (int j = 0; j < ntri; j++) { tri_idx_t idxs; zarray_get(group->group_idx, j, &idxs); for (int i = 0; i < 3; i++) { zarray_get(vertices, idxs.vIdxs[i]-1, &((float*)vert_resc->res)[9*j + i*3]); zarray_get(normals, idxs.nIdxs[i]-1, &((float*)norm_resc->res)[9*j + i*3]); } } vx_style_t * sty = vxo_mesh_style_fancy(group->material.Ka, group->material.Kd, group->material.Ks, group->material.d, group->material.Ns, group->material.illum); vxo_chain_add(vchain, vxo_mesh(vert_resc, ntri*3, norm_resc, GL_TRIANGLES, sty)); total_triangles += ntri; } //Cleanup: // 1. Materials, names are by reference, but materials are by value zhash_vmap_keys(mtl_map, free); zhash_destroy(mtl_map); // 2. Geometry zarray_destroy(vertices); // stored by value zarray_destroy(normals); // stored by value // 2b wav_group_t are stored by reference zarray_vmap(group_list, wav_group_destroy); zarray_destroy(group_list); zarray_destroy(sorted_groups); // duplicate list, so don't need to free fclose(fp_obj); return vchain; }