evas: Evas_3D - add .ply export/import.

Summary:
.ply format is important for relation blender and EFl, because in blender exist only two mesh export API: bpy.ops.import_mesh.ply and bpy.ops.import_mesh.stl. One of them is necessary for .edc 3D generator. Which I writing now.
Sorry, it isn't like image loader. Refactoring of import/export will be soon.

Reviewers: Oleksander, artem.popov, Hermet, raster, cedric

Reviewed By: cedric

Subscribers: cedric

Differential Revision: https://phab.enlightenment.org/D1544

Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
Bogdan Devichev 2014-11-14 07:11:09 +01:00 committed by Cedric BAIL
parent c59fba68de
commit d896dfb342
26 changed files with 27648 additions and 56 deletions

View File

@ -194,7 +194,9 @@ lib/evas/canvas/evas_3d_mesh_loader_obj.c \
lib/evas/canvas/evas_3d_mesh_saver_obj.c \
lib/evas/canvas/evas_3d_mesh_loader_eet.c \
lib/evas/canvas/evas_3d_mesh_saver_eet.c \
lib/evas/canvas/evas_3d_eet.c
lib/evas/canvas/evas_3d_eet.c \
lib/evas/canvas/evas_3d_mesh_loader_ply.c \
lib/evas/canvas/evas_3d_mesh_saver_ply.c
# Engine
lib_evas_libevas_la_SOURCES += \

View File

@ -208,6 +208,11 @@ evas_3d_eet_SOURCES = evas-3d-eet.c
evas_3d_eet_LDADD = $(ECORE_EVAS_COMMON_LDADD) @EFL_PTHREAD_LIBS@
evas_3d_eet_CPPFLAGS = $(ECORE_EVAS_COMMON_CPPFLAGS)
EXTRA_PROGRAMS += evas_3d_ply
evas_3d_ply_SOURCES = evas-3d-ply.c
evas_3d_ply_LDADD = $(ECORE_EVAS_COMMON_LDADD) @EFL_PTHREAD_LIBS@
evas_3d_ply_CPPFLAGS = $(ECORE_EVAS_COMMON_CPPFLAGS)
EXTRA_PROGRAMS += evas_3d_frustum
evas_3d_frustum_SOURCES = evas-3d-frustum.c
evas_3d_frustum_LDADD = $(ECORE_EVAS_COMMON_LDADD) @EFL_PTHREAD_LIBS@

View File

