void write_mesh(FILE *o, Lib3dsFile *f, Lib3dsMeshInstanceNode *node) { float (*orig_vertices)[3]; int export_texcos; int export_normals; int i, j; Lib3dsMesh *mesh; mesh = lib3ds_file_mesh_for_node(f, (Lib3dsNode*)node); if (!mesh || !mesh->vertices) return; fprintf(o, "# object %s\n", node->base.name); fprintf(o, "g %s\n", node->instance_name[0]? node->instance_name : node->base.name); orig_vertices = (float(*)[3])malloc(sizeof(float) * 3 * mesh->nvertices); memcpy(orig_vertices, mesh->vertices, sizeof(float) * 3 * mesh->nvertices); { float inv_matrix[4][4], M[4][4]; float tmp[3]; int i; lib3ds_matrix_copy(M, node->base.matrix); lib3ds_matrix_translate(M, -node->pivot[0], -node->pivot[1], -node->pivot[2]); lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_mult(M, M, inv_matrix); for (i = 0; i < mesh->nvertices; ++i) { lib3ds_vector_transform(tmp, M, mesh->vertices[i]); lib3ds_vector_copy(mesh->vertices[i], tmp); } } export_texcos = (mesh->texcos != 0); export_normals = (mesh->faces != 0); for (i = 0; i < mesh->nvertices; ++i) { fprintf(o, "v %f %f %f\n", mesh->vertices[i][0], mesh->vertices[i][1], mesh->vertices[i][2]); } fprintf(o, "# %d vertices\n", mesh->nvertices); if (export_texcos) { for (i = 0; i < mesh->nvertices; ++i) { fprintf(o, "vt %f %f\n", mesh->texcos[i][0], mesh->texcos[i][1]); } fprintf(o, "# %d texture vertices\n", mesh->nvertices); } if (export_normals) { float (*normals)[3] = (float(*)[3])malloc(sizeof(float) * 9 * mesh->nfaces); lib3ds_mesh_calculate_vertex_normals(mesh, normals); for (i = 0; i < 3 * mesh->nfaces; ++i) { fprintf(o, "vn %f %f %f\n", normals[i][0], normals[i][1], normals[i][2]); } free(normals); fprintf(o, "# %d normals\n", 3 * mesh->nfaces); } { int mat_index = -1; for (i = 0; i < mesh->nfaces; ++i) { if (mat_index != mesh->faces[i].material) { mat_index = mesh->faces[i].material; if (mat_index != -1) { fprintf(o, "usemtl %s\n", f->materials[mat_index]->name); } } fprintf(o, "f "); for (j = 0; j < 3; ++j) { fprintf(o, "%d", mesh->faces[i].index[j] + max_vertices + 1); if (export_texcos) { fprintf(o, "/%d", mesh->faces[i].index[j] + max_texcos + 1); } else if (export_normals) { fprintf(o, "/"); } if (export_normals) { fprintf(o, "/%d", 3 * i + j + max_normals + 1); } if (j < 3) { fprintf(o, " "); } } fprintf(o, "\n"); } } max_vertices += mesh->nvertices; if (export_texcos) max_texcos += mesh->nvertices; if (export_normals) max_normals += 3 * mesh->nfaces; memcpy(mesh->vertices, orig_vertices, sizeof(float) * 3 * mesh->nvertices); free(orig_vertices); }
std::vector<CL_Lib3dsMesh> CL_Lib3dsFile::export_meshes(Lib3dsNode *node) { if (node == 0) { lib3ds_file_eval(file, 0.0f); node = file->nodes; } std::vector<CL_Lib3dsMesh> meshes; for (; node; node = node->next) { if (node->type == LIB3DS_NODE_MESH_INSTANCE) { Lib3dsMeshInstanceNode *instance_node = (Lib3dsMeshInstanceNode *) node; Lib3dsMesh *mesh = lib3ds_file_mesh_for_node(file, (Lib3dsNode*)node); if (mesh && mesh->vertices) { float inv_matrix[4][4], M[4][4]; lib3ds_matrix_copy(M, instance_node->base.matrix); lib3ds_matrix_translate(M, -instance_node->pivot[0], -instance_node->pivot[1], -instance_node->pivot[2]); lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_mult(M, M, inv_matrix); std::vector<CL_Vec3f> positions; for (int i = 0; i < mesh->nvertices; ++i) { float position[3]; lib3ds_vector_transform(position, M, mesh->vertices[i]); positions.push_back(CL_Vec3f(position[0], position[1], position[2])); } std::vector<CL_Vec2f> texcoords; if (mesh->texcos) { for (int i = 0; i < mesh->nvertices; ++i) { float tx = mesh->texcos[i][0]; float ty = mesh->texcos[i][1]; texcoords.push_back(CL_Vec2f(tx, ty)); } } std::vector<CL_Vec3f> normals; if (mesh->faces && mesh->nfaces > 0) { float (*normals_array)[3] = (float(*)[3])malloc(sizeof(float) * 9 * mesh->nfaces); lib3ds_mesh_calculate_vertex_normals(mesh, normals_array); for (int i = 0; i < 3 * mesh->nfaces; ++i) { normals.push_back(CL_Vec3f(normals_array[i][0], normals_array[i][1], normals_array[i][2])); } free(normals_array); } CL_Lib3dsMesh mesh_object; for (int i = 0; i < mesh->nfaces; ++i) { int material_index = mesh->faces[i].material; mesh_object.face_materials.push_back(material_index); for (int j = 0; j < 3; ++j) { int vertex_index = mesh->faces[i].index[j]; mesh_object.positions.push_back(positions[vertex_index]); if (!texcoords.empty()) mesh_object.texcooords.push_back(texcoords[vertex_index]); if (!normals.empty()) mesh_object.normals.push_back(normals[i*3+j]); } } meshes.push_back(mesh_object); } if (node->childs) { std::vector<CL_Lib3dsMesh> child_meshes = export_meshes(node->childs); meshes.insert(meshes.end(), child_meshes.begin(), child_meshes.end()); } } } return meshes; }