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 <cedric@osg.samsung.com>
This commit is contained in:
Oleksandr Shcherbina 2015-02-11 17:44:42 +01:00 committed by Cedric BAIL
parent 46b9b23144
commit dc0b144cf0
7 changed files with 242 additions and 6 deletions

View File

@ -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,

View File

@ -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"

View File

@ -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 {

View File

@ -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)
{
@ -794,6 +815,56 @@ evas_3d_node_mesh_collect(Evas_3D_Node *node, void *data)
return EINA_TRUE;
}
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)
{

View File

@ -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"

View File

@ -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 {

View File

@ -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);