diff --git a/src/lib/evas/canvas/evas_canvas3d_mesh.c b/src/lib/evas/canvas/evas_canvas3d_mesh.c index d19a1fc39a..606d3994b0 100644 --- a/src/lib/evas/canvas/evas_canvas3d_mesh.c +++ b/src/lib/evas/canvas/evas_canvas3d_mesh.c @@ -133,6 +133,8 @@ _mesh_init(Evas_Canvas3D_Mesh_Data *pd) pd->shadows_edges_filtering_level = 4; pd->shadows_edges_size = 300.0; pd->shadows_constant_bias = 0.00015; + pd->near_lod_boundary = 0.0; + pd->far_lod_boundary = 0.0; } static inline void @@ -1151,4 +1153,19 @@ _evas_canvas3d_mesh_convex_hull_data_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh return; } +EOLIAN static void +_evas_canvas3d_mesh_lod_boundary_set(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd, + Evas_Real near, Evas_Real far) +{ + pd->near_lod_boundary = near; + pd->far_lod_boundary = far; +} + +EOLIAN static void +_evas_canvas3d_mesh_lod_boundary_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd, + Evas_Real *near, Evas_Real *far) +{ + *near = pd->near_lod_boundary; + *far = pd->far_lod_boundary; +} #include "canvas/evas_canvas3d_mesh.eo.c" diff --git a/src/lib/evas/canvas/evas_canvas3d_mesh.eo b/src/lib/evas/canvas/evas_canvas3d_mesh.eo index d41b9103ec..3cbae535fb 100644 --- a/src/lib/evas/canvas/evas_canvas3d_mesh.eo +++ b/src/lib/evas/canvas/evas_canvas3d_mesh.eo @@ -405,6 +405,20 @@ class Evas.Canvas3D.Mesh (Evas.Canvas3D.Object, Evas.Common_Interface, Efl.File) bias: Evas.Real; [[Offset.]] } } + @property lod_boundary { + set { + [[Set LOD boundary distances.]] + } + get { + [[Get LOD boundary distances. + + See also @Evas.Canvas3D.Mesh.lod_boundary.set.]] + } + values { + near: Evas.Real; [[up boundary]] + far: Evas.Real; [[down boundary]] + } + } } implements { Eo.Base.constructor; diff --git a/src/lib/evas/canvas/evas_canvas3d_node.c b/src/lib/evas/canvas/evas_canvas3d_node.c index 54f4f07b73..ec7633d812 100644 --- a/src/lib/evas/canvas/evas_canvas3d_node.c +++ b/src/lib/evas/canvas/evas_canvas3d_node.c @@ -892,7 +892,12 @@ evas_canvas3d_node_mesh_collect(Evas_Canvas3D_Node *node, void *data) if (pd->type == EVAS_CANVAS3D_NODE_TYPE_MESH) { scene_data->mesh_nodes = eina_list_append(scene_data->mesh_nodes, node); - + /*In case LOD calculate distance to the camera node*/ + if (pd->lod) + { + Evas_Canvas3D_Node_Data *pd_camera = eo_data_scope_get(scene_data->camera_node, MY_CLASS); + scene_data->lod_distance = eina_vector3_distance_get(&pd_camera->position, &pd->position_world); + } /* calculation of tangent space for all meshes */ list_meshes = (Eina_List *)evas_canvas3d_node_mesh_list_get(node); EINA_LIST_FOREACH(list_meshes, l, mesh) @@ -1034,6 +1039,7 @@ _evas_canvas3d_node_constructor(Eo *obj, Evas_Canvas3D_Node_Data *pd, Evas_Canva pd->scale_inherit = EINA_TRUE; pd->data.mesh.node_meshes = 0; pd->billboard_target = NULL; + pd->lod = EINA_FALSE; evas_box3_set(&pd->aabb, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); @@ -1652,4 +1658,18 @@ _evas_canvas3d_node_billboard_target_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Node { return pd->billboard_target; } + +EOLIAN static void +_evas_canvas3d_node_lod_enable_set(Eo *obj, Evas_Canvas3D_Node_Data *pd, + Eina_Bool enable) +{ + pd->lod = enable; + evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_NODE_LOD, NULL); +} + +EOLIAN static Eina_Bool +_evas_canvas3d_node_lod_enable_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Node_Data *pd) +{ + return pd->lod; +} #include "canvas/evas_canvas3d_node.eo.c" diff --git a/src/lib/evas/canvas/evas_canvas3d_node.eo b/src/lib/evas/canvas/evas_canvas3d_node.eo index 2ae271ad20..bded3241fe 100644 --- a/src/lib/evas/canvas/evas_canvas3d_node.eo +++ b/src/lib/evas/canvas/evas_canvas3d_node.eo @@ -368,6 +368,19 @@ class Evas.Canvas3D.Node (Evas.Canvas3D.Object, Evas.Common_Interface) or $null if there're none.]] } } + @property lod_enable { + set { + [[Enable behavior of node like LOD object.]] + } + get { + [[Get(check) status of node does node is LOD object. + + See also @Evas.Canvas3D.Node.lod_enable.set.]] + } + values { + enable: bool; [[status property (true/false)]] + } + } } implements { Eo.Base.destructor; diff --git a/src/lib/evas/canvas/evas_canvas3d_scene.c b/src/lib/evas/canvas/evas_canvas3d_scene.c index cb7ffc373a..a8cc117050 100644 --- a/src/lib/evas/canvas/evas_canvas3d_scene.c +++ b/src/lib/evas/canvas/evas_canvas3d_scene.c @@ -12,6 +12,7 @@ evas_canvas3d_scene_data_init(Evas_Canvas3D_Scene_Public_Data *data) data->node_mesh_colors = NULL; data->colors_node_mesh = NULL; data->render_to_texture = EINA_FALSE; + data->lod_distance = 0; } void diff --git a/src/lib/evas/canvas/evas_types.eot b/src/lib/evas/canvas/evas_types.eot index 6f37537347..27a2830769 100644 --- a/src/lib/evas/canvas/evas_types.eot +++ b/src/lib/evas/canvas/evas_types.eot @@ -346,7 +346,8 @@ enum Evas.Canvas3D.State node_parent_orientation, node_parent_scale, node_member, - node_parent_billboard [[@since 1.14]] + node_parent_billboard, [[@since 1.14]] + node_lod [[@since 1.18]] } enum Evas.Canvas3D.Space diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 525ff1da9e..ceee4a7aeb 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -289,6 +289,7 @@ struct _Evas_Canvas3D_Node Eina_Bool position_inherit : 1; Eina_Bool orientation_inherit : 1; Eina_Bool scale_inherit : 1; + Eina_Bool lod : 1; }; struct _Evas_Canvas3D_Camera @@ -387,6 +388,8 @@ struct _Evas_Canvas3D_Mesh int shadows_edges_filtering_level; Evas_Real shadows_edges_size; Evas_Real shadows_constant_bias; + Evas_Real near_lod_boundary; + Evas_Real far_lod_boundary; }; struct _Evas_Canvas3D_Texture @@ -437,7 +440,6 @@ struct _Evas_Canvas3D_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; @@ -445,6 +447,8 @@ struct _Evas_Canvas3D_Scene_Public_Data Evas_Real depth_offset; Evas_Real depth_constant; Eina_Bool render_to_texture; + + unsigned int lod_distance; }; struct _Evas_Canvas3D_Pick_Data diff --git a/src/modules/evas/engines/gl_common/evas_gl_3d.c b/src/modules/evas/engines/gl_common/evas_gl_3d.c index fd3e26451e..5ca627fbaf 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_3d.c +++ b/src/modules/evas/engines/gl_common/evas_gl_3d.c @@ -1,6 +1,16 @@ #include "evas_gl_private.h" #include "evas_gl_3d_private.h" +#define CHECK_LOD_DISTANCE \ + if (pd_mesh_node->lod) \ + { \ + if (pdmesh->near_lod_boundary > data->lod_distance) \ + continue; \ + else if ((pdmesh->near_lod_boundary < data->lod_distance) && \ + (pdmesh->far_lod_boundary < data->lod_distance)) \ + continue; \ + } + #define RENDER_MESH_NODE_ITERATE_BEGIN(param) \ Eina_Matrix4 matrix_mv; \ Eina_Matrix4 matrix_mvp; \ @@ -11,8 +21,9 @@ it = eina_hash_iterator_data_new(pd_mesh_node->data.mesh.node_meshes); \ while (eina_iterator_next(it, &ptr)) \ { \ - Evas_Canvas3D_Node_Mesh *nm = (Evas_Canvas3D_Node_Mesh *)ptr; \ - Evas_Canvas3D_Mesh_Data *pdmesh = eo_data_scope_get(nm->mesh, EVAS_CANVAS3D_MESH_CLASS); + Evas_Canvas3D_Node_Mesh *nm = (Evas_Canvas3D_Node_Mesh *)ptr; \ + Evas_Canvas3D_Mesh_Data *pdmesh = eo_data_scope_get(nm->mesh, EVAS_CANVAS3D_MESH_CLASS); \ + CHECK_LOD_DISTANCE #define RENDER_MESH_NODE_ITERATE_END \ } \ @@ -1282,6 +1293,10 @@ _scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_Canvas3D_Scen { Evas_Canvas3D_Node_Mesh *nm = (Evas_Canvas3D_Node_Mesh *)ptr; Evas_Canvas3D_Mesh_Data *pdmesh = eo_data_scope_get(nm->mesh, EVAS_CANVAS3D_MESH_CLASS); + /*In case LOD enable pass in render only LOD meshes in dependences of the + distance to the camera node: + near_boundary <= distance <= far_boundary*/ + CHECK_LOD_DISTANCE if (data->shadows_enabled) { pdmesh->shadowed = EINA_TRUE; @@ -1399,6 +1414,6 @@ e3d_drawable_texture_pixel_color_get(GLuint tex EINA_UNUSED, int x, int y, glBindFramebuffer(GL_FRAMEBUFFER, d->fbo); } - +#undef CHECK_LOD_DISTANCE #undef RENDER_MESH_NODE_ITERATE_BEGIN #undef RENDER_MESH_NODE_ITERATE_END