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>
This commit is contained in:
Bogdan Devichev 2015-02-11 18:13:58 +01:00 committed by Cedric BAIL
parent c6c6233b50
commit 1506130866
15 changed files with 764 additions and 2650 deletions

View File

@ -1,10 +1,12 @@
/**
* Simple Evas example illustrating import/export of .obj format.
* Example demonstrate possibility to load and save mesh without tex_coords or/and normals.
*
* Read mesh from "man_mesh.obj".
* Read mesh from "sweet_home(parameters).obj".
* After that cheange some properties of material.
* After that save material to "saved_man.mtl"
* and geometry to "saved_man.obj".
* After that save material to "saved_home(parameters).mtl"
* and geometry to "saved_home(parameters).obj".
* If material was not set it will be not saved.
*
* @verbatim
* gcc -o evas-3d-obj evas-3d-obj.c `pkg-config --libs --cflags efl evas ecore ecore-evas eo`
@ -19,8 +21,65 @@
#include <Ecore.h>
#include <Ecore_Evas.h>
#define WIDTH 400
#define HEIGHT 400
#define WIDTH 1900
#define HEIGHT 1080
#define COL_LITTLE 0.2
#define COL_BIG 1.0
#define COL_RED COL_BIG, COL_LITTLE, COL_LITTLE
#define COL_GREEN COL_LITTLE, COL_BIG, COL_LITTLE
#define COL_BLUE COL_LITTLE, COL_LITTLE, COL_BIG
#define ANIM_SPEED 0.02
#define COPY_OFFSET 5
#define GRID_SIZE 6
#define NUMBER_OF_MESHES 8
#define RESOURCE_FOLDER "obj_files/"
#define ADD_OBJ_MESH(path, Y, Z, num, shade_mode, name_of_material) \
mesh[num] = eo_add(EVAS_3D_MESH_CLASS, evas); \
eo_do(mesh[num], \
efl_file_set(RESOURCE_FOLDER#path".obj", NULL), \
evas_3d_mesh_frame_material_set(0, name_of_material), \
evas_3d_mesh_shade_mode_set(shade_mode)); \
mesh_node[num] = 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[num])); \
eo_do(mesh_node[num], \
evas_3d_node_mesh_add(mesh[num]), \
evas_3d_node_position_set(0, Y, Z)); \
#define ADD_OBJ_MESH_AND_SAVED_COPY(path, Y, Z, num, shade_mode, name_of_material) \
ADD_OBJ_MESH(sweet_##path, Y, Z, num, shade_mode, name_of_material) \
eo_do(mesh[num], efl_file_save(RESOURCE_FOLDER"saved_"#path".obj", NULL, NULL)); \
ADD_OBJ_MESH(saved_##path, Y + COPY_OFFSET, Z, num + 4, shade_mode, name_of_material)
#define ADD_TEXTURE(name, path) \
name = eo_add(EVAS_3D_TEXTURE_CLASS, evas); \
eo_do(name, \
evas_3d_texture_file_set(path, 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));
#define ADD_MATERIAL(name) \
name = eo_add(EVAS_3D_MATERIAL_CLASS, evas); \
eo_do(name, \
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, \
COL_RED, 0.5), \
evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, \
COL_GREEN, 0.5), \
evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, \
COL_BLUE, 0.5), \
evas_3d_material_shininess_set(100.0));
Ecore_Evas *ecore_evas = NULL;
Evas *evas = NULL;
@ -32,8 +91,9 @@ Eo *root_node = NULL;
Eo *camera_node = NULL;
Eo *light_node = NULL;
Eo *camera = NULL;
Eo *mesh_node = NULL;
Eo *mesh = NULL;
Eo *mesh[NUMBER_OF_MESHES];
Eo *mesh_node[NUMBER_OF_MESHES];
Eo *material_with_tex = NULL;
Eo *material = NULL;
Eo *texture = NULL;
Eo *light = NULL;
@ -43,9 +103,10 @@ static float angle = 0;
static Eina_Bool
_animate_scene(void *data)
{
angle += 0.5;
angle += 0.2;
eo_do((Evas_3D_Node *)data, evas_3d_node_orientation_angle_axis_set(angle, 1.0, 1.0, 1.0));
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;
@ -72,6 +133,7 @@ _on_canvas_resize(Ecore_Evas *ee)
int
main(void)
{
int i;
//Unless Evas 3D supports Software renderer, we set gl backened forcely.
setenv("ECORE_EVAS_ENGINE", "opengl_x11", 1);
@ -92,23 +154,23 @@ main(void)
/* 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));
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));
evas_3d_camera_projection_perspective_set(20.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));
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_node_position_set(100.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);
@ -120,53 +182,31 @@ main(void)
light_node =
eo_add(EVAS_3D_NODE_CLASS, evas,
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_LIGHT));
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_position_set(10.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, 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);
ADD_TEXTURE(texture, "sweet_home_reversed.png")
eo_do(mesh,
efl_file_set("man_mesh.obj", NULL),
evas_3d_mesh_frame_material_set(0, material),
evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_PHONG));
ADD_MATERIAL(material)
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_MATERIAL(material_with_tex)
eo_do(material_with_tex,
evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, texture));
eo_do(mesh, efl_file_save("saved_man.obj", NULL, NULL));
mesh_node = 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));
eo_do(mesh_node,
evas_3d_node_mesh_add(mesh));
ADD_OBJ_MESH_AND_SAVED_COPY(home, -GRID_SIZE, -GRID_SIZE, 0,
EVAS_3D_SHADE_MODE_PHONG, material_with_tex)
ADD_OBJ_MESH_AND_SAVED_COPY(home_without_normals, -GRID_SIZE, GRID_SIZE, 1,
EVAS_3D_SHADE_MODE_DIFFUSE, material_with_tex)
ADD_OBJ_MESH_AND_SAVED_COPY(home_without_tex_coords, GRID_SIZE, -GRID_SIZE, 2,
EVAS_3D_SHADE_MODE_PHONG, material)
ADD_OBJ_MESH_AND_SAVED_COPY(home_only_vertex_coords, GRID_SIZE, GRID_SIZE, 3,
EVAS_3D_SHADE_MODE_SHADOW_MAP_RENDER, NULL)
/* Set up scene. */
eo_do(scene,
@ -174,7 +214,7 @@ main(void)
evas_3d_scene_camera_node_set(camera_node),
evas_3d_scene_size_set(WIDTH, HEIGHT));
/* Add a background rectangle objects. */
/* Add a background rectangle MESHES. */
background = eo_add(EVAS_RECTANGLE_CLASS, evas);
eo_do(background,
evas_obj_color_set(0, 0, 0, 255),
@ -190,7 +230,8 @@ main(void)
/* 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);
for (i = 0; i < NUMBER_OF_MESHES; i++)
ecore_timer_add(ANIM_SPEED, _animate_scene, mesh_node[i]);
/* Enter main loop. */
ecore_main_loop_begin();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
# Blender MTL File: 'sweet_home.blend'
# Material Count: 2
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
map_Kd /home/bdevichev/Desktop/rect.png
newmtl Material_Untitled
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
map_Kd /home/bdevichev/Desktop/sweet_home.png

View File

@ -0,0 +1,107 @@
# Blender v2.69 (sub 0) OBJ File: 'sweet_home.blend'
# www.blender.org
v 1.000003 -0.999997 0.000002
v -0.999997 -1.000003 0.000002
v -1.000002 0.999998 0.000002
v 0.999998 1.000002 0.000002
v 1.000002 -0.999998 2.000002
v -0.999998 -1.000002 2.000002
v -1.000002 0.999998 2.000002
v 0.999997 1.000003 2.000002
v 0.000002 -1.000000 3.075149
v -0.000002 1.000000 3.075149
v 0.666668 -0.644449 2.358384
v 0.333335 -0.644450 2.716766
v 0.666667 -0.293067 2.358384
v 0.333334 -0.293068 2.716766
v 0.662209 -0.629904 2.991038
v 0.337794 -0.629904 2.980731
v 0.662208 -0.307612 2.991038
v 0.337793 -0.307613 2.980731
vt 0.013689 0.608350
vt 0.285640 0.608350
vt 0.285640 0.978776
vt 0.013689 0.978776
vt 0.564957 0.983606
vt 0.293719 0.983606
vt 0.293719 0.613180
vt 0.564957 0.613180
vt 0.646856 0.021326
vt 0.083404 0.021326
vt 0.083369 0.584801
vt 0.646820 0.584801
vt 0.949735 0.303064
vt 0.654355 0.022016
vt 0.957234 0.303753
vt 0.654320 0.585490
vt 0.090869 0.585491
vt 0.090904 0.022016
vt 0.820337 0.692442
vt 0.820337 0.803140
vt 0.740863 0.803140
vt 0.740863 0.692442
vt 0.695284 0.903159
vt 0.695284 0.830265
vt 0.768687 0.830265
vt 0.768687 0.903159
vt 0.874667 0.789013
vt 0.874667 0.893367
vt 0.979009 0.893367
vt 0.979009 0.789013
vt 0.567834 0.981515
vt 0.567834 0.611089
vt 0.768686 0.903159
vt 0.768687 0.823686
vt 0.811715 0.826975
vt 0.811715 0.899870
vt 0.591196 0.903159
vt 0.591196 0.823686
vt 0.695284 0.826975
vt 0.695284 0.899870
vt 0.666035 0.721564
vt 0.667476 0.661838
vt 0.740863 0.660019
vt 0.591196 0.741571
vt 0.666035 0.660015
vt 0.666035 0.803140
vt 0.592658 0.801339
vt 0.013481 0.981515
vt 0.104078 0.915663
vt 0.194676 0.915663
vt 0.285274 0.981515
vt 0.194676 0.850582
vt 0.285274 0.611089
vt 0.104078 0.850582
vt 0.013481 0.611089
vn -0.732233 -0.000002 0.681054
vn 1.000000 0.000002 0.000000
vn 0.000002 -1.000000 0.000000
vn -0.000002 1.000000 -0.000000
vn -0.732233 -0.000001 -0.681054
vn -0.031755 -0.000000 0.999496
vn -0.000000 0.000000 -1.000000
vn -1.000000 -0.000002 -0.000000
vn -0.999857 -0.000002 0.016891
vn 0.999975 0.000002 0.007049
vn 0.017155 0.999327 0.032422
vn 0.017160 -0.999327 0.032422
vn 0.732233 0.000001 0.681054
vn 0.732233 0.000002 0.681054
vn 0.732234 0.000002 0.681053
s off
f 6/1/1 9/2/1 10/3/1 7/4/1
f 4/5/2 8/6/2 5/7/2 1/8/2
f 6/9/3 2/10/3 1/11/3 5/12/3 9/13/3
f 7/14/4 10/15/4 8/16/4 4/17/4 3/18/4
f 11/19/5 12/20/5 14/21/5 13/22/5
f 15/23/6 17/24/6 18/25/6 16/26/6
f 2/27/7 3/28/7 4/29/7 1/30/7
f 6/2/8 7/3/8 3/31/8 2/32/8
f 14/33/9 12/34/9 16/35/9 18/36/9
f 11/37/10 13/38/10 17/39/10 15/40/10
f 13/21/11 14/41/11 18/42/11 17/43/11
f 12/44/12 11/45/12 15/46/12 16/47/12
f 5/48/13 11/49/13 12/50/13 9/51/13
f 9/51/14 12/50/14 14/52/14 10/53/14
f 13/54/14 8/55/14 10/53/14 14/52/14
f 11/49/15 5/48/15 8/55/15 13/54/15

View File

@ -1,4 +1,4 @@
# Blender MTL File: 'None'
# Blender MTL File: 'sweet_home.blend'
# Material Count: 1
newmtl Material
@ -9,3 +9,4 @@ Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
map_Kd /home/bdevichev/Desktop/rect.png

View File

@ -0,0 +1,40 @@
# Blender v2.69 (sub 0) OBJ File: 'sweet_home.blend'
# www.blender.org
mtllib sweet_home_only_vertex_coords.mtl
o Cube
v 1.000003 -0.999997 0.000002
v -0.999997 -1.000003 0.000002
v -1.000002 0.999998 0.000002
v 0.999998 1.000002 0.000002
v 1.000002 -0.999998 2.000002
v -0.999998 -1.000002 2.000002
v -1.000002 0.999998 2.000002
v 0.999997 1.000003 2.000002
v 0.000002 -1.000000 3.075149
v -0.000002 1.000000 3.075149
v 0.666668 -0.644449 2.358384
v 0.333335 -0.644450 2.716766
v 0.666667 -0.293067 2.358384
v 0.333334 -0.293068 2.716766
v 0.662209 -0.629904 2.991038
v 0.337794 -0.629904 2.980731
v 0.662208 -0.307612 2.991038
v 0.337793 -0.307613 2.980731
usemtl Material
s off
f 4 8 5 1
f 6 2 1 5 9
f 7 10 8 4 3
f 11 12 14 13
f 15 17 18 16
f 2 3 4 1
f 6 7 3 2
f 6 9 10 7
f 14 12 16 18
f 11 13 17 15
f 13 14 18 17
f 12 11 15 16
f 5 11 12 9
f 9 12 14 10
f 13 8 10 14
f 11 5 8 13

View File

@ -0,0 +1,22 @@
# Blender MTL File: 'sweet_home.blend'
# Material Count: 2
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
map_Kd /home/bdevichev/Desktop/rect.png
newmtl Material_Untitled
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
map_Kd /home/bdevichev/Desktop/sweet_home.png

View File

@ -0,0 +1,96 @@
# Blender v2.69 (sub 0) OBJ File: 'sweet_home.blend'
# www.blender.org
mtllib sweet_home_without_normals.mtl
o Cube
v 1.000003 -0.999997 0.000002
v -0.999997 -1.000003 0.000002
v -1.000002 0.999998 0.000002
v 0.999998 1.000002 0.000002
v 1.000002 -0.999998 2.000002
v -0.999998 -1.000002 2.000002
v -1.000002 0.999998 2.000002
v 0.999997 1.000003 2.000002
v 0.000002 -1.000000 3.075149
v -0.000002 1.000000 3.075149
v 0.666668 -0.644449 2.358384
v 0.333335 -0.644450 2.716766
v 0.666667 -0.293067 2.358384
v 0.333334 -0.293068 2.716766
v 0.662209 -0.629904 2.991038
v 0.337794 -0.629904 2.980731
v 0.662208 -0.307612 2.991038
v 0.337793 -0.307613 2.980731
vt 0.013689 0.608350
vt 0.285640 0.608350
vt 0.285640 0.978776
vt 0.013689 0.978776
vt 0.564957 0.983606
vt 0.293719 0.983606
vt 0.293719 0.613180
vt 0.564957 0.613180
vt 0.646856 0.021326
vt 0.083404 0.021326
vt 0.083369 0.584801
vt 0.646820 0.584801
vt 0.949735 0.303064
vt 0.654355 0.022016
vt 0.957234 0.303753
vt 0.654320 0.585490
vt 0.090869 0.585491
vt 0.090904 0.022016
vt 0.820337 0.692442
vt 0.820337 0.803140
vt 0.740863 0.803140
vt 0.740863 0.692442
vt 0.695284 0.903159
vt 0.695284 0.830265
vt 0.768687 0.830265
vt 0.768687 0.903159
vt 0.874667 0.789013
vt 0.874667 0.893367
vt 0.979009 0.893367
vt 0.979009 0.789013
vt 0.567834 0.981515
vt 0.567834 0.611089
vt 0.768686 0.903159
vt 0.768687 0.823686
vt 0.811715 0.826975
vt 0.811715 0.899870
vt 0.591196 0.903159
vt 0.591196 0.823686
vt 0.695284 0.826975
vt 0.695284 0.899870
vt 0.666035 0.721564
vt 0.667476 0.661838
vt 0.740863 0.660019
vt 0.591196 0.741571
vt 0.666035 0.660015
vt 0.666035 0.803140
vt 0.592658 0.801339
vt 0.013481 0.981515
vt 0.104078 0.915663
vt 0.194676 0.915663
vt 0.285274 0.981515
vt 0.194676 0.850582
vt 0.285274 0.611089
vt 0.104078 0.850582
vt 0.013481 0.611089
usemtl Material
s off
f 6/1 9/2 10/3 7/4
usemtl Material_Untitled
f 4/5 8/6 5/7 1/8
f 6/9 2/10 1/11 5/12 9/13
f 7/14 10/15 8/16 4/17 3/18
f 11/19 12/20 14/21 13/22
f 15/23 17/24 18/25 16/26
f 2/27 3/28 4/29 1/30
f 6/2 7/3 3/31 2/32
f 14/33 12/34 16/35 18/36
f 11/37 13/38 17/39 15/40
f 13/21 14/41 18/42 17/43
f 12/44 11/45 15/46 16/47
f 5/48 11/49 12/50 9/51
f 9/51 12/50 14/52 10/53
f 13/54 8/55 10/53 14/52
f 11/49 5/48 8/55 13/54

View File

@ -0,0 +1,12 @@
# Blender MTL File: 'sweet_home.blend'
# 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
map_Kd /home/bdevichev/Desktop/rect.png

View File

@ -0,0 +1,55 @@
# Blender v2.69 (sub 0) OBJ File: 'sweet_home.blend'
# www.blender.org
mtllib sweet_home_without_tex_coords.mtl
o Cube
v 1.000003 -0.999997 0.000002
v -0.999997 -1.000003 0.000002
v -1.000002 0.999998 0.000002
v 0.999998 1.000002 0.000002
v 1.000002 -0.999998 2.000002
v -0.999998 -1.000002 2.000002
v -1.000002 0.999998 2.000002
v 0.999997 1.000003 2.000002
v 0.000002 -1.000000 3.075149
v -0.000002 1.000000 3.075149
v 0.666668 -0.644449 2.358384
v 0.333335 -0.644450 2.716766
v 0.666667 -0.293067 2.358384
v 0.333334 -0.293068 2.716766
v 0.662209 -0.629904 2.991038
v 0.337794 -0.629904 2.980731
v 0.662208 -0.307612 2.991038
v 0.337793 -0.307613 2.980731
vn 1.000000 0.000002 0.000000
vn 0.000002 -1.000000 0.000000
vn -0.000002 1.000000 -0.000000
vn -0.732233 -0.000001 -0.681054
vn -0.031755 -0.000000 0.999496
vn -0.000000 0.000000 -1.000000
vn -1.000000 -0.000002 -0.000000
vn -0.732233 -0.000002 0.681054
vn -0.999857 -0.000002 0.016891
vn 0.999975 0.000002 0.007049
vn 0.017155 0.999327 0.032422
vn 0.017160 -0.999327 0.032422
vn 0.732233 0.000001 0.681054
vn 0.732233 0.000002 0.681054
vn 0.732234 0.000002 0.681053
usemtl Material
s off
f 4//1 8//1 5//1 1//1
f 6//2 2//2 1//2 5//2 9//2
f 7//3 10//3 8//3 4//3 3//3
f 11//4 12//4 14//4 13//4
f 15//5 17//5 18//5 16//5
f 2//6 3//6 4//6 1//6
f 6//7 7//7 3//7 2//7
f 6//8 9//8 10//8 7//8
f 14//9 12//9 16//9 18//9
f 11//10 13//10 17//10 15//10
f 13//11 14//11 18//11 17//11
f 12//12 11//12 15//12 16//12
f 5//13 11//13 12//13 9//13
f 9//14 12//14 14//14 10//14
f 13//14 8//14 10//14 14//14
f 11//15 5//15 8//15 13//15

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 KiB

View File

@ -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;
}
}

