Revert "evas: refactor model's savers and loaders."

This reverts commit 32c33ed64d.

This refactor broke the evas test cases for the model loaders and savers. I gave
it a week to get fixed but a first try did not succeed and its blocks a lot of
other automated testing. To be honest, it should have never gone it when it
breaks existing test cases. Once fixed this refactor can happily go in.

Fixes T2905
This commit is contained in:
Stefan Schmidt 2015-12-08 22:23:17 +01:00
parent 842a75423f
commit 96a9d75e0c
8 changed files with 392 additions and 319 deletions

View File

@ -224,7 +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_load_save_common.c \
lib/evas/common3d/save_load/evas_model_common.c \
lib/evas/common3d/save_load/evas_model_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 \

View File

@ -1,4 +1,4 @@
#include "evas_model_load_save_common.h"
#include "evas_model_common.h"
# define SAVE_MESH_INDICES_COPY \
if (header.indices_count) \

View File

@ -128,3 +128,5 @@ evas_model_load_file_eet(Evas_Canvas3D_Mesh *mesh, Eina_File *file)
_evas_canvas3d_eet_file_free();
}

View File

@ -1,4 +1,44 @@
#include "evas_model_load_save_common.h"
#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;
}
static inline char *
_to_next_line(char *current)
@ -41,8 +81,8 @@ _read_data(float *array, int place, int count, char *current, float divider)
return current;
}
static inline Eina_Bool
_read_ply_header(char *map, Evas_Model_Load_Save_Header *header)
static inline PLY_Header
_read_header(char *map)//Check properties of mesh in .ply file.
{
eina_init();
@ -50,29 +90,30 @@ _read_ply_header(char *map, Evas_Model_Load_Save_Header *header)
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 EINA_FALSE;
return header;
}
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 EINA_FALSE;
return header;
}
current = helping_pointer[1];
vertex_lines = header->vertices_count;
vertex_lines = header.vertices_count;
while (*current != '\0')
{
if (vertex_lines == 1)
@ -98,7 +139,8 @@ _read_ply_header(char *map, Evas_Model_Load_Save_Header *header)
current++;
}
header->indices_count = 3 * triangles;
header.triangles_count = triangles;
free(helping_pointer);
/* analyse flags used when file was saved in blender */
helping_pointer = eina_str_split(map, "property float ", 0);
@ -106,124 +148,243 @@ _read_ply_header(char *map, Evas_Model_Load_Save_Header *header)
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 return EINA_FALSE;
header.existence_of_geometries = EINA_TRUE;
else return header;
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_tex_coords = EINA_TRUE;
header.existence_of_texcoords = 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;
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;
}
header.existence_of_colors = EINA_TRUE;
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);
}
return header;
}
void
evas_model_load_file_ply(Evas_Canvas3D_Mesh *mesh, Eina_File *file)
{
char *current = NULL, *map = NULL;
Evas_Model_Load_Save_Header header;
Evas_Model_Load_Save_Data data;
Evas_Model_Load_Save_Stride stride;
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;
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)) return;
header = _read_header(map);
if (!evas_model_load_allocate_data_due_to_header(header, &data))
if (!header.existence_of_geometries)
{
ERR("Memory allocation is failed.");
ERR("File have not x, y, or z field as the first 3 float fields. They are necessary.");
return;
}
current = eina_str_split(map, "end_header\n", 0)[1];
_read_ply_vertex_data(header, &current, data);
_read_ply_indices_data(header, &current, 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);
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);
}
if (map)
{
eina_file_map_free(file, map);
map = NULL;
}
evas_model_load_save_data_free(header, &data);
}

View File

@ -192,3 +192,4 @@ evas_model_save_file_eet(const Evas_Canvas3D_Mesh *mesh,
_evas_canvas3d_eet_file_free();
}

View File

