tizen 2.4 release
[framework/uifw/elementary.git] / src / examples / evas3d_map_example.c
1 #define EFL_EO_API_SUPPORT
2 #define EFL_BETA_API_SUPPORT
3
4 #include <Elementary.h>
5
6 #define WIDTH               1024
7 #define HEIGHT              1024
8 #define IMG_SIZE            1024
9 #define SKYBOX_IMG_WIDTH    4096
10 #define SKYBOX_IMG_HEIGHT   3072
11
12 #define MIN_3D_ZOOM_FACTOR  1.0
13 #define MAX_3D_ZOOM_FACTOR  4.9
14 #define MIN_2D_ZOOM_FACTOR  5.0
15 #define MAX_2D_ZOOM_FACTOR  16.0
16
17 #define MAX_CAMERA_DISTANCE 10.0
18
19 #define ROUND(a) ((a < 0) ? ((int)((a - 0.05) * 10) * 0.1) : ((int)((a + 0.05) * 10) * 0.1))
20
21 typedef struct _mat3
22 {
23    float m[9];
24 } mat3;
25
26 typedef struct _vec4
27 {
28    float x;
29    float y;
30    float z;
31    float w;
32 } vec4;
33
34 typedef struct _vec2
35 {
36    float x;
37    float y;
38 } vec2;
39
40 typedef struct _vec3
41 {
42    float x;
43    float y;
44    float z;
45 } vec3;
46
47 typedef struct _vertex
48 {
49    vec3 position;
50    vec3 normal;
51    vec3 tangent;
52    vec4 color;
53    vec3 texcoord;
54 } vertex;
55
56 typedef enum _Map_Dimension_State
57 {
58    MAP_DIMENSION_STATE_2D = 0,
59    MAP_DIMENSION_STATE_3D
60 } Map_Dimension_State;
61
62 static Evas            *evas            = NULL;
63 static Evas_Object     *win             = NULL;
64 static Evas_Object     *bg              = NULL;
65 static Evas_Object     *image           = NULL;
66 static Evas_Object     *map             = NULL;
67 static Evas_Object     *normal_map      = NULL;
68 static Evas_Object     *control_layout  = NULL;
69 static Evas_Object     *hoversel        = NULL;
70 static Evas_Object     *rotation_toggle = NULL;
71 static Evas_Object     *light_toggle    = NULL;
72 static Evas_Object     *zoom_slider     = NULL;
73 static Evas_Object     *menu            = NULL;
74 static Elm_Object_Item *menu_it         = NULL;
75 static Ecore_Animator  *animator        = NULL;
76
77 static Evas_3D_Scene    *scene           = NULL;
78 static Evas_3D_Node     *root_node       = NULL;
79 static Evas_3D_Node     *camera_node     = NULL;
80 static Evas_3D_Camera   *camera          = NULL;
81 static Evas_3D_Node     *light_node      = NULL;
82 static Evas_3D_Light    *light           = NULL;
83 static Evas_3D_Node     *mesh_node       = NULL;
84 static Evas_3D_Mesh     *mesh            = NULL;
85 static Evas_3D_Material *material        = NULL;
86 static Evas_3D_Texture  *texture_diffuse = NULL;
87 static Evas_3D_Texture  *texture_normal  = NULL;
88
89 static int             vertex_count = 0;
90 static int             index_count  = 0;
91 static vertex         *vertices     = NULL;
92 static unsigned short *indices      = NULL;
93
94 static vec2      mouse_down_pos;
95 static vec3      camera_pos;
96 static vec3      camera_up_vec;
97 static vec3      camera_right_vec;
98 static double    zoom_factor      = MIN_3D_ZOOM_FACTOR;
99 static Eina_Bool is_mouse_pressed = EINA_FALSE;
100 static Map_Dimension_State map_dimension_state = MAP_DIMENSION_STATE_3D;
101
102 static const float skybox_vertices[] =
103 {
104    /* Front */
105    -40.0,  40.0,  40.0,     0.0,  0.0, -1.0,     1.0, 0.0, 0.0, 1.0,     0.99, 0.334,
106    40.0,  40.0,  40.0,     0.0,  0.0, -1.0,     1.0, 0.0, 0.0, 1.0,     0.75, 0.334,
107    -40.0, -40.0,  40.0,     0.0,  0.0, -1.0,     1.0, 0.0, 0.0, 1.0,     0.99, 0.666,
108    40.0, -40.0,  40.0,     0.0,  0.0, -1.0,     1.0, 0.0, 0.0, 1.0,     0.75, 0.666,
109
110    /* Back */
111    40.0,  40.0, -40.0,     0.0,  0.0,  1.0,     0.0, 0.0, 1.0, 1.0,     0.50, 0.334,
112    -40.0,  40.0, -40.0,     0.0,  0.0,  1.0,     0.0, 0.0, 1.0, 1.0,     0.25, 0.334,
113    40.0, -40.0, -40.0,     0.0,  0.0,  1.0,     0.0, 0.0, 1.0, 1.0,     0.50, 0.666,
114    -40.0, -40.0, -40.0,     0.0,  0.0,  1.0,     0.0, 0.0, 1.0, 1.0,     0.25, 0.666,
115
116    /* Left */
117    -40.0,  40.0, -40.0,     1.0,  0.0,  0.0,     0.0, 1.0, 0.0, 1.0,     0.25, 0.334,
118    -40.0,  40.0,  40.0,     1.0,  0.0,  0.0,     0.0, 1.0, 0.0, 1.0,     0.01, 0.334,
119    -40.0, -40.0, -40.0,     1.0,  0.0,  0.0,     0.0, 1.0, 0.0, 1.0,     0.25, 0.666,
120    -40.0, -40.0,  40.0,     1.0,  0.0,  0.0,     0.0, 1.0, 0.0, 1.0,     0.01, 0.666,
121
122    /* Right */
123    40.0,  40.0,  40.0,    -1.0,  0.0,  0.0,     1.0, 1.0, 0.0, 1.0,     0.75, 0.334,
124    40.0,  40.0, -40.0,    -1.0,  0.0,  0.0,     1.0, 1.0, 0.0, 1.0,     0.50, 0.334,
125    40.0, -40.0,  40.0,    -1.0,  0.0,  0.0,     1.0, 1.0, 0.0, 1.0,     0.75, 0.666,
126    40.0, -40.0, -40.0,    -1.0,  0.0,  0.0,     1.0, 1.0, 0.0, 1.0,     0.50, 0.666,
127
128    /* Top */
129    -40.0,  40.0, -40.0,     0.0, -1.0,  0.0,     1.0, 0.0, 1.0, 1.0,     0.25, 0.334,
130    40.0,  40.0, -40.0,     0.0, -1.0,  0.0,     1.0, 0.0, 1.0, 1.0,     0.50, 0.334,
131    -40.0,  40.0,  40.0,     0.0, -1.0,  0.0,     1.0, 0.0, 1.0, 1.0,     0.25, 0.01,
132    40.0,  40.0,  40.0,     0.0, -1.0,  0.0,     1.0, 0.0, 1.0, 1.0,     0.50, 0.01,
133
134    /* Bottom */
135    40.0, -40.0, -40.0,     0.0,  1.0,  0.0,     0.0, 1.0, 1.0, 1.0,     0.50, 0.666,
136    -40.0, -40.0, -40.0,     0.0,  1.0,  0.0,     0.0, 1.0, 1.0, 1.0,     0.25, 0.666,
137    40.0, -40.0,  40.0,     0.0,  1.0,  0.0,     0.0, 1.0, 1.0, 1.0,     0.50, 0.99,
138    -40.0, -40.0,  40.0,     0.0,  1.0,  0.0,     0.0, 1.0, 1.0, 1.0,     0.25, 0.99,
139 };
140
141 static const unsigned short skybox_indices[] =
142 {
143    /* Front */
144    0,   1,  2,  2,  1,  3,
145
146    /* Back */
147    4,   5,  6,  6,  5,  7,
148
149    /* Left */
150    8,   9, 10, 10,  9, 11,
151
152    /* Right */
153    12, 13, 14, 14, 13, 15,
154
155    /* Top */
156    16, 17, 18, 18, 17, 19,
157
158    /* Bottom */
159    20, 21, 22, 22, 21, 23
160 };
161
162 static void zoom_factor_set(double new_zoom_factor);
163
164 static inline void
165 vec3_scale(vec3 *out,
166            const vec3 *v,
167            const double scale)
168 {
169    out->x = scale * v->x;
170    out->y = scale * v->y;
171    out->z = scale * v->z;
172 }
173
174 static inline void
175 vec3_normalize(vec3 *out,
176                const vec3 *vec)
177 {
178    double length = sqrt(vec->x * vec->x + vec->y * vec->y + vec->z * vec->z);
179
180    out->x = vec->x / length;
181    out->y = vec->y / length;
182    out->z = vec->z / length;
183 }
184
185 static inline void
186 mat3_multiply_vec3(vec3 *out,
187                    const mat3 *mat,
188                    const vec3 *vec)
189 {
190    out->x = mat->m[0] * vec->x + mat->m[1] * vec->y + mat->m[2] * vec->z;
191    out->y = mat->m[3] * vec->x + mat->m[4] * vec->y + mat->m[5] * vec->z;
192    out->z = mat->m[6] * vec->x + mat->m[7] * vec->y + mat->m[8] * vec->z;
193 }
194
195 static inline void
196 vec3_rotate_angle_axis(vec3 *out,
197                        const vec3 *vec,
198                        const double radian,
199                        const vec3 *axis)
200 {
201    mat3   mat;
202    double cos_r           = cos(radian);
203    double sin_r           = sin(radian);
204    double one_minus_cos_r = 1.0 - cos_r;
205
206    mat.m[0] = cos_r + one_minus_cos_r * (axis->x * axis->x);
207    mat.m[1] = (-axis->z * sin_r) + one_minus_cos_r * (axis->x * axis->y);
208    mat.m[2] = (axis->y * sin_r) + one_minus_cos_r * (axis->x * axis->z);
209
210    mat.m[3] = (axis->z * sin_r) + one_minus_cos_r * (axis->x * axis->y);
211    mat.m[4] = cos_r + one_minus_cos_r * (axis->y * axis->y);
212    mat.m[5] = (-axis->x * sin_r) + one_minus_cos_r * (axis->y * axis->z);
213
214    mat.m[6] = (-axis->y * sin_r) + one_minus_cos_r * (axis->x * axis->z);
215    mat.m[7] = (axis->x * sin_r) + one_minus_cos_r * (axis->y * axis->z);
216    mat.m[8] = cos_r + one_minus_cos_r * (axis->z * axis->z);
217
218    mat3_multiply_vec3(out, &mat, vec);
219 }
220
221 static Eina_Bool
222 animate_scene(void *data)
223 {
224    static float angle = 0.0f;
225
226    angle += 0.05;
227
228    eo_do((Evas_3D_Node *)data,
229          evas_3d_node_orientation_angle_axis_set(angle, 0.0, 1.0, 0.0));
230
231    /* Rotate */
232    if (angle > 360.0)
233      angle -= 360.0f;
234
235    return EINA_TRUE;
236 }
237
238 static void
239 sphere_init(int precision)
240 {
241    int             i, j;
242    vertex         *v;
243    unsigned short *idx;
244
245    vertex_count = (precision + 1) * (precision + 1);
246    index_count = precision * precision * 6;
247
248    /* Allocate buffer. */
249    vertices = malloc(sizeof(vertex) * vertex_count);
250    indices = malloc(sizeof(unsigned short) * index_count);
251
252    for (i = 0; i <= precision; i++)
253      {
254         double lati = M_PI * ((double)i / (double)precision);
255         double y = cos(lati);
256         double r = fabs(sin(lati));
257
258         for (j = 0; j <= precision; j++)
259           {
260              double longi = (M_PI * 2.0) * ((double)j / (double)precision);
261              v = &vertices[i * (precision + 1) + j];
262
263              if (j == 0 || j == precision) v->position.x = 0.0;
264              else v->position.x = r * sin(longi);
265
266              v->position.y = y;
267
268              if (j == 0 || j == precision) v->position.z = r;
269              else v->position.z = r * cos(longi);
270
271              v->normal = v->position;
272
273              if (v->position.x > 0.0)
274                {
275                   v->tangent.x = -v->normal.y;
276                   v->tangent.y =  v->normal.x;
277                   v->tangent.z =  v->normal.z;
278                }
279              else
280                {
281                   v->tangent.x =  v->normal.y;
282                   v->tangent.y = -v->normal.x;
283                   v->tangent.z =  v->normal.z;
284                }
285
286              v->color.x = 1.0;
287              v->color.y = 1.0;
288              v->color.z = 1.0;
289              v->color.w = 1.0;
290
291              if (j == precision) v->texcoord.x = 1.0;
292              else if (j == 0) v->texcoord.x = 0.0;
293              else v->texcoord.x = (double)j / (double)precision;
294
295              if (i == precision) v->texcoord.y = 1.0;
296              else if (i == 0) v->texcoord.y = 0.0;
297              else v->texcoord.y = (double)i / (double)precision;
298           }
299      }
300
301    idx = &indices[0];
302
303    for (i = 0; i < precision; i++)
304      {
305         for (j = 0; j < precision; j++)
306           {
307              *idx++ = i * (precision + 1) + j;
308              *idx++ = i * (precision + 1) + j + 1;
309              *idx++ = (i + 1) * (precision + 1) + j;
310
311              *idx++ = (i + 1) * (precision + 1) + j;
312              *idx++ = i * (precision + 1) + j + 1;
313              *idx++ = (i + 1) * (precision + 1) + j + 1;
314           }
315      }
316
317    for (i = 0; i < index_count; i += 3)
318      {
319         vertex *v0 = &vertices[indices[i + 0]];
320         vertex *v1 = &vertices[indices[i + 1]];
321         vertex *v2 = &vertices[indices[i + 2]];
322
323         vec3  e1, e2;
324         float du1, du2, dv1, dv2, f;
325         vec3  tangent;
326
327         e1.x = v1->position.x - v0->position.x;
328         e1.y = v1->position.y - v0->position.y;
329         e1.z = v1->position.z - v0->position.z;
330
331         e2.x = v2->position.x - v0->position.x;
332         e2.y = v2->position.y - v0->position.y;
333         e2.z = v2->position.z - v0->position.z;
334
335         du1 = v1->texcoord.x - v0->texcoord.x;
336         dv1 = v1->texcoord.y - v0->texcoord.y;
337
338         du2 = v2->texcoord.x - v0->texcoord.x;
339         dv2 = v2->texcoord.y - v0->texcoord.y;
340
341         f = 1.0 / (du1 * dv2 - du2 * dv1);
342
343         tangent.x = f * (dv2 * e1.x - dv1 * e2.x);
344         tangent.y = f * (dv2 * e1.y - dv1 * e2.y);
345         tangent.z = f * (dv2 * e1.z - dv1 * e2.z);
346
347         v0->tangent = tangent;
348      }
349
350    for (i = 0; i <= precision; i++)
351      {
352         for (j = 0; j <= precision; j++)
353           {
354              if (j == precision)
355                {
356                   v = &vertices[i * (precision  + 1) + j];
357                   v->tangent = vertices[i * (precision + 1)].tangent;
358                }
359           }
360      }
361 }
362
363 static void
364 sphere_fini(void)
365 {
366    if (vertices)
367      free(vertices);
368
369    if (indices)
370      free(indices);
371 }
372
373 static void
374 change_to_2d_map(void)
375 {
376    if (map_dimension_state == MAP_DIMENSION_STATE_2D) return;
377    map_dimension_state = MAP_DIMENSION_STATE_2D;
378
379    elm_object_style_set(map, "default");
380    elm_scroller_policy_set
381       (map, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_AUTO);
382    elm_map_zoom_mode_set(map, ELM_MAP_ZOOM_MODE_MANUAL);
383    elm_map_paused_set(map, EINA_TRUE);
384
385    eo_do(texture_diffuse, evas_3d_texture_source_visible_set(EINA_TRUE));
386
387    evas_object_hide(image);
388
389    elm_slider_unit_format_set(zoom_slider, "X%1.0f");
390    elm_slider_indicator_format_set(zoom_slider, "%1.0f");
391    elm_slider_min_max_set(zoom_slider, MIN_2D_ZOOM_FACTOR, MAX_2D_ZOOM_FACTOR);
392 }
393
394 static void
395 change_to_3d_map(void)
396 {
397    if (map_dimension_state == MAP_DIMENSION_STATE_3D) return;
398    map_dimension_state = MAP_DIMENSION_STATE_3D;
399
400    elm_object_style_set(map, "evas3d");
401    elm_scroller_policy_set
402       (map, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
403    elm_map_zoom_mode_set(map, ELM_MAP_ZOOM_MODE_AUTO_FILL);
404
405    evas_object_show(image);
406
407    elm_slider_unit_format_set(zoom_slider, "X%1.1f");
408    elm_slider_indicator_format_set(zoom_slider, "%1.1f");
409    elm_slider_min_max_set(zoom_slider, MIN_3D_ZOOM_FACTOR, MAX_3D_ZOOM_FACTOR);
410 }
411
412 static void
413 zoom_factor_set(double new_zoom_factor)
414 {
415    double        cur_zoom_factor;
416    double        s, t;
417    double        lon, lat;
418    vec3          camera_pos_unit_vec;
419    Evas_3D_Node *n;
420    Evas_3D_Mesh *m;
421    Evas_Coord    src_x, src_y;
422    Evas_Coord    src_size;
423
424    cur_zoom_factor = zoom_factor;
425    zoom_factor = ROUND(new_zoom_factor);
426
427    if (cur_zoom_factor == zoom_factor) return;
428
429    /* 2D Zoom */
430    if (zoom_factor >= MIN_2D_ZOOM_FACTOR)
431      {
432         /* Transition from 3D to 2D */
433         if (cur_zoom_factor < MIN_2D_ZOOM_FACTOR)
434           {
435              zoom_factor = MIN_2D_ZOOM_FACTOR;
436              eo_do(scene, evas_3d_scene_pick(IMG_SIZE / 2, IMG_SIZE / 2,
437                                              &n, &m, &s, &t));
438              src_size = IMG_SIZE * cur_zoom_factor;
439              src_x = (Evas_Coord)(src_size * s);
440              src_y = (Evas_Coord)(src_size * t);
441              elm_map_canvas_to_region_convert(map, src_x, src_y, &lon, &lat);
442
443              change_to_2d_map();
444              evas_object_resize(map, IMG_SIZE, IMG_SIZE);
445              elm_map_zoom_set(map, (int)zoom_factor);
446              elm_map_region_show(map, lon, lat);
447           }
448         else
449           elm_map_zoom_set(map, (int)zoom_factor);
450      }
451    /* 3D Zoom */
452    else
453      {
454         if (zoom_factor < MIN_3D_ZOOM_FACTOR)
455           zoom_factor = MIN_3D_ZOOM_FACTOR;
456
457         /* Transition from 2D to 3D */
458         if (cur_zoom_factor >= MIN_2D_ZOOM_FACTOR)
459           {
460              change_to_3d_map();
461           }
462
463         /* Update texture source. */
464         src_size = IMG_SIZE * zoom_factor;
465         evas_object_resize(map, src_size, src_size);
466
467         /* Apply updated texture source. */
468         texture_diffuse = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
469         eo_do(texture_diffuse,
470               evas_3d_texture_source_set(map),
471               evas_3d_texture_source_visible_set(EINA_FALSE));
472
473         eo_do(material,
474               evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, texture_diffuse));
475
476         /* Update camera position. */
477         vec3_normalize(&camera_pos_unit_vec, &camera_pos);
478         camera_pos.x = (camera_pos_unit_vec.x * MAX_CAMERA_DISTANCE) / zoom_factor;
479         camera_pos.y = (camera_pos_unit_vec.y * MAX_CAMERA_DISTANCE) / zoom_factor;
480         camera_pos.z = (camera_pos_unit_vec.z * MAX_CAMERA_DISTANCE) / zoom_factor;
481
482         eo_do(camera_node,
483               evas_3d_node_position_set(camera_pos.x, camera_pos.y, camera_pos.z));
484      }
485
486    /* Update zoom slider. */
487    elm_slider_value_set(zoom_slider, zoom_factor);
488 }
489
490 static void
491 zoom_in_cb(void *data,
492            Evas_Object *obj,
493            void *event_info)
494 {
495    zoom_factor_set(zoom_factor + 1);
496 }
497
498 static void
499 zoom_out_cb(void *data,
500             Evas_Object *obj,
501             void *event_info)
502 {
503    zoom_factor_set(zoom_factor - 1);
504 }
505
506 static void
507 zoom_to_2d_map_cb(void *data,
508                   Evas_Object *obj,
509                   void *event_info)
510 {
511    double        s, t;
512    double        lon, lat;
513    Evas_3D_Node *n;
514    Evas_3D_Mesh *m;
515    Evas_Coord    src_x, src_y;
516    Evas_Coord    src_size;
517
518    if (map_dimension_state == MAP_DIMENSION_STATE_2D) return;
519
520    eo_do(scene, evas_3d_scene_pick(mouse_down_pos.x, mouse_down_pos.y, &n, &m, &s, &t));
521    src_size = (Evas_Coord)(IMG_SIZE * zoom_factor);
522    src_x = (Evas_Coord)(src_size * s);
523    src_y = (Evas_Coord)(src_size * t);
524    elm_map_canvas_to_region_convert(map, src_x, src_y, &lon, &lat);
525
526    zoom_factor_set(MIN_2D_ZOOM_FACTOR);
527
528    elm_map_region_show(map, lon, lat);
529 }
530
531 static void
532 zoom_to_3d_map_cb(void *data,
533                   Evas_Object *obj,
534                   void *event_info)
535 {
536    if (map_dimension_state == MAP_DIMENSION_STATE_3D) return;
537
538    zoom_factor_set(MAX_3D_ZOOM_FACTOR);
539 }
540
541 static void
542 submenu_zoom_add(Elm_Object_Item *parent)
543 {
544    if (!parent) return;
545
546    elm_menu_item_add(menu, parent, NULL, "Zoom in", zoom_in_cb, NULL);
547    elm_menu_item_add(menu, parent, NULL, "Zoom out", zoom_out_cb, NULL);
548    elm_menu_item_add(menu, parent, NULL, "Zoom to 2D map", zoom_to_2d_map_cb, NULL);
549    elm_menu_item_add(menu, parent, NULL, "Zoom to 3D map", zoom_to_3d_map_cb, NULL);
550 }
551
552 static void
553 submenu_info_add(Elm_Object_Item *parent)
554 {
555    char          buf[50];
556    double        s, t;
557    double        lon, lat;
558    Evas_3D_Node *n;
559    Evas_3D_Mesh *m;
560    Evas_Coord    src_x, src_y;
561    Evas_Coord    src_size;
562
563    if (!parent) return;
564
565    if (map_dimension_state == MAP_DIMENSION_STATE_3D)
566      {
567         eo_do(scene, evas_3d_scene_pick(mouse_down_pos.x, mouse_down_pos.y, &n, &m, &s, &t));
568         src_size = (Evas_Coord) (IMG_SIZE * zoom_factor);
569         src_x = (Evas_Coord)(src_size * s);
570         src_y = (Evas_Coord)(src_size * t);
571         elm_map_canvas_to_region_convert(map, src_x, src_y, &lon, &lat);
572      }
573    else
574      {
575         elm_map_canvas_to_region_convert(map, mouse_down_pos.x, mouse_down_pos.y, &lon, &lat);
576      }
577
578    snprintf(buf, sizeof(buf), "Longitude : %f", lon);
579    elm_menu_item_add(menu, parent, NULL, buf, NULL, NULL);
580
581    snprintf(buf, sizeof(buf), "Latitude : %f", lat);
582    elm_menu_item_add(menu, parent, NULL, buf, NULL, NULL);
583 }
584
585 static void
586 map_zoom_change_cb(void *data,
587                    Evas_Object *obj,
588                    void *event_info)
589 {
590    int cur_zoom_factor;
591
592    if (map_dimension_state == MAP_DIMENSION_STATE_3D) return;
593
594    cur_zoom_factor = elm_map_zoom_get(map);
595
596    if (elm_map_paused_get(map))
597      elm_map_paused_set(map, EINA_FALSE);
598
599    zoom_factor_set(cur_zoom_factor);
600 }
601
602 static void
603 map_mouse_down_cb(void *data,
604                   Evas *e,
605                   Evas_Object *o,
606                   void *event_info)
607 {
608    Evas_Event_Mouse_Down *ev = event_info;
609    Evas_Coord             x, y, w, h;
610    Evas_Coord             obj_x, obj_y;
611    int                    scene_w, scene_h;
612    double                 scene_x, scene_y;
613    double                 s, t;
614    Evas_3D_Node          *n;
615    Evas_3D_Mesh          *m;
616    Eina_Bool              pick;
617
618    mouse_down_pos.x = ev->canvas.x;
619    mouse_down_pos.y = ev->canvas.y;
620
621    evas_object_geometry_get(o, &x, &y, &w, &h);
622
623    obj_x = ev->canvas.x - x;
624    obj_y = ev->canvas.y - y;
625
626    eo_do(scene, evas_3d_scene_size_get(&scene_w, &scene_h));
627
628    scene_x = obj_x * scene_w / (double)w;
629    scene_y = obj_y * scene_h / (double)h;
630
631    eo_do(scene, pick = evas_3d_scene_pick(scene_x, scene_y, &n, &m, &s, &t));
632    if (pick)
633      printf("Picked     : ");
634    else
635      printf("Not picked : ");
636
637    printf("output(%d, %d) canvas(%d, %d) object(%d, %d) scene(%f, %f) texcoord(%f, %f) "
638           "node(%p) mesh(%p)\n",
639           ev->output.x, ev->output.y,
640           ev->canvas.x, ev->canvas.y,
641           obj_x, obj_y,
642           scene_x, scene_y,
643           s, t, n, m);
644
645    if (ev->button == 3)
646      {
647         if (!menu)
648           {
649              menu = elm_menu_add(o);
650              elm_menu_parent_set(menu, o);
651              menu_it = elm_menu_item_add(menu, NULL, "", "Zoom", NULL, NULL);
652              submenu_zoom_add(menu_it);
653              menu_it = elm_menu_item_add(menu, NULL, "", "Info", NULL, NULL);
654           }
655
656         elm_menu_item_subitems_clear(menu_it);
657         submenu_info_add(menu_it);
658
659         elm_menu_move(menu, ev->canvas.x, ev->canvas.y);
660         evas_object_show(menu);
661      }
662
663 }
664
665 static void
666 mouse_down_cb(void *data,
667               Evas *e,
668               Evas_Object *o,
669               void *event_info)
670 {
671    Evas_Event_Mouse_Down *ev = event_info;
672    Evas_Coord             x, y, w, h;
673    Evas_Coord             obj_x, obj_y;
674    int                    scene_w, scene_h;
675    double                 scene_x, scene_y;
676    double                 s, t;
677    Evas_3D_Node          *n;
678    Evas_3D_Mesh          *m;
679    Eina_Bool              pick;
680
681    mouse_down_pos.x = ev->canvas.x;
682    mouse_down_pos.y = ev->canvas.y;
683
684    /* Stop rotating earth. */
685    if (animator)
686      {
687         ecore_animator_del(animator);
688         animator = NULL;
689      }
690
691    evas_object_geometry_get(o, &x, &y, &w, &h);
692
693    obj_x = ev->canvas.x - x;
694    obj_y = ev->canvas.y - y;
695
696    eo_do(scene, evas_3d_scene_size_get(&scene_w, &scene_h));
697
698    scene_x = obj_x * scene_w / (double)w;
699    scene_y = obj_y * scene_h / (double)h;
700
701    eo_do(scene, pick = evas_3d_scene_pick(scene_x, scene_y, &n, &m, &s, &t));
702    if (pick)
703      printf("Picked     : ");
704    else
705      printf("Not picked : ");
706
707    printf("output(%d, %d) canvas(%d, %d) object(%d, %d) scene(%f, %f) texcoord(%f, %f) "
708           "node(%p) mesh(%p)\n",
709           ev->output.x, ev->output.y,
710           ev->canvas.x, ev->canvas.y,
711           obj_x, obj_y,
712           scene_x, scene_y,
713           s, t, n, m);
714
715    if (ev->button == 1)
716      is_mouse_pressed = EINA_TRUE;
717    else if (ev->button == 3)
718      {
719         elm_check_state_set(rotation_toggle, EINA_FALSE);
720         if (!menu)
721           {
722              menu = elm_menu_add(o);
723              elm_menu_parent_set(menu, o);
724              menu_it = elm_menu_item_add(menu, NULL, "", "Zoom", NULL, NULL);
725              submenu_zoom_add(menu_it);
726              menu_it = elm_menu_item_add(menu, NULL, "", "Info", NULL, NULL);
727           }
728
729         elm_menu_item_subitems_clear(menu_it);
730         submenu_info_add(menu_it);
731
732         elm_menu_move(menu, ev->canvas.x, ev->canvas.y);
733         evas_object_show(menu);
734      }
735 }
736
737 static void
738 mouse_move_cb(void *data,
739               Evas *e,
740               Evas_Object *o,
741               void *event_info)
742 {
743    Evas_Event_Mouse_Move *ev = event_info;
744    double                 distance_to_origin;
745    double                 radian_camera_up_axis, radian_camera_right_axis;
746    vec3                   camera_pos_unit_vec;
747
748    if ((ev->buttons == 1) && is_mouse_pressed)
749      {
750         radian_camera_up_axis = (ev->prev.canvas.x - ev->cur.canvas.x) * 0.01;
751         radian_camera_right_axis = (ev->prev.canvas.y - ev->cur.canvas.y) * 0.01;
752
753         distance_to_origin = sqrt(pow(camera_pos.x, 2) + pow(camera_pos.y, 2) + pow(camera_pos.z, 2));
754
755         /* Update camera position, up vector and right vector. */
756         vec3_rotate_angle_axis(&camera_pos, &camera_pos, radian_camera_up_axis, &camera_up_vec);
757         vec3_rotate_angle_axis(&camera_right_vec, &camera_right_vec, radian_camera_up_axis, &camera_up_vec);
758         vec3_normalize(&camera_right_vec, &camera_right_vec);
759
760         vec3_rotate_angle_axis(&camera_pos, &camera_pos, radian_camera_right_axis, &camera_right_vec);
761         vec3_rotate_angle_axis(&camera_up_vec, &camera_up_vec, radian_camera_right_axis, &camera_right_vec);
762         vec3_normalize(&camera_up_vec, &camera_up_vec);
763         vec3_normalize(&camera_pos_unit_vec, &camera_pos);
764         vec3_scale(&camera_pos, &camera_pos_unit_vec, distance_to_origin);
765
766         eo_do(camera_node,
767               evas_3d_node_position_set(camera_pos.x, camera_pos.y, camera_pos.z),
768               evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 0.0,
769                                        EVAS_3D_SPACE_PARENT, camera_up_vec.x, camera_up_vec.y, camera_up_vec.z));
770
771         if (elm_check_state_get(light_toggle))
772           {
773              /* Update light position as the same as camera position. */
774              eo_do(light_node,
775                    evas_3d_node_position_set(camera_pos.x, camera_pos.y, camera_pos.z),
776                    evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 0.0,
777                                             EVAS_3D_SPACE_PARENT, camera_up_vec.x, camera_up_vec.y, camera_up_vec.z));
778           }
779      }
780 }
781
782 static void
783 mouse_up_cb(void *data,
784             Evas *e,
785             Evas_Object *o,
786             void *event_info)
787 {
788    Evas_Event_Mouse_Up *ev = event_info;
789    Evas_Coord           x, y, w, h;
790    Evas_Coord           obj_x, obj_y;
791    int                  scene_w, scene_h;
792    double               scene_x, scene_y;
793    double               s, t;
794    Evas_3D_Node        *n;
795    Evas_3D_Mesh        *m;
796    Eina_Bool            pick;
797
798    evas_object_geometry_get(o, &x, &y, &w, &h);
799
800    obj_x = ev->canvas.x - x;
801    obj_y = ev->canvas.y - y;
802
803    eo_do(scene, evas_3d_scene_size_get(&scene_w, &scene_h));
804
805    scene_x = obj_x * scene_w / (double)w;
806    scene_y = obj_y * scene_h / (double)h;
807
808    eo_do(scene, pick = evas_3d_scene_pick(scene_x, scene_y, &n, &m, &s, &t));
809    if (pick)
810      printf("Picked     : ");
811    else
812      printf("Not picked : ");
813
814    printf("output(%d, %d) canvas(%d, %d) object(%d, %d) scene(%f, %f) texcoord(%f, %f) "
815           "node(%p) mesh(%p)\n",
816           ev->output.x, ev->output.y,
817           ev->canvas.x, ev->canvas.y,
818           obj_x, obj_y,
819           scene_x, scene_y,
820           s, t, n, m);
821
822    /* Move camera position. */
823    if (ev->button == 1)
824      is_mouse_pressed = EINA_FALSE;
825
826    if (elm_check_state_get(rotation_toggle))
827      {
828         /* Restart rotating earth. */
829         animator = ecore_animator_add(animate_scene, mesh_node);
830      }
831 }
832
833 static void
834 mouse_wheel_cb(void *data,
835                Evas *e,
836                Evas_Object *o,
837                void *event_info)
838 {
839    Evas_Event_Mouse_Wheel *ev = event_info;
840    double                  new_zoom_factor;
841
842    if (map_dimension_state == MAP_DIMENSION_STATE_2D) return;
843
844    new_zoom_factor = zoom_factor - (ev->z * 0.1);
845    zoom_factor_set(new_zoom_factor);
846 }
847
848 static void
849 skybox_setup(void)
850 {
851    Evas_3D_Node     *skybox_mesh_node;
852    Evas_3D_Mesh     *skybox_mesh;
853    Evas_3D_Material *skybox_material;
854    Evas_3D_Texture  *skybox_texture_diffuse;
855    Evas_Object      *skybox_image;
856    char              buf[PATH_MAX];
857
858    skybox_mesh = eo_add(EVAS_3D_MESH_CLASS, evas);
859    eo_do(skybox_mesh,
860          evas_3d_mesh_vertex_count_set(24),
861          evas_3d_mesh_frame_add(0),
862
863          evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_POSITION,
864                                             12 * sizeof(float), &skybox_vertices[0]),
865          evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_NORMAL,
866                                             12 * sizeof(float), &skybox_vertices[3]),
867          evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_COLOR,
868                                             12 * sizeof(float), &skybox_vertices[6]),
869          evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_TEXCOORD,
870                                             12 * sizeof(float), &skybox_vertices[10]),
871
872          evas_3d_mesh_index_data_set(EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT, 36, &skybox_indices[0]),
873          evas_3d_mesh_vertex_assembly_set(EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES));
874
875    /* Set skybox texture source image. */
876    skybox_image = elm_image_add(win);
877    snprintf(buf, sizeof(buf), "%s/images/space.png", elm_app_data_dir_get());
878    elm_image_file_set(skybox_image, buf, NULL);
879    evas_object_resize(skybox_image, SKYBOX_IMG_WIDTH, SKYBOX_IMG_HEIGHT);
880    evas_object_show(skybox_image);
881
882    /* Set skybox texture material. */
883    skybox_material = eo_add(EVAS_3D_MATERIAL_CLASS, evas);
884    eo_do(skybox_mesh, evas_3d_mesh_frame_material_set(0, skybox_material));
885
886    skybox_texture_diffuse = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
887
888    eo_do(skybox_texture_diffuse,
889          evas_3d_texture_source_set(skybox_image),
890          evas_3d_texture_source_visible_set(EINA_FALSE));
891
892    eo_do(skybox_material,
893          evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, skybox_texture_diffuse),
894
895          evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
896          evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
897          evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
898
899          evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 0.1, 0.1, 0.1, 1.0),
900          evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 1.0, 1.0, 1.0, 1.0),
901          evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 0.1, 0.1, 0.1, 1.0),
902          evas_3d_material_shininess_set(50.0));
903
904    skybox_mesh_node = eo_add(EVAS_3D_NODE_CLASS, evas,
905                                     evas_3d_node_constructor(EVAS_3D_NODE_TYPE_MESH));
906    eo_do(root_node, evas_3d_node_member_add(skybox_mesh_node));
907    eo_do(skybox_mesh_node, evas_3d_node_mesh_add(skybox_mesh));
908    eo_do(skybox_mesh, evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_DIFFUSE));
909 }
910
911 static void
912 texture_source_setup(void)
913 {
914    char buf[PATH_MAX];
915
916    snprintf(buf, sizeof(buf), "%s/examples/evas3d_map_example.edj", elm_app_data_dir_get());
917    elm_theme_extension_add(NULL, buf);
918
919    /* Add a map object for the use of the texture source. */
920    map = elm_map_add(win);
921    elm_object_style_set(map, "evas3d");
922    elm_map_source_set(map, ELM_MAP_SOURCE_TYPE_TILE, "MapQuest");
923    elm_scroller_policy_set
924       (map, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
925    elm_map_zoom_mode_set(map, ELM_MAP_ZOOM_MODE_AUTO_FILL);
926    evas_object_resize(map, IMG_SIZE, IMG_SIZE);
927    evas_object_show(map);
928
929    evas_object_smart_callback_add(map, "zoom,change",
930                                   map_zoom_change_cb, NULL);
931    evas_object_event_callback_add(map, EVAS_CALLBACK_MOUSE_DOWN,
932                                   map_mouse_down_cb, map);
933
934    /* Add a normal map object for the use of the normal texture source. */
935    normal_map = elm_image_add(win);
936    snprintf(buf, sizeof(buf), "%s/images/earth_normal.png", elm_app_data_dir_get());
937    elm_image_file_set(normal_map, buf, NULL);
938    evas_object_resize(normal_map, IMG_SIZE, IMG_SIZE);
939    evas_object_show(normal_map);
940 }
941
942 static void
943 camera_setup(void)
944 {
945    /* Add the camera. */
946    camera = eo_add(EVAS_3D_CAMERA_CLASS, evas);
947    eo_do(camera, evas_3d_camera_projection_perspective_set(60.0, 1.0, 1.0, 100.0));
948
949    /* Set camera position. */
950    camera_pos.x = 0.0;
951    camera_pos.y = 0.0;
952    camera_pos.z = MAX_CAMERA_DISTANCE;
953
954    /* Set camera up vector. */
955    camera_up_vec.x = 0.0;
956    camera_up_vec.y = 1.0;
957    camera_up_vec.z = 0.0;
958
959    /* Set camera right vector. */
960    camera_right_vec.x = 1.0;
961    camera_right_vec.y = 0.0;
962    camera_right_vec.z = 0.0;
963
964    camera_node = eo_add(EVAS_3D_NODE_CLASS, evas,
965                                evas_3d_node_constructor(EVAS_3D_NODE_TYPE_CAMERA));
966    eo_do(camera_node,
967          evas_3d_node_camera_set(camera),
968          evas_3d_node_position_set(camera_pos.x, camera_pos.y, camera_pos.z),
969          evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 0.0,
970                                   EVAS_3D_SPACE_PARENT, camera_up_vec.x, camera_up_vec.y, camera_up_vec.z));
971    eo_do(root_node, evas_3d_node_member_add(camera_node));
972 }
973
974 static void
975 light_setup(void)
976 {
977    light = eo_add(EVAS_3D_LIGHT_CLASS, evas);
978    eo_do(light,
979          evas_3d_light_ambient_set(0.2, 0.2, 0.2, 1.0),
980          evas_3d_light_diffuse_set(1.0, 1.0, 1.0, 1.0),
981          evas_3d_light_specular_set(0.2, 0.2, 0.2, 1.0));
982
983    light_node = eo_add(EVAS_3D_NODE_CLASS, evas,
984                               evas_3d_node_constructor(EVAS_3D_NODE_TYPE_LIGHT));
985    eo_do(light_node,
986          evas_3d_node_light_set(light),
987          evas_3d_node_position_set(0.0, 0.0, MAX_CAMERA_DISTANCE),
988          evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 0.0,
989                                   EVAS_3D_SPACE_PARENT, 0.0, 1.0, 0.0));
990    eo_do(root_node, evas_3d_node_member_add(light_node));
991 }
992
993 static void
994 mesh_setup(void)
995 {
996    /* Create a sphere mesh. */
997    sphere_init(50);
998
999    mesh = eo_add(EVAS_3D_MESH_CLASS, evas);
1000    eo_do(mesh,
1001          evas_3d_mesh_vertex_count_set(vertex_count),
1002          evas_3d_mesh_frame_add(0),
1003
1004          evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_POSITION,
1005                                             sizeof(vertex), &vertices[0].position),
1006          evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_NORMAL,
1007                                             sizeof(vertex), &vertices[0].normal),
1008          evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_TANGENT,
1009                                             sizeof(vertex), &vertices[0].tangent),
1010          evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_COLOR,
1011                                             sizeof(vertex), &vertices[0].color),
1012          evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_TEXCOORD,
1013                                             sizeof(vertex), &vertices[0].texcoord),
1014
1015          evas_3d_mesh_index_data_set(EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT, index_count, &indices[0]),
1016          evas_3d_mesh_vertex_assembly_set(EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES));
1017
1018    material = eo_add(EVAS_3D_MATERIAL_CLASS, evas);
1019    eo_do(mesh, evas_3d_mesh_frame_material_set(0, material));
1020
1021    texture_diffuse = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
1022    eo_do(texture_diffuse,
1023          evas_3d_texture_source_set(map),
1024          evas_3d_texture_source_visible_set(EINA_FALSE));
1025
1026    texture_normal = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
1027    eo_do(texture_normal,
1028          evas_3d_texture_source_set(normal_map),
1029          evas_3d_texture_source_visible_set(EINA_FALSE));
1030
1031    eo_do(material,
1032          evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, texture_diffuse),
1033          evas_3d_material_texture_set(EVAS_3D_MATERIAL_NORMAL, texture_normal),
1034
1035          evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
1036          evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
1037          evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
1038          evas_3d_material_enable_set(EVAS_3D_MATERIAL_NORMAL, EINA_TRUE),
1039
1040          evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 0.1, 0.1, 0.1, 1.0),
1041          evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 1.0, 1.0, 1.0, 1.0),
1042          evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 0.1, 0.1, 0.1, 1.0),
1043          evas_3d_material_shininess_set(50.0));
1044
1045    mesh_node = eo_add(EVAS_3D_NODE_CLASS, evas,
1046                              evas_3d_node_constructor(EVAS_3D_NODE_TYPE_MESH));
1047    eo_do(root_node, evas_3d_node_member_add(mesh_node));
1048    eo_do(mesh_node, evas_3d_node_mesh_add(mesh));
1049    eo_do(mesh, evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_NORMAL_MAP));
1050 }
1051
1052 static void
1053 hoversel_cb(void *data,
1054             Evas_Object *obj,
1055             void *event_info)
1056 {
1057    elm_map_source_set(map, ELM_MAP_SOURCE_TYPE_TILE, (char *)data);
1058    zoom_factor_set(zoom_factor);
1059 }
1060
1061 static void
1062 hoversel_setup(Evas_Object *parent)
1063 {
1064    hoversel = elm_hoversel_add(parent);
1065
1066    elm_hoversel_hover_parent_set(hoversel, parent);
1067    elm_object_text_set(hoversel, "Map Sources");
1068    elm_hoversel_item_add(hoversel, "Mapnik", NULL, ELM_ICON_NONE, hoversel_cb, "Mapnik");
1069    elm_hoversel_item_add(hoversel, "CycleMap", NULL, ELM_ICON_NONE, hoversel_cb, "CycleMap");
1070    elm_hoversel_item_add(hoversel, "MapQuest", NULL, ELM_ICON_NONE, hoversel_cb, "MapQuest");
1071
1072    elm_object_part_content_set(parent, "elm.swallow.hoversel", hoversel);
1073    evas_object_show(hoversel);
1074 }
1075
1076 static void
1077 rotation_toggle_changed_cb(void *data,
1078                            Evas_Object *obj,
1079                            void *event_info)
1080 {
1081    /* Stop rotating earth. */
1082    if (animator)
1083      {
1084         ecore_animator_del(animator);
1085         animator = NULL;
1086      }
1087    if (elm_check_state_get(obj))
1088      {
1089         /* Restart rotating earth. */
1090         animator = ecore_animator_add(animate_scene, mesh_node);
1091      }
1092 }
1093
1094 static void
1095 rotation_toggle_setup(Evas_Object *parent)
1096 {
1097    rotation_toggle = elm_check_add(parent);
1098
1099    elm_object_style_set(rotation_toggle, "toggle");
1100    elm_object_text_set(rotation_toggle, "Earth Rotation");
1101    elm_object_part_text_set(rotation_toggle, "on", "ON");
1102    elm_object_part_text_set(rotation_toggle, "off", "OFF");
1103    elm_check_state_set(rotation_toggle, EINA_TRUE);
1104
1105    elm_object_part_content_set(parent, "elm.swallow.rotation_toggle", rotation_toggle);
1106    evas_object_show(rotation_toggle);
1107
1108    evas_object_smart_callback_add(rotation_toggle, "changed", rotation_toggle_changed_cb, NULL);
1109 }
1110
1111 static void
1112 light_toggle_changed_cb(void *data,
1113                         Evas_Object *obj,
1114                         void *event_info)
1115 {
1116    if (elm_check_state_get(obj))
1117      {
1118         /* Set light position as the same as camera position. */
1119         eo_do(light_node,
1120               evas_3d_node_position_set(camera_pos.x, camera_pos.y, camera_pos.z),
1121               evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 0.0,
1122                                        EVAS_3D_SPACE_PARENT, camera_up_vec.x, camera_up_vec.y, camera_up_vec.z));
1123      }
1124    else
1125      {
1126         /* Set light position to default position. */
1127         eo_do(light_node,
1128               evas_3d_node_position_set(0.0, 0.0, MAX_CAMERA_DISTANCE),
1129               evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 0.0,
1130                                        EVAS_3D_SPACE_PARENT, 0.0, 1.0, 0.0));
1131      }
1132 }
1133
1134 static void
1135 light_toggle_setup(Evas_Object *parent)
1136 {
1137    light_toggle = elm_check_add(parent);
1138
1139    elm_object_style_set(light_toggle, "toggle");
1140    elm_object_text_set(light_toggle, "Light on Camera");
1141    elm_object_part_text_set(light_toggle, "on", "ON");
1142    elm_object_part_text_set(light_toggle, "off", "OFF");
1143    elm_check_state_set(light_toggle, EINA_FALSE);
1144
1145    elm_object_part_content_set(parent, "elm.swallow.light_toggle", light_toggle);
1146    evas_object_show(light_toggle);
1147
1148    evas_object_smart_callback_add(light_toggle, "changed", light_toggle_changed_cb, NULL);
1149 }
1150
1151
1152 static void
1153 slider_changed_cb(void *data,
1154                   Evas_Object *obj,
1155                   void *event_info)
1156 {
1157    double new_zoom_factor = ROUND(elm_slider_value_get(obj));
1158
1159    if (new_zoom_factor == zoom_factor) return;
1160
1161    zoom_factor_set(new_zoom_factor);
1162 }
1163
1164 static void
1165 zoom_slider_setup(Evas_Object *parent)
1166 {
1167    zoom_slider = elm_slider_add(parent);
1168
1169    elm_object_text_set(zoom_slider, "Zoom Factor");
1170    elm_slider_unit_format_set(zoom_slider, "X%1.1f");
1171    elm_slider_indicator_format_set(zoom_slider, "%1.1f");
1172    elm_slider_span_size_set(zoom_slider, 100);
1173    elm_slider_min_max_set(zoom_slider, MIN_3D_ZOOM_FACTOR, MAX_3D_ZOOM_FACTOR);
1174
1175    elm_object_part_content_set(parent, "elm.swallow.zoom_slider", zoom_slider);
1176    evas_object_show(zoom_slider);
1177
1178    evas_object_smart_callback_add(zoom_slider, "changed", slider_changed_cb, NULL);
1179 }
1180
1181 EAPI_MAIN int
1182 elm_main(int argc, char **argv)
1183 {
1184    char buf[PATH_MAX];
1185
1186    elm_app_info_set(elm_main, "elementary", "examples/evas3d_map_example.edj");
1187
1188    elm_config_accel_preference_set("3d");
1189
1190    elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
1191
1192    /* Add a window. */
1193    win = elm_win_util_standard_add("elm_map_evas3d", "Elm_Map_Evas3d");
1194    elm_win_autodel_set(win, EINA_TRUE);
1195
1196    evas = evas_object_evas_get(win);
1197
1198    /* Add a background. */
1199    bg = evas_object_rectangle_add(evas);
1200    evas_object_color_set(bg, 0, 0, 0, 255);
1201    evas_object_resize(bg, WIDTH, HEIGHT);
1202    evas_object_show(bg);
1203
1204    /* Add an image which shows a scene. */
1205    image = evas_object_image_filled_add(evas);
1206    evas_object_resize(image, WIDTH, HEIGHT);
1207    evas_object_show(image);
1208
1209    evas_object_event_callback_add(image, EVAS_CALLBACK_MOUSE_DOWN, mouse_down_cb, NULL);
1210    evas_object_event_callback_add(image, EVAS_CALLBACK_MOUSE_MOVE, mouse_move_cb, NULL);
1211    evas_object_event_callback_add(image, EVAS_CALLBACK_MOUSE_UP, mouse_up_cb, NULL);
1212    evas_object_event_callback_add(image, EVAS_CALLBACK_MOUSE_WHEEL, mouse_wheel_cb, NULL);
1213
1214    /* Add a scene object. */
1215    scene = eo_add(EVAS_3D_SCENE_CLASS, evas);
1216
1217    /* Add a root node for the scene. */
1218    root_node = eo_add(EVAS_3D_NODE_CLASS, evas,
1219                              evas_3d_node_constructor(EVAS_3D_NODE_TYPE_NODE));
1220
1221    skybox_setup();
1222    texture_source_setup();
1223    camera_setup();
1224    light_setup();
1225    mesh_setup();
1226
1227    /* Set up scene. */
1228    eo_do(scene,
1229          evas_3d_scene_root_node_set(root_node),
1230          evas_3d_scene_camera_node_set(camera_node),
1231          evas_3d_scene_size_set(WIDTH, HEIGHT));
1232    eo_do(image, evas_obj_image_scene_set(scene));
1233
1234    /* Add a layout for controlers. */
1235    control_layout = elm_layout_add(win);
1236    snprintf(buf, sizeof(buf), "%s/examples/evas3d_map_example.edj", elm_app_data_dir_get());
1237    elm_layout_file_set(control_layout, buf, "control_layout");
1238    evas_object_resize(control_layout, WIDTH, HEIGHT);
1239    evas_object_show(control_layout);
1240
1241    /* Set up controlers. */
1242    hoversel_setup(control_layout);
1243    rotation_toggle_setup(control_layout);
1244    light_toggle_setup(control_layout);
1245    zoom_slider_setup(control_layout);
1246
1247    /* Start rotating earth */
1248    animator = ecore_animator_add(animate_scene, mesh_node);
1249
1250    evas_object_resize(win, WIDTH, HEIGHT);
1251    evas_object_show(win);
1252
1253    elm_run();
1254    sphere_fini();
1255
1256    return 0;
1257 }
1258 ELM_MAIN();