@ -0,0 +1,249 @@
/**
* Simple Evas example illustrating import/export of .ply format.
*
* Read meshes from "tested_man_all_with_mods.ply", "tested_man_only_geometry.ply" and "tested_man_without_UVs.ply".
* After that cheange some properties of material.
* After that save material to "saved_man.mtl"
* and geometry to "saved_man_all_with_mods.ply", "saved_man_only_geometry.ply" and "saved_man_without_UVs.ply".
*
* @verbatim
* gcc -o evas-3d-ply evas-3d-ply.c `pkg-config --libs --cflags evas ecore ecore-evas eo`
* @endverbatim
*/
#define EFL_EO_API_SUPPORT
#define EFL_BETA_API_SUPPORT
#include <Eo.h>
#include <Evas.h>
#include <Ecore.h>
#include <Ecore_Evas.h>
#define WIDTH 1024
#define HEIGHT 1024
#define NUMBER_OF_MESHES 32
int draw_mode[2] = {EVAS_3D_SHADE_MODE_PHONG, EVAS_3D_SHADE_MODE_VERTEX_COLOR};
Ecore_Evas *ecore_evas = NULL;
Evas *evas = NULL;
Eo *background = NULL;
Eo *image = NULL;
Eo *scene = NULL;
Eo *root_node = NULL;
Eo *camera_node = NULL;
Eo *light_node = NULL;
Eo *camera = NULL;
Eo *mesh_node[NUMBER_OF_MESHES];
Eo *mesh[NUMBER_OF_MESHES];
Eo *material = NULL;
Eo *texture = NULL;
Eo *light = NULL;
Ecore_Animator *anim = NULL;
char *folder = "ply_files";
char *path_file[8] = {"ply_files/Normal_UVs_Colors.ply",
"ply_files/Normal_UVs_NoColors.ply",
"ply_files/Normal_NoUVs_Colors.ply",
"ply_files/Normal_NoUVs_NoColors.ply",
"ply_files/NoNormal_UVs_Colors.ply",
"ply_files/NoNormal_UVs_NoColors.ply",
"ply_files/NoNormal_NoUVs_Colors.ply",
"ply_files/NoNormal_NoUVs_NoColors.ply"};
char *file_name[8] = {"Normal_UVs_Colors.ply",
"Normal_UVs_NoColors.ply",
"Normal_NoUVs_Colors.ply",
"Normal_NoUVs_NoColors.ply",
"NoNormal_UVs_Colors.ply",
"NoNormal_UVs_NoColors.ply",
"NoNormal_NoUVs_Colors.ply",
"NoNormal_NoUVs_NoColors.ply"};
static float angle = 0;
static Eina_Bool
_animate_scene(void *data)
{
angle += 0.5;
eo_do((Evas_3D_Node *)data, evas_3d_node_orientation_angle_axis_set(angle, 1.0, 1.0, 1.0));
/* Rotate */
if (angle > 360.0) angle -= 360.0f;
return EINA_TRUE;
}
static void
_on_delete(Ecore_Evas *ee EINA_UNUSED)
{
ecore_main_loop_quit();
}
static void
_on_canvas_resize(Ecore_Evas *ee)
{
int w, h;
ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
eo_do(background, evas_obj_size_set(w, h));
eo_do(image, evas_obj_size_set(w, h));
}
int
main(void)
{
char buffer[PATH_MAX];
int i;
for (i = 0; i < NUMBER_OF_MESHES; i++)
{
mesh_node[i] = NULL;
mesh[i] = NULL;
}
//Unless Evas 3D supports Software renderer, we set gl backened forcely.
setenv("ECORE_EVAS_ENGINE", "opengl_x11", 1);
if (!ecore_evas_init()) return 0;
ecore_evas = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
if (!ecore_evas) return 0;
ecore_evas_callback_delete_request_set(ecore_evas, _on_delete);
ecore_evas_callback_resize_set(ecore_evas, _on_canvas_resize);
ecore_evas_show(ecore_evas);
evas = ecore_evas_get(ecore_evas);
/* Add a scene object .*/
scene = eo_add(EVAS_3D_SCENE_CLASS, evas);
/* Add the root node for the scene. */
root_node = eo_add(EVAS_3D_NODE_CLASS, evas,
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_NODE));
/* Add the camera. */
camera = eo_add(EVAS_3D_CAMERA_CLASS, evas);
eo_do(camera,
evas_3d_camera_projection_perspective_set(60.0, 1.0, 1.0, 500.0));
camera_node = eo_add(EVAS_3D_NODE_CLASS, evas,
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_CAMERA));
eo_do(camera_node,
evas_3d_node_camera_set(camera));
eo_do(root_node,
evas_3d_node_member_add(camera_node));
eo_do(camera_node,
evas_3d_node_position_set(200.0, 0.0, 0.0),
evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 0.0,
EVAS_3D_SPACE_PARENT, 0.0, 0.0, 1.0));
/* Add the light. */
light = eo_add(EVAS_3D_LIGHT_CLASS, evas);
eo_do(light,
evas_3d_light_ambient_set(1.0, 1.0, 1.0, 1.0),
evas_3d_light_diffuse_set(1.0, 1.0, 1.0, 1.0),
evas_3d_light_specular_set(1.0, 1.0, 1.0, 1.0),
evas_3d_light_directional_set(EINA_TRUE));
light_node = eo_add(EVAS_3D_NODE_CLASS, evas,
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_LIGHT));
eo_do(light_node,
evas_3d_node_light_set(light),
evas_3d_node_position_set(1000.0, 0.0, 1000.0),
evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 0.0,
EVAS_3D_SPACE_PARENT, 0.0, 1.0, 0.0));
eo_do(root_node,
evas_3d_node_member_add(light_node));
material = eo_add(EVAS_3D_MATERIAL_CLASS, evas);
texture = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
eo_do(texture,
evas_3d_texture_file_set("indian_DIFF3.png", NULL),
evas_3d_texture_filter_set(EVAS_3D_TEXTURE_FILTER_NEAREST,
EVAS_3D_TEXTURE_FILTER_NEAREST),
evas_3d_texture_wrap_set(EVAS_3D_WRAP_MODE_REPEAT,
EVAS_3D_WRAP_MODE_REPEAT));
eo_do(material,
evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, texture),
evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
evas_3d_material_enable_set(EVAS_3D_MATERIAL_NORMAL, EINA_TRUE),
evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT,
0.01, 0.01, 0.01, 1.0),
evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE,
1.0, 1.0, 1.0, 1.0),
evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR,
1.0, 1.0, 1.0, 1.0),
evas_3d_material_shininess_set(50.0));
/* Add the meshes. */
for (i = 0; i < NUMBER_OF_MESHES; i++)
{
mesh[i] = eo_add(EVAS_3D_MESH_CLASS, evas);
eo_do(mesh[i],
evas_3d_mesh_file_set(EVAS_3D_MESH_FILE_TYPE_PLY, path_file[i % 8], NULL),
evas_3d_mesh_frame_material_set(0, material),
evas_3d_mesh_shade_mode_set(draw_mode[(i % 16) / 8]));
snprintf(buffer, PATH_MAX, "%s/Saved_%s", folder, file_name[i % 8]);
eo_do(mesh[i], evas_3d_mesh_save(EVAS_3D_MESH_FILE_TYPE_PLY, buffer, NULL));
if (i > 15)
eo_do(mesh[i],
evas_3d_mesh_file_set(EVAS_3D_MESH_FILE_TYPE_PLY, path_file[i % 8], NULL),
evas_3d_mesh_frame_material_set(0, material),
evas_3d_mesh_shade_mode_set(draw_mode[(i % 16) / 8]));
mesh_node[i] = eo_add(EVAS_3D_NODE_CLASS, evas,
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_MESH));
eo_do(root_node, evas_3d_node_member_add(mesh_node[i]));
eo_do(mesh_node[i],
evas_3d_node_mesh_add(mesh[i]),
evas_3d_node_position_set(0, ((i % 4) * 40) + ((i / 16) * 10) - 80, (((i % 16) / 4) * 10) - 40),
evas_3d_node_scale_set(0.3, 0.3, 0.3));
}
/* Set up scene. */
eo_do(scene,
evas_3d_scene_root_node_set(root_node),
evas_3d_scene_camera_node_set(camera_node),
evas_3d_scene_background_color_set(0.7, 0.7, 0.7, 1.0),
evas_3d_scene_size_set(WIDTH, HEIGHT));
/* Add a background rectangle objects. */
background = eo_add(EVAS_RECTANGLE_CLASS, evas);
eo_do(background,
evas_obj_color_set(100, 100, 100, 255),
evas_obj_size_set(WIDTH, HEIGHT),
evas_obj_visibility_set(EINA_TRUE));
/* Add an image object for 3D scene rendering. */
image = evas_object_image_filled_add(evas);
eo_do(image,
evas_obj_size_set(WIDTH, HEIGHT),
evas_obj_visibility_set(EINA_TRUE));
/* Set the image object as render target for 3D scene. */
eo_do(image, evas_obj_image_scene_set(scene));
ecore_animator_frametime_set(0.01);
for (i = 0; i < NUMBER_OF_MESHES; i++)
anim = ecore_animator_add(_animate_scene, mesh_node[i]);
/* Enter main loop. */
ecore_main_loop_begin();
ecore_animator_del(anim);
ecore_evas_free(ecore_evas);
ecore_evas_shutdown();
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -726,9 +726,11 @@ typedef enum _Evas_3D_Material_Attrib
*/
typedef enum _Evas_3D_Mesh_File_Type
{
EVAS_3D_MESH_FILE_TYPE_MD2 = 0, /**< Quake's MD2 mesh file format */
EVAS_3D_MESH_FILE_TYPE_OBJ,
EVAS_3D_MESH_FILE_TYPE_EET,
EVAS_3D_MESH_FILE_TYPE_NONE = 0, /**< Noone from read formats */
EVAS_3D_MESH_FILE_TYPE_MD2, /**< Quake's MD2 mesh file format */
EVAS_3D_MESH_FILE_TYPE_OBJ, /**< Wavefront OBJ file format */
EVAS_3D_MESH_FILE_TYPE_EET, /**< EET - own EFL file format */
EVAS_3D_MESH_FILE_TYPE_PLY, /**< Stanford PLY mesh file format */
} Evas_3D_Mesh_File_Type;
#include "canvas/evas_image.eo.h"

