cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=dc0b144cf09deba3a5a6fe746f0130b67b5bf64b

commit dc0b144cf09deba3a5a6fe746f0130b67b5bf64b
Author: Oleksandr Shcherbina <o.shcherb...@samsung.com>
Date:   Wed Feb 11 17:44:42 2015 +0100

    evas: Evas_3D - mechanism for finding node by color pick.
    
    Summary:
    See first part https://phab.enlightenment.org/D1811 (backend, gl)
    
    Add get/set for color pick mode at evas_3d_mesh and evas_3d_scene
    Add evas_3d_node_color_node_mesh_collect function to collect data at force 
rendering
    Add state flag for scene to avoid useless force rendering in case scene 
wasn't changed
    Add functionality for color pick in evas_3d_scene_pick method
    
    Reviewers: Hermet, raster, cedric
    
    Reviewed By: cedric
    
    Subscribers: cedric
    
    Differential Revision: https://phab.enlightenment.org/D1956
    
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 src/lib/evas/Evas_Eo.h               |   1 +
 src/lib/evas/canvas/evas_3d_mesh.c   |  17 ++++++
 src/lib/evas/canvas/evas_3d_mesh.eo  |  21 +++++++
 src/lib/evas/canvas/evas_3d_node.c   |  71 +++++++++++++++++++++++
 src/lib/evas/canvas/evas_3d_scene.c  | 109 +++++++++++++++++++++++++++++++++--
 src/lib/evas/canvas/evas_3d_scene.eo |  21 +++++++
 src/lib/evas/include/evas_private.h  |   8 ++-
 7 files changed, 242 insertions(+), 6 deletions(-)

diff --git a/src/lib/evas/Evas_Eo.h b/src/lib/evas/Evas_Eo.h
index 8fa89b3..033ada2 100644
--- a/src/lib/evas/Evas_Eo.h
+++ b/src/lib/evas/Evas_Eo.h
@@ -468,6 +468,7 @@ typedef enum _Evas_3D_State
    EVAS_3D_STATE_SCENE_BACKGROUND_COLOR,
    EVAS_3D_STATE_SCENE_SIZE,
    EVAS_3D_STATE_SCENE_SHADOWS_ENABLED,
+   EVAS_3D_STATE_SCENE_UPDATED,
 
    EVAS_3D_STATE_TEXTURE_DATA = 1,
    EVAS_3D_STATE_TEXTURE_WRAP,
diff --git a/src/lib/evas/canvas/evas_3d_mesh.c 
b/src/lib/evas/canvas/evas_3d_mesh.c
index ddbf619..44304380 100644
--- a/src/lib/evas/canvas/evas_3d_mesh.c
+++ b/src/lib/evas/canvas/evas_3d_mesh.c
@@ -120,6 +120,9 @@ _mesh_init(Evas_3D_Mesh_Data *pd)
    pd->blend_sfactor = EVAS_3D_BLEND_ONE;
    pd->blend_dfactor = EVAS_3D_BLEND_ZERO;
    pd->blending = EINA_FALSE;
+
+   pd->color_pick_key = -1.0;
+   pd->color_pick_enabled = EINA_FALSE;
 }
 
 static inline void
@@ -963,4 +966,18 @@ evas_3d_mesh_interpolate_vertex_buffer_get(Evas_3D_Mesh 
*mesh, int frame,
      }
 }
 
+EOLIAN static Eina_Bool
+_evas_3d_mesh_color_pick_enable_get(Eo *obj EINA_UNUSED, Evas_3D_Mesh_Data *pd)
+{
+   return pd->color_pick_enabled;
+}
+EOLIAN static Eina_Bool
+_evas_3d_mesh_color_pick_enable_set(Eo *obj, Evas_3D_Mesh_Data *pd, Eina_Bool 
_enabled)
+{
+   if (pd->color_pick_enabled != _enabled)
+     pd->color_pick_enabled = _enabled;
+   eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_MESH_COLOR_PICK, NULL));
+   return EINA_TRUE;
+}
+
 #include "canvas/evas_3d_mesh.eo.c"
