From e6bba4d91c814b260c0b56feb77a7073942cc449 Mon Sep 17 00:00:00 2001 From: "perepelits.m" Date: Tue, 29 Dec 2015 13:28:55 +0900 Subject: [PATCH] [Evas] Refactor model's savers and loaders. Summary: Move common part to a separated document. Make code more readable using smaller functions. (from Task T2713) Everything is OK with make check. Reviewers: cedric, raster, Hermet, stefan_schmidt Reviewed By: stefan_schmidt Subscribers: jpeg, artem.popov Differential Revision: https://phab.enlightenment.org/D3430 --- src/Makefile_Evas.am | 4 +- ...common.c => evas_model_load_save_common.c} | 2 +- ...common.h => evas_model_load_save_common.h} | 0 .../model_loaders/eet/evas_model_load_eet.c | 2 - .../model_loaders/ply/evas_model_load_ply.c | 335 +++++------------- .../model_savers/eet/evas_model_save_eet.c | 20 +- .../model_savers/obj/evas_model_save_obj.c | 263 ++++++++------ .../model_savers/ply/evas_model_save_ply.c | 121 ++++--- src/tests/evas/evas_test_mesh.c | 36 +- 9 files changed, 357 insertions(+), 426 deletions(-) rename src/lib/evas/common3d/save_load/{evas_model_common.c => evas_model_load_save_common.c} (99%) rename src/lib/evas/common3d/save_load/{evas_model_common.h => evas_model_load_save_common.h} (100%) diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index ebc5480151..be24ba5b6a 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -224,8 +224,8 @@ lib/evas/canvas/evas_canvas3d_node_callback.h lib_evas_libevas_la_SOURCES += \ lib/evas/common3d/save_load/evas_model_load.c \ lib/evas/common3d/save_load/evas_model_save.c \ -lib/evas/common3d/save_load/evas_model_common.c \ -lib/evas/common3d/save_load/evas_model_common.h \ +lib/evas/common3d/save_load/evas_model_load_save_common.c \ +lib/evas/common3d/save_load/evas_model_load_save_common.h \ modules/evas/model_loaders/eet/evas_model_load_eet.c \ modules/evas/model_loaders/md2/evas_model_load_md2.c \ modules/evas/model_loaders/obj/evas_model_load_obj.c \ diff --git a/src/lib/evas/common3d/save_load/evas_model_common.c b/src/lib/evas/common3d/save_load/evas_model_load_save_common.c similarity index 99% rename from src/lib/evas/common3d/save_load/evas_model_common.c rename to src/lib/evas/common3d/save_load/evas_model_load_save_common.c index 612bccd5c8..190ba5982c 100644 --- a/src/lib/evas/common3d/save_load/evas_model_common.c +++ b/src/lib/evas/common3d/save_load/evas_model_load_save_common.c @@ -1,4 +1,4 @@ -#include "evas_model_common.h" +#include "evas_model_load_save_common.h" # define SAVE_MESH_INDICES_COPY \ if (header.indices_count) \ diff --git a/src/lib/evas/common3d/save_load/evas_model_common.h b/src/lib/evas/common3d/save_load/evas_model_load_save_common.h similarity index 100% rename from src/lib/evas/common3d/save_load/evas_model_common.h rename to src/lib/evas/common3d/save_load/evas_model_load_save_common.h diff --git a/src/modules/evas/model_loaders/eet/evas_model_load_eet.c b/src/modules/evas/model_loaders/eet/evas_model_load_eet.c index f5b1b6b8ca..e049e2c0a7 100644 --- a/src/modules/evas/model_loaders/eet/evas_model_load_eet.c +++ b/src/modules/evas/model_loaders/eet/evas_model_load_eet.c @@ -127,5 +127,3 @@ evas_model_load_file_eet(Evas_Canvas3D_Mesh *mesh, Eina_File *file) _evas_canvas3d_eet_file_free(eet_file); } - - diff --git a/src/modules/evas/model_loaders/ply/evas_model_load_ply.c b/src/modules/evas/model_loaders/ply/evas_model_load_ply.c index 1beef18a94..971e951613 100644 --- a/src/modules/evas/model_loaders/ply/evas_model_load_ply.c +++ b/src/modules/evas/model_loaders/ply/evas_model_load_ply.c @@ -1,44 +1,4 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include "stdio.h" -#include "evas_common_private.h" -#include "evas_private.h" -#include - -/* set value to position [x][y] to array name which have. */ -#define ARRAY_2D(name, x, y, count_y) (*(name + x * count_y + y)) - -/* Structures for reading data from file. */ -typedef struct _PLY_Header PLY_Header; - -struct _PLY_Header -{ - int vertices_count; - int triangles_count; - Eina_Bool existence_of_geometries; - Eina_Bool existence_of_normals; - Eina_Bool existence_of_texcoords; - Eina_Bool existence_of_colors; -}; - -/* create new header */ -static inline PLY_Header -_new_ply_header() -{ - PLY_Header header; - - header.vertices_count = 0; - header.triangles_count = 0; - header.existence_of_geometries = EINA_FALSE; - header.existence_of_normals = EINA_FALSE; - header.existence_of_texcoords = EINA_FALSE; - header.existence_of_colors = EINA_FALSE; - - return header; -} +#include "evas_model_load_save_common.h" static inline char * _to_next_line(char *current) @@ -81,8 +41,8 @@ _read_data(float *array, int place, int count, char *current, float divider) return current; } -static inline PLY_Header -_read_header(char *map)//Check properties of mesh in .ply file. +static inline Eina_Bool +_read_ply_header(char *map, Evas_Model_Load_Save_Header *header) { eina_init(); @@ -90,30 +50,29 @@ _read_header(char *map)//Check properties of mesh in .ply file. int vertex_lines, triangles = 0, vertices_in_current_face = 0; char **helping_pointer; char *current; - PLY_Header header; - header = _new_ply_header(); helping_pointer = eina_str_split(map, "vertex ", 0); if (helping_pointer == NULL) { ERR("File have not kayword vertex. It is necessary."); - return header; + return EINA_FALSE; } - sscanf(helping_pointer[1], "%d", &header.vertices_count); + sscanf(helping_pointer[1], "%d", &header->vertices_count); + free(helping_pointer); helping_pointer = eina_str_split(map, "end_header\n", 0); if (helping_pointer == NULL) { ERR("File have not kayword end_header. It is necessary."); - return header; + return EINA_FALSE; } current = helping_pointer[1]; - vertex_lines = header.vertices_count; + vertex_lines = header->vertices_count; while (*current != '\0') { if (vertex_lines == 1) @@ -139,8 +98,7 @@ _read_header(char *map)//Check properties of mesh in .ply file. current++; } - header.triangles_count = triangles; - free(helping_pointer); + header->indices_count = 3 * triangles; /* analyse flags used when file was saved in blender */ helping_pointer = eina_str_split(map, "property float ", 0); @@ -148,243 +106,124 @@ _read_header(char *map)//Check properties of mesh in .ply file. 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_geometries = EINA_TRUE; - else return header; + header->existence_of_positions = EINA_TRUE; + else 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; + header->existence_of_normals = EINA_TRUE; - if ((header.existence_of_normals && + 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 && + (!header->existence_of_normals && ((helping_pointer[4] != NULL) && (*helping_pointer[4] == 's') && (helping_pointer[5] != NULL) && (*helping_pointer[5] == 't')))) - header.existence_of_texcoords = EINA_TRUE; + header->existence_of_tex_coords = EINA_TRUE; helping_pointer = eina_str_split(map, "property uchar ", 0); 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; + header->existence_of_colors = EINA_TRUE; + + if (!header->existence_of_positions) + { + ERR("File have not x, y, or z field as the first 3 float fields. They are necessary."); + return EINA_FALSE; + } free(helping_pointer); + return EINA_TRUE; +} - return header; +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) { - Evas_Canvas3D_Mesh_Data *pd; - int i = 0, j = 0, count_of_triangles_in_line = 0; - float *pos, *nor, *tex, *col; - int stride_pos, stride_nor, stride_tex, stride_col; - char *current, *map; - PLY_Header header; - float *_vertices_ply = NULL, *_normals_ply = NULL; - float *_tex_coords_ply = NULL, *_colors_ply = NULL; - char **helping_pointer; + char *current = NULL, *map = NULL; + Evas_Model_Load_Save_Header header; + Evas_Model_Load_Save_Data data; + Evas_Model_Load_Save_Stride stride; 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 = _read_header(map); + header = evas_model_load_save_header_new(); + if(!_read_ply_header(map, &header)) return; - if (!header.existence_of_geometries) + if (!evas_model_load_allocate_data_due_to_header(header, &data)) { - ERR("File have not x, y, or z field as the first 3 float fields. They are necessary."); + ERR("Memory allocation is failed."); return; } - helping_pointer = eina_str_split(map, "end_header\n", 0); - - if (helping_pointer == NULL) - { - ERR("File have not kayword end_header. It is necessary."); - return; - } - - current = helping_pointer[1]; - - _vertices_ply = malloc(header.vertices_count * 3 * sizeof(float)); - if (header.existence_of_normals) - _normals_ply = malloc(header.vertices_count * 3 * sizeof(float)); - if (header.existence_of_texcoords) - _tex_coords_ply = malloc(header.vertices_count * 2 * sizeof(float)); - if (header.existence_of_colors) - _colors_ply = malloc(header.vertices_count * 3 * sizeof(float)); - unsigned short *_indices = malloc(header.triangles_count * 3 * sizeof(unsigned short)); - - if ((header.existence_of_geometries && (_vertices_ply == NULL)) || - (header.existence_of_normals && (_normals_ply == NULL)) || - (header.existence_of_texcoords && (_tex_coords_ply == NULL)) || - (header.existence_of_colors && (_colors_ply == NULL)) || - (_indices == NULL)) - { - ERR("Allocate memory is failed."); - free(_vertices_ply); - free(_normals_ply); - free(_tex_coords_ply); - free(_colors_ply); - free(_indices); - return; - } - - for (i = 0; i < header.vertices_count; i++) - { - current = _read_data(_vertices_ply, i, 3, current, 1.0); - if (header.existence_of_normals) - current = _read_data(_normals_ply, i, 3, current, 1.0); - if (header.existence_of_texcoords) - current = _read_data(_tex_coords_ply, i, 2, current, 1.0); - if (header.existence_of_colors) - current = _read_data(_colors_ply, i, 3, current, 255.0); - current = _to_begin_of_line(current); - } - - for (i = 0; i < header.triangles_count * 3;) - { - sscanf (current,"%d", &count_of_triangles_in_line); - count_of_triangles_in_line -= 2; - current = _to_next_number(current, 1); - - sscanf (current,"%hu", _indices + i); - - for (j = 0; j < count_of_triangles_in_line; j++) - { - if (j > 0) - _indices[i] = _indices[i - 3]; - current = _to_next_number(current, 1); - sscanf (current,"%hu %hu", - _indices + i + 1, - _indices + i + 2); - i+=3; - } - current = _to_next_line(current); - } - - /* prepare of mesh and take pointers to data which must be read */ - eo_do(mesh, - evas_canvas3d_mesh_vertex_count_set(header.vertices_count), - evas_canvas3d_mesh_vertex_assembly_set(EVAS_CANVAS3D_VERTEX_ASSEMBLY_TRIANGLES), - evas_canvas3d_mesh_frame_add(0), - evas_canvas3d_mesh_frame_vertex_data_copy_set(0, EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION, 0, NULL), - evas_canvas3d_mesh_frame_vertex_data_copy_set(0, EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL, 0, NULL), - evas_canvas3d_mesh_frame_vertex_data_copy_set(0, EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD, 0, NULL), - evas_canvas3d_mesh_frame_vertex_data_copy_set(0, EVAS_CANVAS3D_VERTEX_ATTRIB_COLOR, 0, NULL), - - pos = (float *)evas_canvas3d_mesh_frame_vertex_data_map(0, EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION), - nor = (float *)evas_canvas3d_mesh_frame_vertex_data_map(0, EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL), - tex = (float *)evas_canvas3d_mesh_frame_vertex_data_map(0, EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD), - col = (float *)evas_canvas3d_mesh_frame_vertex_data_map(0, EVAS_CANVAS3D_VERTEX_ATTRIB_COLOR), - - stride_pos = evas_canvas3d_mesh_frame_vertex_stride_get(0, EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION), - stride_nor = evas_canvas3d_mesh_frame_vertex_stride_get(0, EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL), - stride_tex = evas_canvas3d_mesh_frame_vertex_stride_get(0, EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD), - stride_col = evas_canvas3d_mesh_frame_vertex_stride_get(0, EVAS_CANVAS3D_VERTEX_ATTRIB_COLOR)); - - if (stride_pos == 0) stride_pos = sizeof(float) * 3; - if (stride_nor == 0) stride_nor = sizeof(float) * 3; - if (stride_tex == 0) stride_tex = sizeof(float) * 2; - if (stride_col == 0) stride_col = sizeof(float) * 4; - - - for (j = 0; j < header.vertices_count; j++) - { - float *p, *n, *t, *c; - - p = (float *)((char *)pos + stride_pos * j); - n = (float *)((char *)nor + stride_nor * j); - t = (float *)((char *)tex + stride_tex * j); - c = (float *)((char *)col + stride_col * j); - - - p[0] = ARRAY_2D(_vertices_ply, j, 0, 3); - p[1] = ARRAY_2D(_vertices_ply, j, 1, 3); - p[2] = ARRAY_2D(_vertices_ply, j, 2, 3); - - if (header.existence_of_normals) - { - n[0] = ARRAY_2D(_normals_ply, j, 0, 3); - n[1] = ARRAY_2D(_normals_ply, j, 1, 3); - n[2] = ARRAY_2D(_normals_ply, j, 2, 3); - } - else - { - n[0] = 0.0; - n[1] = 0.0; - n[2] = 0.0; - } - - if (header.existence_of_texcoords) - { - t[0] = ARRAY_2D(_tex_coords_ply, j, 0, 2); - t[1] = ARRAY_2D(_tex_coords_ply, j, 1, 2); - } - else - { - t[0] = 0.0; - t[1] = 0.0; - } - - if (header.existence_of_colors) - { - c[0] = ARRAY_2D(_colors_ply, j, 0, 3); - c[1] = ARRAY_2D(_colors_ply, j, 1, 3); - c[2] = ARRAY_2D(_colors_ply, j, 2, 3); - c[3] = 1.0; - } - else - { - c[0] = 0.0; - c[1] = 0.0; - c[2] = 0.0; - c[3] = 1.0; - } - } - - eo_do(mesh, - evas_canvas3d_mesh_index_data_copy_set(EVAS_CANVAS3D_INDEX_FORMAT_UNSIGNED_SHORT, - header.triangles_count * 3, - _indices)); - - free(helping_pointer); - free(_vertices_ply); - if (header.existence_of_normals) - free(_normals_ply); - if (header.existence_of_texcoords) - free(_tex_coords_ply); - if (header.existence_of_colors) - free(_colors_ply); - free(_indices); - - /* Unmap vertex buffer. */ - eo_do(mesh, - evas_canvas3d_mesh_frame_vertex_data_unmap(0, EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION), - evas_canvas3d_mesh_frame_vertex_data_unmap(0, EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL), - evas_canvas3d_mesh_frame_vertex_data_unmap(0, EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD), - evas_canvas3d_mesh_frame_vertex_data_unmap(0, EVAS_CANVAS3D_VERTEX_ATTRIB_COLOR)); - - pd = eo_data_scope_get(mesh, EVAS_CANVAS3D_MESH_CLASS); - - if (!evas_canvas3d_mesh_aabb_add_to_frame(pd, 0, stride_pos)) - { - ERR("Axis-Aligned Bounding Box wan't added in frame %d ", 0); - } + current = eina_str_split(map, "end_header\n", 0)[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); if (map) { eina_file_map_free(file, map); map = NULL; } -} + evas_model_load_save_data_free(header, &data); +} diff --git a/src/modules/evas/model_savers/eet/evas_model_save_eet.c b/src/modules/evas/model_savers/eet/evas_model_save_eet.c index 0ac7e66e44..183dadae3c 100644 --- a/src/modules/evas/model_savers/eet/evas_model_save_eet.c +++ b/src/modules/evas/model_savers/eet/evas_model_save_eet.c @@ -41,18 +41,17 @@ _set_geometry_to_eet_file_from_mesh(Evas_Canvas3D_Mesh_Data *mesh, if (vb->data == NULL)\ {\ ERR("Reading of geometrics is failed.");\ - free(vertices);\ - free(geometry);\ - free(geometries);\ - return;\ }\ - src = (float *)vb->data;\ - for (i = 0; i < mesh->vertex_count; i++)\ + else\ {\ - vertices[i].component.x = src[0];\ - vertices[i].component.y = src[1];\ - command_for_z_component\ - src += f->vertices[a].element_count;\ + src = (float *)vb->data;\ + for (i = 0; i < mesh->vertex_count; i++)\ + {\ + vertices[i].component.x = src[0];\ + vertices[i].component.y = src[1];\ + command_for_z_component\ + src += f->vertices[a].element_count;\ + }\ } geometry->vertices = vertices; SAVE_GEOMETRICS(EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION, position, vertices[i].position.z = src[2];) @@ -190,4 +189,3 @@ evas_model_save_file_eet(const Evas_Canvas3D_Mesh *mesh, _evas_canvas3d_eet_file_free(eet_file); } - diff --git a/src/modules/evas/model_savers/obj/evas_model_save_obj.c b/src/modules/evas/model_savers/obj/evas_model_save_obj.c index d9be3dce44..09e5c723c6 100644 --- a/src/modules/evas/model_savers/obj/evas_model_save_obj.c +++ b/src/modules/evas/model_savers/obj/evas_model_save_obj.c @@ -1,86 +1,71 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif +#include "evas_model_load_save_common.h" -#include -#include -#include "stdio.h" -#include "evas_common_private.h" -#include "evas_private.h" - -#define OPEN_FILE(extension)\ - FILE * _##extension##_file = fopen(_##extension##_file_name, "w+"); - -#define SAVE_GEOMETRICS(a, format) \ - vb = &f->vertices[a]; \ - if (vb->data != NULL) \ - { \ - fprintf(_obj_file, "o %s\n",_obj_file_name); \ - src = (float *)vb->data; \ - for (i = 0; i < pd->vertex_count; i++) \ - { \ - fprintf(_obj_file, format, src[0], src[1]); \ - if (a != EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD) \ - fprintf(_obj_file, " %.4f", src[2]); \ - fprintf(_obj_file, "\n"); \ - src += f->vertices[a].element_count; \ - } \ - } - -static void -_write_point(FILE * obj_file, - int num, - int num_of_point, - Eina_Bool existence_of_normal, - Eina_Bool existence_of_tex_point) +static unsigned short* +_init_obj_indices_data(Evas_Model_Load_Save_Header header) { - if (num_of_point == 1) - fprintf(obj_file, "f "); + unsigned short *i_data; + int i = 0; - if (existence_of_normal) - { - if (existence_of_tex_point) - fprintf(obj_file, "%i/%i/%i ", num, num, num); - else - fprintf(obj_file, "%i//%i ", num, num); - } - else - { - if (existence_of_tex_point) - fprintf(obj_file, "%i/%i ", num, num); - else - fprintf(obj_file, "%i ", num); - } + if (header.existence_of_positions) i++; + if (header.existence_of_normals) i++; + if (header.existence_of_tex_coords) i++; + i_data = calloc(header.vertices_count * i, sizeof(unsigned short)); - if (num_of_point == 3) - fprintf(obj_file, "\n"); + return i_data; } static void -_save_mesh(Evas_Canvas3D_Mesh_Data *pd, const char *_obj_file_name, Evas_Canvas3D_Mesh_Frame *f) +_vertex_data_free_cb(void *data) +{ + eina_stringshare_del(data); +} + +static void +_write_point(FILE *obj_file, + int num, + int num_of_point, + Evas_Model_Load_Save_Header header, + unsigned short *i_data) +{ + if (num_of_point == 0) + fprintf(obj_file, "f "); + + if (header.existence_of_normals) + { + if (header.existence_of_tex_coords) + fprintf(obj_file, "%hu/%hu/%hu ", i_data[num], + i_data[num + header.vertices_count], + i_data[num + 2 * header.vertices_count]); + else + fprintf(obj_file, "%hu//%hu ", i_data[num], + i_data[num + header.vertices_count]); + } + else + { + if (header.existence_of_tex_coords) + fprintf(obj_file, "%hu/%hu ", i_data[num], + i_data[num + header.vertices_count]); + else + fprintf(obj_file, "%hu ", i_data[num]); + } + + if (num_of_point == 2) + fprintf(obj_file, "\n"); +} + +static inline Eina_Bool +_write_obj_header(FILE *file, + const char *_mtl_file_name) { - Evas_Canvas3D_Vertex_Buffer *vb; time_t current_time; char* c_time_string; - int i; - float *src; - Eina_Bool existence_of_normal, existence_of_tex_point; - OPEN_FILE(obj) - if (!_obj_file) - { - ERR("File open '%s' for save failed", _obj_file_name); - return; - } - fprintf(_obj_file, "# Evas_3D saver OBJ v0.03 \n");//_obj_file created in macro - /* Adding time comment to .obj file. */ current_time = time(NULL); if (current_time == ((time_t)-1)) { ERR("Failure to compute the current time."); - fclose(_obj_file); - return; + return EINA_FALSE; } c_time_string = ctime(¤t_time); @@ -88,38 +73,117 @@ _save_mesh(Evas_Canvas3D_Mesh_Data *pd, const char *_obj_file_name, Evas_Canvas3 if (c_time_string == NULL) { ERR("Failure to convert the current time."); - fclose(_obj_file); - return; + return EINA_FALSE; } - fprintf(_obj_file,"# Current time is %s \n", c_time_string); - fprintf(_obj_file,"mtllib %s.mtl \n\n", _obj_file_name); + fprintf(file, "# Evas_Canvas3D saver OBJ v0.03 \n"); + fprintf(file, "# Current time is %s \n", c_time_string); + fprintf(file, "mtllib %s \n\n", _mtl_file_name); - /* Adding geometrics to file. */ - if (f == NULL) + return EINA_TRUE; +} + +static inline void +_write_obj_vertex_data(FILE *file, + Evas_Model_Load_Save_Header header, + Evas_Model_Load_Save_Data data, + unsigned short *i_data) +{ + int i, j; + int v = -1; + Eina_Stringshare *str, *cur_str, *cur_index; + unsigned short cur_hu; + + eina_init(); + Eina_Hash *vb; +#define WRITE_OBJ_VERTEX_DATA(name, num, format) \ + if (header.existence_of_##name) \ + { \ + cur_hu = 0; \ + v++; \ + vb = eina_hash_string_superfast_new(_vertex_data_free_cb); \ + for (i = 0; i < header.vertices_count; i++) \ + { \ + str = eina_stringshare_printf(" "); \ + for (j = 0; j < num; j++) \ + str = eina_stringshare_printf("%s %f", str, \ + data.name[i * num + j]); \ + cur_index = eina_hash_find(vb, str); \ + if (!cur_index) \ + { \ + cur_hu++; \ + cur_str = eina_stringshare_printf("%hu", cur_hu); \ + eina_hash_add(vb, str, cur_str); \ + i_data[v * header.vertices_count + i] = cur_hu; \ + fprintf(file, "%s%s\n", format, str); \ + } \ + else sscanf(cur_index, "%hu", \ + i_data + v * header.vertices_count + i); \ + } \ + eina_hash_free(vb); \ + } + WRITE_OBJ_VERTEX_DATA(positions, 3, "v") + WRITE_OBJ_VERTEX_DATA(tex_coords, 2, "vt") + WRITE_OBJ_VERTEX_DATA(normals, 3, "vn") +#undef WRITE_OBJ_VERTEX_DATA + eina_shutdown(); +} + +static inline void +_write_obj_index_data(FILE *file, + Evas_Model_Load_Save_Header header, + Evas_Model_Load_Save_Data data, + unsigned short *i_data) +{ + int i; + int ic; + ic = header.indices_count ? header.indices_count : header.vertices_count; + for (i = 0; i < ic; i++) + _write_point(file, data.indices[i], i % 3, header, i_data); +} + +static void +_save_mesh(Evas_Canvas3D_Mesh_Data *pd, + const char *_obj_file_name, + const char *_mtl_file_name, + Evas_Canvas3D_Mesh_Frame *f) +{ + Evas_Model_Load_Save_Header header; + Evas_Model_Load_Save_Data data; + unsigned short *index_data; + + if (!evas_model_save_header_from_mesh(pd, f, &header)) return; + + index_data = _init_obj_indices_data(header); + if (index_data == NULL) { - ERR("Not existing mesh frame."); - fclose(_obj_file); + ERR("Allocation of index data is failed."); return; } - SAVE_GEOMETRICS(EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION, "v %.4f %.4f") - SAVE_GEOMETRICS(EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL, "vn %.4f %.4f") - SAVE_GEOMETRICS(EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD, "vt %.4f %.4f") + evas_model_save_data_from_mesh(pd, f, header, &data); - existence_of_normal = (f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL].data != NULL); - existence_of_tex_point = (f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD].data != NULL); + FILE * _obj_file = fopen(_obj_file_name, "w+"); + if (!_obj_file) + { + ERR("File open '%s' for save failed", _obj_file_name); + free(index_data); + return; + } + if (!_write_obj_header(_obj_file, _mtl_file_name)) + { + fclose(_obj_file); + free(index_data); + return; + } + + _write_obj_vertex_data(_obj_file, header, data, index_data); fprintf(_obj_file,"usemtl Material\n s off\n"); - for (i = 1; i <= pd->vertex_count; i++)//numeration of faces in .obj started from 1 - { - _write_point(_obj_file, i, 1, existence_of_normal, existence_of_tex_point); - i++; - _write_point(_obj_file, i, 2, existence_of_normal, existence_of_tex_point); - i++; - _write_point(_obj_file, i, 3, existence_of_normal, existence_of_tex_point); - } + _write_obj_index_data(_obj_file, header, data, index_data); fclose(_obj_file); + free(index_data); + free(data.indices); } static void @@ -127,13 +191,13 @@ _save_material(Evas_Canvas3D_Mesh_Data *pd EINA_UNUSED, const char *_mtl_file_name, Evas_Canvas3D_Material_Data *mat) { - OPEN_FILE(mtl) + FILE * _mtl_file = fopen(_mtl_file_name, "w+"); if (!_mtl_file) { ERR("File open '%s' for save failed", _mtl_file_name); return; } - fprintf(_mtl_file, "# Evas_3D saver OBJ v0.03 \n");//_mtl_file created in macro + fprintf(_mtl_file, "# Evas_Canvas3D saver OBJ v0.03 \n");//_mtl_file created in macro fprintf(_mtl_file, "# Material Count: 1 \n\n"); fprintf(_mtl_file, "newmtl Material \n"); fprintf(_mtl_file, "Ns 1.000000 \n");//exp factor for specular highlight @@ -157,7 +221,9 @@ _save_material(Evas_Canvas3D_Mesh_Data *pd EINA_UNUSED, } void -evas_model_save_file_obj(const Evas_Canvas3D_Mesh *mesh, const char *_obj_file_name, Evas_Canvas3D_Mesh_Frame *f) +evas_model_save_file_obj(const Evas_Canvas3D_Mesh *mesh, + const char *_obj_file_name, + Evas_Canvas3D_Mesh_Frame *f) { int len; char *_mtl_file_name, *_without_extention; @@ -166,18 +232,15 @@ evas_model_save_file_obj(const Evas_Canvas3D_Mesh *mesh, const char *_obj_file_n len = strlen(_obj_file_name); _without_extention = (char *)malloc(len - 3); _mtl_file_name = (char *)malloc(len + 1); + eina_strlcpy(_without_extention, _obj_file_name, len - 3); + eina_str_join(_mtl_file_name, len + 1, '.', _without_extention, "mtl"); + free(_without_extention); Evas_Canvas3D_Mesh_Data *pd = eo_data_scope_get(mesh, EVAS_CANVAS3D_MESH_CLASS); - _save_mesh(pd, _obj_file_name, f); - mat = eo_data_scope_get(f->material, EVAS_CANVAS3D_MATERIAL_CLASS); - if (mat != NULL) - { - eina_strlcpy(_without_extention, _obj_file_name, len - 3); - eina_str_join(_mtl_file_name, len + 1, '.', _without_extention, "mtl"); - _save_material(pd, _mtl_file_name, mat); - } - free(_without_extention); + if (mat != NULL) _save_material(pd, _mtl_file_name, mat); + _save_mesh(pd, _obj_file_name, _mtl_file_name, f); + free(_mtl_file_name); } diff --git a/src/modules/evas/model_savers/ply/evas_model_save_ply.c b/src/modules/evas/model_savers/ply/evas_model_save_ply.c index 0be42f7f86..8da8f741ea 100644 --- a/src/modules/evas/model_savers/ply/evas_model_save_ply.c +++ b/src/modules/evas/model_savers/ply/evas_model_save_ply.c @@ -1,21 +1,80 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif +#include "evas_model_load_save_common.h" -#include -#include -#include "stdio.h" -#include "math.h" -#include "evas_common_private.h" -#include "evas_private.h" +static inline void +_write_ply_header(FILE *file, Evas_Model_Load_Save_Header header) +{ + const char *pf = "property float", *puc = "property uchar"; + fprintf(file, "ply\n" \ + "format ascii 1.0\n" \ + "comment Created by EFL evas_canvas3d_mesh_saver_ply.c version 2 " \ + "(sub 0) - www.enlightenment.org, source file: ''\n"); + fprintf(file, "element vertex %d\n", header.vertices_count); + + if (header.existence_of_positions) + fprintf(file, "%s x\n%s y\n%s z\n", pf, pf, pf); + if (header.existence_of_normals) + fprintf(file, "%s nx\n%s ny\n%s nz\n", pf, pf, pf); + if (header.existence_of_tex_coords) + fprintf(file, "%s s\n%s t\n", pf, pf); + if (header.existence_of_colors) + fprintf(file, "%s red\n%s green\n%s blue\n", puc, puc, puc); + + fprintf(file, "element face %d\n" \ + "property list uchar uint vertex_indices\n" \ + "end_header\n", header.indices_count / 3); +} + +static inline void +_write_ply_vertex_data(FILE *file, + Evas_Model_Load_Save_Header header, + Evas_Model_Load_Save_Data data) +{ + int i, j; + for (i = 0; i < header.vertices_count; i++) + { +#define WRITE_PLY_VERTEX_DATA(name, num)\ + if (header.existence_of_##name)\ + for (j = 0; j < num; j++, data.name++)\ + fprintf(file, "%f ", data.name[0]); + WRITE_PLY_VERTEX_DATA(positions, 3) + WRITE_PLY_VERTEX_DATA(normals, 3) + WRITE_PLY_VERTEX_DATA(tex_coords, 2) +#undef WRITE_PLY_VERTEX_DATA + + if (header.existence_of_colors) + { + for (j = 0; j < 3; j++, data.colors++) + fprintf(file, "%.0f ", round(data.colors[0] * 255)); + data.colors++; + } + fprintf(file, "\n"); + } +} + +static inline void +_write_ply_index_data(FILE *file, + Evas_Model_Load_Save_Header header, + Evas_Model_Load_Save_Data data) +{ + int i, triangles_count = header.indices_count / 3; + for (i = 0; i < triangles_count; i++, data.indices += 3) + fprintf(file, "3 %d %d %d\n", data.indices[0], + data.indices[1], + data.indices[2]); +} void -evas_model_save_file_ply(const Evas_Canvas3D_Mesh *mesh, const char *file, Evas_Canvas3D_Mesh_Frame *f) +evas_model_save_file_ply(const Evas_Canvas3D_Mesh *mesh, + const char *file, + Evas_Canvas3D_Mesh_Frame *f) { - float *src_pos, *src_nor, *src_tex, *src_col; - int i; + Evas_Model_Load_Save_Header header; + Evas_Model_Load_Save_Data data; Evas_Canvas3D_Mesh_Data *pd = eo_data_scope_get(mesh, EVAS_CANVAS3D_MESH_CLASS); + if (!evas_model_save_header_from_mesh(pd, f, &header)) return; + evas_model_save_data_from_mesh(pd, f, header, &data); + FILE *_ply_file = fopen(file, "w+"); if (!_ply_file) { @@ -23,40 +82,10 @@ evas_model_save_file_ply(const Evas_Canvas3D_Mesh *mesh, const char *file, Evas_ return; } - fprintf(_ply_file,"ply\nformat ascii 1.0\ncomment Created by EFL evas_canvas3d_mesh_saver_ply.c" \ - "version 1 (sub 0) - www.enlightenment.org, source file: ''\n"); - fprintf(_ply_file,"element vertex %d\n", pd->vertex_count); - fprintf(_ply_file,"property float x\nproperty float y\nproperty float z\n" \ - "property float nx\nproperty float ny\nproperty float nz\n" \ - "property float s\nproperty float t\n" \ - "property uchar red\nproperty uchar green\nproperty uchar blue\n"); - fprintf(_ply_file,"element face %d\nproperty list uchar uint vertex_indices\nend_header\n", - pd->index_count / 3); - - src_pos = (float*)(&f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION])->data; - src_nor = (float*)(&f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL])->data; - src_tex = (float*)(&f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD])->data; - src_col = (float*)(&f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_COLOR])->data; - - for (i = 0; i < pd->vertex_count; i++) - { - fprintf(_ply_file,"%f %f %f %f %f %f %f %f %.0f %.0f %.0f\n", - src_pos[0], src_pos[1], src_pos[2], - src_nor[0], src_nor[1], src_nor[2], - src_tex[0], src_tex[1], - round(src_col[0] * 255), round(src_col[1] * 255), round(src_col[2] * 255)); - src_pos += 3; - src_nor += 3; - src_tex += 2; - src_col += 4; - } - - unsigned short* indices = (unsigned short*) pd->indices; - - for (i = 0; i < pd->index_count / 3; i++) - { - fprintf(_ply_file,"3 %d %d %d\n", indices[3 * i], indices[3 * i + 1], indices[3 * i + 2]); - } + _write_ply_header(_ply_file, header); + _write_ply_vertex_data(_ply_file, header, data); + _write_ply_index_data(_ply_file, header, data); + free(data.indices); fclose(_ply_file); } diff --git a/src/tests/evas/evas_test_mesh.c b/src/tests/evas/evas_test_mesh.c index 34de08f514..7b88680a3e 100644 --- a/src/tests/evas/evas_test_mesh.c +++ b/src/tests/evas/evas_test_mesh.c @@ -16,22 +16,26 @@ #define TESTS_MD2_MESH_DIR TESTS_MESH_DIR"/md2" #define TESTS_PLY_MESH_DIR TESTS_MESH_DIR"/ply" -#define COMPARE_GEOMETRICS(a) \ - vb1 = &f1->vertices[a]; \ - vb2 = &f2->vertices[a]; \ - if ((vb1->data == NULL) || (vb2->data == NULL)) \ - return 1; \ - src1 = (float *)vb1->data; \ - src2 = (float *)vb2->data; \ - for (i = 0; i < pd1->vertex_count; i++) \ - { \ - if ((src1[0] != src2[0]) || (src1[1] != src2[1])) \ - return 1; \ - if (a != EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD) \ - if (src1[2] != src2[2]) \ - return 1; \ - src1 += f1->vertices[a].element_count; \ - src2 += f2->vertices[a].element_count; \ +#define COMPARE_GEOMETRICS(a) \ + vb1 = &f1->vertices[a]; \ + vb2 = &f2->vertices[a]; \ + if ((a == EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION) && \ + ((vb1->data == NULL) || (vb2->data == NULL))) \ + return 1; \ + if ((vb1->data != NULL) && (vb2->data != NULL)) \ + { \ + src1 = (float *)vb1->data; \ + src2 = (float *)vb2->data; \ + for (i = 0; i < pd1->vertex_count; i++) \ + { \ + if ((src1[0] != src2[0]) || (src1[1] != src2[1])) \ + return 1; \ + if (a != EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD) \ + if (src1[2] != src2[2]) \ + return 1; \ + src1 += f1->vertices[a].element_count; \ + src2 += f2->vertices[a].element_count; \ + } \ } #define CHECK_MESHES_IN_FOLDER(folder, ext) \