1 #define EFL_EO_API_SUPPORT
2 #define EFL_BETA_API_SUPPORT
4 #include <Elementary.h>
9 #define SKYBOX_IMG_WIDTH 4096
10 #define SKYBOX_IMG_HEIGHT 3072
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
17 #define MAX_CAMERA_DISTANCE 10.0
19 #define ROUND(a) ((a < 0) ? ((int)((a - 0.05) * 10) * 0.1) : ((int)((a + 0.05) * 10) * 0.1))
47 typedef struct _vertex
56 typedef enum _Map_Dimension_State
58 MAP_DIMENSION_STATE_2D = 0,
59 MAP_DIMENSION_STATE_3D
60 } Map_Dimension_State;
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;
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;
89 static int vertex_count = 0;
90 static int index_count = 0;
91 static vertex *vertices = NULL;
92 static unsigned short *indices = NULL;
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;
102 static const float skybox_vertices[] =
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,
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,
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,
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,
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,
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,
141 static const unsigned short skybox_indices[] =
153 12, 13, 14, 14, 13, 15,
156 16, 17, 18, 18, 17, 19,
159 20, 21, 22, 22, 21, 23
162 static void zoom_factor_set(double new_zoom_factor);
165 vec3_scale(vec3 *out,
169 out->x = scale * v->x;
170 out->y = scale * v->y;
171 out->z = scale * v->z;
175 vec3_normalize(vec3 *out,
178 double length = sqrt(vec->x * vec->x + vec->y * vec->y + vec->z * vec->z);
180 out->x = vec->x / length;
181 out->y = vec->y / length;
182 out->z = vec->z / length;
186 mat3_multiply_vec3(vec3 *out,
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;
196 vec3_rotate_angle_axis(vec3 *out,
202 double cos_r = cos(radian);
203 double sin_r = sin(radian);
204 double one_minus_cos_r = 1.0 - cos_r;
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);
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);
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);
218 mat3_multiply_vec3(out, &mat, vec);
222 animate_scene(void *data)
224 static float angle = 0.0f;
228 eo_do((Evas_3D_Node *)data,
229 evas_3d_node_orientation_angle_axis_set(angle, 0.0, 1.0, 0.0));
239 sphere_init(int precision)
245 vertex_count = (precision + 1) * (precision + 1);
246 index_count = precision * precision * 6;
248 /* Allocate buffer. */
249 vertices = malloc(sizeof(vertex) * vertex_count);
250 indices = malloc(sizeof(unsigned short) * index_count);
252 for (i = 0; i <= precision; i++)
254 double lati = M_PI * ((double)i / (double)precision);
255 double y = cos(lati);
256 double r = fabs(sin(lati));
258 for (j = 0; j <= precision; j++)
260 double longi = (M_PI * 2.0) * ((double)j / (double)precision);
261 v = &vertices[i * (precision + 1) + j];
263 if (j == 0 || j == precision) v->position.x = 0.0;
264 else v->position.x = r * sin(longi);
268 if (j == 0 || j == precision) v->position.z = r;
269 else v->position.z = r * cos(longi);
271 v->normal = v->position;
273 if (v->position.x > 0.0)
275 v->tangent.x = -v->normal.y;
276 v->tangent.y = v->normal.x;
277 v->tangent.z = v->normal.z;
281 v->tangent.x = v->normal.y;
282 v->tangent.y = -v->normal.x;
283 v->tangent.z = v->normal.z;
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;
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;
303 for (i = 0; i < precision; i++)
305 for (j = 0; j < precision; j++)
307 *idx++ = i * (precision + 1) + j;
308 *idx++ = i * (precision + 1) + j + 1;
309 *idx++ = (i + 1) * (precision + 1) + j;
311 *idx++ = (i + 1) * (precision + 1) + j;
312 *idx++ = i * (precision + 1) + j + 1;
313 *idx++ = (i + 1) * (precision + 1) + j + 1;
317 for (i = 0; i < index_count; i += 3)
319 vertex *v0 = &vertices[indices[i + 0]];
320 vertex *v1 = &vertices[indices[i + 1]];
321 vertex *v2 = &vertices[indices[i + 2]];
324 float du1, du2, dv1, dv2, f;
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;
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;
335 du1 = v1->texcoord.x - v0->texcoord.x;
336 dv1 = v1->texcoord.y - v0->texcoord.y;
338 du2 = v2->texcoord.x - v0->texcoord.x;
339 dv2 = v2->texcoord.y - v0->texcoord.y;
341 f = 1.0 / (du1 * dv2 - du2 * dv1);
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);
347 v0->tangent = tangent;
350 for (i = 0; i <= precision; i++)
352 for (j = 0; j <= precision; j++)
356 v = &vertices[i * (precision + 1) + j];
357 v->tangent = vertices[i * (precision + 1)].tangent;
374 change_to_2d_map(void)
376 if (map_dimension_state == MAP_DIMENSION_STATE_2D) return;
377 map_dimension_state = MAP_DIMENSION_STATE_2D;
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);
385 eo_do(texture_diffuse, evas_3d_texture_source_visible_set(EINA_TRUE));
387 evas_object_hide(image);
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);
395 change_to_3d_map(void)
397 if (map_dimension_state == MAP_DIMENSION_STATE_3D) return;
398 map_dimension_state = MAP_DIMENSION_STATE_3D;
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);
405 evas_object_show(image);
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);
413 zoom_factor_set(double new_zoom_factor)
415 double cur_zoom_factor;
418 vec3 camera_pos_unit_vec;
421 Evas_Coord src_x, src_y;
424 cur_zoom_factor = zoom_factor;
425 zoom_factor = ROUND(new_zoom_factor);
427 if (cur_zoom_factor == zoom_factor) return;
430 if (zoom_factor >= MIN_2D_ZOOM_FACTOR)
432 /* Transition from 3D to 2D */
433 if (cur_zoom_factor < MIN_2D_ZOOM_FACTOR)
435 zoom_factor = MIN_2D_ZOOM_FACTOR;
436 eo_do(scene, evas_3d_scene_pick(IMG_SIZE / 2, IMG_SIZE / 2,
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);
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);
449 elm_map_zoom_set(map, (int)zoom_factor);
454 if (zoom_factor < MIN_3D_ZOOM_FACTOR)
455 zoom_factor = MIN_3D_ZOOM_FACTOR;
457 /* Transition from 2D to 3D */
458 if (cur_zoom_factor >= MIN_2D_ZOOM_FACTOR)
463 /* Update texture source. */
464 src_size = IMG_SIZE * zoom_factor;
465 evas_object_resize(map, src_size, src_size);
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));
474 evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, texture_diffuse));
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;
483 evas_3d_node_position_set(camera_pos.x, camera_pos.y, camera_pos.z));
486 /* Update zoom slider. */
487 elm_slider_value_set(zoom_slider, zoom_factor);
491 zoom_in_cb(void *data,
495 zoom_factor_set(zoom_factor + 1);
499 zoom_out_cb(void *data,
503 zoom_factor_set(zoom_factor - 1);
507 zoom_to_2d_map_cb(void *data,
515 Evas_Coord src_x, src_y;
518 if (map_dimension_state == MAP_DIMENSION_STATE_2D) return;
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);
526 zoom_factor_set(MIN_2D_ZOOM_FACTOR);
528 elm_map_region_show(map, lon, lat);
532 zoom_to_3d_map_cb(void *data,
536 if (map_dimension_state == MAP_DIMENSION_STATE_3D) return;
538 zoom_factor_set(MAX_3D_ZOOM_FACTOR);
542 submenu_zoom_add(Elm_Object_Item *parent)
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);
553 submenu_info_add(Elm_Object_Item *parent)
560 Evas_Coord src_x, src_y;
565 if (map_dimension_state == MAP_DIMENSION_STATE_3D)
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);
575 elm_map_canvas_to_region_convert(map, mouse_down_pos.x, mouse_down_pos.y, &lon, &lat);
578 snprintf(buf, sizeof(buf), "Longitude : %f", lon);
579 elm_menu_item_add(menu, parent, NULL, buf, NULL, NULL);
581 snprintf(buf, sizeof(buf), "Latitude : %f", lat);
582 elm_menu_item_add(menu, parent, NULL, buf, NULL, NULL);
586 map_zoom_change_cb(void *data,
592 if (map_dimension_state == MAP_DIMENSION_STATE_3D) return;
594 cur_zoom_factor = elm_map_zoom_get(map);
596 if (elm_map_paused_get(map))
597 elm_map_paused_set(map, EINA_FALSE);
599 zoom_factor_set(cur_zoom_factor);
603 map_mouse_down_cb(void *data,
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;
618 mouse_down_pos.x = ev->canvas.x;
619 mouse_down_pos.y = ev->canvas.y;
621 evas_object_geometry_get(o, &x, &y, &w, &h);
623 obj_x = ev->canvas.x - x;
624 obj_y = ev->canvas.y - y;
626 eo_do(scene, evas_3d_scene_size_get(&scene_w, &scene_h));
628 scene_x = obj_x * scene_w / (double)w;
629 scene_y = obj_y * scene_h / (double)h;
631 eo_do(scene, pick = evas_3d_scene_pick(scene_x, scene_y, &n, &m, &s, &t));
635 printf("Not picked : ");
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,
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);
656 elm_menu_item_subitems_clear(menu_it);
657 submenu_info_add(menu_it);
659 elm_menu_move(menu, ev->canvas.x, ev->canvas.y);
660 evas_object_show(menu);
666 mouse_down_cb(void *data,
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;
681 mouse_down_pos.x = ev->canvas.x;
682 mouse_down_pos.y = ev->canvas.y;
684 /* Stop rotating earth. */
687 ecore_animator_del(animator);
691 evas_object_geometry_get(o, &x, &y, &w, &h);
693 obj_x = ev->canvas.x - x;
694 obj_y = ev->canvas.y - y;
696 eo_do(scene, evas_3d_scene_size_get(&scene_w, &scene_h));
698 scene_x = obj_x * scene_w / (double)w;
699 scene_y = obj_y * scene_h / (double)h;
701 eo_do(scene, pick = evas_3d_scene_pick(scene_x, scene_y, &n, &m, &s, &t));
705 printf("Not picked : ");
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,
716 is_mouse_pressed = EINA_TRUE;
717 else if (ev->button == 3)
719 elm_check_state_set(rotation_toggle, EINA_FALSE);
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);
729 elm_menu_item_subitems_clear(menu_it);
730 submenu_info_add(menu_it);
732 elm_menu_move(menu, ev->canvas.x, ev->canvas.y);
733 evas_object_show(menu);
738 mouse_move_cb(void *data,
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;
748 if ((ev->buttons == 1) && is_mouse_pressed)
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;
753 distance_to_origin = sqrt(pow(camera_pos.x, 2) + pow(camera_pos.y, 2) + pow(camera_pos.z, 2));
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);
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);
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));
771 if (elm_check_state_get(light_toggle))
773 /* Update light position as the same as camera position. */
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));
783 mouse_up_cb(void *data,
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;
798 evas_object_geometry_get(o, &x, &y, &w, &h);
800 obj_x = ev->canvas.x - x;
801 obj_y = ev->canvas.y - y;
803 eo_do(scene, evas_3d_scene_size_get(&scene_w, &scene_h));
805 scene_x = obj_x * scene_w / (double)w;
806 scene_y = obj_y * scene_h / (double)h;
808 eo_do(scene, pick = evas_3d_scene_pick(scene_x, scene_y, &n, &m, &s, &t));
812 printf("Not picked : ");
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,
822 /* Move camera position. */
824 is_mouse_pressed = EINA_FALSE;
826 if (elm_check_state_get(rotation_toggle))
828 /* Restart rotating earth. */
829 animator = ecore_animator_add(animate_scene, mesh_node);
834 mouse_wheel_cb(void *data,
839 Evas_Event_Mouse_Wheel *ev = event_info;
840 double new_zoom_factor;
842 if (map_dimension_state == MAP_DIMENSION_STATE_2D) return;
844 new_zoom_factor = zoom_factor - (ev->z * 0.1);
845 zoom_factor_set(new_zoom_factor);
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;
858 skybox_mesh = eo_add(EVAS_3D_MESH_CLASS, evas);
860 evas_3d_mesh_vertex_count_set(24),
861 evas_3d_mesh_frame_add(0),
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]),
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));
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);
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));
886 skybox_texture_diffuse = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
888 eo_do(skybox_texture_diffuse,
889 evas_3d_texture_source_set(skybox_image),
890 evas_3d_texture_source_visible_set(EINA_FALSE));
892 eo_do(skybox_material,
893 evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, skybox_texture_diffuse),
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),
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));
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));
912 texture_source_setup(void)
916 snprintf(buf, sizeof(buf), "%s/examples/evas3d_map_example.edj", elm_app_data_dir_get());
917 elm_theme_extension_add(NULL, buf);
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);
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);
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);
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));
949 /* Set camera position. */
952 camera_pos.z = MAX_CAMERA_DISTANCE;
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;
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;
964 camera_node = eo_add(EVAS_3D_NODE_CLASS, evas,
965 evas_3d_node_constructor(EVAS_3D_NODE_TYPE_CAMERA));
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));
977 light = eo_add(EVAS_3D_LIGHT_CLASS, evas);
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));
983 light_node = eo_add(EVAS_3D_NODE_CLASS, evas,
984 evas_3d_node_constructor(EVAS_3D_NODE_TYPE_LIGHT));
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));
996 /* Create a sphere mesh. */
999 mesh = eo_add(EVAS_3D_MESH_CLASS, evas);
1001 evas_3d_mesh_vertex_count_set(vertex_count),
1002 evas_3d_mesh_frame_add(0),
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),
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));
1018 material = eo_add(EVAS_3D_MATERIAL_CLASS, evas);
1019 eo_do(mesh, evas_3d_mesh_frame_material_set(0, material));
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));
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));
1032 evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, texture_diffuse),
1033 evas_3d_material_texture_set(EVAS_3D_MATERIAL_NORMAL, texture_normal),
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),
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));
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));
1053 hoversel_cb(void *data,
1057 elm_map_source_set(map, ELM_MAP_SOURCE_TYPE_TILE, (char *)data);
1058 zoom_factor_set(zoom_factor);
1062 hoversel_setup(Evas_Object *parent)
1064 hoversel = elm_hoversel_add(parent);
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");
1072 elm_object_part_content_set(parent, "elm.swallow.hoversel", hoversel);
1073 evas_object_show(hoversel);
1077 rotation_toggle_changed_cb(void *data,
1081 /* Stop rotating earth. */
1084 ecore_animator_del(animator);
1087 if (elm_check_state_get(obj))
1089 /* Restart rotating earth. */
1090 animator = ecore_animator_add(animate_scene, mesh_node);
1095 rotation_toggle_setup(Evas_Object *parent)
1097 rotation_toggle = elm_check_add(parent);
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);
1105 elm_object_part_content_set(parent, "elm.swallow.rotation_toggle", rotation_toggle);
1106 evas_object_show(rotation_toggle);
1108 evas_object_smart_callback_add(rotation_toggle, "changed", rotation_toggle_changed_cb, NULL);
1112 light_toggle_changed_cb(void *data,
1116 if (elm_check_state_get(obj))
1118 /* Set light position as the same as camera position. */
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));
1126 /* Set light position to default position. */
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));
1135 light_toggle_setup(Evas_Object *parent)
1137 light_toggle = elm_check_add(parent);
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);
1145 elm_object_part_content_set(parent, "elm.swallow.light_toggle", light_toggle);
1146 evas_object_show(light_toggle);
1148 evas_object_smart_callback_add(light_toggle, "changed", light_toggle_changed_cb, NULL);
1153 slider_changed_cb(void *data,
1157 double new_zoom_factor = ROUND(elm_slider_value_get(obj));
1159 if (new_zoom_factor == zoom_factor) return;
1161 zoom_factor_set(new_zoom_factor);
1165 zoom_slider_setup(Evas_Object *parent)
1167 zoom_slider = elm_slider_add(parent);
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);
1175 elm_object_part_content_set(parent, "elm.swallow.zoom_slider", zoom_slider);
1176 evas_object_show(zoom_slider);
1178 evas_object_smart_callback_add(zoom_slider, "changed", slider_changed_cb, NULL);
1182 elm_main(int argc, char **argv)
1186 elm_app_info_set(elm_main, "elementary", "examples/evas3d_map_example.edj");
1188 elm_config_accel_preference_set("3d");
1190 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
1193 win = elm_win_util_standard_add("elm_map_evas3d", "Elm_Map_Evas3d");
1194 elm_win_autodel_set(win, EINA_TRUE);
1196 evas = evas_object_evas_get(win);
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);
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);
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);
1214 /* Add a scene object. */
1215 scene = eo_add(EVAS_3D_SCENE_CLASS, evas);
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));
1222 texture_source_setup();
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));
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);
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);
1247 /* Start rotating earth */
1248 animator = ecore_animator_add(animate_scene, mesh_node);
1250 evas_object_resize(win, WIDTH, HEIGHT);
1251 evas_object_show(win);