diff --git a/src/lib/evas/canvas/evas_3d_mesh.eo 
b/src/lib/evas/canvas/evas_3d_mesh.eo
index 5657b32..a23654a 100644
--- a/src/lib/evas/canvas/evas_3d_mesh.eo
+++ b/src/lib/evas/canvas/evas_3d_mesh.eo
@@ -352,6 +352,27 @@ class Evas_3D_Mesh (Evas_3D_Object, Evas.Common_Interface, 
Efl.File)
          params {
          }
       }
+      color_pick_enable_get @const {
+         /*
+           Get status of color picking of the mesh.
+
+           @ingroup Evas_3D_Mesh
+          */
+         return: bool;
+         params {
+         }
+      }
+      color_pick_enable_set {
+         /*
+           Set posibility color picking.
+
+           @ingroup Evas_3D_Mesh
+          */
+         return: bool;
+         params {
+            @in bool _enabled;  /*@ Posibility flag */
+         }
+      }
    }
    properties {
       shade_mode {
diff --git a/src/lib/evas/canvas/evas_3d_node.c 
b/src/lib/evas/canvas/evas_3d_node.c
index a5355ed..62e2c1c 100644
--- a/src/lib/evas/canvas/evas_3d_node.c
+++ b/src/lib/evas/canvas/evas_3d_node.c
@@ -6,6 +6,27 @@
 
 Evas_3D_Mesh_Frame *evas_3d_mesh_frame_find(Evas_3D_Mesh_Data *pd, int frame);
 
+static Eina_Stringshare *
+_generate_unic_color_key(Evas_Color *color, Evas_Color *bg_color, Evas_3D_Node 
*node, Evas_3D_Mesh *mesh,
+                         Eina_Bool init)
+{
+   static unsigned short red = USHRT_MAX;
+
+   if (init) red = USHRT_MAX;
+
+   if (fabs(bg_color->r - (double)red) <= DBL_EPSILON) red--;
+
+   color->r = (double)red / USHRT_MAX;
+   color->g = 0.0;
+   color->b = 0.0;
+
+   red--;
+
+   if (red < 1) red = USHRT_MAX;
+
+   return eina_stringshare_printf("%p %p", node, mesh);
+}
+
 static inline Evas_3D_Node_Mesh *
 _node_mesh_new(Evas_3D_Node *node, Evas_3D_Mesh *mesh)
 {
@@ -795,6 +816,56 @@ evas_3d_node_mesh_collect(Evas_3D_Node *node, void *data)
 }
 
 Eina_Bool
+evas_3d_node_color_node_mesh_collect(Evas_3D_Node *node, void *data)
+{
+   Evas_3D_Scene_Public_Data *scene_data = (Evas_3D_Scene_Public_Data *)data;
+   Evas_3D_Node_Data *pd = eo_data_scope_get(node, MY_CLASS);
+   Evas_3D_Node_Data *pd_camera = eo_data_scope_get(scene_data->camera_node, 
MY_CLASS);
+   Evas_3D_Camera *camera = (Evas_3D_Camera*)pd_camera->data.camera.camera;
+
+   Eina_List *list_meshes, *l;
+   Evas_3D_Mesh *mesh;
+   Eina_Stringshare *key, *datakey;
+   Evas_Color *color;
+   Eina_Bool visible = EINA_FALSE;
+   Eina_Array *arr;
+   if (pd->type == EVAS_3D_NODE_TYPE_MESH)
+     {
+        eo_do(camera,
+              visible = 
evas_3d_camera_node_visible_get(scene_data->camera_node,
+                                                        node, 
EVAS_3D_FRUSTUM_MODE_BSPHERE));
+        if (visible)
+          {
+             eo_do (node, list_meshes = (Eina_List 
*)evas_3d_node_mesh_list_get());
+             EINA_LIST_FOREACH(list_meshes, l, mesh)
+               {
+                 if (eo_do(mesh, evas_3d_mesh_color_pick_enable_get()))
+                   {
+                      color = calloc(1, sizeof(Evas_Color));
+
+                      if (!eina_hash_population(scene_data->node_mesh_colors))
+                        key = _generate_unic_color_key(color, 
&scene_data->bg_color,
+                                                       node, mesh, EINA_TRUE);
+                      else
+                        key = _generate_unic_color_key(color, 
&scene_data->bg_color,
+                                                       node, mesh, EINA_FALSE);
+
+                      datakey = eina_stringshare_printf("%f %f %f", color->r, 
color->g, color->b);
+                      eina_hash_add(scene_data->node_mesh_colors, key, color);
+                      arr = eina_array_new(2);
+                      eina_array_push(arr, (void *)node);
+                      eina_array_push(arr, (void *)mesh);
+                      eina_hash_add(scene_data->colors_node_mesh, datakey, 
arr);
+                   }
+               }
+           }
+        else
+          return EINA_FALSE;
+     }
+   return EINA_TRUE;
+}
+
+Eina_Bool
 evas_3d_node_light_collect(Evas_3D_Node *node, void *data)
 {
    Evas_3D_Scene_Public_Data *scene_data = (Evas_3D_Scene_Public_Data *)data;
diff --git a/src/lib/evas/canvas/evas_3d_scene.c 
b/src/lib/evas/canvas/evas_3d_scene.c
index 0e177a7..a26b6c8 100644
--- a/src/lib/evas/canvas/evas_3d_scene.c
+++ b/src/lib/evas/canvas/evas_3d_scene.c
@@ -9,6 +9,8 @@ evas_3d_scene_data_init(Evas_3D_Scene_Public_Data *data)
    data->camera_node = NULL;
    data->light_nodes = NULL;
    data->mesh_nodes = NULL;
+   data->node_mesh_colors = NULL;
+   data->colors_node_mesh = NULL;
 }
 
 void
@@ -46,6 +48,8 @@ _evas_3d_scene_evas_3d_object_update_notify(Eo *obj 
EINA_UNUSED, Evas_3D_Scene_D
      {
         eo_do(pd->camera_node, evas_3d_object_update());
      }
+
+   eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_SCENE_UPDATED, NULL));
 }
 
 EAPI Evas_3D_Scene *
@@ -65,6 +69,9 @@ _evas_3d_scene_eo_base_constructor(Eo *obj, 
Evas_3D_Scene_Data *pd)
    eo_do(obj, evas_3d_object_type_set(EVAS_3D_OBJECT_TYPE_SCENE));
    evas_color_set(&pd->bg_color, 0.0, 0.0, 0.0, 0.0);
    pd->shadows_enabled = EINA_FALSE;
+   pd->color_pick_enabled = EINA_FALSE;
+   pd->node_mesh_colors = NULL;
+   pd->colors_node_mesh = NULL;
 }
 
 EOLIAN static void
@@ -608,17 +615,32 @@ _node_pick(Evas_3D_Node *node, void *data)
    return EINA_TRUE;
 }
 
+static void _node_mesh_colors_free_cb(void *data)
+{
+   if (data) free(data);
+}
+
 EOLIAN static Eina_Bool
 _evas_3d_scene_pick(Eo *obj, Evas_3D_Scene_Data *pd, Evas_Real x, Evas_Real y,
                     Evas_3D_Node **node, Evas_3D_Mesh **mesh,
                     Evas_Real *s, Evas_Real *t)
 {
-   /* TODO: Use H/W picking if availabe. */
    Evas_3D_Pick_Data data;
+   Evas_3D_Node_Data *pd_camera_node;
+   Evas_3D_Camera_Data *pd_camera;
+   Evas_3D_Object_Data *pd_parent;
+   Evas_Public_Data *e;
+   int tex, px, py;;
+   double redcomponent;
+   Eina_Stringshare *tmp;
+   Eina_Array *arr = NULL;
+   Eina_Bool update_scene = EINA_FALSE;
+
+   pd_parent = eo_data_scope_get(obj, EVAS_3D_OBJECT_CLASS);
+   e = eo_data_scope_get(pd_parent->evas, EVAS_CANVAS_CLASS);
 
    data.x      = ((x * 2.0) / (Evas_Real)pd->w) - 1.0;
    data.y      = (((pd->h - y - 1) * 2.0) / ((Evas_Real)pd->h)) - 1.0;
-
    data.picked = EINA_FALSE;
    data.z      = 1.0;
    data.node   = NULL;
@@ -626,17 +648,78 @@ _evas_3d_scene_pick(Eo *obj, Evas_3D_Scene_Data *pd, 
Evas_Real x, Evas_Real y,
    data.s      = 0.0;
    data.t      = 0.0;
 
+   px = round(x * pd->w / e->viewport.w);
+   py = round((pd->h - (y * pd->h / e->viewport.h) - 1));
+
+   /*Use color pick mechanism finding node and mesh*/
+   if (pd->color_pick_enabled)
+     {
+        Evas_3D_Scene_Public_Data scene_data;
+
+        scene_data.bg_color = pd->bg_color;
+        scene_data.shadows_enabled = pd->shadows_enabled;
+        scene_data.camera_node = pd->camera_node;
+        scene_data.color_pick_enabled = pd->color_pick_enabled;
+        update_scene = eo_do(obj, 
evas_3d_object_dirty_get(EVAS_3D_STATE_SCENE_UPDATED));
+        if (update_scene)
+          {
+             if (pd->node_mesh_colors)
+               {
+                  eina_hash_free(pd->node_mesh_colors);
+                  eina_hash_free(pd->colors_node_mesh);
+                  pd->node_mesh_colors = NULL;
+                  pd->colors_node_mesh = NULL;
+               }
+             pd->node_mesh_colors = 
eina_hash_stringshared_new(_node_mesh_colors_free_cb);
+             pd->colors_node_mesh = 
eina_hash_stringshared_new(_node_mesh_colors_free_cb);
+          }
+        scene_data.node_mesh_colors = pd->node_mesh_colors;
+        scene_data.colors_node_mesh = pd->colors_node_mesh;
+        evas_3d_node_tree_traverse(pd->root_node,
+                                   EVAS_3D_TREE_TRAVERSE_LEVEL_ORDER, 
EINA_TRUE,
+                                   evas_3d_node_color_node_mesh_collect, 
&scene_data);
+
+        if (e->engine.func->drawable_scene_render_to_texture)
+          {
+             if 
(e->engine.func->drawable_scene_render_to_texture(e->engine.data.output,
+                                                         pd->surface, 
&scene_data))
+               {
+                  if (e->engine.func->drawable_texture_color_pick_id_get)
+                    tex = 
e->engine.func->drawable_texture_color_pick_id_get(pd->surface);
+                  if (e->engine.func->drawable_texture_pixel_color_get)
+                    {
+                       redcomponent = 
e->engine.func->drawable_texture_pixel_color_get(tex, px, py, pd->surface);
+                       tmp = eina_stringshare_printf("%f %f %f", redcomponent, 
0.0, 0.0);
+                       arr = (Eina_Array 
*)eina_hash_find(pd->colors_node_mesh, tmp);
+                       if (arr)
+                         {
+                            if (mesh) *mesh = (Evas_3D_Mesh 
*)eina_array_data_get(arr, 1);
+                            if (node) *node = (Evas_3D_Node 
*)eina_array_data_get(arr, 0);
+                            eina_stringshare_del(tmp);
+
+                            return EINA_TRUE;
+                         }
+                       else
+                         {
+                            eina_stringshare_del(tmp);
+                            if (mesh) *mesh = NULL;
+                            if (node) *node = NULL;
+                         }
+                    }
+               }
+          }
+        return EINA_FALSE;
+     }
    /* Update the scene graph. */
    eo_do(obj, evas_3d_object_update());
-   Evas_3D_Node_Data *pd_camera_node = eo_data_scope_get(pd->camera_node, 
EVAS_3D_NODE_CLASS);
-   Evas_3D_Camera_Data *pd_camera = 
eo_data_scope_get(pd_camera_node->data.camera.camera, EVAS_3D_CAMERA_CLASS);
+   pd_camera_node = eo_data_scope_get(pd->camera_node, EVAS_3D_NODE_CLASS);
+   pd_camera = eo_data_scope_get(pd_camera_node->data.camera.camera, 
EVAS_3D_CAMERA_CLASS);
    evas_mat4_multiply(&data.matrix_vp,
                       &pd_camera->projection,
                       &pd_camera_node->data.camera.matrix_world_to_eye);
 
    evas_ray3_init(&data.ray_world, data.x, data.y, &data.matrix_vp);
 
-
    /* Traverse tree while adding meshes into pick data structure. */
    evas_3d_node_tree_traverse(pd->root_node, 
EVAS_3D_TREE_TRAVERSE_LEVEL_ORDER, EINA_TRUE,
                               _node_pick, &data);
@@ -726,4 +809,20 @@ _evas_3d_scene_shadows_enable_set(Eo *obj EINA_UNUSED, 
Evas_3D_Scene_Data *pd, E
    eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_SCENE_SHADOWS_ENABLED, 
NULL));
 }
 
