evas: Evas_3D - add .obj export/import.

@feature

Reviewers: raster, Hermet, cedric

Reviewed By: cedric

CC: cedric

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

Signed-off-by: Cedric BAIL <c.bail@partner.samsung.com>
This commit is contained in:
Bogdan Devichev 2014-06-05 19:46:55 +02:00 committed by Cedric BAIL
parent 125bbf67b9
commit 700f4396e1
11 changed files with 3290 additions and 8 deletions

View File

@ -295,7 +295,9 @@ lib/evas/canvas/evas_3d_light.c \
lib/evas/canvas/evas_3d_mesh.c \
lib/evas/canvas/evas_3d_texture.c \
lib/evas/canvas/evas_3d_material.c \
lib/evas/canvas/evas_3d_mesh_loader_md2.c
lib/evas/canvas/evas_3d_mesh_loader_md2.c \
lib/evas/canvas/evas_3d_mesh_loader_obj.c \
lib/evas/canvas/evas_3d_mesh_saver_obj.c
# Engine
lib_evas_libevas_la_SOURCES += \

View File

@ -0,0 +1,203 @@
/**
* Simple Evas example illustrating import/export of .obj format.
*
* Read mesh from "man_mesh.obj".
* After that cheange some properties of material.
* After that save material to "saved_man.mtl"
* and geometry to "saved_man.obj".
*
* @verbatim
* gcc -o evas-3d-obj evas-3d-obj.c `pkg-config --libs --cflags evas ecore ecore-evas`
* @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
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 = NULL;
Eo *mesh = NULL;
Eo *material = NULL;
Eo *texture = NULL;
Eo *light = NULL;
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)
{
//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_custom(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_custom(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(100.0, 0.0, 20.0),
evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 20.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_custom(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));
/* Add the mesh. */
mesh = eo_add(EVAS_3D_MESH_CLASS, evas);
material = eo_add(EVAS_3D_MATERIAL_CLASS, evas);
eo_do(mesh,
evas_3d_mesh_file_set(EVAS_3D_MESH_FILE_TYPE_OBJ, "man_mesh.obj", NULL),
evas_3d_mesh_frame_material_set(0, material),
evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_PHONG));
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));
eo_do(mesh, evas_3d_mesh_save(EVAS_3D_MESH_FILE_TYPE_OBJ, "saved_man", NULL));
mesh_node = eo_add_custom(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));
eo_do(mesh_node,
evas_3d_node_mesh_add(mesh));
/* 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_size_set(WIDTH, HEIGHT));
/* Add a background rectangle objects. */
background = eo_add(EVAS_OBJ_RECTANGLE_CLASS, evas);
eo_unref(background);
eo_do(background,
evas_obj_color_set(0, 0, 0, 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_timer_add(0.01, _animate_scene, mesh_node);
/* Enter main loop. */
ecore_main_loop_begin();
ecore_evas_free(ecore_evas);
ecore_evas_shutdown();
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

View File

@ -0,0 +1,11 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2

File diff suppressed because it is too large Load Diff

View File

@ -744,6 +744,7 @@ 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;
#include "canvas/evas_image.eo.h"

View File

@ -748,17 +748,46 @@ _evas_3d_mesh_file_set(Eo *obj, Evas_3D_Mesh_Data *pd, Evas_3D_Mesh_File_Type ty
_mesh_fini(pd);
_mesh_init(pd);
if (file == NULL)
return;
if (file == NULL) return;
switch (type)
{
case EVAS_3D_MESH_FILE_TYPE_MD2:
evas_3d_mesh_file_md2_set(obj, file);
break;
evas_3d_mesh_file_md2_set(obj, file);
break;
case EVAS_3D_MESH_FILE_TYPE_OBJ:
evas_3d_mesh_file_obj_set(obj, file);
break;
default:
ERR("Invalid mesh file type.");
break;
ERR("Invalid mesh file type.");
break;
}
}
EOLIAN static void
_evas_3d_mesh_save(Eo *obj, Evas_3D_Mesh_Data *pd, Evas_3D_Mesh_File_Type type,
const char *file, const char *key EINA_UNUSED)
{
if ((file == NULL) || (obj == NULL) || (pd == NULL)) 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;
}
default:
ERR("Invalid mesh file type.");
break;
}
}