View File

@ -27,9 +27,7 @@ evas_3d_mesh_frame_free(Evas_3D_Mesh_Frame *frame)
int i;
if (frame->material)
{
evas_3d_material_mesh_del(frame->material, frame->mesh);
}
evas_3d_material_mesh_del(frame->material, frame->mesh);
for (i = 0; i < EVAS_3D_VERTEX_ATTRIB_COUNT; i++)
{
@ -790,6 +788,9 @@ _evas_3d_mesh_file_set(Eo *obj, Evas_3D_Mesh_Data *pd, Evas_3D_Mesh_File_Type ty
case EVAS_3D_MESH_FILE_TYPE_EET:
evas_3d_mesh_file_eet_set(obj, file);
break;
case EVAS_3D_MESH_FILE_TYPE_PLY:
evas_3d_mesh_file_ply_set(obj, file);
break;
default:
ERR("Invalid mesh file type.");
break;
@ -802,34 +803,25 @@ _evas_3d_mesh_save(Eo *obj, Evas_3D_Mesh_Data *pd, Evas_3D_Mesh_File_Type type,
{
if ((file == NULL) || (obj == NULL) || (pd == NULL)) return;
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find(pd, 0);
if (f == NULL)
{
ERR("Not existing mesh frame.");
return;
}
switch (type)
{
case EVAS_3D_MESH_FILE_TYPE_OBJ:
{
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find(pd, 0);
if (f == NULL)
{
ERR("Not existing mesh frame.");
return;
}
evas_3d_mesh_save_obj(obj, file, f);//file without extension!
break;
}
evas_3d_mesh_save_obj(obj, file, f);//file without extension!
break;
case EVAS_3D_MESH_FILE_TYPE_EET:
{
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find(pd, 0);
if (f == NULL)
{
ERR("Not existing mesh frame.");
return;
}
evas_3d_mesh_save_eet(obj, file, f);
break;
}
evas_3d_mesh_save_eet(obj, file, f);
break;
case EVAS_3D_MESH_FILE_TYPE_PLY:
evas_3d_mesh_save_ply(obj, file, f);
break;
default:
ERR("Invalid mesh file type.");
break;

View File

@ -8,7 +8,7 @@ class Evas_3D_Mesh (Evas_3D_Object, Evas.Common_Interface)
/**
* Load mesh data from file.
*
* Loading a mesh from existing file is supported. Currently, only MD2, OBJ and EET file
* Loading a mesh from existing file is supported. Currently, only MD2, OBJ, PLY and EET file
* formats are supported.
*
* @ingroup Evas_3D_Mesh
@ -24,7 +24,7 @@ class Evas_3D_Mesh (Evas_3D_Object, Evas.Common_Interface)
/**
* Save mesh data to file.
*
* Saving a mesh to file is supported. Currently, only OBJ and EET file
* Saving a mesh to file is supported. Currently, only OBJ, PLY and EET file
* format are supported.
*
* @ingroup Evas_3D_Mesh

View File

@ -0,0 +1,401 @@
#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;
};
static inline char*
_file_to_buf(const char *file, long *length)//prepare text file for reading
{
FILE *file_for_print;
char *buf;
int unused __attribute__((unused));//this variable fixes warning "ignoring return value of fread"
*length = 0;
file_for_print = fopen(file, "rb");
if (!file_for_print) return NULL;
fseek(file_for_print, 0, SEEK_END);//set file_for_print to the end of file
*length = ftell(file_for_print);//set current position of file_for_print
buf = malloc(*length + 1);
fseek(file_for_print, 0, SEEK_SET);//set file_for_print to the begining of file
unused = fread(buf, *length, 1, file_for_print);
fclose(file_for_print);
buf[*length] = '\0';
return buf;
}
/* 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)
{
while (*current != '\n') current++;
current++;
return current;
}
static inline char *
_to_begin_of_line(char *current)
{
while (*current != '\n') current--;
current++;
return current;
}
static inline char *
_to_next_number(char *current, int count)
{
int i;
for (i = 0; i < count; i++)
{
while (*current != ' ') current++;
current++;
}
return current;
}
static inline char *
_read_data(float *array, int place, int count, char *current, float divider)
{
int i;
for (i = 0; i < count; i++)
{
sscanf (current,"%f", &ARRAY_2D(array, place, i, count));
ARRAY_2D(array, place, i, count) /= divider;
current = _to_next_number(current, 1);
}
return current;
}
static inline PLY_Header
_read_header(char *start)//Check properties of mesh in .ply file.
{
eina_init();
Eina_Bool reading_vertices = EINA_TRUE, check_next_char = EINA_FALSE;
int vertex_lines, triangles = 0, vertices_in_current_face = 0;
char **helping_pointer;
char *current;
PLY_Header header;
header = _new_ply_header();
helping_pointer = eina_str_split(start, "vertex ", 0);
if (helping_pointer == NULL)
{
ERR("File have not kayword vertex. It is necessary.");
return header;
}
sscanf(helping_pointer[1], "%d", &header.vertices_count);
free(helping_pointer);
helping_pointer = eina_str_split(start, "end_header\n", 0);
if (helping_pointer == NULL)
{
ERR("File have not kayword end_header. It is necessary.");
return header;
}
current = helping_pointer[1];
vertex_lines = header.vertices_count;
while (*current != '\0')
{
if (vertex_lines == 1)
reading_vertices = EINA_FALSE;
if (*current == '\n')
{
if (reading_vertices)
vertex_lines--;
else
check_next_char = EINA_TRUE;
}
if (check_next_char)
{
if ((*current <= '9') && (*current >= '0'))
vertices_in_current_face = (vertices_in_current_face * 10) + (*current - '0');
else if (*current >= ' ')
{
triangles += (vertices_in_current_face - 2);
vertices_in_current_face = 0;
check_next_char = EINA_FALSE;
}
}
current++;
}
header.triangles_count = triangles;
free(helping_pointer);
/* analyse flags used when file was saved in blender */
helping_pointer = eina_str_split(start, "property float ", 0);
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;
if ((helping_pointer[4] != NULL) && (*helping_pointer[4] == 'n') &&
(helping_pointer[5] != NULL) && (*helping_pointer[5] == 'n') &&
(helping_pointer[6] != NULL) && (*helping_pointer[6] == 'n'))
header.existence_of_normals = EINA_TRUE;
if ((header.existence_of_normals &&
((helping_pointer[7] != NULL) && (*helping_pointer[7] == 's') &&
(helping_pointer[8] != NULL) && (*helping_pointer[8] == 't'))) ||
(!header.existence_of_normals &&
((helping_pointer[4] != NULL) && (*helping_pointer[4] == 's') &&
(helping_pointer[5] != NULL) && (*helping_pointer[5] == 't'))))
header.existence_of_texcoords = EINA_TRUE;
helping_pointer = eina_str_split(start, "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;
free(helping_pointer);
return header;
}
void
evas_3d_mesh_file_ply_set(Evas_3D_Mesh *mesh, const char *file)
{
long length;
Evas_3D_Mesh_Data *pd;
int i = 0, j = 0, k = 0, count_of_triangles_in_line = 0;
float *pos, *nor, *tex, *col;
int stride_pos, stride_nor, stride_tex, stride_col;
char *start, *current;
PLY_Header header;
float *_vertices_ply = NULL, *_normals_ply = NULL, *_tex_coords_ply = NULL, *_colors_ply = NULL;
char **helping_pointer;
start = _file_to_buf(file, &length);
if (start == NULL)
{
ERR("Buffer is empty after preparation file for reading.");
return;
}
header = _read_header(start);
if (!header.existence_of_geometries)
{
ERR("File have not x, y, or z field as the first 3 float fields. They are necessary.");
return;
}
helping_pointer = eina_str_split(start, "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));
int *_triangles = malloc(header.triangles_count * 3 * sizeof(int));
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)) ||
(_triangles == NULL))
{
ERR("Allocate memory is failed.");
free(start);
free(_vertices_ply);
free(_normals_ply);
free(_tex_coords_ply);
free(_colors_ply);
free(_triangles);
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;)
{
sscanf (current,"%d", &count_of_triangles_in_line);
count_of_triangles_in_line -= 2;
current = _to_next_number(current, 1);
sscanf (current,"%i", &ARRAY_2D(_triangles, i, 0, 3));
for (j = 0; j < count_of_triangles_in_line; j++)
{
if (j > 0)
ARRAY_2D(_triangles, i, 0, 3) = ARRAY_2D(_triangles, (i - 1), 0, 3);
current = _to_next_number(current, 1);
sscanf (current,"%i %i",
&ARRAY_2D(_triangles, i, 1, 3),
&ARRAY_2D(_triangles, i, 2, 3));
i++;
}
current = _to_next_line(current);
}
/* prepare of mesh and take pointers to data which must be read */
eo_do(mesh,
evas_3d_mesh_vertex_count_set(header.triangles_count * 3),
evas_3d_mesh_vertex_assembly_set(EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES),
evas_3d_mesh_frame_add(0),
evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_POSITION, 0, NULL),
evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_NORMAL, 0, NULL),
evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_TEXCOORD, 0, NULL),
evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_COLOR, 0, NULL),
pos = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_POSITION),
nor = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_NORMAL),
tex = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_TEXCOORD),
col = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_COLOR),
stride_pos = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_POSITION),
stride_nor = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_NORMAL),
stride_tex = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_TEXCOORD),
stride_col = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_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.triangles_count; j++)
{
for (k = 0; k < 3; k++)
{
float *p, *n, *t, *c;
p = (float *)((char *)pos + stride_pos * (j * 3 + k));
n = (float *)((char *)nor + stride_nor * (j * 3 + k));
t = (float *)((char *)tex + stride_tex * (j * 3 + k));
c = (float *)((char *)col + stride_col * (j * 3 + k));
p[0] = ARRAY_2D(_vertices_ply, ARRAY_2D(_triangles, j, k, 3), 0, 3);
p[1] = ARRAY_2D(_vertices_ply, ARRAY_2D(_triangles, j, k, 3), 1, 3);
p[2] = ARRAY_2D(_vertices_ply, ARRAY_2D(_triangles, j, k, 3), 2, 3);
if (header.existence_of_normals)
{
n[0] = ARRAY_2D(_normals_ply, ARRAY_2D(_triangles, j, k, 3), 0, 3);
n[1] = ARRAY_2D(_normals_ply, ARRAY_2D(_triangles, j, k, 3), 1, 3);
n[2] = ARRAY_2D(_normals_ply, ARRAY_2D(_triangles, j, k, 3), 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, ARRAY_2D(_triangles, j, k, 3), 0, 2);
t[1] = ARRAY_2D(_tex_coords_ply, ARRAY_2D(_triangles, j, k, 3), 1, 2);
}
else
{
t[0] = 0.0;
t[1] = 0.0;
}
if (header.existence_of_colors)
{
c[0] = ARRAY_2D(_colors_ply, ARRAY_2D(_triangles, j, k, 3), 0, 3);
c[1] = ARRAY_2D(_colors_ply, ARRAY_2D(_triangles, j, k, 3), 1, 3);
c[2] = ARRAY_2D(_colors_ply, ARRAY_2D(_triangles, j, k, 3), 2, 3);
c[3] = 1.0;
}
else
{
c[0] = 0.0;
c[1] = 0.0;
c[2] = 0.0;
c[3] = 1.0;
}
}
}
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(_triangles);
/* Unmap vertex buffer. */
eo_do(mesh,
evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_POSITION),
evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_NORMAL),
evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_TEXCOORD),
evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_COLOR));
pd = eo_data_scope_get(mesh, EVAS_3D_MESH_CLASS);
if (!evas_3d_mesh_aabb_add_to_frame(pd, 0, stride_pos))
{
ERR("Axis-Aligned Bounding Box wan't added in frame %d ", 0);
}
}

