summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Walter Seikel <won_fang@yahoo.com.au>2014-05-02 07:21:14 +1000
committerDavid Walter Seikel <won_fang@yahoo.com.au>2014-05-02 07:21:14 +1000
commitf3c02306eabbbba5c4031dfb369e4806abef6e09 (patch)
tree1e244cb202f1db0ae8da5953d83c9b424e059afc
Initial checkin.
-rw-r--r--evas-3d-elm.c826
1 files changed, 826 insertions, 0 deletions
diff --git a/evas-3d-elm.c b/evas-3d-elm.c
new file mode 100644
index 0000000..7a6a66a
--- /dev/null
+++ b/evas-3d-elm.c
@@ -0,0 +1,826 @@
1/* evas-3d-elm - a demonstration of using evas_3d in Elm. */
2
3
4//#define EFL_API_OVERRIDE 1
5/* Enable access to unstable EFL API that are still in beta */
6#define EFL_BETA_API_SUPPORT 1
7/* Enable access to unstable EFL EO API. */
8#define EFL_EO_API_SUPPORT 1
9
10#include <stdio.h>
11#include <ctype.h>
12
13#include <Elementary.h>
14
15
16#define WIDTH (400)
17#define HEIGHT (400)
18
19
20typedef struct _globals
21{
22 Evas *evas; // Our Evas.
23 Evas_Object *win; // Our Elm window.
24} globals;
25
26globals ourGlobals;
27
28
29typedef struct _Scene_Data
30{
31 Evas_Object *image; // Our Elm image.
32 Evas_3D_Scene *scene;
33 Evas_3D_Node *root_node;
34 Evas_3D_Node *camera_node;
35 Evas_3D_Node *light_node;
36
37 Evas_3D_Camera *camera;
38 Evas_3D_Light *light;
39
40 Evas_3D_Mesh *mesh;
41 Evas_3D_Node *mesh_node;
42 Evas_3D_Material *material0;
43 Evas_3D_Material *material1;
44 Evas_3D_Texture *texture0;
45 Evas_3D_Texture *texture1;
46 Evas_3D_Texture *texture_normal;
47
48 Evas_3D_Mesh *mesh2;
49 Evas_3D_Node *mesh2_node;
50 Evas_3D_Material *material2;
51 Evas_3D_Texture *texture2;
52
53 Evas_3D_Mesh *mesh3;
54 Evas_3D_Node *mesh3_node;
55 Evas_3D_Material *material3;
56 Evas_3D_Texture *texture_diffuse;
57
58} Scene_Data;
59
60static Scene_Data ourScene;
61
62
63static const float cube_vertices[] =
64{
65 /* Front */
66 -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0,
67 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,
68 -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
69 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0,
70
71 /* Back */
72 1.0, 1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0,
73 -1.0, 1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0,
74 1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0,
75 -1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0,
76
77 /* Left */
78 -1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0,
79 -1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0,
80 -1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,
81 -1.0, -1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0,
82
83 /* Right */
84 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
85 1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0,
86 1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
87 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0,
88
89 /* Top */
90 -1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
91 1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0,
92 -1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0,
93 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0,
94
95 /* Bottom */
96 1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0,
97 -1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0,
98 1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0,
99 -1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0,
100};
101
102static const unsigned short cube_indices[] =
103{
104 /* Front */
105 0, 1, 2, 2, 1, 3,
106
107 /* Back */
108 4, 5, 6, 6, 5, 7,
109
110 /* Left */
111 8, 9, 10, 10, 9, 11,
112
113 /* Right */
114 12, 13, 14, 14, 13, 15,
115
116 /* Top */
117 16, 17, 18, 18, 17, 19,
118
119 /* Bottom */
120 20, 21, 22, 22, 21, 23
121};
122
123static const unsigned int pixels0[] =
124{
125 0xff0000ff, 0xff0000ff, 0xffff0000, 0xffff0000,
126 0xff0000ff, 0xff0000ff, 0xffff0000, 0xffff0000,
127 0xff00ff00, 0xff00ff00, 0xff000000, 0xff000000,
128 0xff00ff00, 0xff00ff00, 0xff000000, 0xff000000,
129};
130
131static const unsigned int pixels1[] =
132{
133 0xffff0000, 0xffff0000, 0xff00ff00, 0xff00ff00,
134 0xffff0000, 0xffff0000, 0xff00ff00, 0xff00ff00,
135 0xff0000ff, 0xff0000ff, 0xffffffff, 0xffffffff,
136 0xff0000ff, 0xff0000ff, 0xffffffff, 0xffffffff,
137};
138
139
140typedef struct _vec4
141{
142 float x;
143 float y;
144 float z;
145 float w;
146} vec4;
147
148typedef struct _vec3
149{
150 float x;
151 float y;
152 float z;
153} vec3;
154
155typedef struct _vec2
156{
157 float x;
158 float y;
159} vec2;
160
161typedef struct _vertex
162{
163 vec3 position;
164 vec3 normal;
165 vec3 tangent;
166 vec4 color;
167 vec3 texcoord;
168} vertex;
169
170static int vertex_count = 0;
171static vertex *sphere_vertices = NULL;
172
173static int index_count = 0;
174static unsigned short *sphere_indices = NULL;
175
176static inline vec3
177_normalize(const vec3 *v)
178{
179 double l = sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
180 vec3 vec;
181
182 vec.x = v->x / l;
183 vec.y = v->y / l;
184 vec.z = v->z / l;
185
186 return vec;
187}
188
189static void
190_sphere_fini()
191{
192 if (sphere_vertices)
193 free(sphere_vertices);
194
195 if (sphere_indices)
196 free(sphere_indices);
197}
198
199static void
200_sphere_init(int precision)
201{
202 int i, j;
203 unsigned short *index;
204
205 vertex_count = (precision + 1) * (precision + 1);
206 index_count = precision * precision * 6;
207
208 /* Allocate buffer. */
209 sphere_vertices = malloc(sizeof(vertex) * vertex_count);
210 sphere_indices = malloc(sizeof(unsigned short) * index_count);
211
212 for (i = 0; i <= precision; i++)
213 {
214 double lati = (M_PI * (double)i) / (double)precision;
215 double y = cos(lati);
216 double r = fabs(sin(lati));
217
218 for (j = 0; j <= precision; j++)
219 {
220 double longi = (M_PI * 2.0 * j) / precision;
221 vertex *v = &sphere_vertices[i * (precision + 1) + j];
222
223 if (j == 0 || j == precision)
224 v->position.x = 0.0;
225 else
226 v->position.x = r * sin(longi);
227
228 v->position.y = y;
229
230 if (j == 0 || j == precision)
231 v->position.z = r;
232 else
233 v->position.z = r * cos(longi);
234
235 v->normal = v->position;
236
237 if (v->position.x > 0.0)
238 {
239 v->tangent.x = -v->normal.y;
240 v->tangent.y = v->normal.x;
241 v->tangent.z = v->normal.z;
242 }
243 else
244 {
245 v->tangent.x = v->normal.y;
246 v->tangent.y = -v->normal.x;
247 v->tangent.z = v->normal.z;
248 }
249
250 v->color.x = v->position.x;
251 v->color.y = v->position.y;
252 v->color.z = v->position.z;
253 v->color.w = 1.0;
254
255 if (j == precision)
256 v->texcoord.x = 1.0;
257 else if (j == 0)
258 v->texcoord.x = 0.0;
259 else
260 v->texcoord.x = (double)j / (double)precision;
261
262 if (i == precision)
263 v->texcoord.y = 1.0;
264 else if (i == 0)
265 v->texcoord.y = 0.0;
266 else
267 v->texcoord.y = 1.0 - (double)i / (double)precision;
268 }
269 }
270
271 index = &sphere_indices[0];
272
273 for (i = 0; i < precision; i++)
274 {
275 for (j = 0; j < precision; j++)
276 {
277 *index++ = i * (precision + 1) + j;
278 *index++ = i * (precision + 1) + j + 1;
279 *index++ = (i + 1) * (precision + 1) + j;
280
281 *index++ = (i + 1) * (precision + 1) + j;
282 *index++ = i * (precision + 1) + j + 1;
283 *index++ = (i + 1) * (precision + 1) + j + 1;
284 }
285 }
286
287 for (i = 0; i < index_count; i += 3)
288 {
289 vertex *v0 = &sphere_vertices[sphere_indices[i + 0]];
290 vertex *v1 = &sphere_vertices[sphere_indices[i + 1]];
291 vertex *v2 = &sphere_vertices[sphere_indices[i + 2]];
292
293 vec3 e1, e2;
294 float du1, du2, dv1, dv2, f;
295 vec3 tangent;
296
297 e1.x = v1->position.x - v0->position.x;
298 e1.y = v1->position.y - v0->position.y;
299 e1.z = v1->position.z - v0->position.z;
300
301 e2.x = v2->position.x - v0->position.x;
302 e2.y = v2->position.y - v0->position.y;
303 e2.z = v2->position.z - v0->position.z;
304
305 du1 = v1->texcoord.x - v0->texcoord.x;
306 dv1 = v1->texcoord.y - v0->texcoord.y;
307
308 du2 = v2->texcoord.x - v0->texcoord.x;
309 dv2 = v2->texcoord.y - v0->texcoord.y;
310
311 f = 1.0 / (du1 * dv2 - du2 * dv1);
312
313 tangent.x = f * (dv2 * e1.x - dv1 * e2.x);
314 tangent.y = f * (dv2 * e1.y - dv1 * e2.y);
315 tangent.z = f * (dv2 * e1.z - dv1 * e2.z);
316
317 v0->tangent = tangent;
318 }
319
320 for (i = 0; i <= precision; i++)
321 {
322 for (j = 0; j <= precision; j++)
323 {
324 if (j == precision)
325 {
326 vertex *v = &sphere_vertices[i * (precision + 1) + j];
327 v->tangent = sphere_vertices[i * (precision + 1)].tangent;
328 }
329 }
330 }
331}
332
333
334static Eina_Bool
335_animate_scene(void *data)
336{
337 static float angle = 0.0f;
338 static float earthAngle = 0.0f;
339 static int frame = 0;
340 static int inc = 1;
341 static int sonicFrame = 0;
342
343 Scene_Data *scene = (Scene_Data *)data;
344
345 // Animate cube.
346 angle += 0.5;
347 if (angle > 360.0) angle -= 360.0f;
348
349 frame += inc;
350
351 if (frame >= 20) inc = -1;
352 else if (frame <= 0) inc = 1;
353
354 eo_do(scene->mesh_node,
355 evas_3d_node_orientation_angle_axis_set(angle, 1.0, 1.0, 1.0),
356 evas_3d_node_mesh_frame_set(scene->mesh, frame)
357 );
358
359 // Animate sonic.
360 sonicFrame += 32;
361 if (sonicFrame > 256 * 50) sonicFrame = 0;
362 eo_do(scene->mesh2_node,
363 evas_3d_node_mesh_frame_set(scene->mesh2, sonicFrame)
364 );
365
366 // Animate earth.
367 earthAngle += 0.3;
368 if (earthAngle > 360.0) earthAngle -= 360.0f;
369 eo_do(scene->mesh3_node,
370 evas_3d_node_orientation_angle_axis_set(angle, 0.0, 1.0, 0.0)
371 );
372
373 return EINA_TRUE;
374}
375
376
377static void
378_camera_setup(globals *ourGlobals, Scene_Data *scene)
379{
380 scene->camera = eo_add(EVAS_3D_CAMERA_CLASS, ourGlobals->evas);
381 eo_do(scene->camera,
382 evas_3d_camera_projection_perspective_set(60.0, 1.0, 1.0, 500.0)
383 );
384
385 scene->camera_node = evas_3d_node_add(ourGlobals->evas, EVAS_3D_NODE_TYPE_CAMERA);
386 eo_do(scene->camera_node,
387 evas_3d_node_camera_set(scene->camera)
388 );
389 eo_do(scene->root_node, evas_3d_node_member_add(scene->camera_node));
390 eo_do(scene->camera_node,
391 evas_3d_node_position_set(50.0, 0.0, 20.0),
392 evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 20.0, EVAS_3D_SPACE_PARENT, 0.0, 0.0, 1.0)
393 );
394}
395
396static void
397_light_setup(globals *ourGlobals, Scene_Data *scene)
398{
399 scene->light = eo_add(EVAS_3D_LIGHT_CLASS, ourGlobals->evas);
400 eo_do(scene->light,
401 evas_3d_light_ambient_set(1.0, 1.0, 1.0, 1.0),
402 evas_3d_light_diffuse_set(1.0, 1.0, 1.0, 1.0),
403 evas_3d_light_specular_set(1.0, 1.0, 1.0, 1.0),
404 evas_3d_light_directional_set(EINA_TRUE)
405 );
406
407 scene->light_node = evas_3d_node_add(ourGlobals->evas, EVAS_3D_NODE_TYPE_LIGHT);
408 eo_do(scene->light_node,
409 evas_3d_node_light_set(scene->light)
410 );
411 eo_do(scene->root_node,
412 evas_3d_node_member_add(scene->light_node)
413 );
414 eo_do(scene->light_node,
415 evas_3d_node_position_set(1000.0, 0.0, 1000.0),
416 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)
417 );
418}
419
420static void
421_cube_setup(globals *ourGlobals, Scene_Data *scene)
422{
423 // Setup cube materials.
424 scene->material0 = eo_add(EVAS_3D_MATERIAL_CLASS, ourGlobals->evas);
425 scene->material1 = eo_add(EVAS_3D_MATERIAL_CLASS, ourGlobals->evas);
426
427 eo_do(scene->material0,
428 evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
429 evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
430 evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
431 evas_3d_material_enable_set(EVAS_3D_MATERIAL_NORMAL, EINA_TRUE),
432
433 evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 0.2, 0.2, 0.2, 1.0),
434 evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 0.8, 0.8, 0.8, 1.0),
435 evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 1.0, 1.0, 1.0, 1.0),
436 evas_3d_material_shininess_set(100.0)
437 );
438
439 eo_do(scene->material1,
440 evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
441 evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
442 evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
443 evas_3d_material_enable_set(EVAS_3D_MATERIAL_NORMAL, EINA_TRUE),
444
445 evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 0.2, 0.2, 0.2, 1.0),
446 evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 0.8, 0.8, 0.8, 1.0),
447 evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 1.0, 1.0, 1.0, 1.0),
448 evas_3d_material_shininess_set(100.0)
449 );
450
451 scene->texture0 = eo_add(EVAS_3D_TEXTURE_CLASS, ourGlobals->evas);
452 scene->texture1 = eo_add(EVAS_3D_TEXTURE_CLASS, ourGlobals->evas);
453 scene->texture_normal = eo_add(EVAS_3D_TEXTURE_CLASS, ourGlobals->evas);
454
455 eo_do(scene->texture0,
456 evas_3d_texture_data_set(EVAS_3D_COLOR_FORMAT_RGBA, EVAS_3D_PIXEL_FORMAT_8888, 4, 4, &pixels0[0])
457 );
458 eo_do(scene->texture1,
459 evas_3d_texture_data_set(EVAS_3D_COLOR_FORMAT_RGBA, EVAS_3D_PIXEL_FORMAT_8888, 4, 4, &pixels1[0])
460 );
461 eo_do(scene->texture_normal, evas_3d_texture_file_set("media/normal_lego.png", NULL));
462
463 eo_do(scene->material0, evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, scene->texture0));
464 eo_do(scene->material1, evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, scene->texture1));
465 eo_do(scene->material1, evas_3d_material_texture_set(EVAS_3D_MATERIAL_NORMAL, scene->texture_normal));
466
467 // Setup CUBE mesh.
468 scene->mesh = eo_add(EVAS_3D_MESH_CLASS, ourGlobals->evas);
469 eo_do(scene->mesh,
470 evas_3d_mesh_vertex_count_set(24),
471 evas_3d_mesh_frame_add(0),
472
473 evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_POSITION, 12 * sizeof(float), &cube_vertices[ 0]),
474 evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_NORMAL, 12 * sizeof(float), &cube_vertices[ 3]),
475 evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_COLOR, 12 * sizeof(float), &cube_vertices[ 6]),
476 evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_TEXCOORD, 12 * sizeof(float), &cube_vertices[10]),
477
478 evas_3d_mesh_index_data_set(EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT, 36, &cube_indices[0]),
479 evas_3d_mesh_vertex_assembly_set(EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES),
480
481 evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_NORMAL_MAP),
482
483 evas_3d_mesh_frame_material_set(0, scene->material0),
484
485 evas_3d_mesh_frame_add(20),
486 evas_3d_mesh_frame_material_set(20, scene->material1)
487 );
488 scene->mesh_node = evas_3d_node_add(ourGlobals->evas, EVAS_3D_NODE_TYPE_MESH);
489 eo_do(scene->root_node, evas_3d_node_member_add(scene->mesh_node));
490 eo_do(scene->mesh_node,
491 eo_key_data_set("Name", "cube", NULL),
492 evas_3d_node_position_set(40.0, 3.5, 23.0),
493 evas_3d_node_mesh_add(scene->mesh)
494 );
495}
496
497static void
498_sonic_setup(globals *ourGlobals, Scene_Data *scene)
499{
500 // Setup an MD2 mesh.
501 scene->mesh2 = eo_add(EVAS_3D_MESH_CLASS, ourGlobals->evas);
502 eo_do(scene->mesh2,
503 evas_3d_mesh_file_set(EVAS_3D_MESH_FILE_TYPE_MD2, "media/sonic.md2", NULL)
504 );
505
506 scene->material2 = eo_add(EVAS_3D_MATERIAL_CLASS, ourGlobals->evas);
507 eo_do(scene->mesh2,
508 evas_3d_mesh_frame_material_set(0, scene->material2)
509 );
510
511 scene->texture2 = eo_add(EVAS_3D_TEXTURE_CLASS, ourGlobals->evas);
512 eo_do(scene->texture2,
513 evas_3d_texture_file_set("media/sonic.png", NULL),
514 evas_3d_texture_filter_set(EVAS_3D_TEXTURE_FILTER_NEAREST, EVAS_3D_TEXTURE_FILTER_NEAREST),
515 evas_3d_texture_wrap_set(EVAS_3D_WRAP_MODE_REPEAT, EVAS_3D_WRAP_MODE_REPEAT)
516 );
517
518 eo_do(scene->material2,
519 evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, scene->texture2),
520
521 evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
522 evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
523 evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
524 evas_3d_material_enable_set(EVAS_3D_MATERIAL_NORMAL, EINA_TRUE),
525
526 evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 0.01, 0.01, 0.01, 1.0),
527 evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 1.0, 1.0, 1.0, 1.0),
528 evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 1.0, 1.0, 1.0, 1.0),
529 evas_3d_material_shininess_set(50.0)
530 );
531
532 scene->mesh2_node = evas_3d_node_add(ourGlobals->evas, EVAS_3D_NODE_TYPE_MESH);
533 eo_do(scene->root_node,
534 evas_3d_node_member_add(scene->mesh2_node)
535 );
536 eo_do(scene->mesh2_node,
537 eo_key_data_set("Name", "sonic", NULL),
538 evas_3d_node_mesh_add(scene->mesh2)
539 );
540
541 eo_do(scene->mesh2,
542 evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_PHONG)
543 );
544}
545
546static void
547_earth_setup(globals *ourGlobals, Scene_Data *scene)
548{
549 // Setup earth material.
550 scene->material3 = eo_add(EVAS_3D_MATERIAL_CLASS, ourGlobals->evas);
551
552 scene->texture_diffuse = eo_add(EVAS_3D_TEXTURE_CLASS, ourGlobals->evas);
553 eo_do(scene->texture_diffuse,
554 evas_3d_texture_file_set("media/EarthDiffuse.png", NULL),
555 evas_3d_texture_filter_set(EVAS_3D_TEXTURE_FILTER_LINEAR, EVAS_3D_TEXTURE_FILTER_LINEAR));
556 eo_do(scene->material3,
557 evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, scene->texture_diffuse),
558
559 evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
560 evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
561 evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
562
563 evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 0.01, 0.01, 0.01, 1.0),
564 evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 1.0, 1.0, 1.0, 1.0),
565 evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 1.0, 1.0, 1.0, 1.0),
566 evas_3d_material_shininess_set(50.0));
567
568 // Setup earth mesh.
569 _sphere_init(100);
570
571 scene->mesh3 = eo_add(EVAS_3D_MESH_CLASS, ourGlobals->evas);
572 eo_do(scene->mesh3,
573 evas_3d_mesh_vertex_count_set(vertex_count),
574 evas_3d_mesh_frame_add(0),
575 evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_POSITION, sizeof(vertex), &sphere_vertices[0].position),
576 evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_NORMAL, sizeof(vertex), &sphere_vertices[0].normal),
577 evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_TANGENT, sizeof(vertex), &sphere_vertices[0].tangent),
578 evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_COLOR, sizeof(vertex), &sphere_vertices[0].color),
579 evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_TEXCOORD, sizeof(vertex), &sphere_vertices[0].texcoord),
580
581 evas_3d_mesh_index_data_set(EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT, index_count, &sphere_indices[0]),
582 evas_3d_mesh_vertex_assembly_set(EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES),
583 evas_3d_mesh_frame_material_set(0, scene->material3)
584 );
585
586 scene->mesh3_node = evas_3d_node_add(ourGlobals->evas, EVAS_3D_NODE_TYPE_MESH);
587 eo_do(scene->root_node,
588 evas_3d_node_member_add(scene->mesh3_node)
589 );
590 eo_do(scene->mesh3_node,
591 eo_key_data_set("Name", "earth", NULL),
592 evas_3d_node_position_set(40.0, -3.5, 23.0),
593 evas_3d_node_mesh_add(scene->mesh3)
594 );
595
596 eo_do(scene->mesh3,
597 evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_DIFFUSE)
598 );
599}
600
601
602static void
603_scene_setup(globals *ourGlobals, Scene_Data *scene)
604{
605 scene->scene = eo_add(EVAS_3D_SCENE_CLASS, ourGlobals->evas);
606 eo_do(scene->scene,
607 evas_3d_scene_size_set(512, 512),
608 evas_3d_scene_background_color_set(0.0, 0.0, 0.0, 0.0)
609 );
610
611// scene->root_node = eo_add(EVAS_3D_NODE_CLASS, ourGlobals->evas, EVAS_3D_NODE_TYPE_NODE);
612 scene->root_node = evas_3d_node_add(ourGlobals->evas, EVAS_3D_NODE_TYPE_NODE);
613
614 _camera_setup(ourGlobals, scene);
615 _light_setup(ourGlobals, scene);
616 _cube_setup(ourGlobals, scene);
617 _sonic_setup(ourGlobals, scene);
618 _earth_setup(ourGlobals, scene);
619
620 eo_do(scene->scene,
621 evas_3d_scene_root_node_set(scene->root_node),
622 evas_3d_scene_camera_node_set(scene->camera_node)
623 );
624}
625
626
627
628static void _on_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *o, void *einfo)
629{
630 Scene_Data *scene = data;
631 Evas_Event_Mouse_Move *ev = einfo;
632 Evas_Coord x, y, w, h;
633 Evas_Coord obj_x, obj_y;
634 int scene_w, scene_h;
635 Evas_Real scene_x, scene_y;
636 Evas_Real s, t;
637 Evas_3D_Node *n;
638 Evas_3D_Mesh *m;
639 Eina_Bool pick;
640 char *name = NULL;
641
642 evas_object_geometry_get(o, &x, &y, &w, &h);
643
644 obj_x = ev->cur.canvas.x - x;
645 obj_y = ev->cur.canvas.y - y;
646
647 eo_do(scene->scene, evas_3d_scene_size_get(&scene_w, &scene_h));
648
649 scene_x = obj_x * scene_w / (Evas_Real)w;
650 scene_y = obj_y * scene_h / (Evas_Real)h;
651
652 eo_do(scene->scene, pick = evas_3d_scene_pick(scene_x, scene_y, &n, &m, &s, &t));
653 if (pick)
654 name = evas_object_data_get(n, "Name");
655 // This is a raw Evas callback, on the Elm image internal Evas_Object.
656 // So we need to get the Elm Image back from the raw Evas_Object.
657 // Which is why we stuffed it in the scene structure.
658 if (name)
659 {
660 elm_object_tooltip_text_set(scene->image, name);
661 elm_object_tooltip_show(scene->image);
662 }
663 else
664 elm_object_tooltip_hide(scene->image);
665}
666
667static void _on_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *o, void *einfo)
668{
669 Scene_Data *scene = data;
670 Evas_Event_Mouse_Down *ev = einfo;
671 Evas_Coord x, y, w, h;
672 Evas_Coord obj_x, obj_y;
673 int scene_w, scene_h;
674 Evas_Real scene_x, scene_y;
675 Evas_Real s, t;
676 Evas_3D_Node *n;
677 Evas_3D_Mesh *m;
678 Eina_Bool pick;
679 char *name = NULL;
680
681 evas_object_geometry_get(o, &x, &y, &w, &h);
682
683 obj_x = ev->canvas.x - x;
684 obj_y = ev->canvas.y - y;
685
686 eo_do(scene->scene, evas_3d_scene_size_get(&scene_w, &scene_h));
687
688 scene_x = obj_x * scene_w / (Evas_Real)w;
689 scene_y = obj_y * scene_h / (Evas_Real)h;
690
691 eo_do(scene->scene, pick = evas_3d_scene_pick(scene_x, scene_y, &n, &m, &s, &t));
692 if (pick)
693 {
694 name = evas_object_data_get(n, "Name");
695 printf("Picked : ");
696 }
697 else
698 printf("Not picked : ");
699 if (NULL == name)
700 name = "";
701
702 printf("output(%d, %d) canvas(%d, %d) object(%d, %d) scene(%f, %f) texcoord(%f, %f) "
703 "node(%p) %s mesh(%p)\n",
704 ev->output.x, ev->output.y,
705 ev->canvas.x, ev->canvas.y,
706 obj_x, obj_y,
707 scene_x, scene_y,
708 s, t, n, name, m);
709}
710
711static void
712_changed_cb(void *data, Evas_Object *obj, void *event_info)
713{
714 Scene_Data *scene = data;
715 double val = elm_slider_value_get(obj);
716
717 eo_do(scene->camera_node, evas_3d_node_position_set(50.0 + val, 0.0, 20.0));
718}
719
720static void _on_done(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
721{
722 // Tell the main loop to stop, which it will, eventually.
723 elm_exit();
724}
725
726static void open_window(globals *ourGlobals)
727{
728 char *name = "evas-3d-elm";
729 char *title = "Evas_3d Elementary demonstration";
730 Evas_Object *obj, *temp;
731 int w = WIDTH, h = HEIGHT;
732
733 // Set the engine to opengl_x11, then open the window.
734 elm_config_preferred_engine_set("opengl_x11");
735 if ((ourGlobals->win = elm_win_util_standard_add(name, title)))
736 {
737 evas_object_smart_callback_add(ourGlobals->win, "delete,request", _on_done, NULL);
738 evas_object_resize(ourGlobals->win, w, h);
739 evas_object_move(ourGlobals->win, 0, 0);
740 evas_object_show(ourGlobals->win);
741
742 // Get the Evas / canvas from the elm window (that the Evas_Object "lives on"), which is itself an Evas_Object created by Elm.
743 ourGlobals->evas = evas_object_evas_get(ourGlobals->win);
744
745 _scene_setup(ourGlobals, &ourScene);
746
747 // Add a background image object.
748 obj = eo_add(ELM_OBJ_IMAGE_CLASS, ourGlobals->win);
749 eo_do(obj,
750 evas_obj_size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND),
751 elm_obj_image_fill_outside_set(EINA_TRUE),
752 elm_obj_image_file_set("media/sky_01.jpg", NULL),
753 evas_obj_visibility_set(EINA_TRUE)
754 );
755 elm_win_resize_object_add(ourGlobals->win, obj);
756 eo_unref(obj);
757
758 // Add an image object for 3D scene rendering.
759 obj = eo_add(ELM_OBJ_IMAGE_CLASS, ourGlobals->win);
760 ourScene.image = obj;
761 eo_do(obj,
762 evas_obj_size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND),
763 elm_obj_image_fill_outside_set(EINA_TRUE),
764 evas_obj_visibility_set(EINA_TRUE),
765 temp = elm_obj_image_object_get()
766 );
767 eo_do(temp,
768 evas_obj_image_scene_set(ourScene.scene)
769 );
770 elm_object_tooltip_text_set(obj, "");
771 elm_object_tooltip_hide(obj);
772 // Elm can't seem to be able to tell us WHERE an image was clicked, so use raw Evas calbacks instead.
773 evas_object_event_callback_add(temp, EVAS_CALLBACK_MOUSE_MOVE, _on_mouse_move, &ourScene);
774 evas_object_event_callback_add(temp, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down, &ourScene);
775 elm_win_resize_object_add(ourGlobals->win, obj);
776
777 // Add animation timer callback.
778 ecore_timer_add(0.016, _animate_scene, &ourScene);
779
780 // Add a zoom slider.
781 obj = eo_add(ELM_OBJ_SLIDER_CLASS, ourGlobals->win);
782 eo_do(obj,
783 elm_obj_slider_min_max_set(-10, 10),
784 evas_obj_size_hint_align_set(1.0, EVAS_HINT_FILL),
785 evas_obj_size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND),
786 evas_obj_visibility_set(EINA_TRUE)
787 );
788 elm_win_resize_object_add(ourGlobals->win, obj);
789 evas_object_smart_callback_add(obj, "changed", _changed_cb, &ourScene);
790 eo_unref(obj);
791 }
792
793 // Set preferred engine back to default from config
794 elm_config_preferred_engine_set(NULL);
795}
796
797static void close_window(globals *ourGlobals)
798{
799 if (ourGlobals->win)
800 {
801 eo_unref(ourScene.image);
802 evas_object_del(ourGlobals->win);
803 _sphere_fini();
804 }
805
806 // This shuts down Elementary, but keeps the main loop running until all ecore_evas are freed.
807 elm_shutdown();
808}
809
810EAPI_MAIN int elm_main(int argc, char **argv)
811{
812 elm_policy_set(ELM_POLICY_EXIT, ELM_POLICY_EXIT_NONE);
813 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_NONE);
814 elm_policy_set(ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_HIDDEN_ALWAYS);
815
816 open_window(&ourGlobals);
817
818 if (ourGlobals.win)
819 elm_run();
820
821 close_window(&ourGlobals);
822
823 return 0;
824}
825
826ELM_MAIN()