evas.canvas3d: support static LOD technic

Summary:
Main flow: add several meshes(with different number of polygons) in one node,
enable LOD for node, set boundary distances to choose need mesh depend on distance
to the camera node, render only need mesh. Add API's enable lod in
evas_canvas3d_node module and set boundary distance to module
evas_canvas3d_mesh module Refactored function evas_canvas3d_node_mesh_collect
to calculate distance. Refactored _scene_render to have possibility pass to the
render only need LOD mesh.

Reviewers: cedric, Hermet, raster

Subscribers: jpeg

Differential Revision: https://phab.enlightenment.org/D3731

Signed-off-by: Cedric Bail <cedric@osg.samsung.com>
This commit is contained in:
Oleksandr Shcherbina 2016-03-15 12:49:33 -07:00 committed by Cedric Bail
parent cdb7286485
commit 296e8c22b0
8 changed files with 91 additions and 6 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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