View File

@ -0,0 +1,56 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <time.h>
#include "stdio.h"
#include "math.h"
#include "evas_common_private.h"
#include "evas_private.h"
void
evas_3d_mesh_save_ply(Evas_3D_Mesh *mesh, const char *file, Evas_3D_Mesh_Frame *f)
{
float *src_pos, *src_nor, *src_tex, *src_col;
int i;
Evas_3D_Mesh_Data *pd = eo_data_scope_get(mesh, EVAS_3D_MESH_CLASS);
FILE *_ply_file = fopen(file, "w+");
fprintf(_ply_file,"ply\nformat ascii 1.0\ncomment Created by EFL evas_3d_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->vertex_count / 3);
src_pos = (float*)(&f->vertices[EVAS_3D_VERTEX_POSITION])->data;
src_nor = (float*)(&f->vertices[EVAS_3D_VERTEX_NORMAL])->data;
src_tex = (float*)(&f->vertices[EVAS_3D_VERTEX_TEXCOORD])->data;
src_col = (float*)(&f->vertices[EVAS_3D_VERTEX_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;
}
for (i = 0; i < pd->vertex_count;)
{
fprintf(_ply_file,"3 %d %d %d\n", i, i + 1, i + 2);
i += 3;
}
fclose(_ply_file);
}

View File

@ -1613,6 +1613,8 @@ void evas_3d_mesh_file_obj_set(Evas_3D_Mesh *mesh, const char *file);
Eina_Bool evas_3d_mesh_aabb_add_to_frame(Evas_3D_Mesh_Data *pd, int frame, int stride);
void evas_3d_mesh_file_eet_set(Evas_3D_Mesh *mesh, const char *file);
void evas_3d_mesh_save_eet(Evas_3D_Mesh *mesh, const char *file, Evas_3D_Mesh_Frame *f);
void evas_3d_mesh_file_ply_set(Evas_3D_Mesh *mesh, const char *file);
void evas_3d_mesh_save_ply(Evas_3D_Mesh *mesh, const char *file, Evas_3D_Mesh_Frame *f);
/* Texture functions. */
void evas_3d_texture_material_add(Evas_3D_Texture *texture, Evas_3D_Material *material);

View File

@ -14,8 +14,9 @@
#define TESTS_MESH_DIR TESTS_SRC_DIR"/meshes"
#define TESTS_OBJ_MESH_DIR TESTS_MESH_DIR"/obj"
#define TESTS_MD2_MESH_DIR TESTS_MESH_DIR"/md2"
#define TESTS_PLY_MESH_DIR TESTS_MESH_DIR"/ply"
#define COMPARE_GEOMETRICS(a, component) \
#define COMPARE_GEOMETRICS(a) \
vb1 = &f1->vertices[a]; \
vb2 = &f2->vertices[a]; \
if ((vb1->data == NULL) || (vb2->data == NULL)) \
@ -33,21 +34,21 @@
src2 += f2->vertices[a].element_count; \
}
#define CHECK_MESHES_IN_FOLDER(folder, type) \
it = eina_file_direct_ls(folder); \
EINA_ITERATOR_FOREACH(it, file) \
{ \
mesh = eo_add(EVAS_3D_MESH_CLASS, e); \
mesh2 = eo_add(EVAS_3D_MESH_CLASS, e); \
fail_if(mesh == NULL); \
fail_if(mesh2 == NULL); \
eo_do(mesh, evas_3d_mesh_file_set(type, file->path, NULL)); \
eo_do(mesh, evas_3d_mesh_save(EVAS_3D_MESH_FILE_TYPE_EET, buffer, NULL)); \
eo_do(mesh2, evas_3d_mesh_file_set(EVAS_3D_MESH_FILE_TYPE_EET, buffer, NULL)); \
res = _compare_meshes(mesh, mesh2); \
fail_if(res == 1); \
eo_del(mesh2); \
eo_del(mesh); \
#define CHECK_MESHES_IN_FOLDER(folder, type, type_to_check) \
it = eina_file_direct_ls(folder); \
EINA_ITERATOR_FOREACH(it, file) \
{ \
mesh = eo_add(EVAS_3D_MESH_CLASS, e); \
mesh2 = eo_add(EVAS_3D_MESH_CLASS, e); \
fail_if(mesh == NULL); \
fail_if(mesh2 == NULL); \
eo_do(mesh, evas_3d_mesh_file_set(type, file->path, NULL)); \
eo_do(mesh, evas_3d_mesh_save(type_to_check, buffer, NULL)); \
eo_do(mesh2, evas_3d_mesh_file_set(type_to_check, buffer, NULL)); \
res = _compare_meshes(mesh, mesh2); \
fail_if(res == 1); \
eo_del(mesh2); \
eo_del(mesh); \
}
static Evas_3D_Mesh_Frame *
@ -86,9 +87,10 @@ static int _compare_meshes(Evas_3D_Mesh *mesh1, Evas_3D_Mesh *mesh2)
if ((pd1->vertex_count) != (pd2->vertex_count))
return 1;
COMPARE_GEOMETRICS(EVAS_3D_VERTEX_POSITION, position)
COMPARE_GEOMETRICS(EVAS_3D_VERTEX_NORMAL, normal)
COMPARE_GEOMETRICS(EVAS_3D_VERTEX_TEXCOORD, texcoord)
COMPARE_GEOMETRICS(EVAS_3D_VERTEX_POSITION)
COMPARE_GEOMETRICS(EVAS_3D_VERTEX_NORMAL)
COMPARE_GEOMETRICS(EVAS_3D_VERTEX_TEXCOORD)
return 0;
}
@ -97,8 +99,7 @@ START_TEST(evas_object_mesh_loader_saver)
char buffer[PATH_MAX];
Evas *e = _setup_evas();
Eina_Tmpstr *tmp;
Eo *mesh;
Eo *mesh2;
Eo *mesh, *mesh2;
Eina_Iterator *it;
char *file_mask = strdup("evas_test_mesh_XXXXXX");
int res = 0, tmpfd;
@ -110,8 +111,10 @@ START_TEST(evas_object_mesh_loader_saver)
snprintf(buffer, PATH_MAX, "%s", tmp);
CHECK_MESHES_IN_FOLDER(TESTS_OBJ_MESH_DIR, EVAS_3D_MESH_FILE_TYPE_OBJ)
CHECK_MESHES_IN_FOLDER(TESTS_MD2_MESH_DIR, EVAS_3D_MESH_FILE_TYPE_MD2)
CHECK_MESHES_IN_FOLDER(TESTS_OBJ_MESH_DIR, EVAS_3D_MESH_FILE_TYPE_OBJ, EVAS_3D_MESH_FILE_TYPE_EET)
CHECK_MESHES_IN_FOLDER(TESTS_MD2_MESH_DIR, EVAS_3D_MESH_FILE_TYPE_MD2, EVAS_3D_MESH_FILE_TYPE_EET)
CHECK_MESHES_IN_FOLDER(TESTS_PLY_MESH_DIR, EVAS_3D_MESH_FILE_TYPE_PLY, EVAS_3D_MESH_FILE_TYPE_EET)
CHECK_MESHES_IN_FOLDER(TESTS_PLY_MESH_DIR, EVAS_3D_MESH_FILE_TYPE_PLY, EVAS_3D_MESH_FILE_TYPE_PLY)
eina_iterator_free(it);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff