aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/evas/model_loaders/obj
diff options
context:
space:
mode:
authorBogdan Devichev <b.devichev@samsung.com>2015-02-11 18:13:58 +0100
committerCedric BAIL <cedric@osg.samsung.com>2015-02-11 18:31:53 +0100
commit150613086643af46b02acc958252aa553ac89903 (patch)
treea7ea8cf91ffc10998bf700bce41f21d9700bb882 /src/modules/evas/model_loaders/obj
parentevas: example for Evas_3D color pick (diff)
downloadefl-150613086643af46b02acc958252aa553ac89903.tar.gz
evas: Evas_3D - iport/export of Obj format can be read even if obj-file does not have normals or tex-coords.
Summary: This commit fixed several bugs, and show what was be fixed. Bugs: - When designer save obj file in Blender, he/she can set flags (fig 1). Normals and UV coords flags was necessary for obj loader. Loader crushed when they are not set as true. It fixed by this commit. - Another loaders set default values to data which aren't in loading file, so mesh need more memory for unused data. It fixed by this commit for obj and will be fixed for another formats in future. - Saver saved incorrect data if normals or tex_coords was not set in mesh in evas. Now it fixed. - Saver failed if it save mesh without material. It fixed and in this case material file is not created now. - Also fixed some leaks and undefined behavior which valgrind shows. Example: - Example shows cases described above. Example use files saved with different flags for it. Resources: - man_mesh is replaced by several smaller file, to use them for showing new features and fixes. For example, similar to that models can be added when implement work with material for obj, work with different flags for obj loader/saver etc. (big count of man_meshes is to much memory). - texture for home is flipped, because of bug with texture in efl to see if tex_coords is incorrect. Test: - test should be rewritten in future, because another formats still use default values for normals and tex_coords. And test can not pass for all types of obj file because of standardization for any format in him. Test Plan: Test suit will be rewritten after correcting of other formats (they will set NULL to file when save an empty data (like mesh without normals)) Reviewers: Hermet, raster, cedric Reviewed By: cedric Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D1957 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
Diffstat (limited to 'src/modules/evas/model_loaders/obj')
-rw-r--r--src/modules/evas/model_loaders/obj/evas_model_load_obj.c205
1 files changed, 136 insertions, 69 deletions
diff --git a/src/modules/evas/model_loaders/obj/evas_model_load_obj.c b/src/modules/evas/model_loaders/obj/evas_model_load_obj.c
index 64c4eb9e58..24f38c4cc7 100644
--- a/src/modules/evas/model_loaders/obj/evas_model_load_obj.c
+++ b/src/modules/evas/model_loaders/obj/evas_model_load_obj.c
@@ -12,13 +12,21 @@
#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", \
+#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++;
+#define AFTER_NEXT_SPACE(pointer)\
+ do \
+ { \
+ pointer++; \
+ i++; \
+ } \
+ while (*pointer != ' ');
+
/* Structures for reading data from file. */
typedef struct _OBJ_Counts OBJ_Counts;
@@ -177,6 +185,37 @@ _count_elements(char *map)//count elements of mesh in .obj
return counts;
}
+static void
+_read_point(int *triangles,
+ int num,
+ OBJ_Counts counts,
+ int num_cur,
+ char *pointer)
+{
+ if (counts.existence_of_normal)
+ {
+ if (counts.existence_of_tex_point)
+ sscanf(pointer, "%i/%i/%i",
+ &ARRAY_2D(triangles, num_cur, (num - 1) * 3, 9),
+ &ARRAY_2D(triangles, num_cur, (num - 1) * 3 + 1, 9),
+ &ARRAY_2D(triangles, num_cur, (num - 1) * 3 + 2, 9));
+ else
+ sscanf(pointer, "%i//%i",
+ &ARRAY_2D(triangles, num_cur, (num - 1) * 3, 9),
+ &ARRAY_2D(triangles, num_cur, (num - 1) * 3 + 2, 9));
+ }
+ else
+ {
+ if (counts.existence_of_tex_point)
+ sscanf(pointer, "%i/%i",
+ &ARRAY_2D(triangles, num_cur, (num - 1) * 3, 9),
+ &ARRAY_2D(triangles, num_cur, (num - 1) * 3 + 1, 9));
+ else
+ sscanf(pointer, "%i",
+ &ARRAY_2D(triangles, num_cur, (num - 1) * 3, 9));
+ }
+}
+
void
evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
{
@@ -187,8 +226,10 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
Eina_Bool first_char_is_f = EINA_FALSE;
float *pos, *nor, *tex;
int stride_pos, stride_nor, stride_tex;
- int j, k;
+ int j, k, data_for_one_point;
char *current, *map;
+ float *_vertices_obj, *_normales_obj, *_tex_coords_obj;
+ int *_triangles;
map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL);
@@ -199,27 +240,36 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
}
counts = _count_elements(map);
+ _vertices_obj = malloc(counts._vertex_counter * 3 * sizeof(float));
+ data_for_one_point = 1;
+ if (counts.existence_of_normal)
+ {
+ data_for_one_point++;
+ _normales_obj = malloc(counts._normal_counter * 3 * sizeof(float));
+ }
+ if (counts.existence_of_tex_point)
+ {
+ data_for_one_point++;
+ _tex_coords_obj = malloc(counts._texture_point_counter * 3 * sizeof(float));
+ }
+ _triangles = malloc(counts._triangles_counter * 9 * sizeof(int));
- 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 ((map == NULL) || (_vertices_obj == NULL) ||
- (_normales_obj == NULL) || (_tex_coords_obj == NULL) || (_triangles == NULL))
+ if ((map == NULL) || (_vertices_obj == NULL) || (_triangles == NULL) ||
+ ((counts.existence_of_normal) && (_normales_obj == NULL)) ||
+ ((counts.existence_of_tex_point) && (_tex_coords_obj == NULL)))
{
ERR("Allocate memory is failed.");
free(_vertices_obj);
- free(_normales_obj);
- free(_tex_coords_obj);
free(_triangles);
+ if (counts.existence_of_normal)
+ free(_normales_obj);
+ if (counts.existence_of_tex_point)
+ free(_tex_coords_obj);
return;
}
current = map;
i = 0;
-
/* put data to arrays */
for (; *current != '\00'; i++)
{
@@ -235,11 +285,17 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
break;
case 't':
current++;
- PUT_DATA_TO_ARRAY(tex_coords, texture_point)
+ if (counts.existence_of_tex_point)
+ {
+ PUT_DATA_TO_ARRAY(tex_coords, texture_point)
+ }
break;
case 'n':
current++;
- PUT_DATA_TO_ARRAY(normales, normal)
+ if (counts.existence_of_normal)
+ {
+ PUT_DATA_TO_ARRAY(normales, normal)
+ }
break;
default:
break;
@@ -249,49 +305,42 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
}
else if (first_char_is_f)
{
- char * auxiliary_pointer = current;
+ char *auxiliary_pointer = current;
int count_of_triangles_in_line;
+ int the_first_point = counts.current_triangles_counter;
_analyze_face_line(auxiliary_pointer,
&count_of_triangles_in_line);
current++;
i++;
- int first_pos, first_tex, first_norm;
- sscanf (current,"%i/%i/%i",
- &first_pos,
- &first_tex,
- &first_norm);
+ _read_point(_triangles, 1, counts,
+ the_first_point,
+ current);
- do
- {
- current++;
- i++;
- }
- while (*current != ' ');
-
- current++;
- i++;
+ AFTER_NEXT_SPACE(current)
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 != ' ')
+ if (counts.current_triangles_counter != the_first_point)
{
- current++;
- i++;
+ ARRAY_2D(_triangles, counts.current_triangles_counter, 0, 9) = \
+ ARRAY_2D(_triangles, the_first_point, 0, 9);
+ ARRAY_2D(_triangles, counts.current_triangles_counter, 1, 9) = \
+ ARRAY_2D(_triangles, the_first_point, 1, 9);
+ ARRAY_2D(_triangles, counts.current_triangles_counter, 2, 9) = \
+ ARRAY_2D(_triangles, the_first_point, 2, 9);
}
+ _read_point(_triangles, 2, counts,
+ counts.current_triangles_counter,
+ auxiliary_pointer);
+ AFTER_NEXT_SPACE(auxiliary_pointer);
+ _read_point(_triangles, 3, counts,
+ counts.current_triangles_counter,
+ auxiliary_pointer);
+ AFTER_NEXT_SPACE(current);
+
counts.current_triangles_counter++;
}
first_char_is_f = EINA_FALSE;
@@ -328,20 +377,26 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
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_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 (counts.existence_of_normal)
+ eo_do(mesh,
+ evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_NORMAL, 0, NULL),
+ nor = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_NORMAL),
+ stride_nor = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_NORMAL));
+
+ if (counts.existence_of_tex_point)
+ eo_do(mesh,
+ evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_TEXCOORD, 0, NULL),
+ tex = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_TEXCOORD),
+ 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;
+ if ((counts.existence_of_normal) && (stride_nor == 0))
+ stride_nor = sizeof(float) * 3;
+ if ((counts.existence_of_tex_point) && (stride_tex == 0))
+ stride_tex = sizeof(float) * 2;
for (j = 0; j < counts._triangles_counter; j++)
{
@@ -350,30 +405,43 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
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));
+ if (counts.existence_of_normal)
+ n = (float *)((char *)nor + stride_nor * (j * 3 + k));
+ if (counts.existence_of_tex_point)
+ 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);
+ if (counts.existence_of_normal)
+ {
+ 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);
+ if (counts.existence_of_tex_point)
+ {
+ 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);
+ if (counts.existence_of_normal)
+ free(_normales_obj);
+ if (counts.existence_of_tex_point)
+ 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));
+ eo_do(mesh, evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_POSITION));
+ if (counts.existence_of_normal)
+ eo_do(mesh, evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_NORMAL));
+ if (counts.existence_of_tex_point)
+ eo_do(mesh, 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);
@@ -388,4 +456,3 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
map = NULL;
}
}
-