+EOLIAN static Eina_Bool
+_evas_3d_scene_color_pick_enable_get(Eo *obj EINA_UNUSED, Evas_3D_Scene_Data 
*pd)
+{
+   return pd->color_pick_enabled;
+}
+
+EOLIAN static Eina_Bool
+_evas_3d_scene_color_pick_enable_set(Eo *obj EINA_UNUSED, Evas_3D_Scene_Data 
*pd, Eina_Bool _enabled)
+{
+   if (pd->color_pick_enabled != _enabled)
+     pd->color_pick_enabled = _enabled;
+
+   eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_SCENE_UPDATED, NULL));
+   return EINA_TRUE;
+}
+
 #include "canvas/evas_3d_scene.eo.c"
diff --git a/src/lib/evas/canvas/evas_3d_scene.eo 
b/src/lib/evas/canvas/evas_3d_scene.eo
index 1078c02..bb25f90 100644
--- a/src/lib/evas/canvas/evas_3d_scene.eo
+++ b/src/lib/evas/canvas/evas_3d_scene.eo
@@ -136,6 +136,27 @@ class Evas_3D_Scene (Evas_3D_Object, Evas.Common_Interface)
          params {
          }
       }
+      color_pick_enable_get @const {
+         /*
+           Get status of color picking of the scene.
+
+           @ingroup Evas_3D_Scene
+          */
+         return: bool;
+         params {
+         }
+      }
+      color_pick_enable_set {
+         /*
+           Set posibility color picking.
+
+           @ingroup Evas_3D_Scene
+          */
+         return: bool;
+         params {
+            @in bool color_pick;  /*@ Posibility flag */
+         }
+      }
    }
    properties {
 
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index c07cfa3..ceab19d 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -191,11 +191,15 @@ struct _Evas_3D_Scene
    Evas_3D_Node     *root_node;
    Evas_3D_Node     *camera_node;
    Evas_Color       bg_color;
+   Eina_Bool        shadows_enabled :1;
+   Eina_Bool        color_pick_enabled :1;
 
    void             *surface;
    int               w, h;
    Eina_List        *images;
-   Eina_Bool        shadows_enabled :1;
+
+   Eina_Hash        *node_mesh_colors;
+   Eina_Hash        *colors_node_mesh;
 };
 
 struct _Evas_3D_Node_Mesh