View File

@ -8,7 +8,23 @@ 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 file
* Loading a mesh from existing file is supported. Currently, only MD2 and OBJ file
* formats are supported.
*
* @ingroup Evas_3D_Mesh
*/
params {
@in Evas_3D_Mesh_File_Type type; /*@ The type of the mesh file. */
@in const char *file; /*@ Path to the mesh file. */
@in const char *key; /*@ Key in the mesh file. */
}
}
save {
/**
* Save mesh data to file.
*
* Saving a mesh to file is supported. Currently, only OBJ file
* format is supported.
*
* @ingroup Evas_3D_Mesh

View File

@ -0,0 +1,397 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include "stdio.h"
#include "evas_common_private.h"
#include "evas_private.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))
/* read 3 float values in string and put it in array */
#define PUT_DATA_TO_ARRAY(array_name, name) \
sscanf (current,"%f %f %f", \
&ARRAY_2D(_##array_name##_obj, counts.current_##name##_counter, 0, 3), \
&ARRAY_2D(_##array_name##_obj, counts.current_##name##_counter, 1, 3), \
&ARRAY_2D(_##array_name##_obj, counts.current_##name##_counter, 2, 3)); \
counts.current_##name##_counter++;
/* Structures for reading data from file. */
typedef struct _OBJ_Counts OBJ_Counts;
struct _OBJ_Counts
{
int _vertex_counter;
int _normal_counter;
int _texture_point_counter;
int _triangles_counter;
int current_vertex_counter;
int current_normal_counter;
int current_texture_point_counter;
int current_triangles_counter;
Eina_Bool existence_of_normal;
Eina_Bool existence_of_tex_point;
};
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 counter */
static inline OBJ_Counts
_new_count_elements()
{
OBJ_Counts counts;
counts._vertex_counter = 0;
counts._normal_counter = 0;
counts._texture_point_counter = 0;
counts._triangles_counter = 0;
counts.current_vertex_counter = 0;
counts.current_normal_counter = 0;
counts.current_texture_point_counter = 0;
counts.current_triangles_counter = 0;
counts.existence_of_normal = EINA_FALSE;
counts.existence_of_tex_point = EINA_FALSE;
return counts;
}
/* count triangles in face */
static void
_analyze_face_line(char * face_analyzer,
int * count_of_triangles_in_line)
{
int polygon_checker = -2;
Eina_Bool previous_is_space = EINA_TRUE;
while ((*face_analyzer != '\n') && (*face_analyzer != '#'))
{
if (*face_analyzer == ' ')
{
previous_is_space = EINA_TRUE;
}
else if ((previous_is_space) && (*face_analyzer >= '0') && (*face_analyzer <= '9'))
{
polygon_checker++;
previous_is_space = EINA_FALSE;
}
face_analyzer++;
}
*count_of_triangles_in_line = polygon_checker;
}
static inline OBJ_Counts
_count_elements(char *start, long length)//count elements of mesh in .obj
{
OBJ_Counts counts = _new_count_elements();
char * current = start;
int polygon_checker = -2;//polygons with n vertices can be represented as n-2 triangles
Eina_Bool will_check_next_char = EINA_FALSE;
Eina_Bool first_char_is_v = EINA_FALSE;
Eina_Bool first_char_is_f = EINA_FALSE;
Eina_Bool previous_is_space = EINA_FALSE;
long i = 0;
/* count elements of mesh in .obj */
for (; length > i; i++)
{
if (will_check_next_char)
{
if (first_char_is_v)
{
switch (*current)
{
case ' ':
counts._vertex_counter++;
break;
case 't':
counts._texture_point_counter++;
counts.existence_of_tex_point = EINA_TRUE;
break;
case 'n':
counts._normal_counter++;
counts.existence_of_normal = EINA_TRUE;
break;
default:
break;
}
first_char_is_v = EINA_FALSE;
will_check_next_char = EINA_FALSE;
}
else if (first_char_is_f)
{
switch (*current)
{
case '\n':
first_char_is_f = EINA_FALSE;
counts._triangles_counter += polygon_checker;
polygon_checker = -2;
previous_is_space = EINA_FALSE;
break;
case '#':
first_char_is_f = EINA_FALSE;
counts._triangles_counter += polygon_checker;
polygon_checker = -2;
previous_is_space = EINA_FALSE;
break;
case ' ':
previous_is_space = EINA_TRUE;
break;
default:
if ((previous_is_space) && (*current >= '0') && (*current <= '9'))
{
polygon_checker++;
previous_is_space = EINA_FALSE;
}
break;
}
}
else
{
switch (*current)
{
case 'v':
first_char_is_v = EINA_TRUE;
break;
case 'f':
first_char_is_f = EINA_TRUE;
break;
case 'm':
will_check_next_char = EINA_FALSE;
break;
default:
will_check_next_char = EINA_FALSE;
break;
}
}
}
else if (*current == '\n')
{
will_check_next_char = EINA_TRUE;
}
current++;
}
return counts;
}
void
evas_3d_mesh_file_obj_set(Evas_3D_Mesh *mesh, const char *file)
{
long length, i;
char * start = _file_to_buf(file, &length);
OBJ_Counts counts = _count_elements(start, length);//count elements of mesh in .obj
Eina_Bool will_check_next_char = EINA_FALSE;
Eina_Bool first_char_is_v = EINA_FALSE;
Eina_Bool first_char_is_f = EINA_FALSE;
float *pos, *nor, *tex;
int stride_pos, stride_nor, stride_tex;
int j, k;
char * current;
float *_vertices_obj = malloc(counts._vertex_counter * 3 * sizeof(float));
float *_normales_obj = malloc(counts._normal_counter * 3 * sizeof(float));
float *_tex_coords_obj = malloc(counts._texture_point_counter * 3 * sizeof(float));
/* triangle has 3 points, every point has 3(vertix, texture and normal) coord */
int *_triangles = malloc(counts._triangles_counter * 9 * sizeof(int));
if ((start == NULL) || (_vertices_obj == NULL) ||
(_normales_obj == NULL) || (_tex_coords_obj == NULL) || (_triangles == NULL))
{
ERR("Allocate memory is failed.");
free(start);
free(_vertices_obj);
free(_normales_obj);
free(_tex_coords_obj);
free(_triangles);
return;
}
current = start;
i = 0;
/* put data to arrays */
for (; length > i; i++)
{
if (will_check_next_char)
{
if (first_char_is_v)
{
switch (*current)
{
case ' ':
PUT_DATA_TO_ARRAY(vertices, vertex)
i--;
break;
case 't':
current++;
PUT_DATA_TO_ARRAY(tex_coords, texture_point)
break;
case 'n':
current++;
PUT_DATA_TO_ARRAY(normales, normal)
break;
default:
break;
}
first_char_is_v = EINA_FALSE;
will_check_next_char = EINA_FALSE;
}
else if (first_char_is_f)
{
char * auxiliary_pointer = current;
int count_of_triangles_in_line;
_analyze_face_line(auxiliary_pointer,
&count_of_triangles_in_line);
int j;
current++;
i++;
int first_pos, first_tex, first_norm;
sscanf (current,"%i/%i/%i",
&first_pos,
&first_tex,
&first_norm);
do
{
current++;
i++;
}
while (*current != ' ');
current++;
i++;
for (j = 0; j < count_of_triangles_in_line; j++)
{
auxiliary_pointer = current;
ARRAY_2D(_triangles, counts.current_triangles_counter, 0, 9) = first_pos;
ARRAY_2D(_triangles, counts.current_triangles_counter, 1, 9) = first_tex;
ARRAY_2D(_triangles, counts.current_triangles_counter, 2, 9) = first_norm;
sscanf (auxiliary_pointer,"%i/%i/%i %i/%i/%i",
&ARRAY_2D(_triangles, counts.current_triangles_counter, 3, 9),
&ARRAY_2D(_triangles, counts.current_triangles_counter, 4, 9),
&ARRAY_2D(_triangles, counts.current_triangles_counter, 5, 9),
&ARRAY_2D(_triangles, counts.current_triangles_counter, 6, 9),
&ARRAY_2D(_triangles, counts.current_triangles_counter, 7, 9),
&ARRAY_2D(_triangles, counts.current_triangles_counter, 8, 9));
while (*current != ' ')
{
current++;
i++;
}
counts.current_triangles_counter++;
}
first_char_is_f = EINA_FALSE;
}
else
{
switch (*current)
{
case 'v':
first_char_is_v = EINA_TRUE;
break;
case 'f':
first_char_is_f = EINA_TRUE;
break;
case 'm':
will_check_next_char = EINA_FALSE;
break;
default:
will_check_next_char = EINA_FALSE;
break;
}
}
}
else if (*current == '\n')
{
will_check_next_char = EINA_TRUE;
}
current++;
}
free(start);
/* prepare of mesh and take pointers to data which must be read */
eo_do(mesh,
evas_3d_mesh_vertex_count_set(counts._triangles_counter * 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),
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),
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));
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;
for (j = 0; j < counts._triangles_counter; j++)
{
for (k = 0; k < 3; k++)
{
float *p, *n, *t;
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));
p[0] = ARRAY_2D(_vertices_obj, (ARRAY_2D(_triangles, j, (3 * k), 9) - 1), 0, 3);
p[1] = ARRAY_2D(_vertices_obj, (ARRAY_2D(_triangles, j, (3 * k), 9) - 1), 1, 3);
p[2] = ARRAY_2D(_vertices_obj, (ARRAY_2D(_triangles, j, (3 * k), 9) - 1), 2, 3);
n[0] = ARRAY_2D(_normales_obj, (ARRAY_2D(_triangles, j, (3 * k + 2), 9) - 1), 0, 3);
n[1] = ARRAY_2D(_normales_obj, (ARRAY_2D(_triangles, j, (3 * k + 2), 9) - 1), 1, 3);
n[2] = ARRAY_2D(_normales_obj, (ARRAY_2D(_triangles, j, (3 * k + 2), 9) - 1), 2, 3);
t[0] = ARRAY_2D(_tex_coords_obj, (ARRAY_2D(_triangles, j, (3 * k + 1), 9) - 1), 0, 3);
t[1] = ARRAY_2D(_tex_coords_obj, (ARRAY_2D(_triangles, j, (3 * k + 1), 9) - 1), 1, 3);
}
}
free(_vertices_obj);
free(_normales_obj);
free(_tex_coords_obj);
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_Data *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,128 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <time.h>
#include "stdio.h"
#include "evas_common_private.h"
#include "evas_private.h"
#define OPEN_FILE(extension)\
int length=strlen(file);\
char * extension = "."#extension;\
char * _##extension##_file_name = (char *)malloc(length+4);\
strcpy(_##extension##_file_name,file);\
strcpy(_##extension##_file_name+length,extension);\
FILE * _##extension##_file = fopen(_##extension##_file_name, "w+");\
free(_##extension##_file_name);
#define SAVE_GEOMETRICS(a, format)\
vb = &f->vertices[a];\
fprintf(_obj_file, "o %s\n",file);\
if (vb->data == NULL)\
{\
ERR("Reading of geometrics is failed.");\
fclose(_obj_file);\
return;\
}\
src = (float *)vb->data;\
for (i = 0; i < pd->vertex_count; i++)\
{\
fprintf(_obj_file, format, src[0], src[1], src[2]);\
src += f->vertices[a].element_count;\
}
static void
_save_mesh(Evas_3D_Mesh_Data *pd, const char *file, Evas_3D_Mesh_Frame *f)
{
Evas_3D_Vertex_Buffer *vb;
time_t current_time;
char* c_time_string;
int i;
float *src;
OPEN_FILE(obj)
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;
}
c_time_string = ctime(&current_time);
if (c_time_string == NULL)
{
ERR("Failure to convert the current time.");
fclose(_obj_file);
return;
}
fprintf(_obj_file,"# Current time is %s \n", c_time_string);
fprintf(_obj_file,"mtllib %s.mtl \n\n", file);
/* Adding geometrics to file. */
if (f == NULL)
{
ERR("Not existing mesh frame.");
fclose(_obj_file);
return;
}
SAVE_GEOMETRICS(EVAS_3D_VERTEX_POSITION, "v %.4f %.4f %.4f \n")
SAVE_GEOMETRICS(EVAS_3D_VERTEX_NORMAL, "vn %.4f %.4f %.4f \n")
SAVE_GEOMETRICS(EVAS_3D_VERTEX_TEXCOORD, "vt %.4f %.4f %.4f \n")
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
{
fprintf(_obj_file,"f %i/%i/%i ", i, i, i);
i++;
fprintf(_obj_file,"%i/%i/%i ", i, i, i);
i++;
fprintf(_obj_file,"%i/%i/%i \n", i, i, i);
}
fclose(_obj_file);
}
static void
_save_material(Evas_3D_Mesh_Data *pd EINA_UNUSED, const char *file, Evas_3D_Mesh_Frame *f)
{
Evas_3D_Material_Data *mat = eo_data_scope_get(f->material, EVAS_3D_MATERIAL_CLASS);
OPEN_FILE(mtl)
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
fprintf(_mtl_file, "Ka %.6f %.6f %.6f \n",
(float)mat->attribs[EVAS_3D_MATERIAL_AMBIENT].color.r,
(float)mat->attribs[EVAS_3D_MATERIAL_AMBIENT].color.g,
(float)mat->attribs[EVAS_3D_MATERIAL_AMBIENT].color.b);
fprintf(_mtl_file, "Kd %.6f %.6f %.6f \n",
(float)mat->attribs[EVAS_3D_MATERIAL_DIFFUSE].color.r,
(float)mat->attribs[EVAS_3D_MATERIAL_DIFFUSE].color.g,
(float)mat->attribs[EVAS_3D_MATERIAL_DIFFUSE].color.b);
fprintf(_mtl_file, "Ks %.6f %.6f %.6f \n",
(float)mat->attribs[EVAS_3D_MATERIAL_SPECULAR].color.r,
(float)mat->attribs[EVAS_3D_MATERIAL_SPECULAR].color.g,
(float)mat->attribs[EVAS_3D_MATERIAL_SPECULAR].color.b);
fprintf(_mtl_file, "Ni 1.000000 \n");//optical density
fprintf(_mtl_file, "d 1.000000 \n");//a factor d of 1.0 is fully opaque material
fprintf(_mtl_file, "illum 2 \n");//illumination properties
fclose(_mtl_file);
}
void
evas_3d_mesh_save_obj(Evas_3D_Mesh *mesh, const char *file, Evas_3D_Mesh_Frame *f)
{
Evas_3D_Mesh_Data *pd = eo_data_scope_get(mesh, EVAS_3D_MESH_CLASS);
_save_mesh(pd, file, f);
_save_material(pd, file, f);
}

View File

@ -1504,6 +1504,8 @@ void evas_3d_mesh_node_add(Evas_3D_Mesh *mesh, Evas_3D_Node *node);
void evas_3d_mesh_node_del(Evas_3D_Mesh *mesh, Evas_3D_Node *node);
void evas_3d_mesh_interpolate_vertex_buffer_get(Evas_3D_Mesh *mesh, int frame, Evas_3D_Vertex_Attrib attrib, Evas_3D_Vertex_Buffer *buffer0, Evas_3D_Vertex_Buffer *buffer1, Evas_Real *weight);
void evas_3d_mesh_file_md2_set(Evas_3D_Mesh *mesh, const char *file);
void evas_3d_mesh_save_obj(Evas_3D_Mesh *mesh, const char *file, Evas_3D_Mesh_Frame *f);
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);
/* Texture functions. */