@ -1,71 +1,86 @@
#include "evas_model_load_save_common.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
static unsigned short*
_init_obj_indices_data(Evas_Model_Load_Save_Header header)
{
unsigned short *i_data;
int i = 0;
#include <stdlib.h>
#include <time.h>
#include "stdio.h"
#include "evas_common_private.h"
#include "evas_private.h"
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 OPEN_FILE(extension)\
FILE * _##extension##_file = fopen(_##extension##_file_name, "w+");
return i_data;
}
#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
_vertex_data_free_cb(void *data)
{
eina_stringshare_del(data);
}
static void
_write_point(FILE *obj_file,
_write_point(FILE * obj_file,
int num,
int num_of_point,
Evas_Model_Load_Save_Header header,
unsigned short *i_data)
Eina_Bool existence_of_normal,
Eina_Bool existence_of_tex_point)
{
if (num_of_point == 0)
if (num_of_point == 1)
fprintf(obj_file, "f ");
if (header.existence_of_normals)
if (existence_of_normal)
{
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]);
if (existence_of_tex_point)
fprintf(obj_file, "%i/%i/%i ", num, num, num);
else
fprintf(obj_file, "%hu//%hu ", i_data[num],
i_data[num + header.vertices_count]);
fprintf(obj_file, "%i//%i ", num, num);
}
else
{
if (header.existence_of_tex_coords)
fprintf(obj_file, "%hu/%hu ", i_data[num],
i_data[num + header.vertices_count]);
if (existence_of_tex_point)
fprintf(obj_file, "%i/%i ", num, num);
else
fprintf(obj_file, "%hu ", i_data[num]);
fprintf(obj_file, "%i ", num);
}
if (num_of_point == 2)
if (num_of_point == 3)
fprintf(obj_file, "\n");
}
static inline Eina_Bool
_write_obj_header(FILE *file,
const char *_mtl_file_name)
static void
_save_mesh(Evas_Canvas3D_Mesh_Data *pd, const char *_obj_file_name, Evas_Canvas3D_Mesh_Frame *f)
{
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.");
return EINA_FALSE;
fclose(_obj_file);
return;
}
c_time_string = ctime(&current_time);
@ -73,117 +88,38 @@ _write_obj_header(FILE *file,
if (c_time_string == NULL)
{
ERR("Failure to convert the current time.");
return EINA_FALSE;
}
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);
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("Allocation of index data is failed.");
return;
}
evas_model_save_data_from_mesh(pd, f, header, &data);
FILE * _obj_file = fopen(_obj_file_name, "wb+");
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,"# Current time is %s \n", c_time_string);
fprintf(_obj_file,"mtllib %s.mtl \n\n", _obj_file_name);
/* Adding geometrics to file. */
if (f == NULL)
{
ERR("Not existing mesh frame.");
fclose(_obj_file);
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")
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);
fprintf(_obj_file,"usemtl Material\n s off\n");
_write_obj_index_data(_obj_file, header, data, index_data);
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);
}
fclose(_obj_file);
free(index_data);
free(data.indices);
}
static void
@ -191,13 +127,13 @@ _save_material(Evas_Canvas3D_Mesh_Data *pd EINA_UNUSED,
const char *_mtl_file_name,
Evas_Canvas3D_Material_Data *mat)
{
FILE * _mtl_file = fopen(_mtl_file_name, "wb+");
OPEN_FILE(mtl)
if (!_mtl_file)
{
ERR("File open '%s' for save failed", _mtl_file_name);
return;
}
fprintf(_mtl_file, "# Evas_Canvas3D saver OBJ v0.03 \n");//_mtl_file created in macro
fprintf(_mtl_file, "# Evas_3D 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
@ -221,9 +157,7 @@ _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;
@ -232,15 +166,18 @@ evas_model_save_file_obj(const Evas_Canvas3D_Mesh *mesh,
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);
}
if (mat != NULL) _save_material(pd, _mtl_file_name, mat);
_save_mesh(pd, _obj_file_name, _mtl_file_name, f);
free(_without_extention);
free(_mtl_file_name);
}

View File

@ -1,91 +1,62 @@
#include "evas_model_load_save_common.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
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]);
}
#include <stdlib.h>
#include <time.h>
#include "stdio.h"
#include "math.h"
#include "evas_common_private.h"
#include "evas_private.h"
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)
{
Evas_Model_Load_Save_Header header;
Evas_Model_Load_Save_Data data;
float *src_pos, *src_nor, *src_tex, *src_col;
int i;
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, "wb+");
FILE *_ply_file = fopen(file, "w+");
if (!_ply_file)
{
ERR("File open '%s' for save failed", file);
return;
}
_write_ply_header(_ply_file, header);
_write_ply_vertex_data(_ply_file, header, data);
_write_ply_index_data(_ply_file, header, data);
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]);
}
free(data.indices);
fclose(_ply_file);
}