#include "evas_model_load_save_common.h" static inline char * _to_next_line(char *current) { while (*current != '\n') current++; current++; return current; } static inline char * _to_begin_of_line(char *current) { while (*current != '\n') current--; current++; return current; } static inline char * _to_next_number(char *current, int count) { int i; for (i = 0; i < count; i++) { while (*current != ' ') current++; current++; } return current; } static inline char * _read_data(float *array, int place, int count, char *current, float divider) { int i; for (i = 0; i < count; i++) { sscanf (current,"%f", &ARRAY_2D(array, place, i, count)); ARRAY_2D(array, place, i, count) /= divider; current = _to_next_number(current, 1); } return current; } static inline Eina_Bool _read_ply_header(char *map, Evas_Model_Load_Save_Header *header, const char *filename) { Eina_Bool reading_vertices = EINA_TRUE, check_next_char = EINA_FALSE; int vertex_lines, triangles = 0, vertices_in_current_face = 0; char **helping_pointer; char *current; helping_pointer = eina_str_split(map, "vertex ", 0); if (helping_pointer == NULL) { ERR("PLY file doesn't contain the required keyword 'vertex': %s", filename); return EINA_FALSE; } sscanf(helping_pointer[1], "%d", &header->vertices_count); free(helping_pointer[0]); free(helping_pointer); helping_pointer = eina_str_split(map, "end_header\n", 0); if (helping_pointer == NULL) { ERR("PLY file doesn't contain the required keyword 'end_header': %s", filename); return EINA_FALSE; } current = helping_pointer[1]; vertex_lines = header->vertices_count; while (*current != '\0') { if (vertex_lines == 1) reading_vertices = EINA_FALSE; if (*current == '\n') { if (reading_vertices) vertex_lines--; else check_next_char = EINA_TRUE; } if (check_next_char) { if ((*current <= '9') && (*current >= '0')) vertices_in_current_face = (vertices_in_current_face * 10) + (*current - '0'); else if (*current >= ' ') { triangles += (vertices_in_current_face - 2); vertices_in_current_face = 0; check_next_char = EINA_FALSE; } } current++; } header->indices_count = 3 * triangles; free(helping_pointer[0]); free(helping_pointer); /* analyse flags used when file was saved in blender */ helping_pointer = eina_str_split(map, "property float ", 0); if (helping_pointer == NULL) { ERR("PLY file doesn't contain any float properties: %s", filename); return EINA_FALSE; } if ((helping_pointer[1] != NULL) && (*helping_pointer[1] == 'x') && (helping_pointer[2] != NULL) && (*helping_pointer[2] == 'y') && (helping_pointer[3] != NULL) && (*helping_pointer[3] == 'z')) header->existence_of_positions = EINA_TRUE; else { ERR("PLY file doesn't start with x,y,z float fields, they are required: %s", filename); free(helping_pointer[0]); free(helping_pointer); return EINA_FALSE; } if ((helping_pointer[4] != NULL) && (*helping_pointer[4] == 'n') && (helping_pointer[5] != NULL) && (*helping_pointer[5] == 'n') && (helping_pointer[6] != NULL) && (*helping_pointer[6] == 'n')) header->existence_of_normals = EINA_TRUE; if ((header->existence_of_normals && ((helping_pointer[7] != NULL) && (*helping_pointer[7] == 's') && (helping_pointer[8] != NULL) && (*helping_pointer[8] == 't'))) || (!header->existence_of_normals && ((helping_pointer[4] != NULL) && (*helping_pointer[4] == 's') && (helping_pointer[5] != NULL) && (*helping_pointer[5] == 't')))) header->existence_of_tex_coords = EINA_TRUE; free(helping_pointer[0]); free(helping_pointer); helping_pointer = eina_str_split(map, "property uchar ", 0); if (helping_pointer == NULL) { ERR("PLY file doesn't contain any uchar properties: %s", filename); return EINA_FALSE; } if ((helping_pointer[1] != NULL) && (*helping_pointer[1] == 'r') && (helping_pointer[2] != NULL) && (*helping_pointer[2] == 'g') && (helping_pointer[3] != NULL) && (*helping_pointer[3] == 'b')) header->existence_of_colors = EINA_TRUE; free(helping_pointer[0]); free(helping_pointer); return EINA_TRUE; } static inline void _read_ply_vertex_data(Evas_Model_Load_Save_Header header, char **current, Evas_Model_Load_Save_Data data) { int i; for (i = 0; i < header.vertices_count; i++) { *current = _read_data(data.positions, i, 3, *current, 1.0); if (header.existence_of_normals) *current = _read_data(data.normals, i, 3, *current, 1.0); if (header.existence_of_tex_coords) *current = _read_data(data.tex_coords, i, 2, *current, 1.0); if (header.existence_of_colors) *current = _read_data(data.colors, i, 3, *current, 255.0); *current = _to_begin_of_line(*current); } } static inline void _read_ply_indices_data(Evas_Model_Load_Save_Header header, char **current, Evas_Model_Load_Save_Data data) { int i, j, count_of_triangles_in_line = 0; for (i = 0; i < header.indices_count;) { sscanf (*current,"%d", &count_of_triangles_in_line); count_of_triangles_in_line -= 2; *current = _to_next_number(*current, 1); sscanf (*current,"%hu", data.indices + i); for (j = 0; j < count_of_triangles_in_line; j++) { if (j > 0) data.indices[i] = data.indices[i - 3]; *current = _to_next_number(*current, 1); sscanf (*current,"%hu %hu", data.indices + i + 1, data.indices + i + 2); i+=3; } *current = _to_next_line(*current); } } void evas_model_load_file_ply(Evas_Canvas3D_Mesh *mesh, Eina_File *file) { char *current = NULL, *map = NULL, **split_of_map = NULL; Evas_Model_Load_Save_Header header = { 0, 0, 0, 0, 0, 0 }; Evas_Model_Load_Save_Data data = { NULL, NULL, NULL, NULL, NULL }; Evas_Model_Load_Save_Stride stride = { 0, 0, 0, 0 }; map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL); if (map == NULL) { ERR("Failed to create map from file %s\n", eina_file_filename_get(file)); return; } header = evas_model_load_save_header_new(); if(!_read_ply_header(map, &header, eina_file_filename_get(file))) return; if (!evas_model_load_allocate_data_due_to_header(header, &data)) { ERR("Memory allocation is failed."); return; } split_of_map = eina_str_split(map, "end_header\n", 0); current = split_of_map[1]; _read_ply_vertex_data(header, ¤t, data); _read_ply_indices_data(header, ¤t, data); evas_model_load_vertex_data_to_mesh(mesh, header, data, &stride); evas_model_load_indices_data_to_mesh(mesh, header, data); evas_model_load_vertex_data_unmap(mesh, 0, header); evas_model_load_aabb_add_to_frame(mesh, 0, stride); free(split_of_map[0]); free(split_of_map); if (map) { eina_file_map_free(file, map); map = NULL; } evas_model_load_save_data_free(header, &data); }