View File

@ -9,24 +9,53 @@
#include "evas_private.h"
#define OPEN_FILE(extension)\
FILE * _##extension##_file = fopen(_##extension##_file_name, "w+");\
FILE * _##extension##_file = fopen(_##extension##_file_name, "w+");
#define SAVE_GEOMETRICS(a, format)\
vb = &f->vertices[a];\
fprintf(_obj_file, "o %s\n",_obj_file_name);\
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;\
#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_3D_VERTEX_TEXCOORD) \
fprintf(_obj_file, " %.4f", src[2]); \
fprintf(_obj_file, "\n"); \
src += f->vertices[a].element_count; \
} \
}
static void
_write_point(FILE * obj_file,
int num,
int num_of_point,
Eina_Bool existence_of_normal,
Eina_Bool existence_of_tex_point)
{
if (num_of_point == 1)
fprintf(obj_file, "f ");
if (existence_of_normal)
{
if (existence_of_tex_point)
fprintf(obj_file, "%i/%i/%i ", num, num, num);
else
fprintf(obj_file, "%i//%i ", num, num);
}
else
{
if (existence_of_tex_point)
fprintf(obj_file, "%i/%i ", num, num);
else
fprintf(obj_file, "%i ", num);
}
if (num_of_point == 3)
fprintf(obj_file, "\n");
}
static void
_save_mesh(Evas_3D_Mesh_Data *pd, const char *_obj_file_name, Evas_3D_Mesh_Frame *f)
{
@ -35,6 +64,7 @@ _save_mesh(Evas_3D_Mesh_Data *pd, const char *_obj_file_name, Evas_3D_Mesh_Frame
char* c_time_string;
int i;
float *src;
Eina_Bool existence_of_normal, existence_of_tex_point;
OPEN_FILE(obj)
if (!_obj_file)
@ -73,26 +103,30 @@ _save_mesh(Evas_3D_Mesh_Data *pd, const char *_obj_file_name, Evas_3D_Mesh_Frame
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")
SAVE_GEOMETRICS(EVAS_3D_VERTEX_POSITION, "v %.4f %.4f")
SAVE_GEOMETRICS(EVAS_3D_VERTEX_NORMAL, "vn %.4f %.4f")
SAVE_GEOMETRICS(EVAS_3D_VERTEX_TEXCOORD, "vt %.4f %.4f")
existence_of_normal = (f->vertices[EVAS_3D_VERTEX_NORMAL].data != NULL);
existence_of_tex_point = (f->vertices[EVAS_3D_VERTEX_TEXCOORD].data != NULL);
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);
_write_point(_obj_file, i, 1, existence_of_normal, existence_of_tex_point);
i++;
fprintf(_obj_file,"%i/%i/%i ", i, i, i);
_write_point(_obj_file, i, 2, existence_of_normal, existence_of_tex_point);
i++;
fprintf(_obj_file,"%i/%i/%i \n", i, i, i);
_write_point(_obj_file, i, 3, existence_of_normal, existence_of_tex_point);
}
fclose(_obj_file);
}
static void
_save_material(Evas_3D_Mesh_Data *pd EINA_UNUSED, const char *_mtl_file_name, Evas_3D_Mesh_Frame *f)
_save_material(Evas_3D_Mesh_Data *pd EINA_UNUSED,
const char *_mtl_file_name,
Evas_3D_Material_Data *mat)
{
Evas_3D_Material_Data *mat = eo_data_scope_get(f->material, EVAS_3D_MATERIAL_CLASS);
OPEN_FILE(mtl)
if (!_mtl_file)
{
@ -126,21 +160,24 @@ void
evas_model_save_file_obj(Evas_3D_Mesh *mesh, const char *_obj_file_name, Evas_3D_Mesh_Frame *f)
{
int len;
char *without_extention, *_mtl_extension, *_mtl_file_name;
char *_mtl_file_name, *_without_extention;
Evas_3D_Material_Data *mat;
len = strlen(_obj_file_name);
without_extention = (char*)malloc((len - 4) * sizeof(char));
_mtl_extension = ".mtl";
_mtl_file_name = (char *)malloc(len * sizeof(char));
memcpy(without_extention, _obj_file_name, len-4);
strcpy(_mtl_file_name, without_extention);
strcpy(_mtl_file_name + len - 4, _mtl_extension);
_without_extention = (char *)malloc(len - 3);
_mtl_file_name = (char *)malloc(len + 1);
Evas_3D_Mesh_Data *pd = eo_data_scope_get(mesh, EVAS_3D_MESH_CLASS);
_save_mesh(pd, _obj_file_name, f);
_save_material(pd, _mtl_file_name, f);
free(without_extention);
mat = eo_data_scope_get(f->material, EVAS_3D_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);
}
free(_without_extention);
free(_mtl_file_name);
}

View File

@ -0,0 +1,107 @@
# Blender v2.69 (sub 0) OBJ File: 'sweet_home.blend'
# www.blender.org
v 1.000003 -0.999997 0.000002
v -0.999997 -1.000003 0.000002
v -1.000002 0.999998 0.000002
v 0.999998 1.000002 0.000002
v 1.000002 -0.999998 2.000002
v -0.999998 -1.000002 2.000002
v -1.000002 0.999998 2.000002
v 0.999997 1.000003 2.000002
v 0.000002 -1.000000 3.075149
v -0.000002 1.000000 3.075149
v 0.666668 -0.644449 2.358384
v 0.333335 -0.644450 2.716766
v 0.666667 -0.293067 2.358384
v 0.333334 -0.293068 2.716766
v 0.662209 -0.629904 2.991038
v 0.337794 -0.629904 2.980731
v 0.662208 -0.307612 2.991038
v 0.337793 -0.307613 2.980731
vt 0.013689 0.608350
vt 0.285640 0.608350
vt 0.285640 0.978776
vt 0.013689 0.978776
vt 0.564957 0.983606
vt 0.293719 0.983606
vt 0.293719 0.613180
vt 0.564957 0.613180
vt 0.646856 0.021326
vt 0.083404 0.021326
vt 0.083369 0.584801
vt 0.646820 0.584801
vt 0.949735 0.303064
vt 0.654355 0.022016
vt 0.957234 0.303753
vt 0.654320 0.585490
vt 0.090869 0.585491
vt 0.090904 0.022016
vt 0.820337 0.692442
vt 0.820337 0.803140
vt 0.740863 0.803140
vt 0.740863 0.692442
vt 0.695284 0.903159
vt 0.695284 0.830265
vt 0.768687 0.830265
vt 0.768687 0.903159
vt 0.874667 0.789013
vt 0.874667 0.893367
vt 0.979009 0.893367
vt 0.979009 0.789013
vt 0.567834 0.981515
vt 0.567834 0.611089
vt 0.768686 0.903159
vt 0.768687 0.823686
vt 0.811715 0.826975
vt 0.811715 0.899870
vt 0.591196 0.903159
vt 0.591196 0.823686
vt 0.695284 0.826975
vt 0.695284 0.899870
vt 0.666035 0.721564
vt 0.667476 0.661838
vt 0.740863 0.660019
vt 0.591196 0.741571
vt 0.666035 0.660015
vt 0.666035 0.803140
vt 0.592658 0.801339
vt 0.013481 0.981515
vt 0.104078 0.915663
vt 0.194676 0.915663
vt 0.285274 0.981515
vt 0.194676 0.850582
vt 0.285274 0.611089
vt 0.104078 0.850582
vt 0.013481 0.611089
vn -0.732233 -0.000002 0.681054
vn 1.000000 0.000002 0.000000
vn 0.000002 -1.000000 0.000000
vn -0.000002 1.000000 -0.000000
vn -0.732233 -0.000001 -0.681054
vn -0.031755 -0.000000 0.999496
vn -0.000000 0.000000 -1.000000
vn -1.000000 -0.000002 -0.000000
vn -0.999857 -0.000002 0.016891
vn 0.999975 0.000002 0.007049
vn 0.017155 0.999327 0.032422
vn 0.017160 -0.999327 0.032422
vn 0.732233 0.000001 0.681054
vn 0.732233 0.000002 0.681054
vn 0.732234 0.000002 0.681053
s off
f 6/1/1 9/2/1 10/3/1 7/4/1
f 4/5/2 8/6/2 5/7/2 1/8/2
f 6/9/3 2/10/3 1/11/3 5/12/3 9/13/3
f 7/14/4 10/15/4 8/16/4 4/17/4 3/18/4
f 11/19/5 12/20/5 14/21/5 13/22/5
f 15/23/6 17/24/6 18/25/6 16/26/6
f 2/27/7 3/28/7 4/29/7 1/30/7
f 6/2/8 7/3/8 3/31/8 2/32/8
f 14/33/9 12/34/9 16/35/9 18/36/9
f 11/37/10 13/38/10 17/39/10 15/40/10
f 13/21/11 14/41/11 18/42/11 17/43/11
f 12/44/12 11/45/12 15/46/12 16/47/12
f 5/48/13 11/49/13 12/50/13 9/51/13
f 9/51/14 12/50/14 14/52/14 10/53/14
f 13/54/14 8/55/14 10/53/14 14/52/14
f 11/49/15 5/48/15 8/55/15 13/54/15