From cee4c4ca9c9c9bf587cbaa74784b1c77972ad414 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Fri, 2 May 2014 01:23:33 +1000 Subject: Add the rotating Earth and pick example. --- media/EarthDiffuse.png | Bin 0 -> 2123166 bytes src/GuiLua/GuiLua.c | 322 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 317 insertions(+), 5 deletions(-) create mode 100644 media/EarthDiffuse.png diff --git a/media/EarthDiffuse.png b/media/EarthDiffuse.png new file mode 100644 index 0000000..3bcf58b Binary files /dev/null and b/media/EarthDiffuse.png differ diff --git a/src/GuiLua/GuiLua.c b/src/GuiLua/GuiLua.c index 36acd20..48c5c75 100644 --- a/src/GuiLua/GuiLua.c +++ b/src/GuiLua/GuiLua.c @@ -144,6 +144,11 @@ and ordinary elementary widgets. Proper introspection can come later. +globals ourGlobals; +static const char *globName = "ourGlobals"; + + + typedef struct _Scene_Data { @@ -151,22 +156,33 @@ typedef struct _Scene_Data Evas_3D_Node *root_node; Evas_3D_Node *camera_node; Evas_3D_Node *light_node; - Evas_3D_Node *mesh_node; - Evas_3D_Node *mesh2_node; Evas_3D_Camera *camera; Evas_3D_Light *light; + Evas_3D_Mesh *mesh; + Evas_3D_Node *mesh_node; Evas_3D_Material *material0; Evas_3D_Material *material1; Evas_3D_Texture *texture0; Evas_3D_Texture *texture1; Evas_3D_Texture *texture_normal; + Evas_3D_Mesh *mesh2; + Evas_3D_Node *mesh2_node; Evas_3D_Material *material2; Evas_3D_Texture *texture2; + + Evas_3D_Mesh *mesh3; + Evas_3D_Node *mesh3_node; + Evas_3D_Material *material3; + Evas_3D_Texture *texture_diffuse; + } Scene_Data; +static Scene_Data ourScene; + + static const float cube_vertices[] = { /* Front */ @@ -244,16 +260,205 @@ static const unsigned int pixels1[] = }; -globals ourGlobals; -static const char *globName = "ourGlobals"; +typedef struct _vec4 +{ + float x; + float y; + float z; + float w; +} vec4; +typedef struct _vec3 +{ + float x; + float y; + float z; +} vec3; + +typedef struct _vec2 +{ + float x; + float y; +} vec2; + +typedef struct _vertex +{ + vec3 position; + vec3 normal; + vec3 tangent; + vec4 color; + vec3 texcoord; +} vertex; + +static int vertex_count = 0; +static vertex *sphere_vertices = NULL; + +static int index_count = 0; +static unsigned short *sphere_indices = NULL; + +static inline vec3 +_normalize(const vec3 *v) +{ + double l = sqrt(v->x * v->x + v->y * v->y + v->z * v->z); + vec3 vec; + + vec.x = v->x / l; + vec.y = v->y / l; + vec.z = v->z / l; + + return vec; +} + +static void +_sphere_fini() +{ + if (sphere_vertices) + free(sphere_vertices); + + if (sphere_indices) + free(sphere_indices); +} + +static void +_sphere_init(int precision) +{ + int i, j; + unsigned short *index; + + vertex_count = (precision + 1) * (precision + 1); + index_count = precision * precision * 6; + + /* Allocate buffer. */ + sphere_vertices = malloc(sizeof(vertex) * vertex_count); + sphere_indices = malloc(sizeof(unsigned short) * index_count); + + for (i = 0; i <= precision; i++) + { + double lati = (M_PI * (double)i) / (double)precision; + double y = cos(lati); + double r = fabs(sin(lati)); + + for (j = 0; j <= precision; j++) + { + double longi = (M_PI * 2.0 * j) / precision; + vertex *v = &sphere_vertices[i * (precision + 1) + j]; + + if (j == 0 || j == precision) + v->position.x = 0.0; + else + v->position.x = r * sin(longi); + + v->position.y = y; + + if (j == 0 || j == precision) + v->position.z = r; + else + v->position.z = r * cos(longi); + + v->normal = v->position; + + if (v->position.x > 0.0) + { + v->tangent.x = -v->normal.y; + v->tangent.y = v->normal.x; + v->tangent.z = v->normal.z; + } + else + { + v->tangent.x = v->normal.y; + v->tangent.y = -v->normal.x; + v->tangent.z = v->normal.z; + } + + v->color.x = v->position.x; + v->color.y = v->position.y; + v->color.z = v->position.z; + v->color.w = 1.0; + + if (j == precision) + v->texcoord.x = 1.0; + else if (j == 0) + v->texcoord.x = 0.0; + else + v->texcoord.x = (double)j / (double)precision; + + if (i == precision) + v->texcoord.y = 1.0; + else if (i == 0) + v->texcoord.y = 0.0; + else + v->texcoord.y = 1.0 - (double)i / (double)precision; + } + } + + index = &sphere_indices[0]; + + for (i = 0; i < precision; i++) + { + for (j = 0; j < precision; j++) + { + *index++ = i * (precision + 1) + j; + *index++ = i * (precision + 1) + j + 1; + *index++ = (i + 1) * (precision + 1) + j; + + *index++ = (i + 1) * (precision + 1) + j; + *index++ = i * (precision + 1) + j + 1; + *index++ = (i + 1) * (precision + 1) + j + 1; + } + } + + for (i = 0; i < index_count; i += 3) + { + vertex *v0 = &sphere_vertices[sphere_indices[i + 0]]; + vertex *v1 = &sphere_vertices[sphere_indices[i + 1]]; + vertex *v2 = &sphere_vertices[sphere_indices[i + 2]]; + + vec3 e1, e2; + float du1, du2, dv1, dv2, f; + vec3 tangent; + + e1.x = v1->position.x - v0->position.x; + e1.y = v1->position.y - v0->position.y; + e1.z = v1->position.z - v0->position.z; + + e2.x = v2->position.x - v0->position.x; + e2.y = v2->position.y - v0->position.y; + e2.z = v2->position.z - v0->position.z; + + du1 = v1->texcoord.x - v0->texcoord.x; + dv1 = v1->texcoord.y - v0->texcoord.y; + + du2 = v2->texcoord.x - v0->texcoord.x; + dv2 = v2->texcoord.y - v0->texcoord.y; + + f = 1.0 / (du1 * dv2 - du2 * dv1); + + tangent.x = f * (dv2 * e1.x - dv1 * e2.x); + tangent.y = f * (dv2 * e1.y - dv1 * e2.y); + tangent.z = f * (dv2 * e1.z - dv1 * e2.z); + + v0->tangent = tangent; + } + + for (i = 0; i <= precision; i++) + { + for (j = 0; j <= precision; j++) + { + if (j == precision) + { + vertex *v = &sphere_vertices[i * (precision + 1) + j]; + v->tangent = sphere_vertices[i * (precision + 1)].tangent; + } + } + } +} -static Scene_Data ourScene; static Eina_Bool _animate_scene(void *data) { static float angle = 0.0f; + static float earthAngle = 0.0f; static int frame = 0; static int inc = 1; static int sonicFrame = 0; @@ -281,6 +486,13 @@ _animate_scene(void *data) evas_3d_node_mesh_frame_set(scene->mesh2, sonicFrame) ); + // Animate earth. + earthAngle += 0.3; + if (earthAngle > 360.0) earthAngle -= 360.0f; + eo_do(scene->mesh3_node, + evas_3d_node_orientation_angle_axis_set(angle, 0.0, 1.0, 0.0) + ); + return EINA_TRUE; } @@ -399,6 +611,7 @@ _mesh_setup(globals *ourGlobals, Scene_Data *scene) scene->mesh_node = evas_3d_node_add(ourGlobals->evas, EVAS_3D_NODE_TYPE_MESH); eo_do(scene->root_node, evas_3d_node_member_add(scene->mesh_node)); eo_do(scene->mesh_node, + eo_key_data_set("Name", "cube", NULL), evas_3d_node_position_set(40.0, 3.5, 23.0), evas_3d_node_mesh_add(scene->mesh) ); @@ -441,12 +654,65 @@ _mesh_setup(globals *ourGlobals, Scene_Data *scene) evas_3d_node_member_add(scene->mesh2_node) ); eo_do(scene->mesh2_node, + eo_key_data_set("Name", "sonic", NULL), evas_3d_node_mesh_add(scene->mesh2) ); eo_do(scene->mesh2, evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_PHONG) ); + + + // Setup earth material. + scene->material3 = eo_add(EVAS_3D_MATERIAL_CLASS, ourGlobals->evas); + + scene->texture_diffuse = eo_add(EVAS_3D_TEXTURE_CLASS, ourGlobals->evas); + eo_do(scene->texture_diffuse, + evas_3d_texture_file_set("../../media/EarthDiffuse.png", NULL), + evas_3d_texture_filter_set(EVAS_3D_TEXTURE_FILTER_LINEAR, EVAS_3D_TEXTURE_FILTER_LINEAR)); + eo_do(scene->material3, + evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, scene->texture_diffuse), + + evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE), + evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE), + evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE), + + evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 0.01, 0.01, 0.01, 1.0), + evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 1.0, 1.0, 1.0, 1.0), + evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 1.0, 1.0, 1.0, 1.0), + evas_3d_material_shininess_set(50.0)); + + // Setup earth mesh. + _sphere_init(100); + + scene->mesh3 = eo_add(EVAS_3D_MESH_CLASS, ourGlobals->evas); + eo_do(scene->mesh3, + evas_3d_mesh_vertex_count_set(vertex_count), + evas_3d_mesh_frame_add(0), + evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_POSITION, sizeof(vertex), &sphere_vertices[0].position), + evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_NORMAL, sizeof(vertex), &sphere_vertices[0].normal), + evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_TANGENT, sizeof(vertex), &sphere_vertices[0].tangent), + evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_COLOR, sizeof(vertex), &sphere_vertices[0].color), + evas_3d_mesh_frame_vertex_data_set(0, EVAS_3D_VERTEX_TEXCOORD, sizeof(vertex), &sphere_vertices[0].texcoord), + + evas_3d_mesh_index_data_set(EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT, index_count, &sphere_indices[0]), + evas_3d_mesh_vertex_assembly_set(EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES), + evas_3d_mesh_frame_material_set(0, scene->material3) + ); + + scene->mesh3_node = evas_3d_node_add(ourGlobals->evas, EVAS_3D_NODE_TYPE_MESH); + eo_do(scene->root_node, + evas_3d_node_member_add(scene->mesh3_node) + ); + eo_do(scene->mesh3_node, + eo_key_data_set("Name", "earth", NULL), + evas_3d_node_position_set(40.0, -3.5, 23.0), + evas_3d_node_mesh_add(scene->mesh3) + ); + + eo_do(scene->mesh3, + evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_DIFFUSE) + ); } @@ -525,6 +791,50 @@ static void _on_click(void *data, Evas_Object *obj, void *event_info EINA_UNUSED } } +static void _on_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *o, void *einfo) +{ +// globals *ourGlobals = data; + Evas_Event_Mouse_Down *ev = einfo; + Evas_Coord x, y, w, h; + Evas_Coord obj_x, obj_y; + int scene_w, scene_h; + Evas_Real scene_x, scene_y; + Evas_Real s, t; + Evas_3D_Node *n; + Evas_3D_Mesh *m; + Eina_Bool pick; + char *name; + + evas_object_geometry_get(o, &x, &y, &w, &h); + + obj_x = ev->canvas.x - x; + obj_y = ev->canvas.y - y; + + eo_do(ourScene.scene, evas_3d_scene_size_get(&scene_w, &scene_h)); + + scene_x = obj_x * scene_w / (Evas_Real)w; + scene_y = obj_y * scene_h / (Evas_Real)h; + + eo_do(ourScene.scene, pick = evas_3d_scene_pick(scene_x, scene_y, &n, &m, &s, &t)); + if (pick) + { + name = evas_object_data_get(n, "Name"); + printf("Picked : "); + } + else + printf("Not picked : "); + if (NULL == name) + name = ""; + + printf("output(%d, %d) canvas(%d, %d) object(%d, %d) scene(%f, %f) texcoord(%f, %f) " + "node(%p) %s mesh(%p)\n", + ev->output.x, ev->output.y, + ev->canvas.x, ev->canvas.y, + obj_x, obj_y, + scene_x, scene_y, + s, t, n, name, m); +} + static void _on_done(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { // globals *ourGlobals = data; @@ -675,6 +985,7 @@ static int window(lua_State *L) eo_do(temp, evas_obj_image_scene_set(ourScene.scene) ); + evas_object_event_callback_add(temp, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down, &ourGlobals); // Add animation timer callback. ecore_timer_add(0.016, _animate_scene, &ourScene); @@ -741,6 +1052,7 @@ static int closeWindow(lua_State *L) eo_unref(wid->obj); } evas_object_del(ourGlobals->win); + _sphere_fini(); } if (ourGlobals->logDom >= 0) -- cgit v1.1