forked from enlightenment/efl
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) Reviewers: cedric, raster, Hermet Subscribers: artem.popov Differential Revision: https://phab.enlightenment.org/D3373
This commit is contained in:
parent
c421e519b0
commit
32c33ed64d
|
@ -224,8 +224,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 \
|
||||
lib/evas/common3d/save_load/evas_model_common.h \
|
||||
lib/evas/common3d/save_load/evas_model_load_save_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 \
|
||||
|
|
|
@ -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) \
|
|
@ -128,5 +128,3 @@ evas_model_load_file_eet(Evas_Canvas3D_Mesh *mesh, Eina_File *file)
|
|||
|
||||
_evas_canvas3d_eet_file_free();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,44 +1,4 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "stdio.h"
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
#include <Eina.h>
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
|
|
@ -192,4 +192,3 @@ evas_model_save_file_eet(const Evas_Canvas3D_Mesh *mesh,
|
|||
|
||||
_evas_canvas3d_eet_file_free();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,86 +1,71 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include "evas_model_load_save_common.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "stdio.h"
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
static unsigned short*
|
||||
_init_obj_indices_data(Evas_Model_Load_Save_Header header)
|
||||
{
|
||||
unsigned short *i_data;
|
||||
int i = 0;
|
||||
|
||||
#define OPEN_FILE(extension)\
|
||||
FILE * _##extension##_file = fopen(_##extension##_file_name, "w+");
|
||||
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));
|
||||
|
||||
#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; \
|
||||
} \
|
||||
return i_data;
|
||||
}
|
||||
|
||||
static void
|
||||
_vertex_data_free_cb(void *data)
|
||||
{
|
||||
eina_stringshare_del(data);
|
||||
}
|
||||
|
||||
static void
|
||||
_write_point(FILE *obj_file,
|
||||
int num,
|
||||
int num_of_point,
|
||||
Eina_Bool existence_of_normal,
|
||||
Eina_Bool existence_of_tex_point)
|
||||
Evas_Model_Load_Save_Header header,
|
||||
unsigned short *i_data)
|
||||
{
|
||||
if (num_of_point == 1)
|
||||
if (num_of_point == 0)
|
||||
fprintf(obj_file, "f ");
|
||||
|
||||
if (existence_of_normal)
|
||||
if (header.existence_of_normals)
|
||||
{
|
||||
if (existence_of_tex_point)
|
||||
fprintf(obj_file, "%i/%i/%i ", num, num, num);
|
||||
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, "%i//%i ", num, num);
|
||||
fprintf(obj_file, "%hu//%hu ", i_data[num],
|
||||
i_data[num + header.vertices_count]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (existence_of_tex_point)
|
||||
fprintf(obj_file, "%i/%i ", num, num);
|
||||
if (header.existence_of_tex_coords)
|
||||
fprintf(obj_file, "%hu/%hu ", i_data[num],
|
||||
i_data[num + header.vertices_count]);
|
||||
else
|
||||
fprintf(obj_file, "%i ", num);
|
||||
fprintf(obj_file, "%hu ", i_data[num]);
|
||||
}
|
||||
|
||||
if (num_of_point == 3)
|
||||
if (num_of_point == 2)
|
||||
fprintf(obj_file, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
_save_mesh(Evas_Canvas3D_Mesh_Data *pd, const char *_obj_file_name, Evas_Canvas3D_Mesh_Frame *f)
|
||||
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)
|
||||
{
|
||||
ERR("Not existing mesh frame.");
|
||||
fclose(_obj_file);
|
||||
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("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);
|
||||
|
||||
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);
|
||||
|
||||
Evas_Canvas3D_Mesh_Data *pd = eo_data_scope_get(mesh, EVAS_CANVAS3D_MESH_CLASS);
|
||||
mat = eo_data_scope_get(f->material, EVAS_CANVAS3D_MATERIAL_CLASS);
|
||||
|
||||
if (mat != NULL) _save_material(pd, _mtl_file_name, mat);
|
||||
_save_mesh(pd, _obj_file_name, _mtl_file_name, f);
|
||||
|
||||
free(_mtl_file_name);
|
||||
}
|
||||
|
|
|
@ -1,21 +1,80 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include "evas_model_load_save_common.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue