summaryrefslogtreecommitdiff
path: root/src/modules/evas/model_loaders
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
parentc6c6233b50e0328d461158247a4e7db3b5890362 (diff)
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')
-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 64c4eb9..24f38c4 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 @@
12#define ARRAY_2D(name, x, y, count_y) (*(name + x * count_y + y)) 12#define ARRAY_2D(name, x, y, count_y) (*(name + x * count_y + y))
13 13
14/* read 3 float values in string and put it in array */ 14/* read 3 float values in string and put it in array */
15#define PUT_DATA_TO_ARRAY(array_name, name) \ 15#define PUT_DATA_TO_ARRAY(array_name, name) \
16 sscanf (current,"%f %f %f", \ 16 sscanf (current,"%f %f %f", \
17 &ARRAY_2D(_##array_name##_obj, counts.current_##name##_counter, 0, 3), \ 17 &ARRAY_2D(_##array_name##_obj, counts.current_##name##_counter, 0, 3), \
18 &ARRAY_2D(_##array_name##_obj, counts.current_##name##_counter, 1, 3), \ 18 &ARRAY_2D(_##array_name##_obj, counts.current_##name##_counter, 1, 3), \
19 &ARRAY_2D(_##array_name##_obj, counts.current_##name##_counter, 2, 3)); \ 19 &ARRAY_2D(_##array_name##_obj, counts.current_##name##_counter, 2, 3)); \
20 counts.current_##name##_counter++; 20 counts.current_##name##_counter++;
21 21
22#define AFTER_NEXT_SPACE(pointer)\
23 do \
24 { \
25 pointer++; \
26 i++; \
27 } \
28 while (*pointer != ' ');
29
22/* Structures for reading data from file. */ 30/* Structures for reading data from file. */
23typedef struct _OBJ_Counts OBJ_Counts; 31typedef struct _OBJ_Counts OBJ_Counts;
24 32
@@ -177,6 +185,37 @@ _count_elements(char *map)//count elements of mesh in .obj
177 return counts; 185 return counts;
178} 186}
179 187
188static void
189_read_point(int *triangles,
190 int num,
191 OBJ_Counts counts,
192 int num_cur,
193 char *pointer)
194{
195 if (counts.existence_of_normal)
196 {
197 if (counts.existence_of_tex_point)
198 sscanf(pointer, "%i/%i/%i",
199 &ARRAY_2D(triangles, num_cur, (num - 1) * 3, 9),
200 &ARRAY_2D(triangles, num_cur, (num - 1) * 3 + 1, 9),
201 &ARRAY_2D(triangles, num_cur, (num - 1) * 3 + 2, 9));
202 else
203 sscanf(pointer, "%i//%i",
204 &ARRAY_2D(triangles, num_cur, (num - 1) * 3, 9),
205 &ARRAY_2D(triangles, num_cur, (num - 1) * 3 + 2, 9));
206 }
207 else
208 {
209 if (counts.existence_of_tex_point)
210 sscanf(pointer, "%i/%i",
211 &ARRAY_2D(triangles, num_cur, (num - 1) * 3, 9),
212 &ARRAY_2D(triangles, num_cur, (num - 1) * 3 + 1, 9));
213 else
214 sscanf(pointer, "%i",
215 &ARRAY_2D(triangles, num_cur, (num - 1) * 3, 9));
216 }
217}
218
180void 219void
181evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file) 220evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
182{ 221{
@@ -187,8 +226,10 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
187 Eina_Bool first_char_is_f = EINA_FALSE; 226 Eina_Bool first_char_is_f = EINA_FALSE;
188 float *pos, *nor, *tex; 227 float *pos, *nor, *tex;
189 int stride_pos, stride_nor, stride_tex; 228 int stride_pos, stride_nor, stride_tex;
190 int j, k; 229 int j, k, data_for_one_point;
191 char *current, *map; 230 char *current, *map;
231 float *_vertices_obj, *_normales_obj, *_tex_coords_obj;
232 int *_triangles;
192 233
193 map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL); 234 map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL);
194 235
@@ -199,27 +240,36 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
199 } 240 }
200 241
201 counts = _count_elements(map); 242 counts = _count_elements(map);
243 _vertices_obj = malloc(counts._vertex_counter * 3 * sizeof(float));
244 data_for_one_point = 1;
245 if (counts.existence_of_normal)
246 {
247 data_for_one_point++;
248 _normales_obj = malloc(counts._normal_counter * 3 * sizeof(float));
249 }
250 if (counts.existence_of_tex_point)
251 {
252 data_for_one_point++;
253 _tex_coords_obj = malloc(counts._texture_point_counter * 3 * sizeof(float));
254 }
255 _triangles = malloc(counts._triangles_counter * 9 * sizeof(int));
202 256
203 float *_vertices_obj = malloc(counts._vertex_counter * 3 * sizeof(float)); 257 if ((map == NULL) || (_vertices_obj == NULL) || (_triangles == NULL) ||
204 float *_normales_obj = malloc(counts._normal_counter * 3 * sizeof(float)); 258 ((counts.existence_of_normal) && (_normales_obj == NULL)) ||
205 float *_tex_coords_obj = malloc(counts._texture_point_counter * 3 * sizeof(float)); 259 ((counts.existence_of_tex_point) && (_tex_coords_obj == NULL)))
206 /* triangle has 3 points, every point has 3(vertix, texture and normal) coord */
207 int *_triangles = malloc(counts._triangles_counter * 9 * sizeof(int));
208
209 if ((map == NULL) || (_vertices_obj == NULL) ||
210 (_normales_obj == NULL) || (_tex_coords_obj == NULL) || (_triangles == NULL))
211 { 260 {
212 ERR("Allocate memory is failed."); 261 ERR("Allocate memory is failed.");
213 free(_vertices_obj); 262 free(_vertices_obj);
214 free(_normales_obj);
215 free(_tex_coords_obj);
216 free(_triangles); 263 free(_triangles);
264 if (counts.existence_of_normal)
265 free(_normales_obj);
266 if (counts.existence_of_tex_point)
267 free(_tex_coords_obj);
217 return; 268 return;
218 } 269 }
219 270
220 current = map; 271 current = map;
221 i = 0; 272 i = 0;
222
223 /* put data to arrays */ 273 /* put data to arrays */
224 for (; *current != '\00'; i++) 274 for (; *current != '\00'; i++)
225 { 275 {
@@ -235,11 +285,17 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
235 break; 285 break;
236 case 't': 286 case 't':
237 current++; 287 current++;
238 PUT_DATA_TO_ARRAY(tex_coords, texture_point) 288 if (counts.existence_of_tex_point)
289 {
290 PUT_DATA_TO_ARRAY(tex_coords, texture_point)
291 }
239 break; 292 break;
240 case 'n': 293 case 'n':
241 current++; 294 current++;
242 PUT_DATA_TO_ARRAY(normales, normal) 295 if (counts.existence_of_normal)
296 {
297 PUT_DATA_TO_ARRAY(normales, normal)
298 }
243 break; 299 break;
244 default: 300 default:
245 break; 301 break;
@@ -249,49 +305,42 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
249 } 305 }
250 else if (first_char_is_f) 306 else if (first_char_is_f)
251 { 307 {
252 char * auxiliary_pointer = current; 308 char *auxiliary_pointer = current;
253 int count_of_triangles_in_line; 309 int count_of_triangles_in_line;
310 int the_first_point = counts.current_triangles_counter;
254 311
255 _analyze_face_line(auxiliary_pointer, 312 _analyze_face_line(auxiliary_pointer,
256 &count_of_triangles_in_line); 313 &count_of_triangles_in_line);
257 current++; 314 current++;
258 i++; 315 i++;
259 int first_pos, first_tex, first_norm; 316 _read_point(_triangles, 1, counts,
260 sscanf (current,"%i/%i/%i", 317 the_first_point,
261 &first_pos, 318 current);
262 &first_tex,
263 &first_norm);
264 319
265 do 320 AFTER_NEXT_SPACE(current)
266 {
267 current++;
268 i++;
269 }
270 while (*current != ' ');
271
272 current++;
273 i++;
274 321
275 for (j = 0; j < count_of_triangles_in_line; j++) 322 for (j = 0; j < count_of_triangles_in_line; j++)
276 { 323 {
277 auxiliary_pointer = current; 324 auxiliary_pointer = current;
278 ARRAY_2D(_triangles, counts.current_triangles_counter, 0, 9) = first_pos; 325 if (counts.current_triangles_counter != the_first_point)
279 ARRAY_2D(_triangles, counts.current_triangles_counter, 1, 9) = first_tex;
280 ARRAY_2D(_triangles, counts.current_triangles_counter, 2, 9) = first_norm;
281 sscanf (auxiliary_pointer,"%i/%i/%i %i/%i/%i",
282 &ARRAY_2D(_triangles, counts.current_triangles_counter, 3, 9),
283 &ARRAY_2D(_triangles, counts.current_triangles_counter, 4, 9),
284 &ARRAY_2D(_triangles, counts.current_triangles_counter, 5, 9),
285 &ARRAY_2D(_triangles, counts.current_triangles_counter, 6, 9),
286 &ARRAY_2D(_triangles, counts.current_triangles_counter, 7, 9),
287 &ARRAY_2D(_triangles, counts.current_triangles_counter, 8, 9));
288
289 while (*current != ' ')
290 { 326 {
291 current++; 327 ARRAY_2D(_triangles, counts.current_triangles_counter, 0, 9) = \
292 i++; 328 ARRAY_2D(_triangles, the_first_point, 0, 9);
329 ARRAY_2D(_triangles, counts.current_triangles_counter, 1, 9) = \
330 ARRAY_2D(_triangles, the_first_point, 1, 9);
331 ARRAY_2D(_triangles, counts.current_triangles_counter, 2, 9) = \
332 ARRAY_2D(_triangles, the_first_point, 2, 9);
293 } 333 }
294 334
335 _read_point(_triangles, 2, counts,
336 counts.current_triangles_counter,
337 auxiliary_pointer);
338 AFTER_NEXT_SPACE(auxiliary_pointer);
339 _read_point(_triangles, 3, counts,
340 counts.current_triangles_counter,
341 auxiliary_pointer);
342 AFTER_NEXT_SPACE(current);
343
295 counts.current_triangles_counter++; 344 counts.current_triangles_counter++;
296 } 345 }
297 first_char_is_f = EINA_FALSE; 346 first_char_is_f = EINA_FALSE;
@@ -328,20 +377,26 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
328 evas_3d_mesh_vertex_assembly_set(EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES), 377 evas_3d_mesh_vertex_assembly_set(EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES),
329 evas_3d_mesh_frame_add(0), 378 evas_3d_mesh_frame_add(0),
330 evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_POSITION, 0, NULL), 379 evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_POSITION, 0, NULL),
331 evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_NORMAL, 0, NULL),
332 evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_TEXCOORD, 0, NULL),
333
334 pos = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_POSITION), 380 pos = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_POSITION),
335 nor = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_NORMAL), 381 stride_pos = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_POSITION));
336 tex = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_TEXCOORD),
337 382
338 stride_pos = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_POSITION), 383 if (counts.existence_of_normal)
339 stride_nor = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_NORMAL), 384 eo_do(mesh,
340 stride_tex = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_TEXCOORD)); 385 evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_NORMAL, 0, NULL),
386 nor = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_NORMAL),
387 stride_nor = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_NORMAL));
388
389 if (counts.existence_of_tex_point)
390 eo_do(mesh,
391 evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_TEXCOORD, 0, NULL),
392 tex = (float *)evas_3d_mesh_frame_vertex_data_map(0, EVAS_3D_VERTEX_TEXCOORD),
393 stride_tex = evas_3d_mesh_frame_vertex_stride_get(0, EVAS_3D_VERTEX_TEXCOORD));
341 394
342 if (stride_pos == 0) stride_pos = sizeof(float) * 3; 395 if (stride_pos == 0) stride_pos = sizeof(float) * 3;
343 if (stride_nor == 0) stride_nor = sizeof(float) * 3; 396 if ((counts.existence_of_normal) && (stride_nor == 0))
344 if (stride_tex == 0) stride_tex = sizeof(float) * 2; 397 stride_nor = sizeof(float) * 3;
398 if ((counts.existence_of_tex_point) && (stride_tex == 0))
399 stride_tex = sizeof(float) * 2;
345 400
346 for (j = 0; j < counts._triangles_counter; j++) 401 for (j = 0; j < counts._triangles_counter; j++)
347 { 402 {
@@ -350,30 +405,43 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
350 float *p, *n, *t; 405 float *p, *n, *t;
351 406
352 p = (float *)((char *)pos + stride_pos * (j * 3 + k)); 407 p = (float *)((char *)pos + stride_pos * (j * 3 + k));
353 n = (float *)((char *)nor + stride_nor * (j * 3 + k)); 408 if (counts.existence_of_normal)
354 t = (float *)((char *)tex + stride_tex * (j * 3 + k)); 409 n = (float *)((char *)nor + stride_nor * (j * 3 + k));
410 if (counts.existence_of_tex_point)
411 t = (float *)((char *)tex + stride_tex * (j * 3 + k));
355 412
356 p[0] = ARRAY_2D(_vertices_obj, (ARRAY_2D(_triangles, j, (3 * k), 9) - 1), 0, 3); 413 p[0] = ARRAY_2D(_vertices_obj, (ARRAY_2D(_triangles, j, (3 * k), 9) - 1), 0, 3);
357 p[1] = ARRAY_2D(_vertices_obj, (ARRAY_2D(_triangles, j, (3 * k), 9) - 1), 1, 3); 414 p[1] = ARRAY_2D(_vertices_obj, (ARRAY_2D(_triangles, j, (3 * k), 9) - 1), 1, 3);
358 p[2] = ARRAY_2D(_vertices_obj, (ARRAY_2D(_triangles, j, (3 * k), 9) - 1), 2, 3); 415 p[2] = ARRAY_2D(_vertices_obj, (ARRAY_2D(_triangles, j, (3 * k), 9) - 1), 2, 3);
359 416
360 n[0] = ARRAY_2D(_normales_obj, (ARRAY_2D(_triangles, j, (3 * k + 2), 9) - 1), 0, 3); 417 if (counts.existence_of_normal)
361 n[1] = ARRAY_2D(_normales_obj, (ARRAY_2D(_triangles, j, (3 * k + 2), 9) - 1), 1, 3); 418 {
362 n[2] = ARRAY_2D(_normales_obj, (ARRAY_2D(_triangles, j, (3 * k + 2), 9) - 1), 2, 3); 419 n[0] = ARRAY_2D(_normales_obj, (ARRAY_2D(_triangles, j, (3 * k + 2), 9) - 1), 0, 3);
420 n[1] = ARRAY_2D(_normales_obj, (ARRAY_2D(_triangles, j, (3 * k + 2), 9) - 1), 1, 3);
421 n[2] = ARRAY_2D(_normales_obj, (ARRAY_2D(_triangles, j, (3 * k + 2), 9) - 1), 2, 3);
422 }
363 423
364 t[0] = ARRAY_2D(_tex_coords_obj, (ARRAY_2D(_triangles, j, (3 * k + 1), 9) - 1), 0, 3); 424 if (counts.existence_of_tex_point)
365 t[1] = ARRAY_2D(_tex_coords_obj, (ARRAY_2D(_triangles, j, (3 * k + 1), 9) - 1), 1, 3); 425 {
426 t[0] = ARRAY_2D(_tex_coords_obj, (ARRAY_2D(_triangles, j, (3 * k + 1), 9) - 1), 0, 3);
427 t[1] = ARRAY_2D(_tex_coords_obj, (ARRAY_2D(_triangles, j, (3 * k + 1), 9) - 1), 1, 3);
428 }
366 } 429 }
367 } 430 }
431
368 free(_vertices_obj); 432 free(_vertices_obj);
369 free(_normales_obj); 433 if (counts.existence_of_normal)
370 free(_tex_coords_obj); 434 free(_normales_obj);
435 if (counts.existence_of_tex_point)
436 free(_tex_coords_obj);
371 free(_triangles); 437 free(_triangles);
438
372 /* Unmap vertex buffer. */ 439 /* Unmap vertex buffer. */
373 eo_do(mesh, 440 eo_do(mesh, evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_POSITION));
374 evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_POSITION), 441 if (counts.existence_of_normal)
375 evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_NORMAL), 442 eo_do(mesh, evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_NORMAL));
376 evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_TEXCOORD)); 443 if (counts.existence_of_tex_point)
444 eo_do(mesh, evas_3d_mesh_frame_vertex_data_unmap(0, EVAS_3D_VERTEX_TEXCOORD));
377 445
378 Evas_3D_Mesh_Data *pd = eo_data_scope_get(mesh, EVAS_3D_MESH_CLASS); 446 Evas_3D_Mesh_Data *pd = eo_data_scope_get(mesh, EVAS_3D_MESH_CLASS);
379 447
@@ -388,4 +456,3 @@ evas_model_load_file_obj(Evas_3D_Mesh *mesh, Eina_File *file)
388 map = NULL; 456 map = NULL;
389 } 457 }
390} 458}
391