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:
parent
46b9b23144
commit
dc0b144cf0
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue