From 8ab190daec637892465f2c5ea08298b3fafc4e98 Mon Sep 17 00:00:00 2001 From: Bogdan Devichev Date: Mon, 9 Nov 2015 15:01:54 -0800 Subject: [PATCH] evas: add common part of savers and loaders. Summary: Common part will make savers and loaders shorter and easier for understanding and refactoring. https://phab.enlightenment.org/T2713 - due to this task. Should be merged after https://phab.enlightenment.org/D3030 Should be merged to start adding refactored savers and loaders. Reviewers: Hermet, raster, Oleksander, cedric Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D3038 Signed-off-by: Cedric BAIL --- src/Makefile_Evas.am | 2 + .../evas/common3d/save_load/evas_model_common.c | 236 +++++++++++++++++++++ .../evas/common3d/save_load/evas_model_common.h | 62 ++++++ 3 files changed, 300 insertions(+) create mode 100644 src/lib/evas/common3d/save_load/evas_model_common.c create mode 100644 src/lib/evas/common3d/save_load/evas_model_common.h diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 825a987..b94ac1f 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -223,6 +223,7 @@ 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 \ 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 \ @@ -341,6 +342,7 @@ lib_evas_libevas_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ -I$(top_srcdir)/src/lib/evas/canvas \ -I$(top_srcdir)/src/lib/evas/canvas/render2 \ -I$(top_srcdir)/src/lib/evas/common \ +-I$(top_srcdir)/src/lib/evas/common3d/save_load \ -I$(top_srcdir)/src/lib/evas/cserve2 \ -I$(top_srcdir)/src/lib/evas/file \ -I$(top_srcdir)/src/lib/evas/include \ diff --git a/src/lib/evas/common3d/save_load/evas_model_common.c b/src/lib/evas/common3d/save_load/evas_model_common.c new file mode 100644 index 0000000..612bccd --- /dev/null +++ b/src/lib/evas/common3d/save_load/evas_model_common.c @@ -0,0 +1,236 @@ +#include "evas_model_common.h" + +# define SAVE_MESH_INDICES_COPY \ + if (header.indices_count) \ + { \ + data->indices = malloc(header.indices_count \ + * sizeof(unsigned short)); \ + if (pd->index_format == EVAS_CANVAS3D_INDEX_FORMAT_UNSIGNED_BYTE) \ + { \ + for (i = 0; i < header.indices_count; i++) \ + data->indices[i] = ((unsigned char*)(pd->indices))[i]; \ + } \ + else \ + { \ + for (i = 0; i < header.indices_count; i++) \ + data->indices[i] = ((unsigned short*)(pd->indices))[i]; \ + } \ + } \ + else \ + { \ + data->indices = malloc(header.vertices_count * 3 \ + * sizeof(unsigned short)); \ + for (i = 0; i < header.vertices_count * 3; i++) \ + data->indices[i] = (unsigned short)i; \ + } + +/* create new header */ +Evas_Model_Load_Save_Header +evas_model_load_save_header_new() +{ + Evas_Model_Load_Save_Header header; + + header.vertices_count = 0; + header.indices_count = 0; + header.existence_of_positions = EINA_FALSE; + header.existence_of_normals = EINA_FALSE; + header.existence_of_tex_coords = EINA_FALSE; + header.existence_of_colors = EINA_FALSE; + + return header; +} + +void +evas_model_load_vertex_data_unmap(Evas_Canvas3D_Mesh *mesh, + int frame, + Evas_Model_Load_Save_Header header) +{ +#define UNMAP_IF_EXIST(existence, vertex_data_type) \ + if (existence) \ + { \ + eo_do(mesh, \ + evas_canvas3d_mesh_frame_vertex_data_unmap(frame, \ + vertex_data_type)); \ + } + UNMAP_IF_EXIST(header.existence_of_positions, EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION) + UNMAP_IF_EXIST(header.existence_of_normals, EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL) + UNMAP_IF_EXIST(header.existence_of_tex_coords, EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD) + UNMAP_IF_EXIST(header.existence_of_colors, EVAS_CANVAS3D_VERTEX_ATTRIB_COLOR) +#undef UNMAP_IF_EXIST +} + +void +evas_model_load_save_data_free(Evas_Model_Load_Save_Header header, + Evas_Model_Load_Save_Data *data) +{ + if (header.existence_of_positions) free(data->positions); + if (header.existence_of_normals) free(data->normals); + if (header.existence_of_tex_coords) free(data->tex_coords); + if (header.existence_of_colors) free(data->colors); + free(data->indices); +} + +void +evas_model_load_vertex_data_to_mesh(Evas_Canvas3D_Mesh *mesh, + Evas_Model_Load_Save_Header header, + Evas_Model_Load_Save_Data data, + Evas_Model_Load_Save_Stride *stride) +{ + Evas_Model_Load_Save_Data map; + int i, j; + + 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)); + +#define VERTEX_DATA_MAP(name, vertex_data_type, default_size) \ + if (header.existence_of_##name) \ + { \ + eo_do(mesh, \ + evas_canvas3d_mesh_frame_vertex_data_copy_set(0, vertex_data_type, 0, NULL), \ + map.name = (float *)evas_canvas3d_mesh_frame_vertex_data_map(0, vertex_data_type), \ + stride->name = evas_canvas3d_mesh_frame_vertex_stride_get(0, vertex_data_type)); \ + if (stride->name == 0) stride->name = sizeof(float) * default_size; \ + } + VERTEX_DATA_MAP(positions, EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION, 3) + VERTEX_DATA_MAP(normals, EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL, 3) + VERTEX_DATA_MAP(tex_coords, EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD, 2) + VERTEX_DATA_MAP(colors, EVAS_CANVAS3D_VERTEX_ATTRIB_COLOR, 4) +#undef VERTEX_DATA_MAP + + for (i = 0; i < header.vertices_count; i++) + { + Evas_Model_Load_Save_Data current_pointer; + +#define FILL_VERTEX_DATA(name, size) \ + if (header.existence_of_##name) \ + { \ + current_pointer.name = (float *)((char *)map.name + stride->name * i); \ + for (j = 0; j < size; j++) \ + current_pointer.name[j] = ARRAY_2D(data.name, i, j, size); \ + } + FILL_VERTEX_DATA(positions, 3) + FILL_VERTEX_DATA(normals, 3) + FILL_VERTEX_DATA(tex_coords, 2) + FILL_VERTEX_DATA(colors, 3) +#undef FILL_VERTEX_DATA + + if (header.existence_of_colors) current_pointer.colors[3] = 1.0; + } +} + +void +evas_model_load_indices_data_to_mesh(Evas_Canvas3D_Mesh *mesh, + Evas_Model_Load_Save_Header header, + Evas_Model_Load_Save_Data data) +{ + eo_do(mesh, + evas_canvas3d_mesh_index_data_copy_set(EVAS_CANVAS3D_INDEX_FORMAT_UNSIGNED_SHORT, + header.indices_count, + data.indices)); +} + +Eina_Bool +evas_model_load_allocate_data_due_to_header(Evas_Model_Load_Save_Header header, + Evas_Model_Load_Save_Data *data) +{ + if (header.existence_of_positions) + data->positions = malloc(header.vertices_count * 3 * sizeof(float)); + if (header.existence_of_normals) + data->normals = malloc(header.vertices_count * 3 * sizeof(float)); + if (header.existence_of_tex_coords) + data->tex_coords = malloc(header.vertices_count * 2 * sizeof(float)); + if (header.existence_of_colors) + data->colors = malloc(header.vertices_count * 3 * sizeof(float)); + data->indices = malloc(header.indices_count * sizeof(unsigned short)); + + if ((header.existence_of_positions && (data->positions == NULL)) || + (header.existence_of_normals && (data->normals == NULL)) || + (header.existence_of_tex_coords && (data->tex_coords == NULL)) || + (header.existence_of_colors && (data->colors == NULL)) || + (data->indices == NULL)) + { + free(data->positions); + free(data->normals); + free(data->tex_coords); + free(data->colors); + free(data->indices); + return EINA_FALSE; + } + return EINA_TRUE; +} + +void +evas_model_load_aabb_add_to_frame(Evas_Canvas3D_Mesh *mesh, + int frame, + Evas_Model_Load_Save_Stride stride) +{ + Evas_Canvas3D_Mesh_Data *pd; + pd = eo_data_scope_get(mesh, EVAS_CANVAS3D_MESH_CLASS); + + if (!evas_canvas3d_mesh_aabb_add_to_frame(pd, frame, stride.positions)) + { + ERR("Axis-Aligned Bounding Box wan't added in frame %d ", 0); + } +} + +Eina_Bool +evas_model_save_header_from_mesh(Evas_Canvas3D_Mesh_Data *pd, + Evas_Canvas3D_Mesh_Frame *f, + Evas_Model_Load_Save_Header *header) +{ + header->indices_count = pd->index_count; + if (header->indices_count % 3 != 0) + { + printf("Index count is %d. It cannot be divided to triangles correctly.\n", + header->indices_count); + return EINA_FALSE; + } + + header->existence_of_positions = (f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION].data != NULL); + header->existence_of_normals = (f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL].data != NULL); + header->existence_of_tex_coords = (f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD].data != NULL); + header->existence_of_colors = (f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_COLOR].data != NULL); + header->vertices_count = pd->vertex_count; + + return EINA_TRUE; +} + +void +evas_model_save_data_from_mesh(Evas_Canvas3D_Mesh_Data *pd, + Evas_Canvas3D_Mesh_Frame *f, + Evas_Model_Load_Save_Header header, + Evas_Model_Load_Save_Data *data) +{ + int i; + if (header.existence_of_positions) + data->positions = (float*)(&f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION])->data; + if (header.existence_of_normals) + data->normals = (float*)(&f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL])->data; + if (header.existence_of_tex_coords) + data->tex_coords = (float*)(&f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD])->data; + if (header.existence_of_colors) + data->colors = (float*)(&f->vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_COLOR])->data; + SAVE_MESH_INDICES_COPY +} + +void +evas_model_save_data_copy_from_mesh(Evas_Canvas3D_Mesh_Data *pd, + Evas_Canvas3D_Mesh_Frame *f, + Evas_Model_Load_Save_Header header, + Evas_Model_Load_Save_Data *data) +{ + int i; +#define SAVE_MESH_VERTICES_COPY(name, vertex_data_type) \ + if (header.existence_of_##name) \ + memcpy(data->name, \ + (&f->vertices[vertex_data_type])->data, \ + header.vertices_count); + SAVE_MESH_VERTICES_COPY(positions, EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION) + SAVE_MESH_VERTICES_COPY(normals, EVAS_CANVAS3D_VERTEX_ATTRIB_NORMAL) + SAVE_MESH_VERTICES_COPY(tex_coords, EVAS_CANVAS3D_VERTEX_ATTRIB_TEXCOORD) + SAVE_MESH_VERTICES_COPY(colors, EVAS_CANVAS3D_VERTEX_ATTRIB_COLOR) +#undef SAVE_MESH_VERTICES_COPY + SAVE_MESH_INDICES_COPY +} diff --git a/src/lib/evas/common3d/save_load/evas_model_common.h b/src/lib/evas/common3d/save_load/evas_model_common.h new file mode 100644 index 0000000..bda8419 --- /dev/null +++ b/src/lib/evas/common3d/save_load/evas_model_common.h @@ -0,0 +1,62 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef MODEL_LOAD_COMMON +#define MODEL_LOAD_COMMON + +#include +#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 _Evas_Model_Load_Save_Header Evas_Model_Load_Save_Header; +typedef struct _Evas_Model_Load_Save_Data Evas_Model_Load_Save_Data; +typedef struct _Evas_Model_Load_Save_Stride Evas_Model_Load_Save_Stride; + +struct _Evas_Model_Load_Save_Header +{ + int vertices_count; + int indices_count; + Eina_Bool existence_of_positions; + Eina_Bool existence_of_normals; + Eina_Bool existence_of_tex_coords; + Eina_Bool existence_of_colors; +}; + +struct _Evas_Model_Load_Save_Data +{ + float *positions; + float *normals; + float *tex_coords; + float *colors; + unsigned short *indices; +}; + +struct _Evas_Model_Load_Save_Stride +{ + int positions; + int normals; + int tex_coords; + int colors; +}; + +/* create new header */ +Evas_Model_Load_Save_Header evas_model_load_save_header_new(); +void evas_model_load_vertex_data_unmap(Evas_Canvas3D_Mesh *mesh, int frame, Evas_Model_Load_Save_Header header); +void evas_model_load_save_data_free(Evas_Model_Load_Save_Header header, Evas_Model_Load_Save_Data *data); +void evas_model_load_vertex_data_to_mesh(Evas_Canvas3D_Mesh *mesh, Evas_Model_Load_Save_Header header, Evas_Model_Load_Save_Data data, Evas_Model_Load_Save_Stride *stride); +void evas_model_load_indices_data_to_mesh(Evas_Canvas3D_Mesh *mesh, Evas_Model_Load_Save_Header header, Evas_Model_Load_Save_Data data); +Eina_Bool evas_model_load_allocate_data_due_to_header(Evas_Model_Load_Save_Header header, Evas_Model_Load_Save_Data *data); +void evas_model_load_aabb_add_to_frame(Evas_Canvas3D_Mesh *mesh, int frame, Evas_Model_Load_Save_Stride stride); +Eina_Bool evas_model_save_header_from_mesh(Evas_Canvas3D_Mesh_Data *pd, Evas_Canvas3D_Mesh_Frame *f, Evas_Model_Load_Save_Header *header); +void evas_model_save_data_from_mesh(Evas_Canvas3D_Mesh_Data *pd, Evas_Canvas3D_Mesh_Frame *f, Evas_Model_Load_Save_Header header, Evas_Model_Load_Save_Data *data); +void evas_model_save_data_copy_from_mesh(Evas_Canvas3D_Mesh_Data *pd, Evas_Canvas3D_Mesh_Frame *f, Evas_Model_Load_Save_Header header, Evas_Model_Load_Save_Data *data); + +#endif //MODEL_LOAD_COMMON -- 2.7.4