@@ -380,6 +384,7 @@ struct _Evas_3D_Scene_Public_Data
    Eina_List        *mesh_nodes;
    Eina_Bool        shadows_enabled :1;
    Eina_Bool        color_pick_enabled :1;
+
    Eina_Hash        *node_mesh_colors;
    Eina_Hash        *colors_node_mesh;
 };
@@ -1628,6 +1633,7 @@ void _canvas_smart_objects_calculate_count_get(Eo *e, 
void *_pd, va_list *list);
 void evas_3d_node_traverse(Evas_3D_Node *from, Evas_3D_Node *to, 
Evas_3D_Node_Traverse_Type type, Eina_Bool skip, Evas_3D_Node_Func func, void 
*data);
 void evas_3d_node_tree_traverse(Evas_3D_Node *root, Evas_3D_Tree_Traverse_Type 
type, Eina_Bool skip, Evas_3D_Node_Func func, void *data);
 Eina_Bool evas_3d_node_mesh_collect(Evas_3D_Node *node, void *data);
+Eina_Bool evas_3d_node_color_node_mesh_collect(Evas_3D_Node *node, void *data);
 Eina_Bool evas_3d_node_light_collect(Evas_3D_Node *node, void *data);
 void evas_3d_node_scene_root_add(Evas_3D_Node *node, Evas_3D_Scene *scene);
 void evas_3d_node_scene_root_del(Evas_3D_Node *node, Evas_3D_Scene *scene);

-- 


Reply via email to